Albirew/nyaa-pantsu
Albirew
/
nyaa-pantsu
Archivé
1
0
Bifurcation 0

User Settings Notification (WIP)

Cette révision appartient à :
akuma06 2017-05-21 18:13:28 +02:00
Parent 8081e0b639
révision 32c51a57cb
6 fichiers modifiés avec 105 ajouts et 40 suppressions

13
config/notifications.go Fichier normal
Voir le fichier

@ -0,0 +1,13 @@
package config
/*
* Here we config the notifications options
*/
var EnableNotifications = map[string]bool {
"new_torrent": true,
"new_comment_owner": true,
"new_comment_all": true,
"new_follower": false,
"followed": false,
}

Voir le fichier

@ -24,6 +24,7 @@ type User struct {
ApiToken string `gorm:"column:api_token"`
ApiTokenExpiry time.Time `gorm:"column:api_token_expiry"`
Language string `gorm:"column:language"`
UserSettings string `gorm:"column:settings"`
// TODO: move this to PublicUser
Likings []User // Don't work `gorm:"foreignkey:user_id;associationforeignkey:follower_id;many2many:user_follows"`
@ -31,9 +32,10 @@ type User struct {
MD5 string `json:"md5" gorm:"column:md5"` // Hash of email address, used for Gravatar
Torrents []Torrent `gorm:"ForeignKey:UploaderID"`
Notifications []Notification `gorm:"ForeignKey:UserID"`
UnreadNotifications int `gorm:"-"` // We don't want to loop every notifications when accessing user unread notif
Notifications []Notification `gorm:"ForeignKey:UserID"`
Settings *UserSettings `gorm:"-"` // We don't want to loop every notifications when accessing user unread notif
}
type UserJSON struct {
@ -99,6 +101,10 @@ type UserUploadsOld struct {
TorrentId uint `gorm:"column:torrent_id"`
}
type UserSettings struct {
settings map[string]interface{} `json:"settings"`
}
func (c UserUploadsOld) TableName() string {
// is this needed here?
return config.UploadsOldTableName
@ -115,3 +121,26 @@ func (u *User) ToJSON() UserJSON {
}
return json
}
/* User Settings */
func(s *UserSettings) Get(key string) interface{} {
return s.settings[key]
}
func (s *UserSettings) Set(key string, val interface{}) {
s.settings[key] = val
}
func (s *UserSettings) GetSettings() {
return s.settings
}
func (u *User) SaveSettings() {
u.UserSettings , _ = json.Marshal(u.Settings.GetSettings())
}
func (u *User) ParseSettings() {
if len(u.Settings.GetSettings()) == 0
json.Unmarshal([]byte(u.UserSettings), u.Settings)
}

Voir le fichier

@ -79,14 +79,16 @@ func UploadPostHandler(w http.ResponseWriter, r *http.Request) {
url, err := Router.Get("view_torrent").URL("id", strconv.FormatUint(uint64(torrent.ID), 10))
if (user.ID > 0) { // If we are a member
if (user.ID > 0 && config.EnableNotifications["new_torrent"]) { // If we are a member and notifications for new torrents are enabled
userService.GetLikings(user) // We populate the liked field for users
if len(user.Likings) > 0 { // If we are followed by at least someone
for _, follower := range user.Likings {
T, _, _ := languages.TfuncAndLanguageWithFallback(user.Language, user.Language) // We need to send the notification to every user in their language
follower.ParseSettings() // We need to call it before checking settings
if follower.Settings.Get("notifications.new_torrent"] {
T, _, _ := languages.TfuncAndLanguageWithFallback(user.Language, user.Language) // We need to send the notification to every user in their language
notifierService.NotifyUser(&follower, torrent.Identifier(), fmt.Sprintf(T("new_torrent_uploaded"), torrent.Name, user.Username), url.String())
notifierService.NotifyUser(&follower, torrent.Identifier(), fmt.Sprintf(T("new_torrent_uploaded"), torrent.Name, user.Username), url.String())
}
}
}
}

Voir le fichier

@ -137,40 +137,42 @@ func UserProfileFormHandler(w http.ResponseWriter, r *http.Request) {
NotFoundHandler(w, r)
return
}
messages := msg.GetMessages(r)
userForm := form.UserForm{}
err := form.NewErrors()
infos := form.NewInfos()
userSettingsForm := form.UserSettingsForm{}
T := languages.GetTfuncFromRequest(r)
if len(r.PostFormValue("email")) > 0 {
_, err = form.EmailValidation(r.PostFormValue("email"), err)
form.EmailValidation(r.PostFormValue("email"), &messages)
}
if len(r.PostFormValue("username")) > 0 {
_, err = form.ValidateUsername(r.PostFormValue("username"), err)
form.ValidateUsername(r.PostFormValue("username"), &messages)
}
if len(err) == 0 {
if !messages.HasErrors() {
modelHelper.BindValueForm(&userForm, r)
modelHelper.BindValueForm(&userSettingsForm, r)
if !userPermission.HasAdmin(currentUser) {
userForm.Username = userProfile.Username
userForm.Status = userProfile.Status
} else {
if userProfile.Status != userForm.Status && userForm.Status == 2 {
err["errors"] = append(err["errors"], "Elevating status to moderator is prohibited")
messages.AddError("errors", "Elevating status to moderator is prohibited")
}
}
err = modelHelper.ValidateForm(&userForm, err)
if len(err) == 0 {
modelHelper.ValidateForm(&userForm, &messages)
if !messages.HasErrors() {
if userForm.Email != userProfile.Email {
userService.SendVerificationToUser(*currentUser, userForm.Email)
infos["infos"] = append(infos["infos"], fmt.Sprintf(string(T("email_changed")), userForm.Email))
messages.AddInfof("infos", string(T("email_changed")), userForm.Email)
userForm.Email = userProfile.Email // reset, it will be set when user clicks verification
}
userProfile, _, errorUser = userService.UpdateUser(w, &userForm, currentUser, id)
if errorUser != nil {
err["errors"] = append(err["errors"], errorUser.Error())
messages.ImportFromError("errors", errorUser)
} else {
infos["infos"] = append(infos["infos"], string(T("profile_updated")))
messages.AddInfo("infos", string(T("profile_updated")))
}
}
}
@ -179,8 +181,8 @@ func UserProfileFormHandler(w http.ResponseWriter, r *http.Request) {
CommonTemplateVariables: NewCommonVariables(r),
UserProfile: &userProfile,
UserForm: userForm,
FormErrors: err,
FormInfos: infos,
FormErrors: messages.GetAllErrors(),
FormInfos: messages.GetAllInfos(),
Languages: availableLanguages,
}
errorTmpl := viewProfileEditTemplate.ExecuteTemplate(w, "index.html", upev)

Voir le fichier

@ -4,33 +4,34 @@ import (
"regexp"
"github.com/NyaaPantsu/nyaa/util/log"
msg "github.com/NyaaPantsu/nyaa/util/messages"
)
const EMAIL_REGEX = `(\w[-._\w]*\w@\w[-._\w]*\w\.\w{2,3})`
const USERNAME_REGEX = `(\W)`
func EmailValidation(email string, err map[string][]string) (bool, map[string][]string) {
func EmailValidation(email string, mes *msg.Messages) bool {
exp, errorRegex := regexp.Compile(EMAIL_REGEX)
if regexpCompiled := log.CheckError(errorRegex); regexpCompiled {
if exp.MatchString(email) {
return true, err
return true
}
}
err["email"] = append(err["email"], "Email Address is not valid")
return false, err
mes.AddError("email", "Email Address is not valid")
return false
}
func ValidateUsername(username string, err map[string][]string) (bool, map[string][]string) {
func ValidateUsername(username string, mes *msg.Messages) bool {
exp, errorRegex := regexp.Compile(USERNAME_REGEX)
if regexpCompiled := log.CheckError(errorRegex); regexpCompiled {
if exp.MatchString(username) {
err["username"] = append(err["username"], "Username contains illegal characters")
return false, err
mes.AddError("username", "Username contains illegal characters")
return false
}
} else {
return false, err
return false
}
return true, err
return true
}
func NewErrors() map[string][]string {
@ -73,6 +74,20 @@ type UserForm struct {
Status int `form:"status" default:"0"`
}
// UserSettingsForm is used when updating a user.
type UserSettingsForm struct {
NewTorrent bool `form:"new_torrent" default:"true"`
NewTorrentEmail bool `form:"new_torrent_email" default:"true"`
NewComment bool `form:"new_comment" default:"true"`
NewCommentEmail bool `form:"new_comment_email" default:"false"`
NewResponses bool `form:"new_responses" default:"true"`
NewResponsesEmail bool `form:"new_responses_email" default:"false"`
NewFollower bool `form:"new_follower" default:"true"`
NewFollowerEmail bool `form:"new_follower_email" default:"true"`
Followed bool `form:"followed" default:"false"`
FollowedEmail bool `form:"followed_email" default:"false"`
}
// PasswordForm is used when updating a user password.
type PasswordForm struct {
CurrentPassword string `form:"currentPassword"`

Voir le fichier

@ -3,6 +3,7 @@ package modelHelper
import (
"fmt"
"github.com/NyaaPantsu/nyaa/util/log"
msg "github.com/NyaaPantsu/nyaa/util/messages"
"net/http"
"reflect"
"strconv"
@ -57,7 +58,7 @@ func BindValueForm(form interface{}, r *http.Request) {
}
}
func ValidateForm(form interface{}, errorForm map[string][]string) map[string][]string {
func ValidateForm(form interface{}, mes *msg.Messages) {
formElem := reflect.ValueOf(form).Elem()
for i := 0; i < formElem.NumField(); i++ {
typeField := formElem.Type().Field(i)
@ -69,28 +70,28 @@ func ValidateForm(form interface{}, errorForm map[string][]string) map[string][]
if tag.Get("len_min") != "" && (tag.Get("needed") != "" || formElem.Field(i).Len() > 0) { // Check minimum length
lenMin, _ := strconv.Atoi(tag.Get("len_min"))
if formElem.Field(i).Len() < lenMin {
errorForm[tag.Get("form")] = append(errorForm[tag.Get("form")], fmt.Sprintf("Minimal length of %s required for the input: %s", strconv.Itoa(lenMin), inputName))
mes.AddErrorf(tag.Get("form"), "Minimal length of %s required for the input: %s", strconv.Itoa(lenMin), inputName)
}
}
if tag.Get("len_max") != "" && (tag.Get("needed") != "" || formElem.Field(i).Len() > 0) { // Check maximum length
lenMax, _ := strconv.Atoi(tag.Get("len_max"))
if formElem.Field(i).Len() > lenMax {
errorForm[tag.Get("form")] = append(errorForm[tag.Get("form")], fmt.Sprintf("Maximal length of %s required for the input: %s", strconv.Itoa(lenMax), inputName))
mes.AddErrorf(tag.Get("form"), "Maximal length of %s required for the input: %s", strconv.Itoa(lenMax), inputName)
}
}
if tag.Get("equalInput") != "" && (tag.Get("needed") != "" || formElem.Field(i).Len() > 0) {
otherInput := formElem.FieldByName(tag.Get("equalInput"))
if formElem.Field(i).Interface() != otherInput.Interface() {
errorForm[tag.Get("form")] = append(errorForm[tag.Get("form")], fmt.Sprintf("Must be same %s", inputName))
mes.AddErrorf(tag.Get("form"), "Must be same %s", inputName)
}
}
switch typeField.Type.Name() {
case "string":
if tag.Get("equal") != "" && formElem.Field(i).String() != tag.Get("equal") {
errorForm[tag.Get("form")] = append(errorForm[tag.Get("form")], fmt.Sprintf("Wrong value for the input: %s", inputName))
mes.AddErrorf(tag.Get("form"), "Wrong value for the input: %s", inputName)
}
if tag.Get("needed") != "" && formElem.Field(i).String() == "" {
errorForm[tag.Get("form")] = append(errorForm[tag.Get("form")], fmt.Sprintf("Field needed: %s", inputName))
mes.AddErrorf(tag.Get("form"), "Field needed: %s", inputName)
}
if formElem.Field(i).String() == "" && tag.Get("default") != "" {
formElem.Field(i).SetString(tag.Get("default"))
@ -99,11 +100,11 @@ func ValidateForm(form interface{}, errorForm map[string][]string) map[string][]
if tag.Get("equal") != "" { // Check minimum length
equal, _ := strconv.Atoi(tag.Get("equal"))
if formElem.Field(i).Int() > int64(equal) {
errorForm[tag.Get("form")] = append(errorForm[tag.Get("form")], fmt.Sprintf("Wrong value for the input: %s", inputName))
mes.AddErrorf(tag.Get("form"), "Wrong value for the input: %s", inputName)
}
}
if tag.Get("needed") != "" && formElem.Field(i).Int() == 0 {
errorForm[tag.Get("form")] = append(errorForm[tag.Get("form")], fmt.Sprintf("Field needed: %s", inputName))
mes.AddErrorf(tag.Get("form"), "Field needed: %s", inputName)
}
if formElem.Field(i).Interface == nil && tag.Get("default") != "" {
defaultValue, _ := strconv.Atoi(tag.Get("default"))
@ -113,11 +114,11 @@ func ValidateForm(form interface{}, errorForm map[string][]string) map[string][]
if tag.Get("equal") != "" { // Check minimum length
equal, _ := strconv.Atoi(tag.Get("equal"))
if formElem.Field(i).Float() != float64(equal) {
errorForm[tag.Get("form")] = append(errorForm[tag.Get("form")], fmt.Sprintf("Wrong value for the input: %s", inputName))
mes.AddErrorf(tag.Get("form"), "Wrong value for the input: %s", inputName)
}
}
if tag.Get("needed") != "" && formElem.Field(i).Float() == 0 {
errorForm[tag.Get("form")] = append(errorForm[tag.Get("form")], fmt.Sprintf("Field needed: %s", inputName))
mes.AddErrorf(tag.Get("form"), "Field needed: %s", inputName)
}
if formElem.Field(i).Interface == nil && tag.Get("default") != "" {
defaultValue, _ := strconv.Atoi(tag.Get("default"))
@ -127,10 +128,13 @@ func ValidateForm(form interface{}, errorForm map[string][]string) map[string][]
if tag.Get("equal") != "" { // Check minimum length
equal, _ := strconv.ParseBool(tag.Get("equal"))
if formElem.Field(i).Bool() != equal {
errorForm[tag.Get("form")] = append(errorForm[tag.Get("form")], fmt.Sprintf("Wrong value for the input: %s", inputName))
mes.AddErrorf(tag.Get("form"), "Wrong value for the input: %s", inputName)
}
}
if formElem.Field(i).Interface == nil && tag.Get("default") != "" {
defaultValue, _ := strconv.ParseBool(tag.Get("default"))
formElem.Field(i).SetBool(defaultValue)
}
}
}
return errorForm
}