Add the boilerplate code for Kick

This commit is contained in:
Dmitrii Okunev
2024-10-20 22:00:02 +01:00
parent e11665c11d
commit 35a1bec9c3
19 changed files with 348 additions and 7 deletions

View File

@@ -16,6 +16,7 @@ import (
"github.com/spf13/cobra"
"github.com/xaionaro-go/streamctl/pkg/observability"
"github.com/xaionaro-go/streamctl/pkg/streamcontrol"
kick "github.com/xaionaro-go/streamctl/pkg/streamcontrol/kick/types"
obs "github.com/xaionaro-go/streamctl/pkg/streamcontrol/obs/types"
twitch "github.com/xaionaro-go/streamctl/pkg/streamcontrol/twitch/types"
youtube "github.com/xaionaro-go/streamctl/pkg/streamcontrol/youtube/types"
@@ -216,7 +217,7 @@ func streamStatus(cmd *cobra.Command, args []string) {
result := map[streamcontrol.PlatformName]*streamcontrol.StreamStatus{}
for _, platID := range []streamcontrol.PlatformName{
obs.ID, twitch.ID, youtube.ID,
obs.ID, twitch.ID, youtube.ID, kick.ID,
} {
isEnabled, err := streamD.IsBackendEnabled(ctx, platID)
assertNoError(ctx, err)

View File

@@ -12,6 +12,7 @@ import (
"github.com/goccy/go-yaml"
"github.com/spf13/cobra"
"github.com/xaionaro-go/streamctl/pkg/streamcontrol"
"github.com/xaionaro-go/streamctl/pkg/streamcontrol/kick"
"github.com/xaionaro-go/streamctl/pkg/streamcontrol/twitch"
"github.com/xaionaro-go/streamctl/pkg/streamcontrol/youtube"
"github.com/xaionaro-go/streamctl/pkg/xsync"
@@ -138,12 +139,14 @@ func expandPath(rawPath string) string {
const (
idTwitch = twitch.ID
idKick = kick.ID
idYoutube = youtube.ID
)
func newConfig() streamcontrol.Config {
cfg := streamcontrol.Config{}
twitch.InitConfig(cfg)
kick.InitConfig(cfg)
youtube.InitConfig(cfg)
return cfg
}
@@ -157,6 +160,9 @@ func generateConfig(cmd *cobra.Command, args []string) {
cfg[idTwitch].StreamProfiles = map[streamcontrol.ProfileName]streamcontrol.AbstractStreamProfile{
"some_profile": twitch.StreamProfile{},
}
cfg[idKick].StreamProfiles = map[streamcontrol.ProfileName]streamcontrol.AbstractStreamProfile{
"some_profile": kick.StreamProfile{},
}
cfg[idYoutube].StreamProfiles = map[streamcontrol.ProfileName]streamcontrol.AbstractStreamProfile{
"some_profile": youtube.StreamProfile{},
}
@@ -218,13 +224,24 @@ func readConfigFromPath(
logger.Debugf(ctx, "final stream profiles of twitch: %#+v", (*cfg)[idTwitch].StreamProfiles)
}
if (*cfg)[idKick] != nil {
err = streamcontrol.ConvertStreamProfiles[kick.StreamProfile](
ctx,
(*cfg)[idKick].StreamProfiles,
)
if err != nil {
return fmt.Errorf("unable to convert stream profiles of kick: %w: <%s>", err, b)
}
logger.Debugf(ctx, "final stream profiles of kick: %#+v", (*cfg)[idKick].StreamProfiles)
}
if (*cfg)[idYoutube] != nil {
err = streamcontrol.ConvertStreamProfiles[youtube.StreamProfile](
ctx,
(*cfg)[idYoutube].StreamProfiles,
)
if err != nil {
return fmt.Errorf("unable to convert stream profiles of twitch: %w: <%s>", err, b)
return fmt.Errorf("unable to convert stream profiles of youtube: %w: <%s>", err, b)
}
logger.Debugf(
ctx,
@@ -283,6 +300,34 @@ func getTwitchStreamController(
)
}
func getKickStreamController(
ctx context.Context,
cfg streamcontrol.Config,
) (*kick.Kick, error) {
platCfg := streamcontrol.GetPlatformConfig[kick.PlatformSpecificConfig, kick.StreamProfile](
ctx,
cfg,
idKick,
)
if platCfg == nil {
logger.Infof(ctx, "kick config was not found")
return nil, nil
}
logger.Debugf(ctx, "kick config: %#+v", platCfg)
return kick.New(ctx, *platCfg,
func(c kick.Config) error {
return xsync.DoR1(ctx, &saveConfigLock, func() error {
cfg[idKick] = &streamcontrol.AbstractPlatformConfig{
Config: c.Config,
StreamProfiles: streamcontrol.ToAbstractStreamProfiles(c.StreamProfiles),
}
return saveConfig(ctx, cfg)
})
},
)
}
func getYouTubeStreamController(
ctx context.Context,
cfg streamcontrol.Config,
@@ -325,6 +370,14 @@ func getStreamControllers(
result = append(result, streamcontrol.ToAbstract(twitch))
}
kick, err := getKickStreamController(ctx, cfg)
if err != nil {
logger.Panic(ctx, err)
}
if kick != nil {
result = append(result, streamcontrol.ToAbstract(kick))
}
youtube, err := getYouTubeStreamController(ctx, cfg)
if err != nil {
logger.Panic(ctx, err)

View File

@@ -23,6 +23,7 @@ import (
"github.com/xaionaro-go/streamctl/cmd/streamd/ui"
"github.com/xaionaro-go/streamctl/pkg/observability"
"github.com/xaionaro-go/streamctl/pkg/streamcontrol"
"github.com/xaionaro-go/streamctl/pkg/streamcontrol/kick"
"github.com/xaionaro-go/streamctl/pkg/streamcontrol/obs"
"github.com/xaionaro-go/streamctl/pkg/streamcontrol/twitch"
"github.com/xaionaro-go/streamctl/pkg/streamcontrol/youtube"
@@ -265,6 +266,9 @@ func main() {
func(ctx context.Context, cfg *streamcontrol.PlatformConfig[twitch.PlatformSpecificConfig, twitch.StreamProfile]) (bool, error) {
return false, streamd.ErrSkipBackend
},
func(ctx context.Context, cfg *streamcontrol.PlatformConfig[kick.PlatformSpecificConfig, kick.StreamProfile]) (bool, error) {
return false, streamd.ErrSkipBackend
},
func(ctx context.Context, cfg *streamcontrol.PlatformConfig[youtube.PlatformSpecificConfig, youtube.StreamProfile]) (bool, error) {
return false, streamd.ErrSkipBackend
},

View File

@@ -9,6 +9,7 @@ import (
"github.com/facebookincubator/go-belt/tool/logger"
"github.com/xaionaro-go/streamctl/pkg/oauthhandler"
"github.com/xaionaro-go/streamctl/pkg/streamcontrol"
"github.com/xaionaro-go/streamctl/pkg/streamcontrol/kick"
obs "github.com/xaionaro-go/streamctl/pkg/streamcontrol/obs/types"
twitch "github.com/xaionaro-go/streamctl/pkg/streamcontrol/twitch/types"
youtube "github.com/xaionaro-go/streamctl/pkg/streamcontrol/youtube/types"
@@ -28,6 +29,10 @@ type UI struct {
ctx context.Context,
cfg *streamcontrol.PlatformConfig[twitch.PlatformSpecificConfig, twitch.StreamProfile],
) (bool, error)
InputKickUserInfoFn func(
ctx context.Context,
cfg *streamcontrol.PlatformConfig[kick.PlatformSpecificConfig, kick.StreamProfile],
) (bool, error)
InputYouTubeUserInfoFn func(
ctx context.Context,
cfg *streamcontrol.PlatformConfig[youtube.PlatformSpecificConfig, youtube.StreamProfile],
@@ -50,6 +55,10 @@ func NewUI(
ctx context.Context,
cfg *streamcontrol.PlatformConfig[twitch.PlatformSpecificConfig, twitch.StreamProfile],
) (bool, error),
inputKickUserInfoFn func(
ctx context.Context,
cfg *streamcontrol.PlatformConfig[kick.PlatformSpecificConfig, kick.StreamProfile],
) (bool, error),
inputYouTubeUserInfoFn func(
ctx context.Context,
cfg *streamcontrol.PlatformConfig[youtube.PlatformSpecificConfig, youtube.StreamProfile],
@@ -68,6 +77,7 @@ func NewUI(
CodeChMapLocker: xsync.RWMutex{},
SetLoggingLevelFn: setLoggingLevel,
InputTwitchUserInfoFn: inputTwitchUserInfoFn,
InputKickUserInfoFn: inputKickUserInfoFn,
InputYouTubeUserInfoFn: inputYouTubeUserInfoFn,
InputOBSConnectInfoFn: inputOBSConnectInfoFn,
}
@@ -220,6 +230,13 @@ func (ui *UI) OAuthHandlerTwitch(
return ui.oauth2Handler(ctx, twitch.ID, arg)
}
func (ui *UI) OAuthHandlerKick(
ctx context.Context,
arg oauthhandler.OAuthHandlerArgument,
) error {
return ui.oauth2Handler(ctx, kick.ID, arg)
}
func (ui *UI) OAuthHandlerYouTube(
ctx context.Context,
arg oauthhandler.OAuthHandlerArgument,
@@ -234,6 +251,13 @@ func (ui *UI) InputTwitchUserInfo(
return ui.InputTwitchUserInfoFn(ctx, cfg)
}
func (ui *UI) InputKickUserInfo(
ctx context.Context,
cfg *streamcontrol.PlatformConfig[kick.PlatformSpecificConfig, kick.StreamProfile],
) (bool, error) {
return ui.InputKickUserInfoFn(ctx, cfg)
}
func (ui *UI) InputYouTubeUserInfo(
ctx context.Context,
cfg *streamcontrol.PlatformConfig[youtube.PlatformSpecificConfig, youtube.StreamProfile],

View File

@@ -19,6 +19,7 @@ import (
"github.com/xaionaro-go/streamctl/pkg/mainprocess"
"github.com/xaionaro-go/streamctl/pkg/observability"
"github.com/xaionaro-go/streamctl/pkg/streamcontrol"
"github.com/xaionaro-go/streamctl/pkg/streamcontrol/kick"
"github.com/xaionaro-go/streamctl/pkg/streamcontrol/obs"
"github.com/xaionaro-go/streamctl/pkg/streamcontrol/twitch"
"github.com/xaionaro-go/streamctl/pkg/streamcontrol/youtube"
@@ -147,6 +148,12 @@ func runStreamd(
) (bool, error) {
return false, streamd.ErrSkipBackend
},
func(
ctx context.Context,
cfg *streamcontrol.PlatformConfig[kick.PlatformSpecificConfig, kick.StreamProfile],
) (bool, error) {
return false, streamd.ErrSkipBackend
},
func(
ctx context.Context,
cfg *streamcontrol.PlatformConfig[youtube.PlatformSpecificConfig, youtube.StreamProfile],

View File

@@ -19,19 +19,27 @@ type Kick struct {
Channel *kickcom.ChannelV1
Client Client
ChatHandler *ChatHandler
SaveCfgFn func(Config) error
}
var _ streamcontrol.StreamController[StreamProfile] = (*Kick)(nil)
func New(channelSlug string) (*Kick, error) {
ctx := context.TODO()
func New(
ctx context.Context,
cfg Config,
saveCfgFn func(Config) error,
) (*Kick, error) {
if cfg.Config.Channel == "" {
return nil, fmt.Errorf("channel is not set")
}
client, err := kickcom.New()
if err != nil {
return nil, fmt.Errorf("unable to initialize a client to Kick: %w", err)
}
channel, err := client.GetChannelV1(ctx, channelSlug)
channel, err := client.GetChannelV1(ctx, cfg.Config.Channel)
if err != nil {
return nil, fmt.Errorf("unable to obtain channel info: %w", err)
}
@@ -39,6 +47,7 @@ func New(channelSlug string) (*Kick, error) {
k := &Kick{
Client: client,
Channel: channel,
SaveCfgFn: saveCfgFn,
}
chatHandler, err := k.newChatHandler(ctx, channel.ID)

View File

@@ -298,6 +298,9 @@ type BackendDataTwitch struct {
Cache cache.Twitch
}
type BackendDataKick struct {
}
type BackendDataYouTube struct {
Cache cache.YouTube
}

View File

@@ -23,6 +23,7 @@ import (
"github.com/xaionaro-go/streamctl/pkg/player"
"github.com/xaionaro-go/streamctl/pkg/player/protobuf/go/player_grpc"
"github.com/xaionaro-go/streamctl/pkg/streamcontrol"
"github.com/xaionaro-go/streamctl/pkg/streamcontrol/kick"
obs "github.com/xaionaro-go/streamctl/pkg/streamcontrol/obs/types"
twitch "github.com/xaionaro-go/streamctl/pkg/streamcontrol/twitch/types"
youtube "github.com/xaionaro-go/streamctl/pkg/streamcontrol/youtube/types"
@@ -802,6 +803,13 @@ func (c *Client) GetBackendData(
&_data,
)
data = _data
case kick.ID:
_data := api.BackendDataKick{}
err = json.Unmarshal(
[]byte(reply.GetData()),
&_data,
)
data = _data
case youtube.ID:
_data := api.BackendDataYouTube{}
err = json.Unmarshal(

View File

@@ -7,6 +7,7 @@ import (
"github.com/facebookincubator/go-belt/tool/logger"
"github.com/xaionaro-go/streamctl/pkg/streamcontrol"
"github.com/xaionaro-go/streamctl/pkg/streamcontrol/kick"
"github.com/xaionaro-go/streamctl/pkg/streamcontrol/obs"
"github.com/xaionaro-go/streamctl/pkg/streamcontrol/twitch"
"github.com/xaionaro-go/streamctl/pkg/streamcontrol/youtube"
@@ -35,6 +36,7 @@ func NewConfig() Config {
cfg := streamcontrol.Config{}
obs.InitConfig(cfg)
twitch.InitConfig(cfg)
kick.InitConfig(cfg)
youtube.InitConfig(cfg)
return Config{
Backends: cfg,
@@ -54,6 +56,9 @@ func NewSampleConfig() Config {
cfg.Backends[twitch.ID].StreamProfiles = map[streamcontrol.ProfileName]streamcontrol.AbstractStreamProfile{
"some_profile": twitch.StreamProfile{},
}
cfg.Backends[kick.ID].StreamProfiles = map[streamcontrol.ProfileName]streamcontrol.AbstractStreamProfile{
"some_profile": kick.StreamProfile{},
}
cfg.Backends[youtube.ID].StreamProfiles = map[streamcontrol.ProfileName]streamcontrol.AbstractStreamProfile{
"some_profile": youtube.StreamProfile{},
}

View File

@@ -11,6 +11,7 @@ import (
"github.com/goccy/go-yaml"
"github.com/xaionaro-go/streamctl/pkg/observability"
"github.com/xaionaro-go/streamctl/pkg/streamcontrol"
"github.com/xaionaro-go/streamctl/pkg/streamcontrol/kick"
"github.com/xaionaro-go/streamctl/pkg/streamcontrol/obs"
"github.com/xaionaro-go/streamctl/pkg/streamcontrol/twitch"
"github.com/xaionaro-go/streamctl/pkg/streamcontrol/youtube"
@@ -89,6 +90,16 @@ func (cfg *Config) UnmarshalYAML(b []byte) (_err error) {
}
}
if cfg.Backends[kick.ID] != nil {
err = streamcontrol.ConvertStreamProfiles[kick.StreamProfile](
context.Background(),
cfg.Backends[kick.ID].StreamProfiles,
)
if err != nil {
return fmt.Errorf("unable to convert stream profiles of kick: %w", err)
}
}
if cfg.Backends[youtube.ID] != nil {
err = streamcontrol.ConvertStreamProfiles[youtube.StreamProfile](
context.Background(),

View File

@@ -6,6 +6,7 @@ import (
"github.com/goccy/go-yaml"
"github.com/xaionaro-go/streamctl/pkg/streamcontrol"
"github.com/xaionaro-go/streamctl/pkg/streamcontrol/kick"
"github.com/xaionaro-go/streamctl/pkg/streamcontrol/obs"
"github.com/xaionaro-go/streamctl/pkg/streamcontrol/twitch"
"github.com/xaionaro-go/streamctl/pkg/streamcontrol/youtube"
@@ -22,6 +23,8 @@ func ProfileGRPC2Go(
profile = &obs.StreamProfile{}
case twitch.ID:
profile = &twitch.StreamProfile{}
case kick.ID:
profile = &kick.StreamProfile{}
case youtube.ID:
profile = &youtube.StreamProfile{}
default:

View File

@@ -4,6 +4,7 @@ import (
"fmt"
"github.com/xaionaro-go/streamctl/pkg/streamcontrol"
"github.com/xaionaro-go/streamctl/pkg/streamcontrol/kick"
"github.com/xaionaro-go/streamctl/pkg/streamcontrol/obs"
"github.com/xaionaro-go/streamctl/pkg/streamcontrol/twitch"
"github.com/xaionaro-go/streamctl/pkg/streamcontrol/youtube"
@@ -15,6 +16,8 @@ func NewStreamProfile(
switch platID {
case twitch.ID:
return &twitch.StreamProfile{}, nil
case kick.ID:
return &kick.StreamProfile{}, nil
case youtube.ID:
return &youtube.StreamProfile{}, nil
case obs.ID:

View File

@@ -14,6 +14,7 @@ import (
"github.com/facebookincubator/go-belt/tool/logger"
"github.com/hashicorp/go-multierror"
"github.com/xaionaro-go/streamctl/pkg/streamcontrol"
"github.com/xaionaro-go/streamctl/pkg/streamcontrol/kick"
"github.com/xaionaro-go/streamctl/pkg/streamcontrol/obs"
"github.com/xaionaro-go/streamctl/pkg/streamcontrol/twitch"
"github.com/xaionaro-go/streamctl/pkg/streamcontrol/youtube"
@@ -37,6 +38,8 @@ func (d *StreamD) EXPERIMENTAL_ReinitStreamControllers(ctx context.Context) erro
err = d.initOBSBackend(ctx)
case strings.ToLower(string(twitch.ID)):
err = d.initTwitchBackend(ctx)
case strings.ToLower(string(kick.ID)):
err = d.initKickBackend(ctx)
case strings.ToLower(string(youtube.ID)):
err = d.initYouTubeBackend(ctx)
}
@@ -196,6 +199,47 @@ func newTwitch(
return twitch, nil
}
func newKick(
ctx context.Context,
cfg *streamcontrol.AbstractPlatformConfig,
setUserData func(context.Context, *streamcontrol.PlatformConfig[kick.PlatformSpecificConfig, kick.StreamProfile]) (bool, error),
saveCfgFunc func(*streamcontrol.AbstractPlatformConfig) error,
customOAuthHandler kick.OAuthHandler,
getOAuthListenPorts func() []uint16,
) (
*kick.Kick,
error,
) {
platCfg := streamcontrol.ConvertPlatformConfig[kick.PlatformSpecificConfig, kick.StreamProfile](
ctx,
cfg,
)
if platCfg == nil {
return nil, fmt.Errorf("kick config was not found")
}
if cfg.Enable != nil && !*cfg.Enable {
return nil, ErrSkipBackend
}
logger.Debugf(ctx, "kick config: %#+v", platCfg)
cfg = streamcontrol.ToAbstractPlatformConfig(ctx, platCfg)
kick, err := kick.New(ctx, *platCfg,
func(c kick.Config) error {
return saveCfgFunc(&streamcontrol.AbstractPlatformConfig{
Enable: c.Enable,
Config: c.Config,
StreamProfiles: streamcontrol.ToAbstractStreamProfiles(c.StreamProfiles),
Custom: c.Custom,
})
},
)
if err != nil {
return nil, fmt.Errorf("unable to initialize Kick client: %w", err)
}
return kick, nil
}
func newYouTube(
ctx context.Context,
cfg *streamcontrol.AbstractPlatformConfig,
@@ -365,6 +409,24 @@ func (d *StreamD) initTwitchBackend(ctx context.Context) error {
return nil
}
func (d *StreamD) initKickBackend(ctx context.Context) error {
kick, err := newKick(
ctx,
d.Config.Backends[kick.ID],
d.UI.InputKickUserInfo,
func(cfg *streamcontrol.AbstractPlatformConfig) error {
return d.setPlatformConfig(ctx, kick.ID, cfg)
},
d.UI.OAuthHandlerKick,
d.GetOAuthListenPorts,
)
if err != nil {
return err
}
d.StreamControllers.Kick = kick
return nil
}
func (d *StreamD) initYouTubeBackend(ctx context.Context) error {
youTube, err := newYouTube(
ctx,

View File

@@ -8,6 +8,7 @@ import (
"github.com/facebookincubator/go-belt/tool/logger"
"github.com/xaionaro-go/streamctl/pkg/streamcontrol"
"github.com/xaionaro-go/streamctl/pkg/streamcontrol/kick"
twitch "github.com/xaionaro-go/streamctl/pkg/streamcontrol/twitch/types"
youtube "github.com/xaionaro-go/streamctl/pkg/streamcontrol/youtube/types"
"github.com/xaionaro-go/streamctl/pkg/streamd/api"
@@ -35,6 +36,8 @@ func (a *platformsControllerAdapter) CheckStreamStartedByURL(
platID = youtube.ID
case strings.Contains(destination.Hostname(), "twitch"):
platID = twitch.ID
case strings.Contains(destination.Hostname(), "global-contribute.live-video.net"):
platID = kick.ID
default:
return false, fmt.Errorf(
"do not know how to check if the stream started for '%s'",

View File

@@ -19,6 +19,7 @@ import (
"github.com/xaionaro-go/streamctl/pkg/player"
"github.com/xaionaro-go/streamctl/pkg/repository"
"github.com/xaionaro-go/streamctl/pkg/streamcontrol"
"github.com/xaionaro-go/streamctl/pkg/streamcontrol/kick"
"github.com/xaionaro-go/streamctl/pkg/streamcontrol/obs"
"github.com/xaionaro-go/streamctl/pkg/streamcontrol/twitch"
"github.com/xaionaro-go/streamctl/pkg/streamcontrol/youtube"
@@ -42,6 +43,7 @@ import (
type StreamControllers struct {
OBS *obs.OBS
Twitch *twitch.Twitch
Kick *kick.Kick
YouTube *youtube.YouTube
}
@@ -450,6 +452,8 @@ func (d *StreamD) IsBackendEnabled(
return d.StreamControllers.OBS != nil, nil
case twitch.ID:
return d.StreamControllers.Twitch != nil, nil
case kick.ID:
return d.StreamControllers.Kick != nil, nil
case youtube.ID:
return d.StreamControllers.YouTube != nil, nil
default:
@@ -518,6 +522,21 @@ func (d *StreamD) StartStream(
return fmt.Errorf("unable to start the stream on Twitch: %w", err)
}
return nil
case kick.ID:
profile, err := streamcontrol.GetStreamProfile[kick.StreamProfile](ctx, profile)
if err != nil {
return fmt.Errorf("unable to convert the profile into Twitch profile: %w", err)
}
err = d.StreamControllers.Kick.StartStream(
d.ctxForController(ctx),
title,
description,
*profile,
customArgs...)
if err != nil {
return fmt.Errorf("unable to start the stream on Twitch: %w", err)
}
return nil
case youtube.ID:
profile, err := streamcontrol.GetStreamProfile[youtube.StreamProfile](ctx, profile)
if err != nil {
@@ -617,6 +636,8 @@ func (d *StreamD) GetBackendData(
return api.BackendDataOBS{}, nil
case twitch.ID:
return api.BackendDataTwitch{Cache: d.Cache.Twitch}, nil
case kick.ID:
return api.BackendDataKick{}, nil
case youtube.ID:
return api.BackendDataYouTube{Cache: d.Cache.Youtube}, nil
default:
@@ -644,6 +665,21 @@ func (d *StreamD) tryConnectTwitch(
errmon.ObserveErrorCtx(ctx, err)
}
func (d *StreamD) tryConnectKick(
ctx context.Context,
) {
if d.StreamControllers.Kick != nil {
return
}
if _, ok := d.Config.Backends[kick.ID]; !ok {
return
}
err := d.initKickBackend(ctx)
errmon.ObserveErrorCtx(ctx, err)
}
func (d *StreamD) tryConnectYouTube(
ctx context.Context,
) {
@@ -676,6 +712,13 @@ func (d *StreamD) streamController(
if d.StreamControllers.Twitch != nil {
result = streamcontrol.ToAbstract(d.StreamControllers.Twitch)
}
case kick.ID:
if d.StreamControllers.Kick == nil {
d.tryConnectKick(ctx)
}
if d.StreamControllers.Kick != nil {
result = streamcontrol.ToAbstract(d.StreamControllers.Kick)
}
case youtube.ID:
if d.StreamControllers.YouTube == nil {
d.tryConnectYouTube(ctx)

View File

@@ -6,6 +6,7 @@ import (
"github.com/facebookincubator/go-belt/tool/logger"
"github.com/xaionaro-go/streamctl/pkg/oauthhandler"
"github.com/xaionaro-go/streamctl/pkg/streamcontrol"
"github.com/xaionaro-go/streamctl/pkg/streamcontrol/kick"
obs "github.com/xaionaro-go/streamctl/pkg/streamcontrol/obs/types"
twitch "github.com/xaionaro-go/streamctl/pkg/streamcontrol/twitch/types"
youtube "github.com/xaionaro-go/streamctl/pkg/streamcontrol/youtube/types"
@@ -19,12 +20,17 @@ type UI interface {
ctx context.Context,
) (bool, string, []byte, error)
OAuthHandlerTwitch(ctx context.Context, arg oauthhandler.OAuthHandlerArgument) error
OAuthHandlerKick(ctx context.Context, arg oauthhandler.OAuthHandlerArgument) error
OAuthHandlerYouTube(ctx context.Context, arg oauthhandler.OAuthHandlerArgument) error
OpenBrowser(ctx context.Context, url string) error
InputTwitchUserInfo(
ctx context.Context,
cfg *streamcontrol.PlatformConfig[twitch.PlatformSpecificConfig, twitch.StreamProfile],
) (bool, error)
InputKickUserInfo(
ctx context.Context,
cfg *streamcontrol.PlatformConfig[kick.PlatformSpecificConfig, kick.StreamProfile],
) (bool, error)
InputYouTubeUserInfo(
ctx context.Context,
cfg *streamcontrol.PlatformConfig[youtube.PlatformSpecificConfig, youtube.StreamProfile],

View File

@@ -26,6 +26,7 @@ import (
"github.com/xaionaro-go/streamctl/pkg/colorx"
"github.com/xaionaro-go/streamctl/pkg/observability"
"github.com/xaionaro-go/streamctl/pkg/streamcontrol"
"github.com/xaionaro-go/streamctl/pkg/streamcontrol/kick"
"github.com/xaionaro-go/streamctl/pkg/streamcontrol/obs"
"github.com/xaionaro-go/streamctl/pkg/streamcontrol/twitch"
"github.com/xaionaro-go/streamctl/pkg/streamcontrol/youtube"
@@ -278,6 +279,7 @@ func (p *Panel) updateMonitorPageStreamStatus(
obs.ID,
youtube.ID,
twitch.ID,
kick.ID,
} {
wg.Add(1)
observability.Go(ctx, func() {

View File

@@ -35,6 +35,7 @@ import (
"github.com/xaionaro-go/streamctl/pkg/screenshot"
"github.com/xaionaro-go/streamctl/pkg/screenshoter"
"github.com/xaionaro-go/streamctl/pkg/streamcontrol"
"github.com/xaionaro-go/streamctl/pkg/streamcontrol/kick"
"github.com/xaionaro-go/streamctl/pkg/streamcontrol/obs"
"github.com/xaionaro-go/streamctl/pkg/streamcontrol/twitch"
"github.com/xaionaro-go/streamctl/pkg/streamcontrol/youtube"
@@ -107,6 +108,7 @@ type Panel struct {
youtubeCheck *widget.Check
twitchCheck *widget.Check
kickCheck *widget.Check
configPath string
configCache *streamdconfig.Config
@@ -662,6 +664,15 @@ func (p *Panel) OAuthHandlerTwitch(
return p.oauthHandler(ctx, twitch.ID, arg)
}
func (p *Panel) OAuthHandlerKick(
ctx context.Context,
arg oauthhandler.OAuthHandlerArgument,
) error {
logger.Infof(ctx, "OAuthHandlerKick: %#+v", arg)
defer logger.Infof(ctx, "/OAuthHandlerKick")
return p.oauthHandler(ctx, kick.ID, arg)
}
func (p *Panel) OAuthHandlerYouTube(
ctx context.Context,
arg oauthhandler.OAuthHandlerArgument,
@@ -857,6 +868,13 @@ func (p *Panel) InputTwitchUserInfo(
return true, nil
}
func (p *Panel) InputKickUserInfo(
ctx context.Context,
cfg *streamcontrol.PlatformConfig[kick.PlatformSpecificConfig, kick.StreamProfile],
) (bool, error) {
return false, fmt.Errorf("not implemented, yet")
}
var youtubeCredentialsCreateLink, _ = url.Parse(
"https://console.cloud.google.com/apis/credentials/oauthclient",
)
@@ -1105,6 +1123,7 @@ func (p *Panel) refilterProfiles(ctx context.Context) {
subValueMatch = true
break
}
case kick.StreamProfile:
case youtube.StreamProfile:
if containTagSubstringCI(prof.Tags, filterValue) {
subValueMatch = true
@@ -1214,6 +1233,7 @@ func (p *Panel) openSettingsWindow(ctx context.Context) error {
for _, backendID := range []streamcontrol.PlatformName{
obs.ID,
twitch.ID,
kick.ID,
youtube.ID,
} {
isEnabled, err := p.StreamD.IsBackendEnabled(ctx, backendID)
@@ -1319,6 +1339,13 @@ func (p *Panel) openSettingsWindow(ctx context.Context) error {
twitchAlreadyLoggedIn.SetText("(already logged in)")
}
kickAlreadyLoggedIn := widget.NewLabel("")
if !backendEnabled[kick.ID] {
kickAlreadyLoggedIn.SetText("(not logged in)")
} else {
kickAlreadyLoggedIn.SetText("(already logged in)")
}
youtubeAlreadyLoggedIn := widget.NewLabel("")
if !backendEnabled[youtube.ID] {
youtubeAlreadyLoggedIn.SetText("(not logged in)")
@@ -1432,6 +1459,27 @@ func (p *Panel) openSettingsWindow(ctx context.Context) error {
}),
twitchAlreadyLoggedIn,
),
container.NewHBox(
widget.NewButtonWithIcon("(Re-)login in Kick", theme.LoginIcon(), func() {
if cfg.Backends[kick.ID] == nil {
kick.InitConfig(cfg.Backends)
}
cfg.Backends[kick.ID].Enable = nil
cfg.Backends[kick.ID].Config = kick.PlatformSpecificConfig{}
if err := p.StreamD.SetConfig(ctx, cfg); err != nil {
p.DisplayError(err)
return
}
if err := p.StreamD.EXPERIMENTAL_ReinitStreamControllers(ctx); err != nil {
p.DisplayError(err)
return
}
}),
kickAlreadyLoggedIn,
),
container.NewHBox(
widget.NewButtonWithIcon("(Re-)login in YouTube", theme.LoginIcon(), func() {
if cfg.Backends[youtube.ID] == nil {
@@ -1603,6 +1651,7 @@ func (p *Panel) getUpdatedStatus_backends_noLock(ctx context.Context) {
for _, backendID := range []streamcontrol.PlatformName{
obs.ID,
twitch.ID,
kick.ID,
youtube.ID,
} {
isEnabled, err := p.StreamD.IsBackendEnabled(ctx, backendID)
@@ -1616,6 +1665,9 @@ func (p *Panel) getUpdatedStatus_backends_noLock(ctx context.Context) {
if backendEnabled[twitch.ID] {
p.twitchCheck.Enable()
}
if backendEnabled[kick.ID] {
p.kickCheck.Enable()
}
if backendEnabled[youtube.ID] {
p.youtubeCheck.Enable()
}
@@ -1856,6 +1908,10 @@ func (p *Panel) initMainWindow(
p.twitchCheck.SetChecked(true)
p.twitchCheck.Disable()
p.kickCheck = widget.NewCheck("Kick", nil)
p.kickCheck.SetChecked(true)
p.kickCheck.Disable()
p.youtubeCheck = widget.NewCheck("YouTube", nil)
p.youtubeCheck.SetChecked(true)
p.youtubeCheck.Disable()
@@ -1892,6 +1948,9 @@ func (p *Panel) initMainWindow(
twLabel := widget.NewLabel("TW:")
twLabel.Importance = widget.HighImportance
p.streamStatus[twitch.ID] = widget.NewLabel("")
kcLabel := widget.NewLabel("Kc:")
kcLabel.Importance = widget.HighImportance
p.streamStatus[kick.ID] = widget.NewLabel("")
ytLabel := widget.NewLabel("YT:")
ytLabel.Importance = widget.HighImportance
p.streamStatus[youtube.ID] = widget.NewLabel("")
@@ -1903,6 +1962,7 @@ func (p *Panel) initMainWindow(
}
streamInfoItems.Add(container.NewHBox(layout.NewSpacer(), obsLabel, p.streamStatus[obs.ID]))
streamInfoItems.Add(container.NewHBox(layout.NewSpacer(), twLabel, p.streamStatus[twitch.ID]))
streamInfoItems.Add(container.NewHBox(layout.NewSpacer(), kcLabel, p.streamStatus[kick.ID]))
streamInfoItems.Add(container.NewHBox(layout.NewSpacer(), ytLabel, p.streamStatus[youtube.ID]))
streamInfoContainer := container.NewBorder(
nil,
@@ -2243,6 +2303,7 @@ func (p *Panel) setupStreamNoLock(ctx context.Context) {
for _, backendID := range []streamcontrol.PlatformName{
obs.ID,
twitch.ID,
kick.ID,
youtube.ID,
} {
isEnabled, err := p.StreamD.IsBackendEnabled(ctx, backendID)
@@ -2278,6 +2339,19 @@ func (p *Panel) setupStreamNoLock(ctx context.Context) {
}
}
if p.kickCheck.Checked && backendEnabled[kick.ID] {
err := p.StreamD.StartStream(
ctx,
kick.ID,
p.streamTitleField.Text,
p.streamDescriptionField.Text,
profile.PerPlatform[kick.ID],
)
if err != nil {
p.DisplayError(fmt.Errorf("unable to setup the stream on Twitch: %w", err))
}
}
if p.youtubeCheck.Checked && backendEnabled[youtube.ID] {
if p.streamIsRunning(ctx, youtube.ID) {
logger.Debugf(ctx, "updating the stream info at YouTube")
@@ -2435,6 +2509,9 @@ func (p *Panel) stopStreamNoLock(ctx context.Context) {
if backendEnabled[twitch.ID] {
p.twitchCheck.Enable()
}
if backendEnabled[kick.ID] {
p.kickCheck.Enable()
}
if backendEnabled[youtube.ID] {
p.youtubeCheck.Enable()
}
@@ -2845,6 +2922,7 @@ func (p *Panel) profileWindow(
var (
obsProfile *obs.StreamProfile
twitchProfile *twitch.StreamProfile
kickProfile *kick.StreamProfile
youtubeProfile *youtube.StreamProfile
)
@@ -2870,6 +2948,7 @@ func (p *Panel) profileWindow(
for _, backendID := range []streamcontrol.PlatformName{
obs.ID,
twitch.ID,
kick.ID,
youtube.ID,
} {
isEnabled, err := p.StreamD.IsBackendEnabled(ctx, backendID)
@@ -2893,6 +2972,8 @@ func (p *Panel) profileWindow(
}
_ = backendData[obs.ID].(api.BackendDataOBS)
dataTwitch := backendData[twitch.ID].(api.BackendDataTwitch)
dataKick := backendData[kick.ID].(api.BackendDataKick)
_ = dataKick // TODO: delete me!
dataYouTube := backendData[youtube.ID].(api.BackendDataYouTube)
var bottomContent []fyne.CanvasObject
@@ -3026,6 +3107,14 @@ func (p *Panel) profileWindow(
bottomContent = append(bottomContent, widget.NewLabel("Twitch is disabled"))
}
bottomContent = append(bottomContent, widget.NewSeparator())
bottomContent = append(bottomContent, widget.NewRichTextFromMarkdown("# Kick:"))
if backendEnabled[kick.ID] {
bottomContent = append(bottomContent, widget.NewLabel("Kick configuration is not implemented, yet"))
} else {
bottomContent = append(bottomContent, widget.NewLabel("Kick is disabled"))
}
var getYoutubeTags func() []string
bottomContent = append(bottomContent, widget.NewSeparator())
bottomContent = append(bottomContent, widget.NewRichTextFromMarkdown("# YouTube:"))
@@ -3228,6 +3317,9 @@ func (p *Panel) profileWindow(
}
profile.PerPlatform[twitch.ID] = twitchProfile
}
if kickProfile != nil {
profile.PerPlatform[kick.ID] = kickProfile
}
if youtubeProfile != nil {
if getYoutubeTags != nil {
youtubeProfile.Tags = sanitizeTags(getYoutubeTags())

View File

@@ -15,6 +15,7 @@ import (
"github.com/hashicorp/go-multierror"
"github.com/xaionaro-go/streamctl/pkg/observability"
"github.com/xaionaro-go/streamctl/pkg/streamcontrol"
"github.com/xaionaro-go/streamctl/pkg/streamcontrol/kick"
obs "github.com/xaionaro-go/streamctl/pkg/streamcontrol/obs/types"
twitch "github.com/xaionaro-go/streamctl/pkg/streamcontrol/twitch/types"
youtube "github.com/xaionaro-go/streamctl/pkg/streamcontrol/youtube/types"
@@ -250,6 +251,7 @@ func (ui *timersUI) kickOffRemotely(
for _, platID := range []streamcontrol.PlatformName{
youtube.ID,
twitch.ID,
kick.ID,
obs.ID,
} {
_, err := streamD.AddTimer(ctx, deadline, &action.EndStream{