parent
8927e9119b
commit
22740a3965
@ -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,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…
Reference in new issue