mirror of
https://github.com/FloatTech/ZeroBot-Plugin.git
synced 2026-02-12 02:00:24 +00:00
增加小爱回复 (#100)
* fix:去掉count,修sql * feat:增加小爱回复 * fix:修一下lint * fix:修一下lint * fix:修一下lint * fix:修一下lint * fix:修改设置回复模式 * fix:修lint Co-authored-by: Guohuiyuan <haibaraguo@yeahka.com>
This commit is contained in:
147
plugin_ai_reply/ai_reply.go
Normal file
147
plugin_ai_reply/ai_reply.go
Normal file
@@ -0,0 +1,147 @@
|
||||
// Package aireply 人工智能回复
|
||||
package aireply
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"github.com/FloatTech/ZeroBot-Plugin/control"
|
||||
log "github.com/sirupsen/logrus"
|
||||
zero "github.com/wdvxdr1123/ZeroBot"
|
||||
"github.com/wdvxdr1123/ZeroBot/extension/rate"
|
||||
"github.com/wdvxdr1123/ZeroBot/message"
|
||||
"math/rand"
|
||||
"time"
|
||||
)
|
||||
|
||||
var (
|
||||
bucket = rate.NewManager(time.Minute, 20) // 青云客接口回复
|
||||
engine = control.Register(serviceName, &control.Options{
|
||||
DisableOnDefault: false,
|
||||
Help: "人工智能回复\n" +
|
||||
"- @Bot 任意文本(任意一句话回复)\n- 设置回复模式[青云客|小爱]\n- ",
|
||||
})
|
||||
modeMap = map[string]int64{"青云客": 1, "小爱": 2}
|
||||
)
|
||||
|
||||
const (
|
||||
serviceName = "aireply"
|
||||
qykURL = "http://api.qingyunke.com/api.php?key=free&appid=0&msg=%s"
|
||||
qykBotName = "菲菲"
|
||||
xiaoaiURL = "http://81.70.100.130/api/xiaoai.php?msg=%s&n=text"
|
||||
xiaoaiBotName = "小爱"
|
||||
prio = 256
|
||||
)
|
||||
|
||||
// AIReply 公用智能回复类
|
||||
type AIReply interface {
|
||||
// DealQuestion 把椛椛替换为各api接口的bot名字
|
||||
DealQuestion(preMsg string) (msg string)
|
||||
// GetReply 取得回复消息
|
||||
GetReply(msg string) (reply string)
|
||||
// DealReply 处理回复消息
|
||||
DealReply(reply string) (textReply string, faceReply int)
|
||||
}
|
||||
|
||||
// NewAIReply 智能回复简单工厂
|
||||
func NewAIReply(mode int64) AIReply {
|
||||
if mode == 1 {
|
||||
return &QYKReply{}
|
||||
} else if mode == 2 {
|
||||
return &XiaoAiReply{}
|
||||
}
|
||||
return &QYKReply{}
|
||||
}
|
||||
|
||||
func init() { // 插件主体
|
||||
// 回复 @和包括名字
|
||||
engine.OnMessage(zero.OnlyToMe).SetBlock(true).SetPriority(prio).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
aireply := NewAIReply(GetReplyMode(ctx))
|
||||
if !bucket.Load(ctx.Event.UserID).Acquire() {
|
||||
// 频繁触发,不回复
|
||||
return
|
||||
}
|
||||
msg := ctx.ExtractPlainText()
|
||||
// 把消息里的椛椛替换成对应接口机器人的名字
|
||||
msg = aireply.DealQuestion(msg)
|
||||
reply := aireply.GetReply(msg)
|
||||
// 挑出 face 表情
|
||||
textReply, faceReply := aireply.DealReply(reply)
|
||||
// 回复
|
||||
time.Sleep(time.Second * 1)
|
||||
if ctx.Event.MessageType == "group" {
|
||||
if faceReply != -1 {
|
||||
ctx.SendChain(message.Reply(ctx.Event.MessageID), message.Text(textReply), message.Face(faceReply))
|
||||
} else {
|
||||
ctx.SendChain(message.Reply(ctx.Event.MessageID), message.Text(textReply))
|
||||
}
|
||||
}
|
||||
if ctx.Event.MessageType == "private" {
|
||||
if faceReply != -1 {
|
||||
ctx.SendChain(message.Text(textReply), message.Face(faceReply))
|
||||
} else {
|
||||
ctx.SendChain(message.Text(textReply))
|
||||
}
|
||||
}
|
||||
})
|
||||
engine.OnPrefix(`设置回复模式`).SetBlock(true).SetPriority(20).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
param := ctx.State["args"].(string)
|
||||
switch param {
|
||||
case "青云客":
|
||||
if err := setReplyMode(ctx, modeMap["青云客"]); err != nil {
|
||||
log.Errorln("[aireply]:", err)
|
||||
}
|
||||
ctx.SendChain(message.Text("设置为青云客回复"))
|
||||
case "小爱":
|
||||
if err := setReplyMode(ctx, modeMap["小爱"]); err != nil {
|
||||
log.Errorln("[aireply]:", err)
|
||||
}
|
||||
ctx.SendChain(message.Text("设置为小爱回复"))
|
||||
default:
|
||||
ctx.SendChain(message.Text("设置失败"))
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func setReplyMode(ctx *zero.Ctx, mode int64) error {
|
||||
gid := ctx.Event.GroupID
|
||||
if gid == 0 {
|
||||
gid = -ctx.Event.UserID
|
||||
}
|
||||
m, ok := control.Lookup(serviceName)
|
||||
if ok {
|
||||
return m.SetData(gid, mode)
|
||||
}
|
||||
return errors.New("no such plugin")
|
||||
}
|
||||
|
||||
// GetReplyMode 取得回复模式
|
||||
func GetReplyMode(ctx *zero.Ctx) (mode int64) {
|
||||
gid := ctx.Event.GroupID
|
||||
if gid == 0 {
|
||||
gid = -ctx.Event.UserID
|
||||
}
|
||||
m, ok := control.Lookup(serviceName)
|
||||
if ok {
|
||||
mode = m.GetData(gid)
|
||||
}
|
||||
return mode
|
||||
}
|
||||
|
||||
func getAgent() string {
|
||||
agent := [...]string{
|
||||
"Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:50.0) Gecko/20100101 Firefox/50.0",
|
||||
"Opera/9.80 (Macintosh; Intel Mac OS X 10.6.8; U; en) Presto/2.8.131 Version/11.11",
|
||||
"Opera/9.80 (Windows NT 6.1; U; en) Presto/2.8.131 Version/11.11",
|
||||
"Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; 360SE)",
|
||||
"Mozilla/5.0 (Windows NT 6.1; rv:2.0.1) Gecko/20100101 Firefox/4.0.1",
|
||||
"Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; The World)",
|
||||
"User-Agent,Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_6_8; en-us) AppleWebKit/534.50 (KHTML, like Gecko) Version/5.1 Safari/534.50",
|
||||
"User-Agent, Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; Maxthon 2.0)",
|
||||
"User-Agent,Mozilla/5.0 (Windows; U; Windows NT 6.1; en-us) AppleWebKit/534.50 (KHTML, like Gecko) Version/5.1 Safari/534.50",
|
||||
}
|
||||
|
||||
r := rand.New(rand.NewSource(time.Now().UnixNano()))
|
||||
len1 := len(agent)
|
||||
return agent[r.Intn(len1)]
|
||||
}
|
||||
61
plugin_ai_reply/picture.go
Normal file
61
plugin_ai_reply/picture.go
Normal file
@@ -0,0 +1,61 @@
|
||||
package aireply
|
||||
|
||||
// TODO: 待优化
|
||||
|
||||
/*
|
||||
import (
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"math/rand"
|
||||
"net/http"
|
||||
"regexp"
|
||||
)
|
||||
|
||||
var (
|
||||
reImg = `https?://[^"]+?(\.((jpg)|(png)|(jpeg)|(gif)|(bmp)))`
|
||||
)
|
||||
|
||||
//取图片
|
||||
func getPicture() string {
|
||||
prefix := "https://fabiaoqing.com/tag/detail/id/5682/page"
|
||||
url := fmt.Sprintf("%d.html", rand.Intn(11)+1)
|
||||
url = prefix + url
|
||||
log.Println("正在" + url + "寻找图片")
|
||||
urls := getImgs(url)
|
||||
fmt.Println(urls)
|
||||
imageURL := urls[rand.Intn(len(urls))]
|
||||
log.Println("取到" + imageURL)
|
||||
return imageURL
|
||||
}
|
||||
|
||||
func HandleError(err error, why string) {
|
||||
if err != nil {
|
||||
fmt.Println(why, err)
|
||||
}
|
||||
}
|
||||
|
||||
func getImgs(url string) (urls []string) {
|
||||
pageStr := GetPageStr(url)
|
||||
re := regexp.MustCompile(reImg)
|
||||
results := re.FindAllStringSubmatch(pageStr, -1)
|
||||
fmt.Printf("共找到%d条结果\n", len(results))
|
||||
for _, result := range results {
|
||||
url := result[0]
|
||||
urls = append(urls, url)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func GetPageStr(url string) (pageStr string) {
|
||||
resp, err := http.Get(url)
|
||||
HandleError(err, "http.Get url")
|
||||
defer resp.Body.Close()
|
||||
// 2.读取页面内容
|
||||
pageBytes, err := ioutil.ReadAll(resp.Body)
|
||||
HandleError(err, "ioutil.ReadAll")
|
||||
// 字节转字符串
|
||||
pageStr = string(pageBytes)
|
||||
return pageStr
|
||||
}
|
||||
*/
|
||||
68
plugin_ai_reply/qingyunke.go
Normal file
68
plugin_ai_reply/qingyunke.go
Normal file
@@ -0,0 +1,68 @@
|
||||
package aireply
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
log "github.com/sirupsen/logrus"
|
||||
"github.com/tidwall/gjson"
|
||||
zero "github.com/wdvxdr1123/ZeroBot"
|
||||
"github.com/wdvxdr1123/ZeroBot/utils/helper"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"regexp"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// QYKReply 青云客回复类
|
||||
type QYKReply struct{}
|
||||
|
||||
// DealQuestion 把椛椛替换为菲菲
|
||||
func (*QYKReply) DealQuestion(preMsg string) (msg string) {
|
||||
msg = strings.ReplaceAll(preMsg, zero.BotConfig.NickName[0], qykBotName)
|
||||
return msg
|
||||
}
|
||||
|
||||
// GetReply 取得回复消息
|
||||
func (*QYKReply) GetReply(msg string) (reply string) {
|
||||
u := fmt.Sprintf(qykURL, url.QueryEscape(msg))
|
||||
client := &http.Client{}
|
||||
req, err := http.NewRequest("GET", u, nil)
|
||||
if err != nil {
|
||||
log.Errorln("[aireply-qingyunke]:", err)
|
||||
return ""
|
||||
}
|
||||
// 自定义Header
|
||||
req.Header.Set("User-Agent", getAgent())
|
||||
req.Header.Set("Connection", "keep-alive")
|
||||
req.Header.Set("Host", "api.qingyunke.com")
|
||||
resp, err := client.Do(req)
|
||||
if err != nil {
|
||||
log.Errorln("[aireply-qingyunke]:", err)
|
||||
return
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
bytes, err := ioutil.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
log.Errorln("[aireply-qingyunke]:", err)
|
||||
return
|
||||
}
|
||||
reply = gjson.Get(helper.BytesToString(bytes), "content").String()
|
||||
log.Println("reply:", reply)
|
||||
return
|
||||
}
|
||||
|
||||
// DealReply 处理回复消息
|
||||
func (*QYKReply) DealReply(reply string) (textReply string, faceReply int) {
|
||||
reg := regexp.MustCompile(`\{face:(\d+)\}(.*)`)
|
||||
faceReply = -1
|
||||
if reg.MatchString(reply) {
|
||||
faceReply, _ = strconv.Atoi(reg.FindStringSubmatch(reply)[1])
|
||||
textReply = reg.FindStringSubmatch(reply)[2]
|
||||
} else {
|
||||
textReply = reply
|
||||
}
|
||||
textReply = strings.ReplaceAll(textReply, qykBotName, zero.BotConfig.NickName[0])
|
||||
textReply = strings.ReplaceAll(textReply, "{br}", "\n")
|
||||
return
|
||||
}
|
||||
61
plugin_ai_reply/xiaoai.go
Normal file
61
plugin_ai_reply/xiaoai.go
Normal file
@@ -0,0 +1,61 @@
|
||||
package aireply
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
log "github.com/sirupsen/logrus"
|
||||
zero "github.com/wdvxdr1123/ZeroBot"
|
||||
"github.com/wdvxdr1123/ZeroBot/utils/helper"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// XiaoAiReply 小爱回复类
|
||||
type XiaoAiReply struct{}
|
||||
|
||||
// DealQuestion 把椛椛替换为小爱
|
||||
func (*XiaoAiReply) DealQuestion(preMsg string) (msg string) {
|
||||
msg = strings.ReplaceAll(preMsg, zero.BotConfig.NickName[0], xiaoaiBotName)
|
||||
return msg
|
||||
}
|
||||
|
||||
// GetReply 取得回复消息
|
||||
func (*XiaoAiReply) GetReply(msg string) (reply string) {
|
||||
u := fmt.Sprintf(xiaoaiURL, url.QueryEscape(msg))
|
||||
client := &http.Client{}
|
||||
req, err := http.NewRequest("GET", u, nil)
|
||||
if err != nil {
|
||||
log.Errorln("[aireply-xiaoai]:", err)
|
||||
return ""
|
||||
}
|
||||
// 自定义Header
|
||||
req.Header.Set("User-Agent", getAgent())
|
||||
req.Header.Set("Connection", "keep-alive")
|
||||
req.Header.Set("Host", "81.70.100.130")
|
||||
resp, err := client.Do(req)
|
||||
if err != nil {
|
||||
log.Errorln("[aireply-xiaoai]:", err)
|
||||
return
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
bytes, err := ioutil.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
log.Errorln("[aireply-xiaoai]:", err)
|
||||
return
|
||||
}
|
||||
reply = helper.BytesToString(bytes)
|
||||
log.Println("reply:", reply)
|
||||
return
|
||||
}
|
||||
|
||||
// DealReply 处理回复消息
|
||||
func (*XiaoAiReply) DealReply(reply string) (textReply string, faceReply int) {
|
||||
textReply = strings.ReplaceAll(reply, xiaoaiBotName, zero.BotConfig.NickName[0])
|
||||
if textReply == "" {
|
||||
textReply = zero.BotConfig.NickName[0] + "听不懂你的话了,能再说一遍吗"
|
||||
}
|
||||
textReply = strings.ReplaceAll(textReply, "小米智能助理", "电子宠物")
|
||||
faceReply = -1
|
||||
return
|
||||
}
|
||||
Reference in New Issue
Block a user