@@ -32,17 +32,17 @@ public class TwitchApiProxy : ITwitchApiProxy {
3232 /// <summary>
3333 /// The, public, twitch client id.
3434 /// </summary>
35- private static readonly string ClientId = Environment . GetEnvironmentVariable ( "TWITCH_BOT_CLIENT_ID" ) ! ;
35+ protected readonly string ? _clientId ;
3636
3737 /// <summary>
3838 /// The, private, twitch client secret.
3939 /// </summary>
40- private static readonly string ClientSecret = Environment . GetEnvironmentVariable ( "TWITCH_BOT_CLIENT_SECRET" ) ! ;
40+ protected readonly string ? _clientSecret ;
4141
4242 /// <summary>
4343 /// The redirect url.
4444 /// </summary>
45- private static readonly string ClientRedirect = Environment . GetEnvironmentVariable ( "TWITCH_BOT_CLIENT_REDIRECT" ) ! ;
45+ protected readonly string ? _clientRedirect ;
4646
4747 /// <summary>
4848 /// Initializes a new instance of the <see cref="TwitchApiProxy" /> class.
@@ -56,7 +56,18 @@ public TwitchApiProxy() {
5656 /// <param name="token">The access token.</param>
5757 /// <param name="refreshToken">The refresh token.</param>
5858 /// <param name="tokenExpires">When the token expires (utc).</param>
59- public TwitchApiProxy ( string token , string refreshToken , DateTime tokenExpires ) {
59+ /// <param name="clientId">The client id of the registered twitch app, uses environment variable
60+ /// "TWITCH_BOT_CLIENT_ID" when null.</param>
61+ /// <param name="clientSecret">The client secret of the registered twitch app, uses environment variable
62+ /// "TWITCH_BOT_CLIENT_SECRET" when null.</param>
63+ /// <param name="clientRedirect">The url to redirect to from the registered twitch app, uses environment variable
64+ /// "TWITCH_BOT_CLIENT_REDIRECT" when null.</param>
65+ public TwitchApiProxy ( string token , string refreshToken , DateTime tokenExpires , string ? clientId = null ,
66+ string ? clientSecret = null , string ? clientRedirect = null ) {
67+ _clientId = clientId ?? Environment . GetEnvironmentVariable ( "TWITCH_BOT_CLIENT_ID" ) ;
68+ _clientSecret = clientSecret ?? Environment . GetEnvironmentVariable ( "TWITCH_BOT_CLIENT_SECRET" ) ;
69+ _clientRedirect = clientRedirect ?? Environment . GetEnvironmentVariable ( "TWITCH_BOT_CLIENT_REDIRECT" ) ;
70+
6071 OAuth = new TwitchAccessToken {
6172 AccessToken = token ,
6273 RefreshToken = refreshToken ,
@@ -73,9 +84,9 @@ public TwitchApiProxy(string token, string refreshToken, DateTime tokenExpires)
7384 public TwitchAccessToken ? OAuth { get ; set ; }
7485
7586 /// <inheritdoc />
76- public async Task < TwitchAccessToken ? > CreateAccessToken ( string code , CancellationToken token = new ( ) ) {
87+ public virtual async Task < TwitchAccessToken ? > CreateAccessToken ( string code , CancellationToken token = new ( ) ) {
7788 ITwitchAPI api = GetApi ( ) ;
78- AuthCodeResponse ? response = await api . Auth . GetAccessTokenFromCodeAsync ( code , ClientSecret , ClientRedirect ) ;
89+ AuthCodeResponse ? response = await api . Auth . GetAccessTokenFromCodeAsync ( code , _clientSecret , _clientRedirect ) ;
7990 if ( null == response ) {
8091 return null ;
8192 }
@@ -89,10 +100,14 @@ public TwitchApiProxy(string token, string refreshToken, DateTime tokenExpires)
89100 }
90101
91102 /// <inheritdoc />
92- public async Task < TwitchAccessToken ? > RefreshAccessToken ( CancellationToken token = new ( ) ) {
103+ public virtual async Task < TwitchAccessToken ? > RefreshAccessToken ( CancellationToken token = new ( ) ) {
93104 try {
105+ if ( string . IsNullOrWhiteSpace ( _clientSecret ) || string . IsNullOrWhiteSpace ( _clientId ) ) {
106+ return null ;
107+ }
108+
94109 ITwitchAPI api = GetApi ( ) ;
95- RefreshResponse ? response = await api . Auth . RefreshAuthTokenAsync ( OAuth ? . RefreshToken , ClientSecret , ClientId ) ;
110+ RefreshResponse ? response = await api . Auth . RefreshAuthTokenAsync ( OAuth ? . RefreshToken , _clientSecret , _clientId ) ;
96111 if ( null == response ) {
97112 return null ;
98113 }
@@ -111,11 +126,16 @@ public TwitchApiProxy(string token, string refreshToken, DateTime tokenExpires)
111126
112127 /// <inheritdoc />
113128 public async Task < bool > GetAccessTokenIsValid ( CancellationToken token = new ( ) ) {
114- return ! string . IsNullOrWhiteSpace ( ( await GetUser ( token ) ) . id ) ;
129+ try {
130+ return ! string . IsNullOrWhiteSpace ( ( await GetUser ( token ) ) . id ) ;
131+ }
132+ catch {
133+ return false ;
134+ }
115135 }
116136
117137 /// <inheritdoc />
118- public async Task < ( string ? id , string ? username ) > GetUser ( CancellationToken token = new ( ) ) {
138+ public virtual async Task < ( string ? id , string ? username ) > GetUser ( CancellationToken token = new ( ) ) {
119139 return await Retry . Execute ( async ( ) => {
120140 ITwitchAPI api = GetApi ( ) ;
121141 GetUsersResponse ? response = await api . Helix . Users . GetUsersAsync ( ) ;
@@ -129,7 +149,7 @@ public TwitchApiProxy(string token, string refreshToken, DateTime tokenExpires)
129149 }
130150
131151 /// <inheritdoc />
132- public async Task < string ? > GetUserEmail ( CancellationToken token = new ( ) ) {
152+ public virtual async Task < string ? > GetUserEmail ( CancellationToken token = new ( ) ) {
133153 return await Retry . Execute ( async ( ) => {
134154 ITwitchAPI api = GetApi ( ) ;
135155 GetUsersResponse ? response = await api . Helix . Users . GetUsersAsync ( ) ;
@@ -142,7 +162,7 @@ public TwitchApiProxy(string token, string refreshToken, DateTime tokenExpires)
142162 }
143163
144164 /// <inheritdoc />
145- public async Task < IEnumerable < TwitchModeratedChannel > > GetUserModChannels ( string userId ) {
165+ public virtual async Task < IEnumerable < TwitchModeratedChannel > > GetUserModChannels ( string userId ) {
146166 using var client = new HttpClient ( ) ;
147167
148168 var ret = new List < TwitchModeratedChannel > ( ) ;
@@ -155,7 +175,7 @@ public async Task<IEnumerable<TwitchModeratedChannel>> GetUserModChannels(string
155175
156176 var request = new HttpRequestMessage ( HttpMethod . Get , url ) ;
157177 request . Headers . Add ( "Authorization" , $ "Bearer { OAuth ? . AccessToken } ") ;
158- request . Headers . Add ( "Client-Id" , ClientId ) ;
178+ request . Headers . Add ( "Client-Id" , _clientId ) ;
159179
160180 using HttpResponseMessage response = await client . SendAsync ( request ) ;
161181 response . EnsureSuccessStatusCode ( ) ;
@@ -173,7 +193,7 @@ public async Task<IEnumerable<TwitchModeratedChannel>> GetUserModChannels(string
173193 }
174194
175195 /// <inheritdoc />
176- public async Task < IEnumerable < BannedUser > > BanChannelUsers ( string channelId , string botId ,
196+ public virtual async Task < IEnumerable < BannedUser > > BanChannelUsers ( string channelId , string botId ,
177197 IEnumerable < ( string Id , string Username ) > users , string reason , CancellationToken token = new ( ) ) {
178198 return await Retry . Execute ( async ( ) => {
179199 ITwitchAPI api = GetApi ( ) ;
@@ -207,7 +227,7 @@ public async Task<IEnumerable<BannedUser>> BanChannelUsers(string channelId, str
207227 }
208228
209229 /// <inheritdoc />
210- public async Task < IEnumerable < Chatter > > GetChannelUsers ( string channelId , string botId ,
230+ public virtual async Task < IEnumerable < Chatter > > GetChannelUsers ( string channelId , string botId ,
211231 CancellationToken token = new ( ) ) {
212232 return await Retry . Execute ( async ( ) => {
213233 ITwitchAPI api = GetApi ( ) ;
@@ -231,7 +251,7 @@ public async Task<IEnumerable<Chatter>> GetChannelUsers(string channelId, string
231251 }
232252
233253 /// <inheritdoc />
234- public async Task < IEnumerable < string > > GetChannelsLive ( IEnumerable < string > userIds ) {
254+ public virtual async Task < IEnumerable < string > > GetChannelsLive ( IEnumerable < string > userIds ) {
235255 ITwitchAPI api = GetApi ( ) ;
236256
237257 // We can only query 100 at a time, so throttle the search.
@@ -255,7 +275,7 @@ public async Task<IEnumerable<string>> GetChannelsLive(IEnumerable<string> userI
255275 }
256276
257277 /// <inheritdoc />
258- public async Task < IEnumerable < Moderator > > GetChannelMods ( string channelId , CancellationToken token = new ( ) ) {
278+ public virtual async Task < IEnumerable < Moderator > > GetChannelMods ( string channelId , CancellationToken token = new ( ) ) {
259279 return await Retry . Execute ( async ( ) => {
260280 ITwitchAPI api = GetApi ( ) ;
261281
@@ -282,7 +302,7 @@ public async Task<IEnumerable<string>> GetChannelsLive(IEnumerable<string> userI
282302 }
283303
284304 /// <inheritdoc />
285- public async Task < bool > AddChannelMod ( string channelId , string userId , CancellationToken token = new ( ) ) {
305+ public virtual async Task < bool > AddChannelMod ( string channelId , string userId , CancellationToken token = new ( ) ) {
286306 return await Retry . Execute ( async ( ) => {
287307 ITwitchAPI api = GetApi ( ) ;
288308 await api . Helix . Moderation . AddChannelModeratorAsync ( channelId , userId ) ;
@@ -294,10 +314,10 @@ public async Task<IEnumerable<string>> GetChannelsLive(IEnumerable<string> userI
294314 /// Gets a new instance of the <see cref="TwitchAPI" />.
295315 /// </summary>
296316 /// <returns>A new instance of the <see cref="TwitchAPI" />.</returns>
297- protected ITwitchAPI GetApi ( ) {
317+ protected virtual ITwitchAPI GetApi ( ) {
298318 var api = new TwitchAPI {
299319 Settings = {
300- ClientId = ClientId ,
320+ ClientId = _clientId ,
301321 AccessToken = OAuth ? . AccessToken
302322 }
303323 } ;
0 commit comments