core

package
v0.0.0-...-db3ccfa Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Apr 25, 2024 License: AGPL-3.0 Imports: 29 Imported by: 0

Documentation

Overview

Package core implements the core functionality of the project. The package server builds on top of this package to create an HTTP REST API.

Index

Constants

View Source
const (
	CommunitiesSortNew     = CommunitiesSort("new")
	CommunitiesSortOld     = CommunitiesSort("old")
	CommunitiesSortSize    = CommunitiesSort("size")
	CommunitiesSortNameAsc = CommunitiesSort("name_asc")
	CommunitiesSortNameDsc = CommunitiesSort("name_dsc")
	CommunitiesSortDefault = CommunitiesSortNameAsc
)
View Source
const (
	CommunitiesSetAll        = "all"
	CommunitiesSetDefault    = "default"
	CommunitiesSetSubscribed = "subscribed"
)
View Source
const (
	FeedSortHot = FeedSort(iota)
	FeedSortLatest
	FeedSortActivity
	FeedSortTopDay
	FeedSortTopWeek
	FeedSortTopMonth
	FeedSortTopYear
	FeedSortTopAll
)
View Source
const (
	FeedTypeAll = FeedType(iota)
	FeedTypeSubscriptions
)
View Source
const (
	MuteTypeUser      = MuteType("user")
	MuteTypeCommunity = MuteType("community")
)
View Source
const (
	NotificationTypeNewComment   = NotificationType("new_comment")
	NotificationTypeCommentReply = NotificationType("comment_reply")
	NotificationTypeUpvote       = NotificationType("new_votes") // TODO: change string
	NotificationTypeDeletePost   = NotificationType("deleted_post")
	NotificationTypeModAdd       = NotificationType("mod_add")
	NotificationTypeNewBadge     = NotificationType("new_badge")
)
View Source
const (
	PostTypeText = PostType(iota)
	PostTypeImage
	PostTypeLink
)

These are all the valid PostTypes.

View Source
const (
	ReportTypeAll = ReportType(iota - 1) // pseudo type
	ReportTypePost
	ReportTypeComment
)
View Source
const (
	UserGroupNaN = UserGroup(iota) // Psuedo user group.
	UserGroupNormal
	UserGroupAdmins
	UserGroupMods
)
View Source
const MaxNotificationsPerUser = 200
View Source
const MaxPinnedPosts = 2

Variables

View Source
var (
	// ErrWrongPassword is returned by MatchLoginCredentials if username and password
	// do not match.
	ErrWrongPassword = &httperr.Error{HTTPStatus: http.StatusUnauthorized, Code: "wrong-password", Message: "Username and password do not match."}

	ErrUserDeleted = httperr.NewForbidden("user-deleted", "Cannot continue because the user is deleted.")
)
View Source
var (
	ErrInvalidFeedCursor = httperr.NewBadRequest("invalid_cursor", "Invalid feed pagination cursor.")
	ErrInvalidFeedSort   = httperr.NewBadRequest("invalid-sort", "Invalid feed sort.")
)

Functions

func AddAllUsersToCommunity

func AddAllUsersToCommunity(ctx context.Context, db *sql.DB, community string) error

AddAllUsersToCommunity adds all users to community. Do not use this function outside of a CLI environment.

func CalcGhostUserID

func CalcGhostUserID(user uid.ID, unique string) string

func ClearMutes

func ClearMutes(ctx context.Context, db *sql.DB, user uid.ID, t MuteType) (err error)

ClearMutes clears all mutes of user if t is empty, otherwise it clears either the community or the user mutes.

func CountAllUsers

func CountAllUsers(ctx context.Context, db *sql.DB) (n int, err error)

CountAllUsers return the no of users of the site, including deleted users.

func CreateAnalyticsEvent

func CreateAnalyticsEvent(ctx context.Context, db *sql.DB, name string, uniqueKey string, payload string) error

CreateAnalyticsEvent adds a record to the analytics table. If uniqueKey is empty, it is ignored.

func CreateCommentReplyNotification

func CreateCommentReplyNotification(ctx context.Context, db *sql.DB, user uid.ID, parent, comment uid.ID, author string, post *Post) error

CreateCommentReplyNotification creates a notification of type comment_reply. If an identical notification exists in the last 10 items, it is deleted.

func CreateCommunityRequest

func CreateCommunityRequest(ctx context.Context, db *sql.DB, byUser, name, note string) error

func CreateGhostUser

func CreateGhostUser(db *sql.DB) (bool, error)

CreateGhostUser creates the ghost user, if the ghost user isn't already created. The ghost user is the user with the username ghost that takes, so to speak, the place of all deleted users.

The returned bool indicates whether the call to this function created the ghost user (if the ghost user was already created, it will be false).

func CreateNewBadgeNotification

func CreateNewBadgeNotification(ctx context.Context, db *sql.DB, user uid.ID, badgeType string) error

func CreateNewCommentNotification

func CreateNewCommentNotification(ctx context.Context, db *sql.DB, post *Post, comment uid.ID, author string) error

CreateNewCommentNotification creates a notification of type new_comment. If an identical notification exists in the last 10 items, it is deleted.

func CreateNewModAddNotification

func CreateNewModAddNotification(ctx context.Context, db *sql.DB, user uid.ID, community, addedBy string) error

func CreateNewVotesNotification

func CreateNewVotesNotification(ctx context.Context, db *sql.DB, user uid.ID, community string, isPost bool, targetID uid.ID) error

CreateNewVotesNotification creates a notification of type "new_votes".

func CreateNotification

func CreateNotification(ctx context.Context, db *sql.DB, user uid.ID, Type NotificationType, notif notification) error

CreateNotification adds a new notification to user's notifications stack.

func CreatePostDeletedNotification

func CreatePostDeletedNotification(ctx context.Context, db *sql.DB, user uid.ID, deletedAs UserGroup, isPost bool, targetID uid.ID) error

CreatePostDeletedNotification creates a notification of type "deleted_post". In actuall fact it may be a post or a comment.

func DeleteCommunityRequest

func DeleteCommunityRequest(ctx context.Context, db *sql.DB, id int) error

func DeleteWebPushSubscription

func DeleteWebPushSubscription(ctx context.Context, db *sql.DB, sessionID string) error

DeleteWebPushSuscription deletes the Push Subscription object associated with sessionID (if there is one).

Make sure to call this function before logging out a user.

func EnablePushNotifications

func EnablePushNotifications(keys *VAPIDKeys, email string)

EnablePushNotifications enables sending web push notifications. The email address is the email of the webmaster.

func HashPassword

func HashPassword(password []byte) ([]byte, error)

HashPassword returns the hashed password if the password is acceptable, otherwise it returns an httperr.Error.

func IsAdmin

func IsAdmin(db *sql.DB, user *uid.ID) (bool, error)

IsAdmin reports whether user is an admin. User can be nil, in which case this function returns false.

func IsPostLocked

func IsPostLocked(ctx context.Context, db *sql.DB, post uid.ID) (bool, error)

IsPostLocked checks if post is locked.

func IsUserBannedFromCommunity

func IsUserBannedFromCommunity(ctx context.Context, db *sql.DB, community, user uid.ID) (bool, error)

IsUserBannedFromCommunity checks if user is banned from community. If user is banned and the ban is expired he is unbanned.

func IsUsernameValid

func IsUsernameValid(name string) error

IsUsernameValid returns nil if name only consists of valid (0-9, A-Z, a-z, and _) characters and if it's of acceptable length.

func MakeUserMod

func MakeUserMod(ctx context.Context, db *sql.DB, c *Community, viewer uid.ID, user uid.ID, isMod bool) error

MakeUserMod makes user a moderator of c. If user wasn't already a member of c, he's made into one. Calling the function with isMod = false removes user as a moderator of c.

Viewer must be an admin or a higher up mod of c.

func MakeUserModCLI

func MakeUserModCLI(db *sql.DB, c *Community, user uid.ID, isMod bool) error

MakeUserModCLI adds or removes user as a mod of c. Do not use this function in an API.

func MuteCommunity

func MuteCommunity(ctx context.Context, db *sql.DB, user, community uid.ID) error

func MuteUser

func MuteUser(ctx context.Context, db *sql.DB, user, mutedUser uid.ID) error

func NewBadgeType

func NewBadgeType(db *sql.DB, name string) error

NewBadgeType creates a new type of user badge. Calling this function more than once with the same name will not result in an error.

func NextPointsIDCursor

func NextPointsIDCursor(text string) (p int, id *uid.ID, err error)

func NotificationsCount

func NotificationsCount(ctx context.Context, db *sql.DB, user uid.ID) (n int, err error)

NotificationsCount returns the number of notifications of user.

func PostHotness

func PostHotness(upvotes, downvotes int, date time.Time) int

PostHotness calculates the hotness score of a post.

func PurgePostsFromTempTables

func PurgePostsFromTempTables(ctx context.Context, db *sql.DB) error

PurgePostsFromTempTables removes posts from posts_today, posts_week, etc tables. Call this function periodically.

func RemoveAllReportsOfComment

func RemoveAllReportsOfComment(ctx context.Context, db *sql.DB, comment uid.ID) error

func RemoveAllReportsOfCommunity

func RemoveAllReportsOfCommunity(ctx context.Context, db *sql.DB, community uid.ID) error

func RemoveAllReportsOfPost

func RemoveAllReportsOfPost(ctx context.Context, db *sql.DB, post uid.ID) error

func RemoveTempImages

func RemoveTempImages(ctx context.Context, db *sql.DB) (int, error)

RemoveTempImages removes all temp images older than 12 hours and returns how many were removed.

func SavePostImage

func SavePostImage(ctx context.Context, db *sql.DB, authorID uid.ID, image []byte) (*images.ImageRecord, error)

func SaveWebPushSubscription

func SaveWebPushSubscription(ctx context.Context, db *sql.DB, sessionID string, user uid.ID, s webpush.Subscription) error

SaveWebPushSubscription adds an entry into web_push_notifications table. If there's a collision (a duplicate for sessionID), it updates the matching row. It is safe to call this function repeatedly with the same arguments.

func SendPushNotification

func SendPushNotification(ctx context.Context, db *sql.DB, user uid.ID, payload []byte, options *webpush.Options) error

SendPushNotification sends the Web Push notification in payload to all sessions of user (that has web notifications enabled).

func Unmute

func Unmute(ctx context.Context, db *sql.DB, user uid.ID, id string) error

func UnmuteCommunity

func UnmuteCommunity(ctx context.Context, db *sql.DB, user, community uid.ID) error

func UnmuteUser

func UnmuteUser(ctx context.Context, db *sql.DB, user, mutedUser uid.ID) error

func UpdateAllPostsHotness

func UpdateAllPostsHotness(ctx context.Context, db *sql.DB) error

UpdateAllPostsHotness applies the PostHotness function to every row in the posts table.

func UserDeleted

func UserDeleted(db *sql.DB, user uid.ID) (bool, error)

func UserMod

func UserMod(ctx context.Context, db *sql.DB, community, user uid.ID) (bool, error)

UserMod checks if user is a moderator of community.

func UserModOrAdmin

func UserModOrAdmin(ctx context.Context, db *sql.DB, community, user uid.ID) (bool, error)

UserModOrAdmin reports whether user is a moderator of community or if user is an admin.

func UserSeen

func UserSeen(ctx context.Context, db *sql.DB, user uid.ID, userIP string) error

UserSeen updates user's LastSeen to current time. It also updates the IP address of the user.

Types

type AnalyticsEvent

type AnalyticsEvent struct {
	ID        int
	Name      string
	UniqueKey []byte
	Payload   string
	CreatedAt time.Time
}

AnalyticsEven represents a record in the analytics table.

type Badge

type Badge struct {
	ID        int       `json:"id"`
	Type      int       `json:"-"`
	TypeName  string    `json:"type"`
	UserID    uid.ID    `json:"-"`
	CreatedAt time.Time `json:"-"`
}

A Badge corresponds to a row in the user_badges table.

type Badges

type Badges []*Badge

type Comment

type Comment struct {
	ID               uid.ID        `json:"id"`
	PostID           uid.ID        `json:"postId"`
	PostPublicID     string        `json:"postPublicId"`
	CommunityID      uid.ID        `json:"communityId"`
	CommunityName    string        `json:"communityName"`
	AuthorID         uid.ID        `json:"userId,omitempty"`
	AuthorUsername   string        `json:"username"`
	AuthorGhostID    string        `json:"userGhostId,omitempty"`
	PostedAs         UserGroup     `json:"userGroup"`
	AuthorDeleted    bool          `json:"userDeleted"`
	ParentID         uid.NullID    `json:"parentId"`
	Depth            int           `json:"depth"`
	NumReplies       int           `json:"noReplies"`
	NumRepliesDirect int           `json:"noRepliesDirect"`
	Ancestors        []uid.ID      `json:"ancestors"` // From root to parent.
	Body             string        `json:"body"`
	Upvotes          int           `json:"upvotes"`
	Downvotes        int           `json:"downvotes"`
	Points           int           `json:"-"`
	CreatedAt        time.Time     `json:"createdAt"`
	EditedAt         msql.NullTime `json:"editedAt"`

	// If the comment is deleted and the content of the comment (body, author,
	// etc) exists in the DB, and if ContentStripped is true, then those values
	// are stripped to default values in this struct.
	//
	// The JSON value is found only if the comment is deleted.
	ContentStripped *bool `json:"contentStripped,omitempty"`

	Deleted   bool          `json:"deleted"`
	DeletedAt msql.NullTime `json:"deletedAt"`
	DeletedBy uid.NullID    `json:"-"`
	DeletedAs UserGroup     `json:"deletedAs,omitempty"`

	Author *User `json:"author,omitempty"`

	// Reports whether the author of this comment is muted by the viewer.
	IsAuthorMuted bool `json:"isAuthorMuted,omitempty"`

	ViewerVoted   msql.NullBool `json:"userVoted"`
	ViewerVotedUp msql.NullBool `json:"userVotedUp"`

	PostTitle     string    `json:"postTitle,omitempty"`
	PostDeleted   bool      `json:"postDeleted"`
	PostDeletedAs UserGroup `json:"postDeletedAs,omitempty"`
	// contains filtered or unexported fields
}

Comment is a comment of a post.

func GetComment

func GetComment(ctx context.Context, db *sql.DB, id uid.ID, viewer *uid.ID) (*Comment, error)

Get comment returns a comment. If viewer is nil, viewer related fields of the comment (like Comment.ViewerVoted) will be nil.

func (*Comment) ChangeUserGroup

func (c *Comment) ChangeUserGroup(ctx context.Context, author uid.ID, g UserGroup) error

ChangeUserGroup changes the capacity in which the comment's author added the post.

func (*Comment) ChangeVote

func (c *Comment) ChangeVote(ctx context.Context, user uid.ID, up bool) error

ChangeVote returns an error is the comment is deleted or the post locked.

func (*Comment) Delete

func (c *Comment) Delete(ctx context.Context, user uid.ID, g UserGroup) error

Delete returns an error if user, who's deleting the comment, has no permissions in his capacity as g to delete this comment.

func (*Comment) DeleteVote

func (c *Comment) DeleteVote(ctx context.Context, user uid.ID) error

DeleteVote returns an error is the comment is deleted or the post locked.

func (*Comment) Save

func (c *Comment) Save(ctx context.Context, user uid.ID) error

Save updates comment's body.

func (*Comment) StripAuthorInfo

func (c *Comment) StripAuthorInfo()

StripAuthorInfo should be called if the author account of the comment is deleted and the viewer is not an admin.

func (*Comment) StripContent

func (c *Comment) StripContent()

StripContent strips all content of c that is either user generated or relates to a user.

func (*Comment) Vote

func (c *Comment) Vote(ctx context.Context, user uid.ID, up bool) error

Vote votes on comment (if the comment is not deleted or the post locked).

type CommentsCursor

type CommentsCursor struct {
	Upvotes int
	NextID  uid.ID
}

CommentsCursor is an API pagination cursor.

type CommunitiesSort

type CommunitiesSort string

func (CommunitiesSort) Valid

func (s CommunitiesSort) Valid() bool

type Community

type Community struct {
	ID            uid.ID          `json:"id"`
	AuthorID      uid.ID          `json:"userId"`
	Name          string          `json:"name"`
	NameLowerCase string          `json:"-"` // TODO: Remove this field (only from this struct, not also from the database).
	NSFW          bool            `json:"nsfw"`
	About         msql.NullString `json:"about"`
	NumMembers    int             `json:"noMembers"`
	ProPic        *images.Image   `json:"proPic"`
	BannerImage   *images.Image   `json:"bannerImage"`
	CreatedAt     time.Time       `json:"createdAt"`
	DeletedAt     msql.NullTime   `json:"deletedAt"`
	DeletedBy     uid.NullID      `json:"-"`

	// IsDefault is nil until Default is called.
	IsDefault *bool `json:"isDefault,omitempty"`

	ViewerJoined  msql.NullBool `json:"userJoined"`
	ViewerMod     msql.NullBool `json:"userMod"`
	MutedByViewer bool          `json:"isMuted"`

	Mods           []*User                  `json:"mods"`
	Rules          []*CommunityRule         `json:"rules"`
	ReportsDetails *CommunityReportsDetails `json:"ReportsDetails"`
	// contains filtered or unexported fields
}

func CommunityExists

func CommunityExists(ctx context.Context, db *sql.DB, name string) (bool, *Community, error)

func CreateCommunity

func CreateCommunity(ctx context.Context, db *sql.DB, creator uid.ID, reqPoints, maxPerUser int, name, about string) (*Community, error)

CreateCommunity returns an error if creator doesn't have reqPoints or if he's created more communities than maxPerUser.

func GetCommunities

func GetCommunities(ctx context.Context, db *sql.DB, sort CommunitiesSort, set string, n int, viewer *uid.ID) ([]*Community, error)

GetCommunities returns a maximum of n communities.

func GetCommunitiesByIDs

func GetCommunitiesByIDs(ctx context.Context, db *sql.DB, ids []uid.ID, viewer *uid.ID) ([]*Community, error)

func GetCommunitiesPrefix

func GetCommunitiesPrefix(ctx context.Context, db *sql.DB, s string) ([]*Community, error)

GetCommunitiesPrefix returns all communities with name prefix s sorted by created at.

func GetCommunityByID

func GetCommunityByID(ctx context.Context, db *sql.DB, id uid.ID, viewer *uid.ID) (*Community, error)

GetCommunityByID returns a not-found httperr.Error if no community is found.

func GetCommunityByName

func GetCommunityByName(ctx context.Context, db *sql.DB, name string, viewer *uid.ID) (*Community, error)

GetCommunityByName returns a not-found httperr.Error if no community is found.

func (*Community) AddRule

func (c *Community) AddRule(ctx context.Context, rule, description string, mod uid.ID) error

func (*Community) BanUser

func (c *Community) BanUser(ctx context.Context, mod, user uid.ID, expires *time.Time) error

BanUser bans user by mod. If expires is non-nil, the ban is permanent.

func (*Community) Default

func (c *Community) Default(ctx context.Context) (bool, error)

Default reports whether c is a default community, and, if there's no error, it sets c.IsDefault to a non-nil value.

func (*Community) DeleteBannerImage

func (c *Community) DeleteBannerImage(ctx context.Context) error

DeleteBannerImage deletes the community's banner image.

func (*Community) DeleteBannerImageTx

func (c *Community) DeleteBannerImageTx(ctx context.Context, tx *sql.Tx) error

func (*Community) DeleteProPic

func (c *Community) DeleteProPic(ctx context.Context) error

func (*Community) DeleteProPicTx

func (c *Community) DeleteProPicTx(ctx context.Context, tx *sql.Tx) error

func (*Community) FetchRules

func (c *Community) FetchRules(ctx context.Context) error

FetchRules populates c.Rules.

func (*Community) FixModPositions

func (c *Community) FixModPositions(ctx context.Context) error

FixModPositions fixes the mod hierarchy of moderators. If two mods have the same position, they are given new positions according when they were made mods of c.

func (*Community) GetBannedUsers

func (c *Community) GetBannedUsers(ctx context.Context) ([]*User, error)

func (*Community) Join

func (c *Community) Join(ctx context.Context, user uid.ID) error

func (*Community) Leave

func (c *Community) Leave(ctx context.Context, user uid.ID) error

func (*Community) ModHigherUp

func (c *Community) ModHigherUp(ctx context.Context, higher, lower uid.ID) (bool, error)

ModHigherUp reports whether higher mod is above the lower mod in the mod hierarchy. It returns true when the two mods have the same position value. It also returns true if the two mods, higher and lower, are the same.

ModHigherUp does not check properly for permissions.

func (*Community) PopulateMods

func (c *Community) PopulateMods(ctx context.Context) (err error)

PopulateMods populates c.Mods.

func (*Community) PopulateViewerFields

func (c *Community) PopulateViewerFields(ctx context.Context, user uid.ID) error

PopulateViewerFields populates c.ViewerJoined and c.ViewerMod fields.

func (*Community) RemoveRule

func (c *Community) RemoveRule(ctx context.Context, ruleID string, mod uid.ID) error

func (*Community) SetDefault

func (c *Community) SetDefault(ctx context.Context, set bool) error

SetDefault adds c to the list of default communities. If set is false, c is removed from the default communities.

func (*Community) UnbanUser

func (c *Community) UnbanUser(ctx context.Context, mod, user uid.ID) error

func (*Community) Update

func (c *Community) Update(ctx context.Context, mod uid.ID) error

Update updates c.About and c.NSFW.

func (*Community) UpdateBannerImage

func (c *Community) UpdateBannerImage(ctx context.Context, image []byte) error

func (*Community) UpdateProPic

func (c *Community) UpdateProPic(ctx context.Context, image []byte) error

func (*Community) UserBanned

func (c *Community) UserBanned(ctx context.Context, user uid.ID) (bool, error)

UserBanned reports if user is banned from community. If user is banned and the ban is expired he is unbanned.

func (*Community) UserMod

func (c *Community) UserMod(ctx context.Context, user uid.ID) (bool, error)

UserMod checks if user is a moderator of c.

func (*Community) UserModOrAdmin

func (c *Community) UserModOrAdmin(ctx context.Context, user uid.ID) (bool, error)

UserModOrAdmin reports whether user is a moderator of c or if user is an admin.

type CommunityReportsDetails

type CommunityReportsDetails struct {
	NumReports        int `json:"noReports"`
	NumPostReports    int `json:"noPostReports"`
	NumCommentReports int `json:"noCommentReports"`
}

CommunityReportsDetails holds summary information about user-reports submitted in a community.

func FetchReportsDetails

func FetchReportsDetails(ctx context.Context, db *sql.DB, community uid.ID) (d CommunityReportsDetails, err error)

type CommunityRequest

type CommunityRequest struct {
	ID            int        `json:"id"`
	ByUser        string     `json:"byUser"`
	CommunityName string     `json:"communityName"`
	Note          string     `json:"note"`
	CreatedAt     time.Time  `json:"createdAt"`
	DeletedAt     *time.Time `json:"deletedAt"`
}

func GetCommunityRequests

func GetCommunityRequests(ctx context.Context, db *sql.DB) ([]*CommunityRequest, error)

type CommunityRule

type CommunityRule struct {
	ID          uint            `json:"id"`
	Rule        string          `json:"rule"`
	Description msql.NullString `json:"description"`
	CommunityID uid.ID          `json:"communityId"`
	ZIndex      int             `json:"zIndex"`
	CreatedBy   uid.ID          `json:"createdBy"`
	CreatedAt   time.Time       `json:"createdAt"`
	// contains filtered or unexported fields
}

func GetCommunityRule

func GetCommunityRule(ctx context.Context, db *sql.DB, ruleID uint) (*CommunityRule, error)

func (*CommunityRule) Delete

func (r *CommunityRule) Delete(ctx context.Context, mod uid.ID) error

func (*CommunityRule) Update

func (r *CommunityRule) Update(ctx context.Context, mod uid.ID) error

Update updates the rule's rule, description, and ZIndex.

type FeedOptions

type FeedOptions struct {
	Sort        FeedSort
	DefaultSort bool
	Viewer      *uid.ID
	Community   *uid.ID // Community should be nil if Homefeed is true.
	Homefeed    bool
	Limit       int
	Next        string // The pagination cursor, taken from previous API response.
}

type FeedResultSet

type FeedResultSet struct {
	Posts []*Post     `json:"posts"`
	Next  interface{} `json:"next"`
}

FeedResultSet is a page of results of a feed.

func GetFeed

func GetFeed(ctx context.Context, db *sql.DB, opts *FeedOptions) (_ *FeedResultSet, err error)

type FeedSort

type FeedSort int

FeedSort represents how the items in a feed are to be sorted.

func (FeedSort) MarshalText

func (s FeedSort) MarshalText() ([]byte, error)

MarshalText implements the encoding.TextMarshaler interface.

func (*FeedSort) UnmarshalText

func (s *FeedSort) UnmarshalText(text []byte) error

UnmarshalText implements the encoding.TextUnmarshaler interface.

func (FeedSort) Valid

func (s FeedSort) Valid() bool

Valid reports whether f is a valid FeedSort.

type FeedType

type FeedType int

FeedType distinguishes between the two main content feeds.

func (FeedType) MarshalText

func (ft FeedType) MarshalText() ([]byte, error)

MarshalText implements the encoding.TextMarshaler interface.

func (*FeedType) UnmarshalText

func (ft *FeedType) UnmarshalText(text []byte) error

UnmarshalText implements the encoding.TextUnmarshaler interface.

func (FeedType) Valid

func (ft FeedType) Valid() bool

type Mute

type Mute struct {
	ID               int       `json:"-"`
	PublicID         string    `json:"id"` // augmented id based on Type
	User             uid.ID    `json:"-"`
	Type             MuteType  `json:"type"`
	MutedUserID      *uid.ID   `json:"mutedUserId,omitempty"`      // may be empty and omitted base on Type
	MutedCommunityID *uid.ID   `json:"mutedCommunityId,omitempty"` // may be empty and omitted base on Type
	CreatedAt        time.Time `json:"createdAt"`

	MutedUser      *User      `json:"mutedUser,omitempty"`
	MutedCommunity *Community `json:"mutedCommunity,omitempty"`
	// contains filtered or unexported fields
}

func GetMutedCommunities

func GetMutedCommunities(ctx context.Context, db *sql.DB, user uid.ID, fetchCommunities bool) ([]*Mute, error)

func GetMutedUsers

func GetMutedUsers(ctx context.Context, db *sql.DB, user uid.ID, fillUsers bool) ([]*Mute, error)

func GetMutes

func GetMutes(ctx context.Context, db *sql.DB, user uid.ID) ([]*Mute, error)

type MuteType

type MuteType string

func (MuteType) Valid

func (t MuteType) Valid() bool

type Notification

type Notification struct {
	ID     int              `json:"id"`
	UserID uid.ID           `json:"-"`
	Type   NotificationType `json:"type"`

	// Information specific to notification type.
	Notif notification `json:"notif"`

	Seen      bool          `json:"seen"`
	SeenAt    msql.NullTime `json:"seenAt"`
	CreatedAt time.Time     `json:"createdAt"`
	// contains filtered or unexported fields
}

Notification is a user's notification.

func GetNotification

func GetNotification(ctx context.Context, db *sql.DB, ID string) (*Notification, error)

func GetNotifications

func GetNotifications(ctx context.Context, db *sql.DB, user uid.ID, limit int, cursor string) ([]*Notification, string, error)

GetNotifications returns notifications of user. If limit is 0, all notifications are returned. The string returned is the pagination cursor of the next fetch.

func (*Notification) Delete

func (n *Notification) Delete(ctx context.Context) error

func (*Notification) MarshalJSON

func (n *Notification) MarshalJSON() ([]byte, error)

func (*Notification) ResetUserNewNotificationsCount

func (n *Notification) ResetUserNewNotificationsCount(ctx context.Context) error

func (*Notification) Saw

func (n *Notification) Saw(ctx context.Context, seen bool) error

Saw marks the notification as seen. If seen is false the notification is markend as unseen.

func (*Notification) SendPushNotification

func (n *Notification) SendPushNotification(ctx context.Context) error

SendPushNotification sends the notification to all matching sessions. Call EnablePushNotifications before any calls to this method.

func (*Notification) Update

func (n *Notification) Update(ctx context.Context) error

Update updates a notification.

type NotificationCommentReply

type NotificationCommentReply struct {
	PostID          uid.ID `json:"postId"`
	ParentCommentID uid.ID `json:"parentCommentId"`
	CommentID       uid.ID `json:"commentId"`

	// If NumComments > 1, the first user that commented.
	CommentAuthor string `json:"commentAuthor"`

	// If NumComments > 1, many new comments have been added to post and
	// CommentID and CommentAuthor is that of the latest one.
	NumComments int `json:"noComments"`

	// First time this notification was created. Needed to identify the new
	// comments that this notification refers to (all the comments after this
	// time and before comment seen time)
	FirstCreatedAt time.Time `json:"firstCreatedAt"`
}

NotificationCommentReply is for when a comment receives a reply. It is sent to the parent comment's author.

type NotificationModAdd

type NotificationModAdd struct {
	CommunityName string `json:"communityName"`
	AddedBy       string `json:"addedBy"`
}

NotificationModAdd is sent when someone is added as a mod to a community.

type NotificationNewBadge

type NotificationNewBadge struct {
	UserID    uid.ID `json:"userId"`
	BadgeType string `json:"badgeType"`
}

type NotificationNewComment

type NotificationNewComment struct {
	PostID    uid.ID `json:"postId"`
	CommentID uid.ID `json:"commentId"`

	// If NumComments > 1, many new comments have been added to post and
	// CommentID and CommentAuthor is that of the first one.
	NumComments int `json:"noComments"`

	// If NumComments > 1, the first user that commented.
	CommentAuthor string `json:"commentAuthor"`

	// First time this notification was created. Needed to identify the new
	// comments that this notification refers to (all the comments after this
	// time and before comment seen time)
	FirstCreatedAt time.Time `json:"firstCreatedAt"`
}

NotificationNewComment is for when a comment is added to a post. It is sent to the post's author.

type NotificationNewVotes

type NotificationNewVotes struct {
	TargetType string `json:"targetType"` // post or comment
	TargetID   uid.ID `json:"targetId"`
	NoVotes    int    `json:"noVotes"`
}

NotificationNewVotes is sent when a user votes on a post or a comment.

type NotificationPostDeleted

type NotificationPostDeleted struct {
	TargetType string    `json:"targetType"` // post or comment
	TargetID   uid.ID    `json:"targetId"`
	DeletedAs  UserGroup `json:"deletedAs"`
}

NotificationPostDeleted is sent when a mod or an admin removes a post or a comment.

type NotificationType

type NotificationType string

func (NotificationType) Valid

func (t NotificationType) Valid() bool

type Post

type Post struct {
	ID   uid.ID   `json:"id"`
	Type PostType `json:"type"`

	// ID as it appears in the URL.
	PublicID string `json:"publicId"`

	AuthorID       uid.ID `json:"userId"`
	AuthorUsername string `json:"username"`
	AuthorGhostID  string `json:"userGhostId,omitempty"`

	// In which capacity (as mod, admin, or normal user) the post was posted in.
	PostedAs UserGroup `json:"userGroup"`

	// Indicates Whether the account of the user who posted the post is deleted.
	AuthorDeleted bool `json:"userDeleted"`

	// Indicates whether the post is pinned to the community.
	Pinned bool `json:"isPinned"`

	// Indicates whether the post is pinned site-wide.
	PinnedSite bool `json:"isPinnedSite"`

	CommunityID          uid.ID        `json:"communityId"`
	CommunityName        string        `json:"communityName"`
	CommunityProPic      *images.Image `json:"communityProPic"`
	CommunityBannerImage *images.Image `json:"communityBannerImage"`

	Title string          `json:"title"`
	Body  msql.NullString `json:"body"`

	Image *images.Image `json:"image"`

	Link *PostLink `json:"link,omitempty"` // what's sent to the client

	Locked   bool       `json:"locked"`
	LockedBy uid.NullID `json:"lockedBy"`

	// In what capacity (as owner, admin, or mod) the post was locked.
	LockedAs UserGroup `json:"lockedByGroup,omitempty"`

	LockedAt msql.NullTime `json:"lockedAt"`

	Upvotes   int `json:"upvotes"`
	Downvotes int `json:"downvotes"`
	Points    int `json:"-"` // Upvotes - Downvotes

	Hotness        int           `json:"hotness"`
	CreatedAt      time.Time     `json:"createdAt"`
	EditedAt       msql.NullTime `json:"editedAt"`
	LastActivityAt time.Time     `json:"lastActivityAt"`
	Deleted        bool          `json:"deleted"`
	DeletedAt      msql.NullTime `json:"deletedAt,omitempty"`
	DeletedBy      uid.NullID    `json:"-"`

	// In what capacity (as owner, admin, or mod) the post was deleted.
	DeletedAs UserGroup `json:"deletedAs,omitempty"`

	// If true, all links and images contained in the post is deleted.
	DeletedContent bool `json:"deletedContent"`

	DeletedContentAt msql.NullTime `json:"-"`
	DeletedContentBy uid.NullID    `json:"-"`
	DeletedContentAs UserGroup     `json:"deletedContentAs,omitempty"`

	NumComments  int             `json:"noComments"`
	Comments     []*Comment      `json:"comments"`
	CommentsNext msql.NullString `json:"commentsNext"` // pagination cursor

	// Whether the logged in user have voted on this post.
	ViewerVoted msql.NullBool `json:"userVoted"`

	// Whether the logged in user have voted up.
	ViewerVotedUp msql.NullBool `json:"userVotedUp"`

	AuthorMutedByViewer    bool `json:"isAuthorMuted"`
	CommunityMutedByViewer bool `json:"isCommunityMuted"`

	Community *Community `json:"community,omitempty"`
	Author    *User      `json:"author,omitempty"`
	// contains filtered or unexported fields
}

func CreateImagePost

func CreateImagePost(ctx context.Context, db *sql.DB, author, community uid.ID, title string, imageID uid.ID) (*Post, error)

func CreateLinkPost

func CreateLinkPost(ctx context.Context, db *sql.DB, author, community uid.ID, title string, link string) (*Post, error)

func CreateTextPost

func CreateTextPost(ctx context.Context, db *sql.DB, author, community uid.ID, title string, body string) (*Post, error)

func GetPost

func GetPost(ctx context.Context, db *sql.DB, postID *uid.ID, publicID string, viewer *uid.ID, getDeleted bool) (*Post, error)

GetPosts returns a post using publicID, if publicID is not an empty string, or using postID.

func GetPostsDeleted

func GetPostsDeleted(ctx context.Context, db *sql.DB, community uid.ID, limit, page int) (int, []*Post, error)

GetPostsDeleted returns a slice of deleted posts (sorted by ID) and the number of deleted posts in community.

func GetPostsLocked

func GetPostsLocked(ctx context.Context, db *sql.DB, community uid.ID, limit, page int) (int, []*Post, error)

GetPostsLocked returns a slice of locked posts (sorted by ID) and the number of locked posts in community.

func (*Post) AddComment

func (p *Post) AddComment(ctx context.Context, user uid.ID, g UserGroup, parentComment *uid.ID, body string) (*Comment, error)

AddComment adds a new comment to post.

func (*Post) ChangeUserGroup

func (p *Post) ChangeUserGroup(ctx context.Context, user uid.ID, g UserGroup) error

ChangeUserGroup changes the capacity in which the post's author submitted the post.

func (*Post) ChangeVote

func (p *Post) ChangeVote(ctx context.Context, user uid.ID, up bool) error

ChangeVote changes user's vote on post.

func (*Post) Delete

func (p *Post) Delete(ctx context.Context, user uid.ID, g UserGroup, deleteContent bool) error

Delete deletes p on behalf of user, who's deleting the post in his capacity as g. In case the post is deleted by an admin or a mod, a notification is sent to the original poster.

func (*Post) DeleteVote

func (p *Post) DeleteVote(ctx context.Context, user uid.ID) error

DeleteVote undos users's vote on post.

func (*Post) GetCommentReplies

func (p *Post) GetCommentReplies(ctx context.Context, viewer *uid.ID, comment uid.ID) ([]*Comment, error)

GetCommentReplies returns all the replies of comment.

func (*Post) GetComments

func (p *Post) GetComments(ctx context.Context, viewer *uid.ID, cursor *CommentsCursor) (*CommentsCursor, error)

GetComments populates c.Comments and returns the next comment's cursor.

func (*Post) HasLinkImage

func (p *Post) HasLinkImage() bool

func (*Post) Lock

func (p *Post) Lock(ctx context.Context, user uid.ID, g UserGroup) error

Lock locks the post on behalf of user who's locking the post in his or her capacity as g.

func (*Post) Pin

func (p *Post) Pin(ctx context.Context, user uid.ID, siteWide, unpin bool, skipPermissions bool) error

Pin pins a post on behalf of user to its community if siteWide is false, otherwise it pins the post site-wide. If skipPermissions is true, it's not checked if user has the permissioned to perform this action.

func (*Post) Save

func (p *Post) Save(ctx context.Context, user uid.ID) error

Save updates the post's updatable fields.

func (*Post) StripAuthorInfo

func (p *Post) StripAuthorInfo()

StripAuthorInfo should be called if the author account of the post is deleted and the viewer is not an admin.

func (*Post) Unlock

func (p *Post) Unlock(ctx context.Context, user uid.ID) error

Unlock unlocks the post on behalf of user.

func (*Post) Vote

func (p *Post) Vote(ctx context.Context, user uid.ID, up bool) error
type PostLink struct {
	Version  int           `json:"-"`
	URL      string        `json:"url"`
	Hostname string        `json:"hostname"`
	Image    *images.Image `json:"image"`
}

PostLink is the object to be sent to the client.

func (*PostLink) SetImageCopies

func (pl *PostLink) SetImageCopies()

type PostType

type PostType int

PostType represents the type of a post.

func (PostType) MarshalText

func (t PostType) MarshalText() ([]byte, error)

MarshalText implements encoding.TextMarshaler interface.

func (*PostType) UnmarshalText

func (p *PostType) UnmarshalText(text []byte) error

UnmarshalText implements encoding.TextUnmarshaler interface.

func (PostType) Valid

func (t PostType) Valid() bool

Valid reports whether t is a valid PostType.

type Report

type Report struct {
	ID          int             `json:"id"`
	CommunityID uid.ID          `json:"communityId"`
	PostID      uid.NullID      `json:"postId"`
	Reason      string          `json:"reason"`
	Description msql.NullString `json:"description"`
	ReasonID    int             `json:"reasonId"`
	Type        ReportType      `json:"type"` // post or comment
	TargetID    uid.ID          `json:"targetId"`
	CreatedBy   uid.ID          `json:"-"`
	ActionTaken msql.NullString `json:"actionTaken"`
	DealtAt     msql.NullTime   `json:"dealtAt"`
	DealtBy     uid.NullID      `json:"dealtBy"`
	CreatedAt   time.Time       `json:"createdAt"`

	Target interface{} `json:"target"`
	// contains filtered or unexported fields
}

Report is a user submitted report.

func GetReport

func GetReport(ctx context.Context, db *sql.DB, reportID int) (*Report, error)

GetReport returns an error if the report is not found.

func GetReports

func GetReports(ctx context.Context, db *sql.DB, community uid.ID, t ReportType, limit, page int) ([]*Report, error)

GetReports retrives user submitted reports in community. The results are paginated.

func NewCommentReport

func NewCommentReport(ctx context.Context, db *sql.DB, comment uid.ID, reason int, createdBy uid.ID) (*Report, error)

NewCommentReport creates a report on comment.

func NewPostReport

func NewPostReport(ctx context.Context, db *sql.DB, post uid.ID, reason int, createdBy uid.ID) (*Report, error)

NewPostReport creates a report on post.

func NewReport

func NewReport(ctx context.Context, db *sql.DB, community uid.ID, post uid.NullID, t ReportType, reason int, target, createdBy uid.ID) (*Report, error)

NewReport creates a new report on target.

func (*Report) Delete

func (r *Report) Delete(ctx context.Context, mod uid.ID) error

Delete deletes the report permanently.

func (*Report) FetchTarget

func (r *Report) FetchTarget(ctx context.Context) error

FetchTarget populates r.Target with the target object on which the report was made.

type ReportReason

type ReportReason struct {
	ID          int             `json:"id"`
	Title       string          `json:"title"`
	Description msql.NullString `json:"description"`
	CreatedAt   time.Time       `json:"-"`
}

func GetReportReasons

func GetReportReasons(ctx context.Context, db *sql.DB) ([]ReportReason, error)

GetReportReasons returns all report reasons. These are supposed to be about a dozen at most.

type ReportType

type ReportType int

ReportType represents the type of user submitted report.

func (ReportType) MarshalText

func (r ReportType) MarshalText() ([]byte, error)

MarshalText implements the encoding.TextMarshaler interface.

func (*ReportType) UnmarshalText

func (r *ReportType) UnmarshalText(text []byte) error

UnmarshalText implements the encoding.TextUnmarshaler interface.

type User

type User struct {
	ID                uid.ID `json:"id"`
	Username          string `json:"username"`
	UsernameLowerCase string `json:"-"`

	EmailPublic *string `json:"email"`

	Email            msql.NullString `json:"-"`
	EmailConfirmedAt msql.NullTime   `json:"emailConfirmedAt"`
	Password         string          `json:"-"`
	About            msql.NullString `json:"aboutMe"`
	Points           int             `json:"points"`
	Admin            bool            `json:"isAdmin"`
	ProPic           *images.Image   `json:"proPic"`
	Badges           Badges          `json:"badges"`
	NumPosts         int             `json:"noPosts"`
	NumComments      int             `json:"noComments"`
	LastSeen         time.Time       `json:"-"` // accurate to within 5 minutes
	CreatedAt        time.Time       `json:"createdAt"`
	Deleted          bool            `json:"deleted"`
	DeletedAt        msql.NullTime   `json:"deletedAt,omitempty"`

	// User preferences.
	UpvoteNotificationsOff  bool     `json:"upvoteNotificationsOff"`
	ReplyNotificationsOff   bool     `json:"replyNotificationsOff"`
	HomeFeed                FeedType `json:"homeFeed"`
	RememberFeedSort        bool     `json:"rememberFeedSort"`
	EmbedsOff               bool     `json:"embedsOff"`
	HideUserProfilePictures bool     `json:"hideUserProfilePictures"`

	// No banned users are supposed to be logged in. Make sure to log them out
	// before banning.
	BannedAt msql.NullTime `json:"bannedAt"`
	Banned   bool          `json:"isBanned"`

	MutedByViewer bool `json:"-"`

	NumNewNotifications int `json:"notificationsNewCount"`

	// The list of communities the user moderates.
	ModdingList []*Community `json:"moddingList"`
	// contains filtered or unexported fields
}

func GetCommunityMods

func GetCommunityMods(ctx context.Context, db *sql.DB, community uid.ID) ([]*User, error)

GetCommunityMods returns the list of moderators of community sorted by mod hierarchy.

func GetUser

func GetUser(ctx context.Context, db *sql.DB, user uid.ID, viewer *uid.ID) (*User, error)

func GetUserByEmail

func GetUserByEmail(ctx context.Context, db *sql.DB, email string, viewer *uid.ID) (*User, error)

func GetUserByUsername

func GetUserByUsername(ctx context.Context, db *sql.DB, username string, viewer *uid.ID) (*User, error)

func GetUsersByIDs

func GetUsersByIDs(ctx context.Context, db *sql.DB, IDs []uid.ID, viewer *uid.ID) ([]*User, error)

func MakeAdmin

func MakeAdmin(ctx context.Context, db *sql.DB, user string, isAdmin bool) (*User, error)

MakeAdmin makes the user an admin of the site. If isAdmin is false admin user is removed as an admin.

func MatchLoginCredentials

func MatchLoginCredentials(ctx context.Context, db *sql.DB, username, password string) (*User, error)

MatchLoginCredentials returns a nil error if a user was found and the password matches.

func RegisterUser

func RegisterUser(ctx context.Context, db *sql.DB, username, email, password string) (*User, error)

RegisterUser creates a new user.

func (*User) AddBadge

func (u *User) AddBadge(ctx context.Context, badgeType string) error

AddBadge addes new badge to u. Also, u.Badges is refetched upon a successful add.

func (*User) Ban

func (u *User) Ban(ctx context.Context) error

Ban bans the user from site. Important: Make sure to log out all sessions of this user before calling this function, and never allow this user to login.

Note: An admin can be banned.

func (*User) ChangePassword

func (u *User) ChangePassword(ctx context.Context, previousPass, newPass string) error

func (*User) Delete

func (u *User) Delete(ctx context.Context) error

Delete deletes a user. Make sure that the user is logged out on all sessions before calling this function.

func (*User) DeleteAllNotifications

func (u *User) DeleteAllNotifications(ctx context.Context) error

func (*User) DeleteProPic

func (u *User) DeleteProPic(ctx context.Context) error

func (*User) DeleteProPicTx

func (u *User) DeleteProPicTx(ctx context.Context, tx *sql.Tx) error

func (*User) GetBannedFromCommunities

func (u *User) GetBannedFromCommunities(ctx context.Context) ([]uid.ID, error)

GetBannedFromCommunities returns the list of communities that user is banned from.

func (*User) IsGhost

func (u *User) IsGhost() bool

func (*User) LoadModdingList

func (u *User) LoadModdingList(ctx context.Context) error

func (*User) MakeAdmin

func (u *User) MakeAdmin(ctx context.Context, isAdmin bool) error

MakeAdmin makes the user an admin of the site. If isAdmin is false admin is removed as an admin.

func (*User) MarkAllNotificationsAsSeen

func (u *User) MarkAllNotificationsAsSeen(ctx context.Context, t NotificationType) error

MarkAllNotificationsAsSeen marks all notifications as seen, if t is the zero value, and if not, it marks all notifications of type t as seen.

func (*User) RemoveBadge

func (u *User) RemoveBadge(id int) error

func (*User) RemoveBadgesByType

func (u *User) RemoveBadgesByType(badgeType string) error

func (*User) ResetNewNotificationsCount

func (u *User) ResetNewNotificationsCount(ctx context.Context) error

func (*User) Saw

func (u *User) Saw(ctx context.Context, userIP string) error

Saw updates u.LastSeen to current time. It also updates the IP address of the user.

func (*User) SetToGhost

func (u *User) SetToGhost()

SetToGhost sets u.username to "ghost" and u.ID to zero, if the user is deleted.

func (*User) Unban

func (u *User) Unban(ctx context.Context) error

func (*User) UnsetToGhost

func (u *User) UnsetToGhost()

UnsetToGhost is the inverse of u.SetToGhost.

func (*User) Update

func (u *User) Update(ctx context.Context) error

Update updates the user's updatable fields.

func (*User) UpdateProPic

func (u *User) UpdateProPic(ctx context.Context, image []byte) error

type UserFeedItem

type UserFeedItem struct {
	// Item is either a post or a comment.
	Item any `json:"item"`
	// Type is Item's type.
	Type string `json:"type"`
}

UserFeedItem is an item in a user page's feed.

type UserFeedResultSet

type UserFeedResultSet struct {
	Items []UserFeedItem `json:"items"`
	Next  *uid.ID        `json:"next"`
}

UserFeedResultSet holds the user page's feed's items.

func GetUserFeed

func GetUserFeed(ctx context.Context, db *sql.DB, viewer *uid.ID, userID uid.ID, filter string, limit int, next *uid.ID) (*UserFeedResultSet, error)

type UserGroup

type UserGroup int

UserGroup represents who a user is.

func (UserGroup) MarshalText

func (u UserGroup) MarshalText() ([]byte, error)

MarshalText implements encoding.TextMarshaler interface.

func (UserGroup) String

func (u UserGroup) String() string

String implements fmt.Stringer interface. It returns the value returned by u.MarshalText (if u.MarshalText returns an error, it returns "[error]").

func (*UserGroup) UnmarshalText

func (u *UserGroup) UnmarshalText(text []byte) error

UnmarshalText implements encoding.TextUnmarshaler interface.

func (UserGroup) Valid

func (u UserGroup) Valid() bool

type VAPIDKeys

type VAPIDKeys struct {
	Public  string `json:"public"`
	Private string `json:"private"`
}

VAPIDKeys is an application server key-pair used by the Web Push API.

func GetApplicationVAPIDKeys

func GetApplicationVAPIDKeys(ctx context.Context, db *sql.DB) (*VAPIDKeys, error)

GetApplicationVAPIDKeys returns a pair of VAPID public/private keys used by the Web Push API. If no keys are found in the application_data table in the database, a new key-value pair is generated, saved, and returned.

type WebPushSubscription

type WebPushSubscription struct {
	ID               int                  `json:"id"`
	SessionID        string               `json:"sessionId"`
	UserID           uid.ID               `json:"userId"`
	PushSubscription webpush.Subscription `json:"pushSubscription"`
	CreatedAt        time.Time            `json:"createdAt"`
	UpdatedAt        msql.NullTime        `json:"updatedAt"`
	// contains filtered or unexported fields
}

WebPushSubscription stores a PushSubscription object with other necessary information for sending web push notifications for logged in users.

One user could have multiple WebPushSubscription entries in the database (in which case he's signed in on multiple devices).

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL