added migration logic

This commit is contained in:
Nicolas Constant 2022-11-04 02:07:50 -04:00
parent 498134f215
commit df68b9c370
No known key found for this signature in database
GPG key ID: 1E9F677FB01A5688
4 changed files with 104 additions and 19 deletions

View file

@ -4,19 +4,30 @@ using BirdsiteLive.Twitter;
using System.Security.Cryptography;
using System.Text;
using System.Threading.Tasks;
using BirdsiteLive.ActivityPub;
using BirdsiteLive.ActivityPub.Models;
using BirdsiteLive.DAL.Contracts;
using BirdsiteLive.ActivityPub.Converters;
using BirdsiteLive.Common.Settings;
namespace BirdsiteLive.Domain
{
public class MigrationService
{
private readonly InstanceSettings _instanceSettings;
private readonly ITwitterTweetsService _twitterTweetsService;
private readonly IActivityPubService _activityPubService;
private readonly ITwitterUserDal _twitterUserDal;
private readonly IFollowersDal _followersDal;
#region Ctor
public MigrationService(ITwitterTweetsService twitterTweetsService, IActivityPubService activityPubService)
public MigrationService(ITwitterTweetsService twitterTweetsService, IActivityPubService activityPubService, ITwitterUserDal twitterUserDal, IFollowersDal followersDal, InstanceSettings instanceSettings)
{
_twitterTweetsService = twitterTweetsService;
_activityPubService = activityPubService;
_twitterUserDal = twitterUserDal;
_followersDal = followersDal;
_instanceSettings = instanceSettings;
}
#endregion
@ -33,8 +44,14 @@ namespace BirdsiteLive.Domain
var castedTweetId = ExtractedTweetId(tweetId);
var tweet = _twitterTweetsService.GetTweet(castedTweetId);
if (tweet == null) throw new Exception("Tweet not found");
if (!tweet.MessageContent.Contains(code)) throw new Exception("Tweet don't have migration code");
if (tweet == null)
throw new Exception("Tweet not found");
if (tweet.CreatorName.Trim().ToLowerInvariant() != acct.Trim().ToLowerInvariant())
throw new Exception($"Tweet not published by @{acct}");
if (!tweet.MessageContent.Contains(code))
throw new Exception("Tweet don't have migration code");
return true;
}
@ -52,25 +69,81 @@ namespace BirdsiteLive.Domain
throw new ArgumentException("Unvalid Tweet ID");
}
public async Task<bool> ValidateFediverseAcctAsync(string fediverseAcct)
public async Task<ValidatedFediverseUser> ValidateFediverseAcctAsync(string fediverseAcct)
{
if (string.IsNullOrWhiteSpace(fediverseAcct))
throw new ArgumentException("Please provide Fediverse account");
if( !fediverseAcct.Contains('@') || fediverseAcct.Trim('@').Split('@').Length != 2)
if( !fediverseAcct.Contains('@') || !fediverseAcct.StartsWith("@") || fediverseAcct.Trim('@').Split('@').Length != 2)
throw new ArgumentException("Please provide valid Fediverse handle");
var objectId = await _activityPubService.GetUserIdAsync(fediverseAcct);
var user = await _activityPubService.GetUser(objectId);
if(user != null) return true;
var result = new ValidatedFediverseUser
{
FediverseAcct = fediverseAcct,
ObjectId = objectId,
User = user,
IsValid = user != null
};
return false;
return result;
}
public async Task MigrateAccountAsync(string acct, string tweetId, string fediverseAcct, bool triggerRemoteMigration)
public async Task MigrateAccountAsync(ValidatedFediverseUser validatedUser, string acct)
{
throw new NotImplementedException("Migration not implemented");
// Apply moved to
var twitterAccount = await _twitterUserDal.GetTwitterUserAsync(acct);
twitterAccount.MovedTo = validatedUser.ObjectId;
twitterAccount.MovedToAcct = validatedUser.FediverseAcct;
await _twitterUserDal.UpdateTwitterUserAsync(twitterAccount);
// Notify Followers
var t = Task.Run(async () =>
{
var followers = await _followersDal.GetFollowersAsync(twitterAccount.Id);
foreach (var follower in followers)
{
try
{
var noteId = Guid.NewGuid().ToString();
var actorUrl = UrlFactory.GetActorUrl(_instanceSettings.Domain, acct);
var noteUrl = UrlFactory.GetNoteUrl(_instanceSettings.Domain, acct, noteId);
var to = validatedUser.ObjectId;
var cc = new string[0];
var note = new Note
{
id = noteId,
published = DateTime.UtcNow.ToString("s") + "Z",
url = noteUrl,
attributedTo = actorUrl,
to = new[] { to },
cc = cc,
content = $@"<p>[MIRROR SERVICE NOTIFICATION]<br/>
This bot has been disabled by it's original owner.<br/>
It has been redirected to {validatedUser.FediverseAcct}.
</p>"
};
await _activityPubService.PostNewNoteActivity(note, acct, Guid.NewGuid().ToString(), follower.Host, follower.InboxRoute);
}
catch (Exception e)
{
Console.WriteLine(e);
}
}
});
}
public async Task TriggerRemoteMigrationAsync(string id, string tweetid, string handle)
{
//TODO
}
private byte[] GetHash(string inputString)
@ -88,4 +161,12 @@ namespace BirdsiteLive.Domain
return sb.ToString();
}
}
public class ValidatedFediverseUser
{
public string FediverseAcct { get; set; }
public string ObjectId { get; set; }
public Actor User { get; set; }
public bool IsValid { get; set; }
}
}

View file

@ -28,7 +28,8 @@ namespace BirdsiteLive.Twitter.Extractors
IsReply = tweet.InReplyToUserId != null,
IsThread = tweet.InReplyToUserId != null && tweet.InReplyToUserId == tweet.CreatedBy.Id,
IsRetweet = tweet.IsRetweet || tweet.QuotedStatusId != null,
RetweetUrl = ExtractRetweetUrl(tweet)
RetweetUrl = ExtractRetweetUrl(tweet),
CreatorName = tweet.CreatedBy.Name
};
return extractedTweet;

View file

@ -15,5 +15,6 @@ namespace BirdsiteLive.Twitter.Models
public bool IsThread { get; set; }
public bool IsRetweet { get; set; }
public string RetweetUrl { get; set; }
public string CreatorName { get; set; }
}
}

View file

@ -51,25 +51,27 @@ namespace BirdsiteLive.Controllers
FediverseAccount = handle
};
ValidatedFediverseUser fediverseUserValidation = null;
try
{
var isAcctValid = await _migrationService.ValidateFediverseAcctAsync(handle);
fediverseUserValidation = await _migrationService.ValidateFediverseAcctAsync(handle);
var isTweetValid = _migrationService.ValidateTweet(id, tweetid);
data.IsAcctValid = isAcctValid;
data.IsAcctValid = fediverseUserValidation.IsValid;
data.IsTweetValid = isTweetValid;
}
catch (Exception e)
{
data.ErrorMessage = e.Message;
}
if (data.IsAcctValid && data.IsTweetValid)
if (data.IsAcctValid && data.IsTweetValid && fediverseUserValidation != null)
{
try
{
await _migrationService.MigrateAccountAsync(id, tweetid, handle, true);
await _migrationService.MigrateAccountAsync(fediverseUserValidation, id);
await _migrationService.TriggerRemoteMigrationAsync(id, tweetid, handle);
data.MigrationSuccess = true;
}
catch (Exception e)
@ -86,12 +88,12 @@ namespace BirdsiteLive.Controllers
[Route("/migration/{id}/{tweetid}/{handle}")]
public async Task<IActionResult> RemoteMigrate(string id, string tweetid, string handle)
{
var isAcctValid = await _migrationService.ValidateFediverseAcctAsync(handle);
var fediverseUserValidation = await _migrationService.ValidateFediverseAcctAsync(handle);
var isTweetValid = _migrationService.ValidateTweet(id, tweetid);
if (isAcctValid && isTweetValid)
if (fediverseUserValidation.IsValid && isTweetValid)
{
await _migrationService.MigrateAccountAsync(id, tweetid, handle, false);
await _migrationService.MigrateAccountAsync(fediverseUserValidation, id);
return Ok();
}