first commit
This commit is contained in:
commit
91c3337f46
11
README.md
Normal file
11
README.md
Normal file
@ -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}}
|
||||||
|
```
|
6
configs/config.go
Normal file
6
configs/config.go
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
package configs
|
||||||
|
|
||||||
|
const (
|
||||||
|
DingTalkURL = ""
|
||||||
|
BVID = "BV12x411y7SN"
|
||||||
|
)
|
5
go.mod
Normal file
5
go.mod
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
module git.mmeiblog.cn/mei/v-alarm
|
||||||
|
|
||||||
|
go 1.23.4
|
||||||
|
|
||||||
|
require github.com/robfig/cron v1.2.0
|
2
go.sum
Normal file
2
go.sum
Normal file
@ -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=
|
24
internal/alerm.go
Normal file
24
internal/alerm.go
Normal file
@ -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)
|
||||||
|
}
|
||||||
|
}
|
36
internal/dingTalk.go
Normal file
36
internal/dingTalk.go
Normal file
@ -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
|
||||||
|
}
|
90
internal/monitor.go
Normal file
90
internal/monitor.go
Normal file
@ -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
|
||||||
|
}
|
26
main.go
Normal file
26
main.go
Normal file
@ -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
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user