From 1fee7424ff4362e918411bcb9c66581ca5d73698 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=B0=8F=E5=AE=87=E5=AE=87?= <3061196825@qq.com> Date: Mon, 29 Jun 2026 15:57:47 +0800 Subject: [PATCH 1/4] =?UTF-8?q?feat(pixiv):=20=E5=AE=9E=E7=8E=B0=20Pixiv?= =?UTF-8?q?=20API=20=E5=AE=A2=E6=88=B7=E7=AB=AF=E5=8F=8A=E6=8F=92=E7=94=BB?= =?UTF-8?q?=E8=8E=B7=E5=8F=96=E6=A8=A1=E5=9E=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pixiv/client.go | 153 ++++++++++++++++++++++++++++++ pixiv/model/model.go | 136 +++++++++++++++++++++++++++ pixiv/pixiv_api.go | 217 +++++++++++++++++++++++++++++++++++++++++++ pixiv/token.go | 87 +++++++++++++++++ pixiv/utils.go | 161 ++++++++++++++++++++++++++++++++ 5 files changed, 754 insertions(+) create mode 100644 pixiv/client.go create mode 100644 pixiv/model/model.go create mode 100644 pixiv/pixiv_api.go create mode 100644 pixiv/token.go create mode 100644 pixiv/utils.go diff --git a/pixiv/client.go b/pixiv/client.go new file mode 100644 index 0000000..375269f --- /dev/null +++ b/pixiv/client.go @@ -0,0 +1,153 @@ +// Package pixiv (copied from plugin/pixiv/api/client.go) +package pixiv + +import ( + "crypto/tls" + "encoding/json" + "errors" + "fmt" + "io" + "net/http" + "net/url" + "strings" + "time" + + "github.com/FloatTech/AnimeAPI/pixiv/model" +) + +// HTTPStatusError ... +type HTTPStatusError struct { + StatusCode int + URL string +} + +func (e *HTTPStatusError) Error() string { + return fmt.Sprintf("下载图片失败: HTTP %d", e.StatusCode) +} + +// Client 封装 HTTP 客户端与 Pixiv 请求逻辑 +type Client struct { + *http.Client + transport *http.Transport +} + +// NewClient ... +func NewClient() *Client { + transport := &http.Transport{ + TLSClientConfig: &tls.Config{MaxVersion: tls.VersionTLS13}, + Proxy: http.ProxyFromEnvironment, + } + return &Client{ + Client: &http.Client{ + Transport: transport, + Timeout: time.Minute, + }, + transport: transport, + } +} + +// SetProxy 设置代理 +func (c *Client) SetProxy(proxyURL string) error { + if c == nil || c.transport == nil { + return errors.New("pixiv client is nil") + } + proxyURL = strings.TrimSpace(proxyURL) + if proxyURL == "" { + c.transport.Proxy = http.ProxyFromEnvironment + return nil + } + u, err := url.Parse(proxyURL) + if err != nil { + return err + } + c.transport.Proxy = http.ProxyURL(u) + return nil +} + +// SearchPixivIllustrations ... +func (c *Client) SearchPixivIllustrations(accessToken, url string) (*model.RootEntity, error) { + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return nil, err + } + req.Header.Set("Authorization", "Bearer "+accessToken) + + req.Header.Set("User-Agent", "PixivAndroidApp/5.0.234 (Android 11; Pixel 5)") + req.Header.Set("App-OS", "android") + req.Header.Set("App-OS-Version", "11") + req.Header.Set("App-Version", "5.0.234") + + req.Header.Set("Accept-Language", "en_US") + req.Header.Set("Referer", "https://app-api.pixiv.net/") + req.Header.Set("Connection", "keep-alive") + + req.Host = "app-api.pixiv.net" + + resp, err := c.Do(req) + if err != nil { + return nil, err + } + defer resp.Body.Close() + + body, _ := io.ReadAll(resp.Body) + if resp.StatusCode != 200 { + return nil, errors.New("搜索失败: " + resp.Status + "\nbody: " + string(body)) + } + + var result model.RootEntity + if err := json.Unmarshal(body, &result); err != nil { + return nil, err + } + return &result, nil +} + +func (c *Client) fetchOnce(targetURL, referer string) ([]byte, int, error) { + req, err := http.NewRequest("GET", targetURL, nil) + if err != nil { + return nil, 0, err + } + + req.Header.Set("Referer", referer) + req.Header.Set("User-Agent", "PixivAndroidApp/5.0.234 (Android 11; Pixel 5)") + + resp, err := c.Do(req) + if err != nil { + return nil, 0, errors.New("请求失败: " + err.Error()) + } + defer resp.Body.Close() + + data, err := io.ReadAll(resp.Body) + if err != nil { + return nil, resp.StatusCode, err + } + + return data, resp.StatusCode, nil +} + +// FetchPixivImage 直接从 Pixiv 下载图片 +func (c *Client) FetchPixivImage(illust model.IllustCache, url string) ([]byte, error) { + fmt.Println("下载", illust.PID) + + if c == nil { + fmt.Println("FetchPixivImage called on nil IllustCache") + return nil, nil + } + + data, status, err := c.fetchOnce(url, "https://www.pixiv.net/") + if err == nil && status == http.StatusOK { + return data, nil + } + if status == http.StatusNotFound { + return nil, &HTTPStatusError{StatusCode: status, URL: url} + } + + if err != nil { + return nil, err + } + + if status != 0 { + return nil, &HTTPStatusError{StatusCode: status, URL: url} + } + + return nil, errors.New("下载图片失败") +} diff --git a/pixiv/model/model.go b/pixiv/model/model.go new file mode 100644 index 0000000..9e46e43 --- /dev/null +++ b/pixiv/model/model.go @@ -0,0 +1,136 @@ +// Package model ... +package model + +import ( + "github.com/jinzhu/gorm" + "gorm.io/datatypes" +) + +// IllustCache 插画缓存表 +type IllustCache struct { + gorm.Model + + PID int64 `gorm:"unique_index:idx_keyword_pid;not null;column:pid"` // Pixiv 作品 ID + UID int64 `gorm:"default:0;not null;column:uid"` // 插画作者的id + Keyword string `gorm:"unique_index:idx_keyword_pid;type:varchar(255)"` // 搜索关键词 + Title string `gorm:"type:varchar(255)"` // 标题 + AuthorName string `gorm:"type:varchar(255)"` // 用户名 + ImageURL string `gorm:"type:varchar(500)"` // 大图地址 + OriginalURL string `gorm:"type:varchar(500)"` // 原图地址 + R18 bool `gorm:"not null;default:false"` // 是否为 R-18 作品 + Bookmarks int64 // 收藏数 + TotalView int64 // 总浏览数 + CreateDate string // 创建日期 + PageCount int64 `gorm:"default:1"` // 页数 + Tags datatypes.JSON `gorm:"type:json"` // 插画的所有标签 方便后续查找 +} + +// SentImage 已发送记录表 +type SentImage struct { + gorm.Model + + GroupID int64 `gorm:"index:idx_group_pid;not null"` // 群组 ID + PID int64 `gorm:"index:idx_group_pid;not null;column:pid"` // 插画 PID +} + +// GroupR18Permission R18权限表 +type GroupR18Permission struct { + gorm.Model + GroupID int64 `gorm:"unique_index"` +} + +// RefreshToken ... +type RefreshToken struct { + gorm.Model + + User int64 `gorm:"unique"` + + Token string +} + +// PixivProxyConfig 保存 Pixiv API 客户端的代理配置 +type PixivProxyConfig struct { + gorm.Model + + Name string `gorm:"unique_index"` + Proxy string +} + +// RootEntity ... +type RootEntity struct { + Illusts []IllustsEntity `json:"illusts"` + Illust *IllustsEntity `json:"illust"` + NextURL string `json:"next_url"` + SearchSpanLimit int64 `json:"search_span_limit"` + ShowAi bool `json:"show_ai"` +} + +// IllustsEntity ... +type IllustsEntity struct { + ID int64 `json:"id"` + Title string `json:"title"` + Type string `json:"type"` + ImageURLs ImageUrlsEntity `json:"image_urls"` + Caption string `json:"caption"` + Restrict int64 `json:"restrict"` + User UserEntity `json:"user"` + Tags []TagsEntity `json:"tags"` + CreateDate string `json:"create_date"` + PageCount int64 `json:"page_count"` + Width int64 `json:"width"` + Height int64 `json:"height"` + SanityLevel int64 `json:"sanity_level"` + XRestrict int64 `json:"x_restrict"` + MetaSinglePage MetaSinglePageEntity `json:"meta_single_page"` + MetaPages []MetaPage `json:"meta_pages"` + TotalView int64 `json:"total_view"` + TotalBookmarks int64 `json:"total_bookmarks"` + IsBookmarked bool `json:"is_bookmarked"` + Visible bool `json:"visible"` + IsMuted bool `json:"is_muted"` + IllustAiType int64 `json:"illust_ai_type"` + IllustBookStyle int64 `json:"illust_book_style"` +} + +// MetaPage ... +type MetaPage struct { + ImageURLs struct { + SquareMedium string `json:"square_medium"` + Medium string `json:"medium"` + Large string `json:"large"` + Original string `json:"original"` + } `json:"image_urls"` +} + +// ImageUrlsEntity ... +type ImageUrlsEntity struct { + SquareMedium string `json:"square_medium"` + Medium string `json:"medium"` + Large string `json:"large"` +} + +// UserEntity ... +type UserEntity struct { + ID int64 `json:"id"` + Name string `json:"name"` + Account string `json:"account"` + ProfileImageUrls ProfileImageUrlsEntity `json:"profile_image_urls"` + IsFollowed bool `json:"is_followed"` + IsAcceptRequest bool `json:"is_accept_request"` +} + +// ProfileImageUrlsEntity ... +type ProfileImageUrlsEntity struct { + Medium string `json:"medium"` +} + +// TagsEntity ... +type TagsEntity struct { + Name string `json:"name"` + TranslatedName interface{} `json:"translated_name"` +} + +// MetaSinglePageEntity ... +type MetaSinglePageEntity struct { + OriginalImageURL string `json:"original_image_url"` +} diff --git a/pixiv/pixiv_api.go b/pixiv/pixiv_api.go new file mode 100644 index 0000000..4ddcc92 --- /dev/null +++ b/pixiv/pixiv_api.go @@ -0,0 +1,217 @@ +// Package pixiv (copied from plugin/pixiv/api/pixiv_api.go) +package pixiv + +import ( + "errors" + "fmt" + "sort" + + "github.com/FloatTech/AnimeAPI/pixiv/model" + log "github.com/sirupsen/logrus" +) + +// PixivAPI ... +type PixivAPI struct { + Client *Client + Token *TokenStore +} + +// NewPixivAPI ... +func NewPixivAPI(refreshToken string) *PixivAPI { + c := NewClient() + return &PixivAPI{ + Client: c, + Token: NewTokenStore(refreshToken, c), + } +} + +// FetchPixivByPID ... +func (p *PixivAPI) FetchPixivByPID(pid int64) (*model.IllustCache, error) { + url := fmt.Sprintf("https://app-api.pixiv.net/v1/illust/detail?illust_id=%d", pid) + accessToken, err := p.Token.GetAccessToken() + if err != nil { + return nil, err + } + rawData, err := p.Client.SearchPixivIllustrations(accessToken, url) + if err != nil { + return nil, err + } + if rawData == nil || rawData.Illust == nil { + return nil, errors.New("pixiv 返回数据为空或结构不匹配") + } + return convertToIllustCache(rawData.Illust) +} + +// FetchPixivByUser ... +func (p *PixivAPI) FetchPixivByUser(uid int64, limit int, pids []int64) ([]model.IllustCache, error) { + url := fmt.Sprintf("https://app-api.pixiv.net/v1/user/illusts?user_id=%d&type=illust", uid) + + excludeCache := make(map[int64]struct{}) + + for _, pid := range pids { + excludeCache[pid] = struct{}{} + } + return p.fetchPixivCommon(url, limit, nil, excludeCache) +} + +// FetchPixivRecommend ... +func (p *PixivAPI) FetchPixivRecommend(limit int) ([]model.IllustCache, error) { + firstURL := "https://app-api.pixiv.net/v1/illust/recommended?filter=for_ios" + return p.fetchPixivCommon(firstURL, limit, nil, nil) // 不做R18过滤,不排缓存 +} + +// FetchPixivIllusts ... +func (p *PixivAPI) FetchPixivIllusts(keyword string, isR18Req bool, limit int, cachedIDs []int64) ([]model.IllustCache, error) { + cachedMap := make(map[int64]struct{}, len(cachedIDs)) + if len(cachedIDs) > 0 { + for _, id := range cachedIDs { + cachedMap[id] = struct{}{} + } + } + + firstURL := buildPixivSearchURL(keyword) + return p.fetchPixivCommon(firstURL, limit, &isR18Req, cachedMap, keyword) +} + +// GetIllustsByKeyword ... +func (p *PixivAPI) GetIllustsByKeyword(keyword string, limit int, cachedIllust []model.IllustCache, cached []int64) ([]model.IllustCache, error) { + + r18Req := IsR18(keyword) + keyword = RemoveR18Keywords(keyword) + + // 如果查到了,直接返回 + if len(cachedIllust) == limit { + return cachedIllust, nil + } + + // 设置一个保底的关键词 + if keyword == "" && r18Req { + keyword = "R-18" + } + + // 计算还需要几张图片 + needed := 0 + if len(cachedIllust) < limit { + needed = limit - len(cachedIllust) + } + + log.Printf("从数据库读到%d,还需要下载%d\n", len(cachedIllust), needed) + // 缓存没数据 -> 调用Pixiv API拉取 + pixivResults, err := p.FetchPixivIllusts(keyword, r18Req, needed, cached) + if err != nil && len(cachedIllust) == 0 { + return nil, err + } + + // 如果Pixiv也没查到直接返回空 + if len(pixivResults) == 0 && len(cachedIllust) == 0 { + return nil, errors.New("这个关键词可能没有找到符合条件的图片或出现未知错误") + } + + if len(cachedIllust) > 0 && len(pixivResults) == 0 { + log.Println("http没有找到图片") + return cachedIllust, nil + } + + pixivResults = append(pixivResults, cachedIllust...) + + if len(pixivResults) >= limit { + pixivResults = pixivResults[:limit] + } + + log.Println("预计发送", len(pixivResults), "张图片") + + return pixivResults, nil +} + +func (p *PixivAPI) fetchPixivCommon( + firstURL string, + limit int, + isR18Req *bool, + excludeCache map[int64]struct{}, + keywords ...string, +) ([]model.IllustCache, error) { + + accessToken, err := p.Token.GetAccessToken() + if err != nil { + return nil, err + } + + // 高质量图(≥1000) + high := make([]model.IllustCache, 0, limit) + // 低质量图(<1000) + low := make([]model.IllustCache, 0, limit) + + seen := make(map[int64]struct{}) + url := firstURL + + for url != "" { + rawData, err := p.Client.SearchPixivIllustrations(accessToken, url) + if err != nil { + return nil, err + } + + for i := range rawData.Illusts { + raw := &rawData.Illusts[i] + + // 去重 + if _, ok := seen[raw.ID]; ok { + continue + } + if excludeCache != nil { + if _, ok := excludeCache[raw.ID]; ok { + continue + } + } + seen[raw.ID] = struct{}{} + + tagNames := extractTagNames(raw.Tags) + + if isR18Req != nil && *isR18Req && !hasR18Tag(tagNames) { + continue + } + + // 转换 + ill, err := convertToIllustCache(raw) + if err != nil { + continue + } + if len(keywords) > 0 { + ill.Keyword = keywords[0] + } + + // R18过滤 + if isR18Req != nil && ill.R18 != *isR18Req { + continue + } + + // 判断高质量 + if ill.Bookmarks >= 1000 { + high = append(high, *ill) + // 高质量够了就直接返回 + if len(high) >= limit { + return high[:limit], nil + } + } + // 低质量池还没满 → 接受 + if len(low) <= limit { + low = append(low, *ill) + } + // 低质量够 limit 就不再放入,避免爆炸增长 + } + + url = rawData.NextURL + } + + // 低质量排序(按收藏数倒序) + sort.Slice(low, func(i, j int) bool { + return low[i].Bookmarks > low[j].Bookmarks + }) + + // 用低质量中的高质量去补齐不足的图 + high = append(high, low...) + if len(high) > limit { + high = high[:limit] + } + + return high, nil +} diff --git a/pixiv/token.go b/pixiv/token.go new file mode 100644 index 0000000..31bc69a --- /dev/null +++ b/pixiv/token.go @@ -0,0 +1,87 @@ +// Package pixiv (copied from plugin/pixiv/api/token.go) +package pixiv + +import ( + "bytes" + "encoding/json" + "errors" + "io" + "net/http" + "net/url" + "sync" + "time" + + log "github.com/sirupsen/logrus" +) + +// TokenStore ... +type TokenStore struct { + client *Client + AccessToken string `json:"access_token"` + RefreshToken string `json:"refresh_token"` + ExpiresIn int64 `json:"expires_in"` + TokenType string `json:"token_type"` + ExpiresAt time.Time `json:"-"` + mu sync.Mutex +} + +// NewTokenStore ... +func NewTokenStore(refreshToken string, c *Client) *TokenStore { + return &TokenStore{ + RefreshToken: refreshToken, + client: c, + } +} + +// GetAccessToken ... +func (t *TokenStore) GetAccessToken() (string, error) { + t.mu.Lock() + defer t.mu.Unlock() + + if time.Now().Before(t.ExpiresAt) && t.AccessToken != "" { + log.Println("access_token is valid") + return t.AccessToken, nil + } + + if err := t.refreshPixivAccessToken(); err != nil { + return "", err + } + + t.ExpiresAt = time.Now().Add(time.Duration(t.ExpiresIn/2) * time.Second) + return t.AccessToken, nil +} + +// refreshPixivAccessToken 用 refresh_token 刷新 access_token +func (t *TokenStore) refreshPixivAccessToken() error { + endpoint := "https://oauth.secure.pixiv.net/auth/token" + + data := url.Values{} + data.Set("grant_type", "refresh_token") + data.Set("client_id", "MOBrBDS8blbauoSck0ZfDbtuzpyT") + data.Set("client_secret", "lsACyCD94FhDUtGTXi3QzcFE2uU1hqtDaKeqrdwj") + data.Set("refresh_token", t.RefreshToken) + + req, _ := http.NewRequest("POST", endpoint, bytes.NewBufferString(data.Encode())) + req.Header.Set("Content-Type", "application/x-www-form-urlencoded") + req.Header.Set("User-Agent", "PixivAndroidApp/5.0.234 (Android 11; Pixel 5)") + + resp, err := t.client.Do(req) + if err != nil { + return err + } + + defer resp.Body.Close() + + body, _ := io.ReadAll(resp.Body) + if resp.StatusCode != 200 { + return errors.New("刷新失败: " + resp.Status + "\nbody: " + string(body)) + } + + var tokenRes TokenStore + err = json.Unmarshal(body, &tokenRes) + + t.AccessToken = tokenRes.AccessToken + t.ExpiresIn = tokenRes.ExpiresIn + + return err +} diff --git a/pixiv/utils.go b/pixiv/utils.go new file mode 100644 index 0000000..6b8b7f3 --- /dev/null +++ b/pixiv/utils.go @@ -0,0 +1,161 @@ +// Package pixiv (copied from plugin/pixiv/api/utils.go) +package pixiv + +import ( + "encoding/json" + "fmt" + "net/url" + "strings" + + "github.com/FloatTech/AnimeAPI/pixiv/model" +) + +// RemoveR18Keywords ... +func RemoveR18Keywords(keyword string) string { + if keyword == "" { + return keyword + } + + words := strings.Fields(keyword) // 按空格分割成单词 + var result []string + + for _, word := range words { + lowerWord := strings.ToLower(word) + // 只删除完全匹配的R-18 关键词 + if lowerWord != "r-18" && lowerWord != "r18" && lowerWord != "r_18" { + result = append(result, word) + } + } + + return strings.Join(result, " ") +} + +func buildPixivSearchURL(keyword string) string { + + baseURL := &url.URL{ + Scheme: "https", + Host: "app-api.pixiv.net", + Path: "/v1/search/illust", + } + + params := url.Values{} + params.Set("word", keyword) + // 严格匹配 exact_match_for_tags + // 标题简介有相同的 title_and_caption + // 宽松匹配 partial_match_for_tags + // 暂时使用宽松匹配 + params.Set("search_target", "partial_match_for_tags") + params.Set("sort", "popular_desc") + //params.Set("offset", fmt.Sprintf("%d", offset)) + params.Set("order", "date_desc") + params.Set("filter", "for_android") + // params.Set("filter", "for_ios") + // params.Set("bookmark_num_min", "1000") + + baseURL.RawQuery = params.Encode() + return baseURL.String() +} + +func hasR18Tag(tags []string) bool { + for _, tag := range tags { + if IsR18(tag) { + return true + } + } + return false +} + +func extractTagNames(tags []model.TagsEntity) []string { + tagNames := make([]string, 0, len(tags)) + for _, tag := range tags { + tagNames = append(tagNames, tag.Name) + } + return tagNames +} + +// IsR18 ... +func IsR18(s string) bool { + if s == "" { + return false + } + lower := strings.ToLower(s) + r18Keywords := []string{"r-18", "r18", "r_18"} + for _, keyword := range r18Keywords { + if strings.Contains(lower, keyword) { + return true + } + } + return false +} + +// ModifyPageGeneric ... +func ModifyPageGeneric(originalURL string, pageNum int) string { + u, err := url.Parse(originalURL) + if err != nil { + return originalURL + } + + // 获取路径的最后一部分(文件名) + pathParts := strings.Split(u.Path, "/") + if len(pathParts) == 0 { + return originalURL + } + + fileName := pathParts[len(pathParts)-1] + parts := strings.Split(fileName, "_") + if len(parts) < 2 { + return originalURL + } + + // 分离页码和扩展名 + pageAndExt := strings.Split(parts[1], ".") + if len(pageAndExt) < 2 { + return originalURL + } + + // 修改页码部分,保留扩展名 + parts[1] = fmt.Sprintf("p%d.%s", pageNum, pageAndExt[1]) + + // 更新文件名 + pathParts[len(pathParts)-1] = strings.Join(parts, "_") + u.Path = strings.Join(pathParts, "/") + + return u.String() +} + +func convertToIllustCache(raw *model.IllustsEntity) (*model.IllustCache, error) { + tagNames := extractTagNames(raw.Tags) + + jsonTags, err := json.Marshal(tagNames) + if err != nil { + return nil, err + } + + if len(tagNames) == 0 { + tagNames = []string{""} + } + + illust := &model.IllustCache{ + PID: raw.ID, + UID: raw.User.ID, + Keyword: tagNames[0], // 默认为第1个标签后续在其他函数里自定义 + Title: raw.Title, + AuthorName: raw.User.Name, + ImageURL: raw.ImageURLs.Large, + R18: hasR18Tag(tagNames), + Bookmarks: raw.TotalBookmarks, + TotalView: raw.TotalView, + CreateDate: raw.CreateDate, + PageCount: raw.PageCount, + Tags: jsonTags, + } + + originalImageURL := raw.MetaSinglePage.OriginalImageURL + if originalImageURL == "" && len(raw.MetaPages) > 0 { + originalImageURL = raw.MetaPages[0].ImageURLs.Original + } + + illust.OriginalURL = originalImageURL + + return illust, nil +} From fc2ea7e555491c01ad5531d85048573d4a2807db Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=B0=8F=E5=AE=87=E5=AE=87?= <3061196825@qq.com> Date: Mon, 29 Jun 2026 16:00:22 +0800 Subject: [PATCH 2/4] =?UTF-8?q?fix:=E6=9B=B4=E6=96=B0gomod?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- go.mod | 6 ++++++ go.sum | 40 ++++++++++++++++++++++++++++++++++++---- 2 files changed, 42 insertions(+), 4 deletions(-) diff --git a/go.mod b/go.mod index 359a046..f402478 100644 --- a/go.mod +++ b/go.mod @@ -19,9 +19,11 @@ require ( github.com/tidwall/gjson v1.18.0 github.com/wdvxdr1123/ZeroBot v1.8.2-0.20251002074418-56567b7fc282 golang.org/x/image v0.21.0 + gorm.io/datatypes v1.2.7 ) require ( + filippo.io/edwards25519 v1.1.0 // indirect github.com/FloatTech/ttl v0.0.0-20250224045156-012b1463287d // indirect github.com/antchfx/xpath v1.3.3 // indirect github.com/davecgh/go-spew v1.1.1 // indirect @@ -30,8 +32,10 @@ require ( github.com/fumiama/go-registry v0.2.7 // indirect github.com/fumiama/go-simple-protobuf v0.2.0 // indirect github.com/fumiama/gofastTEA v0.1.3 // indirect + github.com/go-sql-driver/mysql v1.8.1 // indirect github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect github.com/jinzhu/inflection v1.0.0 // indirect + github.com/jinzhu/now v1.1.5 // indirect github.com/mattn/go-isatty v0.0.20 // indirect github.com/ncruces/go-strftime v0.1.9 // indirect github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646 // indirect @@ -44,6 +48,8 @@ require ( golang.org/x/sys v0.30.0 // indirect golang.org/x/text v0.29.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect + gorm.io/driver/mysql v1.5.6 // indirect + gorm.io/gorm v1.30.0 // indirect modernc.org/libc v1.61.0 // indirect modernc.org/mathutil v1.6.0 // indirect modernc.org/memory v1.8.0 // indirect diff --git a/go.sum b/go.sum index 1ec345d..0538ebf 100644 --- a/go.sum +++ b/go.sum @@ -1,3 +1,5 @@ +filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA= +filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4= github.com/FloatTech/floatbox v0.0.0-20260408141530-dc0fdf584f62 h1:w9KO9/zSwnh7+68HOmvIC9gt7Kgy6EPYrMnPh20HeBA= github.com/FloatTech/floatbox v0.0.0-20260408141530-dc0fdf584f62/go.mod h1:Cpt6REv4OE5VrO5uA/hdVEofnfyUB2BVJEwYACubLOc= github.com/FloatTech/sqlite v1.7.2 h1:b8COegNLSzofzOyARsVwSbz9OOzWEa8IElsTlx1TBLw= @@ -39,27 +41,44 @@ github.com/fumiama/sqlite3 v1.29.10-simp h1:c5y3uKyU0q9t0/SyfynzYyuslQ5zP+5CD8e0 github.com/fumiama/sqlite3 v1.29.10-simp/go.mod h1:ItX2a1OVGgNsFh6Dv60JQvGfJfTPHPVpV6DF59akYOA= github.com/fumiama/terasu v0.0.0-20250930151601-1d9b679c36c2 h1:NAmsblfyAfQIZLPxkJil/kh6EV7Vrs/c7LGOavnUONM= github.com/fumiama/terasu v0.0.0-20250930151601-1d9b679c36c2/go.mod h1:UVx8YP1jKKL1Cj+uy+OnQRM2Ih6U36Mqy9GSf7jabsI= -github.com/go-sql-driver/mysql v1.5.0 h1:ozyZYNQW3x3HtqT1jira07DN2PArx2v7/mN66gGcHOs= github.com/go-sql-driver/mysql v1.5.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg= -github.com/golang-sql/civil v0.0.0-20190719163853-cb61b32ac6fe h1:lXe2qZdvpiX5WZkZR4hgp4KJVfY3nMkvmwbVkpv1rVY= +github.com/go-sql-driver/mysql v1.7.0/go.mod h1:OXbVy3sEdcQ2Doequ6Z5BW6fXNQTmx+9S1MCJN5yJMI= +github.com/go-sql-driver/mysql v1.8.1 h1:LedoTUt/eveggdHS9qUFC1EFSa8bU2+1pZjSRpvNJ1Y= +github.com/go-sql-driver/mysql v1.8.1/go.mod h1:wEBSXgmK//2ZFJyE+qWnIsVGmvmEKlqwuVSjsCm7DZg= github.com/golang-sql/civil v0.0.0-20190719163853-cb61b32ac6fe/go.mod h1:8vg3r2VgvsThLBIFL93Qb5yWzgyZWhEmBwUJWevAkK0= +github.com/golang-sql/civil v0.0.0-20220223132316-b832511892a9 h1:au07oEsX2xN0ktxqI+Sida1w446QrXBRJ0nee3SNZlA= +github.com/golang-sql/civil v0.0.0-20220223132316-b832511892a9/go.mod h1:8vg3r2VgvsThLBIFL93Qb5yWzgyZWhEmBwUJWevAkK0= +github.com/golang-sql/sqlexp v0.1.0 h1:ZCD6MBpcuOVfGVqsEmY5/4FtYiKz6tSyUv9LPEDei6A= +github.com/golang-sql/sqlexp v0.1.0/go.mod h1:J4ad9Vo8ZCWQ2GMrC4UCQy1JpCbwU9m3EOqtpKwwwHI= github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE= github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= 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/jackc/pgpassfile v1.0.0 h1:/6Hmqy13Ss2zCq62VdNG8tM1wchn8zjSGOBJ6icpsIM= +github.com/jackc/pgpassfile v1.0.0/go.mod h1:CEx0iS5ambNFdcRtxPj5JhEz+xB6uRky5eyVu/W2HEg= +github.com/jackc/pgservicefile v0.0.0-20231201235250-de7065d80cb9 h1:L0QtFUgDarD7Fpv9jeVMgy/+Ec0mtnmYuImjTz6dtDA= +github.com/jackc/pgservicefile v0.0.0-20231201235250-de7065d80cb9/go.mod h1:5TJZWKEWniPve33vlWYSoGYefn3gLQRzjfDlhSJ9ZKM= +github.com/jackc/pgx/v5 v5.5.5 h1:amBjrZVmksIdNjxGW/IiIMzxMKZFelXbUoPNb+8sjQw= +github.com/jackc/pgx/v5 v5.5.5/go.mod h1:ez9gk+OAat140fv9ErkZDYFWmXLfV+++K0uAOiwgm1A= +github.com/jackc/puddle/v2 v2.2.1 h1:RhxXJtFG022u4ibrCSMSiu5aOq1i77R3OHKNJj77OAk= +github.com/jackc/puddle/v2 v2.2.1/go.mod h1:vriiEXHvEE654aYKXXjOvZM39qJ0q+azkZFrfEOc3H4= github.com/jinzhu/gorm v1.9.16 h1:+IyIjPEABKRpsu/F8OvDPy9fyQlgsg2luMV2ZIH5i5o= github.com/jinzhu/gorm v1.9.16/go.mod h1:G3LB3wezTOWM2ITLzPxEXgSkOXAntiLHS7UdBefADcs= github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD/E= github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc= -github.com/jinzhu/now v1.0.1 h1:HjfetcXq097iXP0uoPCdnM4Efp5/9MsM0/M+XOTeR3M= github.com/jinzhu/now v1.0.1/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8= +github.com/jinzhu/now v1.1.5 h1:/o9tlHleP7gOFmsnYNz3RGnqzefHA47wQpKrrdTIwXQ= +github.com/jinzhu/now v1.1.5/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8= github.com/lib/pq v1.1.1 h1:sJZmqHoEaY7f+NPP8pgLB/WxulyR3fewgCM2qaSlBb4= github.com/lib/pq v1.1.1/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= 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-sqlite3 v1.14.0 h1:mLyGNKR8+Vv9CAU7PphKa2hkEqxxhn8i32J6FPj1/QA= github.com/mattn/go-sqlite3 v1.14.0/go.mod h1:JIl7NbARA7phWnGvh0LKTyg7S9BA+6gx71ShQilpsus= +github.com/mattn/go-sqlite3 v1.14.15 h1:vfoHhTN1af61xCRSWzFIWzx2YskyMTwHLrExkBOjvxI= +github.com/mattn/go-sqlite3 v1.14.15/go.mod h1:2eHXhiwb8IkHr+BDWZGa96P6+rkvnG63S2DGjv9HUNg= +github.com/microsoft/go-mssqldb v1.7.2 h1:CHkFJiObW7ItKTJfHo1QX7QBBD1iV+mn1eOyRP3b/PA= +github.com/microsoft/go-mssqldb v1.7.2/go.mod h1:kOvZKUdrhhFQmxLZqbwUV0rHkNkZpthMITIb2Ko1IoA= 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/nfnt/resize v0.0.0-20180221191011-83c6a9932646 h1:zYyBkD/k9seD2A7fsi6Oo2LfFZAehjjQMERAvZLEDnQ= @@ -182,6 +201,19 @@ gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8 gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/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= +gorm.io/datatypes v1.2.7 h1:ww9GAhF1aGXZY3EB3cJPJ7//JiuQo7DlQA7NNlVaTdk= +gorm.io/datatypes v1.2.7/go.mod h1:M2iO+6S3hhi4nAyYe444Pcb0dcIiOMJ7QHaUXxyiNZY= +gorm.io/driver/mysql v1.5.6 h1:Ld4mkIickM+EliaQZQx3uOJDJHtrd70MxAUqWqlx3Y8= +gorm.io/driver/mysql v1.5.6/go.mod h1:sEtPWMiqiN1N1cMXoXmBbd8C6/l+TESwriotuRRpkDM= +gorm.io/driver/postgres v1.5.0 h1:u2FXTy14l45qc3UeCJ7QaAXZmZfDDv0YrthvmRq1l0U= +gorm.io/driver/postgres v1.5.0/go.mod h1:FUZXzO+5Uqg5zzwzv4KK49R8lvGIyscBOqYrtI1Ce9A= +gorm.io/driver/sqlite v1.4.3 h1:HBBcZSDnWi5BW3B3rwvVTc510KGkBkexlOg0QrmLUuU= +gorm.io/driver/sqlite v1.4.3/go.mod h1:0Aq3iPO+v9ZKbcdiz8gLWRw5VOPcBOPUQJFLq5e2ecI= +gorm.io/driver/sqlserver v1.6.0 h1:VZOBQVsVhkHU/NzNhRJKoANt5pZGQAS1Bwc6m6dgfnc= +gorm.io/driver/sqlserver v1.6.0/go.mod h1:WQzt4IJo/WHKnckU9jXBLMJIVNMVeTu25dnOzehntWw= +gorm.io/gorm v1.25.7/go.mod h1:hbnx/Oo0ChWMn1BIhpy1oYozzpM15i4YPuHDmfYtwg8= +gorm.io/gorm v1.30.0 h1:qbT5aPv1UH8gI99OsRlvDToLxW5zR7FzS9acZDOZcgs= +gorm.io/gorm v1.30.0/go.mod h1:8Z33v652h4//uMA76KjeDH8mJXPm1QNCYrMeatR0DOE= modernc.org/cc/v4 v4.21.2 h1:dycHFB/jDc3IyacKipCNSDrjIC0Lm1hyoWOZTRR20Lk= modernc.org/cc/v4 v4.21.2/go.mod h1:HM7VJTZbUCR3rV8EYBi9wxnJ0ZBRiGE5OeGXNA0IsLQ= modernc.org/ccgo/v4 v4.17.8 h1:yyWBf2ipA0Y9GGz/MmCmi3EFpKgeS7ICrAFes+suEbs= From ccf7504d47a8196465f5cc6c3bf9f62359cded4b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=B0=8F=E5=AE=87=E5=AE=87?= <3061196825@qq.com> Date: Mon, 29 Jun 2026 16:05:43 +0800 Subject: [PATCH 3/4] =?UTF-8?q?=E4=BF=AElint?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- go.mod | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/go.mod b/go.mod index f402478..6d848a7 100644 --- a/go.mod +++ b/go.mod @@ -1,6 +1,6 @@ module github.com/FloatTech/AnimeAPI -go 1.24.0 +go 1.25 require ( github.com/FloatTech/floatbox v0.0.0-20260408141530-dc0fdf584f62 From c8f217908faafb1c4113d99571e8e4c4d49deecf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=AE=87=7E?= <158024940+xyy0411@users.noreply.github.com> Date: Mon, 29 Jun 2026 16:16:39 +0800 Subject: [PATCH 4/4] =?UTF-8?q?=E4=BF=AElint?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- go.mod | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/go.mod b/go.mod index 6d848a7..a055bff 100644 --- a/go.mod +++ b/go.mod @@ -1,6 +1,6 @@ module github.com/FloatTech/AnimeAPI -go 1.25 +go 1.24 require ( github.com/FloatTech/floatbox v0.0.0-20260408141530-dc0fdf584f62