diff --git a/bots/reddit/reddit.go b/bots/reddit/reddit.go new file mode 100644 index 0000000..88a85d3 --- /dev/null +++ b/bots/reddit/reddit.go @@ -0,0 +1,146 @@ +package reddit + +import ( + "encoding/json" + "fmt" + "log" + "net/http" + "regexp" + "sort" + "time" + + irc "github.com/fluffle/goirc/client" +) + +const name = "reddit" + +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 _, item := range prime { + seen[item.ID] = item.Score + } + + for { + log.Printf("reddit ...") + latest, err := items() + log.Printf("got %+v items", len(latest)) + if err != nil { + log.Printf("%+v", err) + } + for _, item := range latest { + if _, ok := seen[item.ID]; ok { + continue + } + log.Printf("%+v", item) + seen[item.ID] = item.Score + c.Privmsgf(channel, "%v", item) + } + 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) + } + + return fmt.Sprintf("(%d: %s) %s%s\n%s", i.Score, i.ID, i.Title, com, i.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) + } + sort.Sort(ByScore(items)) + return items, nil +} + +type ByScore []Item + +func (a ByScore) Len() int { return len(a) } +func (a ByScore) Swap(i, j int) { a[i], a[j] = a[j], a[i] } +func (a ByScore) Less(i, j int) bool { return a[i].Score > a[j].Score } diff --git a/main.go b/main.go index 8a3f024..029a174 100644 --- a/main.go +++ b/main.go @@ -7,6 +7,7 @@ import ( "time" "mcquay.me/exmo/bots/bybot" + "mcquay.me/exmo/bots/reddit" ) var host *string = flag.String("host", "localhost:6668", "irc server hostname") @@ -20,5 +21,9 @@ func main() { done := make(chan bool) bybot.Register(*host, *channel, done) - <-done + reddit.Register(*host, *channel, done) + + for i := 0; i < 2; i++ { + <-done + } }