1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
|
package forge
import (
"net/http"
"time"
)
const followSchema = `
create table if not exists follows (
follower integer not null references users(id) on delete cascade,
followee integer not null references users(id) on delete cascade,
created integer not null,
primary key (follower, followee)
);
create index if not exists follows_followee on follows(followee, created);
`
func (s *Store) Follow(follower, followee int64, on bool) {
if on {
s.db.Exec(`insert or ignore into follows(follower, followee, created) values (?, ?, ?)`, follower, followee, time.Now().Unix())
} else {
s.db.Exec(`delete from follows where follower = ? and followee = ?`, follower, followee)
}
}
func (s *Store) Follows(follower, followee int64) bool {
var n int
s.db.QueryRow(`select count(*) from follows where follower = ? and followee = ?`, follower, followee).Scan(&n)
return n > 0
}
func (s *Store) FollowCounts(id int64) (followers, following int) {
s.db.QueryRow(`select
(select count(*) from follows f join users u on u.id = f.follower where f.followee = ?1 and u.banned = 0),
(select count(*) from follows f join users u on u.id = f.followee where f.follower = ?1 and u.banned = 0)`, id).Scan(&followers, &following)
return
}
func (s *Store) Followers(id int64) []User {
return s.userList(`select u.id, u.name, u.created from follows f join users u on u.id = f.follower where f.followee = ? and u.banned = 0 order by f.created desc`, id)
}
func (s *Store) Following(id int64) []User {
return s.userList(`select u.id, u.name, u.created from follows f join users u on u.id = f.followee where f.follower = ? and u.banned = 0 order by f.created desc`, id)
}
func (s *Server) follow(w http.ResponseWriter, r *http.Request, owner User) {
u := s.require(w, r)
if u == nil {
return
}
if u.ID != owner.ID && !s.store.IsOrg(u.ID) {
s.store.Follow(u.ID, owner.ID, !s.store.Follows(u.ID, owner.ID))
}
http.Redirect(w, r, "/~"+owner.Name, http.StatusSeeOther)
}
func (s *Server) follows(w http.ResponseWriter, r *http.Request, owner User, viewer *User, kind string) {
list := s.store.Followers(owner.ID)
if kind == "following" {
list = s.store.Following(owner.ID)
}
people := make([]userHit, 0, len(list))
for _, p := range list {
people = append(people, userHit{User: p, Profile: s.store.Profile(p.ID)})
}
followers, following := s.store.FollowCounts(owner.ID)
s.render(w, r, "follows", page{Title: "~" + owner.Name + " " + kind, User: viewer, Data: map[string]any{"Owner": owner, "Kind": kind, "People": people, "Followers": followers, "Following": following, "Org": s.store.IsOrg(owner.ID)}})
}
|