6f865b7a53
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.
166 lines
3.3 KiB
Go
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
|
|
}
|