Add remote follow from the corpse of twtr.plus
Some checks reported errors
continuous-integration/drone/push Build was killed

This commit is contained in:
Sam Therapy 2023-04-03 21:47:20 +02:00
parent fa5b50f92b
commit d7fa6f04ff
Signed by: sam
GPG key ID: 4D8B07C18F31ACBD
4 changed files with 86 additions and 2 deletions

View file

@ -0,0 +1,21 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace BirdsiteLive.ActivityPub.Models
{
public class WebFingerData
{
public List<string> aliases { get; set; }
public List<WebFingerLink> links { get; set; }
}
public class WebFingerLink
{
public string href { get; set; }
public string rel { get; set; }
public string type { get; set; }
public string template { get; set; }
}
}

View file

@ -24,6 +24,7 @@ namespace BirdsiteLive.Domain
string targetInbox);
ActivityAcceptFollow BuildAcceptFollow(ActivityFollow activity);
Task<WebFingerData> WebFinger(string account);
}
public class ActivityPubService : IActivityPubService
@ -139,5 +140,14 @@ namespace BirdsiteLive.Domain
return response.StatusCode;
}
public async Task<WebFingerData> WebFinger(string account)
{
var httpClient = _httpClientFactory.CreateClient();
var result = await httpClient.GetAsync("https://" + account.Split('@')[1] + "/.well-known/webfinger?resource=acct:" + account);
var content = await result.Content.ReadAsStringAsync();
return JsonSerializer.Deserialize<WebFingerData>(content);
}
}
}

View file

@ -30,16 +30,18 @@ namespace BirdsiteLive.Controllers
private readonly IUserService _userService;
private readonly IStatusService _statusService;
private readonly InstanceSettings _instanceSettings;
private readonly IActivityPubService _activityPubService;
private readonly ILogger<UsersController> _logger;
#region Ctor
public UsersController(ICachedTwitterUserService twitterUserService, IUserService userService, IStatusService statusService, InstanceSettings instanceSettings, ICachedTwitterTweetsService twitterTweetService, ILogger<UsersController> logger)
public UsersController(ICachedTwitterUserService twitterUserService, IUserService userService, IStatusService statusService, InstanceSettings instanceSettings, ICachedTwitterTweetsService twitterTweetService, IActivityPubService activityPubService, ILogger<UsersController> logger)
{
_twitterUserService = twitterUserService;
_userService = userService;
_statusService = statusService;
_instanceSettings = instanceSettings;
_twitterTweetService = twitterTweetService;
_activityPubService = activityPubService;
_logger = logger;
}
#endregion
@ -272,5 +274,51 @@ namespace BirdsiteLive.Controllers
var jsonApUser = JsonSerializer.Serialize(followers);
return Content(jsonApUser, "application/activity+json; charset=utf-8");
}
[Route("/users/{actor}/remote_follow")]
[HttpPost]
public async Task<IActionResult> RemoteFollow(string actor)
{
StringValues webfingerValues;
if (!Request.Form.TryGetValue("webfinger", out webfingerValues)) return BadRequest();
var webfinger = webfingerValues.First();
if (webfinger.Length < 1 || actor.Length < 1) return BadRequest();
if (webfinger[0] == '@') webfinger = webfinger[1..];
if (webfinger.IndexOf("@") < 0 || ! new Regex("^[A-Za-z0-9_]*$").IsMatch(webfinger.Split('@')[0]) || ! new Regex("^[A-Za-z0-9_]*$").IsMatch(actor) || Uri.CheckHostName(webfinger.Split('@')[1]) == UriHostNameType.Unknown)
{
return BadRequest();
}
WebFingerData webfingerData;
try
{
webfingerData = await _activityPubService.WebFinger(webfinger);
}
catch(Exception e)
{
_logger.LogError("Could not WebFinger {user}: {exception}", webfinger, e);
return NotFound();
}
string redirectLink = "";
foreach(var link in webfingerData.links)
{
if(link.rel == "http://ostatus.org/schema/1.0/subscribe" && link.template.Length > 0)
{
redirectLink = link.template.Replace("{uri}", "https://" + _instanceSettings.Domain + "/users/" + actor);
}
}
if (redirectLink == "") return NotFound();
return Redirect(redirectLink);
}
}
}

View file

@ -39,7 +39,12 @@
else
{
<div>
<p>Search this handle to find it in your instance:</p>
<form action="/users/@ViewData.Model.Acct/remote_follow" method="post">
<input type="text" class="form-control mb-2" placeholder="your handle, i.e. @@lain@@pleroma.com" name="webfinger" />
<input type="submit" class="btn btn-primary w-100 mb-2" value="Remote follow" />
</form>
<p>or search this handle to find it in your instance:</p>
<input type="text" name="textbox" value="@ViewData.Model.InstanceHandle" onclick="this.select()" class="form-control" readonly />
</div>