cs-codex-dist-tests/Tools/BiblioTech/UserRepo.cs

235 lines
7.3 KiB
C#
Raw Normal View History

2023-10-22 07:32:03 +00:00
using CodexContractsPlugin;
2023-10-25 09:25:27 +00:00
using Discord;
2023-10-22 07:32:03 +00:00
using GethPlugin;
using Newtonsoft.Json;
2023-10-25 09:25:27 +00:00
using Utils;
2023-10-22 07:32:03 +00:00
namespace BiblioTech
{
public class UserRepo
{
private readonly object repoLock = new object();
2023-10-25 09:25:27 +00:00
public bool AssociateUserWithAddress(IUser user, EthAddress address)
2023-10-22 07:32:03 +00:00
{
lock (repoLock)
{
2023-10-25 09:25:27 +00:00
return SetUserAddress(user, address);
2023-10-22 07:32:03 +00:00
}
}
2023-10-25 09:25:27 +00:00
public void ClearUserAssociatedAddress(IUser user)
2023-10-22 07:32:03 +00:00
{
lock (repoLock)
{
2023-10-25 09:25:27 +00:00
SetUserAddress(user, null);
2023-10-22 07:32:03 +00:00
}
}
2023-10-25 09:25:27 +00:00
public void AddMintEventForUser(IUser user, EthAddress usedAddress, Ether eth, TestToken tokens)
2023-10-22 07:32:03 +00:00
{
lock (repoLock)
{
2023-10-25 09:25:27 +00:00
var userData = GetOrCreate(user);
userData.MintEvents.Add(new UserMintEvent(DateTime.UtcNow, usedAddress, eth, tokens));
SaveUserData(userData);
2023-10-22 07:32:03 +00:00
}
}
2023-10-25 09:25:27 +00:00
public EthAddress? GetCurrentAddressForUser(IUser user)
2023-10-22 07:32:03 +00:00
{
lock (repoLock)
{
2023-10-25 09:25:27 +00:00
return GetOrCreate(user).CurrentAddress;
2023-10-22 07:32:03 +00:00
}
}
2023-10-25 09:25:27 +00:00
public string[] GetInteractionReport(IUser user)
2023-10-22 08:10:52 +00:00
{
var result = new List<string>();
lock (repoLock)
{
2023-10-25 09:25:27 +00:00
var userData = GetUserData(user);
if (userData == null)
2023-10-22 08:10:52 +00:00
{
result.Add("User has not joined the test net.");
}
else
{
2023-10-25 09:25:27 +00:00
result.Add("User joined on " + userData.CreatedUtc.ToString("o"));
result.Add("Current address: " + userData.CurrentAddress);
foreach (var ae in userData.AssociateEvents)
2023-10-22 08:10:52 +00:00
{
2023-10-25 09:25:27 +00:00
result.Add($"{ae.Utc.ToString("o")} - Address set to: {ae.NewAddress}");
2023-10-22 08:10:52 +00:00
}
2023-10-25 09:25:27 +00:00
foreach (var me in userData.MintEvents)
2023-10-22 08:10:52 +00:00
{
2023-10-25 09:25:27 +00:00
result.Add($"{me.Utc.ToString("o")} - Minted {me.EthReceived} and {me.TestTokensMinted} to {me.UsedAddress}.");
2023-10-22 08:10:52 +00:00
}
}
}
return result.ToArray();
}
2023-10-25 09:25:27 +00:00
public string GetUserReport(IUser user)
2023-10-22 07:32:03 +00:00
{
2023-10-25 09:25:27 +00:00
var userData = GetUserData(user);
if (userData == null) return "User has not joined the test net.";
return userData.CreateOverview();
}
public string GetUserReport(EthAddress ethAddress)
{
var userData = GetUserDataForAddress(ethAddress);
if (userData == null) return "No user is using this eth address.";
return userData.CreateOverview();
}
private bool SetUserAddress(IUser user, EthAddress? address)
{
if (GetUserDataForAddress(address) != null)
2023-10-25 08:25:00 +00:00
{
return false;
}
2023-10-25 09:25:27 +00:00
var userData = GetOrCreate(user);
userData.CurrentAddress = address;
userData.AssociateEvents.Add(new UserAssociateAddressEvent(DateTime.UtcNow, address));
SaveUserData(userData);
2023-10-25 08:25:00 +00:00
return true;
2023-10-22 07:32:03 +00:00
}
2023-10-25 09:25:27 +00:00
private UserData? GetUserData(IUser user)
2023-10-22 07:32:03 +00:00
{
2023-10-25 09:25:27 +00:00
var filename = GetFilename(user);
2023-10-22 07:32:03 +00:00
if (!File.Exists(filename))
{
2023-10-25 09:25:27 +00:00
return null;
}
return JsonConvert.DeserializeObject<UserData>(File.ReadAllText(filename))!;
}
private UserData GetOrCreate(IUser user)
{
var userData = GetUserData(user);
if (userData == null)
{
return CreateAndSaveNewUserData(user);
2023-10-22 07:32:03 +00:00
}
2023-10-25 09:25:27 +00:00
return userData;
2023-10-22 07:32:03 +00:00
}
2023-10-25 09:25:27 +00:00
private UserData CreateAndSaveNewUserData(IUser user)
2023-10-22 07:32:03 +00:00
{
2023-10-25 09:25:27 +00:00
var newUser = new UserData(user.Id, user.GlobalName, DateTime.UtcNow, null, new List<UserAssociateAddressEvent>(), new List<UserMintEvent>());
SaveUserData(newUser);
2023-10-22 07:32:03 +00:00
return newUser;
}
2023-10-25 09:25:27 +00:00
private UserData? GetUserDataForAddress(EthAddress? address)
2023-10-25 08:25:00 +00:00
{
2023-10-25 09:25:27 +00:00
if (address == null) return null;
2023-10-25 08:25:00 +00:00
// If this becomes a performance problem, switch to in-memory cached list.
var files = Directory.GetFiles(Program.Config.UserDataPath);
foreach (var file in files)
{
try
{
2023-10-25 09:25:27 +00:00
var user = JsonConvert.DeserializeObject<UserData>(File.ReadAllText(file))!;
2023-10-25 08:25:00 +00:00
if (user.CurrentAddress != null &&
user.CurrentAddress.Address == address.Address)
{
2023-10-25 09:25:27 +00:00
return user;
2023-10-25 08:25:00 +00:00
}
}
catch { }
}
2023-10-25 09:25:27 +00:00
return null;
2023-10-25 08:25:00 +00:00
}
2023-10-25 09:25:27 +00:00
private void SaveUserData(UserData userData)
2023-10-22 07:32:03 +00:00
{
2023-10-25 09:25:27 +00:00
var filename = GetFilename(userData);
2023-10-22 07:32:03 +00:00
if (File.Exists(filename)) File.Delete(filename);
2023-10-25 09:25:27 +00:00
File.WriteAllText(filename, JsonConvert.SerializeObject(userData));
}
private static string GetFilename(IUser user)
{
return GetFilename(user.Id);
}
private static string GetFilename(UserData userData)
{
return GetFilename(userData.DiscordId);
2023-10-22 07:32:03 +00:00
}
private static string GetFilename(ulong discordId)
{
return Path.Combine(Program.Config.UserDataPath, discordId.ToString() + ".json");
}
}
2023-10-25 09:25:27 +00:00
public class UserData
2023-10-22 07:32:03 +00:00
{
2023-10-25 09:25:27 +00:00
public UserData(ulong discordId, string name, DateTime createdUtc, EthAddress? currentAddress, List<UserAssociateAddressEvent> associateEvents, List<UserMintEvent> mintEvents)
2023-10-22 07:32:03 +00:00
{
DiscordId = discordId;
2023-10-25 09:25:27 +00:00
Name = name;
2023-10-22 07:32:03 +00:00
CreatedUtc = createdUtc;
CurrentAddress = currentAddress;
AssociateEvents = associateEvents;
MintEvents = mintEvents;
}
public ulong DiscordId { get; }
2023-10-25 09:25:27 +00:00
public string Name { get; }
2023-10-22 07:32:03 +00:00
public DateTime CreatedUtc { get; }
public EthAddress? CurrentAddress { get; set; }
public List<UserAssociateAddressEvent> AssociateEvents { get; }
public List<UserMintEvent> MintEvents { get; }
2023-10-25 09:25:27 +00:00
public string CreateOverview()
{
var nl = Environment.NewLine;
return
$"name: '{Name}' - id:{DiscordId}{nl}" +
$"joined: {CreatedUtc.ToString("o")}{nl}" +
$"current address: {CurrentAddress}{nl}" +
$"{AssociateEvents.Count + MintEvents.Count} total bot events.";
}
2023-10-22 07:32:03 +00:00
}
public class UserAssociateAddressEvent
{
public UserAssociateAddressEvent(DateTime utc, EthAddress? newAddress)
{
Utc = utc;
NewAddress = newAddress;
}
public DateTime Utc { get; }
public EthAddress? NewAddress { get; }
}
public class UserMintEvent
{
public UserMintEvent(DateTime utc, EthAddress usedAddress, Ether ethReceived, TestToken testTokensMinted)
{
Utc = utc;
UsedAddress = usedAddress;
EthReceived = ethReceived;
TestTokensMinted = testTokensMinted;
}
public DateTime Utc { get; }
public EthAddress UsedAddress { get; }
public Ether EthReceived { get; }
public TestToken TestTokensMinted { get; }
}
}