2016-09-02 16:27:15 +00:00
|
|
|
package v1
|
|
|
|
|
2016-11-23 19:19:11 +00:00
|
|
|
import (
|
|
|
|
"strings"
|
|
|
|
|
2019-02-25 21:04:55 +00:00
|
|
|
"github.com/osuyozora/api/common"
|
2019-02-23 13:14:37 +00:00
|
|
|
"zxq.co/ripple/semantic-icons-ugc"
|
2016-11-23 19:19:11 +00:00
|
|
|
)
|
2016-09-02 16:27:15 +00:00
|
|
|
|
|
|
|
type donorInfoResponse struct {
|
|
|
|
common.ResponseBase
|
|
|
|
HasDonor bool `json:"has_donor"`
|
|
|
|
Expiration common.UnixTimestamp `json:"expiration"`
|
|
|
|
}
|
|
|
|
|
|
|
|
// UsersSelfDonorInfoGET returns information about the users' donor status
|
|
|
|
func UsersSelfDonorInfoGET(md common.MethodData) common.CodeMessager {
|
|
|
|
var r donorInfoResponse
|
|
|
|
var privileges uint64
|
|
|
|
err := md.DB.QueryRow("SELECT privileges, donor_expire FROM users WHERE id = ?", md.ID()).
|
|
|
|
Scan(&privileges, &r.Expiration)
|
|
|
|
if err != nil {
|
|
|
|
md.Err(err)
|
|
|
|
return Err500
|
|
|
|
}
|
|
|
|
r.HasDonor = common.UserPrivileges(privileges)&common.UserPrivilegeDonor > 0
|
|
|
|
r.Code = 200
|
|
|
|
return r
|
|
|
|
}
|
2016-09-27 21:13:55 +00:00
|
|
|
|
|
|
|
type favouriteModeResponse struct {
|
|
|
|
common.ResponseBase
|
|
|
|
FavouriteMode int `json:"favourite_mode"`
|
|
|
|
}
|
|
|
|
|
|
|
|
// UsersSelfFavouriteModeGET gets the current user's favourite mode
|
|
|
|
func UsersSelfFavouriteModeGET(md common.MethodData) common.CodeMessager {
|
|
|
|
var f favouriteModeResponse
|
|
|
|
f.Code = 200
|
|
|
|
if md.ID() == 0 {
|
|
|
|
return f
|
|
|
|
}
|
|
|
|
err := md.DB.QueryRow("SELECT users_stats.favourite_mode FROM users_stats WHERE id = ?", md.ID()).
|
|
|
|
Scan(&f.FavouriteMode)
|
|
|
|
if err != nil {
|
|
|
|
md.Err(err)
|
|
|
|
return Err500
|
|
|
|
}
|
|
|
|
return f
|
|
|
|
}
|
2016-11-06 21:51:21 +00:00
|
|
|
|
|
|
|
type userSettingsData struct {
|
2016-11-23 22:09:06 +00:00
|
|
|
UsernameAKA *string `json:"username_aka"`
|
|
|
|
FavouriteMode *int `json:"favourite_mode"`
|
2016-11-06 21:51:21 +00:00
|
|
|
CustomBadge struct {
|
|
|
|
singleBadge
|
|
|
|
Show *bool `json:"show"`
|
|
|
|
} `json:"custom_badge"`
|
|
|
|
PlayStyle *int `json:"play_style"`
|
|
|
|
}
|
|
|
|
|
|
|
|
// UsersSelfSettingsPOST allows to modify information about the current user.
|
|
|
|
func UsersSelfSettingsPOST(md common.MethodData) common.CodeMessager {
|
|
|
|
var d userSettingsData
|
2017-02-02 12:40:28 +00:00
|
|
|
md.Unmarshal(&d)
|
2016-11-21 15:59:17 +00:00
|
|
|
|
|
|
|
// input sanitisation
|
2016-11-23 22:09:06 +00:00
|
|
|
*d.UsernameAKA = common.SanitiseString(*d.UsernameAKA)
|
2016-11-23 19:19:11 +00:00
|
|
|
if md.User.UserPrivileges&common.UserPrivilegeDonor > 0 {
|
|
|
|
d.CustomBadge.Name = common.SanitiseString(d.CustomBadge.Name)
|
|
|
|
d.CustomBadge.Icon = sanitiseIconName(d.CustomBadge.Icon)
|
|
|
|
} else {
|
|
|
|
d.CustomBadge.singleBadge = singleBadge{}
|
|
|
|
d.CustomBadge.Show = nil
|
|
|
|
}
|
2016-11-21 15:59:17 +00:00
|
|
|
d.FavouriteMode = intPtrIn(0, d.FavouriteMode, 3)
|
|
|
|
|
2016-11-06 21:51:21 +00:00
|
|
|
q := new(common.UpdateQuery).
|
|
|
|
Add("s.username_aka", d.UsernameAKA).
|
|
|
|
Add("s.favourite_mode", d.FavouriteMode).
|
|
|
|
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)
|
|
|
|
_, 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)
|
|
|
|
return Err500
|
|
|
|
}
|
|
|
|
return UsersSelfSettingsGET(md)
|
|
|
|
}
|
|
|
|
|
2016-11-23 19:19:11 +00:00
|
|
|
func sanitiseIconName(s string) string {
|
|
|
|
classes := strings.Split(s, " ")
|
|
|
|
n := make([]string, 0, len(classes))
|
|
|
|
for _, c := range classes {
|
|
|
|
if !in(c, n) && in(c, semanticiconsugc.SaneIcons) {
|
|
|
|
n = append(n, c)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return strings.Join(n, " ")
|
|
|
|
}
|
|
|
|
|
|
|
|
func in(a string, b []string) bool {
|
|
|
|
for _, x := range b {
|
|
|
|
if x == a {
|
|
|
|
return true
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
|
2016-11-06 21:51:21 +00:00
|
|
|
type userSettingsResponse struct {
|
|
|
|
common.ResponseBase
|
|
|
|
ID int `json:"id"`
|
|
|
|
Username string `json:"username"`
|
2016-11-13 18:20:07 +00:00
|
|
|
Email string `json:"email"`
|
2016-12-11 17:38:36 +00:00
|
|
|
Flags uint `json:"flags"`
|
2016-11-06 21:51:21 +00:00
|
|
|
userSettingsData
|
|
|
|
}
|
|
|
|
|
|
|
|
// UsersSelfSettingsGET allows to get "sensitive" information about the current user.
|
|
|
|
func UsersSelfSettingsGET(md common.MethodData) common.CodeMessager {
|
|
|
|
var r userSettingsResponse
|
|
|
|
var ccb bool
|
|
|
|
r.Code = 200
|
|
|
|
err := md.DB.QueryRow(`
|
|
|
|
SELECT
|
|
|
|
u.id, u.username,
|
|
|
|
u.email, s.username_aka, s.favourite_mode,
|
|
|
|
s.show_custom_badge, s.custom_badge_icon,
|
|
|
|
s.custom_badge_name, s.can_custom_badge,
|
2016-12-11 17:38:36 +00:00
|
|
|
s.play_style, u.flags
|
2016-11-06 21:51:21 +00:00
|
|
|
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,
|
2016-12-11 17:38:36 +00:00
|
|
|
&r.PlayStyle, &r.Flags,
|
2016-11-06 21:51:21 +00:00
|
|
|
)
|
|
|
|
if err != nil {
|
|
|
|
md.Err(err)
|
|
|
|
return Err500
|
|
|
|
}
|
|
|
|
if !ccb {
|
|
|
|
r.CustomBadge = struct {
|
|
|
|
singleBadge
|
|
|
|
Show *bool `json:"show"`
|
|
|
|
}{}
|
|
|
|
}
|
|
|
|
return r
|
|
|
|
}
|
2016-11-21 15:59:17 +00:00
|
|
|
|
|
|
|
func intPtrIn(x int, y *int, z int) *int {
|
|
|
|
if y == nil {
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
if *y > z {
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
if *y < x {
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
return y
|
|
|
|
}
|