Fix emotes
This reworks how emotes are cached in relation to their physical location on disk. Functionally, they should be the same from the user perspective but it sets up some stuff that will make it easier to add emotes from various sources.
This commit is contained in:
parent
35774b061f
commit
a73375f152
|
@ -438,19 +438,27 @@ var commands = &CommandControl{
|
||||||
common.CNReloadEmotes.String(): Command{
|
common.CNReloadEmotes.String(): Command{
|
||||||
HelpText: "Reload the emotes on the server.",
|
HelpText: "Reload the emotes on the server.",
|
||||||
Function: func(cl *Client, args []string) (string, error) {
|
Function: func(cl *Client, args []string) (string, error) {
|
||||||
cl.SendServerMessage("Reloading emotes")
|
go func() {
|
||||||
err := loadEmotes()
|
cl.SendServerMessage("Reloading emotes")
|
||||||
if err != nil {
|
err := loadEmotes()
|
||||||
common.LogErrorf("Unbale to reload emotes: %s\n", err)
|
if err != nil {
|
||||||
return "", err
|
common.LogErrorf("Unbale to reload emotes: %s\n", err)
|
||||||
}
|
//return "", err
|
||||||
|
|
||||||
cl.belongsTo.AddChatMsg(common.NewChatHiddenMessage(common.CdEmote, common.Emotes))
|
cl.SendChatData(common.NewChatMessage("", "",
|
||||||
cl.belongsTo.AddModNotice(cl.name + " has reloaded emotes")
|
err.Error(),
|
||||||
|
common.CmdlUser, common.MsgCommandResponse))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
num := len(Emotes)
|
cl.belongsTo.AddChatMsg(common.NewChatHiddenMessage(common.CdEmote, common.Emotes))
|
||||||
common.LogInfof("Loaded %d emotes\n", num)
|
cl.belongsTo.AddModNotice(cl.name + " has reloaded emotes")
|
||||||
return fmt.Sprintf("Emotes loaded: %d", num), nil
|
|
||||||
|
num := len(common.Emotes)
|
||||||
|
common.LogInfof("Loaded %d emotes\n", num)
|
||||||
|
cl.belongsTo.AddModNotice(fmt.Sprintf("%s reloaded %d emotes.", cl.name, num))
|
||||||
|
}()
|
||||||
|
return "Reloading emotes...", nil
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
|
@ -40,7 +40,7 @@ func newChatRoom() (*ChatRoom, error) {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("error loading emotes: %s", err)
|
return nil, fmt.Errorf("error loading emotes: %s", err)
|
||||||
}
|
}
|
||||||
common.LogInfof("Loaded %d emotes\n", len(Emotes))
|
common.LogInfof("Loaded %d emotes\n", len(common.Emotes))
|
||||||
|
|
||||||
//the "heartbeat" for broadcasting messages
|
//the "heartbeat" for broadcasting messages
|
||||||
go cr.Broadcast()
|
go cr.Broadcast()
|
||||||
|
|
|
@ -2,19 +2,41 @@ package common
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"path"
|
"path/filepath"
|
||||||
|
"regexp"
|
||||||
"strings"
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
var Emotes map[string]EmotePath
|
type EmotesMap map[string]string
|
||||||
|
|
||||||
type EmotePath struct {
|
var Emotes EmotesMap
|
||||||
Dir string
|
|
||||||
File string
|
var reStripStatic = regexp.MustCompile(`^(\\|/)?static`)
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
Emotes = map[string]string{}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e EmotePath) path() string {
|
func (em EmotesMap) Add(fullpath string) {
|
||||||
return path.Join(e.Dir, e.File)
|
fullpath = reStripStatic.ReplaceAllLiteralString(fullpath, "")
|
||||||
|
|
||||||
|
base := filepath.Base(fullpath)
|
||||||
|
code := base[0 : len(base)-len(filepath.Ext(base))]
|
||||||
|
|
||||||
|
_, exists := em[code]
|
||||||
|
|
||||||
|
num := 0
|
||||||
|
for exists {
|
||||||
|
num += 1
|
||||||
|
_, exists = em[fmt.Sprintf("%s-%d", code, num)]
|
||||||
|
}
|
||||||
|
|
||||||
|
if num > 0 {
|
||||||
|
code = fmt.Sprintf("%s-%d", code, num)
|
||||||
|
}
|
||||||
|
|
||||||
|
Emotes[code] = fullpath
|
||||||
|
fmt.Printf("Added emote %s at path %q\n", code, fullpath)
|
||||||
}
|
}
|
||||||
|
|
||||||
func EmoteToHtml(file, title string) string {
|
func EmoteToHtml(file, title string) string {
|
||||||
|
@ -30,7 +52,7 @@ func ParseEmotesArray(words []string) []string {
|
||||||
found := false
|
found := false
|
||||||
for key, val := range Emotes {
|
for key, val := range Emotes {
|
||||||
if key == wordTrimmed {
|
if key == wordTrimmed {
|
||||||
newWords = append(newWords, EmoteToHtml(val.File, key))
|
newWords = append(newWords, EmoteToHtml(val, key))
|
||||||
found = true
|
found = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
package common
|
package common
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"os"
|
||||||
"testing"
|
"testing"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -25,21 +26,12 @@ var data_good = map[string]string{
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestMain(m *testing.M) {
|
func TestMain(m *testing.M) {
|
||||||
Emotes = map[string]EmotePath{
|
Emotes = map[string]string{
|
||||||
"one": EmotePath{
|
"one": "/emotes/one.png",
|
||||||
Dir: "",
|
"two": "/emotes/two.png",
|
||||||
File: "one.png",
|
"three": "/emotes/three.gif",
|
||||||
},
|
|
||||||
"two": EmotePath{
|
|
||||||
Dir: "",
|
|
||||||
File: "two.png",
|
|
||||||
},
|
|
||||||
"three": EmotePath{
|
|
||||||
Dir: "",
|
|
||||||
File: "three.gif",
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
// os.Exit(m.Run())
|
os.Exit(m.Run())
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestEmotes_ParseEmotes(t *testing.T) {
|
func TestEmotes_ParseEmotes(t *testing.T) {
|
||||||
|
|
138
emotes.go
138
emotes.go
|
@ -4,28 +4,19 @@ import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
|
"io/ioutil"
|
||||||
"log"
|
"log"
|
||||||
"net/http"
|
"net/http"
|
||||||
"os"
|
"os"
|
||||||
"path"
|
"path/filepath"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
|
"github.com/zorchenhimer/MovieNight/common"
|
||||||
)
|
)
|
||||||
|
|
||||||
const emoteDir = "./static/emotes/"
|
const emoteDir = "./static/emotes/"
|
||||||
|
|
||||||
var Emotes map[string]Emote
|
|
||||||
|
|
||||||
type Emote struct {
|
|
||||||
Dir string
|
|
||||||
File string
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e Emote) path() string {
|
|
||||||
return path.Join(e.Dir, e.File)
|
|
||||||
}
|
|
||||||
|
|
||||||
type TwitchUser struct {
|
type TwitchUser struct {
|
||||||
ID string
|
ID string
|
||||||
Login string
|
Login string
|
||||||
|
@ -36,74 +27,85 @@ type EmoteInfo struct {
|
||||||
Code string
|
Code string
|
||||||
}
|
}
|
||||||
|
|
||||||
// func loadEmotes() error {
|
|
||||||
// newEmotes := map[string]string{}
|
|
||||||
|
|
||||||
// emotePNGs, err := filepath.Glob("./static/emotes/*.png")
|
|
||||||
// if err != nil {
|
|
||||||
// return 0, fmt.Errorf("unable to glob emote directory: %s\n", err)
|
|
||||||
// }
|
|
||||||
|
|
||||||
// emoteGIFs, err := filepath.Glob("./static/emotes/*.gif")
|
|
||||||
// if err != nil {
|
|
||||||
// return 0, fmt.Errorf("unable to glob emote directory: %s\n", err)
|
|
||||||
// }
|
|
||||||
// globbed_files := []string(emotePNGs)
|
|
||||||
// globbed_files = append(globbed_files, emoteGIFs...)
|
|
||||||
|
|
||||||
// LogInfoln("Loading emotes...")
|
|
||||||
// emInfo := []string{}
|
|
||||||
// for _, file := range globbed_files {
|
|
||||||
// file = filepath.Base(file)
|
|
||||||
// key := file[0 : len(file)-4]
|
|
||||||
// newEmotes[key] = file
|
|
||||||
// emInfo = append(emInfo, key)
|
|
||||||
// }
|
|
||||||
// Emotes = newEmotes
|
|
||||||
// LogInfoln(strings.Join(emInfo, " "))
|
|
||||||
// return len(Emotes), nil
|
|
||||||
// }
|
|
||||||
|
|
||||||
func loadEmotes() error {
|
func loadEmotes() error {
|
||||||
fmt.Println(processEmoteDir(emoteDir))
|
//fmt.Println(processEmoteDir(emoteDir))
|
||||||
|
err := processEmoteDir(emoteDir)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func processEmoteDir(path string) ([]Emote, error) {
|
func processEmoteDir(path string) error {
|
||||||
dir, err := os.Open(path)
|
dirInfo, err := ioutil.ReadDir(path)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Wrap(err, "could not open emoteDir:")
|
return errors.Wrap(err, "could not open emoteDir:")
|
||||||
}
|
}
|
||||||
|
|
||||||
files, err := dir.Readdir(0)
|
subDirs := []string{}
|
||||||
if err != nil {
|
|
||||||
return nil, errors.Wrap(err, "could not get files:")
|
|
||||||
}
|
|
||||||
|
|
||||||
var emotes []Emote
|
for _, item := range dirInfo {
|
||||||
for _, file := range files {
|
// Get first level subdirs (eg, "twitch", "discord", etc)
|
||||||
emotes = append(emotes, Emote{Dir: path, File: file.Name()})
|
if item.IsDir() {
|
||||||
}
|
subDirs = append(subDirs, item.Name())
|
||||||
|
continue
|
||||||
subdir, err := dir.Readdirnames(0)
|
|
||||||
if err != nil {
|
|
||||||
return nil, errors.Wrap(err, "could not get sub directories:")
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, d := range subdir {
|
|
||||||
subEmotes, err := processEmoteDir(d)
|
|
||||||
if err != nil {
|
|
||||||
return nil, errors.Wrapf(err, "could not process sub directory \"%s\":", d)
|
|
||||||
}
|
}
|
||||||
emotes = append(emotes, subEmotes...)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return emotes, nil
|
// Find top level emotes
|
||||||
|
err = findEmotes(path)
|
||||||
|
if err != nil {
|
||||||
|
return errors.Wrap(err, "could not findEmotes() in top level directory:")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get second level subdirs (eg, "twitch", "zorchenhimer", etc)
|
||||||
|
for _, dir := range subDirs {
|
||||||
|
subd, err := ioutil.ReadDir(filepath.Join(path, dir))
|
||||||
|
if err != nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
for _, d := range subd {
|
||||||
|
if d.IsDir() {
|
||||||
|
//emotes = append(emotes, findEmotes(filepath.Join(path, dir, d.Name()))...)
|
||||||
|
findEmotes(filepath.Join(path, dir, d.Name()))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func findEmotes(dir string) error {
|
||||||
|
fmt.Printf("finding emotes in %q\n", dir)
|
||||||
|
emotePNGs, err := filepath.Glob(filepath.Join(dir, "*.png"))
|
||||||
|
if err != nil {
|
||||||
|
//return 0, fmt.Errorf("unable to glob emote directory: %s\n", err)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
fmt.Printf("%d emotePNGs\n", len(emotePNGs))
|
||||||
|
|
||||||
|
emoteGIFs, err := filepath.Glob(filepath.Join(dir, "*.gif"))
|
||||||
|
if err != nil {
|
||||||
|
return errors.Wrap(err, "unable to glob emote directory:")
|
||||||
|
}
|
||||||
|
fmt.Printf("%d emoteGIFs\n", len(emoteGIFs))
|
||||||
|
|
||||||
|
for _, file := range emotePNGs {
|
||||||
|
common.Emotes.Add(file)
|
||||||
|
//emotes = append(emotes, common.Emote{FullPath: dir, Code: file})
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, file := range emoteGIFs {
|
||||||
|
common.Emotes.Add(file)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func getEmotes(names []string) error {
|
func getEmotes(names []string) error {
|
||||||
users := getUserIDs(names)
|
users := getUserIDs(names)
|
||||||
users = append(users, TwitchUser{ID: "0", Login: "global"})
|
users = append(users, TwitchUser{ID: "0", Login: "twitch"})
|
||||||
|
|
||||||
for _, user := range users {
|
for _, user := range users {
|
||||||
emotes, cheers, err := getChannelEmotes(user.ID)
|
emotes, cheers, err := getChannelEmotes(user.ID)
|
||||||
|
@ -111,14 +113,14 @@ func getEmotes(names []string) error {
|
||||||
return errors.Wrapf(err, "could not get emote data for \"%s\"", user.ID)
|
return errors.Wrapf(err, "could not get emote data for \"%s\"", user.ID)
|
||||||
}
|
}
|
||||||
|
|
||||||
emoteUserDir := path.Join(emoteDir, "twitch", user.Login)
|
emoteUserDir := filepath.Join(emoteDir, "twitch", user.Login)
|
||||||
if _, err := os.Stat(emoteUserDir); os.IsNotExist(err) {
|
if _, err := os.Stat(emoteUserDir); os.IsNotExist(err) {
|
||||||
os.MkdirAll(emoteUserDir, os.ModePerm)
|
os.MkdirAll(emoteUserDir, os.ModePerm)
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, emote := range emotes {
|
for _, emote := range emotes {
|
||||||
if !strings.ContainsAny(emote.Code, `:;\[]|?&`) {
|
if !strings.ContainsAny(emote.Code, `:;\[]|?&`) {
|
||||||
filePath := path.Join(emoteUserDir, emote.Code+".png")
|
filePath := filepath.Join(emoteUserDir, emote.Code+".png")
|
||||||
file, err := os.Create(filePath)
|
file, err := os.Create(filePath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
||||||
|
@ -134,7 +136,7 @@ func getEmotes(names []string) error {
|
||||||
|
|
||||||
for amount, sizes := range cheers {
|
for amount, sizes := range cheers {
|
||||||
name := fmt.Sprintf("%sCheer%s.gif", user.Login, amount)
|
name := fmt.Sprintf("%sCheer%s.gif", user.Login, amount)
|
||||||
filePath := path.Join(emoteUserDir, name)
|
filePath := filepath.Join(emoteUserDir, name)
|
||||||
file, err := os.Create(filePath)
|
file, err := os.Create(filePath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Wrapf(err, "could not create emote file in path \"%s\":", filePath)
|
return errors.Wrapf(err, "could not create emote file in path \"%s\":", filePath)
|
||||||
|
|
|
@ -79,8 +79,7 @@ func wsImages(w http.ResponseWriter, r *http.Request) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func wsEmotes(w http.ResponseWriter, r *http.Request) {
|
func wsEmotes(w http.ResponseWriter, r *http.Request) {
|
||||||
emotefile := filepath.Base(r.URL.Path)
|
http.ServeFile(w, r, path.Join("./static/", r.URL.Path))
|
||||||
http.ServeFile(w, r, path.Join(emoteDir, emotefile))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Handling the websocket
|
// Handling the websocket
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"MaxMessageCount": 300,
|
"MaxMessageCount": 300,
|
||||||
"TitleLength": 50,
|
"TitleLength": 50,
|
||||||
"AdminPassword": "",
|
"AdminPassword": "",
|
||||||
"Bans": [],
|
"Bans": [],
|
||||||
"StreamKey": "ALongStreamKey",
|
"StreamKey": "ALongStreamKey",
|
||||||
|
|
Loading…
Reference in New Issue