This commit is contained in:
parent
788def6dc4
commit
8884d945aa
19
cron/cron.go
19
cron/cron.go
@ -1 +1,20 @@
|
||||
package cron
|
||||
|
||||
import (
|
||||
"gitee.ltd/lxh/logger/log"
|
||||
"github.com/go-co-op/gocron/v2"
|
||||
"time"
|
||||
"wireguard-ui/cron/task"
|
||||
)
|
||||
|
||||
func Task() {
|
||||
sch, err := gocron.NewScheduler(gocron.WithLocation(time.Local))
|
||||
if err != nil {
|
||||
log.Errorf("初始化定时任务失败")
|
||||
return
|
||||
}
|
||||
|
||||
_, _ = sch.NewJob(gocron.DurationJob(3*time.Minute), gocron.NewTask(task.NetworkClient().ClientOfflineNotify())) // 每三分钟检测离线的客户端并且发送消息
|
||||
|
||||
sch.Start()
|
||||
}
|
||||
|
95
cron/task/client.go
Normal file
95
cron/task/client.go
Normal file
@ -0,0 +1,95 @@
|
||||
package task
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"gitee.ltd/lxh/logger/log"
|
||||
jsoniter "github.com/json-iterator/go"
|
||||
"golang.org/x/exp/slices"
|
||||
"strings"
|
||||
"time"
|
||||
"wireguard-ui/component"
|
||||
"wireguard-ui/global/client"
|
||||
"wireguard-ui/model"
|
||||
"wireguard-ui/service"
|
||||
"wireguard-ui/utils"
|
||||
)
|
||||
|
||||
type NetworkClientImpl interface {
|
||||
ClientOfflineNotify() error // 客户端离线通知
|
||||
}
|
||||
|
||||
type networkClient struct{}
|
||||
|
||||
func NetworkClient() NetworkClientImpl {
|
||||
return networkClient{}
|
||||
}
|
||||
|
||||
// ClientOfflineNotify
|
||||
// @description: 客户端离线通知
|
||||
// @receiver c
|
||||
// @return error
|
||||
func (c networkClient) ClientOfflineNotify() error {
|
||||
// 查询出所有配置了离线通知的客户端
|
||||
var clients []model.Client
|
||||
if err := client.DB.Where("offline_monitoring = ?", 1).Find(&clients).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if len(clients) <= 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
// 开始扫描已经链接过的客户端
|
||||
connectedPeers, err := component.Wireguard().GetClients()
|
||||
if err != nil {
|
||||
log.Errorf("获取已连接客户端失败: %v", err.Error())
|
||||
return err
|
||||
}
|
||||
|
||||
// 查询一下通知配置
|
||||
code, err := service.Setting().GetByCode("WECHAT_NOTIFY")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for _, peer := range connectedPeers {
|
||||
var clientName string
|
||||
if !slices.ContainsFunc(clients, func(cli model.Client) bool {
|
||||
isExist := peer.PublicKey.String() == jsoniter.Get([]byte(cli.Keys), "PublicKey").ToString()
|
||||
if isExist {
|
||||
clientName = cli.Name
|
||||
}
|
||||
return isExist
|
||||
}) {
|
||||
continue
|
||||
}
|
||||
|
||||
// 如果存在,判断离线时间
|
||||
if time.Since(peer.LastHandshakeTime) < 3 {
|
||||
var ipAllocation string
|
||||
for _, iaip := range peer.AllowedIPs {
|
||||
ipAllocation += iaip.String() + ","
|
||||
}
|
||||
// 去除一下最右边的逗号
|
||||
if len(ipAllocation) > 0 {
|
||||
ipAllocation = strings.TrimRight(ipAllocation, ",")
|
||||
}
|
||||
|
||||
// 已经离线,发送通知
|
||||
msg := fmt.Sprintf(`
|
||||
[离线通知]
|
||||
客户端名称 : %v
|
||||
客户端IP : %v
|
||||
最后在线时间 : %v
|
||||
`, clientName, ipAllocation, peer.LastHandshakeTime.Format("2006-01-02 15:04:05"))
|
||||
err := utils.WechatNotify(code).SendTextMessage(msg)
|
||||
if err != nil {
|
||||
log.Errorf("微信消息[%v]通知失败: %v", msg, err.Error())
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
5
go.mod
5
go.mod
@ -44,6 +44,7 @@ require (
|
||||
github.com/gabriel-vasile/mimetype v1.4.3 // indirect
|
||||
github.com/gin-contrib/sse v0.1.0 // indirect
|
||||
github.com/glebarez/go-sqlite v1.21.2 // indirect
|
||||
github.com/go-co-op/gocron/v2 v2.12.4 // indirect
|
||||
github.com/go-kit/kit v0.12.0 // indirect
|
||||
github.com/go-kit/log v0.2.1 // indirect
|
||||
github.com/go-logfmt/logfmt v0.5.1 // indirect
|
||||
@ -61,6 +62,7 @@ require (
|
||||
github.com/jackc/puddle/v2 v2.2.1 // indirect
|
||||
github.com/jinzhu/inflection v1.0.0 // indirect
|
||||
github.com/jinzhu/now v1.1.5 // indirect
|
||||
github.com/jonboulle/clockwork v0.4.0 // indirect
|
||||
github.com/josharian/native v1.1.0 // indirect
|
||||
github.com/jpillora/backoff v1.0.0 // indirect
|
||||
github.com/klauspost/cpuid/v2 v2.2.7 // indirect
|
||||
@ -85,6 +87,7 @@ require (
|
||||
github.com/prometheus/procfs v0.8.0 // indirect
|
||||
github.com/prometheus/prometheus v1.8.2-0.20201028100903-3245b3267b24 // indirect
|
||||
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect
|
||||
github.com/robfig/cron/v3 v3.0.1 // indirect
|
||||
github.com/sagikazarmark/locafero v0.4.0 // indirect
|
||||
github.com/sagikazarmark/slog-shim v0.1.0 // indirect
|
||||
github.com/sourcegraph/conc v0.3.0 // indirect
|
||||
@ -97,7 +100,7 @@ require (
|
||||
go.uber.org/multierr v1.9.0 // indirect
|
||||
go.uber.org/zap v1.23.0 // indirect
|
||||
golang.org/x/arch v0.8.0 // indirect
|
||||
golang.org/x/exp v0.0.0-20230905200255-921286631fa9 // indirect
|
||||
golang.org/x/exp v0.0.0-20240613232115-7f521ea00fb8 // indirect
|
||||
golang.org/x/image v0.18.0 // indirect
|
||||
golang.org/x/net v0.25.0 // indirect
|
||||
golang.org/x/oauth2 v0.18.0 // indirect
|
||||
|
8
go.sum
8
go.sum
@ -224,6 +224,8 @@ github.com/globalsign/mgo v0.0.0-20180905125535-1ca0a4f7cbcb/go.mod h1:xkRDCp4j0
|
||||
github.com/globalsign/mgo v0.0.0-20181015135952-eeefdecb41b8/go.mod h1:xkRDCp4j0OGD1HRkm4kmhM+pmpv3AKq5SU7GMg4oO/Q=
|
||||
github.com/glycerine/go-unsnap-stream v0.0.0-20180323001048-9f0cb55181dd/go.mod h1:/20jfyN9Y5QPEAprSgKAUr+glWDY39ZiUEAYOEv5dsE=
|
||||
github.com/glycerine/goconvey v0.0.0-20190410193231-58a59202ab31/go.mod h1:Ogl1Tioa0aV7gstGFO7KhffUsb9M4ydbEbbxpcEDc24=
|
||||
github.com/go-co-op/gocron/v2 v2.12.4 h1:h1HWApo3T+61UrZqEY2qG1LUpDnB7tkYITxf6YIK354=
|
||||
github.com/go-co-op/gocron/v2 v2.12.4/go.mod h1:xY7bJxGazKam1cz04EebrlP4S9q4iWdiAylMGP3jY9w=
|
||||
github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU=
|
||||
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
|
||||
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
|
||||
@ -508,6 +510,8 @@ github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHW
|
||||
github.com/jmespath/go-jmespath/internal/testify v1.5.1/go.mod h1:L3OGu8Wl2/fWfCI6z80xFu9LTZmf1ZRjMHUOPmWr69U=
|
||||
github.com/joho/godotenv v1.3.0/go.mod h1:7hK45KPybAkOC6peb+G5yklZfMxEjkZhHbwpqxOKXbg=
|
||||
github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo=
|
||||
github.com/jonboulle/clockwork v0.4.0 h1:p4Cf1aMWXnXAUh8lVfewRBx1zaTSYKrKMF2g3ST4RZ4=
|
||||
github.com/jonboulle/clockwork v0.4.0/go.mod h1:xgRqUGwRcjKCO1vbZUEtSLrqKoPSsUpK7fnezOII0kc=
|
||||
github.com/jordan-wright/email v4.0.1-0.20210109023952-943e75fe5223+incompatible h1:jdpOPRN1zP63Td1hDQbZW73xKmzDvZHzVdNYxhnTMDA=
|
||||
github.com/jordan-wright/email v4.0.1-0.20210109023952-943e75fe5223+incompatible/go.mod h1:1c7szIrayyPPB/987hsnvNzLushdWf4o/79s3P08L8A=
|
||||
github.com/josharian/native v1.1.0 h1:uuaP0hAbW7Y4l0ZRQ6C9zfb7Mg1mbFKry/xzDAfmtLA=
|
||||
@ -751,6 +755,8 @@ github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0/go.mod h1:qq
|
||||
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/retailnext/hllpp v1.0.1-0.20180308014038-101a6d2f8b52/go.mod h1:RDpi1RftBQPUCDRw6SmxeaREsAaRKnOclghuzp/WRzc=
|
||||
github.com/robfig/cron/v3 v3.0.1 h1:WdRxkvbJztn8LMz/QEvLN5sBU+xKpSqwwUO1Pjr4qDs=
|
||||
github.com/robfig/cron/v3 v3.0.1/go.mod h1:eQICP3HwyT7UooqI/z+Ov+PtYAWygg1TEWWzGIFLtro=
|
||||
github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg=
|
||||
github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ=
|
||||
github.com/rogpeppe/go-internal v1.1.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
|
||||
@ -924,6 +930,8 @@ golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EH
|
||||
golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU=
|
||||
golang.org/x/exp v0.0.0-20230905200255-921286631fa9 h1:GoHiUyI/Tp2nVkLI2mCxVkOjsbSXD66ic0XW0js0R9g=
|
||||
golang.org/x/exp v0.0.0-20230905200255-921286631fa9/go.mod h1:S2oDrQGGwySpoQPVqRShND87VCbxmc6bL1Yd2oYrm6k=
|
||||
golang.org/x/exp v0.0.0-20240613232115-7f521ea00fb8 h1:yixxcjnhBmY0nkL253HFVIm0JsFHwrHdT3Yh6szTnfY=
|
||||
golang.org/x/exp v0.0.0-20240613232115-7f521ea00fb8/go.mod h1:jj3sYF3dwk5D+ghuXyeI3r5MFf+NT2An6/9dOA95KSI=
|
||||
golang.org/x/image v0.0.0-20180708004352-c73c2afc3b81/go.mod h1:ux5Hcp/YLpHSI86hEcLt0YII63i6oz57MZXIpbrjZUs=
|
||||
golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
|
||||
golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
|
||||
|
4
main.go
4
main.go
@ -10,6 +10,7 @@ import (
|
||||
"os"
|
||||
"time"
|
||||
"wireguard-ui/config"
|
||||
"wireguard-ui/cron"
|
||||
"wireguard-ui/http/router"
|
||||
"wireguard-ui/initialize"
|
||||
"wireguard-ui/script"
|
||||
@ -20,6 +21,9 @@ func init() {
|
||||
if err := script.New().Do(); err != nil {
|
||||
log.Errorf("执行脚本失败: %v", err.Error())
|
||||
}
|
||||
|
||||
// 启动定时任务
|
||||
go cron.Task()
|
||||
}
|
||||
|
||||
func main() {
|
||||
|
57
utils/wechat_notify.go
Normal file
57
utils/wechat_notify.go
Normal file
@ -0,0 +1,57 @@
|
||||
package utils
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"gitee.ltd/lxh/logger/log"
|
||||
jsoniter "github.com/json-iterator/go"
|
||||
"wireguard-ui/global/client"
|
||||
"wireguard-ui/model"
|
||||
)
|
||||
|
||||
// wxid_472vas3av5ug22 /api/sendTextMsg
|
||||
type wechatNotify struct {
|
||||
Addr string
|
||||
Path string
|
||||
Method string
|
||||
toUserId string
|
||||
}
|
||||
|
||||
func WechatNotify(setting *model.Setting) wechatNotify {
|
||||
var sm = make(map[string]string)
|
||||
_ = json.Unmarshal([]byte(setting.Data), &sm)
|
||||
|
||||
return wechatNotify{
|
||||
Addr: sm["addr"],
|
||||
Path: sm["path"],
|
||||
Method: sm["method"],
|
||||
toUserId: sm["toUserId"],
|
||||
}
|
||||
}
|
||||
|
||||
// SendTextMessage
|
||||
// @description: 发送文字通知
|
||||
// @receiver website
|
||||
// @param msg
|
||||
// @return error
|
||||
func (w wechatNotify) SendTextMessage(msg string) error {
|
||||
req := client.HttpClient.R()
|
||||
|
||||
req.SetHeader("Content-Type", "application/json")
|
||||
req.SetBody(map[string]string{
|
||||
"wxid": w.toUserId,
|
||||
"msg": msg,
|
||||
})
|
||||
result, err := req.Post(fmt.Sprintf("%s:%s", w.Addr, w.Path))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if jsoniter.Get(result.Body(), "code").ToInt() != 1 {
|
||||
log.Errorf("发送通知到微信失败: %v", jsoniter.Get(result.Body(), "msg").ToString())
|
||||
return errors.New("发送通知到微信失败")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
Loading…
Reference in New Issue
Block a user