Compare commits

..

24 Commits

Author SHA1 Message Date
fumiama
ce8d98b77d fix: panic: database is locked (5) (SQLITE_BUSY) 2021-12-22 18:37:41 +08:00
fumiama
2858d0b0a4 Merge branch 'master' of https://github.com/FloatTech/ZeroBot-Plugin 2021-12-21 22:22:11 +08:00
fumiama
1f982566e0 更新 codechina 域名 2021-12-21 22:22:01 +08:00
github-actions[bot]
779ec5b2fe 🎨 改进代码样式 2021-12-21 14:18:52 +00:00
fumiama
8499921d67 ✏️ 优化代码结构 2021-12-21 22:18:06 +08:00
fumiama
1e49bad1a6 Merge branch 'master' of https://github.com/FloatTech/ZeroBot-Plugin 2021-12-21 22:12:09 +08:00
fumiama
1d3a61386d ✏️ 优化代码结构 2021-12-21 22:09:43 +08:00
github-actions[bot]
25ef2ca220 🎨 改进代码样式 2021-12-21 13:25:34 +00:00
himawari
b953385bc5 feat:添加词库,骂人和笑话 (#90)
Co-authored-by: Guohuiyuan <haibaraguo@yeahka.com>
2021-12-21 21:24:59 +08:00
fumiama
4fdedd0a7b ✏️ 增加黑名单 (#2) 2021-12-21 14:12:13 +08:00
Kanri
f4bc43e7a5 ✏️ 修改 windows 日志样式 2021-12-21 09:35:59 +08:00
fumiama
596c75eeca ✏️ make lint happy 2021-12-19 17:43:46 +08:00
fumiama
67a493ee84 ✏️ 更新 go.sum 2021-12-19 17:36:13 +08:00
fumiama
f9c7d9419e ✏️ make lint happy 2021-12-19 17:27:32 +08:00
github-actions[bot]
1a1a006283 🎨 改进代码样式 2021-12-19 08:06:16 +00:00
himawari
fd85ce0923 feat:添加铅笔小说搜索插件 (#89)
* feat:添加铅笔小说搜索插件

* fix:小修改help

* fix:微调语句

* fix:替换编码库

* fix:不修改go.sum
2021-12-19 16:05:29 +08:00
fumiama
5ff9069ff2 ✏️ make lint happy 2021-12-19 16:04:14 +08:00
fumiama
4ad7ff7971 ✏️ make lint happy 2021-12-19 11:39:30 +08:00
fumiama
a9f98763c4 ✏️ edit README 2021-12-17 12:30:48 +08:00
fumiama
3b637fad78 ✏️ aifalese 磁盘空间占用仅输出非0挂载点 2021-12-17 12:28:38 +08:00
fumiama
f202797964 ✏️ fix shindan by @Yiwen-Chan 2021-12-17 11:36:50 +08:00
fumiama
242d780048 ✏️ edit README 2021-12-16 17:02:03 +08:00
fumiama
bf23364097 ✏️ edit README 2021-12-16 17:00:11 +08:00
fumiama
7eaac7a20b ✏️ fix gist panic 2021-12-16 16:27:25 +08:00
44 changed files with 2295 additions and 183 deletions

View File

@@ -52,6 +52,8 @@ zerobot -h -t token -u url [-d|w] [-g 监听地址:端口] qq1 qq2 qq3 ...
- [x] /全局启用 xxx
- [x] /全局禁用 xxx
- [x] /还原 xxx (在发送的群/用户还原xxx的开启状态到初始状态)
- [x] /禁止 service qq1 qq2... (禁止 qqs 使用服务 service)
- [x] /允许 service qq1 qq2... (重新允许 qqs 使用服务 service)
- [x] /用法 xxx
- [x] /服务列表
- [x] /服务详情
@@ -63,6 +65,7 @@ zerobot -h -t token -u url [-d|w] [-g 监听地址:端口] qq1 qq2 qq3 ...
- [x] 空调关
- [x] 群温度
- [x] 设置温度[正整数]
- [x] mua|啾咪|摸|上你|傻|裸|贴|老婆|抱|亲|一下|咬|操|123|进去|调教|搓|让|捏|挤|略|呐|原味|胖次|内裤|内衣|衣服|ghs|批|憨批|kkp|咕|骚|喜欢|suki|好き|看|不能|砸了|透|口我|草我|自慰|onani|オナニー|炸了|色图|涩图|告白|对不起|回来|吻|软|壁咚|掰开|女友|是|喵|嗷呜|叫|拜|佬|awsl|臭|香|腿|张开|脚|脸|头发|手|pr|舔|小穴|腰|诶嘿嘿|可爱|扭蛋|鼻|眼|色气|推|床|举|手冲|饿|变|敲|爬|怕|冲|射|不穿|迫害|猫粮|揪尾巴|薄荷|早|晚安|揉|榨|掐|胸|奶子|欧派|嫩|蹭|牵手|握手|拍照|w|睡不着|欧尼酱|哥|爱你|过来|自闭|打不过|么么哒|很懂|膝枕|累了|安慰|洗澡|一起睡觉|一起|多大|姐姐|糖|嗦|牛子|🐂子|🐮子|嫌弃|紧|baka|笨蛋|插|插进来|屁股|翘|翘起来|抬|抬起|爸|傲娇|rua|咕噜咕噜|咕噜|上床|做爱|吃掉|吃|揪|种草莓|种草|掀|妹|病娇|嘻
- **ATRI** `import _ "github.com/FloatTech/ZeroBot-Plugin/plugin_atri"`
- [x] 具体指令看 /用法 atri
- 注:本插件基于 [ATRI](https://github.com/Kyomotoi/ATRI) ,为 Golang 移植版
@@ -96,7 +99,7 @@ zerobot -h -t token -u url [-d|w] [-g 监听地址:端口] qq1 qq2 qq3 ...
- [ ] 撤回[@xxx] [xxx]
- [ ] 警告[@xxx]
- [x] run[xxx]
-使用gist加群自动审批请在群介绍添加以下说明同时开启`需要回答问题并由管理员审核`加群请在github新建一个gist其文件名为本群群号的字符串的md5内容为一行是当前unix时间戳。然后请将您的用户名和gist哈希按照username/gisthash的格式填写到回答即可。
-使用gist加群自动审批请在群介绍添加以下说明同时开启`需要回答问题并由管理员审核`加群请在github新建一个gist其文件名为本群群号的字符串的md5(小写)内容为一行是当前unix时间戳(10分钟内有效)。然后请将您的用户名和gist哈希(小写)按照username/gisthash的格式填写到回答即可。
- **GitHub仓库搜索** `import _ "github.com/FloatTech/ZeroBot-Plugin/plugin_github"`
- [x] >github [xxx]
- [x] >github -p [xxx]
@@ -176,7 +179,7 @@ zerobot -h -t token -u url [-d|w] [-g 监听地址:端口] qq1 qq2 qq3 ...
- 注:由于需要科学,默认注释。
- **AIfalse** `import _ "github.com/FloatTech/ZeroBot-Plugin/plugin_ai_false"`
- [x] 查询计算机当前活跃度: [检查身体|自检|启动自检|系统状态]
- [x] 清理缓存
- [x] 清理缓存 (仅适用于 gocq 且需要 bot 的运行目录和 gocq 相同)
- [ ] 简易语音
- [ ] 爬图合成 [@xxx]
- **抽wife** `import _ "github.com/FloatTech/ZeroBot-Plugin/plugin_nativewife"`
@@ -211,10 +214,16 @@ zerobot -h -t token -u url [-d|w] [-g 监听地址:端口] qq1 qq2 qq3 ...
- [x] vtb语录
- [x] 随机vtb
- **书评** `import _ "github.com/FloatTech/ZeroBot-Plugin/plugin_book_review"`
- [x] 书评[关键字]
- [x] 书评[xxx]
- [x] 随机书评
- **coser** `import _ "github.com/FloatTech/ZeroBot-Plugin/plugin_coser" `
- [x] coser
- **小说** `import _ "github.com/FloatTech/ZeroBot-Plugin/plugin_novel" `
- [x] 小说[xxx]
- **骂人** `import _ "github.com/FloatTech/ZeroBot-Plugin/plugin_curse"`
- [x] 骂他[@xxx]|骂他[qq号]
- **笑话** `import _ "github.com/FloatTech/ZeroBot-Plugin/plugin_funny"`
- [x] 讲个笑话[@xxx]|讲个笑话[qq号]
- **TODO...**
## 使用方法

View File

@@ -9,7 +9,7 @@ var enmap = make(map[string]*zero.Engine)
// Register 注册插件控制器
func Register(service string, o *Options) *zero.Engine {
engine := zero.New()
engine.UsePreHandler(newctrl(service, o).Handler())
engine.UsePreHandler(newctrl(service, o).Handler)
enmap[service] = engine
return engine
}

View File

@@ -2,6 +2,9 @@
package control
import (
"crypto/md5"
"encoding/binary"
"fmt"
"os"
"strconv"
"strings"
@@ -11,6 +14,7 @@ import (
zero "github.com/wdvxdr1123/ZeroBot"
"github.com/wdvxdr1123/ZeroBot/extension"
"github.com/wdvxdr1123/ZeroBot/message"
"github.com/wdvxdr1123/ZeroBot/utils/helper"
"github.com/FloatTech/ZeroBot-Plugin/utils/sql"
)
@@ -47,6 +51,10 @@ func newctrl(service string, o *Options) *Control {
if err != nil {
panic(err)
}
err = db.Create(service+"ban", &ban{})
if err != nil {
panic(err)
}
return m
}
@@ -125,6 +133,78 @@ func (m *Control) IsEnabledIn(gid int64) bool {
return !m.options.DisableOnDefault
}
// Ban 禁止某人在某群使用本插件
func (m *Control) Ban(uid, gid int64) {
var err error
var digest [16]byte
logrus.Debugln("[control] Ban recv gid =", gid, "uid =", uid)
if gid != 0 { // 特定群
digest = md5.Sum(helper.StringToBytes(fmt.Sprintf("%d_%d", uid, gid)))
m.RLock()
err = db.Insert(m.service+"ban", &ban{ID: int64(binary.LittleEndian.Uint64(digest[:8])), UserID: uid, GroupID: gid})
m.RUnlock()
if err == nil {
logrus.Debugf("[control] plugin %s is banned in grp %d for usr %d.", m.service, gid, uid)
return
}
}
// 所有群
digest = md5.Sum(helper.StringToBytes(fmt.Sprintf("%d_all", uid)))
m.RLock()
err = db.Insert(m.service+"ban", &ban{ID: int64(binary.LittleEndian.Uint64(digest[:8])), UserID: uid, GroupID: 0})
m.RUnlock()
if err == nil {
logrus.Debugf("[control] plugin %s is banned in all grp for usr %d.", m.service, uid)
}
}
// Permit 允许某人在某群使用本插件
func (m *Control) Permit(uid, gid int64) {
var digest [16]byte
logrus.Debugln("[control] Permit recv gid =", gid, "uid =", uid)
if gid != 0 { // 特定群
digest = md5.Sum(helper.StringToBytes(fmt.Sprintf("%d_%d", uid, gid)))
m.RLock()
_ = db.Del(m.service+"ban", "WHERE id = "+strconv.FormatInt(int64(binary.LittleEndian.Uint64(digest[:8])), 10))
m.RUnlock()
logrus.Debugf("[control] plugin %s is permitted in grp %d for usr %d.", m.service, gid, uid)
return
}
// 所有群
digest = md5.Sum(helper.StringToBytes(fmt.Sprintf("%d_all", uid)))
m.RLock()
_ = db.Del(m.service+"ban", "WHERE id = "+strconv.FormatInt(int64(binary.LittleEndian.Uint64(digest[:8])), 10))
m.RUnlock()
logrus.Debugf("[control] plugin %s is permitted in all grp for usr %d.", m.service, uid)
}
// IsBannedIn 某人是否在某群被 ban
func (m *Control) IsBannedIn(uid, gid int64) bool {
var b ban
var err error
var digest [16]byte
logrus.Debugln("[control] IsBannedIn recv gid =", gid, "uid =", uid)
if gid != 0 {
digest = md5.Sum(helper.StringToBytes(fmt.Sprintf("%d_%d", uid, gid)))
m.RLock()
err = db.Find(m.service+"ban", &b, "WHERE id = "+strconv.FormatInt(int64(binary.LittleEndian.Uint64(digest[:8])), 10))
m.RUnlock()
if err == nil && gid == b.GroupID && uid == b.UserID {
logrus.Debugf("[control] plugin %s is banned in grp %d for usr %d.", m.service, b.GroupID, b.UserID)
return true
}
}
digest = md5.Sum(helper.StringToBytes(fmt.Sprintf("%d_all", uid)))
m.RLock()
err = db.Find(m.service+"ban", &b, "WHERE id = "+strconv.FormatInt(int64(binary.LittleEndian.Uint64(digest[:8])), 10))
m.RUnlock()
if err == nil && b.GroupID == 0 && uid == b.UserID {
logrus.Debugf("[control] plugin %s is banned in all grp for usr %d.", m.service, b.UserID)
return true
}
return false
}
// GetData 获取某个群的 63 字节配置信息
func (m *Control) GetData(gid int64) int64 {
var c grpcfg
@@ -173,21 +253,19 @@ func (m *Control) SetData(groupID int64, data int64) error {
}
// Handler 返回 预处理器
func (m *Control) Handler() zero.Rule {
return func(ctx *zero.Ctx) bool {
ctx.State["manager"] = m
grp := ctx.Event.GroupID
if grp == 0 {
// 个人用户
grp = -ctx.Event.UserID
}
logrus.Debugln("[control] handler get gid =", grp)
return m.IsEnabledIn(grp)
func (m *Control) Handler(ctx *zero.Ctx) bool {
ctx.State["manager"] = m
grp := ctx.Event.GroupID
if grp == 0 {
// 个人用户
return m.IsEnabledIn(-ctx.Event.UserID)
}
logrus.Debugln("[control] handler get gid =", grp)
return m.IsEnabledIn(grp) && !m.IsBannedIn(ctx.Event.UserID, grp)
}
// Lookup returns a Manager by the service name, if
// not exist, it will returns nil.
// not exist, it will return nil.
func Lookup(service string) (*Control, bool) {
mu.RLock()
m, ok := managers[service]
@@ -276,6 +354,47 @@ func init() {
ctx.SendChain(message.Text("已还原服务的默认启用状态: " + model.Args))
})
zero.OnCommandGroup([]string{
"禁止", "ban", "允许", "permit",
"全局禁止", "banall", "全局允许", "permitall",
}, zero.OnlyGroup, zero.AdminPermission).Handle(func(ctx *zero.Ctx) {
model := extension.CommandModel{}
_ = ctx.Parse(&model)
args := strings.Split(model.Args, " ")
if len(args) >= 2 {
service, ok := Lookup(args[0])
if !ok {
ctx.SendChain(message.Text("没有找到指定服务!"))
return
}
grp := ctx.Event.GroupID
if strings.Contains(model.Command, "全局") || strings.Contains(model.Command, "all") {
grp = 0
}
msg := "**" + args[0] + "报告**"
if strings.Contains(model.Command, "允许") || strings.Contains(model.Command, "permit") {
for _, usr := range args[1:] {
uid, err := strconv.ParseInt(usr, 10, 64)
if err == nil {
service.Permit(uid, grp)
msg += "\n+ 已允许" + usr
}
}
} else {
for _, usr := range args[1:] {
uid, err := strconv.ParseInt(usr, 10, 64)
if err == nil {
service.Ban(uid, grp)
msg += "\n- 已禁止" + usr
}
}
}
ctx.SendChain(message.Text(msg))
return
}
ctx.SendChain(message.Text("参数错误!"))
})
zero.OnCommandGroup([]string{"用法", "usage"}, userOrGrpAdmin).
Handle(func(ctx *zero.Ctx) {
model := extension.CommandModel{}

View File

@@ -6,6 +6,12 @@ type grpcfg struct {
Disable int64 `db:"disable"` // Disable 默认启用该插件
}
type ban struct {
ID int64 `db:"id"`
UserID int64 `db:"uid"`
GroupID int64 `db:"gid"`
}
// Options holds the optional parameters for the Manager.
type Options struct {
DisableOnDefault bool

View File

@@ -1,7 +1,4 @@
// Package webctrl
/*
* 一个用户webui的包里面包含了webui所需的所有内容
*/
// Package webctrl 包含 webui 所需的所有内容
package webctrl
import (

1607
data/Chat/kimoi.json Normal file

File diff suppressed because it is too large Load Diff

BIN
data/Funny/jokes.db Normal file

Binary file not shown.

4
go.mod
View File

@@ -3,9 +3,10 @@ module github.com/FloatTech/ZeroBot-Plugin
go 1.16
require (
github.com/FloatTech/AnimeAPI v1.1.10
github.com/FloatTech/AnimeAPI v1.1.11
github.com/FloatTech/ZeroBot-Plugin-Gif v0.2.4
github.com/FloatTech/bot-manager v1.0.1-0.20211112011524-85b9895271ed
github.com/antchfx/htmlquery v1.2.3
github.com/corona10/goimagehash v1.0.3
github.com/fogleman/gg v1.3.0
github.com/fumiama/cron v1.3.0
@@ -24,4 +25,5 @@ require (
github.com/tidwall/gjson v1.12.1
github.com/wdvxdr1123/ZeroBot v1.4.1
golang.org/x/image v0.0.0-20211028202545-6944b10bf410
golang.org/x/text v0.3.6
)

4
go.sum
View File

@@ -1,6 +1,6 @@
github.com/FloatTech/AnimeAPI v1.1.9/go.mod h1:CC+vF30UGBlcIUxwFOcXIEHoJ4r7c5x2iLQsnUCVdDI=
github.com/FloatTech/AnimeAPI v1.1.10 h1:fYkv65P1HBukHi3GpzYulGx/xLshEL9635QXALDryf0=
github.com/FloatTech/AnimeAPI v1.1.10/go.mod h1:CC+vF30UGBlcIUxwFOcXIEHoJ4r7c5x2iLQsnUCVdDI=
github.com/FloatTech/AnimeAPI v1.1.11 h1:uuV4v5qweh0mI0E2KMiG5XGt0pKboV/EFAlIfSJxIi8=
github.com/FloatTech/AnimeAPI v1.1.11/go.mod h1:CC+vF30UGBlcIUxwFOcXIEHoJ4r7c5x2iLQsnUCVdDI=
github.com/FloatTech/ZeroBot-Plugin v1.1.5/go.mod h1:kWuUARvU7gs4xLggi8Sy37ja2GRL6k0X6kewe5TiZRs=
github.com/FloatTech/ZeroBot-Plugin-Gif v0.2.4 h1:WW0BmmLLqAg+m6qGkrKbsfSIm91fkj3/udt3R7Myodo=
github.com/FloatTech/ZeroBot-Plugin-Gif v0.2.4/go.mod h1:W7ag6hml1pZTNzRXKU74OMr6rS8awQKSU+o2g7Gj4O0=

View File

@@ -33,11 +33,14 @@ import (
_ "github.com/FloatTech/ZeroBot-Plugin/plugin_book_review" // 哀伤雪刃吧推书记录
_ "github.com/FloatTech/ZeroBot-Plugin/plugin_choose" // 选择困难症帮手
_ "github.com/FloatTech/ZeroBot-Plugin/plugin_coser" // 三次元小姐姐
_ "github.com/FloatTech/ZeroBot-Plugin/plugin_curse" // 骂人
_ "github.com/FloatTech/ZeroBot-Plugin/plugin_fortune" // 运势
_ "github.com/FloatTech/ZeroBot-Plugin/plugin_funny" // 笑话
_ "github.com/FloatTech/ZeroBot-Plugin/plugin_hs" // 炉石
_ "github.com/FloatTech/ZeroBot-Plugin/plugin_minecraft" // MCSManager
_ "github.com/FloatTech/ZeroBot-Plugin/plugin_moyu" // 摸鱼
_ "github.com/FloatTech/ZeroBot-Plugin/plugin_music" // 点歌
_ "github.com/FloatTech/ZeroBot-Plugin/plugin_novel" // 铅笔小说网搜索
_ "github.com/FloatTech/ZeroBot-Plugin/plugin_omikuji" // 浅草寺求签
_ "github.com/FloatTech/ZeroBot-Plugin/plugin_reborn" // 投胎
_ "github.com/FloatTech/ZeroBot-Plugin/plugin_shindan" // 测定

View File

@@ -23,7 +23,7 @@ const (
)
var (
datapath = file.BOT_PATH + "/data/acgimage/"
datapath = file.BOTPATH + "/data/acgimage/"
cacheuri = "file:///" + datapath + "cache"
// r18有一定保护一般不会发出图片
randapi = "&loli=true&r18=true"

View File

@@ -58,7 +58,10 @@ func diskPercent() string {
msg := ""
for _, p := range parts {
diskInfo, _ := disk.Usage(p.Mountpoint)
msg += fmt.Sprintf("\n - %s(%dM) %d%%", p.Mountpoint, diskInfo.Total/1024/1024, uint(math.Round(diskInfo.UsedPercent)))
pc := uint(math.Round(diskInfo.UsedPercent))
if pc > 0 {
msg += fmt.Sprintf("\n - %s(%dM) %d%%", p.Mountpoint, diskInfo.Total/1024/1024, pc)
}
}
return msg
}

View File

@@ -20,9 +20,9 @@ const (
// 服务名
servicename = "atri"
// ATRI 所有命令的优先级
prio = 5
prio = 15
// ATRI 表情的 codechina 镜像
res = "https://codechina.csdn.net/u011570312/ZeroBot-Plugin/-/raw/master/plugin_atri/"
res = "https://gitcode.net/u011570312/ZeroBot-Plugin/-/raw/master/plugin_atri/"
)
func init() { // 插件主体

View File

@@ -1,43 +0,0 @@
package main
import (
"os"
"github.com/FloatTech/ZeroBot-Plugin/utils/sql"
)
type book struct {
Id uint64 `db:"id"`
BookReview string `db:"bookreview"`
}
func main() {
db, err := Open(os.Args[1])
if err != nil {
panic(err)
}
newdb := &sql.Sqlite{DBPath: os.Args[2]}
err = newdb.Create("bookreview", &book{})
if err != nil {
panic(err)
}
rs, err := db.Table("book_review").Select("book_review", "").Rows()
if err != nil {
panic(err)
}
var d string
var i uint64
for rs.Next() {
err := rs.Scan(&d)
if err != nil {
panic(err)
}
i++
err = newdb.Insert("bookreview", &book{i, d})
if err != nil {
panic(err)
}
}
db.Close()
newdb.Close()
}

View File

@@ -1,46 +0,0 @@
package main
import (
"os"
"github.com/jinzhu/gorm"
_ "github.com/logoove/sqlite"
)
type BrDB = gorm.DB
func Initialize(dbpath string) *BrDB {
var err error
if _, err = os.Stat(dbpath); err != nil || os.IsNotExist(err) {
// 生成文件
f, err := os.Create(dbpath)
if err != nil {
return nil
}
defer f.Close()
}
gdb, err := gorm.Open("sqlite3", dbpath)
if err != nil {
panic(err)
}
gdb.AutoMigrate(&BookReview{})
return (*BrDB)(gdb)
}
func Open(dbpath string) (*BrDB, error) {
db, err := gorm.Open("sqlite3", dbpath)
if err != nil {
return nil, err
} else {
return (*BrDB)(db), nil
}
}
type BookReview struct {
gorm.Model
BookReview string `gorm:"column:book_review"`
}
func (BookReview) TableName() string {
return "book_review"
}

View File

@@ -13,16 +13,25 @@ import (
"github.com/FloatTech/ZeroBot-Plugin/control"
)
var poke = rate.NewManager(time.Minute*5, 8) // 戳一戳
const (
dbpath = "data/Chat/"
dbfile = dbpath + "kimoi.json"
prio = 10
)
var engine = control.Register("chat", &control.Options{
DisableOnDefault: false,
Help: "chat\n- [BOT名字]\n- [戳一戳BOT]\n- 空调开\n- 空调关\n- 群温度\n- 设置温度[正整数]",
})
var (
poke = rate.NewManager(time.Minute*5, 8) // 戳一戳
engine = control.Register("chat", &control.Options{
DisableOnDefault: false,
Help: "chat\n- [BOT名字]\n- [戳一戳BOT]\n- 空调开\n- 空调关\n- 群温度\n- 设置温度[正整数]\n- mua|啾咪|摸|上你|傻|裸|贴|老婆|抱|亲|一下|咬|操|123|进去|调教|搓|让|捏|挤|略|呐|原味|胖次|内裤|内衣|衣服|ghs|批|憨批|kkp|咕|骚|喜欢|suki|好き|看|不能|砸了|透|口我|草我|自慰|onani|オナニー|炸了|色图|涩图|告白|对不起|回来|吻|软|壁咚|掰开|女友|是|喵|嗷呜|叫|拜|佬|awsl|臭|香|腿|张开|脚|脸|头发|手|pr|舔|小穴|腰|诶嘿嘿|可爱|扭蛋|鼻|眼|色气|推|床|举|手冲|饿|变|敲|爬|怕|冲|射|不穿|迫害|猫粮|揪尾巴|薄荷|早|晚安|揉|榨|掐|胸|奶子|欧派|嫩|蹭|牵手|握手|拍照|w|睡不着|欧尼酱|哥|爱你|过来|自闭|打不过|么么哒|很懂|膝枕|累了|安慰|洗澡|一起睡觉|一起|多大|姐姐|糖|嗦|牛子|🐂子|🐮子|嫌弃|紧|baka|笨蛋|插|插进来|屁股|翘|翘起来|抬|抬起|爸|傲娇|rua|咕噜咕噜|咕噜|上床|做爱|吃掉|吃|揪|种草莓|种草|掀|妹|病娇|嘻",
})
kimomap = make(kimo, 256)
chatList = make([]string, 0, 256)
)
func init() { // 插件主体
// 被喊名字
engine.OnFullMatch("", zero.OnlyToMe).SetBlock(true).FirstPriority().
engine.OnFullMatch("", zero.OnlyToMe).SetBlock(true).SetPriority(prio).
Handle(func(ctx *zero.Ctx) {
var nickname = zero.BotConfig.NickName[0]
time.Sleep(time.Second * 1)
@@ -36,7 +45,7 @@ func init() { // 插件主体
))
})
// 戳一戳
engine.On("notice/notify/poke", zero.OnlyToMe).SetBlock(false).FirstPriority().
engine.On("notice/notify/poke", zero.OnlyToMe).SetBlock(false).SetPriority(prio).
Handle(func(ctx *zero.Ctx) {
var nickname = zero.BotConfig.NickName[0]
switch {
@@ -55,18 +64,18 @@ func init() { // 插件主体
// 群空调
var AirConditTemp = map[int64]int{}
var AirConditSwitch = map[int64]bool{}
engine.OnFullMatch("空调开").SetBlock(true).FirstPriority().
engine.OnFullMatch("空调开").SetBlock(true).SetPriority(prio).
Handle(func(ctx *zero.Ctx) {
AirConditSwitch[ctx.Event.GroupID] = true
ctx.SendChain(message.Text("❄️哔~"))
})
engine.OnFullMatch("空调关").SetBlock(true).FirstPriority().
engine.OnFullMatch("空调关").SetBlock(true).SetPriority(prio).
Handle(func(ctx *zero.Ctx) {
AirConditSwitch[ctx.Event.GroupID] = false
delete(AirConditTemp, ctx.Event.GroupID)
ctx.SendChain(message.Text("💤哔~"))
})
engine.OnRegex(`设置温度(\d+)`).SetBlock(true).FirstPriority().
engine.OnRegex(`设置温度(\d+)`).SetBlock(true).SetPriority(prio).
Handle(func(ctx *zero.Ctx) {
if _, exist := AirConditTemp[ctx.Event.GroupID]; !exist {
AirConditTemp[ctx.Event.GroupID] = 26
@@ -85,7 +94,7 @@ func init() { // 插件主体
))
}
})
engine.OnFullMatch(`群温度`).SetBlock(true).FirstPriority().
engine.OnFullMatch(`群温度`).SetBlock(true).SetPriority(prio).
Handle(func(ctx *zero.Ctx) {
if _, exist := AirConditTemp[ctx.Event.GroupID]; !exist {
AirConditTemp[ctx.Event.GroupID] = 26
@@ -102,4 +111,13 @@ func init() { // 插件主体
))
}
})
initChatList(func() {
engine.OnFullMatchGroup(chatList, zero.OnlyToMe).SetBlock(true).SetPriority(prio).Handle(
func(ctx *zero.Ctx) {
key := ctx.MessageString()
val := *kimomap[key]
text := val[rand.Intn(len(val))]
ctx.SendChain(message.At(ctx.Event.UserID), message.Text(text))
})
})
}

30
plugin_chat/data.go Normal file
View File

@@ -0,0 +1,30 @@
package chat
import (
"encoding/json"
"os"
"github.com/sirupsen/logrus"
"github.com/FloatTech/ZeroBot-Plugin/utils/file"
"github.com/FloatTech/ZeroBot-Plugin/utils/process"
)
type kimo = map[string]*[]string
func initChatList(postinit func()) {
go func() {
process.SleepAbout1sTo2s()
_ = os.MkdirAll(dbpath, 0755)
data, err := file.GetLazyData(dbfile, true, true)
if err != nil {
panic(err)
}
json.Unmarshal(data, &kimomap)
for k := range kimomap {
chatList = append(chatList, k)
}
logrus.Infoln("[chat]加载", len(chatList), "条kimoi")
postinit()
}()
}

View File

@@ -1,4 +1,5 @@
package plugin_coser
// Package coser images
package coser
import (
"time"

54
plugin_curse/curse.go Normal file
View File

@@ -0,0 +1,54 @@
package curse
import (
"time"
zero "github.com/wdvxdr1123/ZeroBot"
"github.com/wdvxdr1123/ZeroBot/extension/rate"
"github.com/wdvxdr1123/ZeroBot/message"
"github.com/wdvxdr1123/ZeroBot/utils/helper"
"github.com/FloatTech/ZeroBot-Plugin/control"
"github.com/FloatTech/ZeroBot-Plugin/utils/math"
"github.com/FloatTech/ZeroBot-Plugin/utils/web"
)
const (
ua = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.107 Safari/537.36"
curseURL = "https://zuanbot.com/api.php?level=min&lang=zh_cn"
)
var (
engine = control.Register("curse", &control.Options{
DisableOnDefault: false,
Help: "骂人\n" +
"- 骂他[@xxx]|骂他[qq号]\n",
})
limit = rate.NewManager(time.Minute, 20)
)
func init() {
engine.OnPrefix("骂我").SetBlock(true).FirstPriority().Handle(func(ctx *zero.Ctx) {
if !limit.Load(ctx.Event.GroupID).Acquire() {
return
}
data, err := web.ReqWith(curseURL, "GET", "", ua)
if err != nil {
ctx.SendChain(message.Text("ERROR:", err))
return
}
ctx.SendChain(message.At(ctx.Event.UserID), message.Text(helper.BytesToString(data)))
})
engine.OnRegex(`^骂他.*?(\d+)`, zero.OnlyGroup).SetBlock(true).SetPriority(40).
Handle(func(ctx *zero.Ctx) {
if !limit.Load(ctx.Event.GroupID).Acquire() {
return
}
data, err := web.ReqWith(curseURL, "GET", "", ua)
if err != nil {
ctx.SendChain(message.Text("ERROR:", err))
return
}
ctx.SendChain(message.At(math.Str2Int64(ctx.State["regex_matched"].([]string)[1])), message.Text(helper.BytesToString(data)))
})
}

38
plugin_funny/data.go Normal file
View File

@@ -0,0 +1,38 @@
package funny
import (
"os"
"github.com/sirupsen/logrus"
"github.com/FloatTech/ZeroBot-Plugin/utils/file"
"github.com/FloatTech/ZeroBot-Plugin/utils/process"
)
type joke struct {
ID uint32 `db:"id"`
Text string `db:"text"`
}
const (
dbpath = "data/Funny/"
dbfile = dbpath + "jokes.db"
)
// 加载数据库
func init() {
go func() {
process.SleepAbout1sTo2s()
_ = os.MkdirAll(dbpath, 0755)
_, err := file.GetLazyData(dbfile, false, true)
if err != nil {
panic(err)
}
err = db.Create("jokes", &joke{})
if err != nil {
panic(err)
}
c, _ := db.Count("jokes")
logrus.Infoln("[funny]加载", c, "个笑话")
}()
}

33
plugin_funny/data_test.go Normal file
View File

@@ -0,0 +1,33 @@
package funny
import (
"crypto/md5"
"encoding/binary"
"os"
"strings"
"testing"
"github.com/FloatTech/ZeroBot-Plugin/utils/sql"
"github.com/wdvxdr1123/ZeroBot/utils/helper"
)
func TestFillData(t *testing.T) {
data, err := os.ReadFile("laugh.txt")
if err != nil {
t.Fatal(err)
}
db := &sql.Sqlite{DBPath: "jokes.db"}
err = db.Create("jokes", &joke{})
if err != nil {
t.Fatal(err)
}
jokes := strings.Split(helper.BytesToString(data), "\n")
for _, j := range jokes {
s := md5.Sum(helper.StringToBytes(j))
db.Insert("jokes", &joke{ID: binary.LittleEndian.Uint32(s[:4]), Text: j})
}
err = db.Close()
if err != nil {
t.Fatal(err)
}
}

47
plugin_funny/laugh.go Normal file
View File

@@ -0,0 +1,47 @@
package funny
import (
"strconv"
"strings"
"time"
zero "github.com/wdvxdr1123/ZeroBot"
"github.com/wdvxdr1123/ZeroBot/extension/rate"
"github.com/wdvxdr1123/ZeroBot/message"
"github.com/FloatTech/ZeroBot-Plugin/control"
"github.com/FloatTech/ZeroBot-Plugin/utils/sql"
)
var (
engine = control.Register("curse", &control.Options{
DisableOnDefault: false,
Help: "讲个笑话\n" +
"- 讲个笑话[@xxx]|讲个笑话[qq号]\n",
})
limit = rate.NewManager(time.Minute, 20)
db = &sql.Sqlite{DBPath: dbfile}
)
func init() {
engine.OnPrefix("讲个笑话").SetBlock(true).FirstPriority().Handle(func(ctx *zero.Ctx) {
if !limit.Load(ctx.Event.GroupID).Acquire() {
return
}
// 获取名字
name := ctx.State["args"].(string)
if len(ctx.Event.Message) > 1 && ctx.Event.Message[1].Type == "at" {
qq, _ := strconv.ParseInt(ctx.Event.Message[1].Data["qq"], 10, 64)
name = ctx.GetGroupMemberInfo(ctx.Event.GroupID, qq, false).Get("nickname").Str
} else if name == "" {
name = ctx.Event.Sender.NickName
}
var j joke
err := db.Pick("jokes", &j)
if err != nil {
ctx.SendChain(message.Text("ERROR:", err))
return
}
ctx.SendChain(message.Text(strings.ReplaceAll(j.Text, "%name", name)))
})
}

View File

@@ -18,7 +18,7 @@ import (
)
var (
cachedir = file.BOT_PATH + "/data/hs/"
cachedir = file.BOTPATH + "/data/hs/"
reqconf = [...]string{"GET", "https://hs.fbigame.com",
"Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.198 Mobile Safari/537.36"}
)

View File

@@ -74,12 +74,12 @@ func init() { // 插件主体
Handle(func(ctx *zero.Ctx) {
ctx.SetGroupAdmin(
ctx.Event.GroupID,
strToInt(ctx.State["regex_matched"].([]string)[1]), // 被升为管理的人的qq
math.Str2Int64(ctx.State["regex_matched"].([]string)[1]), // 被升为管理的人的qq
true,
)
nickname := ctx.GetGroupMemberInfo( // 被升为管理的人的昵称
ctx.Event.GroupID,
strToInt(ctx.State["regex_matched"].([]string)[1]), // 被升为管理的人的qq
math.Str2Int64(ctx.State["regex_matched"].([]string)[1]), // 被升为管理的人的qq
false,
).Get("nickname").Str
ctx.SendChain(message.Text(nickname + " 升为了管理~"))
@@ -89,12 +89,12 @@ func init() { // 插件主体
Handle(func(ctx *zero.Ctx) {
ctx.SetGroupAdmin(
ctx.Event.GroupID,
strToInt(ctx.State["regex_matched"].([]string)[1]), // 被取消管理的人的qq
math.Str2Int64(ctx.State["regex_matched"].([]string)[1]), // 被取消管理的人的qq
false,
)
nickname := ctx.GetGroupMemberInfo( // 被取消管理的人的昵称
ctx.Event.GroupID,
strToInt(ctx.State["regex_matched"].([]string)[1]), // 被取消管理的人的qq
math.Str2Int64(ctx.State["regex_matched"].([]string)[1]), // 被取消管理的人的qq
false,
).Get("nickname").Str
ctx.SendChain(message.Text("残念~ " + nickname + " 暂时失去了管理员的资格"))
@@ -104,12 +104,12 @@ func init() { // 插件主体
Handle(func(ctx *zero.Ctx) {
ctx.SetGroupKick(
ctx.Event.GroupID,
strToInt(ctx.State["regex_matched"].([]string)[1]), // 被踢出群聊的人的qq
math.Str2Int64(ctx.State["regex_matched"].([]string)[1]), // 被踢出群聊的人的qq
false,
)
nickname := ctx.GetGroupMemberInfo( // 被踢出群聊的人的昵称
ctx.Event.GroupID,
strToInt(ctx.State["regex_matched"].([]string)[1]), // 被踢出群聊的人的qq
math.Str2Int64(ctx.State["regex_matched"].([]string)[1]), // 被踢出群聊的人的qq
false,
).Get("nickname").Str
ctx.SendChain(message.Text("残念~ " + nickname + " 被放逐"))
@@ -118,7 +118,7 @@ func init() { // 插件主体
engine.OnRegex(`^退出群聊.*?(\d+)`, zero.OnlyToMe, zero.SuperUserPermission).SetBlock(true).SetPriority(40).
Handle(func(ctx *zero.Ctx) {
ctx.SetGroupLeave(
strToInt(ctx.State["regex_matched"].([]string)[1]), // 要退出的群的群号
math.Str2Int64(ctx.State["regex_matched"].([]string)[1]), // 要退出的群的群号
true,
)
})
@@ -143,7 +143,7 @@ func init() { // 插件主体
// 禁言
engine.OnRegex(`^禁言.*?(\d+).*?\s(\d+)(.*)`, zero.OnlyGroup, zero.AdminPermission).SetBlock(true).SetPriority(40).
Handle(func(ctx *zero.Ctx) {
duration := strToInt(ctx.State["regex_matched"].([]string)[2])
duration := math.Str2Int64(ctx.State["regex_matched"].([]string)[2])
switch ctx.State["regex_matched"].([]string)[3] {
case "分钟":
//
@@ -159,7 +159,7 @@ func init() { // 插件主体
}
ctx.SetGroupBan(
ctx.Event.GroupID,
strToInt(ctx.State["regex_matched"].([]string)[1]), // 要禁言的人的qq
math.Str2Int64(ctx.State["regex_matched"].([]string)[1]), // 要禁言的人的qq
duration*60, // 要禁言的时间(分钟)
)
ctx.SendChain(message.Text("小黑屋收留成功~"))
@@ -169,7 +169,7 @@ func init() { // 插件主体
Handle(func(ctx *zero.Ctx) {
ctx.SetGroupBan(
ctx.Event.GroupID,
strToInt(ctx.State["regex_matched"].([]string)[1]), // 要解除禁言的人的qq
math.Str2Int64(ctx.State["regex_matched"].([]string)[1]), // 要解除禁言的人的qq
0,
)
ctx.SendChain(message.Text("小黑屋释放成功~"))
@@ -177,7 +177,7 @@ func init() { // 插件主体
// 自闭禁言
engine.OnRegex(`^(我要自闭|禅定).*?(\d+)(.*)`, zero.OnlyGroup).SetBlock(true).SetPriority(40).
Handle(func(ctx *zero.Ctx) {
duration := strToInt(ctx.State["regex_matched"].([]string)[2])
duration := math.Str2Int64(ctx.State["regex_matched"].([]string)[2])
switch ctx.State["regex_matched"].([]string)[3] {
case "分钟", "min", "mins", "m":
break
@@ -203,8 +203,8 @@ func init() { // 插件主体
Handle(func(ctx *zero.Ctx) {
ctx.SetGroupCard(
ctx.Event.GroupID,
strToInt(ctx.State["regex_matched"].([]string)[1]), // 被修改群名片的人
ctx.State["regex_matched"].([]string)[2], // 修改成的群名片
math.Str2Int64(ctx.State["regex_matched"].([]string)[1]), // 被修改群名片的人
ctx.State["regex_matched"].([]string)[2], // 修改成的群名片
)
ctx.SendChain(message.Text("嗯!已经修改了"))
})
@@ -213,8 +213,8 @@ func init() { // 插件主体
Handle(func(ctx *zero.Ctx) {
ctx.SetGroupSpecialTitle(
ctx.Event.GroupID,
strToInt(ctx.State["regex_matched"].([]string)[1]), // 被修改群头衔的人
ctx.State["regex_matched"].([]string)[2], // 修改成的群头衔
math.Str2Int64(ctx.State["regex_matched"].([]string)[1]), // 被修改群头衔的人
ctx.State["regex_matched"].([]string)[2], // 修改成的群头衔
)
ctx.SendChain(message.Text("嗯!已经修改了"))
})
@@ -236,7 +236,7 @@ func init() { // 插件主体
content = strings.ReplaceAll(content, "&#91;", "[")
content = strings.ReplaceAll(content, "&#93;", "]")
ctx.SendGroupMessage(
strToInt(ctx.State["regex_matched"].([]string)[1]), // 需要发送的群
math.Str2Int64(ctx.State["regex_matched"].([]string)[1]), // 需要发送的群
content, // 需要发送的信息
)
ctx.SendChain(message.Text("📧 --> " + ctx.State["regex_matched"].([]string)[1]))
@@ -249,7 +249,7 @@ func init() { // 插件主体
content = strings.ReplaceAll(content, "&#91;", "[")
content = strings.ReplaceAll(content, "&#93;", "]")
ctx.SendPrivateMessage(
strToInt(ctx.State["regex_matched"].([]string)[1]), // 需要发送的人的qq
math.Str2Int64(ctx.State["regex_matched"].([]string)[1]), // 需要发送的人的qq
content, // 需要发送的信息
)
ctx.SendChain(message.Text("📧 --> " + ctx.State["regex_matched"].([]string)[1]))
@@ -493,8 +493,8 @@ func init() { // 插件主体
ctx.Send(cmd)
})
// 根据 gist 自动同意加群
// 加群请在github新建一个gist其文件名为本群群号的字符串的md5内容为一行是当前unix时间戳。
// 然后请将您的用户名和gist哈希按照username/gisthash的格式填写到回答即可。
// 加群请在github新建一个gist其文件名为本群群号的字符串的md5(小写)内容为一行是当前unix时间戳(10分钟内有效)
// 然后请将您的用户名和gist哈希(小写)按照username/gisthash的格式填写到回答即可。
engine.OnRequest().SetBlock(false).FirstPriority().Handle(func(ctx *zero.Ctx) {
/*if ctx.Event.RequestType == "friend" {
ctx.SetFriendAddRequest(ctx.Event.Flag, true, "")
@@ -505,6 +505,10 @@ func init() { // 插件主体
// gist 内容是当前 uinx 时间戳,在 10 分钟内视为有效
ans := ctx.Event.Comment[strings.Index(ctx.Event.Comment, "答案:")+len("答案:"):]
divi := strings.Index(ans, "/")
if divi <= 0 {
ctx.SetGroupAddRequest(ctx.Event.Flag, "add", false, "格式错误!")
return
}
ghun := ans[:divi]
hash := ans[divi+1:]
logrus.Infoln("[manager]收到加群申请, 用户:", ghun, ", hash:", hash)
@@ -517,8 +521,3 @@ func init() { // 插件主体
}
})
}
func strToInt(str string) int64 {
val, _ := strconv.ParseInt(str, 10, 64)
return val
}

View File

@@ -22,7 +22,7 @@ import (
const base = "data/nwife"
var baseuri = "file:///" + file.BOT_PATH + "/" + base
var baseuri = "file:///" + file.BOTPATH + "/" + base
func init() {
err := os.MkdirAll(base, 0755)

186
plugin_novel/qianbi.go Normal file
View File

@@ -0,0 +1,186 @@
// Package novel 铅笔小说搜索插件
package novel
import (
"fmt"
"io/ioutil"
"net/http"
"net/http/cookiejar"
"net/url"
"regexp"
"strings"
"time"
"github.com/antchfx/htmlquery"
log "github.com/sirupsen/logrus"
zero "github.com/wdvxdr1123/ZeroBot"
"github.com/wdvxdr1123/ZeroBot/extension/rate"
"github.com/wdvxdr1123/ZeroBot/message"
"github.com/wdvxdr1123/ZeroBot/utils/helper"
"github.com/FloatTech/ZeroBot-Plugin/control"
ub "github.com/FloatTech/ZeroBot-Plugin/utils/binary"
)
const (
websiteURL = "https://www.23qb.net"
websiteTitle = "铅笔小说"
errorTitle = "出现错误!"
username = "zerobot"
password = "123456"
submit = "%26%23160%3B%B5%C7%26%23160%3B%26%23160%3B%C2%BC%26%23160%3B"
ua = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36"
loginURL = websiteURL + "/login.php?do=submit&jumpurl=https%3A%2F%2Fwww.23qb.net%2F"
searchURL = websiteURL + "/saerch.php"
idReg = `/(\d+)/`
)
var (
gCurCookieJar *cookiejar.Jar
engine = control.Register("novel", &control.Options{
DisableOnDefault: false,
Help: "铅笔小说网搜索\n- 小说[xxx]",
})
limit = rate.NewManager(time.Minute, 5)
)
func init() {
engine.OnRegex("^小说([\u4E00-\u9FA5A-Za-z0-9]{1,25})$").SetBlock(true).
Handle(func(ctx *zero.Ctx) {
if !limit.Load(ctx.Event.GroupID).Acquire() {
ctx.SendChain(message.Text("请稍后重试0x0..."))
return
}
ctx.SendChain(message.Text("少女祈祷中......"))
login(username, password)
searchKey := ctx.State["regex_matched"].([]string)[1]
searchHtml := search(searchKey)
var m message.Message
doc, err := htmlquery.Parse(strings.NewReader(searchHtml))
if err != nil {
log.Errorln("[novel]", err)
}
htmlTitle := htmlquery.InnerText(htmlquery.FindOne(doc, "/html/head/title"))
if htmlTitle == websiteTitle {
list, err := htmlquery.QueryAll(doc, "//dl[@id='nr']")
if err != nil {
log.Errorln("[novel]", err)
}
if len(list) != 0 {
for _, v := range list {
bookName := htmlquery.InnerText(htmlquery.FindOne(v, "/dd[1]/h3/a[1]"))
category := htmlquery.InnerText(htmlquery.FindOne(v, "/dt/span[1]"))
author := htmlquery.InnerText(htmlquery.FindOne(v, "/dd[2]/span[1]"))
status := htmlquery.InnerText(htmlquery.FindOne(v, "/dd[2]/span[2]"))
wordNumbers := htmlquery.InnerText(htmlquery.FindOne(v, "/dd[2]/span[3]"))
description := htmlquery.InnerText(htmlquery.FindOne(v, "/dd[3]"))
updateTime := htmlquery.InnerText(htmlquery.FindOne(v, "/dd[1]/h3/span[1]"))
latestChapter := htmlquery.InnerText(htmlquery.FindOne(v, "/dd[4]/a[1]"))
reg := regexp.MustCompile(idReg)
id := reg.FindStringSubmatch(htmlquery.SelectAttr(htmlquery.FindOne(v, "/dt/a[1]"), "href"))[1]
webpageURL := websiteURL + "/book/" + id + "/"
downloadURL := websiteURL + "/modules/article/txtarticle.php?id=" + id
text := fmt.Sprintf("书名:%s\n类型:%s\n作者:%s\n状态:%s\n字数:%s\n简介:%s\n更新时间:%s\n最新章节:%s\n网页链接:%s\n下载地址:%s\n", bookName, category, author, status, wordNumbers, description, updateTime, latestChapter, webpageURL, downloadURL)
m = append(m,
message.CustomNode(
zero.BotConfig.NickName[0],
ctx.Event.SelfID,
text),
)
}
if id := ctx.SendGroupForwardMessage(
ctx.Event.GroupID,
m).Get("message_id").Int(); id == 0 {
ctx.SendChain(message.Text("ERROR: 可能被风控了"))
}
} else {
text := htmlquery.InnerText(htmlquery.FindOne(doc, "//div[@id='tipss']"))
text = strings.Replace(text, " ", "", -1)
text = strings.Replace(text, "本站", websiteURL, -1)
ctx.SendChain(message.Text(text))
}
} else if htmlTitle == errorTitle {
ctx.SendChain(message.Text(errorTitle))
text := htmlquery.InnerText(htmlquery.FindOne(doc, "//div[@style='text-align: center;padding:10px']"))
text = strings.Replace(text, " ", "", -1)
ctx.SendChain(message.Text(text))
} else {
bookName := htmlquery.SelectAttr(htmlquery.FindOne(doc, "//meta[@property='og:novel:book_name']"), "content")
category := htmlquery.SelectAttr(htmlquery.FindOne(doc, "//meta[@property='og:novel:category']"), "content")
author := htmlquery.SelectAttr(htmlquery.FindOne(doc, "//meta[@property='og:novel:author']"), "content")
status := htmlquery.SelectAttr(htmlquery.FindOne(doc, "//meta[@property='og:novel:status']"), "content")
description := htmlquery.InnerText(htmlquery.FindOne(doc, "//div[@id='bookintro']/p"))
updateTime := htmlquery.SelectAttr(htmlquery.FindOne(doc, "//meta[@property='og:novel:update_time']"), "content")
latestChapter := htmlquery.SelectAttr(htmlquery.FindOne(doc, "//meta[@property='og:novel:latest_chapter_name']"), "content")
reg := regexp.MustCompile(idReg)
id := reg.FindStringSubmatch(htmlquery.SelectAttr(htmlquery.FindOne(doc, "//meta[@property='og:novel:read_url']"), "content"))[1]
webpageURL := websiteURL + "/book/" + id + "/"
downloadURL := websiteURL + "/modules/article/txtarticle.php?id=" + id
text := fmt.Sprintf("书名:%s\n类型:%s\n作者:%s\n状态:%s\n简介:%s\n更新时间:%s\n最新章节:%s\n网页链接:%s\n下载地址:%s\n", bookName, category, author, status, description, updateTime, latestChapter, webpageURL, downloadURL)
ctx.SendChain(message.Text(text))
}
})
}
func login(username, password string) {
gCurCookieJar, _ = cookiejar.New(nil)
client := &http.Client{
Jar: gCurCookieJar,
}
usernameData, err := ub.UTF82GBK(helper.StringToBytes(username))
if err != nil {
log.Errorln("[novel]", err)
}
usernameGbk := helper.BytesToString(usernameData)
passwordData, err := ub.UTF82GBK(helper.StringToBytes(password))
if err != nil {
log.Errorln("[novel]", err)
}
passwordGbk := helper.BytesToString(passwordData)
loginReq, err := http.NewRequest("POST", loginURL, strings.NewReader(fmt.Sprintf("username=%s&password=%s&usecookie=315360000&action=login&submit=%s", url.QueryEscape(usernameGbk), url.QueryEscape(passwordGbk), submit)))
if err != nil {
log.Errorln("[novel]", err)
}
loginReq.Header.Set("Content-Type", "application/x-www-form-urlencoded")
loginReq.Header.Set("User-Agent", ua)
loginResp, err := client.Do(loginReq)
if err != nil {
log.Errorln("[novel]", err)
}
defer loginResp.Body.Close()
}
func search(searchKey string) (searchHtml string) {
searchKeyData, err := ub.UTF82GBK(helper.StringToBytes(searchKey))
if err != nil {
log.Errorln("[novel]", err)
}
searchKeyGbk := helper.BytesToString(searchKeyData)
client := &http.Client{
Jar: gCurCookieJar,
}
searchReq, err := http.NewRequest("POST", searchURL, strings.NewReader(fmt.Sprintf("searchkey=%s&searchtype=all", url.QueryEscape(searchKeyGbk))))
if err != nil {
log.Errorln("[novel]", err)
}
searchReq.Header.Set("Content-Type", "application/x-www-form-urlencoded")
searchReq.Header.Set("User-Agent", ua)
searchResp, err := client.Do(searchReq)
if err != nil {
log.Errorln("[novel]", err)
}
defer searchResp.Body.Close()
searchData, err := ioutil.ReadAll(searchResp.Body)
if err != nil {
log.Errorf("[novel] get response for url=%s got error=%s\n", searchURL, err.Error())
}
searchData, err = ub.GBK2UTF8(searchData)
if err != nil {
log.Errorln("[novel]", err)
}
searchHtml = helper.BytesToString(searchData)
return searchHtml
}

View File

@@ -16,7 +16,7 @@ import (
)
const (
bed = "https://codechina.csdn.net/u011570312/senso-ji-omikuji/-/raw/main/%d_%d.jpg"
bed = "https://gitcode.net/u011570312/senso-ji-omikuji/-/raw/main/%d_%d.jpg"
)
var (

View File

@@ -97,15 +97,17 @@ type dataQYK struct {
Content string `json:"content"`
}
const (
qykURL = "http://api.qingyunke.com/api.php"
key = "free"
appid = "0"
)
// 青云客取消息
func getMessage(msg string) (string, error) {
qykUrl := "http://api.qingyunke.com/api.php"
key := "free"
appid := "0"
qykUrl = fmt.Sprintf(qykUrl+"?key=%s&appid=%s&msg=%s", key, appid, url.QueryEscape(msg))
u := fmt.Sprintf(qykURL+"?key=%s&appid=%s&msg=%s", key, appid, url.QueryEscape(msg))
client := &http.Client{}
req, err := http.NewRequest("GET", qykUrl, nil)
req, err := http.NewRequest("GET", u, nil)
if err != nil {
return "", err
}

View File

@@ -19,7 +19,7 @@ import (
)
var (
datapath = file.BOT_PATH + "/data/saucenao/"
datapath = file.BOTPATH + "/data/saucenao/"
)
func init() { // 插件主体

View File

@@ -67,17 +67,17 @@ var (
)
func init() { // 插件主体
engine := control.Register("setutime", &control.Options{
DisableOnDefault: false,
Help: "涩图\n" +
"- 来份[涩图/二次元/风景/车万]\n" +
"- 添加[涩图/二次元/风景/车万][P站图片ID]\n" +
"- 删除[涩图/二次元/风景/车万][P站图片ID]\n" +
"- >setu status",
})
go func() {
process.SleepAbout1sTo2s()
pool = newPools()
engine := control.Register("setutime", &control.Options{
DisableOnDefault: false,
Help: "涩图\n" +
"- 来份[涩图/二次元/风景/车万]\n" +
"- 添加[涩图/二次元/风景/车万][P站图片ID]\n" +
"- 删除[涩图/二次元/风景/车万][P站图片ID]\n" +
"- >setu status",
})
engine.OnRegex(`^来份(.*)$`, rule.FirstValueInList(pool.List)).SetBlock(true).SetPriority(20).
Handle(func(ctx *zero.Ctx) {
if !limit.Load(ctx.Event.UserID).Acquire() {
@@ -217,7 +217,7 @@ func (p *imgpool) pop(imgtype string) (illust *pixiv.Illust) {
func file(i *pixiv.Illust) string {
filename := fmt.Sprint(i.Pid)
filepath := fileutil.BOT_PATH + `/` + pool.Path + filename
filepath := fileutil.BOTPATH + `/` + pool.Path + filename
if _, err := os.Stat(filepath + ".jpg"); err == nil || os.IsExist(err) {
return `file:///` + filepath + ".jpg"
}

View File

@@ -1,4 +1,4 @@
package plugin_sleep_manage
package sleepmanage
import (
"os"
@@ -12,11 +12,10 @@ import (
func init() {
go func() {
defer func() {
//recover() //可以打印panic的错误信息
if err := recover(); err != nil { //产生了panic异常
if err := recover(); err != nil {
log.Println(err)
}
}() //别忘了(), 调用此匿名函数
}()
process.SleepAbout1sTo2s()
_ = os.MkdirAll(dbpath, 0755)
model.Initialize(dbfile)

View File

@@ -1,3 +1,4 @@
// Package model 睡眠管理数据库
package model
import (

View File

@@ -1,4 +1,5 @@
package plugin_sleep_manage
// Package sleepmanage 睡眠管理
package sleepmanage
import (
"fmt"

View File

@@ -3,5 +3,5 @@ go env -w GOPROXY=https://goproxy.cn,direct
go env -w GO111MODULE=auto
go mod tidy
::go build -ldflags="-s -w" -o ZeroBot-Plugin.exe
go run main.go
go run main.go main_win.go
pause

29
utils/binary/encode.go Normal file
View File

@@ -0,0 +1,29 @@
package binary
import (
"bytes"
"io/ioutil"
"golang.org/x/text/encoding/simplifiedchinese"
"golang.org/x/text/transform"
)
// GBK2UTF8 GBK 转 UTF-8
func GBK2UTF8(s []byte) ([]byte, error) {
reader := transform.NewReader(bytes.NewReader(s), simplifiedchinese.GBK.NewDecoder())
d, e := ioutil.ReadAll(reader)
if e != nil {
return nil, e
}
return d, nil
}
// UTF82GBK UTF-8 转 GBK
func UTF82GBK(s []byte) ([]byte, error) {
reader := transform.NewReader(bytes.NewReader(s), simplifiedchinese.GBK.NewEncoder())
d, e := ioutil.ReadAll(reader)
if e != nil {
return nil, e
}
return d, nil
}

View File

@@ -5,6 +5,7 @@ package file
import "os"
// Pwd 获取当前路径
func Pwd() (path string) {
path, _ = os.Getwd()
return

View File

@@ -8,6 +8,7 @@ import (
"strings"
)
// Pwd 获取当前路径的正斜杠表示
func Pwd() string {
path, _ := os.Getwd()
return strings.ReplaceAll(path, "\\", "/")

View File

@@ -2,7 +2,8 @@ package file
import "os"
var BOT_PATH = Pwd()
// BOTPATH BOT当前路径
var BOTPATH = Pwd()
// IsExist 文件/路径存在
func IsExist(path string) bool {
@@ -10,7 +11,7 @@ func IsExist(path string) bool {
return err == nil || os.IsExist(err)
}
// IsExist 文件/路径不存在
// IsNotExist 文件/路径不存在
func IsNotExist(path string) bool {
_, err := os.Stat(path)
return err != nil && os.IsNotExist(err)

View File

@@ -15,7 +15,7 @@ import (
)
const (
dataurl = "https://codechina.csdn.net/u011570312/ZeroBot-Plugin/-/raw/master/"
dataurl = "https://gitcode.net/u011570312/ZeroBot-Plugin/-/raw/master/"
)
var (
@@ -38,7 +38,7 @@ func GetLazyData(path string, isReturnDataBytes, isDataMustEqual bool) ([]byte,
} else {
ms, err = registry.Get(path)
if err != nil || len(ms) != 16 {
logrus.Errorln("[file]获取md5失败请自行确保下载文件 %s 的正确性:", path, err)
logrus.Errorln("[file]获取md5失败请自行确保下载文件", path, "的正确性:", err)
} else {
filemd5 = (*[16]byte)(*(*unsafe.Pointer)(unsafe.Pointer(&ms)))
logrus.Infoln("[file]从验证服务器获得文件md5:", hex.EncodeToString(filemd5[:]))
@@ -82,7 +82,7 @@ func GetLazyData(path string, isReturnDataBytes, isDataMustEqual bool) ([]byte,
if err != nil {
return nil, err
}
if len(data) <= 0 {
if len(data) == 0 {
return nil, errors.New("read body len <= 0")
}
if filemd5 != nil {

8
utils/math/conv.go Normal file
View File

@@ -0,0 +1,8 @@
package math
import "strconv"
func Str2Int64(str string) int64 {
val, _ := strconv.ParseInt(str, 10, 64)
return val
}

View File

@@ -1,3 +1,4 @@
// Package process 流程控制相关
package process
import (
@@ -5,6 +6,7 @@ import (
"time"
)
// SleepAbout1sTo2s 随机阻塞等待 1 ~ 2s
func SleepAbout1sTo2s() {
time.Sleep(time.Second + time.Millisecond*time.Duration(rand.Intn(1000)))
}

View File

@@ -1,3 +1,4 @@
// Package rule zb 规则扩展
package rule
import zero "github.com/wdvxdr1123/ZeroBot"

View File

@@ -366,10 +366,10 @@ func (db *Sqlite) Count(table string) (num int, err error) {
return num, rows.Err()
}
if rows.Next() {
rows.Scan(&num)
err = rows.Scan(&num)
}
rows.Close()
return num, nil
return num, err
}
// tags 反射 返回结构体对象的 tag 数组

View File

@@ -1,3 +1,4 @@
// Package web 网络处理相关
package web
import (
@@ -6,6 +7,7 @@ import (
"net/http"
)
// ReqWith 使用自定义请求头获取数据
func ReqWith(url string, method string, referer string, ua string) (data []byte, err error) {
client := &http.Client{}
// 提交请求
@@ -25,6 +27,7 @@ func ReqWith(url string, method string, referer string, ua string) (data []byte,
return
}
// GetData 获取数据
func GetData(url string) (data []byte, err error) {
var response *http.Response
response, err = http.Get(url)