diff --git a/src/BirdsiteLive.Common/Settings/LogsSettings.cs b/src/BirdsiteLive.Common/Settings/LogsSettings.cs new file mode 100644 index 0000000..4919417 --- /dev/null +++ b/src/BirdsiteLive.Common/Settings/LogsSettings.cs @@ -0,0 +1,8 @@ +namespace BirdsiteLive.Common.Settings +{ + public class LogsSettings + { + public string Type { get; set; } + public string InstrumentationKey { get; set; } + } +} \ No newline at end of file diff --git a/src/BirdsiteLive/BirdsiteLive.csproj b/src/BirdsiteLive/BirdsiteLive.csproj index 8b92b7c..774c4ce 100644 --- a/src/BirdsiteLive/BirdsiteLive.csproj +++ b/src/BirdsiteLive/BirdsiteLive.csproj @@ -4,11 +4,12 @@ netcoreapp3.1 d21486de-a812-47eb-a419-05682bb68856 Linux - 0.1.0 + 0.2.0 + diff --git a/src/BirdsiteLive/Controllers/StatisticsController.cs b/src/BirdsiteLive/Controllers/StatisticsController.cs new file mode 100644 index 0000000..90d58e2 --- /dev/null +++ b/src/BirdsiteLive/Controllers/StatisticsController.cs @@ -0,0 +1,34 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using BirdsiteLive.DAL.Contracts; +using BirdsiteLive.Models.StatisticsModels; +using Microsoft.AspNetCore.Mvc; + +namespace BirdsiteLive.Controllers +{ + public class StatisticsController : Controller + { + private readonly ITwitterUserDal _twitterUserDal; + private readonly IFollowersDal _followersDal; + + #region Ctor + public StatisticsController(ITwitterUserDal twitterUserDal, IFollowersDal followersDal) + { + _twitterUserDal = twitterUserDal; + _followersDal = followersDal; + } + #endregion + + public async Task Index() + { + var stats = new Statistics + { + FollowersCount = await _followersDal.GetFollowersCountAsync(), + TwitterUserCount = await _twitterUserDal.GetTwitterUsersCountAsync() + }; + return View(stats); + } + } +} diff --git a/src/BirdsiteLive/Controllers/WellKnownController.cs b/src/BirdsiteLive/Controllers/WellKnownController.cs index 9ac3bb3..5be47be 100644 --- a/src/BirdsiteLive/Controllers/WellKnownController.cs +++ b/src/BirdsiteLive/Controllers/WellKnownController.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using BirdsiteLive.Common.Settings; +using BirdsiteLive.DAL.Contracts; using BirdsiteLive.Models; using BirdsiteLive.Models.WellKnownModels; using BirdsiteLive.Twitter; @@ -15,12 +16,14 @@ namespace BirdsiteLive.Controllers public class WellKnownController : ControllerBase { private readonly ITwitterService _twitterService; + private readonly ITwitterUserDal _twitterUserDal; private readonly InstanceSettings _settings; #region Ctor - public WellKnownController(InstanceSettings settings, ITwitterService twitterService) + public WellKnownController(InstanceSettings settings, ITwitterService twitterService, ITwitterUserDal twitterUserDal) { _twitterService = twitterService; + _twitterUserDal = twitterUserDal; _settings = settings; } #endregion @@ -48,9 +51,10 @@ namespace BirdsiteLive.Controllers } [Route("/nodeinfo/{id}.json")] - public IActionResult NodeInfo(string id) + public async Task NodeInfo(string id) { var version = System.Reflection.Assembly.GetEntryAssembly().GetName().Version.ToString(3); + var twitterUsersCount = await _twitterUserDal.GetTwitterUsersCountAsync(); if (id == "2.0") { @@ -62,7 +66,7 @@ namespace BirdsiteLive.Controllers localPosts = 0, users = new Users() { - total = 0 + total = twitterUsersCount } }, software = new Software() @@ -97,7 +101,7 @@ namespace BirdsiteLive.Controllers localPosts = 0, users = new Users() { - total = 0 + total = twitterUsersCount } }, software = new SoftwareV21() diff --git a/src/BirdsiteLive/Models/StatisticsModels/Statistics.cs b/src/BirdsiteLive/Models/StatisticsModels/Statistics.cs new file mode 100644 index 0000000..bf62e58 --- /dev/null +++ b/src/BirdsiteLive/Models/StatisticsModels/Statistics.cs @@ -0,0 +1,8 @@ +namespace BirdsiteLive.Models.StatisticsModels +{ + public class Statistics + { + public int FollowersCount { get; set; } + public int TwitterUserCount { get; set; } + } +} \ No newline at end of file diff --git a/src/BirdsiteLive/Startup.cs b/src/BirdsiteLive/Startup.cs index c2d7cb0..a6806b9 100644 --- a/src/BirdsiteLive/Startup.cs +++ b/src/BirdsiteLive/Startup.cs @@ -38,8 +38,12 @@ namespace BirdsiteLive // This method gets called by the runtime. Use this method to add services to the container. public void ConfigureServices(IServiceCollection services) { - //services.Configure(Configuration.GetSection("Instance")); - //services.Configure(Configuration.GetSection("Twitter")); + var logsSettings = Configuration.GetSection("Logging").Get(); + if(string.Equals("insights", logsSettings.Type, StringComparison.OrdinalIgnoreCase)) + { + var key = logsSettings.InstrumentationKey; + services.AddApplicationInsightsTelemetry(key); + } services.AddControllersWithViews(); } @@ -55,6 +59,9 @@ namespace BirdsiteLive var dbSettings = Configuration.GetSection("Db").Get(); services.For().Use(x => dbSettings); + var logsSettings = Configuration.GetSection("Logging").Get(); + services.For().Use(x => logsSettings); + if (string.Equals(dbSettings.Type, DbTypes.Postgres, StringComparison.OrdinalIgnoreCase)) { var connString = $"Host={dbSettings.Host};Username={dbSettings.User};Password={dbSettings.Password};Database={dbSettings.Name}"; diff --git a/src/BirdsiteLive/Views/Statistics/Index.cshtml b/src/BirdsiteLive/Views/Statistics/Index.cshtml new file mode 100644 index 0000000..31dc9f7 --- /dev/null +++ b/src/BirdsiteLive/Views/Statistics/Index.cshtml @@ -0,0 +1,12 @@ +@model BirdsiteLive.Models.StatisticsModels.Statistics + +@{ + ViewBag.Title = "Statistics"; +} + +

Statistics

+ +
    +
  • Twitter Users: @Model.TwitterUserCount
  • +
  • Followers: @Model.FollowersCount
  • +
\ No newline at end of file diff --git a/src/BirdsiteLive/appsettings.json b/src/BirdsiteLive/appsettings.json index 88712f8..f240094 100644 --- a/src/BirdsiteLive/appsettings.json +++ b/src/BirdsiteLive/appsettings.json @@ -1,5 +1,7 @@ { "Logging": { + "Type": "none", + "InstrumentationKey": "key", "LogLevel": { "Default": "Information", "Microsoft": "Warning", diff --git a/src/DataAccessLayers/BirdsiteLive.DAL.Postgres/DataAccessLayers/FollowersPostgresDal.cs b/src/DataAccessLayers/BirdsiteLive.DAL.Postgres/DataAccessLayers/FollowersPostgresDal.cs index 961aa7c..39c07cb 100644 --- a/src/DataAccessLayers/BirdsiteLive.DAL.Postgres/DataAccessLayers/FollowersPostgresDal.cs +++ b/src/DataAccessLayers/BirdsiteLive.DAL.Postgres/DataAccessLayers/FollowersPostgresDal.cs @@ -40,6 +40,19 @@ namespace BirdsiteLive.DAL.Postgres.DataAccessLayers } } + public async Task GetFollowersCountAsync() + { + var query = $"SELECT COUNT(*) FROM {_settings.FollowersTableName}"; + + using (var dbConnection = Connection) + { + dbConnection.Open(); + + var result = (await dbConnection.QueryAsync(query)).FirstOrDefault(); + return result; + } + } + public async Task GetFollowerAsync(string acct, string host) { var query = $"SELECT * FROM {_settings.FollowersTableName} WHERE acct = @acct AND host = @host"; diff --git a/src/DataAccessLayers/BirdsiteLive.DAL.Postgres/DataAccessLayers/TwitterUserPostgresDal.cs b/src/DataAccessLayers/BirdsiteLive.DAL.Postgres/DataAccessLayers/TwitterUserPostgresDal.cs index eaa610b..082229a 100644 --- a/src/DataAccessLayers/BirdsiteLive.DAL.Postgres/DataAccessLayers/TwitterUserPostgresDal.cs +++ b/src/DataAccessLayers/BirdsiteLive.DAL.Postgres/DataAccessLayers/TwitterUserPostgresDal.cs @@ -49,6 +49,19 @@ namespace BirdsiteLive.DAL.Postgres.DataAccessLayers } } + public async Task GetTwitterUsersCountAsync() + { + var query = $"SELECT COUNT(*) FROM {_settings.TwitterUserTableName}"; + + using (var dbConnection = Connection) + { + dbConnection.Open(); + + var result = (await dbConnection.QueryAsync(query)).FirstOrDefault(); + return result; + } + } + public async Task GetAllTwitterUsersAsync() { var query = $"SELECT * FROM {_settings.TwitterUserTableName}"; diff --git a/src/DataAccessLayers/BirdsiteLive.DAL/Contracts/IFollowersDal.cs b/src/DataAccessLayers/BirdsiteLive.DAL/Contracts/IFollowersDal.cs index 8b5e6e1..23cf2b2 100644 --- a/src/DataAccessLayers/BirdsiteLive.DAL/Contracts/IFollowersDal.cs +++ b/src/DataAccessLayers/BirdsiteLive.DAL/Contracts/IFollowersDal.cs @@ -13,5 +13,6 @@ namespace BirdsiteLive.DAL.Contracts Task UpdateFollowerAsync(Follower follower); Task DeleteFollowerAsync(int id); Task DeleteFollowerAsync(string acct, string host); + Task GetFollowersCountAsync(); } } \ No newline at end of file diff --git a/src/DataAccessLayers/BirdsiteLive.DAL/Contracts/ITwitterUserDal.cs b/src/DataAccessLayers/BirdsiteLive.DAL/Contracts/ITwitterUserDal.cs index e0050fd..48d5661 100644 --- a/src/DataAccessLayers/BirdsiteLive.DAL/Contracts/ITwitterUserDal.cs +++ b/src/DataAccessLayers/BirdsiteLive.DAL/Contracts/ITwitterUserDal.cs @@ -10,5 +10,6 @@ namespace BirdsiteLive.DAL.Contracts Task GetAllTwitterUsersAsync(); Task UpdateTwitterUserAsync(int id, long lastTweetPostedId, long lastTweetSynchronizedForAllFollowersId); Task DeleteTwitterUserAsync(string acct); + Task GetTwitterUsersCountAsync(); } } \ No newline at end of file diff --git a/src/Tests/BirdsiteLive.DAL.Postgres.Tests/DataAccessLayers/FollowersPostgresDalTests.cs b/src/Tests/BirdsiteLive.DAL.Postgres.Tests/DataAccessLayers/FollowersPostgresDalTests.cs index e12d08a..cd6162d 100644 --- a/src/Tests/BirdsiteLive.DAL.Postgres.Tests/DataAccessLayers/FollowersPostgresDalTests.cs +++ b/src/Tests/BirdsiteLive.DAL.Postgres.Tests/DataAccessLayers/FollowersPostgresDalTests.cs @@ -137,6 +137,43 @@ namespace BirdsiteLive.DAL.Postgres.Tests.DataAccessLayers Assert.AreEqual(0, result.Length); } + [TestMethod] + public async Task CountFollowersAsync() + { + var dal = new FollowersPostgresDal(_settings); + + var result = await dal.GetFollowersCountAsync(); + Assert.AreEqual(0, result); + + //User 1 + var acct = "myhandle1"; + var host = "domain.ext"; + var following = new[] { 1, 2, 3 }; + var followingSync = new Dictionary(); + var inboxRoute = "/myhandle1/inbox"; + var sharedInboxRoute = "/inbox"; + await dal.CreateFollowerAsync(acct, host, inboxRoute, sharedInboxRoute, following, followingSync); + + //User 2 + acct = "myhandle2"; + host = "domain.ext"; + following = new[] { 2, 4, 5 }; + inboxRoute = "/myhandle2/inbox"; + sharedInboxRoute = "/inbox2"; + await dal.CreateFollowerAsync(acct, host, inboxRoute, sharedInboxRoute, following, followingSync); + + //User 2 + acct = "myhandle3"; + host = "domain.ext"; + following = new[] { 1 }; + inboxRoute = "/myhandle3/inbox"; + sharedInboxRoute = "/inbox3"; + await dal.CreateFollowerAsync(acct, host, inboxRoute, sharedInboxRoute, following, followingSync); + + result = await dal.GetFollowersCountAsync(); + Assert.AreEqual(3, result); + } + [TestMethod] public async Task CreateUpdateAndGetFollower_Add() { diff --git a/src/Tests/BirdsiteLive.DAL.Postgres.Tests/DataAccessLayers/TwitterUserPostgresDalTests.cs b/src/Tests/BirdsiteLive.DAL.Postgres.Tests/DataAccessLayers/TwitterUserPostgresDalTests.cs index 7150409..f900c8f 100644 --- a/src/Tests/BirdsiteLive.DAL.Postgres.Tests/DataAccessLayers/TwitterUserPostgresDalTests.cs +++ b/src/Tests/BirdsiteLive.DAL.Postgres.Tests/DataAccessLayers/TwitterUserPostgresDalTests.cs @@ -115,5 +115,21 @@ namespace BirdsiteLive.DAL.Postgres.Tests.DataAccessLayers Assert.IsFalse(result[0].LastTweetPostedId == default); Assert.IsFalse(result[0].LastTweetSynchronizedForAllFollowersId == default); } + + [TestMethod] + public async Task CountTwitterUsers() + { + var dal = new TwitterUserPostgresDal(_settings); + for (var i = 0; i < 10; i++) + { + var acct = $"myid{i}"; + var lastTweetId = 1548L; + + await dal.CreateTwitterUserAsync(acct, lastTweetId); + } + + var result = await dal.GetTwitterUsersCountAsync(); + Assert.AreEqual(10, result); + } } } \ No newline at end of file