git-gemini-forge 0.6.2

A simple Gemini server that serves a read-only view of public repositories from a Git forge.
use super::ForgejoApi;
use crate::handlers::templates::PercentEncoded;
use crate::network::ForgeApi;
use crate::network::net::{ApiEndpoint, Net};
use crate::network::{error, responses::Repo};
use url::Url;

struct UserReposEndpoint<'a> {
	api: &'a ForgejoApi,
	base_url: Url,
	username: &'a PercentEncoded,
}

impl ApiEndpoint<ForgejoApi, Vec<Repo>> for UserReposEndpoint<'_> {
	fn api(&self) -> &ForgejoApi {
		self.api
	}

	fn url(&self) -> Url {
		let mut url = self
			.base_url
			.join(&format!("users/{}/repos", self.username.uri_component()))
			.expect("Valid URL path");
		// TODO: Open an issue about how forgejo sorts these; if localhost then maybe we can pull all and sort locally?
		url.set_query(Some("limit=15&page=1")); // Matches /{owner}?tab=repositories
		url
	}
}

/// Retrieves the user's repositories from the given API.
pub fn get_user_repos(
	api: &ForgejoApi,
	net: &Net,
	username: &PercentEncoded,
) -> Result<Vec<Repo>, error::Error> {
	let base_url = api.base_url().clone();
	let endpoint = UserReposEndpoint {
		api,
		base_url,
		username,
	};

	// Sort repos by date
	// TODO: Parse X-Total-Count header as usize to get total for pagination
	let mut repos = net.call(&endpoint)?;
	repos.sort_by(|a: &Repo, b: &Repo| {
		return b.updated_at.cmp(&a.updated_at);
	});
	return Ok(repos);
}