feat: Add RSS feed generation for channel messages and update route handling

This commit is contained in:
2026-03-10 00:23:42 +03:30
parent c538bfb799
commit 381cdd42aa
4 changed files with 112 additions and 3 deletions
+3
View File
@@ -4,6 +4,7 @@ import (
"tgss/internal/config"
"tgss/internal/handlers"
"tgss/internal/infra"
"tgss/internal/rss"
"tgss/internal/server"
"tgss/internal/telegram"
@@ -19,6 +20,8 @@ func main() {
handlers.NewChannelHandler,
handlers.NewAuthHandler,
rss.NewRSSGenerator,
),
telegram.Module,
fx.Invoke(server.RegisterRoutes),
+32 -1
View File
@@ -3,6 +3,7 @@ package handlers
import (
"context"
"strconv"
"tgss/internal/rss"
"tgss/internal/telegram"
"time"
@@ -13,6 +14,7 @@ import (
type ChannelHandler struct {
logger *zap.Logger
tgService *telegram.Service
rss *rss.RSSGenerator
}
func NewChannelHandler(
@@ -25,7 +27,7 @@ func NewChannelHandler(
}
}
func (ch *ChannelHandler) GetLatestMessages(c *gin.Context) {
func (ch *ChannelHandler) GetMessagesJson(c *gin.Context) {
channelId := c.Param("id")
limit := 5
@@ -51,3 +53,32 @@ func (ch *ChannelHandler) GetLatestMessages(c *gin.Context) {
c.JSON(200, messages)
}
func (ch *ChannelHandler) GetMessagesRSS(c *gin.Context) {
channelId := c.Param("id")
limit := 5
if limitStr := c.Query("limit"); limitStr != "" {
var err error
limit, err = strconv.Atoi(limitStr)
if err != nil || limit > 50 {
ch.logger.Warn("Invalid limit value provided", zap.String("limit", limitStr))
c.JSON(400, gin.H{"error": "Limit value provided is invalid or bigger than 50"})
return
}
}
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
defer cancel()
messages, err := ch.tgService.LastMessages(ctx, channelId, limit)
if err != nil {
ch.logger.Error("Error getting channel messages:", zap.Error(err))
c.JSON(500, gin.H{"error": "Unable to get channel messages"})
return
}
rssFeed := ch.rss.GenerateFeed(messages, channelId)
c.XML(200, rssFeed)
}
+75 -1
View File
@@ -1 +1,75 @@
package rss
package rss
import (
"encoding/xml"
"strconv"
"time"
"github.com/gotd/td/tg"
"go.uber.org/zap"
)
type RSSItem struct {
Title string `xml:"title"`
Link string `xml:"link"`
PubDate string `xml:"pubDate,omitempty"`
Description string `xml:"description"`
Guid string `xml:"guid,omitempty"`
}
type RSSChannel struct {
Title string `xml:"title"`
Link string `xml:"link"`
Description string `xml:"description"`
PubDate string `xml:"pubDate,omitempty"`
LastBuildDate string `xml:"lastBuildDate,omitempty"`
Generator string `xml:"generator,omitempty"`
Items []RSSItem `xml:"item"`
}
type RSSFeed struct {
XMLName xml.Name `xml:"rss"`
Version string `xml:"version,attr"`
XmlnsAtom string `xml:"xmlns:atom,attr"`
Channel RSSChannel `xml:"channel"`
}
type RSSGenerator struct {
logger *zap.Logger
}
func NewRSSGenerator(logger zap.Logger) *RSSGenerator {
return &RSSGenerator{logger: &logger}
}
func (r *RSSGenerator) GenerateFeed(items []tg.MessageClass, channelId string) *RSSFeed {
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"),
Generator: "Telegram RSS Generator",
}
for _, m := range items {
rssChannel.Items = append(rssChannel.Items, *r.messageToItem(m, channelId))
}
return &RSSFeed{
Version: "2.0",
XmlnsAtom: "http://www.w3.org/2005/Atom",
Channel: *rssChannel,
}
}
func (r *RSSGenerator) messageToItem(msg tg.MessageClass, channelId string) *RSSItem {
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()),
}
}
+2 -1
View File
@@ -41,7 +41,8 @@ func RegisterRoutes(params RouterParams) {
})
})
params.GinEngine.GET("/channel/:id", params.ChannelHandler.GetLatestMessages)
// params.GinEngine.GET("/channel/:id/json", params.ChannelHandler.GetMessagesJson)
params.GinEngine.GET("/channel/:id", params.ChannelHandler.GetMessagesRSS)
params.GinEngine.POST("/auth/send-code", params.AuthHandler.SendCode)
params.GinEngine.POST("/auth/verify", params.AuthHandler.Verify)