Compare commits
10 commits
5675ea116d
...
ea2fb4d818
| Author | SHA1 | Date | |
|---|---|---|---|
| ea2fb4d818 | |||
| fb8284b5e8 | |||
| 8e65cc3a4b | |||
| 09cd72b278 | |||
| 25676baca4 | |||
| ae9a1d14bf | |||
| cce80d1d37 | |||
| 679449e4ec | |||
| 102a1d5d62 | |||
| b2b4eeff05 |
9 changed files with 142 additions and 34 deletions
|
|
@ -10,7 +10,7 @@ public class DBSyncWatcher
|
|||
private FileSystemWatcher _watcher;
|
||||
public Dictionary<string, Type> WatchFiles { get; set; } = [];
|
||||
|
||||
public delegate void DatabaseChange(string db, object value);
|
||||
public delegate void DatabaseChange(string db, string value);
|
||||
public event DatabaseChange OnDatabaseChange;
|
||||
|
||||
public DBSyncWatcher(string path)
|
||||
|
|
@ -43,9 +43,7 @@ public class DBSyncWatcher
|
|||
{
|
||||
if (line == "") continue;
|
||||
var type = WatchFiles[dbName];
|
||||
var item = JsonSerializer.Deserialize(line, type);
|
||||
if (item == null) continue;
|
||||
OnDatabaseChange?.Invoke(dbName, item);
|
||||
OnDatabaseChange?.Invoke(dbName, line);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -58,9 +56,7 @@ public class DBSyncWatcher
|
|||
foreach (var line in data.Split('\n'))
|
||||
{
|
||||
var type = WatchFiles[dbName];
|
||||
var item = JsonSerializer.Deserialize(line, type);
|
||||
if (item == null) continue;
|
||||
OnDatabaseChange?.Invoke(dbName, item);
|
||||
OnDatabaseChange?.Invoke(dbName, line);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,6 @@
|
|||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Text.Json;
|
||||
using FreeTubeSyncer.Library;
|
||||
|
||||
namespace FreeTubeSyncer.Models.DatabaseModels;
|
||||
|
||||
|
|
@ -23,4 +25,31 @@ public class History : IDataModel
|
|||
|
||||
public string Id() => _id;
|
||||
public bool EqualId(string oid) => _id == oid;
|
||||
|
||||
public void MarshalData(string id, string data)
|
||||
{
|
||||
var tobject = JsonSerializer.Deserialize<History>(data, GlobalJsonOptions.Options);
|
||||
if (tobject == null)
|
||||
return;
|
||||
this._id = id;
|
||||
this.videoId = tobject.videoId;
|
||||
this.title = tobject.title;
|
||||
this.author = tobject.author;
|
||||
this.authorId = tobject.authorId;
|
||||
this.published = tobject.published;
|
||||
this.description = tobject.description;
|
||||
this.viewCount = tobject.viewCount;
|
||||
this.lengthSeconds = tobject.lengthSeconds;
|
||||
this.watchProgress = tobject.watchProgress;
|
||||
this.timeWatched = tobject.timeWatched;
|
||||
this.isLive = tobject.isLive;
|
||||
this.type = tobject.type;
|
||||
this.lastViewedPlaylistType = tobject.lastViewedPlaylistType;
|
||||
this.lastViewedPlaylistItemId = tobject.lastViewedPlaylistItemId;
|
||||
}
|
||||
|
||||
public string JsonData()
|
||||
{
|
||||
return JsonSerializer.Serialize(this);
|
||||
}
|
||||
}
|
||||
|
|
@ -4,4 +4,6 @@ public interface IDataModel
|
|||
{
|
||||
string Id();
|
||||
bool EqualId(string oid);
|
||||
void MarshalData(string id, string data);
|
||||
string JsonData();
|
||||
}
|
||||
|
|
@ -1,5 +1,7 @@
|
|||
using System.Collections.Generic;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Text.Json;
|
||||
using FreeTubeSyncer.Library;
|
||||
|
||||
namespace FreeTubeSyncer.Models.DatabaseModels;
|
||||
|
||||
|
|
@ -15,4 +17,21 @@ public class Playlist : IDataModel
|
|||
|
||||
public string Id() => _id;
|
||||
public bool EqualId(string oid) => _id == oid;
|
||||
public void MarshalData(string id, string data)
|
||||
{
|
||||
var tobject = JsonSerializer.Deserialize<Playlist>(data, GlobalJsonOptions.Options);
|
||||
if (tobject == null)
|
||||
return;
|
||||
this._id = id;
|
||||
this.playlistName = tobject.playlistName;
|
||||
this.@protected = tobject.@protected;
|
||||
this.videos = tobject.videos;
|
||||
this.createdAt = tobject.createdAt;
|
||||
this.lastUpdatedAt = tobject.lastUpdatedAt;
|
||||
}
|
||||
|
||||
public string JsonData()
|
||||
{
|
||||
return JsonSerializer.Serialize(this);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,5 +1,7 @@
|
|||
using System.Collections.Generic;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Text.Json;
|
||||
using FreeTubeSyncer.Library;
|
||||
|
||||
namespace FreeTubeSyncer.Models.DatabaseModels;
|
||||
|
||||
|
|
@ -14,4 +16,20 @@ public class Profile : IDataModel
|
|||
|
||||
public string Id() => _id;
|
||||
public bool EqualId(string oid) => _id == oid;
|
||||
public void MarshalData(string id, string data)
|
||||
{
|
||||
var tobject = JsonSerializer.Deserialize<Profile>(data, GlobalJsonOptions.Options);
|
||||
if (tobject == null)
|
||||
return;
|
||||
this._id = tobject._id;
|
||||
this.name = tobject.name;
|
||||
this.bgColor = tobject.bgColor;
|
||||
this.textColor = tobject.textColor;
|
||||
this.subscriptions = tobject.subscriptions;
|
||||
}
|
||||
|
||||
public string JsonData()
|
||||
{
|
||||
return JsonSerializer.Serialize(this);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,4 +1,6 @@
|
|||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Text.Json;
|
||||
using FreeTubeSyncer.Library;
|
||||
|
||||
namespace FreeTubeSyncer.Models.DatabaseModels;
|
||||
|
||||
|
|
@ -10,4 +12,17 @@ public class SearchHistory : IDataModel
|
|||
|
||||
public string Id() => _id;
|
||||
public bool EqualId(string oid) => _id == oid;
|
||||
public void MarshalData(string id, string data)
|
||||
{
|
||||
var tobject = JsonSerializer.Deserialize<SearchHistory>(data, GlobalJsonOptions.Options);
|
||||
if (tobject == null)
|
||||
return;
|
||||
this._id = tobject._id;
|
||||
this.lastUpdatedAt = tobject.lastUpdatedAt;
|
||||
}
|
||||
|
||||
public string JsonData()
|
||||
{
|
||||
return JsonSerializer.Serialize(this);
|
||||
}
|
||||
}
|
||||
|
|
@ -8,17 +8,19 @@ public class Setting : IDataModel
|
|||
{
|
||||
#pragma warning disable CS8618
|
||||
public string _id { get; set; } = string.Empty;
|
||||
public string? ValueJson { get; set; }
|
||||
#pragma warning restore CS8618
|
||||
|
||||
public object Value
|
||||
{
|
||||
#pragma warning disable CS8603
|
||||
get => string.IsNullOrEmpty(ValueJson) ? null : JsonSerializer.Deserialize<object>(ValueJson);
|
||||
#pragma warning restore CS8603
|
||||
set => ValueJson = JsonSerializer.Serialize(value);
|
||||
}
|
||||
|
||||
public string value { get; set; } = string.Empty;
|
||||
|
||||
public string Id() => _id;
|
||||
public bool EqualId(string oid) => _id == oid;
|
||||
|
||||
public void MarshalData(string id, string data)
|
||||
{
|
||||
_id = id;
|
||||
value = data;
|
||||
}
|
||||
|
||||
public string JsonData()
|
||||
{
|
||||
return value;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,7 +1,5 @@
|
|||
using Avalonia;
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Threading;
|
||||
|
|
@ -40,7 +38,7 @@ class Program
|
|||
var historySyncer = new Syncer<History>(dbWatcher, Path.Join(path, "history.db"), "history.db", "/history");
|
||||
var playlistSyncer = new Syncer<Playlist>(dbWatcher, Path.Join(path, "playlists.db"), "playlists.db", "/playlist");
|
||||
var profileSyncer = new Syncer<Profile>(dbWatcher, Path.Join(path, "profiles.db"), "profiles.db", "/profile");
|
||||
var searchHistorySyncer = new Syncer<SearchHistory>(dbWatcher, Path.Join(path, "search-history.db"), "search-history.db", "/search");
|
||||
var searchHistorySyncer = new Syncer<SearchHistory>(dbWatcher, Path.Join(path, "search-history.db"), "search-history.db", "/searchHistory");
|
||||
var settingsSyncer = new Syncer<Setting>(dbWatcher, Path.Join(path, "settings.db"), "settings.db", "/settings");
|
||||
|
||||
Task.Run(() => CheckCanSync(historySyncer, playlistSyncer, profileSyncer, searchHistorySyncer, settingsSyncer));
|
||||
|
|
@ -56,6 +54,9 @@ class Program
|
|||
{
|
||||
Thread.Sleep(100);
|
||||
if (Process.GetProcessesByName("FreeTube").Length > 0) continue;
|
||||
Console.WriteLine("FreeTube has closed, we're going to try and update.");
|
||||
Thread.Sleep(1500);
|
||||
|
||||
if (historySyncer is { IsDirty: true })
|
||||
historySyncer.Sync();
|
||||
if (playlistSyncer is { IsDirty: true })
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ using System.Collections.Generic;
|
|||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text.Json;
|
||||
using System.Text.Json.Nodes;
|
||||
using System.Threading.Tasks;
|
||||
using FreeTubeSyncer.Library;
|
||||
using FreeTubeSyncer.Models.DatabaseModels;
|
||||
|
|
@ -10,11 +11,12 @@ using RestSharp;
|
|||
|
||||
namespace FreeTubeSyncer.REST;
|
||||
|
||||
public class Syncer<T> where T : class, IDataModel
|
||||
public class Syncer<T> where T : class, IDataModel, new()
|
||||
{
|
||||
private List<T> _entries = new List<T>();
|
||||
private RestClient _client;
|
||||
private string _dbPath;
|
||||
private string _dbName;
|
||||
private string _restEndpoint;
|
||||
|
||||
public bool IsDirty = false;
|
||||
|
|
@ -25,6 +27,7 @@ public class Syncer<T> where T : class, IDataModel
|
|||
watcher.OnDatabaseChange += HandleDatabaseChange;
|
||||
_client = new RestClient(new RestClientOptions("http://localhost:5183"));
|
||||
_dbPath = dbPath;
|
||||
_dbName = dbName;
|
||||
_restEndpoint = restEndpoint;
|
||||
ReadDatabase().Wait();
|
||||
FetchDatabase().Wait();
|
||||
|
|
@ -36,20 +39,24 @@ public class Syncer<T> where T : class, IDataModel
|
|||
foreach (var entry in lines)
|
||||
{
|
||||
if (entry == "") continue;
|
||||
T? item;
|
||||
try
|
||||
{
|
||||
var item = JsonSerializer.Deserialize<T>(entry, GlobalJsonOptions.Options);
|
||||
if (item == null) continue;
|
||||
if (_entries.Any(x => x.EqualId(item.Id())))
|
||||
_entries.RemoveAll(x => x.EqualId(item.Id()));
|
||||
_entries.Add(item);
|
||||
Console.WriteLine($"Posting {item.Id()}");
|
||||
await _client.PostJsonAsync<T>(_restEndpoint, item);
|
||||
item = JsonSerializer.Deserialize<T>(entry, GlobalJsonOptions.Options);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Console.WriteLine($"Failed to parse: {entry}");
|
||||
var jobj = JsonSerializer.Deserialize<JsonObject>(entry, GlobalJsonOptions.Options);
|
||||
item = new T();
|
||||
item.MarshalData(jobj["_id"].GetValue<string>(), entry);
|
||||
}
|
||||
if (item == null) continue;
|
||||
item.MarshalData(item.Id(), entry);
|
||||
if (_entries.Any(x => x.EqualId(item.Id())))
|
||||
_entries.RemoveAll(x => x.EqualId(item.Id()));
|
||||
_entries.Add(item);
|
||||
Console.WriteLine($"Posting {item.Id()}");
|
||||
await _client.PostJsonAsync<T>(_restEndpoint, item);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -66,9 +73,25 @@ public class Syncer<T> where T : class, IDataModel
|
|||
}
|
||||
}
|
||||
|
||||
private async void HandleDatabaseChange(string dbName, object entryObject)
|
||||
private async void HandleDatabaseChange(string dbName, string entryObject)
|
||||
{
|
||||
var entry = (T)entryObject;
|
||||
if (dbName != _dbName)
|
||||
return;
|
||||
|
||||
T? entry;
|
||||
try
|
||||
{
|
||||
entry = JsonSerializer.Deserialize<T>(entryObject, GlobalJsonOptions.Options);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
var jobj = JsonSerializer.Deserialize<JsonObject>(entryObject, GlobalJsonOptions.Options);
|
||||
entry = new T();
|
||||
entry.MarshalData(jobj["_id"].GetValue<string>(), entryObject);
|
||||
}
|
||||
|
||||
if (entry == null) return;
|
||||
entry.MarshalData(entry.Id(), entryObject);
|
||||
if (_entries.Any(x => x.EqualId(entry.Id())))
|
||||
_entries.RemoveAll(x => x.EqualId(entry.Id()));
|
||||
_entries.Add(entry);
|
||||
|
|
@ -78,11 +101,14 @@ public class Syncer<T> where T : class, IDataModel
|
|||
|
||||
public void Sync()
|
||||
{
|
||||
if (!IsDirty)
|
||||
return;
|
||||
Console.WriteLine($"Syncing {_dbPath}...");
|
||||
var json = new List<string>();
|
||||
foreach (var entry in _entries)
|
||||
json.Add(JsonSerializer.Serialize(entry));
|
||||
json.Add(entry.JsonData());
|
||||
File.WriteAllLines(_dbPath, json);
|
||||
Console.WriteLine($"Updated {_dbPath}");
|
||||
Console.WriteLine($"Updated {_dbPath}.");
|
||||
IsDirty = false;
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue