Files
SaveAny-Bot/common/utils/tgutil/resolve.go

120 lines
3.2 KiB
Go

package tgutil
import (
"fmt"
"net/url"
"strconv"
"strings"
"github.com/celestix/gotgproto/ext"
"github.com/duke-git/lancet/v2/validator"
"github.com/gotd/td/tg"
)
func ParseChatID(ctx *ext.Context, idOrUsername string) (int64, error) {
idOrUsername = strings.TrimPrefix(idOrUsername, "@")
if validator.IsIntStr(idOrUsername) {
chatID, err := strconv.Atoi(idOrUsername)
if err != nil {
return 0, err
}
return int64(chatID), nil
}
username := idOrUsername
peer := ctx.PeerStorage.GetPeerByUsername(username)
if peer != nil && peer.ID != 0 {
return peer.ID, nil
}
chat, err := ctx.ResolveUsername(username)
if err != nil {
return 0, err
}
if chat == nil {
return 0, fmt.Errorf("no chat found for username: %s", idOrUsername)
}
chatID := chat.GetID()
if chatID == 0 {
return 0, fmt.Errorf("chat ID is zero for username: %s", idOrUsername)
}
return chatID, nil
}
// return: ChatID, MessageID, error
func ParseMessageLink(ctx *ext.Context, link string) (int64, int, error) {
u, err := url.Parse(link)
if err != nil {
return 0, 0, fmt.Errorf("invalid URL: %w", err)
}
paths := strings.Split(strings.TrimPrefix(u.Path, "/"), "/")
if cmt := u.Query().Get("comment"); cmt != "" {
// 频道评论的消息链接
// https://t.me/acherkrau/123?comment=2
chid, err := ParseChatID(ctx, paths[0])
if err != nil {
return 0, 0, fmt.Errorf("failed to parse chat ID: %w", err)
}
chatfull, err := ctx.GetChat(chid)
if err != nil {
return 0, 0, fmt.Errorf("failed to get chat: %w", err)
}
chfull, ok := chatfull.(*tg.ChannelFull)
if !ok {
return 0, 0, fmt.Errorf("chat is not a channel: %s", chatfull.TypeName())
}
linkChatId, ok := chfull.GetLinkedChatID()
if !ok {
return 0, 0, fmt.Errorf("channel has no linked chat")
}
msgID, err := strconv.Atoi(cmt)
if err != nil {
return 0, 0, fmt.Errorf("failed to parse comment ID: %w", err)
}
return linkChatId, msgID, nil
}
switch len(paths) {
case 2: // https://t.me/acherkrau/123
chatID, err := ParseChatID(ctx, paths[0])
if err != nil {
return 0, 0, fmt.Errorf("failed to parse chat ID: %w", err)
}
msgID, err := strconv.Atoi(paths[1])
if err != nil {
return 0, 0, fmt.Errorf("failed to parse message ID: %w", err)
}
return chatID, msgID, nil
case 3:
// https://t.me/c/123456789/123
// https://t.me/acherkrau/123/456 , 123: topic id
chatPart, msgPart := paths[1], paths[2]
if paths[0] != "c" {
chatPart = paths[0]
}
chatID, err := ParseChatID(ctx, chatPart)
if err != nil {
return 0, 0, fmt.Errorf("failed to parse chat ID: %w", err)
}
msgID, err := strconv.Atoi(msgPart)
if err != nil {
return 0, 0, fmt.Errorf("failed to parse message ID: %w", err)
}
return chatID, msgID, nil
case 4:
// https://t.me/c/123456789/111/456 111: topic id
if paths[0] != "c" {
return 0, 0, fmt.Errorf("invalid message link format: %s", link)
}
chatID, err := ParseChatID(ctx, paths[1])
if err != nil {
return 0, 0, fmt.Errorf("failed to parse chat ID: %w", err)
}
msgID, err := strconv.Atoi(paths[3])
if err != nil {
return 0, 0, fmt.Errorf("failed to parse message ID: %w", err)
}
return chatID, msgID, nil
}
return 0, 0, fmt.Errorf("invalid message link format: %s", link)
}