87 lines
3.4 KiB
C#
87 lines
3.4 KiB
C#
#:project ../src/MeWeb.Core/MeWeb.Core.csproj
|
|||
|
|
using System.Text.Json;
|
||
|
|
using System.Text.Json.Serialization;
|
||
|
|
|
||
|
|
using MeWeb.Core.Knowledge;
|
||
|
|
|
||
|
|
var json = new KnowledgeJsonContext(new JsonSerializerOptions(JsonSerializerDefaults.Web)
|
||
|
|
{
|
||
|
|
WriteIndented = true,
|
||
|
|
DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull,
|
||
|
|
});
|
||
|
|
var root = FindRoot();
|
||
|
|
var reviewed = Path.Combine(root, "data", "observed.json");
|
||
|
|
|
||
|
|
if (args.Length < 2 || args[0] is not ("show" or "accept"))
|
||
|
|
{
|
||
|
|
Console.Error.WriteLine("""
|
||
|
|
usage: dotnet run tools/observed.cs -- show <candidates.json>
|
||
|
|
dotnet run tools/observed.cs -- accept <candidates.json> AS<number>/<home|mobile> ...
|
||
|
|
|
||
|
|
<candidates.json> is the server's count of shared findings (/var/lib/meweb/observed.json on the box).
|
||
|
|
show prints every provider line and which notes are ready (at least 5 networks, 4 in 5 agreeing);
|
||
|
|
accept copies the ready notes of the named lines into data/observed.json, which every release embeds.
|
||
|
|
""");
|
||
|
|
return 2;
|
||
|
|
}
|
||
|
|
|
||
|
|
var candidates = Load(args[1]);
|
||
|
|
if (args[0] == "show")
|
||
|
|
{
|
||
|
|
foreach (var line in candidates)
|
||
|
|
{
|
||
|
|
Console.WriteLine($"{line.Key,-16} {line.Name} - {line.Networks} network(s), {line.From} to {line.To}");
|
||
|
|
foreach (var (label, fact) in new[] { ("ipv4", line.Ipv4), ("ipv6", line.Ipv6), ("port25", line.Port25) })
|
||
|
|
if (fact is not null) Console.WriteLine($" {label,-7} {fact.Value,-8} {fact.Agree} of {fact.Of}{(fact.Ready ? " ready" : "")}");
|
||
|
|
}
|
||
|
|
Console.WriteLine($"{candidates.Count} provider line(s), {candidates.Count(c => Ready(c) is not null)} with a ready note");
|
||
|
|
return 0;
|
||
|
|
}
|
||
|
|
|
||
|
|
var wanted = args.Skip(2).ToHashSet(StringComparer.OrdinalIgnoreCase);
|
||
|
|
var current = File.Exists(reviewed) ? Load(reviewed) : [];
|
||
|
|
foreach (var key in wanted)
|
||
|
|
{
|
||
|
|
var line = candidates.FirstOrDefault(c => string.Equals(c.Key, key, StringComparison.OrdinalIgnoreCase));
|
||
|
|
var ready = line is null ? null : Ready(line);
|
||
|
|
if (ready is null)
|
||
|
|
{
|
||
|
|
Console.Error.WriteLine($"{key}: no ready note in {args[1]}");
|
||
|
|
return 1;
|
||
|
|
}
|
||
|
|
current.RemoveAll(c => c.Key == ready.Key);
|
||
|
|
current.Add(ready);
|
||
|
|
Console.WriteLine($"{ready.Key}: accepted ({string.Join(", ", new[] { ready.Ipv4, ready.Ipv6, ready.Port25 }.Where(f => f is not null).Select(f => $"{f.Value} {f.Agree}/{f.Of}"))})");
|
||
|
|
}
|
||
|
|
File.WriteAllText(reviewed, JsonSerializer.Serialize(current.OrderBy(c => c.Asn).ThenBy(c => c.Line, StringComparer.Ordinal).ToList(), json.ListObservedNetwork) + "\n");
|
||
|
|
return 0;
|
||
|
|
|
||
|
|
List<ObservedNetwork> Load(string path)
|
||
|
|
{
|
||
|
|
using var stream = File.OpenRead(path);
|
||
|
|
return JsonSerializer.Deserialize(stream, json.ListObservedNetwork) ?? [];
|
||
|
|
}
|
||
|
|
|
||
|
|
static ObservedNetwork Ready(ObservedNetwork line)
|
||
|
|
{
|
||
|
|
var copy = new ObservedNetwork
|
||
|
|
{
|
||
|
|
Asn = line.Asn,
|
||
|
|
Line = line.Line,
|
||
|
|
Name = line.Name,
|
||
|
|
Networks = line.Networks,
|
||
|
|
From = line.From,
|
||
|
|
To = line.To,
|
||
|
|
Ipv4 = line.Ipv4 is { Ready: true } ? line.Ipv4 : null,
|
||
|
|
Ipv6 = line.Ipv6 is { Ready: true } ? line.Ipv6 : null,
|
||
|
|
Port25 = line.Port25 is { Ready: true } ? line.Port25 : null,
|
||
|
|
};
|
||
|
|
return copy.Ipv4 is null && copy.Ipv6 is null && copy.Port25 is null ? null : copy;
|
||
|
|
}
|
||
|
|
|
||
|
|
static string FindRoot()
|
||
|
|
{
|
||
|
|
var dir = new DirectoryInfo(Directory.GetCurrentDirectory());
|
||
|
|
while (dir is not null && !File.Exists(Path.Combine(dir.FullName, "MeWeb.slnx"))) dir = dir.Parent;
|
||
|
|
return dir?.FullName ?? throw new InvalidOperationException("run from inside the repository (MeWeb.slnx not found)");
|
||
|
|
}
|