- Touches: the ledger marks a server as touched when it sends us a verified activity, when
we exchange activities with it, or when we read its actors, keys, objects or WebFinger.
It upserts RemoteInstance.Seen, FirstSeenAt and LastSeenAt at most hourly per server, and
queues one DescribeInstance a week with the same dedupe key ObjectRecords uses. Suspended
servers and pages behind link previews are never described. Migration _010 marks the
servers already known as touched, with their dates.
- InstanceDescriber.Describe(host, crawled, allowed) reads:
- NodeInfo 2.2/2.1/2.0, now with its published user counts, posts, comments,
description, languages and schema version;
- for software with a Mastodon API, /api/v2/instance falling back to v1: title,
languages, registration mode, character limit, API version, source URL.
It never keeps a contact as a field; the raw document is kept for the admin only. It
locates the server from the address our connection reached (DB-IP Lite city and ASN, the
CDN named when fronted) and writes a RemoteInstanceSnapshot per ISO week, unreachable
weeks included. A crawled server is upserted as crawled only on insert, so it never
downgrades a touched one, and robots.txt can deny any path.
- PublicGeo.Project is the only public form of a location: a CDN-fronted server shows its
CDN only, a server reporting at least ten users shows its city, coordinates and network,
any other only its country.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01ELjqpznMFMNrJoJUj6K5p2
87 lines
3.3 KiB
C#
87 lines
3.3 KiB
C#
using MongoDB.Entities;
|
|
|
|
namespace PrivaPub.Models.Jobs
|
|
{
|
|
public class RemoteInstance : Entity
|
|
{
|
|
public string Host { get; set; }
|
|
public int ConsecutiveFailures { get; set; }
|
|
public DateTime? UnavailableUntil { get; set; }
|
|
public DateTime? LastSuccessAt { get; set; }
|
|
public DateTime? LastFailureAt { get; set; }
|
|
public string LastError { get; set; }
|
|
|
|
public string Software { get; set; }//NodeInfo software.name: for display, never for deciding behaviour
|
|
public string SoftwareVersion { get; set; }
|
|
public string NodeName { get; set; }
|
|
public List<string> Protocols { get; set; } = new();
|
|
public bool? OpenRegistrations { get; set; }
|
|
public string NodeInfo { get; set; }//the raw document, when small enough
|
|
public DateTime? DescribedAt { get; set; }
|
|
public string DescriptionError { get; set; }
|
|
|
|
public string Seen { get; set; }//"touched": we exchanged something with it; "crawled": only its peers list named it
|
|
public DateTime? FirstSeenAt { get; set; }
|
|
public DateTime? LastSeenAt { get; set; }
|
|
public DateTime? LastCrawledAt { get; set; }
|
|
public string CrawlError { get; set; }
|
|
public bool? RobotsDisallowed { get; set; }
|
|
public int? PeersCount { get; set; }
|
|
|
|
public string NodeInfoVersion { get; set; }
|
|
public string NodeDescription { get; set; }
|
|
public long? UsersTotal { get; set; }//as the server publishes them in its NodeInfo
|
|
public long? UsersActiveMonth { get; set; }
|
|
public long? UsersActiveHalfyear { get; set; }
|
|
public long? LocalPosts { get; set; }
|
|
public long? LocalComments { get; set; }
|
|
|
|
public string InstanceApi { get; set; }//"mastodon-v2" or "mastodon-v1"
|
|
public string InstanceApiRaw { get; set; }//admin only: it names maintainers and contact accounts
|
|
public string Title { get; set; }
|
|
public List<string> Languages { get; set; }
|
|
public string RegistrationMode { get; set; }//open, approval, closed
|
|
public int? MaxPostChars { get; set; }
|
|
public int? MastodonApiVersion { get; set; }
|
|
public string SourceUrl { get; set; }
|
|
|
|
public InstanceGeo Geo { get; set; }
|
|
}
|
|
|
|
public class InstanceGeo
|
|
{
|
|
public string Country { get; set; }
|
|
public string City { get; set; }
|
|
public double? Latitude { get; set; }//rounded to one decimal
|
|
public double? Longitude { get; set; }
|
|
public int? Asn { get; set; }
|
|
public string AsnOrg { get; set; }
|
|
public string Cdn { get; set; }//the CDN in front of it, whose edge address says nothing about where it runs
|
|
public bool? Ipv6 { get; set; }
|
|
public string Source { get; set; }
|
|
public DateTime? LocatedAt { get; set; }
|
|
}
|
|
|
|
public class RemoteInstanceSnapshot : Entity
|
|
{
|
|
public string Host { get; set; }
|
|
public string Week { get; set; }//ISO week, "2026-W40"
|
|
public DateTime TakenAt { get; set; }
|
|
public string Seen { get; set; }
|
|
public bool Reachable { get; set; }
|
|
public string Software { get; set; }
|
|
public string SoftwareVersion { get; set; }
|
|
public long? UsersTotal { get; set; }
|
|
public long? UsersActiveMonth { get; set; }
|
|
public long? UsersActiveHalfyear { get; set; }
|
|
public long? LocalPosts { get; set; }
|
|
public bool? OpenRegistrations { get; set; }
|
|
public string RegistrationMode { get; set; }
|
|
public List<string> Languages { get; set; }
|
|
public string Country { get; set; }
|
|
public int? Asn { get; set; }
|
|
public string Cdn { get; set; }
|
|
public bool? Ipv6 { get; set; }
|
|
}
|
|
}
|