feat: sync chatlist sharing support
This commit is contained in:
parent
ec6e8fd13d
commit
2a9c12263f
62 changed files with 3408 additions and 212 deletions
|
|
@ -396,7 +396,7 @@ func (s *Service) handleNewBotUsername(ctx context.Context, state domain.BotChat
|
|||
if err := s.bots.DeleteBotChatState(ctx, domain.BotFatherUserID, state.UserID); err != nil {
|
||||
s.log.Error("botfather: delete chat state", zap.Int64("user_id", state.UserID), zap.Error(err))
|
||||
}
|
||||
head := fmt.Sprintf("Done! Congratulations on your new bot. You will find it at telesrv.net/%s.\n\nUse this token to access the HTTP API:\n", u.Username)
|
||||
head := fmt.Sprintf("Done! Congratulations on your new bot. You will find it at %s.\n\nUse this token to access the HTTP API:\n", s.publicURL(u.Username))
|
||||
return tokenReply(head, token, "\n\nKeep your token secure and store it safely, it can be used by anyone to control your bot.")
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -17,6 +17,7 @@ import (
|
|||
"go.uber.org/zap"
|
||||
|
||||
"telesrv/internal/domain"
|
||||
"telesrv/internal/links"
|
||||
"telesrv/internal/store"
|
||||
)
|
||||
|
||||
|
|
@ -88,6 +89,7 @@ type Service struct {
|
|||
log *zap.Logger
|
||||
now func() time.Time
|
||||
chatBotStreamThrottle time.Duration
|
||||
publicBaseURL string
|
||||
// replySeq 是回复 randomID 在 crypto/rand 失败时的兜底单调序列。
|
||||
replySeq atomic.Int64
|
||||
replyLocks [replyLockStripes]sync.Mutex
|
||||
|
|
@ -182,6 +184,12 @@ func WithAIChatStreamThrottle(d time.Duration) Option {
|
|||
}
|
||||
}
|
||||
|
||||
func WithPublicBaseURL(baseURL string) Option {
|
||||
return func(s *Service) {
|
||||
s.publicBaseURL = links.NormalizeBaseURL(baseURL)
|
||||
}
|
||||
}
|
||||
|
||||
// invalidateUserCache 在 bot 的 users 行变更(含 version bump)后清缓存。
|
||||
// 失效失败只记日志:缓存最长 TTL 后自愈,不阻塞写路径。
|
||||
func (s *Service) invalidateUserCache(ctx context.Context, botUserID int64) {
|
||||
|
|
@ -252,6 +260,7 @@ func NewService(users store.UserStore, bots store.BotStore, messages store.Messa
|
|||
log: zap.NewNop(),
|
||||
now: time.Now,
|
||||
chatBotStreamThrottle: defaultChatBotStreamThrottle,
|
||||
publicBaseURL: links.DefaultPublicBaseURL,
|
||||
}
|
||||
for _, opt := range opts {
|
||||
opt(s)
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ import (
|
|||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"net/url"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
|
@ -13,6 +14,7 @@ import (
|
|||
"go.uber.org/zap"
|
||||
|
||||
"telesrv/internal/domain"
|
||||
"telesrv/internal/links"
|
||||
)
|
||||
|
||||
const (
|
||||
|
|
@ -409,7 +411,7 @@ func (s *Service) handleStickersAddEmoji(ctx context.Context, state domain.BotCh
|
|||
if s.hooks != nil {
|
||||
s.hooks.PushStickerSetsChanged(ctx, state.UserID, stickersBotSetKind(set))
|
||||
}
|
||||
return botReply{Text: fmt.Sprintf("Done. Added to %s.\n\n%s", stickersBotSetTitle(set), stickersBotPublicURL(set))}
|
||||
return botReply{Text: fmt.Sprintf("Done. Added to %s.\n\n%s", stickersBotSetTitle(set), s.stickersBotPublicURL(set))}
|
||||
}
|
||||
|
||||
func (s *Service) handleStickersDeleteDocument(ctx context.Context, state domain.BotChatState, msg domain.Message) botReply {
|
||||
|
|
@ -443,7 +445,7 @@ func (s *Service) handleStickersDeleteDocument(ctx context.Context, state domain
|
|||
if s.hooks != nil {
|
||||
s.hooks.PushStickerSetsChanged(ctx, state.UserID, stickersBotSetKind(set))
|
||||
}
|
||||
return botReply{Text: fmt.Sprintf("Done. Removed from %s.\n\n%s", stickersBotSetTitle(set), stickersBotPublicURL(set))}
|
||||
return botReply{Text: fmt.Sprintf("Done. Removed from %s.\n\n%s", stickersBotSetTitle(set), s.stickersBotPublicURL(set))}
|
||||
}
|
||||
|
||||
func (s *Service) handleStickersShortName(ctx context.Context, state domain.BotChatState, raw string) botReply {
|
||||
|
|
@ -484,7 +486,7 @@ func (s *Service) handleStickersShortName(ctx context.Context, state domain.BotC
|
|||
if s.hooks != nil {
|
||||
s.hooks.PushStickerSetsChanged(ctx, state.UserID, installKind)
|
||||
}
|
||||
return botReply{Text: "Done. Your pack is published and installed.\n\n" + stickersBotPublicURL(set)}
|
||||
return botReply{Text: "Done. Your pack is published and installed.\n\n" + s.stickersBotPublicURL(set)}
|
||||
}
|
||||
|
||||
func (s *Service) stickersBotCreateError(userID int64, err error) botReply {
|
||||
|
|
@ -542,7 +544,7 @@ func (s *Service) listStickersBotPacks(ctx context.Context, userID int64) botRep
|
|||
lines := make([]string, 0, len(sets)+1)
|
||||
lines = append(lines, "Your packs:")
|
||||
for _, set := range sets {
|
||||
lines = append(lines, fmt.Sprintf("%s - %s", set.Title, stickersBotPublicURL(set)))
|
||||
lines = append(lines, fmt.Sprintf("%s - %s", set.Title, s.stickersBotPublicURL(set)))
|
||||
}
|
||||
if total > len(sets) {
|
||||
lines = append(lines, fmt.Sprintf("Showing %d of %d.", len(sets), total))
|
||||
|
|
@ -746,12 +748,21 @@ func cloneStickersBotState(state domain.BotChatState) domain.BotChatState {
|
|||
|
||||
func normalizeStickersBotShortName(raw string) string {
|
||||
raw = strings.TrimSpace(raw)
|
||||
raw = strings.TrimPrefix(raw, "https://telesrv.net/addstickers/")
|
||||
raw = strings.TrimPrefix(raw, "https://telesrv.net/addemoji/")
|
||||
raw = strings.TrimPrefix(raw, "telesrv://addstickers?set=")
|
||||
raw = strings.TrimPrefix(raw, "telesrv://addemoji?set=")
|
||||
raw = strings.TrimPrefix(raw, "tg://addstickers?set=")
|
||||
raw = strings.TrimPrefix(raw, "tg://addemoji?set=")
|
||||
if strings.Contains(raw, "://") {
|
||||
if parsed, err := url.Parse(raw); err == nil {
|
||||
parts := strings.Split(strings.Trim(parsed.Path, "/"), "/")
|
||||
for i, part := range parts {
|
||||
if (part == "addstickers" || part == "addemoji") && i+1 < len(parts) {
|
||||
raw = parts[i+1]
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return strings.ToLower(strings.Trim(raw, " /"))
|
||||
}
|
||||
|
||||
|
|
@ -784,10 +795,18 @@ func validStickersBotEmoji(raw string) bool {
|
|||
return hasEmoji
|
||||
}
|
||||
|
||||
func stickersBotPublicURL(set domain.StickerSet) string {
|
||||
func (s *Service) stickersBotPublicURL(set domain.StickerSet) string {
|
||||
part := "addstickers"
|
||||
if stickersBotSetKind(set) == domain.StickerSetKindEmoji {
|
||||
part = "addemoji"
|
||||
}
|
||||
return "https://telesrv.net/" + part + "/" + set.ShortName
|
||||
return s.publicURL(part + "/" + set.ShortName)
|
||||
}
|
||||
|
||||
func (s *Service) publicURL(path string) string {
|
||||
baseURL := links.DefaultPublicBaseURL
|
||||
if s != nil && s.publicBaseURL != "" {
|
||||
baseURL = s.publicBaseURL
|
||||
}
|
||||
return links.Build(baseURL, path, nil)
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue