feat(twitch): Add flag --oauth-listen-port-twitch

This commit is contained in:
Dmitrii Okunev
2024-10-15 20:48:22 +01:00
parent 3ac051113f
commit a75efc79e1
8 changed files with 81 additions and 15 deletions

View File

@@ -42,6 +42,9 @@ type Flags struct {
Subprocess string `yaml:"Subprocess,omitempty"`
SplitProcess bool `yaml:"SplitProcess,omitempty"`
LockTimeout time.Duration `yaml:"LockTimeout,omitempty"`
OAuthListenPortTwitch uint16 `yaml:"OAuthListenPortTwitch,omitempty"`
OAuthListenPortYouTube uint16 `yaml:"OAuthListenPortYouTube,omitempty"`
}
var platformGetFlagsFuncs []func(*Flags)
@@ -75,6 +78,9 @@ func parseFlags() Flags {
subprocess := pflag.String("subprocess", "", "[internal use flag] run a specific sub-process (format: processName:addressToConnect)")
splitProcess := pflag.Bool("split-process", !isMobile(), "split the process into multiple processes for better stability")
lockTimeout := pflag.Duration("lock-timeout", 2*time.Minute, "[debug option] change the timeout for locking, before reporting it as a deadlock")
oauthListenPortTwitch := pflag.Uint16("oauth-listen-port-twitch", 8091, "the port that is used for OAuth callbacks while authenticating in Twitch")
oauthListenPortYouTube := pflag.Uint16("oauth-listen-port-youtube", 8092, "the port that is used for OAuth callbacks while authenticating in YouTube")
pflag.Parse()
flags := Flags{
@@ -94,6 +100,9 @@ func parseFlags() Flags {
Subprocess: *subprocess,
SplitProcess: *splitProcess,
LockTimeout: *lockTimeout,
OAuthListenPortTwitch: *oauthListenPortTwitch,
OAuthListenPortYouTube: *oauthListenPortYouTube,
}
for _, platformGetFlagsFunc := range platformGetFlagsFuncs {

View File

@@ -69,7 +69,10 @@ func runPanel(
logger.Debugf(ctx, "runPanel: %#+v", flags)
defer logger.Debugf(ctx, "/runPanel")
var opts []streampanel.Option
opts := []streampanel.Option{
streampanel.OptionOAuthListenPortTwitch(flags.OAuthListenPortTwitch),
streampanel.OptionOAuthListenPortYouTube(flags.OAuthListenPortYouTube),
}
if flags.RemoteAddr != "" {
opts = append(opts, streampanel.OptionRemoteStreamDAddr(flags.RemoteAddr))
}

View File

@@ -82,3 +82,17 @@ func (c *Client) RecodingEndedChan(
) (<-chan struct{}, error) {
return nil, fmt.Errorf("not compiled with libav support")
}
func (c *Client) CloseInput(
ctx context.Context,
inputID InputID,
) error {
return fmt.Errorf("not compiled with libav support")
}
func (c *Client) CloseOutput(
ctx context.Context,
outputID OutputID,
) error {
return fmt.Errorf("not compiled with libav support")
}

View File

@@ -44,15 +44,26 @@ func New(
if cfg.Config.ClientID == "" || cfg.Config.ClientSecret == "" {
return nil, fmt.Errorf("'clientid' or/and 'clientsecret' is/are not set; go to https://dev.twitch.tv/console/apps/create and create an app if it not created, yet")
}
client, err := getClient(ctx, cfg)
if err != nil {
return nil, err
getPortsFn := cfg.Config.GetOAuthListenPorts
if getPortsFn == nil {
// TODO: find a way to adjust the OAuth ports dynamically without re-creating the Twitch client.
return nil, fmt.Errorf("the function GetOAuthListenPorts is not set")
}
oauthPorts := getPortsFn()
if len(oauthPorts) == 0 {
return nil, fmt.Errorf("the function GetOAuthListenPorts returned zero ports")
}
t := &Twitch{
client: client,
config: cfg,
saveCfgFn: saveCfgFn,
}
client, err := getClient(ctx, cfg, oauthPorts[0])
if err != nil {
return nil, err
}
t.client = client
var prevTokenUpdate time.Time
client.OnUserAccessTokenRefreshed(func(newAccessToken, newRefreshToken string) {
if twitchDebug == true {
@@ -451,10 +462,6 @@ func (t *Twitch) getNewClientCode(
) (_err error) {
logger.Debugf(ctx, "getNewClientCode")
defer func() { logger.Debugf(ctx, "/getNewClientCode: %v", _err) }()
getPortsFn := t.config.Config.GetOAuthListenPorts
if getPortsFn == nil {
return fmt.Errorf("the function GetOAuthListenPorts is not set")
}
oauthHandler := t.config.Config.CustomOAuthHandler
if oauthHandler == nil {
@@ -532,6 +539,13 @@ func (t *Twitch) getNewClientCode(
}
}
// TODO: either support only one port as in New, or support multiple
// ports as we do below
getPortsFn := t.config.Config.GetOAuthListenPorts
if getPortsFn == nil {
return fmt.Errorf("the function GetOAuthListenPorts is not set")
}
for _, listenPort := range getPortsFn() {
startHandlerForPort(listenPort)
}
@@ -628,14 +642,15 @@ func (t *Twitch) getNewTokenByApp(
func getClient(
ctx context.Context,
cfg Config,
oauthListenPort uint16,
) (*helix.Client, error) {
logger.Debugf(ctx, "getClient")
logger.Debugf(ctx, "getClient(ctx, %#+v, %v)", cfg, oauthListenPort)
defer logger.Debugf(ctx, "/getClient")
options := &helix.Options{
ClientID: cfg.Config.ClientID,
ClientSecret: cfg.Config.ClientSecret,
RedirectURI: authRedirectURI(8091), // TODO: delete this hardcode
RedirectURI: authRedirectURI(oauthListenPort), // TODO: delete this hardcode
}
client, err := helix.NewClient(options)
if err != nil {

View File

@@ -20,11 +20,19 @@ type BrowserConfig struct {
Command string `yaml:"command"`
}
type OAuthConfig struct {
ListenPorts struct {
Twitch uint16 `yaml:"twitch"`
YouTube uint16 `yaml:"youtube"`
} `yaml:"listen_ports"`
}
type Config struct {
RemoteStreamDAddr string `yaml:"streamd_remote"`
BuiltinStreamD streamd.Config `yaml:"streamd_builtin"`
Screenshot ScreenshotConfig `yaml:"screenshot"`
Browser BrowserConfig `yaml:"browser"`
OAuth OAuthConfig `yaml:"oauth"`
}
func DefaultConfig() Config {

View File

@@ -18,3 +18,15 @@ type OptionRemoteStreamDAddr string
func (o OptionRemoteStreamDAddr) Apply(cfg *Config) {
cfg.RemoteStreamDAddr = string(o)
}
type OptionOAuthListenPortTwitch uint16
func (o OptionOAuthListenPortTwitch) Apply(cfg *Config) {
cfg.OAuth.ListenPorts.Twitch = uint16(o)
}
type OptionOAuthListenPortYouTube uint16
func (o OptionOAuthListenPortYouTube) Apply(cfg *Config) {
cfg.OAuth.ListenPorts.YouTube = uint16(o)
}

View File

@@ -1,8 +1,13 @@
package streampanel
import "github.com/xaionaro-go/streamctl/pkg/streampanel/config"
import (
"github.com/xaionaro-go/streamctl/pkg/streampanel/config"
)
type Config = config.Config
type Option = config.Option
type Options = config.Options
type OptionRemoteStreamDAddr = config.OptionRemoteStreamDAddr
type OptionOAuthListenPortTwitch = config.OptionOAuthListenPortTwitch
type OptionOAuthListenPortYouTube = config.OptionOAuthListenPortYouTube

View File

@@ -322,10 +322,10 @@ func (p *Panel) Loop(ctx context.Context, opts ...LoopOption) error {
// TODO: delete this hardcoding of the port
defer closeLoadingWindow()
streamD := p.StreamD.(*streamd.StreamD)
streamD.AddOAuthListenPort(8091)
streamD.AddOAuthListenPort(p.Config.OAuth.ListenPorts.Twitch)
observability.Go(ctx, func() {
<-ctx.Done()
streamD.RemoveOAuthListenPort(8091)
streamD.RemoveOAuthListenPort(p.Config.OAuth.ListenPorts.Twitch)
})
logger.Tracef(ctx, "started oauth listener for the local streamd")
}
@@ -367,7 +367,7 @@ func (p *Panel) startOAuthListenerForRemoteStreamD(
streamD *client.Client,
) error {
ctx, cancelFn := context.WithCancel(ctx)
receiver, listenPort, err := oauthhandler.NewCodeReceiver(ctx, 8091) // TODO: remove the hard-code of port 8091, currently it is needed because the port is hardcoded in Twitch
receiver, listenPort, err := oauthhandler.NewCodeReceiver(ctx, p.Config.OAuth.ListenPorts.Twitch)
if err != nil {
cancelFn()
return fmt.Errorf("unable to start listener for OAuth responses: %w", err)