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