Skip to main content

neptunium_http/endpoints/
meta.rs

1use reqwest::Method;
2use serde::{Deserialize, Serialize};
3
4use crate::{endpoints::Endpoint, request::Request};
5
6mod limits;
7
8pub use limits::*;
9
10#[derive(Copy, Clone, Debug)]
11pub struct InstanceDiscoveryDocument;
12
13impl Endpoint for InstanceDiscoveryDocument {
14    type Response = InstanceDiscoveryDocumentResponse;
15
16    fn into_request(self) -> crate::request::Request {
17        Request::builder()
18            .use_authorization_token(false)
19            .method(Method::GET)
20            .path(String::from("/.well-known/fluxer"))
21            .build()
22    }
23}
24
25#[derive(Serialize, Deserialize, Clone, Debug)]
26pub struct InstanceDiscoveryDocumentEndpoints {
27    /// Base URL for authenticated API requests.
28    pub api: String,
29    /// Base URL for client API requests.
30    pub api_client: String,
31    /// Base URL for public API requests.
32    pub api_public: String,
33    /// WebSocket URL for the gateway.
34    pub gateway: String,
35    /// Base URL for the media proxy.
36    pub media: String,
37    /// Base URL for static assets (avatars, emojis, etc.).
38    pub static_cdn: String,
39    /// Base URL for the marketing website.
40    pub marketing: String,
41    /// Base URL for the admin panel.
42    pub admin: String,
43    /// Base URL for invite links.
44    pub invite: String,
45    /// Base URL for gift links.
46    pub gift: String,
47    /// Base URL for the web application.
48    pub webapp: String,
49}
50
51#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq)]
52#[serde(rename_all = "lowercase", tag = "provider")]
53pub enum InstanceDiscoveryDocumentCaptchaConfig {
54    HCaptcha {
55        hcaptcha_site_key: String,
56        /// Field may still be present.
57        turnstile_site_key: Option<String>,
58    },
59    Turnstile {
60        turnstile_site_key: String,
61        /// Field may still be present.
62        hcaptcha_site_key: Option<String>,
63    },
64    None,
65}
66
67#[expect(clippy::struct_excessive_bools)]
68#[derive(Serialize, Deserialize, Copy, Clone, Debug)]
69pub struct InstanceDiscoveryDocumentFeatures {
70    pub sms_mfa_enabled: bool,
71    pub voice_enabled: bool,
72    pub stripe_enabled: bool,
73    pub self_hosted: bool,
74    // TODO: Check what's up with https://github.com/fluxerapp/fluxer/blob/03813bbe17db008452f0f1be3090a7d2970a5447/packages/api/src/instance/InstanceController.tsx#L86
75    /// This is documented as "required" in the documentation, but appears to be missing.
76    pub manual_review_enabled: Option<bool>,
77    /// Undocumented so far.
78    pub presigned_attachment_uploads: bool,
79}
80
81/// Single sign-on configuration.
82#[derive(Serialize, Deserialize, Clone, Debug)]
83pub struct InstanceDiscoveryDocumentSSOConfiguration {
84    pub enabled: bool,
85    pub enforced: bool,
86    pub display_name: Option<String>,
87    pub redirect_uri: String,
88}
89
90#[derive(Serialize, Deserialize, Copy, Clone, Debug, PartialEq, Eq)]
91#[serde(rename_all = "lowercase")]
92pub enum InstanceDiscoveryDocumentGifProviders {
93    Klipy,
94    Tenor,
95}
96
97pub struct InstanceDiscoveryDocumentGifProvider {
98    pub provider: InstanceDiscoveryDocumentGifProviders,
99}
100
101#[derive(Serialize, Deserialize, Clone, Debug)]
102pub struct InstanceDiscoveryDocumentPushNotificationConfig {
103    pub public_vapid_key: Option<String>,
104}
105
106#[derive(Serialize, Deserialize, Clone, Debug)]
107pub struct InstanceDiscoveryDocumentAppPublic {
108    /// Sentry DSN for client-side error reporting.
109    pub sentry_dsn: String,
110}
111
112#[derive(Serialize, Deserialize, Clone, Debug)]
113pub struct InstanceDiscoveryDocumentFederationConfig {
114    pub enabled: bool,
115    /// Federation protocol version.
116    pub version: u64,
117}
118
119#[derive(Serialize, Deserialize, Copy, Clone, Debug, PartialEq, Eq)]
120pub enum InstanceDiscoveryDocumentPublicKeyAlgorithm {
121    #[serde(rename = "x25519")]
122    X25519,
123}
124
125#[derive(Serialize, Deserialize, Clone, Debug)]
126pub struct InstanceDiscoveryDocumentPublicKey {
127    pub id: String,
128    pub algorithm: InstanceDiscoveryDocumentPublicKeyAlgorithm,
129    pub public_key_base64: String,
130}
131
132#[derive(Serialize, Deserialize, Clone, Debug)]
133pub struct InstanceDiscoveryDocumentOauth2 {
134    pub authorization_endpoint: String,
135    pub token_endpoint: String,
136    pub userinfo_endpoint: String,
137    pub scopes_supported: Vec<String>,
138}
139
140#[derive(Deserialize, Clone, Debug)]
141pub struct InstanceDiscoveryDocumentResponse {
142    /// Version of the API server code.
143    pub api_code_version: u64,
144    pub endpoints: InstanceDiscoveryDocumentEndpoints,
145    pub captcha: InstanceDiscoveryDocumentCaptchaConfig,
146    pub features: InstanceDiscoveryDocumentFeatures,
147    pub sso: InstanceDiscoveryDocumentSSOConfiguration,
148    pub push: InstanceDiscoveryDocumentPushNotificationConfig,
149    pub app_public: InstanceDiscoveryDocumentAppPublic,
150    #[serde(skip_serializing_if = "Option::is_none")]
151    pub federation: Option<InstanceDiscoveryDocumentFederationConfig>,
152    #[serde(skip_serializing_if = "Option::is_none")]
153    pub public_key: Option<InstanceDiscoveryDocumentPublicKey>,
154    #[expect(clippy::doc_markdown)]
155    /// OAuth2 endpoint for federation.
156    #[serde(skip_serializing_if = "Option::is_none")]
157    pub oauth2: Option<InstanceDiscoveryDocumentOauth2>,
158    pub limits: InstanceDiscoveryDocumentLimits,
159}