commit 91c3337f46aff4a5674ae7cbcde0ed078f68bfb5 Author: mei Date: Thu Aug 28 17:41:46 2025 +0800 first commit diff --git a/README.md b/README.md new file mode 100644 index 0000000..dd8f9bc --- /dev/null +++ b/README.md @@ -0,0 +1,11 @@ +# 中V监测器 + +监测中V歌曲并通知到钉钉,写的比较粗糙,十分钟干完(距离凉雨传说还有几百播放的时候,最后成功检测到凉雨传说),搭配 NineVocalRank 使用 + +```shell +(base) mei@mei-SuperPC:~/work/v-alerm$ ./v-alarm +2025/08/28 14:58:34 &{{1000010 23104 35676 46579 9343 5842 3753} {396194 COPY 【洛天依原创】凉雨【PV付/COSMOSⅡ】 http://i1.hdslb.com/bfs/archive/dce146224f830f84618e1e3caffa42800ae611de.jpg 1 1756364314} {8786522 BV12x411y7SN 30} {6730 330 287 244 394 128 78} {9939.34 传说曲 7 10.0001}} +2025/08/28 14:58:39 &{{1000010 23104 35676 46579 9345 5842 3753} {396194 COPY 【洛天依原创】凉雨【PV付/COSMOSⅡ】 http://i1.hdslb.com/bfs/archive/dce146224f830f84618e1e3caffa42800ae611de.jpg 1 1756364319} {8786522 BV12x411y7SN 30} {6730 330 287 244 396 128 78} {9944.74 传说曲 7 10.0001}} +2025/08/28 14:58:44 &{{1000010 23104 35676 46579 9343 5842 3753} {396194 COPY 【洛天依原创】凉雨【PV付/COSMOSⅡ】 http://i1.hdslb.com/bfs/archive/dce146224f830f84618e1e3caffa42800ae611de.jpg 1 1756364324} {8786522 BV12x411y7SN 30} {6730 330 287 244 394 128 78} {9939.34 传说曲 7 10.0001}} +2025/08/28 14:58:49 &{{1000010 23104 35676 46579 9344 5842 3753} {396194 COPY 【洛天依原创】凉雨【PV付/COSMOSⅡ】 http://i1.hdslb.com/bfs/archive/dce146224f830f84618e1e3caffa42800ae611de.jpg 1 1756364329} {8786522 BV12x411y7SN 30} {6730 330 287 244 395 128 78} {9942.04 传说曲 7 10.0001}} +``` diff --git a/configs/config.go b/configs/config.go new file mode 100644 index 0000000..52b645a --- /dev/null +++ b/configs/config.go @@ -0,0 +1,6 @@ +package configs + +const ( + DingTalkURL = "" + BVID = "BV12x411y7SN" +) diff --git a/go.mod b/go.mod new file mode 100644 index 0000000..c54990a --- /dev/null +++ b/go.mod @@ -0,0 +1,5 @@ +module git.mmeiblog.cn/mei/v-alarm + +go 1.23.4 + +require github.com/robfig/cron v1.2.0 diff --git a/go.sum b/go.sum new file mode 100644 index 0000000..b5b4795 --- /dev/null +++ b/go.sum @@ -0,0 +1,2 @@ +github.com/robfig/cron v1.2.0 h1:ZjScXvvxeQ63Dbyxy76Fj3AT3Ut0aKsyd2/tl3DTMuQ= +github.com/robfig/cron v1.2.0/go.mod h1:JGuDeoQd7Z6yL4zQhZ3OPEVHB7fL6Ka6skscFHfmt2k= diff --git a/internal/alerm.go b/internal/alerm.go new file mode 100644 index 0000000..a6102fc --- /dev/null +++ b/internal/alerm.go @@ -0,0 +1,24 @@ +package internal + +import ( + "fmt" + "log" + "time" + + "git.mmeiblog.cn/mei/v-alarm/configs" +) + +func Alerm() { + SongData, err := Monitor(configs.BVID) + if err != nil { + log.Fatalln(err) + } + if SongData.Video_stat.View >= 1000000 { + timestamp := time.Unix(SongData.Video_info.Timestamp, 0) + message := fmt.Sprintf("歌曲%s已达成传说,信息输出在日志,达成时间:%s", + SongData.Video_info.Title, + timestamp.Format("2006-01-02 15:04:05")) + SendDingTalkNotification(message) + log.Println(SongData) + } +} diff --git a/internal/dingTalk.go b/internal/dingTalk.go new file mode 100644 index 0000000..3c9bc94 --- /dev/null +++ b/internal/dingTalk.go @@ -0,0 +1,36 @@ +package internal + +import ( + "encoding/json" + "fmt" + "net/http" + "strings" + + "git.mmeiblog.cn/mei/v-alarm/configs" +) + +func SendDingTalkNotification(message string) error { + msg := map[string]any{ + "msgtype": "text", + "text": map[string]string{"content": message}, + } + jsonBytes, err := json.Marshal(msg) + if err != nil { + return err + } + req, err := http.NewRequest("POST", configs.DingTalkURL, strings.NewReader(string(jsonBytes))) + if err != nil { + return err + } + req.Header.Set("Content-Type", "application/json") + client := &http.Client{} + resp, err := client.Do(req) + if err != nil { + return err + } + defer resp.Body.Close() + if resp.StatusCode != http.StatusOK { + return fmt.Errorf("钉钉API请求失败,状态码: %d", resp.StatusCode) + } + return nil +} diff --git a/internal/monitor.go b/internal/monitor.go new file mode 100644 index 0000000..6ebd309 --- /dev/null +++ b/internal/monitor.go @@ -0,0 +1,90 @@ +package internal + +import ( + "encoding/json" + "fmt" + "io" + "log" + "net/http" +) + +type SongMessage struct { + Video_stat VideoStat `json:"video_stat"` + Video_info VideoInfo `json:"video_info"` + Video_id VideoID `json:"video_id"` + Video_increase VideoIncrease `json:"video_increase"` + Vrank_info VrankInfo `json:"vrank_info"` +} + +type VideoStat struct { + View int `json:"view"` + Like int `json:"like"` + Coin int `json:"coin"` + Favorite int `json:"favorite"` + Reply int `json:"reply"` + Share int `json:"share"` + Danmaku int `json:"danmaku"` +} + +type VideoInfo struct { + Uploader_mid string `json:"uploader_mid"` + Uploader_name string `json:"uploader_name"` + Title string `json:"title"` + Pic string `json:"pic"` + Pages int `json:"pages"` + Timestamp int64 `json:"timestamp"` +} + +type VideoID struct { + Avid string `json:"avid"` + Bvid string `json:"bvid"` + Tid int `json:"tid"` +} + +type VideoIncrease struct { + View int `json:"view"` + Like int `json:"like"` + Coin int `json:"coin"` + Favorite int `json:"favorite"` + Reply int `json:"reply"` + Share int `json:"share"` + Danmaku int `json:"danmaku"` +} + +type VrankInfo struct { + Vrank_score float64 `json:"vrank_score"` + Rank string `json:"rank"` + Rank_code int `json:"rank_code"` + Progress_percentage float64 `json:"progress_percentage"` +} + +func Monitor(bvid string) (SongData *SongMessage, error error) { + + url := fmt.Sprintf("https://api.mmeiblog.cn/NineVocalRank/vocaloid_rank/v1/video/%s", bvid) + method := "GET" + client := &http.Client{} + req, err := http.NewRequest(method, url, nil) + if err != nil { + log.Fatalln(err) + return + } + res, err := client.Do(req) + if err != nil { + log.Fatalln(err) + return + } + defer res.Body.Close() + body, err := io.ReadAll(res.Body) + if err != nil { + log.Fatalln(err) + return + } + + var Data SongMessage + err = json.Unmarshal(body, &Data) + if err != nil { + log.Printf("解析JSON失败: %v\n", err) + return nil, err + } + return &Data, nil +} diff --git a/main.go b/main.go new file mode 100644 index 0000000..e28d306 --- /dev/null +++ b/main.go @@ -0,0 +1,26 @@ +package main + +import ( + "fmt" + "os" + "os/signal" + "syscall" + + "git.mmeiblog.cn/mei/v-alarm/internal" + "github.com/robfig/cron" +) + +// 写的比较粗糙,十分钟干完(距离凉雨传说还有几百播放的时候,最后成功检测到凉雨传说) +func main() { + c := cron.New() + + c.AddFunc("@every 5s", internal.Alerm) + + c.Start() + + sig := make(chan os.Signal, 1) + signal.Notify(sig, os.Interrupt, syscall.SIGTERM) + <-sig // 阻塞直到收到信号 + fmt.Printf("Hava a good Day!") + c.Stop() // 关闭 cron +}