Twitter API

Habe heute eine Weile gebraucht bis ich einen Tweet absetzen konnte. Für mich und im Fall, das es jemand anderer braucht.

Twitter Developer Platform overview | Docs | Twitter Developer Platform

using System;
using System.Collections.Generic;
using System.Net.Http;
using System.Security.Cryptography;
using System.Text;
using System.Text.Json;
using System.Threading.Tasks;

public class TwitterClient
{
    private readonly string consumerKey;
    private readonly string consumerSecret;
    private readonly string accessToken;
    private readonly string tokenSecret;

    private readonly HttpClient httpClient;

    public TwitterClient(HttpClient httpClient, string consumerKey, string consumerSecret, string accessToken, string tokenSecret)
    {
        this.httpClient = httpClient;
        this.consumerKey = consumerKey;
        this.consumerSecret = consumerSecret;
        this.accessToken = accessToken;
        this.tokenSecret = tokenSecret;
    }

    public async Task PostTweet(string text)
    {
        var timstamp = CreateTimestamp();
        var nonce = CreateNonce();
        var body = JsonSerializer.Serialize(new { text });
        var uri = new Uri("https://api.twitter.com/2/tweets");

        var request = new HttpRequestMessage
        {
            RequestUri = uri,
            Method = HttpMethod.Post,
            Content = new StringContent(body, Encoding.ASCII, "application/json")
        };

        var signatureBase64 = CreateSignature(uri.ToString(), "POST", nonce, timstamp);

        request.Headers.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("OAuth",
            $@"oauth_consumer_key=""{Uri.EscapeDataString(consumerKey)}""",
            $@",oauth_token=""{Uri.EscapeDataString(accessToken)}""",
            $@",oauth_signature_method=""HMAC-SHA1"",oauth_timestamp=""{Uri.EscapeDataString(timstamp)}""",
            $@",oauth_nonce=""{Uri.EscapeDataString(nonce)}"",oauth_version=""1.0""",
            $@",oauth_signature=""{Uri.EscapeDataString(signatureBase64)}""");

        var response = await httpClient.SendAsync(request);

        response.EnsureSuccessStatusCode();
    }

    private string CreateSignature(string url, string method, string nonce, string timestamp)
    {
        var parameters = new Dictionary<string, string>();

        parameters.Add("oauth_consumer_key", consumerKey);
        parameters.Add("oauth_nonce", nonce);
        parameters.Add("oauth_signature_method", "HMAC-SHA1");
        parameters.Add("oauth_timestamp", timestamp);
        parameters.Add("oauth_token", accessToken);
        parameters.Add("oauth_version", "1.0");

        var sigBaseString = CombineQueryParams(parameters);

        var signatureBaseString = $"{method}&{Uri.EscapeDataString(url)}&{Uri.EscapeDataString(sigBaseString)}";

        var compositeKey = $"{Uri.EscapeDataString(consumerSecret)}&{Uri.EscapeDataString(tokenSecret)}";

        using (var hasher = new HMACSHA1(Encoding.ASCII.GetBytes(compositeKey)))
        {
            return Convert.ToBase64String(hasher.ComputeHash(Encoding.ASCII.GetBytes(signatureBaseString)));
        }
    }

    private string CreateTimestamp()
    {
        var totalSeconds = (DateTime.UtcNow - new DateTime(1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc))
            .TotalSeconds;

        return Convert.ToInt64(totalSeconds).ToString();
    }

    private string CreateNonce()
    {
        return Convert.ToBase64String(
            new ASCIIEncoding().GetBytes(
                DateTime.Now.Ticks.ToString()));
    }

    public string CombineQueryParams(Dictionary<string, string> parameters)
    {
        var sb = new StringBuilder();
        var first = true;

        foreach (var param in parameters)
        {
            if (!first)
            {
                sb.Append("&");
            }

            sb.Append(param.Key);
            sb.Append("=");
            sb.Append(Uri.EscapeDataString(param.Value));

            first = false;
        }

        return sb.ToString

Imports System.Net.Http
Imports System.Security.Cryptography
Imports System.Text
Imports System.Text.Json

Public Class TwitterClient
    Private ReadOnly consumerKey As String
    Private ReadOnly consumerSecret As String
    Private ReadOnly accessToken As String
    Private ReadOnly tokenSecret As String

    Private ReadOnly httpClient As HttpClient

    Public Sub New(httpClient As HttpClient, consumerKey As String, consumerSecret As String, accessToken As String, tokenSecret As String)
        Me.httpClient = httpClient
        Me.consumerKey = consumerKey
        Me.consumerSecret = consumerSecret
        Me.accessToken = accessToken
        Me.tokenSecret = tokenSecret
    End Sub

    Public Async Function PostTweet(text As String) As Task
        Dim timstamp = CreateTimestamp()
        Dim nonce = CreateNonce()
        Dim body = JsonSerializer.Serialize(New With {Key .text = text})
        Dim uri = New Uri("https://api.twitter.com/2/tweets")

        Dim request = New HttpRequestMessage With {
            .RequestUri = uri,
            .Method = HttpMethod.Post,
            .Content = New StringContent(body, Encoding.ASCII, "application/json")
        }

        Dim signatureBase64 = CreateSignature(uri.ToString(), "POST", nonce, timstamp)

        request.Headers.Authorization = New System.Net.Http.Headers.AuthenticationHeaderValue("OAuth", $"oauth_consumer_key=""{Uri.EscapeDataString(consumerKey)}"",oauth_token=""{Uri.EscapeDataString(accessToken)}"", oauth_signature_method=""HMAC-SHA1"",oauth_timestamp=""{Uri.EscapeDataString(timstamp)}"",oauth_nonce=""{Uri.EscapeDataString(nonce)}"", oauth_version=""1.0"", oauth_signature=""{Uri.EscapeDataString(signatureBase64)}""")

        Dim response = Await httpClient.SendAsync(request)

        response.EnsureSuccessStatusCode()
    End Function

    Private Function CreateSignature(url As String, method As String, nonce As String, timestamp As String) As String
        Dim parameters = New Dictionary(Of String, String)()

        parameters.Add("oauth_consumer_key", consumerKey)
        parameters.Add("oauth_nonce", nonce)
        parameters.Add("oauth_signature_method", "HMAC-SHA1")
        parameters.Add("oauth_timestamp", timestamp)
        parameters.Add("oauth_token", accessToken)
        parameters.Add("oauth_version", "1.0")

        Dim sigBaseString = CombineQueryParams(parameters)

        Dim signatureBaseString = $"{method}&{Uri.EscapeDataString(url)}&{Uri.EscapeDataString(sigBaseString)}"

        Dim compositeKey = $"{Uri.EscapeDataString(consumerSecret)}&{Uri.EscapeDataString(tokenSecret)}"

        Using hasher = New HMACSHA1(Encoding.ASCII.GetBytes(compositeKey))
            Return Convert.ToBase64String(hasher.ComputeHash(Encoding.ASCII.GetBytes(signatureBaseString)))
        End Using
    End Function

    Private Function CreateTimestamp() As String
        Dim totalSeconds = (DateTime.UtcNow - New DateTime(1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc)).TotalSeconds

        Return Convert.ToInt64(totalSeconds).ToString()
    End Function

    Private Function CreateNonce() As String
        Return Convert.ToBase64String(New ASCIIEncoding().GetBytes(DateTime.Now.Ticks.ToString()))
    End Function

    Public Function CombineQueryParams(parameters As Dictionary(Of String, String)) As String
        Dim sb = New StringBuilder()
        Dim first = True

        For Each param In parameters
            If Not first Then
                sb.Append("&")
            End If

            sb.Append(param.Key)
            sb.Append("=")
            sb.Append(Uri.EscapeDataString(param.Value))

            first = False
        Next

        Return sb.ToString()
    End Function
End Class

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert