exmo/bots/reddit/main.go

171 lines
3.2 KiB
Go

package main
import (
"encoding/json"
"flag"
"fmt"
"log"
"math/rand"
"net/http"
"os"
"regexp"
"time"
"mcquay.me/exmo"
irc "github.com/fluffle/goirc/client"
)
var host = flag.String("host", "localhost:6668", "irc server hostname")
var channel = flag.String("channel", "#exmormon", "irc channel")
var top = flag.Int("top", 5, "number of top posts to use")
func main() {
maddr := os.Getenv("ADDR")
if maddr == "" {
fmt.Fprintf(os.Stderr, "failed to set ADDR\n")
os.Exit(1)
}
if err := exmo.Metrics(maddr); err != nil {
fmt.Fprintf(os.Stderr, "can't http: %v\n", err)
os.Exit(1)
}
rand.Seed(time.Now().UnixNano())
flag.Parse()
log.SetFlags(log.Ldate | log.Ltime | log.Lshortfile)
done := make(chan bool)
register(*host, *channel, done)
<-done
}
const name = "reddit-exmo"
func register(host, channel string, done chan<- bool) {
var p *regexp.Regexp
c := irc.SimpleClient(name, name)
c.EnableStateTracking()
c.HandleFunc(
irc.CONNECTED,
func(conn *irc.Conn, line *irc.Line) {
conn.Join(channel)
var err error
p, err = regexp.Compile(`\b` + conn.Me().Nick + `\b`)
if err != nil {
log.Printf("%+v", err)
}
},
)
c.HandleFunc(
irc.DISCONNECTED,
func(conn *irc.Conn, line *irc.Line) {
done <- true
},
)
c.HandleFunc(
irc.PRIVMSG,
func(conn *irc.Conn, line *irc.Line) {
if p.MatchString(line.Text()) {
log.Printf("addressed me: %v", line.Text())
}
},
)
go func() {
seen := map[string]int{}
prime, err := items()
if err != nil {
log.Printf("%+v", err)
}
for _, i := range prime {
seen[i.ID] = i.Score
}
for {
latest, err := items()
if err != nil {
log.Printf("%+v", err)
}
for _, i := range latest {
if _, ok := seen[i.ID]; ok {
continue
}
log.Printf("decided to talk about this: %+v", i)
seen[i.ID] = i.Score
c.Privmsgf(channel, "%v", i)
}
time.Sleep(5 * time.Minute)
}
}()
if err := c.ConnectTo(host); err != nil {
fmt.Printf("Connection error: %s\n", err)
}
}
type item struct {
ID string `json:"id"`
Author string `json:"author"`
Score int `json:"score"`
URL string `json:"url"`
Title string `json:"title"`
Comments int `json:"num_comments"`
}
func (i item) String() string {
com := ""
switch i.Comments {
case 0:
// nothing
case 1:
com = " (1 comment)"
default:
com = fmt.Sprintf(" (%d comments)", i.Comments)
}
url := fmt.Sprintf("https://redd.it/%s", i.ID)
return fmt.Sprintf("%s %v (current score: %d) %s", i.Title, com, i.Score, url)
}
type response struct {
Data struct {
Children []struct {
Data item
}
}
}
func items() ([]item, error) {
url := fmt.Sprintf("https://www.reddit.com/r/exmormon.json")
client := http.Client{}
req, err := http.NewRequest("GET", url, nil)
if err != nil {
return nil, err
}
req.Header.Set("User-Agent", "sm bot")
resp, err := client.Do(req)
if err != nil {
return nil, err
}
rresp := response{}
if err := json.NewDecoder(resp.Body).Decode(&rresp); err != nil {
return nil, err
}
defer resp.Body.Close()
items := []item{}
for _, child := range rresp.Data.Children {
items = append(items, child.Data)
}
if len(items) < *top {
return items, nil
}
return items[:*top], nil
}