1use clap::Parser;
2use db::{Db, PostgresDb, UserId};
3use rand::prelude::*;
4use serde::Deserialize;
5use std::fmt::Write;
6use time::{Duration, OffsetDateTime};
7
8#[allow(unused)]
9#[path = "../db.rs"]
10mod db;
11
12#[derive(Parser)]
13struct Args {
14 /// Seed users from GitHub.
15 #[clap(short, long)]
16 github_users: bool,
17}
18
19#[derive(Debug, Deserialize)]
20struct GitHubUser {
21 id: usize,
22 login: String,
23}
24
25#[tokio::main]
26async fn main() {
27 let args = Args::parse();
28 let mut rng = StdRng::from_entropy();
29 let database_url = std::env::var("DATABASE_URL").expect("missing DATABASE_URL env var");
30 let db = PostgresDb::new(&database_url, 5)
31 .await
32 .expect("failed to connect to postgres database");
33
34 let mut zed_users = vec![
35 "nathansobo".to_string(),
36 "maxbrunsfeld".to_string(),
37 "as-cii".to_string(),
38 "iamnbutler".to_string(),
39 "gibusu".to_string(),
40 "Kethku".to_string(),
41 ];
42
43 if args.github_users {
44 let github_token = std::env::var("GITHUB_TOKEN").expect("missing GITHUB_TOKEN env var");
45 let client = reqwest::Client::new();
46 let mut last_user_id = None;
47 for page in 0..20 {
48 println!("Downloading users from GitHub, page {}", page);
49 let mut uri = "https://api.github.com/users?per_page=100".to_string();
50 if let Some(last_user_id) = last_user_id {
51 write!(&mut uri, "&since={}", last_user_id).unwrap();
52 }
53 let response = client
54 .get(uri)
55 .bearer_auth(&github_token)
56 .header("user-agent", "zed")
57 .send()
58 .await
59 .expect("failed to fetch github users");
60 let users = response
61 .json::<Vec<GitHubUser>>()
62 .await
63 .expect("failed to deserialize github user");
64 zed_users.extend(users.iter().map(|user| user.login.clone()));
65
66 if let Some(last_user) = users.last() {
67 last_user_id = Some(last_user.id);
68 } else {
69 break;
70 }
71 }
72 }
73
74 let mut zed_user_ids = Vec::<UserId>::new();
75 for zed_user in zed_users {
76 if let Some(user) = db
77 .get_user_by_github_login(&zed_user)
78 .await
79 .expect("failed to fetch user")
80 {
81 zed_user_ids.push(user.id);
82 } else {
83 zed_user_ids.push(
84 db.create_user(&zed_user, true)
85 .await
86 .expect("failed to insert user"),
87 );
88 }
89 }
90
91 let zed_org_id = if let Some(org) = db
92 .find_org_by_slug("zed")
93 .await
94 .expect("failed to fetch org")
95 {
96 org.id
97 } else {
98 db.create_org("Zed", "zed")
99 .await
100 .expect("failed to insert org")
101 };
102
103 let general_channel_id = if let Some(channel) = db
104 .get_org_channels(zed_org_id)
105 .await
106 .expect("failed to fetch channels")
107 .iter()
108 .find(|c| c.name == "General")
109 {
110 channel.id
111 } else {
112 let channel_id = db
113 .create_org_channel(zed_org_id, "General")
114 .await
115 .expect("failed to insert channel");
116
117 let now = OffsetDateTime::now_utc();
118 let max_seconds = Duration::days(100).as_seconds_f64();
119 let mut timestamps = (0..1000)
120 .map(|_| now - Duration::seconds_f64(rng.gen_range(0_f64..=max_seconds)))
121 .collect::<Vec<_>>();
122 timestamps.sort();
123 for timestamp in timestamps {
124 let sender_id = *zed_user_ids.choose(&mut rng).unwrap();
125 let body = lipsum::lipsum_words(rng.gen_range(1..=50));
126 db.create_channel_message(channel_id, sender_id, &body, timestamp, rng.gen())
127 .await
128 .expect("failed to insert message");
129 }
130 channel_id
131 };
132
133 for user_id in zed_user_ids {
134 db.add_org_member(zed_org_id, user_id, true)
135 .await
136 .expect("failed to insert org membership");
137 db.add_channel_member(general_channel_id, user_id, true)
138 .await
139 .expect("failed to insert channel membership");
140 }
141}