From e51aacfb228d2a397d5297599852ec3c973b03fe Mon Sep 17 00:00:00 2001 From: Nicolas Constant Date: Thu, 28 Jan 2021 18:47:45 -0500 Subject: [PATCH] added protected support --- .../Models/ActivityRejectFollow.cs | 10 +++ src/BirdsiteLive.ActivityPub/Models/Actor.cs | 1 + src/BirdsiteLive.Domain/UserService.cs | 68 +++++++++++++------ .../Models/TwitterUser.cs | 1 + .../TwitterTweetsService.cs | 2 +- .../TwitterUserService.cs | 3 +- .../Controllers/UsersController.cs | 1 + src/BirdsiteLive/Models/DisplayTwitterUser.cs | 1 + src/BirdsiteLive/Views/Users/Index.cshtml | 17 ++++- 9 files changed, 79 insertions(+), 25 deletions(-) create mode 100644 src/BirdsiteLive.ActivityPub/Models/ActivityRejectFollow.cs diff --git a/src/BirdsiteLive.ActivityPub/Models/ActivityRejectFollow.cs b/src/BirdsiteLive.ActivityPub/Models/ActivityRejectFollow.cs new file mode 100644 index 0000000..da5d613 --- /dev/null +++ b/src/BirdsiteLive.ActivityPub/Models/ActivityRejectFollow.cs @@ -0,0 +1,10 @@ +using Newtonsoft.Json; + +namespace BirdsiteLive.ActivityPub +{ + public class ActivityRejectFollow : Activity + { + [JsonProperty("object")] + public ActivityFollow apObject { get; set; } + } +} \ No newline at end of file diff --git a/src/BirdsiteLive.ActivityPub/Models/Actor.cs b/src/BirdsiteLive.ActivityPub/Models/Actor.cs index 886b862..713ea89 100644 --- a/src/BirdsiteLive.ActivityPub/Models/Actor.cs +++ b/src/BirdsiteLive.ActivityPub/Models/Actor.cs @@ -17,6 +17,7 @@ namespace BirdsiteLive.ActivityPub public string name { get; set; } public string summary { get; set; } public string url { get; set; } + public bool manuallyApprovesFollowers { get; set; } public string inbox { get; set; } public bool? discoverable { get; set; } = true; public PublicKey publicKey { get; set; } diff --git a/src/BirdsiteLive.Domain/UserService.cs b/src/BirdsiteLive.Domain/UserService.cs index 69cdb87..b666c29 100644 --- a/src/BirdsiteLive.Domain/UserService.cs +++ b/src/BirdsiteLive.Domain/UserService.cs @@ -12,6 +12,7 @@ using BirdsiteLive.Cryptography; using BirdsiteLive.Domain.BusinessUseCases; using BirdsiteLive.Domain.Statistics; using BirdsiteLive.Domain.Tools; +using BirdsiteLive.Twitter; using BirdsiteLive.Twitter.Models; using Tweetinvi.Core.Exceptions; using Tweetinvi.Models; @@ -36,8 +37,10 @@ namespace BirdsiteLive.Domain private readonly IStatusExtractor _statusExtractor; private readonly IExtractionStatisticsHandler _statisticsHandler; + private readonly ITwitterUserService _twitterUserService; + #region Ctor - public UserService(InstanceSettings instanceSettings, ICryptoService cryptoService, IActivityPubService activityPubService, IProcessFollowUser processFollowUser, IProcessUndoFollowUser processUndoFollowUser, IStatusExtractor statusExtractor, IExtractionStatisticsHandler statisticsHandler) + public UserService(InstanceSettings instanceSettings, ICryptoService cryptoService, IActivityPubService activityPubService, IProcessFollowUser processFollowUser, IProcessUndoFollowUser processUndoFollowUser, IStatusExtractor statusExtractor, IExtractionStatisticsHandler statisticsHandler, ITwitterUserService twitterUserService) { _instanceSettings = instanceSettings; _cryptoService = cryptoService; @@ -46,7 +49,7 @@ namespace BirdsiteLive.Domain _processUndoFollowUser = processUndoFollowUser; _statusExtractor = statusExtractor; _statisticsHandler = statisticsHandler; - //_host = $"https://{instanceSettings.Domain.Replace("https://",string.Empty).Replace("http://", string.Empty).TrimEnd('/')}"; + _twitterUserService = twitterUserService; } #endregion @@ -75,6 +78,7 @@ namespace BirdsiteLive.Domain inbox = $"{actorUrl}/inbox", summary = description, url = actorUrl, + manuallyApprovesFollowers = twitterUser.Protected, publicKey = new PublicKey() { id = $"{actorUrl}#main-key", @@ -125,26 +129,50 @@ namespace BirdsiteLive.Domain followerInbox = OnlyKeepRoute(followerInbox, followerHost); followerSharedInbox = OnlyKeepRoute(followerSharedInbox, followerHost); - // Execute - await _processFollowUser.ExecuteAsync(followerUserName, followerHost, twitterUser, followerInbox, followerSharedInbox); - - // Send Accept Activity - var acceptFollow = new ActivityAcceptFollow() + var user = _twitterUserService.GetUser(twitterUser); + if (!user.Protected) { - context = "https://www.w3.org/ns/activitystreams", - id = $"{activity.apObject}#accepts/follows/{Guid.NewGuid()}", - type = "Accept", - actor = activity.apObject, - apObject = new ActivityFollow() + // Execute + await _processFollowUser.ExecuteAsync(followerUserName, followerHost, twitterUser, followerInbox, followerSharedInbox); + + // Send Accept Activity + var acceptFollow = new ActivityAcceptFollow() { - id = activity.id, - type = activity.type, - actor = activity.actor, - apObject = activity.apObject - } - }; - var result = await _activityPubService.PostDataAsync(acceptFollow, followerHost, activity.apObject); - return result == HttpStatusCode.Accepted || result == HttpStatusCode.OK; //TODO: revamp this for better error handling + context = "https://www.w3.org/ns/activitystreams", + id = $"{activity.apObject}#accepts/follows/{Guid.NewGuid()}", + type = "Accept", + actor = activity.apObject, + apObject = new ActivityFollow() + { + id = activity.id, + type = activity.type, + actor = activity.actor, + apObject = activity.apObject + } + }; + var result = await _activityPubService.PostDataAsync(acceptFollow, followerHost, activity.apObject); + return result == HttpStatusCode.Accepted || result == HttpStatusCode.OK; //TODO: revamp this for better error handling + } + else + { + // Send Reject Activity + var acceptFollow = new ActivityRejectFollow() + { + context = "https://www.w3.org/ns/activitystreams", + id = $"{activity.apObject}#rejects/follows/{Guid.NewGuid()}", + type = "Reject", + actor = activity.apObject, + apObject = new ActivityFollow() + { + id = activity.id, + type = activity.type, + actor = activity.actor, + apObject = activity.apObject + } + }; + var result = await _activityPubService.PostDataAsync(acceptFollow, followerHost, activity.apObject); + return result == HttpStatusCode.Accepted || result == HttpStatusCode.OK; //TODO: revamp this for better error handling + } } private string OnlyKeepRoute(string inbox, string host) diff --git a/src/BirdsiteLive.Twitter/Models/TwitterUser.cs b/src/BirdsiteLive.Twitter/Models/TwitterUser.cs index 1db3350..0403366 100644 --- a/src/BirdsiteLive.Twitter/Models/TwitterUser.cs +++ b/src/BirdsiteLive.Twitter/Models/TwitterUser.cs @@ -10,5 +10,6 @@ public string ProfileBackgroundImageUrl { get; set; } public string Acct { get; set; } public string ProfileBannerURL { get; set; } + public bool Protected { get; set; } } } \ No newline at end of file diff --git a/src/BirdsiteLive.Twitter/TwitterTweetsService.cs b/src/BirdsiteLive.Twitter/TwitterTweetsService.cs index dd9e29e..e67b125 100644 --- a/src/BirdsiteLive.Twitter/TwitterTweetsService.cs +++ b/src/BirdsiteLive.Twitter/TwitterTweetsService.cs @@ -61,9 +61,9 @@ namespace BirdsiteLive.Twitter TweetinviConfig.CurrentThreadSettings.TweetMode = TweetMode.Extended; var user = _twitterUserService.GetUser(username); + if (user.Protected) return new ExtractedTweet[0]; var tweets = new List(); - try { if (fromTweetId == -1) diff --git a/src/BirdsiteLive.Twitter/TwitterUserService.cs b/src/BirdsiteLive.Twitter/TwitterUserService.cs index 69ecc45..e7d44c3 100644 --- a/src/BirdsiteLive.Twitter/TwitterUserService.cs +++ b/src/BirdsiteLive.Twitter/TwitterUserService.cs @@ -60,7 +60,8 @@ namespace BirdsiteLive.Twitter Url = $"https://twitter.com/{username}", ProfileImageUrl = user.ProfileImageUrlFullSize, ProfileBackgroundImageUrl = user.ProfileBackgroundImageUrlHttps, - ProfileBannerURL = user.ProfileBannerURL + ProfileBannerURL = user.ProfileBannerURL, + Protected = user.Protected }; } } diff --git a/src/BirdsiteLive/Controllers/UsersController.cs b/src/BirdsiteLive/Controllers/UsersController.cs index f91b3cf..d291c67 100644 --- a/src/BirdsiteLive/Controllers/UsersController.cs +++ b/src/BirdsiteLive/Controllers/UsersController.cs @@ -79,6 +79,7 @@ namespace BirdsiteLive.Controllers Acct = user.Acct.ToLowerInvariant(), Url = user.Url, ProfileImageUrl = user.ProfileImageUrl, + Protected = user.Protected, InstanceHandle = $"@{user.Acct.ToLowerInvariant()}@{_instanceSettings.Domain}" }; diff --git a/src/BirdsiteLive/Models/DisplayTwitterUser.cs b/src/BirdsiteLive/Models/DisplayTwitterUser.cs index 58ba348..3a93875 100644 --- a/src/BirdsiteLive/Models/DisplayTwitterUser.cs +++ b/src/BirdsiteLive/Models/DisplayTwitterUser.cs @@ -7,6 +7,7 @@ public string Acct { get; set; } public string Url { get; set; } public string ProfileImageUrl { get; set; } + public bool Protected { get; set; } public string InstanceHandle { get; set; } } diff --git a/src/BirdsiteLive/Views/Users/Index.cshtml b/src/BirdsiteLive/Views/Users/Index.cshtml index af5929d..945964a 100644 --- a/src/BirdsiteLive/Views/Users/Index.cshtml +++ b/src/BirdsiteLive/Views/Users/Index.cshtml @@ -21,7 +21,6 @@ @*

@@@ViewData.Model.Acct

*@ -
@ViewData.Model.Description
@@ -31,7 +30,19 @@

-

Search this handle to find it in your instance:

- + @if (ViewData.Model.Protected) + { + + } + else + { +
+

Search this handle to find it in your instance:

+ + +
+ } \ No newline at end of file