a mini social media app for small communities
at main 7.8 kB view raw
1module database 2 3import entity { User, Notification, Like, LikeCache, Post } 4import util 5import db.pg 6 7// new_user creates a new user and returns their struct after creation. 8pub fn (app &DatabaseAccess) new_user(user User) ?User { 9 sql app.db { 10 insert user into User 11 } or { 12 eprintln('failed to insert user ${user}') 13 return none 14 } 15 16 println('reg: ${user.username}') 17 18 return app.get_user_by_name(user.username) 19} 20 21// set_username sets the given user's username, returns true if this succeeded 22// and false otherwise. 23pub fn (app &DatabaseAccess) set_username(user_id int, new_username string) bool { 24 sql app.db { 25 update User set username = new_username where id == user_id 26 } or { 27 eprintln('failed to update username for ${user_id}') 28 return false 29 } 30 return true 31} 32 33// set_password sets the given user's password, returns true if this succeeded 34// and false otherwise. 35pub fn (app &DatabaseAccess) set_password(user_id int, hashed_new_password string) bool { 36 sql app.db { 37 update User set password = hashed_new_password where id == user_id 38 } or { 39 eprintln('failed to update password for ${user_id}') 40 return false 41 } 42 return true 43} 44 45// set_nickname sets the given user's nickname, returns true if this succeeded 46// and false otherwise. 47pub fn (app &DatabaseAccess) set_nickname(user_id int, new_nickname ?string) bool { 48 sql app.db { 49 update User set nickname = new_nickname where id == user_id 50 } or { 51 eprintln('failed to update nickname for ${user_id}') 52 return false 53 } 54 return true 55} 56 57// set_muted sets the given user's muted status, returns true if this succeeded 58// and false otherwise. 59pub fn (app &DatabaseAccess) set_muted(user_id int, muted bool) bool { 60 sql app.db { 61 update User set muted = muted where id == user_id 62 } or { 63 eprintln('failed to update muted status for ${user_id}') 64 return false 65 } 66 return true 67} 68 69// set_automated sets the given user's automated status, returns true if this 70// succeeded and false otherwise. 71pub fn (app &DatabaseAccess) set_automated(user_id int, automated bool) bool { 72 sql app.db { 73 update User set automated = automated where id == user_id 74 } or { 75 eprintln('failed to update automated status for ${user_id}') 76 return false 77 } 78 return true 79} 80 81// set_theme sets the given user's theme url, returns true if this succeeded and 82// false otherwise. 83pub fn (app &DatabaseAccess) set_theme(user_id int, theme ?string) bool { 84 sql app.db { 85 update User set theme = theme where id == user_id 86 } or { 87 eprintln('failed to update theme url for ${user_id}') 88 return false 89 } 90 return true 91} 92 93// set_css sets the given user's custom CSS, returns true if this succeeded and 94// false otherwise. 95pub fn (app &DatabaseAccess) set_css(user_id int, css ?string) bool { 96 sql app.db { 97 update User set css = css where id == user_id 98 } or { 99 eprintln('failed to update css for ${user_id}') 100 return false 101 } 102 return true 103} 104 105// set_pronouns sets the given user's pronouns, returns true if this succeeded 106// and false otherwise. 107pub fn (app &DatabaseAccess) set_pronouns(user_id int, pronouns string) bool { 108 sql app.db { 109 update User set pronouns = pronouns where id == user_id 110 } or { 111 eprintln('failed to update pronouns for ${user_id}') 112 return false 113 } 114 return true 115} 116 117// set_bio sets the given user's bio, returns true if this succeeded and false 118// otherwise. 119pub fn (app &DatabaseAccess) set_bio(user_id int, bio string) bool { 120 sql app.db { 121 update User set bio = bio where id == user_id 122 } or { 123 eprintln('failed to update bio for ${user_id}') 124 return false 125 } 126 return true 127} 128 129// get_user_by_name gets a user by their username, returns none if the user was 130// not found. 131pub fn (app &DatabaseAccess) get_user_by_name(username string) ?User { 132 users := sql app.db { 133 select from User where username == username 134 } or { [] } 135 if users.len != 1 { 136 return none 137 } 138 return users[0] 139} 140 141// get_user_by_id gets a user by their id, returns none if the user was not 142// found. 143pub fn (app &DatabaseAccess) get_user_by_id(id int) ?User { 144 users := sql app.db { 145 select from User where id == id 146 } or { [] } 147 if users.len != 1 { 148 return none 149 } 150 return users[0] 151} 152 153// get_users returns all users. 154pub fn (app &DatabaseAccess) get_users() []User { 155 users := sql app.db { 156 select from User 157 } or { [] } 158 return users 159} 160 161// does_user_like_post returns true if a user likes the given post. 162pub fn (app &DatabaseAccess) does_user_like_post(user_id int, post_id int) bool { 163 likes := app.db.exec_param2('SELECT id, is_like FROM "Like" WHERE user_id = $1 AND post_id = $2', user_id.str(), post_id.str()) or { [] } 164 if likes.len > 1 { 165 // something is very wrong lol 166 eprintln('does_user_like_post: a user somehow got two or more likes on the same post (user: ${user_id}, post: ${post_id})') 167 } else if likes.len == 0 { 168 return false 169 } 170 return util.or_throw(likes.first().vals[1]).bool() 171} 172 173// does_user_dislike_post returns true if a user dislikes the given post. 174pub fn (app &DatabaseAccess) does_user_dislike_post(user_id int, post_id int) bool { 175 likes := app.db.exec_param2('SELECT id, is_like FROM "Like" WHERE user_id = $1 AND post_id = $2', user_id.str(), post_id.str()) or { [] } 176 if likes.len > 1 { 177 // something is very wrong lol 178 eprintln('does_user_dislike_post: a user somehow got two or more likes on the same post (user: ${user_id}, post: ${post_id})') 179 } else if likes.len == 0 { 180 return false 181 } 182 return !util.or_throw(likes.first().vals[1]).bool() 183} 184 185// does_user_like_or_dislike_post returns true if a user likes *or* dislikes the 186// given post. 187pub fn (app &DatabaseAccess) does_user_like_or_dislike_post(user_id int, post_id int) bool { 188 likes := app.db.exec_param2('SELECT id FROM "Like" WHERE user_id = $1 AND post_id = $2', user_id.str(), post_id.str()) or { [] } 189 if likes.len > 1 { 190 // something is very wrong lol 191 eprintln('does_user_like_or_dislike_post: a user somehow got two or more likes on the same post (user: ${user_id}, post: ${post_id})') 192 } 193 return likes.len == 1 194} 195 196// delete_user deletes the given user and their data, returns true if this 197// succeeded and false otherwise. 198pub fn (app &DatabaseAccess) delete_user(user_id int) bool { 199 sql app.db { 200 delete from User where id == user_id 201 delete from Like where user_id == user_id 202 delete from Notification where user_id == user_id 203 } or { 204 return false 205 } 206 207 // delete posts and their likes 208 posts_from_this_user := app.db.exec_param('SELECT id FROM "Post" WHERE author_id = $1', user_id.str()) or { [] } 209 210 for post in posts_from_this_user { 211 id := util.or_throw(post.vals[0]).int() 212 sql app.db { 213 delete from Like where post_id == id 214 delete from LikeCache where post_id == id 215 } or { 216 eprintln('failed to delete like cache for post during user deletion: ${id}') 217 } 218 } 219 220 sql app.db { 221 delete from Post where author_id == user_id 222 } or { 223 eprintln('failed to delete posts by deleting user: ${user_id}') 224 } 225 226 return true 227} 228 229// search_for_users searches for posts matching the given query. 230// todo: query options/filters, such as created-after:<date>, created-before:<date>, etc 231pub fn (app &DatabaseAccess) search_for_users(query string, limit int, offset int) []User { 232 queried_users := app.db.exec_param_many_result('SELECT * FROM search_for_users($1, $2, $3)', [query, limit.str(), offset.str()]) or { 233 eprintln('search_for_users error in app.db.error: ${err}') 234 pg.Result{} 235 } 236 users := queried_users.rows.map(fn [queried_users] (it pg.Row) User { 237 return User.from_row(queried_users, it) 238 }) 239 return users 240} 241 242// get_user_count gets the number of registered users in the database. 243pub fn (app &DatabaseAccess) get_user_count() int { 244 n := app.db.exec('SELECT COUNT(id) FROM "User"') or { 245 eprintln('get_user_count error in app.db.error: ${err}') 246 [] 247 } 248 return if n.len == 0 { 0 } else { util.or_throw(n[0].vals[0]).int() } 249}