This commit is contained in:
commit
c00090712d
20
.gitea/workflows/build-push.yml
Normal file
20
.gitea/workflows/build-push.yml
Normal file
@ -0,0 +1,20 @@
|
||||
name: Build image
|
||||
on: [push]
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: https://git.timerzz.com:20443/timerzz/setup-go@v4
|
||||
env:
|
||||
HTTPS_PROXY: http://192.168.31.55:10809
|
||||
with:
|
||||
go-version: '1.22.x'
|
||||
- uses: https://git.timerzz.com:20443/timerzz/checkout@v4
|
||||
- uses: https://git.timerzz.com:20443/timerzz/setup-ko@v0.6
|
||||
with:
|
||||
version: v0.15.4
|
||||
env:
|
||||
KO_DOCKER_REPO: 192.168.31.55:5000/paas/bilibili
|
||||
- run: ko build --bare ./subtitles
|
||||
env:
|
||||
KO_DOCKER_REPO: 192.168.31.55:5000/paas/bilibili
|
28
go.mod
Normal file
28
go.mod
Normal file
@ -0,0 +1,28 @@
|
||||
module gitea.timerzz.com/paas/bilibili
|
||||
|
||||
go 1.22.2
|
||||
|
||||
require (
|
||||
github.com/go-playground/validator/v10 v10.22.0
|
||||
github.com/gofiber/fiber/v3 v3.0.0-beta.2
|
||||
)
|
||||
|
||||
require (
|
||||
github.com/andybalholm/brotli v1.1.0 // indirect
|
||||
github.com/gabriel-vasile/mimetype v1.4.3 // indirect
|
||||
github.com/go-playground/locales v0.14.1 // indirect
|
||||
github.com/go-playground/universal-translator v0.18.1 // indirect
|
||||
github.com/gofiber/utils/v2 v2.0.0-beta.4 // indirect
|
||||
github.com/google/uuid v1.6.0 // indirect
|
||||
github.com/klauspost/compress v1.17.6 // indirect
|
||||
github.com/leodido/go-urn v1.4.0 // indirect
|
||||
github.com/mattn/go-colorable v0.1.13 // indirect
|
||||
github.com/mattn/go-isatty v0.0.20 // indirect
|
||||
github.com/valyala/bytebufferpool v1.0.0 // indirect
|
||||
github.com/valyala/fasthttp v1.52.0 // indirect
|
||||
github.com/valyala/tcplisten v1.0.0 // indirect
|
||||
golang.org/x/crypto v0.19.0 // indirect
|
||||
golang.org/x/net v0.21.0 // indirect
|
||||
golang.org/x/sys v0.17.0 // indirect
|
||||
golang.org/x/text v0.14.0 // indirect
|
||||
)
|
51
go.sum
Normal file
51
go.sum
Normal file
@ -0,0 +1,51 @@
|
||||
github.com/andybalholm/brotli v1.1.0 h1:eLKJA0d02Lf0mVpIDgYnqXcUn0GqVmEFny3VuID1U3M=
|
||||
github.com/andybalholm/brotli v1.1.0/go.mod h1:sms7XGricyQI9K10gOSf56VKKWS4oLer58Q+mhRPtnY=
|
||||
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/gabriel-vasile/mimetype v1.4.3 h1:in2uUcidCuFcDKtdcBxlR0rJ1+fsokWf+uqxgUFjbI0=
|
||||
github.com/gabriel-vasile/mimetype v1.4.3/go.mod h1:d8uq/6HKRL6CGdk+aubisF/M5GcPfT7nKyLpA0lbSSk=
|
||||
github.com/go-playground/assert/v2 v2.2.0 h1:JvknZsQTYeFEAhQwI4qEt9cyV5ONwRHC+lYKSsYSR8s=
|
||||
github.com/go-playground/assert/v2 v2.2.0/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4=
|
||||
github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/oXslEjJA=
|
||||
github.com/go-playground/locales v0.14.1/go.mod h1:hxrqLVvrK65+Rwrd5Fc6F2O76J/NuW9t0sjnWqG1slY=
|
||||
github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJnYK9S473LQFuzCbDbfSFY=
|
||||
github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY=
|
||||
github.com/go-playground/validator/v10 v10.22.0 h1:k6HsTZ0sTnROkhS//R0O+55JgM8C4Bx7ia+JlgcnOao=
|
||||
github.com/go-playground/validator/v10 v10.22.0/go.mod h1:dbuPbCMFw/DrkbEynArYaCwl3amGuJotoKCe95atGMM=
|
||||
github.com/gofiber/fiber/v3 v3.0.0-beta.2 h1:mVVgt8PTaHGup3NGl/+7U7nEoZaXJ5OComV4E+HpAao=
|
||||
github.com/gofiber/fiber/v3 v3.0.0-beta.2/go.mod h1:w7sdfTY0okjZ1oVH6rSOGvuACUIt0By1iK0HKUb3uqM=
|
||||
github.com/gofiber/utils/v2 v2.0.0-beta.4 h1:1gjbVFFwVwUb9arPcqiB6iEjHBwo7cHsyS41NeIW3co=
|
||||
github.com/gofiber/utils/v2 v2.0.0-beta.4/go.mod h1:sdRsPU1FXX6YiDGGxd+q2aPJRMzpsxdzCXo9dz+xtOY=
|
||||
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/klauspost/compress v1.17.6 h1:60eq2E/jlfwQXtvZEeBUYADs+BwKBWURIY+Gj2eRGjI=
|
||||
github.com/klauspost/compress v1.17.6/go.mod h1:/dCuZOvVtNoHsyb+cuJD3itjs3NbnF6KH9zAO4BDxPM=
|
||||
github.com/leodido/go-urn v1.4.0 h1:WT9HwE9SGECu3lg4d/dIA+jxlljEa1/ffXKmRjqdmIQ=
|
||||
github.com/leodido/go-urn v1.4.0/go.mod h1:bvxc+MVxLKB4z00jd1z+Dvzr47oO32F/QSNjSBOlFxI=
|
||||
github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA=
|
||||
github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg=
|
||||
github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
|
||||
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/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
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/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw=
|
||||
github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc=
|
||||
github.com/valyala/fasthttp v1.52.0 h1:wqBQpxH71XW0e2g+Og4dzQM8pk34aFYlA1Ga8db7gU0=
|
||||
github.com/valyala/fasthttp v1.52.0/go.mod h1:hf5C4QnVMkNXMspnsUlfM3WitlgYflyhHYoKol/szxQ=
|
||||
github.com/valyala/tcplisten v1.0.0 h1:rBHj/Xf+E1tRGZyWIWwJDiRY0zc1Js+CV5DqwacVSA8=
|
||||
github.com/valyala/tcplisten v1.0.0/go.mod h1:T0xQ8SeCZGxckz9qRXTfG43PvQ/mcWh7FwZEA7Ioqkc=
|
||||
golang.org/x/crypto v0.19.0 h1:ENy+Az/9Y1vSrlrvBSyna3PITt4tiZLf7sgCjZBX7Wo=
|
||||
golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU=
|
||||
golang.org/x/net v0.21.0 h1:AQyQV4dYCvJ7vGmJyKki9+PBdyvhkSd8EIx/qb0AYv4=
|
||||
golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44=
|
||||
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.17.0 h1:25cE3gD+tdBA7lp7QfhuV+rJiE9YXTcS3VG1SqssI/Y=
|
||||
golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ=
|
||||
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
|
||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
129
subtitles/client.go
Normal file
129
subtitles/client.go
Normal file
@ -0,0 +1,129 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/gofiber/fiber/v3/client"
|
||||
"net/url"
|
||||
"regexp"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
var headers = map[string][]string{
|
||||
"Accept": {"application/json"},
|
||||
"Content-Type": {"application/json"},
|
||||
"User-Agent": {"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/110.0.0.0 Safari/537.36"},
|
||||
"Host": {"api.bilibili.com"},
|
||||
}
|
||||
|
||||
type Client struct {
|
||||
cli *client.Client
|
||||
}
|
||||
|
||||
func NewClient(sessData string) *Client {
|
||||
return &Client{
|
||||
cli: client.New().AddHeaders(headers).SetCookie("SESSDATA", sessData),
|
||||
}
|
||||
}
|
||||
|
||||
func (c *Client) GetSubtitles(url string) (string, error) {
|
||||
vid, page, err := parseBilibiliUrl(url)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
data, err := c.callView(vid)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
var aid, cid = data.Data.Stat.Aid, 0
|
||||
for _, p := range data.Data.Pages {
|
||||
if p.Page == page {
|
||||
cid = p.Cid
|
||||
}
|
||||
}
|
||||
player, err := c.callPlayer(aid, cid)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
subTitlesUrl := ""
|
||||
for _, sub := range player.Data.Subtitle.Subtitles {
|
||||
if sub.SubtitleUrl != "" {
|
||||
subTitlesUrl = fmt.Sprintf("https:%s", sub.SubtitleUrl)
|
||||
break
|
||||
}
|
||||
}
|
||||
subtitles, err := c.callSubtitles(subTitlesUrl)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
var subtitlesList = make([]string, 0, len(subtitles.Body))
|
||||
for _, sub := range subtitles.Body {
|
||||
subtitlesList = append(subtitlesList, sub.Content)
|
||||
}
|
||||
return strings.Join(subtitlesList, "\n"), nil
|
||||
}
|
||||
|
||||
func (c *Client) callView(vid string) (data Response[ViewResponseData], err error) {
|
||||
var r = c.cli.R()
|
||||
if strings.HasPrefix(vid, "av") {
|
||||
r.AddParam("aid", vid[2:])
|
||||
} else {
|
||||
r.AddParam("bvid", vid)
|
||||
}
|
||||
resp, err := r.Get("https://api.bilibili.com/x/web-interface/view")
|
||||
if err != nil {
|
||||
return data, fmt.Errorf("请求 %s 出错:%v", r.URL(), err)
|
||||
}
|
||||
err = resp.JSON(&data)
|
||||
return data, err
|
||||
}
|
||||
|
||||
func (c *Client) callPlayer(aid, cid int) (data Response[PlayerResponseData], err error) {
|
||||
var r = c.cli.R()
|
||||
r.AddParam("aid", strconv.Itoa(aid))
|
||||
r.AddParam("cid", strconv.Itoa(cid))
|
||||
|
||||
resp, err := r.Get("https://api.bilibili.com/x/player/v2")
|
||||
if err != nil {
|
||||
return data, fmt.Errorf("请求 %s 出错:%v", r.URL(), err)
|
||||
}
|
||||
err = resp.JSON(&data)
|
||||
return data, err
|
||||
}
|
||||
|
||||
func (c *Client) callSubtitles(url string) (data SubtitlesResponse, err error) {
|
||||
var r = c.cli.R()
|
||||
resp, err := r.Get(url)
|
||||
if err != nil {
|
||||
return data, fmt.Errorf("请求 %s 出错:%v", r.URL(), err)
|
||||
}
|
||||
err = resp.JSON(&data)
|
||||
return data, err
|
||||
}
|
||||
|
||||
func parseBilibiliUrl(bu string) (vid string, page int, err error) {
|
||||
u, err := url.Parse(bu)
|
||||
if err != nil {
|
||||
return "", 0, err
|
||||
}
|
||||
if u.Host != "www.bilibili.com" && u.Host != "m.bilibili.com" {
|
||||
return "", 0, fmt.Errorf("链接似乎不是bilibili的视频链接")
|
||||
}
|
||||
re := regexp.MustCompile("/video/(?P<vid>[a-zA-Z0-9]+)")
|
||||
parts := re.FindStringSubmatch(u.Path)
|
||||
names := re.SubexpNames()
|
||||
for _, name := range names {
|
||||
if name == "vid" {
|
||||
vid = parts[re.SubexpIndex(name)]
|
||||
}
|
||||
}
|
||||
if vid == "" {
|
||||
return "", 0, fmt.Errorf("链接似乎不是bilibili的视频链接,未获取到视频id")
|
||||
}
|
||||
query := u.Query()
|
||||
if query.Get("p") != "" {
|
||||
pageStr := query.Get("p")
|
||||
page, _ = strconv.Atoi(pageStr)
|
||||
}
|
||||
return vid, page, nil
|
||||
}
|
61
subtitles/data.go
Normal file
61
subtitles/data.go
Normal file
@ -0,0 +1,61 @@
|
||||
package main
|
||||
|
||||
type ResponseData interface {
|
||||
ViewResponseData | PlayerResponseData
|
||||
}
|
||||
|
||||
type Response[T ResponseData] struct {
|
||||
Code int `json:"code"`
|
||||
Message string `json:"message"`
|
||||
Ttl int `json:"ttl"`
|
||||
Data T `json:"data"`
|
||||
}
|
||||
|
||||
type ViewResponseData struct {
|
||||
Bvid string `json:"bvid"`
|
||||
Title string `json:"title"`
|
||||
Duration int `json:"duration"`
|
||||
Stat struct {
|
||||
Aid int `json:"aid"`
|
||||
} `json:"stat"`
|
||||
Pages []struct {
|
||||
Cid int `json:"cid"`
|
||||
Page int `json:"page"`
|
||||
From string `json:"from"`
|
||||
Part string `json:"part"`
|
||||
Duration int `json:"duration"`
|
||||
Vid string `json:"vid"`
|
||||
Weblink string `json:"weblink"`
|
||||
} `json:"pages"`
|
||||
}
|
||||
|
||||
type PlayerResponseData struct {
|
||||
Aid int `json:"aid"`
|
||||
Bvid string `json:"bvid"`
|
||||
Cid int `json:"cid"`
|
||||
PageNo int `json:"page_no"`
|
||||
Subtitle struct {
|
||||
Subtitles []struct {
|
||||
Id int64 `json:"id"`
|
||||
Lan string `json:"lan"`
|
||||
LanDoc string `json:"lan_doc"`
|
||||
IsLock bool `json:"is_lock"`
|
||||
SubtitleUrl string `json:"subtitle_url"`
|
||||
Type int `json:"type"`
|
||||
IdStr string `json:"id_str"`
|
||||
AiType int `json:"ai_type"`
|
||||
AiStatus int `json:"ai_status"`
|
||||
} `json:"subtitles"`
|
||||
} `json:"subtitle"`
|
||||
}
|
||||
|
||||
type SubtitlesResponse struct {
|
||||
Body []struct {
|
||||
From float64 `json:"from"`
|
||||
To float64 `json:"to"`
|
||||
Sid int `json:"sid"`
|
||||
Location int `json:"location"`
|
||||
Content string `json:"content"`
|
||||
Music int `json:"music"`
|
||||
} `json:"body"`
|
||||
}
|
62
subtitles/main.go
Normal file
62
subtitles/main.go
Normal file
@ -0,0 +1,62 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"github.com/go-playground/validator/v10"
|
||||
"github.com/gofiber/fiber/v3"
|
||||
"github.com/gofiber/fiber/v3/middleware/cors"
|
||||
"github.com/gofiber/fiber/v3/middleware/healthcheck"
|
||||
"github.com/gofiber/fiber/v3/middleware/recover"
|
||||
"os"
|
||||
)
|
||||
|
||||
type Request struct {
|
||||
Url string `json:"url" validate:"required"`
|
||||
}
|
||||
|
||||
func main() {
|
||||
sessData := os.Getenv("SESSDATA")
|
||||
if sessData == "" {
|
||||
panic("SESSDATA is required")
|
||||
}
|
||||
|
||||
cli := NewClient(sessData)
|
||||
s := &Service{cli: cli}
|
||||
app := fiber.New(fiber.Config{
|
||||
StructValidator: &structValidator{validate: validator.New()},
|
||||
})
|
||||
|
||||
app.Use(recover.New(), cors.New())
|
||||
app.Get(healthcheck.DefaultLivenessEndpoint, healthcheck.NewHealthChecker())
|
||||
// Provide a minimal config for readiness check
|
||||
app.Get(healthcheck.DefaultReadinessEndpoint, healthcheck.NewHealthChecker())
|
||||
|
||||
app.Post("/api/v1/bilibili/subtitles", s.GetSubtitles)
|
||||
|
||||
_ = app.Listen(":80")
|
||||
}
|
||||
|
||||
type Service struct {
|
||||
cli *Client
|
||||
}
|
||||
|
||||
// GetSubtitles @Summary 获取字幕
|
||||
// @Description 获取字幕
|
||||
// @Accept application/json
|
||||
// @Produce application/json
|
||||
// @Param json body Request true "请求参数"
|
||||
// @Router /api/v1/bilibili/subtitles [post]
|
||||
func (s *Service) GetSubtitles(ctx fiber.Ctx) error {
|
||||
var req Request
|
||||
if err := ctx.Bind().JSON(&req); err != nil {
|
||||
return err
|
||||
}
|
||||
data, err := s.cli.GetSubtitles(req.Url)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return ctx.JSON(fiber.Map{
|
||||
"data": data,
|
||||
"code": 0,
|
||||
"msg": "ok",
|
||||
})
|
||||
}
|
73
subtitles/swag/docs.go
Normal file
73
subtitles/swag/docs.go
Normal file
@ -0,0 +1,73 @@
|
||||
// Package swag Code generated by swaggo/swag. DO NOT EDIT
|
||||
package swag
|
||||
|
||||
import "github.com/swaggo/swag"
|
||||
|
||||
const docTemplate = `{
|
||||
"schemes": {{ marshal .Schemes }},
|
||||
"swagger": "2.0",
|
||||
"info": {
|
||||
"description": "{{escape .Description}}",
|
||||
"title": "{{.Title}}",
|
||||
"contact": {},
|
||||
"version": "{{.Version}}"
|
||||
},
|
||||
"host": "{{.Host}}",
|
||||
"basePath": "{{.BasePath}}",
|
||||
"paths": {
|
||||
"/api/v1/bilibili/subtitles": {
|
||||
"post": {
|
||||
"description": "获取字幕",
|
||||
"consumes": [
|
||||
"application/json"
|
||||
],
|
||||
"produces": [
|
||||
"application/json"
|
||||
],
|
||||
"parameters": [
|
||||
{
|
||||
"description": "请求参数",
|
||||
"name": "json",
|
||||
"in": "body",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"$ref": "#/definitions/main.Request"
|
||||
}
|
||||
}
|
||||
],
|
||||
"responses": {}
|
||||
}
|
||||
}
|
||||
},
|
||||
"definitions": {
|
||||
"main.Request": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
"url"
|
||||
],
|
||||
"properties": {
|
||||
"url": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}`
|
||||
|
||||
// SwaggerInfo holds exported Swagger Info so clients can modify it
|
||||
var SwaggerInfo = &swag.Spec{
|
||||
Version: "",
|
||||
Host: "",
|
||||
BasePath: "",
|
||||
Schemes: []string{},
|
||||
Title: "",
|
||||
Description: "",
|
||||
InfoInstanceName: "swagger",
|
||||
SwaggerTemplate: docTemplate,
|
||||
LeftDelim: "{{",
|
||||
RightDelim: "}}",
|
||||
}
|
||||
|
||||
func init() {
|
||||
swag.Register(SwaggerInfo.InstanceName(), SwaggerInfo)
|
||||
}
|
44
subtitles/swag/swagger.json
Normal file
44
subtitles/swag/swagger.json
Normal file
@ -0,0 +1,44 @@
|
||||
{
|
||||
"swagger": "2.0",
|
||||
"info": {
|
||||
"contact": {}
|
||||
},
|
||||
"paths": {
|
||||
"/api/v1/bilibili/subtitles": {
|
||||
"post": {
|
||||
"description": "获取字幕",
|
||||
"consumes": [
|
||||
"application/json"
|
||||
],
|
||||
"produces": [
|
||||
"application/json"
|
||||
],
|
||||
"parameters": [
|
||||
{
|
||||
"description": "请求参数",
|
||||
"name": "json",
|
||||
"in": "body",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"$ref": "#/definitions/main.Request"
|
||||
}
|
||||
}
|
||||
],
|
||||
"responses": {}
|
||||
}
|
||||
}
|
||||
},
|
||||
"definitions": {
|
||||
"main.Request": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
"url"
|
||||
],
|
||||
"properties": {
|
||||
"url": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
27
subtitles/swag/swagger.yaml
Normal file
27
subtitles/swag/swagger.yaml
Normal file
@ -0,0 +1,27 @@
|
||||
definitions:
|
||||
main.Request:
|
||||
properties:
|
||||
url:
|
||||
type: string
|
||||
required:
|
||||
- url
|
||||
type: object
|
||||
info:
|
||||
contact: {}
|
||||
paths:
|
||||
/api/v1/bilibili/subtitles:
|
||||
post:
|
||||
consumes:
|
||||
- application/json
|
||||
description: 获取字幕
|
||||
parameters:
|
||||
- description: 请求参数
|
||||
in: body
|
||||
name: json
|
||||
required: true
|
||||
schema:
|
||||
$ref: '#/definitions/main.Request'
|
||||
produces:
|
||||
- application/json
|
||||
responses: {}
|
||||
swagger: "2.0"
|
15
subtitles/validator.go
Normal file
15
subtitles/validator.go
Normal file
@ -0,0 +1,15 @@
|
||||
package main
|
||||
|
||||
import "github.com/go-playground/validator/v10"
|
||||
|
||||
type structValidator struct {
|
||||
validate *validator.Validate
|
||||
}
|
||||
|
||||
func (v *structValidator) Engine() any {
|
||||
return ""
|
||||
}
|
||||
|
||||
func (v *structValidator) ValidateStruct(out any) error {
|
||||
return v.validate.Struct(out)
|
||||
}
|
Loading…
Reference in New Issue
Block a user