Migrate to new follows storage
This commit is contained in:
parent
99f5ae1b4f
commit
803d303420
@ -46,11 +46,9 @@ func (item *AnimeListItem) Edit(ctx aero.Context, key string, value reflect.Valu
|
|||||||
|
|
||||||
// Broadcast event to all users so they can reload the activity page if needed.
|
// Broadcast event to all users so they can reload the activity page if needed.
|
||||||
for receiver := range StreamUsers() {
|
for receiver := range StreamUsers() {
|
||||||
receiverIsFollowing := Contains(receiver.Follows().Items, user.ID)
|
|
||||||
|
|
||||||
receiver.BroadcastEvent(&aero.Event{
|
receiver.BroadcastEvent(&aero.Event{
|
||||||
Name: "activity",
|
Name: "activity",
|
||||||
Data: receiverIsFollowing,
|
Data: receiver.IsFollowing(user.ID),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
19
arn/User.go
19
arn/User.go
@ -20,17 +20,10 @@ import (
|
|||||||
gravatar "github.com/ungerik/go-gravatar"
|
gravatar "github.com/ungerik/go-gravatar"
|
||||||
)
|
)
|
||||||
|
|
||||||
var setNickMutex sync.Mutex
|
var (
|
||||||
var setEmailMutex sync.Mutex
|
setNickMutex sync.Mutex
|
||||||
|
setEmailMutex sync.Mutex
|
||||||
// Register data lists.
|
)
|
||||||
func init() {
|
|
||||||
DataLists["genders"] = []*Option{
|
|
||||||
// &Option{"", "Prefer not to say"},
|
|
||||||
{"male", "Male"},
|
|
||||||
{"female", "Female"},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// UserID represents a user ID.
|
// UserID represents a user ID.
|
||||||
type UserID = ID
|
type UserID = ID
|
||||||
@ -62,6 +55,7 @@ type User struct {
|
|||||||
Browser UserBrowser `json:"browser" private:"true"`
|
Browser UserBrowser `json:"browser" private:"true"`
|
||||||
OS UserOS `json:"os" private:"true"`
|
OS UserOS `json:"os" private:"true"`
|
||||||
Location *Location `json:"location" private:"true"`
|
Location *Location `json:"location" private:"true"`
|
||||||
|
FollowIDs []UserID `json:"follows"`
|
||||||
|
|
||||||
hasPosts
|
hasPosts
|
||||||
|
|
||||||
@ -124,9 +118,6 @@ func RegisterUser(user *User) {
|
|||||||
Items: []*PushSubscription{},
|
Items: []*PushSubscription{},
|
||||||
})
|
})
|
||||||
|
|
||||||
// Add empty follow list
|
|
||||||
NewUserFollows(user.ID).Save()
|
|
||||||
|
|
||||||
// Add empty notifications list
|
// Add empty notifications list
|
||||||
NewUserNotifications(user.ID).Save()
|
NewUserNotifications(user.ID).Save()
|
||||||
|
|
||||||
|
21
arn/User.init.go
Normal file
21
arn/User.init.go
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
package arn
|
||||||
|
|
||||||
|
import "github.com/aerogo/api"
|
||||||
|
|
||||||
|
// Register data lists.
|
||||||
|
func init() {
|
||||||
|
DataLists["genders"] = []*Option{
|
||||||
|
// &Option{"", "Prefer not to say"},
|
||||||
|
{"male", "Male"},
|
||||||
|
{"female", "Female"},
|
||||||
|
}
|
||||||
|
|
||||||
|
// Actions
|
||||||
|
API.RegisterActions("User", []*api.Action{
|
||||||
|
// Add follow
|
||||||
|
FollowAction(),
|
||||||
|
|
||||||
|
// Remove follow
|
||||||
|
UnfollowAction(),
|
||||||
|
})
|
||||||
|
}
|
@ -1,8 +1,6 @@
|
|||||||
package arn
|
package arn
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
|
||||||
|
|
||||||
"github.com/aerogo/nano"
|
"github.com/aerogo/nano"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -12,130 +10,6 @@ type UserFollows struct {
|
|||||||
Items []string `json:"items"`
|
Items []string `json:"items"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewUserFollows creates a new UserFollows list.
|
|
||||||
func NewUserFollows(userID UserID) *UserFollows {
|
|
||||||
return &UserFollows{
|
|
||||||
UserID: userID,
|
|
||||||
Items: []string{},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add adds an user to the list if it hasn't been added yet.
|
|
||||||
func (list *UserFollows) Add(userID UserID) error {
|
|
||||||
if userID == list.UserID {
|
|
||||||
return errors.New("You can't follow yourself")
|
|
||||||
}
|
|
||||||
|
|
||||||
if list.Contains(userID) {
|
|
||||||
return errors.New("User " + userID + " has already been added")
|
|
||||||
}
|
|
||||||
|
|
||||||
list.Items = append(list.Items, userID)
|
|
||||||
|
|
||||||
// Send notification
|
|
||||||
user, err := GetUser(userID)
|
|
||||||
|
|
||||||
if err == nil {
|
|
||||||
if !user.Settings().Notification.NewFollowers {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
follower, err := GetUser(list.UserID)
|
|
||||||
|
|
||||||
if err == nil {
|
|
||||||
user.SendNotification(&PushNotification{
|
|
||||||
Title: "You have a new follower!",
|
|
||||||
Message: follower.Nick + " started following you.",
|
|
||||||
Icon: "https:" + follower.AvatarLink("large"),
|
|
||||||
Link: "https://notify.moe" + follower.Link(),
|
|
||||||
Type: NotificationTypeFollow,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Remove removes the user ID from the list.
|
|
||||||
func (list *UserFollows) Remove(userID UserID) bool {
|
|
||||||
for index, item := range list.Items {
|
|
||||||
if item == userID {
|
|
||||||
list.Items = append(list.Items[:index], list.Items[index+1:]...)
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
// Contains checks if the list contains the user ID already.
|
|
||||||
func (list *UserFollows) Contains(userID UserID) bool {
|
|
||||||
for _, item := range list.Items {
|
|
||||||
if item == userID {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
// Users returns a slice of all the users you are following.
|
|
||||||
func (list *UserFollows) Users() []*User {
|
|
||||||
followsObj := DB.GetMany("User", list.Items)
|
|
||||||
follows := make([]*User, len(followsObj))
|
|
||||||
|
|
||||||
for i, obj := range followsObj {
|
|
||||||
follows[i] = obj.(*User)
|
|
||||||
}
|
|
||||||
|
|
||||||
return follows
|
|
||||||
}
|
|
||||||
|
|
||||||
// UsersWhoFollowBack returns a slice of all the users you are following that also follow you.
|
|
||||||
func (list *UserFollows) UsersWhoFollowBack() []*User {
|
|
||||||
followsObj := DB.GetMany("User", list.Items)
|
|
||||||
friends := make([]*User, 0, len(followsObj))
|
|
||||||
|
|
||||||
for _, obj := range followsObj {
|
|
||||||
friend := obj.(*User)
|
|
||||||
|
|
||||||
if Contains(friend.Follows().Items, list.UserID) {
|
|
||||||
friends = append(friends, friend)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return friends
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetID returns the ID.
|
|
||||||
func (list *UserFollows) GetID() string {
|
|
||||||
return list.UserID
|
|
||||||
}
|
|
||||||
|
|
||||||
// UserFollowerCountMap returns a map of user ID keys and their corresping number of followers as the value.
|
|
||||||
func UserFollowerCountMap() map[string]int {
|
|
||||||
followCount := map[string]int{}
|
|
||||||
|
|
||||||
for list := range StreamUserFollows() {
|
|
||||||
for _, followUserID := range list.Items {
|
|
||||||
followCount[followUserID]++
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return followCount
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetUserFollows ...
|
|
||||||
func GetUserFollows(id UserID) (*UserFollows, error) {
|
|
||||||
obj, err := DB.Get("UserFollows", id)
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return obj.(*UserFollows), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// StreamUserFollows returns a stream of all user follows.
|
// StreamUserFollows returns a stream of all user follows.
|
||||||
func StreamUserFollows() <-chan *UserFollows {
|
func StreamUserFollows() <-chan *UserFollows {
|
||||||
channel := make(chan *UserFollows, nano.ChannelBufferSize)
|
channel := make(chan *UserFollows, nano.ChannelBufferSize)
|
||||||
@ -150,14 +24,3 @@ func StreamUserFollows() <-chan *UserFollows {
|
|||||||
|
|
||||||
return channel
|
return channel
|
||||||
}
|
}
|
||||||
|
|
||||||
// AllUserFollows returns a slice of all user follows.
|
|
||||||
func AllUserFollows() ([]*UserFollows, error) {
|
|
||||||
all := make([]*UserFollows, 0, DB.Collection("UserFollows").Count())
|
|
||||||
|
|
||||||
for obj := range StreamUserFollows() {
|
|
||||||
all = append(all, obj)
|
|
||||||
}
|
|
||||||
|
|
||||||
return all, nil
|
|
||||||
}
|
|
||||||
|
180
arn/UserFollows2.go
Normal file
180
arn/UserFollows2.go
Normal file
@ -0,0 +1,180 @@
|
|||||||
|
package arn
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
|
||||||
|
"github.com/aerogo/aero"
|
||||||
|
"github.com/aerogo/api"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Add adds an user to the user if it hasn't been added yet.
|
||||||
|
func (user *User) Follow(followUserID UserID) error {
|
||||||
|
if followUserID == user.ID {
|
||||||
|
return errors.New("You can't follow yourself")
|
||||||
|
}
|
||||||
|
|
||||||
|
if user.IsFollowing(followUserID) {
|
||||||
|
return errors.New("User " + followUserID + " has already been added")
|
||||||
|
}
|
||||||
|
|
||||||
|
user.FollowIDs = append(user.FollowIDs, followUserID)
|
||||||
|
|
||||||
|
// Send notification
|
||||||
|
user, err := GetUser(followUserID)
|
||||||
|
|
||||||
|
if err == nil {
|
||||||
|
if !user.Settings().Notification.NewFollowers {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
follower, err := GetUser(user.ID)
|
||||||
|
|
||||||
|
if err == nil {
|
||||||
|
user.SendNotification(&PushNotification{
|
||||||
|
Title: "You have a new follower!",
|
||||||
|
Message: follower.Nick + " started following you.",
|
||||||
|
Icon: "https:" + follower.AvatarLink("large"),
|
||||||
|
Link: "https://notify.moe" + follower.Link(),
|
||||||
|
Type: NotificationTypeFollow,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Unfollow removes the user ID from the follow list.
|
||||||
|
func (user *User) Unfollow(userID UserID) bool {
|
||||||
|
for index, item := range user.FollowIDs {
|
||||||
|
if item == userID {
|
||||||
|
user.FollowIDs = append(user.FollowIDs[:index], user.FollowIDs[index+1:]...)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsFollowing checks if the object follows the user ID.
|
||||||
|
func (user *User) IsFollowing(userID UserID) bool {
|
||||||
|
for _, item := range user.FollowIDs {
|
||||||
|
if item == userID {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// Follows returns a slice of all the users you are following.
|
||||||
|
func (user *User) Follows() []*User {
|
||||||
|
followsObj := DB.GetMany("User", user.FollowIDs)
|
||||||
|
follows := make([]*User, len(followsObj))
|
||||||
|
|
||||||
|
for i, user := range followsObj {
|
||||||
|
follows[i] = user.(*User)
|
||||||
|
}
|
||||||
|
|
||||||
|
return follows
|
||||||
|
}
|
||||||
|
|
||||||
|
// Friends returns a slice of all the users you are following that also follow you.
|
||||||
|
func (user *User) Friends() []*User {
|
||||||
|
followsObj := DB.GetMany("User", user.FollowIDs)
|
||||||
|
friends := make([]*User, 0, len(followsObj))
|
||||||
|
|
||||||
|
for _, friendObj := range followsObj {
|
||||||
|
friend := friendObj.(*User)
|
||||||
|
|
||||||
|
if friend.IsFollowing(user.ID) {
|
||||||
|
friends = append(friends, friend)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return friends
|
||||||
|
}
|
||||||
|
|
||||||
|
// Followers returns the users who follow the user.
|
||||||
|
func (user *User) Followers() []*User {
|
||||||
|
var followerIDs []string
|
||||||
|
|
||||||
|
for follower := range StreamUsers() {
|
||||||
|
if follower.IsFollowing(user.ID) {
|
||||||
|
followerIDs = append(followerIDs, follower.ID)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
usersObj := DB.GetMany("User", followerIDs)
|
||||||
|
users := make([]*User, len(usersObj))
|
||||||
|
|
||||||
|
for i, obj := range usersObj {
|
||||||
|
users[i] = obj.(*User)
|
||||||
|
}
|
||||||
|
|
||||||
|
return users
|
||||||
|
}
|
||||||
|
|
||||||
|
// FollowersCount returns how many followers the user has.
|
||||||
|
func (user *User) FollowersCount() int {
|
||||||
|
count := 0
|
||||||
|
|
||||||
|
for follower := range StreamUsers() {
|
||||||
|
if follower.IsFollowing(user.ID) {
|
||||||
|
count++
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return count
|
||||||
|
}
|
||||||
|
|
||||||
|
// UserFollowerCountMap returns a map of user ID keys and their corresping number of followers as the value.
|
||||||
|
func UserFollowerCountMap() map[string]int {
|
||||||
|
followCount := map[string]int{}
|
||||||
|
|
||||||
|
for user := range StreamUsers() {
|
||||||
|
for _, followUserID := range user.FollowIDs {
|
||||||
|
followCount[followUserID]++
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return followCount
|
||||||
|
}
|
||||||
|
|
||||||
|
// FollowAction returns an API action that adds a user ID to the follow list.
|
||||||
|
func FollowAction() *api.Action {
|
||||||
|
return &api.Action{
|
||||||
|
Name: "follow",
|
||||||
|
Route: "/follow/:follow-id",
|
||||||
|
Run: func(obj interface{}, ctx aero.Context) error {
|
||||||
|
user := obj.(*User)
|
||||||
|
followID := ctx.Get("follow-id")
|
||||||
|
err := user.Follow(followID)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
user.Save()
|
||||||
|
return nil
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// UnfollowAction returns an API action that removes a user ID from the follow list.
|
||||||
|
func UnfollowAction() *api.Action {
|
||||||
|
return &api.Action{
|
||||||
|
Name: "unfollow",
|
||||||
|
Route: "/unfollow/:unfollow-id",
|
||||||
|
Run: func(obj interface{}, ctx aero.Context) error {
|
||||||
|
user := obj.(*User)
|
||||||
|
unfollowID := ctx.Get("unfollow-id")
|
||||||
|
|
||||||
|
if !user.Unfollow(unfollowID) {
|
||||||
|
return errors.New("This item does not exist in the list")
|
||||||
|
}
|
||||||
|
|
||||||
|
user.Save()
|
||||||
|
return nil
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
@ -1,34 +0,0 @@
|
|||||||
package arn
|
|
||||||
|
|
||||||
import (
|
|
||||||
"github.com/aerogo/aero"
|
|
||||||
"github.com/aerogo/api"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Force interface implementations
|
|
||||||
var (
|
|
||||||
_ Identifiable = (*UserFollows)(nil)
|
|
||||||
_ IDCollection = (*UserFollows)(nil)
|
|
||||||
_ api.Editable = (*UserFollows)(nil)
|
|
||||||
)
|
|
||||||
|
|
||||||
// Actions
|
|
||||||
func init() {
|
|
||||||
API.RegisterActions("UserFollows", []*api.Action{
|
|
||||||
// Add follow
|
|
||||||
AddAction(),
|
|
||||||
|
|
||||||
// Remove follow
|
|
||||||
RemoveAction(),
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// Authorize returns an error if the given API request is not authorized.
|
|
||||||
func (list *UserFollows) Authorize(ctx aero.Context, action string) error {
|
|
||||||
return AuthorizeIfLoggedInAndOwnData(ctx, "id")
|
|
||||||
}
|
|
||||||
|
|
||||||
// Save saves the follow list in the database.
|
|
||||||
func (list *UserFollows) Save() {
|
|
||||||
DB.Set("UserFollows", list.UserID, list)
|
|
||||||
}
|
|
@ -42,51 +42,12 @@ func (user *User) Inventory() *Inventory {
|
|||||||
return inventory
|
return inventory
|
||||||
}
|
}
|
||||||
|
|
||||||
// Follows returns the list of user follows.
|
|
||||||
func (user *User) Follows() *UserFollows {
|
|
||||||
follows, _ := GetUserFollows(user.ID)
|
|
||||||
return follows
|
|
||||||
}
|
|
||||||
|
|
||||||
// Notifications returns the list of user notifications.
|
// Notifications returns the list of user notifications.
|
||||||
func (user *User) Notifications() *UserNotifications {
|
func (user *User) Notifications() *UserNotifications {
|
||||||
notifications, _ := GetUserNotifications(user.ID)
|
notifications, _ := GetUserNotifications(user.ID)
|
||||||
return notifications
|
return notifications
|
||||||
}
|
}
|
||||||
|
|
||||||
// Followers ...
|
|
||||||
func (user *User) Followers() []*User {
|
|
||||||
var followerIDs []string
|
|
||||||
|
|
||||||
for list := range StreamUserFollows() {
|
|
||||||
if list.Contains(user.ID) {
|
|
||||||
followerIDs = append(followerIDs, list.UserID)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
usersObj := DB.GetMany("User", followerIDs)
|
|
||||||
users := make([]*User, len(usersObj))
|
|
||||||
|
|
||||||
for i, obj := range usersObj {
|
|
||||||
users[i] = obj.(*User)
|
|
||||||
}
|
|
||||||
|
|
||||||
return users
|
|
||||||
}
|
|
||||||
|
|
||||||
// FollowersCount ...
|
|
||||||
func (user *User) FollowersCount() int {
|
|
||||||
count := 0
|
|
||||||
|
|
||||||
for list := range StreamUserFollows() {
|
|
||||||
if list.Contains(user.ID) {
|
|
||||||
count++
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return count
|
|
||||||
}
|
|
||||||
|
|
||||||
// DraftIndex ...
|
// DraftIndex ...
|
||||||
func (user *User) DraftIndex() *DraftIndex {
|
func (user *User) DraftIndex() *DraftIndex {
|
||||||
draftIndex, _ := GetDraftIndex(user.ID)
|
draftIndex, _ := GetDraftIndex(user.ID)
|
||||||
|
@ -21,14 +21,8 @@ func Followed(ctx aero.Context) error {
|
|||||||
|
|
||||||
// fetchActivities filters the activities by the given filters.
|
// fetchActivities filters the activities by the given filters.
|
||||||
func fetchActivities(user *arn.User, followedOnly bool) []arn.Activity {
|
func fetchActivities(user *arn.User, followedOnly bool) []arn.Activity {
|
||||||
var followedUserIDs []string
|
|
||||||
|
|
||||||
if followedOnly && user != nil {
|
|
||||||
followedUserIDs = user.Follows().Items
|
|
||||||
}
|
|
||||||
|
|
||||||
activities := arn.FilterActivityCreates(func(activity arn.Activity) bool {
|
activities := arn.FilterActivityCreates(func(activity arn.Activity) bool {
|
||||||
if followedOnly && !arn.Contains(followedUserIDs, activity.GetCreatedBy()) {
|
if followedOnly && user != nil && !user.IsFollowing(activity.GetCreatedBy()) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -47,7 +47,7 @@ func Get(ctx aero.Context) error {
|
|||||||
episodeToFriends := map[int][]*arn.User{}
|
episodeToFriends := map[int][]*arn.User{}
|
||||||
|
|
||||||
if user != nil {
|
if user != nil {
|
||||||
friends = user.Follows().Users()
|
friends = user.Follows()
|
||||||
deleted := 0
|
deleted := 0
|
||||||
|
|
||||||
if animeListItem != nil {
|
if animeListItem != nil {
|
||||||
|
@ -23,7 +23,7 @@ func Episodes(ctx aero.Context) error {
|
|||||||
episodeToFriends[ownListItem.Episodes] = append(episodeToFriends[ownListItem.Episodes], user)
|
episodeToFriends[ownListItem.Episodes] = append(episodeToFriends[ownListItem.Episodes], user)
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, friend := range user.Follows().Users() {
|
for _, friend := range user.Follows() {
|
||||||
friendAnimeList := friend.AnimeList()
|
friendAnimeList := friend.AnimeList()
|
||||||
friendAnimeListItem := friendAnimeList.Find(anime.ID)
|
friendAnimeListItem := friendAnimeList.Find(anime.ID)
|
||||||
|
|
||||||
|
@ -126,7 +126,7 @@ func Get(ctx aero.Context) error {
|
|||||||
var friends []*arn.User
|
var friends []*arn.User
|
||||||
|
|
||||||
if user != nil {
|
if user != nil {
|
||||||
friendIDs := utils.Intersection(character.Likes, user.Follows().Items)
|
friendIDs := utils.Intersection(character.Likes, user.FollowIDs)
|
||||||
friendObjects := arn.DB.GetMany("User", friendIDs)
|
friendObjects := arn.DB.GetMany("User", friendIDs)
|
||||||
|
|
||||||
for _, obj := range friendObjects {
|
for _, obj := range friendObjects {
|
||||||
|
@ -120,7 +120,7 @@ func Profile(ctx aero.Context, viewUser *arn.User) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Friends
|
// Friends
|
||||||
friends := viewUser.Follows().UsersWhoFollowBack()
|
friends := viewUser.Friends()
|
||||||
|
|
||||||
arn.SortUsersFollowers(friends)
|
arn.SortUsersFollowers(friends)
|
||||||
|
|
||||||
|
@ -141,12 +141,12 @@ component ProfileHead(viewUser *arn.User, animeList *arn.AnimeList, user *arn.Us
|
|||||||
|
|
||||||
.profile-actions
|
.profile-actions
|
||||||
if user != nil && user.ID != viewUser.ID
|
if user != nil && user.ID != viewUser.ID
|
||||||
if !user.Follows().Contains(viewUser.ID)
|
if !user.IsFollowing(viewUser.ID)
|
||||||
button.profile-action.action.mountable.never-unmount(data-action="followUser", data-trigger="click", data-api="/api/userfollows/" + user.ID + "/add/" + viewUser.ID)
|
button.profile-action.action.mountable.never-unmount(data-action="followUser", data-trigger="click", data-api="/api/user/" + user.ID + "/follow/" + viewUser.ID)
|
||||||
Icon("user-plus")
|
Icon("user-plus")
|
||||||
span Follow
|
span Follow
|
||||||
else
|
else
|
||||||
button.profile-action.action.mountable.never-unmount(data-action="unfollowUser", data-trigger="click", data-api="/api/userfollows/" + user.ID + "/remove/" + viewUser.ID)
|
button.profile-action.action.mountable.never-unmount(data-action="unfollowUser", data-trigger="click", data-api="/api/user/" + user.ID + "/unfollow/" + viewUser.ID)
|
||||||
Icon("user-times")
|
Icon("user-times")
|
||||||
span Unfollow
|
span Unfollow
|
||||||
|
|
||||||
|
22
patches/user-copy-follows/user-copy-follow.go
Normal file
22
patches/user-copy-follows/user-copy-follow.go
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/akyoto/color"
|
||||||
|
"github.com/animenotifier/notify.moe/arn"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
defer arn.Node.Close()
|
||||||
|
|
||||||
|
for follows := range arn.StreamUserFollows() {
|
||||||
|
user, err := arn.GetUser(follows.UserID)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
color.Red(err.Error())
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
user.FollowIDs = follows.Items
|
||||||
|
user.Save()
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user