From 4d7d14e0b50f592e943ceaa5829caeac0bd548f5 Mon Sep 17 00:00:00 2001 From: alexvanin Date: Wed, 18 Mar 2020 22:33:33 +0300 Subject: [PATCH] Add two new twitch chat handlers in v5.1.0 --- changelog.md | 5 + main.go | 4 +- modules/patpet/patpet.go | 88 +++++++++++ modules/settings/settings.go | 5 +- modules/twitchat/dailyemote.go | 257 +++++++++++++++++++++++++++++++++ modules/twitchat/petcat.go | 39 +++++ modules/twitchat/twitchat.go | 5 +- 7 files changed, 400 insertions(+), 3 deletions(-) create mode 100644 modules/patpet/patpet.go create mode 100644 modules/twitchat/dailyemote.go create mode 100644 modules/twitchat/petcat.go diff --git a/changelog.md b/changelog.md index ed8761b..728e083 100644 --- a/changelog.md +++ b/changelog.md @@ -1,5 +1,10 @@ # Changelog +## 5.1.0 - 2020-03-18 +### Added +- PetCat twitch chat handler +- DailyEmote twitch chat handler + ## 5.0.1 - 2020-03-08 ### Changed - Updated `go-twitch-irc` lib to v2.2.2 diff --git a/main.go b/main.go index df7009d..81705ed 100644 --- a/main.go +++ b/main.go @@ -8,6 +8,7 @@ import ( "galched-bot/modules/discord" "galched-bot/modules/grace" + "galched-bot/modules/patpet" "galched-bot/modules/settings" "galched-bot/modules/subday" "galched-bot/modules/twitchat" @@ -87,7 +88,8 @@ func main() { var err error app := fx.New( fx.Logger(new(silentPrinter)), - fx.Provide(settings.New, grace.New, discord.New, subday.New, twitchat.New, web.New, youtube.New), + fx.Provide(settings.New, grace.New, discord.New, subday.New, + twitchat.New, web.New, youtube.New, patpet.New), fx.Invoke(start)) err = app.Start(context.Background()) diff --git a/modules/patpet/patpet.go b/modules/patpet/patpet.go new file mode 100644 index 0000000..35a9592 --- /dev/null +++ b/modules/patpet/patpet.go @@ -0,0 +1,88 @@ +package patpet + +import ( + "encoding/json" + "fmt" + "io/ioutil" + "log" + "os" + "sync" + + "galched-bot/modules/settings" +) + +type ( + Pet struct { + sync.RWMutex + path string + counter int + } +) + +func New(s *settings.Settings) (*Pet, error) { + var ( + err error + counter int + ) + + petData, err := ioutil.ReadFile(s.PetDataPath) + if err != nil { + log.Print("pet: cannot read data file", err) + log.Print("pet: creating new counter") + } else { + err = json.Unmarshal(petData, &counter) + if err != nil { + counter = 0 + log.Print("pet: cannot unmarshal data file", err) + log.Print("pet: creating new counter") + } else { + log.Print("pet: using previously saved counter") + } + } + + return &Pet{ + RWMutex: sync.RWMutex{}, + path: s.PetDataPath, + counter: counter, + }, nil +} + +func (p *Pet) Pet() int { + p.Lock() + defer p.Unlock() + + p.counter++ + return p.counter +} + +func (p *Pet) Counter() int { + p.RUnlock() + defer p.RUnlock() + + return p.counter +} + +func (p *Pet) Dump() { + p.RLock() + defer p.RUnlock() + + data, err := json.Marshal(p.counter) + if err != nil { + log.Print("pet: cannot marshal counter", err) + return + } + file, err := os.Create(p.path) + if err != nil { + log.Print("pet: cannot open counter file", err) + return + } + _, err = fmt.Fprintf(file, string(data)) + if err != nil { + log.Print("pet: cannot write to counter file") + } + err = file.Close() + if err != nil { + log.Print("pet: cannot close counter file") + } + log.Print("pet: counter dumped to file:", p.counter) +} diff --git a/modules/settings/settings.go b/modules/settings/settings.go index 2f4e283..39d5152 100644 --- a/modules/settings/settings.go +++ b/modules/settings/settings.go @@ -8,12 +8,13 @@ import ( ) const ( - version = "5.0.1" + version = "5.1.0" twitchUser = "galchedbot" twitchIRCRoom = "galched" discordTokenPath = "./tokens/.discordtoken" twitchTokenPath = "./tokens/.twitchtoken" subdayDataPath = "./backups/subday" + petDataPath = "./backups/pets" youtubeTokenPath = "./tokens/.youtubetoken" webLoginsPath = "./tokens/.weblogins" @@ -43,6 +44,7 @@ type ( TwitchToken string YoutubeToken string SubdayDataPath string + PetDataPath string PermittedRoles []string DiscordVoiceChannel string Songs []SongInfo @@ -85,6 +87,7 @@ func New() (*Settings, error) { TwitchUser: twitchUser, TwitchIRCRoom: twitchIRCRoom, SubdayDataPath: subdayDataPath, + PetDataPath: petDataPath, DiscordVoiceChannel: "301793085522706432", PermittedRoles: []string{subRole1, subRole2, galchedRole, smorcRole}, Songs: []SongInfo{ diff --git a/modules/twitchat/dailyemote.go b/modules/twitchat/dailyemote.go new file mode 100644 index 0000000..810ecec --- /dev/null +++ b/modules/twitchat/dailyemote.go @@ -0,0 +1,257 @@ +package twitchat + +import ( + "fmt" + "hash/fnv" + "math/rand" + "time" + + "github.com/gempir/go-twitch-irc/v2" +) + +const emoteMsg = "!emote" + +var ( + emotes = []string{ + "4Head", + "ANELE", + "ArgieB8", + "ArsonNoSexy", + "AsexualPride", + "AsianGlow", + "BCWarrior", + "BOP", + "BabyRage", + "BatChest", + "BegWan", + "BibleThump", + "BigBrother", + "BigPhish", + "BisexualPride", + "BlargNaut", + "BlessRNG", + "BloodTrail", + "BrainSlug", + "BrokeBack", + "BuddhaBar", + "CarlSmile", + "ChefFrank", + "CoolCat", + "CoolStoryBob", + "CorgiDerp", + "CrreamAwk", + "CurseLit", + "DAESuppy", + "DBstyle", + "DansGame", + "DarkMode", + "DatSheffy", + "DendiFace", + "DogFace", + "DoritosChip", + "DrinkPurple", + "DxCat", + "EarthDay", + "EleGiggle", + "EntropyWins", + "FBBlock", + "FBCatch", + "FBChallenge", + "FBPass", + "FBPenalty", + "FBRun", + "FBSpiral", + "FBtouchdown", + "FUNgineer", + "FailFish", + "FrankerZ", + "FreakinStinkin", + "FutureMan", + "GayPride", + "GenderFluidPride", + "GingerPower", + "GivePLZ", + "GrammarKing", + "GreenTeam", + "GunRun", + "HSCheers", + "HSWP", + "HassaanChop", + "HassanChop", + "HeyGuys", + "HolidayCookie", + "HolidayLog", + "HolidayOrnament", + "HolidayPresent", + "HolidaySanta", + "HolidayTree", + "HotPokket", + "HumbleLife", + "IntersexPride", + "InuyoFace", + "ItsBoshyTime", + "JKanStyle", + "Jebaited", + "JonCarnage", + "KAPOW", + "Kappa", + "KappaClaus", + "KappaPride", + "KappaRoss", + "KappaWealth", + "Kappu", + "Keepo", + "KevinTurtle", + "Kippa", + "KomodoHype", + "KonCha", + "Kreygasm", + "LUL", + "LesbianPride", + "MVGame", + "Mau5", + "MaxLOL", + "MercyWing1", + "MercyWing2", + "MikeHogu", + "MingLee", + "MorphinTime", + "MrDestructoid", + "NinjaGrumpy", + "NomNom", + "NonBinaryPride", + "NotATK", + "NotLikeThis", + "OSFrog", + "OhMyDog", + "OneHand", + "OpieOP", + "OptimizePrime", + "PJSalt", + "PJSugar", + "PMSTwin", + "PRChase", + "PanicVis", + "PansexualPride", + "PartyHat", + "PartyTime", + "PeoplesChamp", + "PermaSmug", + "PicoMause", + "PinkMercy", + "PipeHype", + "PixelBob", + "PogChamp", + "Poooound", + "PopCorn", + "PorscheWIN", + "PowerUpL", + "PowerUpR", + "PraiseIt", + "PrimeMe", + "PunOko", + "PunchTrees", + "PurpleStar", + "RaccAttack", + "RalpherZ", + "RedCoat", + "RedTeam", + "ResidentSleeper", + "RitzMitz", + "RlyTho", + "RuleFive", + "SMOrc", + "SSSsss", + "SabaPing", + "SeemsGood", + "SeriousSloth", + "ShadyLulu", + "ShazBotstix", + "SingsMic", + "SingsNote", + "SmoocherZ", + "SoBayed", + "SoonerLater", + "Squid1", + "Squid2", + "Squid3", + "Squid4", + "StinkyCheese", + "StoneLightning", + "StrawBeary", + "SuperVinlin", + "SwiftRage", + "TBAngel", + "TF2John", + "TPFufun", + "TPcrunchyroll", + "TTours", + "TakeNRG", + "TearGlove", + "TehePelo", + "ThankEgg", + "TheIlluminati", + "TheRinger", + "TheTarFu", + "TheThing", + "ThunBeast", + "TinyFace", + "TombRaid", + "TooSpicy", + "TransgenderPride", + "TriHard", + "TwitchLit", + "TwitchRPG", + "TwitchSings", + "TwitchUnity", + "TwitchVotes", + "UWot", + "UnSane", + "UncleNox", + "VoHiYo", + "VoteNay", + "VoteYea", + "WTRuck", + "WholeWheat", + "WutFace", + "YouDontSay", + "YouWHY", + "bleedPurple", + "cmonBruh", + "copyThis", + "duDudu", + "imGlitch", + "mcaT", + "panicBasket", + "pastaThat", + "riPepperonis", + "twitchRaid", + } +) + +type ( + dailyEmote struct{} +) + +func DailyEmote() *dailyEmote { + return new(dailyEmote) +} + +func (h *dailyEmote) IsValid(m *twitch.PrivateMessage) bool { + return (m.Tags["msg-id"] == "highlighted-message") && m.Message == emoteMsg +} + +func (h *dailyEmote) Handle(m *twitch.PrivateMessage, r Responser) { + data := time.Now().Format("2006-01-02") + m.User.DisplayName + rng := rand.New(rand.NewSource(hashSeed(data))) + emote := emotes[rng.Intn(len(emotes))] + + msg := fmt.Sprintf("@%s твой эмоут дня: %s", m.User.DisplayName, emote) + r.Say(m.Channel, msg) +} + +func hashSeed(s string) int64 { + h := fnv.New64() + h.Write([]byte(s)) + return int64(h.Sum64()) +} diff --git a/modules/twitchat/petcat.go b/modules/twitchat/petcat.go new file mode 100644 index 0000000..e9aeb13 --- /dev/null +++ b/modules/twitchat/petcat.go @@ -0,0 +1,39 @@ +package twitchat + +import ( + "fmt" + "strings" + + "galched-bot/modules/patpet" + "github.com/gempir/go-twitch-irc/v2" +) + +const ( + petMsg1 = "!погладь" + petMsg2 = "!гладь" + petMsg3 = "!погладить" +) + +type ( + petCat struct { + cat *patpet.Pet + } +) + +func PetCat(pet *patpet.Pet) *petCat { + return &petCat{ + cat: pet, + } +} + +func (h *petCat) IsValid(m *twitch.PrivateMessage) bool { + return (m.Tags["msg-id"] == "highlighted-message") && (strings.HasPrefix(m.Message, petMsg1) || + strings.HasPrefix(m.Message, petMsg2) || + strings.HasPrefix(m.Message, petMsg3)) +} + +func (h *petCat) Handle(m *twitch.PrivateMessage, r Responser) { + msg := fmt.Sprintf("Котэ поглажен уже %d раз(а) InuyoFace", h.cat.Pet()) + r.Say(m.Channel, msg) + h.cat.Dump() +} diff --git a/modules/twitchat/twitchat.go b/modules/twitchat/twitchat.go index 448b886..e64063a 100644 --- a/modules/twitchat/twitchat.go +++ b/modules/twitchat/twitchat.go @@ -1,6 +1,7 @@ package twitchat import ( + "galched-bot/modules/patpet" "galched-bot/modules/settings" "galched-bot/modules/youtube" @@ -15,13 +16,15 @@ type ( } ) -func New(s *settings.Settings, r *youtube.Requester) (*TwitchIRC, error) { +func New(s *settings.Settings, r *youtube.Requester, pet *patpet.Pet) (*TwitchIRC, error) { var irc = new(TwitchIRC) irc.username = s.TwitchUser irc.handlers = append(irc.handlers, DupHandler()) + irc.handlers = append(irc.handlers, DailyEmote()) irc.handlers = append(irc.handlers, SongRequest(r)) + irc.handlers = append(irc.handlers, PetCat(pet)) // irc.handlers = append(irc.handlers, LogCheck()) irc.chat = twitch.NewClient(s.TwitchUser, s.TwitchToken)