~gitpocket/gitpocket

4
main
mainfeed-discovery
gitpocket/forge/follow.go -rw-r--r--2.6 KiB ViewLogBlameView rawPermalink 9108144c05 feat(profile): follow organizations and change usernames with redirects 4 hours ago
 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)}})
}