dd8eaef97d
- Reorganize code into cmd/bilidown and internal/ packages - Rename client/ to web/ for frontend source - Remove systray dependency for headless web service - Embed static files into binary using go:embed - Update import paths to use internal/ prefix - Update .gitignore with common patterns Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
152 lines
3.1 KiB
Go
152 lines
3.1 KiB
Go
package util
|
|
|
|
import (
|
|
"database/sql"
|
|
"errors"
|
|
"fmt"
|
|
"log"
|
|
"os"
|
|
"strings"
|
|
"sync"
|
|
)
|
|
|
|
func CreateLog(db *sql.DB, content string) error {
|
|
SqliteLock.Lock()
|
|
_, err := db.Exec(`INSERT INTO "log" ("content") VALUES (?)`, content)
|
|
SqliteLock.Unlock()
|
|
return err
|
|
}
|
|
|
|
func GetFields(db *sql.DB, names ...string) (map[string]string, error) {
|
|
|
|
if len(names) == 0 {
|
|
return nil, nil
|
|
}
|
|
|
|
placeholders := make([]string, len(names))
|
|
for i := 0; i < len(names); i++ {
|
|
placeholders[i] = "?"
|
|
}
|
|
query := fmt.Sprintf(`SELECT "name", "value" FROM "field" WHERE "name" IN (%s)`, strings.Join(placeholders, ","))
|
|
|
|
values := make([]interface{}, len(names))
|
|
for i := 0; i < len(names); i++ {
|
|
values[i] = names[i]
|
|
}
|
|
SqliteLock.Lock()
|
|
row, err := db.Query(query, values...)
|
|
SqliteLock.Unlock()
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
defer row.Close()
|
|
var name, value string
|
|
fields := make(map[string]string)
|
|
for row.Next() {
|
|
if err := row.Scan(&name, &value); err != nil {
|
|
return nil, err
|
|
}
|
|
fields[name] = value
|
|
}
|
|
return fields, nil
|
|
}
|
|
|
|
func SaveFields(db *sql.DB, data [][2]string) error {
|
|
|
|
if len(data) == 0 {
|
|
return nil
|
|
}
|
|
|
|
tx, err := db.Begin()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
defer func() {
|
|
if err != nil {
|
|
tx.Rollback()
|
|
} else {
|
|
tx.Commit()
|
|
}
|
|
}()
|
|
|
|
stmt, err := tx.Prepare(`INSERT OR REPLACE INTO "field" ("name", "value") VALUES (?, ?)`)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
defer stmt.Close()
|
|
|
|
for _, d := range data {
|
|
SqliteLock.Lock()
|
|
_, err = stmt.Exec(d[0], d[1])
|
|
SqliteLock.Unlock()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// GetCurrentFolder 获取数据库中的下载保存路径,如果不存在则将默认路径保存到数据库
|
|
func GetCurrentFolder(db *sql.DB) (string, error) {
|
|
var folder string
|
|
SqliteLock.Lock()
|
|
err := db.QueryRow(`SELECT "value" FROM "field" WHERE "name" = 'download_folder'`).Scan(&folder)
|
|
SqliteLock.Unlock()
|
|
if err != nil && err == sql.ErrNoRows {
|
|
folder, err = GetDefaultDownloadFolder()
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
err = os.MkdirAll(folder, os.ModePerm)
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
err = SaveDownloadFolder(db, folder)
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
return folder, nil
|
|
}
|
|
err = os.MkdirAll(folder, os.ModePerm)
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
return folder, nil
|
|
}
|
|
|
|
// SaveDownloadFolder 保存下载路径,不存在则自动创建
|
|
func SaveDownloadFolder(db *sql.DB, downloadFolder string) error {
|
|
_, err := os.Stat(downloadFolder)
|
|
if err != nil {
|
|
if os.IsNotExist(err) {
|
|
err = os.MkdirAll(downloadFolder, os.ModePerm)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
}
|
|
return err
|
|
}
|
|
SqliteLock.Lock()
|
|
_, err = db.Exec(`INSERT OR REPLACE INTO "field" ("name", "value") VALUES ('download_folder', ?)`, downloadFolder)
|
|
SqliteLock.Unlock()
|
|
return err
|
|
}
|
|
|
|
var SqliteLock sync.Mutex
|
|
|
|
func MustGetDB(path ...string) *sql.DB {
|
|
pathStr := ""
|
|
if len(path) == 0 {
|
|
pathStr = "./data.db"
|
|
} else if len(path) > 1 {
|
|
log.Fatalln(errors.New("len(path) <= 1"))
|
|
} else {
|
|
pathStr = path[0]
|
|
}
|
|
db, err := sql.Open("sqlite", pathStr)
|
|
if err != nil {
|
|
log.Fatalln("sql.Open:", err)
|
|
}
|
|
return db
|
|
}
|