mirror of
https://gitcode.com/JianFeeeee/homeagent-sdk.git
synced 2026-10-15 12:15:11 +00:00
example/qq: add typing indicator on private messages
- setInputStatus helper wrapping NapCat set_input_status API - startTyping/stopTyping with goroutine-based typing manager (5s interval, 30s auto-timeout) - start typing on webhook private message receipt - stop typing when output channel sends a response - fix plg.json UTF-8 BOM that broke plugindev parse
This commit is contained in:
@ -1,4 +1,4 @@
|
|||||||
{
|
{
|
||||||
"name": "qq",
|
"name": "qq",
|
||||||
"name_zh": "QQ消息",
|
"name_zh": "QQ消息",
|
||||||
"name_en": "qq",
|
"name_en": "qq",
|
||||||
|
|||||||
@ -102,6 +102,13 @@ type Plugin struct {
|
|||||||
agentfsDir string
|
agentfsDir string
|
||||||
downloadMu sync.Mutex
|
downloadMu sync.Mutex
|
||||||
downloadTasks []*DownloadTask
|
downloadTasks []*DownloadTask
|
||||||
|
typingMu sync.Mutex
|
||||||
|
typingMap map[int64]*typingState
|
||||||
|
}
|
||||||
|
|
||||||
|
type typingState struct {
|
||||||
|
userID int64
|
||||||
|
stopCh chan struct{}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *Plugin) Name() string { return p.name }
|
func (p *Plugin) Name() string { return p.name }
|
||||||
@ -759,6 +766,10 @@ func (p *Plugin) handleWebhook(w http.ResponseWriter, r *http.Request) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if evt.MessageType == "private" {
|
||||||
|
p.startTyping(evt.UserID)
|
||||||
|
}
|
||||||
|
|
||||||
if p.sdk != nil {
|
if p.sdk != nil {
|
||||||
p.sdk.InjectInterruptText(p.name, p.name, interrupt)
|
p.sdk.InjectInterruptText(p.name, p.name, interrupt)
|
||||||
}
|
}
|
||||||
@ -956,6 +967,10 @@ func (p *Plugin) handleChannelOutput(args map[string]interface{}) (interface{},
|
|||||||
return nil, fmt.Errorf("meta 中需要 group_id 或 user_id 字段。用 output_send__qq_help 查看格式说明")
|
return nil, fmt.Errorf("meta 中需要 group_id 或 user_id 字段。用 output_send__qq_help 查看格式说明")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if userID > 0 {
|
||||||
|
p.stopTyping(userID)
|
||||||
|
}
|
||||||
|
|
||||||
switch rawType {
|
switch rawType {
|
||||||
case "text":
|
case "text":
|
||||||
text := p.sensitiveFilter(payload)
|
text := p.sensitiveFilter(payload)
|
||||||
@ -2137,6 +2152,54 @@ func (p *Plugin) napcat(action string, params map[string]interface{}) (interface
|
|||||||
return raw, nil
|
return raw, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (p *Plugin) setInputStatus(userID int64, eventType int) (interface{}, error) {
|
||||||
|
return p.napcat("set_input_status", map[string]interface{}{
|
||||||
|
"user_id": userID,
|
||||||
|
"event_type": eventType,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *Plugin) startTyping(userID int64) {
|
||||||
|
p.typingMu.Lock()
|
||||||
|
if _, ok := p.typingMap[userID]; ok {
|
||||||
|
p.typingMu.Unlock()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
ts := &typingState{userID: userID, stopCh: make(chan struct{})}
|
||||||
|
p.typingMap[userID] = ts
|
||||||
|
p.typingMu.Unlock()
|
||||||
|
go p.typingLoop(ts)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *Plugin) stopTyping(userID int64) {
|
||||||
|
p.typingMu.Lock()
|
||||||
|
ts, ok := p.typingMap[userID]
|
||||||
|
if ok {
|
||||||
|
delete(p.typingMap, userID)
|
||||||
|
}
|
||||||
|
p.typingMu.Unlock()
|
||||||
|
if ok {
|
||||||
|
close(ts.stopCh)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *Plugin) typingLoop(ts *typingState) {
|
||||||
|
ticker := time.NewTicker(5 * time.Second)
|
||||||
|
defer ticker.Stop()
|
||||||
|
timeout := time.After(30 * time.Second)
|
||||||
|
for {
|
||||||
|
select {
|
||||||
|
case <-ticker.C:
|
||||||
|
p.setInputStatus(ts.userID, 1)
|
||||||
|
case <-ts.stopCh:
|
||||||
|
return
|
||||||
|
case <-timeout:
|
||||||
|
p.stopTyping(ts.userID)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// ======== Helpers ========
|
// ======== Helpers ========
|
||||||
|
|
||||||
// rawString extracts a string from napcat's return type (json.RawMessage or string).
|
// rawString extracts a string from napcat's return type (json.RawMessage or string).
|
||||||
@ -2192,6 +2255,7 @@ func NewPluginFactory(name string, config map[string]interface{}) (sdk.Plugin, e
|
|||||||
allowFrom: make(map[int64]struct{}),
|
allowFrom: make(map[int64]struct{}),
|
||||||
groupAllowFrom: make(map[int64]struct{}),
|
groupAllowFrom: make(map[int64]struct{}),
|
||||||
downloadTasks: make([]*DownloadTask, 0),
|
downloadTasks: make([]*DownloadTask, 0),
|
||||||
|
typingMap: make(map[int64]*typingState),
|
||||||
dmPolicy: "open",
|
dmPolicy: "open",
|
||||||
groupPolicy: "open",
|
groupPolicy: "open",
|
||||||
}, nil
|
}, nil
|
||||||
|
|||||||
Reference in New Issue
Block a user