Last active
April 3, 2022 03:24
-
-
Save SnowCait/5b48c2ef73a1b79a711a18d88334ab7a to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Collections.Generic; | |
using System.Linq; | |
using System.Net.Http.Headers; | |
using System.Net.Mime; | |
using System.Text; | |
using System.Text.Json; | |
using System.Threading.Tasks; | |
namespace MauiLib1 | |
{ | |
public class Api | |
{ | |
public string AccessToken { get; private set; } | |
protected static readonly HttpClient HttpClient = new HttpClient(); | |
public Api(string accessToken) | |
{ | |
AccessToken = accessToken; | |
HttpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", AccessToken); | |
} | |
public async Task<string> GetTweet(long id) | |
{ | |
var response = await HttpClient.GetAsync($"https://api.twitter.com/2/tweets/{id}").ConfigureAwait(false); | |
return await response.Content.ReadAsStringAsync().ConfigureAwait(false); | |
} | |
public async Task<string> PostTweet(string text) | |
{ | |
var parameters = new Dictionary<string, string>() | |
{ | |
{ "text", text }, | |
}; | |
var json = JsonSerializer.Serialize(parameters); | |
var content = new StringContent(json, Encoding.UTF8, MediaTypeNames.Application.Json); | |
var response = await HttpClient.PostAsync("https://api.twitter.com/2/tweets", content).ConfigureAwait(false); | |
return await response.Content.ReadAsStringAsync().ConfigureAwait(false); | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Collections.Generic; | |
using System.Linq; | |
using System.Net.Http.Headers; | |
using System.Text; | |
using System.Threading.Tasks; | |
using System.Web; | |
namespace MauiLib1 | |
{ | |
public class Client | |
{ | |
protected static readonly HttpClient HttpClient = new HttpClient(); | |
public ClientType ClientType { get; private set; } | |
public string ClientId { get; private set; } | |
public string ClientSecret { get; private set; } | |
public Client(string clientId, string clientSecret = null) | |
{ | |
ClientType = clientSecret == null ? ClientType.Public : ClientType.Confidential; | |
ClientId = clientId; | |
ClientSecret = clientSecret; | |
} | |
public string ConstructAuthorizeUrl(string redirectUri, IEnumerable<Scope> scopes, string state, string challenge, string challengeMethod = "S256") | |
{ | |
var query = HttpUtility.ParseQueryString(""); | |
query.Add("response_type", "code"); | |
query.Add("client_id", ClientId); | |
query.Add("redirect_uri", redirectUri); | |
query.Add("scope", string.Join(" ", scopes.Select(x => x.GetValue()))); | |
query.Add("state", state); | |
query.Add("code_challenge", challenge); | |
query.Add("code_challenge_method", challengeMethod); | |
var uriBuilder = new UriBuilder("https://twitter.com/i/oauth2/authorize") | |
{ | |
Query = query.ToString(), | |
}; | |
return uriBuilder.Uri.AbsoluteUri; | |
} | |
public string RetrieveAuthorizationCode(string callbackedUri, string state) | |
{ | |
var uri = new Uri(callbackedUri); | |
var query = HttpUtility.ParseQueryString(uri.Query); | |
if (query.Get("state") != state) | |
{ | |
throw new InvalidDataException("state is not valid."); | |
} | |
return query.Get("code"); | |
} | |
public async Task<string> GetAccessToken(string redirectUri, string code, string verifier) | |
{ | |
var parameters = new Dictionary<string, string>() | |
{ | |
{ "code", code }, | |
{ "grant_type", "authorization_code" }, | |
{ "redirect_uri", redirectUri }, | |
{ "code_verifier", verifier }, | |
}; | |
if (ClientType == ClientType.Public) | |
{ | |
parameters.Add("client_id", ClientId); | |
} | |
var content = new FormUrlEncodedContent(parameters); | |
var request = new HttpRequestMessage(HttpMethod.Post, "https://api.twitter.com/2/oauth2/token"); | |
if (ClientType == ClientType.Confidential) | |
{ | |
request.Headers.Authorization = new AuthenticationHeaderValue( | |
"Basic", | |
Convert.ToBase64String(Encoding.ASCII.GetBytes($"{ClientId}:{ClientSecret}")) | |
); | |
} | |
request.Content = content; | |
var response = await HttpClient.SendAsync(request).ConfigureAwait(false); | |
return await response.Content.ReadAsStringAsync().ConfigureAwait(false); | |
} | |
public async Task<string> RefreshToken(string refreshToken) | |
{ | |
var parameters = new Dictionary<string, string>() | |
{ | |
{ "refresh_token", refreshToken }, | |
{ "grant_type", "refresh_token" }, | |
}; | |
if (ClientType == ClientType.Public) | |
{ | |
parameters.Add("client_id", ClientId); | |
} | |
var content = new FormUrlEncodedContent(parameters); | |
var request = new HttpRequestMessage(HttpMethod.Post, "https://api.twitter.com/2/oauth2/token"); | |
if (ClientType == ClientType.Confidential) | |
{ | |
request.Headers.Authorization = new AuthenticationHeaderValue( | |
"Basic", | |
Convert.ToBase64String(Encoding.ASCII.GetBytes($"{ClientId}:{ClientSecret}")) | |
); | |
} | |
request.Content = content; | |
var response = await HttpClient.SendAsync(request).ConfigureAwait(false); | |
return await response.Content.ReadAsStringAsync().ConfigureAwait(false); | |
} | |
public async Task<string> RevokeToken(string accessToken) | |
{ | |
var parameters = new Dictionary<string, string>() | |
{ | |
{ "token", accessToken }, | |
{ "token_type_hint", "access_token" } | |
}; | |
if (ClientType == ClientType.Public) | |
{ | |
parameters.Add("client_id", ClientId); | |
} | |
var content = new FormUrlEncodedContent(parameters); | |
var request = new HttpRequestMessage(HttpMethod.Post, "https://api.twitter.com/2/oauth2/revoke"); | |
if (ClientType == ClientType.Confidential) | |
{ | |
request.Headers.Authorization = new AuthenticationHeaderValue( | |
"Basic", | |
Convert.ToBase64String(Encoding.ASCII.GetBytes($"{ClientId}:{ClientSecret}")) | |
); | |
} | |
request.Content = content; | |
var response = await HttpClient.SendAsync(request).ConfigureAwait(false); | |
return await response.Content.ReadAsStringAsync().ConfigureAwait(false); | |
} | |
} | |
public enum ClientType | |
{ | |
Confidential, | |
Public, | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Collections.Generic; | |
using System.Linq; | |
using System.Text; | |
using System.Threading.Tasks; | |
namespace MauiLib1 | |
{ | |
public enum Scope | |
{ | |
TweetRead, | |
TweetWrite, | |
TweetModerateWrite, | |
UsersRead, | |
FollowRead, | |
FollowWrite, | |
OfflineAccess, | |
SpaceRead, | |
MuteRead, | |
MuteWrite, | |
LikeRead, | |
LikeWrite, | |
ListRead, | |
ListWrite, | |
BlockRead, | |
BlockWrite, | |
BookmarkRead, | |
BookmarkWrite, | |
} | |
public static class ScopeExtension | |
{ | |
private static Dictionary<Scope, string> Values = new Dictionary<Scope, string>() | |
{ | |
{ Scope.TweetRead, "tweet.read" }, | |
{ Scope.TweetWrite, "tweet.write" }, | |
{ Scope.TweetModerateWrite, "tweet.moderate.write" }, | |
{ Scope.UsersRead, "users.read" }, | |
{ Scope.FollowRead, "follow.read" }, | |
{ Scope.FollowWrite, "follow.write" }, | |
{ Scope.OfflineAccess, "offline.access" }, | |
{ Scope.SpaceRead, "space.read" }, | |
{ Scope.MuteRead, "mute.read" }, | |
{ Scope.MuteWrite, "mute.write" }, | |
{ Scope.LikeRead, "like.read" }, | |
{ Scope.LikeWrite, "like.write" }, | |
{ Scope.ListRead, "list.read" }, | |
{ Scope.ListWrite, "list.write" }, | |
{ Scope.BlockRead, "block.read" }, | |
{ Scope.BlockWrite, "block.write" }, | |
{ Scope.BookmarkRead, "bookmark.read" }, | |
{ Scope.BookmarkWrite, "bookmark.write" }, | |
}; | |
public static string GetValue(this Scope scope) | |
{ | |
return Values[scope]; | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment