11package bot
22
33import (
4+ "errors"
45 "fmt"
6+ "net/url"
57 "regexp"
68 "strconv"
79 "strings"
@@ -16,39 +18,99 @@ import (
1618)
1719
1820var (
19- linkRegexString = `t .me/.* /\d+`
21+ linkRegexString = `https?://t\ .me/(?:c /\d+|[a-zA-Z0-9_]+)/\d+(?:\?[^\s]*)? `
2022 linkRegex = regexp .MustCompile (linkRegexString )
2123)
2224
23- func parseLink (ctx * ext.Context , link string ) (chatID int64 , messageID int , err error ) {
24- strSlice := strings .Split (link , "/" )
25+ type parseResult struct {
26+ ChatID int64
27+ MessageID int
28+ Files []* types.File
29+ UserClient bool
30+ }
31+
32+ func parseLink (ctx * ext.Context , link string ) (* parseResult , error ) {
33+ u , err := url .Parse (link )
34+ if err != nil {
35+ return nil , fmt .Errorf ("无法解析链接: %s" , err )
36+ }
37+ strSlice := strings .Split (u .Path , "/" )
2538 if len (strSlice ) < 3 {
26- return 0 , 0 , fmt .Errorf ("链接格式错误: %s" , link )
39+ return nil , fmt .Errorf ("链接格式错误: %s" , link )
2740 }
28- messageID , err = strconv .Atoi (strSlice [len (strSlice )- 1 ])
41+ messageID , err : = strconv .Atoi (strSlice [len (strSlice )- 1 ])
2942 if err != nil {
30- return 0 , 0 , fmt .Errorf ("无法解析消息 ID: %s" , err )
43+ return nil , fmt .Errorf ("无法解析消息 ID: %s" , err )
3144 }
45+ var chatID int64
3246 if len (strSlice ) == 3 {
3347 chatUsername := strSlice [1 ]
34- linkChat , err := ctx .ResolveUsername (chatUsername )
35- if err != nil {
36- return 0 , 0 , fmt .Errorf ("解析用户名失败: %s" , err )
37- }
38- if linkChat == nil {
39- return 0 , 0 , fmt .Errorf ("找不到该聊天: %s" , chatUsername )
48+ peer := ctx .PeerStorage .GetPeerByUsername (chatUsername )
49+ if peer != nil {
50+ chatID = peer .ID
51+ } else {
52+ linkChat , err := ctx .ResolveUsername (chatUsername )
53+ if err != nil {
54+ return nil , fmt .Errorf ("解析用户名失败: %s" , err )
55+ }
56+ if linkChat == nil {
57+ return nil , fmt .Errorf ("找不到该聊天: %s" , chatUsername )
58+ }
59+ chatID = linkChat .GetID ()
4060 }
41- chatID = linkChat .GetID ()
4261 } else if len (strSlice ) == 4 {
4362 chatIDInt , err := strconv .Atoi (strSlice [2 ])
4463 if err != nil {
45- return 0 , 0 , fmt .Errorf ("无法解析 Chat ID: %s" , err )
64+ return nil , fmt .Errorf ("无法解析 Chat ID: %s" , err )
4665 }
4766 chatID = int64 (chatIDInt )
4867 } else {
49- return 0 , 0 , fmt .Errorf ("无效的链接: %s" , link )
68+ return nil , errors .New ("链接格式不正确,无法解析 Chat ID" )
69+ }
70+ if chatID == 0 || messageID == 0 {
71+ return nil , fmt .Errorf ("链接中缺少 Chat ID 或 Message ID: %s" , link )
72+ }
73+ msg , _ , err := tryFetchMessage (ctx , chatID , messageID )
74+ if err != nil {
75+ return nil , fmt .Errorf ("获取消息失败: %s" , err )
76+ }
77+ mediaGroup , isGroup := msg .GetGroupedID ()
78+ if u .Query ().Has ("single" ) || ! isGroup || (mediaGroup == 0 ) || userclient .UC == nil {
79+ file , useUserClient , err := tryFetchFileFromMessage (ctx , chatID , messageID , "" )
80+ if err != nil {
81+ return nil , fmt .Errorf ("获取文件失败: %s" , err )
82+ }
83+ if file .FileName == "" {
84+ file .FileName = GenFileNameFromMessage (* msg , file )
85+ }
86+ return & parseResult {
87+ ChatID : chatID ,
88+ MessageID : messageID ,
89+ Files : []* types.File {file },
90+ UserClient : useUserClient ,
91+ }, nil
92+ }
93+ groupMessages , isUserClient , err := tryGetMediaGroup (chatID , messageID , mediaGroup )
94+ if err != nil {
95+ return nil , fmt .Errorf ("获取媒体组消息失败: %s" , err )
96+ }
97+ var files []* types.File
98+ for _ , groupMsg := range groupMessages {
99+ file , err := FileFromMedia (groupMsg .Media , "" )
100+ if err != nil {
101+ return nil , fmt .Errorf ("获取媒体文件失败: %s" , err )
102+ }
103+ if file .FileName == "" {
104+ file .FileName = GenFileNameFromMessage (* groupMsg , file )
105+ }
106+ files = append (files , file )
50107 }
51- return chatID , messageID , nil
108+ return & parseResult {
109+ ChatID : chatID ,
110+ MessageID : messageID ,
111+ Files : files ,
112+ UserClient : isUserClient ,
113+ }, nil
52114}
53115
54116// use passed ctx client to fetch file from message,
@@ -62,18 +124,50 @@ func tryFetchFileFromMessage(ctx *ext.Context, chatID int64, messageID int, file
62124 if (strings .Contains (err .Error (), "peer not found" ) || strings .Contains (err .Error (), "unexpected message type" )) && userclient .UC != nil {
63125 common .Log .Warnf ("无法获取文件 %d:%d, 尝试使用 userbot: %s" , chatID , messageID , err )
64126 uctx := userclient .GetCtx ()
65- // TODO: 群组支持
66- file , err = FileFromMessage (uctx , chatID , messageID , fileName )
67- if err == nil {
68- return file , true , nil
127+ peer := uctx .PeerStorage .GetInputPeerById (chatID )
128+ if peer == nil {
129+ return nil , true , fmt .Errorf ("failed to get peer for chat %d: %w" , chatID , err )
130+ }
131+ msg , err := GetSingleHistoryMessage (uctx , uctx .Raw , peer , messageID )
132+ if err != nil {
133+ return nil , true , err
69134 }
70- return nil , true , err
135+ file , err = FileFromMedia (msg .Media , fileName )
136+ if err != nil {
137+ return nil , true , fmt .Errorf ("failed to get file from userbot message %d:%d: %w" , chatID , messageID , err )
138+ }
139+ return file , true , nil
71140 }
72141 return nil , false , err
73142}
74143
75- func tryFetchMessage (ctx * ext.Context , chatID int64 , messageID int ) (* tg.Message , error ) {
76- return GetTGMessage (ctx , chatID , messageID )
144+ func tryGetMediaGroup (chatID int64 , messageID int , mediaGroupID int64 ) ([]* tg.Message , bool , error ) {
145+ if userclient .UC != nil {
146+ uctx := userclient .GetCtx ()
147+ messages , err := GetMediaGroup (uctx , chatID , messageID , mediaGroupID )
148+ if err != nil {
149+ return nil , true , fmt .Errorf ("failed to get media group from userbot: %w" , err )
150+ }
151+ return messages , true , nil
152+ }
153+ return nil , false , errors .New ("userclient is not available, cannot fetch media group" )
154+ }
155+
156+ func tryFetchMessage (ctx * ext.Context , chatID int64 , messageID int ) (* tg.Message , bool , error ) {
157+ msg , err := GetTGMessage (ctx , chatID , messageID )
158+ if err == nil {
159+ return msg , false , nil
160+ }
161+ if userclient .UC != nil && (strings .Contains (err .Error (), "peer not found" ) || strings .Contains (err .Error (), "unexpected message type" )) {
162+ common .Log .Warnf ("无法获取消息 %d:%d, 尝试使用 userbot: %s" , chatID , messageID , err )
163+ uctx := userclient .GetCtx ()
164+ msg , err := GetTGMessage (uctx , chatID , messageID )
165+ if err == nil {
166+ return msg , true , nil
167+ }
168+ return nil , true , fmt .Errorf ("获取消息失败: %w" , err )
169+ }
170+ return nil , false , fmt .Errorf ("获取消息失败: %s" , err )
77171}
78172
79173func handleLinkMessage (ctx * ext.Context , update * ext.Update ) error {
@@ -82,10 +176,10 @@ func handleLinkMessage(ctx *ext.Context, update *ext.Update) error {
82176 if link == "" {
83177 return dispatcher .ContinueGroups
84178 }
85- linkChatID , messageID , err := parseLink (ctx , link )
179+ result , err := parseLink (ctx , link )
86180 if err != nil {
87181 common .Log .Errorf ("解析链接失败: %s" , err )
88- ctx .Reply (update , ext .ReplyTextString ("解析链接失败: " + err . Error () ), nil )
182+ ctx .Reply (update , ext .ReplyTextString ("解析链接失败" ), nil )
89183 return dispatcher .EndGroups
90184 }
91185
@@ -102,29 +196,15 @@ func handleLinkMessage(ctx *ext.Context, update *ext.Update) error {
102196 return dispatcher .EndGroups
103197 }
104198
105- file , useUserClient , err := tryFetchFileFromMessage (ctx , linkChatID , messageID , "" )
106- if err != nil {
107- common .Log .Errorf ("获取文件失败: %s" , err )
108- ctx .Reply (update , ext .ReplyTextString ("获取文件失败: " + err .Error ()), nil )
109- return dispatcher .EndGroups
110- }
111- if file .FileName == "" {
112- msg , err := tryFetchMessage (ctx , linkChatID , messageID )
113- if err != nil {
114- file .FileName = fmt .Sprintf ("%d_%d" , linkChatID , messageID )
115- } else {
116- file .FileName = GenFileNameFromMessage (* msg , file )
117- }
118- }
119-
199+ // TODO: handle group files
120200 receivedFile := & dao.ReceivedFile {
121201 Processing : false ,
122- FileName : file .FileName ,
123- ChatID : linkChatID ,
124- MessageID : messageID ,
202+ FileName : result . Files [ 0 ] .FileName ,
203+ ChatID : result . ChatID ,
204+ MessageID : result . MessageID ,
125205 ReplyMessageID : replied .ID ,
126206 ReplyChatID : update .GetUserChat ().GetID (),
127- UseUserClient : useUserClient ,
207+ UseUserClient : result . UserClient ,
128208 }
129209 record , err := dao .SaveReceivedFile (receivedFile )
130210 if err != nil {
@@ -135,19 +215,20 @@ func handleLinkMessage(ctx *ext.Context, update *ext.Update) error {
135215 })
136216 return dispatcher .EndGroups
137217 }
218+ file := result .Files [0 ]
138219 if ! user .Silent || user .DefaultStorage == "" {
139- return ProvideSelectMessage (ctx , update , file .FileName , linkChatID , messageID , replied .ID )
220+ return ProvideSelectMessage (ctx , update , file .FileName , result . ChatID , result . MessageID , replied .ID )
140221 }
141222 return HandleSilentAddTask (ctx , update , user , & types.Task {
142223 Ctx : ctx ,
143224 Status : types .Pending ,
144225 FileDBID : record .ID ,
145- UseUserClient : useUserClient ,
226+ UseUserClient : result . UserClient ,
146227 File : file ,
147228 StorageName : user .DefaultStorage ,
148229 UserID : user .ChatID ,
149- FileChatID : linkChatID ,
150- FileMessageID : messageID ,
230+ FileChatID : result . ChatID ,
231+ FileMessageID : result . MessageID ,
151232 ReplyMessageID : replied .ID ,
152233 ReplyChatID : update .GetUserChat ().GetID (),
153234 })
0 commit comments