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