upub_cli/
fetch.rs

1use sea_orm::{EntityTrait, TransactionTrait};
2use upub::traits::{fetch::RequestError, Addresser, Fetcher, Normalizer};
3
4pub async fn fetch(ctx: upub::Context, uri: String, save: bool, actor: Option<String>) -> Result<(), RequestError> {
5	use apb::Base;
6
7	let mut pkey = ctx.pkey().to_string();
8	let mut from = ctx.base().to_string();
9	
10	if let Some(actor) = actor {
11		let actor_model = upub::model::actor::Entity::find_by_ap_id(&actor)
12			.one(ctx.db())
13			.await?
14			.ok_or_else(|| sea_orm::DbErr::RecordNotFound(actor.clone()))?;
15
16		match actor_model.private_key {
17			None => tracing::error!("requested actor lacks a private key, fetching with server key instead"),
18			Some(x) => {
19				pkey = x;
20				from = actor.to_string();
21			},
22		}
23	}
24
25	let mut node = apb::Node::link(uri.to_string());
26	if let apb::Node::Link(ref uri) = node {
27		if let Ok(href) = uri.href() {
28			node = upub::Context::request(reqwest::Method::GET, &href, None, &from, &pkey, ctx.domain())
29				.await?
30				.json::<serde_json::Value>()
31				.await?
32				.into();
33		}
34	}
35
36
37	let obj = node.into_inner().expect("node still empty after fetch?");
38
39	println!("{}", serde_json::to_string_pretty(&obj).unwrap());
40
41	if save {
42		let tx = ctx.db().begin().await?;
43		match obj.base_type() {
44			Ok(apb::BaseType::Object(apb::ObjectType::Actor(_))) => {
45				upub::model::actor::Entity::insert(upub::AP::actor_q(&obj, None)?)
46					.exec(&tx)
47					.await?;
48			},
49			Ok(apb::BaseType::Object(apb::ObjectType::Activity(_))) => {
50				let act = ctx.insert_activity(obj, &tx).await?;
51				ctx.address(Some(&act), None, &tx).await?;
52			},
53			Ok(apb::BaseType::Object(apb::ObjectType::Note)) => {
54				let obj = ctx.insert_object(obj, &tx).await?;
55				ctx.address(None, Some(&obj), &tx).await?;
56			},
57			Ok(apb::BaseType::Object(t)) => tracing::warn!("not implemented: {:?}", t),
58			Ok(apb::BaseType::Link(_)) => tracing::error!("fetched another link?"),
59			Err(_) => tracing::error!("no type on object"),
60		}
61		tx.commit().await?;
62	}
63
64	Ok(())
65}