mirror of
https://github.com/xaionaro-go/streamctl.git
synced 2025-09-29 12:52:10 +08:00
Add mock clients to streaming platforms
This commit is contained in:
@@ -12,14 +12,6 @@ type ChatHandler struct {
|
|||||||
onClose func(context.Context)
|
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(
|
func NewChatHandler(
|
||||||
ctx context.Context,
|
ctx context.Context,
|
||||||
client *gokick.Client,
|
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"
|
"github.com/xaionaro-go/xsync"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
debugUseMockClient = false
|
||||||
|
)
|
||||||
|
|
||||||
type ReverseEngClient interface {
|
type ReverseEngClient interface {
|
||||||
ChatClientOBSOLETE
|
ChatClientOBSOLETE
|
||||||
}
|
}
|
||||||
@@ -31,7 +35,7 @@ type Kick struct {
|
|||||||
CloseCtx context.Context
|
CloseCtx context.Context
|
||||||
CloseFn context.CancelFunc
|
CloseFn context.CancelFunc
|
||||||
Channel *kickcom.ChannelV1
|
Channel *kickcom.ChannelV1
|
||||||
Client *gokick.Client
|
Client *Client
|
||||||
ClientOBSOLETE *kickcom.Kick
|
ClientOBSOLETE *kickcom.Kick
|
||||||
ChatHandler *ChatHandlerOBSOLETE
|
ChatHandler *ChatHandlerOBSOLETE
|
||||||
ChatHandlerLocker xsync.CtxLocker
|
ChatHandlerLocker xsync.CtxLocker
|
||||||
@@ -57,36 +61,50 @@ func New(
|
|||||||
return nil, fmt.Errorf("channel is not set")
|
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()
|
clientOld, err := kickcom.New()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("unable to initialize the old client: %w", err)
|
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)
|
ctx, closeFn := context.WithCancel(ctx)
|
||||||
k := &Kick{
|
k := &Kick{
|
||||||
CloseCtx: ctx,
|
CloseCtx: ctx,
|
||||||
CloseFn: closeFn,
|
CloseFn: closeFn,
|
||||||
ChatHandlerLocker: make(xsync.CtxLocker, 1),
|
ChatHandlerLocker: make(xsync.CtxLocker, 1),
|
||||||
CurrentConfig: cfg,
|
CurrentConfig: cfg,
|
||||||
Client: client,
|
|
||||||
ClientOBSOLETE: clientOld,
|
ClientOBSOLETE: clientOld,
|
||||||
SaveCfgFn: saveCfgFn,
|
SaveCfgFn: saveCfgFn,
|
||||||
}
|
}
|
||||||
|
k.SetClient(client)
|
||||||
client.OnUserAccessTokenRefreshed(k.onUserAccessTokenRefreshed)
|
client.OnUserAccessTokenRefreshed(k.onUserAccessTokenRefreshed)
|
||||||
return k, nil
|
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(
|
func (k *Kick) onUserAccessTokenRefreshed(
|
||||||
userAccessToken string,
|
userAccessToken string,
|
||||||
refreshToken string,
|
refreshToken string,
|
||||||
@@ -230,7 +248,7 @@ func (k *Kick) getAccessTokenNoLock(
|
|||||||
gokick.ScopeModerationBan,
|
gokick.ScopeModerationBan,
|
||||||
}
|
}
|
||||||
logger.Debugf(ctx, "scopes: %v", scopes)
|
logger.Debugf(ctx, "scopes: %v", scopes)
|
||||||
authURL, err := k.getClient().GetAuthorize(
|
authURL, err := k.GetClient().GetAuthorize(
|
||||||
redirectURL,
|
redirectURL,
|
||||||
"EMPTY",
|
"EMPTY",
|
||||||
codeChallenge,
|
codeChallenge,
|
||||||
@@ -248,7 +266,7 @@ func (k *Kick) getAccessTokenNoLock(
|
|||||||
code string,
|
code string,
|
||||||
) error {
|
) error {
|
||||||
now := time.Now()
|
now := time.Now()
|
||||||
token, err := k.getClient().GetToken(ctx, redirectURL, code, codeVerifier)
|
token, err := k.GetClient().GetToken(ctx, redirectURL, code, codeVerifier)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("unable to get an access token: %w", err)
|
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)
|
return fmt.Errorf("unable to get a prepared client: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
_, err = k.getClient().UpdateStreamTitle(ctx, title)
|
_, err = k.GetClient().UpdateStreamTitle(ctx, title)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -391,7 +409,7 @@ func (k *Kick) getStreamStatusUsingNormalClient(
|
|||||||
logger.Debugf(ctx, "getStreamStatusUsingNormalClient")
|
logger.Debugf(ctx, "getStreamStatusUsingNormalClient")
|
||||||
defer func() { logger.Debugf(ctx, "/getStreamStatusUsingNormalClient: %v %v", _ret, _err) }()
|
defer func() { logger.Debugf(ctx, "/getStreamStatusUsingNormalClient: %v %v", _ret, _err) }()
|
||||||
|
|
||||||
resp, err := k.getClient().GetChannels(
|
resp, err := k.GetClient().GetChannels(
|
||||||
ctx,
|
ctx,
|
||||||
gokick.NewChannelListFilter().SetBroadcasterUserIDs([]int{int(k.Channel.UserID)}),
|
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) {
|
func (k *Kick) SendChatMessage(ctx context.Context, message string) (_err error) {
|
||||||
logger.Debugf(ctx, "SendChatMessage(ctx, '%s')", message)
|
logger.Debugf(ctx, "SendChatMessage(ctx, '%s')", message)
|
||||||
defer func() { logger.Debugf(ctx, "/SendChatMessage(ctx, '%s'): %v", message, _err) }()
|
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)
|
logger.Debugf(ctx, "SendChatMessage(ctx, '%s'): %#+v", message, resp)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -535,7 +553,7 @@ func (k *Kick) BanUser(
|
|||||||
return nil
|
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)
|
logger.Debugf(ctx, "BanUser(ctx, %d, '%s', %v): %#+v", userID, reason, deadline, resp)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -556,7 +574,7 @@ func (k *Kick) ApplyProfile(
|
|||||||
|
|
||||||
if profile.CategoryID != nil {
|
if profile.CategoryID != nil {
|
||||||
logger.Debugf(ctx, "has a CategoryID")
|
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 {
|
if err != nil {
|
||||||
result = append(result, fmt.Errorf("unable to update the category: %w", err))
|
result = append(result, fmt.Errorf("unable to update the category: %w", err))
|
||||||
}
|
}
|
||||||
|
@@ -2,13 +2,12 @@ package kick
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/go-ng/xatomic"
|
"github.com/go-ng/xatomic"
|
||||||
"github.com/scorfly/gokick"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func (k *Kick) getClient() *gokick.Client {
|
func (k *Kick) GetClient() Client {
|
||||||
return xatomic.LoadPointer(&k.Client)
|
return *xatomic.LoadPointer(&k.Client)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (k *Kick) setClient(client *gokick.Client) {
|
func (k *Kick) SetClient(client Client) {
|
||||||
xatomic.StorePointer(&k.Client, client)
|
xatomic.StorePointer(&k.Client, &client)
|
||||||
}
|
}
|
||||||
|
@@ -5,13 +5,13 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"github.com/facebookincubator/go-belt/tool/logger"
|
"github.com/facebookincubator/go-belt/tool/logger"
|
||||||
"github.com/nicklaw5/helix/v2"
|
|
||||||
"github.com/xaionaro-go/streamctl/pkg/secret"
|
"github.com/xaionaro-go/streamctl/pkg/secret"
|
||||||
|
twitch "github.com/xaionaro-go/streamctl/pkg/streamcontrol/twitch/types"
|
||||||
)
|
)
|
||||||
|
|
||||||
func NewTokenByApp(
|
func NewTokenByApp(
|
||||||
ctx context.Context,
|
ctx context.Context,
|
||||||
client *helix.Client,
|
client twitch.Client,
|
||||||
) (secret.String, error) {
|
) (secret.String, error) {
|
||||||
logger.Debugf(ctx, "getNewTokenByApp")
|
logger.Debugf(ctx, "getNewTokenByApp")
|
||||||
defer func() { logger.Debugf(ctx, "/getNewTokenByApp") }()
|
defer func() { logger.Debugf(ctx, "/getNewTokenByApp") }()
|
||||||
|
@@ -5,14 +5,14 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"github.com/facebookincubator/go-belt/tool/logger"
|
"github.com/facebookincubator/go-belt/tool/logger"
|
||||||
"github.com/nicklaw5/helix/v2"
|
|
||||||
"github.com/xaionaro-go/observability"
|
"github.com/xaionaro-go/observability"
|
||||||
"github.com/xaionaro-go/streamctl/pkg/secret"
|
"github.com/xaionaro-go/streamctl/pkg/secret"
|
||||||
|
twitch "github.com/xaionaro-go/streamctl/pkg/streamcontrol/twitch/types"
|
||||||
)
|
)
|
||||||
|
|
||||||
func NewTokenByUser(
|
func NewTokenByUser(
|
||||||
ctx context.Context,
|
ctx context.Context,
|
||||||
client *helix.Client,
|
client twitch.Client,
|
||||||
clientCode secret.String,
|
clientCode secret.String,
|
||||||
) (secret.String, secret.String, error) {
|
) (secret.String, secret.String, error) {
|
||||||
logger.Debugf(ctx, "getNewTokenByUser")
|
logger.Debugf(ctx, "getNewTokenByUser")
|
||||||
|
@@ -16,9 +16,10 @@ import (
|
|||||||
"github.com/nicklaw5/helix/v2"
|
"github.com/nicklaw5/helix/v2"
|
||||||
"github.com/xaionaro-go/observability"
|
"github.com/xaionaro-go/observability"
|
||||||
"github.com/xaionaro-go/streamctl/pkg/oauthhandler"
|
"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 {
|
func getScopes() []string {
|
||||||
scopes := map[string]struct{}{
|
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
|
closeFn context.CancelFunc
|
||||||
chatHandlerSub *ChatHandlerSub
|
chatHandlerSub *ChatHandlerSub
|
||||||
chatHandlerIRC *ChatHandlerIRC
|
chatHandlerIRC *ChatHandlerIRC
|
||||||
client *helix.Client
|
client client
|
||||||
config Config
|
config Config
|
||||||
broadcasterID string
|
broadcasterID string
|
||||||
lazyInitOnce sync.Once
|
lazyInitOnce sync.Once
|
||||||
@@ -39,7 +39,10 @@ type Twitch struct {
|
|||||||
clientSecret secret.String
|
clientSecret secret.String
|
||||||
}
|
}
|
||||||
|
|
||||||
const twitchDebug = false
|
const (
|
||||||
|
twitchDebug = false
|
||||||
|
debugUseMockClient = false
|
||||||
|
)
|
||||||
|
|
||||||
var _ streamcontrol.StreamController[StreamProfile] = (*Twitch)(nil)
|
var _ streamcontrol.StreamController[StreamProfile] = (*Twitch)(nil)
|
||||||
|
|
||||||
@@ -141,7 +144,7 @@ func New(
|
|||||||
|
|
||||||
func GetUserID(
|
func GetUserID(
|
||||||
_ context.Context,
|
_ context.Context,
|
||||||
client *helix.Client,
|
client client,
|
||||||
login string,
|
login string,
|
||||||
) (string, error) {
|
) (string, error) {
|
||||||
resp, err := client.GetUsers(&helix.UsersParams{
|
resp, err := client.GetUsers(&helix.UsersParams{
|
||||||
@@ -613,10 +616,13 @@ func (t *Twitch) getNewTokenByApp(
|
|||||||
func (t *Twitch) getClient(
|
func (t *Twitch) getClient(
|
||||||
ctx context.Context,
|
ctx context.Context,
|
||||||
oauthListenPort uint16,
|
oauthListenPort uint16,
|
||||||
) (*helix.Client, error) {
|
) (client, error) {
|
||||||
logger.Debugf(ctx, "getClient(ctx, %#+v, %v)", t.config, oauthListenPort)
|
logger.Debugf(ctx, "getClient(ctx, %#+v, %v)", t.config, oauthListenPort)
|
||||||
defer func() { logger.Debugf(ctx, "/getClient") }()
|
defer func() { logger.Debugf(ctx, "/getClient") }()
|
||||||
|
|
||||||
|
if debugUseMockClient {
|
||||||
|
return newClientMock(), nil
|
||||||
|
}
|
||||||
options := &helix.Options{
|
options := &helix.Options{
|
||||||
ClientID: t.clientID,
|
ClientID: t.clientID,
|
||||||
ClientSecret: t.clientSecret.Get(),
|
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/buildvars"
|
||||||
"github.com/xaionaro-go/streamctl/pkg/secret"
|
"github.com/xaionaro-go/streamctl/pkg/secret"
|
||||||
streamctl "github.com/xaionaro-go/streamctl/pkg/streamcontrol"
|
streamctl "github.com/xaionaro-go/streamctl/pkg/streamcontrol"
|
||||||
"github.com/xaionaro-go/streamctl/pkg/streamcontrol/twitch/auth"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
const ID = streamctl.PlatformName("twitch")
|
const ID = streamctl.PlatformName("twitch")
|
||||||
|
|
||||||
type OAuthHandler = auth.OAuthHandler
|
|
||||||
|
|
||||||
type PlatformSpecificConfig struct {
|
type PlatformSpecificConfig struct {
|
||||||
Channel string
|
Channel string
|
||||||
ClientID 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 {
|
type ChatListener struct {
|
||||||
videoID string
|
videoID string
|
||||||
liveChatID string
|
liveChatID string
|
||||||
client YouTubeChatClient
|
client ChatClient
|
||||||
|
|
||||||
wg sync.WaitGroup
|
wg sync.WaitGroup
|
||||||
cancelFunc context.CancelFunc
|
cancelFunc context.CancelFunc
|
||||||
messagesOutChan chan streamcontrol.ChatMessage
|
messagesOutChan chan streamcontrol.ChatMessage
|
||||||
}
|
}
|
||||||
|
|
||||||
type YouTubeChatClient interface {
|
type ChatClient interface {
|
||||||
GetLiveChatMessages(ctx context.Context, chatID string, pageToken string, parts []string) (*youtube.LiveChatMessageListResponse, error)
|
GetLiveChatMessages(ctx context.Context, chatID string, pageToken string, parts []string) (*youtube.LiveChatMessageListResponse, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewChatListener(
|
func NewChatListener(
|
||||||
ctx context.Context,
|
ctx context.Context,
|
||||||
ytClient YouTubeChatClient,
|
ytClient ChatClient,
|
||||||
videoID string,
|
videoID string,
|
||||||
liveChatID string,
|
liveChatID string,
|
||||||
) (*ChatListener, error) {
|
) (*ChatListener, error) {
|
||||||
|
@@ -36,8 +36,8 @@ func (t BroadcastType) String() string {
|
|||||||
return fmt.Sprintf("unexpected_value_%d", int(t))
|
return fmt.Sprintf("unexpected_value_%d", int(t))
|
||||||
}
|
}
|
||||||
|
|
||||||
type YouTubeClient interface {
|
type client interface {
|
||||||
YouTubeChatClient
|
ChatClient
|
||||||
Ping(context.Context) error
|
Ping(context.Context) error
|
||||||
GetBroadcasts(ctx context.Context, t BroadcastType, ids []string, parts []string, pageToken string) (*youtube.LiveBroadcastListResponse, error)
|
GetBroadcasts(ctx context.Context, t BroadcastType, ids []string, parts []string, pageToken string) (*youtube.LiveBroadcastListResponse, error)
|
||||||
UpdateBroadcast(context.Context, *youtube.LiveBroadcast, []string) error
|
UpdateBroadcast(context.Context, *youtube.LiveBroadcast, []string) error
|
||||||
@@ -65,7 +65,7 @@ const (
|
|||||||
EventTypeUpcoming = EventType("upcoming")
|
EventTypeUpcoming = EventType("upcoming")
|
||||||
)
|
)
|
||||||
|
|
||||||
type YouTubeClientV3 struct {
|
type clientV3 struct {
|
||||||
*youtube.Service
|
*youtube.Service
|
||||||
RequestWrapper func(context.Context, func(context.Context) error) error
|
RequestWrapper func(context.Context, func(context.Context) error) error
|
||||||
}
|
}
|
||||||
@@ -106,24 +106,24 @@ func wrapRequestR[T any](
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
var _ YouTubeClient = (*YouTubeClientV3)(nil)
|
var _ client = (*clientV3)(nil)
|
||||||
|
|
||||||
func NewYouTubeClientV3(
|
func newClientV3(
|
||||||
ctx context.Context,
|
ctx context.Context,
|
||||||
requestWrapper func(context.Context, func(context.Context) error) error,
|
requestWrapper func(context.Context, func(context.Context) error) error,
|
||||||
opts ...option.ClientOption,
|
opts ...option.ClientOption,
|
||||||
) (*YouTubeClientV3, error) {
|
) (*clientV3, error) {
|
||||||
srv, err := youtube.NewService(ctx, opts...)
|
srv, err := youtube.NewService(ctx, opts...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
return &YouTubeClientV3{
|
return &clientV3{
|
||||||
Service: srv,
|
Service: srv,
|
||||||
RequestWrapper: requestWrapper,
|
RequestWrapper: requestWrapper,
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *YouTubeClientV3) Ping(
|
func (c *clientV3) Ping(
|
||||||
ctx context.Context,
|
ctx context.Context,
|
||||||
) (_err error) {
|
) (_err error) {
|
||||||
logger.Tracef(ctx, "Ping")
|
logger.Tracef(ctx, "Ping")
|
||||||
@@ -141,7 +141,7 @@ func (c *YouTubeClientV3) Ping(
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *YouTubeClientV3) GetBroadcasts(
|
func (c *clientV3) GetBroadcasts(
|
||||||
ctx context.Context,
|
ctx context.Context,
|
||||||
t BroadcastType,
|
t BroadcastType,
|
||||||
ids []string,
|
ids []string,
|
||||||
@@ -171,7 +171,7 @@ func (c *YouTubeClientV3) GetBroadcasts(
|
|||||||
return wrapRequestR(ctx, c.RequestWrapper, r.Do, googleapi.QueryParameter("order", "date"))
|
return wrapRequestR(ctx, c.RequestWrapper, r.Do, googleapi.QueryParameter("order", "date"))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *YouTubeClientV3) UpdateBroadcast(
|
func (c *clientV3) UpdateBroadcast(
|
||||||
ctx context.Context,
|
ctx context.Context,
|
||||||
broadcast *youtube.LiveBroadcast,
|
broadcast *youtube.LiveBroadcast,
|
||||||
parts []string,
|
parts []string,
|
||||||
@@ -182,7 +182,7 @@ func (c *YouTubeClientV3) UpdateBroadcast(
|
|||||||
return wrapRequestS(ctx, c.RequestWrapper, do)
|
return wrapRequestS(ctx, c.RequestWrapper, do)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *YouTubeClientV3) InsertBroadcast(
|
func (c *clientV3) InsertBroadcast(
|
||||||
ctx context.Context,
|
ctx context.Context,
|
||||||
broadcast *youtube.LiveBroadcast,
|
broadcast *youtube.LiveBroadcast,
|
||||||
parts []string,
|
parts []string,
|
||||||
@@ -192,7 +192,7 @@ func (c *YouTubeClientV3) InsertBroadcast(
|
|||||||
return c.Service.LiveBroadcasts.Insert(parts, broadcast).Context(ctx).Do()
|
return c.Service.LiveBroadcasts.Insert(parts, broadcast).Context(ctx).Do()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *YouTubeClientV3) DeleteBroadcast(
|
func (c *clientV3) DeleteBroadcast(
|
||||||
ctx context.Context,
|
ctx context.Context,
|
||||||
broadcastID string,
|
broadcastID string,
|
||||||
) (_err error) {
|
) (_err error) {
|
||||||
@@ -202,7 +202,7 @@ func (c *YouTubeClientV3) DeleteBroadcast(
|
|||||||
return wrapRequest(ctx, c.RequestWrapper, do)
|
return wrapRequest(ctx, c.RequestWrapper, do)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *YouTubeClientV3) InsertCuepoint(
|
func (c *clientV3) InsertCuepoint(
|
||||||
ctx context.Context,
|
ctx context.Context,
|
||||||
p *youtube.Cuepoint,
|
p *youtube.Cuepoint,
|
||||||
) (_err error) {
|
) (_err error) {
|
||||||
@@ -212,7 +212,7 @@ func (c *YouTubeClientV3) InsertCuepoint(
|
|||||||
return wrapRequestS(ctx, c.RequestWrapper, do)
|
return wrapRequestS(ctx, c.RequestWrapper, do)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *YouTubeClientV3) GetVideos(
|
func (c *clientV3) GetVideos(
|
||||||
ctx context.Context,
|
ctx context.Context,
|
||||||
broadcastIDs []string,
|
broadcastIDs []string,
|
||||||
parts []string,
|
parts []string,
|
||||||
@@ -223,7 +223,7 @@ func (c *YouTubeClientV3) GetVideos(
|
|||||||
return wrapRequestR(ctx, c.RequestWrapper, do)
|
return wrapRequestR(ctx, c.RequestWrapper, do)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *YouTubeClientV3) UpdateVideo(
|
func (c *clientV3) UpdateVideo(
|
||||||
ctx context.Context,
|
ctx context.Context,
|
||||||
video *youtube.Video,
|
video *youtube.Video,
|
||||||
parts []string,
|
parts []string,
|
||||||
@@ -234,7 +234,7 @@ func (c *YouTubeClientV3) UpdateVideo(
|
|||||||
return wrapRequestS(ctx, c.RequestWrapper, do)
|
return wrapRequestS(ctx, c.RequestWrapper, do)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *YouTubeClientV3) GetPlaylists(
|
func (c *clientV3) GetPlaylists(
|
||||||
ctx context.Context,
|
ctx context.Context,
|
||||||
parts []string,
|
parts []string,
|
||||||
) (_ret *youtube.PlaylistListResponse, _err error) {
|
) (_ret *youtube.PlaylistListResponse, _err error) {
|
||||||
@@ -244,7 +244,7 @@ func (c *YouTubeClientV3) GetPlaylists(
|
|||||||
return wrapRequestR(ctx, c.RequestWrapper, do)
|
return wrapRequestR(ctx, c.RequestWrapper, do)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *YouTubeClientV3) GetPlaylistItems(
|
func (c *clientV3) GetPlaylistItems(
|
||||||
ctx context.Context,
|
ctx context.Context,
|
||||||
playlistID string,
|
playlistID string,
|
||||||
videoID string,
|
videoID string,
|
||||||
@@ -256,7 +256,7 @@ func (c *YouTubeClientV3) GetPlaylistItems(
|
|||||||
return wrapRequestR(ctx, c.RequestWrapper, do)
|
return wrapRequestR(ctx, c.RequestWrapper, do)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *YouTubeClientV3) InsertPlaylistItem(
|
func (c *clientV3) InsertPlaylistItem(
|
||||||
ctx context.Context,
|
ctx context.Context,
|
||||||
item *youtube.PlaylistItem,
|
item *youtube.PlaylistItem,
|
||||||
parts []string,
|
parts []string,
|
||||||
@@ -267,7 +267,7 @@ func (c *YouTubeClientV3) InsertPlaylistItem(
|
|||||||
return wrapRequestS(ctx, c.RequestWrapper, do)
|
return wrapRequestS(ctx, c.RequestWrapper, do)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *YouTubeClientV3) SetThumbnail(
|
func (c *clientV3) SetThumbnail(
|
||||||
ctx context.Context,
|
ctx context.Context,
|
||||||
broadcastID string,
|
broadcastID string,
|
||||||
thumbnail io.Reader,
|
thumbnail io.Reader,
|
||||||
@@ -278,7 +278,7 @@ func (c *YouTubeClientV3) SetThumbnail(
|
|||||||
return wrapRequestS(ctx, c.RequestWrapper, do)
|
return wrapRequestS(ctx, c.RequestWrapper, do)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *YouTubeClientV3) GetStreams(
|
func (c *clientV3) GetStreams(
|
||||||
ctx context.Context,
|
ctx context.Context,
|
||||||
parts []string,
|
parts []string,
|
||||||
) (_ret *youtube.LiveStreamListResponse, _err error) {
|
) (_ret *youtube.LiveStreamListResponse, _err error) {
|
||||||
@@ -288,7 +288,7 @@ func (c *YouTubeClientV3) GetStreams(
|
|||||||
return wrapRequestR(ctx, c.RequestWrapper, do)
|
return wrapRequestR(ctx, c.RequestWrapper, do)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *YouTubeClientV3) InsertCommentThread(
|
func (c *clientV3) InsertCommentThread(
|
||||||
ctx context.Context,
|
ctx context.Context,
|
||||||
t *youtube.CommentThread,
|
t *youtube.CommentThread,
|
||||||
parts []string,
|
parts []string,
|
||||||
@@ -299,7 +299,7 @@ func (c *YouTubeClientV3) InsertCommentThread(
|
|||||||
return wrapRequestS(ctx, c.RequestWrapper, do)
|
return wrapRequestS(ctx, c.RequestWrapper, do)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *YouTubeClientV3) ListChatMessages(
|
func (c *clientV3) ListChatMessages(
|
||||||
ctx context.Context,
|
ctx context.Context,
|
||||||
chatID string,
|
chatID string,
|
||||||
parts []string,
|
parts []string,
|
||||||
@@ -310,7 +310,7 @@ func (c *YouTubeClientV3) ListChatMessages(
|
|||||||
return wrapRequestR(ctx, c.RequestWrapper, do)
|
return wrapRequestR(ctx, c.RequestWrapper, do)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *YouTubeClientV3) DeleteChatMessage(
|
func (c *clientV3) DeleteChatMessage(
|
||||||
ctx context.Context,
|
ctx context.Context,
|
||||||
messageID string,
|
messageID string,
|
||||||
) (_err error) {
|
) (_err error) {
|
||||||
@@ -320,7 +320,7 @@ func (c *YouTubeClientV3) DeleteChatMessage(
|
|||||||
return wrapRequest(ctx, c.RequestWrapper, do)
|
return wrapRequest(ctx, c.RequestWrapper, do)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *YouTubeClientV3) GetLiveChatMessages(
|
func (c *clientV3) GetLiveChatMessages(
|
||||||
ctx context.Context,
|
ctx context.Context,
|
||||||
chatID string,
|
chatID string,
|
||||||
pageToken string,
|
pageToken string,
|
||||||
@@ -335,7 +335,7 @@ func (c *YouTubeClientV3) GetLiveChatMessages(
|
|||||||
return q.Do()
|
return q.Do()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *YouTubeClientV3) Search(
|
func (c *clientV3) Search(
|
||||||
ctx context.Context,
|
ctx context.Context,
|
||||||
chanID string,
|
chanID string,
|
||||||
eventType EventType,
|
eventType EventType,
|
@@ -26,17 +26,17 @@ func init() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// see also: https://developers.google.com/youtube/v3/determine_quota_cost
|
// see also: https://developers.google.com/youtube/v3/determine_quota_cost
|
||||||
type YouTubeClientCalcPoints struct {
|
type ClientCalcPoints struct {
|
||||||
Client YouTubeClient
|
Client client
|
||||||
UsedPoints atomic.Uint64
|
UsedPoints atomic.Uint64
|
||||||
CheckMutex sync.Mutex
|
CheckMutex sync.Mutex
|
||||||
PreviousCheckAt time.Time
|
PreviousCheckAt time.Time
|
||||||
}
|
}
|
||||||
|
|
||||||
var _ YouTubeClient = (*YouTubeClientCalcPoints)(nil)
|
var _ client = (*ClientCalcPoints)(nil)
|
||||||
|
|
||||||
func NewYouTubeClientCalcPoints(client YouTubeClient) *YouTubeClientCalcPoints {
|
func NewYouTubeClientCalcPoints(client client) *ClientCalcPoints {
|
||||||
return &YouTubeClientCalcPoints{
|
return &ClientCalcPoints{
|
||||||
Client: client,
|
Client: client,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -45,7 +45,7 @@ func getQuotaCutoffDate(t time.Time) string {
|
|||||||
return t.In(tzLosAngeles).Format("2006-01-02")
|
return t.In(tzLosAngeles).Format("2006-01-02")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *YouTubeClientCalcPoints) addUsedPointsIfNoError(
|
func (c *ClientCalcPoints) addUsedPointsIfNoError(
|
||||||
ctx context.Context,
|
ctx context.Context,
|
||||||
points uint,
|
points uint,
|
||||||
err error,
|
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) }()
|
defer func() { c.addUsedPointsIfNoError(ctx, 1, _err) }()
|
||||||
return c.Client.Ping(ctx)
|
return c.Client.Ping(ctx)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *YouTubeClientCalcPoints) GetBroadcasts(
|
func (c *ClientCalcPoints) GetBroadcasts(
|
||||||
ctx context.Context,
|
ctx context.Context,
|
||||||
t BroadcastType,
|
t BroadcastType,
|
||||||
ids []string,
|
ids []string,
|
||||||
@@ -87,7 +87,7 @@ func (c *YouTubeClientCalcPoints) GetBroadcasts(
|
|||||||
return c.Client.GetBroadcasts(ctx, t, ids, parts, pageToken)
|
return c.Client.GetBroadcasts(ctx, t, ids, parts, pageToken)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *YouTubeClientCalcPoints) UpdateBroadcast(
|
func (c *ClientCalcPoints) UpdateBroadcast(
|
||||||
ctx context.Context,
|
ctx context.Context,
|
||||||
broadcast *youtube.LiveBroadcast,
|
broadcast *youtube.LiveBroadcast,
|
||||||
parts []string,
|
parts []string,
|
||||||
@@ -96,7 +96,7 @@ func (c *YouTubeClientCalcPoints) UpdateBroadcast(
|
|||||||
return c.Client.UpdateBroadcast(ctx, broadcast, parts)
|
return c.Client.UpdateBroadcast(ctx, broadcast, parts)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *YouTubeClientCalcPoints) InsertBroadcast(
|
func (c *ClientCalcPoints) InsertBroadcast(
|
||||||
ctx context.Context,
|
ctx context.Context,
|
||||||
broadcast *youtube.LiveBroadcast,
|
broadcast *youtube.LiveBroadcast,
|
||||||
parts []string,
|
parts []string,
|
||||||
@@ -105,7 +105,7 @@ func (c *YouTubeClientCalcPoints) InsertBroadcast(
|
|||||||
return c.Client.InsertBroadcast(ctx, broadcast, parts)
|
return c.Client.InsertBroadcast(ctx, broadcast, parts)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *YouTubeClientCalcPoints) DeleteBroadcast(
|
func (c *ClientCalcPoints) DeleteBroadcast(
|
||||||
ctx context.Context,
|
ctx context.Context,
|
||||||
broadcastID string,
|
broadcastID string,
|
||||||
) (_err error) {
|
) (_err error) {
|
||||||
@@ -113,7 +113,7 @@ func (c *YouTubeClientCalcPoints) DeleteBroadcast(
|
|||||||
return c.Client.DeleteBroadcast(ctx, broadcastID)
|
return c.Client.DeleteBroadcast(ctx, broadcastID)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *YouTubeClientCalcPoints) GetStreams(
|
func (c *ClientCalcPoints) GetStreams(
|
||||||
ctx context.Context,
|
ctx context.Context,
|
||||||
parts []string,
|
parts []string,
|
||||||
) (_ret *youtube.LiveStreamListResponse, _err error) {
|
) (_ret *youtube.LiveStreamListResponse, _err error) {
|
||||||
@@ -121,7 +121,7 @@ func (c *YouTubeClientCalcPoints) GetStreams(
|
|||||||
return c.Client.GetStreams(ctx, parts)
|
return c.Client.GetStreams(ctx, parts)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *YouTubeClientCalcPoints) GetVideos(
|
func (c *ClientCalcPoints) GetVideos(
|
||||||
ctx context.Context,
|
ctx context.Context,
|
||||||
broadcastIDs []string,
|
broadcastIDs []string,
|
||||||
parts []string,
|
parts []string,
|
||||||
@@ -130,7 +130,7 @@ func (c *YouTubeClientCalcPoints) GetVideos(
|
|||||||
return c.Client.GetVideos(ctx, broadcastIDs, parts)
|
return c.Client.GetVideos(ctx, broadcastIDs, parts)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *YouTubeClientCalcPoints) UpdateVideo(
|
func (c *ClientCalcPoints) UpdateVideo(
|
||||||
ctx context.Context,
|
ctx context.Context,
|
||||||
video *youtube.Video,
|
video *youtube.Video,
|
||||||
parts []string,
|
parts []string,
|
||||||
@@ -139,7 +139,7 @@ func (c *YouTubeClientCalcPoints) UpdateVideo(
|
|||||||
return c.Client.UpdateVideo(ctx, video, parts)
|
return c.Client.UpdateVideo(ctx, video, parts)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *YouTubeClientCalcPoints) InsertCuepoint(
|
func (c *ClientCalcPoints) InsertCuepoint(
|
||||||
ctx context.Context,
|
ctx context.Context,
|
||||||
cuepoint *youtube.Cuepoint,
|
cuepoint *youtube.Cuepoint,
|
||||||
) (_err error) {
|
) (_err error) {
|
||||||
@@ -147,7 +147,7 @@ func (c *YouTubeClientCalcPoints) InsertCuepoint(
|
|||||||
return c.Client.InsertCuepoint(ctx, cuepoint)
|
return c.Client.InsertCuepoint(ctx, cuepoint)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *YouTubeClientCalcPoints) GetPlaylists(
|
func (c *ClientCalcPoints) GetPlaylists(
|
||||||
ctx context.Context,
|
ctx context.Context,
|
||||||
playlistParts []string,
|
playlistParts []string,
|
||||||
) (_ret *youtube.PlaylistListResponse, _err error) {
|
) (_ret *youtube.PlaylistListResponse, _err error) {
|
||||||
@@ -155,7 +155,7 @@ func (c *YouTubeClientCalcPoints) GetPlaylists(
|
|||||||
return c.Client.GetPlaylists(ctx, playlistParts)
|
return c.Client.GetPlaylists(ctx, playlistParts)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *YouTubeClientCalcPoints) GetPlaylistItems(
|
func (c *ClientCalcPoints) GetPlaylistItems(
|
||||||
ctx context.Context,
|
ctx context.Context,
|
||||||
playlistID string,
|
playlistID string,
|
||||||
videoID string,
|
videoID string,
|
||||||
@@ -165,7 +165,7 @@ func (c *YouTubeClientCalcPoints) GetPlaylistItems(
|
|||||||
return c.Client.GetPlaylistItems(ctx, playlistID, videoID, parts)
|
return c.Client.GetPlaylistItems(ctx, playlistID, videoID, parts)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *YouTubeClientCalcPoints) InsertPlaylistItem(
|
func (c *ClientCalcPoints) InsertPlaylistItem(
|
||||||
ctx context.Context,
|
ctx context.Context,
|
||||||
item *youtube.PlaylistItem,
|
item *youtube.PlaylistItem,
|
||||||
parts []string,
|
parts []string,
|
||||||
@@ -174,7 +174,7 @@ func (c *YouTubeClientCalcPoints) InsertPlaylistItem(
|
|||||||
return c.Client.InsertPlaylistItem(ctx, item, parts)
|
return c.Client.InsertPlaylistItem(ctx, item, parts)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *YouTubeClientCalcPoints) SetThumbnail(
|
func (c *ClientCalcPoints) SetThumbnail(
|
||||||
ctx context.Context,
|
ctx context.Context,
|
||||||
broadcastID string,
|
broadcastID string,
|
||||||
thumbnail io.Reader,
|
thumbnail io.Reader,
|
||||||
@@ -183,7 +183,7 @@ func (c *YouTubeClientCalcPoints) SetThumbnail(
|
|||||||
return c.Client.SetThumbnail(ctx, broadcastID, thumbnail)
|
return c.Client.SetThumbnail(ctx, broadcastID, thumbnail)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *YouTubeClientCalcPoints) InsertCommentThread(
|
func (c *ClientCalcPoints) InsertCommentThread(
|
||||||
ctx context.Context,
|
ctx context.Context,
|
||||||
t *youtube.CommentThread,
|
t *youtube.CommentThread,
|
||||||
parts []string,
|
parts []string,
|
||||||
@@ -192,7 +192,7 @@ func (c *YouTubeClientCalcPoints) InsertCommentThread(
|
|||||||
return c.Client.InsertCommentThread(ctx, t, parts)
|
return c.Client.InsertCommentThread(ctx, t, parts)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *YouTubeClientCalcPoints) ListChatMessages(
|
func (c *ClientCalcPoints) ListChatMessages(
|
||||||
ctx context.Context,
|
ctx context.Context,
|
||||||
chatID string,
|
chatID string,
|
||||||
parts []string,
|
parts []string,
|
||||||
@@ -201,7 +201,7 @@ func (c *YouTubeClientCalcPoints) ListChatMessages(
|
|||||||
return c.Client.ListChatMessages(ctx, chatID, parts)
|
return c.Client.ListChatMessages(ctx, chatID, parts)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *YouTubeClientCalcPoints) DeleteChatMessage(
|
func (c *ClientCalcPoints) DeleteChatMessage(
|
||||||
ctx context.Context,
|
ctx context.Context,
|
||||||
messageID string,
|
messageID string,
|
||||||
) (_err error) {
|
) (_err error) {
|
||||||
@@ -209,7 +209,7 @@ func (c *YouTubeClientCalcPoints) DeleteChatMessage(
|
|||||||
return c.Client.DeleteChatMessage(ctx, messageID)
|
return c.Client.DeleteChatMessage(ctx, messageID)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *YouTubeClientCalcPoints) GetLiveChatMessages(
|
func (c *ClientCalcPoints) GetLiveChatMessages(
|
||||||
ctx context.Context,
|
ctx context.Context,
|
||||||
chatID string,
|
chatID string,
|
||||||
pageToken string,
|
pageToken string,
|
||||||
@@ -219,7 +219,7 @@ func (c *YouTubeClientCalcPoints) GetLiveChatMessages(
|
|||||||
return c.Client.GetLiveChatMessages(ctx, chatID, pageToken, parts)
|
return c.Client.GetLiveChatMessages(ctx, chatID, pageToken, parts)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *YouTubeClientCalcPoints) Search(
|
func (c *ClientCalcPoints) Search(
|
||||||
ctx context.Context,
|
ctx context.Context,
|
||||||
chanID string,
|
chanID string,
|
||||||
eventType EventType,
|
eventType EventType,
|
@@ -9,21 +9,21 @@ import (
|
|||||||
"google.golang.org/api/youtube/v3"
|
"google.golang.org/api/youtube/v3"
|
||||||
)
|
)
|
||||||
|
|
||||||
type YouTubeClientMock struct{}
|
type clientMock struct{}
|
||||||
|
|
||||||
var _ YouTubeClient = (*YouTubeClientMock)(nil)
|
var _ client = (*clientMock)(nil)
|
||||||
|
|
||||||
func NewYouTubeClientMock() *YouTubeClientMock {
|
func newClientMock() *clientMock {
|
||||||
return &YouTubeClientMock{}
|
return &clientMock{}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *YouTubeClientMock) Ping(ctx context.Context) (_err error) {
|
func (c *clientMock) Ping(ctx context.Context) (_err error) {
|
||||||
logger.Tracef(ctx, "Ping")
|
logger.Tracef(ctx, "Ping")
|
||||||
defer func() { logger.Tracef(ctx, "/Ping: %v", _err) }()
|
defer func() { logger.Tracef(ctx, "/Ping: %v", _err) }()
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *YouTubeClientMock) GetBroadcasts(
|
func (c *clientMock) GetBroadcasts(
|
||||||
ctx context.Context,
|
ctx context.Context,
|
||||||
t BroadcastType,
|
t BroadcastType,
|
||||||
ids []string,
|
ids []string,
|
||||||
@@ -39,7 +39,7 @@ func (c *YouTubeClientMock) GetBroadcasts(
|
|||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *YouTubeClientMock) UpdateBroadcast(
|
func (c *clientMock) UpdateBroadcast(
|
||||||
ctx context.Context,
|
ctx context.Context,
|
||||||
broadcast *youtube.LiveBroadcast,
|
broadcast *youtube.LiveBroadcast,
|
||||||
parts []string,
|
parts []string,
|
||||||
@@ -49,7 +49,7 @@ func (c *YouTubeClientMock) UpdateBroadcast(
|
|||||||
return fmt.Errorf("not implemented")
|
return fmt.Errorf("not implemented")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *YouTubeClientMock) InsertBroadcast(
|
func (c *clientMock) InsertBroadcast(
|
||||||
ctx context.Context,
|
ctx context.Context,
|
||||||
broadcast *youtube.LiveBroadcast,
|
broadcast *youtube.LiveBroadcast,
|
||||||
parts []string,
|
parts []string,
|
||||||
@@ -59,7 +59,7 @@ func (c *YouTubeClientMock) InsertBroadcast(
|
|||||||
return nil, fmt.Errorf("not implemented")
|
return nil, fmt.Errorf("not implemented")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *YouTubeClientMock) DeleteBroadcast(
|
func (c *clientMock) DeleteBroadcast(
|
||||||
ctx context.Context,
|
ctx context.Context,
|
||||||
broadcastID string,
|
broadcastID string,
|
||||||
) (_err error) {
|
) (_err error) {
|
||||||
@@ -68,7 +68,7 @@ func (c *YouTubeClientMock) DeleteBroadcast(
|
|||||||
return fmt.Errorf("not implemented")
|
return fmt.Errorf("not implemented")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *YouTubeClientMock) GetStreams(
|
func (c *clientMock) GetStreams(
|
||||||
ctx context.Context,
|
ctx context.Context,
|
||||||
parts []string,
|
parts []string,
|
||||||
) (_ret *youtube.LiveStreamListResponse, _err error) {
|
) (_ret *youtube.LiveStreamListResponse, _err error) {
|
||||||
@@ -80,7 +80,7 @@ func (c *YouTubeClientMock) GetStreams(
|
|||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *YouTubeClientMock) GetVideos(
|
func (c *clientMock) GetVideos(
|
||||||
ctx context.Context,
|
ctx context.Context,
|
||||||
broadcastIDs []string,
|
broadcastIDs []string,
|
||||||
parts []string,
|
parts []string,
|
||||||
@@ -90,7 +90,7 @@ func (c *YouTubeClientMock) GetVideos(
|
|||||||
return nil, fmt.Errorf("not implemented")
|
return nil, fmt.Errorf("not implemented")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *YouTubeClientMock) UpdateVideo(
|
func (c *clientMock) UpdateVideo(
|
||||||
ctx context.Context,
|
ctx context.Context,
|
||||||
video *youtube.Video,
|
video *youtube.Video,
|
||||||
parts []string,
|
parts []string,
|
||||||
@@ -100,7 +100,7 @@ func (c *YouTubeClientMock) UpdateVideo(
|
|||||||
return fmt.Errorf("not implemented")
|
return fmt.Errorf("not implemented")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *YouTubeClientMock) InsertCuepoint(
|
func (c *clientMock) InsertCuepoint(
|
||||||
ctx context.Context,
|
ctx context.Context,
|
||||||
cuepoint *youtube.Cuepoint,
|
cuepoint *youtube.Cuepoint,
|
||||||
) (_err error) {
|
) (_err error) {
|
||||||
@@ -109,7 +109,7 @@ func (c *YouTubeClientMock) InsertCuepoint(
|
|||||||
return fmt.Errorf("not implemented")
|
return fmt.Errorf("not implemented")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *YouTubeClientMock) GetPlaylists(
|
func (c *clientMock) GetPlaylists(
|
||||||
ctx context.Context,
|
ctx context.Context,
|
||||||
playlistParts []string,
|
playlistParts []string,
|
||||||
) (_ret *youtube.PlaylistListResponse, _err error) {
|
) (_ret *youtube.PlaylistListResponse, _err error) {
|
||||||
@@ -118,7 +118,7 @@ func (c *YouTubeClientMock) GetPlaylists(
|
|||||||
return nil, fmt.Errorf("not implemented")
|
return nil, fmt.Errorf("not implemented")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *YouTubeClientMock) GetPlaylistItems(
|
func (c *clientMock) GetPlaylistItems(
|
||||||
ctx context.Context,
|
ctx context.Context,
|
||||||
playlistID string,
|
playlistID string,
|
||||||
videoID string,
|
videoID string,
|
||||||
@@ -129,7 +129,7 @@ func (c *YouTubeClientMock) GetPlaylistItems(
|
|||||||
return nil, fmt.Errorf("not implemented")
|
return nil, fmt.Errorf("not implemented")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *YouTubeClientMock) InsertPlaylistItem(
|
func (c *clientMock) InsertPlaylistItem(
|
||||||
ctx context.Context,
|
ctx context.Context,
|
||||||
item *youtube.PlaylistItem,
|
item *youtube.PlaylistItem,
|
||||||
parts []string,
|
parts []string,
|
||||||
@@ -139,7 +139,7 @@ func (c *YouTubeClientMock) InsertPlaylistItem(
|
|||||||
return fmt.Errorf("not implemented")
|
return fmt.Errorf("not implemented")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *YouTubeClientMock) SetThumbnail(
|
func (c *clientMock) SetThumbnail(
|
||||||
ctx context.Context,
|
ctx context.Context,
|
||||||
broadcastID string,
|
broadcastID string,
|
||||||
thumbnail io.Reader,
|
thumbnail io.Reader,
|
||||||
@@ -149,7 +149,7 @@ func (c *YouTubeClientMock) SetThumbnail(
|
|||||||
return fmt.Errorf("not implemented")
|
return fmt.Errorf("not implemented")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *YouTubeClientMock) InsertCommentThread(
|
func (c *clientMock) InsertCommentThread(
|
||||||
ctx context.Context,
|
ctx context.Context,
|
||||||
t *youtube.CommentThread,
|
t *youtube.CommentThread,
|
||||||
parts []string,
|
parts []string,
|
||||||
@@ -159,7 +159,7 @@ func (c *YouTubeClientMock) InsertCommentThread(
|
|||||||
return fmt.Errorf("not implemented")
|
return fmt.Errorf("not implemented")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *YouTubeClientMock) ListChatMessages(
|
func (c *clientMock) ListChatMessages(
|
||||||
ctx context.Context,
|
ctx context.Context,
|
||||||
chatID string,
|
chatID string,
|
||||||
parts []string,
|
parts []string,
|
||||||
@@ -169,7 +169,7 @@ func (c *YouTubeClientMock) ListChatMessages(
|
|||||||
return nil, fmt.Errorf("not implemented")
|
return nil, fmt.Errorf("not implemented")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *YouTubeClientMock) DeleteChatMessage(
|
func (c *clientMock) DeleteChatMessage(
|
||||||
ctx context.Context,
|
ctx context.Context,
|
||||||
messageID string,
|
messageID string,
|
||||||
) (_err error) {
|
) (_err error) {
|
||||||
@@ -178,7 +178,7 @@ func (c *YouTubeClientMock) DeleteChatMessage(
|
|||||||
return fmt.Errorf("not implemented")
|
return fmt.Errorf("not implemented")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *YouTubeClientMock) GetLiveChatMessages(
|
func (c *clientMock) GetLiveChatMessages(
|
||||||
ctx context.Context,
|
ctx context.Context,
|
||||||
chatID string,
|
chatID string,
|
||||||
pageToken string,
|
pageToken string,
|
||||||
@@ -189,7 +189,7 @@ func (c *YouTubeClientMock) GetLiveChatMessages(
|
|||||||
return nil, fmt.Errorf("not implemented")
|
return nil, fmt.Errorf("not implemented")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *YouTubeClientMock) Search(
|
func (c *clientMock) Search(
|
||||||
ctx context.Context,
|
ctx context.Context,
|
||||||
chanID string,
|
chanID string,
|
||||||
eventType EventType,
|
eventType EventType,
|
@@ -41,7 +41,7 @@ const (
|
|||||||
type YouTube struct {
|
type YouTube struct {
|
||||||
locker xsync.Mutex
|
locker xsync.Mutex
|
||||||
Config Config
|
Config Config
|
||||||
YouTubeClient *YouTubeClientCalcPoints
|
YouTubeClient *ClientCalcPoints
|
||||||
CancelFunc context.CancelFunc
|
CancelFunc context.CancelFunc
|
||||||
SaveConfigFunc func(Config) error
|
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)
|
return fmt.Errorf("the token is invalid: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
var youtubeClient YouTubeClient
|
var youtubeClient client
|
||||||
if debugUseMockClient {
|
if debugUseMockClient {
|
||||||
youtubeClient = NewYouTubeClientMock()
|
youtubeClient = newClientMock()
|
||||||
} else {
|
} else {
|
||||||
var err error
|
var err error
|
||||||
youtubeClient, err = NewYouTubeClientV3(
|
youtubeClient, err = newClientV3(
|
||||||
ctx,
|
ctx,
|
||||||
yt.wrapRequest,
|
yt.wrapRequest,
|
||||||
option.WithTokenSource(tokenSource),
|
option.WithTokenSource(tokenSource),
|
||||||
|
Reference in New Issue
Block a user