mirror of
https://github.com/mmahdium/TGSS.git
synced 2026-08-12 08:32:48 +03:30
feat: Enhance Telegram service with authentication status management and improve RSS feed generation error handling
This commit is contained in:
@@ -55,6 +55,14 @@ func (ch *ChannelHandler) GetMessagesJson(c *gin.Context) {
|
||||
}
|
||||
|
||||
func (ch *ChannelHandler) GetMessagesRSS(c *gin.Context) {
|
||||
authStatCtx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
|
||||
defer cancel()
|
||||
|
||||
authStat, err := ch.tgService.AuthStatus(authStatCtx)
|
||||
if err != nil || !authStat {
|
||||
c.JSON(500, gin.H{"error": "Telegram client is not initialized"})
|
||||
}
|
||||
|
||||
channelId := c.Param("id")
|
||||
limit := 5
|
||||
|
||||
|
||||
+62
-11
@@ -2,6 +2,8 @@ package rss
|
||||
|
||||
import (
|
||||
"encoding/xml"
|
||||
"fmt"
|
||||
"net/url"
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
@@ -40,23 +42,57 @@ type RSSGenerator struct {
|
||||
logger *zap.Logger
|
||||
}
|
||||
|
||||
func NewRSSGenerator(logger zap.Logger) *RSSGenerator {
|
||||
return &RSSGenerator{logger: &logger}
|
||||
func NewRSSGenerator(logger *zap.Logger) *RSSGenerator {
|
||||
return &RSSGenerator{logger: logger}
|
||||
}
|
||||
|
||||
func (r *RSSGenerator) GenerateFeed(items []tg.MessageClass, channelId string) *RSSFeed {
|
||||
if channelId == "" {
|
||||
r.logger.Error("GenerateFeed called with empty channelId")
|
||||
return nil
|
||||
}
|
||||
|
||||
nowStr := time.Now().Format("Mon, 02 Jan 2006 15:04 MST")
|
||||
|
||||
rssChannel := &RSSChannel{
|
||||
Title: "Recent posts from @" + channelId,
|
||||
Link: "https://t.me/" + channelId,
|
||||
Description: "This feed contains the most recent posts from the Telegram channel @" + channelId + ". " +
|
||||
"Stay updated with the latest news and updates from the channel.",
|
||||
PubDate: time.Now().Format("Mon, 02 Jan 2006 15:04 MST"),
|
||||
LastBuildDate: time.Now().Format("Mon, 02 Jan 2006 15:04 MST"),
|
||||
PubDate: nowStr,
|
||||
LastBuildDate: nowStr,
|
||||
Generator: "Telegram RSS Generator",
|
||||
}
|
||||
|
||||
errorCount := 0
|
||||
|
||||
for _, m := range items {
|
||||
rssChannel.Items = append(rssChannel.Items, *r.messageToItem(m, channelId))
|
||||
if m == nil {
|
||||
errorCount++
|
||||
continue
|
||||
}
|
||||
|
||||
item, err := r.messageToItem(m, channelId)
|
||||
if err != nil {
|
||||
r.logger.Error("failed to convert message to RSS item",
|
||||
zap.String("channel", channelId),
|
||||
zap.Int("message_id", m.GetID()),
|
||||
zap.Error(err),
|
||||
)
|
||||
errorCount++
|
||||
continue
|
||||
}
|
||||
|
||||
rssChannel.Items = append(rssChannel.Items, *item)
|
||||
}
|
||||
|
||||
if errorCount > 0 {
|
||||
r.logger.Warn("feed generation completed with errors",
|
||||
zap.String("channel", channelId),
|
||||
zap.Int("failed", errorCount),
|
||||
)
|
||||
}
|
||||
|
||||
return &RSSFeed{
|
||||
Version: "2.0",
|
||||
XmlnsAtom: "http://www.w3.org/2005/Atom",
|
||||
@@ -64,12 +100,27 @@ func (r *RSSGenerator) GenerateFeed(items []tg.MessageClass, channelId string) *
|
||||
}
|
||||
}
|
||||
|
||||
func (r *RSSGenerator) messageToItem(msg tg.MessageClass, channelId string) *RSSItem {
|
||||
func (r *RSSGenerator) messageToItem(msg tg.MessageClass, channelId string) (*RSSItem, error) {
|
||||
message, ok := msg.(*tg.Message)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("unsupported message type: %T", msg)
|
||||
}
|
||||
|
||||
messageURL, err := url.Parse("https://t.me/" + channelId + "/" + strconv.Itoa(msg.GetID()))
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to parse message URL: %w", err)
|
||||
}
|
||||
|
||||
description := message.Message
|
||||
if description == "" {
|
||||
description = "No content"
|
||||
}
|
||||
|
||||
return &RSSItem{
|
||||
Title: "Post by @" + channelId + " on Telegram",
|
||||
Link: "https://t.me/" + channelId + "/" + strconv.Itoa(msg.GetID()), // TODO: URL parse it
|
||||
PubDate: time.Unix(int64(msg.(*tg.Message).Date), 0).Format("Mon, 02 Jan 2006 15:04 MST"),
|
||||
Description: msg.(*tg.Message).Message,
|
||||
Guid: "https://t.me/" + channelId + "/" + strconv.Itoa(msg.GetID()),
|
||||
}
|
||||
Link: messageURL.String(),
|
||||
PubDate: time.Unix(int64(message.Date), 0).Format("Mon, 02 Jan 2006 15:04 MST"),
|
||||
Description: description,
|
||||
Guid: messageURL.String(),
|
||||
}, nil
|
||||
}
|
||||
|
||||
@@ -52,7 +52,7 @@ func NewTelegramClient(cfg *config.Config, logger *zap.Logger) *telegram.Client
|
||||
return telegram.NewClient(cfg.TgAppId, cfg.TgAppHash, opts)
|
||||
}
|
||||
|
||||
func RunClient(lc fx.Lifecycle, client *telegram.Client, logger *zap.Logger) {
|
||||
func RunClient(lc fx.Lifecycle, client *telegram.Client, service *Service, logger *zap.Logger) {
|
||||
var stop func() error
|
||||
|
||||
lc.Append(fx.Hook{
|
||||
@@ -64,6 +64,11 @@ func RunClient(lc fx.Lifecycle, client *telegram.Client, logger *zap.Logger) {
|
||||
|
||||
stop = s
|
||||
logger.Info("telegram client connected")
|
||||
|
||||
if err := service.InitAuthStatus(ctx); err != nil {
|
||||
logger.Warn("Failed to initialize Telegram auth status", zap.Error(err))
|
||||
}
|
||||
|
||||
return nil
|
||||
},
|
||||
OnStop: func(ctx context.Context) error {
|
||||
|
||||
@@ -4,6 +4,7 @@ import (
|
||||
"context"
|
||||
"errors"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/gotd/td/telegram"
|
||||
"github.com/gotd/td/telegram/auth"
|
||||
@@ -15,24 +16,48 @@ type Service struct {
|
||||
client *telegram.Client
|
||||
log *zap.Logger
|
||||
|
||||
mu sync.Mutex
|
||||
phone string
|
||||
phoneCodeHash string
|
||||
mu sync.Mutex
|
||||
phone string
|
||||
phoneCodeHash string
|
||||
authStatus bool
|
||||
authCheckedAt time.Time
|
||||
authTTL time.Duration
|
||||
}
|
||||
|
||||
func NewService(client *telegram.Client, logger *zap.Logger) *Service {
|
||||
return &Service{
|
||||
client: client,
|
||||
log: logger,
|
||||
client: client,
|
||||
log: logger,
|
||||
authTTL: 10 * time.Minute,
|
||||
}
|
||||
}
|
||||
|
||||
func (s *Service) AuthStatus(ctx context.Context) (bool, error) {
|
||||
_, err := s.client.Auth().Status(ctx)
|
||||
if err != nil {
|
||||
return false, err
|
||||
s.mu.Lock()
|
||||
defer s.mu.Unlock()
|
||||
|
||||
if time.Since(s.authCheckedAt) < s.authTTL {
|
||||
return s.authStatus, nil
|
||||
}
|
||||
return true, nil
|
||||
|
||||
status, err := s.client.Auth().Status(ctx)
|
||||
if err != nil {
|
||||
s.authStatus = false
|
||||
} else {
|
||||
s.authStatus = status.Authorized
|
||||
}
|
||||
s.authCheckedAt = time.Now()
|
||||
|
||||
return s.authStatus, err
|
||||
}
|
||||
|
||||
func (s *Service) InitAuthStatus(ctx context.Context) error {
|
||||
status, err := s.AuthStatus(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
s.log.Info("Telegram auth status initialized", zap.Bool("authenticated", status))
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *Service) SendCode(ctx context.Context, phone string) error {
|
||||
|
||||
Reference in New Issue
Block a user