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}