Remote follow

This commit is contained in:
Miss Pasture 2021-07-17 20:26:45 -04:00
parent 3cf3f95ccb
commit af8345d8c9
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

@ -21,6 +21,7 @@ namespace BirdsiteLive.Domain
Task<HttpStatusCode> PostDataAsync<T>(T data, string targetHost, string actorUrl, string inbox = null);
Task PostNewNoteActivity(Note note, string username, string noteId, string targetHost,
string targetInbox);
Task<WebFingerData> WebFinger(string account);
}
public class ActivityPubService : IActivityPubService
@ -118,5 +119,14 @@ namespace BirdsiteLive.Domain
response.EnsureSuccessStatusCode();
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 JsonConvert.DeserializeObject<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(ITwitterUserService twitterUserService, IUserService userService, IStatusService statusService, InstanceSettings instanceSettings, ITwitterTweetsService twitterTweetService, ILogger<UsersController> logger)
public UsersController(ITwitterUserService twitterUserService, IUserService userService, IStatusService statusService, InstanceSettings instanceSettings, ITwitterTweetsService twitterTweetService, IActivityPubService activityPubService, ILogger<UsersController> logger)
{
_twitterUserService = twitterUserService;
_userService = userService;
_statusService = statusService;
_instanceSettings = instanceSettings;
_twitterTweetService = twitterTweetService;
_activityPubService = activityPubService;
_logger = logger;
}
#endregion
@ -188,5 +190,51 @@ namespace BirdsiteLive.Controllers
{
return header.ToDictionary<KeyValuePair<string, StringValues>, string, string>(h => h.Key.ToLowerInvariant(), h => h.Value);
}
[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

@ -40,7 +40,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. @@pasture@@pl.gamers.exposed" 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>