Add remote follow from the corpse of twtr.plus
Some checks reported errors
continuous-integration/drone/push Build was killed
Some checks reported errors
continuous-integration/drone/push Build was killed
This commit is contained in:
parent
fa5b50f92b
commit
d7fa6f04ff
4 changed files with 86 additions and 2 deletions
21
src/BirdsiteLive.ActivityPub/Models/WebFingerData.cs
Normal file
21
src/BirdsiteLive.ActivityPub/Models/WebFingerData.cs
Normal 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; }
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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>
|
||||
|
|
Reference in a new issue