Files
dotnet_dbsync/Services/TvSyncService.cs

152 lines
4.5 KiB
C#

using System.Text.Json;
using dbsync.Config;
using Npgsql;
using Serilog;
namespace TvSyncApp.Services;
public class TvSyncService
{
private readonly string _connectionString;
public TvSyncService(string connectionString)
{
_connectionString = connectionString;
}
// -----------------------------------------
// 1. Download Updates
// -----------------------------------------
public async Task<Dictionary<int, long>> DownloadTvMazeUpdatesAsync(
string updatesUrl,
string tempDir)
{
using var http = new HttpClient();
var json = await http.GetStringAsync(updatesUrl);
// Deserialize first to validate and normalize
var parsed = JsonSerializer.Deserialize<Dictionary<string, long>>(json)
?? new Dictionary<string, long>();
// Convert to int-key dictionary (what your app uses)
var result = parsed
.Where(k => int.TryParse(k.Key, out _))
.ToDictionary(k => int.Parse(k.Key), v => v.Value);
// Pretty-print JSON before saving
var options = new JsonSerializerOptions
{
WriteIndented = true
};
var formattedJson = JsonSerializer.Serialize(result, options);
var filePath = Path.Combine(tempDir, "tvmaze_updates.json");
await File.WriteAllTextAsync(filePath, formattedJson);
return result;
}
// -----------------------------------------
// 2. Update DB
// -----------------------------------------
public void UpdateTvUpdatesTable(Dictionary<int, long> updates)
{
using var conn = new NpgsqlConnection(_connectionString);
conn.Open();
using var transaction = conn.BeginTransaction();
using var batch = new NpgsqlBatch(conn, transaction);
foreach (var kvp in updates)
{
var cmd = new NpgsqlBatchCommand(@"
INSERT INTO updates.tvupdates (seriesid, timestamp)
VALUES (@id, @ts)
ON CONFLICT (seriesid)
DO UPDATE SET timestamp = EXCLUDED.timestamp;");
cmd.Parameters.AddWithValue("id", kvp.Key);
cmd.Parameters.AddWithValue("ts", kvp.Value);
batch.BatchCommands.Add(cmd);
}
batch.ExecuteNonQuery();
transaction.Commit();
Log.Information("Batch updated tvupdates table with {Count} entries.", updates.Count);
}
// -----------------------------------------
// 3. Determine Files Needed
// -----------------------------------------
public List<(string Directory, string FileName)> DetermineFilesNeeded(
Dictionary<int, long> downloadedUpdates,
Dictionary<int, long> previousUpdates,
Dictionary<string, string> directories)
{
var filesNeeded = new List<(string, string)>();
var directoryList = directories.Values.ToList();
foreach (var kvp in downloadedUpdates)
{
var seriesId = kvp.Key;
var newTs = kvp.Value;
if (previousUpdates.TryGetValue(seriesId, out var oldTs))
{
if (newTs > oldTs)
foreach (var dir in directoryList)
filesNeeded.Add((dir, $"{seriesId}.json"));
}
else
{
foreach (var dir in directoryList)
filesNeeded.Add((dir, $"{seriesId}.json"));
}
}
return filesNeeded;
}
// -----------------------------------------
// 4. Download Files
// -----------------------------------------
public async Task DownloadSeriesFilesAsync(
List<(string Directory, string FileName)> filesNeeded,
Dictionary<string, string> skipIds,
Settings settings)
{
using var http = new HttpClient();
foreach (var item in filesNeeded)
{
var seriesId = item.FileName.Replace(".json", "");
var url = settings.Json!.SeriesApi!
.Replace("<seriesid>", seriesId);
if (skipIds.ContainsKey(seriesId))
{
Log.Information("Skipping series {SeriesId}", seriesId);
continue;
}
try
{
var json = await http.GetStringAsync(url);
var savePath = Path.Combine(item.Directory, item.FileName);
await File.WriteAllTextAsync(savePath, json);
}
catch (Exception ex)
{
Log.Error(ex, "Failed downloading {SeriesId}", seriesId);
}
}
}
}