Skip to content

Commit

Permalink
Merge pull request RealistikOsu#5 from Kaimi8/master
Browse files Browse the repository at this point in the history
Profile comments
  • Loading branch information
lenforiee authored May 29, 2022
2 parents 4999d90 + c9e6a6c commit b3e38dc
Show file tree
Hide file tree
Showing 4 changed files with 207 additions and 8 deletions.
4 changes: 4 additions & 0 deletions app/start.go
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,8 @@ func Start(conf common.Conf, dbO *sqlx.DB) *fhr.Router {
r.Method("/api/v1/first/oldest", v1.OldestFirstGET)
r.Method("/api/v1/users/scores/pinned", v1.UserPinnedGET)
r.Method("/api/v1/users/scores/pinned/info", v1.PinnedScoreGET)
r.Method("/api/v1/users/comments", v1.CommentGET)
r.Method("/api/v1/users/comments/info", v1.CommentInfoGET)
r.Method("/api/v1/badges", v1.BadgesGET)
r.Method("/api/v1/badges/members", v1.BadgeMembersGET)
r.Method("/api/v1/beatmaps", v1.BeatmapGET)
Expand All @@ -131,6 +133,8 @@ func Start(conf common.Conf, dbO *sqlx.DB) *fhr.Router {
r.POSTMethod("/api/v1/users/self/settings", v1.UsersSelfSettingsPOST, common.PrivilegeWrite)
r.POSTMethod("/api/v1/users/self/userpage", v1.UserSelfUserpagePOST, common.PrivilegeWrite)
r.POSTMethod("/api/v1/beatmaps/rank_requests", v1.BeatmapRankRequestsSubmitPOST, common.PrivilegeWrite)
r.POSTMethod("/api/v1/users/comments", v1.CommentPOST, common.PrivilegeWrite)
r.POSTMethod("/api/v1/users/comments/delete", v1.CommentDELETE, common.PrivilegeWrite)

// Admin: RAP
r.POSTMethod("/api/v1/rap/log", v1.RAPLogPOST)
Expand Down
192 changes: 192 additions & 0 deletions app/v1/comments.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,192 @@
package v1

import (
"database/sql"
"fmt"
"strings"
"time"

"github.com/RealistikOsu/RealistikAPI/common"
)

const (
MAX_LENGTH = 380
MIN_LENGTH = 3
)

type comment struct {
ID int `json:"id"`
Op int `json:"op"`
Username string `json:"username"`
Message string `json:"message"`
PostedAt int64 `json:"posted_at"`
}

type comments struct {
common.ResponseBase
Comments []comment `json:"comments"`
}

type commentInfo struct {
common.ResponseBase
Total int `json:"total"`
Disabled bool `json:"disabled"`
}

func CommentPOST(md common.MethodData) common.CodeMessager {
var commentDate int64 = time.Now().Unix()
var userExists bool
var doIExist bool
var canComment int

res := common.ResponseBase{}
userid := common.Int(md.Query("id"))
comment := string(md.Ctx.Request.Body())
op := md.User.UserID

// is user restricted? am i restricted? do they allow comments?
err := md.DB.QueryRow("SELECT EXISTS(SELECT 1 FROM users WHERE privileges & 1 = 1 AND id = ?);", userid).Scan(&userExists)
if err != nil && err != sql.ErrNoRows {
md.Err(err)
return Err500
}

err = md.DB.QueryRow("SELECT EXISTS(SELECT 1 FROM users WHERE privileges & 1 = 1 AND id = ?);", op).Scan(&doIExist)
if err != nil && err != sql.ErrNoRows {
md.Err(err)
return Err500
}

err = md.DB.QueryRow("SELECT disabled_comments FROM users WHERE id = ?;", userid).Scan(&canComment)
if err != nil && err != sql.ErrNoRows {
md.Err(err)
return Err500
}

if !userExists || !doIExist {
return common.SimpleResponse(403, "You don't have the permissions to carry out this action!")
} else if canComment == 1 {
return common.SimpleResponse(403, "This user has disabled comments on their profile.")
} else if len(comment) > MAX_LENGTH || len(comment) < MIN_LENGTH {
return common.SimpleResponse(400, fmt.Sprintf("Invalid comment! Comment must be between %d and %d in length.", MIN_LENGTH, MAX_LENGTH))
}

_, err = md.DB.Exec("INSERT INTO user_comments (op, prof, msg, comment_date) VALUES (?, ?, ?, ?)", op, userid, comment, commentDate)
if err != nil {
md.Err(err)
return Err500
}

res.Code = 200
res.Message = "success!"
return res
}

func CommentGET(md common.MethodData) common.CodeMessager {
var commentsAllowed int
var profileNotFound bool

res := comments{}
userid := common.Int(md.Query("id"))
canComment := fmt.Sprintf("SELECT disabled_comments FROM users WHERE id = ? AND %s;", md.User.OnlyUserPublic(true))

if err := md.DB.QueryRow(canComment, userid).Scan(&commentsAllowed); err != nil {
if err == sql.ErrNoRows {
profileNotFound = true
} else {
md.Err(err)
return Err500
}
}

if (commentsAllowed == 1 && !strings.Contains(md.User.UserPrivileges.String(), "AdminManageUsers")) || profileNotFound {
return common.SimpleResponse(404, "Profile not found/comments are disabled.")
}

cquery := `
SELECT
user_comments.op, user_comments.msg,
user_comments.comment_date,
users.username, user_comments.id
FROM user_comments
JOIN users ON users.id = user_comments.op
WHERE user_comments.prof = ? AND users.privileges & 1 = 1
ORDER BY user_comments.comment_date DESC
` + common.Paginate(md.Query("p"), md.Query("l"), 5)

rows, err := md.DB.Query(cquery, userid)

if err != nil {
md.Err(err)
return Err500
}

for rows.Next() {
cmt := comment{}
err = rows.Scan(
&cmt.Op,
&cmt.Message, &cmt.PostedAt,
&cmt.Username, &cmt.ID,
)

if err != nil {
md.Err(err)
return Err500
}

res.Comments = append(res.Comments, cmt)
}

res.Code = 200
return res
}

func CommentDELETE(md common.MethodData) common.CodeMessager {
var op int
var prof int

res := common.ResponseBase{}
id := common.Int(md.Query("id"))

if err := md.DB.QueryRow("SELECT op, prof FROM user_comments WHERE user_comments.id = ?", id).Scan(&op, &prof); err != nil && err != sql.ErrNoRows {
md.Err(err)
return Err500
}

if (op == md.User.UserID || strings.Contains(md.User.UserPrivileges.String(), "AdminManageUsers") || prof == md.User.UserID) && op != 0 {
_, err := md.DB.Exec("DELETE FROM user_comments WHERE id = ?", id)
if err != nil {
md.Err(err)
return Err500
}

res.Code = 200
res.Message = "success!"
return res
}

return common.SimpleResponse(403, "You cannot delete this!")
}

func CommentInfoGET(md common.MethodData) common.CodeMessager {
res := commentInfo{}
id := common.Int(md.Query("id"))
total := "SELECT COUNT(user_comments.id) FROM user_comments JOIN users ON users.id = user_comments.op WHERE prof = ? AND users.privileges & 1 = 1;"

if err := md.DB.QueryRow(total, id).Scan(&res.Total); err != nil && err != sql.ErrNoRows {
md.Err(err)
return Err500
}

if err := md.DB.QueryRow("SELECT disabled_comments FROM users WHERE users.id = ? AND "+md.User.OnlyUserPublic(true), id).Scan(&res.Disabled); err != nil {
if err == sql.ErrNoRows {
return common.SimpleResponse(404, "User not found!")
}

md.Err(err)
return Err500
}

res.Code = 200
return res
}
8 changes: 5 additions & 3 deletions app/v1/self.go
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ type userSettingsData struct {
Show *bool `json:"show"`
} `json:"custom_badge"`
PlayStyle *int `json:"play_style"`
DisableComments *bool `json:"disabled_comments"`
}

// UsersSelfSettingsPOST allows to modify information about the current user.
Expand All @@ -81,7 +82,8 @@ func UsersSelfSettingsPOST(md common.MethodData) common.CodeMessager {
Add("s.custom_badge_name", d.CustomBadge.Name).
Add("s.custom_badge_icon", d.CustomBadge.Icon).
Add("s.show_custom_badge", d.CustomBadge.Show).
Add("s.play_style", d.PlayStyle)
Add("s.play_style", d.PlayStyle).
Add("u.disabled_comments", d.DisableComments)
_, err := md.DB.Exec("UPDATE users u, users_stats s SET "+q.Fields()+" WHERE s.id = u.id AND u.id = ?", append(q.Parameters, md.ID())...)
if err != nil {
md.Err(err)
Expand Down Expand Up @@ -130,15 +132,15 @@ SELECT
u.email, s.username_aka, s.favourite_mode,
s.show_custom_badge, s.custom_badge_icon,
s.custom_badge_name, s.can_custom_badge,
s.play_style, u.flags
s.play_style, u.flags, u.disabled_comments
FROM users u
LEFT JOIN users_stats s ON u.id = s.id
WHERE u.id = ?`, md.ID()).Scan(
&r.ID, &r.Username,
&r.Email, &r.UsernameAKA, &r.FavouriteMode,
&r.CustomBadge.Show, &r.CustomBadge.Icon,
&r.CustomBadge.Name, &ccb,
&r.PlayStyle, &r.Flags,
&r.PlayStyle, &r.Flags, &r.DisableComments,
)
if err != nil {
md.Err(err)
Expand Down
11 changes: 6 additions & 5 deletions app/v1/user_pinned.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@ import (
type pinnedInfo struct {
common.ResponseBase
Pinned struct {
UserID int `json:"userid"`
ScoreID int `json:"scoreid"`
UserID int `json:"userid"`
ScoreID int `json:"scoreid"`
PinnedAt int64 `json:"pinned_at"`
} `json:"pinned"`
}
Expand Down Expand Up @@ -49,10 +49,11 @@ func UserPinnedGET(md common.MethodData) common.CodeMessager {
beatmaps.ranked_status_freezed, beatmaps.latest_update
FROM user_pinned
JOIN scores%[1]s ON scores%[1]s.id = scoreid
JOIN beatmaps on scores%[1]s.beatmap_md5 = beatmaps.beatmap_md5
WHERE user_pinned.userid = ? AND scores%[1]s.play_mode = ?
JOIN beatmaps ON scores%[1]s.beatmap_md5 = beatmaps.beatmap_md5
JOIN users ON user_pinned.userid = users.id
WHERE user_pinned.userid = ? AND scores%[1]s.play_mode = ? AND %[2]s
ORDER BY user_pinned.pin_date DESC
`, dbs[playmode]) + common.Paginate(md.Query("p"), md.Query("l"), 100)
`, dbs[playmode], md.User.OnlyUserPublic(true)) + common.Paginate(md.Query("p"), md.Query("l"), 100)

rows, err := md.DB.Query(query, userid, mode)

Expand Down

0 comments on commit b3e38dc

Please sign in to comment.