index — crispy-website @ 92ea832f9dca4a83ba07869b80482aa26d79e782

My personal homepage (very crispy)

Merge pull request #2 from ish7o/ishu

ishu, redo go stuff and small css fix
crispy-caesus 114518720+crispy-caesus@users.noreply.github.com
Sat, 13 Sep 2025 19:37:45 +0000
commit

92ea832f9dca4a83ba07869b80482aa26d79e782

parent

b8c8ce39f555547be4b60d011b2e7ed2016e8a06

M README.mdREADME.md

@@ -1,2 +1,9 @@

# crispy-website just my little website + +## Run locally: +```go +go run ./cmd/server/ +``` +:3 +
A cmd/server/main.go

@@ -0,0 +1,46 @@

+package main + +import ( + "crispy-website/internal/db" + "crispy-website/internal/repo" + "fmt" + "log" + "net/http" + "text/template" +) + +func main() { + repository, err := repo.NewRepository("walletdrain.db") + if err != nil { + panic("failed to open db") + } + + fs := http.FileServer(http.Dir("static")) + + http.Handle("/static/", http.StripPrefix("/static/", fs)) + + http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { + http.ServeFile(w, r, "templates/index.html") + }) + + http.HandleFunc("/music", func(w http.ResponseWriter, r *http.Request) { + results := repository.LoadMusic() + spending := repository.GetSpending() + tmpl := template.Must(template.ParseFiles("templates/music.html")) + + data := db.MusicData{Releases: results, Spending: spending} + + err := tmpl.Execute(w, data) + if err != nil { + http.Error(w, err.Error(), http.StatusInternalServerError) + } + }) + + http.HandleFunc("/.well-known/discord", func(w http.ResponseWriter, r *http.Request) { + w.Header().Set("Content-Type", "text/plain") + w.Write([]byte("dh=b81129b4e9cc388c5ab63919550316fc3ca5ebe4")) + }) + + fmt.Println("Running on :8080") + log.Fatal(http.ListenAndServe("0.0.0.0:8080", nil)) +}
D index.go

@@ -1,29 +0,0 @@

-package main - -import ( - "log" - "net/http" -) - - -func viewHandler(w http.ResponseWriter, r *http.Request) { - http.ServeFile(w, r, "templates/index.html") -} - -func plainTextHandler(w http.ResponseWriter, r *http.Request) { - w.Header().Set("Content-Type", "text/plain") - w.Write([]byte("dh=b81129b4e9cc388c5ab63919550316fc3ca5ebe4")) -} - -func main() { - fs := http.FileServer(http.Dir("static")) - http.Handle("/static/", http.StripPrefix("/static/", fs)) - - http.HandleFunc("/", viewHandler) - http.HandleFunc("/music", musicHandler) - - http.HandleFunc("/.well-known/discord", plainTextHandler) - - log.Fatal(http.ListenAndServe("0.0.0.0:8080", nil)) -} -
A internal/db/sql.go

@@ -0,0 +1,23 @@

+package db + +import ( + "database/sql" + + _ "github.com/mattn/go-sqlite3" +) + +type MusicData struct { + Releases []MusicItem + Spending float32 +} + +type MusicItem struct { + Id int + External_ids sql.NullString + Name string + Artist string + Price float64 + Seller sql.NullString + Note string + Purchase_date sql.NullString +}
A internal/repo/sql.go

@@ -0,0 +1,65 @@

+package repo + +import ( + "crispy-website/internal/db" + "database/sql" + "log" + + _ "github.com/mattn/go-sqlite3" +) + +type Repository struct { + DB *sql.DB +} + +func NewRepository(dbName string) (*Repository, error) { + db, err := sql.Open("sqlite3", dbName) + if err != nil { + panic("couldn't open db") + } + + return &Repository{DB: db}, nil +} + +func (r *Repository) Close() error { + return r.DB.Close() +} + +func (r *Repository) LoadMusic() []db.MusicItem { + rows, err := r.DB.Query("SELECT * FROM music ORDER BY purchase_date DESC") + if err != nil { + panic(err) + } + defer rows.Close() + + var results []db.MusicItem + for rows.Next() { + var result db.MusicItem + err := rows.Scan( + &result.Id, + &result.External_ids, + &result.Name, + &result.Artist, + &result.Price, + &result.Seller, + &result.Note, + &result.Purchase_date) + if err != nil { + log.Print(err) + } + results = append(results, result) + } + return results +} + +func (r *Repository) GetSpending() (value float32) { + err := r.DB.QueryRow("SELECT ROUND(SUM(price), 2) FROM music").Scan(&value) + + if err == sql.ErrNoRows { + log.Println("No rows found") + } else if err != nil { + log.Fatal(err) + } + + return value +}
A internal/test.go.test

@@ -0,0 +1,135 @@

+package main + +import ( + "database/sql" + "encoding/json" + "fmt" + "io/ioutil" + "net/http" + "net/url" + "time" + + _ "github.com/mattn/go-sqlite3" +) + +type musicItem struct { + id int + external_ids sql.NullString + Name string + Artist string + price float64 + seller sql.NullString + Note sql.NullString + purchase_date sql.NullString +} + +func main() { + // Connect to the SQLite database + db, err := sql.Open("sqlite3", "walletdrain.db") + if err != nil { + fmt.Printf("Error connecting to database: %v\n", err) + return + } + defer db.Close() + + // Query to get the first 10 music items + rows, err := db.Query("SELECT id, external_ids, Name, Artist, price, seller, Note, purchase_date FROM music WHERE artist='Glitch Cat'") + if err != nil { + fmt.Printf("Error querying database: %v\n", err) + return + } + defer rows.Close() + + // Create HTTP client and set user agent + client := &http.Client{} + ua := "MusicCoverArtFetcher/1.0 (your-email@example.com)" + + fmt.Println("ID\tARTIST\tRELEASE\tCOVER ART URL (250px)") + fmt.Println("-----------------------------------------------") + + // Process each row from the database + for rows.Next() { + var item musicItem + + if err := rows.Scan(&item.id, &item.external_ids, &item.Name, &item.Artist, + &item.price, &item.seller, &item.Note, &item.purchase_date); err != nil { + fmt.Printf("Error scanning row: %v\n", err) + continue + } + + // Search MusicBrainz for the release + query := url.QueryEscape(fmt.Sprintf("artist:\"%s\" AND release:\"%s\"", item.Artist, item.Name)) + req, _ := http.NewRequest("GET", "https://musicbrainz.org/ws/2/release?query="+query+"&fmt=json", nil) + req.Header.Set("User-Agent", ua) + + resp, err := client.Do(req) + if err != nil || resp.StatusCode != http.StatusOK { + fmt.Printf("%d\t%s\t%s\tError searching MusicBrainz\n", item.id, item.Artist, item.Name) + continue + } + + var mbResp struct { + Releases []struct { + ID string `json:"id"` + } `json:"releases"` + } + + body, _ := ioutil.ReadAll(resp.Body) + resp.Body.Close() + + if err := json.Unmarshal(body, &mbResp); err != nil || len(mbResp.Releases) == 0 { + fmt.Printf("%d\t%s\t%s\tNo match found\n", item.id, item.Artist, item.Name) + continue + } + + // Get cover art using the MusicBrainz ID + req, _ = http.NewRequest("GET", "https://coverartarchive.org/release/"+mbResp.Releases[0].ID, nil) + req.Header.Set("User-Agent", ua) + + resp, err = client.Do(req) + if err != nil || resp.StatusCode != http.StatusOK { + fmt.Printf("%d\t%s\t%s\tNo cover art available\n", item.id, item.Artist, item.Name) + continue + } + + var caResp struct { + Images []struct { + Thumbnails struct { + Img250 string `json:"250"` + } `json:"thumbnails"` + Front bool `json:"front"` + } `json:"images"` + } + + body, _ = ioutil.ReadAll(resp.Body) + resp.Body.Close() + + if err := json.Unmarshal(body, &caResp); err != nil { + fmt.Printf("%d\t%s\t%s\tError parsing cover art data\n", item.id, item.Artist, item.Name) + continue + } + + // Find and display the front cover URL + coverURL := "" + for _, img := range caResp.Images { + if img.Front { + coverURL = img.Thumbnails.Img250 + break + } + } + + if coverURL == "" { + fmt.Printf("%d\t%s\t%s\tNo front cover found\n", item.id, item.Artist, item.Name) + } else { + fmt.Printf("%d\t%s\t%s\t%s\n", item.id, item.Artist, item.Name, coverURL) + } + + // Respect API rate limits + time.Sleep(1 * time.Second) + } + + // Check for errors from iterating over rows + if err = rows.Err(); err != nil { + fmt.Printf("Error iterating over rows: %v\n", err) + } +}
D music.go

@@ -1,25 +0,0 @@

-package main - -import ( - "net/http" - "text/template" -) - -type musicData struct { - Releases []musicItem - Spending float32 -} - -func musicHandler(w http.ResponseWriter, r *http.Request) { - results := loadMusic() - spending := getSpending() - tmpl := template.Must(template.ParseFiles("templates/music.html")) - - data := musicData{Releases: results, Spending: spending} - - err := tmpl.Execute(w, data) - if err != nil { - http.Error(w, err.Error(), http.StatusInternalServerError) - } - -}
D sql.go

@@ -1,82 +0,0 @@

-package main - -import ( - "database/sql" - "log" - - _ "github.com/mattn/go-sqlite3" -) - -type musicItem struct { - id int - external_ids sql.NullString - Name string - Artist string - price float64 - seller sql.NullString - Note string - purchase_date sql.NullString -} - -func openDB(DBName string) (*sql.DB, error) { - db, err := sql.Open("sqlite3", DBName+".db") - if err != nil { - panic("couldn't open db") - } - - return db, nil -} - -func loadMusic() []musicItem { - db, err := openDB("walletdrain") - if err != nil { - panic("couldn't open db") - } - defer db.Close() - - query := "SELECT * FROM music ORDER BY purchase_date DESC" - - rows, err := db.Query(query) - if err != nil { - panic(err) - } - defer rows.Close() - - var results []musicItem - for rows.Next() { - var result musicItem - err := rows.Scan( - &result.id, - &result.external_ids, - &result.Name, - &result.Artist, - &result.price, - &result.seller, - &result.Note, - &result.purchase_date) - if err != nil { - log.Print(err) - } - results = append(results, result) - } - return results -} - -func getSpending() (value float32) { - db, err := openDB("walletdrain") - if err != nil { - panic("couldn't open db") - } - defer db.Close() - - query := "SELECT ROUND(SUM(price), 2) FROM music" - - err = db.QueryRow(query).Scan(&value) - if err == sql.ErrNoRows { - log.Println("No rows found") - } else if err != nil { - log.Fatal(err) - } - - return value -}
M static/music.cssstatic/music.css

@@ -1,28 +1,33 @@

body { - background-color: #1e2021; - font-family: Arial, sans-serif; - color: #c8c3bc; - line-height: 1.6; - justify-content: center; - align-items: flex-start; - min-height: 100vh; - padding: 15em; - padding-top: 2em; - padding-bottom: 2em; - font-size: 1em; + font-family: Arial, sans-serif; + color: #c8c3bc; + line-height: 1.6; + + background-color: #1e2021; + + justify-content: center; + align-items: flex-start; + + min-height: 100vh; + padding: 2em; +} + +ul { + display: flex; + flex-direction: column; + gap: 20px; + + list-style-type: none; + padding: 0; } - ul { - list-style-type: none; - padding: 0; - } +li { + display: flex; + align-items: center; - li { - display: flex; - align-items: center; - margin-bottom: 10px; - } + gap: 20px; +} - li img { - margin-right: 10px; - } +li p { + margin: 0; +}
M templates/music.htmltemplates/music.html

@@ -18,7 +18,7 @@ <ul>

{{range .Releases}} <li> <img src="{{.Note}}" alt="Album Cover" width="50" /> - {{.Name}} - {{.Artist}} + <p>{{.Name}} - {{.Artist}}</p> </li> {{end}} </ul>