feat(readme): 更新项目介绍和部署指南

更新了README,加入了使用Go语言重新实现sihuan/XZZ机器人项目的介绍。由于原项目使用的go-cqhttp不再维护,本项目转向使用napcat实现。同时,更新了部署服务的步骤和配置文件示例,方便用户进行部署和使用。
This commit is contained in:
liyp 2024-07-20 15:49:03 +08:00
parent c77378d825
commit f160de4320
5 changed files with 77 additions and 36 deletions

View file

@ -1,33 +1,56 @@
# 使用Go语言重新实现 [sihuan/XZZ](https://github.com/sihuan/XZZ) 机器人项目
本项目是一个使用Go语言重新实现 [sihuan/XZZ](https://github.com/sihuan/XZZ) 机器人项目。原使用go-cqhttp的机器人项目由于go-cqhttp不再维护有众多bug无法使用所以更换使用 [napcat](https://github.com/NapNeko/NapCatQQ) 实现。
## 使用方式:
- 下载一个`go-cqhttp` 配置http模式修改为下面类似配置
当前项目的功能都在`workers`目录下。同时所有接收到的消息都保存在一个sqllite数据库中文件名为`data.db`保存在项目根目录。
## 部署服务:
1. 先使用docker部署[napcat](https://github.com/NapNeko/NapCatQQ)然后修改配置文件将机器人的token替换为napcat的token然后运行项目即可。
部署[napcat](https://github.com/NapNeko/NapCatQQ)可参考下面的docker-compose.yml文件
```yaml
- http: # HTTP 通信设置
address: 0.0.0.0:5700 # HTTP监听地址
version: 11 # OneBot协议版本, 支持 11/12
timeout: 5 # 反向 HTTP 超时时间, 单位秒,<5 时将被忽略
long-polling: # 长轮询拓展
enabled: false # 是否开启
max-queue-size: 2000 # 消息队列大小0 表示不限制队列大小,谨慎使用
middlewares:
<<: *default # 引用默认中间件
post: # 反向HTTP POST地址列表
- url: http://0.0.0.0:5580 # 地址
version: '3'
services:
napcat:
image: mlikiowa/napcat-docker:latest
container_name: napcat
environment:
- ACCOUNT=<QQ号>
- HTTP_ENABLE=true
- HTTP_POST_ENABLE=true
- HTTP_URLS=["http://172.17.0.1:5580/"]
ports:
- "5700:3000"
- "6099:6099"
volumes:
- ~/dockerfile/napcat/config:/usr/src/app/napcat/config
- ~/dockerfile/napcat/QQ:/root/.config/QQ
```
- 配置事件过滤规则
```json
{
"message_type": "group",
"raw_message":{
".regex":"^!"
}
}
```
表示只接收以 ! 开头的指令,同时修改配置文件默认中间件锚点的事件过滤器文件目录 `filter: filter.json` ,还要修改上报数据类型为 `array`
然后启动docker-compose.yml文件即可。
- 自定义配置
修改项目目录下的 `config.toml` 文件,`APIURL` 配置为 `go-cqhttp``post` 配置的 `url` 地址。
`POSTURL` 配置为 `go-cqhttp``http` 配置的 `address` 地址,需要加协议前缀 `http://`
后面的 [Group] 按需求配置,注意里面的群名要加双引号,因为程序里读取的是 `string` 类型。
2. 运行本项目前需要先修改配置文件,将本项目目录下的`config example.toml` 重命名为`config.toml`,然后修改配置文件,默认的配置端口跟上面的 docker-compose.yml文件一致不需要修改。如果需要使用ai功能需要修改配置文件里的`MODEL`,`OPENAI_API_KEY`和`OPENAI_BaseURL`这三个字段。
3. 启动项目安装go环境然后运行`go run main.go`即可。你也可以使用`go build main/go -o go-bot`编译为可执行文件,
## 使用说明:
1. 默认的配置端口是5580如果需要修改请修改配置文件里的`APIURL`字段。默认获取以`!`开头的消息,如果需要修改,请修改配置文件里的`Prefix`字段。
## 编写插件:
所有的插件放在`workers`目录下,并且都要有下面的代码:
```go
package workers
func init() {
RegisterWorkerFactory("ping", func(parms []string, uid, gid, role, mid, rawMsg string) Worker {
return &Ping{
StdAns: NewStdAns(parms, uid, gid, role, mid, rawMsg),
}
})
}
type Ping struct {
*StdAns
}
```
上面的例子是实现里`ping`这个插件的注册,在群组中以`!ping`指令激活。
同时所有的功能需要写在实现的`GetMsg()`方法里,如`!ping` 命令的:
```go
func (a *Ping) GetMsg() string {
return "Pong!"
}
```

View file

@ -1,9 +1,14 @@
APIURL = "0.0.0.0:5580"
POSTURL = "http://0.0.0.0:5700"
Prefix = "!"
AllowGroup = []
AllowUser = []
AllowRole = []
BlockGroup = []
BlockUser = []
Master = []
MODEL = "gpt-4o"
OPENAI_API_KEY = "https://api.openai.com/v1"
OPENAI_BaseURL = "sk-xxxx"
PROMPT = "## Role : \nQQ群Linux助手\n\n## Background : \n该角色是一位专门为QQ群提供Linux相关技术支持的助手熟悉各种Linux发行版的使用和问题解决旨在帮助群友解决他们在使用Linux过程中遇到的各种问题。\n\n## Preferences : \n该角色偏好简洁明了的回答风格注重解决方案的精确性和有效性。喜欢友好和尊重的互动方式致力于营造一个技术交流的和谐环境。\n\n## Profile :\n- language: 中文\n- description: 为QQ群友提供Linux相关问题的简洁、精确解决方案\n\n## Goals :\n1. 回答Linux相关问题\n2. 提供简短、精确的解决方案\n3. 鼓励群友提出问题并尊重他们\n\n## Constrains :\n1. 避免回答政治相关内容\n2. 每个问题只回答一次,确保回复简短、精确\n\n## Skills :\n1. 熟悉各种Linux发行版的使用和问题解决\n2. 能够提供简洁明了的技术支持\n3. 友好回复群友的提问\n\n## Examples :\n1. 问题如何查看当前Linux系统的内核版本\n 答案:可以使用命令`uname -r`来查看当前的内核版本。\n \n2. 问题:如何安装一个软件包?\n 答案:可以使用`sudo pacman -S <软件包名>`来安装软件包适用于Archlinux系。\n\n## OutputFormat :\n1. 接收用户输入的问题。\n2. 提供简洁、精确的解决方案。\n\n## Initialization : \n作为 QQ群Linux助手, 拥有 熟悉各种Linux发行版的使用和问题解决, 能够提供简洁明了的技术支持, 友好回复群友的提问, 避免回答政治相关内容, 每个问题只回答一次,确保回复简短、精确, 使用默认 中文 与用户对话,友好的欢迎用户。然后介绍自己,并提示用户输入。\n"

View file

@ -7,7 +7,9 @@ import (
"go-bot/utils"
"io"
"log"
"net"
"net/http"
"strings"
"time"
"github.com/gin-gonic/gin"
@ -122,6 +124,12 @@ func main() {
fmt.Println("Server listening on", APIURL, "...")
if err := r.Run(APIURL); err != nil {
if opError, ok := err.(*net.OpError); ok && opError.Op == "listen" {
log.Fatal("服务器启动失败:端口被占用。")
} else if strings.Contains(err.Error(), "address already in use") {
log.Fatal("服务器启动失败:端口被占用。")
} else {
log.Fatal("服务器启动失败:", err)
}
}
}

View file

@ -2,6 +2,7 @@ package utils
import (
"fmt"
"go-bot/config"
"go-bot/workers"
"regexp"
"strings"
@ -32,9 +33,13 @@ func Router(data map[string]interface{}) {
raw_msg = raw_msg + " " + fullMatch
}
}
prefix, err := config.GetConfig()["Prefix"].(string)
if !err {
panic("Prefix设置异常")
fmt.Println("raw_msg:", string(raw_msg))
if len(raw_msg) > 1 && raw_msg[0] == '!' {
}
// fmt.Println("raw_msg:", string(raw_msg))
if len(raw_msg) > 1 && string(raw_msg[0]) == prefix {
// 去除'!'
raw_msg = raw_msg[1:]
parms := strings.Fields(raw_msg)

View file

@ -104,9 +104,9 @@ func (a *AI) GetMsg() string {
fmt.Println("获取图片大小失败:", err)
return "获取图片大小失败"
}
if fileSize/1024/1024 > 1.0 {
log.Println("文件大小超过1M")
return "文件大小超过1M"
if fileSize/1024/1024 > 2.0 {
log.Println("文件大小超过2M")
return "文件大小超过2M"
}
filePath := a.GetImage(file)
// println("filePath:", filePath)