gruik

Fork of GCU-Squad's RSS-to-IRC bridge
git clone https://git.instinctive.eu/gruik.git
Log | Files | Refs | README | LICENSE

commit 8f2f52c1cfa816db1531324e32367d2dc0420ce1
parent 7d3bae69890d1d17deb4e8bb063ba730a480a054
Author: Emile 'iMil' Heitor <imil@NetBSD.org>
Date:   Fri, 14 Jul 2023 09:46:32 +0200

feat: added xpost support

Diffstat:
MREADME.md | 3++-
Mmain.go | 111+++++++++++++++++++++++++++++++++++++++++++++++++++++--------------------------
2 files changed, 77 insertions(+), 37 deletions(-)

diff --git a/README.md b/README.md @@ -17,7 +17,7 @@ irc: port: 6667 # ditto delay: 2s # ditto, delay between 2 lines to avoid flood colors: # ditto - title: pink # ditto + origin: pink # ditto news: bold # ditto link: lightblue # ditto hash: gray # ditto @@ -59,6 +59,7 @@ $ ./Gruik For everybody: * `!lsfeeds` lists available RSS feeds, can be asked privately +* `!xpost <news hash>` posts news with hash `<news hash>` to `xchannels` For ops: diff --git a/main.go b/main.go @@ -24,6 +24,8 @@ type News struct { Hash string `json:"hash"` } +var newslist []News + func mkHash(s1, s2 string) string { s := s1 + s2 h := sha256.Sum256([]byte(s)) @@ -31,7 +33,7 @@ func mkHash(s1, s2 string) string { return hash[:8] } -func newsExists(newslist []News, news News) bool { +func newsExists(news News) bool { for _, n := range newslist { if n.Hash == news.Hash { return true @@ -40,10 +42,34 @@ func newsExists(newslist []News, news News) bool { return false } +func getNewsByHash(hash string) News { + if strings.Contains(hash, "#") { + hash = hash[1:] + } + for _, n := range newslist { + if n.Hash == hash { + return n + } + } + return News{} +} + +func fmtNews(news News) string { + return fmt.Sprintf("[{%s}%s{c}] {%s}%s{c} {%s}%s{c} {%s}#%s{c}", + viper.GetString("irc.colors.origin"), + news.Origin, + viper.GetString("irc.colors.title"), + news.Title, + viper.GetString("irc.colors.link"), + news.Link, + viper.GetString("irc.colors.hash"), + news.Hash) +} + // Fetch and post news from RSS feeds func newsFetch(client *girc.Client, channel string) { - newslist := []News{} + newslist = make([]News, 0) start := time.Now() @@ -74,7 +100,7 @@ func newsFetch(client *girc.Client, channel string) { for { // reset news list after one day if time.Since(start) > oneDay { - newslist = []News{} + newslist = make([]News, 0) } for _, feedURL := range viper.GetStringSlice("feeds.urls") { log.Printf("fetching %s...\n", feedURL) @@ -94,7 +120,7 @@ func newsFetch(client *girc.Client, channel string) { Hash: mkHash(item.Title, item.Link), } // Check if item was already posted - if newsExists(newslist, news) { + if newsExists(news) { log.Printf("already posted %s (%s)\n", item.Title, news.Hash) continue } @@ -109,17 +135,7 @@ func newsFetch(client *girc.Client, channel string) { break } - post := fmt.Sprintf("[{%s}%s{c}] {%s}%s{c} {%s}%s{c} {%s}#%s{c}", - viper.GetString("irc.colors.title"), - feed.Title, - viper.GetString("irc.colors.news"), - item.Title, - viper.GetString("irc.colors.link"), - item.Link, - viper.GetString("irc.colors.hash"), - news.Hash) - - client.Cmd.Message(channel, girc.Fmt(post)) + client.Cmd.Message(channel, girc.Fmt(fmtNews(news))) time.Sleep(viper.GetDuration("irc.delay")) @@ -144,20 +160,21 @@ func newsFetch(client *girc.Client, channel string) { func confDefault() { kv := map[string]interface{}{ - "irc.server": "irc.libera.chat", - "irc.nick": "gruik", - "irc.channel": "goaste", - "irc.debug": false, - "irc.port": 6667, - "irc.delay": "2s", - "irc.colors.title": "pink", - "irc.colors.news": "bold", - "irc.colors.link": "lightblue", - "irc.colors.hash": "gray", - "feeds.urls": []string{}, - "feeds.maxnews": 10, - "feeds.maxage": "1h", - "feeds.frequency": "10m", + "irc.server": "irc.libera.chat", + "irc.nick": "gruik", + "irc.channel": "goaste", + "irc.xchannels": []string{"goaste2"}, + "irc.debug": false, + "irc.port": 6667, + "irc.delay": "2s", + "irc.colors.origin": "pink", + "irc.colors.title": "bold", + "irc.colors.link": "lightblue", + "irc.colors.hash": "gray", + "feeds.urls": []string{}, + "feeds.maxnews": 10, + "feeds.maxage": "1h", + "feeds.frequency": "10m", } for k, v := range kv { @@ -176,6 +193,13 @@ func isOp(nick string) bool { return false } +func getParam(s string) string { + if !strings.Contains(s, " ") { + return "" + } + return s[strings.LastIndex(s, " ")+1:] +} + func main() { config := "config" if len(os.Args) > 1 { @@ -195,7 +219,7 @@ func main() { password := viper.GetString("irc.password") name := nick user := strings.ToLower(nick) - channel := "#" + viper.GetString("irc.channel") + channel := viper.GetString("irc.channel") debug := io.Discard if viper.GetBool("irc.debug") { debug = os.Stdout @@ -221,6 +245,11 @@ func main() { client.Handlers.Add(girc.CONNECTED, func(c *girc.Client, e girc.Event) { c.Cmd.Join(channel) + + // join secondary channels for xposting + for _, xchan := range viper.GetStringSlice("irc.xchannels") { + c.Cmd.Join(xchan) + } }) client.Handlers.Add(girc.PRIVMSG, func(c *girc.Client, e girc.Event) { dest := channel @@ -241,11 +270,10 @@ func main() { } } if isOp(e.Source.Name) && strings.HasPrefix(e.Last(), "!addfeed") { - s := e.Last() - if !strings.Contains(s, " ") { + s := getParam(e.Last()) + if s == "" { return } - s = s[strings.LastIndex(s, " ")+1:] ss := append(viper.GetStringSlice("feeds.urls"), s) viper.Set("feeds.urls", ss) c.Cmd.ReplyTo(e, girc.Fmt("feed {b}{green}added{c}{b}")) @@ -254,11 +282,10 @@ func main() { } } if isOp(e.Source.Name) && strings.HasPrefix(e.Last(), "!rmfeed") { - s := e.Last() - if !strings.Contains(s, " ") { + s := getParam(e.Last()) + if s == "" { return } - s = s[strings.LastIndex(s, " ")+1:] ss := viper.GetStringSlice("feeds.urls") i, err := strconv.Atoi(s) if err != nil { @@ -276,6 +303,18 @@ func main() { c.Cmd.ReplyTo(e, girc.Fmt("removing feed {b}{red}failed{c}{b}")) } } + if strings.HasPrefix(e.Last(), "!xpost") { + s := getParam(e.Last()) + if s == "" { + return + } + for _, xchan := range viper.GetStringSlice("irc.xchannels") { + if news := getNewsByHash(s); news.Hash != "" { + post := fmt.Sprintf(" {r}(from %s)", channel) + c.Cmd.Message(xchan, girc.Fmt(fmtNews(news)+post)) + } + } + } }) go newsFetch(client, channel)