Game sync and live services for independent game developers (targeting itch.io)
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

at main 57 lines 1.7 kB view raw
1use anyhow::{Context, Result}; 2use rusqlite::Connection; 3use ulid::Ulid; 4 5pub async fn generate(count: usize, expires_days: u32, database: &std::path::Path) -> Result<()> { 6 let conn = Connection::open(database).context("Failed to open database")?; 7 8 let expires_at = chrono::Utc::now() 9 + chrono::Duration::days(expires_days as i64); 10 let expires_str = expires_at.to_rfc3339(); 11 12 for _ in 0..count { 13 let code = generate_code(); 14 conn.execute( 15 "INSERT INTO invites (code, created_by, expires_at) VALUES (?1, 'admin', ?2)", 16 [&code, &expires_str], 17 ) 18 .context("Failed to insert invite")?; 19 println!("{}", code); 20 } 21 22 Ok(()) 23} 24 25pub async fn list(database: &std::path::Path, unused_only: bool) -> Result<()> { 26 let conn = Connection::open(database).context("Failed to open database")?; 27 28 let query = if unused_only { 29 "SELECT code, expires_at FROM invites WHERE used_by IS NULL" 30 } else { 31 "SELECT code, used_by, expires_at FROM invites" 32 }; 33 34 let mut stmt = conn.prepare(query)?; 35 let rows = stmt.query_map([], |row| { 36 let code: String = row.get(0)?; 37 let expires_at: String = row.get(1)?; 38 let used_by: Option<String> = row.get(2).ok(); 39 Ok((code, used_by, expires_at)) 40 })?; 41 42 println!("{:<20} {:<20} {}", "CODE", "USED_BY", "EXPIRES_AT"); 43 println!("{}", "-".repeat(60)); 44 45 for row in rows { 46 let (code, used_by, expires_at) = row?; 47 let used = used_by.map(|_| "yes").unwrap_or("no"); 48 println!("{:<20} {:<20} {}", code, used, expires_at); 49 } 50 51 Ok(()) 52} 53 54fn generate_code() -> String { 55 let ulid = Ulid::new(); 56 ulid.to_string() 57}