Files
Sillyv2/core/base_sender.go
T
2023-06-01 08:41:54 +08:00

556 lines
10 KiB
Go

package core
import (
"errors"
"fmt"
"reflect"
"regexp"
"strings"
"sync"
"sync/atomic"
"time"
"github.com/cdle/sillyplus/core/common"
"github.com/cdle/sillyplus/utils"
)
var RegistedSenders = map[string]func() common.Sender{}
type Faker struct {
Message string
Type string
UserID string
ChatID string
Carry chan string
BaseSender
Admin bool
}
func (sender *Faker) Listen() chan string {
return sender.Carry
}
func (sender *Faker) GetContent() string {
if sender.Fsps.Content != "" {
return sender.Fsps.Content
}
return sender.Message
}
func (sender *Faker) GetUserID() string {
return sender.UserID
}
func (sender *Faker) GetBotID() string {
return ""
}
func (sender *Faker) GetChatID() string {
return sender.ChatID
}
func (sender *Faker) GetImType() string {
if sender.Type == "" {
return "fake"
}
return sender.Type
}
func (sender *Faker) GetMessageID() string {
return ""
}
func (sender *Faker) GetUserName() string {
return ""
}
func (sender *Faker) GetChatName() string {
return ""
}
func (sender *Faker) IsReply() bool {
return false
}
func (sender *Faker) GetReplyUserID() int {
return 0
}
func (sender *Faker) GetRawMessage() interface{} {
return sender.Message
}
func (sender *Faker) IsAdmin() bool {
return sender.Admin
}
func (sender *Faker) IsMedia() bool {
return false
}
func (sender *Faker) Reply(msgs ...interface{}) (string, error) {
rt := ""
for _, msg := range msgs {
switch msg := msg.(type) {
case []byte:
rt = (string(msg))
case string:
rt = msg
}
}
{
for _, v := range regexp.MustCompile(`\[CQ:image,file=([^\[\]]+)\]`).FindAllStringSubmatch(rt, -1) {
// qr := qrcode2console.NewQRCode2ConsoleWithUrl(v[1], true)
// defer qr.Output()
rt = strings.Replace(rt, fmt.Sprintf(`[CQ:image,file=%s]`, v[1]), "", -1)
}
}
// if rt != "" && n != nil {
// NotifyMasters(rt)
// }
// if rt != "" && sender.Carry != nil {
// sender.Carry <- rt
// }
if rt != "" && sender.Type == "terminal" {
fmt.Printf("\x1b[%dm%s \x1b[0m\n", 31, rt)
}
return "", nil
}
func (sender *Faker) Delete() error {
return nil
}
func (sender *Faker) Disappear(lifetime ...time.Duration) {
}
func (sender *Faker) Finish() {
if sender.Carry != nil {
close(sender.Carry)
}
}
func (sender *Faker) Copy() common.Sender {
new := reflect.Indirect(reflect.ValueOf(interface{}(sender))).Interface().(Faker)
return &new
}
func (sender *Faker) GroupKick(uid string, reject_add_request bool) {
}
func (sender *Faker) GroupBan(uid string, duration int) {
}
type BaseSender struct {
matches [][]string
goon bool
Fsps common.FakerSenderParams
Atlast bool
ToSendMessages []string
IsFinished bool
Duration *time.Duration
mark interface{}
params []string
level int
}
func (sender *BaseSender) SetLevel(l int) {
sender.level = l
}
func (sender *BaseSender) GetLevel() int {
return sender.level
}
func (sender *BaseSender) SetMark(mark interface{}) {
sender.mark = mark
}
func (sender *BaseSender) GetMark() interface{} {
return sender.mark
}
func (sender *BaseSender) SetMatch(ss []string) {
sender.matches = [][]string{ss}
}
func (sender *BaseSender) SetParams(ss []string) {
sender.params = ss
}
func (sender *BaseSender) SetAllMatch(ss [][]string) {
sender.matches = ss
}
func (sender *BaseSender) SetContent(content string) {
sender.Fsps.Content = content
}
func (sender *BaseSender) SetFsps(fsps *common.FakerSenderParams) {
sender.Fsps = *fsps
}
func (sender *BaseSender) GetMatch() []string {
return sender.matches[0]
}
func (sender *BaseSender) GetAllMatch() [][]string {
return sender.matches
}
func (sender *BaseSender) Continue() {
sender.goon = true
}
func (sender *BaseSender) IsContinue() bool {
return sender.goon
}
func (sender *BaseSender) ClearContinue() {
sender.goon = false
}
func (sender *BaseSender) Get(i interface{}) string {
switch i := i.(type) {
case int:
if len(sender.matches) == 0 {
return ""
}
if len(sender.matches[0]) < i+1 {
return ""
}
return sender.matches[0][i]
case string:
for j := range sender.params {
if sender.params[j] == i {
return sender.Get(j)
}
}
return ""
}
return ""
}
func (sender *BaseSender) Delete() error {
return nil
}
func (sender *BaseSender) Disappear(lifetime ...time.Duration) {
}
func (sender *BaseSender) Finish() {
sender.IsFinished = true
}
func (sender *BaseSender) IsMedia() bool {
return false
}
func (sender *BaseSender) GetRawMessage() interface{} {
return nil
}
func (sender *BaseSender) IsReply() bool {
return false
}
func (sender *BaseSender) GetMessageID() string {
return ""
}
func (sender *BaseSender) RecallMessage(...interface{}) error {
return nil
}
func (sender *BaseSender) GetUserID() string {
return ""
}
func (sender *BaseSender) GetChatID() string {
return ""
}
func (sender *BaseSender) Push(msg map[string]string) (string, error) {
return "", nil
}
func (sender *BaseSender) GetImType() string {
return ""
}
func (sender *BaseSender) GroupKick(uid string, reject_add_request bool) {
}
func (sender *BaseSender) GroupUnkick(uid string) {
}
func (sender *BaseSender) GroupBan(uid string, duration int) {
}
func (sender *BaseSender) GroupUnban(uid string) {
}
func (sender *BaseSender) GetUserName() string {
return ""
}
func (sender *BaseSender) IsAdmin() bool {
return false
}
func (sender *BaseSender) GetChatName() string {
return ""
}
func (sender *BaseSender) GetReplyUserID() int {
return 0
}
func (sender *BaseSender) GetReplyMessageID() int {
return 0
}
func (sender *BaseSender) AtLast() {
sender.Atlast = true
}
func (sender *BaseSender) UAtLast() {
sender.Atlast = false
}
func (sender *BaseSender) Stop() {
panic("stop")
}
func (sender *BaseSender) IsAtLast() bool {
return sender.Atlast
}
func (sender *BaseSender) MessagesToSend() string {
return strings.Join(sender.ToSendMessages, "\n")
}
var ErrorTimeOut = errors.New("指令超时")
var ErrorInterrupt = errors.New("被其他指令中断")
type Carrys struct {
list map[int64]*Carry
sync.RWMutex
}
func (cs *Carrys) Add(key int64, c *Carry) {
// logs.Info("add", c.Function.Rules)
cs.Lock()
defer cs.Unlock()
cs.list[key] = c
}
func (cs *Carrys) Remove(Key1 int64) {
cs.Lock()
defer cs.Unlock()
for key := range cs.list {
if key == Key1 {
// logs.Info("rem", cs.list[key].Function.Rules)
delete(cs.list, Key1)
}
}
}
func (cs *Carrys) RemoveByUUID(uuid string) {
cs.Foreach(func(key int64, c *Carry) bool {
if c.UUID == uuid {
cs.Remove(key)
}
return true
})
}
func (cs *Carrys) Foreach(f func(key int64, c *Carry) bool) {
cs.RLock()
defer cs.RUnlock()
for key, c := range cs.list {
f(key, c)
}
}
var waits = map[int]*Carrys{
1: {
list: map[int64]*Carry{},
},
2: {
list: map[int64]*Carry{},
},
3: {
list: map[int64]*Carry{},
},
4: {
list: map[int64]*Carry{},
},
5: {
list: map[int64]*Carry{},
},
}
type Carry struct {
// Rules []string
Chan chan interface{}
Result chan interface{}
Message common.Sender
Function common.Function
RequireAdmin bool
AllowPlatforms []string
ProhibitPlatforms []string
AllowGroups []string
ProhibitGroups []string
AllowUsers []string
ProhibitUsers []string
ListenPrivate bool
ListenGroup bool
UserID string
ChatID string
UUID string
}
type again string
var Again again = ""
var GoAgain = func(str string) again {
return again(str)
}
type YesOrNo string
var YesNo YesOrNo = "yeson"
var Yes YesOrNo = "yes"
var No YesOrNo = "no"
type Range []int
type Switch []string
var listenCounter int64
func (s *BaseSender) Await(message common.Sender, callback func(common.Sender) interface{}, params ...interface{}) interface{} {
timeout := time.Hour * 999999
var handleErr func(error)
var persistent = false
var c *Carry
for _, param := range params {
switch param := param.(type) {
case string:
if param == "persistent" {
persistent = true
} else {
c.Function.Rules = append(c.Function.Rules, param)
}
case []string:
c.Function.Rules = append(c.Function.Rules, param...)
case time.Duration:
du := param
if du != 0 {
timeout = du
}
case func(error):
handleErr = param
case *Carry:
c = param
}
}
c.Message = message
if len(c.Function.Rules) == 0 {
c.Function.Rules = []string{`raw [\s\S]+`}
}
fmtRule(&c.Function)
c.Chan = make(chan interface{}, 1)
c.Result = make(chan interface{}, 1)
key := atomic.AddInt64(&listenCounter, 1)
// key := fmt.Sprintf("u=%v&c=%v&i=%v&t=%v&p=%v", message.GetUserID(), message.GetChatID(), message.GetImType(), atomic.LoadInt64(&listenCounter))
// if fg != nil {
// if *fg == "me" {
// key += "&f=me"
// } else {
// key += "&f=true"
// }
// }
waits[4-s.level].Add(key, c)
defer func() {
waits[4-s.level].Remove(key)
}()
for {
select {
case result := <-c.Chan:
switch s := result.(type) {
case common.Sender:
if callback == nil {
return s.GetContent()
}
if persistent {
go func() {
c.Result <- callback(s)
}()
continue
}
result := callback(s)
if v, ok := result.(again); ok { //阻塞
if v == "" {
c.Result <- nil
} else {
c.Result <- string(v)
}
} else if _, ok := result.(YesOrNo); ok {
o := strings.ToLower(regexp.MustCompile("[yYnN]").FindString(s.GetContent()))
if o == "y" {
return Yes
}
if o == "n" {
return No
}
c.Result <- "Y or n ?"
} else if vv, ok := result.(Switch); ok {
ct := s.GetContent()
for _, v := range vv {
if ct == v {
return v
}
}
c.Result <- fmt.Sprintf("请从%s中选择一个。", strings.Join(vv, "、"))
} else if vv, ok := result.(Range); ok {
ct := s.GetContent()
n := utils.Int(ct)
if fmt.Sprint(n) == ct {
if (n >= vv[0]) && (n <= vv[1]) {
return n
}
}
c.Result <- fmt.Sprintf("请从%d~%d中选择一个整数。", vv[0], vv[1])
} else {
c.Result <- result
return s.GetContent()
}
case error:
if handleErr != nil {
handleErr(s)
}
c.Result <- nil
return nil
}
case <-time.After(timeout):
if handleErr != nil {
handleErr(ErrorTimeOut)
}
c.Result <- nil
return nil
}
}
}