@ -13,7 +13,7 @@
require_once 'utils/numeric.php';
/**
* Representation of Session Community room .
* Represents a Session Community.
*/
class CommunityRoom implements JsonSerializable {
/**
@ -173,6 +173,12 @@
/**
* Create incomplete CommunityRoom instance from intermediate data.
*
* Use when room data has been fetched, but the server's public key is still unknown.
*
* @param CommunityServer $server Open Group Server hosting given Community.
* @param array $details Associative data describing given Community.
* @return CommunityRoom Incomplete CommunityRoom instance. Expect errors.
*/
public static function _from_intermediate_data(
CommunityServer $server,
@ -273,7 +279,9 @@
/**
* Create a CommunityRoom instance from associative data.
* @param CommunityServer $server
* @param CommunityServer $server Open Group Server hosting given Community.
* @param array $details Associative data describing Community.
* @return CommunityRoom
*/
public static function from_details($server, array $details) {
return new CommunityRoom($server, $details);
@ -281,7 +289,8 @@
/**
* Create an array of CommunityRoom instances from associative data.
* @param array[] $details
* @param CommunityServer $server Open Group server hosting the given rooms.
* @param array[] $details_array Array of associative arrays holding room data.
* @return CommunityRoom[]
*/
public static function from_details_array($server, array $details_array) {
@ -294,9 +303,11 @@
* Sort Community rooms in-place by the given string property.
* @param CommunityRoom[] $rooms Rooms to sort by given key.
* @param string $key String property of CommunityRoom to sort by.
* @param bool $descending If true, sort in descending order.
* @return void
*/
public static function sort_rooms_str(array & $rooms, string $key, bool $reverse = false) {
usort($rooms, $reverse ? function(CommunityRoom $a, CommunityRoom $b) use ($key) {
public static function sort_rooms_str(array & $rooms, string $key, bool $descending = false) {
usort($rooms, $descending ? function(CommunityRoom $a, CommunityRoom $b) use ($key) {
return strcmp(
$b->$key,
$a->$key
@ -313,9 +324,11 @@
* Sort Community rooms in-place by the given numeric property.
* @param CommunityRoom[] $rooms Rooms to sort by given key.
* @param string $key Numeric property of CommunityRoom to sort by.
* @param bool $descending If true, sort in descending order.
* @return void
*/
public static function sort_rooms_num(array & $rooms, string $key, bool $reverse = false) {
usort($rooms, $reverse ? function(CommunityRoom $a, CommunityRoom $b) use ($key) {
public static function sort_rooms_num(array & $rooms, string $key, bool $descending = false) {
usort($rooms, $descending ? function(CommunityRoom $a, CommunityRoom $b) use ($key) {
return $b->$key - $a->$key;
} : function(CommunityRoom $a, CommunityRoom $b) use ($key) {
return $a->$key - $b->$key;
@ -325,6 +338,8 @@
/**
* Sort Community rooms in-place by their server.
* @param CommunityRoom[] $rooms Rooms to sort by server.
* @param bool $random If true, use random server order to sort rooms.
* @return void
*/
public static function sort_rooms_by_server(array & $rooms, bool $random = false) {
if ($random) {
@ -345,7 +360,9 @@
}
/**
* Re-fetch assets for the given Communities as necessary.
* @param CommunityRoom[] $rooms
* @return void
*/
public static function fetch_assets(array $rooms) {
// Sequential in each server, see note in fetch_room_hints_coroutine()
@ -362,9 +379,12 @@
}
/**
* @param CommunityRoom[] $rooms
* Keep only pinned Communities from the input list.
* @param CommunityRoom[] $rooms Input list of Communities.
* @param CommunityRoom[] $rest (output) Remainder of Communities from the list. (optional)
* @return CommunityRoom[] Pinned Communities.
*/
public static function get_stickied_rooms(array & $rooms, array & $rest = null) {
public static function get_stickied_rooms(array $rooms, array & $rest = null) {
global $STICKIED_ROOMS;
return CommunityRoom::select_rooms($rooms, $STICKIED_ROOMS, unmatched: $rest);
}
@ -538,7 +558,7 @@
* Check whether the given list matches the current Community or its parent server.
* @param string[] $filter
* Array of unique room identifiers, server pubkeys and/or server hostnames.
* @param string $matchee String matching room. Output parameter .
* @param string $matchee (output) String matching current room .
* @return bool True if the array matches the Community, false otherwise.
*/
public function matched_by_list(array $filter, string & $matchee = null): bool {
@ -553,9 +573,11 @@
}
/**
* Select Communities matching the given filter list.
* @param CommunityRoom[] $rooms
* @param string[] $filter
* @param string[] $matchees output parameter
* @param string[] $filter List of room identifiers, server pubkeys and/or hostnames.
* @param string[] $matchees (output) Filter list items used to select at least one Community. (optional)
* @param CommunityRoom[] $unmatched (output) Communities not matched by any filter items. (optional)
* @return CommunityRoom[]
*/
public static function select_rooms(array $rooms, array|string $filter, array & $matchees = null, array & $unmatched = null): array {
@ -615,11 +637,21 @@
return $this->has_nsfw_keywords() || $this->matched_by_list($NSFW_INCLUDE);
}
/**
* Return true if the Community is marked for testing.
*
* @return bool
*/
public function is_testing_room(): bool {
global $TESTING_INCLUDE;
return in_array("test", $this->string_tags) || $this->matched_by_list($TESTING_INCLUDE);
}
/**
* Return true if the Community is manually stickied.
*
* @return bool
*/
public function is_stickied_room(): bool {
global $STICKIED_ROOMS;
return $this->matched_by_list($STICKIED_ROOMS);
@ -642,7 +674,12 @@
return 0;
}
public function get_recommended_staff_count() {
/**
* Compute the recommended threshold for Community staff count.
*
* @return float
*/
public function get_recommended_staff_count(): float {
if ($this->active_users == null || $this->active_users == 0) return INF;
$recommended_staff_count = ceil($this->active_users ** 0.25);
return max(2, $recommended_staff_count);
@ -650,18 +687,30 @@
/**
* Estimate whether the Community has enough staff.
*
* @return bool
*/
public function has_good_staff_rating(): bool {
$staff_count = count($this->get_staff());
return $staff_count >= $this->get_recommended_staff_count();
}
public function get_numeric_staff_rating() {
/**
* Return a rating for the Community's staff count relative to active users.
*
* @return float
*/
public function get_numeric_staff_rating(): float {
if (!$this->write || !$this->read) return 2;
return min(2, count($this->get_staff()) / $this->get_recommended_staff_count());
}
public function get_minimal_staff_count() {
/**
* Compute the lower threshold for Community staff count.
*
* @return float
*/
public function get_minimal_staff_count(): float {
if ($this->active_users == null || $this->active_users == 0) return INF;
$minimal_staff_count = 1 + round((0.38 * log($this->active_users)) ** 1.15);
return max(2, $minimal_staff_count);
@ -797,7 +846,7 @@
}
/**
* Class representing Session Community server hosting Community rooms .
* Represents a Session Open Group Server .
*/
class CommunityServer implements JsonSerializable {
/**
@ -858,6 +907,7 @@
/**
* Sort an array of servers in place based on URL.
* @param CommunityServer[] & $servers
* @return void
*/
static function sort_by_url(array & $servers) {
usort($servers, 'CommunityServer::compare_by_url');
@ -878,6 +928,7 @@
/**
* Sorts an array of servers in place by public key.
* @param CommunityServer[] $servers
* @return void
*/
public static function sort_by_pubkey(& $servers) {
foreach ($servers as $server) {
@ -893,6 +944,9 @@
/**
* Return true whether the two servers given share a room.
* @param CommunityServer $a First server to compare.
* @param CommunityServer $b Second server to compare.
* @return bool
*/
public static function rooms_in_common(CommunityServer $a, CommunityServer $b): bool {
// Rely on at least token or creation date differing.
@ -1122,7 +1176,7 @@
/**
* Create Community server instance from array loaded server data.
* @param array $details Decoded JSON associative arrays about server .
* @param array $details_array Array of associative arrays holding server data .
* @return CommunityServer[] Servers represented by given data.
*/
static function from_details_array(array $details_array) {
@ -1139,6 +1193,7 @@
* Add to the given servers additional data extracted from our sources.
* @param CommunityServer[] $servers
* @param CommunitySources $source
* @return void
*/
static function source_additional_info(array $servers, CommunitySources $source): void {
foreach ($servers as $server) {
@ -1214,13 +1269,17 @@
/**
* Returns the hostname for this server.
* @param bool $include_scheme [optional]
* Includes the port. `true` by default .
* @param bool $include_port
* Include port in output, if provided. Default: `true` .
* @return string URL with hostname and port, if applicable.
* Scheme not included.
*/
function get_hostname(bool $include_port = true) {
return url_get_base($this->base_url, include_scheme: false, include_port: $include_port);
return url_get_base(
$this->base_url,
include_scheme: false,
include_port: $include_port
);
}
/**
@ -1232,7 +1291,9 @@
}
/**
* Returns the URL to the endpoint listing this server's rooms.
* Returns the URL to the endpoint describing this server's rooms.
*
* @return string
*/
function get_rooms_api_url(): string {
$base_url = $this->base_url;
@ -1240,7 +1301,11 @@
}
/**
* Returns the URL for the endpoint of the particular room.
* Returns the URL for the endpoint describing a particular room.
*
* @param string $token Token of Community to construct URL.
*
* @return string
*/
function get_room_api_url(string $token): string {
$base_url = $this->base_url;
@ -1318,12 +1383,19 @@
return $pubkey_prefix . $hostname_hash_prefix;
}
/**
* Return string value used to sort Communities by host.
*
* @return string
*/
public function get_server_sort_key(): string {
return $this->get_pubkey() . $this->get_hostname();
}
/**
* Returns the room of the given token, or null if one does not exist.
* @param string $token The string token of a room on the server.
* @return CommunityRoom|null
*/
function get_room_by_token(string $token): CommunityRoom | null {
$candidates = array_filter($this->rooms, function(CommunityRoom $room) use ($token) {
@ -1577,7 +1649,14 @@
return true;
}
/**
* Construct full-fledged Community objects if the public key is available.
* @return void
*/
public function construct_rooms() {
if (!$this->has_pubkey()) {
throw new Error("Cannot construct rooms before pubkey is fetched");
}
$this->rooms = CommunityRoom::from_details_array(
$this,
$this->_intermediate_room_data
@ -1585,7 +1664,9 @@
}
/**
* @return CommunityServer[]
* Deserialize Community servers from the given JSON file.
* @param string $file Path to JSON file containing fetched server data.
* @return CommunityServer[] Array of Session Open Group servers.
*/
public static function read_servers_from_file(string $file): array {
// Read the server data from disk.