2025-04-11 12:29:29 +01:00
|
|
|
use main::ap::{http};
|
|
|
|
use rocket::{
|
|
|
|
build, get, http::ContentType, request::{FromRequest, Outcome}, routes, serde::{
|
|
|
|
json::Json, Deserialize, Serialize
|
|
|
|
}, Build, Request, Rocket
|
|
|
|
};
|
2025-04-10 19:40:50 +01:00
|
|
|
|
|
|
|
|
2025-04-11 12:29:29 +01:00
|
|
|
mod cors;
|
|
|
|
mod types;
|
|
|
|
mod endpoints;
|
2025-04-10 19:40:50 +01:00
|
|
|
|
2025-04-11 12:29:29 +01:00
|
|
|
use endpoints::{api::{self, user::CredentialAcount}, oauth, well_known, custom, user};
|
2025-04-10 19:40:50 +01:00
|
|
|
|
2025-04-11 12:29:29 +01:00
|
|
|
use rocket_db_pools::sqlx;
|
|
|
|
use rocket_db_pools::Database;
|
2025-04-10 19:40:50 +01:00
|
|
|
|
|
|
|
#[derive(Database)]
|
|
|
|
#[database("sqlite_ferri")]
|
2025-04-11 12:29:29 +01:00
|
|
|
pub struct Db(sqlx::SqlitePool);
|
2025-04-10 19:40:50 +01:00
|
|
|
|
|
|
|
#[get("/")]
|
|
|
|
async fn user_profile() -> (ContentType, &'static str) {
|
|
|
|
(ContentType::HTML, "<p>hello</p>")
|
|
|
|
}
|
|
|
|
|
|
|
|
#[get("/activities/<activity>")]
|
2025-04-11 12:29:29 +01:00
|
|
|
async fn activity_endpoint(activity: String) {
|
2025-04-10 19:40:50 +01:00
|
|
|
dbg!(activity);
|
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Debug)]
|
|
|
|
struct AuthenticatedUser {
|
2025-04-11 12:29:29 +01:00
|
|
|
username: String,
|
|
|
|
actor_id: String
|
2025-04-10 19:40:50 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Debug)]
|
|
|
|
enum LoginError {
|
|
|
|
InvalidData,
|
|
|
|
UsernameDoesNotExist,
|
2025-04-11 12:29:29 +01:00
|
|
|
WrongPassword,
|
2025-04-10 19:40:50 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
#[rocket::async_trait]
|
|
|
|
impl<'a> FromRequest<'a> for AuthenticatedUser {
|
|
|
|
type Error = LoginError;
|
|
|
|
async fn from_request(request: &'a Request<'_>) -> Outcome<AuthenticatedUser, LoginError> {
|
|
|
|
let token = request.headers().get_one("Authorization").unwrap();
|
|
|
|
Outcome::Success(AuthenticatedUser {
|
2025-04-11 12:29:29 +01:00
|
|
|
username: token.to_string(),
|
|
|
|
actor_id: format!("https://ferri.amy.mov/users/{}", token)
|
2025-04-10 19:40:50 +01:00
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2025-04-11 12:29:29 +01:00
|
|
|
pub type TimelineAccount = CredentialAcount;
|
|
|
|
|
|
|
|
#[derive(Debug, Serialize, Deserialize)]
|
|
|
|
#[serde(crate = "rocket::serde")]
|
|
|
|
struct TimelineStatus {
|
|
|
|
id: String,
|
|
|
|
created_at: String,
|
|
|
|
in_reply_to_id: Option<String>,
|
|
|
|
in_reply_to_account_id: Option<String>,
|
|
|
|
content: String,
|
|
|
|
visibility: String,
|
|
|
|
spoiler_text: String,
|
|
|
|
sensitive: bool,
|
|
|
|
uri: String,
|
|
|
|
url: String,
|
|
|
|
replies_count: i64,
|
|
|
|
reblogs_count: i64,
|
|
|
|
favourites_count: i64,
|
|
|
|
favourited: bool,
|
|
|
|
reblogged: bool,
|
|
|
|
muted: bool,
|
|
|
|
bookmarked: bool,
|
|
|
|
media_attachments: Vec<()>,
|
|
|
|
account: TimelineAccount,
|
|
|
|
}
|
|
|
|
|
|
|
|
#[get("/timelines/home?<limit>")]
|
|
|
|
async fn home_timeline(limit: i64) -> Json<Vec<TimelineStatus>> {
|
|
|
|
Json(vec![TimelineStatus {
|
|
|
|
id: "1".to_string(),
|
|
|
|
created_at: "2025-04-10T22:12:09Z".to_string(),
|
|
|
|
in_reply_to_id: None,
|
|
|
|
in_reply_to_account_id: None,
|
|
|
|
content: "My first post".to_string(),
|
|
|
|
visibility: "public".to_string(),
|
|
|
|
spoiler_text: "".to_string(),
|
|
|
|
sensitive: false,
|
|
|
|
uri: "https://ferri.amy.mov/users/amy/posts/1".to_string(),
|
|
|
|
url: "https://ferri.amy.mov/users/amy/posts/1".to_string(),
|
|
|
|
replies_count: 0,
|
|
|
|
reblogs_count: 0,
|
|
|
|
favourites_count: 0,
|
|
|
|
favourited: false,
|
|
|
|
reblogged: false,
|
|
|
|
muted: false,
|
|
|
|
bookmarked: false,
|
|
|
|
media_attachments: vec![],
|
|
|
|
account: CredentialAcount {
|
|
|
|
id: "https://ferri.amy.mov/users/amy".to_string(),
|
|
|
|
username: "amy".to_string(),
|
|
|
|
acct: "amy@ferri.amy.mov".to_string(),
|
|
|
|
display_name: "amy".to_string(),
|
|
|
|
locked: false,
|
|
|
|
bot: false,
|
|
|
|
created_at: "2025-04-10T22:12:09Z".to_string(),
|
|
|
|
attribution_domains: vec![],
|
|
|
|
note: "".to_string(),
|
|
|
|
url: "https://ferri.amy.mov/@amy".to_string(),
|
|
|
|
avatar: "https://i.sstatic.net/l60Hf.png".to_string(),
|
|
|
|
avatar_static: "https://i.sstatic.net/l60Hf.png".to_string(),
|
|
|
|
header: "https://i.sstatic.net/l60Hf.png".to_string(),
|
|
|
|
header_static: "https://i.sstatic.net/l60Hf.png".to_string(),
|
|
|
|
followers_count: 1,
|
|
|
|
following_count: 1,
|
|
|
|
statuses_count: 1,
|
|
|
|
last_status_at: "2025-04-10T22:14:34Z".to_string(),
|
|
|
|
},
|
|
|
|
}])
|
2025-04-10 19:40:50 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
pub fn launch() -> Rocket<Build> {
|
2025-04-11 12:29:29 +01:00
|
|
|
let http_client = http::HttpClient::new();
|
|
|
|
build()
|
|
|
|
.manage(http_client)
|
|
|
|
.attach(Db::init())
|
|
|
|
.attach(cors::CORS)
|
|
|
|
.mount(
|
|
|
|
"/",
|
|
|
|
routes![
|
|
|
|
custom::test,
|
|
|
|
user::inbox,
|
|
|
|
user::post_inbox,
|
|
|
|
user::outbox,
|
|
|
|
user::user,
|
|
|
|
user::followers,
|
|
|
|
user::following,
|
|
|
|
user::post,
|
|
|
|
oauth::authorize,
|
|
|
|
oauth::new_token,
|
|
|
|
cors::options_req,
|
|
|
|
activity_endpoint,
|
|
|
|
well_known::webfinger,
|
|
|
|
well_known::host_meta,
|
|
|
|
user_profile,
|
|
|
|
],
|
|
|
|
)
|
|
|
|
.mount("/api/v2", routes![api::instance::instance])
|
|
|
|
.mount(
|
|
|
|
"/api/v1",
|
|
|
|
routes![
|
|
|
|
api::status::new_status,
|
|
|
|
api::user::new_follow,
|
|
|
|
api::apps::new_app,
|
|
|
|
api::preferences::preferences,
|
|
|
|
api::user::verify_credentials,
|
|
|
|
custom::finger_account,
|
|
|
|
home_timeline
|
|
|
|
],
|
|
|
|
)
|
2025-04-10 19:40:50 +01:00
|
|
|
}
|