saving following in db
This commit is contained in:
parent
34bf9ff140
commit
5f5eeb9530
15 changed files with 174 additions and 43 deletions
|
@ -3,5 +3,7 @@
|
||||||
public class InstanceSettings
|
public class InstanceSettings
|
||||||
{
|
{
|
||||||
public string Domain { get; set; }
|
public string Domain { get; set; }
|
||||||
|
|
||||||
|
public string PostgresConnString { get; set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -8,6 +8,7 @@
|
||||||
<ProjectReference Include="..\BirdsiteLive.ActivityPub\BirdsiteLive.ActivityPub.csproj" />
|
<ProjectReference Include="..\BirdsiteLive.ActivityPub\BirdsiteLive.ActivityPub.csproj" />
|
||||||
<ProjectReference Include="..\BirdsiteLive.Cryptography\BirdsiteLive.Cryptography.csproj" />
|
<ProjectReference Include="..\BirdsiteLive.Cryptography\BirdsiteLive.Cryptography.csproj" />
|
||||||
<ProjectReference Include="..\BirdsiteLive.Twitter\BirdsiteLive.Twitter.csproj" />
|
<ProjectReference Include="..\BirdsiteLive.Twitter\BirdsiteLive.Twitter.csproj" />
|
||||||
|
<ProjectReference Include="..\DataAccessLayers\BirdsiteLive.DAL\BirdsiteLive.DAL.csproj" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
</Project>
|
</Project>
|
||||||
|
|
|
@ -0,0 +1,55 @@
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using BirdsiteLive.DAL.Contracts;
|
||||||
|
|
||||||
|
namespace BirdsiteLive.Domain.BusinessUseCases
|
||||||
|
{
|
||||||
|
public interface IProcessFollowUser
|
||||||
|
{
|
||||||
|
Task ExecuteAsync(string followerUsername, string followerDomain, string followerInbox, string twitterUser);
|
||||||
|
}
|
||||||
|
|
||||||
|
public class ProcessFollowUser : IProcessFollowUser
|
||||||
|
{
|
||||||
|
private readonly IFollowersDal _followerDal;
|
||||||
|
private readonly ITwitterUserDal _twitterUserDal;
|
||||||
|
|
||||||
|
#region Ctor
|
||||||
|
public ProcessFollowUser(IFollowersDal followerDal, ITwitterUserDal twitterUserDal)
|
||||||
|
{
|
||||||
|
_followerDal = followerDal;
|
||||||
|
_twitterUserDal = twitterUserDal;
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
public async Task ExecuteAsync(string followerUsername, string followerDomain, string followerInbox, string twitterUsername)
|
||||||
|
{
|
||||||
|
// Get Follower and Twitter Users
|
||||||
|
var follower = await _followerDal.GetFollowerAsync(followerUsername, followerDomain);
|
||||||
|
if (follower == null)
|
||||||
|
{
|
||||||
|
await _followerDal.CreateFollowerAsync(followerUsername, followerDomain, followerInbox);
|
||||||
|
follower = await _followerDal.GetFollowerAsync(followerUsername, followerDomain);
|
||||||
|
}
|
||||||
|
|
||||||
|
var twitterUser = await _twitterUserDal.GetTwitterUserAsync(twitterUsername);
|
||||||
|
if (twitterUser == null)
|
||||||
|
{
|
||||||
|
await _twitterUserDal.CreateTwitterUserAsync(twitterUsername, -1);
|
||||||
|
twitterUser = await _twitterUserDal.GetTwitterUserAsync(twitterUsername);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update Follower
|
||||||
|
var twitterUserId = twitterUser.Id;
|
||||||
|
if(!follower.Followings.Contains(twitterUserId))
|
||||||
|
follower.Followings.Add(twitterUserId);
|
||||||
|
|
||||||
|
if(!follower.FollowingsSyncStatus.ContainsKey(twitterUserId))
|
||||||
|
follower.FollowingsSyncStatus.Add(twitterUserId, -1);
|
||||||
|
|
||||||
|
follower.FollowingsSyncStatus[twitterUserId] = -1;
|
||||||
|
|
||||||
|
// Save Follower
|
||||||
|
await _followerDal.UpdateFollowerAsync(follower);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,7 @@
|
||||||
|
namespace BirdsiteLive.Domain.BusinessUseCases
|
||||||
|
{
|
||||||
|
public class ProcessUnfollowUser
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
|
@ -8,6 +8,7 @@ using System.Threading.Tasks;
|
||||||
using BirdsiteLive.ActivityPub;
|
using BirdsiteLive.ActivityPub;
|
||||||
using BirdsiteLive.Common.Settings;
|
using BirdsiteLive.Common.Settings;
|
||||||
using BirdsiteLive.Cryptography;
|
using BirdsiteLive.Cryptography;
|
||||||
|
using BirdsiteLive.Domain.BusinessUseCases;
|
||||||
using BirdsiteLive.Twitter.Models;
|
using BirdsiteLive.Twitter.Models;
|
||||||
using Tweetinvi.Core.Exceptions;
|
using Tweetinvi.Core.Exceptions;
|
||||||
using Tweetinvi.Models;
|
using Tweetinvi.Models;
|
||||||
|
@ -23,15 +24,18 @@ namespace BirdsiteLive.Domain
|
||||||
|
|
||||||
public class UserService : IUserService
|
public class UserService : IUserService
|
||||||
{
|
{
|
||||||
|
private readonly IProcessFollowUser _processFollowUser;
|
||||||
|
|
||||||
private readonly ICryptoService _cryptoService;
|
private readonly ICryptoService _cryptoService;
|
||||||
private readonly IActivityPubService _activityPubService;
|
private readonly IActivityPubService _activityPubService;
|
||||||
private readonly string _host;
|
private readonly string _host;
|
||||||
|
|
||||||
#region Ctor
|
#region Ctor
|
||||||
public UserService(InstanceSettings instanceSettings, ICryptoService cryptoService, IActivityPubService activityPubService)
|
public UserService(InstanceSettings instanceSettings, ICryptoService cryptoService, IActivityPubService activityPubService, IProcessFollowUser processFollowUser)
|
||||||
{
|
{
|
||||||
_cryptoService = cryptoService;
|
_cryptoService = cryptoService;
|
||||||
_activityPubService = activityPubService;
|
_activityPubService = activityPubService;
|
||||||
|
_processFollowUser = processFollowUser;
|
||||||
_host = $"https://{instanceSettings.Domain.Replace("https://",string.Empty).Replace("http://", string.Empty).TrimEnd('/')}";
|
_host = $"https://{instanceSettings.Domain.Replace("https://",string.Empty).Replace("http://", string.Empty).TrimEnd('/')}";
|
||||||
}
|
}
|
||||||
#endregion
|
#endregion
|
||||||
|
@ -100,15 +104,21 @@ namespace BirdsiteLive.Domain
|
||||||
return note;
|
return note;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<bool> FollowRequestedAsync(string signature, string method, string path, string queryString, Dictionary<string, string> requestHeaders, ActivityFollow activity)
|
public async Task<bool> FollowRequestedAsync(string signature, string method, string path, string queryString, Dictionary<string, string> requestHeaders, ActivityFollow activity)
|
||||||
{
|
{
|
||||||
// Validate
|
// Validate
|
||||||
if (!await ValidateSignature(activity.actor, signature, method, path, queryString, requestHeaders)) return false;
|
var sigValidation = await ValidateSignature(activity.actor, signature, method, path, queryString, requestHeaders);
|
||||||
|
if (!sigValidation.SignatureIsValidated) return false;
|
||||||
|
|
||||||
// Save Follow in DB
|
// Save Follow in DB
|
||||||
|
var followerUserName = sigValidation.User.name.ToLowerInvariant();
|
||||||
// Send Accept Activity
|
var followerHost = sigValidation.User.url.Replace("https://", string.Empty).Split('/').First();
|
||||||
var targetHost = activity.actor.Replace("https://", string.Empty).Split('/').First();
|
var followerInbox = sigValidation.User.inbox;
|
||||||
|
var twitterUser = activity.apObject.Split('/').Last().Replace("@", string.Empty);
|
||||||
|
await _processFollowUser.ExecuteAsync(followerUserName, followerHost, followerInbox, twitterUser);
|
||||||
|
|
||||||
|
// Send Accept Activity
|
||||||
|
//var followerHost = activity.actor.Replace("https://", string.Empty).Split('/').First();
|
||||||
var acceptFollow = new ActivityAcceptFollow()
|
var acceptFollow = new ActivityAcceptFollow()
|
||||||
{
|
{
|
||||||
context = "https://www.w3.org/ns/activitystreams",
|
context = "https://www.w3.org/ns/activitystreams",
|
||||||
|
@ -123,11 +133,11 @@ namespace BirdsiteLive.Domain
|
||||||
apObject = activity.apObject
|
apObject = activity.apObject
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
var result = await _activityPubService.PostDataAsync(acceptFollow, targetHost, activity.apObject);
|
var result = await _activityPubService.PostDataAsync(acceptFollow, followerHost, activity.apObject);
|
||||||
return result == HttpStatusCode.Accepted;
|
return result == HttpStatusCode.Accepted;
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task<bool> ValidateSignature(string actor, string rawSig, string method, string path, string queryString, Dictionary<string, string> requestHeaders)
|
private async Task<SignatureValidationResult> ValidateSignature(string actor, string rawSig, string method, string path, string queryString, Dictionary<string, string> requestHeaders)
|
||||||
{
|
{
|
||||||
var signatures = rawSig.Split(',');
|
var signatures = rawSig.Split(',');
|
||||||
var signature_header = new Dictionary<string, string>();
|
var signature_header = new Dictionary<string, string>();
|
||||||
|
@ -184,7 +194,17 @@ namespace BirdsiteLive.Domain
|
||||||
|
|
||||||
var result = signKey.VerifyData(Encoding.UTF8.GetBytes(toSign.ToString()), sig, HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1);
|
var result = signKey.VerifyData(Encoding.UTF8.GetBytes(toSign.ToString()), sig, HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1);
|
||||||
|
|
||||||
return result;
|
return new SignatureValidationResult()
|
||||||
|
{
|
||||||
|
SignatureIsValidated = result,
|
||||||
|
User = remoteUser
|
||||||
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public class SignatureValidationResult
|
||||||
|
{
|
||||||
|
public bool SignatureIsValidated { get; set; }
|
||||||
|
public Actor User { get; set; }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,6 +17,7 @@
|
||||||
<ProjectReference Include="..\BirdsiteLive.Cryptography\BirdsiteLive.Cryptography.csproj" />
|
<ProjectReference Include="..\BirdsiteLive.Cryptography\BirdsiteLive.Cryptography.csproj" />
|
||||||
<ProjectReference Include="..\BirdsiteLive.Domain\BirdsiteLive.Domain.csproj" />
|
<ProjectReference Include="..\BirdsiteLive.Domain\BirdsiteLive.Domain.csproj" />
|
||||||
<ProjectReference Include="..\BirdsiteLive.Twitter\BirdsiteLive.Twitter.csproj" />
|
<ProjectReference Include="..\BirdsiteLive.Twitter\BirdsiteLive.Twitter.csproj" />
|
||||||
|
<ProjectReference Include="..\DataAccessLayers\BirdsiteLive.DAL.Postgres\BirdsiteLive.DAL.Postgres.csproj" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -18,10 +18,10 @@ namespace BirdsiteLive.Controllers
|
||||||
private readonly InstanceSettings _settings;
|
private readonly InstanceSettings _settings;
|
||||||
|
|
||||||
#region Ctor
|
#region Ctor
|
||||||
public WellKnownController(IOptions<InstanceSettings> settings, ITwitterService twitterService)
|
public WellKnownController(InstanceSettings settings, ITwitterService twitterService)
|
||||||
{
|
{
|
||||||
_twitterService = twitterService;
|
_twitterService = twitterService;
|
||||||
_settings = settings.Value;
|
_settings = settings;
|
||||||
}
|
}
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
using BirdsiteLive.DAL.Contracts;
|
||||||
using BirdsiteLive.Domain;
|
using BirdsiteLive.Domain;
|
||||||
using Microsoft.Extensions.Hosting;
|
using Microsoft.Extensions.Hosting;
|
||||||
|
|
||||||
|
@ -8,22 +9,41 @@ namespace BirdsiteLive.Services
|
||||||
{
|
{
|
||||||
public class FederationService : BackgroundService
|
public class FederationService : BackgroundService
|
||||||
{
|
{
|
||||||
|
private readonly IDbInitializerDal _dbInitializerDal;
|
||||||
private readonly IUserService _userService;
|
private readonly IUserService _userService;
|
||||||
|
|
||||||
#region Ctor
|
#region Ctor
|
||||||
public FederationService(IUserService userService)
|
public FederationService(IDbInitializerDal dbInitializerDal, IUserService userService)
|
||||||
{
|
{
|
||||||
|
_dbInitializerDal = dbInitializerDal;
|
||||||
_userService = userService;
|
_userService = userService;
|
||||||
}
|
}
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
|
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
|
||||||
{
|
{
|
||||||
|
await DbInitAsync();
|
||||||
|
|
||||||
for (;;)
|
for (;;)
|
||||||
{
|
{
|
||||||
Console.WriteLine("RUNNING SERVICE");
|
Console.WriteLine("RUNNING SERVICE");
|
||||||
await Task.Delay(TimeSpan.FromSeconds(5), stoppingToken);
|
await Task.Delay(TimeSpan.FromSeconds(5), stoppingToken);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private async Task DbInitAsync()
|
||||||
|
{
|
||||||
|
var currentVersion = await _dbInitializerDal.GetCurrentDbVersionAsync();
|
||||||
|
var mandatoryVersion = _dbInitializerDal.GetMandatoryDbVersion();
|
||||||
|
|
||||||
|
if (currentVersion == null)
|
||||||
|
{
|
||||||
|
await _dbInitializerDal.InitDbAsync();
|
||||||
|
}
|
||||||
|
else if (currentVersion != mandatoryVersion)
|
||||||
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -3,6 +3,9 @@ using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using BirdsiteLive.Common.Settings;
|
using BirdsiteLive.Common.Settings;
|
||||||
|
using BirdsiteLive.DAL.Contracts;
|
||||||
|
using BirdsiteLive.DAL.Postgres.DataAccessLayers;
|
||||||
|
using BirdsiteLive.DAL.Postgres.Settings;
|
||||||
using BirdsiteLive.Models;
|
using BirdsiteLive.Models;
|
||||||
using Lamar;
|
using Lamar;
|
||||||
using Microsoft.AspNetCore.Builder;
|
using Microsoft.AspNetCore.Builder;
|
||||||
|
@ -34,7 +37,7 @@ namespace BirdsiteLive
|
||||||
// This method gets called by the runtime. Use this method to add services to the container.
|
// This method gets called by the runtime. Use this method to add services to the container.
|
||||||
public void ConfigureServices(IServiceCollection services)
|
public void ConfigureServices(IServiceCollection services)
|
||||||
{
|
{
|
||||||
services.Configure<InstanceSettings>(Configuration.GetSection("Instance"));
|
//services.Configure<InstanceSettings>(Configuration.GetSection("Instance"));
|
||||||
//services.Configure<TwitterSettings>(Configuration.GetSection("Twitter"));
|
//services.Configure<TwitterSettings>(Configuration.GetSection("Twitter"));
|
||||||
|
|
||||||
services.AddControllersWithViews();
|
services.AddControllersWithViews();
|
||||||
|
@ -48,15 +51,27 @@ namespace BirdsiteLive
|
||||||
var instanceSettings = Configuration.GetSection("Instance").Get<InstanceSettings>();
|
var instanceSettings = Configuration.GetSection("Instance").Get<InstanceSettings>();
|
||||||
services.For<InstanceSettings>().Use(x => instanceSettings);
|
services.For<InstanceSettings>().Use(x => instanceSettings);
|
||||||
|
|
||||||
|
var postgresSettings = new PostgresSettings
|
||||||
|
{
|
||||||
|
ConnString = instanceSettings.PostgresConnString
|
||||||
|
};
|
||||||
|
services.For<PostgresSettings>().Use(x => postgresSettings);
|
||||||
|
|
||||||
|
services.For<ITwitterUserDal>().Use<TwitterUserPostgresDal>().Singleton();
|
||||||
|
services.For<IFollowersDal>().Use<FollowersPostgresDal>().Singleton();
|
||||||
|
services.For<IDbInitializerDal>().Use<DbInitializerPostgresDal>().Singleton();
|
||||||
|
|
||||||
services.Scan(_ =>
|
services.Scan(_ =>
|
||||||
{
|
{
|
||||||
_.Assembly("BirdsiteLive.Twitter");
|
_.Assembly("BirdsiteLive.Twitter");
|
||||||
_.Assembly("BirdsiteLive.Domain");
|
_.Assembly("BirdsiteLive.Domain");
|
||||||
|
_.Assembly("BirdsiteLive.DAL");
|
||||||
|
_.Assembly("BirdsiteLive.DAL.Postgres");
|
||||||
_.TheCallingAssembly();
|
_.TheCallingAssembly();
|
||||||
|
|
||||||
//_.AssemblyContainingType<IDal>();
|
//_.AssemblyContainingType<IDal>();
|
||||||
//_.Exclude(type => type.Name.Contains("Settings"));
|
//_.Exclude(type => type.Name.Contains("Settings"));
|
||||||
|
|
||||||
_.WithDefaultConventions();
|
_.WithDefaultConventions();
|
||||||
|
|
||||||
_.LookForRegistries();
|
_.LookForRegistries();
|
||||||
|
|
|
@ -8,7 +8,8 @@
|
||||||
},
|
},
|
||||||
"AllowedHosts": "*",
|
"AllowedHosts": "*",
|
||||||
"Instance": {
|
"Instance": {
|
||||||
"Domain": "domain.name"
|
"Domain": "domain.name",
|
||||||
|
"PostgresConnString": "Host=127.0.0.1;Username=username;Password=password;Database=mydb"
|
||||||
},
|
},
|
||||||
"Twitter": {
|
"Twitter": {
|
||||||
"ConsumerKey": "twitter.api.key",
|
"ConsumerKey": "twitter.api.key",
|
||||||
|
|
|
@ -20,8 +20,11 @@ namespace BirdsiteLive.DAL.Postgres.DataAccessLayers
|
||||||
}
|
}
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
public async Task CreateFollowerAsync(string acct, string host, int[] followings, Dictionary<int, long> followingSyncStatus, string inboxUrl)
|
public async Task CreateFollowerAsync(string acct, string host, string inboxUrl, int[] followings = null, Dictionary<int, long> followingSyncStatus = null)
|
||||||
{
|
{
|
||||||
|
if(followings == null) followings = new int[0];
|
||||||
|
if(followingSyncStatus == null) followingSyncStatus = new Dictionary<int, long>();
|
||||||
|
|
||||||
var serializedDic = JsonConvert.SerializeObject(followingSyncStatus);
|
var serializedDic = JsonConvert.SerializeObject(followingSyncStatus);
|
||||||
|
|
||||||
acct = acct.ToLowerInvariant();
|
acct = acct.ToLowerInvariant();
|
||||||
|
@ -68,18 +71,19 @@ namespace BirdsiteLive.DAL.Postgres.DataAccessLayers
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task UpdateFollowerAsync(int id, int[] followings, Dictionary<int, long> followingsSyncStatus)
|
public async Task UpdateFollowerAsync(Follower follower)
|
||||||
{
|
{
|
||||||
if (id == default) throw new ArgumentException("id");
|
if (follower == default) throw new ArgumentException("follower");
|
||||||
|
if (follower.Id == default) throw new ArgumentException("id");
|
||||||
|
|
||||||
var serializedDic = JsonConvert.SerializeObject(followingsSyncStatus);
|
var serializedDic = JsonConvert.SerializeObject(follower.FollowingsSyncStatus);
|
||||||
var query = $"UPDATE {_settings.FollowersTableName} SET followings = @followings, followingsSyncStatus = CAST(@followingsSyncStatus as json) WHERE id = @id";
|
var query = $"UPDATE {_settings.FollowersTableName} SET followings = @followings, followingsSyncStatus = CAST(@followingsSyncStatus as json) WHERE id = @id";
|
||||||
|
|
||||||
using (var dbConnection = Connection)
|
using (var dbConnection = Connection)
|
||||||
{
|
{
|
||||||
dbConnection.Open();
|
dbConnection.Open();
|
||||||
|
|
||||||
await dbConnection.QueryAsync(query, new { id, followings, followingsSyncStatus = serializedDic });
|
await dbConnection.QueryAsync(query, new { follower.Id, follower.Followings, followingsSyncStatus = serializedDic });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -125,7 +129,7 @@ namespace BirdsiteLive.DAL.Postgres.DataAccessLayers
|
||||||
Acct = follower.Acct,
|
Acct = follower.Acct,
|
||||||
Host = follower.Host,
|
Host = follower.Host,
|
||||||
InboxUrl = follower.InboxUrl,
|
InboxUrl = follower.InboxUrl,
|
||||||
Followings = follower.Followings,
|
Followings = follower.Followings.ToList(),
|
||||||
FollowingsSyncStatus = JsonConvert.DeserializeObject<Dictionary<int,long>>(follower.FollowingsSyncStatus)
|
FollowingsSyncStatus = JsonConvert.DeserializeObject<Dictionary<int,long>>(follower.FollowingsSyncStatus)
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,9 +4,9 @@
|
||||||
{
|
{
|
||||||
public string ConnString { get; set; }
|
public string ConnString { get; set; }
|
||||||
|
|
||||||
public string DbVersionTableName { get; set; } = "db-version";
|
public string DbVersionTableName { get; set; } = "db_version";
|
||||||
public string TwitterUserTableName { get; set; } = "twitter-users";
|
public string TwitterUserTableName { get; set; } = "twitter_users";
|
||||||
public string FollowersTableName { get; set; } = "followers";
|
public string FollowersTableName { get; set; } = "followers";
|
||||||
public string CachedTweetsTableName { get; set; } = "cached-tweets";
|
public string CachedTweetsTableName { get; set; } = "cached_tweets";
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -7,9 +7,10 @@ namespace BirdsiteLive.DAL.Contracts
|
||||||
public interface IFollowersDal
|
public interface IFollowersDal
|
||||||
{
|
{
|
||||||
Task<Follower> GetFollowerAsync(string acct, string host);
|
Task<Follower> GetFollowerAsync(string acct, string host);
|
||||||
Task CreateFollowerAsync(string acct, string host, int[] followings, Dictionary<int, long> followingSyncStatus, string inboxUrl);
|
Task CreateFollowerAsync(string acct, string host, string inboxUrl, int[] followings = null,
|
||||||
|
Dictionary<int, long> followingSyncStatus = null);
|
||||||
Task<Follower[]> GetFollowersAsync(int followedUserId);
|
Task<Follower[]> GetFollowersAsync(int followedUserId);
|
||||||
Task UpdateFollowerAsync(int id, int[] followings, Dictionary<int, long> followingSyncStatus);
|
Task UpdateFollowerAsync(Follower follower);
|
||||||
Task DeleteFollowerAsync(int id);
|
Task DeleteFollowerAsync(int id);
|
||||||
Task DeleteFollowerAsync(string acct, string host);
|
Task DeleteFollowerAsync(string acct, string host);
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,7 +6,7 @@ namespace BirdsiteLive.DAL.Models
|
||||||
{
|
{
|
||||||
public int Id { get; set; }
|
public int Id { get; set; }
|
||||||
|
|
||||||
public int[] Followings { get; set; }
|
public List<int> Followings { get; set; }
|
||||||
public Dictionary<int, long> FollowingsSyncStatus { get; set; }
|
public Dictionary<int, long> FollowingsSyncStatus { get; set; }
|
||||||
|
|
||||||
public string Acct { get; set; }
|
public string Acct { get; set; }
|
||||||
|
|
|
@ -48,7 +48,7 @@ namespace BirdsiteLive.DAL.Postgres.Tests.DataAccessLayers
|
||||||
var inboxUrl = "https://domain.ext/myhandle/inbox";
|
var inboxUrl = "https://domain.ext/myhandle/inbox";
|
||||||
|
|
||||||
var dal = new FollowersPostgresDal(_settings);
|
var dal = new FollowersPostgresDal(_settings);
|
||||||
await dal.CreateFollowerAsync(acct, host, following, followingSync, inboxUrl);
|
await dal.CreateFollowerAsync(acct, host, inboxUrl, following, followingSync);
|
||||||
|
|
||||||
var result = await dal.GetFollowerAsync(acct, host);
|
var result = await dal.GetFollowerAsync(acct, host);
|
||||||
|
|
||||||
|
@ -56,7 +56,7 @@ namespace BirdsiteLive.DAL.Postgres.Tests.DataAccessLayers
|
||||||
Assert.AreEqual(acct, result.Acct);
|
Assert.AreEqual(acct, result.Acct);
|
||||||
Assert.AreEqual(host, result.Host);
|
Assert.AreEqual(host, result.Host);
|
||||||
Assert.AreEqual(inboxUrl, result.InboxUrl);
|
Assert.AreEqual(inboxUrl, result.InboxUrl);
|
||||||
Assert.AreEqual(following.Length, result.Followings.Length);
|
Assert.AreEqual(following.Length, result.Followings.Count);
|
||||||
Assert.AreEqual(following[0], result.Followings[0]);
|
Assert.AreEqual(following[0], result.Followings[0]);
|
||||||
Assert.AreEqual(followingSync.Count, result.FollowingsSyncStatus.Count);
|
Assert.AreEqual(followingSync.Count, result.FollowingsSyncStatus.Count);
|
||||||
Assert.AreEqual(followingSync.First().Key, result.FollowingsSyncStatus.First().Key);
|
Assert.AreEqual(followingSync.First().Key, result.FollowingsSyncStatus.First().Key);
|
||||||
|
@ -74,21 +74,21 @@ namespace BirdsiteLive.DAL.Postgres.Tests.DataAccessLayers
|
||||||
var following = new[] { 1,2,3 };
|
var following = new[] { 1,2,3 };
|
||||||
var followingSync = new Dictionary<int, long>();
|
var followingSync = new Dictionary<int, long>();
|
||||||
var inboxUrl = "https://domain.ext/myhandle1/inbox";
|
var inboxUrl = "https://domain.ext/myhandle1/inbox";
|
||||||
await dal.CreateFollowerAsync(acct, host, following, followingSync, inboxUrl);
|
await dal.CreateFollowerAsync(acct, host, inboxUrl, following, followingSync);
|
||||||
|
|
||||||
//User 2
|
//User 2
|
||||||
acct = "myhandle2";
|
acct = "myhandle2";
|
||||||
host = "domain.ext";
|
host = "domain.ext";
|
||||||
following = new[] { 2, 4, 5 };
|
following = new[] { 2, 4, 5 };
|
||||||
inboxUrl = "https://domain.ext/myhandle2/inbox";
|
inboxUrl = "https://domain.ext/myhandle2/inbox";
|
||||||
await dal.CreateFollowerAsync(acct, host, following, followingSync, inboxUrl);
|
await dal.CreateFollowerAsync(acct, host, inboxUrl, following, followingSync);
|
||||||
|
|
||||||
//User 2
|
//User 2
|
||||||
acct = "myhandle3";
|
acct = "myhandle3";
|
||||||
host = "domain.ext";
|
host = "domain.ext";
|
||||||
following = new[] { 1 };
|
following = new[] { 1 };
|
||||||
inboxUrl = "https://domain.ext/myhandle3/inbox";
|
inboxUrl = "https://domain.ext/myhandle3/inbox";
|
||||||
await dal.CreateFollowerAsync(acct, host, following, followingSync, inboxUrl);
|
await dal.CreateFollowerAsync(acct, host, inboxUrl, following, followingSync);
|
||||||
|
|
||||||
var result = await dal.GetFollowersAsync(2);
|
var result = await dal.GetFollowersAsync(2);
|
||||||
Assert.AreEqual(2, result.Length);
|
Assert.AreEqual(2, result.Length);
|
||||||
|
@ -115,22 +115,24 @@ namespace BirdsiteLive.DAL.Postgres.Tests.DataAccessLayers
|
||||||
var inboxUrl = "https://domain.ext/myhandle/inbox";
|
var inboxUrl = "https://domain.ext/myhandle/inbox";
|
||||||
|
|
||||||
var dal = new FollowersPostgresDal(_settings);
|
var dal = new FollowersPostgresDal(_settings);
|
||||||
await dal.CreateFollowerAsync(acct, host, following, followingSync, inboxUrl);
|
await dal.CreateFollowerAsync(acct, host, inboxUrl, following, followingSync);
|
||||||
var result = await dal.GetFollowerAsync(acct, host);
|
var result = await dal.GetFollowerAsync(acct, host);
|
||||||
|
|
||||||
var updatedFollowing = new[] { 12, 19, 23, 24 };
|
var updatedFollowing = new List<int> { 12, 19, 23, 24 };
|
||||||
var updatedFollowingSync = new Dictionary<int, long>()
|
var updatedFollowingSync = new Dictionary<int, long>(){
|
||||||
{
|
|
||||||
{12, 170L},
|
{12, 170L},
|
||||||
{19, 171L},
|
{19, 171L},
|
||||||
{23, 172L},
|
{23, 172L},
|
||||||
{24, 173L}
|
{24, 173L}
|
||||||
};
|
};
|
||||||
|
result.Followings = updatedFollowing.ToList();
|
||||||
|
result.FollowingsSyncStatus = updatedFollowingSync;
|
||||||
|
|
||||||
|
|
||||||
await dal.UpdateFollowerAsync(result.Id, updatedFollowing, updatedFollowingSync);
|
await dal.UpdateFollowerAsync(result);
|
||||||
result = await dal.GetFollowerAsync(acct, host);
|
result = await dal.GetFollowerAsync(acct, host);
|
||||||
|
|
||||||
Assert.AreEqual(updatedFollowing.Length, result.Followings.Length);
|
Assert.AreEqual(updatedFollowing.Count, result.Followings.Count);
|
||||||
Assert.AreEqual(updatedFollowing[0], result.Followings[0]);
|
Assert.AreEqual(updatedFollowing[0], result.Followings[0]);
|
||||||
Assert.AreEqual(updatedFollowingSync.Count, result.FollowingsSyncStatus.Count);
|
Assert.AreEqual(updatedFollowingSync.Count, result.FollowingsSyncStatus.Count);
|
||||||
Assert.AreEqual(updatedFollowingSync.First().Key, result.FollowingsSyncStatus.First().Key);
|
Assert.AreEqual(updatedFollowingSync.First().Key, result.FollowingsSyncStatus.First().Key);
|
||||||
|
@ -152,7 +154,7 @@ namespace BirdsiteLive.DAL.Postgres.Tests.DataAccessLayers
|
||||||
var inboxUrl = "https://domain.ext/myhandle/inbox";
|
var inboxUrl = "https://domain.ext/myhandle/inbox";
|
||||||
|
|
||||||
var dal = new FollowersPostgresDal(_settings);
|
var dal = new FollowersPostgresDal(_settings);
|
||||||
await dal.CreateFollowerAsync(acct, host, following, followingSync, inboxUrl);
|
await dal.CreateFollowerAsync(acct, host, inboxUrl, following, followingSync);
|
||||||
var result = await dal.GetFollowerAsync(acct, host);
|
var result = await dal.GetFollowerAsync(acct, host);
|
||||||
|
|
||||||
var updatedFollowing = new[] { 12, 19 };
|
var updatedFollowing = new[] { 12, 19 };
|
||||||
|
@ -161,11 +163,13 @@ namespace BirdsiteLive.DAL.Postgres.Tests.DataAccessLayers
|
||||||
{12, 170L},
|
{12, 170L},
|
||||||
{19, 171L}
|
{19, 171L}
|
||||||
};
|
};
|
||||||
|
result.Followings = updatedFollowing.ToList();
|
||||||
|
result.FollowingsSyncStatus = updatedFollowingSync;
|
||||||
|
|
||||||
await dal.UpdateFollowerAsync(result.Id, updatedFollowing, updatedFollowingSync);
|
await dal.UpdateFollowerAsync(result);
|
||||||
result = await dal.GetFollowerAsync(acct, host);
|
result = await dal.GetFollowerAsync(acct, host);
|
||||||
|
|
||||||
Assert.AreEqual(updatedFollowing.Length, result.Followings.Length);
|
Assert.AreEqual(updatedFollowing.Length, result.Followings.Count);
|
||||||
Assert.AreEqual(updatedFollowing[0], result.Followings[0]);
|
Assert.AreEqual(updatedFollowing[0], result.Followings[0]);
|
||||||
Assert.AreEqual(updatedFollowingSync.Count, result.FollowingsSyncStatus.Count);
|
Assert.AreEqual(updatedFollowingSync.Count, result.FollowingsSyncStatus.Count);
|
||||||
Assert.AreEqual(updatedFollowingSync.First().Key, result.FollowingsSyncStatus.First().Key);
|
Assert.AreEqual(updatedFollowingSync.First().Key, result.FollowingsSyncStatus.First().Key);
|
||||||
|
@ -187,7 +191,7 @@ namespace BirdsiteLive.DAL.Postgres.Tests.DataAccessLayers
|
||||||
var inboxUrl = "https://domain.ext/myhandle/inbox";
|
var inboxUrl = "https://domain.ext/myhandle/inbox";
|
||||||
|
|
||||||
var dal = new FollowersPostgresDal(_settings);
|
var dal = new FollowersPostgresDal(_settings);
|
||||||
await dal.CreateFollowerAsync(acct, host, following, followingSync, inboxUrl);
|
await dal.CreateFollowerAsync(acct, host, inboxUrl, following, followingSync);
|
||||||
var result = await dal.GetFollowerAsync(acct, host);
|
var result = await dal.GetFollowerAsync(acct, host);
|
||||||
Assert.IsNotNull(result);
|
Assert.IsNotNull(result);
|
||||||
|
|
||||||
|
@ -212,7 +216,7 @@ namespace BirdsiteLive.DAL.Postgres.Tests.DataAccessLayers
|
||||||
var inboxUrl = "https://domain.ext/myhandle/inbox";
|
var inboxUrl = "https://domain.ext/myhandle/inbox";
|
||||||
|
|
||||||
var dal = new FollowersPostgresDal(_settings);
|
var dal = new FollowersPostgresDal(_settings);
|
||||||
await dal.CreateFollowerAsync(acct, host, following, followingSync, inboxUrl);
|
await dal.CreateFollowerAsync(acct, host, inboxUrl, following, followingSync);
|
||||||
var result = await dal.GetFollowerAsync(acct, host);
|
var result = await dal.GetFollowerAsync(acct, host);
|
||||||
Assert.IsNotNull(result);
|
Assert.IsNotNull(result);
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue