This commit is contained in:
Ben 2025-04-09 15:25:31 +02:00
parent 89f1f74ffa
commit 7ccdbd3c26
No known key found for this signature in database
GPG Key ID: 0F16E812E736C24B
6 changed files with 84 additions and 181 deletions

View File

@ -20,11 +20,6 @@ namespace WebUtils
private readonly Action<HttpClient> onClientCreated;
private readonly string id;
internal Http(string id, ILog log, IWebCallTimeSet timeSet)
: this(id, log, timeSet, DoNothing)
{
}
internal Http(string id, ILog log, IWebCallTimeSet timeSet, Action<HttpClient> onClientCreated)
{
this.id = id;
@ -89,9 +84,5 @@ namespace WebUtils
onClientCreated(client);
return client;
}
private static void DoNothing(HttpClient client)
{
}
}
}

View File

@ -13,16 +13,28 @@ namespace WebUtils
{
private readonly ILog log;
private readonly IWebCallTimeSet defaultTimeSet;
private readonly Action<HttpClient> factoryOnClientCreated;
public HttpFactory(ILog log)
: this (log, new DefaultWebCallTimeSet())
{
}
public HttpFactory(ILog log, Action<HttpClient> onClientCreated)
: this(log, new DefaultWebCallTimeSet(), onClientCreated)
{
}
public HttpFactory(ILog log, IWebCallTimeSet defaultTimeSet)
: this(log, defaultTimeSet, DoNothing)
{
}
public HttpFactory(ILog log, IWebCallTimeSet defaultTimeSet, Action<HttpClient> onClientCreated)
{
this.log = log;
this.defaultTimeSet = defaultTimeSet;
this.factoryOnClientCreated = onClientCreated;
}
public IHttp CreateHttp(string id, Action<HttpClient> onClientCreated)
@ -32,12 +44,20 @@ namespace WebUtils
public IHttp CreateHttp(string id, Action<HttpClient> onClientCreated, IWebCallTimeSet ts)
{
return new Http(id, log, ts, onClientCreated);
return new Http(id, log, ts, (c) =>
{
factoryOnClientCreated(c);
onClientCreated(c);
});
}
public IHttp CreateHttp(string id)
{
return new Http(id, log, defaultTimeSet);
return new Http(id, log, defaultTimeSet, factoryOnClientCreated);
}
private static void DoNothing(HttpClient client)
{
}
}
}

View File

@ -1,167 +0,0 @@
using CodexClient;
using Logging;
using Utils;
namespace BiblioTech
{
public class CodexCidChecker
{
private static readonly string nl = Environment.NewLine;
private readonly Configuration config;
private readonly ILog log;
private readonly Mutex checkMutex = new Mutex();
private readonly CodexNodeFactory factory;
private ICodexNode? currentCodexNode;
public CodexCidChecker(Configuration config, ILog log)
{
this.config = config;
this.log = log;
factory = new CodexNodeFactory(log, dataDir: config.DataPath);
if (!string.IsNullOrEmpty(config.CodexEndpointAuth) && config.CodexEndpointAuth.Contains(":"))
{
throw new Exception("Todo: codexnodefactory httpfactory support basicauth!");
//var tokens = config.CodexEndpointAuth.Split(':');
//if (tokens.Length != 2) throw new Exception("Expected '<username>:<password>' in CodexEndpointAuth parameter.");
//client.SetBasicAuthentication(tokens[0], tokens[1]);
}
}
public CheckResponse PerformCheck(string cid)
{
if (string.IsNullOrEmpty(config.CodexEndpoint))
{
return new CheckResponse(false, "Codex CID checker is not (yet) available.");
}
try
{
checkMutex.WaitOne();
var codex = GetCodex();
var nodeCheck = CheckCodex(codex);
if (!nodeCheck) return new CheckResponse(false, "Codex node is not available. Cannot perform check.");
return PerformCheck(codex, cid);
}
finally
{
checkMutex.ReleaseMutex();
}
}
private CheckResponse PerformCheck(ICodexNode codex, string cid)
{
try
{
var manifest = codex.DownloadManifestOnly(new ContentId(cid));
return SuccessMessage(manifest);
}
catch
{
return FailedMessage();
}
}
#region Response formatting
private CheckResponse SuccessMessage(LocalDataset content)
{
return FormatResponse(
success: true,
title: $"Success",
$"cid: '{content.Cid}'",
$"size: {content.Manifest.OriginalBytes} bytes",
$"blockSize: {content.Manifest.BlockSize} bytes",
$"protected: {content.Manifest.Protected}"
);
}
private CheckResponse FailedMessage()
{
var msg = "Could not download content.";
return FormatResponse(
success: false,
title: "Failed",
msg,
$"Connection trouble? See 'https://docs.codex.storage/learn/troubleshoot'"
);
}
private CheckResponse FormatResponse(bool success, string title, params string[] content)
{
var msg = string.Join(nl,
new string[]
{
title,
"```"
}
.Concat(content)
.Concat(new string[]
{
"```"
})
) + nl + nl;
return new CheckResponse(success, msg);
}
#endregion
#region Codex Node API
private ICodexNode GetCodex()
{
if (currentCodexNode == null) currentCodexNode = CreateCodex();
return currentCodexNode;
}
private bool CheckCodex(ICodexNode node)
{
try
{
var info = node.GetDebugInfo();
if (info == null || string.IsNullOrEmpty(info.Id)) return false;
return true;
}
catch (Exception e)
{
log.Error(e.ToString());
return false;
}
}
private ICodexNode CreateCodex()
{
var endpoint = config.CodexEndpoint;
var splitIndex = endpoint.LastIndexOf(':');
var host = endpoint.Substring(0, splitIndex);
var port = Convert.ToInt32(endpoint.Substring(splitIndex + 1));
var address = new Address(
logName: $"cdx@{host}:{port}",
host: host,
port: port
);
var instance = CodexInstance.CreateFromApiEndpoint("ac", address);
return factory.CreateCodexNode(instance);
}
#endregion
}
public class CheckResponse
{
public CheckResponse(bool success, string message)
{
Success = success;
Message = message;
}
public bool Success { get; }
public string Message { get; }
}
}

View File

@ -0,0 +1,59 @@
using CodexClient;
using IdentityModel.Client;
using Logging;
using Utils;
using WebUtils;
namespace BiblioTech
{
public class CodexTwoWayChecker
{
private static readonly string nl = Environment.NewLine;
private readonly Configuration config;
private readonly ILog log;
private readonly CodexNodeFactory factory;
private ICodexNode? currentCodexNode;
public CodexTwoWayChecker(Configuration config, ILog log)
{
this.config = config;
this.log = log;
var httpFactory = CreateHttpFactory();
factory = new CodexNodeFactory(log, httpFactory, dataDir: config.DataPath);
}
// down check:
// generate unique data
// upload to cloud node
// give CID to user to download
// user inputs unique data into command to clear this check
// up check:
// generate unique data
// create file and send it to user via discord api
// user uploads and gives CID via command
// download manifest: file is not larger than expected
// download file: contents is unique data -> clear this check
// both checks: altruistic role
private HttpFactory CreateHttpFactory()
{
if (string.IsNullOrEmpty(config.CodexEndpointAuth) && config.CodexEndpointAuth.Contains(":"))
{
return new HttpFactory(log);
}
var tokens = config.CodexEndpointAuth.Split(':');
if (tokens.Length != 2) throw new Exception("Expected '<username>:<password>' in CodexEndpointAuth parameter.");
return new HttpFactory(log, onClientCreated: client =>
{
client.SetBasicAuthentication(tokens[0], tokens[1]);
});
}
}
}

View File

@ -10,10 +10,10 @@ namespace BiblioTech.Commands
name: "cid",
description: "Codex Content-Identifier",
isRequired: true);
private readonly CodexCidChecker checker;
private readonly CodexTwoWayChecker checker;
private readonly CidStorage cidStorage;
public CheckCidCommand(CodexCidChecker checker)
public CheckCidCommand(CodexTwoWayChecker checker)
{
this.checker = checker;
this.cidStorage = new CidStorage(Path.Combine(Program.Config.DataPath, "valid_cids.txt"));

View File

@ -80,7 +80,7 @@ namespace BiblioTech
client = new DiscordSocketClient();
client.Log += ClientLog;
var checker = new CodexCidChecker(Config, Log);
var checker = new CodexTwoWayChecker(Config, Log);
var notifyCommand = new NotifyCommand();
var associateCommand = new UserAssociateCommand(notifyCommand);
var sprCommand = new SprCommand();