152 lines
4.5 KiB
C#
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);
|
|
}
|
|
}
|
|
}
|
|
} |