You cannot select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
	
	
		
			149 lines
		
	
	
		
			4.1 KiB
		
	
	
	
		
			PHP
		
	
			
		
		
	
	
			149 lines
		
	
	
		
			4.1 KiB
		
	
	
	
		
			PHP
		
	
| <?php
 | |
| 	/**
 | |
| 	 * \file
 | |
| 	 * Implement Community listings for the [Listing Provider API](https://codeberg.org/gravel/session-listing-providers).
 | |
| 	 */
 | |
| 
 | |
| 	require_once "getenv.php";
 | |
| 	require_once "utils/logging.php";
 | |
| 	require_once "servers/servers-rooms.php";
 | |
| 
 | |
| 	/**
 | |
| 	 * Represents a Community listing in the Listing Provider API.
 | |
| 	 */
 | |
| 	class CommunityListing implements JsonSerializable {
 | |
| 		/**
 | |
| 		 * @var string $id
 | |
| 		 * Unique listing identifier.
 | |
| 		 */
 | |
| 		public readonly string $id;
 | |
| 		/**
 | |
| 		 * @var string $name
 | |
| 		 * Human-readable listing name.
 | |
| 		 */
 | |
| 		public readonly string $name;
 | |
| 		/**
 | |
| 		 * @var string $rating
 | |
| 		 * One-word content rating for Communities listed.
 | |
| 		 */
 | |
| 		public readonly string $rating;
 | |
| 		/**
 | |
| 		 * @var CommunityRoom[] $rooms
 | |
| 		 * Communities included in the listing.
 | |
| 		 */
 | |
| 		public readonly array $rooms;
 | |
| 
 | |
| 		/**
 | |
| 		 * Create a new CommunityListing instance with the given parameters.
 | |
| 		 * @param string $id Unique listing identifier.
 | |
| 		 * @param string $name Human-readable listing name.
 | |
| 		 * @param string $rating One-word content rating for Communities listed.
 | |
| 		 * @param CommunityRoom[] $rooms Communities included in the listing.
 | |
| 		 */
 | |
| 		public function __construct(string $id, string $name, ?string $rating, array $rooms) {
 | |
| 			$this->id = $id;
 | |
| 			$this->name = $name;
 | |
| 			$this->rating = $rating ?? "unknown";
 | |
| 			$this->rooms = $rooms;
 | |
| 		}
 | |
| 
 | |
| 		/**
 | |
| 		 * Produce associative listing data for JSON serialization.
 | |
| 		 */
 | |
| 		public function jsonSerialize(): mixed {
 | |
| 			// TODO: Careful serialization
 | |
| 			$details = get_object_vars($this);
 | |
| 			$details['rooms'] = array_map(function(CommunityRoom $room){
 | |
| 				return $room->to_listing_data();
 | |
| 			}, $this->rooms);
 | |
| 			return $details;
 | |
| 		}
 | |
| 
 | |
| 		/**
 | |
| 		 * Produce associative data summarizing this listing.
 | |
| 		 */
 | |
| 		public function to_summary(): array {
 | |
| 			return array(
 | |
| 				'id' => $this->id,
 | |
| 				'name' => $this->name,
 | |
| 				'rating' => $this->rating,
 | |
| 				'rooms' => count($this->rooms)
 | |
| 			);
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	/**
 | |
| 	 * Construct Community listings from listing configuration and cached Communities.
 | |
| 	 * @return CommunityListing[]
 | |
| 	 * \todo Refactor
 | |
| 	 */
 | |
| 	function resolve_listings_config(): array {
 | |
| 		global $LISTINGS_INI, $ROOMS_FILE;
 | |
| 
 | |
| 		$listings_raw = parse_ini_file($LISTINGS_INI, process_sections: true, scanner_mode: INI_SCANNER_RAW);
 | |
| 		$servers_raw = file_get_contents($ROOMS_FILE);
 | |
| 		$server_data = json_decode($servers_raw, true);
 | |
| 
 | |
| 		$servers = CommunityServer::from_details_array($server_data);
 | |
| 		$rooms_all = CommunityServer::enumerate_rooms($servers);
 | |
| 
 | |
| 		$listings = [];
 | |
| 		foreach ($listings_raw as $id => $listing_props) {
 | |
| 			$filter = [...($listing_props['rooms'] ?? []), ...($listing_props['sogs'] ?? [])];
 | |
| 			$matchees = [];
 | |
| 			$rooms = CommunityRoom::select_rooms($rooms_all, $filter, $matchees);
 | |
| 
 | |
| 			foreach ($filter as $filter_item) {
 | |
| 				if (!in_array($filter_item, $matchees)) {
 | |
| 					log_warning("Could not find $filter_item from listing $id.");
 | |
| 				}
 | |
| 			}
 | |
| 
 | |
| 			$rooms = array_filter($rooms, function(CommunityRoom $room) {
 | |
| 				return !$room->is_off_record();
 | |
| 			});
 | |
| 
 | |
| 			$listings[] = new CommunityListing(
 | |
| 				$id,
 | |
| 				$listing_props['name'],
 | |
| 				$listing_props['rating'],
 | |
| 				$rooms
 | |
| 			);
 | |
| 		}
 | |
| 
 | |
| 		return $listings;
 | |
| 	}
 | |
| 
 | |
| 	/**
 | |
| 	 * Resolve and write configured Community listings to disk.
 | |
| 	 */
 | |
| 	function generate_listings() {
 | |
| 		global $LISTING_PROVIDER_LISTING_SUMMARY, $LISTING_PROVIDER_LISTINGS;
 | |
| 		log_info("Generating listings...");
 | |
| 
 | |
| 		$listings_resolved = resolve_listings_config();
 | |
| 		$summaries = array_map(function(CommunityListing $listing) {
 | |
| 			return $listing->to_summary();
 | |
| 		}, $listings_resolved);
 | |
| 		file_put_contents($LISTING_PROVIDER_LISTING_SUMMARY, json_encode($summaries));
 | |
| 		foreach ($listings_resolved as $listing) {
 | |
| 			$id = $listing->id;
 | |
| 			file_put_contents(
 | |
| 				"$LISTING_PROVIDER_LISTINGS/$id",
 | |
| 				json_encode($listing)
 | |
| 			);
 | |
| 		}
 | |
| 		$listings_count = count($listings_resolved);
 | |
| 		log_info("Generated $listings_count listings.");
 | |
| 	}
 | |
| 
 | |
| 	file_exists($LISTING_PROVIDER_LISTINGS) or mkdir($LISTING_PROVIDER_LISTINGS, 0755, true);
 | |
| 
 | |
| 	$options = getopt("v", ["verbose"]);
 | |
| 	if (isset($options["v"]) or isset($options["verbose"])) {
 | |
| 		$LOGGING_VERBOSITY = LoggingVerbosity::Debug;
 | |
| 	}
 | |
| 
 | |
| 	generate_listings();
 | |
| ?>
 |