Merge branch 'master' of https://github.com/osuYozora/hanayo
This commit is contained in:
commit
164500d235
34 files changed
+2599
-50
No files matched your search
+107
@@ -0,0 +1,107 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"database/sql"
|
||||
"strconv"
|
||||
"strings"
|
||||
"regexp"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
func ccreate(c *gin.Context) {
|
||||
ccreateResp(c)
|
||||
}
|
||||
|
||||
func ccreateSubmit(c *gin.Context) {
|
||||
if getContext(c).User.ID == 0 {
|
||||
resp403(c)
|
||||
return
|
||||
}
|
||||
// check registrations are enabled
|
||||
if !ccreationEnabled() {
|
||||
ccreateResp(c, errorMessage{T(c, "Sorry, it's not possible to create a clan at the moment. Please try again later.")})
|
||||
return
|
||||
}
|
||||
|
||||
// check username is valid by our criteria
|
||||
username := strings.TrimSpace(c.PostForm("username"))
|
||||
if !cnameRegex.MatchString(username) {
|
||||
ccreateResp(c, errorMessage{T(c, "Your clans name must contain alphanumerical characters, spaces, or any of <code>_[]-</code>.")})
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
// check whether name already exists
|
||||
if db.QueryRow("SELECT 1 FROM clans WHERE name = ?", c.PostForm("username")).
|
||||
Scan(new(int)) != sql.ErrNoRows {
|
||||
ccreateResp(c, errorMessage{T(c, "A clan with that name already exists!")})
|
||||
return
|
||||
}
|
||||
|
||||
// check whether tag already exists
|
||||
if db.QueryRow("SELECT 1 FROM clans WHERE tag = ?", c.PostForm("tag")).
|
||||
Scan(new(int)) != sql.ErrNoRows {
|
||||
ccreateResp(c, errorMessage{T(c, "A clan with that tag already exists!")})
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
// recaptcha verify
|
||||
|
||||
tag := "0"
|
||||
if c.PostForm("tag") != "" {
|
||||
tag = c.PostForm("tag")
|
||||
}
|
||||
|
||||
// The actual registration.
|
||||
|
||||
res, err := db.Exec(`INSERT INTO clans(name, description, icon, tag)
|
||||
VALUES (?, ?, ?, ?);`,
|
||||
username, c.PostForm("password"), c.PostForm("email"), tag)
|
||||
if err != nil {
|
||||
ccreateResp(c, errorMessage{T(c, "Whoops, an error slipped in. Clan might have been created, though. I don't know.")})
|
||||
fmt.Println(err)
|
||||
return
|
||||
}
|
||||
lid, _ := res.LastInsertId()
|
||||
|
||||
db.Exec("INSERT INTO `user_clans`(user, clan, perms) VALUES (?, ?, 8);", getContext(c).User.ID, lid)
|
||||
|
||||
|
||||
|
||||
addMessage(c, successMessage{T(c, "Clan created.")})
|
||||
getSession(c).Save()
|
||||
c.Redirect(302, "/c/"+strconv.Itoa(int(lid)))
|
||||
}
|
||||
|
||||
func ccreateResp(c *gin.Context, messages ...message) {
|
||||
resp(c, 200, "clans/create.html", &baseTemplateData{
|
||||
TitleBar: "Create Clan",
|
||||
KyutGrill: "register.jpg",
|
||||
Scripts: []string{"https://www.google.com/recaptcha/api.js"},
|
||||
Messages: messages,
|
||||
FormData: normaliseURLValues(c.Request.PostForm),
|
||||
})
|
||||
}
|
||||
|
||||
func ccreationEnabled() bool {
|
||||
var enabled bool
|
||||
db.QueryRow("SELECT value_int FROM system_settings WHERE name = 'ccreation_enabled'").Scan(&enabled)
|
||||
return enabled
|
||||
}
|
||||
|
||||
// Check User In Query Is Same As User In Y Cookie
|
||||
|
||||
|
||||
func ccin(s string, ss []string) bool {
|
||||
for _, x := range ss {
|
||||
if x == s {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
var cnameRegex = regexp.MustCompile(`^[A-Za-z0-9 '_\[\]-]{2,15}$`)
|
||||
@@ -0,0 +1,302 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"database/sql"
|
||||
"strconv"
|
||||
"fmt"
|
||||
"github.com/gin-gonic/gin"
|
||||
"math/rand"
|
||||
"time"
|
||||
)
|
||||
|
||||
// TODO: replace with simple ResponseInfo containing userid
|
||||
type clanData struct {
|
||||
baseTemplateData
|
||||
ClanID int
|
||||
}
|
||||
|
||||
|
||||
func leaveClan(c *gin.Context) {
|
||||
i := c.Param("cid")
|
||||
// login check
|
||||
if getContext(c).User.ID == 0 {
|
||||
resp403(c)
|
||||
return
|
||||
}
|
||||
if db.QueryRow("SELECT 1 FROM user_clans WHERE user = ? AND clan = ? AND perms = 8", getContext(c).User.ID, i).
|
||||
Scan(new(int)) == sql.ErrNoRows {
|
||||
// check if a nigga the clan
|
||||
if db.QueryRow("SELECT 1 FROM user_clans WHERE user = ? AND clan = ?", getContext(c).User.ID, i).
|
||||
Scan(new(int)) == sql.ErrNoRows {
|
||||
addMessage(c, errorMessage{T(c, "Unexpected Error...")})
|
||||
return
|
||||
}
|
||||
// idk how the fuck this gonna work but fuck it
|
||||
|
||||
|
||||
db.Exec("DELETE FROM user_clans WHERE user = ? AND clan = ?", getContext(c).User.ID, i)
|
||||
addMessage(c, successMessage{T(c, "Left clan.")})
|
||||
getSession(c).Save()
|
||||
c.Redirect(302, "/c/"+i)
|
||||
} else {
|
||||
//check if user even in clan!!!
|
||||
if db.QueryRow("SELECT 1 FROM user_clans WHERE user = ? AND clan = ?", getContext(c).User.ID, i).
|
||||
Scan(new(int)) == sql.ErrNoRows {
|
||||
addMessage(c, errorMessage{T(c, "Unexpected Error...")})
|
||||
return
|
||||
}
|
||||
// delete invites
|
||||
db.Exec("DELETE FROM clans_invites WHERE clan = ?", i)
|
||||
// delete all members out of clan :c
|
||||
db.Exec("DELETE FROM user_clans WHERE clan = ?", i)
|
||||
// delete clan :c
|
||||
db.Exec("DELETE FROM clans WHERE id = ?", i)
|
||||
|
||||
addMessage(c, successMessage{T(c, "Disbanded Clan.")})
|
||||
getSession(c).Save()
|
||||
c.Redirect(302, "/clans?mode=0")
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
func clanPage(c *gin.Context) {
|
||||
var (
|
||||
clanID int
|
||||
clanName string
|
||||
clanDescription string
|
||||
clanIcon string
|
||||
)
|
||||
|
||||
// ctx := getContext(c)
|
||||
|
||||
i := c.Param("cid")
|
||||
if _, err := strconv.Atoi(i); err != nil {
|
||||
err := db.QueryRow("SELECT id, name, description, icon FROM clans WHERE name = ? LIMIT 1", i).Scan(&clanID, &clanName, &clanDescription, &clanIcon)
|
||||
if err != nil && err != sql.ErrNoRows {
|
||||
c.Error(err)
|
||||
}
|
||||
} else {
|
||||
err := db.QueryRow(`SELECT id, name, description, icon FROM clans WHERE id = ? LIMIT 1`, i).Scan(&clanID, &clanName, &clanDescription, &clanIcon)
|
||||
switch {
|
||||
case err == nil:
|
||||
case err == sql.ErrNoRows:
|
||||
err := db.QueryRow("SELECT id, name, description, icon FROM clans WHERE name = ? LIMIT 1", i).Scan(&clanID, &clanName, &clanDescription, &clanIcon)
|
||||
if err != nil && err != sql.ErrNoRows {
|
||||
c.Error(err)
|
||||
}
|
||||
default:
|
||||
c.Error(err)
|
||||
}
|
||||
}
|
||||
|
||||
data := new(clanData)
|
||||
data.ClanID = clanID
|
||||
defer resp(c, 200, "clansample.html", data)
|
||||
|
||||
if data.ClanID == 0 {
|
||||
data.TitleBar = "Clan not found"
|
||||
data.Messages = append(data.Messages, warningMessage{T(c, "That clan could not be found.")})
|
||||
return
|
||||
}
|
||||
|
||||
if getContext(c).User.Privileges&1 > 0 {
|
||||
if db.QueryRow("SELECT 1 FROM clans WHERE clan = ?", clanID).Scan(new(string)) != sql.ErrNoRows {
|
||||
var bg string
|
||||
db.QueryRow("SELECT background FROM clans WHERE id = ?", clanID).Scan(&bg)
|
||||
data.KyutGrill = bg
|
||||
data.KyutGrillAbsolute = true
|
||||
}
|
||||
}
|
||||
|
||||
data.TitleBar = T(c, "%s's Clan Page", clanName)
|
||||
data.DisableHH = true
|
||||
// data.Scripts = append(data.Scripts, "/static/profile.js")
|
||||
}
|
||||
|
||||
func checkCount(rows *sql.Rows) (count int) {
|
||||
for rows.Next() {
|
||||
err:= rows.Scan(&count)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
return count
|
||||
}
|
||||
|
||||
var letters = []rune("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ")
|
||||
|
||||
func randSeq(n int) string {
|
||||
rand.Seed(time.Now().UnixNano()+int64(3))
|
||||
b := make([]rune, n)
|
||||
for i := range b {
|
||||
b[i] = letters[rand.Intn(len(letters))]
|
||||
}
|
||||
return string(b)
|
||||
}
|
||||
|
||||
func createInvite(c *gin.Context) {
|
||||
ctx := getContext(c)
|
||||
if string(c.PostForm("password")) == "" && string(c.PostForm("email")) == "" && string(c.PostForm("tag")) == "" && string(c.PostForm("bg")) == "" {
|
||||
|
||||
|
||||
if ctx.User.ID == 0 {
|
||||
resp403(c)
|
||||
return
|
||||
}
|
||||
// big perms check lol ok
|
||||
var perms int
|
||||
db.QueryRow("SELECT perms FROM user_clans WHERE user = ? AND perms = 8 LIMIT 1", ctx.User.ID).Scan(&perms)
|
||||
// delete old invite
|
||||
var clan int
|
||||
db.QueryRow("SELECT clan FROM user_clans WHERE user = ? AND perms = 8 LIMIT 1", ctx.User.ID).Scan(&clan)
|
||||
if clan == 0 {
|
||||
resp403(c)
|
||||
return
|
||||
}
|
||||
|
||||
db.Exec("DELETE FROM clans_invites WHERE clan = ?", clan)
|
||||
|
||||
var s string
|
||||
|
||||
s = randSeq(8)
|
||||
|
||||
db.Exec("INSERT INTO clans_invites(clan, invite) VALUES (?, ?)", clan, s)
|
||||
} else {
|
||||
// big perms check lol ok
|
||||
var perms int
|
||||
db.QueryRow("SELECT perms FROM user_clans WHERE user = ? AND perms = 8 LIMIT 1", ctx.User.ID).Scan(&perms)
|
||||
// delete old invite
|
||||
var clan int
|
||||
db.QueryRow("SELECT clan FROM user_clans WHERE user = ? AND perms = 8 LIMIT 1", ctx.User.ID).Scan(&clan)
|
||||
if clan == 0 {
|
||||
resp403(c)
|
||||
return
|
||||
}
|
||||
|
||||
tag := "0"
|
||||
if c.PostForm("tag") != "" {
|
||||
tag = c.PostForm("tag")
|
||||
}
|
||||
|
||||
if db.QueryRow("SELECT 1 FROM clans WHERE tag = ? AND id != ?", c.PostForm("tag"), clan).
|
||||
Scan(new(int)) != sql.ErrNoRows {
|
||||
resp403(c)
|
||||
addMessage(c, errorMessage{T(c, "A clan with that tag already exists...")})
|
||||
return
|
||||
}
|
||||
|
||||
db.Exec("UPDATE clans SET description = ?, icon = ?, tag = ?, background = ? WHERE id = ?", c.PostForm("password"), c.PostForm("email"), tag, c.PostForm("bg"), clan)
|
||||
}
|
||||
addMessage(c, successMessage{T(c, "Success")})
|
||||
getSession(c).Save()
|
||||
c.Redirect(302, "/settings/clansettings")
|
||||
}
|
||||
|
||||
|
||||
func clanInvite(c *gin.Context) {
|
||||
i := c.Param("inv")
|
||||
|
||||
res := resolveInvite(i)
|
||||
s := strconv.Itoa(res)
|
||||
if res != 0 {
|
||||
|
||||
// check if a nigga logged in
|
||||
if getContext(c).User.ID == 0 {
|
||||
resp403(c)
|
||||
return
|
||||
}
|
||||
|
||||
// restricted stuff
|
||||
if getContext(c).User.Privileges & 1 != 1 {
|
||||
resp403(c)
|
||||
return
|
||||
}
|
||||
|
||||
// check if clan even exists?
|
||||
if db.QueryRow("SELECT 1 FROM clans WHERE id = ?", res).
|
||||
Scan(new(int)) == sql.ErrNoRows {
|
||||
|
||||
addMessage(c, errorMessage{T(c, "Clan doesn't exist.")})
|
||||
getSession(c).Save()
|
||||
c.Redirect(302, "/c/"+s)
|
||||
return
|
||||
}
|
||||
// check if a nigga in a clan already
|
||||
if db.QueryRow("SELECT 1 FROM user_clans WHERE user = ?", getContext(c).User.ID).
|
||||
Scan(new(int)) != sql.ErrNoRows {
|
||||
|
||||
addMessage(c, errorMessage{T(c, "Seems like you're already in a Clan")})
|
||||
getSession(c).Save()
|
||||
c.Redirect(302, "/c/"+s)
|
||||
return
|
||||
}
|
||||
|
||||
// idk how the fuck this gonna work but fuck it
|
||||
var count int
|
||||
var limit int
|
||||
// members check
|
||||
db.QueryRow("SELECT COUNT(*) FROM user_clans WHERE clan = ? ", res).Scan(&count)
|
||||
db.QueryRow("SELECT mlimit FROM clans WHERE id = ? ", res).Scan(&limit)
|
||||
if count >= limit {
|
||||
addMessage(c, errorMessage{T(c, "Sorry, this clan is full.")})
|
||||
getSession(c).Save()
|
||||
c.Redirect(302, "/c/"+s)
|
||||
return
|
||||
}
|
||||
// join
|
||||
db.Exec("INSERT INTO `user_clans`(user, clan, perms) VALUES (?, ?, 1);", getContext(c).User.ID, res)
|
||||
addMessage(c, successMessage{T(c, "Joined clan.")})
|
||||
getSession(c).Save()
|
||||
c.Redirect(302, "/c/"+s)
|
||||
} else {
|
||||
resp403(c)
|
||||
addMessage(c, errorMessage{T(c, "nah nigga")})
|
||||
}
|
||||
}
|
||||
|
||||
func clanKick(c *gin.Context) {
|
||||
if getContext(c).User.ID == 0 {
|
||||
resp403(c)
|
||||
return
|
||||
}
|
||||
|
||||
if db.QueryRow("SELECT 1 FROM user_clans WHERE user = ? AND perms = 8", getContext(c).User.ID).
|
||||
Scan(new(int)) == sql.ErrNoRows {
|
||||
resp403(c)
|
||||
return
|
||||
}
|
||||
|
||||
member, err := strconv.ParseInt(c.PostForm("member"), 10, 32)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
}
|
||||
if member == 0 {
|
||||
resp403(c)
|
||||
return
|
||||
}
|
||||
|
||||
if db.QueryRow("SELECT 1 FROM user_clans WHERE user = ? AND perms = 1", member).
|
||||
Scan(new(int)) == sql.ErrNoRows {
|
||||
resp403(c)
|
||||
return
|
||||
}
|
||||
|
||||
db.Exec("DELETE FROM user_clans WHERE user = ?", member)
|
||||
addMessage(c, successMessage{T(c, "Success.")})
|
||||
getSession(c).Save()
|
||||
c.Redirect(302, "/settings/clansettings")
|
||||
}
|
||||
|
||||
func resolveInvite(c string)(int) {
|
||||
var clanid int
|
||||
row := db.QueryRow("SELECT clan FROM clans_invites WHERE invite = ?", c)
|
||||
err := row.Scan(&clanid)
|
||||
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
}
|
||||
fmt.Println(clanid)
|
||||
return clanid
|
||||
}
|
||||
+1
-1
@@ -190,7 +190,7 @@ func blogRedirect(c *gin.Context) {
|
||||
a := c.Param("url")
|
||||
red := blogRedirectMap[a]
|
||||
if red == "" {
|
||||
red = "https://blog.ripple.moe"
|
||||
red = "https://medium.com/@yozora"
|
||||
}
|
||||
c.Redirect(301, red)
|
||||
}
|
||||
@@ -278,7 +278,13 @@ func generateEngine() *gin.Engine {
|
||||
r.GET("/register/verify", verifyAccount)
|
||||
r.GET("/register/welcome", welcome)
|
||||
|
||||
r.GET("/clans/create", ccreate)
|
||||
r.POST("/clans/create", ccreateSubmit)
|
||||
r.GET("/c/:cid", clanPage)
|
||||
|
||||
r.GET("/u/:user", userProfile)
|
||||
r.GET("/rx/u/:user", relaxProfile)
|
||||
r.GET("/ap/u/:user", autoProfile)
|
||||
r.GET("/b/:bid", beatmapInfo)
|
||||
|
||||
r.POST("/pwreset", passwordReset)
|
||||
@@ -303,6 +309,8 @@ func generateEngine() *gin.Engine {
|
||||
r.POST("/settings/2fa/totp", totpSetup)
|
||||
r.GET("/settings/discord/finish", discordFinish)
|
||||
r.POST("/settings/profbackground/:type", profBackground)
|
||||
r.POST("/settings/clansettings", createInvite)
|
||||
r.POST("settings/clansettings/k", clanKick)
|
||||
|
||||
r.POST("/dev/tokens/create", createAPIToken)
|
||||
r.POST("/dev/tokens/delete", deleteAPIToken)
|
||||
@@ -317,14 +325,12 @@ func generateEngine() *gin.Engine {
|
||||
r.GET("/oauth/token", oauth.Token)
|
||||
r.POST("/oauth/token", oauth.Token)
|
||||
|
||||
r.GET("/clans/invite/:inv", clanInvite)
|
||||
|
||||
r.GET("/donate/rates", btcconversions.GetRates)
|
||||
|
||||
r.Any("/blog/*url", blogRedirect)
|
||||
|
||||
r.GET("/help", func(c *gin.Context) {
|
||||
c.Redirect(301, "https://support.ripple.moe")
|
||||
})
|
||||
|
||||
loadSimplePages(r)
|
||||
|
||||
r.NoRoute(notFound)
|
||||
|
||||
+119
@@ -73,3 +73,122 @@ func userProfile(c *gin.Context) {
|
||||
data.DisableHH = true
|
||||
data.Scripts = append(data.Scripts, "/static/profile.js")
|
||||
}
|
||||
func relaxProfile(c *gin.Context) {
|
||||
var (
|
||||
userID int
|
||||
username string
|
||||
privileges uint64
|
||||
)
|
||||
|
||||
ctx := getContext(c)
|
||||
|
||||
u := c.Param("user")
|
||||
if _, err := strconv.Atoi(u); err != nil {
|
||||
err := db.QueryRow("SELECT id, username, privileges FROM users WHERE username = ? AND "+ctx.OnlyUserPublic()+" LIMIT 1", u).Scan(&userID, &username, &privileges)
|
||||
if err != nil && err != sql.ErrNoRows {
|
||||
c.Error(err)
|
||||
}
|
||||
} else {
|
||||
err := db.QueryRow(`SELECT id, username, privileges FROM users WHERE id = ? AND `+ctx.OnlyUserPublic()+` LIMIT 1`, u).Scan(&userID, &username, &privileges)
|
||||
switch {
|
||||
case err == nil:
|
||||
case err == sql.ErrNoRows:
|
||||
err := db.QueryRow(`SELECT id, username, privileges FROM users WHERE username = ? AND `+ctx.OnlyUserPublic()+` LIMIT 1`, u).Scan(&userID, &username, &privileges)
|
||||
if err != nil && err != sql.ErrNoRows {
|
||||
c.Error(err)
|
||||
}
|
||||
default:
|
||||
c.Error(err)
|
||||
}
|
||||
}
|
||||
|
||||
data := new(profileData)
|
||||
data.UserID = userID
|
||||
|
||||
defer resp(c, 200, "profile_relax.html", data)
|
||||
|
||||
if data.UserID == 0 {
|
||||
data.TitleBar = "User not found"
|
||||
data.Messages = append(data.Messages, warningMessage{T(c, "That user could not be found.")})
|
||||
return
|
||||
}
|
||||
|
||||
if common.UserPrivileges(privileges)&common.UserPrivilegeDonor > 0 {
|
||||
var profileBackground struct {
|
||||
Type int
|
||||
Value string
|
||||
}
|
||||
db.Get(&profileBackground, "SELECT type, value FROM profile_backgrounds WHERE uid = ?", data.UserID)
|
||||
switch profileBackground.Type {
|
||||
case 1:
|
||||
data.KyutGrill = "/static/profbackgrounds/" + profileBackground.Value
|
||||
data.KyutGrillAbsolute = true
|
||||
case 2:
|
||||
data.SolidColour = profileBackground.Value
|
||||
}
|
||||
}
|
||||
|
||||
data.TitleBar = T(c, "%s's profile", username)
|
||||
data.DisableHH = true
|
||||
data.Scripts = append(data.Scripts, "/static/profile_relax.js")
|
||||
}
|
||||
|
||||
func autoProfile(c *gin.Context) {
|
||||
var (
|
||||
userID int
|
||||
username string
|
||||
privileges uint64
|
||||
)
|
||||
|
||||
ctx := getContext(c)
|
||||
|
||||
u := c.Param("user")
|
||||
if _, err := strconv.Atoi(u); err != nil {
|
||||
err := db.QueryRow("SELECT id, username, privileges FROM users WHERE username = ? AND "+ctx.OnlyUserPublic()+" LIMIT 1", u).Scan(&userID, &username, &privileges)
|
||||
if err != nil && err != sql.ErrNoRows {
|
||||
c.Error(err)
|
||||
}
|
||||
} else {
|
||||
err := db.QueryRow(`SELECT id, username, privileges FROM users WHERE id = ? AND `+ctx.OnlyUserPublic()+` LIMIT 1`, u).Scan(&userID, &username, &privileges)
|
||||
switch {
|
||||
case err == nil:
|
||||
case err == sql.ErrNoRows:
|
||||
err := db.QueryRow(`SELECT id, username, privileges FROM users WHERE username = ? AND `+ctx.OnlyUserPublic()+` LIMIT 1`, u).Scan(&userID, &username, &privileges)
|
||||
if err != nil && err != sql.ErrNoRows {
|
||||
c.Error(err)
|
||||
}
|
||||
default:
|
||||
c.Error(err)
|
||||
}
|
||||
}
|
||||
|
||||
data := new(profileData)
|
||||
data.UserID = userID
|
||||
|
||||
defer resp(c, 200, "profile_auto.html", data)
|
||||
|
||||
if data.UserID == 0 {
|
||||
data.TitleBar = "User not found"
|
||||
data.Messages = append(data.Messages, warningMessage{T(c, "That user could not be found.")})
|
||||
return
|
||||
}
|
||||
|
||||
if common.UserPrivileges(privileges)&common.UserPrivilegeDonor > 0 {
|
||||
var profileBackground struct {
|
||||
Type int
|
||||
Value string
|
||||
}
|
||||
db.Get(&profileBackground, "SELECT type, value FROM profile_backgrounds WHERE uid = ?", data.UserID)
|
||||
switch profileBackground.Type {
|
||||
case 1:
|
||||
data.KyutGrill = "/static/profbackgrounds/" + profileBackground.Value
|
||||
data.KyutGrillAbsolute = true
|
||||
case 2:
|
||||
data.SolidColour = profileBackground.Value
|
||||
}
|
||||
}
|
||||
|
||||
data.TitleBar = T(c, "%s's profile", username)
|
||||
data.DisableHH = true
|
||||
data.Scripts = append(data.Scripts, "/static/profile_auto.js")
|
||||
}
|
||||
+1
-1
@@ -96,7 +96,7 @@ func registerSubmit(c *gin.Context) {
|
||||
|
||||
errr := db.QueryRow("SELECT id FROM beta_keys WHERE key_md5 = ? AND allowed = 1", cmd5(c.PostForm("key")))
|
||||
if errr.Scan(new(int)) == sql.ErrNoRows {
|
||||
registerResp(c, errorMessage{T(c, "key bad.")})
|
||||
registerResp(c, errorMessage{T(c, "Your Invitation Code is invalid. Please use the form below to obtain one.")})
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,2 @@
|
||||
.map{width:100%;min-height:145px;display:inline-block;background:#fff;overflow:hidden;position:relative;border-radius:20px;-webkit-transition:.3s;transition:.3s;box-shadow:0 0 10px 0 rgba(0,0,0,.75)}.bodySearching{margin-top:10px;background-color:rgba(0,0,0,.25);border-radius:10px;padding:25px 10px}.status{font-weight:500;z-index:3;position:absolute;-webkit-transform:translateY(-100px) translateX(5px);transform:translateY(-100px) translateX(5px);padding:2px 10px;color:#fff;margin-left:5px;border-radius:20px;background:rgba(0,0,0,.6)}.name{font-size:1.3em;-webkit-transform:translateY(-59px) translateX(7px);transform:translateY(-59px) translateX(7px);font-weight:600}.artist,.name{color:#fff;position:absolute;text-shadow:0 0 12px #000;margin-left:10px}.artist{font-size:1.1em;font-weight:500;-webkit-transform:translateY(-31px) translateX(7px);transform:translateY(-31px) translateX(7px)}.map:hover{box-shadow:0 0 10px 0 #fff}.map-header{cursor:pointer;display:block;overflow:hidden;box-shadow:0 0 10px 0 rgba(0,0,0,.75)}.map-header,.map-header img{border-top-left-radius:20px;border-top-right-radius:20px;width:100%;height:130px}.map-header img{position:absolute;background:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAZAAAABkCAMAAACfFZZFAAABlVBMVEU0PEE1PUImLDAzO0AlKy8yOj8kKi4uNToxOT4tNDknLjIvNjswNzw2PkMoLzMrMjYqMTUrMjcnLTEpMDQmLTEyOT40PUIiKCwjKS0sMzclLDAwOD0xOD0sMzguNjovNzszOz8nLTIyOj4xOT0tNDgsNDgpLzQoLjMkKy8uNTkqMTYmLDEzOj8oLjIqMDU0PEA0O0AvNzwtNTkjKCw1PUM0PEIoLzQwODwlKzApMDUvNjorMzcuNjskKy4yOz8zPEArMTYmLTAqMDQtNToiJys1PkMsMjc1PUEtMzgoLzI1PEEzOkAnLjElLC8lKi4uNDkmKzAzPEEpLzMnLjM2P0Q0PUElKi8jKi4xOD4kKS0zO0E0O0EkKi8sNDkjKS42PkQwNz0wNzswOT0yOT8kKi0oLTIxOj4pMDMqMjYmLC8kKS4nLDEgJSk1PEIqLzQvODw2PUIhJyswNjsyOT0iKSw1PkIjKi0iKC0gJyopMTUqMTQrMTUjKC02P0M3P0QgJiozOT8xODwnLTAvNjw2PkIiJywjKSwILjsNAAALBklEQVR4Xu2d1Y/suNZHvQ1hhmJmhmamg8wwyHCZmfn7u29V98y8XMn2+XRGo5GzpH772VlWVFE68d5BHGANJ8DJCoK5/8+kCqhygfluNTTLSMYIiF0Mhy2QSDI9vFmbyBlVzLC6XIAKqmJgia2qXoyiMoiz3b2nnWGAe0SUnc8ez4ZmTEMJgdQan+nVKT4CBVSFgK2Z87adEl9rC48SDurAysCsiAiiVsJYfUnaNBYKMRqT7Y9IbkPTQQFV8TH0RlTIb/af3MSCKDha+4Z7+AO4kWvOgJs8xKiq5fMPa/deDgVCuWkMWyc/1F3X1gxQQJUPFK13cb5QKFy/g0o14GetQ7e8e4iNGrRpmuMkG3R3uJ40v1nWz0VnmRJUaw9q9fTnOwEooMoHmvpBvrBmsxLu84eSqHJj1iwm3WMCiQ7cCyi59Cnk+wwbXCEwe1vp2xsl80HXtbECqiKwU7wamtev9flDGxaDy1VSAl6Vk4VrzYZ2NSk+SRz+KqvhVqqtVlnq3ihjooAqH0hs88uh9WqPP5RYxtZPx6tVagSaJicL9pg82Lz0iRq4wl9lN9hKC6tV0q67xHMFVPlAMJto+bVP6bR5G/jZZOiat6uJE+QY5bnnWiV2dn3tc33DKRG+gI0RufgZ1f2lG3qggCofaGtGvZDP57VKnTJBtoMRuIcUAQTRT7jJnR66k1+xf7fpC3zIg84NOCnoLrS0OiigKgB8ylgx6BBHG4IobFnE3TUBiprBz7KBj+rf9x0UJwuRQF3T4VaRua3SPiigKuRWqAXOW7+MtY54JOnvhU77UZPuCrJg4ESvVMy9aJJDAqD28E7NcEbHMyVUxUA5xhgHqcTIHNL7GEfFe8IszDsRxtYGkvCBT32MH3tLUENVDAAiCHLSWQC55GIul0S5SwFQVVWejIyMjIyMjIyMN/7iX5AUZ8XJTBUmt/vjfpGJjcDwrWRHJzJGt5wgivbrEjpzvZc0/QrHXS1VsKll2uaU6iASLx575rUixm2xEfnecaAf+QOP5AQ6XySl8JoZH/uckEqqYP+2Nrc79jsHwnf0Pi2DC4BCzRAu875FUtM0iBfxc9stOkKuC2DQGUddIdV7VG/RwmaBGnWNbfO3CKQuu80QgiAS+RTHKNxc8SfUPANuctoDpNcQAqbZnKQyqtBpoj3r6IcHfbroH/KEwDvbAvPHt11AhDp8IVJy9LzuTQ/ynUqpwfOpUAZIe0UAQdHiTKqMKnimXWCsYJBXus49DMGr/GTIdAfBTsgVgjIm4z/8Zcd6/v3Sehgn2V0f066nJoEy5p06VVQh0jt7YBTKv8GhnfDcGW4Dyn3Yyo8BRiP+KuvnhG64O5Zb0xqJzclCGANCW8+Dv9WhhXlbc9RQfe1z2ZD/hQTPZX4h76+PWV+mHdEvRBVVuL2+2tkf1PqDhSe42vnyF+a9N35hVkX16/uBgdz9QJUhBCOpW5f85uafgxeR6NYllrt1UUYV7M8OTu3OAbLf9M29YZrGO14ifXN/wZlUJVU4uvqfcqCL1O/ePPZMvTjGEs8OiHfsHx35VPzvr5GUQt2MtTNuTCVVmFT742ev8dTlHUAS1GdRIvmAaCdpnvFPshKq36VHqJmqmIyMjIyMjIyMjG9+b+9CesPsOi3DNtwlCEAB1Te9+30bHXnSW8qbGD+7hiTcgfkY46dLUEZVXMnQtiWLLmjolB8198pSRRe7JpUtumh/PDoOFFAVAyFtsWrQaciWJZXNLbmypKXvO+h7kmVJ1XVZ0gyUUBXXGL59WQ1nD4SFe6WvC/csfuFe76vCPZSE8oV7gyUooMoHRl/Vi+KFuLT10euWtv5nKFXa+sevS1sVUM3q1L9t1ayTw3dHNet18u2rvvluQGOpFjsbr9NiR1+32DHWLXaUURV3djp9k02owqsmVFqNDIRNqKz/aUKlgCq/9xn6xE5PQ4k2bf5gCZOKVJu26O+Tjx2ZNm3bLbpPYJeArumggKoQcEolvzt6MP4ExNnuIPKr3kDcyHBxMfCq1alU5UF6f3DR9ce0BiqoigFSG8UjG4FMlnX2Y/8fElFoF+P926mMzjZa+nEwbIBSqlnf3m9HVRkyMjIyMjIytuWT3/jhM1WARovJvaNHrEXWSbksQ1KTAmlxkuqpgj3F5/j+0bbY20zw+Z5XkTCCib+aFAdMmIV2/BjjpMtZp1qqdwOtakzS7vE+EkCsx6bR2g20jli9QqcOY7ueuN3kNW3mpIaOI8ZJKaQKPmVGPI3bpBQIhKwpugErHE341IbREJn9aQd13mvlBFsE7C1YgXYiTkwdVTC0tPY7ukl/PWRamScPw70FlBMH0NaQEoFP/BRFb2uaht8NPL4Q7roouJijHMJdTlIZVQh7jYKfFirFAgtG3KFRF0D/he4CQljwE2F7hv8Z63kTbcZKvJJu+Lh0mkMligCBPkYcVFGFZxu6dmoUyi9o5yjiV1SvT3VKekUE+z5wfZxzQm/+dcd63n1JxnVOFqoeIMQatpWCgRnioIgqNHWTotVQwEV+z4GTy/5BH04KFhK2R1iO71Fz3R5Bl2qPAK5/3YEWbm0jDmqoQhyW87usYLTzy6rHdcc2QGVaZgyBVeUmoY0b02ir98z1EoLLnCwMI0DI94mBwOHu2VBFFWp76Knmf+A/tBAe8vd5eQDD37/volxKRa8gx0MjHzejWf6jGubE1lNVgFD6BBBcxDxzdVSTAM0KhUKMfIy4QkwbuqhMELy4L/BBcKC1HFoo0DrTNrhZOEvm0DIQ+rdgi4Ayqtuf0otJw2AkGLRBpF5cuJD7VZLMxffhmr0wjFOHBjlBdPrPCmzBvMvfIqCQKrS8wTSYUisVv6MfUy+OaEAAiQCT4jge065QHY1oFHs/wP/iJdVSvVvphN0K2haro3o1fJQCkvzI6aHUp0shHYbV+oKbVEj19d/R55Ac0pPmRElVVDMyMjIyMjIyMjIytkE+m5POQg5JA9vKqIoB1HqLScrD3DAaADLnjRgGkZwUmNFCoIiqeODQ83pefCSTJUWv1/OCCgiT6Vm/1+v7TObcLeP1rOYTUEFVzPRx7eSEmQ/3xTpGybLZpBxopvhJ9+ytCSs/pbvicxdqN417rVqpSRRQFQJxE9W9JK4Q6ouESCkAV5+BWxf0e4aKVlv4kVVF1ZdMJGBqhos8Z/VnKaAqAuoLine truncated
|
||||
/*# sourceMappingURL=main.dfc480ea.chunk.css.map */
|
||||
Vendored
+1
-1
@@ -42,4 +42,4 @@ w.hide())},show:function(e){if(e=e||function(){},w.debug("Showing pop-up",C.tran
|
||||
e.each(n,function(n,i){if(e.isArray(i.results)&&(r=p.search.object(t,i.results,o)[0]))return!1})):(p.debug("Finding result in results object",t),r=p.search.object(t,n,o)[0]),r||!1}},select:{firstResult:function(){p.verbose("Selecting first result"),j.first().addClass(g.active)}},set:{focus:function(){T.addClass(g.focus)},loading:function(){T.addClass(g.loading)},value:function(e){p.verbose("Setting search input value",e),S.val(e)},type:function(e){e=e||h.type,"category"==h.type&&T.addClass(h.type)},buttonPressed:function(){A.addClass(g.pressed)}},remove:{loading:function(){T.removeClass(g.loading)},focus:function(){T.removeClass(g.focus)},buttonPressed:function(){A.removeClass(g.pressed)}},query:function(){var t=p.get.value(),n=p.read.cache(t);p.has.minimumCharacters()?(n?(p.debug("Reading result from cache",t),p.save.results(n.results),p.addResults(n.html),p.inject.id(n.results)):(p.debug("Querying for",t),e.isPlainObject(h.source)||e.isArray(h.source)?p.search.local(t):p.can.useAPI()?p.search.remote(t):p.error(x.source)),h.onSearchQuery.call(D,t)):p.hideResults()},search:{local:function(e){var t,n=p.search.object(e,h.content);p.set.loading(),p.save.results(n),p.debug("Returned local search results",n),t=p.generateResults({results:n}),p.remove.loading(),p.addResults(t),p.inject.id(n),p.write.cache(e,{html:t,results:n})},remote:function(e){T.api("is loading")&&T.api("abort"),p.setup.api(e),T.api("query")},object:function(t,n,o){var r=[],a=[],s=t.toString().replace(v.escape,"\\$&"),l=new RegExp(v.beginsWith+s,"i"),c=function(t,n){var i=e.inArray(n,r)==-1,o=e.inArray(n,a)==-1;i&&o&&t.push(n)};return n=n||h.source,o=o!==i?o:h.searchFields,e.isArray(o)||(o=[o]),n===i||n===!1?(p.error(x.source),[]):(e.each(o,function(i,o){e.each(n,function(e,n){var i="string"==typeof n[o];i&&(n[o].search(l)!==-1?c(r,n):h.searchFullText&&p.fuzzySearch(t,n[o])&&c(a,n))})}),e.merge(r,a))}},fuzzySearch:function(e,t){var n=t.length,i=e.length;if("string"!=typeof e)return!1;if(e=e.toLowerCase(),t=t.toLowerCase(),i>n)return!1;if(i===n)return e===t;e:for(var o=0,r=0;o<i;o++){for(var a=e.charCodeAt(o);r<n;)if(t.charCodeAt(r++)===a)continue e;return!1}return!0},parse:{response:function(e,t){var n=p.generateResults(e);p.verbose("Parsing server response",e),e!==i&&t!==i&&e[b.results]!==i&&(p.addResults(n),p.inject.id(e[b.results]),p.write.cache(t,{html:n,results:e[b.results]}),p.save.results(e[b.results]))}},cancel:{query:function(){p.can.useAPI()&&T.api("abort")}},has:{minimumCharacters:function(){var e=p.get.value(),t=e.length;return t>=h.minCharacters}},clear:{cache:function(e){var t=T.data(m.cache);e?e&&t&&t[e]&&(p.debug("Removing value from cache",e),delete t[e],T.data(m.cache,t)):(p.debug("Clearing cache",e),T.removeData(m.cache))}},read:{cache:function(e){var t=T.data(m.cache);return!!h.cache&&(p.verbose("Checking cache for generated html for query",e),"object"==typeof t&&t[e]!==i&&t[e])}},create:{id:function(e,t){var n,o,r=e+1;return t!==i?(n=String.fromCharCode(97+t),o=n+r,p.verbose("Creating category result id",o)):(o=r,p.verbose("Creating result id",o)),o},results:function(){0===E.length&&(E=e("<div />").addClass(g.results).appendTo(T))}},inject:{result:function(e,t,n){p.verbose("Injecting result into results");var o=n!==i?E.children().eq(n).children(y.result).eq(t):E.children(y.result).eq(t);p.verbose("Injecting results metadata",o),o.data(m.result,e)},id:function(t){p.debug("Injecting unique ids into results");var n=0,o=0;return"category"===h.type?e.each(t,function(t,r){o=0,e.each(r.results,function(e,t){var a=r.results[e];a.id===i&&(a.id=p.create.id(o,n)),p.inject.result(a,o,n),o++}),n++}):e.each(t,function(e,n){var r=t[e];r.id===i&&(r.id=p.create.id(o)),p.inject.result(r,o),o++}),t}},save:{results:function(e){p.verbose("Saving current search results to metadata",e),T.data(m.results,e)}},write:{cache:function(e,t){var n=T.data(m.cache)!==i?T.data(m.cache):{};h.cache&&(p.verbose("Writing generated html to cache",e,t),n[e]=t,T.data(m.cache,n))}},addResults:function(t){return e.isFunction(h.onResultsAdd)&&h.onResultsAdd.call(E,t)===!1?(p.debug("onResultsAdd callback cancelled default action"),!1):void(t?(E.html(t),p.refreshResults(),h.selectFirstResult&&p.select.firstResult(),p.showResults()):p.hideResults())},showResults:function(){p.is.visible()||(p.can.transition()?(p.debug("Showing results with css animations"),E.transition({animation:h.transition+" in",debug:h.debug,verbose:h.verbose,duration:h.duration,queue:!0})):(p.debug("Showing results with javascript"),E.stop().fadeIn(h.duration,h.easing)),h.onResultsOpen.call(E))},hideResults:function(){p.is.visible()&&(p.can.transition()?(p.debug("Hiding results with css animations"),E.transition({animation:h.transition+" out",debug:h.debug,verbose:h.verbose,duration:h.duration,queue:!0})):(p.debug("Hiding results with javascript"),E.stop().fadeOut(h.duration,h.easing)),h.onResultsClose.call(E))},generateResults:function(t){p.debug("Generating html from response",t);var n=h.templateLine truncated
|
||||
var t=a.filter("[data-"+C.tab+'^="'+e+'/"]').eq(0),n=t.data(C.tab)||!1;if(n){if(b.debug("Found default tab",n),D<x.maxDepth)return D++,b.get.defaultPath(n);b.error(T.recursion)}else b.debug("No default tabs found for",e,g);return D=0,e},navElement:function(e){return e=e||m,a.filter("[data-"+C.tab+'="'+e+'"]')},tabElement:function(e){var t,n,i,o;return e=e||m,i=b.utilities.pathToArray(e),o=b.utilities.last(i),t=g.filter("[data-"+C.tab+'="'+e+'"]'),n=g.filter("[data-"+C.tab+'="'+o+'"]'),t.length>0?t:n},tab:function(){return m}},utilities:{filterArray:function(t,n){return e.grep(t,function(t){return e.inArray(t,n)==-1})},last:function(t){return!!e.isArray(t)&&t[t.length-1]},pathToArray:function(e){return e===i&&(e=m),"string"==typeof e?e.split("/"):[e]},arrayToPath:function(t){return!!e.isArray(t)&&t.join("/")}},setting:function(t,n){if(b.debug("Changing setting",t,n),e.isPlainObject(t))e.extend(!0,x,t);else{if(n===i)return x[t];e.isPlainObject(x[t])?e.extend(!0,x[t],n):x[t]=n}},internal:function(t,n){if(e.isPlainObject(t))e.extend(!0,b,t);else{if(n===i)return b[t];b[t]=n}},debug:function(){!x.silent&&x.debug&&(x.performance?b.performance.log(arguments):(b.debug=Function.prototype.bind.call(console.info,console,x.name+":"),b.debug.apply(console,arguments)))},verbose:function(){!x.silent&&x.verbose&&x.debug&&(x.performance?b.performance.log(arguments):(b.verbose=Function.prototype.bind.call(console.info,console,x.name+":"),b.verbose.apply(console,arguments)))},error:function(){x.silent||(b.error=Function.prototype.bind.call(console.error,console,x.name+":"),b.error.apply(console,arguments))},performance:{log:function(e){var t,n,i;x.performance&&(t=(new Date).getTime(),i=l||t,n=t-i,l=t,c.push({Name:e[0],Arguments:[].slice.call(e,1)||"",Element:O,"Execution Time":n})),clearTimeout(b.performance.timer),b.performance.timer=setTimeout(b.performance.display,500)},display:function(){var t=x.name+":",n=0;l=!1,clearTimeout(b.performance.timer),e.each(c,function(e,t){n+=t["Execution Time"]}),t+=" "+n+"ms",s&&(t+=" '"+s+"'"),(console.group!==i||console.table!==i)&&c.length>0&&(console.groupCollapsed(t),console.table?console.table(c):e.each(c,function(e,t){console.log(t.Name+": "+t["Execution Time"]+"ms")}),console.groupEnd()),c=[]}},invoke:function(t,n,o){var a,s,l,c=P;return n=n||f,o=O||o,"string"==typeof t&&c!==i&&(t=t.split(/[\. ]/),a=t.length-1,e.each(t,function(n,o){var r=n!=a?o+t[n+1].charAt(0).toUpperCase()+t[n+1].slice(1):t;if(e.isPlainObject(c[r])&&n!=a)c=c[r];else{if(c[r]!==i)return s=c[r],!1;if(!e.isPlainObject(c[o])||n==a)return c[o]!==i?(s=c[o],!1):(b.error(T.method,t),!1);c=c[o]}})),e.isFunction(s)?l=s.apply(o,n):s!==i&&(l=s),e.isArray(r)?r.push(l):r!==i?r=[r,l]:l!==i&&(r=l),s}},d?(P===i&&b.initialize(),b.invoke(u)):(P!==i&&P.invoke("destroy"),b.initialize())}),r!==i?r:this},e.tab=function(){e(t).tab.apply(this,arguments)},e.fn.tab.settings={name:"Tab",namespace:"tab",silent:!1,debug:!1,verbose:!1,performance:!0,auto:!1,history:!1,historyType:"hash",path:!1,context:!1,childrenOnly:!1,maxDepth:25,deactivate:"siblings",alwaysRefresh:!1,cache:!0,cacheType:"response",ignoreFirstLoad:!1,apiSettings:!1,evaluateScripts:"once",onFirstLoad:function(e,t,n){},onLoad:function(e,t,n){},onVisible:function(e,t,n){},onRequest:function(e,t,n){},templates:{determineTitle:function(e){}},error:{api:"You attempted to load content without API module",method:"The method you called is not defined",missingTab:"Activated tab cannot be found. Tabs are case-sensitive.",noContent:"The tab you specified is missing a content url.",path:"History enabled, but no path was specified",recursion:"Max recursive depth reached",legacyInit:"onTabInit has been renamed to onFirstLoad in 2.0, please adjust your code.",legacyLoad:"onTabLoad has been renamed to onLoad in 2.0. Please adjust your code",state:"History requires Asual's Address library <https://github.com/asual/jquery-address>"},metadata:{tab:"tab",loaded:"loaded",promise:"promise"},className:{loading:"loading",active:"active"},selector:{tabs:".ui.tab",ui:".ui"}}}(jQuery,window,document),function(e,t,n,i){"use strict";t="undefined"!=typeof t&&t.Math==Math?t:"undefined"!=typeof self&&self.Math==Math?self:Function("return this")(),e.fn.transition=function(){var o,r=e(this),a=r.selector||"",s=(new Date).getTime(),l=[],c=arguments,u=c[0],d=[].slice.call(arguments,1),f="string"==typeof u;return t.requestAnimationFrame||t.mozRequestAnimationFrame||t.webkitRequestAnimationFrame||t.msRequestAnimationFrame||function(e){setTimeout(e,0)},r.each(function(t){var p,h,g,m,v,b,y,x,w,C=e(this),k=this;w={initialize:function(){p=w.get.settings.apply(k,c),m=p.className,g=p.error,v=p.metadata,x="."+p.namespace,y="module-"+p.namespace,h=C.data(y)||w,b=w.get.animationEndEvent(),f&&(f=w.invoke(u)),f===!1&&(w.verbose("Converted arguments into settings object",p),p.interval?w.delay(p.animate):w.animate(),w.instantiate())},instantiate:function(){w.verbose("Storing instance of module",w),h=w,C.data(y,h)},destroy:functLine truncated
|
||||
return"aborted"==t?(m.debug("XHR Aborted (Most likely caused by page navigation or CORS Policy)",t,n),v.onAbort.call(R,t,S,e),!0):("invalid"==t?m.debug("JSON did not pass success test. A server-side error has most likely occurred",o):"error"==t&&e!==i&&(m.debug("XHR produced a server error",t,n),200!=e.status&&n!==i&&""!==n&&m.error(w.statusMessage+n,r.url),v.onError.call(R,a,S,e)),v.errorDuration&&"aborted"!==t&&(m.debug("Adding error state"),m.set.error(),m.should.removeError()&&setTimeout(m.remove.error,v.errorDuration)),m.debug("API Request failed",a,e),void v.onFailure.call(R,o,S,e))}}},create:{request:function(){return e.Deferred().always(m.event.request.complete).done(m.event.request.done).fail(m.event.request.fail)},mockedXHR:function(){var t,n,i,o=!1,r=!1,a=!1,s=v.mockResponse||v.response,l=v.mockResponseAsync||v.responseAsync;return i=e.Deferred().always(m.event.xhr.complete).done(m.event.xhr.done).fail(m.event.xhr.fail),s?(e.isFunction(s)?(m.debug("Using specified synchronous callback",s),n=s.call(R,f)):(m.debug("Using settings specified response",s),n=s),i.resolveWith(R,[n,o,{responseText:n}])):e.isFunction(l)&&(t=function(e){m.debug("Async callback returned response",e),e?i.resolveWith(R,[e,o,{responseText:e}]):i.rejectWith(R,[{responseText:e},r,a])},m.debug("Using specified async response callback",l),l.call(R,f,t)),i},xhr:function(){var t;return t=e.ajax(r).always(m.event.xhr.always).done(m.event.xhr.done).fail(m.event.xhr.fail),m.verbose("Created server request",t,r),t}},set:{error:function(){m.verbose("Adding error state to element",E),E.addClass(C.error)},loading:function(){m.verbose("Adding loading state to element",E),E.addClass(C.loading),g=(new Date).getTime()}},remove:{error:function(){m.verbose("Removing error state from element",E),E.removeClass(C.error)},loading:function(){m.verbose("Removing loading state from element",E),E.removeClass(C.loading)}},get:{responseFromXHR:function(t){return!!e.isPlainObject(t)&&(m.is.expectingJSON()?m.decode.json(t.responseText):t.responseText)},errorFromRequest:function(t,n,o){return e.isPlainObject(t)&&t.error!==i?t.error:v.error[n]!==i?v.error[n]:o},request:function(){return m.request||!1},xhr:function(){return m.xhr||!1},settings:function(){var t;return t=v.beforeSend.call(R,v),t&&(t.success!==i&&(m.debug("Legacy success callback detected",t),m.error(w.legacyParameters,t.success),t.onSuccess=t.success),t.failure!==i&&(m.debug("Legacy failure callback detected",t),m.error(w.legacyParameters,t.failure),t.onFailure=t.failure),t.complete!==i&&(m.debug("Legacy complete callback detected",t),m.error(w.legacyParameters,t.complete),t.onComplete=t.complete)),t===i&&m.error(w.noReturnedValue),t===!1?t:t!==i?e.extend(!0,{},t):e.extend(!0,{},v)},urlEncodedValue:function(e){var n=t.decodeURIComponent(e),i=t.encodeURIComponent(e),o=n!==e;return o?(m.debug("URL value is already encoded, avoiding double encoding",e),e):(m.verbose("Encoding value using encodeURIComponent",e,i),i)},defaultData:function(){var t={};return e.isWindow(j)||(m.is.input()?t.value=S.val():m.is.form()||(t.text=S.text())),t},event:function(){return e.isWindow(j)||"now"==v.on?(m.debug("API called without element, no events attached"),!1):"auto"==v.on?S.is("input")?j.oninput!==i?"input":j.onpropertychange!==i?"propertychange":"keyup":S.is("form")?"submit":"click":v.on},templatedURL:function(e){if(e=e||S.data(y.action)||v.action||!1,p=S.data(y.url)||v.url||!1)return m.debug("Using specified url",p),p;if(e){if(m.debug("Looking up url for action",e,v.api),v.api[e]===i&&!m.is.mocked())return void m.error(w.missingAction,v.action,v.api);p=v.api[e]}else m.is.form()&&(p=S.attr("action")||E.attr("action")||!1,m.debug("No url or action specified, defaulting to form action",p));return p}},abort:function(){var e=m.get.xhr();e&&"resolved"!==e.state()&&(m.debug("Cancelling API request"),e.abort())},reset:function(){m.remove.error(),m.remove.loading()},setting:function(t,n){if(m.debug("Changing setting",t,n),e.isPlainObject(t))e.extend(!0,v,t);else{if(n===i)return v[t];e.isPlainObject(v[t])?e.extend(!0,v[t],n):v[t]=n}},internal:function(t,n){if(e.isPlainObject(t))e.extend(!0,m,t);else{if(n===i)return m[t];m[t]=n}},debug:function(){!v.silent&&v.debug&&(v.performance?m.performance.log(arguments):(m.debug=Function.prototype.bind.call(console.info,console,v.name+":"),m.debug.apply(console,arguments)))},verbose:function(){!v.silent&&v.verbose&&v.debug&&(v.performance?m.performance.log(arguments):(m.verbose=Function.prototype.bind.call(console.info,console,v.name+":"),m.verbose.apply(console,arguments)))},error:function(){v.silent||(m.error=Function.prototype.bind.call(console.error,console,v.name+":"),m.error.apply(console,arguments))},performance:{log:function(e){var t,n,i;v.performance&&(t=(new Date).getTime(),i=s||t,n=t-i,s=t,l.push({Name:e[0],Arguments:[].slice.call(e,1)||"","Execution Time":n})),clearTimeout(m.performance.timer),m.performance.timer=setTimeout(m.performance.display,500)},display:function()Line truncated
|
||||
"string"!=typeof a&&(a=e(a)),a||(this.logger.warn("missed to pass in variable "+r[1]+" for interpolating "+t),a=""),t=t.replace(r[0],a),this.regexp.lastIndex=0;return t},t}(),H=function(e){function t(n,i,o){var r=arguments.length>3&&void 0!==arguments[3]?arguments[3]:{};w(this,t);var a=T(this,e.call(this));return a.backend=n,a.store=i,a.services=o,a.options=r,a.logger=j.create("backendConnector"),a.state={},a.queue=[],a.backend&&a.backend.init&&a.backend.init(o,r.backend,r),a}return k(t,e),t.prototype.queueLoad=function(e,t,n){var i=this,o=[],r=[],a=[],s=[];return e.forEach(function(e){var n=!0;t.forEach(function(t){var a=e+"|"+t;i.store.hasResourceBundle(e,t)?i.state[a]=2:i.state[a]<0||(1===i.state[a]?r.indexOf(a)<0&&r.push(a):(i.state[a]=1,n=!1,r.indexOf(a)<0&&r.push(a),o.indexOf(a)<0&&o.push(a),s.indexOf(t)<0&&s.push(t)))}),n||a.push(e)}),(o.length||r.length)&&this.queue.push({pending:r,loaded:{},errors:[],callback:n}),{toLoad:o,pending:r,toLoadLanguages:a,toLoadNamespaces:s}},t.prototype.loaded=function(e,t,n){var i=this,r=e.split("|"),a=S(r,2),s=a[0],l=a[1];t&&this.emit("failedLoading",s,l,t),n&&this.store.addResourceBundle(s,l,n),this.state[e]=t?-1:2,this.queue.forEach(function(n){o(n.loaded,[s],l),m(n.pending,e),t&&n.errors.push(t),0!==n.pending.length||n.done||(i.emit("loaded",n.loaded),n.errors.length?n.callback(n.errors):n.callback(),n.done=!0)}),this.queue=this.queue.filter(function(e){return!e.done})},t.prototype.read=function(e,t,n,i,o,r){var a=this;return i||(i=0),o||(o=250),e.length?void this.backend[n](e,t,function(s,l){return s&&l&&i<5?void setTimeout(function(){a.read.call(a,e,t,n,++i,2*o,r)},o):void r(s,l)}):r(null,{})},t.prototype.load=function(e,t,n){var i=this;if(!this.backend)return this.logger.warn("No backend was added via i18next.use. Will not load resources."),n&&n();var o=C({},this.backend.options,this.options.backend);"string"==typeof e&&(e=this.services.languageUtils.toResolveHierarchy(e)),"string"==typeof t&&(t=[t]);var a=this.queueLoad(e,t,n);if(!a.toLoad.length)return void(a.pending.length||n());if(o.allowMultiLoading&&this.backend.readMulti)this.read(a.toLoadLanguages,a.toLoadNamespaces,"readMulti",null,null,function(e,t){e&&i.logger.warn("loading namespaces "+a.toLoadNamespaces.join(", ")+" for languages "+a.toLoadLanguages.join(", ")+" via multiloading failed",e),!e&&t&&i.logger.log("loaded namespaces "+a.toLoadNamespaces.join(", ")+" for languages "+a.toLoadLanguages.join(", ")+" via multiloading",t),a.toLoad.forEach(function(n){var o=n.split("|"),a=S(o,2),s=a[0],l=a[1],c=r(t,[s,l]);if(c)i.loaded(n,e,c);else{var u="loading namespace "+l+" for language "+s+" via multiloading failed";i.loaded(n,u),i.logger.error(u)}})});else{var s=function(e){var t=this,n=e.split("|"),i=S(n,2),o=i[0],r=i[1];this.read(o,r,"read",null,null,function(n,i){n&&t.logger.warn("loading namespace "+r+" for language "+o+" failed",n),!n&&i&&t.logger.log("loaded namespace "+r+" for language "+o,i),t.loaded(e,n,i)})};a.toLoad.forEach(function(e){s.call(i,e)})}},t.prototype.reload=function(e,t){var n=this;this.backend||this.logger.warn("No backend was added via i18next.use. Will not load resources.");var i=C({},this.backend.options,this.options.backend);if("string"==typeof e&&(e=this.services.languageUtils.toResolveHierarchy(e)),"string"==typeof t&&(t=[t]),i.allowMultiLoading&&this.backend.readMulti)this.read(e,t,"readMulti",null,null,function(i,o){i&&n.logger.warn("reloading namespaces "+t.join(", ")+" for languages "+e.join(", ")+" via multiloading failed",i),!i&&o&&n.logger.log("reloaded namespaces "+t.join(", ")+" for languages "+e.join(", ")+" via multiloading",o),e.forEach(function(e){t.forEach(function(t){var a=r(o,[e,t]);if(a)n.loaded(e+"|"+t,i,a);else{var s="reloading namespace "+t+" for language "+e+" via multiloading failed";n.loaded(e+"|"+t,s),n.logger.error(s)}})})});else{var o=function(e){var t=this,n=e.split("|"),i=S(n,2),o=i[0],r=i[1];this.read(o,r,"read",null,null,function(n,i){n&&t.logger.warn("reloading namespace "+r+" for language "+o+" failed",n),!n&&i&&t.logger.log("reloaded namespace "+r+" for language "+o,i),t.loaded(e,n,i)})};e.forEach(function(e){t.forEach(function(t){o.call(n,e+"|"+t)})})}},t.prototype.saveMissing=function(e,t,n,i){this.backend&&this.backend.create&&this.backend.create(e,t,n,i),e&&e[0]&&this.store.addResource(e[0],t,n,i)},t}(R),$=function(e){function t(n,i,o){var r=arguments.length>3&&void 0!==arguments[3]?arguments[3]:{};w(this,t);var a=T(this,e.call(this));return a.cache=n,a.store=i,a.services=o,a.options=r,a.logger=j.create("cacheConnector"),a.cache&&a.cache.init&&a.cache.init(o,r.cache,r),a}return k(t,e),t.prototype.load=function(e,t,n){var i=this;if(!this.cache)return n&&n();var o=C({},this.cache.options,this.options.cache);"string"==typeof e&&(e=this.services.languageUtils.toResolveHierarchy(e)),"string"==typeof t&&(t=[t]),o.enabled?this.cache.load(e,function(t,o){if(t&&i.logger.error("loading languages "+e.join(", ")+" from cache failed",t),o)for(var r
Line truncated
|
||||
"string"!=typeof a&&(a=e(a)),a||(this.logger.warn("missed to pass in variable "+r[1]+" for interpolating "+t),a=""),t=t.replace(r[0],a),this.regexp.lastIndex=0;return t},t}(),H=function(e){function t(n,i,o){var r=arguments.length>3&&void 0!==arguments[3]?arguments[3]:{};w(this,t);var a=T(this,e.call(this));return a.backend=n,a.store=i,a.services=o,a.options=r,a.logger=j.create("backendConnector"),a.state={},a.queue=[],a.backend&&a.backend.init&&a.backend.init(o,r.backend,r),a}return k(t,e),t.prototype.queueLoad=function(e,t,n){var i=this,o=[],r=[],a=[],s=[];return e.forEach(function(e){var n=!0;t.forEach(function(t){var a=e+"|"+t;i.store.hasResourceBundle(e,t)?i.state[a]=2:i.state[a]<0||(1===i.state[a]?r.indexOf(a)<0&&r.push(a):(i.state[a]=1,n=!1,r.indexOf(a)<0&&r.push(a),o.indexOf(a)<0&&o.push(a),s.indexOf(t)<0&&s.push(t)))}),n||a.push(e)}),(o.length||r.length)&&this.queue.push({pending:r,loaded:{},errors:[],callback:n}),{toLoad:o,pending:r,toLoadLanguages:a,toLoadNamespaces:s}},t.prototype.loaded=function(e,t,n){var i=this,r=e.split("|"),a=S(r,2),s=a[0],l=a[1];t&&this.emit("failedLoading",s,l,t),n&&this.store.addResourceBundle(s,l,n),this.state[e]=t?-1:2,this.queue.forEach(function(n){o(n.loaded,[s],l),m(n.pending,e),t&&n.errors.push(t),0!==n.pending.length||n.done||(i.emit("loaded",n.loaded),n.errors.length?n.callback(n.errors):n.callback(),n.done=!0)}),this.queue=this.queue.filter(function(e){return!e.done})},t.prototype.read=function(e,t,n,i,o,r){var a=this;return i||(i=0),o||(o=250),e.length?void this.backend[n](e,t,function(s,l){return s&&l&&i<5?void setTimeout(function(){a.read.call(a,e,t,n,++i,2*o,r)},o):void r(s,l)}):r(null,{})},t.prototype.load=function(e,t,n){var i=this;if(!this.backend)return this.logger.warn("No backend was added via i18next.use. Will not load resources."),n&&n();var o=C({},this.backend.options,this.options.backend);"string"==typeof e&&(e=this.services.languageUtils.toResolveHierarchy(e)),"string"==typeof t&&(t=[t]);var a=this.queueLoad(e,t,n);if(!a.toLoad.length)return void(a.pending.length||n());if(o.allowMultiLoading&&this.backend.readMulti)this.read(a.toLoadLanguages,a.toLoadNamespaces,"readMulti",null,null,function(e,t){e&&i.logger.warn("loading namespaces "+a.toLoadNamespaces.join(", ")+" for languages "+a.toLoadLanguages.join(", ")+" via multiloading failed",e),!e&&t&&i.logger.log("loaded namespaces "+a.toLoadNamespaces.join(", ")+" for languages "+a.toLoadLanguages.join(", ")+" via multiloading",t),a.toLoad.forEach(function(n){var o=n.split("|"),a=S(o,2),s=a[0],l=a[1],c=r(t,[s,l]);if(c)i.loaded(n,e,c);else{var u="loading namespace "+l+" for language "+s+" via multiloading failed";i.loaded(n,u),i.logger.error(u)}})});else{var s=function(e){var t=this,n=e.split("|"),i=S(n,2),o=i[0],r=i[1];this.read(o,r,"read",null,null,function(n,i){n&&t.logger.warn("loading namespace "+r+" for language "+o+" failed",n),!n&&i&&t.logger.log("loaded namespace "+r+" for language "+o,i),t.loaded(e,n,i)})};a.toLoad.forEach(function(e){s.call(i,e)})}},t.prototype.reload=function(e,t){var n=this;this.backend||this.logger.warn("No backend was added via i18next.use. Will not load resources.");var i=C({},this.backend.options,this.options.backend);if("string"==typeof e&&(e=this.services.languageUtils.toResolveHierarchy(e)),"string"==typeof t&&(t=[t]),i.allowMultiLoading&&this.backend.readMulti)this.read(e,t,"readMulti",null,null,function(i,o){i&&n.logger.warn("reloading namespaces "+t.join(", ")+" for languages "+e.join(", ")+" via multiloading failed",i),!i&&o&&n.logger.log("reloaded namespaces "+t.join(", ")+" for languages "+e.join(", ")+" via multiloading",o),e.forEach(function(e){t.forEach(function(t){var a=r(o,[e,t]);if(a)n.loaded(e+"|"+t,i,a);else{var s="reloading namespace "+t+" for language "+e+" via multiloading failed";n.loaded(e+"|"+t,s),n.logger.error(s)}})})});else{var o=function(e){var t=this,n=e.split("|"),i=S(n,2),o=i[0],r=i[1];this.read(o,r,"read",null,null,function(n,i){n&&t.logger.warn("reloading namespace "+r+" for language "+o+" failed",n),!n&&i&&t.logger.log("reloaded namespace "+r+" for language "+o,i),t.loaded(e,n,i)})};e.forEach(function(e){t.forEach(function(t){o.call(n,e+"|"+t)})})}},t.prototype.saveMissing=function(e,t,n,i){this.backend&&this.backend.create&&this.backend.create(e,t,n,i),e&&e[0]&&this.store.addResource(e[0],t,n,i)},t}(R),$=function(e){function t(n,i,o){var r=arguments.length>3&&void 0!==arguments[3]?arguments[3]:{};w(this,t);var a=T(this,e.call(this));return a.cache=n,a.store=i,a.services=o,a.options=r,a.logger=j.create("cacheConnector"),a.cache&&a.cache.init&&a.cache.init(o,r.cache,r),a}return k(t,e),t.prototype.load=function(e,t,n){var i=this;if(!this.cache)return n&&n();var o=C({},this.cache.options,this.options.cache);"string"==typeof e&&(e=this.services.languageUtils.toResolveHierarchy(e)),"string"==typeof t&&(t=[t]),o.enabled?this.cache.load(e,function(t,o){if(t&&i.logger.error("loading languages "+e.join(", ")+" from cache failed",t),o)for(var r
Line truncated
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 3.6 MiB |
@@ -0,0 +1,2 @@
|
||||
(window.webpackJsonp=window.webpackJsonp||[]).push([[1],[function(e,t,n){"use strict";e.exports=n(14)},function(e,t,n){"use strict";function r(e){if(void 0===e)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return e}n.d(t,"a",function(){return r})},function(e,t,n){"use strict";var r=Object.getOwnPropertySymbols,o=Object.prototype.hasOwnProperty,i=Object.prototype.propertyIsEnumerable;e.exports=function(){try{if(!Object.assign)return!1;var e=new String("abc");if(e[5]="de","5"===Object.getOwnPropertyNames(e)[0])return!1;for(var t={},n=0;n<10;n++)t["_"+String.fromCharCode(n)]=n;if("0123456789"!==Object.getOwnPropertyNames(t).map(function(e){return t[e]}).join(""))return!1;var r={};return"abcdefghijklmnopqrst".split("").forEach(function(e){r[e]=e}),"abcdefghijklmnopqrst"===Object.keys(Object.assign({},r)).join("")}catch(o){return!1}}()?Object.assign:function(e,t){for(var n,l,a=function(e){if(null===e||void 0===e)throw new TypeError("Object.assign cannot be called with null or undefined");return Object(e)}(e),u=1;u<arguments.length;u++){for(var c in n=Object(arguments[u]))o.call(n,c)&&(a[c]=n[c]);if(r){l=r(n);for(var s=0;s<l.length;s++)i.call(n,l[s])&&(a[l[s]]=n[l[s]])}}return a}},function(e,t){var n;n=function(){return this}();try{n=n||Function("return this")()||(0,eval)("this")}catch(r){"object"===typeof window&&(n=window)}e.exports=n},function(e,t,n){(function(t){var n="Expected a function",r=NaN,o="[object Symbol]",i=/^\s+|\s+$/g,l=/^[-+]0x[0-9a-f]+$/i,a=/^0b[01]+$/i,u=/^0o[0-7]+$/i,c=parseInt,s="object"==typeof t&&t&&t.Object===Object&&t,f="object"==typeof self&&self&&self.Object===Object&&self,d=s||f||Function("return this")(),p=Object.prototype.toString,m=Math.max,h=Math.min,y=function(){return d.Date.now()};function v(e){var t=typeof e;return!!e&&("object"==t||"function"==t)}function g(e){if("number"==typeof e)return e;if(function(e){return"symbol"==typeof e||function(e){return!!e&&"object"==typeof e}(e)&&p.call(e)==o}(e))return r;if(v(e)){var t="function"==typeof e.valueOf?e.valueOf():e;e=v(t)?t+"":t}if("string"!=typeof e)return 0===e?e:+e;e=e.replace(i,"");var n=a.test(e);return n||u.test(e)?c(e.slice(2),n?2:8):l.test(e)?r:+e}e.exports=function(e,t,r){var o,i,l,a,u,c,s=0,f=!1,d=!1,p=!0;if("function"!=typeof e)throw new TypeError(n);function b(t){var n=o,r=i;return o=i=void 0,s=t,a=e.apply(r,n)}function k(e){var n=e-c;return void 0===c||n>=t||n<0||d&&e-s>=l}function w(){var e=y();if(k(e))return T(e);u=setTimeout(w,function(e){var n=t-(e-c);return d?h(n,l-(e-s)):n}(e))}function T(e){return u=void 0,p&&o?b(e):(o=i=void 0,a)}function x(){var e=y(),n=k(e);if(o=arguments,i=this,c=e,n){if(void 0===u)return function(e){return s=e,u=setTimeout(w,t),f?b(e):a}(c);if(d)return u=setTimeout(w,t),b(c)}return void 0===u&&(u=setTimeout(w,t)),a}return t=g(t)||0,v(r)&&(f=!!r.leading,l=(d="maxWait"in r)?m(g(r.maxWait)||0,t):l,p="trailing"in r?!!r.trailing:p),x.cancel=function(){void 0!==u&&clearTimeout(u),s=0,o=c=i=u=void 0},x.flush=function(){return void 0===u?a:T(y())},x}}).call(this,n(3))},function(e,t,n){"use strict";!function e(){if("undefined"!==typeof __REACT_DEVTOOLS_GLOBAL_HOOK__&&"function"===typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE)try{__REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE(e)}catch(t){console.error(t)}}(),e.exports=n(15)},function(e,t,n){"use strict";function r(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}n.d(t,"a",function(){return r})},function(e,t,n){"use strict";function r(e,t){for(var n=0;n<t.length;n++){var r=t[n];r.enumerable=r.enumerable||!1,r.configurable=!0,"value"in r&&(r.writable=!0),Object.defineProperty(e,r.key,r)}}function o(e,t,n){return t&&r(e.prototype,t),n&&r(e,n),e}n.d(t,"a",function(){return o})},function(e,t,n){"use strict";function r(e){return(r=Object.setPrototypeOf?Object.getPrototypeOf:function(e){return e.__proto__||Object.getPrototypeOf(e)})(e)}n.d(t,"a",function(){return r})},function(e,t,n){"use strict";var r=n(20).DebounceInput;r.DebounceInput=r,e.exports=r},function(e,t,n){e.exports=function(e,t,n){"use strict";var r="default"in e?e.default:e;t=t&&t.hasOwnProperty("default")?t.default:t,n=n&&n.hasOwnProperty("default")?n.default:n;var o=function(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")},i=function(){function e(e,t){for(var n=0;n<t.length;n++){var r=t[n];r.enumerable=r.enumerable||!1,r.configurable=!0,"value"in r&&(r.writable=!0),Object.defineProperty(e,r.key,r)}}return function(t,n,r){return n&&e(t.prototype,n),r&&e(t,r),t}}(),l=function(e,t){if(!e)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return!t||"object"!==typeof t&&"function"!==typeof t?e:t},a=function(e){function t(e){o(this,t);var r=l(this,(t.__proto__||Object.getPrototypeOf(t)).call(this,e));return e.debounce?r.handleOnScroll=n(r.handleOnScroll.bind(r),e.debounce,{trailing:!0}):r.handleOnScroll=r.handleOnScroll.bind(r),r}return function(e,t){if("functioLine truncated
|
||||
//# sourceMappingURL=1.7e1ca608.chunk.js.map
|
||||
@@ -0,0 +1,2 @@
|
||||
(window.webpackJsonp = window.webpackJsonp || []).push([[0], { 13: function (e, t, a) { e.exports = a(26) }, 18: function (e, t, a) { }, 21: function (e, t, a) { }, 26: function (e, t, a) { "use strict"; a.r(t); var s = a(0), n = a.n(s), i = a(5), r = a.n(i), c = (a(18), a(6)), l = a(7), o = a(11), u = a(8), m = a(12), d = a(1), h = a(9), f = function (e) { if (e.status >= 200 && e.status < 300) return e; var t = new Error("HTTP Error ".concat(e.statusText)); throw t.status = e.statusText, t.response = e, console.log(t), t }, k = function (e) { return e.json() }, p = { api_beatmaps_request: function (e, t) { return fetch("https://cg.mxr.lol/api/".concat(e), { method: "get", cache: "default" }).then(f).then(k).then(t) } }, b = (a(21), a(10)), v = a.n(b), E = function (e) { function t(e) { var a; return Object(c.a)(this, t), (a = Object(o.a)(this, Object(u.a)(t).call(this, e))).renderDummyData = function () { var e = a.state.beatmaps.map(function (e, t) { var s = e.ChildrenBeatmaps.map(function (e, t) { return n.a.createElement("div", { key: e.BeatmapID, className: "diff2" }, n.a.createElement("div", { className: "faa fal fa-extra-mode-" + a.getGameMode(e.Mode), style: { color: a.getDiffColor(e.DifficultyRating) } })) }); return n.a.createElement("div", { className: "eight wide column", key: e.SetID }, n.a.createElement("div", { className: "map" }, n.a.createElement("div", { className: "map-header" }, n.a.createElement("a", { href: "/b/" + e.ChildrenBeatmaps[e.ChildrenBeatmaps.length - 1].BeatmapID }, n.a.createElement("img", { src: "https://assets.ppy.sh/beatmaps/" + e.ChildrenBeatmaps[0].ParentSetID + "/covers/card.jpg", alt: "" }))), n.a.createElement("div", { className: "status" }, a.getRankStatus(e.RankedStatus)), n.a.createElement("div", { className: "name" }, e.Title.substring(0, 35)), n.a.createElement("div", { className: "artist" }, e.Artist.substring(0, 35)), n.a.createElement("div", { className: "creator" }, "by ", e.Creator), n.a.createElement("a", { title: "Download beatmap", href: "https://storage.yozora.pw/d/" + e.ChildrenBeatmaps[e.ChildrenBeatmaps.length - 1].ParentSetID, className: "download" }, n.a.createElement("i", { className: "download disk icon" })), n.a.createElement("div", { id: "alldiff" }, s))) }); return n.a.createElement("div", { className: "ui stackable two grid", onScrollCapture: a.scrollListener }, e, n.a.createElement(v.a, { onBottom: a.scrollListener })) }, a.state = { offset: 100, count: 22, query: "", mode: 0, loading: !0, status: 1 }, a.renderDummyData.bind(Object(d.a)(Object(d.a)(a))), a.scrollListener = a.scrollListener.bind(Object(d.a)(Object(d.a)(a))), a.reCallApi = a.reCallApi.bind(Object(d.a)(Object(d.a)(a))), a.queryNew = a.queryNew.bind(Object(d.a)(Object(d.a)(a))), a } return Object(m.a)(t, e), Object(l.a)(t, [{ key: "componentDidMount", value: function () { var e = this; p.api_beatmaps_request("search?offset=" + this.state.offset + "&amount=" + this.state.count + "&mode=" + this.state.mode + "&status=" + this.state.status + "&query=" + this.state.query, function (t) { e.setState({ loading: !1, beatmaps: t }) }) } }, { key: "reCallApi", value: function () { var e = this; this.setState({ loading: !0 }), p.api_beatmaps_request("search?offset=" + this.state.offset + "&amount=" + this.state.count + "&mode=" + this.state.mode + "&status=" + this.state.status + "&query=" + this.state.query, function (t) { e.setState({ loading: !1, beatmaps: t }) }) } }, { key: "getDiffColor", value: function (e) { return e <= 1.5 ? "#8AAE17" : e > 1.5 && e <= 2.25 ? "#9AD4DF" : e > 2.25 && e <= 3.75 ? "#DEB32A" : e > 3.75 && e <= 5.25 ? "#EB69A4" : e > 5.25 && e <= 6.75 ? "#7264B5" : "#050505" } }, { key: "getRankStatus", value: function (e) { switch (e) { case 0: return "PENDING"; case 1: return "RANKED"; case 3: return "APPROVED"; case 4: return "Loved"; default: return "UNKNOWN" } } }, { key: "getGameMode", value: function (e) { switch (e) { case 0: return "osu"; case 1: return "taiko"; case 2: return "fruits"; case 3: return "mania"; default: return "osu" } } }, { key: "scrollListener", value: function () { var e = this; this.setState({ offset: this.state.offset + 22 }), p.api_beatmaps_request("search?offset=" + this.state.offset + "&amount=" + this.state.count + "&mode=" + this.state.mode + "&status=" + this.state.status + "&query=" + this.state.query, function (t) { for (var a = e.state.beatmaps, s = 0; s < t.length; s++)a.push(t[s]); e.setState({ beatmaps: a }) }) } }, { key: "switchMode", value: function (e) { var t = this, a = Number(e.target.dataset.modeosu); this.setState({ mode: a, offset: 0 }, function () { t.reCallApi() }) } }, { key: "switchRank", value: function (e) { var t = this, a = Number(e.target.dataset.rankstatus); this.setState({ status: a, offset: 0 }, function () { t.reCallApi() }) } }, { key: "queryNew", value: function (e) { var t = this, a = e.target.value; this.setState({ query: a, offset: 0 }, function () { t.reCallApi() }) } }, { key: "render", value: fLine truncated
|
||||
//# sourceMappingURL=main.faace68d.chunk.js.map
|
||||
@@ -0,0 +1,2 @@
|
||||
!function(e){function r(r){for(var n,f,i=r[0],l=r[1],a=r[2],c=0,s=[];c<i.length;c++)f=i[c],o[f]&&s.push(o[f][0]),o[f]=0;for(n in l)Object.prototype.hasOwnProperty.call(l,n)&&(e[n]=l[n]);for(p&&p(r);s.length;)s.shift()();return u.push.apply(u,a||[]),t()}function t(){for(var e,r=0;r<u.length;r++){for(var t=u[r],n=!0,i=1;i<t.length;i++){var l=t[i];0!==o[l]&&(n=!1)}n&&(u.splice(r--,1),e=f(f.s=t[0]))}return e}var n={},o={2:0},u=[];function f(r){if(n[r])return n[r].exports;var t=n[r]={i:r,l:!1,exports:{}};return e[r].call(t.exports,t,t.exports,f),t.l=!0,t.exports}f.m=e,f.c=n,f.d=function(e,r,t){f.o(e,r)||Object.defineProperty(e,r,{enumerable:!0,get:t})},f.r=function(e){"undefined"!==typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},f.t=function(e,r){if(1&r&&(e=f(e)),8&r)return e;if(4&r&&"object"===typeof e&&e&&e.__esModule)return e;var t=Object.create(null);if(f.r(t),Object.defineProperty(t,"default",{enumerable:!0,value:e}),2&r&&"string"!=typeof e)for(var n in e)f.d(t,n,function(r){return e[r]}.bind(null,n));return t},f.n=function(e){var r=e&&e.__esModule?function(){return e.default}:function(){return e};return f.d(r,"a",r),r},f.o=function(e,r){return Object.prototype.hasOwnProperty.call(e,r)},f.p="/";var i=window.webpackJsonp=window.webpackJsonp||[],l=i.push.bind(i);i.push=r,i=i.slice();for(var a=0;a<i.length;a++)r(i[a]);var p=l;t()}([]);
|
||||
//# sourceMappingURL=runtime~main.229c360f.js.map
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 9.3 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 1.2 KiB After Width: | Height: | Size: 975 B |
Binary file not shown.
|
Before Width: | Height: | Size: 2.2 KiB After Width: | Height: | Size: 1005 B |
@@ -0,0 +1,442 @@
|
||||
// code that is executed on every user profile
|
||||
$(document).ready(function() {
|
||||
var wl = window.location;
|
||||
var newPathName = wl.pathname;
|
||||
// userID is defined in profile.html
|
||||
if (newPathName.split("/")[2] != userID) {
|
||||
newPathName = "/u/" + userID;
|
||||
}
|
||||
// if there's no mode parameter in the querystring, add it
|
||||
if (wl.search.indexOf("mode=") === -1)
|
||||
window.history.replaceState('', document.title, newPathName + "?mode=" + favouriteMode + wl.hash);
|
||||
else if (wl.pathname != newPathName)
|
||||
window.history.replaceState('', document.title, newPathName + wl.search + wl.hash);
|
||||
setDefaultScoreTable();
|
||||
// when an item in the mode menu is clicked, it means we should change the mode.
|
||||
$("#mode-menu>.item").click(function(e) {
|
||||
e.preventDefault();
|
||||
if ($(this).hasClass("active"))
|
||||
return;
|
||||
var m = $(this).data("mode");
|
||||
$("[data-mode]:not(.item):not([hidden])").attr("hidden", "");
|
||||
$("[data-mode=" + m + "]:not(.item)").removeAttr("hidden");
|
||||
$("#mode-menu>.active.item").removeClass("active");
|
||||
var needsLoad = $("#scores-zone>[data-mode=" + m + "][data-loaded=0]");
|
||||
if (needsLoad.length > 0)
|
||||
initialiseScores(needsLoad, m);
|
||||
$(this).addClass("active");
|
||||
window.history.replaceState('', document.title, wl.pathname + "?mode=" + m + wl.hash);
|
||||
});
|
||||
initialiseAchievements();
|
||||
initialiseFriends();
|
||||
// load scores page for the current favourite mode
|
||||
var i = function(){initialiseScores($("#scores-zone>div[data-mode=" + favouriteMode + "]"), favouriteMode)};
|
||||
if (i18nLoaded)
|
||||
i();
|
||||
else
|
||||
i18next.on("loaded", function() {
|
||||
i();
|
||||
});
|
||||
});
|
||||
|
||||
function initialiseAchievements() {
|
||||
api('users/achievements' + (currentUserID == userID ? '?all' : ''),
|
||||
{id: userID}, function (resp) {
|
||||
var achievements = resp.achievements;
|
||||
// no achievements -- show default message
|
||||
if (achievements.length === 0) {
|
||||
$("#achievements")
|
||||
.append($("<div class='ui sixteen wide column'>")
|
||||
.text(T("Nothing here. Yet.")));
|
||||
$("#load-more-achievements").remove();
|
||||
return;
|
||||
}
|
||||
|
||||
var displayAchievements = function(limit, achievedOnly) {
|
||||
var $ach = $("#achievements").empty();
|
||||
limit = limit < 0 ? achievements.length : limit;
|
||||
var shown = 0;
|
||||
for (var i = 0; i < achievements.length; i++) {
|
||||
var ach = achievements[i];
|
||||
if (shown >= limit || (achievedOnly && !ach.achieved)) {
|
||||
continue;
|
||||
}
|
||||
shown++;
|
||||
$ach.append(
|
||||
$("<div class='ui two wide column'>").append(
|
||||
$("<img src='https://s.ripple.moe/images/medals-" +
|
||||
"client/" + ach.icon + ".png' alt='" + ach.name +
|
||||
"' class='" +
|
||||
(!ach.achieved ? "locked-achievement" : "achievement") +
|
||||
"'>").popup({
|
||||
title: ach.name,
|
||||
content: ach.description,
|
||||
position: "bottom center",
|
||||
distanceAway: 10
|
||||
})
|
||||
)
|
||||
);
|
||||
}
|
||||
// if we've shown nothing, and achievedOnly is enabled, try again
|
||||
// this time disabling it.
|
||||
if (shown == 0 && achievedOnly) {
|
||||
displayAchievements(limit, false);
|
||||
}
|
||||
};
|
||||
|
||||
// only 8 achievements - we can remove the button completely, because
|
||||
// it won't be used (no more achievements).
|
||||
// otherwise, we simply remove the disabled class and add the click handler
|
||||
// to activate it.
|
||||
if (achievements.length <= 8) {
|
||||
$("#load-more-achievements").remove();
|
||||
} else {
|
||||
$("#load-more-achievements")
|
||||
.removeClass("disabled")
|
||||
.click(function() {
|
||||
$(this).remove();
|
||||
displayAchievements(-1, false);
|
||||
});
|
||||
}
|
||||
displayAchievements(8, true);
|
||||
});
|
||||
}
|
||||
|
||||
function initialiseFriends() {
|
||||
var b = $("#add-friend-button");
|
||||
if (b.length == 0) return;
|
||||
api('friends/with', {id: userID}, setFriendOnResponse);
|
||||
b.click(friendClick);
|
||||
}
|
||||
function setFriendOnResponse(r) {
|
||||
var x = 0;
|
||||
if (r.friend) x++;
|
||||
if (r.mutual) x++;
|
||||
setFriend(x);
|
||||
}
|
||||
function setFriend(i) {
|
||||
var b = $("#add-friend-button");
|
||||
b.removeClass("loading green blue red");
|
||||
switch (i) {
|
||||
case 0:
|
||||
b
|
||||
.addClass("blue")
|
||||
.attr("title", T("Add friend"))
|
||||
.html("<i class='plus icon'></i>");
|
||||
break;
|
||||
case 1:
|
||||
b
|
||||
.addClass("green")
|
||||
.attr("title", T("Remove friend"))
|
||||
.html("<i class='minus icon'></i>");
|
||||
break;
|
||||
case 2:
|
||||
b
|
||||
.addClass("red")
|
||||
.attr("title", T("Unmutual friend"))
|
||||
.html("<i class='heart icon'></i>");
|
||||
break;
|
||||
}
|
||||
b.attr("data-friends", i > 0 ? 1 : 0)
|
||||
}
|
||||
function friendClick() {
|
||||
var t = $(this);
|
||||
if (t.hasClass("loading")) return;
|
||||
t.addClass("loading");
|
||||
api("friends/" + (t.attr("data-friends") == 1 ? "del" : "add"), {user: userID}, setFriendOnResponse, true);
|
||||
}
|
||||
|
||||
var defaultScoreTable;
|
||||
function setDefaultScoreTable() {
|
||||
defaultScoreTable = $("<table class='ui table score-table' />")
|
||||
.append(
|
||||
$("<thead />").append(
|
||||
$("<tr />").append(
|
||||
$("<th>" + T("General info") + "</th>"),
|
||||
$("<th>"+ T("Score") + "</th>")
|
||||
)
|
||||
)
|
||||
)
|
||||
.append(
|
||||
$("<tbody />")
|
||||
)
|
||||
.append(
|
||||
$("<tfoot />").append(
|
||||
$("<tr />").append(
|
||||
$("<th colspan=2 />").append(
|
||||
$("<div class='ui right floated pagination menu' />").append(
|
||||
$("<a class='disabled item load-more-button'>" + T("Load more") + "</a>").click(loadMoreClick)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
;
|
||||
}
|
||||
i18next.on('loaded', function(loaded) {
|
||||
setDefaultScoreTable();
|
||||
});
|
||||
function initialiseScores(el, mode) {
|
||||
el.attr("data-loaded", "1");
|
||||
var best = defaultScoreTable.clone(true).addClass("orange");
|
||||
var recent = defaultScoreTable.clone(true).addClass("blue");
|
||||
best.attr("data-type", "best");
|
||||
recent.attr("data-type", "recent");
|
||||
recent.addClass("no bottom margin");
|
||||
el.append($("<div class='ui segments no bottom margin' />").append(
|
||||
$("<div class='ui segment' />").append("<h2 class='ui header'>" + T("Best scores") + "</h2>", best),
|
||||
$("<div class='ui segment' />").append("<h2 class='ui header'>" + T("Recent scores") + "</h2>", recent)
|
||||
));
|
||||
loadScoresPage("best", mode);
|
||||
loadScoresPage("recent", mode);
|
||||
};
|
||||
function loadMoreClick() {
|
||||
var t = $(this);
|
||||
if (t.hasClass("disabled"))
|
||||
return;
|
||||
t.addClass("disabled");
|
||||
var type = t.parents("table[data-type]").data("type");
|
||||
var mode = t.parents("div[data-mode]").data("mode");
|
||||
loadScoresPage(type, mode);
|
||||
}
|
||||
// currentPage for each mode
|
||||
var currentPage = {
|
||||
0: {best: 0, recent: 0},
|
||||
1: {best: 0, recent: 0},
|
||||
2: {best: 0, recent: 0},
|
||||
3: {best: 0, recent: 0},
|
||||
};
|
||||
var scoreStore = {};
|
||||
function loadScoresPage(type, mode) {
|
||||
var table = $("#scores-zone div[data-mode=" + mode + "] table[data-type=" + type + "] tbody");
|
||||
var page = ++currentPage[mode][type];
|
||||
console.log("loadScoresPage with", {
|
||||
page: page,
|
||||
type: type,
|
||||
mode: mode,
|
||||
});
|
||||
api("users/scores/ap/" + type, {
|
||||
mode: mode,
|
||||
p: page,
|
||||
l: 20,
|
||||
id: userID,
|
||||
}, function(r) {
|
||||
if (r.scores == null) {
|
||||
disableLoadMoreButton(type, mode);
|
||||
return;
|
||||
}
|
||||
r.scores.forEach(function(v, idx){
|
||||
scoreStore[v.id] = v;
|
||||
if (v.completed == 0){
|
||||
var scoreRank = "failed";
|
||||
}else{
|
||||
var scoreRank = getRank(mode, v.mods, v.accuracy, v.count_300, v.count_100, v.count_50, v.count_miss);
|
||||
}
|
||||
|
||||
table.append($("<tr class='new score-row' data-scoreid='" + v.id + "' />").append(
|
||||
$(
|
||||
"<td><img src='/static/ranking-icons/" + scoreRank + ".png' class='score rank' alt='" + scoreRank + "' height='16' width='16' > " +
|
||||
escapeHTML(v.beatmap.song_name) + " <b>" + getScoreMods(v.mods) + "</b> <i>(" + v.accuracy.toFixed(2) + "%)</i><br />" +
|
||||
"<div class='subtitle'><time class='new timeago' datetime='" + v.time + "'>" + v.time + "</time></div></td>"
|
||||
),
|
||||
$("<td><b>" + ppOrScore(v.pp, v.score) + "</b> " + weightedPP(type, page, idx, v.pp) + (v.completed == 3 ? "<br>" + downloadStar(v.id) : "") + "</td>")
|
||||
));
|
||||
});
|
||||
$(".new.timeago").timeago().removeClass("new");
|
||||
$(".new.score-row").click(viewScoreInfo).removeClass("new");
|
||||
$(".new.downloadstar").click(function(e) {
|
||||
e.stopPropagation();
|
||||
}).removeClass("new");
|
||||
var enable = true;
|
||||
if (r.scores.length != 20)
|
||||
enable = false;
|
||||
disableLoadMoreButton(type, mode, enable);
|
||||
});
|
||||
}
|
||||
function downloadStar(id) {
|
||||
return "<a href='/web/replays_auto/" + id + "' class='new downloadstar'><i class='star icon'></i>" + T("Download") + "</a>";
|
||||
}
|
||||
function weightedPP(type, page, idx, pp) {
|
||||
if (type != "best" || pp == 0)
|
||||
return "";
|
||||
var perc = Math.pow(0.95, ((page - 1) * 20) + idx);
|
||||
var wpp = pp * perc;
|
||||
return "<i title='Weighted PP, " + Math.round(perc*100) + "%'>(" + wpp.toFixed(2) + "pp)</i>";
|
||||
}
|
||||
function disableLoadMoreButton(type, mode, enable) {
|
||||
var button = $("#scores-zone div[data-mode=" + mode + "] table[data-type=" + type + "] .load-more-button");
|
||||
if (enable) button.removeClass("disabled");
|
||||
else button.addClass("disabled");
|
||||
}
|
||||
function viewScoreInfo() {
|
||||
var scoreid = $(this).data("scoreid");
|
||||
if (!scoreid && scoreid !== 0) return;
|
||||
var s = scoreStore[scoreid];
|
||||
if (s === undefined) return;
|
||||
|
||||
// data to be displayed in the table.
|
||||
var data = {
|
||||
"Points": addCommas(s.score),
|
||||
"PP": addCommas(s.pp),
|
||||
"Beatmap": "<a href='/b/" + s.beatmap.beatmap_id + "'>" + escapeHTML(s.beatmap.song_name) + "</a>",
|
||||
"Accuracy": s.accuracy + "%",
|
||||
"Max combo": addCommas(s.max_combo) + "/" + addCommas(s.beatmap.max_combo)
|
||||
+ (s.full_combo ? " " + T("(full combo)") : ""),
|
||||
"Difficulty": T("{{ stars }} star", {
|
||||
stars: s.beatmap.difficulty2[modesShort[s.play_mode]],
|
||||
count: Math.round(s.beatmap.difficulty2[modesShort[s.play_mode]]),
|
||||
}),
|
||||
"Mods": getScoreMods(s.mods, true),
|
||||
};
|
||||
|
||||
// hits data
|
||||
var hd = {};
|
||||
var trans = modeTranslations[s.play_mode];
|
||||
[
|
||||
s.count_300,
|
||||
s.count_100,
|
||||
s.count_50,
|
||||
s.count_geki,
|
||||
s.count_katu,
|
||||
s.count_miss,
|
||||
].forEach(function(val, i) {
|
||||
hd[trans[i]] = val;
|
||||
});
|
||||
|
||||
data = $.extend(data, hd, {
|
||||
"Ranked?": T(s.completed == 3 ? "Yes" : "No"),
|
||||
"Achieved": s.time,
|
||||
"Mode": modes[s.play_mode],
|
||||
});
|
||||
|
||||
var els = [];
|
||||
$.each(data, function(key, value) {
|
||||
els.push(
|
||||
$("<tr />").append(
|
||||
$("<td>" + T(key) + "</td>"),
|
||||
$("<td>" + value + "</td>")
|
||||
)
|
||||
);
|
||||
});
|
||||
|
||||
$("#score-data-table tr").remove();
|
||||
$("#score-data-table").append(els);
|
||||
$(".ui.modal").modal("show");
|
||||
}
|
||||
|
||||
var modeTranslations = [
|
||||
[
|
||||
"300s",
|
||||
"100s",
|
||||
"50s",
|
||||
"Gekis",
|
||||
"Katus",
|
||||
"Misses"
|
||||
],
|
||||
[
|
||||
"GREATs",
|
||||
"GOODs",
|
||||
"50s",
|
||||
"GREATs (Gekis)",
|
||||
"GOODs (Katus)",
|
||||
"Misses"
|
||||
],
|
||||
[
|
||||
"Fruits (300s)",
|
||||
"Ticks (100s)",
|
||||
"Droplets",
|
||||
"Gekis",
|
||||
"Droplet misses",
|
||||
"Misses"
|
||||
],
|
||||
[
|
||||
"300s",
|
||||
"200s",
|
||||
"50s",
|
||||
"Max 300s",
|
||||
"100s",
|
||||
"Misses"
|
||||
]
|
||||
];
|
||||
|
||||
function getRank(gameMode, mods, acc, c300, c100, c50, cmiss) {
|
||||
var total = c300+c100+c50+cmiss;
|
||||
|
||||
// Hidden | Flashlight | FadeIn
|
||||
var hdfl = (mods & (1049608)) > 0;
|
||||
|
||||
var ss = hdfl ? "SSHD" : "SS";
|
||||
var s = hdfl ? "SHD" : "S";
|
||||
|
||||
switch(gameMode) {
|
||||
case 0:
|
||||
case 1:
|
||||
var ratio300 = c300 / total;
|
||||
var ratio50 = c50 / total;
|
||||
|
||||
if (ratio300 == 1)
|
||||
return ss;
|
||||
|
||||
if (ratio300 > 0.9 && ratio50 <= 0.01 && cmiss == 0)
|
||||
return s;
|
||||
|
||||
if ((ratio300 > 0.8 && cmiss == 0) || (ratio300 > 0.9))
|
||||
return "A";
|
||||
|
||||
if ((ratio300 > 0.7 && cmiss == 0) || (ratio300 > 0.8))
|
||||
return "B";
|
||||
|
||||
if (ratio300 > 0.6)
|
||||
return "C";
|
||||
|
||||
return "D";
|
||||
|
||||
case 2:
|
||||
if (acc == 100)
|
||||
return ss;
|
||||
|
||||
if (acc > 98)
|
||||
return s;
|
||||
|
||||
if (acc > 94)
|
||||
return "A";
|
||||
|
||||
if (acc > 90)
|
||||
return "B";
|
||||
|
||||
if (acc > 85)
|
||||
return "C";
|
||||
|
||||
return "D";
|
||||
|
||||
case 3:
|
||||
if (acc == 100)
|
||||
return ss;
|
||||
|
||||
if (acc > 95)
|
||||
return s;
|
||||
|
||||
if (acc > 90)
|
||||
return "A";
|
||||
|
||||
if (acc > 80)
|
||||
return "B";
|
||||
|
||||
if (acc > 70)
|
||||
return "C";
|
||||
|
||||
return "D";
|
||||
}
|
||||
}
|
||||
|
||||
function ppOrScore(pp, score) {
|
||||
if (pp != 0)
|
||||
return addCommas(pp.toFixed(2)) + "pp";
|
||||
return addCommas(score);
|
||||
}
|
||||
|
||||
function beatmapLink(type, id) {
|
||||
if (type == "s")
|
||||
return "<a href='/s/" + id + "'>" + id + '</a>';
|
||||
return "<a href='/b/" + id + "'>" + id + '</a>';
|
||||
}
|
||||
@@ -0,0 +1,442 @@
|
||||
// code that is executed on every user profile
|
||||
$(document).ready(function() {
|
||||
var wl = window.location;
|
||||
var newPathName = wl.pathname;
|
||||
// userID is defined in profile.html
|
||||
if (newPathName.split("/")[2] != userID) {
|
||||
newPathName = "/u/" + userID;
|
||||
}
|
||||
// if there's no mode parameter in the querystring, add it
|
||||
if (wl.search.indexOf("mode=") === -1)
|
||||
window.history.replaceState('', document.title, newPathName + "?mode=" + favouriteMode + wl.hash);
|
||||
else if (wl.pathname != newPathName)
|
||||
window.history.replaceState('', document.title, newPathName + wl.search + wl.hash);
|
||||
setDefaultScoreTable();
|
||||
// when an item in the mode menu is clicked, it means we should change the mode.
|
||||
$("#mode-menu>.item").click(function(e) {
|
||||
e.preventDefault();
|
||||
if ($(this).hasClass("active"))
|
||||
return;
|
||||
var m = $(this).data("mode");
|
||||
$("[data-mode]:not(.item):not([hidden])").attr("hidden", "");
|
||||
$("[data-mode=" + m + "]:not(.item)").removeAttr("hidden");
|
||||
$("#mode-menu>.active.item").removeClass("active");
|
||||
var needsLoad = $("#scores-zone>[data-mode=" + m + "][data-loaded=0]");
|
||||
if (needsLoad.length > 0)
|
||||
initialiseScores(needsLoad, m);
|
||||
$(this).addClass("active");
|
||||
window.history.replaceState('', document.title, wl.pathname + "?mode=" + m + wl.hash);
|
||||
});
|
||||
initialiseAchievements();
|
||||
initialiseFriends();
|
||||
// load scores page for the current favourite mode
|
||||
var i = function(){initialiseScores($("#scores-zone>div[data-mode=" + favouriteMode + "]"), favouriteMode)};
|
||||
if (i18nLoaded)
|
||||
i();
|
||||
else
|
||||
i18next.on("loaded", function() {
|
||||
i();
|
||||
});
|
||||
});
|
||||
|
||||
function initialiseAchievements() {
|
||||
api('users/achievements' + (currentUserID == userID ? '?all' : ''),
|
||||
{id: userID}, function (resp) {
|
||||
var achievements = resp.achievements;
|
||||
// no achievements -- show default message
|
||||
if (achievements.length === 0) {
|
||||
$("#achievements")
|
||||
.append($("<div class='ui sixteen wide column'>")
|
||||
.text(T("Nothing here. Yet.")));
|
||||
$("#load-more-achievements").remove();
|
||||
return;
|
||||
}
|
||||
|
||||
var displayAchievements = function(limit, achievedOnly) {
|
||||
var $ach = $("#achievements").empty();
|
||||
limit = limit < 0 ? achievements.length : limit;
|
||||
var shown = 0;
|
||||
for (var i = 0; i < achievements.length; i++) {
|
||||
var ach = achievements[i];
|
||||
if (shown >= limit || (achievedOnly && !ach.achieved)) {
|
||||
continue;
|
||||
}
|
||||
shown++;
|
||||
$ach.append(
|
||||
$("<div class='ui two wide column'>").append(
|
||||
$("<img src='https://s.ripple.moe/images/medals-" +
|
||||
"client/" + ach.icon + ".png' alt='" + ach.name +
|
||||
"' class='" +
|
||||
(!ach.achieved ? "locked-achievement" : "achievement") +
|
||||
"'>").popup({
|
||||
title: ach.name,
|
||||
content: ach.description,
|
||||
position: "bottom center",
|
||||
distanceAway: 10
|
||||
})
|
||||
)
|
||||
);
|
||||
}
|
||||
// if we've shown nothing, and achievedOnly is enabled, try again
|
||||
// this time disabling it.
|
||||
if (shown == 0 && achievedOnly) {
|
||||
displayAchievements(limit, false);
|
||||
}
|
||||
};
|
||||
|
||||
// only 8 achievements - we can remove the button completely, because
|
||||
// it won't be used (no more achievements).
|
||||
// otherwise, we simply remove the disabled class and add the click handler
|
||||
// to activate it.
|
||||
if (achievements.length <= 8) {
|
||||
$("#load-more-achievements").remove();
|
||||
} else {
|
||||
$("#load-more-achievements")
|
||||
.removeClass("disabled")
|
||||
.click(function() {
|
||||
$(this).remove();
|
||||
displayAchievements(-1, false);
|
||||
});
|
||||
}
|
||||
displayAchievements(8, true);
|
||||
});
|
||||
}
|
||||
|
||||
function initialiseFriends() {
|
||||
var b = $("#add-friend-button");
|
||||
if (b.length == 0) return;
|
||||
api('friends/with', {id: userID}, setFriendOnResponse);
|
||||
b.click(friendClick);
|
||||
}
|
||||
function setFriendOnResponse(r) {
|
||||
var x = 0;
|
||||
if (r.friend) x++;
|
||||
if (r.mutual) x++;
|
||||
setFriend(x);
|
||||
}
|
||||
function setFriend(i) {
|
||||
var b = $("#add-friend-button");
|
||||
b.removeClass("loading green blue red");
|
||||
switch (i) {
|
||||
case 0:
|
||||
b
|
||||
.addClass("blue")
|
||||
.attr("title", T("Add friend"))
|
||||
.html("<i class='plus icon'></i>");
|
||||
break;
|
||||
case 1:
|
||||
b
|
||||
.addClass("green")
|
||||
.attr("title", T("Remove friend"))
|
||||
.html("<i class='minus icon'></i>");
|
||||
break;
|
||||
case 2:
|
||||
b
|
||||
.addClass("red")
|
||||
.attr("title", T("Unmutual friend"))
|
||||
.html("<i class='heart icon'></i>");
|
||||
break;
|
||||
}
|
||||
b.attr("data-friends", i > 0 ? 1 : 0)
|
||||
}
|
||||
function friendClick() {
|
||||
var t = $(this);
|
||||
if (t.hasClass("loading")) return;
|
||||
t.addClass("loading");
|
||||
api("friends/" + (t.attr("data-friends") == 1 ? "del" : "add"), {user: userID}, setFriendOnResponse, true);
|
||||
}
|
||||
|
||||
var defaultScoreTable;
|
||||
function setDefaultScoreTable() {
|
||||
defaultScoreTable = $("<table class='ui table score-table' />")
|
||||
.append(
|
||||
$("<thead />").append(
|
||||
$("<tr />").append(
|
||||
$("<th>" + T("General info") + "</th>"),
|
||||
$("<th>"+ T("Score") + "</th>")
|
||||
)
|
||||
)
|
||||
)
|
||||
.append(
|
||||
$("<tbody />")
|
||||
)
|
||||
.append(
|
||||
$("<tfoot />").append(
|
||||
$("<tr />").append(
|
||||
$("<th colspan=2 />").append(
|
||||
$("<div class='ui right floated pagination menu' />").append(
|
||||
$("<a class='disabled item load-more-button'>" + T("Load more") + "</a>").click(loadMoreClick)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
;
|
||||
}
|
||||
i18next.on('loaded', function(loaded) {
|
||||
setDefaultScoreTable();
|
||||
});
|
||||
function initialiseScores(el, mode) {
|
||||
el.attr("data-loaded", "1");
|
||||
var best = defaultScoreTable.clone(true).addClass("orange");
|
||||
var recent = defaultScoreTable.clone(true).addClass("blue");
|
||||
best.attr("data-type", "best");
|
||||
recent.attr("data-type", "recent");
|
||||
recent.addClass("no bottom margin");
|
||||
el.append($("<div class='ui segments no bottom margin' />").append(
|
||||
$("<div class='ui segment' />").append("<h2 class='ui header'>" + T("Best scores") + "</h2>", best),
|
||||
$("<div class='ui segment' />").append("<h2 class='ui header'>" + T("Recent scores") + "</h2>", recent)
|
||||
));
|
||||
loadScoresPage("best", mode);
|
||||
loadScoresPage("recent", mode);
|
||||
};
|
||||
function loadMoreClick() {
|
||||
var t = $(this);
|
||||
if (t.hasClass("disabled"))
|
||||
return;
|
||||
t.addClass("disabled");
|
||||
var type = t.parents("table[data-type]").data("type");
|
||||
var mode = t.parents("div[data-mode]").data("mode");
|
||||
loadScoresPage(type, mode);
|
||||
}
|
||||
// currentPage for each mode
|
||||
var currentPage = {
|
||||
0: {best: 0, recent: 0},
|
||||
1: {best: 0, recent: 0},
|
||||
2: {best: 0, recent: 0},
|
||||
3: {best: 0, recent: 0},
|
||||
};
|
||||
var scoreStore = {};
|
||||
function loadScoresPage(type, mode) {
|
||||
var table = $("#scores-zone div[data-mode=" + mode + "] table[data-type=" + type + "] tbody");
|
||||
var page = ++currentPage[mode][type];
|
||||
console.log("loadScoresPage with", {
|
||||
page: page,
|
||||
type: type,
|
||||
mode: mode,
|
||||
});
|
||||
api("users/scores/relax/" + type, {
|
||||
mode: mode,
|
||||
p: page,
|
||||
l: 20,
|
||||
id: userID,
|
||||
}, function(r) {
|
||||
if (r.scores == null) {
|
||||
disableLoadMoreButton(type, mode);
|
||||
return;
|
||||
}
|
||||
r.scores.forEach(function(v, idx){
|
||||
scoreStore[v.id] = v;
|
||||
if (v.completed == 0){
|
||||
var scoreRank = "failed";
|
||||
}else{
|
||||
var scoreRank = getRank(mode, v.mods, v.accuracy, v.count_300, v.count_100, v.count_50, v.count_miss);
|
||||
}
|
||||
|
||||
table.append($("<tr class='new score-row' data-scoreid='" + v.id + "' />").append(
|
||||
$(
|
||||
"<td><img src='/static/ranking-icons/" + scoreRank + ".png' class='score rank' alt='" + scoreRank + "' height='16' width='16' > " +
|
||||
escapeHTML(v.beatmap.song_name) + " <b>" + getScoreMods(v.mods) + "</b> <i>(" + v.accuracy.toFixed(2) + "%)</i><br />" +
|
||||
"<div class='subtitle'><time class='new timeago' datetime='" + v.time + "'>" + v.time + "</time></div></td>"
|
||||
),
|
||||
$("<td><b>" + ppOrScore(v.pp, v.score) + "</b> " + weightedPP(type, page, idx, v.pp) + (v.completed == 3 ? "<br>" + downloadStar(v.id) : "") + "</td>")
|
||||
));
|
||||
});
|
||||
$(".new.timeago").timeago().removeClass("new");
|
||||
$(".new.score-row").click(viewScoreInfo).removeClass("new");
|
||||
$(".new.downloadstar").click(function(e) {
|
||||
e.stopPropagation();
|
||||
}).removeClass("new");
|
||||
var enable = true;
|
||||
if (r.scores.length != 20)
|
||||
enable = false;
|
||||
disableLoadMoreButton(type, mode, enable);
|
||||
});
|
||||
}
|
||||
function downloadStar(id) {
|
||||
return "<a href='/web/replays_relax/" + id + "' class='new downloadstar'><i class='star icon'></i>" + T("Download") + "</a>";
|
||||
}
|
||||
function weightedPP(type, page, idx, pp) {
|
||||
if (type != "best" || pp == 0)
|
||||
return "";
|
||||
var perc = Math.pow(0.95, ((page - 1) * 20) + idx);
|
||||
var wpp = pp * perc;
|
||||
return "<i title='Weighted PP, " + Math.round(perc*100) + "%'>(" + wpp.toFixed(2) + "pp)</i>";
|
||||
}
|
||||
function disableLoadMoreButton(type, mode, enable) {
|
||||
var button = $("#scores-zone div[data-mode=" + mode + "] table[data-type=" + type + "] .load-more-button");
|
||||
if (enable) button.removeClass("disabled");
|
||||
else button.addClass("disabled");
|
||||
}
|
||||
function viewScoreInfo() {
|
||||
var scoreid = $(this).data("scoreid");
|
||||
if (!scoreid && scoreid !== 0) return;
|
||||
var s = scoreStore[scoreid];
|
||||
if (s === undefined) return;
|
||||
|
||||
// data to be displayed in the table.
|
||||
var data = {
|
||||
"Points": addCommas(s.score),
|
||||
"PP": addCommas(s.pp),
|
||||
"Beatmap": "<a href='/b/" + s.beatmap.beatmap_id + "'>" + escapeHTML(s.beatmap.song_name) + "</a>",
|
||||
"Accuracy": s.accuracy + "%",
|
||||
"Max combo": addCommas(s.max_combo) + "/" + addCommas(s.beatmap.max_combo)
|
||||
+ (s.full_combo ? " " + T("(full combo)") : ""),
|
||||
"Difficulty": T("{{ stars }} star", {
|
||||
stars: s.beatmap.difficulty2[modesShort[s.play_mode]],
|
||||
count: Math.round(s.beatmap.difficulty2[modesShort[s.play_mode]]),
|
||||
}),
|
||||
"Mods": getScoreMods(s.mods, true),
|
||||
};
|
||||
|
||||
// hits data
|
||||
var hd = {};
|
||||
var trans = modeTranslations[s.play_mode];
|
||||
[
|
||||
s.count_300,
|
||||
s.count_100,
|
||||
s.count_50,
|
||||
s.count_geki,
|
||||
s.count_katu,
|
||||
s.count_miss,
|
||||
].forEach(function(val, i) {
|
||||
hd[trans[i]] = val;
|
||||
});
|
||||
|
||||
data = $.extend(data, hd, {
|
||||
"Ranked?": T(s.completed == 3 ? "Yes" : "No"),
|
||||
"Achieved": s.time,
|
||||
"Mode": modes[s.play_mode],
|
||||
});
|
||||
|
||||
var els = [];
|
||||
$.each(data, function(key, value) {
|
||||
els.push(
|
||||
$("<tr />").append(
|
||||
$("<td>" + T(key) + "</td>"),
|
||||
$("<td>" + value + "</td>")
|
||||
)
|
||||
);
|
||||
});
|
||||
|
||||
$("#score-data-table tr").remove();
|
||||
$("#score-data-table").append(els);
|
||||
$(".ui.modal").modal("show");
|
||||
}
|
||||
|
||||
var modeTranslations = [
|
||||
[
|
||||
"300s",
|
||||
"100s",
|
||||
"50s",
|
||||
"Gekis",
|
||||
"Katus",
|
||||
"Misses"
|
||||
],
|
||||
[
|
||||
"GREATs",
|
||||
"GOODs",
|
||||
"50s",
|
||||
"GREATs (Gekis)",
|
||||
"GOODs (Katus)",
|
||||
"Misses"
|
||||
],
|
||||
[
|
||||
"Fruits (300s)",
|
||||
"Ticks (100s)",
|
||||
"Droplets",
|
||||
"Gekis",
|
||||
"Droplet misses",
|
||||
"Misses"
|
||||
],
|
||||
[
|
||||
"300s",
|
||||
"200s",
|
||||
"50s",
|
||||
"Max 300s",
|
||||
"100s",
|
||||
"Misses"
|
||||
]
|
||||
];
|
||||
|
||||
function getRank(gameMode, mods, acc, c300, c100, c50, cmiss) {
|
||||
var total = c300+c100+c50+cmiss;
|
||||
|
||||
// Hidden | Flashlight | FadeIn
|
||||
var hdfl = (mods & (1049608)) > 0;
|
||||
|
||||
var ss = hdfl ? "SSHD" : "SS";
|
||||
var s = hdfl ? "SHD" : "S";
|
||||
|
||||
switch(gameMode) {
|
||||
case 0:
|
||||
case 1:
|
||||
var ratio300 = c300 / total;
|
||||
var ratio50 = c50 / total;
|
||||
|
||||
if (ratio300 == 1)
|
||||
return ss;
|
||||
|
||||
if (ratio300 > 0.9 && ratio50 <= 0.01 && cmiss == 0)
|
||||
return s;
|
||||
|
||||
if ((ratio300 > 0.8 && cmiss == 0) || (ratio300 > 0.9))
|
||||
return "A";
|
||||
|
||||
if ((ratio300 > 0.7 && cmiss == 0) || (ratio300 > 0.8))
|
||||
return "B";
|
||||
|
||||
if (ratio300 > 0.6)
|
||||
return "C";
|
||||
|
||||
return "D";
|
||||
|
||||
case 2:
|
||||
if (acc == 100)
|
||||
return ss;
|
||||
|
||||
if (acc > 98)
|
||||
return s;
|
||||
|
||||
if (acc > 94)
|
||||
return "A";
|
||||
|
||||
if (acc > 90)
|
||||
return "B";
|
||||
|
||||
if (acc > 85)
|
||||
return "C";
|
||||
|
||||
return "D";
|
||||
|
||||
case 3:
|
||||
if (acc == 100)
|
||||
return ss;
|
||||
|
||||
if (acc > 95)
|
||||
return s;
|
||||
|
||||
if (acc > 90)
|
||||
return "A";
|
||||
|
||||
if (acc > 80)
|
||||
return "B";
|
||||
|
||||
if (acc > 70)
|
||||
return "C";
|
||||
|
||||
return "D";
|
||||
}
|
||||
}
|
||||
|
||||
function ppOrScore(pp, score) {
|
||||
if (pp != 0)
|
||||
return addCommas(pp.toFixed(2)) + "pp";
|
||||
return addCommas(score);
|
||||
}
|
||||
|
||||
function beatmapLink(type, id) {
|
||||
if (type == "s")
|
||||
return "<a href='/s/" + id + "'>" + id + '</a>';
|
||||
return "<a href='/b/" + id + "'>" + id + '</a>';
|
||||
}
|
||||
@@ -466,4 +466,78 @@ img.locked-achievement:hover {
|
||||
-webkit-filter: brightness(0.5) drop-shadow(0 5px 5px #777);
|
||||
filter: brightness(0.5) drop-shadow(0 5px 5px #777);
|
||||
}
|
||||
.animated.flipOutX,
|
||||
.animated.flipOutY,
|
||||
.animated.bounceIn,
|
||||
.animated.bounceOut {
|
||||
-webkit-animation-duration: .75s;
|
||||
animation-duration: .75s;
|
||||
}
|
||||
|
||||
@-webkit-keyframes bounce {
|
||||
from, 20%, 53%, 80%, to {
|
||||
-webkit-animation-timing-function: cubic-bezier(0.215, 0.610, 0.355, 1.000);
|
||||
animation-timing-function: cubic-bezier(0.215, 0.610, 0.355, 1.000);
|
||||
-webkit-transform: translate3d(0,0,0);
|
||||
transform: translate3d(0,0,0);
|
||||
}
|
||||
|
||||
40%, 43% {
|
||||
-webkit-animation-timing-function: cubic-bezier(0.755, 0.050, 0.855, 0.060);
|
||||
animation-timing-function: cubic-bezier(0.755, 0.050, 0.855, 0.060);
|
||||
-webkit-transform: translate3d(0, -30px, 0);
|
||||
transform: translate3d(0, -30px, 0);
|
||||
}
|
||||
|
||||
70% {
|
||||
-webkit-animation-timing-function: cubic-bezier(0.755, 0.050, 0.855, 0.060);
|
||||
animation-timing-function: cubic-bezier(0.755, 0.050, 0.855, 0.060);
|
||||
-webkit-transform: translate3d(0, -15px, 0);
|
||||
transform: translate3d(0, -15px, 0);
|
||||
}
|
||||
|
||||
90% {
|
||||
-webkit-transform: translate3d(0,-4px,0);
|
||||
transform: translate3d(0,-4px,0);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes bounce {
|
||||
from, 20%, 53%, 80%, to {
|
||||
-webkit-animation-timing-function: cubic-bezier(0.215, 0.610, 0.355, 1.000);
|
||||
animation-timing-function: cubic-bezier(0.215, 0.610, 0.355, 1.000);
|
||||
-webkit-transform: translate3d(0,0,0);
|
||||
transform: translate3d(0,0,0);
|
||||
}
|
||||
|
||||
40%, 43% {
|
||||
-webkit-animation-timing-function: cubic-bezier(0.755, 0.050, 0.855, 0.060);
|
||||
animation-timing-function: cubic-bezier(0.755, 0.050, 0.855, 0.060);
|
||||
-webkit-transform: translate3d(0, -30px, 0);
|
||||
transform: translate3d(0, -30px, 0);
|
||||
}
|
||||
|
||||
70% {
|
||||
-webkit-animation-timing-function: cubic-bezier(0.755, 0.050, 0.855, 0.060);
|
||||
animation-timing-function: cubic-bezier(0.755, 0.050, 0.855, 0.060);
|
||||
-webkit-transform: translate3d(0, -15px, 0);
|
||||
transform: translate3d(0, -15px, 0);
|
||||
}
|
||||
|
||||
90% {
|
||||
-webkit-transform: translate3d(0,-4px,0);
|
||||
transform: translate3d(0,-4px,0);
|
||||
}
|
||||
}
|
||||
#bouncy {
|
||||
-webkit-animation-duration: 1s;
|
||||
animation-duration: 1s;
|
||||
-webkit-animation-fill-mode: both;
|
||||
animation-fill-mode: both;
|
||||
-webkit-animation-iteration-count: infinite;
|
||||
animation-iteration-count: infinite;
|
||||
-webkit-animation-name: bounce;
|
||||
animation-name: bounce;
|
||||
-webkit-transform-origin: center bottom;
|
||||
transform-origin: center bottom;
|
||||
}
|
||||
@@ -13,6 +13,7 @@
|
||||
<link rel="stylesheet" type="text/css" href="/static/{{ if $ds }}dark/{{ end }}semantic.min.css?{{ unixNano }}">
|
||||
<link rel="stylesheet" type="text/css" href="/static/ripple.css?{{ unixNano }}">
|
||||
<link rel="stylesheet" type="text/css" href="/static/snow/snow.css?{{ unixNano }}">
|
||||
<link href="/static/css/beatmaps.dfc480ea.chunk.css" rel="stylesheet">
|
||||
</head>
|
||||
<body {{ if $ds }} class="ds"{{ end }}>
|
||||
{{/*
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
{{/*###
|
||||
Handler=/beatmaps
|
||||
TitleBar=Beatmaps
|
||||
KyutGrill=beatmaps.jpg
|
||||
*/}}
|
||||
{{ define "tpl" }}
|
||||
<div class="ui container">
|
||||
<div id="react-app"></div>
|
||||
</div>
|
||||
<script>!function (l) { function e(e) { for (var r, t, n = e[0], o = e[1], u = e[2], f = 0, i = []; f < n.length; f++)t = n[f], p[t] && i.push(p[t][0]), p[t] = 0; for (r in o) Object.prototype.hasOwnProperty.call(o, r) && (l[r] = o[r]); for (s && s(e); i.length;)i.shift()(); return c.push.apply(c, u || []), a() } function a() { for (var e, r = 0; r < c.length; r++) { for (var t = c[r], n = !0, o = 1; o < t.length; o++) { var u = t[o]; 0 !== p[u] && (n = !1) } n && (c.splice(r--, 1), e = f(f.s = t[0])) } return e } var t = {}, p = { 2: 0 }, c = []; function f(e) { if (t[e]) return t[e].exports; var r = t[e] = { i: e, l: !1, exports: {} }; return l[e].call(r.exports, r, r.exports, f), r.l = !0, r.exports } f.m = l, f.c = t, f.d = function (e, r, t) { f.o(e, r) || Object.defineProperty(e, r, { enumerable: !0, get: t }) }, f.r = function (e) { "undefined" != typeof Symbol && Symbol.toStringTag && Object.defineProperty(e, Symbol.toStringTag, { value: "Module" }), Object.defineProperty(e, "__esModule", { value: !0 }) }, f.t = function (r, e) { if (1 & e && (r = f(r)), 8 & e) return r; if (4 & e && "object" == typeof r && r && r.__esModule) return r; var t = Object.create(null); if (f.r(t), Object.defineProperty(t, "default", { enumerable: !0, value: r }), 2 & e && "string" != typeof r) for (var n in r) f.d(t, n, function (e) { return r[e] }.bind(null, n)); return t }, f.n = function (e) { var r = e && e.__esModule ? function () { return e.default } : function () { return e }; return f.d(r, "a", r), r }, f.o = function (e, r) { return Object.prototype.hasOwnProperty.call(e, r) }, f.p = "/"; var r = window.webpackJsonp = window.webpackJsonp || [], n = r.push.bind(r); r.push = e, r = r.slice(); for (var o = 0; o < r.length; o++)e(r[o]); var s = n; a() }([])</script>
|
||||
<script src="/static/js/1.7e1ca608.chunk.js"></script>
|
||||
<script src="/static/js/beatmaps.faace68d.chunk.js"></script>
|
||||
{{ end }}
|
||||
@@ -0,0 +1,59 @@
|
||||
{{/*###
|
||||
NoCompile=true
|
||||
*/}}
|
||||
{{ define "clanGroup" }}
|
||||
{{ with . }}
|
||||
<div class="ui one column center aligned stackable grid">
|
||||
{{ $teamJSON := teamJSON }}
|
||||
{{ range .members }}
|
||||
{{/* ignore fokabot */}}
|
||||
{{ if ne (int .id) 999 }}
|
||||
{{ $tj := index $teamJSON (print .id)}}
|
||||
<div class="column">
|
||||
<div class="ui left aligned fluid card">
|
||||
<div class="image">
|
||||
<img src="{{ config "AvatarURL" }}/{{ .id }}" alt="Avatar">
|
||||
</div>
|
||||
<div class="content">
|
||||
<a class="header" href="/u/{{ .id }}">{{ country .country false }}{{ .username }}</a>
|
||||
{{ with $tj.real_name }}
|
||||
<div class="meta">
|
||||
<a>{{ . }}</a>
|
||||
</div>
|
||||
{{ end }}
|
||||
{{ with $tj.role }}
|
||||
<div class="description">
|
||||
{{ . }}
|
||||
</div>
|
||||
{{ end }}
|
||||
</div>
|
||||
<div class="extra content">
|
||||
<div title="Registered">
|
||||
<i class="sign in icon"></i>
|
||||
{{ time .registered_on }}
|
||||
</div>
|
||||
<div title="Latest activity">
|
||||
<i class="sign out icon"></i>
|
||||
{{ time .latest_activity }}
|
||||
</div>
|
||||
</div>
|
||||
{{ if or $tj.twitter $tj.mail $tj.github }}
|
||||
<div class="extra content">
|
||||
<div class="center aligned">
|
||||
{{ range $k, $v := $tj }}
|
||||
{{ if and $v (in $k "github" "twitter" "mail") }}
|
||||
<a href="{{ servicePrefix $k }}{{ $v }}" title="{{ capitalise $k }}">
|
||||
<i class="{{ $k }} icon"></i>
|
||||
</a>
|
||||
{{ end }}
|
||||
{{ end }}
|
||||
</div>
|
||||
</div>
|
||||
{{ end }}
|
||||
</div>
|
||||
</div>
|
||||
{{ end }}
|
||||
{{ end }}
|
||||
</div>
|
||||
{{ end }}
|
||||
{{ end }}
|
||||
@@ -0,0 +1,44 @@
|
||||
{{/*###
|
||||
Handler=/clans
|
||||
TitleBar=Clans
|
||||
KyutGrill=leaderboard2.jpg
|
||||
*/}}
|
||||
{{ define "tpl" }}
|
||||
<div class="ui container">
|
||||
{{ $favMode := _or (atoi (.Gin.Query "mode")) }}
|
||||
<script>
|
||||
var favouriteMode = {{ $favMode }};
|
||||
var page = {{ .Gin.Query "p" | atoint | atLeastOne }};
|
||||
</script>
|
||||
<div class="ui four item menu" id="mode-menu">
|
||||
<a class="0 item" href="/clans?mode=0">osu!</a>
|
||||
<a class="1 item" href="/clans?mode=1">osu!taiko</a>
|
||||
<a class="2 item" href="/clans?mode=2">osu!catch</a>
|
||||
<a class="3 item" href="/clans?mode=3">osu!mania</a>
|
||||
</div>
|
||||
<table class="ui fixed table">
|
||||
<thead>
|
||||
{{ template "simplepag" 4 }}
|
||||
<tr>
|
||||
<th class="four wide">{{ .T "Rank" }} </th>
|
||||
<th class="four wide">{{ .T "Clan" }} </th>
|
||||
<th class="four wide">{{ .T "PP/Score" }} </th>
|
||||
<th class="four wide">{{ .T "Playcount" }} </th>
|
||||
</tr>
|
||||
</table>
|
||||
<table class="ui fixed table">
|
||||
<thead>
|
||||
{{ range (.Get "clans/stats/all?m=$d" $favMode).clans }}
|
||||
{{ if .name }}
|
||||
<tr>
|
||||
<th class="four wide">#{{ .rank }} </th>
|
||||
<th class="four wide"> <a href="/c/{{ .id }}?mode={{ $favMode }}">{{ .name }}</a></th>
|
||||
<th class="four wide">{{ .chosen_mode.pp }}pp ({{ humanize .chosen_mode.total_score }})</th>
|
||||
<th class="four wide">{{ .chosen_mode.playcount }}</th>
|
||||
</tr>
|
||||
{{end}}
|
||||
{{end}}
|
||||
</thead>
|
||||
</table>
|
||||
</div>
|
||||
{{ end }}
|
||||
@@ -0,0 +1,48 @@
|
||||
{{ define "tpl" }}
|
||||
<div class="ui container">
|
||||
{{ $regEnabled := qb "SELECT value_int FROM system_settings WHERE name = 'ccreation_enabled'" }}
|
||||
{{ $isClan := qb "SELECT user, clan FROM user_clans WHERE user = ?" .Context.User.ID }}
|
||||
{{ if not .Context.User.ID }}
|
||||
<div class="ui segment">
|
||||
{{ .T "You need to login!" }}
|
||||
</div>
|
||||
{{ else if not ($regEnabled.value_int.Bool) }}
|
||||
<div class="ui error message">
|
||||
{{ .T "Sorry, it's not possible to create a clan at the moment. Please try again later." }}
|
||||
</div>
|
||||
{{ else if ($isClan) }}
|
||||
<div class="ui segment">
|
||||
{{ .T "You're already in a Clan." }}
|
||||
</div>
|
||||
{{ else }}
|
||||
<div class="tiny container">
|
||||
<div class="ui raised segments">
|
||||
<div class="ui segment">
|
||||
<form id="register-form" class="ui form" method="post" action="/clans/create">
|
||||
<div class="field">
|
||||
<label>{{ .T "Name (2 to 15 characters, alphanumeric, spaces, <code>_[]-</code>)" | html }}</label>
|
||||
<input tabindex="1" type="text" name="username" placeholder="{{ .T "Name" }}" value="{{ .FormData.username }}" required pattern="{2,15}$">
|
||||
</div>
|
||||
<div class="field">
|
||||
<label class="left aligned">{{ "Clantag (2 to 6 characters)" }}</label>
|
||||
<input tabindex="2" type="text" name="tag" placeholder="{{ "Clantag" }}" value="{{ .FormData.tag }}" pattern="{2,6}$">
|
||||
</div>
|
||||
<div class="field">
|
||||
<label>{{ .T "Description (optional)" }}</label>
|
||||
<input tabindex="3" type="text" name="password" placeholder="{{ .T "Description" }}" value="{{ .FormData.password }}">
|
||||
</div>
|
||||
<div class="field">
|
||||
<label>{{ .T "Icon [URL] (optional)" }}</label>
|
||||
<input tabindex="4" type="url" name="email" placeholder="{{ .T "Icon URL" }}" value="{{ .FormData.email }}">
|
||||
</div>
|
||||
{{ ieForm .Gin }}
|
||||
</form>
|
||||
</div>
|
||||
<div class="ui right aligned segment">
|
||||
<button tabindex="5" class="ui primary button" type="submit" form="register-form">{{ .T "Submit" }}</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{{ end }}
|
||||
</div>
|
||||
{{ end }}
|
||||
@@ -0,0 +1,128 @@
|
||||
{{/*###
|
||||
Include=members.html
|
||||
*/}}
|
||||
{{ define "tpl" }}
|
||||
<div class="ui container">
|
||||
|
||||
{{ if .ClanID }}
|
||||
{{ $gqm := .Gin.Query "mode" }}
|
||||
{{ $global := . }}
|
||||
{{ $favouritemode := $gqm }}
|
||||
{{ range (.Get "clans?id=%d" .ClanID).clans }}
|
||||
<div class="ui top attached segment overflow auto aligned">
|
||||
<div class="magic table">
|
||||
{{ if .icon }}
|
||||
<div class="table element">
|
||||
<img src="{{ .icon }}" alt="icon" class="clan icon" style="border-radius:5%; height:90px;">
|
||||
</div>
|
||||
{{ end }}
|
||||
<div class="table element">
|
||||
<h1 class="ui header">
|
||||
|
||||
{{ $global.T "%s" .name | html }}
|
||||
</h1>
|
||||
<div class="subtitle">
|
||||
{{ $global.T "(%s)" (.tag | htmlescaper) | html }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="ui four item bottom attached menu" id="mode-menu">
|
||||
<a class="mode item" href="/c/{{ .id }}?mode=0">osu!</a>
|
||||
<a class="mode item" href="/c/{{ .id }}?mode=1">osu!taiko</a>
|
||||
<a class="mode item" href="/c/{{ .id }}?mode=2">osu!catch</a>
|
||||
<a class="mode item" href="/c/{{ .id }}?mode=3">osu!mania</a>
|
||||
</div>
|
||||
<div class="ui segment">
|
||||
<div class="ui two column divided stackable grid">
|
||||
<div class="row">
|
||||
<div class="column">
|
||||
|
||||
{{ $global.T "%s" (.description | htmlescaper) | html }}
|
||||
{{ end }}
|
||||
<br><br><table class="ui very basic two column compact table nopad">
|
||||
<tbody>
|
||||
{{ with (.Get "clans/stats?id=%d&m=%d" .ClanID (.Gin.Query "mode"))}}
|
||||
<td></td>
|
||||
<tr>
|
||||
<td><b>{{ $global.T "Global Rank" }}</b></td>
|
||||
<td class="right aligned">#{{ humanize .rank }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><b>{{ $global.T "PP" }}</b></td>
|
||||
<td class="right aligned">{{ humanize .chosen_mode.pp }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><b>{{ $global.T "Ranked Score" }}</b></td>
|
||||
<td class="right aligned">{{ humanize .chosen_mode.ranked_score }}</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td><b>{{ $global.T "Total Score" }}</b></td>
|
||||
<td class="right aligned">{{ humanize .chosen_mode.total_score }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><b>{{ $global.T "Total Playcount" }}</b></td>
|
||||
<td class="right aligned">{{ humanize .chosen_mode.playcount }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><b>{{ $global.T "Total Replays Watched" }}</b></td>
|
||||
<td class="right aligned">{{ humanize .chosen_mode.replays_watched }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><b>{{ $global.T "Total Hits" }}</b></td>
|
||||
<td class="right aligned">{{ humanize .chosen_mode.total_hits }}</td>
|
||||
</tr>
|
||||
{{end}}
|
||||
{{ range (.Get "clans?id=%d" .ClanID).clans }}
|
||||
</tbody>
|
||||
</table>{{ end }}
|
||||
</div>
|
||||
<div class="column">
|
||||
{{ if $global.Context.User.ID }}
|
||||
{{ $d := qb "SELECT user, clan, perms FROM user_clans WHERE user = ? LIMIT 1" .Context.User.ID }}
|
||||
{{ $p := qb "SELECT user, clan, perms FROM user_clans WHERE user = ? AND perms = 8 LIMIT 1" .Context.User.ID }}
|
||||
{{ $tc := qb "SELECT user, clan, perms FROM user_clans WHERE user = ? AND clan = ? LIMIT 1" .Context.User.ID .ClanID }}
|
||||
{{ $uc := or $d.clan.Int -1 }}
|
||||
{{ if $d }}
|
||||
{{ if $tc }}
|
||||
{{ if $p }}
|
||||
<form id="register-form" class="ui form" method="post" action="/c/{{ .ClanID }}">
|
||||
{{ ieForm .Gin }}
|
||||
</form>
|
||||
<div class="ui one item menu"><button tabindex="1" class="ui primary button" style="background-color:rgba(255,0,0,.5)" type="submit" form="register-form">{{ .T "Disband Clan" }}</button></div>
|
||||
{{ else }}
|
||||
<form id="register-form" class="ui form" method="post" action="/c/{{ .ClanID }}">
|
||||
{{ ieForm .Gin }}
|
||||
</form>
|
||||
<div class="ui one item menu"><button tabindex="1" class="ui primary button" style="background-color:rgba(255,0,0,.3)" type="submit" form="register-form">{{ .T "Leave Clan" }}</button></div>
|
||||
{{ end }}
|
||||
{{ else }}
|
||||
<div class="ui one item menu" id="join-menu"><a class="item" style="background-color:rgba(255,0,0,.3)">Already joined a clan</a></div>
|
||||
{{end}}
|
||||
{{ else }}
|
||||
|
||||
{{ end }}
|
||||
{{ else }}
|
||||
<div class="ui one item menu" id="join-menu"><a class="item" href="/login" style="background-color:rgba(0,128,255,.3)">Please login to join a clan</a></div>
|
||||
|
||||
{{ end }}
|
||||
<h1 class="ui heading">{{ .T "Clan Owner" }}</h1>
|
||||
<p>
|
||||
{{ .T "The leader of the clan." }}<br>
|
||||
</p>
|
||||
{{ template "clanMembers" (.Get "clans/members?id=%d&r=%d" .ClanID 8) }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="ui aligned segment">
|
||||
<h1 class="ui heading">{{ .T "Members" }}</h1>
|
||||
<p>
|
||||
{{ .T "The members of the clan." }}<br>
|
||||
</p>
|
||||
{{ template "clanMembers" (.Get "clans/members?id=%d&r=%d" .ClanID 1) }}
|
||||
</div>
|
||||
</div>
|
||||
{{ end }}
|
||||
</div>
|
||||
{{ end }}
|
||||
@@ -0,0 +1,25 @@
|
||||
{{/*###
|
||||
Handler=/help
|
||||
TitleBar=Contact support
|
||||
KyutGrill=help.jpg
|
||||
*/}}
|
||||
{{ define "tpl" }}
|
||||
<div class="ui container">
|
||||
<div class="ui segments">
|
||||
<div class="ui segment">
|
||||
<p>
|
||||
{{ .T "If you need to get in touch with our support team (our Community Managers), you will need to either send an email to our support email address, or join our <a href='https://discord.gg/mT2EsD8'>Discord Server</a>. You can compose an email to it by clicking the button at the bottom of this page." | html }}
|
||||
</p>
|
||||
<p>
|
||||
{{ .T "When contacting the support mail, please make sure to <b>send the email from the email address you signed up on Akatsuki with</b>." | html }}
|
||||
</p>
|
||||
</div>
|
||||
<div class="ui right aligned segment">
|
||||
<a class="ui right labeled blue icon button" href="mailto:[email protected]">
|
||||
<i class="right arrow icon"></i>
|
||||
{{ .T "Do be warned though, our email is rarely checked as we handle most support via the Discord server." }}
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{{ end }}
|
||||
@@ -0,0 +1,41 @@
|
||||
{{/*###
|
||||
NoCompile=true
|
||||
*/}}
|
||||
{{ define "clanMembers" }}
|
||||
{{ with . }}
|
||||
<div class="ui three column center aligned stackable grid">
|
||||
{{ $teamJSON := teamJSON }}
|
||||
{{ range .members }}
|
||||
{{/* ignore fokabot */}}
|
||||
{{ if ne (int .id) 999 }}
|
||||
{{ $tj := index $teamJSON (print .id)}}
|
||||
<div class="column">
|
||||
<div class="ui left aligned fluid card">
|
||||
<div class="image">
|
||||
<img src="{{ config "AvatarURL" }}/{{ .id }}" alt="Avatar">
|
||||
</div>
|
||||
<div class="content">
|
||||
<a class="header" href="/u/{{ .id }}">{{ country .country false }}{{ .username }}</a>
|
||||
{{ with $tj.real_name }}
|
||||
<div class="meta">
|
||||
<a>{{ . }}</a>
|
||||
</div>
|
||||
{{ end }}
|
||||
</div>
|
||||
<div class="extra content">
|
||||
<div title="Registered">
|
||||
<i class="sign in icon"></i>
|
||||
{{ time .registered_on }}
|
||||
</div>
|
||||
<div title="Latest activity">
|
||||
<i class="sign out icon"></i>
|
||||
{{ time .latest_activity }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{{ end }}
|
||||
{{ end }}
|
||||
</div>
|
||||
{{ end }}
|
||||
{{ end }}
|
||||
+15
-1
@@ -37,12 +37,26 @@
|
||||
<div class="ui dropdown item">
|
||||
<span>{{ .T "Beatmaps" }}</span>
|
||||
<div class="menu">
|
||||
{{ navbarItem .Path (.T "Listing") "/beatmaps" }}
|
||||
{{ navbarItem .Path (.T "Request beatmap ranking") "/beatmaps/rank_request" }}
|
||||
</div>
|
||||
</div>
|
||||
<div class="ui dropdown item">
|
||||
<span>{{ .T "Clans" }}</span>
|
||||
<div class="menu">
|
||||
{{ navbarItem .Path (.T "Create Clan") "/clans/create" }}
|
||||
</div>
|
||||
</div>
|
||||
{{ else }}
|
||||
<div class="ui dropdown item">
|
||||
<span>{{ .T "Beatmaps" }}</span>
|
||||
<div class="menu">
|
||||
{{ navbarItem .Path (.T "Listing") "/beatmaps" }}
|
||||
</div>
|
||||
</div>
|
||||
{{ end }}
|
||||
{{ navbarItem .Path (.T "Donate" | printf "<i class=\"red heart icon\"></i>%s") "/donate" }}
|
||||
{{ if $isAdmin }}{{ navbarItem .Path (.T "RAP" | printf "<b>%s</b>") "https://old.yozora.pw/p/100" }}{{ end }}
|
||||
{{ if $isAdmin }}{{ navbarItem .Path (.T "Admin" | printf "<b>%s</b>") "https://old.yozora.pw/p/100" }}{{ end }}
|
||||
{{ end }}
|
||||
<div class="firetrucking-right-menu">
|
||||
<div class="item">
|
||||
|
||||
+18
-1
@@ -62,15 +62,27 @@
|
||||
</div>
|
||||
<div class="table element">
|
||||
<h1 class="ui header">
|
||||
{{ $user := . }}
|
||||
|
||||
{{ if $super }}
|
||||
<div class="owner">
|
||||
{{ .username }}
|
||||
{{ if $user.clan.tag}}
|
||||
<td class="right aligned"><a href="/c/{{ $user.clan.id }}?mode=0">[{{ $user.clan.tag }}]</a></td>
|
||||
{{ end }}
|
||||
|
||||
{{ .username }}
|
||||
</div>
|
||||
{{else if $donor}}
|
||||
<div class="dev">
|
||||
{{ if $user.clan.tag}}
|
||||
<td class="right aligned"><a href="/c/{{ $user.clan.id }}?mode=0">[{{ $user.clan.tag }}]</a></td>
|
||||
{{ end }}
|
||||
{{ .username }}
|
||||
</div>
|
||||
{{ else }}
|
||||
{{ if $user.clan.tag}}
|
||||
<td class="right aligned"><a href="/c/{{ $user.clan.id }}?mode=0">[{{ $user.clan.tag }}]</a></td>
|
||||
{{ end }}
|
||||
{{ .username }}
|
||||
{{ end }}
|
||||
</h1>
|
||||
@@ -115,6 +127,11 @@
|
||||
</div>
|
||||
</div>
|
||||
{{ $user := . }}
|
||||
<div class="ui three item bottom attached menu" id="rx-menu">
|
||||
<a class="0 item" data-rx="0" href="/u/{{ $user.id }}">Vanilla</a>
|
||||
<a class="1 item" data-rx="1" href="/rx/u/{{ $user.id }}">Relax</a>
|
||||
<a class="1 item" data-rx="2" href="/ap/u/{{ $user.id }}">AutoPilot</a>
|
||||
</div>
|
||||
<div class="ui four item bottom attached menu" id="mode-menu">
|
||||
{{ range $k, $v := modes }}
|
||||
<a class="{{ favMode $favouritemode $k }}item" data-mode="{{ $k }}" href="/u/{{ $user.id }}?mode={{ $k }}">{{ $v }}</a>
|
||||
|
||||
@@ -0,0 +1,280 @@
|
||||
{{ define "tpl" }}
|
||||
<div class="ui container">
|
||||
{{ if .UserID }}
|
||||
{{ $gqm := atoi (.Gin.Query "mode") }}
|
||||
{{ $global := . }}
|
||||
{{ with (.Get "users/ap/full?id=%d" .UserID) }}
|
||||
{{ $favouritemode := _or $gqm .favourite_mode }}
|
||||
<script>
|
||||
window.favouriteMode = {{ $favouritemode }};
|
||||
window.userID = {{ .id }};
|
||||
</script>
|
||||
{{ if after .silence_info.end }}
|
||||
<div class="ui error centered message">{{ $global.T "User is <b>silenced</b> for %s, expires %s." (.silence_info.reason | htmlescaper) (time .silence_info.end) | html }}</div>
|
||||
{{ end }}
|
||||
|
||||
{{ $sarah := has .id 1193 }}
|
||||
{{ $alicia := has .id 1000 }}
|
||||
{{ $catherine := has .id 999 }}
|
||||
|
||||
{{ $super := has .privileges 7340031 }}
|
||||
{{ $dev := has .privileges 11534335 }}
|
||||
{{ $donor := has .privileges 7 }}
|
||||
{{ $admin := has .privileges 3049983 }}
|
||||
{{ $chatmod := has .privileges 786763 }}
|
||||
{{ $bn := has .privileges 267 }}
|
||||
|
||||
{{ if hasAdmin $global.Context.User.Privileges }}
|
||||
{{ $restr := not (has .privileges 1) }}
|
||||
{{ $disab := not (has .privileges 2) }}
|
||||
{{ $pend := has .privileges 1048576 }}
|
||||
{{ if and $disab $restr }}
|
||||
{{ if $pend }}
|
||||
<div class="ui warning centered message">{{ $global.T "User is <b>%s</b>" "pending verification" | html }}.</div>
|
||||
{{ else }}
|
||||
<div class="ui error centered message">{{ $global.T "User is <b>%s</b>" "banned" | html }}.</div>
|
||||
{{ end }}
|
||||
{{ else if $restr }}
|
||||
<div class="ui error centered message">{{ $global.T "User is <b>%s</b>" "restricted" | html }}.</div>
|
||||
{{ else if $disab }}
|
||||
<div class="ui error centered message">{{ $global.T "User is <b>%s</b>" "locked" | html }}.</div>
|
||||
{{ end }}
|
||||
{{ end }}
|
||||
{{ with $global.Get "users/userpage?id=%.0f" .id }}
|
||||
{{ if .userpage }}
|
||||
{{ with parseUserpage .userpage }}
|
||||
<div class="ui raised segment twemoji" id="userpage-content">
|
||||
{{ html . }}
|
||||
</div>
|
||||
{{ end }}
|
||||
{{ end }}
|
||||
{{ end }}
|
||||
<div class="ui top attached segment overflow auto">
|
||||
<div class="magic table">
|
||||
<div class="table element">
|
||||
{{ if eq $global.UserID $global.Context.User.ID }}
|
||||
<a href="/settings/avatar">
|
||||
{{ end }}
|
||||
<img src="{{ config "AvatarURL" }}/{{ .id }}" alt="avatar" class="user avatar">
|
||||
{{ if eq $global.UserID $global.Context.User.ID }}
|
||||
</a>
|
||||
{{ end }}
|
||||
</div>
|
||||
<div class="table element">
|
||||
<h1 class="ui header">
|
||||
{{ $user := . }}
|
||||
{{ if $super }}
|
||||
<div class="owner">
|
||||
{{ if $user.clan.tag }}
|
||||
<td class="right aligned"><a href="/c/{{ $user.clan.id }}?mode=0">[{{ $user.clan.tag }}]</a></td>
|
||||
{{ end }}
|
||||
|
||||
{{ .username }}
|
||||
</div>
|
||||
{{else if $donor}}
|
||||
<div class="dev">
|
||||
{{ if $user.clan.tag}}
|
||||
<td class="right aligned"><a href="/c/{{ $user.clan.id }}?mode=0">[{{ $user.clan.tag }}]</a></td>
|
||||
{{ end }}
|
||||
{{ .username }}
|
||||
</div>
|
||||
{{ else }}
|
||||
{{ if $user.clan.tag}}
|
||||
<td class="right aligned"><a href="/c/{{ $user.clan.id }}?mode=0">[{{ $user.clan.tag }}]</a></td>
|
||||
{{ end }}
|
||||
{{ .username }}
|
||||
{{ end }}
|
||||
</h1>
|
||||
{{ if .username_aka }}
|
||||
<div class="subtitle">
|
||||
{{ $global.T "(aka <b>%s</b>)" (.username_aka | htmlescaper) | html }}
|
||||
</div>
|
||||
{{ end }}
|
||||
{{ with bget "isOnline?id=%.0f" .id }}
|
||||
<div class="subtitle">
|
||||
<i class="{{ if .result }}green{{ else }}grey{{ end }} circle icon"></i>
|
||||
{{ if .result }}{{ $global.T "Online" }}{{ else }}{{ $global.T "Offline" }}{{ end }}
|
||||
</div>
|
||||
{{ end }}
|
||||
</div>
|
||||
</div>
|
||||
<div class="magic table floating right">
|
||||
<div class="table element">
|
||||
{{ range $k, $v := (slice .std .taiko .ctb .mania) }}
|
||||
<h1 data-mode="{{ $k }}"{{ if ne $k (int $favouritemode) }} hidden{{ end }}>{{ with and $v $v.global_leaderboard_rank }}#{{ . }}{{ else }}{{ $global.T "Unknown" }}{{ end }}</h1>
|
||||
{{ end }}
|
||||
<div id="profile-actions">
|
||||
{{ if and (ne $global.Context.User.ID $global.UserID) (ne $global.Context.User.ID 0) }}
|
||||
<button class="ui circular mini icon loading button" id="add-friend-button">
|
||||
<i class="horizontal ellipsis icon"></i>
|
||||
</button>
|
||||
{{ end }}
|
||||
{{ if eq $global.Context.User.ID $global.UserID }}
|
||||
<a href="/settings" class="ui circular mini teal icon button"
|
||||
title="{{ $global.T "Settings" }}">
|
||||
<i class="edit icon"></i>
|
||||
</a>
|
||||
{{ end }}
|
||||
{{ if hasAdmin $global.Context.User.Privileges }}
|
||||
<a href="https://old.yozora.pw/index.php?p=103&id={{ $global.UserID }}"
|
||||
target="_blank" title="Quick edit" class="ui circular mini blue icon button">
|
||||
<i class="folder open outline icon"></i>
|
||||
</a>
|
||||
{{ end }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{{ $user := . }}
|
||||
<div class="ui three item bottom attached menu" id="rx-menu">
|
||||
<a class="0 item" data-rx="0" href="/u/{{ $user.id }}">Vanilla</a>
|
||||
<a class="1 item" data-rx="1" href="/rx/u/{{ $user.id }}">Relax</a>
|
||||
<a class="1 item" data-rx="2" href="/ap/u/{{ $user.id }}">AutoPilot</a>
|
||||
</div>
|
||||
<div class="ui four item bottom attached menu" id="mode-menu">
|
||||
{{ range $k, $v := modes }}
|
||||
<a class="{{ favMode $favouritemode $k }}item" data-mode="{{ $k }}" href="/u/{{ $user.id }}?mode={{ $k }}">{{ $v }}</a>
|
||||
{{ end }}
|
||||
</div>
|
||||
<div class="ui segment">
|
||||
<div class="ui three column divided stackable grid">
|
||||
<div class="row">
|
||||
<div class="column">
|
||||
{{if $super }}
|
||||
{{ $global.T "<b >%s</b> " .username | html }}
|
||||
is an <i class="pink code small icon"></i><b>Owner</b>
|
||||
{{ $global.T " from <b>%s</b>." (country .country true) | html }}
|
||||
{{else if $dev}}
|
||||
{{ $global.T "<b>%s</b> " .username | html }}
|
||||
is a <i class="blue code small icon"></i><b>Developer</b>
|
||||
{{ $global.T " from <b>%s</b>." (country .country true) | html }}
|
||||
{{else if $admin}}
|
||||
{{ $global.T "<b>%s</b> " .username | html }}
|
||||
is an <i class="red lightning small icon"></i><b>Administrator</b>
|
||||
{{ $global.T " from <b>%s</b>." (country .country true) | html }}
|
||||
{{else if $chatmod}}
|
||||
{{ $global.T "<b>%s</b> " .username | html }}
|
||||
is a <i class="blue star small icon"></i><b>Chat Mod</b>
|
||||
{{ $global.T " from <b>%s</b>." (country .country true) | html }}
|
||||
{{else if $bn}}
|
||||
{{ $global.T "<b>%s</b> " .username | html }}
|
||||
is a <i class="orange universal access small icon"></i><b>Nominator</b>
|
||||
{{ $global.T " from <b>%s</b>." (country .country true) | html }}
|
||||
{{else if $donor }}
|
||||
{{ $global.T "<b>%s</b> " .username | html }}
|
||||
is a <i class="pink heart small icon"></i><b>Supporter</b>
|
||||
{{ $global.T " from <b>%s</b>." (country .country true) | html }}
|
||||
{{ else }}
|
||||
{{ $global.T "<b>%s</b> is a player from <b>%s</b>." .username (country .country true) | html }}
|
||||
{{ end }}
|
||||
|
||||
<br>{{ $global.T "They signed up on Yozora %s." (time $user.registered_on) | html }}
|
||||
<br>{{ $global.T "Last seen: %s." (time $user.latest_activity) | html }}
|
||||
<br>{{ with playstyle .play_style $global }}{{ $global.T "They play with %s." . }}{{ end }}
|
||||
</div>
|
||||
<div class="column">
|
||||
{{ if and (not .badges) (not .custom_badge) }}
|
||||
{{ $global.T "This user hasn't got any badges!" }}
|
||||
{{ else }}
|
||||
<div class="ui grid">
|
||||
{{ range .badges }}
|
||||
<div class="eight wide centered column">
|
||||
<i class="circular {{ faIcon .icon }} big icon"></i><br>
|
||||
<b>{{ .name }}</b>
|
||||
</div>
|
||||
{{ end }}
|
||||
{{ with .custom_badge }}
|
||||
<div class="eight wide centered column">
|
||||
<i class="circular {{ faIcon .icon }} big icon"></i><br>
|
||||
<b><i>{{ .name }}</i></b>
|
||||
</div>
|
||||
{{ end }}
|
||||
</div>
|
||||
{{ end }}
|
||||
</div>
|
||||
<div class="column">
|
||||
{{ range $k, $v := (slice .std .taiko .ctb .mania) }}
|
||||
<div data-mode="{{ $k }}" {{ if ne $k (int $favouritemode) }} hidden{{ end }}>
|
||||
<table class="ui very basic two column compact table nopad">
|
||||
<tbody>
|
||||
{{ with .global_leaderboard_rank }}
|
||||
<tr>
|
||||
<td><b>{{ $global.T "Global rank" }}</b></td>
|
||||
<td class="right aligned">#{{ . }}</td>
|
||||
</tr>
|
||||
{{ end }}
|
||||
{{ with .country_leaderboard_rank }}
|
||||
<tr>
|
||||
<td><b>{{ $global.T "Country rank" }} {{ country $user.country false }}</b></td>
|
||||
<td class="right aligned">#{{ . }}</td>
|
||||
</tr>
|
||||
{{ end }}
|
||||
<tr>
|
||||
<td><b>{{ $global.T "PP" }}</b></td>
|
||||
<td class="right aligned">{{ humanize .pp }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><b>{{ $global.T "Ranked score" }}</b></td>
|
||||
<td class="right aligned">{{ humanize .ranked_score }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><b>{{ $global.T "Total score" }}</b></td>
|
||||
<td class="right aligned">{{ humanize .total_score }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><b>{{ $global.T "Playcount" }}</b></td>
|
||||
<td class="right aligned">{{ humanize .playcount }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><b>{{ $global.T "Replays watched" }}</b></td>
|
||||
<td class="right aligned">{{ humanize .replays_watched }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><b>{{ $global.T "Total hits" }}</b></td>
|
||||
<td class="right aligned">{{ humanize .total_hits }}</td>
|
||||
</tr> <tr>
|
||||
<td><b>{{ $global.T "Accuracy" }}</b></td>
|
||||
<td class="right aligned">{{ printf "%.2f" .accuracy }}%</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<div class="ui blue progress little margin top" data-percent="{{ levelPercent .level }}">
|
||||
<div class="bar">
|
||||
<div class="progress">{{ levelPercent .level }}%</div>
|
||||
</div>
|
||||
<div class="label">{{ $global.T "Level %s" (level .level) }}</div>
|
||||
</div>
|
||||
</div>
|
||||
{{ end }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div> <!-- end grid segment -->
|
||||
<div id="scores-zone">
|
||||
{{ range _range 4 }}
|
||||
<div data-mode="{{ . }}" {{ if ne . (int $favouritemode) }} hidden{{ end }} data-loaded="0">
|
||||
</div>
|
||||
{{ end }}
|
||||
</div>
|
||||
|
||||
<div class="ui segment">
|
||||
<h2 class="ui header">{{ $global.T "Achievements" }}</h2>
|
||||
<div id="achievements" class="ui grid">
|
||||
</div>
|
||||
<div class="right aligned">
|
||||
<button class="ui disabled button" id="load-more-achievements">
|
||||
{{ $global.T "Load more" }}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="ui modal">
|
||||
<i class="close icon"></i>
|
||||
<div class="content">
|
||||
<table class="ui definition table" id="score-data-table">
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
{{ end }}
|
||||
{{ end }}
|
||||
</div>
|
||||
{{ end }}
|
||||
@@ -0,0 +1,280 @@
|
||||
{{ define "tpl" }}
|
||||
<div class="ui container">
|
||||
{{ if .UserID }}
|
||||
{{ $gqm := atoi (.Gin.Query "mode") }}
|
||||
{{ $global := . }}
|
||||
{{ with (.Get "users/rx/full?id=%d" .UserID) }}
|
||||
{{ $favouritemode := _or $gqm .favourite_mode }}
|
||||
<script>
|
||||
window.favouriteMode = {{ $favouritemode }};
|
||||
window.userID = {{ .id }};
|
||||
</script>
|
||||
{{ if after .silence_info.end }}
|
||||
<div class="ui error centered message">{{ $global.T "User is <b>silenced</b> for %s, expires %s." (.silence_info.reason | htmlescaper) (time .silence_info.end) | html }}</div>
|
||||
{{ end }}
|
||||
|
||||
{{ $sarah := has .id 1193 }}
|
||||
{{ $alicia := has .id 1000 }}
|
||||
{{ $catherine := has .id 999 }}
|
||||
|
||||
{{ $super := has .privileges 7340031 }}
|
||||
{{ $dev := has .privileges 11534335 }}
|
||||
{{ $donor := has .privileges 7 }}
|
||||
{{ $admin := has .privileges 3049983 }}
|
||||
{{ $chatmod := has .privileges 786763 }}
|
||||
{{ $bn := has .privileges 267 }}
|
||||
|
||||
{{ if hasAdmin $global.Context.User.Privileges }}
|
||||
{{ $restr := not (has .privileges 1) }}
|
||||
{{ $disab := not (has .privileges 2) }}
|
||||
{{ $pend := has .privileges 1048576 }}
|
||||
{{ if and $disab $restr }}
|
||||
{{ if $pend }}
|
||||
<div class="ui warning centered message">{{ $global.T "User is <b>%s</b>" "pending verification" | html }}.</div>
|
||||
{{ else }}
|
||||
<div class="ui error centered message">{{ $global.T "User is <b>%s</b>" "banned" | html }}.</div>
|
||||
{{ end }}
|
||||
{{ else if $restr }}
|
||||
<div class="ui error centered message">{{ $global.T "User is <b>%s</b>" "restricted" | html }}.</div>
|
||||
{{ else if $disab }}
|
||||
<div class="ui error centered message">{{ $global.T "User is <b>%s</b>" "locked" | html }}.</div>
|
||||
{{ end }}
|
||||
{{ end }}
|
||||
{{ with $global.Get "users/userpage?id=%.0f" .id }}
|
||||
{{ if .userpage }}
|
||||
{{ with parseUserpage .userpage }}
|
||||
<div class="ui raised segment twemoji" id="userpage-content">
|
||||
{{ html . }}
|
||||
</div>
|
||||
{{ end }}
|
||||
{{ end }}
|
||||
{{ end }}
|
||||
<div class="ui top attached segment overflow auto">
|
||||
<div class="magic table">
|
||||
<div class="table element">
|
||||
{{ if eq $global.UserID $global.Context.User.ID }}
|
||||
<a href="/settings/avatar">
|
||||
{{ end }}
|
||||
<img src="{{ config "AvatarURL" }}/{{ .id }}" alt="avatar" class="user avatar">
|
||||
{{ if eq $global.UserID $global.Context.User.ID }}
|
||||
</a>
|
||||
{{ end }}
|
||||
</div>
|
||||
<div class="table element">
|
||||
<h1 class="ui header">
|
||||
{{ $user := . }}
|
||||
{{ if $super }}
|
||||
<div class="owner">
|
||||
{{ if $user.clan.tag}}
|
||||
<td class="right aligned"><a href="/c/{{ $user.clan.id }}?mode=0">[{{ $user.clan.tag }}]</a></td>
|
||||
{{ end }}
|
||||
|
||||
{{ .username }}
|
||||
</div>
|
||||
{{else if $donor}}
|
||||
<div class="dev">
|
||||
{{ if $user.clan.tag}}
|
||||
<td class="right aligned"><a href="/c/{{ $user.clan.id }}?mode=0">[{{ $user.clan.tag }}]</a></td>
|
||||
{{ end }}
|
||||
{{ .username }}
|
||||
</div>
|
||||
{{ else }}
|
||||
{{ if $user.clan.tag}}
|
||||
<td class="right aligned"><a href="/c/{{ $user.clan.id }}?mode=0">[{{ $user.clan.tag }}]</a></td>
|
||||
{{ end }}
|
||||
{{ .username }}
|
||||
{{ end }}
|
||||
</h1>
|
||||
{{ if .username_aka }}
|
||||
<div class="subtitle">
|
||||
{{ $global.T "(aka <b>%s</b>)" (.username_aka | htmlescaper) | html }}
|
||||
</div>
|
||||
{{ end }}
|
||||
{{ with bget "isOnline?id=%.0f" .id }}
|
||||
<div class="subtitle">
|
||||
<i class="{{ if .result }}green{{ else }}grey{{ end }} circle icon"></i>
|
||||
{{ if .result }}{{ $global.T "Online" }}{{ else }}{{ $global.T "Offline" }}{{ end }}
|
||||
</div>
|
||||
{{ end }}
|
||||
</div>
|
||||
</div>
|
||||
<div class="magic table floating right">
|
||||
<div class="table element">
|
||||
{{ range $k, $v := (slice .std .taiko .ctb .mania) }}
|
||||
<h1 data-mode="{{ $k }}"{{ if ne $k (int $favouritemode) }} hidden{{ end }}>{{ with and $v $v.global_leaderboard_rank }}#{{ . }}{{ else }}{{ $global.T "Unknown" }}{{ end }}</h1>
|
||||
{{ end }}
|
||||
<div id="profile-actions">
|
||||
{{ if and (ne $global.Context.User.ID $global.UserID) (ne $global.Context.User.ID 0) }}
|
||||
<button class="ui circular mini icon loading button" id="add-friend-button">
|
||||
<i class="horizontal ellipsis icon"></i>
|
||||
</button>
|
||||
{{ end }}
|
||||
{{ if eq $global.Context.User.ID $global.UserID }}
|
||||
<a href="/settings" class="ui circular mini teal icon button"
|
||||
title="{{ $global.T "Settings" }}">
|
||||
<i class="edit icon"></i>
|
||||
</a>
|
||||
{{ end }}
|
||||
{{ if hasAdmin $global.Context.User.Privileges }}
|
||||
<a href="https://old.yozora.pw/index.php?p=103&id={{ $global.UserID }}"
|
||||
target="_blank" title="Quick edit" class="ui circular mini blue icon button">
|
||||
<i class="folder open outline icon"></i>
|
||||
</a>
|
||||
{{ end }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{{ $user := . }}
|
||||
<div class="ui three item bottom attached menu" id="rx-menu">
|
||||
<a class="0 item" data-rx="0" href="/u/{{ $user.id }}">Vanilla</a>
|
||||
<a class="1 item" data-rx="1" href="/rx/u/{{ $user.id }}">Relax</a>
|
||||
<a class="1 item" data-rx="2" href="/ap/u/{{ $user.id }}">AutoPilot</a>
|
||||
</div>
|
||||
<div class="ui four item bottom attached menu" id="mode-menu">
|
||||
{{ range $k, $v := modes }}
|
||||
<a class="{{ favMode $favouritemode $k }}item" data-mode="{{ $k }}" href="/u/{{ $user.id }}?mode={{ $k }}">{{ $v }}</a>
|
||||
{{ end }}
|
||||
</div>
|
||||
<div class="ui segment">
|
||||
<div class="ui three column divided stackable grid">
|
||||
<div class="row">
|
||||
<div class="column">
|
||||
{{if $super }}
|
||||
{{ $global.T "<b >%s</b> " .username | html }}
|
||||
is an <i class="pink code small icon"></i><b>Owner</b>
|
||||
{{ $global.T " from <b>%s</b>." (country .country true) | html }}
|
||||
{{else if $dev}}
|
||||
{{ $global.T "<b>%s</b> " .username | html }}
|
||||
is a <i class="blue code small icon"></i><b>Developer</b>
|
||||
{{ $global.T " from <b>%s</b>." (country .country true) | html }}
|
||||
{{else if $admin}}
|
||||
{{ $global.T "<b>%s</b> " .username | html }}
|
||||
is an <i class="red lightning small icon"></i><b>Administrator</b>
|
||||
{{ $global.T " from <b>%s</b>." (country .country true) | html }}
|
||||
{{else if $chatmod}}
|
||||
{{ $global.T "<b>%s</b> " .username | html }}
|
||||
is a <i class="blue star small icon"></i><b>Chat Mod</b>
|
||||
{{ $global.T " from <b>%s</b>." (country .country true) | html }}
|
||||
{{else if $bn}}
|
||||
{{ $global.T "<b>%s</b> " .username | html }}
|
||||
is a <i class="orange universal access small icon"></i><b>Nominator</b>
|
||||
{{ $global.T " from <b>%s</b>." (country .country true) | html }}
|
||||
{{else if $donor }}
|
||||
{{ $global.T "<b>%s</b> " .username | html }}
|
||||
is a <i class="pink heart small icon"></i><b>Supporter</b>
|
||||
{{ $global.T " from <b>%s</b>." (country .country true) | html }}
|
||||
{{ else }}
|
||||
{{ $global.T "<b>%s</b> is a player from <b>%s</b>." .username (country .country true) | html }}
|
||||
{{ end }}
|
||||
|
||||
<br>{{ $global.T "They signed up on Yozora %s." (time $user.registered_on) | html }}
|
||||
<br>{{ $global.T "Last seen: %s." (time $user.latest_activity) | html }}
|
||||
<br>{{ with playstyle .play_style $global }}{{ $global.T "They play with %s." . }}{{ end }}
|
||||
</div>
|
||||
<div class="column">
|
||||
{{ if and (not .badges) (not .custom_badge) }}
|
||||
{{ $global.T "This user hasn't got any badges!" }}
|
||||
{{ else }}
|
||||
<div class="ui grid">
|
||||
{{ range .badges }}
|
||||
<div class="eight wide centered column">
|
||||
<i class="circular {{ faIcon .icon }} big icon"></i><br>
|
||||
<b>{{ .name }}</b>
|
||||
</div>
|
||||
{{ end }}
|
||||
{{ with .custom_badge }}
|
||||
<div class="eight wide centered column">
|
||||
<i class="circular {{ faIcon .icon }} big icon"></i><br>
|
||||
<b><i>{{ .name }}</i></b>
|
||||
</div>
|
||||
{{ end }}
|
||||
</div>
|
||||
{{ end }}
|
||||
</div>
|
||||
<div class="column">
|
||||
{{ range $k, $v := (slice .std .taiko .ctb .mania) }}
|
||||
<div data-mode="{{ $k }}" {{ if ne $k (int $favouritemode) }} hidden{{ end }}>
|
||||
<table class="ui very basic two column compact table nopad">
|
||||
<tbody>
|
||||
{{ with .global_leaderboard_rank }}
|
||||
<tr>
|
||||
<td><b>{{ $global.T "Global rank" }}</b></td>
|
||||
<td class="right aligned">#{{ . }}</td>
|
||||
</tr>
|
||||
{{ end }}
|
||||
{{ with .country_leaderboard_rank }}
|
||||
<tr>
|
||||
<td><b>{{ $global.T "Country rank" }} {{ country $user.country false }}</b></td>
|
||||
<td class="right aligned">#{{ . }}</td>
|
||||
</tr>
|
||||
{{ end }}
|
||||
<tr>
|
||||
<td><b>{{ $global.T "PP" }}</b></td>
|
||||
<td class="right aligned">{{ humanize .pp }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><b>{{ $global.T "Ranked score" }}</b></td>
|
||||
<td class="right aligned">{{ humanize .ranked_score }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><b>{{ $global.T "Total score" }}</b></td>
|
||||
<td class="right aligned">{{ humanize .total_score }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><b>{{ $global.T "Playcount" }}</b></td>
|
||||
<td class="right aligned">{{ humanize .playcount }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><b>{{ $global.T "Replays watched" }}</b></td>
|
||||
<td class="right aligned">{{ humanize .replays_watched }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><b>{{ $global.T "Total hits" }}</b></td>
|
||||
<td class="right aligned">{{ humanize .total_hits }}</td>
|
||||
</tr> <tr>
|
||||
<td><b>{{ $global.T "Accuracy" }}</b></td>
|
||||
<td class="right aligned">{{ printf "%.2f" .accuracy }}%</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<div class="ui blue progress little margin top" data-percent="{{ levelPercent .level }}">
|
||||
<div class="bar">
|
||||
<div class="progress">{{ levelPercent .level }}%</div>
|
||||
</div>
|
||||
<div class="label">{{ $global.T "Level %s" (level .level) }}</div>
|
||||
</div>
|
||||
</div>
|
||||
{{ end }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div> <!-- end grid segment -->
|
||||
<div id="scores-zone">
|
||||
{{ range _range 4 }}
|
||||
<div data-mode="{{ . }}" {{ if ne . (int $favouritemode) }} hidden{{ end }} data-loaded="0">
|
||||
</div>
|
||||
{{ end }}
|
||||
</div>
|
||||
|
||||
<div class="ui segment">
|
||||
<h2 class="ui header">{{ $global.T "Achievements" }}</h2>
|
||||
<div id="achievements" class="ui grid">
|
||||
</div>
|
||||
<div class="right aligned">
|
||||
<button class="ui disabled button" id="load-more-achievements">
|
||||
{{ $global.T "Load more" }}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="ui modal">
|
||||
<i class="close icon"></i>
|
||||
<div class="content">
|
||||
<table class="ui definition table" id="score-data-table">
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
{{ end }}
|
||||
{{ end }}
|
||||
</div>
|
||||
{{ end }}
|
||||
@@ -2,52 +2,60 @@
|
||||
<div class="ui container">
|
||||
{{ $regEnabled := qb "SELECT value_int FROM system_settings WHERE name = 'registrations_enabled'" }}
|
||||
{{ if .Context.User.ID }}
|
||||
<div class="ui segment">
|
||||
{{ .T "You're already logged in!" }}
|
||||
</div>
|
||||
<div class="ui segment">
|
||||
{{ .T "You're already logged in!" }}
|
||||
</div>
|
||||
{{ else if not ($regEnabled.value_int.Bool) }}
|
||||
<div class="ui error message">
|
||||
{{ .T "Sorry, it's not possible to register at the moment. Please try again later." }}
|
||||
</div>
|
||||
<div class="ui error message">
|
||||
{{ .T "Sorry, it's not possible to register at the moment. Please try again later." }}
|
||||
</div>
|
||||
{{ else }}
|
||||
{{ if eq (.Gin.Query "stopsign") "1" }}
|
||||
<div class="ui warning message">
|
||||
{{ .T "Remember: this seems like it's your second account! Do not multiaccount, or you're likely to get restricted!" }}
|
||||
{{ if eq (.Gin.Query "stopsign") "1" }}
|
||||
<div class="ui warning message">
|
||||
{{ .T "Remember: this seems like it's your second account! Do not multiaccount, or you're likely to get restricted!" }}
|
||||
</div>
|
||||
{{ end }}
|
||||
<div class="ui info message">
|
||||
<center> Don't have a code? Apply <a href="https://docs.google.com/forms/d/1oYO8Cky0piTsfhMDxnQOZnNOo4K4tT3itZ5CdLY-w2k">here!</a></center>
|
||||
</div>
|
||||
<div class="tiny container">
|
||||
<div class="ui raised segments">
|
||||
<div class="ui segment">
|
||||
<form id="register-form" class="ui form" method="post" action="/register">
|
||||
<div class="field">
|
||||
<label>{{ .T "Username (2 to 15 characters, alphanumeric, spaces, <code>_[]-</code>)" | html }}</label>
|
||||
<input tabindex="1" type="text" name="username" placeholder="{{ .T "Username" }}"
|
||||
value="{{ .FormData.username }}" required pattern="^[A-Za-z0-9 _\[\]-]{2,15}$">
|
||||
</div>
|
||||
<div class="field">
|
||||
<label>{{ .T "Password (at least 8 characters)" }}</label>
|
||||
<input tabindex="2" type="password" name="password" placeholder="{{ .T "Password" }}"
|
||||
value="{{ .FormData.password }}" required pattern="^.{8,}$">
|
||||
</div>
|
||||
<div class="field">
|
||||
<label>{{ .T "Email" }}</label>
|
||||
<input tabindex="3" type="email" name="email" placeholder="{{ .T "Email" }}"
|
||||
value="{{ .FormData.email }}" required>
|
||||
</div>
|
||||
<div class="field">
|
||||
<label>{{ .T "Registration Key" }}</label>
|
||||
<input tabindex="3" type="text" name="key" placeholder="{{ .T "Key" }}"
|
||||
value="{{ .FormData.key }}" required>
|
||||
</div>
|
||||
{{ with config "RecaptchaSite" }}
|
||||
<div class="field">
|
||||
<div class="g-recaptcha" data-sitekey="{{ . }}"></div>
|
||||
</div>
|
||||
{{ end }}
|
||||
{{ ieForm .Gin }}
|
||||
</form>
|
||||
</div>
|
||||
{{ end }}
|
||||
<div class="tiny container">
|
||||
<div class="ui raised segments">
|
||||
<div class="ui segment">
|
||||
<form id="register-form" class="ui form" method="post" action="/register">
|
||||
<div class="field">
|
||||
<label>{{ .T "Username (2 to 15 characters, alphanumeric, spaces, <code>_[]-</code>)" | html }}</label>
|
||||
<input tabindex="1" type="text" name="username" placeholder="{{ .T "Username" }}" value="{{ .FormData.username }}" required pattern="^[A-Za-z0-9 _\[\]-]{2,15}$">
|
||||
</div>
|
||||
<div class="field">
|
||||
<label>{{ .T "Password (at least 8 characters)" }}</label>
|
||||
<input tabindex="2" type="password" name="password" placeholder="{{ .T "Password" }}" value="{{ .FormData.password }}" required pattern="^.{8,}$">
|
||||
</div>
|
||||
<div class="field">
|
||||
<label>{{ .T "Email" }}</label>
|
||||
<input tabindex="3" type="email" name="email" placeholder="{{ .T "Email" }}" value="{{ .FormData.email }}" required>
|
||||
</div>
|
||||
<div class="field">
|
||||
<label>{{ .T "Registration Key" }}</label>
|
||||
<input tabindex="3" type="text" name="key" placeholder="{{ .T "Key" }}" value="{{ .FormData.key }}" required>
|
||||
</div>
|
||||
{{ with config "RecaptchaSite" }}
|
||||
<div class="field">
|
||||
<div class="g-recaptcha" data-sitekey="{{ . }}"></div>
|
||||
</div>
|
||||
{{ end }}
|
||||
{{ ieForm .Gin }}
|
||||
</form>
|
||||
</div>
|
||||
<div class="ui right aligned segment">
|
||||
<button tabindex="4" class="ui primary button" type="submit" form="register-form">{{ .T "Submit" }}</button>
|
||||
</div>
|
||||
<div class="ui right aligned segment">
|
||||
<button tabindex="4" class="ui primary button" type="submit"
|
||||
form="register-form">{{ .T "Submit" }}</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{{ end }}
|
||||
</div>
|
||||
{{ end }}
|
||||
@@ -0,0 +1,86 @@
|
||||
{{/*###
|
||||
Handler=/settings/clansettings
|
||||
TitleBar=Clan Settings
|
||||
Include=menu.html
|
||||
*/}}
|
||||
{{ define "tpl" }}
|
||||
<div class="ui container">
|
||||
<div class="ui stackable grid">
|
||||
{{ template "settingsSidebar" . }}
|
||||
<div class="twelve wide column">
|
||||
<div class="ui segment">
|
||||
{{ $d := qb "SELECT user, clan, perms FROM user_clans WHERE user = ? AND perms = 8 LIMIT 1" .Context.User.ID }}
|
||||
{{ $g := or $d.clan.Int -1 }}
|
||||
{{ if $d }}
|
||||
<font size="6">Clan Settings</font>
|
||||
<br>
|
||||
<br>
|
||||
<div class="ui center aligned segment">
|
||||
{{ $o := (.Get "clans/isclan?uid=%d" .Context.User.ID).clan.clan }}
|
||||
{{ $c := qb "SELECT * FROM clans WHERE id = ? LIMIT 1" $o }}
|
||||
{{ $tag := or $c.tag.String "" }}
|
||||
{{ $desc := or $c.description.String "" }}
|
||||
{{ $icon := or $c.icon.String "" }}
|
||||
{{ $bg := or $c.background.String "" }}
|
||||
<form id="register-form" class="ui form" method="post" action="/settings/clansettings">
|
||||
<div class="field">
|
||||
<label class="left aligned">{{ "Clantag (2 to 6 characters)" }}</label>
|
||||
<input tabindex="1" type="text" name="tag" placeholder="{{ "Clantag" }}" value="{{ $tag }}" pattern="{2,6}$">
|
||||
</div>
|
||||
<div class="field">
|
||||
<label class="left aligned">{{ "Description (optional)" }}</label>
|
||||
<input tabindex="2" type="text" name="password" placeholder="{{ "Description" }}" value="{{ $desc }}">
|
||||
</div>
|
||||
<div class="field">
|
||||
<label class="left aligned">{{ "Icon [URL] (optional)" }}</label>
|
||||
<input tabindex="3" type="url" name="email" placeholder="{{ "Icon URL" }}" value="{{ $icon }}">
|
||||
</div>
|
||||
{{ if has .Context.User.Privileges 8388612 }}
|
||||
<div class="field">
|
||||
<label class="left aligned">{{ "Background [URL] (optional)" }}</label>
|
||||
<input tabindex="4" type="url" name="bg" placeholder="{{ "Background URL" }}" value="{{ $bg }}">
|
||||
</div>
|
||||
|
||||
{{ end }}
|
||||
{{ ieForm .Gin }}
|
||||
</form>
|
||||
|
||||
<br>
|
||||
<button tabindex="5" class="ui primary button" type="submit" form="register-form">{{ .T "Save" }}</button>
|
||||
</div>
|
||||
<br>
|
||||
<font size="6">Invite</font>
|
||||
<br>
|
||||
<br><center><div class="ui two item menu" id="join-menu">
|
||||
{{ with .Get "clans/getinvite?id=%d" .Context.User.ID }}
|
||||
<input class="item" type="text" value="https://yozora.pw/clans/invite/{{ .invite }}" href="https://yozora.pw/clans/invite/{{ .invite }}" style="background-color:rgba(0,0,0,.6)" disabled></input>
|
||||
{{ end }}
|
||||
</div>
|
||||
<br><form action="/settings/clansettings" method="POST">
|
||||
{{ ieForm .Gin }}
|
||||
<button type="submit" class="ui right green button">
|
||||
{{ .T "Generate a new invite!" }}
|
||||
</button>
|
||||
</form>
|
||||
<br>
|
||||
<font size="6">Members {{ $g }}</font>
|
||||
<br>
|
||||
{{ range (.Get "clans/members?id=%d&r=%d" $g 1).members }}
|
||||
<form id="kick-form" class="ui form" method="post" action="/settings/clansettings/k">
|
||||
<div class="column">
|
||||
<div class="ui left aligned fluid card">
|
||||
<div class="content">
|
||||
<a href="/u/{{ .id }}"><a class="header" href="/u/{{ .id }}">{{ country .country false }}{{ .username }}</a> <button name="member" value="{{ .id }}" class="ui right green button" style="float:right; display:block; margin-right:0px; clear:left; width: 40%;"> Kick </button></a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
{{ end }}
|
||||
{{ else }}
|
||||
<font size="3">You haven't joined a clan yet, or you aren't the owner of your current one.</font>
|
||||
{{ end }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{{ end }}
|
||||
@@ -15,6 +15,8 @@ NoCompile=true
|
||||
{{ navbarItem .Path (.T "Two Factor Authentication") "/settings/2fa" }}
|
||||
|
||||
{{ navbarItem .Path (.T "Authorized applications") "/settings/authorized_applications" }}
|
||||
|
||||
{{ navbarItem .Path (.T "Clan Settings") "/settings/clansettings" }}
|
||||
|
||||
{{/* Stuff for donators */}}
|
||||
{{ if has .Context.User.Privileges 4 }}
|
||||
|
||||
@@ -64,6 +64,9 @@ KyutGrill=team2.jpg
|
||||
{{ .T "<b>jrosdahl</b>, for <a href='https://github.com/jrosdahl/miniircd'>miniircd</a>, used as a base for our IRC server." | html }}<br>
|
||||
miniircd is licensed under GPL v2. Our implementation can be found <a href="https://zxq.co/ripple/pep.py/src/master/irc/ircserver.py">here</a>.
|
||||
</li>
|
||||
<li>
|
||||
{{ .T "<b>Kotrik</b>, for helping out with some features." | html }}.
|
||||
</li>
|
||||
<li>{{ .T "<b>Jacksonisiah</b>, for designing the Yozora logo." | html }}</li>
|
||||
<li>{{ .T "<b><a id='everyone' class='clickable'>Everyone</a></b> who has supported the Yozora project by donating or inviting other people." | html }}</li>
|
||||
</ul>
|
||||
|
||||
Reference in new issue
Block a user