Skip to content

Instantly share code, notes, and snippets.

@theGeekPirate
Created November 15, 2018 01:15
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save theGeekPirate/f2a451190f64b9aa9af0239c3b9c4589 to your computer and use it in GitHub Desktop.
Save theGeekPirate/f2a451190f64b9aa9af0239c3b9c4589 to your computer and use it in GitHub Desktop.
BAPCSalesLiveFeed will show a constant stream of live updates from the /r/bapcsalescanada subreddit. It was hacked together as quickly as possible in preparation for Black Friday.
// BAPCSalesLiveFeed will show a constant stream of live updates from the /r/bapcsalescanada subreddit.
// It was hacked together as quickly as possible in preparation for Black Friday.
// Note that this leaks memory _very slowly_ due to us constantly adding IDs to the postCache.
// This isn't a big deal since the amount of data stored is miniscule, but worth noting if you're
// going to be running it non-stop for a couple of years on a memory-constrained system for whatever reason.
package main
import (
"encoding/json"
"fmt"
"log"
"net/http"
"os"
"strconv"
"strings"
"time"
"github.com/faiface/beep/speaker"
"github.com/faiface/beep/wav"
"github.com/fatih/color"
)
const (
subreddit = "bapcsalescanada"
redditURL = "https://www.reddit.com/r/" + subreddit + "/new"
userAgent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.77 Safari/537.36"
// The notification sound comes from https://www.leshylabs.com/apps/sfMaker/
// Copy-and-paste the string below into the "Sound Text" field, then click on "Load Text".
// W=44100,f=992.364,v=113.026,V=9.898,t=1.598,T=0.112,_=0.047,d=286.446,D=0.164,p=1.729,b=1.6,r=0.3,c=-27,C=48.503,s=164,S=5.336,z=Down,g=0.419,l=0.33,L=0.605
soundFile = "notification.wav"
)
var postCache = make(map[string]struct{})
type reddit struct {
Data struct {
Children []struct {
Data struct {
ID string `json:"id"`
Title string `json:"title"`
Domain string `json:"domain"`
Permalink string `json:"permalink"`
URL string `json:"url"`
CreatedUtc float64 `json:"created_utc"`
} `json:"data"`
} `json:"children"`
} `json:"data"`
}
func main() {
run(false)
for range time.Tick(time.Second * 10) {
run(true)
}
}
func run(playSound bool) {
r := parseJSON()
for i := 0; i <= len(r.Data.Children)-1; i++ {
item := r.Data.Children[len(r.Data.Children)-1-i].Data
_, exists := postCache[item.ID]
if exists {
continue
}
postCache[item.ID] = struct{}{}
timeInt, err := strconv.Atoi(strings.Split(strconv.FormatFloat(item.CreatedUtc, 'f', 6, 64), ".")[0])
if err != nil {
log.Println(color.RedString("Unable to convert UTC time to int: " + err.Error()))
}
localTime := color.YellowString(time.Unix(int64(timeInt), int64(0)).Format("3:04PM"))
title := item.Title
redditLink := color.BlueString("https://www.reddit.com" + item.Permalink)
var storeLink string
if item.Domain != "self."+subreddit {
storeLink = color.CyanString(item.URL)
}
fmt.Println(localTime + " " + title + "\n" + redditLink)
if storeLink != "" {
fmt.Println(storeLink)
}
fmt.Println(strings.Repeat("-", 80))
if playSound {
f, err := os.Open(soundFile)
if err != nil {
log.Println(color.RedString("Missing sound file: " + soundFile + ": " + err.Error()))
playSound = false
continue
}
s, format, err := wav.Decode(f)
if err != nil {
log.Println(color.RedString("Unable to decode sound file: " + soundFile + ": " + err.Error()))
playSound = false
continue
}
speaker.Init(format.SampleRate, format.SampleRate.N(time.Second/10))
speaker.Play(s)
}
}
}
func parseJSON() reddit {
req, err := http.NewRequest("GET", redditURL+".json", nil)
if err != nil {
log.Fatalln(color.RedString("Error retrieving HTTP: " + err.Error()))
}
// Setting a User-Agent is required otherwise reddit will block the request.
req.Header.Set("User-Agent", userAgent)
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
log.Println(color.RedString("Error receiving a response: " + err.Error()))
return parseJSON()
}
defer resp.Body.Close()
r := reddit{}
json.NewDecoder(resp.Body).Decode(&r)
if err != nil {
log.Println(color.RedString("Error decoding JSON: " + err.Error()))
return parseJSON()
}
return r
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment