First version working.

master
Zed A. Shaw 4 hours ago
parent 8927e9119b
commit 22740a3965
  1. 36
      .gitignore
  2. 8
      Makefile
  3. 6
      commands.json
  4. 28
      config.json
  5. 5
      go.mod
  6. 2
      go.sum
  7. 96
      main.go
  8. 4
      secret_sample.json

36
.gitignore vendored

@ -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

@ -0,0 +1,8 @@
build:
go build .
run: build
./app

@ -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."
}

@ -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."
}
]
}

@ -0,0 +1,5 @@
module MY/app
go 1.25.3
require github.com/gempir/go-twitch-irc/v4 v4.4.1

@ -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=

@ -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) }
}

@ -0,0 +1,4 @@
{
"ClientSecret": "oauth:MUST_HAVE_oauth_IN_FRONT",
"RefreshToken": "GET THIS FROM twitch-cli"
}
Loading…
Cancel
Save