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:
+20
-9
@@ -1,11 +1,22 @@
|
|||||||
|
# Dependencies
|
||||||
node_modules/
|
node_modules/
|
||||||
dist/
|
|
||||||
tmp/
|
# Build output
|
||||||
static/
|
|
||||||
*.db
|
|
||||||
*.exe
|
|
||||||
download/
|
|
||||||
build/
|
build/
|
||||||
.VSCodeCounter/
|
|
||||||
.claude/
|
# IDE
|
||||||
server/bilidown.exe~
|
.idea/
|
||||||
|
.vscode/
|
||||||
|
*.swp
|
||||||
|
*.swo
|
||||||
|
|
||||||
|
# OS
|
||||||
|
.DS_Store
|
||||||
|
Thumbs.db
|
||||||
|
|
||||||
|
# Project specific
|
||||||
|
.omc/
|
||||||
|
backup/
|
||||||
|
*.db
|
||||||
|
download/
|
||||||
|
bin/
|
||||||
@@ -1,201 +0,0 @@
|
|||||||
Apache License
|
|
||||||
Version 2.0, January 2004
|
|
||||||
http://www.apache.org/licenses/
|
|
||||||
|
|
||||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
|
||||||
|
|
||||||
1. Definitions.
|
|
||||||
|
|
||||||
"License" shall mean the terms and conditions for use, reproduction,
|
|
||||||
and distribution as defined by Sections 1 through 9 of this document.
|
|
||||||
|
|
||||||
"Licensor" shall mean the copyright owner or entity authorized by
|
|
||||||
the copyright owner that is granting the License.
|
|
||||||
|
|
||||||
"Legal Entity" shall mean the union of the acting entity and all
|
|
||||||
other entities that control, are controlled by, or are under common
|
|
||||||
control with that entity. For the purposes of this definition,
|
|
||||||
"control" means (i) the power, direct or indirect, to cause the
|
|
||||||
direction or management of such entity, whether by contract or
|
|
||||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
|
||||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
|
||||||
|
|
||||||
"You" (or "Your") shall mean an individual or Legal Entity
|
|
||||||
exercising permissions granted by this License.
|
|
||||||
|
|
||||||
"Source" form shall mean the preferred form for making modifications,
|
|
||||||
including but not limited to software source code, documentation
|
|
||||||
source, and configuration files.
|
|
||||||
|
|
||||||
"Object" form shall mean any form resulting from mechanical
|
|
||||||
transformation or translation of a Source form, including but
|
|
||||||
not limited to compiled object code, generated documentation,
|
|
||||||
and conversions to other media types.
|
|
||||||
|
|
||||||
"Work" shall mean the work of authorship, whether in Source or
|
|
||||||
Object form, made available under the License, as indicated by a
|
|
||||||
copyright notice that is included in or attached to the work
|
|
||||||
(an example is provided in the Appendix below).
|
|
||||||
|
|
||||||
"Derivative Works" shall mean any work, whether in Source or Object
|
|
||||||
form, that is based on (or derived from) the Work and for which the
|
|
||||||
editorial revisions, annotations, elaborations, or other modifications
|
|
||||||
represent, as a whole, an original work of authorship. For the purposes
|
|
||||||
of this License, Derivative Works shall not include works that remain
|
|
||||||
separable from, or merely link (or bind by name) to the interfaces of,
|
|
||||||
the Work and Derivative Works thereof.
|
|
||||||
|
|
||||||
"Contribution" shall mean any work of authorship, including
|
|
||||||
the original version of the Work and any modifications or additions
|
|
||||||
to that Work or Derivative Works thereof, that is intentionally
|
|
||||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
|
||||||
or by an individual or Legal Entity authorized to submit on behalf of
|
|
||||||
the copyright owner. For the purposes of this definition, "submitted"
|
|
||||||
means any form of electronic, verbal, or written communication sent
|
|
||||||
to the Licensor or its representatives, including but not limited to
|
|
||||||
communication on electronic mailing lists, source code control systems,
|
|
||||||
and issue tracking systems that are managed by, or on behalf of, the
|
|
||||||
Licensor for the purpose of discussing and improving the Work, but
|
|
||||||
excluding communication that is conspicuously marked or otherwise
|
|
||||||
designated in writing by the copyright owner as "Not a Contribution."
|
|
||||||
|
|
||||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
|
||||||
on behalf of whom a Contribution has been received by Licensor and
|
|
||||||
subsequently incorporated within the Work.
|
|
||||||
|
|
||||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
|
||||||
this License, each Contributor hereby grants to You a perpetual,
|
|
||||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
|
||||||
copyright license to reproduce, prepare Derivative Works of,
|
|
||||||
publicly display, publicly perform, sublicense, and distribute the
|
|
||||||
Work and such Derivative Works in Source or Object form.
|
|
||||||
|
|
||||||
3. Grant of Patent License. Subject to the terms and conditions of
|
|
||||||
this License, each Contributor hereby grants to You a perpetual,
|
|
||||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
|
||||||
(except as stated in this section) patent license to make, have made,
|
|
||||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
|
||||||
where such license applies only to those patent claims licensable
|
|
||||||
by such Contributor that are necessarily infringed by their
|
|
||||||
Contribution(s) alone or by combination of their Contribution(s)
|
|
||||||
with the Work to which such Contribution(s) was submitted. If You
|
|
||||||
institute patent litigation against any entity (including a
|
|
||||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
|
||||||
or a Contribution incorporated within the Work constitutes direct
|
|
||||||
or contributory patent infringement, then any patent licenses
|
|
||||||
granted to You under this License for that Work shall terminate
|
|
||||||
as of the date such litigation is filed.
|
|
||||||
|
|
||||||
4. Redistribution. You may reproduce and distribute copies of the
|
|
||||||
Work or Derivative Works thereof in any medium, with or without
|
|
||||||
modifications, and in Source or Object form, provided that You
|
|
||||||
meet the following conditions:
|
|
||||||
|
|
||||||
(a) You must give any other recipients of the Work or
|
|
||||||
Derivative Works a copy of this License; and
|
|
||||||
|
|
||||||
(b) You must cause any modified files to carry prominent notices
|
|
||||||
stating that You changed the files; and
|
|
||||||
|
|
||||||
(c) You must retain, in the Source form of any Derivative Works
|
|
||||||
that You distribute, all copyright, patent, trademark, and
|
|
||||||
attribution notices from the Source form of the Work,
|
|
||||||
excluding those notices that do not pertain to any part of
|
|
||||||
the Derivative Works; and
|
|
||||||
|
|
||||||
(d) If the Work includes a "NOTICE" text file as part of its
|
|
||||||
distribution, then any Derivative Works that You distribute must
|
|
||||||
include a readable copy of the attribution notices contained
|
|
||||||
within such NOTICE file, excluding those notices that do not
|
|
||||||
pertain to any part of the Derivative Works, in at least one
|
|
||||||
of the following places: within a NOTICE text file distributed
|
|
||||||
as part of the Derivative Works; within the Source form or
|
|
||||||
documentation, if provided along with the Derivative Works; or,
|
|
||||||
within a display generated by the Derivative Works, if and
|
|
||||||
wherever such third-party notices normally appear. The contents
|
|
||||||
of the NOTICE file are for informational purposes only and
|
|
||||||
do not modify the License. You may add Your own attribution
|
|
||||||
notices within Derivative Works that You distribute, alongside
|
|
||||||
or as an addendum to the NOTICE text from the Work, provided
|
|
||||||
that such additional attribution notices cannot be construed
|
|
||||||
as modifying the License.
|
|
||||||
|
|
||||||
You may add Your own copyright statement to Your modifications and
|
|
||||||
may provide additional or different license terms and conditions
|
|
||||||
for use, reproduction, or distribution of Your modifications, or
|
|
||||||
for any such Derivative Works as a whole, provided Your use,
|
|
||||||
reproduction, and distribution of the Work otherwise complies with
|
|
||||||
the conditions stated in this License.
|
|
||||||
|
|
||||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
|
||||||
any Contribution intentionally submitted for inclusion in the Work
|
|
||||||
by You to the Licensor shall be under the terms and conditions of
|
|
||||||
this License, without any additional terms or conditions.
|
|
||||||
Notwithstanding the above, nothing herein shall supersede or modify
|
|
||||||
the terms of any separate license agreement you may have executed
|
|
||||||
with Licensor regarding such Contributions.
|
|
||||||
|
|
||||||
6. Trademarks. This License does not grant permission to use the trade
|
|
||||||
names, trademarks, service marks, or product names of the Licensor,
|
|
||||||
except as required for reasonable and customary use in describing the
|
|
||||||
origin of the Work and reproducing the content of the NOTICE file.
|
|
||||||
|
|
||||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
|
||||||
agreed to in writing, Licensor provides the Work (and each
|
|
||||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
|
||||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
|
||||||
implied, including, without limitation, any warranties or conditions
|
|
||||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
|
||||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
|
||||||
appropriateness of using or redistributing the Work and assume any
|
|
||||||
risks associated with Your exercise of permissions under this License.
|
|
||||||
|
|
||||||
8. Limitation of Liability. In no event and under no legal theory,
|
|
||||||
whether in tort (including negligence), contract, or otherwise,
|
|
||||||
unless required by applicable law (such as deliberate and grossly
|
|
||||||
negligent acts) or agreed to in writing, shall any Contributor be
|
|
||||||
liable to You for damages, including any direct, indirect, special,
|
|
||||||
incidental, or consequential damages of any character arising as a
|
|
||||||
result of this License or out of the use or inability to use the
|
|
||||||
Work (including but not limited to damages for loss of goodwill,
|
|
||||||
work stoppage, computer failure or malfunction, or any and all
|
|
||||||
other commercial damages or losses), even if such Contributor
|
|
||||||
has been advised of the possibility of such damages.
|
|
||||||
|
|
||||||
9. Accepting Warranty or Additional Liability. While redistributing
|
|
||||||
the Work or Derivative Works thereof, You may choose to offer,
|
|
||||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
|
||||||
or other liability obligations and/or rights consistent with this
|
|
||||||
License. However, in accepting such obligations, You may act only
|
|
||||||
on Your own behalf and on Your sole responsibility, not on behalf
|
|
||||||
of any other Contributor, and only if You agree to indemnify,
|
|
||||||
defend, and hold each Contributor harmless for any liability
|
|
||||||
incurred by, or claims asserted against, such Contributor by reason
|
|
||||||
of your accepting any such warranty or additional liability.
|
|
||||||
|
|
||||||
END OF TERMS AND CONDITIONS
|
|
||||||
|
|
||||||
APPENDIX: How to apply the Apache License to your work.
|
|
||||||
|
|
||||||
To apply the Apache License to your work, attach the following
|
|
||||||
boilerplate notice, with the fields enclosed by brackets "[]"
|
|
||||||
replaced with your own identifying information. (Don't include
|
|
||||||
the brackets!) The text should be enclosed in the appropriate
|
|
||||||
comment syntax for the file format. We also recommend that a
|
|
||||||
file or class name and description of purpose be included on the
|
|
||||||
same "printed page" as the copyright notice for easier
|
|
||||||
identification within third-party archives.
|
|
||||||
|
|
||||||
Copyright 2025 iuroc
|
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
you may not use this file except in compliance with the License.
|
|
||||||
You may obtain a copy of the License at
|
|
||||||
|
|
||||||
http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
|
|
||||||
Unless required by applicable law or agreed to in writing, software
|
|
||||||
distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
See the License for the specific language governing permissions and
|
|
||||||
limitations under the License.
|
|
||||||
@@ -1,136 +0,0 @@
|
|||||||
# Bilidown
|
|
||||||
|
|
||||||
[](https://github.com/iuroc/bilidown/releases)
|
|
||||||
|
|
||||||
哔哩哔哩视频解析下载工具,支持 8K 视频、Hi-Res 音频、杜比视界下载、批量解析,可扫码登录,常驻托盘。
|
|
||||||
|
|
||||||
## 支持解析的链接类型
|
|
||||||
|
|
||||||
- 【单个视频】https://www.bilibili.com/video/BV1LLDCYJEU3/
|
|
||||||
- 【番剧和影视剧】https://www.bilibili.com/bangumi/play/ss48831
|
|
||||||
- 【视频合集】https://space.bilibili.com/282565107/channel/collectiondetail?sid=1427135
|
|
||||||
- 【收藏夹】https://space.bilibili.com/1176277996/favlist?fid=1234122612
|
|
||||||
- 【UP 主空间地址】等待 3.x 版本支持
|
|
||||||
|
|
||||||
## 使用说明
|
|
||||||
|
|
||||||
1. 从 [Releases](https://github.com/iuroc/bilidown/releases) 下载适合您系统版本的安装包
|
|
||||||
2. 非 Windows 系统,请先安装 [FFmpeg 工具](https://www.ffmpeg.org/)
|
|
||||||
3. 将安装包解压后执行即可
|
|
||||||
|
|
||||||
## 软件特色
|
|
||||||
|
|
||||||
1. 前端采用 [Bootstrap](https://github.com/twbs/bootstrap) 和 [VanJS](https://github.com/vanjs-org/van) 构建,轻量美观
|
|
||||||
2. 后端使用 Go 语言开发,数据库采用 SQlite,简化构建和部署过程
|
|
||||||
3. 前端通过 [p-queue](https://github.com/sindresorhus/p-queue) 控制并发请求,加快批量解析速度
|
|
||||||
|
|
||||||
## 其他说明
|
|
||||||
|
|
||||||
- 本程序不支持也不建议 HTTP 代理,直接使用国内网络访问能提升批量解析的成功率和稳定性。
|
|
||||||
|
|
||||||
## 打包可执行文件
|
|
||||||
|
|
||||||
```shell
|
|
||||||
git clone https://github.com/iuroc/bilidown
|
|
||||||
cd bilidown/client
|
|
||||||
pnpm install
|
|
||||||
pnpm build
|
|
||||||
cd ../server
|
|
||||||
go mod tidy
|
|
||||||
CGO_ENABLED=1 go build
|
|
||||||
```
|
|
||||||
|
|
||||||
## 交叉编译
|
|
||||||
|
|
||||||
### 说明
|
|
||||||
|
|
||||||
- 镜像名称:`iuroc/cgo-cross-build`
|
|
||||||
- 支持的系统架构
|
|
||||||
- `linux/amd64`
|
|
||||||
- `windows/amd64`
|
|
||||||
- `windows/386`
|
|
||||||
- `windows/arm64`
|
|
||||||
- `darwin/amd64`
|
|
||||||
- `darwin/arm64`
|
|
||||||
|
|
||||||
### 拉取镜像和项目源码
|
|
||||||
|
|
||||||
```shell
|
|
||||||
docker pull iuroc/cgo-cross-build:latest
|
|
||||||
git clone https://github.com/iuroc/bilidown
|
|
||||||
```
|
|
||||||
|
|
||||||
### 交叉编译发行版
|
|
||||||
|
|
||||||
> 执行 `goreleaser` 命令时将自动执行 `pnpm build` 和 `go mod tidy`
|
|
||||||
|
|
||||||
将 `ffmpeg.exe` 放入 `server/bin` 目录内。
|
|
||||||
|
|
||||||
在项目根目录执行如下代码,进入 Docker 容器。
|
|
||||||
|
|
||||||
```shell
|
|
||||||
docker run --rm -it -v .:/usr/src/data iuroc/cgo-cross-build
|
|
||||||
```
|
|
||||||
|
|
||||||
在容器内的终端执行如下代码,开始交叉编译。
|
|
||||||
|
|
||||||
```shell
|
|
||||||
cd server
|
|
||||||
git tag v2.1.1
|
|
||||||
goreleaser release --snapshot --clean
|
|
||||||
# 正式发行
|
|
||||||
# GITHUB_TOKEN=xxx goreleaser release --clean
|
|
||||||
```
|
|
||||||
|
|
||||||
### 编译指定系统架构
|
|
||||||
|
|
||||||
```ini
|
|
||||||
# 按上面的步骤进入 Docker 容器内终端
|
|
||||||
|
|
||||||
# [darwin-amd64]
|
|
||||||
GOOS=darwin
|
|
||||||
GOARCH=amd64
|
|
||||||
CC=o64-clang
|
|
||||||
CGO_ENABLED=1
|
|
||||||
go build
|
|
||||||
```
|
|
||||||
|
|
||||||
### 非 Docker 环境编译
|
|
||||||
|
|
||||||
在 Linux amd64 平台上执行 `go build` 时,您可能需要安装以下依赖包:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
sudo apt install pkg-config gcc libayatana-appindicator3-dev
|
|
||||||
```
|
|
||||||
|
|
||||||
## 开发环境
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# client
|
|
||||||
pnpm install
|
|
||||||
pnpm dev
|
|
||||||
# server
|
|
||||||
go build && ./bilidown
|
|
||||||
```
|
|
||||||
|
|
||||||
## 特别感谢
|
|
||||||
|
|
||||||
- [twbs/bootstrap](https://github.com/twbs/bootstrap) - 前端开发必备的响应式框架,简化页面布局
|
|
||||||
- [vanjs-org/van](https://github.com/vanjs-org/van) - 轻量级的前端框架,专注于构建高效应用
|
|
||||||
- [vitejs/vite](https://github.com/vitejs/vite) - 快速的前端构建工具,基于 ES 模块开发
|
|
||||||
- [SocialSisterYi/bilibili-API-collec](https://github.com/SocialSisterYi/bilibili-API-collect) - B 站 API 集合,支持多种操作接口
|
|
||||||
- [sindresorhus/p-queue](https://github.com/sindresorhus/p-queue) - 支持并发限制的 JavaScript 队列处理库
|
|
||||||
- [iuroc/vanjs-router](https://github.com/iuroc/vanjs-router) - 轻量级前端路由工具,适用于 Van.js 框架
|
|
||||||
- [uuidjs/uuid](https://www.npmjs.com/package/uuid) - 用于生成唯一标识符(UUID)的 JavaScript 库
|
|
||||||
- [getlantern/systray](https://github.com/getlantern/systray) - 简单的跨平台系统托盘图标库,支持图标管理
|
|
||||||
- [modernc.org/sqlite](https://pkg.go.dev/modernc.org/sqlite) - Go 语言的 SQLite3 数据库驱动,轻量高效
|
|
||||||
- [skip2/go-qrcode](https://github.com/skip2/go-qrcode) - 生成 QR 码的 Go 语言库,简单易用
|
|
||||||
|
|
||||||
## 软件界面
|
|
||||||
|
|
||||||

|
|
||||||
|
|
||||||
|
|
||||||
## Star History
|
|
||||||
|
|
||||||
[](https://www.star-history.com/#iuroc/bilidown&Date)
|
|
||||||
@@ -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
|
||||||
|
}
|
||||||
Binary file not shown.
|
Before Width: | Height: | Size: 411 KiB |
@@ -0,0 +1,24 @@
|
|||||||
|
module bilidown
|
||||||
|
|
||||||
|
go 1.23.0
|
||||||
|
|
||||||
|
require (
|
||||||
|
github.com/skip2/go-qrcode v0.0.0-20200617195104-da1b6568686e
|
||||||
|
modernc.org/sqlite v1.33.1
|
||||||
|
)
|
||||||
|
|
||||||
|
require (
|
||||||
|
github.com/dustin/go-humanize v1.0.1 // indirect
|
||||||
|
github.com/google/uuid v1.6.0 // indirect
|
||||||
|
github.com/hashicorp/golang-lru/v2 v2.0.7 // indirect
|
||||||
|
github.com/mattn/go-isatty v0.0.20 // indirect
|
||||||
|
github.com/ncruces/go-strftime v0.1.9 // indirect
|
||||||
|
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect
|
||||||
|
golang.org/x/sys v0.22.0 // indirect
|
||||||
|
modernc.org/gc/v3 v3.0.0-20240107210532-573471604cb6 // indirect
|
||||||
|
modernc.org/libc v1.55.3 // indirect
|
||||||
|
modernc.org/mathutil v1.6.0 // indirect
|
||||||
|
modernc.org/memory v1.8.0 // indirect
|
||||||
|
modernc.org/strutil v1.2.0 // indirect
|
||||||
|
modernc.org/token v1.1.0 // indirect
|
||||||
|
)
|
||||||
@@ -0,0 +1,51 @@
|
|||||||
|
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/google/pprof v0.0.0-20240409012703-83162a5b38cd h1:gbpYu9NMq8jhDVbvlGkMFWCjLFlqqEZjEmObmhUy6Vo=
|
||||||
|
github.com/google/pprof v0.0.0-20240409012703-83162a5b38cd/go.mod h1:kf6iHlnVGwgKolg33glAes7Yg/8iWP8ukqeldJSO7jw=
|
||||||
|
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
|
||||||
|
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||||
|
github.com/hashicorp/golang-lru/v2 v2.0.7 h1:a+bsQ5rvGLjzHuww6tVxozPZFVghXaHOwFs4luLUK2k=
|
||||||
|
github.com/hashicorp/golang-lru/v2 v2.0.7/go.mod h1:QeFd9opnmA6QUJc5vARoKUSoFhyfM2/ZepoAG6RGpeM=
|
||||||
|
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/ncruces/go-strftime v0.1.9 h1:bY0MQC28UADQmHmaF5dgpLmImcShSi2kHU9XLdhx/f4=
|
||||||
|
github.com/ncruces/go-strftime v0.1.9/go.mod h1:Fwc5htZGVVkseilnfgOVb9mKy6w1naJmn9CehxcKcls=
|
||||||
|
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||||
|
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||||
|
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec h1:W09IVJc94icq4NjY3clb7Lk8O1qJ8BdBEF8z0ibU0rE=
|
||||||
|
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo=
|
||||||
|
github.com/skip2/go-qrcode v0.0.0-20200617195104-da1b6568686e h1:MRM5ITcdelLK2j1vwZ3Je0FKVCfqOLp5zO6trqMLYs0=
|
||||||
|
github.com/skip2/go-qrcode v0.0.0-20200617195104-da1b6568686e/go.mod h1:XV66xRDqSt+GTGFMVlhk3ULuV0y9ZmzeVGR4mloJI3M=
|
||||||
|
golang.org/x/mod v0.16.0 h1:QX4fJ0Rr5cPQCF7O9lh9Se4pmwfwskqZfq5moyldzic=
|
||||||
|
golang.org/x/mod v0.16.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
|
||||||
|
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
|
golang.org/x/sys v0.22.0 h1:RI27ohtqKCnwULzJLqkv897zojh5/DwS/ENaMzUOaWI=
|
||||||
|
golang.org/x/sys v0.22.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||||
|
golang.org/x/tools v0.19.0 h1:tfGCXNR1OsFG+sVdLAitlpjAvD/I6dHDKnYrpEZUHkw=
|
||||||
|
golang.org/x/tools v0.19.0/go.mod h1:qoJWxmGSIBmAeriMx19ogtrEPrGtDbPK634QFIcLAhc=
|
||||||
|
modernc.org/cc/v4 v4.21.4 h1:3Be/Rdo1fpr8GrQ7IVw9OHtplU4gWbb+wNgeoBMmGLQ=
|
||||||
|
modernc.org/cc/v4 v4.21.4/go.mod h1:HM7VJTZbUCR3rV8EYBi9wxnJ0ZBRiGE5OeGXNA0IsLQ=
|
||||||
|
modernc.org/ccgo/v4 v4.19.2 h1:lwQZgvboKD0jBwdaeVCTouxhxAyN6iawF3STraAal8Y=
|
||||||
|
modernc.org/ccgo/v4 v4.19.2/go.mod h1:ysS3mxiMV38XGRTTcgo0DQTeTmAO4oCmJl1nX9VFI3s=
|
||||||
|
modernc.org/fileutil v1.3.0 h1:gQ5SIzK3H9kdfai/5x41oQiKValumqNTDXMvKo62HvE=
|
||||||
|
modernc.org/fileutil v1.3.0/go.mod h1:XatxS8fZi3pS8/hKG2GH/ArUogfxjpEKs3Ku3aK4JyQ=
|
||||||
|
modernc.org/gc/v2 v2.4.1 h1:9cNzOqPyMJBvrUipmynX0ZohMhcxPtMccYgGOJdOiBw=
|
||||||
|
modernc.org/gc/v2 v2.4.1/go.mod h1:wzN5dK1AzVGoH6XOzc3YZ+ey/jPgYHLuVckd62P0GYU=
|
||||||
|
modernc.org/gc/v3 v3.0.0-20240107210532-573471604cb6 h1:5D53IMaUuA5InSeMu9eJtlQXS2NxAhyWQvkKEgXZhHI=
|
||||||
|
modernc.org/gc/v3 v3.0.0-20240107210532-573471604cb6/go.mod h1:Qz0X07sNOR1jWYCrJMEnbW/X55x206Q7Vt4mz6/wHp4=
|
||||||
|
modernc.org/libc v1.55.3 h1:AzcW1mhlPNrRtjS5sS+eW2ISCgSOLLNyFzRh/V3Qj/U=
|
||||||
|
modernc.org/libc v1.55.3/go.mod h1:qFXepLhz+JjFThQ4kzwzOjA/y/artDeg+pcYnY+Q83w=
|
||||||
|
modernc.org/mathutil v1.6.0 h1:fRe9+AmYlaej+64JsEEhoWuAYBkOtQiMEU7n/XgfYi4=
|
||||||
|
modernc.org/mathutil v1.6.0/go.mod h1:Ui5Q9q1TR2gFm0AQRqQUaBWFLAhQpCwNcuhBOSedWPo=
|
||||||
|
modernc.org/memory v1.8.0 h1:IqGTL6eFMaDZZhEWwcREgeMXYwmW83LYW8cROZYkg+E=
|
||||||
|
modernc.org/memory v1.8.0/go.mod h1:XPZ936zp5OMKGWPqbD3JShgd/ZoQ7899TUuQqxY+peU=
|
||||||
|
modernc.org/opt v0.1.3 h1:3XOZf2yznlhC+ibLltsDGzABUGVx8J6pnFMS3E4dcq4=
|
||||||
|
modernc.org/opt v0.1.3/go.mod h1:WdSiB5evDcignE70guQKxYUl14mgWtbClRi5wmkkTX0=
|
||||||
|
modernc.org/sortutil v1.2.0 h1:jQiD3PfS2REGJNzNCMMaLSp/wdMNieTbKX920Cqdgqc=
|
||||||
|
modernc.org/sortutil v1.2.0/go.mod h1:TKU2s7kJMf1AE84OoiGppNHJwvB753OYfNl2WRb++Ss=
|
||||||
|
modernc.org/sqlite v1.33.1 h1:trb6Z3YYoeM9eDL1O8do81kP+0ejv+YzgyFo+Gwy0nM=
|
||||||
|
modernc.org/sqlite v1.33.1/go.mod h1:pXV2xHxhzXZsgT/RtTFAPY6JJDEvOTcTdwADQCCWD4k=
|
||||||
|
modernc.org/strutil v1.2.0 h1:agBi9dp1I+eOnxXeiZawM8F4LawKv4NzGWSaLfyeNZA=
|
||||||
|
modernc.org/strutil v1.2.0/go.mod h1:/mdcBmfOibveCTBxUl5B5l6W+TTH1FXPLHZE6bTosX0=
|
||||||
|
modernc.org/token v1.1.0 h1:Xl7Ap9dKaEs5kLoOQeQmPWevfnk/DM5qcLcYlA8ys6Y=
|
||||||
|
modernc.org/token v1.1.0/go.mod h1:UGzOrNV1mAFSEB63lOFHIpNRUVMvYTc6yu1SMY/XTDM=
|
||||||
@@ -8,7 +8,7 @@ import (
|
|||||||
"net/url"
|
"net/url"
|
||||||
"regexp"
|
"regexp"
|
||||||
|
|
||||||
"bilidown/util"
|
"bilidown/internal/util"
|
||||||
)
|
)
|
||||||
|
|
||||||
type BiliClient struct {
|
type BiliClient struct {
|
||||||
@@ -3,7 +3,7 @@ package bilibili
|
|||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
|
|
||||||
"bilidown/common"
|
"bilidown/internal/common"
|
||||||
)
|
)
|
||||||
|
|
||||||
// BaseRes 来自 Bilibili 的接口响应,Message 字段为 msg
|
// BaseRes 来自 Bilibili 的接口响应,Message 字段为 msg
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
package bilibili
|
package bilibili
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bilidown/util"
|
"bilidown/internal/util"
|
||||||
"database/sql"
|
"database/sql"
|
||||||
"net/url"
|
"net/url"
|
||||||
"strconv"
|
"strconv"
|
||||||
@@ -4,8 +4,8 @@ import (
|
|||||||
"encoding/base64"
|
"encoding/base64"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
|
||||||
"bilidown/bilibili"
|
"bilidown/internal/bilibili"
|
||||||
"bilidown/util"
|
"bilidown/internal/util"
|
||||||
|
|
||||||
"github.com/skip2/go-qrcode"
|
"github.com/skip2/go-qrcode"
|
||||||
)
|
)
|
||||||
@@ -6,8 +6,8 @@ import (
|
|||||||
"net/http"
|
"net/http"
|
||||||
"os"
|
"os"
|
||||||
|
|
||||||
"bilidown/util"
|
"bilidown/internal/util"
|
||||||
"bilidown/util/res_error"
|
"bilidown/internal/util/res_error"
|
||||||
)
|
)
|
||||||
|
|
||||||
func API() *http.ServeMux {
|
func API() *http.ServeMux {
|
||||||
@@ -10,8 +10,8 @@ import (
|
|||||||
"runtime"
|
"runtime"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
|
||||||
"bilidown/task"
|
"bilidown/internal/task"
|
||||||
"bilidown/util"
|
"bilidown/internal/util"
|
||||||
)
|
)
|
||||||
|
|
||||||
func createTask(w http.ResponseWriter, r *http.Request) {
|
func createTask(w http.ResponseWriter, r *http.Request) {
|
||||||
@@ -6,9 +6,9 @@ import (
|
|||||||
"path/filepath"
|
"path/filepath"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
"bilidown/bilibili"
|
"bilidown/internal/bilibili"
|
||||||
"bilidown/util"
|
"bilidown/internal/util"
|
||||||
"bilidown/util/res_error"
|
"bilidown/internal/util/res_error"
|
||||||
)
|
)
|
||||||
|
|
||||||
// getVideoInfo 通过 BV 号获取视频信息
|
// getVideoInfo 通过 BV 号获取视频信息
|
||||||
@@ -18,9 +18,9 @@ import (
|
|||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"bilidown/bilibili"
|
"bilidown/internal/bilibili"
|
||||||
"bilidown/common"
|
"bilidown/internal/common"
|
||||||
"bilidown/util"
|
"bilidown/internal/util"
|
||||||
)
|
)
|
||||||
|
|
||||||
// TaskInitOption 创建任务时需要从 POST 请求获取的参数
|
// TaskInitOption 创建任务时需要从 POST 请求获取的参数
|
||||||
@@ -3,7 +3,7 @@ package res_error
|
|||||||
import (
|
import (
|
||||||
"net/http"
|
"net/http"
|
||||||
|
|
||||||
"bilidown/util"
|
"bilidown/internal/util"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Send 发送异常响应
|
// Send 发送异常响应
|
||||||
@@ -11,7 +11,7 @@ import (
|
|||||||
"regexp"
|
"regexp"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
|
||||||
"bilidown/common"
|
"bilidown/internal/common"
|
||||||
)
|
)
|
||||||
|
|
||||||
func CheckBvidFormat(bvid string) bool {
|
func CheckBvidFormat(bvid string) bool {
|
||||||
@@ -1,3 +0,0 @@
|
|||||||
[build]
|
|
||||||
exclude_dir = ["download", "bin"]
|
|
||||||
include_ext = ["go"]
|
|
||||||
@@ -1,71 +0,0 @@
|
|||||||
# This is an example .goreleaser.yml file with some sensible defaults.
|
|
||||||
# Make sure to check the documentation at https://goreleaser.com
|
|
||||||
|
|
||||||
# The lines below are called `modelines`. See `:help modeline`
|
|
||||||
# Feel free to remove those if you don't want/need to use them.
|
|
||||||
# yaml-language-server: $schema=https://goreleaser.com/static/schema.json
|
|
||||||
# vim: set ts=2 sw=2 tw=0 fo=cnqoj
|
|
||||||
|
|
||||||
version: 2
|
|
||||||
|
|
||||||
before:
|
|
||||||
hooks:
|
|
||||||
# You may remove this if you don't use go modules.
|
|
||||||
- go mod tidy
|
|
||||||
# you may remove this if you don't need go generate
|
|
||||||
- go generate ./...
|
|
||||||
|
|
||||||
builds:
|
|
||||||
- id: bilidown_windows
|
|
||||||
env:
|
|
||||||
- CGO_ENABLED=1
|
|
||||||
- >-
|
|
||||||
{{- if eq .Arch "amd64" }}CC=x86_64-w64-mingw32-gcc{{ end }}
|
|
||||||
{{- if eq .Arch "386" }}CC=i686-w64-mingw32-gcc{{ end }}
|
|
||||||
goos:
|
|
||||||
- windows
|
|
||||||
ldflags:
|
|
||||||
- -s -w -H windowsgui
|
|
||||||
- id: bilidown_darwin
|
|
||||||
env:
|
|
||||||
- CGO_ENABLED=1
|
|
||||||
- CC=o64-clang
|
|
||||||
goos:
|
|
||||||
- darwin
|
|
||||||
ldflags:
|
|
||||||
- -s -w
|
|
||||||
- id: bilidown_linux
|
|
||||||
env:
|
|
||||||
- CGO_ENABLED=1
|
|
||||||
- >-
|
|
||||||
{{- if eq .Arch "arm64" }}CC=aarch64-linux-gnu-gcc{{ end }}
|
|
||||||
goos:
|
|
||||||
- linux
|
|
||||||
goarch:
|
|
||||||
- amd64
|
|
||||||
ldflags:
|
|
||||||
- -s -w
|
|
||||||
archives:
|
|
||||||
- format: tar.gz
|
|
||||||
# this name template makes the OS and Arch compatible with the results of `uname`.
|
|
||||||
name_template: >-
|
|
||||||
{{ .ProjectName }}_
|
|
||||||
{{- title .Os }}_
|
|
||||||
{{- if eq .Arch "amd64" }}x86_64
|
|
||||||
{{- else if eq .Arch "386" }}i386
|
|
||||||
{{- else }}{{ .Arch }}{{ end }}
|
|
||||||
{{- if .Arm }}v{{ .Arm }}{{ end }}
|
|
||||||
# use zip for windows archives
|
|
||||||
format_overrides:
|
|
||||||
- goos: windows
|
|
||||||
format: zip
|
|
||||||
files:
|
|
||||||
- static/**
|
|
||||||
- >-
|
|
||||||
{{- if eq .Os "windows" }}bin/ffmpeg.exe{{- end }}
|
|
||||||
changelog:
|
|
||||||
sort: asc
|
|
||||||
filters:
|
|
||||||
exclude:
|
|
||||||
- "^docs:"
|
|
||||||
- "^test:"
|
|
||||||
@@ -1,41 +0,0 @@
|
|||||||
module bilidown
|
|
||||||
|
|
||||||
go 1.23.0
|
|
||||||
|
|
||||||
require (
|
|
||||||
github.com/getlantern/systray v1.2.2
|
|
||||||
github.com/skip2/go-qrcode v0.0.0-20200617195104-da1b6568686e
|
|
||||||
modernc.org/sqlite v1.33.1
|
|
||||||
)
|
|
||||||
|
|
||||||
require (
|
|
||||||
github.com/dustin/go-humanize v1.0.1 // indirect
|
|
||||||
github.com/getlantern/context v0.0.0-20220418194847-3d5e7a086201 // indirect
|
|
||||||
github.com/getlantern/errors v1.0.4 // indirect
|
|
||||||
github.com/getlantern/golog v0.0.0-20230503153817-8e72de7e0a65 // indirect
|
|
||||||
github.com/getlantern/hex v0.0.0-20220104173244-ad7e4b9194dc // indirect
|
|
||||||
github.com/getlantern/hidden v0.0.0-20220104173330-f221c5a24770 // indirect
|
|
||||||
github.com/getlantern/ops v0.0.0-20231025133620-f368ab734534 // indirect
|
|
||||||
github.com/go-logr/logr v1.4.2 // indirect
|
|
||||||
github.com/go-logr/stdr v1.2.2 // indirect
|
|
||||||
github.com/go-stack/stack v1.8.1 // indirect
|
|
||||||
github.com/google/uuid v1.6.0 // indirect
|
|
||||||
github.com/hashicorp/golang-lru/v2 v2.0.7 // indirect
|
|
||||||
github.com/mattn/go-isatty v0.0.20 // indirect
|
|
||||||
github.com/ncruces/go-strftime v0.1.9 // indirect
|
|
||||||
github.com/oxtoacart/bpool v0.0.0-20190530202638-03653db5a59c // indirect
|
|
||||||
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect
|
|
||||||
go.opentelemetry.io/otel v1.31.0 // indirect
|
|
||||||
go.opentelemetry.io/otel/metric v1.31.0 // indirect
|
|
||||||
go.opentelemetry.io/otel/trace v1.31.0 // indirect
|
|
||||||
go.uber.org/multierr v1.11.0 // indirect
|
|
||||||
go.uber.org/zap v1.27.0 // indirect
|
|
||||||
golang.org/x/exp v0.0.0-20231108232855-2478ac86f678 // indirect
|
|
||||||
golang.org/x/sys v0.26.0 // indirect
|
|
||||||
modernc.org/gc/v3 v3.0.0-20241004144649-1aea3fae8852 // indirect
|
|
||||||
modernc.org/libc v1.61.0 // indirect
|
|
||||||
modernc.org/mathutil v1.6.0 // indirect
|
|
||||||
modernc.org/memory v1.8.0 // indirect
|
|
||||||
modernc.org/strutil v1.2.0 // indirect
|
|
||||||
modernc.org/token v1.1.0 // indirect
|
|
||||||
)
|
|
||||||
-164
@@ -1,164 +0,0 @@
|
|||||||
github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA=
|
|
||||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
|
||||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
|
||||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
|
||||||
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/getlantern/context v0.0.0-20190109183933-c447772a6520/go.mod h1:L+mq6/vvYHKjCX2oez0CgEAJmbq1fbb/oNJIWQkBybY=
|
|
||||||
github.com/getlantern/context v0.0.0-20220418194847-3d5e7a086201 h1:oEZYEpZo28Wdx+5FZo4aU7JFXu0WG/4wJWese5reQSA=
|
|
||||||
github.com/getlantern/context v0.0.0-20220418194847-3d5e7a086201/go.mod h1:Y9WZUHEb+mpra02CbQ/QczLUe6f0Dezxaw5DCJlJQGo=
|
|
||||||
github.com/getlantern/errors v0.0.0-20190325191628-abdb3e3e36f7/go.mod h1:l+xpFBrCtDLpK9qNjxs+cHU6+BAdlBaxHqikB6Lku3A=
|
|
||||||
github.com/getlantern/errors v1.0.1/go.mod h1:l+xpFBrCtDLpK9qNjxs+cHU6+BAdlBaxHqikB6Lku3A=
|
|
||||||
github.com/getlantern/errors v1.0.4 h1:i2iR1M9GKj4WuingpNqJ+XQEw6i6dnAgKAmLj6ZB3X0=
|
|
||||||
github.com/getlantern/errors v1.0.4/go.mod h1:/Foq8jtSDGP8GOXzAjeslsC4Ar/3kB+UiQH+WyV4pzY=
|
|
||||||
github.com/getlantern/golog v0.0.0-20190830074920-4ef2e798c2d7/go.mod h1:zx/1xUUeYPy3Pcmet8OSXLbF47l+3y6hIPpyLWoR9oc=
|
|
||||||
github.com/getlantern/golog v0.0.0-20230503153817-8e72de7e0a65 h1:NlQedYmPI3pRAXJb+hLVVDGqfvvXGRPV8vp7XOjKAZ0=
|
|
||||||
github.com/getlantern/golog v0.0.0-20230503153817-8e72de7e0a65/go.mod h1:+ZU1h+iOVqWReBpky6d5Y2WL0sF2Llxu+QcxJFs2+OU=
|
|
||||||
github.com/getlantern/hex v0.0.0-20190417191902-c6586a6fe0b7/go.mod h1:dD3CgOrwlzca8ed61CsZouQS5h5jIzkK9ZWrTcf0s+o=
|
|
||||||
github.com/getlantern/hex v0.0.0-20220104173244-ad7e4b9194dc h1:sue+aeVx7JF5v36H1HfvcGFImLpSD5goj8d+MitovDU=
|
|
||||||
github.com/getlantern/hex v0.0.0-20220104173244-ad7e4b9194dc/go.mod h1:D9RWpXy/EFPYxiKUURo2TB8UBosbqkiLhttRrZYtvqM=
|
|
||||||
github.com/getlantern/hidden v0.0.0-20190325191715-f02dbb02be55/go.mod h1:6mmzY2kW1TOOrVy+r41Za2MxXM+hhqTtY3oBKd2AgFA=
|
|
||||||
github.com/getlantern/hidden v0.0.0-20220104173330-f221c5a24770 h1:cSrD9ryDfTV2yaur9Qk3rHYD414j3Q1rl7+L0AylxrE=
|
|
||||||
github.com/getlantern/hidden v0.0.0-20220104173330-f221c5a24770/go.mod h1:GOQsoDnEHl6ZmNIL+5uVo+JWRFWozMEp18Izcb++H+A=
|
|
||||||
github.com/getlantern/ops v0.0.0-20190325191751-d70cb0d6f85f/go.mod h1:D5ao98qkA6pxftxoqzibIBBrLSUli+kYnJqrgBf9cIA=
|
|
||||||
github.com/getlantern/ops v0.0.0-20220713155959-1315d978fff7/go.mod h1:D5ao98qkA6pxftxoqzibIBBrLSUli+kYnJqrgBf9cIA=
|
|
||||||
github.com/getlantern/ops v0.0.0-20231025133620-f368ab734534 h1:3BwvWj0JZzFEvNNiMhCu4bf60nqcIuQpTYb00Ezm1ag=
|
|
||||||
github.com/getlantern/ops v0.0.0-20231025133620-f368ab734534/go.mod h1:ZsLfOY6gKQOTyEcPYNA9ws5/XHZQFroxqCOhHjGcs9Y=
|
|
||||||
github.com/getlantern/systray v1.2.2 h1:dCEHtfmvkJG7HZ8lS/sLklTH4RKUcIsKrAD9sThoEBE=
|
|
||||||
github.com/getlantern/systray v1.2.2/go.mod h1:pXFOI1wwqwYXEhLPm9ZGjS2u/vVELeIgNMY5HvhHhcE=
|
|
||||||
github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
|
|
||||||
github.com/go-logr/logr v1.2.3/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
|
|
||||||
github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY=
|
|
||||||
github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
|
|
||||||
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-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
|
|
||||||
github.com/go-stack/stack v1.8.1 h1:ntEHSVwIt7PNXNpgPmVfMrNhLtgjlmnZha2kOpuRiDw=
|
|
||||||
github.com/go-stack/stack v1.8.1/go.mod h1:dcoOX6HbPZSZptuspn9bctJ+N/CnF5gGygcUP3XYfe4=
|
|
||||||
github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
|
||||||
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
|
|
||||||
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
|
||||||
github.com/google/pprof v0.0.0-20240409012703-83162a5b38cd h1:gbpYu9NMq8jhDVbvlGkMFWCjLFlqqEZjEmObmhUy6Vo=
|
|
||||||
github.com/google/pprof v0.0.0-20240409012703-83162a5b38cd/go.mod h1:kf6iHlnVGwgKolg33glAes7Yg/8iWP8ukqeldJSO7jw=
|
|
||||||
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
|
|
||||||
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
|
||||||
github.com/hashicorp/golang-lru/v2 v2.0.7 h1:a+bsQ5rvGLjzHuww6tVxozPZFVghXaHOwFs4luLUK2k=
|
|
||||||
github.com/hashicorp/golang-lru/v2 v2.0.7/go.mod h1:QeFd9opnmA6QUJc5vARoKUSoFhyfM2/ZepoAG6RGpeM=
|
|
||||||
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
|
|
||||||
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
|
||||||
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
|
||||||
github.com/lxn/walk v0.0.0-20210112085537-c389da54e794/go.mod h1:E23UucZGqpuUANJooIbHWCufXvOcT6E7Stq81gU+CSQ=
|
|
||||||
github.com/lxn/win v0.0.0-20210218163916-a377121e959e/go.mod h1:KxxjdtRkfNoYDCUP5ryK7XJJNTnpC8atvtmTheChOtk=
|
|
||||||
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/ncruces/go-strftime v0.1.9 h1:bY0MQC28UADQmHmaF5dgpLmImcShSi2kHU9XLdhx/f4=
|
|
||||||
github.com/ncruces/go-strftime v0.1.9/go.mod h1:Fwc5htZGVVkseilnfgOVb9mKy6w1naJmn9CehxcKcls=
|
|
||||||
github.com/oxtoacart/bpool v0.0.0-20190530202638-03653db5a59c h1:rp5dCmg/yLR3mgFuSOe4oEnDDmGLROTvMragMUXpTQw=
|
|
||||||
github.com/oxtoacart/bpool v0.0.0-20190530202638-03653db5a59c/go.mod h1:X07ZCGwUbLaax7L0S3Tw4hpejzu63ZrrQiUe6W0hcy0=
|
|
||||||
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
|
||||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
|
||||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
|
||||||
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec h1:W09IVJc94icq4NjY3clb7Lk8O1qJ8BdBEF8z0ibU0rE=
|
|
||||||
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo=
|
|
||||||
github.com/skip2/go-qrcode v0.0.0-20200617195104-da1b6568686e h1:MRM5ITcdelLK2j1vwZ3Je0FKVCfqOLp5zO6trqMLYs0=
|
|
||||||
github.com/skip2/go-qrcode v0.0.0-20200617195104-da1b6568686e/go.mod h1:XV66xRDqSt+GTGFMVlhk3ULuV0y9ZmzeVGR4mloJI3M=
|
|
||||||
github.com/skratchdot/open-golang v0.0.0-20200116055534-eef842397966/go.mod h1:sUM3LWHvSMaG192sy56D9F7CNvL7jUJVXoqM1QKLnog=
|
|
||||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
|
||||||
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
|
|
||||||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
|
||||||
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
|
||||||
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
|
||||||
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
|
|
||||||
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
|
|
||||||
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
|
|
||||||
github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
|
|
||||||
go.opentelemetry.io/otel v1.9.0/go.mod h1:np4EoPGzoPs3O67xUVNoPPcmSvsfOxNlNA4F4AC+0Eo=
|
|
||||||
go.opentelemetry.io/otel v1.31.0 h1:NsJcKPIW0D0H3NgzPDHmo0WW6SptzPdqg/L1zsIm2hY=
|
|
||||||
go.opentelemetry.io/otel v1.31.0/go.mod h1:O0C14Yl9FgkjqcCZAsE053C13OaddMYr/hz6clDkEJE=
|
|
||||||
go.opentelemetry.io/otel/metric v1.31.0 h1:FSErL0ATQAmYHUIzSezZibnyVlft1ybhy4ozRPcF2fE=
|
|
||||||
go.opentelemetry.io/otel/metric v1.31.0/go.mod h1:C3dEloVbLuYoX41KpmAhOqNriGbA+qqH6PQ5E5mUfnY=
|
|
||||||
go.opentelemetry.io/otel/trace v1.9.0/go.mod h1:2737Q0MuG8q1uILYm2YYVkAyLtOofiTNGg6VODnOiPo=
|
|
||||||
go.opentelemetry.io/otel/trace v1.31.0 h1:ffjsj1aRouKewfr85U2aGagJ46+MvodynlQ1HYdmJys=
|
|
||||||
go.opentelemetry.io/otel/trace v1.31.0/go.mod h1:TXZkRk7SM2ZQLtR6eoAWQFIHPvzQ06FJAsO1tJg480A=
|
|
||||||
go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=
|
|
||||||
go.uber.org/goleak v1.1.11-0.20210813005559-691160354723/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ=
|
|
||||||
go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto=
|
|
||||||
go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE=
|
|
||||||
go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU=
|
|
||||||
go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0=
|
|
||||||
go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y=
|
|
||||||
go.uber.org/zap v1.19.1/go.mod h1:j3DNczoxDZroyBnOT1L/Q79cfUMGZxlv/9dzN7SM1rI=
|
|
||||||
go.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8=
|
|
||||||
go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E=
|
|
||||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
|
||||||
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
|
||||||
golang.org/x/exp v0.0.0-20231108232855-2478ac86f678 h1:mchzmB1XO2pMaKFRqk/+MV3mgGG96aqaPXaMifQU47w=
|
|
||||||
golang.org/x/exp v0.0.0-20231108232855-2478ac86f678/go.mod h1:zk2irFbV9DP96SEBUUAy67IdHUaZuSnrz1n472HUCLE=
|
|
||||||
golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
|
|
||||||
golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
|
||||||
golang.org/x/mod v0.19.0 h1:fEdghXQSo20giMthA7cd28ZC+jts4amQ3YMXiP5oMQ8=
|
|
||||||
golang.org/x/mod v0.19.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
|
|
||||||
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
|
||||||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
|
||||||
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
|
||||||
golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
|
|
||||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
|
||||||
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
|
||||||
golang.org/x/sync v0.7.0 h1:YsImfSBoP9QPYL0xyKJPq0gcaJdG3rInoqxTWbfQu9M=
|
|
||||||
golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
|
|
||||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
|
||||||
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
|
||||||
golang.org/x/sys v0.0.0-20201018230417-eeed37f84f13/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
|
||||||
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
|
||||||
golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
|
||||||
golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
|
||||||
golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
|
||||||
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
|
||||||
golang.org/x/sys v0.26.0 h1:KHjCJyddX0LoSTb3J+vWpupP9p0oznkqVk/IfjymZbo=
|
|
||||||
golang.org/x/sys v0.26.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
|
||||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
|
||||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
|
||||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
|
||||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
|
||||||
golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
|
||||||
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
|
||||||
golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
|
|
||||||
golang.org/x/tools v0.23.0 h1:SGsXPZ+2l4JsgaCKkx+FQ9YZ5XEtA1GZYuoDjenLjvg=
|
|
||||||
golang.org/x/tools v0.23.0/go.mod h1:pnu6ufv6vQkll6szChhK3C3L/ruaIv5eBeztNG8wtsI=
|
|
||||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
|
||||||
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
|
||||||
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
|
||||||
gopkg.in/Knetic/govaluate.v3 v3.0.0/go.mod h1:csKLBORsPbafmSCGTEh3U7Ozmsuq8ZSIlKk1bcqph0E=
|
|
||||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
|
||||||
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
|
||||||
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
|
||||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
|
||||||
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
|
||||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
|
||||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
|
||||||
modernc.org/cc/v4 v4.21.4 h1:3Be/Rdo1fpr8GrQ7IVw9OHtplU4gWbb+wNgeoBMmGLQ=
|
|
||||||
modernc.org/cc/v4 v4.21.4/go.mod h1:HM7VJTZbUCR3rV8EYBi9wxnJ0ZBRiGE5OeGXNA0IsLQ=
|
|
||||||
modernc.org/ccgo/v4 v4.21.0 h1:kKPI3dF7RIag8YcToh5ZwDcVMIv6VGa0ED5cvh0LMW4=
|
|
||||||
modernc.org/ccgo/v4 v4.21.0/go.mod h1:h6kt6H/A2+ew/3MW/p6KEoQmrq/i3pr0J/SiwiaF/g0=
|
|
||||||
modernc.org/fileutil v1.3.0 h1:gQ5SIzK3H9kdfai/5x41oQiKValumqNTDXMvKo62HvE=
|
|
||||||
modernc.org/fileutil v1.3.0/go.mod h1:XatxS8fZi3pS8/hKG2GH/ArUogfxjpEKs3Ku3aK4JyQ=
|
|
||||||
modernc.org/gc/v2 v2.5.0 h1:bJ9ChznK1L1mUtAQtxi0wi5AtAs5jQuw4PrPHO5pb6M=
|
|
||||||
modernc.org/gc/v2 v2.5.0/go.mod h1:wzN5dK1AzVGoH6XOzc3YZ+ey/jPgYHLuVckd62P0GYU=
|
|
||||||
modernc.org/gc/v3 v3.0.0-20241004144649-1aea3fae8852 h1:IYXPPTTjjoSHvUClZIYexDiO7g+4x+XveKT4gCIAwiY=
|
|
||||||
modernc.org/gc/v3 v3.0.0-20241004144649-1aea3fae8852/go.mod h1:Qz0X07sNOR1jWYCrJMEnbW/X55x206Q7Vt4mz6/wHp4=
|
|
||||||
modernc.org/libc v1.61.0 h1:eGFcvWpqlnoGwzZeZe3PWJkkKbM/3SUGyk1DVZQ0TpE=
|
|
||||||
modernc.org/libc v1.61.0/go.mod h1:DvxVX89wtGTu+r72MLGhygpfi3aUGgZRdAYGCAVVud0=
|
|
||||||
modernc.org/mathutil v1.6.0 h1:fRe9+AmYlaej+64JsEEhoWuAYBkOtQiMEU7n/XgfYi4=
|
|
||||||
modernc.org/mathutil v1.6.0/go.mod h1:Ui5Q9q1TR2gFm0AQRqQUaBWFLAhQpCwNcuhBOSedWPo=
|
|
||||||
modernc.org/memory v1.8.0 h1:IqGTL6eFMaDZZhEWwcREgeMXYwmW83LYW8cROZYkg+E=
|
|
||||||
modernc.org/memory v1.8.0/go.mod h1:XPZ936zp5OMKGWPqbD3JShgd/ZoQ7899TUuQqxY+peU=
|
|
||||||
modernc.org/opt v0.1.3 h1:3XOZf2yznlhC+ibLltsDGzABUGVx8J6pnFMS3E4dcq4=
|
|
||||||
modernc.org/opt v0.1.3/go.mod h1:WdSiB5evDcignE70guQKxYUl14mgWtbClRi5wmkkTX0=
|
|
||||||
modernc.org/sortutil v1.2.0 h1:jQiD3PfS2REGJNzNCMMaLSp/wdMNieTbKX920Cqdgqc=
|
|
||||||
modernc.org/sortutil v1.2.0/go.mod h1:TKU2s7kJMf1AE84OoiGppNHJwvB753OYfNl2WRb++Ss=
|
|
||||||
modernc.org/sqlite v1.33.1 h1:trb6Z3YYoeM9eDL1O8do81kP+0ejv+YzgyFo+Gwy0nM=
|
|
||||||
modernc.org/sqlite v1.33.1/go.mod h1:pXV2xHxhzXZsgT/RtTFAPY6JJDEvOTcTdwADQCCWD4k=
|
|
||||||
modernc.org/strutil v1.2.0 h1:agBi9dp1I+eOnxXeiZawM8F4LawKv4NzGWSaLfyeNZA=
|
|
||||||
modernc.org/strutil v1.2.0/go.mod h1:/mdcBmfOibveCTBxUl5B5l6W+TTH1FXPLHZE6bTosX0=
|
|
||||||
modernc.org/token v1.1.0 h1:Xl7Ap9dKaEs5kLoOQeQmPWevfnk/DM5qcLcYlA8ys6Y=
|
|
||||||
modernc.org/token v1.1.0/go.mod h1:UGzOrNV1mAFSEB63lOFHIpNRUVMvYTc6yu1SMY/XTDM=
|
|
||||||
-226
@@ -1,226 +0,0 @@
|
|||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"database/sql"
|
|
||||||
"errors"
|
|
||||||
"fmt"
|
|
||||||
"log"
|
|
||||||
"net/http"
|
|
||||||
"os"
|
|
||||||
"os/exec"
|
|
||||||
"runtime"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"bilidown/router"
|
|
||||||
"bilidown/util"
|
|
||||||
|
|
||||||
"github.com/getlantern/systray"
|
|
||||||
_ "modernc.org/sqlite"
|
|
||||||
)
|
|
||||||
|
|
||||||
const (
|
|
||||||
HTTP_PORT = 8098 // 限定 HTTP 服务器端口
|
|
||||||
HTTP_HOST = "" // 限定 HTTP 服务器主机
|
|
||||||
VERSION = "v2.1.1" // 软件版本号,将影响托盘标题显示
|
|
||||||
)
|
|
||||||
|
|
||||||
var urlLocal = fmt.Sprintf("http://127.0.0.1:%d", HTTP_PORT)
|
|
||||||
var urlLocalUnix = fmt.Sprintf("%s?___%d", urlLocal, time.Now().UnixMilli())
|
|
||||||
|
|
||||||
func main() {
|
|
||||||
checkFFmpeg()
|
|
||||||
// 启动托盘程序
|
|
||||||
systray.Run(onReady, nil)
|
|
||||||
}
|
|
||||||
|
|
||||||
func onReady() {
|
|
||||||
// 设置托盘图标
|
|
||||||
setIcon()
|
|
||||||
// 设置托盘标题
|
|
||||||
setTitle()
|
|
||||||
// 设置托盘菜单
|
|
||||||
setMenuItem()
|
|
||||||
// 初始化数据表
|
|
||||||
mustInitTables()
|
|
||||||
// 配置和启动 HTTP 服务器
|
|
||||||
mustRunServer()
|
|
||||||
// 调用默认浏览器访问端口
|
|
||||||
time.Sleep(time.Millisecond * 1000)
|
|
||||||
openBrowser(urlLocalUnix)
|
|
||||||
// 保持运行
|
|
||||||
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 or place it in ./bin, then restart the application.")
|
|
||||||
select {}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 配置和启动 HTTP 服务器
|
|
||||||
func mustRunServer() {
|
|
||||||
// 前端打包文件
|
|
||||||
http.Handle("/", http.FileServer(http.Dir("static")))
|
|
||||||
// 后端接口服务
|
|
||||||
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)
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
}
|
|
||||||
|
|
||||||
// openBrowser 调用系统默认浏览器打开指定 URL
|
|
||||||
func openBrowser(url string) {
|
|
||||||
var cmd *exec.Cmd
|
|
||||||
switch runtime.GOOS {
|
|
||||||
case "windows":
|
|
||||||
cmd = exec.Command("rundll32", "url.dll,FileProtocolHandler", url)
|
|
||||||
case "darwin":
|
|
||||||
cmd = exec.Command("open", url)
|
|
||||||
case "linux":
|
|
||||||
cmd = exec.Command("xdg-open", url)
|
|
||||||
default:
|
|
||||||
log.Printf("openBrowser: %v.", errors.New("unsupported operating system"))
|
|
||||||
}
|
|
||||||
if err := cmd.Start(); err != nil {
|
|
||||||
log.Printf("openBrowser: %v.", err)
|
|
||||||
}
|
|
||||||
fmt.Printf("Opened in default browser: %s.\n", url)
|
|
||||||
}
|
|
||||||
|
|
||||||
// setIcon 设置托盘图标
|
|
||||||
func setIcon() {
|
|
||||||
var path string
|
|
||||||
if runtime.GOOS == "windows" {
|
|
||||||
path = "static/favicon.ico"
|
|
||||||
} else {
|
|
||||||
path = "static/favicon-32x32.png"
|
|
||||||
}
|
|
||||||
systray.SetIcon(mustReadFile(path))
|
|
||||||
}
|
|
||||||
|
|
||||||
// mustReadFile 返回文件字节内容
|
|
||||||
func mustReadFile(path string) []byte {
|
|
||||||
data, err := os.ReadFile(path)
|
|
||||||
if err != nil {
|
|
||||||
log.Fatalln("os.ReadFile:", err)
|
|
||||||
}
|
|
||||||
return data
|
|
||||||
}
|
|
||||||
|
|
||||||
// setTitle 设置托盘标题和工具提示
|
|
||||||
func setTitle() {
|
|
||||||
title := "Bilidown"
|
|
||||||
tooltip := fmt.Sprintf("%s 视频解析器 %s (port:%d)", title, VERSION, HTTP_PORT)
|
|
||||||
// only available on Mac and Windows.
|
|
||||||
systray.SetTooltip(tooltip)
|
|
||||||
}
|
|
||||||
|
|
||||||
// setMenuItem 设置托盘菜单
|
|
||||||
func setMenuItem() {
|
|
||||||
openBrowserItemText := fmt.Sprintf("打开主界面 (port:%d)", HTTP_PORT)
|
|
||||||
openBrowserItem := systray.AddMenuItem(openBrowserItemText, openBrowserItemText)
|
|
||||||
go func() {
|
|
||||||
for {
|
|
||||||
<-openBrowserItem.ClickedCh
|
|
||||||
openBrowser(urlLocalUnix)
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
|
|
||||||
aboutItemText := "Github 项目主页"
|
|
||||||
aboutItem := systray.AddMenuItem(aboutItemText, aboutItemText)
|
|
||||||
go func() {
|
|
||||||
for {
|
|
||||||
<-aboutItem.ClickedCh
|
|
||||||
openBrowser("https://github.com/iuroc/bilidown")
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
|
|
||||||
exitItemText := "退出应用"
|
|
||||||
exitItem := systray.AddMenuItem(exitItemText, exitItemText)
|
|
||||||
go func() {
|
|
||||||
<-exitItem.ClickedCh
|
|
||||||
log.Printf("Bilidown has exited.")
|
|
||||||
systray.Quit()
|
|
||||||
}()
|
|
||||||
}
|
|
||||||
|
|
||||||
// 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 {
|
|
||||||
// 检查download_type列是否存在,如果不存在则添加
|
|
||||||
// SQLite没有直接的方法检查列是否存在,我们尝试添加列并忽略错误
|
|
||||||
// 使用事务确保操作原子性
|
|
||||||
util.SqliteLock.Lock()
|
|
||||||
_, _ = db.Exec(`ALTER TABLE "task" ADD COLUMN "download_type" TEXT DEFAULT 'merge'`)
|
|
||||||
// 将现有记录中的NULL值更新为默认值'merge'
|
|
||||||
_, _ = db.Exec(`UPDATE "task" SET "download_type" = 'merge' WHERE "download_type" IS NULL`)
|
|
||||||
util.SqliteLock.Unlock()
|
|
||||||
|
|
||||||
// 忽略错误,因为列可能已经存在
|
|
||||||
// SQLite错误码为1表示列已存在
|
|
||||||
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
|
|
||||||
}
|
|
||||||
|
Before Width: | Height: | Size: 1.6 KiB After Width: | Height: | Size: 1.6 KiB |
|
Before Width: | Height: | Size: 15 KiB After Width: | Height: | Size: 15 KiB |
@@ -9,7 +9,7 @@ export default defineConfig({
|
|||||||
host: '0.0.0.0'
|
host: '0.0.0.0'
|
||||||
},
|
},
|
||||||
build: {
|
build: {
|
||||||
outDir: '../server/static',
|
outDir: '../build/static',
|
||||||
emptyOutDir: true,
|
emptyOutDir: true,
|
||||||
},
|
},
|
||||||
css: {
|
css: {
|
||||||
Reference in New Issue
Block a user