|
2 | 2 | package driftbottle
|
3 | 3 |
|
4 | 4 | import (
|
| 5 | + "fmt" |
| 6 | + "hash/crc64" |
5 | 7 | "strconv"
|
6 |
| - "strings" |
7 | 8 | "sync"
|
8 | 9 | "time"
|
| 10 | + "unicode/utf8" |
9 | 11 |
|
| 12 | + "github.com/FloatTech/floatbox/binary" |
| 13 | + sql "github.com/FloatTech/sqlite" |
10 | 14 | ctrl "github.com/FloatTech/zbpctrl"
|
11 | 15 | "github.com/FloatTech/zbputils/control"
|
12 |
| - "github.com/sirupsen/logrus" |
| 16 | + "github.com/FloatTech/zbputils/ctxext" |
13 | 17 | zero "github.com/wdvxdr1123/ZeroBot"
|
14 | 18 | "github.com/wdvxdr1123/ZeroBot/message"
|
15 | 19 | )
|
16 | 20 |
|
| 21 | +type sea struct { |
| 22 | + ID int64 `db:"id"` // ID qq_grp_name_msg 的 crc64 hashCheck. |
| 23 | + QQ int64 `db:"qq"` // Get current user(Who sends this) |
| 24 | + Name string `db:"Name"` // his or her name at that time:P |
| 25 | + Msg string `db:"msg"` // What he or she sent to bot? |
| 26 | + Grp int64 `db:"grp"` // which group sends this msg? |
| 27 | + Time string `db:"time"` // we need to know the current time,master> |
| 28 | +} |
| 29 | + |
| 30 | +var seaSide = &sql.Sqlite{} |
| 31 | +var seaLocker sync.RWMutex |
| 32 | + |
| 33 | +// We need a container to inject what we need :( |
| 34 | + |
17 | 35 | func init() {
|
18 | 36 | en := control.Register("driftbottle", &ctrl.Options[*zero.Ctx]{
|
19 | 37 | DisableOnDefault: false,
|
20 |
| - Help: "漂流瓶\n- (在群xxx)丢漂流瓶(到频道xxx) [消息]\n- (从频道xxx)捡漂流瓶\n- @BOT 创建频道 xxx\n- 跳入(频道)海中\n- 注:不显式限制时,私聊发送可在所有群抽到,群聊发送仅可在本群抽到,默认频道为 global", |
| 38 | + Help: "简单的漂流瓶\n" + "- @bot pick" + "- @bot throw xxx (xxx为投递内容)", |
21 | 39 | PrivateDataFolder: "driftbottle",
|
22 | 40 | })
|
23 |
| - sea.DBPath = en.DataFolder() + "sea.db" |
24 |
| - err := sea.Open(time.Hour * 24) |
| 41 | + seaSide.DBPath = en.DataFolder() + "sea.db" |
| 42 | + err := seaSide.Open(time.Hour * 24) |
25 | 43 | if err != nil {
|
26 | 44 | panic(err)
|
27 | 45 | }
|
28 |
| - _ = createChannel(sea, "global") |
29 |
| - en.OnRegex(`^(在群\d+)?丢漂流瓶(到频道\w+)?\s+(.*)$`).SetBlock(true). |
30 |
| - Handle(func(ctx *zero.Ctx) { |
31 |
| - msgs := ctx.State["regex_matched"].([]string) |
32 |
| - grp := ctx.Event.GroupID |
33 |
| - channel := "global" |
34 |
| - msg := msgs[3] |
35 |
| - var err error |
36 |
| - if msgs[1] != "" { |
37 |
| - grp, err = strconv.ParseInt(msgs[1][6:], 10, 64) |
38 |
| - if err != nil { |
39 |
| - ctx.SendChain(message.Text("群号非法!")) |
40 |
| - return |
41 |
| - } |
42 |
| - } |
43 |
| - if msgs[2] != "" { |
44 |
| - channel = msgs[2][9:] |
45 |
| - } |
46 |
| - if msg == "" { |
47 |
| - ctx.SendChain(message.Text("消息为空!")) |
48 |
| - return |
49 |
| - } |
50 |
| - logrus.Debugln("[driftbottle]", grp, channel, msg) |
51 |
| - err = newBottle( |
52 |
| - ctx.Event.UserID, |
53 |
| - grp, |
54 |
| - ctx.CardOrNickName(ctx.Event.UserID), |
55 |
| - msg, |
56 |
| - ).throw(sea, channel) |
57 |
| - if err != nil { |
58 |
| - ctx.SendChain(message.Text("ERROR: ", err)) |
59 |
| - return |
60 |
| - } |
61 |
| - ctx.Send(message.ReplyWithMessage(ctx.Event.MessageID, message.Text("你将它扔进大海,希望有人捞到吧~"))) |
62 |
| - }) |
63 |
| - en.OnRegex(`^(从频道\w+)?捡漂流瓶$`).SetBlock(true). |
64 |
| - Handle(func(ctx *zero.Ctx) { |
65 |
| - msgs := ctx.State["regex_matched"].([]string) |
66 |
| - grp := ctx.Event.GroupID |
67 |
| - if grp == 0 { |
68 |
| - grp = -ctx.Event.UserID |
69 |
| - } |
70 |
| - if grp == 0 { |
71 |
| - ctx.SendChain(message.Text("找不到对象!")) |
72 |
| - return |
73 |
| - } |
74 |
| - channel := "global" |
75 |
| - if msgs[1] != "" { |
76 |
| - channel = msgs[1][9:] |
77 |
| - } |
78 |
| - logrus.Debugln("[driftbottle]", grp, channel) |
79 |
| - b, err := fetchBottle(sea, channel, grp) |
80 |
| - if err != nil { |
81 |
| - ctx.SendChain(message.Text("ERROR: ", err)) |
82 |
| - return |
83 |
| - } |
84 |
| - var wg sync.WaitGroup |
85 |
| - wg.Add(1) |
86 |
| - go func() { |
87 |
| - err = b.destroy(sea, channel) |
88 |
| - wg.Done() |
89 |
| - }() |
90 |
| - ctx.Send( |
91 |
| - message.ReplyWithMessage( |
92 |
| - ctx.Event.MessageID, |
93 |
| - message.Text("你在海边捡到了一个来自 ", b.Name, " 的漂流瓶,打开瓶子,里面有一张纸条,写着:"), |
94 |
| - message.Text(b.Msg), |
95 |
| - ), |
96 |
| - ) |
97 |
| - wg.Wait() |
98 |
| - if err != nil { |
99 |
| - ctx.SendChain(message.Text("ERROR: ", err)) |
100 |
| - return |
101 |
| - } |
102 |
| - }) |
103 |
| - en.OnPrefix("创建频道", zero.SuperUserPermission, zero.OnlyToMe).SetBlock(true). |
104 |
| - Handle(func(ctx *zero.Ctx) { |
105 |
| - channel := strings.TrimRight(ctx.State["args"].(string), " ") |
106 |
| - if channel == "" { |
107 |
| - ctx.SendChain(message.Text("频道名为空!")) |
108 |
| - return |
109 |
| - } |
110 |
| - err := createChannel(sea, channel) |
111 |
| - if err != nil { |
112 |
| - ctx.SendChain(message.Text("ERROR: ", err)) |
113 |
| - return |
114 |
| - } |
115 |
| - ctx.Send(message.ReplyWithMessage(ctx.Event.MessageID, message.Text("成功~"))) |
116 |
| - }) |
117 |
| - en.OnRegex(`^跳入(\w+)?海中$`).SetBlock(true). |
118 |
| - Handle(func(ctx *zero.Ctx) { |
119 |
| - msgs := ctx.State["regex_matched"].([]string) |
120 |
| - channel := "global" |
121 |
| - if msgs[1] != "" { |
122 |
| - channel = msgs[1] |
123 |
| - } |
124 |
| - seamu.RLock() |
125 |
| - c, err := sea.Count(channel) |
126 |
| - seamu.RUnlock() |
127 |
| - if err != nil { |
128 |
| - ctx.SendChain(message.Text("ERROR: ", err)) |
129 |
| - return |
130 |
| - } |
131 |
| - ctx.Send(message.ReplyWithMessage(ctx.Event.MessageID, message.Text("你缓缓走入大海,感受着海浪轻柔地拍打着你的小腿,膝盖……\n波浪卷着你的腰腹,你感觉有些把握不住平衡了……\n……\n你沉入海中,", c, " 个物体与你一同沉浮。\n不知何处涌来一股暗流,你失去了意识。"))) |
132 |
| - }) |
| 46 | + |
| 47 | + _ = createChannel(seaSide) |
| 48 | + en.OnFullMatch("pick", zero.OnlyToMe, zero.OnlyGroup).Limit(ctxext.LimitByGroup).SetBlock(true).Handle(func(ctx *zero.Ctx) { |
| 49 | + be, err := fetchBottle(seaSide) |
| 50 | + if err != nil { |
| 51 | + ctx.SendChain(message.Text("ERR:", err)) |
| 52 | + } |
| 53 | + idstr := strconv.Itoa(int(be.ID)) |
| 54 | + qqstr := strconv.Itoa(int(be.QQ)) |
| 55 | + grpstr := strconv.Itoa(int(be.Grp)) |
| 56 | + botname := zero.BotConfig.NickName[0] |
| 57 | + msg := message.Message{message.CustomNode(botname, ctx.Event.SelfID, botname+"试着帮你捞出来了这个~\nID:"+idstr+"\n投递人: "+be.Name+"("+qqstr+")"+"\n群号: "+grpstr+"\n时间: "+be.Time+"\n内容: \n"+be.Msg)} |
| 58 | + ctx.Send(msg) |
| 59 | + }) |
| 60 | + |
| 61 | + en.OnRegex(`throw.*?(.*)`, zero.OnlyToMe, zero.OnlyGroup).SetBlock(true).Handle(func(ctx *zero.Ctx) { |
| 62 | + senderFormatTime := time.Unix(ctx.Event.Time, 0).Format("2006-01-02 15:04:05") |
| 63 | + rawSenderMessage := ctx.State["regex_matched"].([]string)[1] |
| 64 | + rawMessageCallBack := message.UnescapeCQCodeText(rawSenderMessage) |
| 65 | + keyWordsNum := utf8.RuneCountInString(rawMessageCallBack) |
| 66 | + if keyWordsNum < 10 { |
| 67 | + ctx.SendChain(message.Reply(ctx.Event.MessageID), message.Text("需要投递的内容过少( ")) |
| 68 | + return |
| 69 | + } |
| 70 | + // check current needs and prepare to throw drift_bottle. |
| 71 | + err = globalbottle( |
| 72 | + ctx.Event.UserID, |
| 73 | + ctx.Event.GroupID, |
| 74 | + senderFormatTime, |
| 75 | + ctx.CardOrNickName(ctx.Event.UserID), |
| 76 | + rawMessageCallBack, |
| 77 | + ).throw(seaSide) |
| 78 | + if err != nil { |
| 79 | + ctx.SendChain(message.Text("ERROR: ", err)) |
| 80 | + return |
| 81 | + } |
| 82 | + ctx.Send(message.ReplyWithMessage(ctx.Event.MessageID, message.Text("已经帮你丢出去了哦~"))) |
| 83 | + }) |
| 84 | +} |
| 85 | + |
| 86 | +func globalbottle(qq, grp int64, time, name, msg string) *sea { // Check as if the User is available and collect information to store. |
| 87 | + id := int64(crc64.Checksum(binary.StringToBytes(fmt.Sprintf("%d_%d_%s_%s_%s", grp, qq, time, name, msg)), crc64.MakeTable(crc64.ISO))) |
| 88 | + return &sea{ID: id, Grp: grp, Time: time, QQ: qq, Name: name, Msg: msg} |
| 89 | +} |
| 90 | + |
| 91 | +func (be *sea) throw(db *sql.Sqlite) error { |
| 92 | + seaLocker.Lock() |
| 93 | + defer seaLocker.Unlock() |
| 94 | + return db.Insert("global", be) |
| 95 | +} |
| 96 | + |
| 97 | +func fetchBottle(db *sql.Sqlite) (*sea, error) { |
| 98 | + seaLocker.Lock() |
| 99 | + defer seaLocker.Unlock() |
| 100 | + be := new(sea) |
| 101 | + return be, db.Pick("global", be) |
| 102 | +} |
| 103 | + |
| 104 | +func createChannel(db *sql.Sqlite) error { |
| 105 | + seaLocker.Lock() |
| 106 | + defer seaLocker.Unlock() |
| 107 | + return db.Create("global", &sea{}) |
133 | 108 | }
|
0 commit comments