From 348c46eb8f0e79d0e53fffdb083b4bead5dd89aa Mon Sep 17 00:00:00 2001 From: Vincent Cloutier Date: Thu, 30 Mar 2023 19:19:16 -0400 Subject: [PATCH] twitter auth tweaks --- .../Settings/InstanceSettings.cs | 2 + .../Tools/TwitterAuthenticationInitializer.cs | 43 +++++++++++++++++-- .../TimelineTests.cs | 2 +- .../BirdsiteLive.Twitter.Tests/TweetTests.cs | 2 +- .../BirdsiteLive.Twitter.Tests/UsersTest.cs | 7 ++- 5 files changed, 50 insertions(+), 6 deletions(-) diff --git a/src/BirdsiteLive.Common/Settings/InstanceSettings.cs b/src/BirdsiteLive.Common/Settings/InstanceSettings.cs index 93c25a2..56ae0b6 100644 --- a/src/BirdsiteLive.Common/Settings/InstanceSettings.cs +++ b/src/BirdsiteLive.Common/Settings/InstanceSettings.cs @@ -16,6 +16,8 @@ public int UserCacheCapacity { get; set; } = 40_000; public int TweetCacheCapacity { get; set; } = 20_000; + // "AAAAAAAAAAAAAAAAAAAAAPYXBAAAAAAACLXUNDekMxqa8h%2F40K4moUkGsoc%3DTYfbDKbT3jJPCEVnMYqilB28NHfOPqkca3qaAxGfsyKCs0wRbw" + public string TwitterBearerToken { get; set; } = "AAAAAAAAAAAAAAAAAAAAANRILgAAAAAAnNwIzUejRCOuH5E6I8xnZz4puTs%3D1Zv7ttfk8LF81IUq16cHjhLTvJu4FA33AGWWjCpTnA"; public int ParallelTwitterRequests { get; set; } = 10; public int ParallelFediversePosts { get; set; } = 10; } diff --git a/src/BirdsiteLive.Twitter/Tools/TwitterAuthenticationInitializer.cs b/src/BirdsiteLive.Twitter/Tools/TwitterAuthenticationInitializer.cs index 6602213..7ffbb42 100644 --- a/src/BirdsiteLive.Twitter/Tools/TwitterAuthenticationInitializer.cs +++ b/src/BirdsiteLive.Twitter/Tools/TwitterAuthenticationInitializer.cs @@ -7,6 +7,8 @@ using BirdsiteLive.Common.Settings; using Microsoft.Extensions.Logging; using System.Net.Http; using System.Net; +using System.Net.Http.Headers; +using System.Text; using System.Text.Json; using System.Threading.RateLimiting; @@ -30,18 +32,51 @@ namespace BirdsiteLive.Twitter.Tools private RateLimiter _rateLimiter; static SemaphoreSlim semaphoreSlim = new SemaphoreSlim(1, 1); private const int _targetClients = 3; + private InstanceSettings _instanceSettings; + private readonly (string, string)[] _apiKeys = new[] + { + ("IQKbtAYlXLripLGPWd0HUA", "GgDYlkSvaPxGxC4X8liwpUoqKwwr3lCADbz8A7ADU"), // iPhone + ("3nVuSoBZnx6U4vzUxf5w", "Bcs59EFbbsdF6Sl9Ng71smgStWEGwXXKSjYvPVt7qys"), // Android + ("CjulERsDeqhhjSme66ECg", "IQWdVyqFxghAtURHGeGiWAsmCAGmdW3WmbEx6Hck"), // iPad + ("3rJOl1ODzm9yZy63FACdg", "5jPoQ5kQvMJFDYRNE8bQ4rHuds4xJqhvgNJM4awaE8"), // Mac + }; public String BearerToken { - get { return "AAAAAAAAAAAAAAAAAAAAAPYXBAAAAAAACLXUNDekMxqa8h%2F40K4moUkGsoc%3DTYfbDKbT3jJPCEVnMYqilB28NHfOPqkca3qaAxGfsyKCs0wRbw"; } + //get { return "AAAAAAAAAAAAAAAAAAAAAPYXBAAAAAAACLXUNDekMxqa8h%2F40K4moUkGsoc%3DTYfbDKbT3jJPCEVnMYqilB28NHfOPqkca3qaAxGfsyKCs0wRbw"; } + get + { + return _instanceSettings.TwitterBearerToken; + } } #region Ctor - public TwitterAuthenticationInitializer(IHttpClientFactory httpClientFactory, ILogger logger) + public TwitterAuthenticationInitializer(IHttpClientFactory httpClientFactory, InstanceSettings settings, ILogger logger) { _logger = logger; + _instanceSettings = settings; _httpClientFactory = httpClientFactory; } #endregion + private async Task GenerateBearerToken() + { + var httpClient = _httpClientFactory.CreateClient(); + using (var request = new HttpRequestMessage(new HttpMethod("POST"), "https://api.twitter.com/oauth2/token?grant_type=client_credentials")) + { + int r = rnd.Next(_apiKeys.Length); + var (login, password) = _apiKeys[r]; + var authValue = new AuthenticationHeaderValue("Basic", Convert.ToBase64String(Encoding.UTF8.GetBytes($"{login}:{password}"))); + request.Headers.TryAddWithoutValidation("Basic", $"Bearer " + authValue); + + var httpResponse = await httpClient.SendAsync(request); + + var c = await httpResponse.Content.ReadAsStringAsync(); + httpResponse.EnsureSuccessStatusCode(); + var doc = JsonDocument.Parse(c); + var token = doc.RootElement.GetProperty("access_token").GetString(); + } + + } + public async Task RefreshClient(HttpRequestMessage req) { @@ -49,7 +84,7 @@ namespace BirdsiteLive.Twitter.Tools var i = _tokens.IndexOf(token); - // this is prabably not thread save but yolo + // this is prabably not thread safe but yolo try { _twitterClients.RemoveAt(i); @@ -143,6 +178,8 @@ namespace BirdsiteLive.Twitter.Tools var request = new HttpRequestMessage(m, endpoint); int r = rnd.Next(_twitterClients.Count); request.Headers.TryAddWithoutValidation("Authorization", $"Bearer " + BearerToken); + request.Headers.TryAddWithoutValidation("Referer", "https://twitter.com/"); + request.Headers.TryAddWithoutValidation("x-twitter-active-user", "yes"); if (addToken) request.Headers.TryAddWithoutValidation("x-guest-token", _tokens[r]); //request.Headers.TryAddWithoutValidation("Referer", "https://twitter.com/"); diff --git a/src/Tests/BirdsiteLive.Twitter.Tests/TimelineTests.cs b/src/Tests/BirdsiteLive.Twitter.Tests/TimelineTests.cs index ef26e2e..f09f28f 100644 --- a/src/Tests/BirdsiteLive.Twitter.Tests/TimelineTests.cs +++ b/src/Tests/BirdsiteLive.Twitter.Tests/TimelineTests.cs @@ -37,7 +37,7 @@ namespace BirdsiteLive.ActivityPub.Tests )) .ReturnsAsync(new SyncTwitterUser { TwitterUserId = default }); - ITwitterAuthenticationInitializer auth = new TwitterAuthenticationInitializer(httpFactory.Object, logger1.Object); + ITwitterAuthenticationInitializer auth = new TwitterAuthenticationInitializer(httpFactory.Object, settings, logger1.Object); ITwitterUserService user = new TwitterUserService(auth, stats.Object, logger2.Object); ICachedTwitterUserService user2 = new CachedTwitterUserService(user, settings); _tweetService = new TwitterTweetsService(auth, stats.Object, user2, twitterDal.Object, settings, logger3.Object); diff --git a/src/Tests/BirdsiteLive.Twitter.Tests/TweetTests.cs b/src/Tests/BirdsiteLive.Twitter.Tests/TweetTests.cs index ed245bc..e25ab59 100644 --- a/src/Tests/BirdsiteLive.Twitter.Tests/TweetTests.cs +++ b/src/Tests/BirdsiteLive.Twitter.Tests/TweetTests.cs @@ -32,7 +32,7 @@ namespace BirdsiteLive.ActivityPub.Tests { Domain = "domain.name" }; - ITwitterAuthenticationInitializer auth = new TwitterAuthenticationInitializer(httpFactory.Object, logger1.Object); + ITwitterAuthenticationInitializer auth = new TwitterAuthenticationInitializer(httpFactory.Object, settings, logger1.Object); ITwitterUserService user = new TwitterUserService(auth, stats.Object, logger2.Object); ICachedTwitterUserService user2 = new CachedTwitterUserService(user, settings); _tweetService = new TwitterTweetsService(auth, stats.Object, user2, twitterDal.Object, settings, logger3.Object); diff --git a/src/Tests/BirdsiteLive.Twitter.Tests/UsersTest.cs b/src/Tests/BirdsiteLive.Twitter.Tests/UsersTest.cs index a3ec0e6..06e248a 100644 --- a/src/Tests/BirdsiteLive.Twitter.Tests/UsersTest.cs +++ b/src/Tests/BirdsiteLive.Twitter.Tests/UsersTest.cs @@ -6,6 +6,7 @@ using BirdsiteLive.Twitter.Tools; using BirdsiteLive.Statistics.Domain; using Moq; using System.Net.Http; +using BirdsiteLive.Common.Settings; namespace BirdsiteLive.ActivityPub.Tests { @@ -21,8 +22,12 @@ namespace BirdsiteLive.ActivityPub.Tests var logger3 = new Mock>(); var stats = new Mock(); var httpFactory = new Mock(); + var settings = new InstanceSettings + { + Domain = "domain.name" + }; httpFactory.Setup(_ => _.CreateClient(string.Empty)).Returns(new HttpClient()); - ITwitterAuthenticationInitializer auth = new TwitterAuthenticationInitializer(httpFactory.Object, logger1.Object); + ITwitterAuthenticationInitializer auth = new TwitterAuthenticationInitializer(httpFactory.Object, settings, logger1.Object); _tweetService = new TwitterUserService(auth, stats.Object, logger3.Object); }