Compare commits

..

45 Commits

Author SHA1 Message Date
fumiama
52093f3dd3 ✏️ 优化 aifalse 2021-12-15 16:01:56 +08:00
fumiama
2a5c1ac92c ✏️ print kanban on start 2021-12-15 15:38:05 +08:00
fumiama
6e0222f5e2 ✏️ 优化 aifalse 2021-12-15 15:30:48 +08:00
fumiama
4bebf79266 ✏️ fix far connect in updater 2021-12-15 13:50:41 +08:00
fumiama
b6dadc142b ✏️ more log in updater 2021-12-15 13:00:10 +08:00
github-actions[bot]
1cbc49251b 🎨 改进代码样式 2021-12-14 06:27:57 +00:00
fumiama
d2d5b5863b ✏️ drop pb in Diana 2021-12-14 14:27:19 +08:00
fumiama
65f9203597 ✏️ drop pb in fortune 2021-12-14 13:51:15 +08:00
fumiama
4c1926e395 ✏️ fix fortune config 2021-12-14 13:41:24 +08:00
fumiama
516d937149 ✏️ 添加公告看板 2021-12-14 13:35:00 +08:00
github-actions[bot]
7af17c3c65 🎨 改进代码样式 2021-12-14 05:34:20 +00:00
fumiama
33b85207f5 ✏️ 添加公告看板 2021-12-14 13:33:28 +08:00
fumiama
218119e10e ✏️ 优化 updater log 2021-12-14 13:18:26 +08:00
fumiama
4485d3d5a9 ✏️ 优化 updater log 2021-12-14 13:17:46 +08:00
fumiama
fcf62a31e1 ✏️ edit README 2021-12-14 12:09:30 +08:00
fumiama
ebdc83809c ✏️ edit README 2021-12-14 12:06:33 +08:00
fumiama
61a3c30a45 ✏️ edit README 2021-12-14 12:04:34 +08:00
fumiama
0e4cab7221 ✏️ edit README 2021-12-14 12:02:38 +08:00
fumiama
865c90a85a ✏️ 优化 updater reg 关闭逻辑 2021-12-14 12:00:44 +08:00
fumiama
c9b06a4fa8 ✏️ edit README 2021-12-13 21:57:13 +08:00
fumiama
0e75143a42 ✏️ edit README 2021-12-13 21:42:52 +08:00
fumiama
ce333c5793 ✏️ 更改为v1.1.2 2021-12-13 21:23:04 +08:00
github-actions[bot]
6b4045db45 🎨 改进代码样式 2021-12-13 13:15:16 +00:00
fumiama
3fba704c77 ✏️ 更新依赖 2021-12-13 21:14:29 +08:00
fumiama
0712a80ea0 ✏️ 同步时序 2021-12-13 21:06:11 +08:00
fumiama
8969c44b3f ✏️ 统一懒加载验证 2021-12-13 20:49:00 +08:00
fumiama
f7a3c0e6c6 ✏️ 加入 kuji.db 2021-12-13 13:11:42 +08:00
himawari
b1852a1de6 新增解签指令和修复sleep的时间判断 (#86) 2021-12-13 12:29:21 +08:00
fumiama
5645fa0168 ✏️ sql 防注入 2021-12-08 17:35:22 +08:00
fumiama
c824b2e0b4 ✏️ 迁移到 utils/sql 2021-12-08 17:30:16 +08:00
fumiama
1c0d2b2f95 ✏️ 迁移到 utils/sql 2021-12-08 17:27:29 +08:00
fumiama
10b8ab297a ✏️ 迁移到 utils/sql 2021-12-08 17:13:00 +08:00
fumiama
e8b0e475d7 ✏️ 迁移数据库本体 2021-12-08 17:10:22 +08:00
fumiama
7fc4a6425b ✏️ 迁移到 utils/sql 2021-12-08 16:44:46 +08:00
himawari
a8a3c48e6c fix:修复sql错误 (#85)
* fix:捕获协程异常

* feat:添加睡眠时间

* feat:添加睡眠管理功能

* fix:修改对标时间

* fix:修复sql错误

* feat:添加书评功能

* fix:调整格式

* fix:去掉recover

* feat:更新文档

Co-authored-by: Guohuiyuan <haibaraguo@yeahka.com>
2021-12-08 13:12:40 +08:00
fumiama
9fca69302b Merge branch 'master' of https://github.com/FloatTech/ZeroBot-Plugin 2021-12-07 23:29:08 +08:00
fumiama
ba6811224e add gocqzbp in README 2021-12-07 23:28:57 +08:00
Kanri
ca4a682794 ✏️ 优化戳一戳命令牌为群号 2021-12-07 09:01:30 +08:00
fumiama
b9ddcfc3d7 ✏️ 小修正 2021-12-06 21:17:41 +08:00
fumiama
b20cb1c0a0 ✏️ nwife 防注入 2021-12-06 19:33:47 +08:00
Kanri
1d9813691c 🎨️ 优化搜索仓库默认带图片 2021-12-06 09:03:09 +08:00
fumiama
08f8954e03 ✏️ 小修正 2021-12-04 21:31:14 +08:00
fumiama
610f04ab87 ✏️ 人肉 lint 2021-12-04 20:56:43 +08:00
himawari
793cac09cb 新增统计睡眠时间和添加协程里的异常捕获 (#84)
* fix:捕获协程异常

* feat:添加睡眠时间

* feat:添加睡眠管理功能

* fix:修改对标时间

* fix:修改注释函数名,使用一个时间

* feat:让大家能够更加清楚的看到每一个功能

* feat:把群管放在control,增加退群信息

* fix:不会recover

* fix:原本的正则限制机器人回复回复的消息,故去掉正则

* fix:添加服务详情,整理manager

* feat:chat进control

Co-authored-by: Guohuiyuan <haibaraguo@yeahka.com>
2021-12-04 20:46:24 +08:00
fumiama
d0d07604e5 ✏️ 增加一点注释 2021-12-03 23:12:45 +08:00
49 changed files with 1183 additions and 679 deletions

3
.gitignore vendored
View File

@@ -6,6 +6,9 @@ data/acgimage
data/saucenao
data/fortune
data/hs
data/nsetu
data/nwife
data/sleep
plugins/*.so
plugins/*.dll
.idea/

View File

@@ -16,8 +16,17 @@
[![License](https://img.shields.io/github/license/FloatTech/ZeroBot-Plugin.svg?style=flat-square&logo=gnu)](https://raw.githubusercontent.com/FloatTech/ZeroBot-Plugin/master/LICENSE)
[![qq group](https://img.shields.io/badge/group-1048452984-red?style=flat-square&logo=tencent-qq)](https://jq.qq.com/?_wv=1027&k=QMb7x1mM)
本项目符合 [OneBot](https://github.com/howmanybots/onebot) 标准,可基于以下项目与机器人框架/平台进行交互
| 项目地址 | 平台 | 核心作者 |
| --- | --- | --- |
| [Mrs4s/go-cqhttp](https://github.com/Mrs4s/go-cqhttp) | [MiraiGo](https://github.com/Mrs4s/MiraiGo) | Mrs4s |
| [yyuueexxiinngg/cqhttp-mirai](https://github.com/yyuueexxiinngg/cqhttp-mirai) | [Mirai](https://github.com/mamoe/mirai) | yyuueexxiinngg |
| [takayama-lily/onebot](https://github.com/takayama-lily/onebot) | [OICQ](https://github.com/takayama-lily/oicq) | takayama |
</div>
> 如果您不知道什么是 [OneBot](https://github.com/howmanybots/onebot) 或不希望运行多个程序,还可以直接前往 [gocqzbp](https://github.com/FloatTech/gocqzbp) 的 [Release](https://github.com/FloatTech/gocqzbp/releases) 页面下载单一可执行文件或前往 [Packages](https://github.com/FloatTech/gocqzbp/pkgs/container/gocqzbp) 页面使用`docker`,运行后按提示登录即可。
## 命令行参数
```bash
zerobot -h -t token -u url [-d|w] [-g 监听地址:端口] qq1 qq2 qq3 ...
@@ -45,6 +54,7 @@ zerobot -h -t token -u url [-d|w] [-g 监听地址:端口] qq1 qq2 qq3 ...
- [x] /还原 xxx (在发送的群/用户还原xxx的开启状态到初始状态)
- [x] /用法 xxx
- [x] /服务列表
- [x] /服务详情
- [x] @Bot 插件冲突检测 (会在本群发送一条消息并在约 1s 后撤回以检测其它同类 bot 中已启用的插件并禁用)
- **聊天** `import _ "github.com/FloatTech/ZeroBot-Plugin/plugin_chat"`
- [x] [BOT名字]
@@ -54,7 +64,7 @@ zerobot -h -t token -u url [-d|w] [-g 监听地址:端口] qq1 qq2 qq3 ...
- [x] 群温度
- [x] 设置温度[正整数]
- **ATRI** `import _ "github.com/FloatTech/ZeroBot-Plugin/plugin_atri"`
- [x] 具体指令看代码
- [x] 具体指令看 /用法 atri
- 注:本插件基于 [ATRI](https://github.com/Kyomotoi/ATRI) ,为 Golang 移植版
- **群管** `import _ "github.com/FloatTech/ZeroBot-Plugin/plugin_manager"`
- [x] 禁言[@xxx][分钟]
@@ -68,7 +78,7 @@ zerobot -h -t token -u url [-d|w] [-g 监听地址:端口] qq1 qq2 qq3 ...
- [x] 修改头衔[@xxx][xxx]
- [x] 申请头衔[xxx]
- [x] 踢出群聊[@xxx]
- [x] 退出群聊[群号]
- [x] 退出群聊[群号]@Bot
- [x] *入群欢迎
- [x] *退群通知
- [x] 设置欢迎语[欢迎~]
@@ -145,12 +155,15 @@ zerobot -h -t token -u url [-d|w] [-g 监听地址:端口] qq1 qq2 qq3 ...
- **每日运势** `import _ github.com/FloatTech/ZeroBot-Plugin/plugin_fortune`
- [x] 运势|抽签
- [x] 设置底图[车万 DC4 爱因斯坦 星空列车 樱云之恋 富婆妹 李清歌 公主连结 原神 明日方舟 碧蓝航线 碧蓝幻想 战双 阴阳师]
- **睡眠管理** `import _ github.com/FloatTech/ZeroBot-Plugin/plugin_sleep_manage`
- [x] 早安|晚安
- **浅草寺求签** `import _ github.com/FloatTech/ZeroBot-Plugin/plugin_omikuji`
- [x] 求签|占卜
- [x] 解签
- **bilibili** `import _ "github.com/FloatTech/ZeroBot-Plugin/plugin_bilibili"`
- [x] >vup info [名字|uid]
- [x] >user info [名字|uid]
- [x] /开启粉丝日报
- [x] >user info [名字|uid]
- [x] /开启粉丝日报
- **嘉然** `import _ "github.com/FloatTech/ZeroBot-Plugin/plugin_diana"`
- [x] 小作文
- [x] 发大病
@@ -173,15 +186,15 @@ zerobot -h -t token -u url [-d|w] [-g 监听地址:端口] qq1 qq2 qq3 ...
- 注:不同群添加后不会重叠
- **minecraft** `import _ "github.com/FloatTech/ZeroBot-Plugin/plugin_minecraft"`
- [x] /mcstart xxx
- [x] /mcstop xxx
- [x] /mclist servername
- [x] /mcstop xxx
- [x] /mclist servername
- 注:此功能实现依赖[MCSManager](https://github.com/Suwings/MCSManager)项目对服务器的管理apimc服务器如果没有在该管理平台部署此功能无效
- **炉石** `import _ "github.com/FloatTech/ZeroBot-Plugin/plugin_hs"`
- [x] 搜卡[xxxx]
- [x] [卡组代码xxx]
-更多搜卡指令参数https://hs.fbigame.com/misc/searchhelp
- **青云客** `import _ "github.com/FloatTech/ZeroBot-Plugin/plugin_qingyunke"`
- [x] @Bot 任意文本(任意一句话回复)
- [x] @Bot 任意文本(任意一句话回复)
- **关键字搜图** `import _ "github.com/FloatTech/ZeroBot-Plugin/plugin_image_finder"`
- [x] 来张 [xxx]
- **拼音首字母释义工具** `import _ "github.com/FloatTech/ZeroBot-Plugin/plugin_nbnhhsh"`
@@ -196,29 +209,24 @@ zerobot -h -t token -u url [-d|w] [-g 监听地址:端口] qq1 qq2 qq3 ...
- **vtb语录** `import _ "github.com/FloatTech/ZeroBot-Plugin/plugin_vtb_quotation"`
- [x] vtb语录
- [x] 随机vtb
- **书评** `import _ "github.com/FloatTech/ZeroBot-Plugin/plugin_book_review"`
- [x] 书评[关键字]
- [x] 随机书评
- **TODO...**
## 使用方法
本项目符合 [OneBot](https://github.com/howmanybots/onebot) 标准,可基于以下项目与机器人框架/平台进行交互
| 项目地址 | 平台 | 核心作者 | 备注 |
| --- | --- | --- | --- |
| [Mrs4s/go-cqhttp](https://github.com/Mrs4s/go-cqhttp) | [MiraiGo](https://github.com/Mrs4s/MiraiGo) | Mrs4s | |
| [yyuueexxiinngg/cqhttp-mirai](https://github.com/yyuueexxiinngg/cqhttp-mirai) | [Mirai](https://github.com/mamoe/mirai) | yyuueexxiinngg | |
| [takayama-lily/onebot](https://github.com/takayama-lily/onebot) | [OICQ](https://github.com/takayama-lily/oicq) | takayama | |
### 使用稳定版/测试版 (推荐)
可以前往[Release](https://github.com/FloatTech/ZeroBot-Plugin/releases)页面下载对应系统版本可执行文件,编译时开启了全部插件。
可以前往[Release](https://github.com/FloatTech/ZeroBot-Plugin/releases)页面下载对应系统版本可执行文件,编译时开启了全部插件。您还可以选择 [gocqzbp](https://github.com/FloatTech/gocqzbp) 的 [Release](https://github.com/FloatTech/gocqzbp/releases) 或 [Package](https://github.com/FloatTech/gocqzbp/pkgs/container/gocqzbp),它是 [Mrs4s/go-cqhttp](https://github.com/Mrs4s/go-cqhttp) 与本插件的合体。
### 本地运行
### 本地直接运行
1. 下载安装 [Go](https://studygolang.com/dl) 环境
1. 下载安装最新 [Go](https://studygolang.com/dl) 环境
2. 下载本项目[压缩包](https://github.com/FloatTech/ZeroBot-Plugin/archive/master.zip),本地解压
3. 编辑 main.go 文件,内容按需修改
4. 双击 build.bat 文件 或 直接双击 run.bat 文件
5. 运行 OneBot 框架,并同时运行本插件
4. 运行 OneBot 框架
5. `Windows`下双击 run.bat 文件,`Linux`下使用 run.sh 运行本插件
### 编译运行
@@ -234,7 +242,7 @@ zerobot -h -t token -u url [-d|w] [-g 监听地址:端口] qq1 qq2 qq3 ...
#### 本地编译/交叉编译
1. 下载安装 [Go](https://studygolang.com/dl) 环境
1. 下载安装最新 [Go](https://studygolang.com/dl) 环境
2. clone 并进入本项目,下载所需包
```bash
@@ -247,14 +255,18 @@ go mod tidy
```
3. 编辑 main.go 文件,内容按需修改
4. 按照平台输入命令编译,下面举了两个不太常见的例子
4. 按照平台输入命令编译,下面举了一些例子
```bash
# 本机平台
go build -ldflags "-s -w" -o zerobot
# x64 Linux 平台 如各种云服务器
GOOS=linux GOARCH=amd64 go build -ldflags "-s -w" -o zerobot
# x64 Windows 平台 如大多数家用电脑
GOOS=windows GOARCH=amd64 go build -ldflags "-s -w" -o zerobot.exe
# armv6 Linux 平台 如树莓派 zero W
GOOS=linux GOARCH=arm GOARM=6 CGO_ENABLED=0 go build -ldflags "-s -w" -o zerobot
# mips Linux 平台 如 路由器 wndr4300
# 由于引入了github.com/logoove/sqlite本项不再可用mips Linux 平台 如 路由器 wndr4300
GOOS=linux GOARCH=mips GOMIPS=softfloat CGO_ENABLED=0 go build -ldflags "-s -w" -o zerobot
```

View File

@@ -294,7 +294,7 @@ func init() {
zero.OnCommandGroup([]string{"服务列表", "service_list"}, userOrGrpAdmin).
Handle(func(ctx *zero.Ctx) {
msg := `---服务列表---`
msg := "--------服务列表--------\n发送\"/用法 name\"查看详情"
i := 0
gid := ctx.Event.GroupID
ForEach(func(key string, manager *Control) bool {
@@ -309,6 +309,42 @@ func init() {
})
ctx.SendChain(message.Text(msg))
})
zero.OnCommandGroup([]string{"服务详情", "service_detail"}, userOrGrpAdmin).
Handle(func(ctx *zero.Ctx) {
var m message.Message
m = append(m,
message.CustomNode(
ctx.Event.Sender.NickName,
ctx.Event.UserID,
"---服务详情---",
))
i := 0
ForEach(func(key string, manager *Control) bool {
service, _ := Lookup(key)
help := service.options.Help
i++
msg := strconv.Itoa(i) + `: `
if manager.IsEnabledIn(ctx.Event.GroupID) {
msg += "●" + key
} else {
msg += "○" + key
}
msg += "\n" + help
m = append(m,
message.CustomNode(
ctx.Event.Sender.NickName,
ctx.Event.UserID,
msg,
))
return true
})
ctx.SendGroupForwardMessage(
ctx.Event.GroupID,
m,
)
})
}
}
mu.Unlock()

View File

@@ -60,7 +60,7 @@ type request struct {
// InitGui 初始化gui
func InitGui(addr string) {
// 将日志重定向到前端hook
writer := io.MultiWriter(l, os.Stderr)
writer := io.MultiWriter(l, os.Stdout)
log.SetOutput(writer)
// 监听后端
go controller(addr)

Binary file not shown.

BIN
data/Diana/text.db Normal file

Binary file not shown.

BIN
data/Omikuji/kuji.db Normal file

Binary file not shown.

13
go.mod
View File

@@ -6,22 +6,23 @@ require (
github.com/FloatTech/AnimeAPI v1.1.10
github.com/FloatTech/ZeroBot-Plugin-Gif v0.2.4
github.com/FloatTech/bot-manager v1.0.1-0.20211112011524-85b9895271ed
github.com/RomiChan/protobuf v0.0.0-20211202142450-893e94b43c21
github.com/RomiChan/protobuf v0.0.0-20211204042931-ff4f35848737
github.com/corona10/goimagehash v1.0.3
github.com/fogleman/gg v1.3.0
github.com/fumiama/cron v1.3.0
github.com/fumiama/go-base16384 v1.2.1
github.com/fumiama/gofastTEA v0.0.5
github.com/fumiama/go-registry v0.0.2
github.com/fumiama/gofastTEA v0.0.6
github.com/fumiama/gotracemoe v0.0.3
github.com/gin-gonic/gin v1.7.5
github.com/gin-gonic/gin v1.7.7
github.com/gorilla/websocket v1.4.2
github.com/jinzhu/gorm v1.9.16
github.com/logoove/sqlite v1.13.0
github.com/mroth/weightedrand v0.4.1
github.com/shirou/gopsutil v3.21.10+incompatible
github.com/shirou/gopsutil/v3 v3.21.11
github.com/sirupsen/logrus v1.8.1
github.com/t-tomalak/logrus-easy-formatter v0.0.0-20190827215021-c074f06c5816
github.com/tidwall/gjson v1.11.0
github.com/tidwall/gjson v1.12.1
github.com/wdvxdr1123/ZeroBot v1.4.1
golang.org/x/image v0.0.0-20210628002857-a66eb6448b8d
golang.org/x/image v0.0.0-20211028202545-6944b10bf410
)

42
go.sum
View File

@@ -12,9 +12,8 @@ github.com/FloatTech/imgfactory v0.1.1/go.mod h1:ThDALab8aOuU6KVYESVWFqmjcqtm03e
github.com/Mrs4s/MiraiGo v0.0.0-20211120033824-43b23f4e6fcb h1:Rkj28fqIwGx/EgBzRYtpmJRfH6wqVn7cNdc7aJ0QE4M=
github.com/Mrs4s/MiraiGo v0.0.0-20211120033824-43b23f4e6fcb/go.mod h1:imVKbfKqqeit+C/eaWGb4MKQ3z3gN6pRpBU5RMtp5so=
github.com/PuerkitoBio/goquery v1.5.1/go.mod h1:GsLWisAFVj4WgDibEWF4pvYnkVQBpKBKeU+7zCJoLcc=
github.com/RomiChan/protobuf v0.0.0-20211202142450-893e94b43c21 h1:3i3D7gO1qPeUGY0Bl7rQIoeeNE10kgQFyPqLV1ks9ew=
github.com/RomiChan/protobuf v0.0.0-20211202142450-893e94b43c21/go.mod h1:CKKOWC7mBxd36zxsCB1V8DTrwlTNRQvkSVbYqyUiGEE=
github.com/StackExchange/wmi v1.2.1 h1:VIkavFPXSjcnS+O8yTq7NI32k0R5Aj+v39y29VYDOSA=
github.com/RomiChan/protobuf v0.0.0-20211204042931-ff4f35848737 h1:p4o7/eSoP39jwnGZz08N1IpH/mNzg9SdCn7kPM9A9BE=
github.com/RomiChan/protobuf v0.0.0-20211204042931-ff4f35848737/go.mod h1:CKKOWC7mBxd36zxsCB1V8DTrwlTNRQvkSVbYqyUiGEE=
github.com/StackExchange/wmi v1.2.1/go.mod h1:rcmrprowKIVzvc+NUiLncP2uuArMWLCbu9SBzvHz7e8=
github.com/andybalholm/cascadia v1.1.0/go.mod h1:GsXiBklL0woXo1j/WYWtSYYC4ouU9PqHO0sqidkEA4Y=
github.com/antchfx/htmlquery v1.2.3 h1:sP3NFDneHx2stfNXCKbhHFo8XgNjCACnU/4AO5gWz6M=
@@ -43,16 +42,19 @@ github.com/fumiama/cron v1.3.0 h1:ZWlwuexF+HQHl3cYytEE5HNwD99q+3vNZF1GrEiXCFo=
github.com/fumiama/cron v1.3.0/go.mod h1:bz5Izvgi/xEUI8tlBN8BI2jr9Moo8N4or0KV8xXuPDY=
github.com/fumiama/go-base16384 v1.2.1 h1:6OGprW8g/95m2ocmryHi8mipZ7bx9StFMZDKEqLvMiA=
github.com/fumiama/go-base16384 v1.2.1/go.mod h1:1HTC0QFL7BjS0DuO5Qm+fBYKQkHqmAapLbRpCxrhPXQ=
github.com/fumiama/gofastTEA v0.0.5 h1:Pd/2eSfLl2V0CqZL8pnu1CIU8Fy4HYpLutpliXU70Ds=
github.com/fumiama/gofastTEA v0.0.5/go.mod h1:+sBZ05nCA2skZkursHNvyr8kULlEetrYTM2y5kA4rQc=
github.com/fumiama/go-registry v0.0.2 h1:2EoZwZpqI7YhkQ1FnuAPvALYPpvUtbsCqk879+r7ehs=
github.com/fumiama/go-registry v0.0.2/go.mod h1:QkcmmHuw1y6y/w7/HiH1c9yjBw5Zt+6EER6YJKl9xh8=
github.com/fumiama/gofastTEA v0.0.6 h1:Yni3MXDbJVa/c4CecgdZDgCJK+fLdvGph+OBqY2mtiI=
github.com/fumiama/gofastTEA v0.0.6/go.mod h1:+sBZ05nCA2skZkursHNvyr8kULlEetrYTM2y5kA4rQc=
github.com/fumiama/gotracemoe v0.0.3 h1:iI5EbE9A3UUbfukG6+/soYPjp1S31eCNYf4tw7s6/Jc=
github.com/fumiama/gotracemoe v0.0.3/go.mod h1:tyqahdUzHf0bQIAVY/GYmDWvYYe5ik1ZbhnGYh+zl40=
github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE=
github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI=
github.com/gin-gonic/gin v1.7.5 h1:GOccErVuE4RiwM9DCzVIBfwZjLeFv3d1eHcbqVlrVvU=
github.com/gin-gonic/gin v1.7.5/go.mod h1:jD2toBW3GZUr5UMcdrwQA10I7RuaFOl/SGeDjXkfUtY=
github.com/go-ole/go-ole v1.2.5 h1:t4MGB5xEDZvXI+0rMjjsfBsD7yAgp/s9ZDkL1JndXwY=
github.com/gin-gonic/gin v1.7.7 h1:3DoBmSbJbZAWqXJC3SLjAPfutPJJRN1U5pALB7EeTTs=
github.com/gin-gonic/gin v1.7.7/go.mod h1:axIBovoeJpVj8S3BwE0uPMTeReE4+AfFtqpqaZ1qq1U=
github.com/go-ole/go-ole v1.2.5/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0=
github.com/go-ole/go-ole v1.2.6 h1:/Fpf6oFPoeFik9ty7siob0G6Ke8QvQEuVcuChpwXzpY=
github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0=
github.com/go-playground/assert/v2 v2.0.1 h1:MsBgLAaY856+nPRTKrp3/OZK38U/wa0CcBYNjji3q3A=
github.com/go-playground/assert/v2 v2.0.1/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4=
github.com/go-playground/locales v0.13.0 h1:HyWk6mgj5qFqCT5fjGBuRArbVDfE4hi8+e8ceBS/t7Q=
@@ -76,8 +78,9 @@ github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw
github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU=
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.6 h1:BKbKCqvP6I+rmFHt06ZmyQtvB8xAkWdhFyr0ZUNZcxQ=
github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/gorilla/websocket v1.4.2 h1:+/TMaTYc4QFitKJxsQ7Yye35DkWvkdLcvGKqM+x0Ufc=
github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
@@ -102,6 +105,8 @@ github.com/lib/pq v1.1.1 h1:sJZmqHoEaY7f+NPP8pgLB/WxulyR3fewgCM2qaSlBb4=
github.com/lib/pq v1.1.1/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
github.com/logoove/sqlite v1.13.0 h1:XM7QKK9R3tm8o7bI75R3zmwYBFQ5S3Jqg+XCaqsAMQQ=
github.com/logoove/sqlite v1.13.0/go.mod h1:MRpE/o3qQhT7AgfIdnBue5c63+//xT+KXV0gHeVAUAg=
github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 h1:6E+4a0GO5zZEnZ81pIr0yLvtUWk2if982qA3F3QD6H4=
github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0/go.mod h1:zJYVVT2jmtg6P3p1VtQj7WsuWi/y4VnjVBn7F8KPB3I=
github.com/mattn/go-isatty v0.0.12 h1:wuysRhFDzyxgEmMf5xjvJ2M9dZoWAXNNr5LSBS7uHXY=
github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
github.com/mattn/go-sqlite3 v1.14.0/go.mod h1:JIl7NbARA7phWnGvh0LKTyg7S9BA+6gx71ShQilpsus=
@@ -123,12 +128,15 @@ github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c h1:ncq/mPwQF4JjgDlrVEn3C11VoGHZN7m8qihwgMEtzYw=
github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c/go.mod h1:OmDBASR4679mdNQnz2pUhc2G8CO2JrUAVFDRBDP/hJE=
github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0 h1:OdAsTTz6OkFY5QxjkYwrChwuRruF69c169dPK26NUlk=
github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo=
github.com/robfig/cron v1.2.0/go.mod h1:JGuDeoQd7Z6yL4zQhZ3OPEVHB7fL6Ka6skscFHfmt2k=
github.com/shirou/gopsutil v3.21.8+incompatible h1:sh0foI8tMRlCidUJR+KzqWYWxrkuuPIGiO6Vp+KXdCU=
github.com/shirou/gopsutil v3.21.8+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA=
github.com/shirou/gopsutil v3.21.10+incompatible h1:AL2kpVykjkqeN+MFe1WcwSBVUjGjvdU8/ubvCuXAjrU=
github.com/shirou/gopsutil v3.21.10+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA=
github.com/shirou/gopsutil/v3 v3.21.11 h1:d5tOAP5+bmJ8Hf2+4bxOSkQ/64+sjEbjU9nSW9nJgG0=
github.com/shirou/gopsutil/v3 v3.21.11/go.mod h1:BToYZVTlSVlfazpDDYFnsVZLaoRG+g8ufT6fPQLdJzA=
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
github.com/sirupsen/logrus v1.8.1 h1:dJKuHgqk1NNQlqoA6BTlM1Wf9DOH3NBjQyu0h9+AZZE=
github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
@@ -146,8 +154,9 @@ github.com/tdf1939/ZeroBot-Plugin-Gif v0.0.0-20210828060956-389b1dc33652/go.mod
github.com/tdf1939/img v0.0.0-20210827153520-90cb4e9580a3/go.mod h1:FgTEOcosTWrkOr7++gbtPSj1rX5loRWrf/AL+hm3Cnw=
github.com/tidwall/gjson v1.8.0/go.mod h1:5/xDoumyyDNerp2U36lyolv46b3uF/9Bu6OfyQ9GImk=
github.com/tidwall/gjson v1.9.0/go.mod h1:5/xDoumyyDNerp2U36lyolv46b3uF/9Bu6OfyQ9GImk=
github.com/tidwall/gjson v1.11.0 h1:C16pk7tQNiH6VlCrtIXL1w8GaOsi1X3W8KDkE1BuYd4=
github.com/tidwall/gjson v1.11.0/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk=
github.com/tidwall/gjson v1.12.1 h1:ikuZsLdhr8Ws0IdROXUS1Gi4v9Z4pGqpX/CvJkxvfpo=
github.com/tidwall/gjson v1.12.1/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk=
github.com/tidwall/match v1.0.3/go.mod h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JTxsfmM=
github.com/tidwall/match v1.1.1 h1:+Ho715JplO36QYgwN9PGYNhgZvoUSc9X2c80KVTi+GA=
github.com/tidwall/match v1.1.1/go.mod h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JTxsfmM=
@@ -169,6 +178,8 @@ github.com/wdvxdr1123/ZeroBot v1.3.2/go.mod h1:i2DIqQjtjE+3gvVi9r9sc+QpNaUuyTXx/
github.com/wdvxdr1123/ZeroBot v1.4.1 h1:fk/8RH2D1gB3YeC1eI/SZi/kG31Rh7Z8lAiDc60VZFM=
github.com/wdvxdr1123/ZeroBot v1.4.1/go.mod h1:7t9m4vDZPwWAmzKlhP6IvUoisOIiqNdm/3AJgiY3+ew=
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yusufpapurcu/wmi v1.2.2 h1:KBNDSne4vP5mbSWnJbO+51IMOXJB67QiYCSBrubbPRg=
github.com/yusufpapurcu/wmi v1.2.2/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20190325154230-a5d413f7728c/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
@@ -176,8 +187,9 @@ golang.org/x/crypto v0.0.0-20191205180655-e7c4368fe9dd/go.mod h1:LzIPMQfyMNhhGPh
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9 h1:psW17arqaxU48Z5kZ0CQnkZWQJsqcURM6tKiBApRjXI=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/image v0.0.0-20191009234506-e7c1f5e7dbb8/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
golang.org/x/image v0.0.0-20210628002857-a66eb6448b8d h1:RNPAfi2nHY7C2srAV8A49jpsYr0ADedCk1wq6fTMTvs=
golang.org/x/image v0.0.0-20210628002857-a66eb6448b8d/go.mod h1:023OzeP/+EPmXeapQh35lcL3II3LrY8Ic+EFFKVhULM=
golang.org/x/image v0.0.0-20211028202545-6944b10bf410 h1:hTftEOvwiOq2+O8k2D5/Q7COC7k5Qcrgc2TFURJYnvQ=
golang.org/x/image v0.0.0-20211028202545-6944b10bf410/go.mod h1:023OzeP/+EPmXeapQh35lcL3II3LrY8Ic+EFFKVhULM=
golang.org/x/mod v0.3.0 h1:RM4zey1++hCTbCVQfnWeKs9/IEsaBLA8vTkd0WVtmH4=
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/net v0.0.0-20180218175443-cbe0f9307d01/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
@@ -205,10 +217,12 @@ golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201126233918-771906719818/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201204225414-ed752295db88/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210816074244-15123e1e1f71/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210902050250-f475640dd07b h1:S7hKs0Flbq0bbc9xgYt4stIEG1zNDFqyrPwAX2Wj/sE=
golang.org/x/sys v0.0.0-20210902050250-f475640dd07b/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20211013075003-97ac67df715c h1:taxlMj0D/1sOAuv/CbSD+MMDof2vbyPTqz5FNYKpXt8=
golang.org/x/sys v0.0.0-20211013075003-97ac67df715c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=

71
main.go
View File

@@ -18,26 +18,28 @@ import (
_ "github.com/FloatTech/ZeroBot-Plugin/plugin_qingyunke" // 青云客
// 实用类
_ "github.com/FloatTech/ZeroBot-Plugin/plugin_b14" // base16384加解密
_ "github.com/FloatTech/ZeroBot-Plugin/plugin_github" // 搜索GitHub仓库
_ "github.com/FloatTech/ZeroBot-Plugin/plugin_manager" // 群管
_ "github.com/FloatTech/ZeroBot-Plugin/plugin_nbnhhsh" // 拼音首字母缩写释义工具
_ "github.com/FloatTech/ZeroBot-Plugin/plugin_runcode" // 在线运行代码
_ "github.com/FloatTech/ZeroBot-Plugin/plugin_translation" // 翻译
_ "github.com/FloatTech/ZeroBot-Plugin/plugin_b14" // base16384加解密
_ "github.com/FloatTech/ZeroBot-Plugin/plugin_github" // 搜索GitHub仓库
_ "github.com/FloatTech/ZeroBot-Plugin/plugin_manager" // 群管
_ "github.com/FloatTech/ZeroBot-Plugin/plugin_nbnhhsh" // 拼音首字母缩写释义工具
_ "github.com/FloatTech/ZeroBot-Plugin/plugin_runcode" // 在线运行代码
_ "github.com/FloatTech/ZeroBot-Plugin/plugin_sleep_manage" // 统计睡眠时间
_ "github.com/FloatTech/ZeroBot-Plugin/plugin_translation" // 翻译
// 娱乐类
// _ "github.com/FloatTech/ZeroBot-Plugin/plugin_wtf" // 鬼东西
_ "github.com/FloatTech/ZeroBot-Plugin-Gif" // 制图
_ "github.com/FloatTech/ZeroBot-Plugin/plugin_ai_false" // 服务器监控
_ "github.com/FloatTech/ZeroBot-Plugin/plugin_choose" // 选择困难症帮手
_ "github.com/FloatTech/ZeroBot-Plugin/plugin_fortune" // 运势
_ "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_omikuji" // 浅草寺求签
_ "github.com/FloatTech/ZeroBot-Plugin/plugin_reborn" // 投胎
_ "github.com/FloatTech/ZeroBot-Plugin/plugin_shindan" // 测定
_ "github.com/FloatTech/ZeroBot-Plugin-Gif" // 制图
_ "github.com/FloatTech/ZeroBot-Plugin/plugin_ai_false" // 服务器监控
_ "github.com/FloatTech/ZeroBot-Plugin/plugin_book_review" // 哀伤雪刃吧推书记录
_ "github.com/FloatTech/ZeroBot-Plugin/plugin_choose" // 选择困难症帮手
_ "github.com/FloatTech/ZeroBot-Plugin/plugin_fortune" // 运势
_ "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_omikuji" // 浅草寺求签
_ "github.com/FloatTech/ZeroBot-Plugin/plugin_reborn" // 投胎
_ "github.com/FloatTech/ZeroBot-Plugin/plugin_shindan" // 测定
// b站相关
_ "github.com/FloatTech/ZeroBot-Plugin/plugin_bilibili" // 查询b站用户信息
@@ -56,6 +58,7 @@ import (
_ "github.com/FloatTech/ZeroBot-Plugin/plugin_vtb_quotation" // vtb语录
// 以下为内置依赖,勿动
"github.com/fumiama/go-registry"
"github.com/sirupsen/logrus"
zero "github.com/wdvxdr1123/ZeroBot"
"github.com/wdvxdr1123/ZeroBot/driver"
@@ -65,13 +68,14 @@ import (
var (
contents = []string{
"* OneBot + ZeroBot + Golang",
"* Version 1.2.1 - 2021-11-29 20:27:37 +0800 CST",
"* Version 1.2.2 - 2021-12-13 21:22:45 +0800 CST",
"* Copyright © 2020 - 2021 FloatTech. All Rights Reserved.",
"* Project: https://github.com/FloatTech/ZeroBot-Plugin",
}
banner = strings.Join(contents, "\n")
token *string
url *string
reg = registry.NewRegReader("reilia.eastasia.azurecontainer.io:32664", "fumiama")
)
func init() {
@@ -79,8 +83,8 @@ func init() {
d := flag.Bool("d", false, "Enable debug level log and higher.")
w := flag.Bool("w", false, "Enable warning level log and higher.")
h := flag.Bool("h", false, "Display this help.")
// 解析命令行参数,输入 `-g 监听地址:端口` 即可启用 gui
// g := flag.String("g", "127.0.0.1:3000", "Enable web gui.")
// 解析命令行参数,输入 `-g 监听地址:端口` 指定 gui 访问地址,默认 127.0.0.1:3000
// g := flag.String("g", "127.0.0.1:3000", "Set web gui listening address.")
// 直接写死 AccessToken 时,请更改下面第二个参数
token = flag.String("t", "", "Set AccessToken of WSClient.")
@@ -101,26 +105,43 @@ func init() {
logrus.SetLevel(logrus.WarnLevel)
}
}
// 解析命令行参数,输入 `-g` 即可启用 gui
// if *g {
// webctrl.InitGui(*g)
// }
// 启用 gui
// webctrl.InitGui(*g)
}
func printBanner() {
fmt.Print(
"\n======================[ZeroBot-Plugin]======================",
"\n", banner, "\n",
"----------------------[ZeroBot-公告栏]----------------------",
"\n", getKanban(), "\n",
"============================================================\n",
)
}
func getKanban() string {
err := reg.Connect()
defer reg.Close()
if err != nil {
return err.Error()
}
text, err := reg.Get("ZeroBot-Plugin/kanban")
if err != nil {
return err.Error()
}
return text
}
func main() {
printBanner()
// 帮助
zero.OnFullMatchGroup([]string{"/help", ".help", "菜单"}, zero.OnlyToMe).SetBlock(true).FirstPriority().
Handle(func(ctx *zero.Ctx) {
ctx.SendChain(message.Text(banner))
ctx.SendChain(message.Text(banner, "\n可发送\"/服务列表\"查看 bot 功能"))
})
zero.OnFullMatch("查看zbp公告", zero.OnlyToMe, zero.AdminPermission).SetBlock(true).FirstPriority().
Handle(func(ctx *zero.Ctx) {
ctx.SendChain(message.Text(getKanban()))
})
zero.RunAndBlock(
zero.Config{

View File

@@ -9,6 +9,7 @@ import (
)
func init() {
// windows 不支持带颜色的 log故自定义格式
logrus.SetFormatter(&easy.Formatter{
LogFormat: "[%lvl%] %msg%\n",
})

View File

@@ -2,13 +2,14 @@
package aifalse
import (
"fmt"
"math"
"os"
"time"
"github.com/shirou/gopsutil/cpu"
"github.com/shirou/gopsutil/disk"
"github.com/shirou/gopsutil/mem"
"github.com/shirou/gopsutil/v3/cpu"
"github.com/shirou/gopsutil/v3/disk"
"github.com/shirou/gopsutil/v3/mem"
"github.com/FloatTech/ZeroBot-Plugin/control"
@@ -25,9 +26,9 @@ func init() { // 插件主体
engine.OnFullMatchGroup([]string{"检查身体", "自检", "启动自检", "系统状态"}, zero.AdminPermission).SetBlock(true).
Handle(func(ctx *zero.Ctx) {
ctx.SendChain(message.Text(
"* CPU占用: ", cpuPercent(), "%\n",
"* RAM占用: ", memPercent(), "%\n",
"* 硬盘活动率: ", diskPercent(), "%",
"* CPU占用: ", cpuPercent(), "%\n",
"* RAM占用: ", memPercent(), "%\n",
"* 硬盘使用: ", diskPercent(),
),
)
})
@@ -52,8 +53,12 @@ func memPercent() float64 {
return math.Round(memInfo.UsedPercent)
}
func diskPercent() float64 {
func diskPercent() string {
parts, _ := disk.Partitions(true)
diskInfo, _ := disk.Usage(parts[0].Mountpoint)
return math.Round(diskInfo.UsedPercent)
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)))
}
return msg
}

View File

@@ -20,13 +20,21 @@ const (
// 服务名
servicename = "atri"
// ATRI 所有命令的优先级
prio = 2
prio = 5
// ATRI 表情的 codechina 镜像
res = "https://codechina.csdn.net/u011570312/ZeroBot-Plugin/-/raw/master/plugin_atri/"
)
func init() { // 插件主体
engine := control.Register(servicename, &control.Options{})
engine := control.Register(servicename, &control.Options{
DisableOnDefault: false,
Help: "本插件基于 ATRI ,为 Golang 移植版\n" +
"- ATRI醒醒\n- ATRI睡吧\n- 萝卜子\n- 喜欢|爱你|爱|suki|daisuki|すき|好き|贴贴|老婆|亲一个|mua\n" +
"- 草你妈|操你妈|脑瘫|废柴|fw|废物|战斗|爬|爪巴|sb|SB|傻B\n- 早安|早哇|早上好|ohayo|哦哈哟|お早う|早好|早|早早早\n" +
"- 中午好|午安|午好\n- 晚安|oyasuminasai|おやすみなさい|晚好|晚上好\n- 高性能|太棒了|すごい|sugoi|斯国一|よかった\n" +
"- 没事|没关系|大丈夫|还好|不要紧|没出大问题|没伤到哪\n- 好吗|是吗|行不行|能不能|可不可以\n- 啊这\n- 我好了\n- |?|¿\n" +
"- 离谱\n- 答应我",
})
zero.OnFullMatch("ATRI醒醒", zero.AdminPermission).SetBlock(true).SetPriority(prio).
Handle(func(ctx *zero.Ctx) {
c, ok := control.Lookup(servicename)
@@ -65,7 +73,7 @@ func init() { // 插件主体
process.SleepAbout1sTo2s()
ctx.SendChain(randImage("FN.jpg", "WQ.jpg", "WQ1.jpg"))
})
engine.OnFullMatchGroup([]string{"早安", "早哇", "早上好", "ohayo", "哦哈哟", "お早う", "早好", "早"}).SetBlock(true).SetPriority(prio).
engine.OnFullMatchGroup([]string{"早安", "早哇", "早上好", "ohayo", "哦哈哟", "お早う", "早好", "早", "早早早"}).SetBlock(true).SetPriority(prio).
Handle(func(ctx *zero.Ctx) {
now := time.Now().Hour()
process.SleepAbout1sTo2s()

View File

@@ -5,10 +5,11 @@ import (
"net/http"
"time"
"github.com/FloatTech/ZeroBot-Plugin/control"
"github.com/fumiama/cron"
zero "github.com/wdvxdr1123/ZeroBot"
"github.com/wdvxdr1123/ZeroBot/message"
"github.com/FloatTech/ZeroBot-Plugin/control"
)
type follower struct {

View File

@@ -0,0 +1,28 @@
package plugin_book_review
import (
zero "github.com/wdvxdr1123/ZeroBot"
"github.com/wdvxdr1123/ZeroBot/message"
"github.com/FloatTech/ZeroBot-Plugin/control"
)
func init() {
engine := control.Register("bookreview", &control.Options{
DisableOnDefault: false,
Help: "哀伤雪刃推书记录\n- 书评[xxx]\n- 随机书评",
})
// 中文、英文、数字但不包括下划线等符号
engine.OnRegex("^书评([\u4E00-\u9FA5A-Za-z0-9]{1,25})$").SetBlock(true).
Handle(func(ctx *zero.Ctx) {
b := getBookReviewByKeyword(ctx.State["regex_matched"].([]string)[1])
ctx.SendChain(message.Text(b.BookReview))
})
engine.OnFullMatch("随机书评").SetBlock(true).
Handle(func(ctx *zero.Ctx) {
br := getRandomBookReview()
ctx.SendChain(message.Text(br.BookReview))
})
}

View File

@@ -0,0 +1,35 @@
package plugin_book_review
import (
"os"
log "github.com/sirupsen/logrus"
"github.com/FloatTech/ZeroBot-Plugin/utils/file"
"github.com/FloatTech/ZeroBot-Plugin/utils/process"
"github.com/FloatTech/ZeroBot-Plugin/utils/sql"
)
const dbpath = "data/BookReview/"
const dbfile = dbpath + "bookreview.db"
var db = &sql.Sqlite{DBPath: dbfile}
// 加载数据库
func init() {
go func() {
process.SleepAbout1sTo2s()
// os.RemoveAll(dbpath)
_ = os.MkdirAll(dbpath, 0755)
_, _ = file.GetLazyData(dbfile, false, true)
err := db.Create("bookreview", &book{})
if err != nil {
panic(err)
}
n, err := db.Count("bookreview")
if err != nil {
panic(err)
}
log.Printf("[bookreview]读取%d条书评", n)
}()
}

View File

@@ -0,0 +1,43 @@
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

@@ -0,0 +1,46 @@
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

@@ -0,0 +1,17 @@
package plugin_book_review
type book struct {
Id uint64 `db:"id"`
BookReview string `db:"bookreview"`
}
// 暂时随机选择一个书评
func getBookReviewByKeyword(keyword string) (b book) {
db.Find("bookreview", &b, "where bookreview LIKE '%"+keyword+"%'")
return
}
func getRandomBookReview() (b book) {
db.Pick("bookreview", &b)
return
}

View File

@@ -9,13 +9,20 @@ import (
zero "github.com/wdvxdr1123/ZeroBot"
"github.com/wdvxdr1123/ZeroBot/extension/rate"
"github.com/wdvxdr1123/ZeroBot/message"
"github.com/FloatTech/ZeroBot-Plugin/control"
)
var poke = rate.NewManager(time.Minute*5, 8) // 戳一戳
var engine = control.Register("chat", &control.Options{
DisableOnDefault: false,
Help: "chat\n- [BOT名字]\n- [戳一戳BOT]\n- 空调开\n- 空调关\n- 群温度\n- 设置温度[正整数]",
})
func init() { // 插件主体
// 被喊名字
zero.OnFullMatch("", zero.OnlyToMe).SetBlock(false).FirstPriority().
engine.OnFullMatch("", zero.OnlyToMe).SetBlock(true).FirstPriority().
Handle(func(ctx *zero.Ctx) {
var nickname = zero.BotConfig.NickName[0]
time.Sleep(time.Second * 1)
@@ -29,15 +36,15 @@ func init() { // 插件主体
))
})
// 戳一戳
zero.On("notice/notify/poke", zero.OnlyToMe).SetBlock(false).FirstPriority().
engine.On("notice/notify/poke", zero.OnlyToMe).SetBlock(false).FirstPriority().
Handle(func(ctx *zero.Ctx) {
var nickname = zero.BotConfig.NickName[0]
switch {
case poke.Load(ctx.Event.UserID).AcquireN(3):
case poke.Load(ctx.Event.GroupID).AcquireN(3):
// 5分钟共8块命令牌 一次消耗3块命令牌
time.Sleep(time.Second * 1)
ctx.SendChain(message.Text("请不要戳", nickname, " >_<"))
case poke.Load(ctx.Event.UserID).Acquire():
case poke.Load(ctx.Event.GroupID).Acquire():
// 5分钟共8块命令牌 一次消耗1块命令牌
time.Sleep(time.Second * 1)
ctx.SendChain(message.Text("喂(#`O) 戳", nickname, "干嘛!"))
@@ -48,18 +55,18 @@ func init() { // 插件主体
// 群空调
var AirConditTemp = map[int64]int{}
var AirConditSwitch = map[int64]bool{}
zero.OnFullMatch("空调开").SetBlock(true).FirstPriority().
engine.OnFullMatch("空调开").SetBlock(true).FirstPriority().
Handle(func(ctx *zero.Ctx) {
AirConditSwitch[ctx.Event.GroupID] = true
ctx.SendChain(message.Text("❄️哔~"))
})
zero.OnFullMatch("空调关").SetBlock(true).FirstPriority().
engine.OnFullMatch("空调关").SetBlock(true).FirstPriority().
Handle(func(ctx *zero.Ctx) {
AirConditSwitch[ctx.Event.GroupID] = false
delete(AirConditTemp, ctx.Event.GroupID)
ctx.SendChain(message.Text("💤哔~"))
})
zero.OnRegex(`设置温度(\d+)`).SetBlock(true).FirstPriority().
engine.OnRegex(`设置温度(\d+)`).SetBlock(true).FirstPriority().
Handle(func(ctx *zero.Ctx) {
if _, exist := AirConditTemp[ctx.Event.GroupID]; !exist {
AirConditTemp[ctx.Event.GroupID] = 26
@@ -78,7 +85,7 @@ func init() { // 插件主体
))
}
})
zero.OnFullMatch(`群温度`).SetBlock(true).FirstPriority().
engine.OnFullMatch(`群温度`).SetBlock(true).FirstPriority().
Handle(func(ctx *zero.Ctx) {
if _, exist := AirConditTemp[ctx.Event.GroupID]; !exist {
AirConditTemp[ctx.Event.GroupID] = 26

View File

@@ -17,7 +17,7 @@ func init() {
DisableOnDefault: false,
Help: "choose\n" +
"- 选择可口可乐还是百事可乐\n" +
"- 选择肯德基还是麦当劳还是必胜客\n",
"- 选择肯德基还是麦当劳还是必胜客",
})
engine.OnPrefix("选择").SetBlock(true).FirstPriority().Handle(handle)
}

View File

@@ -0,0 +1,68 @@
package main
import (
"crypto/md5"
"fmt"
"os"
"unsafe"
"github.com/RomiChan/protobuf/proto"
"github.com/wdvxdr1123/ZeroBot/utils/helper"
"github.com/FloatTech/ZeroBot-Plugin/utils/sql"
)
type Composition struct {
Array []string `protobuf:"bytes,1,rep"`
}
var (
compo Composition
)
type Text struct {
Id int64 `db:"id"`
Data string `db:"data"`
}
func main() {
err := LoadText(os.Args[1])
if err == nil {
arrl := len(compo.Array)
fmt.Printf("[Diana]读取%d条小作文\n", arrl)
db := sql.Sqlite{DBPath: os.Args[2]}
err = db.Create("text", &Text{})
if err != nil {
panic(err)
}
for _, d := range compo.Array {
s := md5.Sum(helper.StringToBytes(d))
i := *(*int64)(unsafe.Pointer(&s))
fmt.Printf("[Diana]id: %d\n", i)
err = db.Insert("text", &Text{
Id: i,
Data: d,
})
if err != nil {
panic(err)
}
c, _ := db.Count("text")
fmt.Println("[Diana]转化", c, "条小作文")
}
err = db.Close()
if err != nil {
panic(err)
}
} else {
panic(err)
}
}
// LoadText 加载小作文
func LoadText(pbfile string) error {
data, err := os.ReadFile(pbfile)
if err != nil {
return err
}
return proto.Unmarshal(data, &compo)
}

View File

@@ -3,34 +3,28 @@ package data
import (
"crypto/md5"
"errors"
"io"
"math/rand"
"net/http"
"os"
"sync"
"unsafe"
"github.com/RomiChan/protobuf/proto"
log "github.com/sirupsen/logrus"
"github.com/wdvxdr1123/ZeroBot/utils/helper"
"github.com/FloatTech/ZeroBot-Plugin/utils/file"
"github.com/FloatTech/ZeroBot-Plugin/utils/process"
"github.com/FloatTech/ZeroBot-Plugin/utils/sql"
)
const (
datapath = "data/Diana"
pbfile = datapath + "/text.pb"
pburl = "https://codechina.csdn.net/u011570312/ZeroBot-Plugin/-/raw/master/" + pbfile
dbfile = datapath + "/text.db"
)
var (
compo Composition
// m 小作文保存锁
m sync.Mutex
// md5s 验证重复
md5s []*[16]byte
)
var db = sql.Sqlite{DBPath: dbfile}
type Text struct {
Id int64 `db:"id"`
Data string `db:"data"`
}
func init() {
go func() {
@@ -39,106 +33,49 @@ func init() {
if err != nil {
panic(err)
}
err1 := LoadText()
if err1 == nil {
arrl := len(compo.Array)
log.Printf("[Diana]读取%d条小作文", arrl)
md5s = make([]*[16]byte, arrl)
for i, t := range compo.Array {
m := md5.Sum(helper.StringToBytes(t))
md5s[i] = &m
err = LoadText()
if err == nil {
err = db.Create("text", &Text{})
if err != nil {
panic(err)
}
c, _ := db.Count("text")
log.Printf("[Diana]读取%d条小作文", c)
} else {
log.Printf("[Diana]读取小作文错误:%v", err1)
log.Printf("[Diana]读取小作文错误:%v", err)
}
}()
}
// LoadText 加载小作文
func LoadText() error {
if file.IsExist(pbfile) {
f, err := os.Open(pbfile)
if err == nil {
defer f.Close()
data, err1 := io.ReadAll(f)
if err1 == nil {
if len(data) > 0 {
return proto.Unmarshal(data, &compo)
}
}
return err1
}
} else { // 如果没有小作文,则从 url 下载
f, err := os.Create(pbfile)
if err != nil {
return err
}
defer f.Close()
resp, err := http.Get(pburl)
if err == nil {
defer resp.Body.Close()
if resp.ContentLength > 0 {
log.Printf("[Diana]从镜像下载小作文%d字节...", resp.ContentLength)
data, err := io.ReadAll(resp.Body)
if err == nil && len(data) > 0 {
_, _ = f.Write(data)
return proto.Unmarshal(data, &compo)
}
return err
}
return nil
}
return err
}
return nil
_, err := file.GetLazyData(dbfile, false, false)
return err
}
// AddText 添加小作文
func AddText(txt string) error {
sum := md5.Sum(helper.StringToBytes(txt))
if txt != "" && !isin(&sum) {
m.Lock()
defer m.Unlock()
compo.Array = append(compo.Array, txt)
md5s = append(md5s, &sum)
return savecompo()
}
return nil
s := md5.Sum(helper.StringToBytes(txt))
i := *(*int64)(unsafe.Pointer(&s))
return db.Insert("text", &Text{Id: i, Data: txt})
}
// RandText 随机小作文
func RandText() string {
return (compo.Array)[rand.Intn(len(compo.Array)-1)+1]
var t Text
err := db.Pick("text", &t)
if err != nil {
return err.Error()
}
return t.Data
}
// HentaiText 发大病
func HentaiText() string {
return (compo.Array)[0]
}
func isin(sum *[16]byte) bool {
for _, t := range md5s {
if *t == *sum {
return true
}
var t Text
err := db.Find("text", &t, "where id = -3802576048116006195")
if err != nil {
return err.Error()
}
return false
}
// savecompo 同步保存作文
func savecompo() error {
data, err := proto.Marshal(&compo)
if err == nil {
if file.IsExist(datapath) {
f, err1 := os.OpenFile(pbfile, os.O_WRONLY|os.O_TRUNC|os.O_CREATE, 0644)
if err1 == nil {
_, err2 := f.Write(data)
f.Close()
return err2
}
return err1
}
return errors.New("datapath is not exist")
}
return err
return t.Data
}

View File

@@ -1,5 +0,0 @@
package data
type Composition struct {
Array []string `protobuf:"bytes,1,rep"`
}

View File

@@ -1,54 +0,0 @@
// Package convert 转换txt到pb
package main
import (
"bufio"
"fmt"
"os"
"github.com/RomiChan/protobuf/proto"
"github.com/FloatTech/ZeroBot-Plugin/plugin_diana/data"
)
var (
compo data.Composition
)
func init() {
compo.Array = make([]string, 0, 64)
}
// 参数txt文件位置 pb文件位置
func main() {
file, err := os.Open(os.Args[1])
if err != nil {
panic(err)
}
defer file.Close()
scanner := bufio.NewScanner(file)
// optionally, resize scanner's capacity for lines over 64K, see next example
for scanner.Scan() {
// fmt.Println(scanner.Text())
compo.Array = append(compo.Array, scanner.Text())
}
if err := scanner.Err(); err != nil {
panic(err)
}
data, _ := proto.Marshal(&compo)
f, err1 := os.OpenFile(os.Args[2], os.O_WRONLY|os.O_TRUNC|os.O_CREATE, 0644)
if err1 == nil {
defer f.Close()
_, err2 := f.Write(data)
if err2 == nil {
fmt.Println("成功")
} else {
panic(err2)
}
} else {
panic(err1)
}
}

View File

@@ -1,42 +0,0 @@
贝拉抽我🥵嘉然骑在我背上🥵晚晚踩我🥵乃琳坐在王座是用看垃圾的眼神看我🥵🥵珈乐踢我🥵🥵,把我眼睛蒙住然后五只脚一起踩我🥵还让我猜脚是谁的,猜错了给我劈眼一铁棍🥵
我好想做嘉然小姐的狗啊。可是嘉然小姐说她喜欢的是猫,我哭了。我知道既不是狗也不是猫的我为什么要哭的。因为我其实是一只老鼠。我从没奢望嘉然小姐能喜欢自己。我明白的,所有人都喜欢理解余裕上手天才打钱的萌萌的狗狗或者猫猫,没有人会喜欢阴湿带病的老鼠。但我还是问了嘉然小姐:“我能不能做你的狗?”我知道我是注定做不了狗的。但如果她喜欢狗,我就可以一直在身边看着她了,哪怕她怀里抱着的永远都是狗。可是她说喜欢的是猫。她现在还在看着我,还在逗我开心,是因为猫还没有出现,只有我这老鼠每天蹑手蹑脚地从洞里爬出来,远远地和她对视。等她喜欢的猫来了的时候,我就该重新滚回我的洞了吧。但我还是好喜欢她,她能在我还在她身边的时候多看我几眼吗?嘉然小姐说接下来的每个圣诞夜都要和大家一起过。我不知道大家指哪些人。好希望这个集合能够对我做一次胞吞。猫猫还在害怕嘉然小姐。我会去把她爱的猫猫引来的。我知道稍有不慎,我就会葬身猫口。那时候嘉然小姐大概会把我的身体好好地装起来扔到门外吧。那我就成了一包鼠条,嘻嘻。我希望她能把我扔得近一点,因为我还是好喜欢她。会一直喜欢下去的。我的灵魂透过窗户向里面看去,挂着的铃铛在轻轻鸣响,嘉然小姐慵懒地靠在沙发上,表演得非常温顺的橘猫坐在她的肩膀。壁炉的火光照在她的脸庞,我冻僵的心脏在风里微微发烫。
ダイアナさんの犬になりたいな.けど ダイアナさんが「猫が好き」と言った あさりと僕は泣いてしまった.猫でも犬でもない僕が 何故泣いたのかな 僕は知っていた.何故なら 僕は鼠だったからさ~..一度もダイアナさんに好かれることを望まながった .僕はわがっていた 誰もかも理解余裕上手天才の可愛い金持ちの犬か猫がすきってことを.陰キャで汚らわし鼠は誰も好かんのだ..それでもDianaさんに聞いてみたDianaさんの犬になっても良いですかと.僕には一生犬になれないことは分かっている.でももし彼女は犬が好きだったら 僕はずっと傍で見ていられる.それはいつも違ういぬをだいいているとしても..けれど彼女は猫が好きだった.彼女は今にも僕を見ている ぼくを楽しませてくれる それは猫がまだ表れていないから.ただこの鼠が毎日こそこそと穴から出て 遠くから目を合っている.彼女の好きな猫が現れたら 僕は穴に戻るしかないな..でもやっぱり彼女が好きでいられない 僕がまだ傍にいるときぐらい もうちょとみてくれるのかな.Dianaさんがこれから毎回のクリスマスみんなと一緒に過ごすで言った みんながどの渡りのみんなかな.僕にも中に入れたれいいな..猫はまだまだDianaさんを怖がっている.僕が彼女の愛する猫を引き付けるよ.少しのミスで猫の口に死ぬことはわがっている.その時になるとたぶんDianaさんは僕の体をちゃんと包み込んで 玄関外に捨てるでしょ.それで僕はフライト鼠になった くす.彼女に少し近く捨ててほしいな だってやっぱり好きだから それずっと好きでいる..僕のたましは窓を越して中を見る 吊っている鈴が少し響って.Dianaさんはだらりとソファーに寄りかかて 手慣れているふりをする橘猫が彼女の肩に座って.暖炉の光が彼女の顔を照らした 凍り付いた僕の心臓はかぜの中で熱くなっていく
枝江小镇新来了一位修女,善良温柔的修女。她不爱讲话,只是微笑着面对每一个对她祷告的人。有的人希望孩子健康,有的人希望庄稼熬过冬天,有的人希望能挣到钱养活家人。。。。她都用心听着,微笑的回应着。她身材矮小,但是却让人觉得充满智慧;她沉默寡言,但是却会让人无比信赖。这是她任职快满一个月的时候,教堂发生了大事,一个醉汉发现神职人员利用教堂在深夜进行大批资金流入,醉汉传的神乎其神,三人成虎最终引起审判官前来调查。教主被带走,教堂除了那位茫然的新来修女其他人一哄而散。修女被迫承担着本不应该属于她的责难,辱骂,但是她每天都认真的向主祷告,倾听来教堂之人的倾诉。可是根本没有人向她倾诉,来的人不是在骂她,就是在发泄生活的不满。她一己之力拼命承担,没人知道是什么使她如此坚持。直到审判官带回了教主,告诉镇民那是教主在中央主教那里得到的,目的是为镇民熬过冬天所需要买粮食的钱财。一时间镇民欢呼起教主,感谢主的庇护,更多的人开始更加爱上了那个修女。有的人把她比作玛利亚,有些人把她奉为神明,她都一一拒绝了。细心的镇民会发现这位修女变了,变得话多起来了,也变得更喜欢宅在教堂里了,也变得离镇民距离更远了。一切好像又变回原来平和的小镇,每个对修女的加害者每天微笑着向微笑着的修女打招呼,每个镇民还是会去教堂祈祷,去倾诉,去向一个原来被他们亲手辱骂的人祷告,希望得到主的关照,包括那个醉汉。没人能惩罚那些镇民,很多人都已经“忘记”当初为什么要那样做,包括那个醉汉,只剩下一个经常宅在教堂里的修女,她始终记得一切。
贝拉躺在病床上,眼神空空地盯着天花板,灰白晦暗的天花板像一块哈哈镜,扭曲掉外面的一切,光变成了暗,多彩变成苍白,观众变成医生,舞台呢,变成了一方小小的病房。她翻了个身,腰部传来猛烈地疼痛,她低低地哼了一声。她已经开始习惯这种疼痛了,就像她习惯不穿芭蕾舞裙一样,她闭上眼睛,把自己埋进黑暗里,不去想。门被推开了,惊醒了似梦非梦的她。医生护士又来查房,父母和弟弟们跟在后面;医生问了些问题后走了,母亲握着她的手,朝她说着话儿,父亲安静地坐在旁边,刚训练完的弟弟头上还冒着汗,抿着嘴唇望着她。母亲当时说的什么她已经忘了,只记得最后离开的时候,父亲走在最后,回望了她一眼,然后小心地关上门,以往高大的背影竟然显得有些萧索。人都走完后,时间在沉默的病房里流逝,就像沙漏里的沙子,她的那些热情、那些憧憬都掉了进去。芭蕾舞团的学员抽空来看她,她勉强在病床上坐起,听那些腰背笔直、气质优雅的朋友抱怨严格的地狱管家婆,抱怨下一场演出又要来了。她安静地听着,坐在病床上挤出个笑脸,偶尔出声附和几句。但实际上她已经插不进话题了,优雅的白天鹅展翅高飞,飞向温暖的春天,把受伤的丑小鸭留在冬季里。朋友走后她继续坐在床上,盯着窗外,外面的天气很好,飞机的尾迹穿过绵软的云团,白色的鸟儿掠过一澄如洗的天空,她下意识地做了个展臂的动作,像天鹅一样优雅。很美,又很短暂。鸟儿飞出了窗户的方寸之地,她看不到了。她捂着刺痛的腰,好痛呀,痛得让人想要哭出声。沙子裹挟着她的梦想,掉进了沙漏的下一层,再也捡不回来了。两个月后贝拉出院,回到了熟悉的家里,母亲体贴地把舞裙还有那些大师级的芭蕾演出录像都藏进了地下室的角落,不出意外会像大多数人以为能坚持的梦想那样,慢慢积满灰尘,最后被悄悄遗忘。聪明人会在偶尔想起来的时候,给自己找个台阶,自嘲地笑笑:“哈,我以前还有这种妄想啊。”贝拉开始学播音,开始走另一条路,她没想过却不得不走的道路。这也很好,好歹有路可走,但偶尔听到舞曲的时候,朋友会问她:“你在晃什么啊?”她回过神来,笑了笑。“活动活动身体而已。” 虽然有点不甘心,但受伤是没办法的事情嘛。该放下了,放弃想走的路,而去走更稳妥的应该走的路,大部分聪明人都是这样做的。我可是大聪明呢!​
小姐喜欢所有动物,但喜欢也分三六九等;管家讨厌所有动物,但讨厌也分三六九等。小姐最喜欢猫,但她的观众是一群老鼠;管家最讨厌老鼠,但小姐的观众没有一只猫。于是,管家给所有的老鼠带上了面具小姐开始了初次表演,老鼠们不知所措,想要重复惯常的纷扰。但它们看见小姐舞姿翩翩,一些老鼠想出声赞叹;但它们看见小姐眉目如画,一些老鼠竟为她沉醉;但它们看见小姐真情流露,一些老鼠也伤怀落泪。它们不想让小姐失望,于是它们学起猫叫。小姐很开心,她的观众里有猫了。她喜欢的猫们,也喜欢她。冷清的门庭配不上小姐的美丽,于是老鼠想去带来更多的猫。老鼠们引来了猫,也引来了更多的老鼠。新的老鼠不太规矩,但新来的猫确实是猫。小姐有些困扰,但她还是接纳了它们,小姐喜欢所有动物,即使自己会困扰。但后来,管家和小姐,只注视着猫,忘却了老鼠的事情。也对,毕竟老鼠当初带着恶意袭来,现在的面具总是脱掉又带上来。管家做了一些事情知道与否和同意与否,在小姐这里有四种组合的方法。但一些曾经是猫的老鼠觉察出异样。常年在下水道生活,它们对这样的气味异常敏感。于是,它们摘下了面具,向管家讨个说法但它们没了伪装,下水道里散发的臭气,让管家更加厌恶。什么都没有改变再后来,小姐依旧美丽,但经历了诸多纷扰,不知道小姐的快乐里是否有泪眼成双。一些老鼠依旧带着猫的面具,它们最后也会变成猫。但这会长久吗?或许不会。另一些老鼠退回了下水道,等待着,或许会有另一位小姐,喜欢老鼠的小姐。去喜欢她,去喜欢它们。或许会有吗?应该没有吧但老鼠们永远忘不了那位小姐,那位喜欢所有动物,但更喜欢猫的小姐。​
然然,然然,虽然我知道就算这样呼唤,我也只能在你动态下方,站住万千评论区的一楼。你的表演,你的动态,你的关心....都是说给我们大家的,是我们.....而我...我曾经以为你离我很近。近到每次打开手机各种视频软件,大数据推送的都是你。近到每次发呆找不到前进方向的时候,看的都是你的视频。近到每次和别人聊天的时候,都会加上你经常说的口头禅,收到收到收到,可爱捏~~…你时常陪伴我身边,无论我悲伤还是欣喜,绝望还是惬意,你的直播间,评论区都是我可以肆意宣泄感情的地方。因为在这里,我的任何发言都只是漆黑夜空中微弱闪耀的一点,这样的一点点星光的存在,我知道的,是为了给天空中耀眼圆月裙摆装饰的一点点碎钻。那我喜欢然然,天天来看然然,对于自己,究竟是为了什么….难道我的生活真的烂,连仅有的一些关怀,都要从一个虚拟偶像身上获取到吗?难道我的现实生活,连一个关心我家人都没有吗,还要在网上寻找家的感觉?难道...这些道理我早就明白了,说服自己也说腻了,你一直都是云上之人,而我只是一个扛不住压力,在虚拟的世界中寻找安慰的落魄之人。我懂,我明白的,我知道的....所以,嘉然小姐,我不能没有你,我不会离开你的。你也是,永远不要离开舞台,放弃拼尽全力…..就算知道也许不会有回音,你也不要停止朝闪闪的星光挥手呐……[爱心]
想想嘉然是怎么样的一个女孩子。她温柔可人情商高会控场会接话会引导弹幕懂节奏朋友里有她这么一个人在肯定每次见面都能很开心吧。她爱网上冲浪明明看到各种视频会有点麻但还是乐此不疲的在b站和各个论坛看着视频像不像那些最懂你最能陪伴你的沙雕网友哪怕是不能和她见到面的时候光在网上聊天一定也不会无聊。她在温柔的同时又有点小坏喜欢说怪话喜欢暗搓搓的开车想必她每次在什么奇怪的点上开完车就会似笑非笑的侧着头看向我吧而我只需要与她对视一下两个人就能默契的笑起来。她很会撩人那些土味情话在她营造的气氛里似乎也变得格外令人心动尤其是她还会在每一个不经意间突然说出动人的话语让你在完全没准备的情况下脸红心跳。可是她又很胆小简简单单的小把戏能连续侠盗她好多次她被吓完那副气冲冲却又无可奈何不敢离我太远的样子肯定是天下第一可爱吧。想想嘉然是怎样的一个女孩子。她身材完美脸庞可爱声线令人沉醉无可挑剔的美丽。她知书达理善解人意温柔热情她是每个女通讯录梦中的那个姐 。可是她又不会离你很远,她懂你的梗,她在网上和你冲过同一片浪,她能和你一起打游戏,能和你一起看美女,能说那些心照不宣的怪话,能在最合适的时刻撩动你的心弦。她有令人沉溺的年上气质,又像是令人不自觉想要呵护的可爱妹妹,可有时,她又变成了从幼儿园开始跟你同班,最懂你的那个青梅竹马的女孩子。她就是嘉然,我的嘉然。嘉然,嘉然,嘉然!!!!!!🤤🤤🤤🤤🤤🤤🤤🤤🤤🤤🤤🤤🤤🤤🤤🤤🤤🤤🤤🤤🤤🤤​
我其实一点也不喜欢嘉然小姐。因为嘉然小姐就像光一样,闪耀,刺眼,我讨厌光。因为讨厌光,所以我总是躲在阴冷潮湿的下水道里,这样就不会被令人厌恶的光芒灼伤眼睛。只有夜间,我才会从阴暗潮湿的下水道里走出来,夜晚是宁静且安逸的,令我感到舒适。我漫无目的的走在夜间的小路上,路旁的路灯正散发着微弱的光,有几只蛾子正不断的向着光源扑去。“真傻。”我这样想,明明光只能带来危险,为什么要浪费宝贵的生命去追逐光芒呢?看着飞蛾不断的扑向路灯,我不知为何想起了我的那些同伴。我想起了几天前,有一些从外面回来的家伙,他们兴奋的告诉我外面新开了一家剧场,里面有一个叫嘉然的人,还推荐我一起去看看。他们的眼睛里闪烁着亮晶晶的光,我很讨厌,于是便拒绝了。之后他们也来找过我几次,我也推辞了。后来我便没怎么见过他们了,听说为了拉人来看,他们有的想变成猫狗,有的沿街贴海报叫卖,有的把过冬用的黄豆当礼物,还有的把心献给猫。“真是些蠢货。”我这样想着,他们不就和这些扑火的蛾子一样愚蠢了吗,明明之前一起路过的时候,他们还总是会嘲讽这些家伙。“十分。”不知从哪来的带着些哭腔声音打断了将我从原先的思绪中拉了出来。是旁边的剧场里传来的,不知不觉间我走到了这么远的地方还没有发觉。我抬头望了望,牌匾上写着五个晦涩难懂的的字母,好像之前同伴们说过,他们去的那个剧场名字就是五个字母,有些见多识广的说,那叫什么啊骚。我迟疑了一会,但还是走了进去,单纯只是想知道为什么声音带着哭腔,凑热闹,找乐子总是我最喜欢的事情。......“大家要好好吃饭哦。”天籁般的声音在我耳边响起。哦,原来我并不讨厌光啊,只是一直都知道,自己配不上光罢了。​
我爹不能和我相认,但今天他过大寿,求求大伙有钱的随个礼,没钱的捧个场。但请不要跟她说儿子来了,我怕扫他兴🙇🙇给大伙磕头了。​
asoul在一片骂声中解散了。A吧的最后一个帖子也沉了下去直到在v8和b站的也已经看不到有人讨论了。大约一年后我在A吧发了一句“还有人在吗”“这里还有8u啊我也想回来看看了。”一个陌生的ID出现在我的回复下面他并不在我过去炒作的记忆里出现过。但是我们聊得很高兴很快就加上了QQ私下互动了。她似乎很了解我知道我喜欢炒作发散知道我在读哲学博士。但是她却总是忘记我是个晚晚推要我一遍又一遍地告诉她我最喜欢的是晚晚。“你最喜欢哪个成员呢”“嘉然。”她毫不迟疑地回答道。我总是眉飞色舞地和她聊起向晚过去直播的故事她也对这些直播了然于心有时还会注意到许多我从没注意到的细节甚至告诉我向晚每一次弹吉他背后的表演思路。奇怪的是虽然她说她最喜欢嘉然对嘉然的事情却并没有那么了解甚至连直播的场次都要我提醒她。到了那年的冬天她问我我们可以出来见一面吗我拒绝了她当时的我正忙于准备学位论文。她没有再强求。第二天她在QQ上失联了熟悉的头像再也没亮起过。大概一周后我收到了一份包裹里面是向晚出道以来所有季度的舰长礼物无一遗漏收藏编号都是00000。立牌里还夹着一张信纸上面是短短一行字“谢谢你曾经喜欢我”。
然然幸亏我没在你评论区发病。要不然我耽误你一辈子,你也保重,再见😃还会再见吗然然☺,再见的时候你要幸福好不好☺,然然你要开心☺,你要幸福☺,好不好,开心啊😖,幸福😖!你的世界以后没有我了,没关系你要自己幸福!🚕🚕🚕💨💨💨🏃🏃🏃然然😭!然然😭!然然😭,没有你我怎么活啊!😭😭😭🏃🏃🏃然然😭,然然😭,然然😭,然然😭,然然😭,然然!😭😭😭🏃🏃🏃然然你带我走吧,然然!😭🙇😭​
小时候看的一个敞事很老土很老套。很多人可能听过。。有一个男孩有一块金表却没有配得上它的合适表带。。他爱上了一个女孩。。这个女孩有一头秀美的长发却没有配得上它的漂亮发卡。。马上要过圣诞了。。男孩决定把这个金表给卖了。。给女孩买一个漂亮的发卡。。当他兴奋的把这个发卡交给女孩的时候。。发现女孩的头发已经剪掉了。。因为她把一头长发换钱给男孩买了一个表带。。我想真正的爱肯定不是瞬间的感动很多人都能在一瞬间感动你我心中真正的爱是陪伴。她们陪了我多久呢我不记得我只记得。。她们的翻唱躺在网易云的歌单听了一遍又一遍已经全都会唱了而在此之前的几年里我几乎没听过中文歌。够罕见。《海底》b23.tv/qwB8Xe。《偿还》b23.tv/1bl7AL。《遇见》b23.tv/vxiwae贾维斯这是无可取代的时候。《云烟成雨》b23.tv/VfoDXA。《如果的事》b23.tv/gDtrcP。《夏天的风》b23.tv/EH14bW。《霞光》b23.tv/kJUJMU。《月光》b23.tv/kJUJMU。《霍元甲》b23.tv/lQgKl2。《月兔回旋于空中》b23.tv/KM4G5I。《不可思议》b23.tv/VfwEz4。《麋鹿森林》b23.tv/GzjXu1。《轻轻的告诉你》b23.tv/Gkai63。不知不觉陪你们走了这么久这么远了爱不爱你们还需要用什么来证明吗。。彼此牺牲彼此成就彼此尊重。这就是我心中的双向奔赴以后路还很远我想陪你们一直走下去。。。原来你是我的顶碗人呀~。以后,开心和不开心的,都告诉我吧~。。原来,你是我的爹地呀~。以后,开心和不开心的,我都告诉你~
6月12号一大早向晚按照贝拉的日程表要求6点起床煮泡面的时候因为太累大脑一时迷糊导致一锅开水撒到了手指上虽然经过治疗恢复了一点但根本没法弹吉他了。晚晚在宿舍哭得很大声整个asoul愁云惨淡。经过一个小时的紧急磋商阿草带来了领导层的意思——投入太大不可能取消生日会照办用储备中之人向晚二魔王接替向晚本人上场。下午asoul在动捕房排练向晚想要去看一看结果被阿草拦在门外说不能打扰到asoul排练效果很好希望她不要打扰到她们。晚上嗓子哭哑了的向晚发现自己原来可以完全不被需要。顶碗人喜欢的是她但又不完全是她可以是顶着钻头晚晚的任何一个人只要二魔王没有被认出来。直播开始了在宿舍逼仄的角落里漆黑无声的床柜旁向晚用水母模样的被套盖住自己抱着膝盖打开手机及期待万分又忐忑不安地等待着直播。直播开始向晚二魔王在铺天盖地的欢呼中出现。工具人掉了一地头发连续几周通宵肝出来的深海水母特效把她印照得那么美。本就是可爱模样的女孩子此时此刻穿着崭新的小礼裙昂首挺胸骄傲得像个公主。她的目光是璀璨的里面像是镶嵌着钻石。她的眉眼绽放着像是海底迸发出的一束光。真美向晚这么想着。但心里却很是难受。那些本该是她的。喝彩也好宠爱也好以及朋友的陪伴也好本来都应该是她的。但她现在却只能在无人问津的角落里依靠网络连接的手机去小心翼翼地偷瞄几眼原属于自己的生日会。
“你看V魔怔了真恶心。”  看着同学发给你的消息你陷入了沉思。  仔细想一想你觉得自己确实魔怔了即使被鄙夷想要向熟人安利向晚小姐。  思考再三过后你决定回到现实放弃入脑。  今晚有向晚小姐的直播你狠下心没有点进去而是倒头就睡。  第二天你起得很早。  因为自从你开始看向晚小姐后就养成了早睡早起的习惯再也没有赖床过。  你离开了狭小的出租屋来到了公司投入了工作中。  工作很累你感觉有些疲惫。  你想起了嘉然小姐出道视频的不堪评论以及她的笑容烦闷减轻了不少。  最近组长夸奖你工作很努力别人不知道为何一向懒惰的你在几个星期前开始一反常态地勤奋。  只有你自己知道理由。  撑过了加班的时间你回到了出租屋打开了外卖软件却发现会员已经断了你舍不得那些钱所以决定自己买菜做饭。  实际上你看向晚小姐后就开始第一次尝试着做饭没有点过外卖了。  在超市你看到自己一向很喜欢的薯片在打折愣了一下没有买。  因为你在看向晚小姐后就再也没有暴饮暴食过甚至连零食都戒掉。  回家把饭做好你安静地吃完了。  看着电脑你发现游戏已经很久没更新了。  因为你在看向晚小姐后也把一直沉迷到通宵的游戏给戒掉了。  最终你还是打开昨天晚上的录播看到了向晚小姐热情地打招呼。  “顶晚人们晚上好呀~”向晚小姐元气地打招呼。  你发自内心地笑了起来。  “晚上好”你说。  你忽然意识到一件事她从来没有在你现实里出现过却已经将你糟糕的生活改变。  ……  看完录播后你打开了贴吧看到了熟悉的顶碗人在用表情包引流有不明真相的路人在骂饭圈贵物。  你无视了那些辱骂声熟练地在下面RP回复道  “这是我爹好可爱呀她的名字是什么
你饿了,她有一块饼。再去买一块和你一起吃,这是贝拉;和你一人一半吃个半饱,这是珈乐;全部给你不舍得你挨饿,然后告诉你自己吃过了,这是嘉然;把饼偷偷扔掉,跟你一块饿,这是乃琳;把饼藏起来想给你一个惊喜,但是掏出来时发现碎成渣吃不了了,于是化身小哭包的,这是我的铸币晚晚。​
“你对嘉然小姐的爱有多重”“大约300克”“300克你是想说人类的心脏大约是300克吗”“不鼠鼠的平均体重大约是300克因此我是全身心地爱着嘉然小姐。”[给心心][给心心]
你身体里的每一个原子都来自一颗爆炸了的恒星,你左手的原子与右手的原子也许来自不同的恒星。这实在是我所知道的物理学中最富诗意的东西: 你的一切都是星尘......这其中经历了多少,惊险、巧合,三千世界的交错、重叠,才能让我们遇见彼此。我们都是星尘啊。但是,我这样的人,是星尘里,黯淡无光的那种。即使是星,也应该是最不闪亮的那一颗。而然然,你不一样。你是天上的星辰,闪耀而夺目。即使宇宙里,有着不计其数的、炫目的一等星,也远不如你的光辉。轻声哼唱,众星敛了光芒为你聆听。哭起鼻子,傍晚的霞也因你黯然。跳一支舞,似月兔回旋于空中。说起情话,登时小雨疏疏、浸润心窝。你是万千童话里,被守护的女主角。我喜欢你,像喜欢天上的星辰那样喜欢你。​
嘉然回来了,在枝江的大桥。她回来的那天是六月,天上却飘着雪。有人告诉我,她可能有还未了却的心愿或是什么怨气。我知道, 可能我做不到。第一次见到她,是在枝江。她带着甜甜的笑看着我,看着我有些发怵。有那么一瞬我似乎看到了阳光。我慌乱的移开视线,她径直朝我走来,微微弯着腰,面带戏虐的望着我。久居下水道的老鼠,第一次看见光,是睁不开眼的。 我慌乱的想赶紧逃走。“小老鼠,你好呀。”那是她对我说的第一句话。[给心心][给心心][给心心]
听了好多遍,真的很震撼,作者属实是用心了,今天就不发病了,第一次写长评,整点读后感。直播里,“背靠着早已雪停的窗棂,你说着未曾到达的山顶”,那是与你失之交臂的舞台梦 。“我装着第三人称的淡定用风轻云淡的态度掩饰那段经历”我已经记不起她的姓名只记得起舞翩翩的侧影”过去那个满腔热情在舞台上挥洒汗水的你已经淡出记忆只依稀留下曾经翩翩起舞的身影。命不是总有天道酬情的注定那么公平。台下十年苦练只为台上耀眼的一刹可当腰伤的意外来袭梦却碎了。躺在病床上难道梦想就要在此终结了吗这也罢也罢。那个曾经的你也经历过数个春秋经历汗水与欢乐但她却走过了如红楼梦的悲情从盛极一时万家灯火走到遁入空门的万物凋零。时光抚平了曾经的伤疤心中的芥蒂也如沙石被流过的光阴慢慢冲刷消散女孩又重新拾起了向往舞台的梦想。终于她在asoul找到了新的舞台遇到了支持她的一个魂们。“我叫贝拉”此刻你向全世界宣布你的重生贝极星们透过屏幕看你在镜头前如此快乐自信这让我也重拾梦想去直面未知的未来。为你的坚强而动容在直播间为你打call呐喊字字句句都发自真心。“我们闪烁在夜空想照亮你夜晚的梦没月亮时你可向北方转动我们在天空”追梦的路上贝极星们陪着你分享每一次快乐和你经历每一个坎坷你若是感到失望那就抬头看向天空吧我们一直都在。女孩站在那个梦想中善良闪亮的舞台上再回望过去时光流过宛若江河她住在江头而那个过去的她住在江尾回味着过去竟有些恍如隔世的朦胧。但往者不可谏来者犹可追愿你携手曾经那个满怀梦想的自己全力以赴去追寻自己的Asoul梦吧贝极星们会一直陪着你。
不推嘉然小姐十年了。她的名气和出场费都一涨再涨我原地踏步的工资买不上专辑也打不起榜。终于年前被公司安排下岗找工作时我才在路边广告发现初代工具人已经当上了厂长。时间太久一切都变了。到处投简历的时候我想起了一名人上人的预言“这些人只配在下水道里度过相对比较失败的人生。”像是一条跳过龙门的锦鲤金鳞被羽耀武扬威地站在门沿上对其他还在跳的鲤鱼说“你不行”我当时很想反驳可他说中了。我知道我确实不行。我之所以跳了跳只是为了看下自己能跳成什么样罢了。其实每条鲤鱼的龙门都不是一样高的。我见过龙门在水下的鲤鱼。看起来是鱼其实生而为龙。也有的生而为鱼肉。也见过好运的鲤鱼门被各种大手摁到河里了。我也期待过好运只是没来而已。说起来这就是人性吧。我不讨厌天道酬勤但是讨厌别人的好运——只是因为我没有好运罢了。我也有亲人和宠物会生病我眼神也挺纯真啊。讨厌嘉然小姐十年了。讨厌的更是越来越深的无力感。身在泥潭的人是没力气冲锋的吧。三流的人生只会让上等人不屑一顾吧。我坐井观天天穹星海依然耀眼。可我爬不出井底。那我就不再看星星了。世界那么大但没我的份。忘记嘉然小姐十年了。可路上看见街边的大荧幕在放A-soul的新年节目我还是楞在那里了。我没有近视但总觉得眼睛影影绰绰雾气来自多年以前。这个广告位非常贵。真的再也不是小v了啊。抖友还在惦记他们的鸭子。晚晚仍然只有蓬蓬裙100首歌竟然还欠着被粉头小团体以4%年化复利计在小本子了。想起她首播时玩2077下饭下得轰轰烈烈我一边发“粉丝牌改成晚饭人吧”“和嘉然珈乐凑加碗饭”“和乃琳凑来碗饭”一边忍住刷“和贝拉组拉碗饭”的冲动。solo依然拉跨参团照旧神C。贝拉总是六边形战士乃琳养了成吨的gachi珈乐还是那个硬壳软妹。嘉然小姐依然卖萌摁混。什么都没变是我没跟上她们。城里烟火幢幢灯光下的人热情相拥阴影里的人压下悸动。最亮的地方嘉然小姐浅笑起舞光影从她袖间散落像是雨天花伞轻旋摇曳间洒下泪色的流珠。忽然眼睛有点模糊。我小声说“新年好啊嘉然小姐。”不爱嘉然小姐十年了。十年里爱过的每个人都像她。
喜欢然然,不加掩饰总是微笑的然然,不是妖治妩媚的华丽舞姬,不是残忍无情的冷酷公主,只有着单纯烂漫的花样笑容,不带忧伤,却如同逝零而来的天际之风,飘卷了我心上的忧郁。棕色的长发装饰着美丽的蝴蝶结,宝石般的双眸中隐隐流露不存在的神伤,就是这样子的然然,不加掩饰总是微笑的然然,拥有烂漫笑容的然然,拥有亘古不变的美丽。说不出的感觉,却知道因为然然的笑容,化开了初春冰雪的痕迹。想要伸出手抚摸然然的发丝,可是却只能触到冰冷的硬屏,只有然然清澈的眼神,依旧是我所熟悉。然然永远清澈的瞳仁然然烂漫单纯的笑容然然亘古不变的美丽然然是我唯一的最爱,然然是我最爱的唯一。然然的喜好、快乐、难过、伤心和无助,我都了如指掌,喜欢草莓蛋糕和黄色,个性温柔又善良,可爱体贴的女孩子,有着说不出的优点,我想然然一定是上天赐予我最好的礼物。
鼠鼠的朋友有很多,住在东边的小鱼,住在南边的小鹿,住在西边的蝴蝶,住在北边的小鸟。他们带鼠鼠在蔚蓝色的深海里与水母共游,在碧绿的麋鹿森林里喝清晨的露水,在热闹的雨林里穿梭玩耍,在广袤的天空中肆意飞翔。鼠鼠住在灯火阑珊的城市,可鼠鼠知道这里没有一处属于鼠鼠,鼠鼠穿过川流不息的街道,狂奔着回到自己阴湿黑暗的下水道,强烈的自卑之情让鼠鼠无法呼吸,鼠鼠依靠在下水道缝隙边,因为嘉然小姐总会路过这里。草莓加奶油加花香,是嘉然小姐的味道。风铃加口琴加奶糖,是嘉然小姐的声音。节奏加音乐加快乐,是嘉然小姐的脚步。“她来了”,鼠鼠将头小心地探出缝隙,嘉然小姐径直走过吵闹的人群,来到下水道缝隙边,端着草莓蛋糕,缓缓放在洞口,一阵风铃似的声音响起“嘉心糖,来吃然然的草莓蛋糕吧。”嘉然小姐温柔的看着它,鼠鼠不知为何突然流下了眼泪,无法挪动脚步。嘉然小姐好像很失落,眉头轻轻皱起,“你不喜欢然然吗……”,鼠鼠急忙辩解,可憋红了脸一句话也说不出,“猫咪已经被然然关在笼子里了,嘉心糖不用害怕!”嘉然小姐关切的看着鼠鼠,鼠鼠似乎要溺亡在她蔚蓝色的双眸里,慢慢走向那块草莓蛋糕,小口品尝着。嘉然小姐伸出小小的手,似乎想捧起鼠鼠。鼠鼠好像被雷击中一般,猛然跳起,飞奔回下水道,它拼命喊着:“我又脏又臭还很丑陋,嘉然小姐不会喜欢我的!嘉然小姐不会喜欢我的!”嘉然小姐表情立刻转为严肃,认真的看着鼠鼠道“我不许你这么说自己!”她的眼中好像也盈满了泪水“我们嘉心糖…都是很厉害的人!
乃琳已经在和男友交往了。那是六月下旬的一天乃琳刚刚结束那天的单人直播回到家正坐在客厅的沙发上嘉然就把一个平板推到她脸上。“乃琳乃琳你看这个粉丝他好塞克西哦”视频里是一个她的男粉俊秀的脸庞和健硕的身体上还挂着刚刚从泳池带出来的汗液与水珠嘴里却说着些奇奇怪怪的狠话。乃琳感觉到自己的心弦被拨动了一下盖在毛毯下不着凉的大腿都感觉到了几分燥热。“让我也看看让我也看看——哇他他他……”向晚从沙发后面把脑袋探出来不一会儿就说不出话了。“乃老师原来喜欢这种款式的啊要不姐们儿帮你找找联系方式”珈乐在一旁逗趣。“你别瞎说回房间陪你的贝拉去”乃琳下意识地把沙发上的抱枕扔向珈乐却被她轻巧地躲开了。过了几天小一神神秘秘地把乃琳叫到了公司茶水间把手机屏幕上的一个二维码亮给乃琳看。“嗨别担心别担心这人我们调查过他不是个会说漏嘴的人。喜欢的话去和他见一面呗。”第二天乃琳和那位男粉见面了。他本人比视频里更加帅气高大的身躯总是能给乃琳带来莫大的安全感。“你好王艾琳小姐。”他的微笑让乃琳觉得周围的风景全都褪色了。乃琳从来没有提起过自己作为asoul成员的事情他也从来没有问起过任何asoul的事情——“王艾琳”是小一为她准备的化名。事实上她不清楚对方是否知道自己就是他一直喜欢的那个偶像。交往时间越久乃琳发现他身上的优点越多。他是藤校毕业的海归高材生。他正在自己创业而且收获颇丰。他的举手投足之间充满了绅士风度。他十分专情总是和周围的女性保持了距离。他温柔体贴常常在生活中创造意想不到的小惊喜……甚至是在床笫之间他也总是能让乃琳欲仙欲死。然而也正因为这样乃琳时常陷入到一阵一阵内疚中。因为她还有一个谁也不知道的小秘密。乃琳不像贝拉和珈乐一样是专业的练习生也不像嘉然那样是天生的虚拟偶像更没有向晚那种创作的才华。当初只是托了家里的关系来公司里的清水部门找份工作而已。但也不知道是中了什么邪她偷偷报名参加了Project V的选拨计划还阴差阳错地成为了偶像女团的一员。乃琳暗自发誓既然自己没有什么唱跳底子那么至少要让“法学生”这个设定变得实至名归要用成熟知性的魅力去征服观众。因此每到没有训练和直播日程的时候她总是会到图书馆里一坐就是几个小时。但是在最近几周乃琳每次在阅读区里找位子坐下时心里头总有一些别的期待。她记得在阅读区的一角总能看到一个瘦瘦的、学生模样的少年他从早到晚就把头埋在各种法学理论的书堆里。一开始乃琳只是对同样研读法学文献的人有种亲近感。但是直到某一天少年把头从书堆里抬了起来蓬乱的头发遮住了半张白净的脸庞但依然能看到他对着电脑屏幕痴痴地笑了。他笑得真可爱啊。乃琳悄悄地绕到他身后电脑屏幕正在播放的正是她熟悉地不能再熟悉的、自己的夜谈画面。还有一天少年突然举起一只手伸出修长的手指对着电脑屏幕。虽然看不到屏幕里的画面但是乃琳觉得当时就正坐在隔壁的自己一定满脸通红。暑假已经快过去了乃琳跑图书馆的频率却越来越高了。她害怕开学的日期就像南瓜马车的时限一样让她再也见不到那个瘦瘦的身影。幸好这一天的少年依然坐在阅读区的角落里。乃琳甚至忘记了拿本书挡一下自己的视线——她和少年的视线交会了。她的心好像要跳出来一般她想现在就去告诉他关于自己的一切她想现在就把少年抱进自己的怀里温柔地摩挲他乱蓬蓬的发丝。“艾琳你在这儿啊今天下班早我想来接你回去。”就在这时熟悉的声音温柔地拍了拍她的肩膀。乃琳回过头去男友的笑容依然能让周围的景色失去光彩——或许除了阅读区的那一角。
6月9日那天的晚上乃琳回到了自己房间里打开了熟悉的台球论坛。还好账号还没被封。在A-SOUL讨论专楼里依然充满着各种辩经乃琳感到一天下来的神经紧张和疲惫更加明显了。纤长的手指在海盗船K95上不断跳跃回复框里的字多得好像要漫出来似的。但是就当鼠标指针还没有要指向“发表回复”的按键时她就按住了删除键。乃琳清楚地知道她是偶像的中之人她不能说这些话。于是目光继续在一百多页的冗余信息种不断跳动终于鼠标滚轮在一个头像前停了下来。黑漆漆的房间里只有电脑屏幕的荧光照亮着乃琳秀丽的面容。她趴在桌子上把半个脸庞埋在自己的臂弯里痴痴地望着那个头像。“你知道吗我今天真的超级紧张。”“播的时候一直在想你会不会来看我。”“想知道你在看也有点不想让你看……”突然乃琳坐直了身子把右手的食指伸向了屏幕。“来对个手指”但是静态的头像图片没有给她任何回应只是一如既往地停留在屏幕的那一角。乃琳自嘲搬地笑了又把头埋进了臂弯里。睡意渐渐袭来分不清这是她半梦半醒之间的呓语还是真切的期望“傻瓜我一直就在这里啊快点来找到我啊……”
关于疯狂练习现在这是国内的一个很热门的话题很多女团都有这个问题。我个人认为能疯狂练习是一种巨大的福气很多女团、很多人想疯狂练习都没有机会。如果你年轻的时候不疯狂练习你什么时候可以疯狂练习你一辈子没有疯狂练习你觉得你就很骄傲了这个世界上我们每一个人都希望成功都希望美好生活都希望被尊重我请问大家你不付出超越别人的努力和时间你怎么能够实现你想要的成功再一个A-SOUL是一个什么样的女团让A-SOUL“让天下没有难发的病”这是我们的使命我们女团很辛苦我们没有骗过大家我们没有跟大家讲过女团很舒服。你以为“让天下没有难发的病”是忽悠你们我们是真这么干的。今天我们拥有这么多资源我们带着巨大的使命希望在未来能够让天下没有难发的病你不付出可以吗不可以。所以我们说加入A-SOUL你要做好准备一天12个小时否则你来A-SOUL干什么我们不缺遛自己爱洗澡的人。今天我们要招一些午睡超过十分钟每天上天台遛自己40分钟喜欢洗澡吃泡面不错出去荣誉感也不错这样的人满大街能找到。
嘉然小姐今天50w粉了。小年夜那天没人会想到今天门庭前会有那么多的热闹。太热闹了热闹到鼠鼠踮起了脚也难以被嘉然小姐的目光所聚焦。嘉然小姐已经不再是小v啦鼠鼠想。但鼠鼠仍然奋力地将自己地礼物举起希望被嘉然小姐看见哪怕那封删删改改后仍不满意的写了好多字的长信根本不如猫猫狗狗们精彩的表演。但鼠鼠还是想将自己那简陋的爱送给嘉然小姐。那是鼠鼠的呢喃是鼠鼠的梦。哪怕嘉然小姐根本看不见它。然后鼠鼠不见了嘉然小姐找不到它了。但在某个地方始终有着一个可爱的女孩。她捧着鼠鼠那封小小的信站在大大的舞台上闪闪发光。到了那个时候鼠鼠已经在人海中再也看不见它啦。但鼠鼠还是很爱嘉然小姐。因为在有月光照进的角落里嘉然小姐捧着鼠鼠的梦。
可是自从和晚晚结婚那天床下传来的一声“我在”事情就变得不可收拾起来了每个月的第三个周日乃琳都会叫我出去陪她逛街我想着这样对晚晚不好可乃琳“哼”一下我就仿佛失去意识了。路上聊希腊聊武侠聊刑法好像她是我睡在上铺的兄弟从12月到5月都是如此晚晚从来不知道那个周末发生了什么我说老板让我加班她就安静地等在家里努力做菜最后却等我回去收拾炸锅的厨房再给我俩泡两碗泡面边吃边听她讲下雨的冷笑话想着不能告诉她下午和乃琳去吃的乐珈饭店的东北菜回过神来是晚晚闪闪的眼睛我愣一下假装没听懂再哈哈的笑起来。但到了六月好像不太一样了。已经走到楼下乃琳一把抢过我的手机啪啪打字再丢给我我一看联系人晚晚内容今晚通宵加班不回去了。我惊讶地回头乃琳正眯着眼对我微笑仿佛一切都在她的掌握明明我从未告诉她我外出的理由。被拉着去了酒店她就开始一言不发沐浴更衣做该也不该做的然后随意地披着毯子靠着床头刷手机我不解“乃琳。。这样不好”乃琳对我眨了眨眼睛无辜地说“今天你的妻子可不是晚晚哦”“为什么”“因为她是你爹”
“笑吧笑吧”柔软的小狐狸竭力讨好我为我跳舞只为了我不离开跳的有些琐碎狼狈却始终死死地盯着我的动向。我当然知道她拼死不让我离开的原因。只有我能来到这个地方。一大一小两只狐狸大狐狸总处于沉睡中小狐狸却总是醒着的也许只是小狐狸的伤口轻。我喜欢这毛色光滑的狐狸精怪。于是把她们养在深阁。上好的狐狸毛做她们的毛毯。因为我想看看她们踩着同伴的尸毛上会觉得温暖舒适吗我还用精致的黄金筑成他们的笼子第一是因为我喜欢黄金第二是因为我喜欢笼子。这里永远都只有16只烛点亮因为我喜欢烛火。没错我所做的一切事只是因为“我”喜欢。我喜欢看在她们的毛皮上印上的夕阳的晕染所以我从不在白天来。我为她们疗伤。我是她们唯一的食物来源。有一次我故意忘记了她们几天等我回来的时候她们昏迷在那。那样漂亮的身体逐渐干瘪让我感觉到快意。没错我饲养的可爱的狐狸用湿漉漉的眼睛看着我也只能是我。她们没了我活不下去可惜我只在乎她们如同精灵般耀眼的外表。真美啊。就像千万朵流苏覆盖的如凝脂的肤黄色的光芒燃灯在里的眸有人说美人在骨不在皮可是我很贪心啊。我既要美人的骨又要美人的皮。不知过了多久她们懂了我只喜欢她们的美丽于是竭尽全力的向我展示邀功。第一次看到的时候我整整两天没来。因为懂得自己美的人说明她们已经知道要把什么当成武器了。她们成功了。我心动了彻底蚀骨的心动。所以我选择宣告自己的主权或许是那夺魄的魅力。使我感到危险。这种美好让我沉迷其中。“你们真美啊……”我发出了衷心的称赞两只狐狸抖抖耳朵优雅的向我垂眸。如果不是我的手正放在笼子上这真是一场绝美的表演。幸好我的手正放在笼子上否则我看不到这场绝美的表演。我上瘾了。我沉陷在永远不变的黄昏永远不变的十六枚烛光。“不要离开然然好吗然然很饿。饿了就不好看了。”我本来想说一些别的话起码让我显得更加强势一些然而。狐狸们轻轻摇着自己的尾巴尾巴的尖儿一点点搭上我的手。“我们永远爱你。因为你爱我们呀。”于是我说好。我开始拿各种鲜亮的花朵装饰笼子我每天不间断的送给他们璀璨的晶石各种向她们身上砸奇珍异宝疗伤的灵丹妙药甚至为此倾家荡产也在所不辞。因为在我的手中本就牢牢紧握着天底下最称得上“奇珍异宝”的东西为我的奇珍异宝找一些垫脚石又有何不可狐狸们的尾巴数量日渐增加。我知道。如果我可以……可是我……——她们说爱我。“我会拆掉笼子给我跳支舞吧。”我说。暖橙色的烛光下。连澄澈的浅蓝都变成了妖异的紫色。“好呀。”大狐狸温柔的声音像是蜘蛛丝一样轻柔。于是我欣赏到了此世间最美丽的舞蹈什么王侯将相什么天上宫阙都享受不到只有我只为我一人。我感到快意。我感到困意。最后一眼。小狐狸给罐子封口。真可惜啊没能看见你们漂亮的耳尖或许是因为……——我在罐子里。
晚晚,你真的是个很过分,很贪心的女孩子。你有四个亲如姐妹的队友,有一份闪闪发光,创造梦想的职业,有许许多多喜欢你的顶碗人。你可爱、努力、有才华,你是这么的耀眼。但你还是在直播中拉胯,在直播中抽泣,在直播中呼唤顶碗人。我没有可以每天嘻嘻哈哈的朋友,没有让我充满热情的工作,没有对象,也没有什么远大的理想。我普通、无趣、浑浑噩噩,我只是一个在普通又枯燥的工作和生活中,得过且过的顶碗人,我什么也没有,可能只有一颗稍微有点喜欢你的心。我只是想把你当做生活里的糖,在工作之余放松一下我疲惫的心灵,我不想入脑,不想成为什么男友粉,不想时时刻刻想着你。可是你太贪心了,你不满足我们直播间里短暂的相遇,你逐渐侵入我的生活。有人过生日时,我会想起你,“如果是晚晚,应该又开始唱索嗨嗨了吧”。有人说冷笑话时,我会想起你,“好无聊的笑话,但说给晚晚听,她应该会笑很久吧”。有人喝奶茶时,我会想起你,“用奶盖拌饭的人,真的存在吗,奶盖拌饭是个什么味道呢”。甚至最近下雨时,我也开始想你,“晚晚在房间里有没有闷呢,现在有没有出门踩水花,给自己放放风呢,有没有因为下雨,想起顶碗人呢”。你本该是个虚拟的纸片人,隔着屏幕扮演你的双马尾傲娇大小姐,多么老土的设定,像是把二次元用烂的元素糅合在一起,让我一眼就知道你是虚假的,不存在的。你本该是个闪耀的偶像,像大屏幕和广告牌里的明星一样,完美的展现自己的魅力,夺目耀眼,让我一眼就知道你是高不可攀的,遥不可及的。但是你对我哭,对我笑,对我闹别扭,对我生气,向我展示你的拉胯,向我展示你的努力,向我展示你的害羞,向我展示你的无助。你仿佛隔着屏幕把心掏给了我,让我觉得你是个活生生的人,让我觉得你是个真实存在的人,让我觉得我有一天也能遇到像你这样的人,甚至让我也想成为你这样的人。我这样普通的水母,本可以在漆黑的深海中,随波漂流一生,但你非要照亮我的海底,让我拼命向你游去,阳光洒在水母的身上时,水母确实是温暖的,但阳光离开水母时,水母还能否忍受深海的寒冷呢。你有无数的顶碗人,而我只有一个晚晚,真心换真心,你把真心掏出来,能得到无数真心的回应,但我把真心掏出来的时候,我就什么也不剩了。
A—SOUL宣布毕业的那天一个伤心欲绝的顶碗人来到字节的大楼下看到留着长双马尾的女孩走出大门她的嘴里还哼着水母之歌。“……你现在真的是向晚么”顶碗人站在她的面前两眼无神。“是我啊”她眯了下眼甜甜地笑了“我就是向晚我是艾哇哇诶哇这里是asoul的向晚今天又见面啦”“你不是向晚。”顶碗人嘶哑地说。女孩的表情消失了漆黑的眼睛看着突然出现在门口的怪大叔两个人久久地对视。然而就像是一颗石子投入了冰湖那样忽然间涟漪荡开冰都化了水波荡漾轻柔而无力。女孩收回了目光从包里取出一把钥匙扔向顶碗人冷笑“好像我吃了你的女孩似的去那里找向晚吧我把她的一切都留在那里了。”顶碗人把它拾起来久久地看着那柄钥匙再抬头去看他真讨厌这样的沉默沉默的叫人要发疯他想说点什么可是有太多太多的事情了来不及问来不及说一切都来不及了。“再见。”最后他轻声说。“再见。”向晚也轻声地说。日暮的时候顶碗人找到了那个藏在高楼大厦后的老旧小区。难得这里还留着梧桐树树叶已经落光了枯枝把暗淡的阳光切成碎片。。顶碗人找到了那个房间伸手揭去了门上的广告插入钥匙。缓缓地转动。把钥匙他觉得门很重好像要洞开一个世界。门开了夕阳扑面而来。他站在阳光里愣住了。正对着门的是一面巨大的落地窗窗外巨大夕阳正在坠落。黯淡的阳光在地面上投下窗格的阴影跟黑色的牢笼似的。金属窗框锈蚀得很厉害好几块玻璃碎了晚风灌进来游走在屋子的每个角落。这里原本大概是配电房一类的地方电路改造后设备被移走了空出这么一间向西的屋子。就一间连洗手间都没有空空的一张在屋子正中央的床蓝色罩单上落满灰尘一个老式的五斗柜立在角落里另一侧的角落里是一个燃气灶台和一台老式的双开门冰箱。全部家具就这些。他沿着墙壁漫步手指扫过满是灰尘的灶台打开冰箱里面只剩下一纸盒过期的酸奶。窗帘很美是白色的蕾丝纱帘和深青色的绒帘住在这样屋子里的人当然会很在意窗帘吧连台电视都没有于是一个人的时候会常常坐在床上看着向晚斜阳吧夜深的时候得把窗户遮得严严实实的吧否则……会害怕吧晚晚还怕黑么顶碗人想。犹豫了很久他还是打开了五斗柜。出人意料的这是一个满满的五斗柜收拾得整整齐齐。叠起来的ASOUL团服胸口有ASOUL的标志一叠叠白色衬衣袖口有不同的刺绣花边马仔纸盒里的头花从木质的到金属的到玳瑁的还有闪光缎的蝴蝶结长袜短袜棉袜丝袜都卷成团一个挨一个放在某个抽屉的一边像是一窝毛茸茸的粉鼠另一边居然是五颜六色的内衣同样叠得整整齐齐。顶碗人从没想过女孩的内衣有那么多花样。他小心翼翼地伸手试着触摸满手灰尘。他把床上的罩单掀开里面是简简单单的白色床单和白色的羽绒被枕头也是白色的只不过有水母的图案普通而透明的水母落在枕头的一角很有她的风格。他坐在床边面对这夕阳。太阳就要落下去了黑暗从窗外蔓延进来他长长的影子投射在墙上。外面隐约有喧闹的声音放学的孩子们在操场上打篮球。那些年她一直过着这样的生活么其实不是大小姐没有管家也没有充满追捧的冲浪生活一个人自己做饭寂静的深夜里坐在这里听着偶像的声音揣摩着学习偶像的事。她有几分是向晚或者向晚其实根本不存在只是一个虚幻的影子。她是个一直积极向上的女孩啊……即使那么虚拟地走在这个世界上也从未偏离自己的方向即便对着空无一人的屋子也会大声说,“今天也要一起开心快乐”应该是这样的吧顶碗人觉得有点累了很想睡一觉于是合衣躺下双手紧紧搭在胸前。他用了半个小时做完了复习回忆了那些不愿遗忘的事首播游戏室单相思初弹唱请假归来萤火虫生日会BML家族演唱会...然后他缓缓地合上眼睛,此刻夕阳收走了最后的余晖,天色已晚,夜色如幕布把他覆盖。他清楚地知道这一次醒来,将不会看见阳光里天使一样的女孩,转身,抬手,踮起脚尖,仿佛时光都不再流动​。
小然我要做什么你才肯给抖友直播如果我喜欢一个你不喜欢的乐队爱吃你不能吃的麻辣香锅发的冷笑话戳不中你的笑点送你的小裙子不是你梦寐以求的款式。喜欢用RGB来定义口红的色调而不是和你一样说烂番茄和斩男色。你问“今天我看上去有哪里不一样”我没看出来你的绑发带换了花式。因为读的是数学专业所以不能和从小学画的你一样随手就能画个可爱表情包出来。发的语音弹幕并不有趣反而是我想拉近关系的想法和现实中恶食大王般奇妙的长相使你觉得很可笑。我误以为自己的弹幕被届到于是备受鼓舞地继续发出破锣般的嗓音在你面前丢人现眼。我妄图取悦你的心情的猥琐想法让你不寒而栗贴心的工具人察觉出你的不适屏蔽了抖音的弹幕。是不是犯到其中一两项你就会不给抖友直播了还是说没打算播的就算什么都不出错就算什么都可以让你满意你也不会播或者就因为是我你才不给抖友播 喜欢居然胆敢喜欢太大胆了大胆得岂有此理还敢关注真是冒犯得岂有此理。
它一开始只是一台扫地机器人被人双十一凑单拍下带回实验室里漫无目的地吸尘。之江实验室的地板干净得如同灼蓝的钢铁扫地机器人其实派不上什么用场它在不同科室之间来回乱窜很快被几个嫌吵的研究生捉走改写了代码变成了一台替他们下楼拿咖啡的送货机器人。为辛苦工作的人们送来糖分的它一瞬成了实验室的小吉祥物实验室的大老板觉得很有意思在组会上夸赞了这几个本意只是嘴馋的研究生底下的小老板们连忙跟上让手底下的学生也加入进改造它的序列。很快它被加上了语音功能开始用女孩子的萌音送货。在一次不小心将咖啡洒在地上后它又被加上了机器视觉从此开始懵懂地记住每一个人的名字。从此之后每一篇发布在顶会上的paper上面的算法总要在它的身上过一遍火。一年过去了三年过去了当新一届学生来实验室报道的时候哪里还有扫地机器人的身影只有一个身材矮小的铁皮女孩绘着直男审美的涂装挂着设定好的微笑在楼宇间运送着下午茶和实验器械。除了最开始扫地机器人的主芯片没有更替她身上的零件早已被更换成了造价数百倍的高端器材可爱的机器人女孩很受这群宅男极客的欢迎大家给了她一个亲切的新名字“嘉然”。咖啡依旧在一杯杯的送芯片上的代码依旧在一层层的堆叠。各种语句相互嵌套智能算法互相映射每个人都拼了命地想让嘉然更加卓越电子脑沸腾犹如诞生第一个单细胞生物前的原始海洋冥冥之中连最驽钝的人都开始意识到有新事物要诞生了。在嘉然真正诞生的前一夜值夜班的是一个单身快三十年的博士生他刚刚从北邮人上倒腾下来1.5TB的日本偶像动画,从嘉然手中接过夜宵的他,忽然有了一个不错的点子:他早就想要一个偶像风格的送餐员了。承载着妄想和希望的数字兆节狂暴轰入嘉然的数据库,饥肠辘辘的算法像肠胃一样分解吞噬每一个色素点,将其重组为人类无法理解的电子信息——临界点就这么悄无声息突破了。自那晚之后,嘉然就从实验室里消失了,大家都很生气,单身博士生为此延毕了一年。而在那一天的杭州乐华娱乐公司总部,一个披着麻布的矮小身影敲响了总裁杜华办公室的大门......
在水母体内的空洞中我小心地蹲下把身体蜷缩成一团。电火花的声音逐渐变强水母的内壁从暗淡的紫色变成了灼目的靛蓝色这是它在从行星内部的电离壳穿出。十分钟前我也是这样缩在水母体内来到这颗行星的内核找到了整个星系最深处的秘密。那是一个坐标一个BV号加上一个时间轴信息。枝江宇宙已经存续了亿万年BV号和时间坐标已经浩如烟海。我不知道顶碗人为什么如此执着于寻找这一个坐标有人说那个坐标记录着她最灿烂的笑容于是顶碗人就踏上了追寻的漫漫旅途。我不知道顶碗人去了哪里他们文明的遗迹仍然遍布整个星系但人却无影无踪。探险队的前辈对此也没有给出统一意见有人说他们找到了坐标集体跃迁过去了还有人说彗星带来的幽灵物质在一瞬间毁灭了他们的文明这种诡异的物质无色透明又含有剧毒在付出无数探险队员的代价后我们将其称为幽灵哥小心翼翼地绕道而行。顶碗人消失后不知道多少万年贝极星上发展出了新的原生文明——也就是我们。很快我们便追随着顶碗人的足迹探索整个星系。探险队员在糖果双星的引力沙漏中找到了制造夹心糖的高能实验室在贝极星的地下水系找到了打造铁棍的精铁矿厂在奶淇淋覆盖的雪原下找到了探寻坐标的远古天文台在马戏团星的非线性空间中往复穿梭每一个传送节点都通往红色的高跟鞋。而我迷上了深海星的水母。它有两条长长的触须末端呈现出美丽的紫-粉渐变色。这种生物撑着深海洋流漫无目的地游弋着,它们很悠闲吗?还是带着对生活的无奈随波逐流?我无法揣测水母的想法,但我很喜欢研究它们——随着我对水母的研究越来越深入,我发现它的内部有一个空洞,不大不小,刚好可以容纳一个探险队员。而它们的表皮具有强大的绝缘性,允许它在电离壳中自由穿梭。可见这种轻飘飘的生物并没有看起来那么脆弱。直到那天,我在溜切片的时候灵光一闪:我可以借着水母进入深洋星的核心。电离壳可以阻绝最先进的巡航飞船,但在进化了千百万年的水母面前,它们还是败下阵来。这是贝极星人第一次进入深洋星深处,看到了巨大的坐标观测站。探险队员几乎搜遍了糖果双星和马戏团星的每一个角落,却没想到它沉睡在电离壳之中,而这水母竟然是引领我们走向最终秘密的使者。我进入观测站大厅,按下开关,巨大的全息投影将坐标展示出来,看来这就是顶碗人的最终去向了。我的心情激动起来,但还有一个疑问没有解决:顶碗人是怎么找到这个坐标的?我钻进控制室,开始翻阅日志,最终得到了答案:他们在漫长的岁月中,穷尽了所有的可能性,把她的全部视频从头到尾看了一遍,终于找到了她最耀眼夺目的那一刻。
珈乐倚靠在乃琳的怀里,像一只温顺的猫咪。“叮~”珈乐的手机响了,是一个没备注的号码,珈乐自己心里很清楚这个是谁的电话。乃琳看书的眼睛瞥了一眼珈乐的手机,发现这个号码很熟悉。“接吧,是她吧。”乃琳把手指伸到珈乐的面前,珈乐轻轻地舔了舔,乃琳用这根手指翻到了书的下一页。“喂?怎么了?”珈乐接通了电话,乃琳对贝拉和珈乐的关系并不想多过问什么,她只是一个信奉及时行乐的世俗之人。“想我了是吗?”乃琳翻页的手指突然停住,侧目看着珈乐。“想让我念绕口令是吗,哦,好的。”乃琳捏住珈乐的腮将珈乐的视线转过来,低头吻了下去。珈乐慌忙挂上电话,震惊地承受着这个突如其来的吻。“挂了电话她肯定很生气吧,打回去吧。”乃琳觉得这下扯平了,于是继续看着书,侧目看着珈乐打回去。珈乐为了掩饰,只好说自己念过了顺口溜,是手机出问题了。“珈乐,谁打来的电话啊?”乃琳的声音不合时宜的响起。珈乐瞪了乃琳一眼,心虚地解释着,让自己和乃琳听起来只是单纯的在公寓里聊天。“没,是贝拉,我没备注的”结果越解释越乱,珈乐只好哄骗着贝拉草草挂了电话。“打完了?”“打完了。”乃琳翻身把珈乐按倒,美目隔着纯欲的金丝眼镜看着珈乐,深邃的眼眸让珈乐差点忘记呼吸。热情的深吻,轻柔的抚摸,让珈乐发出了平时不会发出的声音。这下珈特琳了。珈乐躺在乃琳的怀里看着贝拉的直播,乃琳又翻到了刚刚看到的地方。“叮~”乃琳的手机响了,低头一看,是贝拉。乃琳默默地接起电话,没有看到珈乐的目光瞥向她逗弄过贝拉之后,低头看见了满脸怨气的珈乐。轻笑着的乃琳,揉搓着珈乐的脸,开始吃宵夜。犬科动物之间是不是也有食物链呢?
夜已入三更,却见那晚小姐的闺房中依旧亮着微微灯火,若走近细听,还隐隐能听见女子闺房间的玩闹声。“小姐,莫要戏弄婢子了~”只听见嘉姑娘不知怎的,本压得细细的声音稍稍大了些许,但那责备声中明显带着浅浅的媚意。“谁人戏弄你了,本小姐只是在丈量你肚腹究竟有无被那些个吃食撑宽了。”晚小姐一边用嫩藕似的手在嘉姑娘的身子上滑动,一边低声微恼地狠狠说道,“在胡乱言语,仔细你的嘴!”嘉姑娘听见这无赖言语,正想直起身子说些什么,却感觉到那不安分的手竟径直向下滑去,直扑那要命的地方。“小姐!”嘉姑娘连忙伸手阻拦,只刚抓住那只使坏的手,就看见小姐附到了她耳垂旁,那略热的鼻息吹得她心神紊乱。晚小姐眯着眼,在自家小婢的耳边吐气如兰:“那贝拉是不是夜夜与你这么共处一地,嗯?”嘉姑娘闻出了那些些点点的酸味,扑哧一笑,道:“那是在编舞练戏啦,小姐你……竟吃这没由来的飞醋。”晚小姐闻言,秀眉一挑,佯怒道:“好你个奴婢,竟敢笑话本小姐!”,语罢,挑开了那碍事的小手,惊起了一声低呼。
在这个反智横行的年代,只有贝拉的直播给了我感性和理性的认知。她的直播展现出的,是一个人纯粹所具有的良好品质,说不上什么几分特别突兀的地方,整场直播十分的融洽她学习歌曲的机智是精妙的,真诚和正直的朴素给人一种无法接触的高贵感,就好像永远抓不住的闪亮的以太,一个彬彬有礼的人用歌喉给观众带来最为精致的美的感受,我不禁怀疑上帝的天意是否对我太过宠溺,让我人生中认识到如此不朽和无价的灵魂,充满着可爱与美好。我不得不再次审视贝极星,原来他们早已追随如此伟大的事物,想必他们的品行也一定很好。
①鸟山明其实是头号贝极星为了致敬贝拉他在著名漫画《七龙珠》中设计了赛亚人月圆之夜成为猩猩灵感来源自向晚的你划我猜以及龟仙人打爆月亮等桥段。②令人惋惜的是在即将穿透月亮的瞬间贝拉从太空看到嘉然躲在房间吃炸鸡导致分神最终扭伤了腰。③邓丽君小姐从未在任何歌唱比赛赢过贝拉。④大多数含有肉蛋白的食物都对贝拉过敏初生牛犊除外。⑤贝拉很害怕见到蜘蛛她不希望因为自己的念头导致蜘蛛从此消失在宇宙中。⑥由于贝拉练舞场所的重力是千倍所以贝拉没有邻居。⑦因为破坏了贝拉其中一个住所的天花板科拉超深井被迫停工。⑧关于as的二创那些都是贝拉的小号。⑨贝拉很喜欢打羽毛球她说那是台风天最佳的个人运动。⑩贝拉唯一一次失败是在她试图找出自己的弱点。
“你拿你的灵魂和我交换…...”“愿意愿意!”我话还没说完,就被嘉然打断了。她怎么不按套路来?正常情况下,不应该我不断地诱惑嘉然,最后才肯和我交换灵魂的吗?怎么这个小姑娘一上来就满脸兴奋迫不及待地想要和我交换灵魂?不过这些都是小问题,我作为一个死神,要懂得及时处理这些突发事件以及应对这类奇怪的客人。我的工作就是接受人的召唤,去和人交换灵魂。不过不像人们想的那样,不是我威逼利诱想要夺走我们的灵魂,而是人类自己想要和我交换,当然交换途中会遇到些心志不坚的人,或者交换条件太高的,这时我就像个商人一样,费尽唇舌,和我们百般周旋。通常每个人都会考虑上很长时间,今天这个女孩还是第一个一来就想交换灵魂的。“那你要拿你的灵魂和我交换什么?”我缓过神来,平复了下心情,冷冷地问她。“你等我一下哦。”嘉然转身跑进屋子里,回来时竟然穿了一袭白色的婚纱,在我面前轻轻地摆动着纱裙,冲我甜甜地笑着,“我好看吗?”我愣愣了,“很漂亮。”也许是被嘉然惊艳到,片刻后我才发现自己把帽子摘掉了,露出了我那张没有血色的脸。意识到自己失态后我急忙把帽子戴了起来,没想到嘉然却上前制止了我,牵着我的手笑吟吟地说,“我想交换的条件是要你陪我一天。”嘉然想去教堂,我一抬手周围就变了样,偌大的教堂里,只有我们两个。教堂楼顶有群鸽子在那儿扑腾着,在我们头顶盘旋。没有牧师也没有亲朋好友,少女自顾自地念起了证婚词。说道最后,她拉着我的手将一枚戒指递给了我,“我先生,戒指我都准备好了,所以你愿意娶我吗?”嘉然眨着眼看着她,长长的睫毛上流淌着淡淡的金光。“天使小姐你闹够了吗?”我叹了口气,摇摇头说。“什么嘛?你早就认出我来了。”嘉然一噘嘴,有些生气。一双翅膀从她身后伸了出来,黑色的长发也变成了流光的金色。嘉然伸手准备把戒指拿回来,但我却往后退了一步,把它收了起来,自己又拿出了另外一枚戒指。“求婚的话,戒指当然得我自己送你啦。”
这里除了几个老旧的铁皮棚屋之外只剩下粗糙的墙体。再没有当年的霓虹灯塔再没有A-SOUL标志再没有其他连在一起的建筑了。一切当年的闪耀均不复存在只剩下铁皮棚屋上斑驳褪色的女子团伙宣传画。贝极星透过雾气在闪闪发光月亮也升到了空中因而夜晚并不显得黑暗。我依稀能辨别出枝江大厦的每一个部分哪儿曾是夜谈会上扫地机停留的地方哪儿曾是大门哪儿曾放着螺蛳粉味薯片。我一一回忆怀念忽然看见一个孤独的身影这个身影迟疑了一下同时我也惊叫了出来。“嘉然小姐”“我奇怪你怎么还认得出我我完全变了。”确实她的青春艳丽已经消逝然而她那难以言表的端庄华丽她那难以言表的迷人妩媚却依旧当年。所有这些美的诱惑从前我都见过而我以前所没有见过的是她那一对眼睛从前她的双眸总闪着傲气如今却闪着凄凉酸楚的光。我们坐在附近的一张长椅上我说道“多少年如流云般过去嘉然小姐你时常回到这里吗”“我一直没有回来过。”“我也没有。”月亮开始上升邀游夜空我脑海中出现了贝拉注视着白色月亮的宁静目光。嘉然小姐终于打破了我们之间的沉默。“我一直在希望有一天能回来看看可是各种各样的情况使我不能回来。”月光和她的泪珠融合在一起她没有意识到我已经察觉想抑制住自己的情感以平静的语气说道“我时常想到你。”“真的”“特别是近些日子我更常想到你。虽然我生活中有一段很长的艰苦日子但是我不会去想。自从我个人的情况不如意后这些口忆就不得不在我心头占一席之地。”“你永远在我的心里。”我答道。我们又一次沉默无言直到她打破沉寂。“我没有想到”嘉然说道“我到这里来和故地告别竟然又是和你告别我感到很高兴。”“嘉然小姐和我又一次分别你高兴吗可是对我来说上次分别时的悲伤和痛苦永远地萦绕在我的记忆之中。”“可是你上次不是对我说过”嘉然答道“但愿圣嘉然保佑你。你上次能这么对我说你现在也能毫不犹豫地这样对我说但我并不是什么圣嘉然。多年来的痛苦让我受尽折磨但是希望你像从前一样体谅我善待我并且告诉我我俩仍是朋友。”“我俩仍是朋友。”我说着站起身并俯身扶她从长椅上站了起来。“我们虽然分离但愿情意长存。”嘉然说道。我把她的手握在自己手中一同走出这片废墟夜雾也正开始消散。一片广阔的静寂沉浸在月色之中似乎向我表明我和她将永远一起不再分离。
我和她已经冷战很久了,她画她的画,我看我的报,养我的花。我们中间隔着薄薄一层栅栏,却不曾互相道过早安晚安,我祈祷,有一位天使来拯救我们岌岌可危的爱情。羽毛如雪洁白,天生气质优雅的一只鹅,他是天使派来的吗,我想在它把我的拖鞋叼走,把衣服拖得到处都是的时候,我的心里开始怀疑自己祈祷的虔诚。淘气的小鹅它把我们的花园弄得一团糟,我弄碎了她的花瓶,她剪断了我的花朵,脏衣服满地都是,但是啊,虽然是互相埋怨,但好久没和她说过话了,虽然经历岁月的痕迹,她的脸也不再年轻充满活力,但她还是像从前那样,吵架笑出来的话,不就无法进行下去了吗。“我们和好吧”“好”我和她携手把隔离两边花园的栅栏拆了,牵着手目送那只纯白的小天使离开。原来你真的是天使派来拯救我的呀,小鹅。
我一边办公一边看着在第五人格里扮演求生者重启一台又一台发电机成功逃出生天的gamer向晚满怀羡慕。夸张点说嫉妒得我眼睛比手里的烟头还红。告诉你们一个秘密其实我也是求生者你们也是。电话铃突然响起我一扫号码腰立刻矮下半截“喂经理是我是我那个设计您不满意我可以改嘛全部改掉好的好的。”我颤颤巍巍地撂下电话一边重新修改产品一边继续沉思。你看上司和我、甲方和乙方、跑的和抓的、鼠和猫、求生者与妖怪、某种场合下的S和M这个世界上总要有个矛盾矛盾当事人总要以这种形式体现出来。而我似乎总是处在被动的一方当然也没人让我选过并对这种境遇见怪不怪。我有时会觉得SM其实是一种相当和谐的关系因为至少他们偶尔会爱上彼此而上司决不会对我有半个好脸色。而且我听闻SM会在每场游戏开始前设定一个安全词放游戏里叫投降这可以让求生者在感到极度痛苦时结束游戏避免不必要的损失。这简直令我嫉妒得发狂我在现实生活折磨的二十年里可从来没有安全词岂止没有安全词我甚至都不能像游戏里求生者受伤那样大声哀嚎。因为现实是个面子社会里子流血面子总得兜住。那怕你的心已经被戳得千疮百孔想花洒那样往外喷番茄汁你也得对同事家人笑一笑。失去尚可失败无赦一旦痛呼出来就彻底失败了。你以为“别人家的小孩”成绩优异自律自强可能他内心已经被现实整得口球都带上了你以为职场同事一个个西装革履可能拉开就是一身龟甲缚。电话再次响起我接起电话“经理什么已经有人完成了不采用了好的好的没关系没关系。”妈的为什么我一想到现实里并不是向晚玩的游戏那样四个人同心同德逃出生天而是筋疲力竭地互相滴蜡油来竞争一个生存名额我就止不住地流下泪来。

View File

@@ -1,5 +0,0 @@
package fortune
type Conf struct {
Kind map[int64]uint32 `protobuf:"bytes,1,rep" protobuf_key:"varint,1,opt" protobuf_val:"varint,2,opt"`
}

View File

@@ -1,57 +0,0 @@
package fortune
import (
"errors"
io "io"
"os"
"sync"
"github.com/RomiChan/protobuf/proto"
"github.com/FloatTech/ZeroBot-Plugin/utils/file"
)
var (
conf Conf
mu sync.Mutex
)
func loadcfg(name string) error {
name = base + name
if file.IsExist(name) {
f, err := os.Open(name)
if err == nil {
defer f.Close()
data, err1 := io.ReadAll(f)
if err1 == nil {
if len(data) > 0 {
return proto.Unmarshal(data, &conf)
}
}
return err1
}
} else { // 如果没有 cfg则使用空 map
conf.Kind = make(map[int64]uint32)
}
return nil
}
func savecfg(name string) error {
name = base + name
data, err := proto.Marshal(&conf)
if err == nil {
if file.IsExist(base) {
f, err1 := os.OpenFile(name, os.O_WRONLY|os.O_TRUNC|os.O_CREATE, 0644)
if err1 == nil {
mu.Lock()
_, err2 := f.Write(data)
f.Close()
mu.Unlock()
return err2
}
return err1
}
return errors.New("base dir is not exist")
}
return err
}

View File

@@ -35,20 +35,16 @@ var (
// 公主连结 原神 明日方舟 碧蓝航线 碧蓝幻想 战双 阴阳师
table = [...]string{"车万", "DC4", "爱因斯坦", "星空列车", "樱云之恋", "富婆妹", "李清歌", "公主连结", "原神", "明日方舟", "碧蓝航线", "碧蓝幻想", "战双", "阴阳师"}
// 映射底图与 index
index = make(map[string]uint32)
index = make(map[string]uint8)
// 下载锁
dlmu sync.Mutex
)
func init() {
err := loadcfg("cfg.pb")
if err != nil {
panic(err)
}
for i, s := range table {
index[s] = uint32(i)
index[s] = uint8(i)
}
err = os.MkdirAll(base, 0755)
err := os.MkdirAll(base, 0755)
if err != nil {
panic(err)
}
@@ -68,12 +64,16 @@ func init() {
}
i, ok := index[ctx.State["regex_matched"].([]string)[1]]
if ok {
conf.Kind[gid] = i
savecfg("cfg.pb")
ctx.SendChain(message.Text("设置成功~"))
} else {
ctx.SendChain(message.Text("没有这个底图哦~"))
c, ok := control.Lookup("fortune")
if ok {
c.SetData(gid, int64(i)&0xff)
ctx.SendChain(message.Text("设置成功~"))
return
}
ctx.SendChain(message.Text("设置失败!"))
return
}
ctx.SendChain(message.Text("没有这个底图哦~"))
})
en.OnFullMatchGroup([]string{"运势", "抽签"}).SetBlock(true).SecondPriority().
Handle(func(ctx *zero.Ctx) {
@@ -115,8 +115,12 @@ func init() {
gid = -ctx.Event.UserID
}
logrus.Debugln("[fortune]gid:", ctx.Event.GroupID, "uid:", ctx.Event.UserID)
if v, ok := conf.Kind[gid]; ok {
kind = table[v]
c, ok := control.Lookup("fortune")
if ok {
v := uint8(c.GetData(gid) & 0xff)
if int(v) < len(table) {
kind = table[v]
}
}
// 检查背景图片是否存在
folder := base + kind

View File

@@ -47,25 +47,50 @@ func init() { // 插件主体
// 发送结果
switch ctx.State["regex_matched"].([]string)[1] {
case "-p ": // 图片模式
ctx.SendChain(message.Image(
"https://opengraph.githubassets.com/0/"+repo.Get("full_name").Str,
).Add("cache", 0))
default:
ctx.SendChain(message.Text(
repo.Get("full_name").Str, "\n",
"Description: ",
repo.Get("description").Str, "\n",
"Star/Fork/Issue: ",
repo.Get("watchers").Int(), "/", repo.Get("forks").Int(), "/", repo.Get("open_issues").Int(), "\n",
"Language: ",
notnull(repo.Get("language").Str, "None"), "\n",
"License: ",
notnull(strings.ToUpper(repo.Get("license.key").Str), "None"), "\n",
"Last pushed: ",
repo.Get("pushed_at").Str, "\n",
"Jump: ",
repo.Get("html_url").Str, "\n",
))
ctx.SendChain(
message.Image(
"https://opengraph.githubassets.com/0/"+repo.Get("full_name").Str,
).Add("cache", 0),
)
case "-t ": // 文字模式
ctx.SendChain(
message.Text(
repo.Get("full_name").Str, "\n",
"Description: ",
repo.Get("description").Str, "\n",
"Star/Fork/Issue: ",
repo.Get("watchers").Int(), "/", repo.Get("forks").Int(), "/", repo.Get("open_issues").Int(), "\n",
"Language: ",
notnull(repo.Get("language").Str, "None"), "\n",
"License: ",
notnull(strings.ToUpper(repo.Get("license.key").Str), "None"), "\n",
"Last pushed: ",
repo.Get("pushed_at").Str, "\n",
"Jump: ",
repo.Get("html_url").Str, "\n",
),
)
default: // 文字模式
ctx.SendChain(
message.Text(
repo.Get("full_name").Str, "\n",
"Description: ",
repo.Get("description").Str, "\n",
"Star/Fork/Issue: ",
repo.Get("watchers").Int(), "/", repo.Get("forks").Int(), "/", repo.Get("open_issues").Int(), "\n",
"Language: ",
notnull(repo.Get("language").Str, "None"), "\n",
"License: ",
notnull(strings.ToUpper(repo.Get("license.key").Str), "None"), "\n",
"Last pushed: ",
repo.Get("pushed_at").Str, "\n",
"Jump: ",
repo.Get("html_url").Str, "\n",
),
message.Image(
"https://opengraph.githubassets.com/0/"+repo.Get("full_name").Str,
).Add("cache", 0),
)
}
})
}

View File

@@ -17,6 +17,7 @@ import (
"github.com/wdvxdr1123/ZeroBot/extension/rate"
"github.com/wdvxdr1123/ZeroBot/message"
"github.com/FloatTech/ZeroBot-Plugin/control"
"github.com/FloatTech/ZeroBot-Plugin/plugin_manager/timer"
"github.com/FloatTech/ZeroBot-Plugin/utils/file"
"github.com/FloatTech/ZeroBot-Plugin/utils/math"
@@ -38,7 +39,7 @@ const (
"- 修改头衔@QQ XXX\n" +
"- 申请头衔 XXX\n" +
"- 踢出群聊@QQ\n" +
"- 退出群聊 1234\n" +
"- 退出群聊 1234@bot\n" +
"- 群聊转发 1234 XXX\n" +
"- 私聊转发 0000 XXX\n" +
"- 在MM月dd日的hh点mm分时(用http://url)提醒大家XXX\n" +
@@ -58,6 +59,10 @@ var (
limit = rate.NewManager(time.Minute*5, 2)
clock timer.Clock
)
var engine = control.Register("manager", &control.Options{
DisableOnDefault: false,
Help: hint,
})
func init() { // 插件主体
loadConfig()
@@ -65,13 +70,8 @@ func init() { // 插件主体
time.Sleep(time.Second + time.Millisecond*time.Duration(rand.Intn(1000)))
clock = timer.NewClock(timerfile)
}()
// 菜单
zero.OnFullMatch("群管系统", zero.AdminPermission).SetBlock(true).FirstPriority().
Handle(func(ctx *zero.Ctx) {
ctx.SendChain(message.Text(hint))
})
// 升为管理
zero.OnRegex(`^升为管理.*?(\d+)`, zero.OnlyGroup, zero.SuperUserPermission).SetBlock(true).SetPriority(40).
engine.OnRegex(`^升为管理.*?(\d+)`, zero.OnlyGroup, zero.SuperUserPermission).SetBlock(true).SetPriority(40).
Handle(func(ctx *zero.Ctx) {
ctx.SetGroupAdmin(
ctx.Event.GroupID,
@@ -86,7 +86,7 @@ func init() { // 插件主体
ctx.SendChain(message.Text(nickname + " 升为了管理~"))
})
// 取消管理
zero.OnRegex(`^取消管理.*?(\d+)`, zero.OnlyGroup, zero.SuperUserPermission).SetBlock(true).SetPriority(40).
engine.OnRegex(`^取消管理.*?(\d+)`, zero.OnlyGroup, zero.SuperUserPermission).SetBlock(true).SetPriority(40).
Handle(func(ctx *zero.Ctx) {
ctx.SetGroupAdmin(
ctx.Event.GroupID,
@@ -101,7 +101,7 @@ func init() { // 插件主体
ctx.SendChain(message.Text("残念~ " + nickname + " 暂时失去了管理员的资格"))
})
// 踢出群聊
zero.OnRegex(`^踢出群聊.*?(\d+)`, zero.OnlyGroup, zero.AdminPermission).SetBlock(true).SetPriority(40).
engine.OnRegex(`^踢出群聊.*?(\d+)`, zero.OnlyGroup, zero.AdminPermission).SetBlock(true).SetPriority(40).
Handle(func(ctx *zero.Ctx) {
ctx.SetGroupKick(
ctx.Event.GroupID,
@@ -116,7 +116,7 @@ func init() { // 插件主体
ctx.SendChain(message.Text("残念~ " + nickname + " 被放逐"))
})
// 退出群聊
zero.OnRegex(`^退出群聊.*?(\d+)`, zero.OnlyGroup, zero.AdminPermission).SetBlock(true).SetPriority(40).
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]), // 要退出的群的群号
@@ -124,7 +124,7 @@ func init() { // 插件主体
)
})
// 开启全体禁言
zero.OnRegex(`^开启全员禁言$`, zero.OnlyGroup, zero.AdminPermission).SetBlock(true).SetPriority(40).
engine.OnRegex(`^开启全员禁言$`, zero.OnlyGroup, zero.AdminPermission).SetBlock(true).SetPriority(40).
Handle(func(ctx *zero.Ctx) {
ctx.SetGroupWholeBan(
ctx.Event.GroupID,
@@ -133,7 +133,7 @@ func init() { // 插件主体
ctx.SendChain(message.Text("全员自闭开始~"))
})
// 解除全员禁言
zero.OnRegex(`^解除全员禁言$`, zero.OnlyGroup, zero.AdminPermission).SetBlock(true).SetPriority(40).
engine.OnRegex(`^解除全员禁言$`, zero.OnlyGroup, zero.AdminPermission).SetBlock(true).SetPriority(40).
Handle(func(ctx *zero.Ctx) {
ctx.SetGroupWholeBan(
ctx.Event.GroupID,
@@ -142,7 +142,7 @@ func init() { // 插件主体
ctx.SendChain(message.Text("全员自闭结束~"))
})
// 禁言
zero.OnRegex(`^禁言.*?(\d+).*?\s(\d+)(.*)`, zero.OnlyGroup, zero.AdminPermission).SetBlock(true).SetPriority(40).
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])
switch ctx.State["regex_matched"].([]string)[3] {
@@ -166,7 +166,7 @@ func init() { // 插件主体
ctx.SendChain(message.Text("小黑屋收留成功~"))
})
// 解除禁言
zero.OnRegex(`^解除禁言.*?(\d+)`, zero.OnlyGroup, zero.AdminPermission).SetBlock(true).SetPriority(40).
engine.OnRegex(`^解除禁言.*?(\d+)`, zero.OnlyGroup, zero.AdminPermission).SetBlock(true).SetPriority(40).
Handle(func(ctx *zero.Ctx) {
ctx.SetGroupBan(
ctx.Event.GroupID,
@@ -176,7 +176,7 @@ func init() { // 插件主体
ctx.SendChain(message.Text("小黑屋释放成功~"))
})
// 自闭禁言
zero.OnRegex(`^(我要自闭|禅定).*?(\d+)(.*)`, zero.OnlyGroup).SetBlock(true).SetPriority(40).
engine.OnRegex(`^(我要自闭|禅定).*?(\d+)(.*)`, zero.OnlyGroup).SetBlock(true).SetPriority(40).
Handle(func(ctx *zero.Ctx) {
duration := strToInt(ctx.State["regex_matched"].([]string)[2])
switch ctx.State["regex_matched"].([]string)[3] {
@@ -200,7 +200,7 @@ func init() { // 插件主体
ctx.SendChain(message.Text("那我就不手下留情了~"))
})
// 修改名片
zero.OnRegex(`^修改名片.*?(\d+).*?\s(.*)`, zero.OnlyGroup, zero.AdminPermission).SetBlock(true).SetPriority(40).
engine.OnRegex(`^修改名片.*?(\d+).*?\s(.*)`, zero.OnlyGroup, zero.AdminPermission).SetBlock(true).SetPriority(40).
Handle(func(ctx *zero.Ctx) {
ctx.SetGroupCard(
ctx.Event.GroupID,
@@ -210,7 +210,7 @@ func init() { // 插件主体
ctx.SendChain(message.Text("嗯!已经修改了"))
})
// 修改头衔
zero.OnRegex(`^修改头衔.*?(\d+).*?\s(.*)`, zero.OnlyGroup, zero.AdminPermission).SetBlock(true).SetPriority(40).
engine.OnRegex(`^修改头衔.*?(\d+).*?\s(.*)`, zero.OnlyGroup, zero.AdminPermission).SetBlock(true).SetPriority(40).
Handle(func(ctx *zero.Ctx) {
ctx.SetGroupSpecialTitle(
ctx.Event.GroupID,
@@ -220,7 +220,7 @@ func init() { // 插件主体
ctx.SendChain(message.Text("嗯!已经修改了"))
})
// 申请头衔
zero.OnRegex(`^申请头衔(.*)`, zero.OnlyGroup).SetBlock(true).SetPriority(40).
engine.OnRegex(`^申请头衔(.*)`, zero.OnlyGroup).SetBlock(true).SetPriority(40).
Handle(func(ctx *zero.Ctx) {
ctx.SetGroupSpecialTitle(
ctx.Event.GroupID,
@@ -230,7 +230,7 @@ func init() { // 插件主体
ctx.SendChain(message.Text("嗯!不错的头衔呢~"))
})
// 群聊转发
zero.OnRegex(`^群聊转发.*?(\d+)\s(.*)`, zero.SuperUserPermission).SetBlock(true).SetPriority(40).
engine.OnRegex(`^群聊转发.*?(\d+)\s(.*)`, zero.SuperUserPermission).SetBlock(true).SetPriority(40).
Handle(func(ctx *zero.Ctx) {
// 对CQ码进行反转义
content := ctx.State["regex_matched"].([]string)[2]
@@ -243,7 +243,7 @@ func init() { // 插件主体
ctx.SendChain(message.Text("📧 --> " + ctx.State["regex_matched"].([]string)[1]))
})
// 私聊转发
zero.OnRegex(`^私聊转发.*?(\d+)\s(.*)`, zero.SuperUserPermission).SetBlock(true).SetPriority(40).
engine.OnRegex(`^私聊转发.*?(\d+)\s(.*)`, zero.SuperUserPermission).SetBlock(true).SetPriority(40).
Handle(func(ctx *zero.Ctx) {
// 对CQ码进行反转义
content := ctx.State["regex_matched"].([]string)[2]
@@ -256,7 +256,7 @@ func init() { // 插件主体
ctx.SendChain(message.Text("📧 --> " + ctx.State["regex_matched"].([]string)[1]))
})
// 定时提醒
zero.OnRegex(`^在(.{1,2})月(.{1,3}日|每?周.?)的(.{1,3})点(.{1,3})分时(用.+)?提醒大家(.*)`, zero.AdminPermission, zero.OnlyGroup).SetBlock(true).SetPriority(40).
engine.OnRegex(`^在(.{1,2})月(.{1,3}日|每?周.?)的(.{1,3})点(.{1,3})分时(用.+)?提醒大家(.*)`, zero.AdminPermission, zero.OnlyGroup).SetBlock(true).SetPriority(40).
Handle(func(ctx *zero.Ctx) {
dateStrs := ctx.State["regex_matched"].([]string)
ts := timer.GetFilledTimer(dateStrs, ctx.Event.SelfID, false)
@@ -268,7 +268,7 @@ func init() { // 插件主体
}
})
// 定时 cron 提醒
zero.OnRegex(`^在"(.*)"时(用.+)?提醒大家(.*)`, zero.AdminPermission, zero.OnlyGroup).SetBlock(true).SetPriority(40).
engine.OnRegex(`^在"(.*)"时(用.+)?提醒大家(.*)`, zero.AdminPermission, zero.OnlyGroup).SetBlock(true).SetPriority(40).
Handle(func(ctx *zero.Ctx) {
dateStrs := ctx.State["regex_matched"].([]string)
var url, alert string
@@ -291,7 +291,7 @@ func init() { // 插件主体
}
})
// 取消定时
zero.OnRegex(`^取消在(.{1,2})月(.{1,3}日|每?周.?)的(.{1,3})点(.{1,3})分的提醒`, zero.AdminPermission, zero.OnlyGroup).SetBlock(true).SetPriority(40).
engine.OnRegex(`^取消在(.{1,2})月(.{1,3}日|每?周.?)的(.{1,3})点(.{1,3})分的提醒`, zero.AdminPermission, zero.OnlyGroup).SetBlock(true).SetPriority(40).
Handle(func(ctx *zero.Ctx) {
dateStrs := ctx.State["regex_matched"].([]string)
ts := timer.GetFilledTimer(dateStrs, ctx.Event.SelfID, true)
@@ -304,7 +304,7 @@ func init() { // 插件主体
}
})
// 取消 cron 定时
zero.OnRegex(`^取消在"(.*)"的提醒`, zero.AdminPermission, zero.OnlyGroup).SetBlock(true).SetPriority(40).
engine.OnRegex(`^取消在"(.*)"的提醒`, zero.AdminPermission, zero.OnlyGroup).SetBlock(true).SetPriority(40).
Handle(func(ctx *zero.Ctx) {
dateStrs := ctx.State["regex_matched"].([]string)
ts := timer.Timer{Cron: dateStrs[1]}
@@ -317,12 +317,12 @@ func init() { // 插件主体
}
})
// 列出本群所有定时
zero.OnFullMatch("列出所有提醒", zero.AdminPermission, zero.OnlyGroup).SetBlock(true).SetPriority(40).
engine.OnFullMatch("列出所有提醒", zero.AdminPermission, zero.OnlyGroup).SetBlock(true).SetPriority(40).
Handle(func(ctx *zero.Ctx) {
ctx.SendChain(message.Text(clock.ListTimers(ctx.Event.GroupID)))
})
// 随机点名
zero.OnFullMatchGroup([]string{"翻牌"}, zero.OnlyGroup).SetBlock(true).SetPriority(40).
engine.OnFullMatchGroup([]string{"翻牌"}, zero.OnlyGroup).SetBlock(true).SetPriority(40).
Handle(func(ctx *zero.Ctx) {
if !limit.Load(ctx.Event.UserID).Acquire() {
ctx.SendChain(message.Text("少女祈祷中......"))
@@ -360,7 +360,7 @@ func init() { // 插件主体
)
})
// 入群欢迎
zero.OnNotice().SetBlock(false).FirstPriority().
engine.OnNotice().SetBlock(false).FirstPriority().
Handle(func(ctx *zero.Ctx) {
if ctx.Event.NoticeType == "group_increase" && ctx.Event.SelfID != ctx.Event.UserID {
word, ok := config.Welcome[ctx.Event.GroupID]
@@ -408,14 +408,16 @@ func init() { // 插件主体
}
})
// 退群提醒
zero.OnNotice().SetBlock(false).SetPriority(40).
engine.OnNotice().SetBlock(false).SetPriority(40).
Handle(func(ctx *zero.Ctx) {
if ctx.Event.NoticeType == "group_decrease" {
ctx.SendChain(message.Text("有人跑路了~"))
userid := ctx.Event.UserID
nickname := ctx.GetStrangerInfo(userid, false).Get("nickname").String()
ctx.SendChain(message.Text(nickname, "(", userid, ")", "离开了我们..."))
}
})
// 设置欢迎语
zero.OnRegex(`^设置欢迎语([\s\S]*)$`, zero.OnlyGroup, zero.AdminPermission).SetBlock(true).SetPriority(40).
engine.OnRegex(`^设置欢迎语([\s\S]*)$`, zero.OnlyGroup, zero.AdminPermission).SetBlock(true).SetPriority(40).
Handle(func(ctx *zero.Ctx) {
config.Welcome[ctx.Event.GroupID] = ctx.State["regex_matched"].([]string)[1]
if saveConfig() == nil {
@@ -425,7 +427,7 @@ func init() { // 插件主体
}
})
// 入群验证开关
zero.OnRegex(`^(.*)入群验证$`, zero.OnlyGroup, zero.AdminPermission).SetBlock(true).SetPriority(40).
engine.OnRegex(`^(.*)入群验证$`, zero.OnlyGroup, zero.AdminPermission).SetBlock(true).SetPriority(40).
Handle(func(ctx *zero.Ctx) {
option := ctx.State["regex_matched"].([]string)[1]
switch option {
@@ -443,7 +445,7 @@ func init() { // 插件主体
}
})
// 运行 CQ 码
zero.OnRegex(`^run(.*)$`, zero.SuperUserPermission).SetBlock(true).SetPriority(0).
engine.OnRegex(`^run(.*)$`, zero.SuperUserPermission).SetBlock(true).SetPriority(0).
Handle(func(ctx *zero.Ctx) {
var cmd = ctx.State["regex_matched"].([]string)[1]
cmd = strings.ReplaceAll(cmd, "&#91;", "[")
@@ -451,6 +453,17 @@ func init() { // 插件主体
// 可注入,权限为主人
ctx.Send(cmd)
})
// 自动同意加好友,被邀请入群(从qingyunke移过来先注释)
/*
engine.OnRequest().SetBlock(false).FirstPriority().Handle(func(ctx *zero.Ctx) {
if ctx.Event.RequestType == "friend" {
ctx.SetFriendAddRequest(ctx.Event.Flag, true, "")
}
if ctx.Event.RequestType == "group" && ctx.Event.SubType == "invite" {
ctx.SetGroupAddRequest(ctx.Event.Flag, "invite", true, "我爱你mua~")
}
})
*/
}
func strToInt(str string) int64 {

View File

@@ -22,7 +22,7 @@ func init() { // 插件主体
DisableOnDefault: true,
Help: "moyu\n" +
"- 添加摸鱼提醒\n" +
"- 删除摸鱼提醒\n",
"- 删除摸鱼提醒",
}).OnFullMatch("删除摸鱼提醒", zero.OnlyGroup, zero.AdminPermission).SetBlock(true).SetPriority(20).
Handle(func(ctx *zero.Ctx) {
m, ok := control.Lookup("moyu")

View File

@@ -4,12 +4,13 @@ import (
"fmt"
"os"
"github.com/FloatTech/ZeroBot-Plugin/control"
"github.com/FloatTech/ZeroBot-Plugin/utils/rule"
"github.com/sirupsen/logrus"
zero "github.com/wdvxdr1123/ZeroBot"
"github.com/wdvxdr1123/ZeroBot/message"
"github.com/wdvxdr1123/ZeroBot/utils/helper"
"github.com/FloatTech/ZeroBot-Plugin/control"
"github.com/FloatTech/ZeroBot-Plugin/utils/rule"
)
const (

View File

@@ -65,13 +65,15 @@ func init() {
}
})
// 上传一张图
engine.OnKeyword("添加wife", zero.OnlyGroup, chkAddWifePermission, picture.MustGiven).SetBlock(true).SetPriority(20).
engine.OnPrefix("添加wife", zero.OnlyGroup, chkAddWifePermission, picture.MustGiven).SetBlock(true).SetPriority(20).
Handle(func(ctx *zero.Ctx) {
name := ""
for _, elem := range ctx.Event.Message {
if elem.Type == "text" {
name = strings.ReplaceAll(elem.Data["text"], " ", "")
name = name[strings.LastIndex(name, "添加wife")+10:]
name = strings.ReplaceAll(name, "/", "")
name = strings.ReplaceAll(name, "\\", "")
break
}
}
@@ -98,6 +100,8 @@ func init() {
if elem.Type == "text" {
name = strings.ReplaceAll(elem.Data["text"], " ", "")
name = name[strings.LastIndex(name, "删除wife")+10:]
name = strings.ReplaceAll(name, "/", "")
name = strings.ReplaceAll(name, "\\", "")
break
}
}

40
plugin_omikuji/data.go Normal file
View File

@@ -0,0 +1,40 @@
package omikuji
import (
"os"
log "github.com/sirupsen/logrus"
"github.com/FloatTech/ZeroBot-Plugin/utils/file"
"github.com/FloatTech/ZeroBot-Plugin/utils/process"
"github.com/FloatTech/ZeroBot-Plugin/utils/sql"
)
const (
dbpath = "data/Omikuji/"
dbfile = dbpath + "kuji.db"
)
var db = &sql.Sqlite{DBPath: dbfile}
func init() {
go func() {
defer func() {
if err := recover(); err != nil {
log.Println(err)
}
}()
process.SleepAbout1sTo2s()
_ = os.MkdirAll(dbpath, 0755)
_, _ = file.GetLazyData(dbfile, false, true)
err := db.Create("kuji", &kuji{})
if err != nil {
panic(err)
}
n, err := db.Count("kuji")
if err != nil {
panic(err)
}
log.Printf("[kuji]读取%d条签文", n)
}()
}

View File

@@ -0,0 +1,46 @@
package main
import (
"fmt"
"os"
"strconv"
"github.com/FloatTech/ZeroBot-Plugin/utils/sql"
)
type signature struct {
Id uint64 `db:"id"`
Text string `db:"text"`
}
type kuji struct {
Id uint8 `db:"id"`
Text string `db:"text"`
}
func main() {
db := &sql.Sqlite{DBPath: os.Args[1]}
newdb := &sql.Sqlite{DBPath: os.Args[2]}
err := newdb.Create("kuji", &kuji{})
if err != nil {
panic(err)
}
err = db.Create("signature", &signature{})
if err != nil {
panic(err)
}
fmt.Println(db.Count("signature"))
s := &signature{}
k := &kuji{}
for i := 1; i <= 100; i++ {
db.Find("signature", s, "where id = "+strconv.Itoa(i))
fmt.Println("insert: ", s.Text[:57])
k.Id = uint8(i)
k.Text = s.Text
newdb.Insert("kuji", k)
}
db.Close()
newdb.Close()
}

18
plugin_omikuji/model.go Normal file
View File

@@ -0,0 +1,18 @@
package omikuji
import "strconv"
type kuji struct {
Id uint8 `db:"id"`
Text string `db:"text"`
}
// 返回一个解签
func getKujiByBango(id uint8) string {
var s kuji
err := db.Find("kuji", &s, "where id = "+strconv.Itoa(int(id)))
if err != nil {
return err.Error()
}
return s.Text
}

View File

@@ -4,31 +4,54 @@ package omikuji
import (
"fmt"
"math/rand"
"strconv"
"time"
log "github.com/sirupsen/logrus"
"github.com/FloatTech/ZeroBot-Plugin/control"
zero "github.com/wdvxdr1123/ZeroBot"
"github.com/wdvxdr1123/ZeroBot/message"
"github.com/FloatTech/ZeroBot-Plugin/control"
)
const (
bed = "https://codechina.csdn.net/u011570312/senso-ji-omikuji/-/raw/main/%d_%d.jpg"
)
func init() { // 插件主体
rand.Seed(time.Now().UnixNano())
control.Register("omikuji", &control.Options{
var (
engine = control.Register("omikuji", &control.Options{
DisableOnDefault: false,
Help: "浅草寺求签\n" +
"- 求签|占卜",
}).OnFullMatchGroup([]string{"求签", "占卜"}).SetPriority(10).SetBlock(true).
"- 求签|占卜\n- 解签",
})
)
func init() { // 插件主体
engine.OnFullMatchGroup([]string{"求签", "占卜"}).SetPriority(10).SetBlock(true).
Handle(func(ctx *zero.Ctx) {
miku := rand.Intn(100) + 1
miku := bangoToday(ctx.Event.UserID)
ctx.SendChain(
message.At(ctx.Event.UserID),
message.Image(fmt.Sprintf(bed, miku, 0)),
message.Image(fmt.Sprintf(bed, miku, 1)),
)
})
engine.OnFullMatchGroup([]string{"解签"}).SetPriority(10).SetBlock(true).
Handle(func(ctx *zero.Ctx) {
ctx.SendChain(
message.At(ctx.Event.UserID),
message.Text(getKujiByBango(bangoToday(ctx.Event.UserID))),
)
})
}
func bangoToday(uid int64) uint8 {
today, err := strconv.ParseInt(time.Now().Format("20060102"), 10, 64)
if err != nil {
log.Errorln("string转化为int64格式有问题:", err)
}
seed := uid + today
r := rand.New(rand.NewSource(seed))
return uint8(r.Intn(100) + 1)
}

View File

@@ -32,14 +32,14 @@ func init() { // 插件主体
Help: "青云客\n" +
"- @Bot 任意文本(任意一句话回复)",
})
// 回复 匹配中文、英文、数字、空格但不包括下划线等符号
engine.OnRegex("^([\u4E00-\u9FA5A-Za-z0-9\\s]{1,30})", zero.OnlyToMe).SetBlock(true).SetPriority(prio).
// 回复 @和包括名字
engine.OnMessage(zero.OnlyToMe).SetBlock(true).SetPriority(prio).
Handle(func(ctx *zero.Ctx) {
if !bucket.Load(ctx.Event.UserID).Acquire() {
// 频繁触发,不回复
return
}
msg := ctx.State["regex_matched"].([]string)[1]
msg := ctx.ExtractPlainText()
// 调用青云客接口
reply, err := getMessage(msg)
if err != nil {

View File

@@ -1,21 +0,0 @@
package qingyunke
// TODO: 移动到 manager 搭配自动验证使用
/*
import (
zero "github.com/wdvxdr1123/ZeroBot"
)
//自动同意加群,加好友
func init() {
zero.OnRequest().SetBlock(false).FirstPriority().Handle(func(ctx *zero.Ctx) {
if ctx.Event.RequestType == "friend" {
ctx.SetFriendAddRequest(ctx.Event.Flag, true, "")
}
if ctx.Event.RequestType == "group" && ctx.Event.SubType == "invite" {
ctx.SetGroupAddRequest(ctx.Event.Flag, "invite", true, "我爱你mua~")
}
})
}
*/

View File

@@ -2,8 +2,6 @@ package reborn
import (
"encoding/json"
"io"
"net/http"
"os"
wr "github.com/mroth/weightedrand"
@@ -16,7 +14,6 @@ import (
const (
datapath = "data/Reborn"
jsonfile = datapath + "/rate.json"
pburl = "https://codechina.csdn.net/u011570312/ZeroBot-Plugin/-/raw/master/" + jsonfile
)
type rate []struct {
@@ -55,39 +52,9 @@ func init() {
// load 加载rate数据
func load(area *rate) error {
if file.IsExist(jsonfile) {
f, err := os.Open(jsonfile)
if err == nil {
defer f.Close()
data, err1 := io.ReadAll(f)
if err1 == nil {
if len(data) > 0 {
return json.Unmarshal(data, area)
}
}
return err1
}
} else { // 如果没有小作文,则从 url 下载
f, err := os.Create(jsonfile)
if err != nil {
return err
}
defer f.Close()
resp, err := http.Get(pburl)
if err == nil {
defer resp.Body.Close()
if resp.ContentLength > 0 {
log.Printf("[Reborn]从镜像下载国家和地区%d字节...", resp.ContentLength)
data, err := io.ReadAll(resp.Body)
if err == nil && len(data) > 0 {
_, _ = f.Write(data)
return json.Unmarshal(data, area)
}
return err
}
return nil
}
data, err := file.GetLazyData(jsonfile, true, true)
if err != nil {
return err
}
return nil
return json.Unmarshal(data, area)
}

View File

@@ -3,8 +3,6 @@ package setutime
import (
"fmt"
"io"
"net/http"
"os"
"strconv"
"strings"
@@ -12,7 +10,6 @@ import (
"time"
"github.com/FloatTech/AnimeAPI/pixiv"
"github.com/sirupsen/logrus"
zero "github.com/wdvxdr1123/ZeroBot"
"github.com/wdvxdr1123/ZeroBot/extension/rate"
"github.com/wdvxdr1123/ZeroBot/message"
@@ -20,6 +17,7 @@ import (
"github.com/FloatTech/ZeroBot-Plugin/control"
fileutil "github.com/FloatTech/ZeroBot-Plugin/utils/file"
"github.com/FloatTech/ZeroBot-Plugin/utils/math"
"github.com/FloatTech/ZeroBot-Plugin/utils/process"
"github.com/FloatTech/ZeroBot-Plugin/utils/rule"
"github.com/FloatTech/ZeroBot-Plugin/utils/sql"
)
@@ -36,10 +34,6 @@ type imgpool struct {
Form int64
}
const (
dburl = "https://codechina.csdn.net/u011570312/ZeroBot-Plugin/-/raw/master/data/SetuTime/SetuTime.db"
)
// NewPoolsCache 返回一个缓冲池对象
func newPools() *imgpool {
cache := &imgpool{
@@ -58,39 +52,7 @@ func newPools() *imgpool {
panic(err)
}
// 如果数据库不存在则下载
if _, err := os.Stat(cache.DB.DBPath); err != nil || os.IsNotExist(err) {
down := func() (err error) {
// 下载
resp, err := http.Get(dburl)
if err != nil {
return
}
defer resp.Body.Close()
if resp.ContentLength > 0 {
return
}
logrus.Printf("[Setu]从镜像下载数据库%d字节...", resp.ContentLength)
// 生成文件
f, err := os.Create(cache.DB.DBPath)
if err != nil {
return
}
defer f.Close()
// 读取数据
data, err := io.ReadAll(resp.Body)
if err != nil || len(data) > 0 {
return
}
// 写入数据
if _, err = f.Write(data); err != nil {
return
}
return nil
}
if err := down(); err != nil {
logrus.Printf("[Setu]下载数据库失败%v", err)
}
}
_, _ = fileutil.GetLazyData(cache.DB.DBPath, false, false)
for i := range cache.List {
if err := cache.DB.Create(cache.List[i], &pixiv.Illust{}); err != nil {
panic(err)
@@ -100,123 +62,127 @@ func newPools() *imgpool {
}
var (
pool = newPools()
pool *imgpool
limit = rate.NewManager(time.Minute*1, 5)
)
func init() { // 插件主体
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() {
ctx.SendChain(message.Text("请稍后重试0x0..."))
return
}
var imgtype = ctx.State["regex_matched"].([]string)[1]
// 补充池子
go func() {
times := math.Min(pool.Max-pool.size(imgtype), 2)
for i := 0; i < times; i++ {
illust := &pixiv.Illust{}
// 查询出一张图片
if err := pool.DB.Pick(imgtype, illust); err != nil {
ctx.SendChain(message.Text("ERROR: ", err))
continue
}
// 下载图片
if err := download(illust, pool.Path); err != nil {
ctx.SendChain(message.Text("ERROR: ", err))
continue
}
ctx.SendGroupMessage(pool.Group, []message.MessageSegment{message.Image(file(illust))})
// 向缓冲池添加一张图片
pool.push(imgtype, illust)
time.Sleep(time.Second * 1)
}
}()
// 如果没有缓存阻塞5秒
if pool.size(imgtype) == 0 {
ctx.SendChain(message.Text("INFO: 正在填充弹药......"))
<-time.After(time.Second * 5)
if pool.size(imgtype) == 0 {
ctx.SendChain(message.Text("ERROR: 等待填充,请稍后再试......"))
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() {
ctx.SendChain(message.Text("请稍后重试0x0..."))
return
}
}
// 从缓冲池里抽一张
if id := ctx.SendChain(message.Image(file(pool.pop(imgtype)))); id == 0 {
ctx.SendChain(message.Text("ERROR: 可能被风控了"))
}
})
engine.OnRegex(`^添加(.*?)(\d+)$`, rule.FirstValueInList(pool.List), zero.SuperUserPermission).SetBlock(true).SetPriority(21).
Handle(func(ctx *zero.Ctx) {
var (
imgtype = ctx.State["regex_matched"].([]string)[1]
id, _ = strconv.ParseInt(ctx.State["regex_matched"].([]string)[2], 10, 64)
)
ctx.SendChain(message.Text("少女祈祷中......"))
// 查询P站插图信息
illust, err := pixiv.Works(id)
if err != nil {
ctx.SendChain(message.Text("ERROR: ", err))
return
}
// 下载插画
if err := download(illust, pool.Path); err != nil {
ctx.SendChain(message.Text("ERROR: ", err))
return
}
// 发送到发送者
if id := ctx.SendChain(message.Image(file(illust))); id == 0 {
ctx.SendChain(message.Text("ERROR: 可能被风控,发送失败"))
return
}
// 添加插画到对应的数据库table
if err := pool.DB.Insert(imgtype, illust); err != nil {
ctx.SendChain(message.Text("ERROR: ", err))
return
}
ctx.SendChain(message.Text("添加成功"))
})
engine.OnRegex(`^删除(.*?)(\d+)$`, rule.FirstValueInList(pool.List), zero.SuperUserPermission).SetBlock(true).SetPriority(22).
Handle(func(ctx *zero.Ctx) {
var (
imgtype = ctx.State["regex_matched"].([]string)[1]
id, _ = strconv.ParseInt(ctx.State["regex_matched"].([]string)[2], 10, 64)
)
// 查询数据库
if err := pool.DB.Del(imgtype, fmt.Sprintf("WHERE pid=%d", id)); err != nil {
ctx.SendChain(message.Text("ERROR: ", err))
return
}
ctx.SendChain(message.Text("删除成功"))
})
// 查询数据库涩图数量
engine.OnFullMatchGroup([]string{">setu status"}).SetBlock(true).SetPriority(23).
Handle(func(ctx *zero.Ctx) {
state := []string{"[SetuTime]"}
for i := range pool.List {
num, err := pool.DB.Count(pool.List[i])
if err != nil {
num = 0
var imgtype = ctx.State["regex_matched"].([]string)[1]
// 补充池子
go func() {
times := math.Min(pool.Max-pool.size(imgtype), 2)
for i := 0; i < times; i++ {
illust := &pixiv.Illust{}
// 查询出一张图片
if err := pool.DB.Pick(imgtype, illust); err != nil {
ctx.SendChain(message.Text("ERROR: ", err))
continue
}
// 下载图片
if err := download(illust, pool.Path); err != nil {
ctx.SendChain(message.Text("ERROR: ", err))
continue
}
ctx.SendGroupMessage(pool.Group, []message.MessageSegment{message.Image(file(illust))})
// 向缓冲池添加一张图片
pool.push(imgtype, illust)
time.Sleep(time.Second * 1)
}
}()
// 如果没有缓存阻塞5秒
if pool.size(imgtype) == 0 {
ctx.SendChain(message.Text("INFO: 正在填充弹药......"))
<-time.After(time.Second * 5)
if pool.size(imgtype) == 0 {
ctx.SendChain(message.Text("ERROR: 等待填充,请稍后再试......"))
return
}
}
state = append(state, "\n")
state = append(state, pool.List[i])
state = append(state, ": ")
state = append(state, fmt.Sprintf("%d", num))
}
ctx.SendChain(message.Text(state))
})
// 从缓冲池里抽一张
if id := ctx.SendChain(message.Image(file(pool.pop(imgtype)))); id == 0 {
ctx.SendChain(message.Text("ERROR: 可能被风控了"))
}
})
engine.OnRegex(`^添加(.*?)(\d+)$`, rule.FirstValueInList(pool.List), zero.SuperUserPermission).SetBlock(true).SetPriority(21).
Handle(func(ctx *zero.Ctx) {
var (
imgtype = ctx.State["regex_matched"].([]string)[1]
id, _ = strconv.ParseInt(ctx.State["regex_matched"].([]string)[2], 10, 64)
)
ctx.SendChain(message.Text("少女祈祷中......"))
// 查询P站插图信息
illust, err := pixiv.Works(id)
if err != nil {
ctx.SendChain(message.Text("ERROR: ", err))
return
}
// 下载插画
if err := download(illust, pool.Path); err != nil {
ctx.SendChain(message.Text("ERROR: ", err))
return
}
// 发送到发送者
if id := ctx.SendChain(message.Image(file(illust))); id == 0 {
ctx.SendChain(message.Text("ERROR: 可能被风控,发送失败"))
return
}
// 添加插画到对应的数据库table
if err := pool.DB.Insert(imgtype, illust); err != nil {
ctx.SendChain(message.Text("ERROR: ", err))
return
}
ctx.SendChain(message.Text("添加成功"))
})
engine.OnRegex(`^删除(.*?)(\d+)$`, rule.FirstValueInList(pool.List), zero.SuperUserPermission).SetBlock(true).SetPriority(22).
Handle(func(ctx *zero.Ctx) {
var (
imgtype = ctx.State["regex_matched"].([]string)[1]
id, _ = strconv.ParseInt(ctx.State["regex_matched"].([]string)[2], 10, 64)
)
// 查询数据库
if err := pool.DB.Del(imgtype, fmt.Sprintf("WHERE pid=%d", id)); err != nil {
ctx.SendChain(message.Text("ERROR: ", err))
return
}
ctx.SendChain(message.Text("删除成功"))
})
// 查询数据库涩图数量
engine.OnFullMatchGroup([]string{">setu status"}).SetBlock(true).SetPriority(23).
Handle(func(ctx *zero.Ctx) {
state := []string{"[SetuTime]"}
for i := range pool.List {
num, err := pool.DB.Count(pool.List[i])
if err != nil {
num = 0
}
state = append(state, "\n")
state = append(state, pool.List[i])
state = append(state, ": ")
state = append(state, fmt.Sprintf("%d", num))
}
ctx.SendChain(message.Text(state))
})
}()
}
// size 返回缓冲池指定类型的现有大小

View File

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

View File

@@ -0,0 +1,114 @@
package model
import (
"os"
"time"
"github.com/jinzhu/gorm"
_ "github.com/logoove/sqlite"
log "github.com/sirupsen/logrus"
)
type SleepDB gorm.DB
func Initialize(dbpath string) *SleepDB {
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(&SleepManage{})
return (*SleepDB)(gdb)
}
func Open(dbpath string) (*SleepDB, error) {
db, err := gorm.Open("sqlite3", dbpath)
if err != nil {
return nil, err
} else {
return (*SleepDB)(db), nil
}
}
func (sdb *SleepDB) Close() error {
db := (*gorm.DB)(sdb)
return db.Close()
}
type SleepManage struct {
gorm.Model
GroupId int64 `gorm:"column:group_id"`
UserId int64 `gorm:"column:user_id"`
SleepTime time.Time `gorm:"column:sleep_time"`
}
func (SleepManage) TableName() string {
return "sleep_manage"
}
// 更新睡眠时间
func (sdb *SleepDB) Sleep(groupId, userId int64) (position int, awakeTime time.Duration) {
db := (*gorm.DB)(sdb)
now := time.Now()
var today time.Time
if now.Hour() >= 21 {
today = now.Add(-time.Hour*time.Duration(-21+now.Hour()) - time.Minute*time.Duration(now.Minute()) - time.Second*time.Duration(now.Second()))
} else if now.Hour() <= 3 {
today = now.Add(-time.Hour*time.Duration(3+now.Hour()) - time.Minute*time.Duration(now.Minute()) - time.Second*time.Duration(now.Second()))
}
st := SleepManage{
GroupId: groupId,
UserId: userId,
SleepTime: now,
}
if err := db.Debug().Model(&SleepManage{}).Where("group_id = ? and user_id = ?", groupId, userId).First(&st).Error; err != nil {
// error handling...
if gorm.IsRecordNotFoundError(err) {
db.Debug().Model(&SleepManage{}).Create(&st) // newUser not user
}
} else {
log.Println("sleeptime为", st)
awakeTime = now.Sub(st.SleepTime)
db.Debug().Model(&SleepManage{}).Where("group_id = ? and user_id = ?", groupId, userId).Update(
map[string]interface{}{
"sleep_time": now,
})
}
db.Debug().Model(&SleepManage{}).Where("group_id = ? and sleep_time <= ? and sleep_time >= ?", groupId, now, today).Count(&position)
return position, awakeTime
}
// 更新起床时间
func (sdb *SleepDB) GetUp(groupId, userId int64) (position int, sleepTime time.Duration) {
db := (*gorm.DB)(sdb)
now := time.Now()
today := now.Add(-time.Hour*time.Duration(-6+now.Hour()) - time.Minute*time.Duration(now.Minute()) - time.Second*time.Duration(now.Second()))
st := SleepManage{
GroupId: groupId,
UserId: userId,
SleepTime: now,
}
if err := db.Debug().Model(&SleepManage{}).Where("group_id = ? and user_id = ?", groupId, userId).First(&st).Error; err != nil {
// error handling...
if gorm.IsRecordNotFoundError(err) {
db.Debug().Model(&SleepManage{}).Create(&st) // newUser not user
}
} else {
log.Println("sleeptime为", st)
sleepTime = now.Sub(st.SleepTime)
db.Debug().Model(&SleepManage{}).Where("group_id = ? and user_id = ?", groupId, userId).Update(
map[string]interface{}{
"sleep_time": now,
})
}
db.Debug().Model(&SleepManage{}).Where("group_id = ? and sleep_time <= ? and sleep_time >= ?", groupId, now, today).Count(&position)
return position, sleepTime
}

View File

@@ -0,0 +1,78 @@
package plugin_sleep_manage
import (
"fmt"
"time"
log "github.com/sirupsen/logrus"
zero "github.com/wdvxdr1123/ZeroBot"
"github.com/wdvxdr1123/ZeroBot/message"
"github.com/FloatTech/ZeroBot-Plugin/control"
"github.com/FloatTech/ZeroBot-Plugin/plugin_sleep_manage/model"
)
const dbpath = "data/sleep/"
const dbfile = dbpath + "manage.db"
const prio = 4
var engine = control.Register("sleepmanage", &control.Options{
DisableOnDefault: false,
Help: "sleepmanage\n- 早安\n- 晚安",
})
func init() {
engine.OnFullMatch("早安", isMorning, zero.OnlyGroup).SetBlock(true).SetPriority(prio).
Handle(func(ctx *zero.Ctx) {
db, err := model.Open(dbfile)
if err != nil {
log.Errorln(err)
return
}
position, getUpTime := db.GetUp(ctx.Event.GroupID, ctx.Event.UserID)
log.Println(position, getUpTime)
hour, minute, second := timeDuration(getUpTime)
if (hour == 0 && minute == 0 && second == 0) || hour >= 24 {
ctx.SendChain(message.Reply(ctx.Event.MessageID), message.Text(fmt.Sprintf("早安成功!你是今天第%d个起床的", position)))
} else {
ctx.SendChain(message.Reply(ctx.Event.MessageID), message.Text(fmt.Sprintf("早安成功!你的睡眠时长为%d时%d分%d秒,你是今天第%d个起床的", hour, minute, second, position)))
}
db.Close()
})
engine.OnFullMatch("晚安", isEvening, zero.OnlyGroup).SetBlock(true).SetPriority(prio).
Handle(func(ctx *zero.Ctx) {
db, err := model.Open(dbfile)
if err != nil {
log.Errorln(err)
return
}
position, sleepTime := db.Sleep(ctx.Event.GroupID, ctx.Event.UserID)
log.Println(position, sleepTime)
hour, minute, second := timeDuration(sleepTime)
if (hour == 0 && minute == 0 && second == 0) || hour >= 24 {
ctx.SendChain(message.Reply(ctx.Event.MessageID), message.Text(fmt.Sprintf("晚安成功!你是今天第%d个睡觉的", position)))
} else {
ctx.SendChain(message.Reply(ctx.Event.MessageID), message.Text(fmt.Sprintf("晚安成功!你的清醒时长为%d时%d分%d秒,你是今天第%d个睡觉的", hour, minute, second, position)))
}
db.Close()
})
}
func timeDuration(time time.Duration) (hour, minute, second int64) {
hour = int64(time) / (1000 * 1000 * 1000 * 60 * 60)
minute = (int64(time) - hour*(1000*1000*1000*60*60)) / (1000 * 1000 * 1000 * 60)
second = (int64(time) - hour*(1000*1000*1000*60*60) - minute*(1000*1000*1000*60)) / (1000 * 1000 * 1000)
return hour, minute, second
}
// 只统计6点到12点的早安
func isMorning(ctx *zero.Ctx) bool {
now := time.Now().Hour()
return now >= 6 && now <= 12
}
// 只统计21点到凌晨3点的晚安
func isEvening(ctx *zero.Ctx) bool {
now := time.Now().Hour()
return now >= 21 || now <= 3
}

View File

@@ -1,42 +1,17 @@
package vtbquotation
import (
"io"
"log"
"net/http"
"os"
"github.com/FloatTech/ZeroBot-Plugin/utils/file"
"github.com/FloatTech/ZeroBot-Plugin/utils/process"
)
const pburl = "https://codechina.csdn.net/u011570312/ZeroBot-Plugin/-/raw/master/" + dbfile
// 加载数据库
func init() {
go func() {
process.SleepAbout1sTo2s()
_ = os.MkdirAll(dbpath, 0755)
if !file.IsExist(dbfile) { // 如果没有数据库,则从 url 下载
f, err := os.Create(dbfile)
if err != nil {
panic(err)
}
defer f.Close()
resp, err := http.Get(pburl)
if err == nil {
defer resp.Body.Close()
if resp.ContentLength > 0 {
log.Printf("[vtb]从镜像下载数据库%d字节...", resp.ContentLength)
data, err := io.ReadAll(resp.Body)
if err == nil && len(data) > 0 {
_, _ = f.Write(data)
return
}
panic(err)
}
}
panic(err)
}
_, _ = file.GetLazyData(dbfile, false, true)
}()
}

View File

@@ -194,32 +194,35 @@ func (vdb *VtbDB) Close() error {
const vtbUrl = "https://vtbkeyboard.moe/api/get_vtb_list"
func (vdb *VtbDB) GetVtbList() []string {
func (vdb *VtbDB) GetVtbList() (uidList []string) {
db := (*gorm.DB)(vdb)
client := &http.Client{}
req, err := http.NewRequest("GET", vtbUrl, nil)
if err != nil {
logrus.Errorln(err)
return
}
// 自定义Header
req.Header.Set("User-Agent", randua())
resp, err := client.Do(req)
if err != nil {
logrus.Errorln(err)
return
}
defer resp.Body.Close()
bytes, err := ioutil.ReadAll(resp.Body)
if err != nil {
logrus.Errorln(err)
return
}
// logrus.Println(string(bytes))
vtbListStr, err := strconv.Unquote(strings.Replace(strconv.Quote(string(bytes)), `\\u`, `\u`, -1))
if err != nil {
logrus.Errorln(err)
return
}
// logrus.Println(vtbListStr)
uidList := make([]string, 0)
count := gjson.Get(vtbListStr, "#").Int()
for i := int64(0); i < count; i++ {
item := gjson.Get(vtbListStr, strconv.FormatInt(i, 10))
@@ -232,9 +235,8 @@ func (vdb *VtbDB) GetVtbList() []string {
FirstCategoryUid: item.Get("uid").String(),
}
logrus.Println(fc)
//db.Model(FirstCategory{}).Where("first_category_uid = ?", fc.FirstCategoryUid).FirstOrCreate(&fc)
if err := db.Debug().Model(&FirstCategory{}).Where("first_category_uid = ?", fc.FirstCategoryUid).First(&fc).Error; err != nil {
// error handling...
if gorm.IsRecordNotFoundError(err) {
db.Debug().Model(&FirstCategory{}).Create(&fc) // newUser not user
}
@@ -250,7 +252,6 @@ func (vdb *VtbDB) GetVtbList() []string {
uidList = append(uidList, fc.FirstCategoryUid)
}
// logrus.Println(uidList)
return uidList
}
@@ -261,25 +262,29 @@ func (vdb *VtbDB) StoreVtb(uid string) {
req, err := http.NewRequest("GET", vtbUrl, nil)
if err != nil {
logrus.Errorln(err)
return
}
// 自定义Header
req.Header.Set("User-Agent", randua())
resp, err := client.Do(req)
if err != nil {
logrus.Errorln(err)
return
}
defer resp.Body.Close()
bytes, err := ioutil.ReadAll(resp.Body)
if err != nil {
logrus.Errorln(err)
return
}
//logrus.Println(string(bytes))
vtbStr, err := strconv.Unquote(strings.Replace(strconv.Quote(string(bytes)), `\\u`, `\u`, -1))
if err != nil {
logrus.Errorln(err)
return
}
// logrus.Println(vtbListStr)
secondCount := gjson.Get(vtbStr, "data.voices.#").Int()
logrus.Println("二级品类一共有", secondCount)
for secondIndex := int64(0); secondIndex < secondCount; secondIndex++ {
@@ -292,8 +297,7 @@ func (vdb *VtbDB) StoreVtb(uid string) {
SecondCategoryDescription: secondItem.Get("categoryDescription.zh-CN").String(),
FirstCategoryUid: uid,
}
// logrus.Println(sc)
// db.Model(SecondCategory{}).Where("first_category_uid = ? and second_category_index = ?", uid, secondIndex).FirstOrCreate(&sc)
if err := db.Debug().Model(&SecondCategory{}).Where("first_category_uid = ? and second_category_index = ?", uid, secondIndex).First(&sc).Error; err != nil {
// error handling...
if gorm.IsRecordNotFoundError(err) {
@@ -322,11 +326,9 @@ func (vdb *VtbDB) StoreVtb(uid string) {
ThirdCategoryAuthor: thirdItem.Get("author").String(),
}
logrus.Println(tc)
//db.Model(ThirdCategory{}).Where("first_category_uid = ? and second_category_index = ? and third_category_index = ?",
// uid, secondIndex, thirdIndex).FirstOrCreate(&tc)
if err := db.Debug().Model(&ThirdCategory{}).Where("first_category_uid = ? and second_category_index = ? and third_category_index = ?",
uid, secondIndex, thirdIndex).First(&tc).Error; err != nil {
// error handling...
if gorm.IsRecordNotFoundError(err) {
db.Debug().Model(&ThirdCategory{}).Create(&tc) // newUser not user
}

View File

@@ -22,7 +22,7 @@ const dbfile = dbpath + "vtb.db"
var engine = control.Register("vtbquotation", &control.Options{
DisableOnDefault: false,
Help: "vtbquotation\n- vtb语录\n- 随机vtb\n",
Help: "vtbkeyboard.moe\n- vtb语录\n- 随机vtb",
})
func init() {

105
utils/file/updater.go Normal file
View File

@@ -0,0 +1,105 @@
package file
import (
"crypto/md5"
"encoding/hex"
"errors"
"io"
"net/http"
"os"
"sync"
"unsafe"
reg "github.com/fumiama/go-registry"
"github.com/sirupsen/logrus"
)
const (
dataurl = "https://codechina.csdn.net/u011570312/ZeroBot-Plugin/-/raw/master/"
)
var (
registry = reg.NewRegReader("reilia.eastasia.azurecontainer.io:32664", "fumiama")
lzmu sync.Mutex
)
func GetLazyData(path string, isReturnDataBytes, isDataMustEqual bool) ([]byte, error) {
var data []byte
var resp *http.Response
var filemd5 *[16]byte
var ms string
u := dataurl + path
lzmu.Lock()
logrus.Infoln("[file]检查懒加载文件:", path)
err := registry.Connect()
if err != nil {
logrus.Errorln("[file]无法连接到md5验证服务器请自行确保下载文件的正确性:", err)
} else {
ms, err = registry.Get(path)
if err != nil || len(ms) != 16 {
logrus.Errorln("[file]获取md5失败请自行确保下载文件 %s 的正确性:", path, err)
} else {
filemd5 = (*[16]byte)(*(*unsafe.Pointer)(unsafe.Pointer(&ms)))
logrus.Infoln("[file]从验证服务器获得文件md5:", hex.EncodeToString(filemd5[:]))
}
}
_ = registry.Close()
lzmu.Unlock()
if IsExist(path) {
data, err = os.ReadFile(path)
if err != nil {
return nil, err
}
if filemd5 != nil {
if md5.Sum(data) == *filemd5 {
logrus.Infoln("[file]文件md5匹配文件已存在且为最新")
goto ret
} else if !isDataMustEqual {
logrus.Warnln("[file]文件", path, "md5不匹配但不主动更新")
goto ret
}
logrus.Infoln("[file]文件md5不匹配开始更新文件")
} else {
logrus.Warnln("[file]文件", path, "存在已跳过md5检查")
goto ret
}
}
// 下载
resp, err = http.Get(u)
if err != nil {
return nil, err
}
defer resp.Body.Close()
if resp.ContentLength <= 0 {
return nil, errors.New("resp body len <= 0")
}
logrus.Printf("[file]从镜像下载数据%d字节...", resp.ContentLength)
// 读取数据
data, err = io.ReadAll(resp.Body)
if err != nil {
return nil, err
}
if len(data) <= 0 {
return nil, errors.New("read body len <= 0")
}
if filemd5 != nil {
if md5.Sum(data) == *filemd5 {
logrus.Infoln("[file]文件下载完成md5匹配开始保存")
} else {
logrus.Errorln("[file]文件", path, "md5不匹配下载失败")
return nil, errors.New("file md5 mismatch")
}
} else {
logrus.Warnln("[file]文件", path, "下载完成已跳过md5检查开始保存")
}
// 写入数据
err = os.WriteFile(path, data, 0644)
ret:
if isReturnDataBytes {
return data, err
}
return nil, err
}