First commit... it kinda works, but it's missing most things

This commit is contained in:
Gervasio Marchand 2022-12-02 16:38:42 -03:00
commit 609d441dce
No known key found for this signature in database
GPG Key ID: B7736CB188DD0A38
5 changed files with 160 additions and 0 deletions

8
.gitignore vendored Normal file
View File

@ -0,0 +1,8 @@
.vscode/
bin/
obj/
.vs/
*.csproj.user
launchSettings.json
.idea/
.DS_Store

31
Helpers/CryptoHelper.cs Normal file
View File

@ -0,0 +1,31 @@
using System.Security.Cryptography;
using System.Text;
namespace ImportDataAsRelay.Helpers;
public static class CryptoHelper
{
public static string GetSHA256Digest(string content)
{
using var sha256 = SHA256.Create();
var hashValue = sha256.ComputeHash(Encoding.UTF8.GetBytes(content));
return Convert.ToBase64String(hashValue);
}
public static string ConvertPemToBase64(string filename)
{
var rsa = RSA.Create();
rsa.ImportFromPem(File.ReadAllText(filename).ToCharArray());
return Convert.ToBase64String(rsa.ExportRSAPrivateKey());
}
public static string Sign(string stringToSign)
{
using var rsaProvider = new RSACryptoServiceProvider();
using var sha256 = SHA256.Create();
rsaProvider.ImportRSAPrivateKey(Convert.FromBase64String(Environment.GetEnvironmentVariable("PRIVATE_KEY")), out _);
var signature = rsaProvider.SignData(Encoding.UTF8.GetBytes(stringToSign), sha256);
return Convert.ToBase64String(signature);
}
}

54
Helpers/MastodonHelper.cs Normal file
View File

@ -0,0 +1,54 @@
using System.Net.Http.Headers;
namespace ImportDataAsRelay.Helpers;
public static class MastodonHelper
{
private static string TargetHost = Environment.GetEnvironmentVariable("TARGET_HOST");
private static string RelayHost = Environment.GetEnvironmentVariable("RELAY_HOST");
public static async Task EnqueueStatusToFetch(string statusUrl)
{
var client = new HttpClient();
var date = DateTime.UtcNow;
var content = $@"{{
""@context"": ""https://www.w3.org/ns/activitystreams"",
""actor"": ""https://{RelayHost}/actor"",
""id"": ""https://{RelayHost}/activities/23af173e-e1fd-4283-93eb-514f1e5e5408"",
""object"": ""{statusUrl}"",
""to"": [
""https://{RelayHost}/followers""
],
""type"": ""Announce""
}}";
var digest = CryptoHelper.GetSHA256Digest(content);
var requestContent = new StringContent(content);
requestContent.Headers.Add("Digest", "SHA-256=" + digest);
var stringToSign = $"(request-target): post /inbox\ndate: {date.ToString("R")}\nhost: {TargetHost}\ndigest: SHA-256={digest}\ncontent-length: {content.Length}";
var signature = CryptoHelper.Sign(stringToSign);
requestContent.Headers.Add("Signature", $@"keyId=""https://{RelayHost}/actor#main-key"",algorithm=""rsa-sha256"",headers=""(request-target) date host digest content-length"",signature=""{signature}""");
requestContent.Headers.ContentType = new MediaTypeHeaderValue("application/activity+json");
client.DefaultRequestHeaders.Date = date;
var response = await client.PostAsync($"https://{TargetHost}/inbox", requestContent);
try
{
response.EnsureSuccessStatusCode();
}
catch (Exception e)
{
Console.WriteLine("Error: " + e.Message);
Console.WriteLine("Status code: " + response.StatusCode);
var body = await response.Content.ReadAsStringAsync();
Console.WriteLine("Response content: " + body);
throw;
}
}
}

14
ImportDataAsRelay.csproj Normal file
View File

@ -0,0 +1,14 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net6.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Jil" Version="2.17.0" />
</ItemGroup>
</Project>

53
Program.cs Normal file
View File

@ -0,0 +1,53 @@
using ImportDataAsRelay.Helpers;
using Jil;
var interestingTagsEverywhere = new[] { "dotnet", "csharp" };
var sources = new Dictionary<string, string[]>
{
["hachyderm.io"] = new [] { "hachyderm" },
["mastodon.social"] = Array.Empty<string>(),
["dotnet.social"] = Array.Empty<string>(),
};
var client = new HttpClient();
foreach (var (site, specificTags) in sources)
{
var tags = specificTags.Concat(interestingTagsEverywhere).ToList();
foreach (var tag in tags)
{
Console.WriteLine($"Fetching tag #{tag} from {site}");
var response = await client.GetAsync($"https://{site}/tags/{tag}.json");
try
{
response.EnsureSuccessStatusCode();
}
catch (Exception e)
{
Console.WriteLine($"Error fetching tag, status code: {response.StatusCode}. Error: {e.Message}");
continue;
}
var json = await response.Content.ReadAsStringAsync();
var data = JSON.Deserialize<TagResponse>(json, Options.CamelCase);
foreach (var statusLink in data.OrderedItems)
{
Console.WriteLine($"Bringing in {statusLink}");
try
{
await MastodonHelper.EnqueueStatusToFetch(statusLink);
await Task.Delay(500);
}
catch (Exception e)
{
Console.WriteLine($"{e.Message}");
}
}
}
}
public class TagResponse
{
public string[] OrderedItems { get; private set; }
}