Skip to content

Commit

Permalink
Test4 (#26)
Browse files Browse the repository at this point in the history
* Compiled main.go and pushed changes

* test

* 适配了频道私聊,用bolt数据库取代ini

* 适配了nonebot2

* add license

* add a lot

* trss support

* add action

* add action

* add action

* fixbug

* add wss

* bugfix

* fix action

* fix action again

* fa

* fix

* add a lot

* add ws server token

* bugifx

* fixat

* bugfix

* bugfix

* test

* test2

* add url service
  • Loading branch information
Hoshinonyaruko authored Oct 31, 2023
1 parent 8d387ce commit dc1ddb7
Show file tree
Hide file tree
Showing 17 changed files with 517 additions and 51 deletions.
1 change: 1 addition & 0 deletions callapi/callapi.go
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,7 @@ type Client interface {
// 为了解决processor和server循环依赖设计的接口
type WebSocketServerClienter interface {
SendMessage(message map[string]interface{}) error
Close() error
}

// 根据action订阅handler处理api
Expand Down
39 changes: 39 additions & 0 deletions config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,9 @@ type Settings struct {
MasterID []string `yaml:"master_id,omitempty"` // 如果需要在群权限判断是管理员是,将user_id填入这里,master_id是一个文本数组
EnableWsServer bool `yaml:"enable_ws_server,omitempty"` //正向ws开关
WsServerToken string `yaml:"ws_server_token,omitempty"` //正向ws token
IdentifyFile bool `yaml:"identify_file"` // 域名校验文件
Crt string `yaml:"crt"`
Key string `yaml:"key"`
}

// LoadConfig 从文件中加载配置并初始化单例配置
Expand Down Expand Up @@ -182,3 +185,39 @@ func GetWsServerToken() string {
}
return instance.Settings.WsServerToken
}

// 获取identify_file的值
func GetIdentifyFile() bool {
mu.Lock()
defer mu.Unlock()

if instance == nil {
log.Println("Warning: instance is nil when trying to get identify file name.")
return false
}
return instance.Settings.IdentifyFile
}

// 获取crt路径
func GetCrtPath() string {
mu.Lock()
defer mu.Unlock()

if instance == nil {
log.Println("Warning: instance is nil when trying to get crt path.")
return ""
}
return instance.Settings.Crt
}

// 获取key路径
func GetKeyPath() string {
mu.Lock()
defer mu.Unlock()

if instance == nil {
log.Println("Warning: instance is nil when trying to get key path.")
return ""
}
return instance.Settings.Key
}
4 changes: 4 additions & 0 deletions config_template.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,4 +41,8 @@ settings:
master_id : ["1","2"] #群场景尚未开放获取管理员和列表能力,手动从日志中获取需要设置为管理,的user_id并填入(适用插件有权限判断场景)
enable_ws_server: true #是否启用正向ws服务器 监听server_dir:port/ws
ws_server_token : "12345" #正向ws的token 不启动正向ws可忽略
ws_server_token : "12345" #正向ws的token 不启动正向ws可忽略
identify_file: true #自动生成域名校验文件,在q.qq.com配置信息URL,在server_dir填入自己已备案域名,正确解析到机器人所在服务器ip地址,机器人即可发送链接
crt: "" #证书路径 从你的域名服务商或云服务商申请签发SSL证书(qq要求SSL)
key: "" #密钥路径 Apache(crt文件、key文件)示例: "C:\\123.key" \需要双写成\\
`
6 changes: 5 additions & 1 deletion config_template.yml
Original file line number Diff line number Diff line change
Expand Up @@ -31,4 +31,8 @@ settings:
ws_token: ["",""] #连接wss地址时服务器所需的token,如果是ws,可留空,按顺序一一对应
master_id : ["1","2"] #群场景尚未开放获取管理员和列表能力,手动从日志中获取需要设置为管理,的user_id并填入(适用插件有权限判断场景)
enable_ws_server: true #是否启用正向ws服务器 监听server_dir:port/ws
ws_server_token : "12345" #正向ws的token 不启动正向ws可忽略
ws_server_token : "12345" #正向ws的token 不启动正向ws可忽略
ws_server_token : "12345" #正向ws的token 不启动正向ws可忽略
identify_file: true #自动生成域名校验文件,在q.qq.com配置信息URL,在server_dir填入自己已备案域名,正确解析到机器人所在服务器ip地址,机器人即可发送链接
crt: "" #证书路径 从你的域名服务商或云服务商申请签发SSL证书(qq要求SSL)
key: "" #密钥路径 Apache(crt文件、key文件)示例: "C:\\123.key" \需要双写成\\
6 changes: 3 additions & 3 deletions echo/echo.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,21 +16,21 @@ var globalEchoMapping = &EchoMapping{
msgIDMapping: make(map[string]string),
}

func (e *EchoMapping) generateKey(appid string, s int64) string {
func (e *EchoMapping) GenerateKey(appid string, s int64) string {
return appid + "_" + strconv.FormatInt(s, 10)
}

// 添加echo对应的类型
func AddMsgType(appid string, s int64, msgType string) {
key := globalEchoMapping.generateKey(appid, s)
key := globalEchoMapping.GenerateKey(appid, s)
globalEchoMapping.mu.Lock()
defer globalEchoMapping.mu.Unlock()
globalEchoMapping.msgTypeMapping[key] = msgType
}

// 添加echo对应的messageid
func AddMsgID(appid string, s int64, msgID string) {
key := globalEchoMapping.generateKey(appid, s)
key := globalEchoMapping.GenerateKey(appid, s)
globalEchoMapping.mu.Lock()
defer globalEchoMapping.mu.Unlock()
globalEchoMapping.msgIDMapping[key] = msgID
Expand Down
Binary file added gensokyo.db
Binary file not shown.
2 changes: 2 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -45,4 +45,6 @@ require (
golang.org/x/sys v0.8.0 // indirect
golang.org/x/text v0.9.0 // indirect
google.golang.org/protobuf v1.30.0 // indirect
mvdan.cc/xurls v1.1.0
mvdan.cc/xurls/v2 v2.5.0 // indirect
)
4 changes: 4 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -193,4 +193,8 @@ gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
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=
mvdan.cc/xurls v1.1.0 h1:kj0j2lonKseISJCiq1Tfk+iTv65dDGCl0rTbanXJGGc=
mvdan.cc/xurls v1.1.0/go.mod h1:TNWuhvo+IqbUCmtUIb/3LJSQdrzel8loVpgFm0HikbI=
mvdan.cc/xurls/v2 v2.5.0 h1:lyBNOm8Wo71UknhUs4QTFUNNMyxy2JEIaKKo0RWOh+8=
mvdan.cc/xurls/v2 v2.5.0/go.mod h1:yQgaGQ1rFtJUzkmKiHYSSfuQxqfYmd//X6PxvholpeE=
rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4=
9 changes: 5 additions & 4 deletions handlers/get_group_info.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import (
"context"
"encoding/json"
"log"
"strconv"

"github.com/hoshinonyaruko/gensokyo/callapi"
"github.com/hoshinonyaruko/gensokyo/idmap"
Expand All @@ -28,11 +27,13 @@ type OnebotGroupInfo struct {
}

func ConvertGuildToGroupInfo(guild *dto.Guild, GroupId string) *OnebotGroupInfo {
groupidstr, err := strconv.ParseInt(GroupId, 10, 64)
// 使用idmap.StoreIDv2映射GroupId到一个int64的值
groupid64, err := idmap.StoreIDv2(GroupId)
if err != nil {
log.Printf("groupidstr: %v", err)
log.Printf("Error storing GroupID: %v", err)
return nil
}

ts, err := guild.JoinedAt.Time()
if err != nil {
log.Printf("转换JoinedAt失败: %v", err)
Expand All @@ -41,7 +42,7 @@ func ConvertGuildToGroupInfo(guild *dto.Guild, GroupId string) *OnebotGroupInfo
groupCreateTime := uint32(ts.Unix())

return &OnebotGroupInfo{
GroupID: groupidstr,
GroupID: groupid64,
GroupName: guild.Name,
GroupMemo: guild.Desc,
GroupCreateTime: groupCreateTime,
Expand Down
15 changes: 13 additions & 2 deletions handlers/message_parser.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,9 @@ import (

"github.com/hoshinonyaruko/gensokyo/callapi"
"github.com/hoshinonyaruko/gensokyo/idmap"
"github.com/hoshinonyaruko/gensokyo/url"
"github.com/tencent-connect/botgo/dto"
"mvdan.cc/xurls" //xurls是一个从文本提取url的库 适用于多种场景
)

var BotID string
Expand Down Expand Up @@ -58,6 +60,7 @@ func SendResponse(client callapi.Client, err error, message *callapi.ActionMessa
return nil
}

// 信息处理函数
func parseMessageContent(paramsMessage callapi.ParamsContent) (string, map[string][]string) {
messageText := ""

Expand Down Expand Up @@ -156,11 +159,11 @@ func parseMessageContent(paramsMessage callapi.ParamsContent) (string, map[strin
return messageText, foundItems
}

// at处理和链接处理
func transformMessageText(messageText string) string {
// 使用正则表达式来查找所有[CQ:at,qq=数字]的模式
re := regexp.MustCompile(`\[CQ:at,qq=(\d+)\]`)
// 使用正则表达式来替换找到的模式为<@!数字>
return re.ReplaceAllStringFunc(messageText, func(m string) string {
messageText = re.ReplaceAllStringFunc(messageText, func(m string) string {
submatches := re.FindStringSubmatch(m)
if len(submatches) > 1 {
realUserID, err := idmap.RetrieveRowByIDv2(submatches[1])
Expand All @@ -172,6 +175,14 @@ func transformMessageText(messageText string) string {
}
return m
})

// 使用xurls来查找和替换所有的URL
messageText = xurls.Relaxed.ReplaceAllStringFunc(messageText, func(originalURL string) string {
shortURL := url.GenerateShortURL(originalURL)
// 使用getBaseURL函数来获取baseUrl并与shortURL组合
return url.GetBaseURL() + "/url/" + shortURL
})
return messageText
}

// 处理at和其他定形文到onebotv11格式(cq码)
Expand Down
5 changes: 5 additions & 0 deletions handlers/send_guild_channel_msg.go
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,11 @@ func handleSendGuildChannelMsg(client callapi.Client, api openapi.OpenAPI, apiv2
messageID = echo.GetMsgIDByKey(echoStr)
log.Println("echo取频道发信息对应的message_id:", messageID)
}
// 如果messageID为空,通过函数获取
if messageID == "" {
messageID = GetMessageIDByUseridOrGroupid(config.GetAppIDStr(), channelID)
log.Println("通过GetMessageIDByUserid函数获取的message_id:", messageID)
}
log.Println("频道发信息messageText:", messageText)
log.Println("foundItems:", foundItems)
var err error
Expand Down
5 changes: 5 additions & 0 deletions handlers/send_msg.go
Original file line number Diff line number Diff line change
Expand Up @@ -169,6 +169,11 @@ func handleSendMsg(client callapi.Client, api openapi.OpenAPI, apiv2 openapi.Ope
messageID = echo.GetMsgIDByKey(echoStr)
log.Println("echo取私聊发信息对应的message_id:", messageID)
}
// 如果messageID为空,通过函数获取
if messageID == "" {
messageID = GetMessageIDByUseridOrGroupid(config.GetAppIDStr(), UserID)
log.Println("通过GetMessageIDByUserid函数获取的message_id:", messageID)
}
log.Println("私聊发信息messageText:", messageText)
log.Println("foundItems:", foundItems)

Expand Down
10 changes: 10 additions & 0 deletions handlers/send_private_msg.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,12 @@ func handleSendPrivateMsg(client callapi.Client, api openapi.OpenAPI, apiv2 open
messageID = echo.GetMsgIDByKey(echoStr)
log.Println("echo取私聊发信息对应的message_id:", messageID)
}
// 如果messageID仍然为空,尝试使用config.GetAppID和UserID的组合来获取messageID
// 如果messageID为空,通过函数获取
if messageID == "" {
messageID = GetMessageIDByUseridOrGroupid(config.GetAppIDStr(), UserID)
log.Println("通过GetMessageIDByUserid函数获取的message_id:", messageID)
}
log.Println("私聊发信息messageText:", messageText)
log.Println("foundItems:", foundItems)

Expand All @@ -66,6 +72,8 @@ func handleSendPrivateMsg(client callapi.Client, api openapi.OpenAPI, apiv2 open
if err != nil {
log.Printf("发送文本私聊信息失败: %v", err)
}
//发送成功回执
SendResponse(client, err, &message)
}

// 遍历 foundItems 并发送每种信息
Expand All @@ -85,6 +93,8 @@ func handleSendPrivateMsg(client callapi.Client, api openapi.OpenAPI, apiv2 open
if err != nil {
log.Printf("发送 %s 私聊信息失败: %v", key, err)
}
//发送成功回执
SendResponse(client, err, &message)
}
case "guild_private":
//当收到发私信调用 并且来源是频道
Expand Down
40 changes: 0 additions & 40 deletions idmap/cMapping.go

This file was deleted.

58 changes: 57 additions & 1 deletion main.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (
"errors"
"fmt"
"log"
"net/http"
"os"
"os/signal"
"syscall"
Expand All @@ -16,6 +17,7 @@ import (
"github.com/hoshinonyaruko/gensokyo/handlers"
"github.com/hoshinonyaruko/gensokyo/idmap"
"github.com/hoshinonyaruko/gensokyo/server"
"github.com/hoshinonyaruko/gensokyo/url"
"github.com/hoshinonyaruko/gensokyo/wsclient"

"github.com/gin-gonic/gin"
Expand Down Expand Up @@ -169,13 +171,49 @@ func main() {
//是否启动服务器
shouldStartServer := !conf.Settings.Lotus || conf.Settings.EnableWsServer
//如果连接到其他gensokyo,则不需要启动服务器
var httpServer *http.Server
if shouldStartServer {
r := gin.Default()
r.GET("/getid", server.GetIDHandler)
r.POST("/uploadpic", server.UploadBase64ImageHandler(rateLimiter))
r.Static("/channel_temp", "./channel_temp")
r.GET("/ws", server.WsHandlerWithDependencies(api, apiV2, p))
r.Run("0.0.0.0:" + conf.Settings.Port) // 监听0.0.0.0地址的Port端口
r.POST("/url", url.CreateShortURLHandler)
r.GET("/url/:shortURL", url.RedirectFromShortURLHandler)
if config.GetIdentifyFile() {
appIDStr := config.GetAppIDStr()
fileName := appIDStr + ".json"
r.GET("/"+fileName, func(c *gin.Context) {
content := fmt.Sprintf(`{"bot_appid":%d}`, config.GetAppID())
c.Header("Content-Type", "application/json")
c.String(200, content)
})
}
// 创建一个http.Server实例
httpServer = &http.Server{
Addr: "0.0.0.0:" + conf.Settings.Port,
Handler: r,
}
// 在一个新的goroutine中启动Gin服务器
go func() {
if conf.Settings.Port == "443" {
// 使用HTTPS
crtPath := config.GetCrtPath()
keyPath := config.GetKeyPath()
if crtPath == "" || keyPath == "" {
log.Fatalf("crt or key path is missing for HTTPS")
return
}
if err := httpServer.ListenAndServeTLS(crtPath, keyPath); err != nil && err != http.ErrServerClosed {
log.Fatalf("listen (HTTPS): %s\n", err)
}
} else {
// 使用HTTP
if err := httpServer.ListenAndServe(); err != nil && err != http.ErrServerClosed {
log.Fatalf("listen: %s\n", err)
}
}
}()
}

// 使用通道来等待信号
Expand All @@ -193,6 +231,24 @@ func main() {
fmt.Printf("Error closing WebSocket connection: %v\n", err)
}
}

// 关闭BoltDB数据库
url.CloseDB()
idmap.CloseDB()

// 在关闭WebSocket客户端之前
for _, wsClient := range p.WsServerClients {
if err := wsClient.Close(); err != nil {
log.Printf("Error closing WebSocket server client: %v\n", err)
}
}

// 使用一个5秒的超时优雅地关闭Gin服务器
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()
if err := httpServer.Shutdown(ctx); err != nil {
log.Fatal("Server forced to shutdown:", err)
}
}

// ReadyHandler 自定义 ReadyHandler 感知连接成功事件
Expand Down
Loading

0 comments on commit dc1ddb7

Please sign in to comment.