137 lines
3.8 KiB
C#
137 lines
3.8 KiB
C#
using Blog3000.Shared;
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using System.Threading.Tasks;
|
|
using Microsoft.AspNetCore.Mvc;
|
|
using Microsoft.Extensions.Logging;
|
|
using Microsoft.Extensions.Caching.Memory;
|
|
using System.Text;
|
|
using System.IO;
|
|
using Microsoft.AspNetCore.StaticFiles;
|
|
using Microsoft.CodeAnalysis.CSharp.Syntax;
|
|
using Blog3000.Client;
|
|
using System.Text.Json;
|
|
using System.Xml.Linq;
|
|
using System.Threading;
|
|
|
|
namespace Blog3000.Server.Controllers
|
|
{
|
|
[ApiController]
|
|
[Route("[controller]")]
|
|
public class ViewStatsController : ControllerBase
|
|
{
|
|
|
|
private readonly ILogger<BlogPostsController> logger;
|
|
private readonly BlogPostRepo blogPostRepo;
|
|
|
|
private readonly string statsFile;
|
|
|
|
private static readonly SemaphoreSlim myLock = new SemaphoreSlim(1);
|
|
|
|
public ViewStatsController(ILogger<BlogPostsController> logger, BlogPostRepo blogPostRepo)
|
|
{
|
|
this.logger = logger;
|
|
this.blogPostRepo = blogPostRepo;
|
|
|
|
statsFile = System.IO.Path.Combine(
|
|
(string)AppDomain.CurrentDomain.GetData("AppDataPath"),
|
|
"stats.json");
|
|
}
|
|
|
|
|
|
[HttpGet]
|
|
public async Task<ActionResult<Dictionary<string, int>>> GetAsync()
|
|
{
|
|
logger.LogInformation($"ViewStats|{HttpContext.Connection.RemoteIpAddress}|GetAsync");
|
|
|
|
await myLock.WaitAsync();
|
|
try
|
|
{
|
|
var res = await LoadAsync();
|
|
return res;
|
|
}
|
|
finally
|
|
{
|
|
myLock.Release();
|
|
}
|
|
}
|
|
|
|
|
|
[HttpPost]
|
|
public async Task <ActionResult<Dictionary<string, int>>> PostAsync(Dictionary<string, int> newStats)
|
|
{
|
|
// Only add 1 view for each read post to prevent user manipulating stats to much
|
|
// Ignoew unknwon posts
|
|
|
|
logger.LogInformation($"ViewStats|{HttpContext.Connection.RemoteIpAddress}|PostAsync");
|
|
await myLock.WaitAsync();
|
|
try
|
|
{
|
|
var stats = await LoadAsync();
|
|
foreach (var k in newStats.Keys)
|
|
{
|
|
if (blogPostRepo.GetHeaders().FirstOrDefault(p => p.Id.Equals(k)) != null)
|
|
{
|
|
int nv;
|
|
stats.TryGetValue(k, out nv);
|
|
nv++;
|
|
stats.Remove(k);
|
|
stats.Add(k, nv);
|
|
}
|
|
}
|
|
await SaveAsync(stats);
|
|
return stats;
|
|
}
|
|
finally
|
|
{
|
|
myLock.Release();
|
|
}
|
|
}
|
|
|
|
private async Task<Dictionary<String, int>> LoadAsync()
|
|
{
|
|
Dictionary<string, int> res = null;
|
|
|
|
try
|
|
{
|
|
if (System.IO.File.Exists(statsFile))
|
|
{
|
|
var text = await System.IO.File.ReadAllTextAsync(statsFile);
|
|
res = JsonSerializer.Deserialize<Dictionary<string, int>>(text);
|
|
}
|
|
}
|
|
catch(Exception ex)
|
|
{
|
|
logger.LogWarning(ex, $"Error reading stats file ${statsFile}");
|
|
}
|
|
|
|
return res ?? new Dictionary<string, int>();
|
|
|
|
}
|
|
|
|
|
|
private async Task<bool> SaveAsync(Dictionary<string, int> stats)
|
|
{
|
|
stats ??= new Dictionary<string, int>();
|
|
|
|
try
|
|
{
|
|
var text = JsonSerializer.Serialize(stats);
|
|
await System.IO.File.WriteAllTextAsync(statsFile, text);
|
|
return true;
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
logger.LogWarning(ex, $"Error writing stats file ${statsFile}");
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
}
|