feat: implement chat merging and logging in Safew
- Introduced a new function `mergeAndLog` in the Watcher to handle merging Safew chats and logging newly discovered chats. - Added a test `TestNewSafewChatsSkipsKnownIDs` to ensure that known chat IDs are skipped during the merging process. - Enhanced the polling mechanism to improve chat management and reduce duplicates.
This commit is contained in:
@@ -188,7 +188,7 @@ func (w *Watcher) pollOnce(ctx context.Context, token string, timeout int) error
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if err := w.store.MergeSafewChats(ctx, token, chats); err != nil {
|
if err := w.mergeAndLog(ctx, token, chats); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if next != offset {
|
if next != offset {
|
||||||
@@ -197,6 +197,43 @@ func (w *Watcher) pollOnce(ctx context.Context, token string, timeout int) error
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (w *Watcher) mergeAndLog(ctx context.Context, token string, chats []adapter.SafewChat) error {
|
||||||
|
if len(chats) == 0 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
existing, err := w.store.ListSafewChats(ctx, token)
|
||||||
|
if err != nil {
|
||||||
|
return w.store.MergeSafewChats(ctx, token, chats)
|
||||||
|
}
|
||||||
|
known := map[string]struct{}{}
|
||||||
|
for _, c := range existing {
|
||||||
|
known[c.ID] = struct{}{}
|
||||||
|
}
|
||||||
|
if err := w.store.MergeSafewChats(ctx, token, chats); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
for _, c := range newSafewChats(known, chats) {
|
||||||
|
slog.Info("safew chat discovered", "id", c.ID, "type", c.Type, "title", c.Title)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func newSafewChats(known map[string]struct{}, chats []adapter.SafewChat) []adapter.SafewChat {
|
||||||
|
var out []adapter.SafewChat
|
||||||
|
seen := map[string]struct{}{}
|
||||||
|
for _, c := range chats {
|
||||||
|
if _, ok := known[c.ID]; ok {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if _, ok := seen[c.ID]; ok {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
seen[c.ID] = struct{}{}
|
||||||
|
out = append(out, c)
|
||||||
|
}
|
||||||
|
return out
|
||||||
|
}
|
||||||
|
|
||||||
func isSafewAuth(err error) bool {
|
func isSafewAuth(err error) bool {
|
||||||
var e *adapter.SafewAuthError
|
var e *adapter.SafewAuthError
|
||||||
return errors.As(err, &e)
|
return errors.As(err, &e)
|
||||||
|
|||||||
@@ -115,6 +115,18 @@ func TestEnsurePollsInBackground(t *testing.T) {
|
|||||||
w.Stop()
|
w.Stop()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestNewSafewChatsSkipsKnownIDs(t *testing.T) {
|
||||||
|
known := map[string]struct{}{"1": {}}
|
||||||
|
got := newSafewChats(known, []adapter.SafewChat{
|
||||||
|
{ID: "1", Title: "old"},
|
||||||
|
{ID: "2", Title: "测试AI", Type: "group"},
|
||||||
|
{ID: "2", Title: "dup"},
|
||||||
|
})
|
||||||
|
if len(got) != 1 || got[0].ID != "2" || got[0].Title != "测试AI" {
|
||||||
|
t.Fatalf("%#v", got)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func TestPollConflictIsRetryable(t *testing.T) {
|
func TestPollConflictIsRetryable(t *testing.T) {
|
||||||
err := errors.New("safew getUpdates status 400: BAD_REQUEST: Conflict: terminated by other getUpdates request; make sure that only one bot instance is running")
|
err := errors.New("safew getUpdates status 400: BAD_REQUEST: Conflict: terminated by other getUpdates request; make sure that only one bot instance is running")
|
||||||
if !isGetUpdatesConflict(err) {
|
if !isGetUpdatesConflict(err) {
|
||||||
|
|||||||
Reference in New Issue
Block a user