use collab::{ db::{self, NewUserParams}, env::load_dotenv, executor::Executor, }; use db::{ConnectOptions, Database}; use serde::{de::DeserializeOwned, Deserialize}; use std::{fmt::Write, fs}; #[derive(Debug, Deserialize)] struct GitHubUser { id: i32, login: String, email: Option, } #[tokio::main] async fn main() { load_dotenv().expect("failed to load .env.toml file"); let mut admin_logins = load_admins("crates/collab/.admins.default.json") .expect("failed to load default admins file"); if let Ok(other_admins) = load_admins("./.admins.json") { admin_logins.extend(other_admins); } let database_url = std::env::var("DATABASE_URL").expect("missing DATABASE_URL env var"); let db = Database::new(ConnectOptions::new(database_url), Executor::Production) .await .expect("failed to connect to postgres database"); let client = reqwest::Client::new(); // Create admin users for all of the users in `.admins.toml` or `.admins.default.toml`. for admin_login in admin_logins { let user = fetch_github::( &client, &format!("https://api.github.com/users/{admin_login}"), ) .await; db.create_user( &user.email.unwrap_or(format!("{admin_login}@example.com")), true, NewUserParams { github_login: user.login, github_user_id: user.id, }, ) .await .expect("failed to create admin user"); } // Fetch 100 other random users from GitHub and insert them into the database. let mut user_count = db .get_all_users(0, 200) .await .expect("failed to load users from db") .len(); let mut last_user_id = None; while user_count < 100 { let mut uri = "https://api.github.com/users?per_page=100".to_string(); if let Some(last_user_id) = last_user_id { write!(&mut uri, "&since={}", last_user_id).unwrap(); } let users = fetch_github::>(&client, &uri).await; for github_user in users { last_user_id = Some(github_user.id); user_count += 1; db.get_or_create_user_by_github_account( &github_user.login, Some(github_user.id), github_user.email.as_deref(), ) .await .expect("failed to insert user"); } } } fn load_admins(path: &str) -> anyhow::Result> { let file_content = fs::read_to_string(path)?; Ok(serde_json::from_str(&file_content)?) } async fn fetch_github(client: &reqwest::Client, url: &str) -> T { let response = client .get(url) .header("user-agent", "zed") .send() .await .expect(&format!("failed to fetch '{}'", url)); response .json() .await .expect(&format!("failed to deserialize github user from '{}'", url)) }