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 }