From 3ef41b1cdd7303fd554a973f9b04d668600e1698 Mon Sep 17 00:00:00 2001 From: Eduard Urbach Date: Sat, 31 Aug 2019 16:52:42 +0900 Subject: [PATCH] Introduced length limits --- arn/limits/limits.go | 6 +++ arn/search/AMVs.go | 4 +- arn/search/All.go | 16 ++++++- arn/search/Anime.go | 10 ++--- arn/search/Companies.go | 2 +- arn/search/SoundTracks.go | 4 +- arn/search/Users.go | 2 +- mixins/FuzzySearch.pixy | 2 +- mixins/Input.pixy | 8 ++-- mixins/NewPostArea.pixy | 2 +- mixins/Postable.pixy | 2 +- pages/animelistitem/animelistitem.pixy | 2 +- pages/newthread/newthread.pixy | 2 +- pages/search/multisearch/multisearch.pixy | 2 +- pages/search/search.go | 51 +++++++++++++++++------ pages/settings/accounts.pixy | 14 +++---- pages/settings/info.pixy | 4 +- pages/settings/personal.pixy | 29 +------------ pages/welcome/welcome.pixy | 4 +- scripts/Actions/Search.ts | 7 +--- utils/editform/editform.go | 17 +++++++- 21 files changed, 110 insertions(+), 80 deletions(-) create mode 100644 arn/limits/limits.go diff --git a/arn/limits/limits.go b/arn/limits/limits.go new file mode 100644 index 00000000..e6049392 --- /dev/null +++ b/arn/limits/limits.go @@ -0,0 +1,6 @@ +package limits + +const ( + DefaultTextMaxLength = 100 + DefaultTextAreaMaxLength = 20000 +) diff --git a/arn/search/AMVs.go b/arn/search/AMVs.go index 9dc51b29..78dc0b9e 100644 --- a/arn/search/AMVs.go +++ b/arn/search/AMVs.go @@ -25,7 +25,7 @@ func AMVs(originalTerm string, maxLength int) []*arn.AMV { text := strings.ToLower(amv.Title.Canonical) similarity := stringutils.AdvancedStringSimilarity(term, text) - if similarity >= MinimumStringSimilarity { + if similarity >= MinStringSimilarity { results = append(results, &Result{ obj: amv, similarity: similarity, @@ -36,7 +36,7 @@ func AMVs(originalTerm string, maxLength int) []*arn.AMV { text = strings.ToLower(amv.Title.Native) similarity = stringutils.AdvancedStringSimilarity(term, text) - if similarity >= MinimumStringSimilarity { + if similarity >= MinStringSimilarity { results = append(results, &Result{ obj: amv, similarity: similarity, diff --git a/arn/search/All.go b/arn/search/All.go index 3e85a5f5..930350b4 100644 --- a/arn/search/All.go +++ b/arn/search/All.go @@ -1,16 +1,24 @@ package search import ( + "fmt" + "github.com/aerogo/flow" "github.com/animenotifier/notify.moe/arn" ) -// MinimumStringSimilarity is the minimum JaroWinkler distance we accept for search results. -const MinimumStringSimilarity = 0.89 +// MinStringSimilarity is the minimum JaroWinkler distance we accept for search results. +const MinStringSimilarity = 0.89 + +// MaxSearchTermLength defines how long the search term can be. +const MaxSearchTermLength = 100 // popularityDamping reduces the factor of popularity in search results. const popularityDamping = 0.0009 +// ErrTermTooLong is used when the search term is too long +var ErrTermTooLong = fmt.Errorf("Search term is too long (maximum %d characters)", MaxSearchTermLength) + // Result ... type Result struct { obj interface{} @@ -23,6 +31,10 @@ func All(term string, maxUsers, maxAnime, maxPosts, maxThreads, maxTracks, maxCh return nil, nil, nil, nil, nil, nil, nil, nil } + if len(term) > MaxSearchTermLength { + return nil, nil, nil, nil, nil, nil, nil, nil + } + var ( userResults []*arn.User animeResults []*arn.Anime diff --git a/arn/search/Anime.go b/arn/search/Anime.go index c0e73f5a..3c36fd00 100644 --- a/arn/search/Anime.go +++ b/arn/search/Anime.go @@ -42,7 +42,7 @@ func Anime(originalTerm string, maxLength int) []*arn.Anime { // Canonical title similarity := check(anime.Title.Canonical) - if similarity >= MinimumStringSimilarity { + if similarity >= MinStringSimilarity { add(anime, similarity) continue } @@ -50,7 +50,7 @@ func Anime(originalTerm string, maxLength int) []*arn.Anime { // English similarity = check(anime.Title.English) - if similarity >= MinimumStringSimilarity { + if similarity >= MinStringSimilarity { add(anime, similarity) continue } @@ -58,7 +58,7 @@ func Anime(originalTerm string, maxLength int) []*arn.Anime { // Romaji similarity = check(anime.Title.Romaji) - if similarity >= MinimumStringSimilarity { + if similarity >= MinStringSimilarity { add(anime, similarity) continue } @@ -67,7 +67,7 @@ func Anime(originalTerm string, maxLength int) []*arn.Anime { for _, synonym := range anime.Title.Synonyms { similarity := check(synonym) - if similarity >= MinimumStringSimilarity { + if similarity >= MinStringSimilarity { add(anime, similarity) goto nextAnime } @@ -76,7 +76,7 @@ func Anime(originalTerm string, maxLength int) []*arn.Anime { // Japanese similarity = check(anime.Title.Japanese) - if similarity >= MinimumStringSimilarity { + if similarity >= MinStringSimilarity { add(anime, similarity) continue } diff --git a/arn/search/Companies.go b/arn/search/Companies.go index 6c6fdd3c..7abb0c08 100644 --- a/arn/search/Companies.go +++ b/arn/search/Companies.go @@ -25,7 +25,7 @@ func Companies(originalTerm string, maxLength int) []*arn.Company { text := strings.ToLower(stringutils.RemoveSpecialCharacters(company.Name.English)) similarity := stringutils.AdvancedStringSimilarity(term, text) - if similarity >= MinimumStringSimilarity { + if similarity >= MinStringSimilarity { results = append(results, &Result{ obj: company, similarity: similarity, diff --git a/arn/search/SoundTracks.go b/arn/search/SoundTracks.go index d2c212dc..9867a885 100644 --- a/arn/search/SoundTracks.go +++ b/arn/search/SoundTracks.go @@ -25,7 +25,7 @@ func SoundTracks(originalTerm string, maxLength int) []*arn.SoundTrack { text := strings.ToLower(track.Title.Canonical) similarity := stringutils.AdvancedStringSimilarity(term, text) - if similarity >= MinimumStringSimilarity { + if similarity >= MinStringSimilarity { results = append(results, &Result{ obj: track, similarity: similarity, @@ -36,7 +36,7 @@ func SoundTracks(originalTerm string, maxLength int) []*arn.SoundTrack { text = strings.ToLower(track.Title.Native) similarity = stringutils.AdvancedStringSimilarity(term, text) - if similarity >= MinimumStringSimilarity { + if similarity >= MinStringSimilarity { results = append(results, &Result{ obj: track, similarity: similarity, diff --git a/arn/search/Users.go b/arn/search/Users.go index 50aaf768..2bd8ee20 100644 --- a/arn/search/Users.go +++ b/arn/search/Users.go @@ -23,7 +23,7 @@ func Users(originalTerm string, maxLength int) []*arn.User { // Similarity check similarity := stringutils.AdvancedStringSimilarity(term, text) - if similarity < MinimumStringSimilarity { + if similarity < MinStringSimilarity { continue } diff --git a/mixins/FuzzySearch.pixy b/mixins/FuzzySearch.pixy index 3730b7bb..58b41250 100644 --- a/mixins/FuzzySearch.pixy +++ b/mixins/FuzzySearch.pixy @@ -1,2 +1,2 @@ component FuzzySearch(value string) - input#search.action(data-action="search", data-trigger="input", type="search", autocomplete="off", autocorrect="off", autocapitalize="none", spellcheck="false", placeholder="Search...", title="Shortcut: F", value=value) \ No newline at end of file + input#search.action(data-action="search", data-trigger="input", type="search", autocomplete="off", autocorrect="off", autocapitalize="none", spellcheck="false", placeholder="Search...", title="Shortcut: F", maxlength="100", value=value) \ No newline at end of file diff --git a/mixins/Input.pixy b/mixins/Input.pixy index 10d63e39..85d2c7f4 100644 --- a/mixins/Input.pixy +++ b/mixins/Input.pixy @@ -1,7 +1,7 @@ -component InputText(id string, value string, label string, placeholder string) +component InputText(id string, value string, label string, placeholder string, maxLength int) .widget-section label(for=id)= label + ":" - input.widget-ui-element.action(id=id, data-field=id, type="text", value=value, placeholder=placeholder, title=placeholder, data-action="save", data-trigger="change") + input.widget-ui-element.action(id=id, data-field=id, type="text", value=value, placeholder=placeholder, title=placeholder, data-action="save", data-trigger="change", maxlength=maxLength) component InputBool(id string, value bool, label string, title string) .widget-section @@ -16,10 +16,10 @@ component InputBool(id string, value bool, label string, title string) span OFF //- input.widget-ui-element.action(id=id, data-field=id, type="checkbox", value=value, checked=value, data-action="save", data-trigger="change") -component InputTextArea(id string, value string, label string, placeholder string) +component InputTextArea(id string, value string, label string, placeholder string, maxLength int) .widget-section label(for=id)= label + ":" - textarea.widget-ui-element.action(id=id, data-field=id, placeholder=placeholder, title=placeholder, data-action="save", data-trigger="change")= value + textarea.widget-ui-element.action(id=id, data-field=id, placeholder=placeholder, title=placeholder, data-action="save", data-trigger="change", maxlength=maxLength)= value component InputNumber(id string, value float64, label string, placeholder string, min string, max string, step string) .widget-section diff --git a/mixins/NewPostArea.pixy b/mixins/NewPostArea.pixy index fcfa1a38..1595d74a 100644 --- a/mixins/NewPostArea.pixy +++ b/mixins/NewPostArea.pixy @@ -4,7 +4,7 @@ component NewPostArea(parent arn.PostParent, user *arn.User, placeholder string) .post-author Avatar(user) - textarea#new-post-text.post-content(placeholder=placeholder + "...", aria-label=placeholder) + textarea#new-post-text.post-content(placeholder=placeholder + "...", aria-label=placeholder, maxlength=limits.DefaultTextAreaMaxLength) if !arn.IsLocked(parent) NewPostActions(parent, false) diff --git a/mixins/Postable.pixy b/mixins/Postable.pixy index 508d3430..7038f57e 100644 --- a/mixins/Postable.pixy +++ b/mixins/Postable.pixy @@ -40,7 +40,7 @@ component Postable(post arn.Postable, user *arn.User, includeReplies bool, showP if post.TypeName() == "Thread" input.post-title-input.hidden(id="title-" + post.GetID(), value=post.TitleByUser(user), type="text", placeholder="Thread title") - textarea.post-text-input.hidden(id="source-" + post.GetID())= post.GetText() + textarea.post-text-input.hidden(id="source-" + post.GetID(), maxlength=limits.DefaultTextAreaMaxLength)= post.GetText() .buttons.hidden(id="edit-toolbar-" + post.GetID()) a.button.post-save.action(data-action="savePost", data-trigger="click", data-id=post.GetID()) diff --git a/pages/animelistitem/animelistitem.pixy b/pages/animelistitem/animelistitem.pixy index 8687a264..f18c0735 100644 --- a/pages/animelistitem/animelistitem.pixy +++ b/pages/animelistitem/animelistitem.pixy @@ -26,7 +26,7 @@ component AnimeListItem(viewUser *arn.User, item *arn.AnimeListItem, anime *arn. InputBool("Private", item.Private, "Private", "Hidden entry") .mountable - InputTextArea("Notes", item.Notes, "Notes", "Your notes") + InputTextArea("Notes", item.Notes, "Notes", "Your notes", 2000) .buttons.mountable a.button.mountable(href="/+" + viewUser.Nick + "/animelist/" + item.Status) diff --git a/pages/newthread/newthread.pixy b/pages/newthread/newthread.pixy index cd28f085..ae5d39fe 100644 --- a/pages/newthread/newthread.pixy +++ b/pages/newthread/newthread.pixy @@ -5,7 +5,7 @@ component NewThread(user *arn.User) .widget input#title.widget-ui-element(type="text", placeholder="Title") - textarea#text.widget-ui-element(placeholder="Content") + textarea#text.widget-ui-element(placeholder="Content", maxlength=limits.DefaultTextAreaMaxLength) select#tag.widget-ui-element(value="general") option(value="general") General diff --git a/pages/search/multisearch/multisearch.pixy b/pages/search/multisearch/multisearch.pixy index 39f17c82..e2098a6c 100644 --- a/pages/search/multisearch/multisearch.pixy +++ b/pages/search/multisearch/multisearch.pixy @@ -1,3 +1,3 @@ component MultiSearch - textarea.action(data-action="multiSearchAnime", data-trigger="change", placeholder="Paste multiple anime titles here, one per line") + textarea.action(data-action="multiSearchAnime", data-trigger="change", placeholder="Paste multiple anime titles here, one per line", maxlength=limits.DefaultTextAreaMaxLength) #multi-search-anime \ No newline at end of file diff --git a/pages/search/search.go b/pages/search/search.go index c0b55da9..b318dbbd 100644 --- a/pages/search/search.go +++ b/pages/search/search.go @@ -1,7 +1,7 @@ package search import ( - "strings" + "net/http" "github.com/animenotifier/notify.moe/utils" @@ -24,9 +24,12 @@ const ( // Get search page. func Get(ctx aero.Context) error { term := ctx.Get("term") - term = strings.TrimPrefix(term, "/") user := utils.GetUser(ctx) + if len(term) > search.MaxSearchTermLength { + ctx.SetStatus(http.StatusRequestEntityTooLarge) + } + users, animes, posts, threads, tracks, characters, amvs, companies := search.All( term, maxUsers, @@ -50,9 +53,12 @@ func GetEmptySearch(ctx aero.Context) error { // Anime search. func Anime(ctx aero.Context) error { term := ctx.Get("term") - term = strings.TrimPrefix(term, "/") user := utils.GetUser(ctx) + if len(term) > search.MaxSearchTermLength { + ctx.SetStatus(http.StatusRequestEntityTooLarge) + } + animes := search.Anime(term, maxAnime) return ctx.HTML(components.AnimeSearchResults(animes, user)) } @@ -60,9 +66,12 @@ func Anime(ctx aero.Context) error { // Characters search. func Characters(ctx aero.Context) error { term := ctx.Get("term") - term = strings.TrimPrefix(term, "/") user := utils.GetUser(ctx) + if len(term) > search.MaxSearchTermLength { + ctx.SetStatus(http.StatusRequestEntityTooLarge) + } + characters := search.Characters(term, maxCharacters) return ctx.HTML(components.CharacterSearchResults(characters, user)) } @@ -70,29 +79,38 @@ func Characters(ctx aero.Context) error { // Posts search. func Posts(ctx aero.Context) error { term := ctx.Get("term") - term = strings.TrimPrefix(term, "/") user := utils.GetUser(ctx) - posts := search.Posts(term, maxPosts) + if len(term) > search.MaxSearchTermLength { + ctx.SetStatus(http.StatusRequestEntityTooLarge) + } + + posts := search.Posts(term, maxPosts) return ctx.HTML(components.PostsSearchResults(posts, user)) } // Threads search. func Threads(ctx aero.Context) error { term := ctx.Get("term") - term = strings.TrimPrefix(term, "/") user := utils.GetUser(ctx) - threads := search.Threads(term, maxThreads) + if len(term) > search.MaxSearchTermLength { + ctx.SetStatus(http.StatusRequestEntityTooLarge) + } + + threads := search.Threads(term, maxThreads) return ctx.HTML(components.ThreadsSearchResults(threads, user)) } // SoundTracks search. func SoundTracks(ctx aero.Context) error { term := ctx.Get("term") - term = strings.TrimPrefix(term, "/") user := utils.GetUser(ctx) + if len(term) > search.MaxSearchTermLength { + ctx.SetStatus(http.StatusRequestEntityTooLarge) + } + tracks := search.SoundTracks(term, maxSoundTracks) return ctx.HTML(components.SoundTrackSearchResults(tracks, user)) } @@ -100,9 +118,12 @@ func SoundTracks(ctx aero.Context) error { // AMVs search. func AMVs(ctx aero.Context) error { term := ctx.Get("term") - term = strings.TrimPrefix(term, "/") user := utils.GetUser(ctx) + if len(term) > search.MaxSearchTermLength { + ctx.SetStatus(http.StatusRequestEntityTooLarge) + } + amvs := search.AMVs(term, maxAMVs) return ctx.HTML(components.AMVSearchResults(amvs, user)) } @@ -110,7 +131,10 @@ func AMVs(ctx aero.Context) error { // Users search. func Users(ctx aero.Context) error { term := ctx.Get("term") - term = strings.TrimPrefix(term, "/") + + if len(term) > search.MaxSearchTermLength { + ctx.SetStatus(http.StatusRequestEntityTooLarge) + } users := search.Users(term, maxUsers) return ctx.HTML(components.UserSearchResults(users)) @@ -119,7 +143,10 @@ func Users(ctx aero.Context) error { // Companies search. func Companies(ctx aero.Context) error { term := ctx.Get("term") - term = strings.TrimPrefix(term, "/") + + if len(term) > search.MaxSearchTermLength { + ctx.SetStatus(http.StatusRequestEntityTooLarge) + } companies := search.Companies(term, maxCompanies) return ctx.HTML(components.CompanySearchResults(companies)) diff --git a/pages/settings/accounts.pixy b/pages/settings/accounts.pixy index d327d9b9..88f0734f 100644 --- a/pages/settings/accounts.pixy +++ b/pages/settings/accounts.pixy @@ -9,20 +9,20 @@ component SettingsAccounts(user *arn.User) Icon("cubes") span Accounts - InputText("Accounts.AniList.Nick", user.Accounts.AniList.Nick, "AniList", "Your username on anilist.co") - InputText("Accounts.Kitsu.Nick", user.Accounts.Kitsu.Nick, "Kitsu", "Your username on kitsu.io") - InputText("Accounts.MyAnimeList.Nick", user.Accounts.MyAnimeList.Nick, "MyAnimeList", "Your username on myanimelist.net") - InputText("Accounts.Discord.Nick", user.Accounts.Discord.Nick, "Discord", "Your username on Discord") + InputText("Accounts.AniList.Nick", user.Accounts.AniList.Nick, "AniList", "Your username on anilist.co", 30) + InputText("Accounts.Kitsu.Nick", user.Accounts.Kitsu.Nick, "Kitsu", "Your username on kitsu.io", 30) + InputText("Accounts.MyAnimeList.Nick", user.Accounts.MyAnimeList.Nick, "MyAnimeList", "Your username on myanimelist.net", 30) + InputText("Accounts.Discord.Nick", user.Accounts.Discord.Nick, "Discord", "Your username on Discord", 30) .widget.mountable(data-api="/api/user/" + user.ID) h3.widget-title Icon("gamepad") span Games - InputText("Accounts.FinalFantasyXIV.Nick", user.Accounts.FinalFantasyXIV.Nick, "Final Fantasy XIV", "Your character name on FFXIV") + InputText("Accounts.FinalFantasyXIV.Nick", user.Accounts.FinalFantasyXIV.Nick, "Final Fantasy XIV", "Your character name on FFXIV", 30) InputSelection("Accounts.FinalFantasyXIV.Server", user.Accounts.FinalFantasyXIV.Server, "Final Fantasy XIV - World", "Your server/world on FFXIV", arn.DataLists["ffxiv-servers"]) - InputText("Accounts.Osu.Nick", user.Accounts.Osu.Nick, "Osu", "Your username on osu.ppy.sh") - InputText("Accounts.Overwatch.BattleTag", user.Accounts.Overwatch.BattleTag, "Overwatch", "Your battletag on Overwatch") + InputText("Accounts.Osu.Nick", user.Accounts.Osu.Nick, "Osu", "Your username on osu.ppy.sh", 30) + InputText("Accounts.Overwatch.BattleTag", user.Accounts.Overwatch.BattleTag, "Overwatch", "Your battletag on Overwatch", 30) .widget.mountable h3.widget-title diff --git a/pages/settings/info.pixy b/pages/settings/info.pixy index c6210c98..370212be 100644 --- a/pages/settings/info.pixy +++ b/pages/settings/info.pixy @@ -10,8 +10,8 @@ component SettingsInfo(user *arn.User) span Info InputSelection("Gender", user.Gender, "Gender", "Your gender", arn.DataLists["genders"]) - InputText("BirthDay", user.BirthDay, "Birthday", "YYYY-MM-DD") - InputText("Website", user.Website, "Website", "Your homepage") + InputText("BirthDay", user.BirthDay, "Birthday", "YYYY-MM-DD", len("YYYY-MM-DD")) + InputText("Website", user.Website, "Website", "Your homepage", 100) .widget.mountable(data-api="/api/settings/" + user.ID) h3.widget-title diff --git a/pages/settings/personal.pixy b/pages/settings/personal.pixy index 53eee477..8b7c17dc 100644 --- a/pages/settings/personal.pixy +++ b/pages/settings/personal.pixy @@ -9,38 +9,13 @@ component SettingsPersonal(user *arn.User) Icon("user") span Personal - InputText("Nick", user.Nick, "Username", "Your username on notify.moe") - InputTextArea("Introduction", user.Introduction, "Introduction", "Tell us a little bit about yourself") + InputText("Nick", user.Nick, "Username", "Your username on notify.moe", 25) + InputTextArea("Introduction", user.Introduction, "Introduction", "Tell us a little bit about yourself", 2000) .widget.mountable(data-api="/api/settings/" + user.ID) h3.widget-title Icon("camera") span Avatar - - //- .widget-section - //- label(for="Avatar.Source") Source: - //- select.widget-ui-element.action(id="Avatar.Source", data-field="Avatar.Source", value=user.Settings().Avatar.Source, data-action="save", data-trigger="change") - //- option(value="") Automatic - //- option(value="Gravatar") Gravatar - //- option(value="URL") Link - //- option(value="FileSystem") Upload - - //- //- URL input - //- if user.Settings().Avatar.Source == "URL" - //- InputText("Avatar.SourceURL", user.Settings().Avatar.SourceURL, "Link", "Post the link to the image here") - - //- //- Gravatar preview image - //- if user.Settings().Avatar.Source == "Gravatar" || (user.Settings().Avatar.Source == "" && user.Avatar.Source == "Gravatar") - //- .profile-image-container.avatar-preview - //- img.profile-image.mountable(src=user.Gravatar(), alt="Gravatar (" + user.Email + ")", title="Gravatar (" + user.Email + ")") - - //- //- URL preview image - //- if user.Settings().Avatar.Source == "URL" && user.Settings().Avatar.SourceURL != "" - //- .profile-image-container.avatar-preview - //- img.profile-image.mountable(src=strings.Replace(user.Settings().Avatar.SourceURL, "http://", "https://", 1), alt="Avatar preview") - - //- //- File upload - //- if user.Settings().Avatar.Source == "FileSystem" AvatarInput(user) diff --git a/pages/welcome/welcome.pixy b/pages/welcome/welcome.pixy index c87e00a5..5d463833 100644 --- a/pages/welcome/welcome.pixy +++ b/pages/welcome/welcome.pixy @@ -10,7 +10,7 @@ component Welcome(user *arn.User) .mountable(data-api="/api/user/" + user.ID) //- [^\\W\\s\\d]{1,24}[A-Za-z]{1} - InputText("Nick", user.CleanNick(), "Nick", "Your username on notify.moe") + InputText("Nick", user.CleanNick(), "Nick", "Your username on notify.moe", 25) .footer.mountable p Only letters and underscore. @@ -26,7 +26,7 @@ component Welcome(user *arn.User) p.welcome-text.mountable Write a little introduction for your profile. .mountable(data-api="/api/user/" + user.ID) - InputTextArea("Introduction", user.Introduction, "Introduction", "Tell us a little bit about yourself") + InputTextArea("Introduction", user.Introduction, "Introduction", "Tell us a little bit about yourself", 2000) .footer.mountable p Markdown allowed. diff --git a/scripts/Actions/Search.ts b/scripts/Actions/Search.ts index 00adc3f3..bc54f4ac 100644 --- a/scripts/Actions/Search.ts +++ b/scripts/Actions/Search.ts @@ -34,9 +34,6 @@ const fetchOptions: RequestInit = { credentials: "same-origin" } -// Error message -const searchErrorMessage = "Looks like the website is offline, please retry later." - // Speech recognition let recognition: SpeechRecognition @@ -122,7 +119,7 @@ export async function search(arn: AnimeNotifier, search: HTMLInputElement, evt?: // Start searching anime fetch("/_/anime-search/" + term, fetchOptions) .then(showResponseInElement(arn, url, "anime", results["anime"])) - .catch(_ => arn.statusMessage.showError(searchErrorMessage)) + .catch(err => arn.statusMessage.showError(err)) requestIdleCallback(() => { // Check that the term hasn't changed in the meantime @@ -138,7 +135,7 @@ export async function search(arn: AnimeNotifier, search: HTMLInputElement, evt?: fetch(`/_/${key}-search/` + term, fetchOptions) .then(showResponseInElement(arn, url, key, results[key])) - .catch(_ => arn.statusMessage.showError(searchErrorMessage)) + .catch(err => arn.statusMessage.showError(err)) } }) } catch(err) { diff --git a/utils/editform/editform.go b/utils/editform/editform.go index db93e3a0..f26eaf26 100644 --- a/utils/editform/editform.go +++ b/utils/editform/editform.go @@ -9,6 +9,7 @@ import ( "github.com/aerogo/api" "github.com/animenotifier/notify.moe/arn" + "github.com/animenotifier/notify.moe/arn/limits" "github.com/animenotifier/notify.moe/components" "github.com/animenotifier/notify.moe/utils" ) @@ -214,7 +215,13 @@ func renderStringField(b io.StringWriter, v *reflect.Value, field reflect.Struct b.WriteString(components.InputSelection(idPrefix+field.Name, fieldValue.String(), field.Name, field.Tag.Get("tooltip"), values)) case field.Tag.Get("type") == "textarea": - b.WriteString(components.InputTextArea(idPrefix+field.Name, fieldValue.String(), field.Name, field.Tag.Get("tooltip"))) + maxLength, err := strconv.Atoi(field.Tag.Get("maxLength")) + + if err != nil { + maxLength = limits.DefaultTextAreaMaxLength + } + + b.WriteString(components.InputTextArea(idPrefix+field.Name, fieldValue.String(), field.Name, field.Tag.Get("tooltip"), maxLength)) case field.Tag.Get("type") == "upload": endpoint := field.Tag.Get("endpoint") @@ -224,7 +231,13 @@ func renderStringField(b io.StringWriter, v *reflect.Value, field reflect.Struct b.WriteString(components.InputFileUpload(idPrefix+field.Name, field.Name, field.Tag.Get("filetype"), endpoint)) default: - b.WriteString(components.InputText(idPrefix+field.Name, fieldValue.String(), field.Name, field.Tag.Get("tooltip"))) + maxLength, err := strconv.Atoi(field.Tag.Get("maxLength")) + + if err != nil { + maxLength = limits.DefaultTextMaxLength + } + + b.WriteString(components.InputText(idPrefix+field.Name, fieldValue.String(), field.Name, field.Tag.Get("tooltip"), maxLength)) } if showPreview {