From 22740a39654c19184537e4e961de029f09a4794b Mon Sep 17 00:00:00 2001 From: "Zed A. Shaw" Date: Mon, 1 Jun 2026 12:52:37 -0400 Subject: [PATCH] First version working. --- .gitignore | 36 +++++++++++++++++ Makefile | 8 ++++ commands.json | 6 +++ config.json | 28 ++++++++++++++ go.mod | 5 +++ go.sum | 2 + main.go | 96 ++++++++++++++++++++++++++++++++++++++++++++++ secret_sample.json | 4 ++ 8 files changed, 185 insertions(+) create mode 100644 .gitignore create mode 100644 Makefile create mode 100644 commands.json create mode 100644 config.json create mode 100644 go.mod create mode 100644 go.sum create mode 100644 main.go create mode 100644 secret_sample.json diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..4c05a82 --- /dev/null +++ b/.gitignore @@ -0,0 +1,36 @@ +# ---> Vim +# Swap +[._]*.s[a-v][a-z] +!*.svg # comment out if you don't need vector files +[._]*.sw[a-p] +[._]s[a-rt-v][a-z] +[._]ss[a-gi-z] +[._]sw[a-p] + +# Session +Session.vim +Sessionx.vim + +# Temporary +.netrwhist +*~ +# Auto-generated tag files +tags +# Persistent undo +[._]*.un~ + +backup +*.exe +*.dll +*.world +coverage +coverage/* +.venv +*.gz +config.toml +public +*.idx +*.sqlite3 +*.log +secret.json + diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..ef2f3f4 --- /dev/null +++ b/Makefile @@ -0,0 +1,8 @@ + + + +build: + go build . + +run: build + ./app diff --git a/commands.json b/commands.json new file mode 100644 index 0000000..100e167 --- /dev/null +++ b/commands.json @@ -0,0 +1,6 @@ +{ + "keyboard": "I use https://hhkeyboard.us/hhkb/pro-classic-type-s but I don't recommend it.", + "mic": "It's a Samson se50x https://samsontech.com/products/microphones/headworn-microphones/se50x/", + "site": "https://learncodethehardway.com/", + "help": "Available commands: !mic !keyboard !site." +} diff --git a/config.json b/config.json new file mode 100644 index 0000000..38fe392 --- /dev/null +++ b/config.json @@ -0,0 +1,28 @@ +{ + "ClientNick": "zedashaw", + "Channel": "ZedAShaw", + "Commands": { + "keyboard": "I use https://hhkeyboard.us/hhkb/pro-classic-type-s but I don't recommend it.", + "mic": "It's a Samson se50x https://samsontech.com/products/microphones/headworn-microphones/se50x/", + "site": "https://learncodethehardway.com/", + "help": "COMMANDS: !mic !keyboard !site !ai !lsp !linux !windows !neovim !gvim !vim", + "ai": "I don't use AI, or really anything, but I don't hate AI.", + "lsp": "I use only a Terminal and Vim, no LSP, AI, or many other tools.", + "linux": "I do use Linux, and I might have to totally switch if Microsoft forces Windows 11 on me.", + "windows": "I use Windows because 95% of the world uses Windows and I want to teach them to code.", + "neovim": "NeoVIM is trying too hard to be like VSCode instead of being a better Vim.", + "gvim": "I use gvim because it works on all my computers and I'm not a troglodyte who runs...vim in a terminal? Blech.", + "vim": "I'll get my vim config on my git repo in a bit.", + "instagram": "My paintings are at https://www.instagram.com/zed.a.shaw" + }, + "Periodic": [ + { + "Seconds": 1800, + "Message": "You can use !help to get help from my Twitch IRC bot." + }, + { + "Seconds": 3300, + "Message": "I run 3 minute ads once an hour. Take a break during that time." + } + ] +} diff --git a/go.mod b/go.mod new file mode 100644 index 0000000..b52fd36 --- /dev/null +++ b/go.mod @@ -0,0 +1,5 @@ +module MY/app + +go 1.25.3 + +require github.com/gempir/go-twitch-irc/v4 v4.4.1 diff --git a/go.sum b/go.sum new file mode 100644 index 0000000..f5276a7 --- /dev/null +++ b/go.sum @@ -0,0 +1,2 @@ +github.com/gempir/go-twitch-irc/v4 v4.4.1 h1:R1WxeDyOiwHpt6rn96yZcXTS+Bri30n7pNvIjTMH598= +github.com/gempir/go-twitch-irc/v4 v4.4.1/go.mod h1:QsOMMAk470uxQ7EYD9GJBGAVqM/jDrXBNbuePfTauzg= diff --git a/main.go b/main.go new file mode 100644 index 0000000..bb55533 --- /dev/null +++ b/main.go @@ -0,0 +1,96 @@ +package main + +import ( + "log" + "os" + "strings" + "encoding/json" + "time" + + "github.com/gempir/go-twitch-irc/v4" +) + +type Secret struct { + ClientSecret string + RefreshToken string +} + +type Periodic struct { + Seconds int + Message string +} + +type Config struct { + ClientNick string + Channel string + Commands map[string]string + Periodic []Periodic +} + +func LoadJSON[T any](file string) T { + data, err := os.ReadFile(file) + if err != nil { log.Fatal(err) } + + var config T + err = json.Unmarshal(data, &config) + if err != nil { log.Fatal(err) } + + return config +} + +func RunPeriodic(message Periodic, channel string, client *twitch.Client) { + for { + time.Sleep(time.Duration(message.Seconds) * time.Second) + client.Say(channel, message.Message) + } +} + +func main() { + SECRETS := LoadJSON[Secret]("secret.json") + CONFIG := LoadJSON[Config]("config.json") + + // or client := twitch.NewAnonymousClient() for an anonymous user (no write capabilities) + client := twitch.NewClient(CONFIG.ClientNick, SECRETS.ClientSecret) + + client.OnPrivateMessage(func(message twitch.PrivateMessage) { + cmd, found := strings.CutPrefix(message.Message, "!") + reply, valid_cmd := CONFIG.Commands[strings.ToLower(cmd)] + + if found { + if valid_cmd { + client.Reply(message.Channel, message.ID, reply) + } else if !valid_cmd { + client.Reply(message.Channel, message.ID, "Invalid command. Use !help to see what's available.") + } + } + }) + + client.OnSelfJoinMessage(func (message twitch.UserJoinMessage) { + log.Println("Join", message.Channel, "as", message.User, "successful") + }) + + client.OnConnect(func () { + log.Println("Connected. Joining", CONFIG.Channel) + client.Join(CONFIG.Channel) + }) + + client.OnPingMessage(func (message twitch.PingMessage) { + log.Println("PING!", message.Message) + }) + + client.OnPongMessage(func (message twitch.PongMessage) { + log.Println("PONG!", message.Message) + }) + + client.OnNoticeMessage(func (message twitch.NoticeMessage) { + log.Println("NOTICE", message.Channel, message.Message) + }) + + for _, perodic := range(CONFIG.Periodic) { + go RunPeriodic(perodic, CONFIG.Channel, client) + } + + log.Println("Connecting to Twitch...") + err := client.Connect() + if err != nil { log.Fatal(err) } +} diff --git a/secret_sample.json b/secret_sample.json new file mode 100644 index 0000000..f8a53eb --- /dev/null +++ b/secret_sample.json @@ -0,0 +1,4 @@ +{ + "ClientSecret": "oauth:MUST_HAVE_oauth_IN_FRONT", + "RefreshToken": "GET THIS FROM twitch-cli" +}