upub/src/main.rs

135 lines
3.3 KiB
Rust
Raw Normal View History

2024-03-14 05:27:08 +01:00
pub mod activitystream;
pub mod activitypub;
2024-03-25 05:08:29 +01:00
mod model;
mod migrations;
mod server;
mod router;
mod errors;
mod auth;
mod dispatcher;
use clap::{Parser, Subcommand};
use sea_orm::{ConnectOptions, Database, EntityTrait, IntoActiveModel};
use sea_orm_migration::MigratorTrait;
use crate::activitystream::{BaseType, ObjectType};
2024-03-25 05:02:20 +01:00
pub const VERSION: &str = env!("CARGO_PKG_VERSION");
#[derive(Parser)]
/// all names were taken
struct CliArgs {
#[clap(subcommand)]
/// command to run
command: CliCommand,
2024-03-20 09:04:08 +01:00
#[arg(short = 'd', long = "db", default_value = "sqlite://./upub.db")]
/// database connection uri
database: String,
2024-03-20 09:04:08 +01:00
#[arg(short = 'D', long, default_value = "http://localhost:3000")]
2024-03-20 08:56:35 +01:00
/// instance base domain, for AP ids
domain: String,
#[arg(long, default_value_t=false)]
/// run with debug level tracing
debug: bool,
}
#[derive(Clone, Subcommand)]
enum CliCommand {
/// run fediverse server
Serve ,
/// apply database migrations
Migrate,
2024-03-16 05:46:14 +01:00
/// generate fake user, note and activity
Faker,
/// fetch a single AP object
Fetch {
/// object id, or uri, to fetch
uri: String,
#[arg(long, default_value_t = false)]
/// store fetched object in local db
save: bool,
},
}
2024-02-09 17:07:55 +01:00
#[tokio::main]
async fn main() {
let args = CliArgs::parse();
tracing_subscriber::fmt()
.compact()
.with_max_level(if args.debug { tracing::Level::DEBUG } else { tracing::Level::INFO })
.init();
// TODO can i do connectoptions.into() or .connect() and skip these ugly bindings?
let mut opts = ConnectOptions::new(&args.database);
opts
.sqlx_logging_level(tracing::log::LevelFilter::Debug);
let db = Database::connect(opts)
.await.expect("error connecting to db");
match args.command {
2024-03-23 20:24:14 +01:00
CliCommand::Serve => router::serve(db, args.domain)
.await,
CliCommand::Migrate => migrations::Migrator::up(&db, None)
.await.expect("error applying migrations"),
2024-03-16 05:46:14 +01:00
2024-03-21 20:36:28 +01:00
CliCommand::Faker => model::faker::faker(&db, args.domain)
2024-03-16 05:46:14 +01:00
.await.expect("error creating fake entities"),
CliCommand::Fetch { uri, save } => fetch(&db, &uri, save)
.await.expect("error fetching object"),
}
}
async fn fetch(db: &sea_orm::DatabaseConnection, uri: &str, save: bool) -> reqwest::Result<()> {
use crate::activitystream::{Base, Object};
let mut node = activitystream::Node::from(uri);
tracing::info!("fetching object");
node.fetch().await?;
tracing::info!("fetched node");
let obj = node.get().expect("node still empty after fetch?");
tracing::info!("fetched object:{}, name:{}", obj.id().unwrap_or(""), obj.name().unwrap_or(""));
if save {
match obj.base_type() {
Some(BaseType::Object(ObjectType::Actor(_))) => {
model::user::Entity::insert(
model::user::Model::new(obj).unwrap().into_active_model()
).exec(db).await.unwrap();
},
Some(BaseType::Object(ObjectType::Activity(_))) => {
model::activity::Entity::insert(
model::activity::Model::new(obj).unwrap().into_active_model()
).exec(db).await.unwrap();
},
Some(BaseType::Object(ObjectType::Note)) => {
model::object::Entity::insert(
model::object::Model::new(obj).unwrap().into_active_model()
).exec(db).await.unwrap();
},
Some(BaseType::Object(t)) => tracing::warn!("not implemented: {:?}", t),
Some(BaseType::Link(_)) => tracing::error!("fetched another link?"),
None => tracing::error!("no type on object"),
}
}
Ok(())
}