refactor: restructure project to standard Go layout
- 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>
This commit is contained in:
@@ -0,0 +1,131 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"database/sql"
|
||||
"embed"
|
||||
"fmt"
|
||||
"io/fs"
|
||||
"log"
|
||||
"net/http"
|
||||
"os"
|
||||
|
||||
"bilidown/internal/router"
|
||||
"bilidown/internal/util"
|
||||
|
||||
_ "modernc.org/sqlite"
|
||||
)
|
||||
|
||||
//go:embed all:build/static
|
||||
var staticFiles embed.FS
|
||||
|
||||
const (
|
||||
HTTP_PORT = 8098 // HTTP 服务器端口
|
||||
HTTP_HOST = "" // HTTP 服务器主机
|
||||
VERSION = "v2.1.1" // 软件版本号
|
||||
)
|
||||
|
||||
var urlLocal = fmt.Sprintf("http://127.0.0.1:%d", HTTP_PORT)
|
||||
|
||||
func main() {
|
||||
checkFFmpeg()
|
||||
mustInitTables()
|
||||
mustRunServer()
|
||||
fmt.Printf("Bilidown %s server running at %s\n", VERSION, urlLocal)
|
||||
select {} // 保持运行
|
||||
}
|
||||
|
||||
// checkFFmpeg 检测 ffmpeg 的安装情况
|
||||
func checkFFmpeg() {
|
||||
if _, err := util.GetFFmpegPath(); err != nil {
|
||||
fmt.Println("FFmpeg is missing. Install it from https://www.ffmpeg.org/download.html, then restart.")
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
||||
|
||||
// mustRunServer 配置和启动 HTTP 服务器
|
||||
func mustRunServer() {
|
||||
// 从嵌入的文件系统中获取静态文件
|
||||
staticFS, err := fs.Sub(staticFiles, "build/static")
|
||||
if err != nil {
|
||||
log.Fatal("Failed to load static files:", err)
|
||||
}
|
||||
// 前端静态文件
|
||||
http.Handle("/", http.FileServer(http.FS(staticFS)))
|
||||
// 后端 API 接口
|
||||
http.Handle("/api/", http.StripPrefix("/api", router.API()))
|
||||
// 启动 HTTP 服务器
|
||||
go func() {
|
||||
err := http.ListenAndServe(fmt.Sprintf("%s:%d", HTTP_HOST, HTTP_PORT), nil)
|
||||
if err != nil {
|
||||
log.Fatal("http.ListenAndServe:", err)
|
||||
}
|
||||
}()
|
||||
}
|
||||
|
||||
// mustInitTables 初始化数据表
|
||||
func mustInitTables() {
|
||||
db := util.MustGetDB()
|
||||
defer db.Close()
|
||||
|
||||
if _, err := db.Exec(`CREATE TABLE IF NOT EXISTS "field" (
|
||||
"name" TEXT PRIMARY KEY NOT NULL,
|
||||
"value" TEXT
|
||||
)`); err != nil {
|
||||
log.Fatalln("create table field:", err)
|
||||
}
|
||||
|
||||
if _, err := db.Exec(`CREATE TABLE IF NOT EXISTS "log" (
|
||||
"id" integer NOT NULL PRIMARY KEY AUTOINCREMENT,
|
||||
"content" TEXT NOT NULL,
|
||||
"create_at" text NOT NULL DEFAULT CURRENT_TIMESTAMP
|
||||
)`); err != nil {
|
||||
log.Fatalln("create table log:", err)
|
||||
}
|
||||
|
||||
if _, err := db.Exec(`CREATE TABLE IF NOT EXISTS "task" (
|
||||
"id" integer NOT NULL PRIMARY KEY AUTOINCREMENT,
|
||||
"bvid" text NOT NULL,
|
||||
"cid" integer NOT NULL,
|
||||
"format" integer NOT NULL,
|
||||
"title" text NOT NULL,
|
||||
"owner" text NOT NULL,
|
||||
"cover" text NOT NULL,
|
||||
"status" text NOT NULL,
|
||||
"folder" text NOT NULL,
|
||||
"duration" integer NOT NULL,
|
||||
"download_type" text NOT NULL DEFAULT 'merge',
|
||||
"create_at" text NOT NULL DEFAULT CURRENT_TIMESTAMP
|
||||
)`); err != nil {
|
||||
log.Fatalln("create table task:", err)
|
||||
}
|
||||
|
||||
if _, err := util.GetCurrentFolder(db); err != nil {
|
||||
log.Fatalln("util.GetCurrentFolder:", err)
|
||||
}
|
||||
|
||||
if err := initHistoryTask(db); err != nil {
|
||||
log.Fatalln("initHistoryTask:", err)
|
||||
}
|
||||
|
||||
// 添加可能缺失的列(用于数据库迁移)
|
||||
if err := addMissingColumns(db); err != nil {
|
||||
log.Fatalln("addMissingColumns:", err)
|
||||
}
|
||||
}
|
||||
|
||||
// addMissingColumns 添加可能缺失的列(用于数据库迁移)
|
||||
func addMissingColumns(db *sql.DB) error {
|
||||
util.SqliteLock.Lock()
|
||||
_, _ = db.Exec(`ALTER TABLE "task" ADD COLUMN "download_type" TEXT DEFAULT 'merge'`)
|
||||
_, _ = db.Exec(`UPDATE "task" SET "download_type" = 'merge' WHERE "download_type" IS NULL`)
|
||||
util.SqliteLock.Unlock()
|
||||
return nil
|
||||
}
|
||||
|
||||
// initHistoryTask 将上一次程序运行时未完成的任务状态变为 error
|
||||
func initHistoryTask(db *sql.DB) error {
|
||||
util.SqliteLock.Lock()
|
||||
_, err := db.Exec(`UPDATE "task" SET "status" = 'error' WHERE "status" IN ('waiting', 'running')`)
|
||||
util.SqliteLock.Unlock()
|
||||
return err
|
||||
}
|
||||
Reference in New Issue
Block a user