MovieNight/emotes.go
Zorchenhimer 6f865b7a53 Start adding support to download twitch emotes
The code has been transferred over from the utility, and should work,
but it hasn't been tested nor has it been linked to the command.
2019-03-28 16:22:08 -04:00

166 lines
3.3 KiB
Go

package main
import (
"encoding/json"
"fmt"
"io"
"net/http"
"os"
"strings"
)
type twitchChannel struct {
ChannelName string `json:"channel_name"`
DisplayName string `json:"display_name"`
ChannelId string `json:"channel_id"`
BroadcasterType string `json:"broadcaster_type"`
Plans map[string]string `json:"plans"`
Emotes []struct {
Code string `json:"code"`
Set string `json:"emoticon_set"`
Id int `json:"id"`
} `json:"emotes"`
BaseSetId string `json:"base_set_id"`
GeneratedAt string `json:"generated_at"`
}
// Used in settings
type EmoteSet struct {
Channel string // channel name
Prefix string // emote prefix
Found bool `json:"-"`
}
const subscriberJson string = `subscribers.json`
// Download a single channel's emote set
func (tc *twitchChannel) downloadEmotes() (*EmoteSet, error) {
es := &EmoteSet{Channel: strings.ToLower(tc.ChannelName)}
for _, emote := range tc.Emotes {
url := fmt.Sprintf(`https://static-cdn.jtvnw.net/emoticons/v1/%d/1.0`, emote.Id)
png := `static/emotes/` + emote.Code + `.png`
if len(es.Prefix) == 0 {
// For each letter
for i := 0; i < len(emote.Code); i++ {
// Find the first capital
b := emote.Code[i]
if b >= 'A' && b <= 'Z' {
es.Prefix = emote.Code[0 : i-1]
fmt.Printf("Found prefix for channel %q: %q (%q)\n", es.Channel, es.Prefix, emote)
break
}
}
}
resp, err := http.Get(url)
if err != nil {
return nil, err
}
f, err := os.Create(png)
if err != nil {
return nil, err
}
_, err = io.Copy(f, resp.Body)
if err != nil {
return nil, err
}
}
return es, nil
}
func GetEmotes(names []string) ([]*EmoteSet, error) {
// Do this up-front
for i := 0; i < len(names); i++ {
names[i] = strings.ToLower(names[i])
}
channels, err := findChannels(names)
if err != nil {
return nil, fmt.Errorf("Error reading %q: %v", subscriberJson, err)
}
emoteSets := []*EmoteSet{}
for _, c := range channels {
es, err := c.downloadEmotes()
if err != nil {
return nil, fmt.Errorf("Error downloading emotes: %v", err)
}
emoteSets = append(emoteSets, es)
}
for _, es := range emoteSets {
found := false
for _, name := range names {
if es.Channel == name {
found = true
break
}
}
if !found {
es.Found = false
}
}
return emoteSets, nil
}
func findChannels(names []string) ([]twitchChannel, error) {
file, err := os.Open(subscriberJson)
if err != nil {
return nil, err
}
defer file.Close()
data := []twitchChannel{}
dec := json.NewDecoder(file)
// Open bracket
_, err = dec.Token()
if err != nil {
return nil, err
}
done := false
for dec.More() && !done {
// opening bracket of channel
_, err = dec.Token()
if err != nil {
return nil, err
}
// Decode the channel stuff
var c twitchChannel
err = dec.Decode(&c)
if err != nil {
return nil, err
}
// Is this a channel we are looking for?
found := false
for _, search := range names {
if strings.ToLower(c.ChannelName) == search {
found = true
break
}
}
// Yes it is. Add it to the data
if found {
data = append(data, c)
}
// Check for completion. Don't bother parsing the rest of
// the json file if we've already found everything that we're
// looking for.
if len(data) == len(names) {
done = true
}
}
return data, nil
}