Merge pull request #4 from NicolasConstant/topic_add-dals
Topic add dals
This commit is contained in:
commit
a96c4fee0f
17 changed files with 938 additions and 57 deletions
2
.github/workflows/dotnet-core.yml
vendored
2
.github/workflows/dotnet-core.yml
vendored
|
@ -28,5 +28,5 @@ jobs:
|
||||||
run: dotnet build --configuration Release --no-restore
|
run: dotnet build --configuration Release --no-restore
|
||||||
working-directory: ${{env.working-directory}}
|
working-directory: ${{env.working-directory}}
|
||||||
- name: Test
|
- name: Test
|
||||||
run: dotnet test --no-restore --verbosity normal
|
run: dotnet test --no-restore --verbosity quiet
|
||||||
working-directory: ${{env.working-directory}}
|
working-directory: ${{env.working-directory}}
|
||||||
|
|
|
@ -24,6 +24,52 @@ namespace BirdsiteLive.Controllers
|
||||||
}
|
}
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
|
[Route("/.well-known/nodeinfo")]
|
||||||
|
public IActionResult WellKnownNodeInfo()
|
||||||
|
{
|
||||||
|
var nodeInfo = new WellKnownNodeInfo
|
||||||
|
{
|
||||||
|
links = new Link[]
|
||||||
|
{
|
||||||
|
new Link()
|
||||||
|
{
|
||||||
|
rel = "http://nodeinfo.diaspora.software/ns/schema/2.0",
|
||||||
|
href = $"https://{_settings.Domain}/nodeinfo/2.0.json"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
return new JsonResult(nodeInfo);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Route("/nodeinfo/2.0.json")]
|
||||||
|
public IActionResult NodeInfo()
|
||||||
|
{
|
||||||
|
var nodeInfo = new NodeInfo
|
||||||
|
{
|
||||||
|
version = "2.0",
|
||||||
|
usage = new Usage()
|
||||||
|
{
|
||||||
|
localPosts = 0,
|
||||||
|
users = new Users()
|
||||||
|
{
|
||||||
|
total = 0
|
||||||
|
}
|
||||||
|
},
|
||||||
|
software = new Software()
|
||||||
|
{
|
||||||
|
name = "BirdsiteLive",
|
||||||
|
version = "0.1.0"
|
||||||
|
},
|
||||||
|
protocols = new []
|
||||||
|
{
|
||||||
|
"activitypub"
|
||||||
|
},
|
||||||
|
openRegistrations = false
|
||||||
|
};
|
||||||
|
|
||||||
|
return new JsonResult(nodeInfo);
|
||||||
|
}
|
||||||
|
|
||||||
[Route("/.well-known/webfinger")]
|
[Route("/.well-known/webfinger")]
|
||||||
public IActionResult Webfinger(string resource = null)
|
public IActionResult Webfinger(string resource = null)
|
||||||
{
|
{
|
||||||
|
@ -51,7 +97,7 @@ namespace BirdsiteLive.Controllers
|
||||||
|
|
||||||
if (!string.IsNullOrWhiteSpace(domain) && domain != _settings.Domain)
|
if (!string.IsNullOrWhiteSpace(domain) && domain != _settings.Domain)
|
||||||
return NotFound();
|
return NotFound();
|
||||||
|
|
||||||
var user = _twitterService.GetUser(name);
|
var user = _twitterService.GetUser(name);
|
||||||
if (user == null)
|
if (user == null)
|
||||||
return NotFound();
|
return NotFound();
|
||||||
|
@ -59,7 +105,7 @@ namespace BirdsiteLive.Controllers
|
||||||
var result = new WebFingerResult()
|
var result = new WebFingerResult()
|
||||||
{
|
{
|
||||||
subject = $"acct:{name}@{_settings.Domain}",
|
subject = $"acct:{name}@{_settings.Domain}",
|
||||||
aliases = new []
|
aliases = new[]
|
||||||
{
|
{
|
||||||
$"https://{_settings.Domain}/@{name}",
|
$"https://{_settings.Domain}/@{name}",
|
||||||
$"https://{_settings.Domain}/users/{name}"
|
$"https://{_settings.Domain}/users/{name}"
|
||||||
|
@ -83,19 +129,64 @@ namespace BirdsiteLive.Controllers
|
||||||
|
|
||||||
return new JsonResult(result);
|
return new JsonResult(result);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public class WebFingerResult
|
public class WebFingerResult
|
||||||
{
|
{
|
||||||
public string subject { get; set; }
|
public string subject { get; set; }
|
||||||
public string[] aliases { get; set; }
|
public string[] aliases { get; set; }
|
||||||
public List<WebFingerLink> links { get; set; } = new List<WebFingerLink>();
|
public List<WebFingerLink> links { get; set; } = new List<WebFingerLink>();
|
||||||
}
|
}
|
||||||
|
|
||||||
public class WebFingerLink
|
public class WebFingerLink
|
||||||
{
|
{
|
||||||
public string rel { get; set; }
|
public string rel { get; set; }
|
||||||
public string type { get; set; }
|
public string type { get; set; }
|
||||||
public string href { get; set; }
|
public string href { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public class WellKnownNodeInfo
|
||||||
|
{
|
||||||
|
public Link[] links { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public class Link
|
||||||
|
{
|
||||||
|
public string href { get; set; }
|
||||||
|
public string rel { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public class NodeInfo
|
||||||
|
{
|
||||||
|
public string version { get; set; }
|
||||||
|
public string[] protocols { get; set; }
|
||||||
|
public Software software { get; set; }
|
||||||
|
public Usage usage { get; set; }
|
||||||
|
public bool openRegistrations { get; set; }
|
||||||
|
public Services services { get; set; }
|
||||||
|
public object metadata { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public class Services
|
||||||
|
{
|
||||||
|
public object[] inbound { get; set; }
|
||||||
|
public object[] outbound { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public class Software
|
||||||
|
{
|
||||||
|
public string name { get; set; }
|
||||||
|
public string version { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public class Usage
|
||||||
|
{
|
||||||
|
public int localPosts { get; set; }
|
||||||
|
public Users users { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public class Users
|
||||||
|
{
|
||||||
|
public int total { get; set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -0,0 +1,83 @@
|
||||||
|
using System;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using BirdsiteLive.DAL.Contracts;
|
||||||
|
using BirdsiteLive.DAL.Models;
|
||||||
|
using BirdsiteLive.DAL.Postgres.DataAccessLayers.Base;
|
||||||
|
using BirdsiteLive.DAL.Postgres.Settings;
|
||||||
|
using BirdsiteLive.DAL.Postgres.Tools;
|
||||||
|
using Dapper;
|
||||||
|
using Newtonsoft.Json;
|
||||||
|
using Tweetinvi.Models;
|
||||||
|
|
||||||
|
namespace BirdsiteLive.DAL.Postgres.DataAccessLayers
|
||||||
|
{
|
||||||
|
public class CachedTweetsPostgresDal : PostgresBase, ICachedTweetsDal
|
||||||
|
{
|
||||||
|
#region Ctor
|
||||||
|
public CachedTweetsPostgresDal(PostgresSettings settings) : base(settings)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
public async Task CreateTweetAsync(long tweetId, int userId, CachedTweet tweet)
|
||||||
|
{
|
||||||
|
if(tweetId == default) throw new ArgumentException("tweetId");
|
||||||
|
if(userId == default) throw new ArgumentException("userId");
|
||||||
|
|
||||||
|
var serializedData = JsonConvert.SerializeObject(tweet);
|
||||||
|
|
||||||
|
using (var dbConnection = Connection)
|
||||||
|
{
|
||||||
|
dbConnection.Open();
|
||||||
|
|
||||||
|
await dbConnection.ExecuteAsync(
|
||||||
|
$"INSERT INTO {_settings.CachedTweetsTableName} (id,twitterUserId,data) VALUES(@id,@twitterUserId,CAST(@data as json))",
|
||||||
|
new { id = tweetId, twitterUserId = userId, data = serializedData });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<CachedTweet> GetTweetAsync(long tweetId)
|
||||||
|
{
|
||||||
|
if (tweetId == default) throw new ArgumentException("tweetId");
|
||||||
|
|
||||||
|
var query = $"SELECT * FROM {_settings.CachedTweetsTableName} WHERE id = @id";
|
||||||
|
|
||||||
|
using (var dbConnection = Connection)
|
||||||
|
{
|
||||||
|
dbConnection.Open();
|
||||||
|
|
||||||
|
var result = (await dbConnection.QueryAsync<SerializedTweet>(query, new { id = tweetId })).FirstOrDefault();
|
||||||
|
return Convert(result);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task DeleteTweetAsync(long tweetId)
|
||||||
|
{
|
||||||
|
if (tweetId == default) throw new ArgumentException("tweetId");
|
||||||
|
|
||||||
|
var query = $"DELETE FROM {_settings.CachedTweetsTableName} WHERE id = @id";
|
||||||
|
|
||||||
|
using (var dbConnection = Connection)
|
||||||
|
{
|
||||||
|
dbConnection.Open();
|
||||||
|
|
||||||
|
await dbConnection.QueryAsync(query, new { id = tweetId });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private CachedTweet Convert(SerializedTweet result)
|
||||||
|
{
|
||||||
|
if (result == null || string.IsNullOrWhiteSpace(result.Data)) return null;
|
||||||
|
return JsonConvert.DeserializeObject<CachedTweet>(result.Data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal class SerializedTweet
|
||||||
|
{
|
||||||
|
public long Id { get; set; }
|
||||||
|
public int TwitterUserId { get; set; }
|
||||||
|
public string Data { get; set; }
|
||||||
|
}
|
||||||
|
}
|
|
@ -106,8 +106,9 @@ namespace BirdsiteLive.DAL.Postgres.DataAccessLayers
|
||||||
followings INTEGER[],
|
followings INTEGER[],
|
||||||
followingsSyncStatus JSONB,
|
followingsSyncStatus JSONB,
|
||||||
|
|
||||||
acct VARCHAR(20) UNIQUE,
|
acct VARCHAR(50),
|
||||||
host VARCHAR(20)
|
host VARCHAR(253),
|
||||||
|
UNIQUE (acct, host)
|
||||||
);";
|
);";
|
||||||
await _tools.ExecuteRequestAsync(createFollowers);
|
await _tools.ExecuteRequestAsync(createFollowers);
|
||||||
|
|
||||||
|
|
|
@ -1,9 +1,142 @@
|
||||||
using BirdsiteLive.DAL.Contracts;
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using BirdsiteLive.DAL.Contracts;
|
||||||
|
using BirdsiteLive.DAL.Models;
|
||||||
|
using BirdsiteLive.DAL.Postgres.DataAccessLayers.Base;
|
||||||
|
using BirdsiteLive.DAL.Postgres.Settings;
|
||||||
|
using Dapper;
|
||||||
|
using Newtonsoft.Json;
|
||||||
|
|
||||||
namespace BirdsiteLive.DAL.Postgres.DataAccessLayers
|
namespace BirdsiteLive.DAL.Postgres.DataAccessLayers
|
||||||
{
|
{
|
||||||
public class FollowersPostgresDal : IFollowersDal
|
public class FollowersPostgresDal : PostgresBase, IFollowersDal
|
||||||
{
|
{
|
||||||
|
#region Ctor
|
||||||
|
public FollowersPostgresDal(PostgresSettings settings) : base(settings)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
public async Task CreateFollowerAsync(string acct, string host, int[] followings, Dictionary<int, long> followingSyncStatus)
|
||||||
|
{
|
||||||
|
var serializedDic = JsonConvert.SerializeObject(followingSyncStatus);
|
||||||
|
|
||||||
|
acct = acct.ToLowerInvariant();
|
||||||
|
host = host.ToLowerInvariant();
|
||||||
|
|
||||||
|
using (var dbConnection = Connection)
|
||||||
|
{
|
||||||
|
dbConnection.Open();
|
||||||
|
|
||||||
|
await dbConnection.ExecuteAsync(
|
||||||
|
$"INSERT INTO {_settings.FollowersTableName} (acct,host,followings,followingsSyncStatus) VALUES(@acct,@host,@followings, CAST(@followingsSyncStatus as json))",
|
||||||
|
new { acct, host, followings, followingsSyncStatus = serializedDic });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<Follower> GetFollowerAsync(string acct, string host)
|
||||||
|
{
|
||||||
|
var query = $"SELECT * FROM {_settings.FollowersTableName} WHERE acct = @acct AND host = @host";
|
||||||
|
|
||||||
|
acct = acct.ToLowerInvariant();
|
||||||
|
host = host.ToLowerInvariant();
|
||||||
|
|
||||||
|
using (var dbConnection = Connection)
|
||||||
|
{
|
||||||
|
dbConnection.Open();
|
||||||
|
|
||||||
|
var result = (await dbConnection.QueryAsync<SerializedFollower>(query, new { acct, host })).FirstOrDefault();
|
||||||
|
return Convert(result);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<Follower[]> GetFollowersAsync(int followedUserId)
|
||||||
|
{
|
||||||
|
if (followedUserId == default) throw new ArgumentException("followedUserId");
|
||||||
|
|
||||||
|
var query = $"SELECT * FROM {_settings.FollowersTableName} WHERE @id=ANY(followings)";
|
||||||
|
|
||||||
|
using (var dbConnection = Connection)
|
||||||
|
{
|
||||||
|
dbConnection.Open();
|
||||||
|
|
||||||
|
var result = await dbConnection.QueryAsync<SerializedFollower>(query, new { id = followedUserId});
|
||||||
|
return result.Select(Convert).ToArray();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task UpdateFollowerAsync(int id, int[] followings, Dictionary<int, long> followingsSyncStatus)
|
||||||
|
{
|
||||||
|
if (id == default) throw new ArgumentException("id");
|
||||||
|
|
||||||
|
var serializedDic = JsonConvert.SerializeObject(followingsSyncStatus);
|
||||||
|
var query = $"UPDATE {_settings.FollowersTableName} SET followings = @followings, followingsSyncStatus = CAST(@followingsSyncStatus as json) WHERE id = @id";
|
||||||
|
|
||||||
|
using (var dbConnection = Connection)
|
||||||
|
{
|
||||||
|
dbConnection.Open();
|
||||||
|
|
||||||
|
await dbConnection.QueryAsync(query, new { id, followings, followingsSyncStatus = serializedDic });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task DeleteFollowerAsync(int id)
|
||||||
|
{
|
||||||
|
if (id == default) throw new ArgumentException("id");
|
||||||
|
|
||||||
|
var query = $"DELETE FROM {_settings.FollowersTableName} WHERE id = @id";
|
||||||
|
|
||||||
|
using (var dbConnection = Connection)
|
||||||
|
{
|
||||||
|
dbConnection.Open();
|
||||||
|
|
||||||
|
await dbConnection.QueryAsync(query, new { id });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task DeleteFollowerAsync(string acct, string host)
|
||||||
|
{
|
||||||
|
if (acct == default) throw new ArgumentException("acct");
|
||||||
|
if (host == default) throw new ArgumentException("host");
|
||||||
|
|
||||||
|
acct = acct.ToLowerInvariant();
|
||||||
|
host = host.ToLowerInvariant();
|
||||||
|
|
||||||
|
var query = $"DELETE FROM {_settings.FollowersTableName} WHERE acct = @acct AND host = @host";
|
||||||
|
|
||||||
|
using (var dbConnection = Connection)
|
||||||
|
{
|
||||||
|
dbConnection.Open();
|
||||||
|
|
||||||
|
await dbConnection.QueryAsync(query, new { acct, host });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private Follower Convert(SerializedFollower follower)
|
||||||
|
{
|
||||||
|
if (follower == null) return null;
|
||||||
|
|
||||||
|
return new Follower()
|
||||||
|
{
|
||||||
|
Id = follower.Id,
|
||||||
|
Acct = follower.Acct,
|
||||||
|
Host = follower.Host,
|
||||||
|
Followings = follower.Followings,
|
||||||
|
FollowingsSyncStatus = JsonConvert.DeserializeObject<Dictionary<int,long>>(follower.FollowingsSyncStatus)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal class SerializedFollower {
|
||||||
|
public int Id { get; set; }
|
||||||
|
|
||||||
|
public int[] Followings { get; set; }
|
||||||
|
public string FollowingsSyncStatus { get; set; }
|
||||||
|
|
||||||
|
public string Acct { get; set; }
|
||||||
|
public string Host { get; set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,9 +1,97 @@
|
||||||
using BirdsiteLive.DAL.Contracts;
|
using System;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using BirdsiteLive.DAL.Contracts;
|
||||||
|
using BirdsiteLive.DAL.Models;
|
||||||
|
using BirdsiteLive.DAL.Postgres.DataAccessLayers.Base;
|
||||||
|
using BirdsiteLive.DAL.Postgres.Settings;
|
||||||
|
using BirdsiteLive.DAL.Postgres.Tools;
|
||||||
|
using Dapper;
|
||||||
|
using Npgsql;
|
||||||
|
|
||||||
namespace BirdsiteLive.DAL.Postgres.DataAccessLayers
|
namespace BirdsiteLive.DAL.Postgres.DataAccessLayers
|
||||||
{
|
{
|
||||||
public class TwitterUserPostgresDal : ITwitterUserDal
|
public class TwitterUserPostgresDal : PostgresBase, ITwitterUserDal
|
||||||
{
|
{
|
||||||
|
#region Ctor
|
||||||
|
public TwitterUserPostgresDal(PostgresSettings settings) : base(settings)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
public async Task CreateTwitterUserAsync(string acct, long lastTweetPostedId)
|
||||||
|
{
|
||||||
|
acct = acct.ToLowerInvariant();
|
||||||
|
|
||||||
|
using (var dbConnection = Connection)
|
||||||
|
{
|
||||||
|
dbConnection.Open();
|
||||||
|
|
||||||
|
await dbConnection.ExecuteAsync(
|
||||||
|
$"INSERT INTO {_settings.TwitterUserTableName} (acct,lastTweetPostedId,lastTweetSynchronizedForAllFollowersId) VALUES(@acct,@lastTweetPostedId,@lastTweetSynchronizedForAllFollowersId)",
|
||||||
|
new { acct, lastTweetPostedId, lastTweetSynchronizedForAllFollowersId = lastTweetPostedId });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<SyncTwitterUser> GetTwitterUserAsync(string acct)
|
||||||
|
{
|
||||||
|
var query = $"SELECT * FROM {_settings.TwitterUserTableName} WHERE acct = @acct";
|
||||||
|
|
||||||
|
acct = acct.ToLowerInvariant();
|
||||||
|
|
||||||
|
using (var dbConnection = Connection)
|
||||||
|
{
|
||||||
|
dbConnection.Open();
|
||||||
|
|
||||||
|
var result = (await dbConnection.QueryAsync<SyncTwitterUser>(query, new { acct = acct })).FirstOrDefault();
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<SyncTwitterUser[]> GetAllTwitterUsersAsync()
|
||||||
|
{
|
||||||
|
var query = $"SELECT * FROM {_settings.TwitterUserTableName}";
|
||||||
|
|
||||||
|
using (var dbConnection = Connection)
|
||||||
|
{
|
||||||
|
dbConnection.Open();
|
||||||
|
|
||||||
|
var result = await dbConnection.QueryAsync<SyncTwitterUser>(query);
|
||||||
|
return result.ToArray();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task UpdateTwitterUserAsync(int id, long lastTweetPostedId, long lastTweetSynchronizedForAllFollowersId)
|
||||||
|
{
|
||||||
|
if(id == default) throw new ArgumentException("id");
|
||||||
|
if(lastTweetPostedId == default) throw new ArgumentException("lastTweetPostedId");
|
||||||
|
if(lastTweetSynchronizedForAllFollowersId == default) throw new ArgumentException("lastTweetSynchronizedForAllFollowersId");
|
||||||
|
|
||||||
|
var query = $"UPDATE {_settings.TwitterUserTableName} SET lastTweetPostedId = @lastTweetPostedId, lastTweetSynchronizedForAllFollowersId = @lastTweetSynchronizedForAllFollowersId WHERE id = @id";
|
||||||
|
|
||||||
|
using (var dbConnection = Connection)
|
||||||
|
{
|
||||||
|
dbConnection.Open();
|
||||||
|
|
||||||
|
await dbConnection.QueryAsync(query, new { id, lastTweetPostedId, lastTweetSynchronizedForAllFollowersId });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task DeleteTwitterUserAsync(string acct)
|
||||||
|
{
|
||||||
|
if (acct == default) throw new ArgumentException("acct");
|
||||||
|
|
||||||
|
acct = acct.ToLowerInvariant();
|
||||||
|
|
||||||
|
var query = $"DELETE FROM {_settings.TwitterUserTableName} WHERE acct = @acct";
|
||||||
|
|
||||||
|
using (var dbConnection = Connection)
|
||||||
|
{
|
||||||
|
dbConnection.Open();
|
||||||
|
|
||||||
|
await dbConnection.QueryAsync(query, new { acct });
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -4,4 +4,8 @@
|
||||||
<TargetFramework>netstandard2.0</TargetFramework>
|
<TargetFramework>netstandard2.0</TargetFramework>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageReference Include="TweetinviAPI" Version="4.0.3" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
</Project>
|
</Project>
|
||||||
|
|
|
@ -0,0 +1,13 @@
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using BirdsiteLive.DAL.Models;
|
||||||
|
using Tweetinvi.Models;
|
||||||
|
|
||||||
|
namespace BirdsiteLive.DAL.Contracts
|
||||||
|
{
|
||||||
|
public interface ICachedTweetsDal
|
||||||
|
{
|
||||||
|
Task CreateTweetAsync(long tweetId, int userId, CachedTweet tweet);
|
||||||
|
Task<CachedTweet> GetTweetAsync(long tweetId);
|
||||||
|
Task DeleteTweetAsync(long tweetId);
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,7 +1,16 @@
|
||||||
namespace BirdsiteLive.DAL.Contracts
|
using System.Collections.Generic;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using BirdsiteLive.DAL.Models;
|
||||||
|
|
||||||
|
namespace BirdsiteLive.DAL.Contracts
|
||||||
{
|
{
|
||||||
public interface IFollowersDal
|
public interface IFollowersDal
|
||||||
{
|
{
|
||||||
|
Task<Follower> GetFollowerAsync(string acct, string host);
|
||||||
|
Task CreateFollowerAsync(string acct, string host, int[] followings, Dictionary<int, long> followingSyncStatus);
|
||||||
|
Task<Follower[]> GetFollowersAsync(int followedUserId);
|
||||||
|
Task UpdateFollowerAsync(int id, int[] followings, Dictionary<int, long> followingSyncStatus);
|
||||||
|
Task DeleteFollowerAsync(int id);
|
||||||
|
Task DeleteFollowerAsync(string acct, string host);
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,7 +1,14 @@
|
||||||
namespace BirdsiteLive.DAL.Contracts
|
using System.Threading.Tasks;
|
||||||
|
using BirdsiteLive.DAL.Models;
|
||||||
|
|
||||||
|
namespace BirdsiteLive.DAL.Contracts
|
||||||
{
|
{
|
||||||
public interface ITwitterUserDal
|
public interface ITwitterUserDal
|
||||||
{
|
{
|
||||||
|
Task CreateTwitterUserAsync(string acct, long lastTweetPostedId);
|
||||||
|
Task<SyncTwitterUser> GetTwitterUserAsync(string acct);
|
||||||
|
Task<SyncTwitterUser[]> GetAllTwitterUsersAsync();
|
||||||
|
Task UpdateTwitterUserAsync(int id, long lastTweetPostedId, long lastTweetSynchronizedForAllFollowersId);
|
||||||
|
Task DeleteTwitterUserAsync(string acct);
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,10 +1,31 @@
|
||||||
namespace BirdsiteLive.DAL.Models
|
using System;
|
||||||
|
|
||||||
|
namespace BirdsiteLive.DAL.Models
|
||||||
{
|
{
|
||||||
public class CachedTweet
|
public class CachedTweet
|
||||||
{
|
{
|
||||||
|
public int UserId { get; set; }
|
||||||
|
|
||||||
public long Id { get; set; }
|
public long Id { get; set; }
|
||||||
public long TwitterUserId { get; set; }
|
public DateTime CreatedAt { get; set; }
|
||||||
|
|
||||||
public string TweetData { get; set; }
|
public string Text { get; set; }
|
||||||
|
public string FullText { get; set; }
|
||||||
|
|
||||||
|
public long? InReplyToStatusId { get; set; }
|
||||||
|
public string InReplyToStatusIdStr { get; set; }
|
||||||
|
public long? InReplyToUserId { get; set; }
|
||||||
|
public string InReplyToUserIdStr { get; set; }
|
||||||
|
public string InReplyToScreenName { get; set; }
|
||||||
|
|
||||||
|
// List<IHashtagEntity> Hashtags { get; }
|
||||||
|
//List<IUrlEntity> Urls { get; }
|
||||||
|
//List<IMediaEntity> Media { get; }
|
||||||
|
//List<IUserMentionEntity> UserMentions { get; }
|
||||||
|
//List<ITweet> Retweets { get; set; }
|
||||||
|
public bool IsRetweet { get; }
|
||||||
|
public CachedTweet RetweetedTweet { get; }
|
||||||
|
public string Url { get; }
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
|
@ -1,13 +1,15 @@
|
||||||
namespace BirdsiteLive.DAL.Models
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
namespace BirdsiteLive.DAL.Models
|
||||||
{
|
{
|
||||||
public class Follower
|
public class Follower
|
||||||
{
|
{
|
||||||
public int Id { get; set; }
|
public int Id { get; set; }
|
||||||
public int FollowingAccountId { get; set; }
|
|
||||||
|
|
||||||
|
public int[] Followings { get; set; }
|
||||||
|
public Dictionary<int, long> FollowingsSyncStatus { get; set; }
|
||||||
|
|
||||||
public string Acct { get; set; }
|
public string Acct { get; set; }
|
||||||
public string Host { get; set; }
|
public string Host { get; set; }
|
||||||
|
|
||||||
public long LastTweetSynchronizedId { get; set; }
|
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -0,0 +1,27 @@
|
||||||
|
using BirdsiteLive.DAL.Postgres.Settings;
|
||||||
|
using BirdsiteLive.DAL.Postgres.Tools;
|
||||||
|
using BirdsiteLive.DAL.Tools;
|
||||||
|
|
||||||
|
namespace BirdsiteLive.DAL.Postgres.Tests.DataAccessLayers.Base
|
||||||
|
{
|
||||||
|
public class PostgresTestingBase
|
||||||
|
{
|
||||||
|
protected readonly PostgresSettings _settings;
|
||||||
|
protected readonly PostgresTools _tools;
|
||||||
|
|
||||||
|
#region Ctor
|
||||||
|
public PostgresTestingBase()
|
||||||
|
{
|
||||||
|
_settings = new PostgresSettings
|
||||||
|
{
|
||||||
|
ConnString = "Host=127.0.0.1;Username=postgres;Password=mysecretpassword;Database=mytestdb",
|
||||||
|
DbVersionTableName = "DbVersionTableName" + RandomGenerator.GetString(4),
|
||||||
|
CachedTweetsTableName = "CachedTweetsTableName" + RandomGenerator.GetString(4),
|
||||||
|
FollowersTableName = "FollowersTableName" + RandomGenerator.GetString(4),
|
||||||
|
TwitterUserTableName = "TwitterUserTableName" + RandomGenerator.GetString(4),
|
||||||
|
};
|
||||||
|
_tools = new PostgresTools(_settings);
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,87 @@
|
||||||
|
using System;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using BirdsiteLive.DAL.Models;
|
||||||
|
using BirdsiteLive.DAL.Postgres.DataAccessLayers;
|
||||||
|
using BirdsiteLive.DAL.Postgres.Tests.DataAccessLayers.Base;
|
||||||
|
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||||
|
|
||||||
|
namespace BirdsiteLive.DAL.Postgres.Tests.DataAccessLayers
|
||||||
|
{
|
||||||
|
[TestClass]
|
||||||
|
public class CachedTweetsPostgresDalTests : PostgresTestingBase
|
||||||
|
{
|
||||||
|
[TestInitialize]
|
||||||
|
public async Task TestInit()
|
||||||
|
{
|
||||||
|
var dal = new DbInitializerPostgresDal(_settings, _tools);
|
||||||
|
await dal.InitDbAsync();
|
||||||
|
}
|
||||||
|
|
||||||
|
[TestCleanup]
|
||||||
|
public async Task CleanUp()
|
||||||
|
{
|
||||||
|
var dal = new DbInitializerPostgresDal(_settings, _tools);
|
||||||
|
try
|
||||||
|
{
|
||||||
|
await dal.DeleteAllAsync();
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
Console.WriteLine(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[TestMethod]
|
||||||
|
public async Task CreateAndGet()
|
||||||
|
{
|
||||||
|
var id = 152L;
|
||||||
|
var userId = 15;
|
||||||
|
|
||||||
|
var tweet = new CachedTweet
|
||||||
|
{
|
||||||
|
UserId = userId,
|
||||||
|
Id = id,
|
||||||
|
Text = "text data",
|
||||||
|
FullText = "full text data",
|
||||||
|
CreatedAt = DateTime.UtcNow
|
||||||
|
};
|
||||||
|
|
||||||
|
var dal = new CachedTweetsPostgresDal(_settings);
|
||||||
|
await dal.CreateTweetAsync(id, userId, tweet);
|
||||||
|
|
||||||
|
var result = await dal.GetTweetAsync(id);
|
||||||
|
|
||||||
|
Assert.IsNotNull(result);
|
||||||
|
Assert.AreEqual(id, result.Id);
|
||||||
|
Assert.AreEqual(tweet.Text, result.Text);
|
||||||
|
Assert.AreEqual(tweet.FullText, result.FullText);
|
||||||
|
Assert.AreEqual(tweet.CreatedAt, result.CreatedAt);
|
||||||
|
}
|
||||||
|
|
||||||
|
[TestMethod]
|
||||||
|
public async Task CreateAndDelete()
|
||||||
|
{
|
||||||
|
var id = 152L;
|
||||||
|
var userId = 15;
|
||||||
|
|
||||||
|
var tweet = new CachedTweet
|
||||||
|
{
|
||||||
|
UserId = userId,
|
||||||
|
Id = id,
|
||||||
|
Text = "text data",
|
||||||
|
FullText = "full text data",
|
||||||
|
CreatedAt = DateTime.UtcNow
|
||||||
|
};
|
||||||
|
|
||||||
|
var dal = new CachedTweetsPostgresDal(_settings);
|
||||||
|
await dal.CreateTweetAsync(id, userId, tweet);
|
||||||
|
|
||||||
|
var result = await dal.GetTweetAsync(id);
|
||||||
|
Assert.IsNotNull(result);
|
||||||
|
|
||||||
|
await dal.DeleteTweetAsync(id);
|
||||||
|
result = await dal.GetTweetAsync(id);
|
||||||
|
Assert.IsNull(result);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,34 +1,14 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using BirdsiteLive.DAL.Postgres.DataAccessLayers;
|
using BirdsiteLive.DAL.Postgres.DataAccessLayers;
|
||||||
using BirdsiteLive.DAL.Postgres.Settings;
|
using BirdsiteLive.DAL.Postgres.Tests.DataAccessLayers.Base;
|
||||||
using BirdsiteLive.DAL.Postgres.Tools;
|
|
||||||
using BirdsiteLive.DAL.Tools;
|
|
||||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||||
|
|
||||||
namespace BirdsiteLive.DAL.Postgres.Tests.DataAccessLayers
|
namespace BirdsiteLive.DAL.Postgres.Tests.DataAccessLayers
|
||||||
{
|
{
|
||||||
[TestClass]
|
[TestClass]
|
||||||
public class DbInitializerPostgresDalTests
|
public class DbInitializerPostgresDalTests : PostgresTestingBase
|
||||||
{
|
{
|
||||||
private readonly PostgresSettings _settings;
|
|
||||||
private readonly PostgresTools _tools;
|
|
||||||
|
|
||||||
#region Ctor
|
|
||||||
public DbInitializerPostgresDalTests()
|
|
||||||
{
|
|
||||||
_settings = new PostgresSettings
|
|
||||||
{
|
|
||||||
ConnString = "Host=127.0.0.1;Username=postgres;Password=mysecretpassword;Database=mytestdb",
|
|
||||||
DbVersionTableName = "DbVersionTableName" + RandomGenerator.GetString(4),
|
|
||||||
CachedTweetsTableName = "CachedTweetsTableName" + RandomGenerator.GetString(4),
|
|
||||||
FollowersTableName = "FollowersTableName" + RandomGenerator.GetString(4),
|
|
||||||
TwitterUserTableName = "TwitterUserTableName" + RandomGenerator.GetString(4),
|
|
||||||
};
|
|
||||||
_tools = new PostgresTools(_settings);
|
|
||||||
}
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
[TestCleanup]
|
[TestCleanup]
|
||||||
public async Task CleanUp()
|
public async Task CleanUp()
|
||||||
{
|
{
|
||||||
|
|
|
@ -0,0 +1,216 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.ComponentModel;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using BirdsiteLive.DAL.Postgres.DataAccessLayers;
|
||||||
|
using BirdsiteLive.DAL.Postgres.Tests.DataAccessLayers.Base;
|
||||||
|
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||||
|
|
||||||
|
namespace BirdsiteLive.DAL.Postgres.Tests.DataAccessLayers
|
||||||
|
{
|
||||||
|
[TestClass]
|
||||||
|
public class FollowersPostgresDalTests : PostgresTestingBase
|
||||||
|
{
|
||||||
|
[TestInitialize]
|
||||||
|
public async Task TestInit()
|
||||||
|
{
|
||||||
|
var dal = new DbInitializerPostgresDal(_settings, _tools);
|
||||||
|
await dal.InitDbAsync();
|
||||||
|
}
|
||||||
|
|
||||||
|
[TestCleanup]
|
||||||
|
public async Task CleanUp()
|
||||||
|
{
|
||||||
|
var dal = new DbInitializerPostgresDal(_settings, _tools);
|
||||||
|
try
|
||||||
|
{
|
||||||
|
await dal.DeleteAllAsync();
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
Console.WriteLine(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[TestMethod]
|
||||||
|
public async Task CreateAndGetFollower()
|
||||||
|
{
|
||||||
|
var acct = "myhandle";
|
||||||
|
var host = "domain.ext";
|
||||||
|
var following = new[] {12, 19, 23};
|
||||||
|
var followingSync = new Dictionary<int, long>()
|
||||||
|
{
|
||||||
|
{12, 165L},
|
||||||
|
{19, 166L},
|
||||||
|
{23, 167L}
|
||||||
|
};
|
||||||
|
|
||||||
|
var dal = new FollowersPostgresDal(_settings);
|
||||||
|
await dal.CreateFollowerAsync(acct, host, following, followingSync);
|
||||||
|
|
||||||
|
var result = await dal.GetFollowerAsync(acct, host);
|
||||||
|
|
||||||
|
Assert.IsNotNull(result);
|
||||||
|
Assert.AreEqual(acct, result.Acct);
|
||||||
|
Assert.AreEqual(host, result.Host);
|
||||||
|
Assert.AreEqual(following.Length, result.Followings.Length);
|
||||||
|
Assert.AreEqual(following[0], result.Followings[0]);
|
||||||
|
Assert.AreEqual(followingSync.Count, result.FollowingsSyncStatus.Count);
|
||||||
|
Assert.AreEqual(followingSync.First().Key, result.FollowingsSyncStatus.First().Key);
|
||||||
|
Assert.AreEqual(followingSync.First().Value, result.FollowingsSyncStatus.First().Value);
|
||||||
|
}
|
||||||
|
|
||||||
|
[TestMethod]
|
||||||
|
public async Task GetFollowersAsync()
|
||||||
|
{
|
||||||
|
var dal = new FollowersPostgresDal(_settings);
|
||||||
|
|
||||||
|
//User 1
|
||||||
|
var acct = "myhandle1";
|
||||||
|
var host = "domain.ext";
|
||||||
|
var following = new[] { 1,2,3 };
|
||||||
|
var followingSync = new Dictionary<int, long>();
|
||||||
|
await dal.CreateFollowerAsync(acct, host, following, followingSync);
|
||||||
|
|
||||||
|
//User 2
|
||||||
|
acct = "myhandle2";
|
||||||
|
host = "domain.ext";
|
||||||
|
following = new[] { 2, 4, 5 };
|
||||||
|
await dal.CreateFollowerAsync(acct, host, following, followingSync);
|
||||||
|
|
||||||
|
//User 2
|
||||||
|
acct = "myhandle3";
|
||||||
|
host = "domain.ext";
|
||||||
|
following = new[] { 1 };
|
||||||
|
await dal.CreateFollowerAsync(acct, host, following, followingSync);
|
||||||
|
|
||||||
|
var result = await dal.GetFollowersAsync(2);
|
||||||
|
Assert.AreEqual(2, result.Length);
|
||||||
|
|
||||||
|
result = await dal.GetFollowersAsync(5);
|
||||||
|
Assert.AreEqual(1, result.Length);
|
||||||
|
|
||||||
|
result = await dal.GetFollowersAsync(24);
|
||||||
|
Assert.AreEqual(0, result.Length);
|
||||||
|
}
|
||||||
|
|
||||||
|
[TestMethod]
|
||||||
|
public async Task CreateUpdateAndGetFollower_Add()
|
||||||
|
{
|
||||||
|
var acct = "myhandle";
|
||||||
|
var host = "domain.ext";
|
||||||
|
var following = new[] { 12, 19, 23 };
|
||||||
|
var followingSync = new Dictionary<int, long>()
|
||||||
|
{
|
||||||
|
{12, 165L},
|
||||||
|
{19, 166L},
|
||||||
|
{23, 167L}
|
||||||
|
};
|
||||||
|
|
||||||
|
var dal = new FollowersPostgresDal(_settings);
|
||||||
|
await dal.CreateFollowerAsync(acct, host, following, followingSync);
|
||||||
|
var result = await dal.GetFollowerAsync(acct, host);
|
||||||
|
|
||||||
|
var updatedFollowing = new[] { 12, 19, 23, 24 };
|
||||||
|
var updatedFollowingSync = new Dictionary<int, long>()
|
||||||
|
{
|
||||||
|
{12, 170L},
|
||||||
|
{19, 171L},
|
||||||
|
{23, 172L},
|
||||||
|
{24, 173L}
|
||||||
|
};
|
||||||
|
|
||||||
|
await dal.UpdateFollowerAsync(result.Id, updatedFollowing, updatedFollowingSync);
|
||||||
|
result = await dal.GetFollowerAsync(acct, host);
|
||||||
|
|
||||||
|
Assert.AreEqual(updatedFollowing.Length, result.Followings.Length);
|
||||||
|
Assert.AreEqual(updatedFollowing[0], result.Followings[0]);
|
||||||
|
Assert.AreEqual(updatedFollowingSync.Count, result.FollowingsSyncStatus.Count);
|
||||||
|
Assert.AreEqual(updatedFollowingSync.First().Key, result.FollowingsSyncStatus.First().Key);
|
||||||
|
Assert.AreEqual(updatedFollowingSync.First().Value, result.FollowingsSyncStatus.First().Value);
|
||||||
|
}
|
||||||
|
|
||||||
|
[TestMethod]
|
||||||
|
public async Task CreateUpdateAndGetFollower_Remove()
|
||||||
|
{
|
||||||
|
var acct = "myhandle";
|
||||||
|
var host = "domain.ext";
|
||||||
|
var following = new[] { 12, 19, 23 };
|
||||||
|
var followingSync = new Dictionary<int, long>()
|
||||||
|
{
|
||||||
|
{12, 165L},
|
||||||
|
{19, 166L},
|
||||||
|
{23, 167L}
|
||||||
|
};
|
||||||
|
|
||||||
|
var dal = new FollowersPostgresDal(_settings);
|
||||||
|
await dal.CreateFollowerAsync(acct, host, following, followingSync);
|
||||||
|
var result = await dal.GetFollowerAsync(acct, host);
|
||||||
|
|
||||||
|
var updatedFollowing = new[] { 12, 19 };
|
||||||
|
var updatedFollowingSync = new Dictionary<int, long>()
|
||||||
|
{
|
||||||
|
{12, 170L},
|
||||||
|
{19, 171L}
|
||||||
|
};
|
||||||
|
|
||||||
|
await dal.UpdateFollowerAsync(result.Id, updatedFollowing, updatedFollowingSync);
|
||||||
|
result = await dal.GetFollowerAsync(acct, host);
|
||||||
|
|
||||||
|
Assert.AreEqual(updatedFollowing.Length, result.Followings.Length);
|
||||||
|
Assert.AreEqual(updatedFollowing[0], result.Followings[0]);
|
||||||
|
Assert.AreEqual(updatedFollowingSync.Count, result.FollowingsSyncStatus.Count);
|
||||||
|
Assert.AreEqual(updatedFollowingSync.First().Key, result.FollowingsSyncStatus.First().Key);
|
||||||
|
Assert.AreEqual(updatedFollowingSync.First().Value, result.FollowingsSyncStatus.First().Value);
|
||||||
|
}
|
||||||
|
|
||||||
|
[TestMethod]
|
||||||
|
public async Task CreateAndDeleteFollower_ById()
|
||||||
|
{
|
||||||
|
var acct = "myhandle";
|
||||||
|
var host = "domain.ext";
|
||||||
|
var following = new[] { 12, 19, 23 };
|
||||||
|
var followingSync = new Dictionary<int, long>()
|
||||||
|
{
|
||||||
|
{12, 165L},
|
||||||
|
{19, 166L},
|
||||||
|
{23, 167L}
|
||||||
|
};
|
||||||
|
|
||||||
|
var dal = new FollowersPostgresDal(_settings);
|
||||||
|
await dal.CreateFollowerAsync(acct, host, following, followingSync);
|
||||||
|
var result = await dal.GetFollowerAsync(acct, host);
|
||||||
|
Assert.IsNotNull(result);
|
||||||
|
|
||||||
|
await dal.DeleteFollowerAsync(result.Id);
|
||||||
|
|
||||||
|
result = await dal.GetFollowerAsync(acct, host);
|
||||||
|
Assert.IsNull(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
[TestMethod]
|
||||||
|
public async Task CreateAndDeleteFollower_ByHandle()
|
||||||
|
{
|
||||||
|
var acct = "myhandle";
|
||||||
|
var host = "domain.ext";
|
||||||
|
var following = new[] { 12, 19, 23 };
|
||||||
|
var followingSync = new Dictionary<int, long>()
|
||||||
|
{
|
||||||
|
{12, 165L},
|
||||||
|
{19, 166L},
|
||||||
|
{23, 167L}
|
||||||
|
};
|
||||||
|
|
||||||
|
var dal = new FollowersPostgresDal(_settings);
|
||||||
|
await dal.CreateFollowerAsync(acct, host, following, followingSync);
|
||||||
|
var result = await dal.GetFollowerAsync(acct, host);
|
||||||
|
Assert.IsNotNull(result);
|
||||||
|
|
||||||
|
await dal.DeleteFollowerAsync(acct, host);
|
||||||
|
|
||||||
|
result = await dal.GetFollowerAsync(acct, host);
|
||||||
|
Assert.IsNull(result);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,119 @@
|
||||||
|
using System;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using System.Xml;
|
||||||
|
using BirdsiteLive.DAL.Postgres.DataAccessLayers;
|
||||||
|
using BirdsiteLive.DAL.Postgres.Tests.DataAccessLayers.Base;
|
||||||
|
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||||
|
|
||||||
|
namespace BirdsiteLive.DAL.Postgres.Tests.DataAccessLayers
|
||||||
|
{
|
||||||
|
[TestClass]
|
||||||
|
public class TwitterUserPostgresDalTests : PostgresTestingBase
|
||||||
|
{
|
||||||
|
[TestInitialize]
|
||||||
|
public async Task TestInit()
|
||||||
|
{
|
||||||
|
var dal = new DbInitializerPostgresDal(_settings, _tools);
|
||||||
|
await dal.InitDbAsync();
|
||||||
|
}
|
||||||
|
|
||||||
|
[TestCleanup]
|
||||||
|
public async Task CleanUp()
|
||||||
|
{
|
||||||
|
var dal = new DbInitializerPostgresDal(_settings, _tools);
|
||||||
|
try
|
||||||
|
{
|
||||||
|
await dal.DeleteAllAsync();
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
Console.WriteLine(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[TestMethod]
|
||||||
|
public async Task GetTwitterUserAsync_NoUser()
|
||||||
|
{
|
||||||
|
var dal = new TwitterUserPostgresDal(_settings);
|
||||||
|
var result = await dal.GetTwitterUserAsync("dontexist");
|
||||||
|
Assert.IsNull(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
[TestMethod]
|
||||||
|
public async Task CreateAndGetUser()
|
||||||
|
{
|
||||||
|
var acct = "myid";
|
||||||
|
var lastTweetId = 1548L;
|
||||||
|
|
||||||
|
var dal = new TwitterUserPostgresDal(_settings);
|
||||||
|
|
||||||
|
await dal.CreateTwitterUserAsync(acct, lastTweetId);
|
||||||
|
var result = await dal.GetTwitterUserAsync(acct);
|
||||||
|
|
||||||
|
Assert.AreEqual(acct, result.Acct);
|
||||||
|
Assert.AreEqual(lastTweetId, result.LastTweetPostedId);
|
||||||
|
Assert.AreEqual(lastTweetId, result.LastTweetSynchronizedForAllFollowersId);
|
||||||
|
Assert.IsTrue(result.Id > 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
[TestMethod]
|
||||||
|
public async Task CreateUpdateAndGetUser()
|
||||||
|
{
|
||||||
|
var acct = "myid";
|
||||||
|
var lastTweetId = 1548L;
|
||||||
|
|
||||||
|
var dal = new TwitterUserPostgresDal(_settings);
|
||||||
|
|
||||||
|
await dal.CreateTwitterUserAsync(acct, lastTweetId);
|
||||||
|
var result = await dal.GetTwitterUserAsync(acct);
|
||||||
|
|
||||||
|
|
||||||
|
var updatedLastTweetId = 1600L;
|
||||||
|
var updatedLastSyncId = 1550L;
|
||||||
|
await dal.UpdateTwitterUserAsync(result.Id, updatedLastTweetId, updatedLastSyncId);
|
||||||
|
|
||||||
|
result = await dal.GetTwitterUserAsync(acct);
|
||||||
|
|
||||||
|
Assert.AreEqual(acct, result.Acct);
|
||||||
|
Assert.AreEqual(updatedLastTweetId, result.LastTweetPostedId);
|
||||||
|
Assert.AreEqual(updatedLastSyncId, result.LastTweetSynchronizedForAllFollowersId);
|
||||||
|
}
|
||||||
|
|
||||||
|
[TestMethod]
|
||||||
|
public async Task CreateAndDeleteUser()
|
||||||
|
{
|
||||||
|
var acct = "myid";
|
||||||
|
var lastTweetId = 1548L;
|
||||||
|
|
||||||
|
var dal = new TwitterUserPostgresDal(_settings);
|
||||||
|
|
||||||
|
await dal.CreateTwitterUserAsync(acct, lastTweetId);
|
||||||
|
var result = await dal.GetTwitterUserAsync(acct);
|
||||||
|
Assert.IsNotNull(result);
|
||||||
|
|
||||||
|
await dal.DeleteTwitterUserAsync(acct);
|
||||||
|
result = await dal.GetTwitterUserAsync(acct);
|
||||||
|
Assert.IsNull(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
[TestMethod]
|
||||||
|
public async Task GetAllTwitterUsers()
|
||||||
|
{
|
||||||
|
var dal = new TwitterUserPostgresDal(_settings);
|
||||||
|
for (var i = 0; i < 1000; i++)
|
||||||
|
{
|
||||||
|
var acct = $"myid{i}";
|
||||||
|
var lastTweetId = 1548L;
|
||||||
|
|
||||||
|
await dal.CreateTwitterUserAsync(acct, lastTweetId);
|
||||||
|
}
|
||||||
|
|
||||||
|
var result = await dal.GetAllTwitterUsersAsync();
|
||||||
|
Assert.AreEqual(1000, result.Length);
|
||||||
|
Assert.IsFalse(result[0].Id == default);
|
||||||
|
Assert.IsFalse(result[0].Acct == default);
|
||||||
|
Assert.IsFalse(result[0].LastTweetPostedId == default);
|
||||||
|
Assert.IsFalse(result[0].LastTweetSynchronizedForAllFollowersId == default);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Add table
Reference in a new issue