Merge pull request #64 from NicolasConstant/topic_reply-publication
Topic reply publication
This commit is contained in:
commit
ffdd041a8c
11 changed files with 923 additions and 18 deletions
|
@ -10,4 +10,5 @@ You can configure some of BirdsiteLIVE's settings via environment variables (tho
|
|||
## Instance customization
|
||||
|
||||
* `Instance:Name` (default: BirdsiteLIVE) the name of the instance
|
||||
* `Instance:ResolveMentionsInProfiles` (default: true) to enable or disable mentions parsing in profile's description. Resolving it will consume more User's API calls since newly discovered account can also contain references to others accounts as well. On a big instance it is recommended to disable it.
|
||||
* `Instance:ResolveMentionsInProfiles` (default: true) to enable or disable mentions parsing in profile's description. Resolving it will consume more User's API calls since newly discovered account can also contain references to others accounts as well. On a big instance it is recommended to disable it.
|
||||
* `Instance:PublishReplies` (default: false) to enable or disable replies publishing.
|
|
@ -6,5 +6,6 @@
|
|||
public string Domain { get; set; }
|
||||
public string AdminEmail { get; set; }
|
||||
public bool ResolveMentionsInProfiles { get; set; }
|
||||
public bool PublishReplies { get; set; }
|
||||
}
|
||||
}
|
|
@ -3,6 +3,7 @@ using System.Collections.Generic;
|
|||
using System.Linq;
|
||||
using System.Net;
|
||||
using System.Threading.Tasks;
|
||||
using BirdsiteLive.Common.Settings;
|
||||
using BirdsiteLive.DAL.Contracts;
|
||||
using BirdsiteLive.DAL.Models;
|
||||
using BirdsiteLive.Domain;
|
||||
|
@ -21,15 +22,17 @@ namespace BirdsiteLive.Pipeline.Processors.SubTasks
|
|||
private readonly IActivityPubService _activityPubService;
|
||||
private readonly IStatusService _statusService;
|
||||
private readonly IFollowersDal _followersDal;
|
||||
private readonly InstanceSettings _settings;
|
||||
private readonly ILogger<SendTweetsToInboxTask> _logger;
|
||||
|
||||
|
||||
#region Ctor
|
||||
public SendTweetsToInboxTask(IActivityPubService activityPubService, IStatusService statusService, IFollowersDal followersDal, ILogger<SendTweetsToInboxTask> logger)
|
||||
public SendTweetsToInboxTask(IActivityPubService activityPubService, IStatusService statusService, IFollowersDal followersDal, InstanceSettings settings, ILogger<SendTweetsToInboxTask> logger)
|
||||
{
|
||||
_activityPubService = activityPubService;
|
||||
_statusService = statusService;
|
||||
_followersDal = followersDal;
|
||||
_settings = settings;
|
||||
_logger = logger;
|
||||
}
|
||||
#endregion
|
||||
|
@ -52,8 +55,13 @@ namespace BirdsiteLive.Pipeline.Processors.SubTasks
|
|||
{
|
||||
try
|
||||
{
|
||||
var note = _statusService.GetStatus(user.Acct, tweet);
|
||||
await _activityPubService.PostNewNoteActivity(note, user.Acct, tweet.Id.ToString(), follower.Host, inbox);
|
||||
if (!tweet.IsReply ||
|
||||
tweet.IsReply && tweet.IsThread ||
|
||||
_settings.PublishReplies)
|
||||
{
|
||||
var note = _statusService.GetStatus(user.Acct, tweet);
|
||||
await _activityPubService.PostNewNoteActivity(note, user.Acct, tweet.Id.ToString(), follower.Host, inbox);
|
||||
}
|
||||
}
|
||||
catch (ArgumentException e)
|
||||
{
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
using System.Linq;
|
||||
using System.Net;
|
||||
using System.Threading.Tasks;
|
||||
using BirdsiteLive.Common.Settings;
|
||||
using BirdsiteLive.DAL.Contracts;
|
||||
using BirdsiteLive.DAL.Models;
|
||||
using BirdsiteLive.Domain;
|
||||
|
@ -20,14 +21,16 @@ namespace BirdsiteLive.Pipeline.Processors.SubTasks
|
|||
private readonly IStatusService _statusService;
|
||||
private readonly IActivityPubService _activityPubService;
|
||||
private readonly IFollowersDal _followersDal;
|
||||
private readonly InstanceSettings _settings;
|
||||
private readonly ILogger<SendTweetsToSharedInboxTask> _logger;
|
||||
|
||||
#region Ctor
|
||||
public SendTweetsToSharedInboxTask(IActivityPubService activityPubService, IStatusService statusService, IFollowersDal followersDal, ILogger<SendTweetsToSharedInboxTask> logger)
|
||||
public SendTweetsToSharedInboxTask(IActivityPubService activityPubService, IStatusService statusService, IFollowersDal followersDal, InstanceSettings settings, ILogger<SendTweetsToSharedInboxTask> logger)
|
||||
{
|
||||
_activityPubService = activityPubService;
|
||||
_statusService = statusService;
|
||||
_followersDal = followersDal;
|
||||
_settings = settings;
|
||||
_logger = logger;
|
||||
}
|
||||
#endregion
|
||||
|
@ -52,8 +55,13 @@ namespace BirdsiteLive.Pipeline.Processors.SubTasks
|
|||
{
|
||||
try
|
||||
{
|
||||
var note = _statusService.GetStatus(user.Acct, tweet);
|
||||
await _activityPubService.PostNewNoteActivity(note, user.Acct, tweet.Id.ToString(), host, inbox);
|
||||
if (!tweet.IsReply ||
|
||||
tweet.IsReply && tweet.IsThread ||
|
||||
_settings.PublishReplies)
|
||||
{
|
||||
var note = _statusService.GetStatus(user.Acct, tweet);
|
||||
await _activityPubService.PostNewNoteActivity(note, user.Acct, tweet.Id.ToString(), host, inbox);
|
||||
}
|
||||
}
|
||||
catch (ArgumentException e)
|
||||
{
|
||||
|
@ -66,7 +74,7 @@ namespace BirdsiteLive.Pipeline.Processors.SubTasks
|
|||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
syncStatus = tweet.Id;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -24,7 +24,9 @@ namespace BirdsiteLive.Twitter.Extractors
|
|||
InReplyToAccount = tweet.InReplyToScreenName,
|
||||
MessageContent = ExtractMessage(tweet),
|
||||
Media = ExtractMedia(tweet.Media),
|
||||
CreatedAt = tweet.CreatedAt.ToUniversalTime()
|
||||
CreatedAt = tweet.CreatedAt.ToUniversalTime(),
|
||||
IsReply = tweet.InReplyToUserId != null,
|
||||
IsThread = tweet.InReplyToUserId != null && tweet.InReplyToUserId == tweet.CreatedBy.Id
|
||||
};
|
||||
return extractedTweet;
|
||||
}
|
||||
|
|
|
@ -11,5 +11,7 @@ namespace BirdsiteLive.Twitter.Models
|
|||
public ExtractedMedia[] Media { get; set; }
|
||||
public DateTime CreatedAt { get; set; }
|
||||
public string InReplyToAccount { get; set; }
|
||||
public bool IsReply { get; set; }
|
||||
public bool IsThread { get; set; }
|
||||
}
|
||||
}
|
|
@ -40,7 +40,7 @@ namespace BirdsiteLive.Twitter
|
|||
var tweet = Tweet.GetTweet(statusId);
|
||||
_statisticsHandler.CalledTweetApi();
|
||||
if (tweet == null) return null; //TODO: test this
|
||||
return _tweetExtractor.Extract(tweet);
|
||||
return _tweetExtractor.Extract(tweet);
|
||||
}
|
||||
|
||||
public ExtractedTweet[] GetTimeline(string username, int nberTweets, long fromTweetId = -1)
|
||||
|
|
|
@ -13,7 +13,8 @@
|
|||
"Name": "BirdsiteLIVE",
|
||||
"Domain": "domain.name",
|
||||
"AdminEmail": "me@domain.name",
|
||||
"ResolveMentionsInProfiles": true
|
||||
"ResolveMentionsInProfiles": true,
|
||||
"PublishReplies": false
|
||||
},
|
||||
"Db": {
|
||||
"Type": "postgres",
|
||||
|
|
|
@ -76,7 +76,7 @@ namespace BirdsiteLive.Pipeline.Tests.Processors
|
|||
processor.WaitFactor = 2;
|
||||
processor.GetTwitterUsersAsync(buffer, CancellationToken.None);
|
||||
|
||||
await Task.Delay(200);
|
||||
await Task.Delay(300);
|
||||
|
||||
#region Validations
|
||||
twitterUserDalMock.VerifyAll();
|
||||
|
|
|
@ -4,6 +4,7 @@ using System.Net;
|
|||
using System.Net.Http;
|
||||
using System.Threading.Tasks;
|
||||
using BirdsiteLive.ActivityPub.Models;
|
||||
using BirdsiteLive.Common.Settings;
|
||||
using BirdsiteLive.DAL.Contracts;
|
||||
using BirdsiteLive.DAL.Models;
|
||||
using BirdsiteLive.Domain;
|
||||
|
@ -54,6 +55,11 @@ namespace BirdsiteLive.Pipeline.Tests.Processors.SubTasks
|
|||
InboxRoute = inbox,
|
||||
FollowingsSyncStatus = new Dictionary<int, long> { { twitterUserId, 9 } }
|
||||
};
|
||||
|
||||
var settings = new InstanceSettings
|
||||
{
|
||||
PublishReplies = false
|
||||
};
|
||||
#endregion
|
||||
|
||||
#region Mocks
|
||||
|
@ -83,7 +89,239 @@ namespace BirdsiteLive.Pipeline.Tests.Processors.SubTasks
|
|||
var loggerMock = new Mock<ILogger<SendTweetsToInboxTask>>();
|
||||
#endregion
|
||||
|
||||
var task = new SendTweetsToInboxTask(activityPubService.Object, statusServiceMock.Object, followersDalMock.Object, loggerMock.Object);
|
||||
var task = new SendTweetsToInboxTask(activityPubService.Object, statusServiceMock.Object, followersDalMock.Object, settings, loggerMock.Object);
|
||||
await task.ExecuteAsync(tweets.ToArray(), follower, twitterUser);
|
||||
|
||||
#region Validations
|
||||
activityPubService.VerifyAll();
|
||||
statusServiceMock.VerifyAll();
|
||||
followersDalMock.VerifyAll();
|
||||
#endregion
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public async Task ExecuteAsync_SingleTweet_Reply_Test()
|
||||
{
|
||||
#region Stubs
|
||||
var tweetId = 10;
|
||||
var tweets = new List<ExtractedTweet>
|
||||
{
|
||||
new ExtractedTweet
|
||||
{
|
||||
Id = tweetId,
|
||||
IsReply = true,
|
||||
IsThread = false
|
||||
}
|
||||
};
|
||||
|
||||
var noteId = "noteId";
|
||||
var note = new Note()
|
||||
{
|
||||
id = noteId
|
||||
};
|
||||
|
||||
var twitterHandle = "Test";
|
||||
var twitterUserId = 7;
|
||||
var twitterUser = new SyncTwitterUser
|
||||
{
|
||||
Id = twitterUserId,
|
||||
Acct = twitterHandle
|
||||
};
|
||||
|
||||
var host = "domain.ext";
|
||||
var inbox = "/user/inbox";
|
||||
var follower = new Follower
|
||||
{
|
||||
Id = 1,
|
||||
Host = host,
|
||||
InboxRoute = inbox,
|
||||
FollowingsSyncStatus = new Dictionary<int, long> { { twitterUserId, 9 } }
|
||||
};
|
||||
|
||||
var settings = new InstanceSettings
|
||||
{
|
||||
PublishReplies = false
|
||||
};
|
||||
#endregion
|
||||
|
||||
#region Mocks
|
||||
var activityPubService = new Mock<IActivityPubService>(MockBehavior.Strict);
|
||||
var statusServiceMock = new Mock<IStatusService>(MockBehavior.Strict);
|
||||
|
||||
var followersDalMock = new Mock<IFollowersDal>(MockBehavior.Strict);
|
||||
followersDalMock
|
||||
.Setup(x => x.UpdateFollowerAsync(
|
||||
It.Is<Follower>(y => y.Id == follower.Id && y.FollowingsSyncStatus[twitterUserId] == tweetId)))
|
||||
.Returns(Task.CompletedTask);
|
||||
|
||||
var loggerMock = new Mock<ILogger<SendTweetsToInboxTask>>();
|
||||
#endregion
|
||||
|
||||
var task = new SendTweetsToInboxTask(activityPubService.Object, statusServiceMock.Object, followersDalMock.Object, settings, loggerMock.Object);
|
||||
await task.ExecuteAsync(tweets.ToArray(), follower, twitterUser);
|
||||
|
||||
#region Validations
|
||||
activityPubService.VerifyAll();
|
||||
statusServiceMock.VerifyAll();
|
||||
followersDalMock.VerifyAll();
|
||||
#endregion
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public async Task ExecuteAsync_SingleTweet_ReplyThread_Test()
|
||||
{
|
||||
#region Stubs
|
||||
var tweetId = 10;
|
||||
var tweets = new List<ExtractedTweet>
|
||||
{
|
||||
new ExtractedTweet
|
||||
{
|
||||
Id = tweetId,
|
||||
IsReply = true,
|
||||
IsThread = true
|
||||
}
|
||||
};
|
||||
|
||||
var noteId = "noteId";
|
||||
var note = new Note()
|
||||
{
|
||||
id = noteId
|
||||
};
|
||||
|
||||
var twitterHandle = "Test";
|
||||
var twitterUserId = 7;
|
||||
var twitterUser = new SyncTwitterUser
|
||||
{
|
||||
Id = twitterUserId,
|
||||
Acct = twitterHandle
|
||||
};
|
||||
|
||||
var host = "domain.ext";
|
||||
var inbox = "/user/inbox";
|
||||
var follower = new Follower
|
||||
{
|
||||
Id = 1,
|
||||
Host = host,
|
||||
InboxRoute = inbox,
|
||||
FollowingsSyncStatus = new Dictionary<int, long> { { twitterUserId, 9 } }
|
||||
};
|
||||
|
||||
var settings = new InstanceSettings
|
||||
{
|
||||
PublishReplies = false
|
||||
};
|
||||
#endregion
|
||||
|
||||
#region Mocks
|
||||
var activityPubService = new Mock<IActivityPubService>(MockBehavior.Strict);
|
||||
activityPubService
|
||||
.Setup(x => x.PostNewNoteActivity(
|
||||
It.Is<Note>(y => y.id == noteId),
|
||||
It.Is<string>(y => y == twitterHandle),
|
||||
It.Is<string>(y => y == tweetId.ToString()),
|
||||
It.Is<string>(y => y == host),
|
||||
It.Is<string>(y => y == inbox)))
|
||||
.Returns(Task.CompletedTask);
|
||||
|
||||
var statusServiceMock = new Mock<IStatusService>(MockBehavior.Strict);
|
||||
statusServiceMock
|
||||
.Setup(x => x.GetStatus(
|
||||
It.Is<string>(y => y == twitterHandle),
|
||||
It.Is<ExtractedTweet>(y => y.Id == tweetId)))
|
||||
.Returns(note);
|
||||
|
||||
var followersDalMock = new Mock<IFollowersDal>(MockBehavior.Strict);
|
||||
followersDalMock
|
||||
.Setup(x => x.UpdateFollowerAsync(
|
||||
It.Is<Follower>(y => y.Id == follower.Id && y.FollowingsSyncStatus[twitterUserId] == tweetId)))
|
||||
.Returns(Task.CompletedTask);
|
||||
|
||||
var loggerMock = new Mock<ILogger<SendTweetsToInboxTask>>();
|
||||
#endregion
|
||||
|
||||
var task = new SendTweetsToInboxTask(activityPubService.Object, statusServiceMock.Object, followersDalMock.Object, settings, loggerMock.Object);
|
||||
await task.ExecuteAsync(tweets.ToArray(), follower, twitterUser);
|
||||
|
||||
#region Validations
|
||||
activityPubService.VerifyAll();
|
||||
statusServiceMock.VerifyAll();
|
||||
followersDalMock.VerifyAll();
|
||||
#endregion
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public async Task ExecuteAsync_SingleTweet_PublishReply_Test()
|
||||
{
|
||||
#region Stubs
|
||||
var tweetId = 10;
|
||||
var tweets = new List<ExtractedTweet>
|
||||
{
|
||||
new ExtractedTweet
|
||||
{
|
||||
Id = tweetId,
|
||||
IsReply = true,
|
||||
IsThread = false
|
||||
}
|
||||
};
|
||||
|
||||
var noteId = "noteId";
|
||||
var note = new Note()
|
||||
{
|
||||
id = noteId
|
||||
};
|
||||
|
||||
var twitterHandle = "Test";
|
||||
var twitterUserId = 7;
|
||||
var twitterUser = new SyncTwitterUser
|
||||
{
|
||||
Id = twitterUserId,
|
||||
Acct = twitterHandle
|
||||
};
|
||||
|
||||
var host = "domain.ext";
|
||||
var inbox = "/user/inbox";
|
||||
var follower = new Follower
|
||||
{
|
||||
Id = 1,
|
||||
Host = host,
|
||||
InboxRoute = inbox,
|
||||
FollowingsSyncStatus = new Dictionary<int, long> { { twitterUserId, 9 } }
|
||||
};
|
||||
|
||||
var settings = new InstanceSettings
|
||||
{
|
||||
PublishReplies = true
|
||||
};
|
||||
#endregion
|
||||
|
||||
#region Mocks
|
||||
var activityPubService = new Mock<IActivityPubService>(MockBehavior.Strict);
|
||||
activityPubService
|
||||
.Setup(x => x.PostNewNoteActivity(
|
||||
It.Is<Note>(y => y.id == noteId),
|
||||
It.Is<string>(y => y == twitterHandle),
|
||||
It.Is<string>(y => y == tweetId.ToString()),
|
||||
It.Is<string>(y => y == host),
|
||||
It.Is<string>(y => y == inbox)))
|
||||
.Returns(Task.CompletedTask);
|
||||
|
||||
var statusServiceMock = new Mock<IStatusService>(MockBehavior.Strict);
|
||||
statusServiceMock
|
||||
.Setup(x => x.GetStatus(
|
||||
It.Is<string>(y => y == twitterHandle),
|
||||
It.Is<ExtractedTweet>(y => y.Id == tweetId)))
|
||||
.Returns(note);
|
||||
|
||||
var followersDalMock = new Mock<IFollowersDal>(MockBehavior.Strict);
|
||||
followersDalMock
|
||||
.Setup(x => x.UpdateFollowerAsync(
|
||||
It.Is<Follower>(y => y.Id == follower.Id && y.FollowingsSyncStatus[twitterUserId] == tweetId)))
|
||||
.Returns(Task.CompletedTask);
|
||||
|
||||
var loggerMock = new Mock<ILogger<SendTweetsToInboxTask>>();
|
||||
#endregion
|
||||
|
||||
var task = new SendTweetsToInboxTask(activityPubService.Object, statusServiceMock.Object, followersDalMock.Object, settings, loggerMock.Object);
|
||||
await task.ExecuteAsync(tweets.ToArray(), follower, twitterUser);
|
||||
|
||||
#region Validations
|
||||
|
@ -126,6 +364,11 @@ namespace BirdsiteLive.Pipeline.Tests.Processors.SubTasks
|
|||
InboxRoute = inbox,
|
||||
FollowingsSyncStatus = new Dictionary<int, long> { { twitterUserId, 10 } }
|
||||
};
|
||||
|
||||
var settings = new InstanceSettings
|
||||
{
|
||||
PublishReplies = false
|
||||
};
|
||||
#endregion
|
||||
|
||||
#region Mocks
|
||||
|
@ -161,7 +404,7 @@ namespace BirdsiteLive.Pipeline.Tests.Processors.SubTasks
|
|||
var loggerMock = new Mock<ILogger<SendTweetsToInboxTask>>();
|
||||
#endregion
|
||||
|
||||
var task = new SendTweetsToInboxTask(activityPubService.Object, statusServiceMock.Object, followersDalMock.Object, loggerMock.Object);
|
||||
var task = new SendTweetsToInboxTask(activityPubService.Object, statusServiceMock.Object, followersDalMock.Object, settings, loggerMock.Object);
|
||||
await task.ExecuteAsync(tweets.ToArray(), follower, twitterUser);
|
||||
|
||||
#region Validations
|
||||
|
@ -205,6 +448,11 @@ namespace BirdsiteLive.Pipeline.Tests.Processors.SubTasks
|
|||
InboxRoute = inbox,
|
||||
FollowingsSyncStatus = new Dictionary<int, long> { { twitterUserId, 10 } }
|
||||
};
|
||||
|
||||
var settings = new InstanceSettings
|
||||
{
|
||||
PublishReplies = false
|
||||
};
|
||||
#endregion
|
||||
|
||||
#region Mocks
|
||||
|
@ -247,7 +495,7 @@ namespace BirdsiteLive.Pipeline.Tests.Processors.SubTasks
|
|||
var loggerMock = new Mock<ILogger<SendTweetsToInboxTask>>();
|
||||
#endregion
|
||||
|
||||
var task = new SendTweetsToInboxTask(activityPubService.Object, statusServiceMock.Object, followersDalMock.Object, loggerMock.Object);
|
||||
var task = new SendTweetsToInboxTask(activityPubService.Object, statusServiceMock.Object, followersDalMock.Object, settings, loggerMock.Object);
|
||||
|
||||
try
|
||||
{
|
||||
|
@ -262,5 +510,147 @@ namespace BirdsiteLive.Pipeline.Tests.Processors.SubTasks
|
|||
#endregion
|
||||
}
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public async Task ExecuteAsync_SingleTweet_ParsingError_Test()
|
||||
{
|
||||
#region Stubs
|
||||
var tweetId = 10;
|
||||
var tweets = new List<ExtractedTweet>
|
||||
{
|
||||
new ExtractedTweet
|
||||
{
|
||||
Id = tweetId,
|
||||
}
|
||||
};
|
||||
|
||||
var noteId = "noteId";
|
||||
var note = new Note()
|
||||
{
|
||||
id = noteId
|
||||
};
|
||||
|
||||
var twitterHandle = "Test";
|
||||
var twitterUserId = 7;
|
||||
var twitterUser = new SyncTwitterUser
|
||||
{
|
||||
Id = twitterUserId,
|
||||
Acct = twitterHandle
|
||||
};
|
||||
|
||||
var host = "domain.ext";
|
||||
var inbox = "/user/inbox";
|
||||
var follower = new Follower
|
||||
{
|
||||
Id = 1,
|
||||
Host = host,
|
||||
InboxRoute = inbox,
|
||||
FollowingsSyncStatus = new Dictionary<int, long> { { twitterUserId, 9 } }
|
||||
};
|
||||
|
||||
var settings = new InstanceSettings
|
||||
{
|
||||
PublishReplies = false
|
||||
};
|
||||
#endregion
|
||||
|
||||
#region Mocks
|
||||
var activityPubService = new Mock<IActivityPubService>(MockBehavior.Strict);
|
||||
|
||||
var statusServiceMock = new Mock<IStatusService>(MockBehavior.Strict);
|
||||
statusServiceMock
|
||||
.Setup(x => x.GetStatus(
|
||||
It.Is<string>(y => y == twitterHandle),
|
||||
It.Is<ExtractedTweet>(y => y.Id == tweetId)))
|
||||
.Throws(new ArgumentException("Invalid pattern blabla at offset 9"));
|
||||
|
||||
var followersDalMock = new Mock<IFollowersDal>(MockBehavior.Strict);
|
||||
followersDalMock
|
||||
.Setup(x => x.UpdateFollowerAsync(
|
||||
It.Is<Follower>(y => y.Id == follower.Id && y.FollowingsSyncStatus[twitterUserId] == tweetId)))
|
||||
.Returns(Task.CompletedTask);
|
||||
|
||||
var loggerMock = new Mock<ILogger<SendTweetsToInboxTask>>();
|
||||
#endregion
|
||||
|
||||
var task = new SendTweetsToInboxTask(activityPubService.Object, statusServiceMock.Object, followersDalMock.Object, settings, loggerMock.Object);
|
||||
await task.ExecuteAsync(tweets.ToArray(), follower, twitterUser);
|
||||
|
||||
#region Validations
|
||||
activityPubService.VerifyAll();
|
||||
statusServiceMock.VerifyAll();
|
||||
followersDalMock.VerifyAll();
|
||||
#endregion
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
[ExpectedException(typeof(ArgumentException))]
|
||||
public async Task ExecuteAsync_SingleTweet_ArgumentException_Test()
|
||||
{
|
||||
#region Stubs
|
||||
var tweetId = 10;
|
||||
var tweets = new List<ExtractedTweet>
|
||||
{
|
||||
new ExtractedTweet
|
||||
{
|
||||
Id = tweetId,
|
||||
}
|
||||
};
|
||||
|
||||
var twitterHandle = "Test";
|
||||
var twitterUserId = 7;
|
||||
var twitterUser = new SyncTwitterUser
|
||||
{
|
||||
Id = twitterUserId,
|
||||
Acct = twitterHandle
|
||||
};
|
||||
|
||||
var host = "domain.ext";
|
||||
var inbox = "/user/inbox";
|
||||
var follower = new Follower
|
||||
{
|
||||
Id = 1,
|
||||
Host = host,
|
||||
InboxRoute = inbox,
|
||||
FollowingsSyncStatus = new Dictionary<int, long> { { twitterUserId, 9 } }
|
||||
};
|
||||
|
||||
var settings = new InstanceSettings
|
||||
{
|
||||
PublishReplies = false
|
||||
};
|
||||
#endregion
|
||||
|
||||
#region Mocks
|
||||
var activityPubService = new Mock<IActivityPubService>(MockBehavior.Strict);
|
||||
|
||||
var statusServiceMock = new Mock<IStatusService>(MockBehavior.Strict);
|
||||
statusServiceMock
|
||||
.Setup(x => x.GetStatus(
|
||||
It.Is<string>(y => y == twitterHandle),
|
||||
It.Is<ExtractedTweet>(y => y.Id == tweetId)))
|
||||
.Throws(new ArgumentException());
|
||||
|
||||
var followersDalMock = new Mock<IFollowersDal>(MockBehavior.Strict);
|
||||
|
||||
var loggerMock = new Mock<ILogger<SendTweetsToInboxTask>>();
|
||||
#endregion
|
||||
|
||||
var task = new SendTweetsToInboxTask(activityPubService.Object, statusServiceMock.Object, followersDalMock.Object, settings, loggerMock.Object);
|
||||
|
||||
try
|
||||
{
|
||||
await task.ExecuteAsync(tweets.ToArray(), follower, twitterUser);
|
||||
|
||||
}
|
||||
finally
|
||||
{
|
||||
#region Validations
|
||||
activityPubService.VerifyAll();
|
||||
statusServiceMock.VerifyAll();
|
||||
followersDalMock.VerifyAll();
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -5,6 +5,7 @@ using System.Net;
|
|||
using System.Net.Http;
|
||||
using System.Threading.Tasks;
|
||||
using BirdsiteLive.ActivityPub.Models;
|
||||
using BirdsiteLive.Common.Settings;
|
||||
using BirdsiteLive.DAL.Contracts;
|
||||
using BirdsiteLive.DAL.Models;
|
||||
using BirdsiteLive.Domain;
|
||||
|
@ -72,6 +73,11 @@ namespace BirdsiteLive.Pipeline.Tests.Processors.SubTasks
|
|||
FollowingsSyncStatus = new Dictionary<int, long> { { twitterUserId, 7 } }
|
||||
}
|
||||
};
|
||||
|
||||
var settings = new InstanceSettings
|
||||
{
|
||||
PublishReplies = false
|
||||
};
|
||||
#endregion
|
||||
|
||||
#region Mocks
|
||||
|
@ -105,7 +111,303 @@ namespace BirdsiteLive.Pipeline.Tests.Processors.SubTasks
|
|||
var loggerMock = new Mock<ILogger<SendTweetsToSharedInboxTask>>();
|
||||
#endregion
|
||||
|
||||
var task = new SendTweetsToSharedInboxTask(activityPubService.Object, statusServiceMock.Object, followersDalMock.Object, loggerMock.Object);
|
||||
var task = new SendTweetsToSharedInboxTask(activityPubService.Object, statusServiceMock.Object, followersDalMock.Object, settings, loggerMock.Object);
|
||||
await task.ExecuteAsync(tweets.ToArray(), twitterUser, host, followers.ToArray());
|
||||
|
||||
#region Validations
|
||||
activityPubService.VerifyAll();
|
||||
statusServiceMock.VerifyAll();
|
||||
followersDalMock.VerifyAll();
|
||||
#endregion
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public async Task ExecuteAsync_SingleTweet_Reply_Test()
|
||||
{
|
||||
#region Stubs
|
||||
var tweetId = 10;
|
||||
var tweets = new List<ExtractedTweet>
|
||||
{
|
||||
new ExtractedTweet
|
||||
{
|
||||
Id = tweetId,
|
||||
IsReply = true,
|
||||
IsThread = false
|
||||
}
|
||||
};
|
||||
|
||||
var noteId = "noteId";
|
||||
var note = new Note()
|
||||
{
|
||||
id = noteId
|
||||
};
|
||||
|
||||
var twitterHandle = "Test";
|
||||
var twitterUserId = 7;
|
||||
var twitterUser = new SyncTwitterUser
|
||||
{
|
||||
Id = twitterUserId,
|
||||
Acct = twitterHandle
|
||||
};
|
||||
|
||||
var host = "domain.ext";
|
||||
var inbox = "/inbox";
|
||||
var followers = new List<Follower>
|
||||
{
|
||||
new Follower
|
||||
{
|
||||
Id = 1,
|
||||
Host = host,
|
||||
SharedInboxRoute = inbox,
|
||||
FollowingsSyncStatus = new Dictionary<int, long> { { twitterUserId, 9 } }
|
||||
},
|
||||
new Follower
|
||||
{
|
||||
Id = 2,
|
||||
Host = host,
|
||||
SharedInboxRoute = inbox,
|
||||
FollowingsSyncStatus = new Dictionary<int, long> { { twitterUserId, 8 } }
|
||||
},
|
||||
new Follower
|
||||
{
|
||||
Id = 3,
|
||||
Host = host,
|
||||
SharedInboxRoute = inbox,
|
||||
FollowingsSyncStatus = new Dictionary<int, long> { { twitterUserId, 7 } }
|
||||
}
|
||||
};
|
||||
|
||||
var settings = new InstanceSettings
|
||||
{
|
||||
PublishReplies = false
|
||||
};
|
||||
#endregion
|
||||
|
||||
#region Mocks
|
||||
var activityPubService = new Mock<IActivityPubService>(MockBehavior.Strict);
|
||||
|
||||
var statusServiceMock = new Mock<IStatusService>(MockBehavior.Strict);
|
||||
|
||||
var followersDalMock = new Mock<IFollowersDal>(MockBehavior.Strict);
|
||||
|
||||
foreach (var follower in followers)
|
||||
{
|
||||
followersDalMock
|
||||
.Setup(x => x.UpdateFollowerAsync(
|
||||
It.Is<Follower>(y => y.Id == follower.Id && y.FollowingsSyncStatus[twitterUserId] == tweetId)))
|
||||
.Returns(Task.CompletedTask);
|
||||
}
|
||||
|
||||
var loggerMock = new Mock<ILogger<SendTweetsToSharedInboxTask>>();
|
||||
#endregion
|
||||
|
||||
var task = new SendTweetsToSharedInboxTask(activityPubService.Object, statusServiceMock.Object, followersDalMock.Object, settings, loggerMock.Object);
|
||||
await task.ExecuteAsync(tweets.ToArray(), twitterUser, host, followers.ToArray());
|
||||
|
||||
#region Validations
|
||||
activityPubService.VerifyAll();
|
||||
statusServiceMock.VerifyAll();
|
||||
followersDalMock.VerifyAll();
|
||||
#endregion
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public async Task ExecuteAsync_SingleTweet_ReplyThread_Test()
|
||||
{
|
||||
#region Stubs
|
||||
var tweetId = 10;
|
||||
var tweets = new List<ExtractedTweet>
|
||||
{
|
||||
new ExtractedTweet
|
||||
{
|
||||
Id = tweetId,
|
||||
IsReply = true,
|
||||
IsThread = true
|
||||
}
|
||||
};
|
||||
|
||||
var noteId = "noteId";
|
||||
var note = new Note()
|
||||
{
|
||||
id = noteId
|
||||
};
|
||||
|
||||
var twitterHandle = "Test";
|
||||
var twitterUserId = 7;
|
||||
var twitterUser = new SyncTwitterUser
|
||||
{
|
||||
Id = twitterUserId,
|
||||
Acct = twitterHandle
|
||||
};
|
||||
|
||||
var host = "domain.ext";
|
||||
var inbox = "/inbox";
|
||||
var followers = new List<Follower>
|
||||
{
|
||||
new Follower
|
||||
{
|
||||
Id = 1,
|
||||
Host = host,
|
||||
SharedInboxRoute = inbox,
|
||||
FollowingsSyncStatus = new Dictionary<int, long> { { twitterUserId, 9 } }
|
||||
},
|
||||
new Follower
|
||||
{
|
||||
Id = 2,
|
||||
Host = host,
|
||||
SharedInboxRoute = inbox,
|
||||
FollowingsSyncStatus = new Dictionary<int, long> { { twitterUserId, 8 } }
|
||||
},
|
||||
new Follower
|
||||
{
|
||||
Id = 3,
|
||||
Host = host,
|
||||
SharedInboxRoute = inbox,
|
||||
FollowingsSyncStatus = new Dictionary<int, long> { { twitterUserId, 7 } }
|
||||
}
|
||||
};
|
||||
|
||||
var settings = new InstanceSettings
|
||||
{
|
||||
PublishReplies = false
|
||||
};
|
||||
#endregion
|
||||
|
||||
#region Mocks
|
||||
var activityPubService = new Mock<IActivityPubService>(MockBehavior.Strict);
|
||||
activityPubService
|
||||
.Setup(x => x.PostNewNoteActivity(
|
||||
It.Is<Note>(y => y.id == noteId),
|
||||
It.Is<string>(y => y == twitterHandle),
|
||||
It.Is<string>(y => y == tweetId.ToString()),
|
||||
It.Is<string>(y => y == host),
|
||||
It.Is<string>(y => y == inbox)))
|
||||
.Returns(Task.CompletedTask);
|
||||
|
||||
var statusServiceMock = new Mock<IStatusService>(MockBehavior.Strict);
|
||||
statusServiceMock
|
||||
.Setup(x => x.GetStatus(
|
||||
It.Is<string>(y => y == twitterHandle),
|
||||
It.Is<ExtractedTweet>(y => y.Id == tweetId)))
|
||||
.Returns(note);
|
||||
|
||||
var followersDalMock = new Mock<IFollowersDal>(MockBehavior.Strict);
|
||||
|
||||
foreach (var follower in followers)
|
||||
{
|
||||
followersDalMock
|
||||
.Setup(x => x.UpdateFollowerAsync(
|
||||
It.Is<Follower>(y => y.Id == follower.Id && y.FollowingsSyncStatus[twitterUserId] == tweetId)))
|
||||
.Returns(Task.CompletedTask);
|
||||
}
|
||||
|
||||
var loggerMock = new Mock<ILogger<SendTweetsToSharedInboxTask>>();
|
||||
#endregion
|
||||
|
||||
var task = new SendTweetsToSharedInboxTask(activityPubService.Object, statusServiceMock.Object, followersDalMock.Object, settings, loggerMock.Object);
|
||||
await task.ExecuteAsync(tweets.ToArray(), twitterUser, host, followers.ToArray());
|
||||
|
||||
#region Validations
|
||||
activityPubService.VerifyAll();
|
||||
statusServiceMock.VerifyAll();
|
||||
followersDalMock.VerifyAll();
|
||||
#endregion
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public async Task ExecuteAsync_SingleTweet_PublishReply_Test()
|
||||
{
|
||||
#region Stubs
|
||||
var tweetId = 10;
|
||||
var tweets = new List<ExtractedTweet>
|
||||
{
|
||||
new ExtractedTweet
|
||||
{
|
||||
Id = tweetId,
|
||||
IsReply = true,
|
||||
IsThread = false
|
||||
}
|
||||
};
|
||||
|
||||
var noteId = "noteId";
|
||||
var note = new Note()
|
||||
{
|
||||
id = noteId
|
||||
};
|
||||
|
||||
var twitterHandle = "Test";
|
||||
var twitterUserId = 7;
|
||||
var twitterUser = new SyncTwitterUser
|
||||
{
|
||||
Id = twitterUserId,
|
||||
Acct = twitterHandle
|
||||
};
|
||||
|
||||
var host = "domain.ext";
|
||||
var inbox = "/inbox";
|
||||
var followers = new List<Follower>
|
||||
{
|
||||
new Follower
|
||||
{
|
||||
Id = 1,
|
||||
Host = host,
|
||||
SharedInboxRoute = inbox,
|
||||
FollowingsSyncStatus = new Dictionary<int, long> { { twitterUserId, 9 } }
|
||||
},
|
||||
new Follower
|
||||
{
|
||||
Id = 2,
|
||||
Host = host,
|
||||
SharedInboxRoute = inbox,
|
||||
FollowingsSyncStatus = new Dictionary<int, long> { { twitterUserId, 8 } }
|
||||
},
|
||||
new Follower
|
||||
{
|
||||
Id = 3,
|
||||
Host = host,
|
||||
SharedInboxRoute = inbox,
|
||||
FollowingsSyncStatus = new Dictionary<int, long> { { twitterUserId, 7 } }
|
||||
}
|
||||
};
|
||||
|
||||
var settings = new InstanceSettings
|
||||
{
|
||||
PublishReplies = true
|
||||
};
|
||||
#endregion
|
||||
|
||||
#region Mocks
|
||||
var activityPubService = new Mock<IActivityPubService>(MockBehavior.Strict);
|
||||
activityPubService
|
||||
.Setup(x => x.PostNewNoteActivity(
|
||||
It.Is<Note>(y => y.id == noteId),
|
||||
It.Is<string>(y => y == twitterHandle),
|
||||
It.Is<string>(y => y == tweetId.ToString()),
|
||||
It.Is<string>(y => y == host),
|
||||
It.Is<string>(y => y == inbox)))
|
||||
.Returns(Task.CompletedTask);
|
||||
|
||||
var statusServiceMock = new Mock<IStatusService>(MockBehavior.Strict);
|
||||
statusServiceMock
|
||||
.Setup(x => x.GetStatus(
|
||||
It.Is<string>(y => y == twitterHandle),
|
||||
It.Is<ExtractedTweet>(y => y.Id == tweetId)))
|
||||
.Returns(note);
|
||||
|
||||
var followersDalMock = new Mock<IFollowersDal>(MockBehavior.Strict);
|
||||
|
||||
foreach (var follower in followers)
|
||||
{
|
||||
followersDalMock
|
||||
.Setup(x => x.UpdateFollowerAsync(
|
||||
It.Is<Follower>(y => y.Id == follower.Id && y.FollowingsSyncStatus[twitterUserId] == tweetId)))
|
||||
.Returns(Task.CompletedTask);
|
||||
}
|
||||
|
||||
var loggerMock = new Mock<ILogger<SendTweetsToSharedInboxTask>>();
|
||||
#endregion
|
||||
|
||||
var task = new SendTweetsToSharedInboxTask(activityPubService.Object, statusServiceMock.Object, followersDalMock.Object, settings, loggerMock.Object);
|
||||
await task.ExecuteAsync(tweets.ToArray(), twitterUser, host, followers.ToArray());
|
||||
|
||||
#region Validations
|
||||
|
@ -165,6 +467,11 @@ namespace BirdsiteLive.Pipeline.Tests.Processors.SubTasks
|
|||
FollowingsSyncStatus = new Dictionary<int, long> {{twitterUserId, 7}}
|
||||
}
|
||||
};
|
||||
|
||||
var settings = new InstanceSettings
|
||||
{
|
||||
PublishReplies = false
|
||||
};
|
||||
#endregion
|
||||
|
||||
#region Mocks
|
||||
|
@ -204,7 +511,7 @@ namespace BirdsiteLive.Pipeline.Tests.Processors.SubTasks
|
|||
var loggerMock = new Mock<ILogger<SendTweetsToSharedInboxTask>>();
|
||||
#endregion
|
||||
|
||||
var task = new SendTweetsToSharedInboxTask(activityPubService.Object, statusServiceMock.Object, followersDalMock.Object, loggerMock.Object);
|
||||
var task = new SendTweetsToSharedInboxTask(activityPubService.Object, statusServiceMock.Object, followersDalMock.Object, settings, loggerMock.Object);
|
||||
await task.ExecuteAsync(tweets.ToArray(), twitterUser, host, followers.ToArray());
|
||||
|
||||
#region Validations
|
||||
|
@ -265,6 +572,11 @@ namespace BirdsiteLive.Pipeline.Tests.Processors.SubTasks
|
|||
FollowingsSyncStatus = new Dictionary<int, long> {{twitterUserId, 7}}
|
||||
}
|
||||
};
|
||||
|
||||
var settings = new InstanceSettings
|
||||
{
|
||||
PublishReplies = false
|
||||
};
|
||||
#endregion
|
||||
|
||||
#region Mocks
|
||||
|
@ -311,7 +623,7 @@ namespace BirdsiteLive.Pipeline.Tests.Processors.SubTasks
|
|||
var loggerMock = new Mock<ILogger<SendTweetsToSharedInboxTask>>();
|
||||
#endregion
|
||||
|
||||
var task = new SendTweetsToSharedInboxTask(activityPubService.Object, statusServiceMock.Object, followersDalMock.Object, loggerMock.Object);
|
||||
var task = new SendTweetsToSharedInboxTask(activityPubService.Object, statusServiceMock.Object, followersDalMock.Object, settings, loggerMock.Object);
|
||||
|
||||
try
|
||||
{
|
||||
|
@ -326,5 +638,185 @@ namespace BirdsiteLive.Pipeline.Tests.Processors.SubTasks
|
|||
#endregion
|
||||
}
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public async Task ExecuteAsync_SingleTweet_ParsingError_Test()
|
||||
{
|
||||
#region Stubs
|
||||
var tweetId = 10;
|
||||
var tweets = new List<ExtractedTweet>
|
||||
{
|
||||
new ExtractedTweet
|
||||
{
|
||||
Id = tweetId,
|
||||
}
|
||||
};
|
||||
|
||||
var noteId = "noteId";
|
||||
var note = new Note()
|
||||
{
|
||||
id = noteId
|
||||
};
|
||||
|
||||
var twitterHandle = "Test";
|
||||
var twitterUserId = 7;
|
||||
var twitterUser = new SyncTwitterUser
|
||||
{
|
||||
Id = twitterUserId,
|
||||
Acct = twitterHandle
|
||||
};
|
||||
|
||||
var host = "domain.ext";
|
||||
var inbox = "/inbox";
|
||||
var followers = new List<Follower>
|
||||
{
|
||||
new Follower
|
||||
{
|
||||
Id = 1,
|
||||
Host = host,
|
||||
SharedInboxRoute = inbox,
|
||||
FollowingsSyncStatus = new Dictionary<int, long> { { twitterUserId, 9 } }
|
||||
},
|
||||
new Follower
|
||||
{
|
||||
Id = 2,
|
||||
Host = host,
|
||||
SharedInboxRoute = inbox,
|
||||
FollowingsSyncStatus = new Dictionary<int, long> { { twitterUserId, 8 } }
|
||||
},
|
||||
new Follower
|
||||
{
|
||||
Id = 3,
|
||||
Host = host,
|
||||
SharedInboxRoute = inbox,
|
||||
FollowingsSyncStatus = new Dictionary<int, long> { { twitterUserId, 7 } }
|
||||
}
|
||||
};
|
||||
|
||||
var settings = new InstanceSettings
|
||||
{
|
||||
PublishReplies = false
|
||||
};
|
||||
#endregion
|
||||
|
||||
#region Mocks
|
||||
var activityPubService = new Mock<IActivityPubService>(MockBehavior.Strict);
|
||||
|
||||
var statusServiceMock = new Mock<IStatusService>(MockBehavior.Strict);
|
||||
statusServiceMock
|
||||
.Setup(x => x.GetStatus(
|
||||
It.Is<string>(y => y == twitterHandle),
|
||||
It.Is<ExtractedTweet>(y => y.Id == tweetId)))
|
||||
.Throws(new ArgumentException("Invalid pattern blabla at offset 9"));
|
||||
|
||||
var followersDalMock = new Mock<IFollowersDal>(MockBehavior.Strict);
|
||||
|
||||
foreach (var follower in followers)
|
||||
{
|
||||
followersDalMock
|
||||
.Setup(x => x.UpdateFollowerAsync(
|
||||
It.Is<Follower>(y => y.Id == follower.Id && y.FollowingsSyncStatus[twitterUserId] == tweetId)))
|
||||
.Returns(Task.CompletedTask);
|
||||
}
|
||||
|
||||
var loggerMock = new Mock<ILogger<SendTweetsToSharedInboxTask>>();
|
||||
#endregion
|
||||
|
||||
var task = new SendTweetsToSharedInboxTask(activityPubService.Object, statusServiceMock.Object, followersDalMock.Object, settings, loggerMock.Object);
|
||||
await task.ExecuteAsync(tweets.ToArray(), twitterUser, host, followers.ToArray());
|
||||
|
||||
#region Validations
|
||||
activityPubService.VerifyAll();
|
||||
statusServiceMock.VerifyAll();
|
||||
followersDalMock.VerifyAll();
|
||||
#endregion
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
[ExpectedException(typeof(ArgumentException))]
|
||||
public async Task ExecuteAsync_SingleTweet_ArgumentException_Test()
|
||||
{
|
||||
#region Stubs
|
||||
var tweetId = 10;
|
||||
var tweets = new List<ExtractedTweet>
|
||||
{
|
||||
new ExtractedTweet
|
||||
{
|
||||
Id = tweetId,
|
||||
}
|
||||
};
|
||||
|
||||
var twitterHandle = "Test";
|
||||
var twitterUserId = 7;
|
||||
var twitterUser = new SyncTwitterUser
|
||||
{
|
||||
Id = twitterUserId,
|
||||
Acct = twitterHandle
|
||||
};
|
||||
|
||||
var host = "domain.ext";
|
||||
var inbox = "/inbox";
|
||||
var followers = new List<Follower>
|
||||
{
|
||||
new Follower
|
||||
{
|
||||
Id = 1,
|
||||
Host = host,
|
||||
SharedInboxRoute = inbox,
|
||||
FollowingsSyncStatus = new Dictionary<int, long> { { twitterUserId, 9 } }
|
||||
},
|
||||
new Follower
|
||||
{
|
||||
Id = 2,
|
||||
Host = host,
|
||||
SharedInboxRoute = inbox,
|
||||
FollowingsSyncStatus = new Dictionary<int, long> { { twitterUserId, 8 } }
|
||||
},
|
||||
new Follower
|
||||
{
|
||||
Id = 3,
|
||||
Host = host,
|
||||
SharedInboxRoute = inbox,
|
||||
FollowingsSyncStatus = new Dictionary<int, long> { { twitterUserId, 7 } }
|
||||
}
|
||||
};
|
||||
|
||||
var settings = new InstanceSettings
|
||||
{
|
||||
PublishReplies = false
|
||||
};
|
||||
#endregion
|
||||
|
||||
#region Mocks
|
||||
var activityPubService = new Mock<IActivityPubService>(MockBehavior.Strict);
|
||||
|
||||
var statusServiceMock = new Mock<IStatusService>(MockBehavior.Strict);
|
||||
statusServiceMock
|
||||
.Setup(x => x.GetStatus(
|
||||
It.Is<string>(y => y == twitterHandle),
|
||||
It.Is<ExtractedTweet>(y => y.Id == tweetId)))
|
||||
.Throws(new ArgumentException());
|
||||
|
||||
var followersDalMock = new Mock<IFollowersDal>(MockBehavior.Strict);
|
||||
|
||||
var loggerMock = new Mock<ILogger<SendTweetsToSharedInboxTask>>();
|
||||
#endregion
|
||||
|
||||
var task = new SendTweetsToSharedInboxTask(activityPubService.Object, statusServiceMock.Object, followersDalMock.Object, settings, loggerMock.Object);
|
||||
|
||||
try
|
||||
{
|
||||
await task.ExecuteAsync(tweets.ToArray(), twitterUser, host, followers.ToArray());
|
||||
|
||||
}
|
||||
finally
|
||||
{
|
||||
#region Validations
|
||||
activityPubService.VerifyAll();
|
||||
statusServiceMock.VerifyAll();
|
||||
followersDalMock.VerifyAll();
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
Reference in a new issue