diff --git a/bot_routes.go b/bot_routes.go index 4e26f376..32c77733 100644 --- a/bot_routes.go +++ b/bot_routes.go @@ -1,13 +1,13 @@ package main import ( + "errors" "log" "net/http" "strconv" "strings" "./common" - "./query_gen/lib" ) // TODO: Make this a static file somehow? Is it possible for us to put this file somewhere else? @@ -23,8 +23,6 @@ Disallow: /report/ return nil } -var xmlInternalError = []byte(` -A problem has occured`) var sitemapPageCap = 40000 // 40k, bump it up to 50k once we gzip this? Does brotli work on sitemaps? func writeXMLHeader(w http.ResponseWriter, r *http.Request) { @@ -110,11 +108,7 @@ func routeSitemapForums(w http.ResponseWriter, r *http.Request) common.RouteErro group, err := common.Groups.Get(common.GuestUser.Group) if err != nil { - log.Print("The guest group doesn't exist for some reason") - // TODO: Add XML error handling to errors.go - w.WriteHeader(500) - w.Write(xmlInternalError) - return common.HandledRouteError() + return common.SilentInternalErrorXML(errors.New("The guest group doesn't exist for some reason"), w, r) } writeXMLHeader(w, r) @@ -145,54 +139,29 @@ func routeSitemapTopics(w http.ResponseWriter, r *http.Request) common.RouteErro `)) } - writeXMLHeader(w, r) group, err := common.Groups.Get(common.GuestUser.Group) if err != nil { - log.Print("The guest group doesn't exist for some reason") - // TODO: Add XML error handling to errors.go - w.WriteHeader(500) - w.Write(xmlInternalError) - return common.HandledRouteError() + return common.SilentInternalErrorXML(errors.New("The guest group doesn't exist for some reason"), w, r) } - var argList []interface{} - var qlist string + var visibleForums []common.Forum for _, fid := range group.CanSee { forum := common.Forums.DirtyGet(fid) if forum.Name != "" && forum.Active { - argList = append(argList, strconv.Itoa(fid)) - qlist += "?," + visibleForums = append(visibleForums, forum.Copy()) } } - if qlist != "" { - qlist = qlist[0 : len(qlist)-1] - } - // TODO: Abstract this - topicCountStmt, err := qgen.Builder.SimpleCount("topics", "parentID IN("+qlist+")", "") + topicCount, err := common.TopicCountInForums(visibleForums) if err != nil { - // TODO: Add XML error handling to errors.go - w.WriteHeader(500) - w.Write(xmlInternalError) - common.LogError(err) - return common.HandledRouteError() - } - defer topicCountStmt.Close() - - var topicCount int - err = topicCountStmt.QueryRow(argList...).Scan(&topicCount) - if err != nil && err != ErrNoRows { - // TODO: Add XML error handling to errors.go - w.WriteHeader(500) - w.Write(xmlInternalError) - common.LogError(err) - return common.HandledRouteError() + return common.InternalErrorXML(err, w, r) } var pageCount = topicCount / sitemapPageCap //log.Print("topicCount", topicCount) //log.Print("pageCount", pageCount) + writeXMLHeader(w, r) w.Write([]byte("\n")) for i := 0; i <= pageCount; i++ { sitemapItem("sitemaps/topics_page_" + strconv.Itoa(i) + ".xml") @@ -215,45 +184,21 @@ func routeSitemapTopic(w http.ResponseWriter, r *http.Request, page int) common. group, err := common.Groups.Get(common.GuestUser.Group) if err != nil { - log.Print("The guest group doesn't exist for some reason") - // TODO: Add XML error handling to errors.go - w.WriteHeader(500) - w.Write(xmlInternalError) - return common.HandledRouteError() + return common.SilentInternalErrorXML(errors.New("The guest group doesn't exist for some reason"), w, r) } - var argList []interface{} - var qlist string + var visibleForums []common.Forum for _, fid := range group.CanSee { forum := common.Forums.DirtyGet(fid) if forum.Name != "" && forum.Active { - argList = append(argList, strconv.Itoa(fid)) - qlist += "?," + visibleForums = append(visibleForums, forum.Copy()) } } - if qlist != "" { - qlist = qlist[0 : len(qlist)-1] - } - // TODO: Abstract this - topicCountStmt, err := qgen.Builder.SimpleCount("topics", "parentID IN("+qlist+")", "") + argList, qlist := common.ForumListToArgQ(visibleForums) + topicCount, err := common.ArgQToTopicCount(argList, qlist) if err != nil { - // TODO: Add XML error handling to errors.go - w.WriteHeader(500) - w.Write(xmlInternalError) - common.LogError(err) - return common.HandledRouteError() - } - defer topicCountStmt.Close() - - var topicCount int - err = topicCountStmt.QueryRow(argList...).Scan(&topicCount) - if err != nil && err != ErrNoRows { - // TODO: Add XML error handling to errors.go - w.WriteHeader(500) - w.Write(xmlInternalError) - common.LogError(err) - return common.HandledRouteError() + return common.InternalErrorXML(err, w, r) } var pageCount = topicCount / sitemapPageCap diff --git a/common/errors.go b/common/errors.go index cc1ad568..79f39ce6 100644 --- a/common/errors.go +++ b/common/errors.go @@ -99,6 +99,26 @@ func InternalErrorJS(err error, w http.ResponseWriter, r *http.Request) RouteErr return HandledRouteError() } +var xmlInternalError = []byte(` +A problem has occured`) + +func InternalErrorXML(err error, w http.ResponseWriter, r *http.Request) RouteError { + w.Header().Set("Content-Type", "application/xml") + w.WriteHeader(500) + w.Write(xmlInternalError) + LogError(err) + return HandledRouteError() +} + +// TODO: Stop killing the instance upon hitting an error with InternalError* and deprecate this +func SilentInternalErrorXML(err error, w http.ResponseWriter, r *http.Request) RouteError { + w.Header().Set("Content-Type", "application/xml") + w.WriteHeader(500) + w.Write(xmlInternalError) + log.Print("InternalError: ", err) + return HandledRouteError() +} + func PreError(errmsg string, w http.ResponseWriter, r *http.Request) RouteError { w.WriteHeader(500) pi := Page{"Error", GuestUser, DefaultHeaderVar(), tList, errmsg} diff --git a/common/forum_store.go b/common/forum_store.go index d9177e8b..fb75e931 100644 --- a/common/forum_store.go +++ b/common/forum_store.go @@ -27,6 +27,7 @@ type ForumStore interface { DirtyGet(id int) *Forum Get(id int) (*Forum, error) BypassGet(id int) (*Forum, error) + BulkGetCopy(ids []int) (forums []Forum, err error) Reload(id int) error // ? - Should we move this to ForumCache? It might require us to do some unnecessary casting though //Update(Forum) error Delete(id int) error @@ -188,6 +189,19 @@ func (mfs *MemoryForumStore) BypassGet(id int) (*Forum, error) { return forum, err } +// TODO: Optimise this +func (mfs *MemoryForumStore) BulkGetCopy(ids []int) (forums []Forum, err error) { + forums = make([]Forum, len(ids)) + for i, id := range ids { + forum, err := mfs.Get(id) + if err != nil { + return nil, err + } + forums[i] = forum.Copy() + } + return forums, nil +} + func (mfs *MemoryForumStore) Reload(id int) error { var forum = &Forum{ID: id} err := mfs.get.QueryRow(id).Scan(&forum.Name, &forum.Desc, &forum.Active, &forum.Preset, &forum.ParentID, &forum.ParentType, &forum.TopicCount, &forum.LastTopicID, &forum.LastReplyerID) diff --git a/common/parser.go b/common/parser.go index 52b86ee9..ff051c16 100644 --- a/common/parser.go +++ b/common/parser.go @@ -165,10 +165,10 @@ func shortcodeToUnicode(msg string) string { } func PreparseMessage(msg string) string { - msg = strings.Replace(msg, "


", "\n", -1) - msg = strings.Replace(msg, "

", "\n", -1) + msg = strings.Replace(msg, "


", "\n\n", -1) + msg = strings.Replace(msg, "

", "\n\n", -1) msg = strings.Replace(msg, "

", "", -1) - msg = strings.Replace(msg, "
", "\n", -1) + msg = strings.Replace(msg, "
", "\n\n", -1) if Sshooks["preparse_preassign"] != nil { msg = RunSshook("preparse_preassign", msg) } diff --git a/common/topic_list.go b/common/topic_list.go new file mode 100644 index 00000000..b6282417 --- /dev/null +++ b/common/topic_list.go @@ -0,0 +1,35 @@ +package common + +import "strconv" +import "../query_gen/lib" + +// Internal. Don't rely on it. +func ForumListToArgQ(forums []Forum) (argList []interface{}, qlist string) { + for _, forum := range forums { + argList = append(argList, strconv.Itoa(forum.ID)) + qlist += "?," + } + if qlist != "" { + qlist = qlist[0 : len(qlist)-1] + } + return argList, qlist +} + +// Internal. Don't rely on it. +func ArgQToTopicCount(argList []interface{}, qlist string) (topicCount int, err error) { + topicCountStmt, err := qgen.Builder.SimpleCount("topics", "parentID IN("+qlist+")", "") + if err != nil { + return 0, err + } + defer topicCountStmt.Close() + + err = topicCountStmt.QueryRow(argList...).Scan(&topicCount) + if err != nil && err != ErrNoRows { + return 0, err + } + return topicCount, err +} + +func TopicCountInForums(forums []Forum) (topicCount int, err error) { + return ArgQToTopicCount(ForumListToArgQ(forums)) +} diff --git a/routes.go b/routes.go index e8b00891..1cfdfb01 100644 --- a/routes.go +++ b/routes.go @@ -135,8 +135,6 @@ func routeTopics(w http.ResponseWriter, r *http.Request, user common.User) commo headerVars.Zone = "topics" headerVars.MetaDesc = headerVars.Settings["meta_desc"].(string) - // TODO: Add a function for the qlist stuff - var qlist string group, err := common.Groups.Get(user.Group) if err != nil { log.Printf("Group #%d doesn't exist despite being used by common.User #%d", user.Group, user.ID) @@ -156,39 +154,28 @@ func routeTopics(w http.ResponseWriter, r *http.Request, user common.User) commo // We need a list of the visible forums for Quick Topic var forumList []common.Forum - var argList []interface{} - for _, fid := range canSee { forum := common.Forums.DirtyGet(fid) if forum.Name != "" && forum.Active { // This bit's for quick topic, as we don't want unbound forums (e.g. ones in plugin_socialgroups) showing up + // ? - Would it be useful, if we could post in social groups from /topics/? if (forum.ParentType == "" || forum.ParentType == "forum") && user.Loggedin { fcopy := forum.Copy() // TODO: Add a hook here for plugin_guilds forumList = append(forumList, fcopy) } - // ? - Should we be showing plugin_guilds posts on /topics/? - // ? - Would it be useful, if we could post in social groups from /topics/? - argList = append(argList, strconv.Itoa(fid)) - qlist += "?," } } + // ? - Should we be showing plugin_guilds posts on /topics/? + argList, qlist := common.ForumListToArgQ(forumList) + // ! Need an inline error not a page level error if qlist == "" { return common.NotFound(w, r) } - qlist = qlist[0 : len(qlist)-1] - // TODO: Abstract this - topicCountStmt, err := qgen.Builder.SimpleCount("topics", "parentID IN("+qlist+")", "") - if err != nil { - return common.InternalError(err, w, r) - } - defer topicCountStmt.Close() - - var topicCount int - err = topicCountStmt.QueryRow(argList...).Scan(&topicCount) + topicCount, err := common.ArgQToTopicCount(argList, qlist) if err != nil { return common.InternalError(err, w, r) } @@ -304,7 +291,6 @@ func routeForum(w http.ResponseWriter, r *http.Request, user common.User, sfid s if ferr != nil { return ferr } - if !user.Perms.ViewTopic { return common.NoPermissions(w, r, user) } diff --git a/themes/cosora/public/main.css b/themes/cosora/public/main.css index b57df627..f4e73676 100644 --- a/themes/cosora/public/main.css +++ b/themes/cosora/public/main.css @@ -580,11 +580,10 @@ select, input, textarea, button { display: inline-block; } .topic_list .rowtopic span { - max-width: 112px; + max-width: 162px; overflow: hidden; color: var(--primary-text-color); } - .topic_list .rowsmall { font-size: 15px; } @@ -596,17 +595,9 @@ select, input, textarea, button { font-size: 15px; } -.topic_list .rowsmall.starter:before { - content: "\f007"; - font: normal normal normal 14px/1 FontAwesome; - margin-right: 5px; - font-size: 15px; -} - .topic_list .lastReplyAt { font-size: 14px; } - .topic_list .topic_status_e { display: none; } @@ -615,7 +606,6 @@ select, input, textarea, button { flex: 1 1 calc(100% - 380px); border-right: none; } - .topic_inner_right { margin-left: 15%; margin-right: auto; @@ -633,12 +623,9 @@ select, input, textarea, button { .topic_inner_right { margin-top: 12px; } - .topic_inner_right span { - /*font-size: 15px;*/ font-size: 16px; } - .topic_inner_right span:after { font-size: 13.5px; } @@ -656,7 +643,6 @@ select, input, textarea, button { content: var(--likes-lang-string); color: var(--lightened-primary-text-color); } - .parent_forum { color: var(--lightened-primary-text-color); } @@ -684,7 +670,7 @@ select, input, textarea, button { margin-top: 12px; margin-left: 8px; margin-bottom: 14px; - width: 240px; + width: 220px; } .topic_right > span { margin-top: 12px; @@ -698,7 +684,7 @@ select, input, textarea, button { background-color: hsl(81, 60%, 95%); } -@element .topic_left .rowtopic and (min-width: 110px) { +@element .topic_left .rowtopic and (min-width: 160px) { $this, $this span, $this + .parent_forum { float: left; } @@ -712,6 +698,18 @@ select, input, textarea, button { } } +@element .topic_list and (min-width: 738px) { + .topic_left .topic_inner_left { + width: calc(240px + 1%); + } +} + +@element .topic_list and (min-width: 875px) { + .topic_left .topic_inner_left { + width: calc(240px + 10%); + } +} + .forum_list, .post_container { border: none; } @@ -778,6 +776,9 @@ select, input, textarea, button { .userinfo .tag_block { color: var(--extra-lightened-primary-text-color); } +.post_item .user_content { + margin-bottom: 10px; +} .button_container { margin-top: auto; display: flex; diff --git a/themes/cosora/public/panel.css b/themes/cosora/public/panel.css index 8ad5abc3..f5248a38 100644 --- a/themes/cosora/public/panel.css +++ b/themes/cosora/public/panel.css @@ -77,10 +77,41 @@ .formlist .formitem { padding: 8px; } -#forum_quick_perms .panel_floater, .panel_theme_mobile, .panel_theme_tag { display: none; } #panel_plugins .rowitem { display: block; +} + +#forum_quick_perms .formitem { + display: flex; +} +#forum_quick_perms .formitem .edit_fields { + margin-left: 3px; + margin-top: 1px; +} +.perm_preset_no_access:before { + content: "No Access"; + color: hsl(0,100%,20%); +} +.perm_preset_read_only:before, .perm_preset_can_post:before { + color: hsl(120,100%,20%); +} +.perm_preset_read_only:before { + content: "Read Only"; +} +.perm_preset_can_post:before { + content: "Can Post"; +} +.perm_preset_can_moderate:before { + content: "Can Moderate"; + color: hsl(240,100%,20%); +} +.perm_preset_custom:before { + content: "Custom"; + color: hsl(0,0%,20%); +} +.perm_preset_default:before { + content: "Default"; } \ No newline at end of file