+1
-1
build.maple
+1
-1
build.maple
+1
-1
doc/todo.md
+1
-1
doc/todo.md
···
23
created-before:<date>
24
is:admin
25
```
26
-
- [ ] misc:replace `SEARCH *` with `SEARCH <column>`
27
28
## planing
29
···
65
discord, and other common links. we want those ones to look fancy!
66
- [x] post:saving (add the post to a list of saved posts that a user can view later)
67
- [x] site:message of the day (admins can add a welcome message displayed on index.html)
68
69
## graveyard
70
···
23
created-before:<date>
24
is:admin
25
```
26
27
## planing
28
···
64
discord, and other common links. we want those ones to look fancy!
65
- [x] post:saving (add the post to a list of saved posts that a user can view later)
66
- [x] site:message of the day (admins can add a welcome message displayed on index.html)
67
+
- [x] misc:replace `SELECT *` with `SELECT <column>`
68
69
## graveyard
70
+5
-9
src/database/like.v
+5
-9
src/database/like.v
···
1
module database
2
3
import entity { Like, LikeCache }
4
5
// add_like adds a like to the database, returns true if this succeeds and false
6
// otherwise.
···
18
// get_net_likes_for_post returns the net likes of the given post.
19
pub fn (app &DatabaseAccess) get_net_likes_for_post(post_id int) int {
20
// check cache
21
-
cache := sql app.db {
22
-
select from LikeCache where post_id == post_id limit 1
23
-
} or { [] }
24
25
mut likes := 0
26
27
if cache.len != 1 {
28
println('calculating net likes for post: ${post_id}')
29
// calculate
30
-
db_likes := sql app.db {
31
-
select from Like where post_id == post_id
32
-
} or { [] }
33
-
34
for like in db_likes {
35
-
if like.is_like {
36
likes++
37
} else {
38
likes--
···
51
return likes
52
}
53
} else {
54
-
likes = cache.first().likes
55
}
56
57
return likes
···
1
module database
2
3
import entity { Like, LikeCache }
4
+
import util
5
6
// add_like adds a like to the database, returns true if this succeeds and false
7
// otherwise.
···
19
// get_net_likes_for_post returns the net likes of the given post.
20
pub fn (app &DatabaseAccess) get_net_likes_for_post(post_id int) int {
21
// check cache
22
+
cache := app.db.exec_param('SELECT likes FROM "LikeCache" WHERE post_id = $1 LIMIT 1', post_id.str()) or { [] }
23
24
mut likes := 0
25
26
if cache.len != 1 {
27
println('calculating net likes for post: ${post_id}')
28
// calculate
29
+
db_likes := app.db.exec_param('SELECT is_like FROM "Like" WHERE post_id = $1', post_id.str()) or { [] }
30
for like in db_likes {
31
+
if util.or_throw(like.vals[0]).bool() {
32
likes++
33
} else {
34
likes--
···
47
return likes
48
}
49
} else {
50
+
likes = util.or_throw(cache.first().vals[0]).int()
51
}
52
53
return likes
+1
-3
src/database/notification.v
+1
-3
src/database/notification.v
···
47
// get_notification_count gets the amount of notifications a user has, with a
48
// given limit.
49
pub fn (app &DatabaseAccess) get_notification_count(user_id int, limit int) int {
50
-
notifications := sql app.db {
51
-
select from Notification where user_id == user_id limit limit
52
-
} or { [] }
53
return notifications.len
54
}
55
···
47
// get_notification_count gets the amount of notifications a user has, with a
48
// given limit.
49
pub fn (app &DatabaseAccess) get_notification_count(user_id int, limit int) int {
50
+
notifications := app.db.exec_param2('SELECT id FROM "Notification" WHERE user_id = $1 LIMIT $2', user_id.str(), limit.str()) or { [] }
51
return notifications.len
52
}
53
+5
-5
src/database/post.v
+5
-5
src/database/post.v
···
1
module database
2
3
import time
4
import entity { Post, User, Like, LikeCache }
5
6
// add_post adds a new post to the database, returns true if this succeeded and
7
// false otherwise.
···
66
// get_popular_posts returns a list of the ten most liked posts.
67
// TODO: make this time-gated (i.e, top ten liked posts of the day)
68
pub fn (app &DatabaseAccess) get_popular_posts() []Post {
69
-
cached_likes := sql app.db {
70
-
select from LikeCache order by likes desc limit 10
71
-
} or { [] }
72
-
posts := cached_likes.map(fn [app] (it LikeCache) Post {
73
-
return app.get_post_by_id(it.post_id) or {
74
eprintln('cached like ${it} does not have a post related to it (from get_popular_posts)')
75
return Post{}
76
}
···
1
module database
2
3
import time
4
+
import db.pg
5
import entity { Post, User, Like, LikeCache }
6
+
import util
7
8
// add_post adds a new post to the database, returns true if this succeeded and
9
// false otherwise.
···
68
// get_popular_posts returns a list of the ten most liked posts.
69
// TODO: make this time-gated (i.e, top ten liked posts of the day)
70
pub fn (app &DatabaseAccess) get_popular_posts() []Post {
71
+
cached_likes := app.db.exec('SELECT post_id FROM "LikeCache" ORDER BY likes DESC LIMIT 10') or { [] }
72
+
posts := cached_likes.map(fn [app] (it pg.Row) Post {
73
+
return app.get_post_by_id(util.or_throw(it.vals[0]).int()) or {
74
eprintln('cached like ${it} does not have a post related to it (from get_popular_posts)')
75
return Post{}
76
}
+7
-6
src/database/saved_post.v
+7
-6
src/database/saved_post.v
···
1
module database
2
3
import entity { SavedPost, Post }
4
5
// get_saved_posts_for gets all SavedPost objects for a given user.
6
pub fn (app &DatabaseAccess) get_saved_posts_for(user_id int) []SavedPost {
···
13
// get_saved_posts_as_post_for gets all saved posts for a given user converted
14
// to Post objects.
15
pub fn (app &DatabaseAccess) get_saved_posts_as_post_for(user_id int) []Post {
16
-
saved_posts := sql app.db {
17
-
select from SavedPost where user_id == user_id && saved == true
18
-
} or { [] }
19
-
posts := saved_posts.map(fn [app] (it SavedPost) Post {
20
-
return app.get_post_by_id(it.post_id) or {
21
// if the post does not exist, we will remove it now
22
sql app.db {
23
-
delete from SavedPost where id == it.id
24
} or {
25
eprintln('get_saved_posts_as_post_for: failed to remove non-existent post from saved post: ${it}')
26
}
···
1
module database
2
3
+
import db.pg
4
import entity { SavedPost, Post }
5
+
import util
6
7
// get_saved_posts_for gets all SavedPost objects for a given user.
8
pub fn (app &DatabaseAccess) get_saved_posts_for(user_id int) []SavedPost {
···
15
// get_saved_posts_as_post_for gets all saved posts for a given user converted
16
// to Post objects.
17
pub fn (app &DatabaseAccess) get_saved_posts_as_post_for(user_id int) []Post {
18
+
saved_posts := app.db.exec_param('SELECT id, post_id FROM "SavedPost" WHERE user_id = $1 AND saved = TRUE', user_id.str()) or { [] }
19
+
posts := saved_posts.map(fn [app] (it pg.Row) Post {
20
+
return app.get_post_by_id(util.or_throw(it.vals[1]).int()) or {
21
// if the post does not exist, we will remove it now
22
+
id := util.or_throw(it.vals[0]).int()
23
sql app.db {
24
+
delete from SavedPost where id == id
25
} or {
26
eprintln('get_saved_posts_as_post_for: failed to remove non-existent post from saved post: ${it}')
27
}
+14
-20
src/database/user.v
+14
-20
src/database/user.v
···
1
module database
2
3
import entity { User, Notification, Like, LikeCache, Post }
4
5
// new_user creates a new user and returns their struct after creation.
6
pub fn (app &DatabaseAccess) new_user(user User) ?User {
···
134
135
// does_user_like_post returns true if a user likes the given post.
136
pub 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.
150
pub 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.
165
pub 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
}
···
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
···
1
module database
2
3
import entity { User, Notification, Like, LikeCache, Post }
4
+
import util
5
6
// new_user creates a new user and returns their struct after creation.
7
pub fn (app &DatabaseAccess) new_user(user User) ?User {
···
135
136
// does_user_like_post returns true if a user likes the given post.
137
pub fn (app &DatabaseAccess) does_user_like_post(user_id int, post_id int) bool {
138
+
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 { [] }
139
if likes.len > 1 {
140
// something is very wrong lol
141
+
eprintln('does_user_like_post: a user somehow got two or more likes on the same post (user: ${user_id}, post: ${post_id})')
142
} else if likes.len == 0 {
143
return false
144
}
145
+
return util.or_throw(likes.first().vals[1]).bool()
146
}
147
148
// does_user_dislike_post returns true if a user dislikes the given post.
149
pub fn (app &DatabaseAccess) does_user_dislike_post(user_id int, post_id int) bool {
150
+
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 { [] }
151
if likes.len > 1 {
152
// something is very wrong lol
153
+
eprintln('does_user_dislike_post: a user somehow got two or more likes on the same post (user: ${user_id}, post: ${post_id})')
154
} else if likes.len == 0 {
155
return false
156
}
157
+
return !util.or_throw(likes.first().vals[1]).bool()
158
}
159
160
// does_user_like_or_dislike_post returns true if a user likes *or* dislikes the
161
// given post.
162
pub fn (app &DatabaseAccess) does_user_like_or_dislike_post(user_id int, post_id int) bool {
163
+
likes := app.db.exec_param2('SELECT id 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_or_dislike_post: a user somehow got two or more likes on the same post (user: ${user_id}, post: ${post_id})')
167
}
168
return likes.len == 1
169
}
···
180
}
181
182
// delete posts and their likes
183
+
posts_from_this_user := app.db.exec_param('SELECT id FROM "Post" WHERE author_id = $1', user_id.str()) or { [] }
184
185
for post in posts_from_this_user {
186
+
id := util.or_throw(post.vals[0]).int()
187
sql app.db {
188
+
delete from Like where post_id == id
189
+
delete from LikeCache where post_id == id
190
} or {
191
+
eprintln('failed to delete like cache for post during user deletion: ${id}')
192
}
193
}
194