1
0
Fork 0
mirror of https://git.sr.ht/~ashkeel/strimertul synced 2024-09-18 01:50:50 +00:00
strimertul/modules/twitch/client.go

169 lines
3.8 KiB
Go
Raw Normal View History

package twitch
import (
"errors"
"fmt"
2021-11-24 10:55:12 +00:00
jsoniter "github.com/json-iterator/go"
2022-01-27 15:49:18 +00:00
"github.com/nicklaw5/helix/v2"
2022-02-01 11:35:34 +00:00
"github.com/strimertul/strimertul/modules/database"
2022-01-27 15:49:18 +00:00
"go.uber.org/zap"
2021-11-24 10:55:12 +00:00
"github.com/strimertul/strimertul/modules"
"github.com/strimertul/strimertul/modules/loyalty"
)
type Client struct {
Config Config
Bot *Bot
2022-02-01 11:35:34 +00:00
db *database.DBModule
API *helix.Client
2022-01-27 15:49:18 +00:00
logger *zap.Logger
2021-11-24 10:55:12 +00:00
restart chan bool
}
func Register(manager *modules.Manager) error {
2022-02-01 11:35:34 +00:00
db, ok := manager.Modules["db"].(*database.DBModule)
if !ok {
return errors.New("db module not found")
}
2022-01-27 15:49:18 +00:00
logger := manager.Logger(modules.ModuleTwitch)
// Get Twitch config
var config Config
err := db.GetJSON(ConfigKey, &config)
if err != nil {
return fmt.Errorf("failed to get twitch config: %w", err)
}
// Create Twitch client
2021-11-24 10:55:12 +00:00
api, err := getHelixAPI(config.APIClientID, config.APIClientSecret)
if err != nil {
return fmt.Errorf("failed to create twitch client: %w", err)
}
client := &Client{
Config: config,
2021-11-24 10:55:12 +00:00
db: db,
API: api,
2022-01-27 15:49:18 +00:00
logger: logger,
2021-11-24 10:55:12 +00:00
restart: make(chan bool),
}
// Get Twitch bot config
var twitchBotConfig BotConfig
err = db.GetJSON(BotConfigKey, &twitchBotConfig)
if err != nil {
return fmt.Errorf("failed to get bot config: %w", err)
}
// Create and run IRC bot
client.Bot = NewBot(client, twitchBotConfig)
go func() {
2021-11-24 10:55:12 +00:00
for {
err := client.RunBot()
if err != nil {
2022-01-27 15:49:18 +00:00
logger.Error("failed to connect to Twitch IRC", zap.Error(err))
2021-11-24 10:55:12 +00:00
// Wait for config change before retrying
<-client.restart
}
}
}()
// If loyalty module is enabled, set-up loyalty commands
if loyaltyManager, ok := manager.Modules[modules.ModuleLoyalty].(*loyalty.Manager); ok && client.Bot != nil {
client.Bot.SetupLoyalty(loyaltyManager)
}
2021-11-24 10:55:12 +00:00
// Listen for config changes
2022-02-01 11:35:34 +00:00
go db.Subscribe(func(key, value string) {
switch key {
case ConfigKey:
err := jsoniter.ConfigFastest.UnmarshalFromString(value, &config)
if err != nil {
logger.Error("failed to unmarshal config", zap.Error(err))
return
}
api, err := getHelixAPI(config.APIClientID, config.APIClientSecret)
if err != nil {
logger.Warn("failed to create new twitch client, keeping old credentials", zap.Error(err))
return
}
client.API = api
logger.Info("reloaded/updated Twitch API")
case BotConfigKey:
err := jsoniter.ConfigFastest.UnmarshalFromString(value, &twitchBotConfig)
if err != nil {
logger.Error("failed to unmarshal config", zap.Error(err))
return
}
err = client.Bot.Client.Disconnect()
if err != nil {
logger.Warn("failed to disconnect from Twitch IRC", zap.Error(err))
2021-11-24 10:55:12 +00:00
}
2022-02-01 11:35:34 +00:00
client.Bot = NewBot(client, twitchBotConfig)
client.restart <- true
logger.Info("reloaded/restarted Twitch bot")
2021-11-24 10:55:12 +00:00
}
}, ConfigKey, BotConfigKey)
manager.Modules[modules.ModuleTwitch] = client
return nil
}
2021-11-24 10:55:12 +00:00
func getHelixAPI(clientID string, clientSecret string) (*helix.Client, error) {
// Create Twitch client
api, err := helix.NewClient(&helix.Options{
ClientID: clientID,
ClientSecret: clientSecret,
})
if err != nil {
return nil, err
}
// Get access token
resp, err := api.RequestAppAccessToken([]string{"user:read:email"})
if err != nil {
return nil, err
}
// Set the access token on the client
api.SetAppAccessToken(resp.Data.AccessToken)
return api, nil
}
func (c *Client) RunBot() error {
cherr := make(chan error)
go func() {
cherr <- c.Bot.Connect()
}()
select {
case <-c.restart:
return nil
case err := <-cherr:
return err
}
}
2021-12-09 09:46:14 +00:00
func (c *Client) Status() modules.ModuleStatus {
if !c.Config.Enabled {
return modules.ModuleStatus{
Enabled: false,
}
}
2021-12-09 09:46:14 +00:00
return modules.ModuleStatus{
Enabled: true,
Working: c.Bot != nil && c.Bot.Client != nil,
Data: struct{}{},
StatusString: "",
}
}
func (c *Client) Close() error {
return c.Bot.Client.Disconnect()
}