mirror of
https://github.com/JuLi0n21/pwa-player.git
synced 2026-04-19 15:30:05 +00:00
replace sql mostly with sqlc
This commit is contained in:
@@ -10,7 +10,6 @@ import (
|
|||||||
"os"
|
"os"
|
||||||
"path"
|
"path"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"strconv"
|
|
||||||
|
|
||||||
"github.com/juli0n21/go-osu-parser/parser"
|
"github.com/juli0n21/go-osu-parser/parser"
|
||||||
_ "modernc.org/sqlite"
|
_ "modernc.org/sqlite"
|
||||||
@@ -49,7 +48,9 @@ func initDB(connectionString string, osuDb *parser.OsuDB, osuroot string) (*sql.
|
|||||||
return nil, nil, err
|
return nil, nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if err = checkhealth(db, osuDB); err != nil {
|
sqlcQueries := sqlcdb.New(db)
|
||||||
|
|
||||||
|
if err = checkhealth(sqlcQueries, osuDB); err != nil {
|
||||||
if err = rebuildBeatmapDb(db, osuDB); err != nil {
|
if err = rebuildBeatmapDb(db, osuDB); err != nil {
|
||||||
return nil, nil, err
|
return nil, nil, err
|
||||||
}
|
}
|
||||||
@@ -70,8 +71,6 @@ func initDB(connectionString string, osuDb *parser.OsuDB, osuroot string) (*sql.
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
sqlcQueries := sqlcdb.New(db)
|
|
||||||
|
|
||||||
return db, sqlcQueries, nil
|
return db, sqlcQueries, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -90,13 +89,13 @@ func createDB(db *sql.DB) error {
|
|||||||
MD5Hash TEXT DEFAULT '00000000000000000000000000000000',
|
MD5Hash TEXT DEFAULT '00000000000000000000000000000000',
|
||||||
File TEXT DEFAULT 'unknown.osu',
|
File TEXT DEFAULT 'unknown.osu',
|
||||||
RankedStatus TEXT DEFAULT Unknown,
|
RankedStatus TEXT DEFAULT Unknown,
|
||||||
LastModifiedTime DATETIME DEFAULT '0001-01-01 00:00:00',
|
LastModifiedTime INTEGER DEFAULT 0,
|
||||||
TotalTime INTEGER DEFAULT 0,
|
TotalTime INTEGER DEFAULT 0,
|
||||||
AudioPreviewTime INTEGER DEFAULT 0,
|
AudioPreviewTime INTEGER DEFAULT 0,
|
||||||
BeatmapSetId INTEGER DEFAULT -1,
|
BeatmapSetId INTEGER DEFAULT -1,
|
||||||
Source TEXT DEFAULT '',
|
Source TEXT DEFAULT '',
|
||||||
Tags TEXT DEFAULT '',
|
Tags TEXT DEFAULT '',
|
||||||
LastPlayed DATETIME DEFAULT '0001-01-01 00:00:00',
|
LastPlayed INTEGER DEFAULT 0,
|
||||||
Folder TEXT DEFAULT 'Unknown Folder',
|
Folder TEXT DEFAULT 'Unknown Folder',
|
||||||
UNIQUE (Artist, Title, MD5Hash, Difficulty)
|
UNIQUE (Artist, Title, MD5Hash, Difficulty)
|
||||||
);
|
);
|
||||||
@@ -146,34 +145,24 @@ func createCollectionDB(db *sql.DB) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func checkhealth(db *sql.DB, osuDb *parser.OsuDB) error {
|
func checkhealth(db *sqlcdb.Queries, osuDb *parser.OsuDB) error {
|
||||||
|
|
||||||
rows, err := db.Query(`SELECT COUNT(*) FROM Beatmap GROUP BY BeatmapSetId;`)
|
count, err := db.GetBeatmapSetCount(context.TODO())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
defer rows.Close()
|
|
||||||
|
|
||||||
var count int
|
if count != int64(osuDb.FolderCount) {
|
||||||
if err = rows.Scan(&count); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
if count != int(osuDb.FolderCount) {
|
|
||||||
log.Println("Folder count missmatch rebuilding db...")
|
log.Println("Folder count missmatch rebuilding db...")
|
||||||
return ErrBeatmapCountNotMatch
|
return ErrBeatmapCountNotMatch
|
||||||
}
|
}
|
||||||
|
|
||||||
rows, err = db.Query(`SELECT COUNT(*) FROM Beatmap;`)
|
count, err = db.GetBeatmapCount(context.TODO())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if err = rows.Scan(&count); err != nil {
|
if count != int64(osuDb.NumberOfBeatmaps) {
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
if count != int(osuDb.NumberOfBeatmaps) {
|
|
||||||
log.Println("Beatmap count missmatch rebuilding db...")
|
log.Println("Beatmap count missmatch rebuilding db...")
|
||||||
return ErrBeatmapCountNotMatch
|
return ErrBeatmapCountNotMatch
|
||||||
}
|
}
|
||||||
@@ -310,268 +299,6 @@ func rebuildCollectionDb(db *sql.DB, collectionDb *parser.Collections) error {
|
|||||||
return tx.Commit()
|
return tx.Commit()
|
||||||
}
|
}
|
||||||
|
|
||||||
func getBeatmapCount(db *sql.DB) int {
|
|
||||||
rows, err := db.Query("SELECT COUNT(*) FROM Beatmap")
|
|
||||||
if err != nil {
|
|
||||||
log.Println(err)
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
defer rows.Close()
|
|
||||||
|
|
||||||
var count int
|
|
||||||
if rows.Next() {
|
|
||||||
err = rows.Scan(&count)
|
|
||||||
if err != nil {
|
|
||||||
log.Println(err)
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
return count
|
|
||||||
}
|
|
||||||
|
|
||||||
func getRecent(ctx context.Context, q *sqlcdb.Queries, limit, offset int) ([]Song, error) {
|
|
||||||
rows, err := q.GetRecentBeatmaps(ctx, sqlcdb.GetRecentBeatmapsParams{
|
|
||||||
Limit: int64(limit), Offset: int64(offset),
|
|
||||||
})
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
var songs []Song
|
|
||||||
|
|
||||||
for _, song := range rows {
|
|
||||||
songs = append(songs, convertToSong(song))
|
|
||||||
}
|
|
||||||
return songs, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func getSearch(db *sql.DB, q string, limit, offset int) (ActiveSearch, error) {
|
|
||||||
rows, err := db.Query(
|
|
||||||
`
|
|
||||||
SELECT
|
|
||||||
BeatmapId,
|
|
||||||
MD5Hash,
|
|
||||||
Title,
|
|
||||||
Artist,
|
|
||||||
Creator,
|
|
||||||
Folder,
|
|
||||||
File,
|
|
||||||
Audio,
|
|
||||||
TotalTime
|
|
||||||
FROM Beatmap WHERE Title LIKE ? OR Artist LIKE ? LIMIT ? OFFSET ?
|
|
||||||
`, "%"+q+"%", "%"+q+"%", limit, offset)
|
|
||||||
if err != nil {
|
|
||||||
return ActiveSearch{}, err
|
|
||||||
}
|
|
||||||
defer rows.Close()
|
|
||||||
s, err := scanSongs(rows)
|
|
||||||
if err != nil {
|
|
||||||
return ActiveSearch{}, err
|
|
||||||
}
|
|
||||||
return ActiveSearch{Songs: s}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func getArtists(db *sql.DB, q string, limit, offset int) ([]Artist, error) {
|
|
||||||
rows, err := db.Query("SELECT Artist, COUNT(Artist) FROM Beatmap WHERE Artist LIKE ? OR Title LIKE ? GROUP BY Artist LIMIT ? OFFSET ?", "%"+q+"%", "%"+q+"%", limit, offset)
|
|
||||||
if err != nil {
|
|
||||||
return []Artist{}, err
|
|
||||||
}
|
|
||||||
defer rows.Close()
|
|
||||||
|
|
||||||
artist := []Artist{}
|
|
||||||
for rows.Next() {
|
|
||||||
var a string
|
|
||||||
var c int
|
|
||||||
err := rows.Scan(&a, &c)
|
|
||||||
if err != nil {
|
|
||||||
return []Artist{}, err
|
|
||||||
}
|
|
||||||
artist = append(artist, Artist{Artist: a, Count: c})
|
|
||||||
}
|
|
||||||
|
|
||||||
return artist, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func getFavorites(db *sql.DB, q string, limit, offset int) ([]Song, error) {
|
|
||||||
rows, err := db.Query("SELECT * FROM Songs WHERE IsFavorite = 1 LIMIT ? OFFSET ?", limit, offset)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
defer rows.Close()
|
|
||||||
return scanSongs(rows)
|
|
||||||
}
|
|
||||||
|
|
||||||
func getCollection(db *sql.DB, limit, offset, index int) (Collection, error) {
|
|
||||||
rows, err := db.Query(`
|
|
||||||
WITH cols AS (
|
|
||||||
SELECT
|
|
||||||
c.Name,
|
|
||||||
ROW_NUMBER() OVER (ORDER BY c.Name) AS RowNumber
|
|
||||||
FROM Collection c
|
|
||||||
GROUP BY c.Name
|
|
||||||
)
|
|
||||||
|
|
||||||
SELECT
|
|
||||||
c.Name, b.BeatmapId, b.MD5Hash, b.Title, b.Artist,
|
|
||||||
b.Creator, b.Folder, b.File, b.Audio, b.TotalTime
|
|
||||||
FROM Collection c
|
|
||||||
Join Beatmap b ON c.MD5Hash = b.MD5Hash
|
|
||||||
WHERE c.Name = (SELECT Name FROM cols WHERE RowNumber = ?)
|
|
||||||
LIMIT ?
|
|
||||||
OFFSET ?;`, index, limit, offset)
|
|
||||||
if err != nil {
|
|
||||||
return Collection{}, err
|
|
||||||
}
|
|
||||||
defer rows.Close()
|
|
||||||
|
|
||||||
var c Collection
|
|
||||||
for rows.Next() {
|
|
||||||
s := Song{}
|
|
||||||
if err := rows.Scan(&c.Name, &s.BeatmapID, &s.MD5Hash, &s.Title, &s.Artist, &s.Creator, &s.Folder, &s.File, &s.Audio, &s.TotalTime); err != nil {
|
|
||||||
return Collection{}, err
|
|
||||||
}
|
|
||||||
|
|
||||||
s.Image = extractImageFromFile(osuRoot, s.Folder, s.File)
|
|
||||||
|
|
||||||
c.Songs = append(c.Songs, s)
|
|
||||||
}
|
|
||||||
|
|
||||||
row := db.QueryRow(`SELECT COUNT(*) FROM Collection WHERE Name = ?`, c.Name)
|
|
||||||
var count string
|
|
||||||
row.Scan(&count)
|
|
||||||
|
|
||||||
if i, err := strconv.Atoi(count); err == nil {
|
|
||||||
c.Items = i
|
|
||||||
}
|
|
||||||
|
|
||||||
return c, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func getCollectionByName(db *sql.DB, limit, offset int, name string) (Collection, error) {
|
|
||||||
rows, err := db.Query(`
|
|
||||||
SELECT
|
|
||||||
c.Name, b.BeatmapId, b.MD5Hash, b.Title, b.Artist,
|
|
||||||
b.Creator, b.Folder, b.File, b.Audio, b.TotalTime
|
|
||||||
FROM Collection c
|
|
||||||
Join Beatmap b ON c.MD5Hash = b.MD5Hash
|
|
||||||
WHERE c.Name = ?
|
|
||||||
LIMIT ?
|
|
||||||
OFFSET ?;`, name, limit, offset)
|
|
||||||
if err != nil {
|
|
||||||
return Collection{}, err
|
|
||||||
}
|
|
||||||
defer rows.Close()
|
|
||||||
|
|
||||||
var c Collection
|
|
||||||
for rows.Next() {
|
|
||||||
s := Song{}
|
|
||||||
if err := rows.Scan(&c.Name, &s.BeatmapID, &s.MD5Hash, &s.Title, &s.Artist, &s.Creator, &s.Folder, &s.File, &s.Audio, &s.TotalTime); err != nil {
|
|
||||||
return Collection{}, err
|
|
||||||
}
|
|
||||||
|
|
||||||
s.Image = extractImageFromFile(osuRoot, s.Folder, s.File)
|
|
||||||
|
|
||||||
c.Songs = append(c.Songs, s)
|
|
||||||
}
|
|
||||||
|
|
||||||
row := db.QueryRow(`SELECT COUNT(*) FROM Collection WHERE Name = ?`, c.Name)
|
|
||||||
var count string
|
|
||||||
row.Scan(&count)
|
|
||||||
|
|
||||||
if i, err := strconv.Atoi(count); err == nil {
|
|
||||||
c.Items = i
|
|
||||||
} else {
|
|
||||||
return Collection{}, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return c, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func getCollections(db *sql.DB, q string, limit, offset int) ([]CollectionPreview, error) {
|
|
||||||
rows, err := db.Query(`
|
|
||||||
SELECT
|
|
||||||
c.Name,
|
|
||||||
COUNT(b.MD5Hash) AS Count,
|
|
||||||
MIN(b.Folder) AS Folder,
|
|
||||||
MIN(b.File) AS File
|
|
||||||
FROM Collection c
|
|
||||||
JOIN Beatmap b ON c.MD5Hash = b.MD5Hash
|
|
||||||
WHERE c.Name LIKE ?
|
|
||||||
GROUP BY c.Name
|
|
||||||
LIMIT ?
|
|
||||||
OFFSET ?`, "%"+q+"%", limit, offset)
|
|
||||||
if err != nil {
|
|
||||||
return []CollectionPreview{}, err
|
|
||||||
}
|
|
||||||
defer rows.Close()
|
|
||||||
|
|
||||||
var collections []CollectionPreview
|
|
||||||
for rows.Next() {
|
|
||||||
var c CollectionPreview
|
|
||||||
var folder, file, count string
|
|
||||||
if err := rows.Scan(&c.Name, &count, &folder, &file); err != nil {
|
|
||||||
return []CollectionPreview{}, err
|
|
||||||
}
|
|
||||||
|
|
||||||
if i, err := strconv.Atoi(count); err == nil {
|
|
||||||
c.Items = i
|
|
||||||
}
|
|
||||||
c.Image = extractImageFromFile(osuRoot, folder, file)
|
|
||||||
|
|
||||||
collections = append(collections, c)
|
|
||||||
}
|
|
||||||
|
|
||||||
return collections, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func getSong(db *sql.DB, hash string) (Song, error) {
|
|
||||||
|
|
||||||
row := db.QueryRow("SELECT BeatmapId, MD5Hash, Title, Artist, Creator, Folder, File, Audio, TotalTime FROM Beatmap WHERE MD5Hash = ?", hash)
|
|
||||||
s, err := scanSong(row)
|
|
||||||
return s, err
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
func scanSongs(rows *sql.Rows) ([]Song, error) {
|
|
||||||
songs := []Song{}
|
|
||||||
for rows.Next() {
|
|
||||||
var s Song
|
|
||||||
if err := rows.Scan(&s.BeatmapID, &s.MD5Hash, &s.Title, &s.Artist, &s.Creator, &s.Folder, &s.File, &s.Audio, &s.TotalTime); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
bm, err := parser.ParseOsuFile(fmt.Sprintf("%sSongs/%s/%s", osuRoot, s.Folder, s.File))
|
|
||||||
if err != nil {
|
|
||||||
fmt.Println(err)
|
|
||||||
s.Image = "404.png"
|
|
||||||
} else {
|
|
||||||
if bgImage := bm.BackgroundImage(); bgImage != "" {
|
|
||||||
s.Image = fmt.Sprintf("%s/%s", s.Folder, bgImage)
|
|
||||||
} else {
|
|
||||||
s.Image = "404.png"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
songs = append(songs, s)
|
|
||||||
}
|
|
||||||
return songs, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func scanSong(row *sql.Row) (Song, error) {
|
|
||||||
|
|
||||||
s := Song{}
|
|
||||||
if err := row.Scan(&s.BeatmapID, &s.MD5Hash, &s.Title, &s.Artist, &s.Creator, &s.Folder, &s.File, &s.Audio, &s.TotalTime); err != nil {
|
|
||||||
return Song{}, err
|
|
||||||
}
|
|
||||||
|
|
||||||
s.Image = extractImageFromFile(osuRoot, s.Folder, s.File)
|
|
||||||
|
|
||||||
return s, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func extractImageFromFile(osuRoot, folder, file string) string {
|
func extractImageFromFile(osuRoot, folder, file string) string {
|
||||||
bm, err := parser.ParseOsuFile(filepath.Join(osuRoot, "Songs", folder, file))
|
bm, err := parser.ParseOsuFile(filepath.Join(osuRoot, "Songs", folder, file))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -586,67 +313,3 @@ func extractImageFromFile(osuRoot, folder, file string) string {
|
|||||||
|
|
||||||
return "404.png"
|
return "404.png"
|
||||||
}
|
}
|
||||||
|
|
||||||
func scanCollections(rows *sql.Rows) ([]Collection, error) {
|
|
||||||
|
|
||||||
var collection []Collection
|
|
||||||
for rows.Next() {
|
|
||||||
var c Collection
|
|
||||||
if err := rows.Scan(&c); err != nil {
|
|
||||||
return []Collection{}, err
|
|
||||||
}
|
|
||||||
collection = append(collection, c)
|
|
||||||
}
|
|
||||||
return collection, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func scanCollectionPreviews(rows *sql.Rows) ([]CollectionPreview, error) {
|
|
||||||
|
|
||||||
var collection []CollectionPreview
|
|
||||||
for rows.Next() {
|
|
||||||
var c CollectionPreview
|
|
||||||
if err := rows.Scan(&c); err != nil {
|
|
||||||
return []CollectionPreview{}, err
|
|
||||||
}
|
|
||||||
collection = append(collection, c)
|
|
||||||
}
|
|
||||||
return collection, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func scanCollectionPreview(row *sql.Row) (CollectionPreview, error) {
|
|
||||||
|
|
||||||
var c CollectionPreview
|
|
||||||
if err := row.Scan(&c); err != nil {
|
|
||||||
return CollectionPreview{}, err
|
|
||||||
}
|
|
||||||
return c, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func convertToSong(r sqlcdb.GetRecentBeatmapsRow) Song {
|
|
||||||
return Song{
|
|
||||||
BeatmapID: safeInt64(r.Beatmapid),
|
|
||||||
MD5Hash: safeString(r.Md5hash),
|
|
||||||
Title: safeString(r.Title),
|
|
||||||
Artist: safeString(r.Artist),
|
|
||||||
Creator: safeString(r.Creator),
|
|
||||||
Folder: safeString(r.Folder),
|
|
||||||
File: safeString(r.File),
|
|
||||||
Audio: safeString(r.Audio),
|
|
||||||
TotalTime: int64(safeInt64(r.Totaltime)),
|
|
||||||
Image: extractImageFromFile(osuRoot, safeString(r.Folder), safeString(r.File)),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func safeString(ns sql.NullString) string {
|
|
||||||
if ns.Valid {
|
|
||||||
return ns.String
|
|
||||||
}
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
|
|
||||||
func safeInt64(n sql.NullInt64) int {
|
|
||||||
if n.Valid {
|
|
||||||
return int(n.Int64)
|
|
||||||
}
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -5,9 +5,9 @@ go 1.24.5
|
|||||||
require (
|
require (
|
||||||
github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.1
|
github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.1
|
||||||
github.com/joho/godotenv v1.5.1
|
github.com/joho/godotenv v1.5.1
|
||||||
github.com/juli0n21/go-osu-parser v0.0.10
|
github.com/juli0n21/go-osu-parser v0.0.11
|
||||||
google.golang.org/genproto/googleapis/api v0.0.0-20250707201910-8d1bb00bc6a7
|
google.golang.org/genproto/googleapis/api v0.0.0-20250715232539-7130f93afb79
|
||||||
google.golang.org/grpc v1.73.0
|
google.golang.org/grpc v1.74.0
|
||||||
google.golang.org/protobuf v1.36.6
|
google.golang.org/protobuf v1.36.6
|
||||||
modernc.org/sqlite v1.38.0
|
modernc.org/sqlite v1.38.0
|
||||||
)
|
)
|
||||||
@@ -26,7 +26,7 @@ require (
|
|||||||
golang.org/x/net v0.42.0 // indirect
|
golang.org/x/net v0.42.0 // indirect
|
||||||
golang.org/x/sys v0.34.0 // indirect
|
golang.org/x/sys v0.34.0 // indirect
|
||||||
golang.org/x/text v0.27.0 // indirect
|
golang.org/x/text v0.27.0 // indirect
|
||||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20250707201910-8d1bb00bc6a7 // indirect
|
google.golang.org/genproto/googleapis/rpc v0.0.0-20250715232539-7130f93afb79 // indirect
|
||||||
modernc.org/libc v1.66.3 // indirect
|
modernc.org/libc v1.66.3 // indirect
|
||||||
modernc.org/mathutil v1.7.1 // indirect
|
modernc.org/mathutil v1.7.1 // indirect
|
||||||
modernc.org/memory v1.11.0 // indirect
|
modernc.org/memory v1.11.0 // indirect
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY=
|
github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY=
|
||||||
github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto=
|
github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto=
|
||||||
github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY=
|
github.com/go-logr/logr v1.4.3 h1:CjnDlHq8ikf6E492q6eKboGOC0T8CDaOvkHCIg8idEI=
|
||||||
github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
|
github.com/go-logr/logr v1.4.3/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
|
||||||
github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag=
|
github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag=
|
||||||
github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE=
|
github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE=
|
||||||
github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek=
|
github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek=
|
||||||
@@ -16,8 +16,8 @@ github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.1 h1:X5VWvz21y3gzm9Nw/kaUeku/1+u
|
|||||||
github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.1/go.mod h1:Zanoh4+gvIgluNqcfMVTJueD4wSS5hT7zTt4Mrutd90=
|
github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.1/go.mod h1:Zanoh4+gvIgluNqcfMVTJueD4wSS5hT7zTt4Mrutd90=
|
||||||
github.com/joho/godotenv v1.5.1 h1:7eLL/+HRGLY0ldzfGMeQkb7vMd0as4CfYvUVzLqw0N0=
|
github.com/joho/godotenv v1.5.1 h1:7eLL/+HRGLY0ldzfGMeQkb7vMd0as4CfYvUVzLqw0N0=
|
||||||
github.com/joho/godotenv v1.5.1/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4=
|
github.com/joho/godotenv v1.5.1/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4=
|
||||||
github.com/juli0n21/go-osu-parser v0.0.9 h1:3hx+ZtLKRJGdyJLhRbZzGyJ60Q3yRk9+tDJqwBJOZEg=
|
github.com/juli0n21/go-osu-parser v0.0.11 h1:p0kZc7zQ4YdmDO9/gor4zgvw2nfQPoDUtUXpV+hcOgU=
|
||||||
github.com/juli0n21/go-osu-parser v0.0.9/go.mod h1:oLLWnZReOMW4i5aNva/zvXsFqzdQigrbjyxOSs0cx+0=
|
github.com/juli0n21/go-osu-parser v0.0.11/go.mod h1:oLLWnZReOMW4i5aNva/zvXsFqzdQigrbjyxOSs0cx+0=
|
||||||
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
|
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
|
||||||
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
|
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
|
||||||
github.com/ncruces/go-strftime v0.1.9 h1:bY0MQC28UADQmHmaF5dgpLmImcShSi2kHU9XLdhx/f4=
|
github.com/ncruces/go-strftime v0.1.9 h1:bY0MQC28UADQmHmaF5dgpLmImcShSi2kHU9XLdhx/f4=
|
||||||
@@ -26,16 +26,16 @@ github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec h1:W09IVJc94
|
|||||||
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo=
|
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo=
|
||||||
go.opentelemetry.io/auto/sdk v1.1.0 h1:cH53jehLUN6UFLY71z+NDOiNJqDdPRaXzTel0sJySYA=
|
go.opentelemetry.io/auto/sdk v1.1.0 h1:cH53jehLUN6UFLY71z+NDOiNJqDdPRaXzTel0sJySYA=
|
||||||
go.opentelemetry.io/auto/sdk v1.1.0/go.mod h1:3wSPjt5PWp2RhlCcmmOial7AvC4DQqZb7a7wCow3W8A=
|
go.opentelemetry.io/auto/sdk v1.1.0/go.mod h1:3wSPjt5PWp2RhlCcmmOial7AvC4DQqZb7a7wCow3W8A=
|
||||||
go.opentelemetry.io/otel v1.35.0 h1:xKWKPxrxB6OtMCbmMY021CqC45J+3Onta9MqjhnusiQ=
|
go.opentelemetry.io/otel v1.36.0 h1:UumtzIklRBY6cI/lllNZlALOF5nNIzJVb16APdvgTXg=
|
||||||
go.opentelemetry.io/otel v1.35.0/go.mod h1:UEqy8Zp11hpkUrL73gSlELM0DupHoiq72dR+Zqel/+Y=
|
go.opentelemetry.io/otel v1.36.0/go.mod h1:/TcFMXYjyRNh8khOAO9ybYkqaDBb/70aVwkNML4pP8E=
|
||||||
go.opentelemetry.io/otel/metric v1.35.0 h1:0znxYu2SNyuMSQT4Y9WDWej0VpcsxkuklLa4/siN90M=
|
go.opentelemetry.io/otel/metric v1.36.0 h1:MoWPKVhQvJ+eeXWHFBOPoBOi20jh6Iq2CcCREuTYufE=
|
||||||
go.opentelemetry.io/otel/metric v1.35.0/go.mod h1:nKVFgxBZ2fReX6IlyW28MgZojkoAkJGaE8CpgeAU3oE=
|
go.opentelemetry.io/otel/metric v1.36.0/go.mod h1:zC7Ks+yeyJt4xig9DEw9kuUFe5C3zLbVjV2PzT6qzbs=
|
||||||
go.opentelemetry.io/otel/sdk v1.35.0 h1:iPctf8iprVySXSKJffSS79eOjl9pvxV9ZqOWT0QejKY=
|
go.opentelemetry.io/otel/sdk v1.36.0 h1:b6SYIuLRs88ztox4EyrvRti80uXIFy+Sqzoh9kFULbs=
|
||||||
go.opentelemetry.io/otel/sdk v1.35.0/go.mod h1:+ga1bZliga3DxJ3CQGg3updiaAJoNECOgJREo9KHGQg=
|
go.opentelemetry.io/otel/sdk v1.36.0/go.mod h1:+lC+mTgD+MUWfjJubi2vvXWcVxyr9rmlshZni72pXeY=
|
||||||
go.opentelemetry.io/otel/sdk/metric v1.35.0 h1:1RriWBmCKgkeHEhM7a2uMjMUfP7MsOF5JpUCaEqEI9o=
|
go.opentelemetry.io/otel/sdk/metric v1.36.0 h1:r0ntwwGosWGaa0CrSt8cuNuTcccMXERFwHX4dThiPis=
|
||||||
go.opentelemetry.io/otel/sdk/metric v1.35.0/go.mod h1:is6XYCUMpcKi+ZsOvfluY5YstFnhW0BidkR+gL+qN+w=
|
go.opentelemetry.io/otel/sdk/metric v1.36.0/go.mod h1:qTNOhFDfKRwX0yXOqJYegL5WRaW376QbB7P4Pb0qva4=
|
||||||
go.opentelemetry.io/otel/trace v1.35.0 h1:dPpEfJu1sDIqruz7BHFG3c7528f6ddfSWfFDVt/xgMs=
|
go.opentelemetry.io/otel/trace v1.36.0 h1:ahxWNuqZjpdiFAyrIoQ4GIiAIhxAunQR6MUoKrsNd4w=
|
||||||
go.opentelemetry.io/otel/trace v1.35.0/go.mod h1:WUk7DtFp1Aw2MkvqGdwiXYDZZNvA/1J8o6xRXLrIkyc=
|
go.opentelemetry.io/otel/trace v1.36.0/go.mod h1:gQ+OnDZzrybY4k4seLzPAWNwVBBVlF2szhehOBB/tGA=
|
||||||
golang.org/x/exp v0.0.0-20250711185948-6ae5c78190dc h1:TS73t7x3KarrNd5qAipmspBDS1rkMcgVG/fS1aRb4Rc=
|
golang.org/x/exp v0.0.0-20250711185948-6ae5c78190dc h1:TS73t7x3KarrNd5qAipmspBDS1rkMcgVG/fS1aRb4Rc=
|
||||||
golang.org/x/exp v0.0.0-20250711185948-6ae5c78190dc/go.mod h1:A+z0yzpGtvnG90cToK5n2tu8UJVP2XUATh+r+sfOOOc=
|
golang.org/x/exp v0.0.0-20250711185948-6ae5c78190dc/go.mod h1:A+z0yzpGtvnG90cToK5n2tu8UJVP2XUATh+r+sfOOOc=
|
||||||
golang.org/x/mod v0.26.0 h1:EGMPT//Ezu+ylkCijjPc+f4Aih7sZvaAr+O3EHBxvZg=
|
golang.org/x/mod v0.26.0 h1:EGMPT//Ezu+ylkCijjPc+f4Aih7sZvaAr+O3EHBxvZg=
|
||||||
@@ -51,12 +51,12 @@ golang.org/x/text v0.27.0 h1:4fGWRpyh641NLlecmyl4LOe6yDdfaYNrGb2zdfo4JV4=
|
|||||||
golang.org/x/text v0.27.0/go.mod h1:1D28KMCvyooCX9hBiosv5Tz/+YLxj0j7XhWjpSUF7CU=
|
golang.org/x/text v0.27.0/go.mod h1:1D28KMCvyooCX9hBiosv5Tz/+YLxj0j7XhWjpSUF7CU=
|
||||||
golang.org/x/tools v0.35.0 h1:mBffYraMEf7aa0sB+NuKnuCy8qI/9Bughn8dC2Gu5r0=
|
golang.org/x/tools v0.35.0 h1:mBffYraMEf7aa0sB+NuKnuCy8qI/9Bughn8dC2Gu5r0=
|
||||||
golang.org/x/tools v0.35.0/go.mod h1:NKdj5HkL/73byiZSJjqJgKn3ep7KjFkBOkR/Hps3VPw=
|
golang.org/x/tools v0.35.0/go.mod h1:NKdj5HkL/73byiZSJjqJgKn3ep7KjFkBOkR/Hps3VPw=
|
||||||
google.golang.org/genproto/googleapis/api v0.0.0-20250707201910-8d1bb00bc6a7 h1:FiusG7LWj+4byqhbvmB+Q93B/mOxJLN2DTozDuZm4EU=
|
google.golang.org/genproto/googleapis/api v0.0.0-20250715232539-7130f93afb79 h1:iOye66xuaAK0WnkPuhQPUFy8eJcmwUXqGGP3om6IxX8=
|
||||||
google.golang.org/genproto/googleapis/api v0.0.0-20250707201910-8d1bb00bc6a7/go.mod h1:kXqgZtrWaf6qS3jZOCnCH7WYfrvFjkC51bM8fz3RsCA=
|
google.golang.org/genproto/googleapis/api v0.0.0-20250715232539-7130f93afb79/go.mod h1:HKJDgKsFUnv5VAGeQjz8kxcgDP0HoE0iZNp0OdZNlhE=
|
||||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20250707201910-8d1bb00bc6a7 h1:pFyd6EwwL2TqFf8emdthzeX+gZE1ElRq3iM8pui4KBY=
|
google.golang.org/genproto/googleapis/rpc v0.0.0-20250715232539-7130f93afb79 h1:1ZwqphdOdWYXsUHgMpU/101nCtf/kSp9hOrcvFsnl10=
|
||||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20250707201910-8d1bb00bc6a7/go.mod h1:qQ0YXyHHx3XkvlzUtpXDkS29lDSafHMZBAZDc03LQ3A=
|
google.golang.org/genproto/googleapis/rpc v0.0.0-20250715232539-7130f93afb79/go.mod h1:qQ0YXyHHx3XkvlzUtpXDkS29lDSafHMZBAZDc03LQ3A=
|
||||||
google.golang.org/grpc v1.73.0 h1:VIWSmpI2MegBtTuFt5/JWy2oXxtjJ/e89Z70ImfD2ok=
|
google.golang.org/grpc v1.74.0 h1:sxRSkyLxlceWQiqDofxDot3d4u7DyoHPc7SBXMj8gGY=
|
||||||
google.golang.org/grpc v1.73.0/go.mod h1:50sbHOUqWoCQGI8V2HQLJM0B+LMlIUjNSZmow7EVBQc=
|
google.golang.org/grpc v1.74.0/go.mod h1:NZUaK8dAMUfzhK6uxZ+9511LtOrk73UGWOFoNvz7z+s=
|
||||||
google.golang.org/protobuf v1.36.6 h1:z1NpPI8ku2WgiWnf+t9wTPsn6eP1L7ksHUlkfLvd9xY=
|
google.golang.org/protobuf v1.36.6 h1:z1NpPI8ku2WgiWnf+t9wTPsn6eP1L7ksHUlkfLvd9xY=
|
||||||
google.golang.org/protobuf v1.36.6/go.mod h1:jduwjTPXsFjZGTmRluh+L6NjiWu7pchiJ2/5YcXBHnY=
|
google.golang.org/protobuf v1.36.6/go.mod h1:jduwjTPXsFjZGTmRluh+L6NjiWu7pchiJ2/5YcXBHnY=
|
||||||
modernc.org/cc/v4 v4.26.2 h1:991HMkLjJzYBIfha6ECZdjrIYz2/1ayr+FL8GN+CNzM=
|
modernc.org/cc/v4 v4.26.2 h1:991HMkLjJzYBIfha6ECZdjrIYz2/1ayr+FL8GN+CNzM=
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ import (
|
|||||||
|
|
||||||
v1 "backend/gen"
|
v1 "backend/gen"
|
||||||
"backend/internal/db"
|
"backend/internal/db"
|
||||||
|
sqlcdb "backend/internal/db"
|
||||||
|
|
||||||
"github.com/joho/godotenv"
|
"github.com/joho/godotenv"
|
||||||
"google.golang.org/grpc/codes"
|
"google.golang.org/grpc/codes"
|
||||||
@@ -83,36 +84,39 @@ func (s *Server) Song(ctx context.Context, req *v1.SongRequest) (*v1.SongRespons
|
|||||||
return nil, status.Errorf(codes.InvalidArgument, "hash is required and cant be empty")
|
return nil, status.Errorf(codes.InvalidArgument, "hash is required and cant be empty")
|
||||||
}
|
}
|
||||||
|
|
||||||
song, err := getSong(s.Db, hash)
|
song, err := s.Sqlc.GetBeatmapByHash(ctx, sql.NullString{Valid: true, String: hash})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Println(err)
|
fmt.Println(err)
|
||||||
return nil, status.Errorf(codes.NotFound, "beatmap not found by hash")
|
return nil, status.Errorf(codes.NotFound, "beatmap not found by hash")
|
||||||
}
|
}
|
||||||
|
|
||||||
return &v1.SongResponse{
|
return &v1.SongResponse{
|
||||||
Song: song.toProto(),
|
Song: toProtoSongSqlC(song),
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Server) Recent(ctx context.Context, req *v1.RecentRequest) (*v1.RecentResponse, error) {
|
func (s *Server) Recent(ctx context.Context, req *v1.RecentRequest) (*v1.RecentResponse, error) {
|
||||||
|
|
||||||
limit := defaultLimit(int(req.Limit))
|
limit := defaultLimit(int(req.Limit))
|
||||||
offset := int(req.Offset)
|
offset := int(req.Offset)
|
||||||
|
|
||||||
recent, err := getRecent(context.Background(), s.Sqlc, limit, offset)
|
rows, err := s.Sqlc.GetRecentBeatmaps(ctx, sqlcdb.GetRecentBeatmapsParams{
|
||||||
|
Limit: int64(limit),
|
||||||
|
Offset: int64(offset),
|
||||||
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Println(err)
|
fmt.Println(err)
|
||||||
return nil, status.Errorf(codes.Internal, "failed to get recents")
|
return nil, status.Errorf(codes.Internal, "failed to get recents")
|
||||||
}
|
}
|
||||||
|
|
||||||
return &v1.RecentResponse{
|
return &v1.RecentResponse{
|
||||||
Songs: toProtoSongs(recent),
|
Songs: toProtoSongsSqlC(rows),
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Server) Favorite(ctx context.Context, req *v1.FavoriteRequest) (*v1.FavoriteResponse, error) {
|
func (s *Server) Favorite(ctx context.Context, req *v1.FavoriteRequest) (*v1.FavoriteResponse, error) {
|
||||||
|
return nil, fmt.Errorf("not implemented!")
|
||||||
|
|
||||||
limit := defaultLimit(int(req.Limit))
|
/*limit := defaultLimit(int(req.Limit))
|
||||||
offset := int(req.Offset)
|
offset := int(req.Offset)
|
||||||
favorites, err := getFavorites(s.Db, req.Query, limit, offset)
|
favorites, err := getFavorites(s.Db, req.Query, limit, offset)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -123,6 +127,7 @@ func (s *Server) Favorite(ctx context.Context, req *v1.FavoriteRequest) (*v1.Fav
|
|||||||
return &v1.FavoriteResponse{
|
return &v1.FavoriteResponse{
|
||||||
Songs: toProtoSongs(favorites),
|
Songs: toProtoSongs(favorites),
|
||||||
}, nil
|
}, nil
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Server) Collections(ctx context.Context, req *v1.CollectionRequest) (*v1.CollectionResponse, error) {
|
func (s *Server) Collections(ctx context.Context, req *v1.CollectionRequest) (*v1.CollectionResponse, error) {
|
||||||
@@ -132,29 +137,32 @@ func (s *Server) Collections(ctx context.Context, req *v1.CollectionRequest) (*v
|
|||||||
|
|
||||||
name := req.Name
|
name := req.Name
|
||||||
if name != "" {
|
if name != "" {
|
||||||
c, err := getCollectionByName(s.Db, limit, offset, name)
|
c, err := s.Sqlc.GetCollectionByName(ctx,
|
||||||
|
sqlcdb.GetCollectionByNameParams{
|
||||||
|
Name: sql.NullString{Valid: true, String: name},
|
||||||
|
Limit: int64(limit),
|
||||||
|
Offset: int64(offset),
|
||||||
|
},
|
||||||
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Println(err)
|
fmt.Println(err)
|
||||||
return nil, status.Errorf(codes.Internal, fmt.Sprintf("failed to fetch collection with name: %s", name))
|
return nil, status.Errorf(codes.Internal, fmt.Sprintf("failed to fetch collection with name: %s", name))
|
||||||
}
|
}
|
||||||
return &v1.CollectionResponse{
|
|
||||||
Songs: toProtoSongs(c.Songs),
|
return toProtoCollectionSqlc(c), nil
|
||||||
Items: int32(c.Items),
|
|
||||||
Name: c.Name,
|
|
||||||
}, nil
|
|
||||||
}
|
}
|
||||||
fmt.Println(limit, offset, req.Index)
|
|
||||||
c, err := getCollection(s.Db, limit, offset, int(req.Index))
|
c, err := s.Sqlc.GetCollectionByOffset(ctx, sqlcdb.GetCollectionByOffsetParams{
|
||||||
|
Offset: int64(req.Index),
|
||||||
|
Limit: int64(limit),
|
||||||
|
Offset_2: int64(offset),
|
||||||
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Println(err)
|
fmt.Println(err)
|
||||||
return nil, status.Errorf(codes.Internal, fmt.Sprintf("failed to fetch collection with index: %d", req.Index))
|
return nil, status.Errorf(codes.Internal, fmt.Sprintf("failed to fetch collection with index: %d", req.Index))
|
||||||
}
|
}
|
||||||
fmt.Println(c)
|
|
||||||
return &v1.CollectionResponse{
|
return toProtoCollectionoffsetSqlc(c), nil
|
||||||
Songs: toProtoSongs(c.Songs),
|
|
||||||
Items: int32(c.Items),
|
|
||||||
Name: c.Name,
|
|
||||||
}, nil
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -163,38 +171,45 @@ func (s *Server) Search(ctx context.Context, req *v1.SearchSharedRequest) (*v1.S
|
|||||||
if q == "" {
|
if q == "" {
|
||||||
return nil, status.Error(codes.InvalidArgument, "query cant be empty")
|
return nil, status.Error(codes.InvalidArgument, "query cant be empty")
|
||||||
}
|
}
|
||||||
|
q = "%" + q + "%"
|
||||||
|
|
||||||
limit := defaultLimit(int(req.Limit))
|
limit := defaultLimit(int(req.Limit))
|
||||||
offset := int(req.Offset)
|
offset := int(req.Offset)
|
||||||
|
|
||||||
search, err := getSearch(s.Db, q, limit, offset)
|
search, err := s.Sqlc.SearchBeatmaps(ctx, sqlcdb.SearchBeatmapsParams{
|
||||||
|
Title: sql.NullString{String: q, Valid: true},
|
||||||
|
Artist: sql.NullString{String: q, Valid: true},
|
||||||
|
Limit: int64(limit),
|
||||||
|
Offset: int64(offset),
|
||||||
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Println(err)
|
fmt.Println(err)
|
||||||
return nil, status.Error(codes.Internal, "failed to fetch search")
|
return nil, status.Error(codes.Internal, "failed to fetch search")
|
||||||
}
|
}
|
||||||
|
|
||||||
return &v1.SearchSharedResponse{
|
return &v1.SearchSharedResponse{
|
||||||
Artist: search.Artist,
|
Artist: "",
|
||||||
Songs: toProtoSongs(search.Songs),
|
Songs: toProtoSongsSqlC(search),
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Server) SearchCollections(ctx context.Context, req *v1.SearchCollectionRequest) (*v1.SearchCollectionResponse, error) {
|
func (s *Server) SearchCollections(ctx context.Context, req *v1.SearchCollectionRequest) (*v1.SearchCollectionResponse, error) {
|
||||||
q := req.Query
|
q := req.Query
|
||||||
|
q = "%" + q + "%"
|
||||||
limit := defaultLimit(int(req.Limit))
|
//limit := defaultLimit(int(req.Limit))
|
||||||
|
limit := 10000
|
||||||
offset := int(req.Offset)
|
offset := int(req.Offset)
|
||||||
|
|
||||||
fmt.Println(req)
|
preview, err := s.Sqlc.SearchCollection(ctx, sqlcdb.SearchCollectionParams{
|
||||||
preview, err := getCollections(s.Db, q, limit, offset)
|
Name: sql.NullString{String: q, Valid: true},
|
||||||
|
Limit: int64(limit),
|
||||||
|
Offset: int64(offset),
|
||||||
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Println(err)
|
fmt.Println(err)
|
||||||
return nil, status.Errorf(codes.Internal, "failed to search for collections")
|
return nil, status.Errorf(codes.Internal, "failed to search for collections")
|
||||||
}
|
}
|
||||||
|
return toProtoCollectionsSearchPreview(preview), nil
|
||||||
return &v1.SearchCollectionResponse{
|
|
||||||
Collections: toProtoCollectionPreview(preview),
|
|
||||||
}, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Server) SearchArtists(ctx context.Context, req *v1.SearchArtistRequest) (*v1.SearchArtistResponse, error) {
|
func (s *Server) SearchArtists(ctx context.Context, req *v1.SearchArtistRequest) (*v1.SearchArtistResponse, error) {
|
||||||
@@ -206,13 +221,17 @@ func (s *Server) SearchArtists(ctx context.Context, req *v1.SearchArtistRequest)
|
|||||||
limit := defaultLimit(int(req.Limit))
|
limit := defaultLimit(int(req.Limit))
|
||||||
offset := int(req.Offset)
|
offset := int(req.Offset)
|
||||||
|
|
||||||
a, err := getArtists(s.Db, q, limit, offset)
|
_, err := s.Sqlc.SearchArtists(ctx, sqlcdb.SearchArtistsParams{
|
||||||
|
Artist: sql.NullString{Valid: true, String: q},
|
||||||
|
Limit: int64(limit),
|
||||||
|
Offset: int64(offset),
|
||||||
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Println(err)
|
fmt.Println(err)
|
||||||
return nil, status.Error(codes.Internal, "failed to search artists")
|
return nil, status.Error(codes.Internal, "failed to search artists")
|
||||||
}
|
}
|
||||||
return &v1.SearchArtistResponse{
|
return &v1.SearchArtistResponse{
|
||||||
Artists: toProtoArtist(a),
|
Artists: nil,
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -10,54 +10,6 @@ import (
|
|||||||
"database/sql"
|
"database/sql"
|
||||||
)
|
)
|
||||||
|
|
||||||
const getArtists = `-- name: GetArtists :many
|
|
||||||
SELECT Artist, COUNT(Artist) AS count
|
|
||||||
FROM Beatmap
|
|
||||||
WHERE Artist LIKE ? OR Title LIKE ?
|
|
||||||
GROUP BY Artist
|
|
||||||
LIMIT ? OFFSET ?
|
|
||||||
`
|
|
||||||
|
|
||||||
type GetArtistsParams struct {
|
|
||||||
Artist sql.NullString `json:"artist"`
|
|
||||||
Title sql.NullString `json:"title"`
|
|
||||||
Limit int64 `json:"limit"`
|
|
||||||
Offset int64 `json:"offset"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type GetArtistsRow struct {
|
|
||||||
Artist sql.NullString `json:"artist"`
|
|
||||||
Count int64 `json:"count"`
|
|
||||||
}
|
|
||||||
|
|
||||||
func (q *Queries) GetArtists(ctx context.Context, arg GetArtistsParams) ([]GetArtistsRow, error) {
|
|
||||||
rows, err := q.db.QueryContext(ctx, getArtists,
|
|
||||||
arg.Artist,
|
|
||||||
arg.Title,
|
|
||||||
arg.Limit,
|
|
||||||
arg.Offset,
|
|
||||||
)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
defer rows.Close()
|
|
||||||
items := []GetArtistsRow{}
|
|
||||||
for rows.Next() {
|
|
||||||
var i GetArtistsRow
|
|
||||||
if err := rows.Scan(&i.Artist, &i.Count); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
items = append(items, i)
|
|
||||||
}
|
|
||||||
if err := rows.Close(); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
if err := rows.Err(); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return items, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
const getBeatmapByHash = `-- name: GetBeatmapByHash :one
|
const getBeatmapByHash = `-- name: GetBeatmapByHash :one
|
||||||
SELECT beatmapid, artist, artistunicode, title, titleunicode, creator, difficulty, audio, md5hash, file, rankedstatus, lastmodifiedtime, totaltime, audiopreviewtime, beatmapsetid, source, tags, lastplayed, folder FROM Beatmap WHERE MD5Hash = ?
|
SELECT beatmapid, artist, artistunicode, title, titleunicode, creator, difficulty, audio, md5hash, file, rankedstatus, lastmodifiedtime, totaltime, audiopreviewtime, beatmapsetid, source, tags, lastplayed, folder FROM Beatmap WHERE MD5Hash = ?
|
||||||
`
|
`
|
||||||
@@ -100,8 +52,19 @@ func (q *Queries) GetBeatmapCount(ctx context.Context) (int64, error) {
|
|||||||
return count, err
|
return count, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const getBeatmapSetCount = `-- name: GetBeatmapSetCount :one
|
||||||
|
SELECT COUNT(*) FROM Beatmap GROUP BY BeatmapSetId
|
||||||
|
`
|
||||||
|
|
||||||
|
func (q *Queries) GetBeatmapSetCount(ctx context.Context) (int64, error) {
|
||||||
|
row := q.db.QueryRowContext(ctx, getBeatmapSetCount)
|
||||||
|
var count int64
|
||||||
|
err := row.Scan(&count)
|
||||||
|
return count, err
|
||||||
|
}
|
||||||
|
|
||||||
const getRecentBeatmaps = `-- name: GetRecentBeatmaps :many
|
const getRecentBeatmaps = `-- name: GetRecentBeatmaps :many
|
||||||
SELECT BeatmapId, MD5Hash, Title, Artist, Creator, Folder, File, Audio, TotalTime
|
SELECT beatmapid, artist, artistunicode, title, titleunicode, creator, difficulty, audio, md5hash, file, rankedstatus, lastmodifiedtime, totaltime, audiopreviewtime, beatmapsetid, source, tags, lastplayed, folder
|
||||||
FROM Beatmap GROUP BY Folder ORDER BY LastModifiedTime DESC LIMIT ? OFFSET ?
|
FROM Beatmap GROUP BY Folder ORDER BY LastModifiedTime DESC LIMIT ? OFFSET ?
|
||||||
`
|
`
|
||||||
|
|
||||||
@@ -110,37 +73,35 @@ type GetRecentBeatmapsParams struct {
|
|||||||
Offset int64 `json:"offset"`
|
Offset int64 `json:"offset"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type GetRecentBeatmapsRow struct {
|
func (q *Queries) GetRecentBeatmaps(ctx context.Context, arg GetRecentBeatmapsParams) ([]Beatmap, error) {
|
||||||
Beatmapid sql.NullInt64 `json:"beatmapid"`
|
|
||||||
Md5hash sql.NullString `json:"md5hash"`
|
|
||||||
Title sql.NullString `json:"title"`
|
|
||||||
Artist sql.NullString `json:"artist"`
|
|
||||||
Creator sql.NullString `json:"creator"`
|
|
||||||
Folder sql.NullString `json:"folder"`
|
|
||||||
File sql.NullString `json:"file"`
|
|
||||||
Audio sql.NullString `json:"audio"`
|
|
||||||
Totaltime sql.NullInt64 `json:"totaltime"`
|
|
||||||
}
|
|
||||||
|
|
||||||
func (q *Queries) GetRecentBeatmaps(ctx context.Context, arg GetRecentBeatmapsParams) ([]GetRecentBeatmapsRow, error) {
|
|
||||||
rows, err := q.db.QueryContext(ctx, getRecentBeatmaps, arg.Limit, arg.Offset)
|
rows, err := q.db.QueryContext(ctx, getRecentBeatmaps, arg.Limit, arg.Offset)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
defer rows.Close()
|
defer rows.Close()
|
||||||
items := []GetRecentBeatmapsRow{}
|
items := []Beatmap{}
|
||||||
for rows.Next() {
|
for rows.Next() {
|
||||||
var i GetRecentBeatmapsRow
|
var i Beatmap
|
||||||
if err := rows.Scan(
|
if err := rows.Scan(
|
||||||
&i.Beatmapid,
|
&i.Beatmapid,
|
||||||
&i.Md5hash,
|
|
||||||
&i.Title,
|
|
||||||
&i.Artist,
|
&i.Artist,
|
||||||
|
&i.Artistunicode,
|
||||||
|
&i.Title,
|
||||||
|
&i.Titleunicode,
|
||||||
&i.Creator,
|
&i.Creator,
|
||||||
&i.Folder,
|
&i.Difficulty,
|
||||||
&i.File,
|
|
||||||
&i.Audio,
|
&i.Audio,
|
||||||
|
&i.Md5hash,
|
||||||
|
&i.File,
|
||||||
|
&i.Rankedstatus,
|
||||||
|
&i.Lastmodifiedtime,
|
||||||
&i.Totaltime,
|
&i.Totaltime,
|
||||||
|
&i.Audiopreviewtime,
|
||||||
|
&i.Beatmapsetid,
|
||||||
|
&i.Source,
|
||||||
|
&i.Tags,
|
||||||
|
&i.Lastplayed,
|
||||||
|
&i.Folder,
|
||||||
); err != nil {
|
); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@@ -176,13 +137,13 @@ type InsertBeatmapParams struct {
|
|||||||
Md5hash sql.NullString `json:"md5hash"`
|
Md5hash sql.NullString `json:"md5hash"`
|
||||||
File sql.NullString `json:"file"`
|
File sql.NullString `json:"file"`
|
||||||
Rankedstatus sql.NullString `json:"rankedstatus"`
|
Rankedstatus sql.NullString `json:"rankedstatus"`
|
||||||
Lastmodifiedtime sql.NullTime `json:"lastmodifiedtime"`
|
Lastmodifiedtime sql.NullInt64 `json:"lastmodifiedtime"`
|
||||||
Totaltime sql.NullInt64 `json:"totaltime"`
|
Totaltime sql.NullInt64 `json:"totaltime"`
|
||||||
Audiopreviewtime sql.NullInt64 `json:"audiopreviewtime"`
|
Audiopreviewtime sql.NullInt64 `json:"audiopreviewtime"`
|
||||||
Beatmapsetid sql.NullInt64 `json:"beatmapsetid"`
|
Beatmapsetid sql.NullInt64 `json:"beatmapsetid"`
|
||||||
Source sql.NullString `json:"source"`
|
Source sql.NullString `json:"source"`
|
||||||
Tags sql.NullString `json:"tags"`
|
Tags sql.NullString `json:"tags"`
|
||||||
Lastplayed sql.NullTime `json:"lastplayed"`
|
Lastplayed sql.NullInt64 `json:"lastplayed"`
|
||||||
Folder sql.NullString `json:"folder"`
|
Folder sql.NullString `json:"folder"`
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -211,8 +172,56 @@ func (q *Queries) InsertBeatmap(ctx context.Context, arg InsertBeatmapParams) er
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const searchArtists = `-- name: SearchArtists :many
|
||||||
|
SELECT Artist, COUNT(Artist) AS count
|
||||||
|
FROM Beatmap
|
||||||
|
WHERE Artist LIKE ? OR Title LIKE ?
|
||||||
|
GROUP BY Artist
|
||||||
|
LIMIT ? OFFSET ?
|
||||||
|
`
|
||||||
|
|
||||||
|
type SearchArtistsParams struct {
|
||||||
|
Artist sql.NullString `json:"artist"`
|
||||||
|
Title sql.NullString `json:"title"`
|
||||||
|
Limit int64 `json:"limit"`
|
||||||
|
Offset int64 `json:"offset"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type SearchArtistsRow struct {
|
||||||
|
Artist sql.NullString `json:"artist"`
|
||||||
|
Count int64 `json:"count"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (q *Queries) SearchArtists(ctx context.Context, arg SearchArtistsParams) ([]SearchArtistsRow, error) {
|
||||||
|
rows, err := q.db.QueryContext(ctx, searchArtists,
|
||||||
|
arg.Artist,
|
||||||
|
arg.Title,
|
||||||
|
arg.Limit,
|
||||||
|
arg.Offset,
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
defer rows.Close()
|
||||||
|
items := []SearchArtistsRow{}
|
||||||
|
for rows.Next() {
|
||||||
|
var i SearchArtistsRow
|
||||||
|
if err := rows.Scan(&i.Artist, &i.Count); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
items = append(items, i)
|
||||||
|
}
|
||||||
|
if err := rows.Close(); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if err := rows.Err(); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return items, nil
|
||||||
|
}
|
||||||
|
|
||||||
const searchBeatmaps = `-- name: SearchBeatmaps :many
|
const searchBeatmaps = `-- name: SearchBeatmaps :many
|
||||||
SELECT BeatmapId, MD5Hash, Title, Artist, Creator, Folder, File, Audio, TotalTime
|
SELECT beatmapid, artist, artistunicode, title, titleunicode, creator, difficulty, audio, md5hash, file, rankedstatus, lastmodifiedtime, totaltime, audiopreviewtime, beatmapsetid, source, tags, lastplayed, folder
|
||||||
FROM Beatmap
|
FROM Beatmap
|
||||||
WHERE Title LIKE ? OR Artist LIKE ?
|
WHERE Title LIKE ? OR Artist LIKE ?
|
||||||
LIMIT ? OFFSET ?
|
LIMIT ? OFFSET ?
|
||||||
@@ -225,19 +234,7 @@ type SearchBeatmapsParams struct {
|
|||||||
Offset int64 `json:"offset"`
|
Offset int64 `json:"offset"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type SearchBeatmapsRow struct {
|
func (q *Queries) SearchBeatmaps(ctx context.Context, arg SearchBeatmapsParams) ([]Beatmap, error) {
|
||||||
Beatmapid sql.NullInt64 `json:"beatmapid"`
|
|
||||||
Md5hash sql.NullString `json:"md5hash"`
|
|
||||||
Title sql.NullString `json:"title"`
|
|
||||||
Artist sql.NullString `json:"artist"`
|
|
||||||
Creator sql.NullString `json:"creator"`
|
|
||||||
Folder sql.NullString `json:"folder"`
|
|
||||||
File sql.NullString `json:"file"`
|
|
||||||
Audio sql.NullString `json:"audio"`
|
|
||||||
Totaltime sql.NullInt64 `json:"totaltime"`
|
|
||||||
}
|
|
||||||
|
|
||||||
func (q *Queries) SearchBeatmaps(ctx context.Context, arg SearchBeatmapsParams) ([]SearchBeatmapsRow, error) {
|
|
||||||
rows, err := q.db.QueryContext(ctx, searchBeatmaps,
|
rows, err := q.db.QueryContext(ctx, searchBeatmaps,
|
||||||
arg.Title,
|
arg.Title,
|
||||||
arg.Artist,
|
arg.Artist,
|
||||||
@@ -248,19 +245,29 @@ func (q *Queries) SearchBeatmaps(ctx context.Context, arg SearchBeatmapsParams)
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
defer rows.Close()
|
defer rows.Close()
|
||||||
items := []SearchBeatmapsRow{}
|
items := []Beatmap{}
|
||||||
for rows.Next() {
|
for rows.Next() {
|
||||||
var i SearchBeatmapsRow
|
var i Beatmap
|
||||||
if err := rows.Scan(
|
if err := rows.Scan(
|
||||||
&i.Beatmapid,
|
&i.Beatmapid,
|
||||||
&i.Md5hash,
|
|
||||||
&i.Title,
|
|
||||||
&i.Artist,
|
&i.Artist,
|
||||||
|
&i.Artistunicode,
|
||||||
|
&i.Title,
|
||||||
|
&i.Titleunicode,
|
||||||
&i.Creator,
|
&i.Creator,
|
||||||
&i.Folder,
|
&i.Difficulty,
|
||||||
&i.File,
|
|
||||||
&i.Audio,
|
&i.Audio,
|
||||||
|
&i.Md5hash,
|
||||||
|
&i.File,
|
||||||
|
&i.Rankedstatus,
|
||||||
|
&i.Lastmodifiedtime,
|
||||||
&i.Totaltime,
|
&i.Totaltime,
|
||||||
|
&i.Audiopreviewtime,
|
||||||
|
&i.Beatmapsetid,
|
||||||
|
&i.Source,
|
||||||
|
&i.Tags,
|
||||||
|
&i.Lastplayed,
|
||||||
|
&i.Folder,
|
||||||
); err != nil {
|
); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,82 +10,6 @@ import (
|
|||||||
"database/sql"
|
"database/sql"
|
||||||
)
|
)
|
||||||
|
|
||||||
const getCollection = `-- name: GetCollection :many
|
|
||||||
SELECT
|
|
||||||
c.Name,
|
|
||||||
b.BeatmapId,
|
|
||||||
b.MD5Hash,
|
|
||||||
b.Title,
|
|
||||||
b.Artist,
|
|
||||||
b.Creator,
|
|
||||||
b.Folder,
|
|
||||||
b.File,
|
|
||||||
b.Audio,
|
|
||||||
b.TotalTime
|
|
||||||
FROM Collection c
|
|
||||||
JOIN Beatmap b ON c.MD5Hash = b.MD5Hash
|
|
||||||
JOIN (
|
|
||||||
SELECT DISTINCT Name
|
|
||||||
FROM Collection
|
|
||||||
ORDER BY Name
|
|
||||||
LIMIT 1 OFFSET ?
|
|
||||||
) selected_name ON c.Name = selected_name.Name
|
|
||||||
LIMIT ? OFFSET ?
|
|
||||||
`
|
|
||||||
|
|
||||||
type GetCollectionParams struct {
|
|
||||||
Offset int64 `json:"offset"`
|
|
||||||
Limit int64 `json:"limit"`
|
|
||||||
Offset_2 int64 `json:"offset_2"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type GetCollectionRow struct {
|
|
||||||
Name sql.NullString `json:"name"`
|
|
||||||
Beatmapid sql.NullInt64 `json:"beatmapid"`
|
|
||||||
Md5hash sql.NullString `json:"md5hash"`
|
|
||||||
Title sql.NullString `json:"title"`
|
|
||||||
Artist sql.NullString `json:"artist"`
|
|
||||||
Creator sql.NullString `json:"creator"`
|
|
||||||
Folder sql.NullString `json:"folder"`
|
|
||||||
File sql.NullString `json:"file"`
|
|
||||||
Audio sql.NullString `json:"audio"`
|
|
||||||
Totaltime sql.NullInt64 `json:"totaltime"`
|
|
||||||
}
|
|
||||||
|
|
||||||
func (q *Queries) GetCollection(ctx context.Context, arg GetCollectionParams) ([]GetCollectionRow, error) {
|
|
||||||
rows, err := q.db.QueryContext(ctx, getCollection, arg.Offset, arg.Limit, arg.Offset_2)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
defer rows.Close()
|
|
||||||
items := []GetCollectionRow{}
|
|
||||||
for rows.Next() {
|
|
||||||
var i GetCollectionRow
|
|
||||||
if err := rows.Scan(
|
|
||||||
&i.Name,
|
|
||||||
&i.Beatmapid,
|
|
||||||
&i.Md5hash,
|
|
||||||
&i.Title,
|
|
||||||
&i.Artist,
|
|
||||||
&i.Creator,
|
|
||||||
&i.Folder,
|
|
||||||
&i.File,
|
|
||||||
&i.Audio,
|
|
||||||
&i.Totaltime,
|
|
||||||
); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
items = append(items, i)
|
|
||||||
}
|
|
||||||
if err := rows.Close(); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
if err := rows.Err(); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return items, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
const getCollectionByName = `-- name: GetCollectionByName :many
|
const getCollectionByName = `-- name: GetCollectionByName :many
|
||||||
SELECT c.Name, b.BeatmapId, b.MD5Hash, b.Title, b.Artist, b.Creator, b.Folder, b.File, b.Audio, b.TotalTime
|
SELECT c.Name, b.BeatmapId, b.MD5Hash, b.Title, b.Artist, b.Creator, b.Folder, b.File, b.Audio, b.TotalTime
|
||||||
FROM Collection c
|
FROM Collection c
|
||||||
@@ -147,6 +71,83 @@ func (q *Queries) GetCollectionByName(ctx context.Context, arg GetCollectionByNa
|
|||||||
return items, nil
|
return items, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const getCollectionByOffset = `-- name: GetCollectionByOffset :many
|
||||||
|
SELECT
|
||||||
|
c.Name,
|
||||||
|
b.BeatmapId,
|
||||||
|
b.MD5Hash,
|
||||||
|
b.Title,
|
||||||
|
b.Artist,
|
||||||
|
b.Creator,
|
||||||
|
b.Folder,
|
||||||
|
b.File,
|
||||||
|
b.Audio,
|
||||||
|
b.TotalTime
|
||||||
|
FROM Collection c
|
||||||
|
JOIN Beatmap b ON c.MD5Hash = b.MD5Hash
|
||||||
|
WHERE c.Name = (
|
||||||
|
SELECT Name
|
||||||
|
FROM Collection
|
||||||
|
GROUP BY Name
|
||||||
|
ORDER BY Name
|
||||||
|
LIMIT 1 OFFSET ?1
|
||||||
|
)
|
||||||
|
LIMIT ?2 OFFSET ?3
|
||||||
|
`
|
||||||
|
|
||||||
|
type GetCollectionByOffsetParams struct {
|
||||||
|
Offset int64 `json:"offset"`
|
||||||
|
Limit int64 `json:"limit"`
|
||||||
|
Offset_2 int64 `json:"offset_2"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type GetCollectionByOffsetRow struct {
|
||||||
|
Name sql.NullString `json:"name"`
|
||||||
|
Beatmapid sql.NullInt64 `json:"beatmapid"`
|
||||||
|
Md5hash sql.NullString `json:"md5hash"`
|
||||||
|
Title sql.NullString `json:"title"`
|
||||||
|
Artist sql.NullString `json:"artist"`
|
||||||
|
Creator sql.NullString `json:"creator"`
|
||||||
|
Folder sql.NullString `json:"folder"`
|
||||||
|
File sql.NullString `json:"file"`
|
||||||
|
Audio sql.NullString `json:"audio"`
|
||||||
|
Totaltime sql.NullInt64 `json:"totaltime"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (q *Queries) GetCollectionByOffset(ctx context.Context, arg GetCollectionByOffsetParams) ([]GetCollectionByOffsetRow, error) {
|
||||||
|
rows, err := q.db.QueryContext(ctx, getCollectionByOffset, arg.Offset, arg.Limit, arg.Offset_2)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
defer rows.Close()
|
||||||
|
items := []GetCollectionByOffsetRow{}
|
||||||
|
for rows.Next() {
|
||||||
|
var i GetCollectionByOffsetRow
|
||||||
|
if err := rows.Scan(
|
||||||
|
&i.Name,
|
||||||
|
&i.Beatmapid,
|
||||||
|
&i.Md5hash,
|
||||||
|
&i.Title,
|
||||||
|
&i.Artist,
|
||||||
|
&i.Creator,
|
||||||
|
&i.Folder,
|
||||||
|
&i.File,
|
||||||
|
&i.Audio,
|
||||||
|
&i.Totaltime,
|
||||||
|
); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
items = append(items, i)
|
||||||
|
}
|
||||||
|
if err := rows.Close(); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if err := rows.Err(); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return items, nil
|
||||||
|
}
|
||||||
|
|
||||||
const getCollectionCountByName = `-- name: GetCollectionCountByName :one
|
const getCollectionCountByName = `-- name: GetCollectionCountByName :one
|
||||||
SELECT COUNT(*) FROM Collection WHERE Name = ?
|
SELECT COUNT(*) FROM Collection WHERE Name = ?
|
||||||
`
|
`
|
||||||
@@ -158,37 +159,55 @@ func (q *Queries) GetCollectionCountByName(ctx context.Context, name sql.NullStr
|
|||||||
return count, err
|
return count, err
|
||||||
}
|
}
|
||||||
|
|
||||||
const getCollections = `-- name: GetCollections :many
|
const insertCollection = `-- name: InsertCollection :exec
|
||||||
SELECT c.Name, COUNT(b.MD5Hash) AS Count, MIN(b.Folder) AS Folder, MIN(b.File) AS File
|
INSERT INTO Collection (Name, MD5Hash) VALUES (?, ?)
|
||||||
FROM Collection c
|
`
|
||||||
|
|
||||||
|
type InsertCollectionParams struct {
|
||||||
|
Name sql.NullString `json:"name"`
|
||||||
|
Md5hash sql.NullString `json:"md5hash"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (q *Queries) InsertCollection(ctx context.Context, arg InsertCollectionParams) error {
|
||||||
|
_, err := q.db.ExecContext(ctx, insertCollection, arg.Name, arg.Md5hash)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
const searchCollection = `-- name: SearchCollection :many
|
||||||
|
SELECT
|
||||||
|
c.Name,
|
||||||
|
COUNT(b.MD5Hash) AS Count,
|
||||||
|
b.Folder,
|
||||||
|
b.File
|
||||||
|
FROM Collection c
|
||||||
JOIN Beatmap b ON c.MD5Hash = b.MD5Hash
|
JOIN Beatmap b ON c.MD5Hash = b.MD5Hash
|
||||||
WHERE c.Name LIKE ?
|
WHERE c.Name LIKE ?
|
||||||
GROUP BY c.Name
|
GROUP BY c.Name
|
||||||
LIMIT ? OFFSET ?
|
LIMIT ? OFFSET ?
|
||||||
`
|
`
|
||||||
|
|
||||||
type GetCollectionsParams struct {
|
type SearchCollectionParams struct {
|
||||||
Name sql.NullString `json:"name"`
|
Name sql.NullString `json:"name"`
|
||||||
Limit int64 `json:"limit"`
|
Limit int64 `json:"limit"`
|
||||||
Offset int64 `json:"offset"`
|
Offset int64 `json:"offset"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type GetCollectionsRow struct {
|
type SearchCollectionRow struct {
|
||||||
Name sql.NullString `json:"name"`
|
Name sql.NullString `json:"name"`
|
||||||
Count int64 `json:"count"`
|
Count int64 `json:"count"`
|
||||||
Folder interface{} `json:"folder"`
|
Folder sql.NullString `json:"folder"`
|
||||||
File interface{} `json:"file"`
|
File sql.NullString `json:"file"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (q *Queries) GetCollections(ctx context.Context, arg GetCollectionsParams) ([]GetCollectionsRow, error) {
|
func (q *Queries) SearchCollection(ctx context.Context, arg SearchCollectionParams) ([]SearchCollectionRow, error) {
|
||||||
rows, err := q.db.QueryContext(ctx, getCollections, arg.Name, arg.Limit, arg.Offset)
|
rows, err := q.db.QueryContext(ctx, searchCollection, arg.Name, arg.Limit, arg.Offset)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
defer rows.Close()
|
defer rows.Close()
|
||||||
items := []GetCollectionsRow{}
|
items := []SearchCollectionRow{}
|
||||||
for rows.Next() {
|
for rows.Next() {
|
||||||
var i GetCollectionsRow
|
var i SearchCollectionRow
|
||||||
if err := rows.Scan(
|
if err := rows.Scan(
|
||||||
&i.Name,
|
&i.Name,
|
||||||
&i.Count,
|
&i.Count,
|
||||||
@@ -207,17 +226,3 @@ func (q *Queries) GetCollections(ctx context.Context, arg GetCollectionsParams)
|
|||||||
}
|
}
|
||||||
return items, nil
|
return items, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
const insertCollection = `-- name: InsertCollection :exec
|
|
||||||
INSERT INTO Collection (Name, MD5Hash) VALUES (?, ?)
|
|
||||||
`
|
|
||||||
|
|
||||||
type InsertCollectionParams struct {
|
|
||||||
Name sql.NullString `json:"name"`
|
|
||||||
Md5hash sql.NullString `json:"md5hash"`
|
|
||||||
}
|
|
||||||
|
|
||||||
func (q *Queries) InsertCollection(ctx context.Context, arg InsertCollectionParams) error {
|
|
||||||
_, err := q.db.ExecContext(ctx, insertCollection, arg.Name, arg.Md5hash)
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -20,13 +20,13 @@ type Beatmap struct {
|
|||||||
Md5hash sql.NullString `json:"md5hash"`
|
Md5hash sql.NullString `json:"md5hash"`
|
||||||
File sql.NullString `json:"file"`
|
File sql.NullString `json:"file"`
|
||||||
Rankedstatus sql.NullString `json:"rankedstatus"`
|
Rankedstatus sql.NullString `json:"rankedstatus"`
|
||||||
Lastmodifiedtime sql.NullTime `json:"lastmodifiedtime"`
|
Lastmodifiedtime sql.NullInt64 `json:"lastmodifiedtime"`
|
||||||
Totaltime sql.NullInt64 `json:"totaltime"`
|
Totaltime sql.NullInt64 `json:"totaltime"`
|
||||||
Audiopreviewtime sql.NullInt64 `json:"audiopreviewtime"`
|
Audiopreviewtime sql.NullInt64 `json:"audiopreviewtime"`
|
||||||
Beatmapsetid sql.NullInt64 `json:"beatmapsetid"`
|
Beatmapsetid sql.NullInt64 `json:"beatmapsetid"`
|
||||||
Source sql.NullString `json:"source"`
|
Source sql.NullString `json:"source"`
|
||||||
Tags sql.NullString `json:"tags"`
|
Tags sql.NullString `json:"tags"`
|
||||||
Lastplayed sql.NullTime `json:"lastplayed"`
|
Lastplayed sql.NullInt64 `json:"lastplayed"`
|
||||||
Folder sql.NullString `json:"folder"`
|
Folder sql.NullString `json:"folder"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -10,17 +10,18 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type Querier interface {
|
type Querier interface {
|
||||||
GetArtists(ctx context.Context, arg GetArtistsParams) ([]GetArtistsRow, error)
|
|
||||||
GetBeatmapByHash(ctx context.Context, md5hash sql.NullString) (Beatmap, error)
|
GetBeatmapByHash(ctx context.Context, md5hash sql.NullString) (Beatmap, error)
|
||||||
GetBeatmapCount(ctx context.Context) (int64, error)
|
GetBeatmapCount(ctx context.Context) (int64, error)
|
||||||
GetCollection(ctx context.Context, arg GetCollectionParams) ([]GetCollectionRow, error)
|
GetBeatmapSetCount(ctx context.Context) (int64, error)
|
||||||
GetCollectionByName(ctx context.Context, arg GetCollectionByNameParams) ([]GetCollectionByNameRow, error)
|
GetCollectionByName(ctx context.Context, arg GetCollectionByNameParams) ([]GetCollectionByNameRow, error)
|
||||||
|
GetCollectionByOffset(ctx context.Context, arg GetCollectionByOffsetParams) ([]GetCollectionByOffsetRow, error)
|
||||||
GetCollectionCountByName(ctx context.Context, name sql.NullString) (int64, error)
|
GetCollectionCountByName(ctx context.Context, name sql.NullString) (int64, error)
|
||||||
GetCollections(ctx context.Context, arg GetCollectionsParams) ([]GetCollectionsRow, error)
|
GetRecentBeatmaps(ctx context.Context, arg GetRecentBeatmapsParams) ([]Beatmap, error)
|
||||||
GetRecentBeatmaps(ctx context.Context, arg GetRecentBeatmapsParams) ([]GetRecentBeatmapsRow, error)
|
|
||||||
InsertBeatmap(ctx context.Context, arg InsertBeatmapParams) error
|
InsertBeatmap(ctx context.Context, arg InsertBeatmapParams) error
|
||||||
InsertCollection(ctx context.Context, arg InsertCollectionParams) error
|
InsertCollection(ctx context.Context, arg InsertCollectionParams) error
|
||||||
SearchBeatmaps(ctx context.Context, arg SearchBeatmapsParams) ([]SearchBeatmapsRow, error)
|
SearchArtists(ctx context.Context, arg SearchArtistsParams) ([]SearchArtistsRow, error)
|
||||||
|
SearchBeatmaps(ctx context.Context, arg SearchBeatmapsParams) ([]Beatmap, error)
|
||||||
|
SearchCollection(ctx context.Context, arg SearchCollectionParams) ([]SearchCollectionRow, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
var _ Querier = (*Queries)(nil)
|
var _ Querier = (*Queries)(nil)
|
||||||
|
|||||||
@@ -1,125 +0,0 @@
|
|||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
v1 "backend/gen"
|
|
||||||
"backend/internal/db"
|
|
||||||
"fmt"
|
|
||||||
)
|
|
||||||
|
|
||||||
type Song struct {
|
|
||||||
BeatmapID int `json:"beatmap_id" example:"123456"`
|
|
||||||
MD5Hash string `json:"md5_hash" example:"abcd1234efgh5678"`
|
|
||||||
Title string `json:"title" example:"Shape of You"`
|
|
||||||
Artist string `json:"artist" example:"Ed Sheeran"`
|
|
||||||
Creator string `json:"creator" example:"JohnDoe"`
|
|
||||||
Folder string `json:"folder" example:"osu/Songs/123456"`
|
|
||||||
File string `json:"file" example:"beatmap.osu"`
|
|
||||||
Audio string `json:"audio" example:"audio.mp3"`
|
|
||||||
TotalTime int64 `json:"total_time" example:"240"`
|
|
||||||
Image string `json:"image" example:"cover.jpg"`
|
|
||||||
}
|
|
||||||
|
|
||||||
func (song Song) toProto() *v1.Song {
|
|
||||||
return &v1.Song{
|
|
||||||
BeatmapId: int32(song.BeatmapID),
|
|
||||||
Md5Hash: song.MD5Hash,
|
|
||||||
Title: song.Title,
|
|
||||||
Artist: song.Artist,
|
|
||||||
Creator: song.Creator,
|
|
||||||
Folder: song.Folder,
|
|
||||||
File: song.File,
|
|
||||||
Audio: song.Audio,
|
|
||||||
TotalTime: song.TotalTime,
|
|
||||||
Image: song.Image,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// The function `toSongProto` converts a `db.Beatmap` struct into a `v1.Song` struct by mapping the
|
|
||||||
// fields and performing some data type conversions.
|
|
||||||
func toSongProto(song db.Beatmap) *v1.Song {
|
|
||||||
fmt.Println(song)
|
|
||||||
return &v1.Song{
|
|
||||||
BeatmapId: int32(safeInt64(song.Beatmapid)),
|
|
||||||
Md5Hash: safeString(song.Md5hash),
|
|
||||||
Title: safeString(song.Title),
|
|
||||||
Artist: safeString(song.Artist),
|
|
||||||
Creator: safeString(song.Creator),
|
|
||||||
Folder: safeString(song.Folder),
|
|
||||||
File: safeString(song.File),
|
|
||||||
Audio: safeString(song.Audio),
|
|
||||||
TotalTime: int64(safeInt64(song.Totaltime)),
|
|
||||||
Image: extractImageFromFile(osuRoot, safeString(song.Folder), safeString(song.File)),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func toProtoSongs(local []Song) []*v1.Song {
|
|
||||||
songs := make([]*v1.Song, len(local))
|
|
||||||
for i, s := range local {
|
|
||||||
songs[i] = s.toProto()
|
|
||||||
}
|
|
||||||
|
|
||||||
return songs
|
|
||||||
}
|
|
||||||
|
|
||||||
// CollectionPreview represents a preview of a song collection
|
|
||||||
// @Description CollectionPreview contains summary data of a song collection
|
|
||||||
type CollectionPreview struct {
|
|
||||||
Name string `json:"name" example:"Collection Name"`
|
|
||||||
Image string `json:"image" example:"cover.jpg"`
|
|
||||||
Items int `json:"items" example:"10"`
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c CollectionPreview) toProto() *v1.CollectionPreview {
|
|
||||||
return &v1.CollectionPreview{
|
|
||||||
Name: c.Name,
|
|
||||||
Image: c.Image,
|
|
||||||
Items: int32(c.Items),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func toProtoCollectionPreview(local []CollectionPreview) []*v1.CollectionPreview {
|
|
||||||
collection := make([]*v1.CollectionPreview, len(local))
|
|
||||||
for i, c := range local {
|
|
||||||
collection[i] = c.toProto()
|
|
||||||
}
|
|
||||||
|
|
||||||
return collection
|
|
||||||
}
|
|
||||||
|
|
||||||
// Collection represents a full song collection
|
|
||||||
// @Description Collection holds a list of songs
|
|
||||||
type Collection struct {
|
|
||||||
Name string `json:"name" example:"Best of 2023"`
|
|
||||||
Items int `json:"items" example:"15"`
|
|
||||||
Songs []Song `json:"songs"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// ActiveSearch represents an active song search query
|
|
||||||
// @Description ActiveSearch holds search results for a given artist
|
|
||||||
type ActiveSearch struct {
|
|
||||||
Artist string `json:"artist" example:"Ed Sheeran"`
|
|
||||||
Songs []Song `json:"songs"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// Artist represents an active song search query
|
|
||||||
// @Description Artist holds search results for a given artist
|
|
||||||
type Artist struct {
|
|
||||||
Artist string `json:"artist" example:"Miku"`
|
|
||||||
Count int `json:"count" example:"21"`
|
|
||||||
}
|
|
||||||
|
|
||||||
func (a Artist) toProto() *v1.Artist {
|
|
||||||
return &v1.Artist{
|
|
||||||
Artist: a.Artist,
|
|
||||||
Items: int32(a.Count),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func toProtoArtist(local []Artist) []*v1.Artist {
|
|
||||||
artists := make([]*v1.Artist, len(local))
|
|
||||||
for i, a := range local {
|
|
||||||
artists[i] = a.toProto()
|
|
||||||
}
|
|
||||||
|
|
||||||
return artists
|
|
||||||
}
|
|
||||||
@@ -12,3 +12,6 @@ sql:
|
|||||||
emit_json_tags: true
|
emit_json_tags: true
|
||||||
emit_interface: true
|
emit_interface: true
|
||||||
emit_empty_slices: true
|
emit_empty_slices: true
|
||||||
|
overrides:
|
||||||
|
- db_type: "INTEGER"
|
||||||
|
go_type: "int"
|
||||||
@@ -12,17 +12,20 @@ SELECT * FROM Beatmap WHERE MD5Hash = ?;
|
|||||||
-- name: GetBeatmapCount :one
|
-- name: GetBeatmapCount :one
|
||||||
SELECT COUNT(*) FROM Beatmap;
|
SELECT COUNT(*) FROM Beatmap;
|
||||||
|
|
||||||
|
-- name: GetBeatmapSetCount :one
|
||||||
|
SELECT COUNT(*) FROM Beatmap GROUP BY BeatmapSetId;
|
||||||
|
|
||||||
-- name: GetRecentBeatmaps :many
|
-- name: GetRecentBeatmaps :many
|
||||||
SELECT BeatmapId, MD5Hash, Title, Artist, Creator, Folder, File, Audio, TotalTime
|
SELECT *
|
||||||
FROM Beatmap GROUP BY Folder ORDER BY LastModifiedTime DESC LIMIT ? OFFSET ?;
|
FROM Beatmap GROUP BY Folder ORDER BY LastModifiedTime DESC LIMIT ? OFFSET ?;
|
||||||
|
|
||||||
-- name: SearchBeatmaps :many
|
-- name: SearchBeatmaps :many
|
||||||
SELECT BeatmapId, MD5Hash, Title, Artist, Creator, Folder, File, Audio, TotalTime
|
SELECT *
|
||||||
FROM Beatmap
|
FROM Beatmap
|
||||||
WHERE Title LIKE ? OR Artist LIKE ?
|
WHERE Title LIKE ? OR Artist LIKE ?
|
||||||
LIMIT ? OFFSET ?;
|
LIMIT ? OFFSET ?;
|
||||||
|
|
||||||
-- name: GetArtists :many
|
-- name: SearchArtists :many
|
||||||
SELECT Artist, COUNT(Artist) AS count
|
SELECT Artist, COUNT(Artist) AS count
|
||||||
FROM Beatmap
|
FROM Beatmap
|
||||||
WHERE Artist LIKE ? OR Title LIKE ?
|
WHERE Artist LIKE ? OR Title LIKE ?
|
||||||
|
|||||||
@@ -4,15 +4,19 @@ INSERT INTO Collection (Name, MD5Hash) VALUES (?, ?);
|
|||||||
-- name: GetCollectionCountByName :one
|
-- name: GetCollectionCountByName :one
|
||||||
SELECT COUNT(*) FROM Collection WHERE Name = ?;
|
SELECT COUNT(*) FROM Collection WHERE Name = ?;
|
||||||
|
|
||||||
-- name: GetCollections :many
|
-- name: SearchCollection :many
|
||||||
SELECT c.Name, COUNT(b.MD5Hash) AS Count, MIN(b.Folder) AS Folder, MIN(b.File) AS File
|
SELECT
|
||||||
FROM Collection c
|
c.Name,
|
||||||
|
COUNT(b.MD5Hash) AS Count,
|
||||||
|
b.Folder,
|
||||||
|
b.File
|
||||||
|
FROM Collection c
|
||||||
JOIN Beatmap b ON c.MD5Hash = b.MD5Hash
|
JOIN Beatmap b ON c.MD5Hash = b.MD5Hash
|
||||||
WHERE c.Name LIKE ?
|
WHERE c.Name LIKE ?
|
||||||
GROUP BY c.Name
|
GROUP BY c.Name
|
||||||
LIMIT ? OFFSET ?;
|
LIMIT ? OFFSET ?;
|
||||||
|
|
||||||
-- name: GetCollection :many
|
-- name: GetCollectionByOffset :many
|
||||||
SELECT
|
SELECT
|
||||||
c.Name,
|
c.Name,
|
||||||
b.BeatmapId,
|
b.BeatmapId,
|
||||||
@@ -26,13 +30,14 @@ SELECT
|
|||||||
b.TotalTime
|
b.TotalTime
|
||||||
FROM Collection c
|
FROM Collection c
|
||||||
JOIN Beatmap b ON c.MD5Hash = b.MD5Hash
|
JOIN Beatmap b ON c.MD5Hash = b.MD5Hash
|
||||||
JOIN (
|
WHERE c.Name = (
|
||||||
SELECT DISTINCT Name
|
SELECT Name
|
||||||
FROM Collection
|
FROM Collection
|
||||||
|
GROUP BY Name
|
||||||
ORDER BY Name
|
ORDER BY Name
|
||||||
LIMIT 1 OFFSET ?
|
LIMIT 1 OFFSET ?1
|
||||||
) selected_name ON c.Name = selected_name.Name
|
)
|
||||||
LIMIT ? OFFSET ?;
|
LIMIT ?2 OFFSET ?3;
|
||||||
|
|
||||||
-- name: GetCollectionByName :many
|
-- name: GetCollectionByName :many
|
||||||
SELECT c.Name, b.BeatmapId, b.MD5Hash, b.Title, b.Artist, b.Creator, b.Folder, b.File, b.Audio, b.TotalTime
|
SELECT c.Name, b.BeatmapId, b.MD5Hash, b.Title, b.Artist, b.Creator, b.Folder, b.File, b.Audio, b.TotalTime
|
||||||
|
|||||||
@@ -11,13 +11,13 @@ CREATE TABLE IF NOT EXISTS Beatmap (
|
|||||||
MD5Hash TEXT DEFAULT '00000000000000000000000000000000',
|
MD5Hash TEXT DEFAULT '00000000000000000000000000000000',
|
||||||
File TEXT DEFAULT 'unknown.osu',
|
File TEXT DEFAULT 'unknown.osu',
|
||||||
RankedStatus TEXT DEFAULT 'Unknown',
|
RankedStatus TEXT DEFAULT 'Unknown',
|
||||||
LastModifiedTime DATETIME DEFAULT '0001-01-01 00:00:00',
|
LastModifiedTime INTEGER DEFAULT 0,
|
||||||
TotalTime INTEGER DEFAULT 0,
|
TotalTime INTEGER DEFAULT 0,
|
||||||
AudioPreviewTime INTEGER DEFAULT 0,
|
AudioPreviewTime INTEGER DEFAULT 0,
|
||||||
BeatmapSetId INTEGER DEFAULT -1,
|
BeatmapSetId INTEGER DEFAULT -1,
|
||||||
Source TEXT DEFAULT '',
|
Source TEXT DEFAULT '',
|
||||||
Tags TEXT DEFAULT '',
|
Tags TEXT DEFAULT '',
|
||||||
LastPlayed DATETIME DEFAULT '0001-01-01 00:00:00',
|
LastPlayed INTEGER DEFAULT 0,
|
||||||
Folder TEXT DEFAULT 'Unknown Folder',
|
Folder TEXT DEFAULT 'Unknown Folder',
|
||||||
UNIQUE (Artist, Title, MD5Hash, Difficulty)
|
UNIQUE (Artist, Title, MD5Hash, Difficulty)
|
||||||
);
|
);
|
||||||
|
|||||||
96
grpc-backend/sqlc_converters.go
Normal file
96
grpc-backend/sqlc_converters.go
Normal file
@@ -0,0 +1,96 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
v1 "backend/gen"
|
||||||
|
"backend/internal/db"
|
||||||
|
)
|
||||||
|
|
||||||
|
func toProtoSongsSqlC(songs []db.Beatmap) []*v1.Song {
|
||||||
|
protoSongs := make([]*v1.Song, len(songs))
|
||||||
|
for i, s := range songs {
|
||||||
|
protoSongs[i] = toProtoSongSqlC(s)
|
||||||
|
}
|
||||||
|
|
||||||
|
return protoSongs
|
||||||
|
}
|
||||||
|
|
||||||
|
func toProtoSongSqlC(song db.Beatmap) *v1.Song {
|
||||||
|
return &v1.Song{
|
||||||
|
BeatmapId: int32(song.Beatmapid.Int64),
|
||||||
|
Md5Hash: song.Md5hash.String,
|
||||||
|
Title: song.Title.String,
|
||||||
|
Artist: song.Artist.String,
|
||||||
|
Creator: song.Creator.String,
|
||||||
|
Folder: song.Folder.String,
|
||||||
|
File: song.File.String,
|
||||||
|
Audio: song.Audio.String,
|
||||||
|
TotalTime: song.Totaltime.Int64,
|
||||||
|
Image: extractImageFromFile(osuRoot, song.Folder.String, song.File.String),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func toProtoCollectionSqlc(rows []db.GetCollectionByNameRow) *v1.CollectionResponse {
|
||||||
|
songs := make([]*v1.Song, len(rows))
|
||||||
|
|
||||||
|
for i, b := range rows {
|
||||||
|
songs[i] = toProtoSongSqlC(db.Beatmap{
|
||||||
|
Beatmapid: b.Beatmapid,
|
||||||
|
Md5hash: b.Md5hash,
|
||||||
|
Title: b.Title,
|
||||||
|
Artist: b.Artist,
|
||||||
|
Creator: b.Creator,
|
||||||
|
Folder: b.Folder,
|
||||||
|
File: b.File,
|
||||||
|
Audio: b.Audio,
|
||||||
|
Totaltime: b.Totaltime,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
return &v1.CollectionResponse{
|
||||||
|
Name: rows[0].Name.String,
|
||||||
|
Items: int32(len(rows)),
|
||||||
|
Songs: songs,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func toProtoCollectionoffsetSqlc(rows []db.GetCollectionByOffsetRow) *v1.CollectionResponse {
|
||||||
|
songs := make([]*v1.Song, len(rows))
|
||||||
|
|
||||||
|
for i, b := range rows {
|
||||||
|
songs[i] = toProtoSongSqlC(db.Beatmap{
|
||||||
|
Beatmapid: b.Beatmapid,
|
||||||
|
Md5hash: b.Md5hash,
|
||||||
|
Title: b.Title,
|
||||||
|
Artist: b.Artist,
|
||||||
|
Creator: b.Creator,
|
||||||
|
Folder: b.Folder,
|
||||||
|
File: b.File,
|
||||||
|
Audio: b.Audio,
|
||||||
|
Totaltime: b.Totaltime,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
return &v1.CollectionResponse{
|
||||||
|
Name: rows[0].Name.String,
|
||||||
|
Items: int32(len(rows)),
|
||||||
|
Songs: songs,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func toProtoCollectionsSearchPreview(rows []db.SearchCollectionRow) *v1.SearchCollectionResponse {
|
||||||
|
|
||||||
|
collection := make([]*v1.CollectionPreview, len(rows))
|
||||||
|
for i, c := range rows {
|
||||||
|
collection[i] = toProtoCollectionPreviewSqlc(c)
|
||||||
|
}
|
||||||
|
|
||||||
|
return &v1.SearchCollectionResponse{Collections: collection}
|
||||||
|
}
|
||||||
|
|
||||||
|
func toProtoCollectionPreviewSqlc(row db.SearchCollectionRow) *v1.CollectionPreview {
|
||||||
|
return &v1.CollectionPreview{
|
||||||
|
Name: row.Name.String,
|
||||||
|
Items: int32(row.Count),
|
||||||
|
Image: extractImageFromFile(osuRoot, row.Folder.String, row.File.String),
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user