Fix server merging and room sort

dev
gravel 1 year ago
parent b2308e4095
commit 44a47cad1d
Signed by: gravel
GPG Key ID: C0538F3C906B308F

@ -245,7 +245,10 @@ const TRANSFORMATION = {
numeric: (el) => parseInt(el.innerText),
casefold: (el) => el.innerText.toLowerCase().trim(),
getName: (_, row) => dom.row_info(row).name.toLowerCase(),
getRoomPublicKey: (_, row) => dom.row_info(row).public_key
getServerId: (_, row) => {
const rowInfo = dom.row_info(row);
return `${rowInfo.public_key}${rowInfo.join_link}`;
}
}
/**
@ -256,7 +259,7 @@ export const COLUMN_TRANSFORMATION = {
[COLUMN.IDENTIFIER]: TRANSFORMATION.casefold,
[COLUMN.NAME]: TRANSFORMATION.getName,
[COLUMN.DESCRIPTION]: TRANSFORMATION.casefold,
[COLUMN.SERVER_ICON]: TRANSFORMATION.getRoomPublicKey
[COLUMN.SERVER_ICON]: TRANSFORMATION.getServerId
}
/**

@ -48,8 +48,8 @@
// Fetch server data and filter unreachable servers.
$servers = CommunityServer::poll_reachable($servers);
// Merge servers with the same public key.
$servers = CommunityServer::dedupe_by_pubkey($servers);
// Merge servers with the same public key and rooms.
$servers = CommunityServer::dedupe_by_data($servers);
// Fill additional information from sources.
CommunityServer::source_additional_info($servers, $sources);

@ -296,14 +296,14 @@
}
/**
* Sort Community rooms in-place by their server's public key.
* @param CommunityRoom[] $rooms Rooms to sort by server pubkey.
* Sort Community rooms in-place by their server.
* @param CommunityRoom[] $rooms Rooms to sort by server.
*/
public static function sort_rooms_by_pubkey(array &$rooms) {
public static function sort_rooms_by_server(array &$rooms) {
usort($rooms, function(CommunityRoom $a, CommunityRoom $b) {
return strcmp(
$a->server->get_pubkey(),
$b->server->get_pubkey()
$a->server->get_pubkey() . $a->server->get_hostname(),
$b->server->get_pubkey() . $b->server->get_hostname()
);
});
}
@ -493,7 +493,7 @@
* @param string $matchee String matching room. Output parameter.
* @return bool True if the array matches the Community, false otherwise.
*/
public function matched_by_list(array $filter, string &$matchee): bool {
public function matched_by_list(array $filter, string &$matchee = null): bool {
foreach ($filter as $filter_item) {
if ($this->matched_by_identifier($filter_item)) {
$matchee = $filter_item;
@ -510,7 +510,7 @@
* @param string[] $matchees output parameter
* @return CommunityRoom[]
*/
public static function select_rooms(array $rooms, array|string $filter, array &$matchees): array {
public static function select_rooms(array $rooms, array|string $filter, array &$matchees = null): array {
$_matchees = [];
$rooms = array_values(array_filter($rooms, function(CommunityRoom $room) use ($filter, $_matchees) {
$matchee = null;
@ -687,10 +687,10 @@
case SameHostname;
/**
* @var SamePublicKey
* Strategy considering two servers to be identical if they share a SOGS public key.
* @var SameData
* Strategy considering two servers to be identical if they share a SOGS public key and room data.
*/
case SamePublicKey;
case SameData;
/**
* Determine whether two CommunityServer instances are identical under the given criteria.
@ -700,8 +700,11 @@
*/
public function should_merge_servers(CommunityServer $a, CommunityServer $b): bool {
return match ($this) {
CommunityServerMergeStrategy::SameHostname => $a->get_hostname() == $b->get_hostname(),
CommunityServerMergeStrategy::SamePublicKey => $a->get_pubkey() == $b->get_pubkey()
CommunityServerMergeStrategy::SameHostname =>
$a->get_hostname() == $b->get_hostname(),
CommunityServerMergeStrategy::SameData =>
$a->get_pubkey() == $b->get_pubkey() &&
CommunityServer::rooms_in_common($a, $b)
};
}
}
@ -801,6 +804,27 @@
usort($servers, 'CommunityServer::compare_by_pubkey');
}
/**
* Return true whether the two servers given share a room.
*/
public static function rooms_in_common(CommunityServer $a, CommunityServer $b): bool {
// Rely on at least token or creation date differing.
// Do not strictly compare room lists because the servers
// may have been polled at different times.
$room_date_pairs = [];
$rooms = CommunityServer::enumerate_rooms([$a, $b]);
foreach ($rooms as $room) {
$room_date_pairs[] = $room->token . "+" . $room->created;
}
if (count(array_unique($room_date_pairs)) < count($rooms)) {
return true;
}
return false;
}
/**
* Absorb candidates for the SOGS public key from a duplicate server instance.
*/
@ -830,7 +854,7 @@
exit(1);
}
$this->merge_pubkeys_from($server);
} else if ($strategy == CommunityServerMergeStrategy::SamePublicKey) {
} else if ($strategy == CommunityServerMergeStrategy::SameData) {
if ($this->get_pubkey() != $server->get_pubkey()) {
log_error("SamePublicKey merging: Merged servers differ in public key");
exit(1);
@ -919,10 +943,10 @@
* @param CommunityServer[] $servers Servers to merge by public key.
* @return CommunityServer[] Servers merged by public key-
*/
public static function dedupe_by_pubkey($servers) {
public static function dedupe_by_data($servers) {
CommunityServer::sort_by_pubkey($servers);
CommunityServer::merge_by($servers, CommunityServerMergeStrategy::SamePublicKey);
CommunityServer::merge_by($servers, CommunityServerMergeStrategy::SameData);
$servers = CommunityServer::ensure_merge_consistency($servers);

@ -22,7 +22,7 @@
// Sort rooms by name and then host.
CommunityRoom::sort_rooms_str($rooms, 'name');
CommunityRoom::sort_rooms_by_pubkey($rooms);
CommunityRoom::sort_rooms_by_server($rooms);
// Set the last-updated timestamp
// to the time the server data file was last modified.

Loading…
Cancel
Save