Skip to content

Commit

Permalink
chore: disable ref links when chat is not super group (#166)
Browse files Browse the repository at this point in the history
* chore: disable ref links when chat is not super group
* chore: adjust ent lint
  • Loading branch information
nekomeowww authored Jul 24, 2023
1 parent c4089b7 commit b2e7630
Show file tree
Hide file tree
Showing 6 changed files with 144 additions and 48 deletions.
17 changes: 14 additions & 3 deletions internal/bots/telegram/handlers/recap/recap_callback_query.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import (

"github.com/nekomeowww/insights-bot/pkg/bots/tgbot"
"github.com/nekomeowww/insights-bot/pkg/types/bot/handlers/recap"
"github.com/nekomeowww/insights-bot/pkg/types/telegram"
"github.com/nekomeowww/insights-bot/pkg/types/tgchat"
)

Expand Down Expand Up @@ -82,7 +83,9 @@ func (h *CallbackQueryHandler) handleCallbackQuerySelectHours(c *tgbot.Context)
WithReply(replyToMessage)
}

logID, summarizations, err := h.chatHistories.SummarizeChatHistories(data.ChatID, histories)
chatType := telegram.ChatType(c.Update.CallbackQuery.Message.Chat.Type)

logID, summarizations, err := h.chatHistories.SummarizeChatHistories(data.ChatID, chatType, histories)
if err != nil {
return nil, tgbot.
NewExceptionError(err).WithMessage("聊天记录回顾生成失败,请稍后再试!").
Expand Down Expand Up @@ -118,9 +121,17 @@ func (h *CallbackQueryHandler) handleCallbackQuerySelectHours(c *tgbot.Context)
for i, s := range summarizationBatches {
var content string
if len(summarizationBatches) > 1 {
content = fmt.Sprintf("%s\n\n(%d/%d)\n#recap\n<em>🤖️ Generated by chatGPT</em>", strings.Join(s, "\n\n"), i+1, len(summarizationBatches))
content = fmt.Sprintf("%s\n\n(%d/%d)\n%s#recap\n<em>🤖️ Generated by chatGPT</em>",
strings.Join(s, "\n\n"),
i+1,
len(summarizationBatches),
lo.Ternary(chatType == telegram.ChatTypeGroup, "\n<b>Tips: </b>由于群组不是超级群组(supergroup),因此消息链接引用暂时被禁用了,如果希望使用该功能,请通过短时间内将群组开放为公共群组并还原回私有群组,或通过其他操作将本群组升级为超级群组后,该功能方可恢复正常运作。\n\n", ""),
)
} else {
content = fmt.Sprintf("%s\n\n#recap\n<em>🤖️ Generated by chatGPT</em>", strings.Join(s, "\n\n"))
content = fmt.Sprintf("%s\n\n%s#recap\n<em>🤖️ Generated by chatGPT</em>",
strings.Join(s, "\n\n"),
lo.Ternary(chatType == telegram.ChatTypeGroup, "<b>Tips: </b>由于群组不是超级群组(supergroup),因此消息链接引用暂时被禁用了,如果希望使用该功能,请通过短时间内将群组开放为公共群组并还原回私有群组,或通过其他操作将本群组升级为超级群组后,该功能方可恢复正常运作。\n\n", ""),
)
}

msg := tgbotapi.NewMessage(c.Update.CallbackQuery.Message.Chat.ID, content)
Expand Down
4 changes: 2 additions & 2 deletions internal/models/chathistories/chat_histories.go
Original file line number Diff line number Diff line change
Expand Up @@ -363,7 +363,7 @@ func formatFullNameAndUsername(fullName, username string) string {
return strings.ReplaceAll(fullName, "#", "")
}

func (m *Model) SummarizeChatHistories(chatID int64, histories []*ent.ChatHistories) (uuid.UUID, []string, error) {
func (m *Model) SummarizeChatHistories(chatID int64, chatType telegram.ChatType, histories []*ent.ChatHistories) (uuid.UUID, []string, error) {
historiesLLMFriendly := make([]string, 0, len(histories))
historiesIncludedMessageIDs := make([]int64, 0)

Expand Down Expand Up @@ -402,7 +402,7 @@ func (m *Model) SummarizeChatHistories(chatID int64, histories []*ent.ChatHistor
return uuid.Nil, make([]string, 0), err
}

ss, err := m.renderRecapTemplates(chatID, summarizations)
ss, err := m.renderRecapTemplates(chatID, chatType, summarizations)
if err != nil {
return uuid.Nil, make([]string, 0), err
}
Expand Down
3 changes: 2 additions & 1 deletion internal/models/chathistories/private_forwarded.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import (
"github.com/nekomeowww/insights-bot/internal/thirdparty/openai"
"github.com/nekomeowww/insights-bot/pkg/bots/tgbot"
"github.com/nekomeowww/insights-bot/pkg/types/redis"
"github.com/nekomeowww/insights-bot/pkg/types/telegram"
"github.com/redis/rueidis"
"github.com/samber/lo"
"go.uber.org/zap"
Expand Down Expand Up @@ -237,7 +238,7 @@ func (m *Model) SummarizePrivateForwardedChatHistories(userID int64, histories [
return item
})

ss, err := m.renderRecapTemplates(0, summarizations)
ss, err := m.renderRecapTemplates(0, telegram.ChatTypePrivate, summarizations)
if err != nil {
return make([]string, 0), err
}
Expand Down
46 changes: 37 additions & 9 deletions internal/models/chathistories/recap.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import (

"github.com/nekomeowww/insights-bot/internal/thirdparty/openai"
"github.com/nekomeowww/insights-bot/pkg/bots/tgbot"
"github.com/nekomeowww/insights-bot/pkg/types/telegram"
)

type RecapOutputTemplateInputs struct {
Expand Down Expand Up @@ -46,6 +47,20 @@ var RecapOutputTemplate = lo.Must(template.
- {{ escape $d.Point }}{{ if len $d.KeyIDs }} {{ range $cIndex, $c := $d.KeyIDs }}<a href="https://t.me/c/{{ $chatID }}/{{ $c }}">[{{ add $cIndex 1 }}]</a>{{ if not (eq $cIndex (sub (len $d.KeyIDs) 1)) }} {{ end }}{{ end }}{{ end }}{{ end }}{{ if .Recap.Conclusion }}
结论:{{ escape .Recap.Conclusion }}{{ end }}`))

var RecapWithoutLinksOutputTemplate = lo.Must(template.
New("recap output markdown template").
Funcs(template.FuncMap{
"join": strings.Join,
"sub": func(a, b int) int { return a - b },
"add": func(a, b int) int { return a + b },
"escape": tgbot.EscapeHTMLSymbols,
}).
Parse(`{{ $chatID := .ChatID }}{{ if .Recap.SinceID }}## {{ escape .Recap.TopicName }}{{ else }}## {{ escape .Recap.TopicName }}{{ end }}
参与人:{{ join .Recap.ParticipantsNamesWithoutUsername "," }}
讨论:{{ range $di, $d := .Recap.Discussion }}
- {{ escape $d.Point }}{{ end }}{{ if .Recap.Conclusion }}
结论:{{ escape .Recap.Conclusion }}{{ end }}`))

func (m *Model) summarizeChatHistoriesSlice(chatID int64, s string) ([]*openai.ChatHistorySummarizationOutputs, goopenai.Usage, error) {
if s == "" {
return make([]*openai.ChatHistorySummarizationOutputs, 0), goopenai.Usage{}, nil
Expand Down Expand Up @@ -171,21 +186,34 @@ func (m *Model) summarizeChatHistories(chatID int64, messageIDs []int64, llmFrie
return chatHistoriesSummarizations, statusUsage, nil
}

func (m *Model) renderRecapTemplates(chatID int64, summarizations []*openai.ChatHistorySummarizationOutputs) ([]string, error) {
func (m *Model) renderRecapTemplates(chatID int64, chatType telegram.ChatType, summarizations []*openai.ChatHistorySummarizationOutputs) ([]string, error) {
ss := make([]string, 0)

for _, r := range summarizations {
sb := new(strings.Builder)

err := RecapOutputTemplate.Execute(sb, RecapOutputTemplateInputs{
ChatID: formatChatID(chatID),
Recap: r,
})
if err != nil {
return make([]string, 0), err
}
switch chatType {
case telegram.ChatTypeSuperGroup:
err := RecapOutputTemplate.Execute(sb, RecapOutputTemplateInputs{
ChatID: formatChatID(chatID),
Recap: r,
})
if err != nil {
return make([]string, 0), err
}

ss = append(ss, sb.String())
ss = append(ss, sb.String())
case telegram.ChatTypePrivate, telegram.ChatTypeGroup, telegram.ChatTypeChannel:
err := RecapWithoutLinksOutputTemplate.Execute(sb, RecapOutputTemplateInputs{
ChatID: formatChatID(chatID),
Recap: r,
})
if err != nil {
return make([]string, 0), err
}

ss = append(ss, sb.String())
}
}

return ss, nil
Expand Down
96 changes: 66 additions & 30 deletions internal/models/chathistories/recap_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,24 +9,16 @@ import (
"github.com/stretchr/testify/require"
)

func TestRecapOutputTemplateExecute(t *testing.T) {
func TestRecapOutputTemplateExecute(t *testing.T) { //nolint:dupl
sb := new(strings.Builder)
err := RecapOutputTemplate.Execute(sb, RecapOutputTemplateInputs{
ChatID: formatChatID(-100123456789),
Recap: &openai.ChatHistorySummarizationOutputs{
TopicName: "Topic 1",
SinceID: 1,
ParticipantsNamesWithoutUsername: []string{"User 1", "User 2"},
Discussion: []*openai.ChatHistorySummarizationOutputsDiscussion{
{
Point: "Point 1",
KeyIDs: []int64{1, 2},
},
{
Point: "Point 2",
},
},
Conclusion: "Conclusion 1",
Discussion: []*openai.ChatHistorySummarizationOutputsDiscussion{{Point: "Point 1", KeyIDs: []int64{1, 2}}, {Point: "Point 2"}},
Conclusion: "Conclusion 1",
},
})
require.NoError(t, err)
Expand All @@ -44,15 +36,7 @@ func TestRecapOutputTemplateExecute(t *testing.T) {
Recap: &openai.ChatHistorySummarizationOutputs{
TopicName: "Topic 3",
ParticipantsNamesWithoutUsername: []string{"User 1", "User 2"},
Discussion: []*openai.ChatHistorySummarizationOutputsDiscussion{
{
Point: "Point 1",
},
{
Point: "Point 2",
KeyIDs: []int64{1, 2},
},
},
Discussion: []*openai.ChatHistorySummarizationOutputsDiscussion{{Point: "Point 1"}, {Point: "Point 2", KeyIDs: []int64{1, 2}}},
},
})
require.NoError(t, err)
Expand All @@ -70,16 +54,8 @@ func TestRecapOutputTemplateExecute(t *testing.T) {
TopicName: "Topic 1",
SinceID: 2,
ParticipantsNamesWithoutUsername: []string{"User 1", "User 2"},
Discussion: []*openai.ChatHistorySummarizationOutputsDiscussion{
{
Point: "Point 1",
KeyIDs: []int64{1, 2},
},
{
Point: "Point 2",
},
},
Conclusion: "Conclusion 2",
Discussion: []*openai.ChatHistorySummarizationOutputsDiscussion{{Point: "Point 1", KeyIDs: []int64{1, 2}}, {Point: "Point 2"}},
Conclusion: "Conclusion 2",
},
})
require.NoError(t, err)
Expand All @@ -93,6 +69,66 @@ func TestRecapOutputTemplateExecute(t *testing.T) {
assert.Equal(t, expected, sb.String())
}

func TestRecapWithoutLinksOutputTemplateExecute(t *testing.T) { //nolint:dupl
sb := new(strings.Builder)
err := RecapWithoutLinksOutputTemplate.Execute(sb, RecapOutputTemplateInputs{
ChatID: formatChatID(-100123456789),
Recap: &openai.ChatHistorySummarizationOutputs{
TopicName: "Topic 1",
SinceID: 1,
ParticipantsNamesWithoutUsername: []string{"User 1", "User 2"},
Discussion: []*openai.ChatHistorySummarizationOutputsDiscussion{{Point: "Point 1", KeyIDs: []int64{1, 2}}, {Point: "Point 2"}},
Conclusion: "Conclusion 1",
},
})
require.NoError(t, err)
expected := `## Topic 1
参与人:User 1,User 2
讨论:
- Point 1
- Point 2
结论:Conclusion 1`
assert.Equal(t, expected, sb.String())

sb = new(strings.Builder)
err = RecapWithoutLinksOutputTemplate.Execute(sb, RecapOutputTemplateInputs{
ChatID: formatChatID(-100123456789),
Recap: &openai.ChatHistorySummarizationOutputs{
TopicName: "Topic 3",
ParticipantsNamesWithoutUsername: []string{"User 1", "User 2"},
Discussion: []*openai.ChatHistorySummarizationOutputsDiscussion{{Point: "Point 1"}, {Point: "Point 2", KeyIDs: []int64{1, 2}}},
},
})
require.NoError(t, err)
expected = `## Topic 3
参与人:User 1,User 2
讨论:
- Point 1
- Point 2`
assert.Equal(t, expected, sb.String())

sb = new(strings.Builder)
err = RecapWithoutLinksOutputTemplate.Execute(sb, RecapOutputTemplateInputs{
ChatID: formatChatID(-100123456789),
Recap: &openai.ChatHistorySummarizationOutputs{
TopicName: "Topic 1",
SinceID: 2,
ParticipantsNamesWithoutUsername: []string{"User 1", "User 2"},
Discussion: []*openai.ChatHistorySummarizationOutputsDiscussion{{Point: "Point 1", KeyIDs: []int64{1, 2}}, {Point: "Point 2"}},
Conclusion: "Conclusion 2",
},
})
require.NoError(t, err)

expected = `## Topic 1
参与人:User 1,User 2
讨论:
- Point 1
- Point 2
结论:Conclusion 2`
assert.Equal(t, expected, sb.String())
}

func TestFormatFullNameAndUsername(t *testing.T) {
tests := []struct {
name string
Expand Down
26 changes: 23 additions & 3 deletions internal/services/autorecap/autorecap.go
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,18 @@ func (m *AutoRecapService) sendChatHistoriesRecapTimeCapsuleHandler(
func (m *AutoRecapService) summarize(chatID int64, options *ent.TelegramChatRecapsOptions, subscribers []*ent.TelegramChatAutoRecapsSubscribers) {
m.logger.Info("generating chat histories recap for chat", zap.Int64("chat_id", chatID))

chat, err := m.botService.GetChat(tgbotapi.ChatInfoConfig{
ChatConfig: tgbotapi.ChatConfig{
ChatID: chatID,
},
})
if err != nil {
m.logger.Error("failed to get chat", zap.Error(err), zap.Int64("chat_id", chatID))
return
}

chatType := telegram.ChatType(chat.Type)

histories, err := m.chathistories.FindLastSixHourChatHistories(chatID)
if err != nil {
m.logger.Error("failed to find last six hour chat histories", zap.Error(err), zap.Int64("chat_id", chatID))
Expand All @@ -166,7 +178,7 @@ func (m *AutoRecapService) summarize(chatID int64, options *ent.TelegramChatReca

chatTitle := histories[len(histories)-1].ChatTitle

logID, summarizations, err := m.chathistories.SummarizeChatHistories(chatID, histories)
logID, summarizations, err := m.chathistories.SummarizeChatHistories(chatID, chatType, histories)
if err != nil {
m.logger.Error("failed to summarize last six hour chat histories", zap.Error(err), zap.Int64("chat_id", chatID))
return
Expand Down Expand Up @@ -276,9 +288,17 @@ func (m *AutoRecapService) summarize(chatID int64, options *ent.TelegramChatReca
for i, b := range summarizationBatches {
var content string
if len(summarizationBatches) > 1 {
content = fmt.Sprintf("%s\n\n(%d/%d)\n#recap #recap_auto\n<em>🤖️ Generated by chatGPT</em>", strings.Join(b, "\n\n"), i+1, len(summarizationBatches))
content = fmt.Sprintf("%s\n\n(%d/%d)\n%s#recap #recap_auto\n<em>🤖️ Generated by chatGPT</em>",
strings.Join(b, "\n\n"),
i+1,
len(summarizationBatches),
lo.Ternary(chatType == telegram.ChatTypeGroup, "\n<b>Tips: </b>由于群组不是超级群组(supergroup),因此消息链接引用暂时被禁用了,如果希望使用该功能,请通过短时间内将群组开放为公共群组并还原回私有群组,或通过其他操作将本群组升级为超级群组后,该功能方可恢复正常运作。\n\n", ""),
)
} else {
content = fmt.Sprintf("%s\n\n#recap #recap_auto\n<em>🤖️ Generated by chatGPT</em>", strings.Join(b, "\n\n"))
content = fmt.Sprintf("%s\n\n%s#recap #recap_auto\n<em>🤖️ Generated by chatGPT</em>",
strings.Join(b, "\n\n"),
lo.Ternary(chatType == telegram.ChatTypeGroup, "<b>Tips: </b>由于群组不是超级群组(supergroup),因此消息链接引用暂时被禁用了,如果希望使用该功能,请通过短时间内将群组开放为公共群组并还原回私有群组,或通过其他操作将本群组升级为超级群组后,该功能方可恢复正常运作。\n\n", ""),
)
}

for _, targetChat := range targetChats {
Expand Down

0 comments on commit b2e7630

Please sign in to comment.