Fix panics on empty config

This commit is contained in:
Dmitrii Okunev
2024-10-21 20:34:42 +01:00
parent c284735c34
commit c9ab76a0f3
6 changed files with 84 additions and 11 deletions

View File

@@ -287,6 +287,9 @@ func ConvertPlatformConfig[T any, S StreamProfile](
ctx context.Context, ctx context.Context,
platCfg *AbstractPlatformConfig, platCfg *AbstractPlatformConfig,
) *PlatformConfig[T, S] { ) *PlatformConfig[T, S] {
if platCfg == nil {
platCfg = &AbstractPlatformConfig{}
}
return &PlatformConfig[T, S]{ return &PlatformConfig[T, S]{
Enable: platCfg.Enable, Enable: platCfg.Enable,
Config: GetPlatformSpecificConfig[T](ctx, platCfg.Config), Config: GetPlatformSpecificConfig[T](ctx, platCfg.Config),
@@ -299,6 +302,10 @@ func GetPlatformSpecificConfig[T any](
ctx context.Context, ctx context.Context,
platCfgCfg any, platCfgCfg any,
) T { ) T {
if platCfgCfg == nil {
var zeroValue T
return zeroValue
}
switch platCfgCfg := platCfgCfg.(type) { switch platCfgCfg := platCfgCfg.(type) {
case T: case T:
return platCfgCfg return platCfgCfg

View File

@@ -57,6 +57,21 @@ func NewChatHandler(
close(h.messagesOutChan) close(h.messagesOutChan)
}() }()
h.sendMessage(kickcom.ChatMessageV2{
ID: "",
ChatID: 0,
UserID: 0,
Content: "test\nmultiline message",
Type: "",
Metadata: nil,
CreatedAt: time.Time{},
Sender: kickcom.ChatMessageSenderV2{
ID: 0,
Slug: "",
Username: "test-user",
Identity: kickcom.Identity{},
},
})
err := h.iterate(ctx) err := h.iterate(ctx)
if err != nil { if err != nil {
logger.Errorf(ctx, "unable to perform an iteration: %w", err) logger.Errorf(ctx, "unable to perform an iteration: %w", err)

View File

@@ -3,6 +3,7 @@ package twitch
import ( import (
"context" "context"
"fmt" "fmt"
"time"
"github.com/adeithe/go-twitch/irc" "github.com/adeithe/go-twitch/irc"
"github.com/xaionaro-go/streamctl/pkg/observability" "github.com/xaionaro-go/streamctl/pkg/observability"
@@ -47,6 +48,13 @@ func newChatHandler(
messagesOutChan: make(chan streamcontrol.ChatMessage, 100), messagesOutChan: make(chan streamcontrol.ChatMessage, 100),
} }
h.messagesOutChan <- streamcontrol.ChatMessage{
CreatedAt: time.Now(),
UserID: "test-twitch-user",
MessageID: "test-message-id",
Message: "test\nmultiline message",
}
observability.Go(ctx, func() { observability.Go(ctx, func() {
defer func() { defer func() {
h.client.Close() h.client.Close()

View File

@@ -5,6 +5,7 @@ import (
"fmt" "fmt"
"time" "time"
"github.com/facebookincubator/go-belt/tool/logger"
"github.com/xaionaro-go/streamctl/pkg/observability" "github.com/xaionaro-go/streamctl/pkg/observability"
"github.com/xaionaro-go/streamctl/pkg/streamcontrol" "github.com/xaionaro-go/streamctl/pkg/streamcontrol"
"github.com/xaionaro-go/streamctl/pkg/streamd/api" "github.com/xaionaro-go/streamctl/pkg/streamd/api"
@@ -14,6 +15,7 @@ func (d *StreamD) startListeningForChatMessages(
ctx context.Context, ctx context.Context,
platName streamcontrol.PlatformName, platName streamcontrol.PlatformName,
) error { ) error {
logger.Debugf(ctx, "startListeningForChatMessages(ctx, '%s')", platName)
ctrl, err := d.streamController(ctx, platName) ctrl, err := d.streamController(ctx, platName)
if err != nil { if err != nil {
return fmt.Errorf("unable to get the just initialized '%s': %w", platName, err) return fmt.Errorf("unable to get the just initialized '%s': %w", platName, err)
@@ -23,6 +25,7 @@ func (d *StreamD) startListeningForChatMessages(
return fmt.Errorf("unable to get the channel for chat messages of '%s': %w", platName, err) return fmt.Errorf("unable to get the channel for chat messages of '%s': %w", platName, err)
} }
observability.Go(ctx, func() { observability.Go(ctx, func() {
logger.Debugf(ctx, "/startListeningForChatMessages(ctx, '%s')", platName)
for { for {
select { select {
case <-ctx.Done(): case <-ctx.Done():

View File

@@ -4,7 +4,6 @@ import (
"context" "context"
"errors" "errors"
"fmt" "fmt"
"sort"
"strings" "strings"
"time" "time"
@@ -22,16 +21,16 @@ import (
"github.com/xaionaro-go/streamctl/pkg/xsync" "github.com/xaionaro-go/streamctl/pkg/xsync"
) )
func (d *StreamD) EXPERIMENTAL_ReinitStreamControllers(ctx context.Context) error { func (d *StreamD) EXPERIMENTAL_ReinitStreamControllers(ctx context.Context) (_err error) {
platNames := make([]streamcontrol.PlatformName, 0, len(d.Config.Backends)) logger.Debugf(ctx, "ReinitStreamControllers")
for platName := range d.Config.Backends { defer func() { logger.Debugf(ctx, "/ReinitStreamControllers: %v", _err) }()
platNames = append(platNames, platName)
}
sort.Slice(platNames, func(i, j int) bool {
return platNames[i] < platNames[j]
})
var result *multierror.Error var result *multierror.Error
for _, platName := range platNames { for _, platName := range []streamcontrol.PlatformName{
youtube.ID,
twitch.ID,
kick.ID,
obs.ID,
} {
var err error var err error
switch strings.ToLower(string(platName)) { switch strings.ToLower(string(platName)) {
case strings.ToLower(string(obs.ID)): case strings.ToLower(string(obs.ID)):
@@ -76,7 +75,9 @@ func newOBS(
) { ) {
logger.Debugf(ctx, "newOBS(ctx, %#+v, ...)", cfg) logger.Debugf(ctx, "newOBS(ctx, %#+v, ...)", cfg)
defer func() { logger.Debugf(ctx, "/newOBS: %v", _err) }() defer func() { logger.Debugf(ctx, "/newOBS: %v", _err) }()
if cfg == nil {
cfg = &streamcontrol.AbstractPlatformConfig{}
}
platCfg := streamcontrol.ConvertPlatformConfig[ platCfg := streamcontrol.ConvertPlatformConfig[
obs.PlatformSpecificConfig, obs.StreamProfile, obs.PlatformSpecificConfig, obs.StreamProfile,
]( ](
@@ -139,6 +140,9 @@ func newTwitch(
*twitch.Twitch, *twitch.Twitch,
error, error,
) { ) {
if cfg == nil {
cfg = &streamcontrol.AbstractPlatformConfig{}
}
platCfg := streamcontrol.ConvertPlatformConfig[twitch.PlatformSpecificConfig, twitch.StreamProfile]( platCfg := streamcontrol.ConvertPlatformConfig[twitch.PlatformSpecificConfig, twitch.StreamProfile](
ctx, ctx,
cfg, cfg,
@@ -210,6 +214,9 @@ func newKick(
*kick.Kick, *kick.Kick,
error, error,
) { ) {
if cfg == nil {
cfg = &streamcontrol.AbstractPlatformConfig{}
}
platCfg := streamcontrol.ConvertPlatformConfig[kick.PlatformSpecificConfig, kick.StreamProfile]( platCfg := streamcontrol.ConvertPlatformConfig[kick.PlatformSpecificConfig, kick.StreamProfile](
ctx, ctx,
cfg, cfg,
@@ -222,6 +229,27 @@ func newKick(
return nil, ErrSkipBackend return nil, ErrSkipBackend
} }
hadSetNewUserData := false
if platCfg.Config.Channel == "" {
ok, err := setUserData(ctx, platCfg)
if !ok {
err := saveCfgFunc(&streamcontrol.AbstractPlatformConfig{
Enable: platCfg.Enable,
Config: platCfg.Config,
StreamProfiles: streamcontrol.ToAbstractStreamProfiles(platCfg.StreamProfiles),
Custom: platCfg.Custom,
})
if err != nil {
logger.Error(ctx, err)
}
return nil, ErrSkipBackend
}
if err != nil {
return nil, fmt.Errorf("unable to set user info: %w", err)
}
hadSetNewUserData = true
}
logger.Debugf(ctx, "kick config: %#+v", platCfg) logger.Debugf(ctx, "kick config: %#+v", platCfg)
cfg = streamcontrol.ToAbstractPlatformConfig(ctx, platCfg) cfg = streamcontrol.ToAbstractPlatformConfig(ctx, platCfg)
kick, err := kick.New(ctx, *platCfg, kick, err := kick.New(ctx, *platCfg,
@@ -237,6 +265,12 @@ func newKick(
if err != nil { if err != nil {
return nil, fmt.Errorf("unable to initialize Kick client: %w", err) return nil, fmt.Errorf("unable to initialize Kick client: %w", err)
} }
if hadSetNewUserData {
logger.Debugf(ctx, "confirmed new youtube user data, saving it")
if err := saveCfgFunc(cfg); err != nil {
return nil, fmt.Errorf("unable to save the configuration: %w", err)
}
}
return kick, nil return kick, nil
} }
@@ -251,6 +285,9 @@ func newYouTube(
*youtube.YouTube, *youtube.YouTube,
error, error,
) { ) {
if cfg == nil {
cfg = &streamcontrol.AbstractPlatformConfig{}
}
platCfg := streamcontrol.ConvertPlatformConfig[youtube.PlatformSpecificConfig, youtube.StreamProfile]( platCfg := streamcontrol.ConvertPlatformConfig[youtube.PlatformSpecificConfig, youtube.StreamProfile](
ctx, ctx,
cfg, cfg,

View File

@@ -318,6 +318,9 @@ func (d *StreamD) setPlatformConfig(
logger.Debugf(ctx, "setPlatformConfig('%s', '%#+v')", platID, platCfg) logger.Debugf(ctx, "setPlatformConfig('%s', '%#+v')", platID, platCfg)
defer logger.Debugf(ctx, "endof setPlatformConfig('%s', '%#+v')", platID, platCfg) defer logger.Debugf(ctx, "endof setPlatformConfig('%s', '%#+v')", platID, platCfg)
return xsync.DoR1(ctx, &d.ConfigLock, func() error { return xsync.DoR1(ctx, &d.ConfigLock, func() error {
if d.Config.Backends == nil {
d.Config.Backends = make(streamcontrol.Config)
}
d.Config.Backends[platID] = platCfg d.Config.Backends[platID] = platCfg
return d.SaveConfig(ctx) return d.SaveConfig(ctx)
}) })