upub_cli/
faker.rs

1use upub::{ext::JsonVec, model::{activity, actor, addressing, config, credential, object}};
2use openssl::rsa::Rsa;
3use sea_orm::{ActiveValue::NotSet, IntoActiveModel};
4
5pub async fn faker(ctx: upub::Context, count: i64) -> Result<(), sea_orm::DbErr> {
6	use sea_orm::{EntityTrait, Set};
7
8	let domain = ctx.domain();
9	let db = ctx.db();
10
11	let key = Rsa::generate(2048).unwrap();
12	let test_user = actor::Model {
13		internal: 42,
14		id: format!("{domain}/actors/test"),
15		name: Some("μpub".into()),
16		domain: clean_domain(domain),
17		preferred_username: "test".to_string(),
18		summary: Some("hello world! i'm manually generated but served dynamically from db! check progress at https://git.alemi.dev/upub.git".to_string()),
19		following: None,
20		following_count: 0,
21		followers: None,
22		followers_count: 0,
23		statuses_count: count as i32,
24		fields: JsonVec::default(),
25		also_known_as: JsonVec::default(),
26		moved_to: None,
27		icon: Some("https://cdn.alemi.dev/social/circle-square.png".to_string()),
28		image: Some("https://cdn.alemi.dev/social/someriver-xs.jpg".to_string()),
29		inbox: None,
30		shared_inbox: None,
31		outbox: None,
32		actor_type: apb::ActorType::Person,
33		published: chrono::Utc::now(),
34		updated: chrono::Utc::now(),
35		private_key: Some(std::str::from_utf8(&key.private_key_to_pem().unwrap()).unwrap().to_string()),
36		// TODO generate a fresh one every time
37		public_key: std::str::from_utf8(&key.public_key_to_pem().unwrap()).unwrap().to_string(),
38	};
39
40	actor::Entity::insert(test_user.clone().into_active_model()).exec(db).await?;
41
42	config::Entity::insert(config::ActiveModel {
43		internal: NotSet,
44		actor: Set(test_user.id.clone()),
45		accept_follow_requests: Set(true),
46		show_following_count: Set(true),
47		show_followers_count: Set(true),
48		show_followers: Set(false),
49		show_following: Set(false),
50		show_liked_objects: Set(false),
51		show_lists: Set(false),
52	}).exec(db).await?;
53
54	credential::Entity::insert(credential::ActiveModel {
55		internal: NotSet,
56		actor: Set(test_user.id.clone()),
57		login: Set("mail@example.net".to_string()),
58		password: Set(sha256::digest("very-strong-password")),
59		active: Set(true),
60	}).exec(db).await?;
61
62	let context = uuid::Uuid::new_v4().to_string();
63
64	for i in (0..count).rev() {
65		let oid = uuid::Uuid::new_v4();
66		let aid = uuid::Uuid::new_v4();
67
68		addressing::Entity::insert(addressing::ActiveModel {
69			actor: Set(None),
70			instance: Set(None),
71			activity: Set(Some(42 + i)),
72			object: Set(Some(42 + i)),
73			published: Set(chrono::Utc::now()),
74			..Default::default()
75		}).exec(db).await?;
76
77		object::Entity::insert(object::ActiveModel {
78			internal: Set(42 + i),
79			id: Set(format!("{domain}/objects/{oid}")),
80			name: Set(None),
81			object_type: Set(apb::ObjectType::Note),
82			attributed_to: Set(Some(format!("{domain}/actors/test"))),
83			summary: Set(None),
84			context: Set(Some(context.clone())),
85			in_reply_to: Set(None),
86			quote: Set(None),
87			content: Set(Some(format!("[{i}] Tic(k). Quasiparticle of intensive multiplicity. Tics (or ticks) are intrinsically several components of autonomously numbering anorganic populations, propagating by contagion between segmentary divisions in the order of nature. Ticks - as nonqualitative differentially-decomposable counting marks - each designate a multitude comprehended as a singular variation in tic(k)-density."))),
88			image: Set(None),
89			published: Set(chrono::Utc::now() - std::time::Duration::from_secs(60*i as u64)),
90			updated: Set(chrono::Utc::now()),
91			replies: Set(0),
92			likes: Set(0),
93			announces: Set(0),
94			audience: Set(None),
95			to: Set(JsonVec(vec![apb::target::PUBLIC.to_string()])),
96			bto: Set(JsonVec::default()),
97			cc: Set(JsonVec(vec![])),
98			bcc: Set(JsonVec::default()),
99			url: Set(None),
100			sensitive: Set(false),
101		}).exec(db).await?;
102
103		activity::Entity::insert(activity::ActiveModel {
104			internal: Set(42 + i),
105			id: Set(format!("{domain}/activities/{aid}")),
106			activity_type: Set(apb::ActivityType::Create),
107			actor: Set(format!("{domain}/actors/test")),
108			object: Set(Some(format!("{domain}/objects/{oid}"))),
109			target: Set(None),
110			content: Set(None),
111			published: Set(chrono::Utc::now() - std::time::Duration::from_secs(60*i as u64)),
112			to: Set(JsonVec(vec![apb::target::PUBLIC.to_string()])),
113			bto: Set(JsonVec::default()),
114			cc: Set(JsonVec(vec![])),
115			bcc: Set(JsonVec::default()),
116		}).exec(db).await?;
117	}
118
119	Ok(())
120}
121
122fn clean_domain(domain: &str) -> String {
123	domain
124		.replace("http://", "")
125		.replace("https://", "")
126		.replace('/', "")
127}