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:
M | README.md | | | 3 | ++- |
M | main.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)