mirror of
https://github.com/xaionaro-go/streamctl.git
synced 2025-09-26 19:41:17 +08:00
Add mock clients to streaming platforms
This commit is contained in:
@@ -12,14 +12,6 @@ type ChatHandler struct {
|
||||
onClose func(context.Context)
|
||||
}
|
||||
|
||||
func (k *Kick) newChatHandler(
|
||||
ctx context.Context,
|
||||
broadcasterUserID *int,
|
||||
onClose func(context.Context),
|
||||
) (*ChatHandler, error) {
|
||||
return NewChatHandler(ctx, k.Client, broadcasterUserID, onClose)
|
||||
}
|
||||
|
||||
func NewChatHandler(
|
||||
ctx context.Context,
|
||||
client *gokick.Client,
|
||||
|
46
pkg/streamcontrol/kick/client.go
Normal file
46
pkg/streamcontrol/kick/client.go
Normal file
@@ -0,0 +1,46 @@
|
||||
package kick
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/scorfly/gokick"
|
||||
)
|
||||
|
||||
type Client interface {
|
||||
GetAuthorize(redirectURI, state, codeChallenge string, scope []gokick.Scope) (string, error)
|
||||
GetToken(ctx context.Context, redirectURI, code, codeVerifier string) (gokick.TokenResponse, error)
|
||||
OnUserAccessTokenRefreshed(callback func(accessToken, refreshToken string))
|
||||
UpdateStreamTitle(ctx context.Context, title string) (gokick.EmptyResponse, error)
|
||||
UpdateStreamCategory(ctx context.Context, categoryID int) (gokick.EmptyResponse, error)
|
||||
GetChannels(ctx context.Context, filter gokick.ChannelListFilter) (gokick.ChannelsResponseWrapper, error)
|
||||
SendChatMessage(
|
||||
ctx context.Context,
|
||||
broadcasterUserID *int,
|
||||
content string,
|
||||
replyToMessageID *string,
|
||||
messageType gokick.MessageType,
|
||||
) (gokick.ChatResponseWrapper, error)
|
||||
BanUser(
|
||||
ctx context.Context,
|
||||
broadcasterUserID int,
|
||||
userID int,
|
||||
duration *int,
|
||||
reason *string,
|
||||
) (gokick.BanUserResponseWrapper, error)
|
||||
}
|
||||
|
||||
type clientScorfly struct {
|
||||
*gokick.Client
|
||||
}
|
||||
|
||||
func newClient(options *gokick.ClientOptions) (*clientScorfly, error) {
|
||||
client, err := gokick.NewClient(options)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &clientScorfly{Client: client}, nil
|
||||
}
|
||||
|
||||
func (c *clientScorfly) OnUserAccessTokenRefreshed(callback func(accessToken, refreshToken string)) {
|
||||
c.Client.OnUserAccessTokenRefreshed(callback)
|
||||
}
|
87
pkg/streamcontrol/kick/client_mock.go
Normal file
87
pkg/streamcontrol/kick/client_mock.go
Normal file
@@ -0,0 +1,87 @@
|
||||
package kick
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/scorfly/gokick"
|
||||
)
|
||||
|
||||
type clientMock struct{}
|
||||
|
||||
var _ Client = (*clientMock)(nil)
|
||||
|
||||
func newClientMock() *clientMock {
|
||||
return &clientMock{}
|
||||
}
|
||||
|
||||
func (clientMock) GetAuthorize(redirectURI, state, codeChallenge string, scope []gokick.Scope) (string, error) {
|
||||
return "", nil
|
||||
}
|
||||
|
||||
func (clientMock) GetToken(ctx context.Context, redirectURI, code, codeVerifier string) (gokick.TokenResponse, error) {
|
||||
return gokick.TokenResponse{}, nil
|
||||
}
|
||||
|
||||
func (clientMock) OnUserAccessTokenRefreshed(callback func(accessToken, refreshToken string)) {}
|
||||
|
||||
func (clientMock) UpdateStreamTitle(ctx context.Context, title string) (gokick.EmptyResponse, error) {
|
||||
return gokick.EmptyResponse{}, nil
|
||||
}
|
||||
|
||||
func (clientMock) UpdateStreamCategory(ctx context.Context, categoryID int) (gokick.EmptyResponse, error) {
|
||||
return gokick.EmptyResponse{}, nil
|
||||
}
|
||||
|
||||
func (clientMock) GetChannels(ctx context.Context, filter gokick.ChannelListFilter) (gokick.ChannelsResponseWrapper, error) {
|
||||
return gokick.ChannelsResponseWrapper{
|
||||
Result: []gokick.ChannelResponse{{
|
||||
BannerPicture: "BannerPicture",
|
||||
BroadcasterUserID: 1,
|
||||
Category: gokick.CategoryResponse{
|
||||
ID: 2,
|
||||
Name: "Name",
|
||||
Thumbnail: "Thumbnail",
|
||||
},
|
||||
ChannelDescription: "ChannelDescription",
|
||||
Slug: "Slug",
|
||||
Stream: gokick.StreamResponse{
|
||||
Key: "Key",
|
||||
URL: "URL",
|
||||
IsLive: true,
|
||||
IsMature: false,
|
||||
Language: "Language",
|
||||
StartTime: "StartTime",
|
||||
Thumbnail: "Thumbnail",
|
||||
ViewerCount: 3,
|
||||
},
|
||||
StreamTitle: "StreamTitle",
|
||||
}},
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (clientMock) SendChatMessage(
|
||||
ctx context.Context,
|
||||
broadcasterUserID *int,
|
||||
content string,
|
||||
replyToMessageID *string,
|
||||
messageType gokick.MessageType,
|
||||
) (gokick.ChatResponseWrapper, error) {
|
||||
return gokick.ChatResponseWrapper{
|
||||
Result: gokick.ChatResponse{
|
||||
IsSent: true,
|
||||
MessageID: "MessageID",
|
||||
},
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (clientMock) BanUser(
|
||||
ctx context.Context,
|
||||
broadcasterUserID int,
|
||||
userID int,
|
||||
duration *int,
|
||||
reason *string,
|
||||
) (gokick.BanUserResponseWrapper, error) {
|
||||
return gokick.BanUserResponseWrapper{
|
||||
Result: gokick.BanUserResponse{},
|
||||
}, nil
|
||||
}
|
@@ -23,6 +23,10 @@ import (
|
||||
"github.com/xaionaro-go/xsync"
|
||||
)
|
||||
|
||||
const (
|
||||
debugUseMockClient = false
|
||||
)
|
||||
|
||||
type ReverseEngClient interface {
|
||||
ChatClientOBSOLETE
|
||||
}
|
||||
@@ -31,7 +35,7 @@ type Kick struct {
|
||||
CloseCtx context.Context
|
||||
CloseFn context.CancelFunc
|
||||
Channel *kickcom.ChannelV1
|
||||
Client *gokick.Client
|
||||
Client *Client
|
||||
ClientOBSOLETE *kickcom.Kick
|
||||
ChatHandler *ChatHandlerOBSOLETE
|
||||
ChatHandlerLocker xsync.CtxLocker
|
||||
@@ -57,36 +61,50 @@ func New(
|
||||
return nil, fmt.Errorf("channel is not set")
|
||||
}
|
||||
|
||||
options := &gokick.ClientOptions{
|
||||
UserAccessToken: cfg.Config.UserAccessToken.Get(),
|
||||
UserRefreshToken: cfg.Config.RefreshToken.Get(),
|
||||
ClientID: cfg.Config.ClientID,
|
||||
ClientSecret: cfg.Config.ClientSecret.Get(),
|
||||
}
|
||||
client, err := gokick.NewClient(options)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("unable to initialize a client to Kick: %w", err)
|
||||
}
|
||||
|
||||
clientOld, err := kickcom.New()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("unable to initialize the old client: %w", err)
|
||||
}
|
||||
|
||||
client, err := getClient(cfg.Config)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("unable to initialize the client: %w", err)
|
||||
}
|
||||
|
||||
ctx, closeFn := context.WithCancel(ctx)
|
||||
k := &Kick{
|
||||
CloseCtx: ctx,
|
||||
CloseFn: closeFn,
|
||||
ChatHandlerLocker: make(xsync.CtxLocker, 1),
|
||||
CurrentConfig: cfg,
|
||||
Client: client,
|
||||
ClientOBSOLETE: clientOld,
|
||||
SaveCfgFn: saveCfgFn,
|
||||
}
|
||||
k.SetClient(client)
|
||||
client.OnUserAccessTokenRefreshed(k.onUserAccessTokenRefreshed)
|
||||
return k, nil
|
||||
}
|
||||
|
||||
func getClient(
|
||||
cfg PlatformSpecificConfig,
|
||||
) (Client, error) {
|
||||
if debugUseMockClient {
|
||||
return newClientMock(), nil
|
||||
}
|
||||
|
||||
client, err := newClient(&gokick.ClientOptions{
|
||||
UserAccessToken: cfg.UserAccessToken.Get(),
|
||||
UserRefreshToken: cfg.RefreshToken.Get(),
|
||||
ClientID: cfg.ClientID,
|
||||
ClientSecret: cfg.ClientSecret.Get(),
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return client, nil
|
||||
}
|
||||
|
||||
func (k *Kick) onUserAccessTokenRefreshed(
|
||||
userAccessToken string,
|
||||
refreshToken string,
|
||||
@@ -230,7 +248,7 @@ func (k *Kick) getAccessTokenNoLock(
|
||||
gokick.ScopeModerationBan,
|
||||
}
|
||||
logger.Debugf(ctx, "scopes: %v", scopes)
|
||||
authURL, err := k.getClient().GetAuthorize(
|
||||
authURL, err := k.GetClient().GetAuthorize(
|
||||
redirectURL,
|
||||
"EMPTY",
|
||||
codeChallenge,
|
||||
@@ -248,7 +266,7 @@ func (k *Kick) getAccessTokenNoLock(
|
||||
code string,
|
||||
) error {
|
||||
now := time.Now()
|
||||
token, err := k.getClient().GetToken(ctx, redirectURL, code, codeVerifier)
|
||||
token, err := k.GetClient().GetToken(ctx, redirectURL, code, codeVerifier)
|
||||
if err != nil {
|
||||
return fmt.Errorf("unable to get an access token: %w", err)
|
||||
}
|
||||
@@ -297,7 +315,7 @@ func (k *Kick) SetTitle(ctx context.Context, title string) (err error) {
|
||||
return fmt.Errorf("unable to get a prepared client: %w", err)
|
||||
}
|
||||
|
||||
_, err = k.getClient().UpdateStreamTitle(ctx, title)
|
||||
_, err = k.GetClient().UpdateStreamTitle(ctx, title)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -391,7 +409,7 @@ func (k *Kick) getStreamStatusUsingNormalClient(
|
||||
logger.Debugf(ctx, "getStreamStatusUsingNormalClient")
|
||||
defer func() { logger.Debugf(ctx, "/getStreamStatusUsingNormalClient: %v %v", _ret, _err) }()
|
||||
|
||||
resp, err := k.getClient().GetChannels(
|
||||
resp, err := k.GetClient().GetChannels(
|
||||
ctx,
|
||||
gokick.NewChannelListFilter().SetBroadcasterUserIDs([]int{int(k.Channel.UserID)}),
|
||||
)
|
||||
@@ -500,7 +518,7 @@ func (k *Kick) GetChatMessagesChan(
|
||||
func (k *Kick) SendChatMessage(ctx context.Context, message string) (_err error) {
|
||||
logger.Debugf(ctx, "SendChatMessage(ctx, '%s')", message)
|
||||
defer func() { logger.Debugf(ctx, "/SendChatMessage(ctx, '%s'): %v", message, _err) }()
|
||||
resp, err := k.Client.SendChatMessage(ctx, ptr(int(k.Channel.UserID)), message, nil, gokick.MessageTypeUser)
|
||||
resp, err := k.GetClient().SendChatMessage(ctx, ptr(int(k.Channel.UserID)), message, nil, gokick.MessageTypeUser)
|
||||
logger.Debugf(ctx, "SendChatMessage(ctx, '%s'): %#+v", message, resp)
|
||||
return err
|
||||
}
|
||||
@@ -535,7 +553,7 @@ func (k *Kick) BanUser(
|
||||
return nil
|
||||
}
|
||||
}
|
||||
resp, err := k.Client.BanUser(ctx, int(k.Channel.UserID), int(userIDInt), duration, reasonPtr)
|
||||
resp, err := k.GetClient().BanUser(ctx, int(k.Channel.UserID), int(userIDInt), duration, reasonPtr)
|
||||
logger.Debugf(ctx, "BanUser(ctx, %d, '%s', %v): %#+v", userID, reason, deadline, resp)
|
||||
return err
|
||||
}
|
||||
@@ -556,7 +574,7 @@ func (k *Kick) ApplyProfile(
|
||||
|
||||
if profile.CategoryID != nil {
|
||||
logger.Debugf(ctx, "has a CategoryID")
|
||||
_, err := k.getClient().UpdateStreamCategory(ctx, int(*profile.CategoryID))
|
||||
_, err := k.GetClient().UpdateStreamCategory(ctx, int(*profile.CategoryID))
|
||||
if err != nil {
|
||||
result = append(result, fmt.Errorf("unable to update the category: %w", err))
|
||||
}
|
||||
|
@@ -2,13 +2,12 @@ package kick
|
||||
|
||||
import (
|
||||
"github.com/go-ng/xatomic"
|
||||
"github.com/scorfly/gokick"
|
||||
)
|
||||
|
||||
func (k *Kick) getClient() *gokick.Client {
|
||||
return xatomic.LoadPointer(&k.Client)
|
||||
func (k *Kick) GetClient() Client {
|
||||
return *xatomic.LoadPointer(&k.Client)
|
||||
}
|
||||
|
||||
func (k *Kick) setClient(client *gokick.Client) {
|
||||
xatomic.StorePointer(&k.Client, client)
|
||||
func (k *Kick) SetClient(client Client) {
|
||||
xatomic.StorePointer(&k.Client, &client)
|
||||
}
|
||||
|
@@ -5,13 +5,13 @@ import (
|
||||
"fmt"
|
||||
|
||||
"github.com/facebookincubator/go-belt/tool/logger"
|
||||
"github.com/nicklaw5/helix/v2"
|
||||
"github.com/xaionaro-go/streamctl/pkg/secret"
|
||||
twitch "github.com/xaionaro-go/streamctl/pkg/streamcontrol/twitch/types"
|
||||
)
|
||||
|
||||
func NewTokenByApp(
|
||||
ctx context.Context,
|
||||
client *helix.Client,
|
||||
client twitch.Client,
|
||||
) (secret.String, error) {
|
||||
logger.Debugf(ctx, "getNewTokenByApp")
|
||||
defer func() { logger.Debugf(ctx, "/getNewTokenByApp") }()
|
||||
|
@@ -5,14 +5,14 @@ import (
|
||||
"fmt"
|
||||
|
||||
"github.com/facebookincubator/go-belt/tool/logger"
|
||||
"github.com/nicklaw5/helix/v2"
|
||||
"github.com/xaionaro-go/observability"
|
||||
"github.com/xaionaro-go/streamctl/pkg/secret"
|
||||
twitch "github.com/xaionaro-go/streamctl/pkg/streamcontrol/twitch/types"
|
||||
)
|
||||
|
||||
func NewTokenByUser(
|
||||
ctx context.Context,
|
||||
client *helix.Client,
|
||||
client twitch.Client,
|
||||
clientCode secret.String,
|
||||
) (secret.String, secret.String, error) {
|
||||
logger.Debugf(ctx, "getNewTokenByUser")
|
||||
|
@@ -16,9 +16,10 @@ import (
|
||||
"github.com/nicklaw5/helix/v2"
|
||||
"github.com/xaionaro-go/observability"
|
||||
"github.com/xaionaro-go/streamctl/pkg/oauthhandler"
|
||||
twitch "github.com/xaionaro-go/streamctl/pkg/streamcontrol/twitch/types"
|
||||
)
|
||||
|
||||
type OAuthHandler func(context.Context, oauthhandler.OAuthHandlerArgument) error
|
||||
type OAuthHandler = twitch.OAuthHandler
|
||||
|
||||
func getScopes() []string {
|
||||
scopes := map[string]struct{}{
|
||||
|
12
pkg/streamcontrol/twitch/client.go
Normal file
12
pkg/streamcontrol/twitch/client.go
Normal file
@@ -0,0 +1,12 @@
|
||||
package twitch
|
||||
|
||||
import (
|
||||
"github.com/nicklaw5/helix/v2"
|
||||
twitch "github.com/xaionaro-go/streamctl/pkg/streamcontrol/twitch/types"
|
||||
)
|
||||
|
||||
type client = twitch.Client
|
||||
|
||||
type clientNicklaw5 struct {
|
||||
*helix.Client
|
||||
}
|
155
pkg/streamcontrol/twitch/client_mock.go
Normal file
155
pkg/streamcontrol/twitch/client_mock.go
Normal file
@@ -0,0 +1,155 @@
|
||||
package twitch
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/nicklaw5/helix/v2"
|
||||
)
|
||||
|
||||
type clientMock struct{}
|
||||
|
||||
func newClientMock() *clientMock {
|
||||
return &clientMock{}
|
||||
}
|
||||
|
||||
var _ client = (*clientMock)(nil)
|
||||
|
||||
func (c *clientMock) GetAppAccessToken() string {
|
||||
return ""
|
||||
}
|
||||
func (c *clientMock) GetUserAccessToken() string {
|
||||
return ""
|
||||
}
|
||||
func (c *clientMock) GetRefreshToken() string {
|
||||
return ""
|
||||
}
|
||||
func (c *clientMock) SetAppAccessToken(accessToken string) {}
|
||||
|
||||
func (c *clientMock) SetUserAccessToken(accessToken string) {}
|
||||
|
||||
func (c *clientMock) SetRefreshToken(refreshToken string) {}
|
||||
|
||||
func (c *clientMock) OnUserAccessTokenRefreshed(f func(newAccessToken, newRefreshToken string)) {}
|
||||
|
||||
func (c *clientMock) GetChannelInformation(params *helix.GetChannelInformationParams) (*helix.GetChannelInformationResponse, error) {
|
||||
return &helix.GetChannelInformationResponse{
|
||||
Data: helix.ManyChannelInformation{
|
||||
Channels: []helix.ChannelInformation{{
|
||||
BroadcasterID: "BroadcasterID",
|
||||
BroadcasterName: "BroadcasterName",
|
||||
BroadcasterLanguage: "BroadcasterLanguage",
|
||||
GameID: "GameID",
|
||||
GameName: "GameName",
|
||||
Title: "Title",
|
||||
Delay: 1,
|
||||
Tags: []string{"Tag"},
|
||||
}},
|
||||
},
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (c *clientMock) RequestUserAccessToken(code string) (*helix.UserAccessTokenResponse, error) {
|
||||
return &helix.UserAccessTokenResponse{}, nil
|
||||
}
|
||||
|
||||
func (c *clientMock) RequestAppAccessToken(scopes []string) (*helix.AppAccessTokenResponse, error) {
|
||||
return &helix.AppAccessTokenResponse{}, nil
|
||||
}
|
||||
|
||||
func (c *clientMock) EditChannelInformation(params *helix.EditChannelInformationParams) (*helix.EditChannelInformationResponse, error) {
|
||||
return &helix.EditChannelInformationResponse{}, nil
|
||||
}
|
||||
|
||||
func (c *clientMock) GetGames(params *helix.GamesParams) (*helix.GamesResponse, error) {
|
||||
return &helix.GamesResponse{
|
||||
Data: helix.ManyGames{
|
||||
Games: []helix.Game{{
|
||||
ID: "ID",
|
||||
Name: "Name",
|
||||
BoxArtURL: "BoxArtURL",
|
||||
}},
|
||||
},
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (c *clientMock) GetStreams(params *helix.StreamsParams) (*helix.StreamsResponse, error) {
|
||||
return &helix.StreamsResponse{
|
||||
Data: helix.ManyStreams{
|
||||
Streams: []helix.Stream{{
|
||||
ID: "ID",
|
||||
UserID: "UserID",
|
||||
UserLogin: "UserLogin",
|
||||
UserName: "UserName",
|
||||
GameID: "GameID",
|
||||
GameName: "GameName",
|
||||
TagIDs: []string{"TagID"},
|
||||
Tags: []string{"Tag"},
|
||||
IsMature: false,
|
||||
Type: "Type",
|
||||
Title: "Title",
|
||||
ViewerCount: 1,
|
||||
StartedAt: time.Now(),
|
||||
Language: "Language",
|
||||
ThumbnailURL: "ThumbnailURL",
|
||||
}},
|
||||
},
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (c *clientMock) GetTopGames(params *helix.TopGamesParams) (*helix.TopGamesResponse, error) {
|
||||
return &helix.TopGamesResponse{
|
||||
Data: helix.ManyGamesWithPagination{
|
||||
ManyGames: helix.ManyGames{
|
||||
Games: []helix.Game{{
|
||||
ID: "ID",
|
||||
Name: "Name",
|
||||
BoxArtURL: "BoxArtURL",
|
||||
}},
|
||||
},
|
||||
},
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (c *clientMock) SendChatMessage(params *helix.SendChatMessageParams) (*helix.ChatMessageResponse, error) {
|
||||
return &helix.ChatMessageResponse{}, nil
|
||||
}
|
||||
|
||||
func (c *clientMock) DeleteChatMessage(params *helix.DeleteChatMessageParams) (*helix.DeleteChatMessageResponse, error) {
|
||||
return &helix.DeleteChatMessageResponse{}, nil
|
||||
}
|
||||
|
||||
func (c *clientMock) BanUser(params *helix.BanUserParams) (*helix.BanUserResponse, error) {
|
||||
return &helix.BanUserResponse{}, nil
|
||||
}
|
||||
|
||||
func (c *clientMock) StartRaid(params *helix.StartRaidParams) (*helix.RaidResponse, error) {
|
||||
return &helix.RaidResponse{}, nil
|
||||
}
|
||||
|
||||
func (c *clientMock) SendShoutout(params *helix.SendShoutoutParams) (*helix.SendShoutoutResponse, error) {
|
||||
return &helix.SendShoutoutResponse{}, nil
|
||||
}
|
||||
|
||||
func (c *clientMock) CreateEventSubSubscription(payload *helix.EventSubSubscription) (*helix.EventSubSubscriptionsResponse, error) {
|
||||
return &helix.EventSubSubscriptionsResponse{}, nil
|
||||
}
|
||||
|
||||
func (c *clientMock) GetUsers(params *helix.UsersParams) (*helix.UsersResponse, error) {
|
||||
return &helix.UsersResponse{
|
||||
Data: helix.ManyUsers{
|
||||
Users: []helix.User{{
|
||||
ID: "ID",
|
||||
Login: "Login",
|
||||
DisplayName: "DisplayName",
|
||||
Type: "Type",
|
||||
BroadcasterType: "BroadcasterType",
|
||||
Description: "Description",
|
||||
ProfileImageURL: "ProfileImageURL",
|
||||
OfflineImageURL: "OfflineImageURL",
|
||||
ViewCount: 1,
|
||||
Email: "Email",
|
||||
CreatedAt: helix.Time{Time: time.Now()},
|
||||
}},
|
||||
},
|
||||
}, nil
|
||||
}
|
@@ -28,7 +28,7 @@ type Twitch struct {
|
||||
closeFn context.CancelFunc
|
||||
chatHandlerSub *ChatHandlerSub
|
||||
chatHandlerIRC *ChatHandlerIRC
|
||||
client *helix.Client
|
||||
client client
|
||||
config Config
|
||||
broadcasterID string
|
||||
lazyInitOnce sync.Once
|
||||
@@ -39,7 +39,10 @@ type Twitch struct {
|
||||
clientSecret secret.String
|
||||
}
|
||||
|
||||
const twitchDebug = false
|
||||
const (
|
||||
twitchDebug = false
|
||||
debugUseMockClient = false
|
||||
)
|
||||
|
||||
var _ streamcontrol.StreamController[StreamProfile] = (*Twitch)(nil)
|
||||
|
||||
@@ -141,7 +144,7 @@ func New(
|
||||
|
||||
func GetUserID(
|
||||
_ context.Context,
|
||||
client *helix.Client,
|
||||
client client,
|
||||
login string,
|
||||
) (string, error) {
|
||||
resp, err := client.GetUsers(&helix.UsersParams{
|
||||
@@ -613,10 +616,13 @@ func (t *Twitch) getNewTokenByApp(
|
||||
func (t *Twitch) getClient(
|
||||
ctx context.Context,
|
||||
oauthListenPort uint16,
|
||||
) (*helix.Client, error) {
|
||||
) (client, error) {
|
||||
logger.Debugf(ctx, "getClient(ctx, %#+v, %v)", t.config, oauthListenPort)
|
||||
defer func() { logger.Debugf(ctx, "/getClient") }()
|
||||
|
||||
if debugUseMockClient {
|
||||
return newClientMock(), nil
|
||||
}
|
||||
options := &helix.Options{
|
||||
ClientID: t.clientID,
|
||||
ClientSecret: t.clientSecret.Get(),
|
||||
|
29
pkg/streamcontrol/twitch/types/client.go
Normal file
29
pkg/streamcontrol/twitch/types/client.go
Normal file
@@ -0,0 +1,29 @@
|
||||
package twitch
|
||||
|
||||
import (
|
||||
"github.com/nicklaw5/helix/v2"
|
||||
)
|
||||
|
||||
type Client interface {
|
||||
GetAppAccessToken() string
|
||||
GetUserAccessToken() string
|
||||
GetRefreshToken() string
|
||||
SetAppAccessToken(accessToken string)
|
||||
SetUserAccessToken(accessToken string)
|
||||
SetRefreshToken(refreshToken string)
|
||||
OnUserAccessTokenRefreshed(f func(newAccessToken, newRefreshToken string))
|
||||
GetChannelInformation(params *helix.GetChannelInformationParams) (*helix.GetChannelInformationResponse, error)
|
||||
RequestUserAccessToken(code string) (*helix.UserAccessTokenResponse, error)
|
||||
RequestAppAccessToken(scopes []string) (*helix.AppAccessTokenResponse, error)
|
||||
EditChannelInformation(params *helix.EditChannelInformationParams) (*helix.EditChannelInformationResponse, error)
|
||||
GetGames(params *helix.GamesParams) (*helix.GamesResponse, error)
|
||||
GetStreams(params *helix.StreamsParams) (*helix.StreamsResponse, error)
|
||||
GetTopGames(params *helix.TopGamesParams) (*helix.TopGamesResponse, error)
|
||||
SendChatMessage(params *helix.SendChatMessageParams) (*helix.ChatMessageResponse, error)
|
||||
DeleteChatMessage(params *helix.DeleteChatMessageParams) (*helix.DeleteChatMessageResponse, error)
|
||||
BanUser(params *helix.BanUserParams) (*helix.BanUserResponse, error)
|
||||
StartRaid(params *helix.StartRaidParams) (*helix.RaidResponse, error)
|
||||
SendShoutout(params *helix.SendShoutoutParams) (*helix.SendShoutoutResponse, error)
|
||||
CreateEventSubSubscription(payload *helix.EventSubSubscription) (*helix.EventSubSubscriptionsResponse, error)
|
||||
GetUsers(params *helix.UsersParams) (*helix.UsersResponse, error)
|
||||
}
|
@@ -4,13 +4,10 @@ import (
|
||||
"github.com/xaionaro-go/streamctl/pkg/buildvars"
|
||||
"github.com/xaionaro-go/streamctl/pkg/secret"
|
||||
streamctl "github.com/xaionaro-go/streamctl/pkg/streamcontrol"
|
||||
"github.com/xaionaro-go/streamctl/pkg/streamcontrol/twitch/auth"
|
||||
)
|
||||
|
||||
const ID = streamctl.PlatformName("twitch")
|
||||
|
||||
type OAuthHandler = auth.OAuthHandler
|
||||
|
||||
type PlatformSpecificConfig struct {
|
||||
Channel string
|
||||
ClientID string
|
||||
|
9
pkg/streamcontrol/twitch/types/oauth_handler.go
Normal file
9
pkg/streamcontrol/twitch/types/oauth_handler.go
Normal file
@@ -0,0 +1,9 @@
|
||||
package twitch
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/xaionaro-go/streamctl/pkg/oauthhandler"
|
||||
)
|
||||
|
||||
type OAuthHandler func(context.Context, oauthhandler.OAuthHandlerArgument) error
|
@@ -17,20 +17,20 @@ import (
|
||||
type ChatListener struct {
|
||||
videoID string
|
||||
liveChatID string
|
||||
client YouTubeChatClient
|
||||
client ChatClient
|
||||
|
||||
wg sync.WaitGroup
|
||||
cancelFunc context.CancelFunc
|
||||
messagesOutChan chan streamcontrol.ChatMessage
|
||||
}
|
||||
|
||||
type YouTubeChatClient interface {
|
||||
type ChatClient interface {
|
||||
GetLiveChatMessages(ctx context.Context, chatID string, pageToken string, parts []string) (*youtube.LiveChatMessageListResponse, error)
|
||||
}
|
||||
|
||||
func NewChatListener(
|
||||
ctx context.Context,
|
||||
ytClient YouTubeChatClient,
|
||||
ytClient ChatClient,
|
||||
videoID string,
|
||||
liveChatID string,
|
||||
) (*ChatListener, error) {
|
||||
|
@@ -36,8 +36,8 @@ func (t BroadcastType) String() string {
|
||||
return fmt.Sprintf("unexpected_value_%d", int(t))
|
||||
}
|
||||
|
||||
type YouTubeClient interface {
|
||||
YouTubeChatClient
|
||||
type client interface {
|
||||
ChatClient
|
||||
Ping(context.Context) error
|
||||
GetBroadcasts(ctx context.Context, t BroadcastType, ids []string, parts []string, pageToken string) (*youtube.LiveBroadcastListResponse, error)
|
||||
UpdateBroadcast(context.Context, *youtube.LiveBroadcast, []string) error
|
||||
@@ -65,7 +65,7 @@ const (
|
||||
EventTypeUpcoming = EventType("upcoming")
|
||||
)
|
||||
|
||||
type YouTubeClientV3 struct {
|
||||
type clientV3 struct {
|
||||
*youtube.Service
|
||||
RequestWrapper func(context.Context, func(context.Context) error) error
|
||||
}
|
||||
@@ -106,24 +106,24 @@ func wrapRequestR[T any](
|
||||
return
|
||||
}
|
||||
|
||||
var _ YouTubeClient = (*YouTubeClientV3)(nil)
|
||||
var _ client = (*clientV3)(nil)
|
||||
|
||||
func NewYouTubeClientV3(
|
||||
func newClientV3(
|
||||
ctx context.Context,
|
||||
requestWrapper func(context.Context, func(context.Context) error) error,
|
||||
opts ...option.ClientOption,
|
||||
) (*YouTubeClientV3, error) {
|
||||
) (*clientV3, error) {
|
||||
srv, err := youtube.NewService(ctx, opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &YouTubeClientV3{
|
||||
return &clientV3{
|
||||
Service: srv,
|
||||
RequestWrapper: requestWrapper,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (c *YouTubeClientV3) Ping(
|
||||
func (c *clientV3) Ping(
|
||||
ctx context.Context,
|
||||
) (_err error) {
|
||||
logger.Tracef(ctx, "Ping")
|
||||
@@ -141,7 +141,7 @@ func (c *YouTubeClientV3) Ping(
|
||||
return err
|
||||
}
|
||||
|
||||
func (c *YouTubeClientV3) GetBroadcasts(
|
||||
func (c *clientV3) GetBroadcasts(
|
||||
ctx context.Context,
|
||||
t BroadcastType,
|
||||
ids []string,
|
||||
@@ -171,7 +171,7 @@ func (c *YouTubeClientV3) GetBroadcasts(
|
||||
return wrapRequestR(ctx, c.RequestWrapper, r.Do, googleapi.QueryParameter("order", "date"))
|
||||
}
|
||||
|
||||
func (c *YouTubeClientV3) UpdateBroadcast(
|
||||
func (c *clientV3) UpdateBroadcast(
|
||||
ctx context.Context,
|
||||
broadcast *youtube.LiveBroadcast,
|
||||
parts []string,
|
||||
@@ -182,7 +182,7 @@ func (c *YouTubeClientV3) UpdateBroadcast(
|
||||
return wrapRequestS(ctx, c.RequestWrapper, do)
|
||||
}
|
||||
|
||||
func (c *YouTubeClientV3) InsertBroadcast(
|
||||
func (c *clientV3) InsertBroadcast(
|
||||
ctx context.Context,
|
||||
broadcast *youtube.LiveBroadcast,
|
||||
parts []string,
|
||||
@@ -192,7 +192,7 @@ func (c *YouTubeClientV3) InsertBroadcast(
|
||||
return c.Service.LiveBroadcasts.Insert(parts, broadcast).Context(ctx).Do()
|
||||
}
|
||||
|
||||
func (c *YouTubeClientV3) DeleteBroadcast(
|
||||
func (c *clientV3) DeleteBroadcast(
|
||||
ctx context.Context,
|
||||
broadcastID string,
|
||||
) (_err error) {
|
||||
@@ -202,7 +202,7 @@ func (c *YouTubeClientV3) DeleteBroadcast(
|
||||
return wrapRequest(ctx, c.RequestWrapper, do)
|
||||
}
|
||||
|
||||
func (c *YouTubeClientV3) InsertCuepoint(
|
||||
func (c *clientV3) InsertCuepoint(
|
||||
ctx context.Context,
|
||||
p *youtube.Cuepoint,
|
||||
) (_err error) {
|
||||
@@ -212,7 +212,7 @@ func (c *YouTubeClientV3) InsertCuepoint(
|
||||
return wrapRequestS(ctx, c.RequestWrapper, do)
|
||||
}
|
||||
|
||||
func (c *YouTubeClientV3) GetVideos(
|
||||
func (c *clientV3) GetVideos(
|
||||
ctx context.Context,
|
||||
broadcastIDs []string,
|
||||
parts []string,
|
||||
@@ -223,7 +223,7 @@ func (c *YouTubeClientV3) GetVideos(
|
||||
return wrapRequestR(ctx, c.RequestWrapper, do)
|
||||
}
|
||||
|
||||
func (c *YouTubeClientV3) UpdateVideo(
|
||||
func (c *clientV3) UpdateVideo(
|
||||
ctx context.Context,
|
||||
video *youtube.Video,
|
||||
parts []string,
|
||||
@@ -234,7 +234,7 @@ func (c *YouTubeClientV3) UpdateVideo(
|
||||
return wrapRequestS(ctx, c.RequestWrapper, do)
|
||||
}
|
||||
|
||||
func (c *YouTubeClientV3) GetPlaylists(
|
||||
func (c *clientV3) GetPlaylists(
|
||||
ctx context.Context,
|
||||
parts []string,
|
||||
) (_ret *youtube.PlaylistListResponse, _err error) {
|
||||
@@ -244,7 +244,7 @@ func (c *YouTubeClientV3) GetPlaylists(
|
||||
return wrapRequestR(ctx, c.RequestWrapper, do)
|
||||
}
|
||||
|
||||
func (c *YouTubeClientV3) GetPlaylistItems(
|
||||
func (c *clientV3) GetPlaylistItems(
|
||||
ctx context.Context,
|
||||
playlistID string,
|
||||
videoID string,
|
||||
@@ -256,7 +256,7 @@ func (c *YouTubeClientV3) GetPlaylistItems(
|
||||
return wrapRequestR(ctx, c.RequestWrapper, do)
|
||||
}
|
||||
|
||||
func (c *YouTubeClientV3) InsertPlaylistItem(
|
||||
func (c *clientV3) InsertPlaylistItem(
|
||||
ctx context.Context,
|
||||
item *youtube.PlaylistItem,
|
||||
parts []string,
|
||||
@@ -267,7 +267,7 @@ func (c *YouTubeClientV3) InsertPlaylistItem(
|
||||
return wrapRequestS(ctx, c.RequestWrapper, do)
|
||||
}
|
||||
|
||||
func (c *YouTubeClientV3) SetThumbnail(
|
||||
func (c *clientV3) SetThumbnail(
|
||||
ctx context.Context,
|
||||
broadcastID string,
|
||||
thumbnail io.Reader,
|
||||
@@ -278,7 +278,7 @@ func (c *YouTubeClientV3) SetThumbnail(
|
||||
return wrapRequestS(ctx, c.RequestWrapper, do)
|
||||
}
|
||||
|
||||
func (c *YouTubeClientV3) GetStreams(
|
||||
func (c *clientV3) GetStreams(
|
||||
ctx context.Context,
|
||||
parts []string,
|
||||
) (_ret *youtube.LiveStreamListResponse, _err error) {
|
||||
@@ -288,7 +288,7 @@ func (c *YouTubeClientV3) GetStreams(
|
||||
return wrapRequestR(ctx, c.RequestWrapper, do)
|
||||
}
|
||||
|
||||
func (c *YouTubeClientV3) InsertCommentThread(
|
||||
func (c *clientV3) InsertCommentThread(
|
||||
ctx context.Context,
|
||||
t *youtube.CommentThread,
|
||||
parts []string,
|
||||
@@ -299,7 +299,7 @@ func (c *YouTubeClientV3) InsertCommentThread(
|
||||
return wrapRequestS(ctx, c.RequestWrapper, do)
|
||||
}
|
||||
|
||||
func (c *YouTubeClientV3) ListChatMessages(
|
||||
func (c *clientV3) ListChatMessages(
|
||||
ctx context.Context,
|
||||
chatID string,
|
||||
parts []string,
|
||||
@@ -310,7 +310,7 @@ func (c *YouTubeClientV3) ListChatMessages(
|
||||
return wrapRequestR(ctx, c.RequestWrapper, do)
|
||||
}
|
||||
|
||||
func (c *YouTubeClientV3) DeleteChatMessage(
|
||||
func (c *clientV3) DeleteChatMessage(
|
||||
ctx context.Context,
|
||||
messageID string,
|
||||
) (_err error) {
|
||||
@@ -320,7 +320,7 @@ func (c *YouTubeClientV3) DeleteChatMessage(
|
||||
return wrapRequest(ctx, c.RequestWrapper, do)
|
||||
}
|
||||
|
||||
func (c *YouTubeClientV3) GetLiveChatMessages(
|
||||
func (c *clientV3) GetLiveChatMessages(
|
||||
ctx context.Context,
|
||||
chatID string,
|
||||
pageToken string,
|
||||
@@ -335,7 +335,7 @@ func (c *YouTubeClientV3) GetLiveChatMessages(
|
||||
return q.Do()
|
||||
}
|
||||
|
||||
func (c *YouTubeClientV3) Search(
|
||||
func (c *clientV3) Search(
|
||||
ctx context.Context,
|
||||
chanID string,
|
||||
eventType EventType,
|
@@ -26,17 +26,17 @@ func init() {
|
||||
}
|
||||
|
||||
// see also: https://developers.google.com/youtube/v3/determine_quota_cost
|
||||
type YouTubeClientCalcPoints struct {
|
||||
Client YouTubeClient
|
||||
type ClientCalcPoints struct {
|
||||
Client client
|
||||
UsedPoints atomic.Uint64
|
||||
CheckMutex sync.Mutex
|
||||
PreviousCheckAt time.Time
|
||||
}
|
||||
|
||||
var _ YouTubeClient = (*YouTubeClientCalcPoints)(nil)
|
||||
var _ client = (*ClientCalcPoints)(nil)
|
||||
|
||||
func NewYouTubeClientCalcPoints(client YouTubeClient) *YouTubeClientCalcPoints {
|
||||
return &YouTubeClientCalcPoints{
|
||||
func NewYouTubeClientCalcPoints(client client) *ClientCalcPoints {
|
||||
return &ClientCalcPoints{
|
||||
Client: client,
|
||||
}
|
||||
}
|
||||
@@ -45,7 +45,7 @@ func getQuotaCutoffDate(t time.Time) string {
|
||||
return t.In(tzLosAngeles).Format("2006-01-02")
|
||||
}
|
||||
|
||||
func (c *YouTubeClientCalcPoints) addUsedPointsIfNoError(
|
||||
func (c *ClientCalcPoints) addUsedPointsIfNoError(
|
||||
ctx context.Context,
|
||||
points uint,
|
||||
err error,
|
||||
@@ -71,12 +71,12 @@ func (c *YouTubeClientCalcPoints) addUsedPointsIfNoError(
|
||||
}
|
||||
}
|
||||
|
||||
func (c *YouTubeClientCalcPoints) Ping(ctx context.Context) (_err error) {
|
||||
func (c *ClientCalcPoints) Ping(ctx context.Context) (_err error) {
|
||||
defer func() { c.addUsedPointsIfNoError(ctx, 1, _err) }()
|
||||
return c.Client.Ping(ctx)
|
||||
}
|
||||
|
||||
func (c *YouTubeClientCalcPoints) GetBroadcasts(
|
||||
func (c *ClientCalcPoints) GetBroadcasts(
|
||||
ctx context.Context,
|
||||
t BroadcastType,
|
||||
ids []string,
|
||||
@@ -87,7 +87,7 @@ func (c *YouTubeClientCalcPoints) GetBroadcasts(
|
||||
return c.Client.GetBroadcasts(ctx, t, ids, parts, pageToken)
|
||||
}
|
||||
|
||||
func (c *YouTubeClientCalcPoints) UpdateBroadcast(
|
||||
func (c *ClientCalcPoints) UpdateBroadcast(
|
||||
ctx context.Context,
|
||||
broadcast *youtube.LiveBroadcast,
|
||||
parts []string,
|
||||
@@ -96,7 +96,7 @@ func (c *YouTubeClientCalcPoints) UpdateBroadcast(
|
||||
return c.Client.UpdateBroadcast(ctx, broadcast, parts)
|
||||
}
|
||||
|
||||
func (c *YouTubeClientCalcPoints) InsertBroadcast(
|
||||
func (c *ClientCalcPoints) InsertBroadcast(
|
||||
ctx context.Context,
|
||||
broadcast *youtube.LiveBroadcast,
|
||||
parts []string,
|
||||
@@ -105,7 +105,7 @@ func (c *YouTubeClientCalcPoints) InsertBroadcast(
|
||||
return c.Client.InsertBroadcast(ctx, broadcast, parts)
|
||||
}
|
||||
|
||||
func (c *YouTubeClientCalcPoints) DeleteBroadcast(
|
||||
func (c *ClientCalcPoints) DeleteBroadcast(
|
||||
ctx context.Context,
|
||||
broadcastID string,
|
||||
) (_err error) {
|
||||
@@ -113,7 +113,7 @@ func (c *YouTubeClientCalcPoints) DeleteBroadcast(
|
||||
return c.Client.DeleteBroadcast(ctx, broadcastID)
|
||||
}
|
||||
|
||||
func (c *YouTubeClientCalcPoints) GetStreams(
|
||||
func (c *ClientCalcPoints) GetStreams(
|
||||
ctx context.Context,
|
||||
parts []string,
|
||||
) (_ret *youtube.LiveStreamListResponse, _err error) {
|
||||
@@ -121,7 +121,7 @@ func (c *YouTubeClientCalcPoints) GetStreams(
|
||||
return c.Client.GetStreams(ctx, parts)
|
||||
}
|
||||
|
||||
func (c *YouTubeClientCalcPoints) GetVideos(
|
||||
func (c *ClientCalcPoints) GetVideos(
|
||||
ctx context.Context,
|
||||
broadcastIDs []string,
|
||||
parts []string,
|
||||
@@ -130,7 +130,7 @@ func (c *YouTubeClientCalcPoints) GetVideos(
|
||||
return c.Client.GetVideos(ctx, broadcastIDs, parts)
|
||||
}
|
||||
|
||||
func (c *YouTubeClientCalcPoints) UpdateVideo(
|
||||
func (c *ClientCalcPoints) UpdateVideo(
|
||||
ctx context.Context,
|
||||
video *youtube.Video,
|
||||
parts []string,
|
||||
@@ -139,7 +139,7 @@ func (c *YouTubeClientCalcPoints) UpdateVideo(
|
||||
return c.Client.UpdateVideo(ctx, video, parts)
|
||||
}
|
||||
|
||||
func (c *YouTubeClientCalcPoints) InsertCuepoint(
|
||||
func (c *ClientCalcPoints) InsertCuepoint(
|
||||
ctx context.Context,
|
||||
cuepoint *youtube.Cuepoint,
|
||||
) (_err error) {
|
||||
@@ -147,7 +147,7 @@ func (c *YouTubeClientCalcPoints) InsertCuepoint(
|
||||
return c.Client.InsertCuepoint(ctx, cuepoint)
|
||||
}
|
||||
|
||||
func (c *YouTubeClientCalcPoints) GetPlaylists(
|
||||
func (c *ClientCalcPoints) GetPlaylists(
|
||||
ctx context.Context,
|
||||
playlistParts []string,
|
||||
) (_ret *youtube.PlaylistListResponse, _err error) {
|
||||
@@ -155,7 +155,7 @@ func (c *YouTubeClientCalcPoints) GetPlaylists(
|
||||
return c.Client.GetPlaylists(ctx, playlistParts)
|
||||
}
|
||||
|
||||
func (c *YouTubeClientCalcPoints) GetPlaylistItems(
|
||||
func (c *ClientCalcPoints) GetPlaylistItems(
|
||||
ctx context.Context,
|
||||
playlistID string,
|
||||
videoID string,
|
||||
@@ -165,7 +165,7 @@ func (c *YouTubeClientCalcPoints) GetPlaylistItems(
|
||||
return c.Client.GetPlaylistItems(ctx, playlistID, videoID, parts)
|
||||
}
|
||||
|
||||
func (c *YouTubeClientCalcPoints) InsertPlaylistItem(
|
||||
func (c *ClientCalcPoints) InsertPlaylistItem(
|
||||
ctx context.Context,
|
||||
item *youtube.PlaylistItem,
|
||||
parts []string,
|
||||
@@ -174,7 +174,7 @@ func (c *YouTubeClientCalcPoints) InsertPlaylistItem(
|
||||
return c.Client.InsertPlaylistItem(ctx, item, parts)
|
||||
}
|
||||
|
||||
func (c *YouTubeClientCalcPoints) SetThumbnail(
|
||||
func (c *ClientCalcPoints) SetThumbnail(
|
||||
ctx context.Context,
|
||||
broadcastID string,
|
||||
thumbnail io.Reader,
|
||||
@@ -183,7 +183,7 @@ func (c *YouTubeClientCalcPoints) SetThumbnail(
|
||||
return c.Client.SetThumbnail(ctx, broadcastID, thumbnail)
|
||||
}
|
||||
|
||||
func (c *YouTubeClientCalcPoints) InsertCommentThread(
|
||||
func (c *ClientCalcPoints) InsertCommentThread(
|
||||
ctx context.Context,
|
||||
t *youtube.CommentThread,
|
||||
parts []string,
|
||||
@@ -192,7 +192,7 @@ func (c *YouTubeClientCalcPoints) InsertCommentThread(
|
||||
return c.Client.InsertCommentThread(ctx, t, parts)
|
||||
}
|
||||
|
||||
func (c *YouTubeClientCalcPoints) ListChatMessages(
|
||||
func (c *ClientCalcPoints) ListChatMessages(
|
||||
ctx context.Context,
|
||||
chatID string,
|
||||
parts []string,
|
||||
@@ -201,7 +201,7 @@ func (c *YouTubeClientCalcPoints) ListChatMessages(
|
||||
return c.Client.ListChatMessages(ctx, chatID, parts)
|
||||
}
|
||||
|
||||
func (c *YouTubeClientCalcPoints) DeleteChatMessage(
|
||||
func (c *ClientCalcPoints) DeleteChatMessage(
|
||||
ctx context.Context,
|
||||
messageID string,
|
||||
) (_err error) {
|
||||
@@ -209,7 +209,7 @@ func (c *YouTubeClientCalcPoints) DeleteChatMessage(
|
||||
return c.Client.DeleteChatMessage(ctx, messageID)
|
||||
}
|
||||
|
||||
func (c *YouTubeClientCalcPoints) GetLiveChatMessages(
|
||||
func (c *ClientCalcPoints) GetLiveChatMessages(
|
||||
ctx context.Context,
|
||||
chatID string,
|
||||
pageToken string,
|
||||
@@ -219,7 +219,7 @@ func (c *YouTubeClientCalcPoints) GetLiveChatMessages(
|
||||
return c.Client.GetLiveChatMessages(ctx, chatID, pageToken, parts)
|
||||
}
|
||||
|
||||
func (c *YouTubeClientCalcPoints) Search(
|
||||
func (c *ClientCalcPoints) Search(
|
||||
ctx context.Context,
|
||||
chanID string,
|
||||
eventType EventType,
|
@@ -9,21 +9,21 @@ import (
|
||||
"google.golang.org/api/youtube/v3"
|
||||
)
|
||||
|
||||
type YouTubeClientMock struct{}
|
||||
type clientMock struct{}
|
||||
|
||||
var _ YouTubeClient = (*YouTubeClientMock)(nil)
|
||||
var _ client = (*clientMock)(nil)
|
||||
|
||||
func NewYouTubeClientMock() *YouTubeClientMock {
|
||||
return &YouTubeClientMock{}
|
||||
func newClientMock() *clientMock {
|
||||
return &clientMock{}
|
||||
}
|
||||
|
||||
func (c *YouTubeClientMock) Ping(ctx context.Context) (_err error) {
|
||||
func (c *clientMock) Ping(ctx context.Context) (_err error) {
|
||||
logger.Tracef(ctx, "Ping")
|
||||
defer func() { logger.Tracef(ctx, "/Ping: %v", _err) }()
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *YouTubeClientMock) GetBroadcasts(
|
||||
func (c *clientMock) GetBroadcasts(
|
||||
ctx context.Context,
|
||||
t BroadcastType,
|
||||
ids []string,
|
||||
@@ -39,7 +39,7 @@ func (c *YouTubeClientMock) GetBroadcasts(
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (c *YouTubeClientMock) UpdateBroadcast(
|
||||
func (c *clientMock) UpdateBroadcast(
|
||||
ctx context.Context,
|
||||
broadcast *youtube.LiveBroadcast,
|
||||
parts []string,
|
||||
@@ -49,7 +49,7 @@ func (c *YouTubeClientMock) UpdateBroadcast(
|
||||
return fmt.Errorf("not implemented")
|
||||
}
|
||||
|
||||
func (c *YouTubeClientMock) InsertBroadcast(
|
||||
func (c *clientMock) InsertBroadcast(
|
||||
ctx context.Context,
|
||||
broadcast *youtube.LiveBroadcast,
|
||||
parts []string,
|
||||
@@ -59,7 +59,7 @@ func (c *YouTubeClientMock) InsertBroadcast(
|
||||
return nil, fmt.Errorf("not implemented")
|
||||
}
|
||||
|
||||
func (c *YouTubeClientMock) DeleteBroadcast(
|
||||
func (c *clientMock) DeleteBroadcast(
|
||||
ctx context.Context,
|
||||
broadcastID string,
|
||||
) (_err error) {
|
||||
@@ -68,7 +68,7 @@ func (c *YouTubeClientMock) DeleteBroadcast(
|
||||
return fmt.Errorf("not implemented")
|
||||
}
|
||||
|
||||
func (c *YouTubeClientMock) GetStreams(
|
||||
func (c *clientMock) GetStreams(
|
||||
ctx context.Context,
|
||||
parts []string,
|
||||
) (_ret *youtube.LiveStreamListResponse, _err error) {
|
||||
@@ -80,7 +80,7 @@ func (c *YouTubeClientMock) GetStreams(
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (c *YouTubeClientMock) GetVideos(
|
||||
func (c *clientMock) GetVideos(
|
||||
ctx context.Context,
|
||||
broadcastIDs []string,
|
||||
parts []string,
|
||||
@@ -90,7 +90,7 @@ func (c *YouTubeClientMock) GetVideos(
|
||||
return nil, fmt.Errorf("not implemented")
|
||||
}
|
||||
|
||||
func (c *YouTubeClientMock) UpdateVideo(
|
||||
func (c *clientMock) UpdateVideo(
|
||||
ctx context.Context,
|
||||
video *youtube.Video,
|
||||
parts []string,
|
||||
@@ -100,7 +100,7 @@ func (c *YouTubeClientMock) UpdateVideo(
|
||||
return fmt.Errorf("not implemented")
|
||||
}
|
||||
|
||||
func (c *YouTubeClientMock) InsertCuepoint(
|
||||
func (c *clientMock) InsertCuepoint(
|
||||
ctx context.Context,
|
||||
cuepoint *youtube.Cuepoint,
|
||||
) (_err error) {
|
||||
@@ -109,7 +109,7 @@ func (c *YouTubeClientMock) InsertCuepoint(
|
||||
return fmt.Errorf("not implemented")
|
||||
}
|
||||
|
||||
func (c *YouTubeClientMock) GetPlaylists(
|
||||
func (c *clientMock) GetPlaylists(
|
||||
ctx context.Context,
|
||||
playlistParts []string,
|
||||
) (_ret *youtube.PlaylistListResponse, _err error) {
|
||||
@@ -118,7 +118,7 @@ func (c *YouTubeClientMock) GetPlaylists(
|
||||
return nil, fmt.Errorf("not implemented")
|
||||
}
|
||||
|
||||
func (c *YouTubeClientMock) GetPlaylistItems(
|
||||
func (c *clientMock) GetPlaylistItems(
|
||||
ctx context.Context,
|
||||
playlistID string,
|
||||
videoID string,
|
||||
@@ -129,7 +129,7 @@ func (c *YouTubeClientMock) GetPlaylistItems(
|
||||
return nil, fmt.Errorf("not implemented")
|
||||
}
|
||||
|
||||
func (c *YouTubeClientMock) InsertPlaylistItem(
|
||||
func (c *clientMock) InsertPlaylistItem(
|
||||
ctx context.Context,
|
||||
item *youtube.PlaylistItem,
|
||||
parts []string,
|
||||
@@ -139,7 +139,7 @@ func (c *YouTubeClientMock) InsertPlaylistItem(
|
||||
return fmt.Errorf("not implemented")
|
||||
}
|
||||
|
||||
func (c *YouTubeClientMock) SetThumbnail(
|
||||
func (c *clientMock) SetThumbnail(
|
||||
ctx context.Context,
|
||||
broadcastID string,
|
||||
thumbnail io.Reader,
|
||||
@@ -149,7 +149,7 @@ func (c *YouTubeClientMock) SetThumbnail(
|
||||
return fmt.Errorf("not implemented")
|
||||
}
|
||||
|
||||
func (c *YouTubeClientMock) InsertCommentThread(
|
||||
func (c *clientMock) InsertCommentThread(
|
||||
ctx context.Context,
|
||||
t *youtube.CommentThread,
|
||||
parts []string,
|
||||
@@ -159,7 +159,7 @@ func (c *YouTubeClientMock) InsertCommentThread(
|
||||
return fmt.Errorf("not implemented")
|
||||
}
|
||||
|
||||
func (c *YouTubeClientMock) ListChatMessages(
|
||||
func (c *clientMock) ListChatMessages(
|
||||
ctx context.Context,
|
||||
chatID string,
|
||||
parts []string,
|
||||
@@ -169,7 +169,7 @@ func (c *YouTubeClientMock) ListChatMessages(
|
||||
return nil, fmt.Errorf("not implemented")
|
||||
}
|
||||
|
||||
func (c *YouTubeClientMock) DeleteChatMessage(
|
||||
func (c *clientMock) DeleteChatMessage(
|
||||
ctx context.Context,
|
||||
messageID string,
|
||||
) (_err error) {
|
||||
@@ -178,7 +178,7 @@ func (c *YouTubeClientMock) DeleteChatMessage(
|
||||
return fmt.Errorf("not implemented")
|
||||
}
|
||||
|
||||
func (c *YouTubeClientMock) GetLiveChatMessages(
|
||||
func (c *clientMock) GetLiveChatMessages(
|
||||
ctx context.Context,
|
||||
chatID string,
|
||||
pageToken string,
|
||||
@@ -189,7 +189,7 @@ func (c *YouTubeClientMock) GetLiveChatMessages(
|
||||
return nil, fmt.Errorf("not implemented")
|
||||
}
|
||||
|
||||
func (c *YouTubeClientMock) Search(
|
||||
func (c *clientMock) Search(
|
||||
ctx context.Context,
|
||||
chanID string,
|
||||
eventType EventType,
|
@@ -41,7 +41,7 @@ const (
|
||||
type YouTube struct {
|
||||
locker xsync.Mutex
|
||||
Config Config
|
||||
YouTubeClient *YouTubeClientCalcPoints
|
||||
YouTubeClient *ClientCalcPoints
|
||||
CancelFunc context.CancelFunc
|
||||
SaveConfigFunc func(Config) error
|
||||
|
||||
@@ -208,12 +208,12 @@ func (yt *YouTube) initNoLock(ctx context.Context) (_err error) {
|
||||
return fmt.Errorf("the token is invalid: %w", err)
|
||||
}
|
||||
|
||||
var youtubeClient YouTubeClient
|
||||
var youtubeClient client
|
||||
if debugUseMockClient {
|
||||
youtubeClient = NewYouTubeClientMock()
|
||||
youtubeClient = newClientMock()
|
||||
} else {
|
||||
var err error
|
||||
youtubeClient, err = NewYouTubeClientV3(
|
||||
youtubeClient, err = newClientV3(
|
||||
ctx,
|
||||
yt.wrapRequest,
|
||||
option.WithTokenSource(tokenSource),
|
||||
|
Reference in New Issue
Block a user