1 Star 0 Fork 1

tcsnzh / 54robot

forked from Arrivederci / 54robot 
加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
克隆/下载
cmd.go 6.76 KB
一键复制 编辑 原始数据 按行查看 历史
tcsnzh 提交于 2024-04-24 16:10 . feat: 大功告成
package main
import (
"encoding/csv"
"errors"
"fmt"
"io"
"os"
"time"
"github.com/alecthomas/kong"
"github.com/eatmoreapple/openwechat"
"github.com/sirupsen/logrus"
"go.mongodb.org/mongo-driver/mongo"
"golang.org/x/text/encoding/unicode"
"golang.org/x/text/transform"
)
var CmdPrefix = "cmd"
type CmdContext struct {
c *Context
msg *openwechat.Message
db *mongo.Client
stdout *[]byte
stderr *[]byte
}
func NewCmdContext(c *Context, msg *openwechat.Message, db *mongo.Client) CmdContext {
return CmdContext{
c: c,
msg: msg,
db: db,
stdout: &[]byte{},
stderr: &[]byte{},
}
}
type simpleWriter struct {
to int
cc *CmdContext
}
func (w *simpleWriter) Write(p []byte) (n int, err error) {
if w.to == 1 {
buf := w.cc.stdout
buf2 := append(*buf, p...)
w.cc.stdout = &buf2
return len(p), nil
} else if w.to == 2 {
buf := w.cc.stderr
buf2 := append(*buf, p...)
w.cc.stderr = &buf2
return len(p), nil
} else {
return -1, errors.New("invalid argument of to = " + fmt.Sprint(w.to))
}
}
func (cc *CmdContext) StdoutWriter() io.Writer {
return &simpleWriter{to: 1, cc: cc}
}
func (cc *CmdContext) StderrWriter() io.Writer {
return &simpleWriter{to: 2, cc: cc}
}
func (cc *CmdContext) StdoutString() string {
return string(*cc.stdout)
}
func (cc *CmdContext) StderrString() string {
return string(*cc.stderr)
}
func (cc *CmdContext) Apply(k *kong.Kong) error {
k.Exit = cc.exit
k.Stdout = cc.StdoutWriter()
k.Stderr = cc.StderrWriter()
return nil
}
func (h *CmdContext) exit(code int) {
logrus.Debugf("CmdContext exit : %v", code)
}
var Cmd struct {
Tip TipCmd `cmd:"" help:"展示提示消息"`
Statistics StatisticsCmd `cmd:"" help:"展示统计信息"`
Pause PauseCmd `cmd:"" help:"暂停机器人消息处理"`
Resume ResumeCmd `cmd:"" help:"恢复机器人消息处理"`
Status StatusCmd `cmd:"" help:"展示状态信息"`
InviteToJoinGroup InviteToJoinGroupCmd `cmd:"" help:"邀请加入所有的咨询群"`
}
var CmdRunMsgNPEErrorMessage = "Require ctx.msg not nil !"
type TipCmd struct{}
func (cmd *TipCmd) Run(ctx *CmdContext) error {
_, err := ctx.msg.ReplyText(tip)
if err != nil {
return err
}
return nil
}
type StatisticsCmd struct {
// AllPeople bool `help:"搜索所有人的发言。"`
NicknameRegex string `help:"搜索昵称匹配此正则表达式的用户"`
BeforeWeek int `help:"搜索多少周前的"`
// 每周绩点统计的分隔时间点。
SplitWeekday int `help:"每周绩点统计的分隔时间点。分隔于星期X。如果三个都不传或都为0,则改为默认值:周一"`
SplitHour int `help:"每周绩点统计的分隔时间点。分隔于X点。如果三个都不传或都为0,则改为默认值:凌晨5点"`
SplitMinute int `help:"每周绩点统计的分隔时间点。分隔于X分。如果三个都不传或都为0,则改为默认值:0分"`
}
const (
// 每周绩点统计的分隔时间点 的默认值。
// 请维护其与 StatisticsCmd 的参数 help 值相匹配。
defaultSplitWeekday = int(time.Monday)
defaultSplitHour = 5
defaultSplitMinute = 0
)
func (cmd *StatisticsCmd) Run(ctx *CmdContext) error {
if ctx.msg == nil {
// nil on test
return errors.New(CmdRunMsgNPEErrorMessage)
}
replyText := "统计于: " + fmt.Sprint(time.Now()) + "\n\n"
msg := ctx.msg
replyText += "可以使用 --help 参数来查看其他参数信息。\n\n"
info, err := StatisticsAll(ctx.db, cmd)
if err != nil {
return err
}
replyText += info.ReportString()
_, err = msg.ReplyText(replyText)
if err != nil {
return err
}
f, err := os.CreateTemp("", "54robot.messages."+fmt.Sprint(time.Now().Unix())+".*.csv")
if err != nil {
logrus.WithError(err).Error("Error on create temp file")
return err
}
logrus.Debugf("create temp file %s", f.Name())
defer f.Close()
// 解决中文乱码
_, err = f.WriteString("\xEF\xBB\xBF")
if err != nil {
return err
}
csvW := csv.NewWriter(transform.NewWriter(f, unicode.UTF8.NewEncoder()))
csvW.UseCRLF = true
csvW.Write([]string{
"时间",
"群聊",
"用户名",
"用户群名",
"是否是文本消息",
"内容",
})
for _, m := range *info.Messages {
columns := []string{
m.CreateTime.String(),
m.GroupName,
m.UserNickName,
m.UserDisplayName,
fmt.Sprint(m.ContentIsText),
m.Content,
}
err = csvW.Write(columns)
if err != nil {
logrus.WithError(err).Error("Error on write csv")
return err
}
}
csvW.Flush()
err = f.Sync()
if err != nil {
logrus.WithError(err).Error("Error on temp file sync")
return err
}
f.Seek(0, io.SeekStart)
_, err = msg.ReplyFile(f)
if err != nil {
if err == io.EOF {
logrus.Debugf("eof")
} else {
logrus.WithError(err).Error("Error on reply file")
return err
}
}
return nil
}
type PauseCmd struct{}
type ResumeCmd struct{}
func (cmd *PauseCmd) Run(ctx *CmdContext) error {
GlobalState.Pause = true
_, err := ctx.msg.ReplyText("已暂停机器人消息处理")
if err != nil {
return err
}
return nil
}
func (cmd *ResumeCmd) Run(ctx *CmdContext) error {
GlobalState.Pause = false
_, err := ctx.msg.ReplyText("已恢复机器人消息处理")
if err != nil {
return err
}
return nil
}
type StatusCmd struct{}
func (cmd *StatusCmd) Run(ctx *CmdContext) error {
c := ctx.c
groups, err := AllGroups(c, true)
if err != nil {
return err
}
replyText := ""
replyText += "调试信息:"
replyText += fmt.Sprintf("\n Global state : %v", GlobalState)
replyText += fmt.Sprintf("\n Self nickname :%v", GetSelf().NickName)
replyText += "\n\n群聊列表:"
for _, group := range *groups {
if group.MemberCount == 0 {
_, err := group.Members()
if err != nil {
return err
}
}
replyText += fmt.Sprintf("\n %s(人数=%v)", group.NickName, group.MemberCount)
itsMemberGroup, err := isMemberGroup(c, group, true)
if err != nil {
return err
}
if itsMemberGroup {
replyText += "(成员群) "
}
itsConsultingGroup, err := isConsultingGroup(c, group, true)
if err != nil {
return err
}
if itsConsultingGroup {
replyText += "(咨询群) "
}
}
_, err = ctx.msg.ReplyText(replyText)
if err != nil {
return err
}
return nil
}
type InviteToJoinGroupCmd struct{}
func (cmd *InviteToJoinGroupCmd) Run(ctx *CmdContext) error {
if ctx.msg.IsSendByFriend() {
sender, err := ctx.msg.Sender()
if err != nil {
return err
}
friend, isFriend := sender.AsFriend()
if !isFriend {
return errors.New("你不是机器人的好友,AsFriend错误")
}
_, err = inviteToJoinConsultingGroup(ctx.c, friend, false)
if err != nil {
return err
}
return nil
} else {
waitRate()
_, err := ctx.msg.ReplyText("需要私聊")
if err != nil {
return err
}
return nil
}
}
Go
1
https://gitee.com/tcsn_site/54robot.git
git@gitee.com:tcsn_site/54robot.git
tcsn_site
54robot
54robot
master

搜索帮助

53164aa7 5694891 3bd8fe86 5694891