package templates import ( "net/http" "path" "strconv" "github.com/NyaaPantsu/nyaa/config" "github.com/NyaaPantsu/nyaa/models" "github.com/NyaaPantsu/nyaa/utils/filelist" msg "github.com/NyaaPantsu/nyaa/utils/messages" "github.com/NyaaPantsu/nyaa/utils/publicSettings" "github.com/NyaaPantsu/nyaa/utils/search" "github.com/gin-gonic/gin" "github.com/justinas/nosurf" "fmt" "github.com/CloudyKit/jet" "github.com/NyaaPantsu/nyaa/utils/cookies" "github.com/NyaaPantsu/nyaa/utils/validator/user" ) // TemplateDir : Variable to the template directory const TemplateDir = "./templates" // FIXME: Need to be a constant! // ModeratorDir : Variable to the admin template sub directory const ModeratorDir = "admin" // SiteDir : Variable pointing to the site page templates const SiteDir = "site" // ErrorsDir : Variable pointing to the errors page templates const ErrorsDir = "errors" // View : Jet Template Renderer var View = jet.NewHTMLSet("./templates") func init() { if config.Get().Environment == "DEVELOPMENT" { View.SetDevelopmentMode(true) fmt.Println("Template Live Update enabled") } } // Commonvariables return a jet.VarMap variable containing the necessary variables to run index layouts func Commonvariables(c *gin.Context) jet.VarMap { token := nosurf.Token(c.Request) messages := msg.GetMessages(c) user, _, _ := cookies.CurrentUser(c) variables := templateFunctions(make(jet.VarMap)) variables.Set("Navigation", NewNavigation()) variables.Set("Search", NewSearchForm(c)) variables.Set("T", publicSettings.GetTfuncFromRequest(c)) variables.Set("Theme", publicSettings.GetThemeFromRequest(c)) variables.Set("DarkTheme", publicSettings.GetDarkThemeFromRequest(c)) variables.Set("AltColors", publicSettings.GetAltColorsFromRequest(c)) variables.Set("OldNav", publicSettings.GetOldNavFromRequest(c)) variables.Set("Mascot", publicSettings.GetMascotFromRequest(c)) variables.Set("MascotURL", publicSettings.GetMascotURLFromRequest(c)) variables.Set("User", user) variables.Set("URL", c.Request.URL) variables.Set("CsrfToken", token) variables.Set("EUCookieLaw", publicSettings.GetEUCookieFromRequest(c)) variables.Set("Config", config.Get()) variables.Set("Infos", messages.GetAllInfos()) variables.Set("Errors", messages.GetAllErrors()) return variables } // NewPanelSearchForm : Helper that creates a search form without items/page field // these need to be used when the templateVariables don't include `navigation` func NewPanelSearchForm(c *gin.Context) SearchForm { form := NewSearchForm(c) form.ShowItemsPerPage = false return form } // NewPanelCommonvariables return a jet.VarMap variable containing the necessary variables to run index admin layouts func NewPanelCommonvariables(c *gin.Context) jet.VarMap { common := Commonvariables(c) common.Set("Search", NewPanelSearchForm(c)) return common } // Render is a function rendering a template func Render(c *gin.Context, templateName string, variables jet.VarMap) { t, err := View.GetTemplate(templateName) if err != nil { c.AbortWithError(http.StatusInternalServerError, err) return } if err = t.Execute(c.Writer, variables, nil); err != nil { c.AbortWithError(http.StatusInternalServerError, err) return } } // HttpError render an error template func HttpError(c *gin.Context, errorCode int) { switch errorCode { case http.StatusNotFound: Static(c, path.Join(ErrorsDir, "404.jet.html")) c.AbortWithStatus(errorCode) return case http.StatusBadRequest: Static(c, path.Join(ErrorsDir, "400.jet.html")) c.AbortWithStatus(errorCode) return case http.StatusInternalServerError: Static(c, path.Join(ErrorsDir, "500.jet.html")) c.AbortWithStatus(errorCode) return } } // Static render static templates func Static(c *gin.Context, templateName string) { var variables jet.VarMap if isAdminTemplate(templateName) { variables = NewPanelCommonvariables(c) } else { variables = Commonvariables(c) } Render(c, templateName, variables) } // ModelList render list models templates func ModelList(c *gin.Context, templateName string, models interface{}, nav Navigation, search SearchForm) { var variables jet.VarMap if isAdminTemplate(templateName) { variables = NewPanelCommonvariables(c) } else { variables = Commonvariables(c) } variables.Set("Models", models) variables.Set("Navigation", nav) variables.Set("Search", search) Render(c, templateName, variables) } // Form render a template form func Form(c *gin.Context, templateName string, form interface{}) { var variables jet.VarMap if isAdminTemplate(templateName) { variables = NewPanelCommonvariables(c) } else { variables = Commonvariables(c) } variables.Set("Form", form) Render(c, templateName, variables) } // Torrent render a torrent view template func Torrent(c *gin.Context, torrent models.TorrentJSON, rootFolder *filelist.FileListFolder, captchaID string) { variables := Commonvariables(c) variables.Set("Torrent", torrent) variables.Set("RootFolder", rootFolder) variables.Set("CaptchaID", captchaID) Render(c, path.Join(SiteDir, "torrents", "view.jet.html"), variables) } // userProfilBase render the base for user profile func userProfileBase(c *gin.Context, templateName string, userProfile *models.User, variables jet.VarMap) { currentUser, _, _ := cookies.CurrentUser(c) query := c.Request.URL.Query() query.Set("userID", strconv.Itoa(int(userProfile.ID))) query.Set("limit", "15") c.Request.URL.RawQuery = query.Encode() nbTorrents := 0 if userProfile.ID > 0 && currentUser.CurrentOrJanitor(userProfile.ID) { _, userProfile.Torrents, nbTorrents, _ = search.ByQuery(c, 1, true, false, false, true) } else { _, userProfile.Torrents, nbTorrents, _ = search.ByQuery(c, 1, true, false, true, false) } var uploadedSize int64 for _, torrent := range userProfile.Torrents { uploadedSize += torrent.Filesize } variables.Set("UserProfile", userProfile) variables.Set("NbTorrents", []int64{int64(nbTorrents), uploadedSize}) Render(c, path.Join(SiteDir, "user", templateName), variables) } // UserProfileEdit render a form to edit a profile func UserProfileEdit(c *gin.Context, userProfile *models.User, userForm userValidator.UserForm, languages publicSettings.Languages) { variables := Commonvariables(c) variables.Set("UserForm", userForm) variables.Set("Languages", languages) userProfileBase(c, "edit.jet.html", userProfile, variables) } // UserProfile render a user profile func UserProfile(c *gin.Context, userProfile *models.User) { userProfileBase(c, "torrents.jet.html", userProfile, Commonvariables(c)) } // UserProfileNotifications render a user profile notifications func UserProfileNotifications(c *gin.Context, userProfile *models.User) { userProfileBase(c, "notifications.jet.html", userProfile, Commonvariables(c)) } // DatabaseDump render the list of database dumps template func DatabaseDump(c *gin.Context, listDumps []models.DatabaseDumpJSON, GPGLink string) { variables := Commonvariables(c) variables.Set("ListDumps", listDumps) variables.Set("GPGLink", GPGLink) Render(c, path.Join(SiteDir, "database", "dumps.jet.html"), variables) } // PanelAdmin render the panel admin template index func PanelAdmin(c *gin.Context, torrent []models.Torrent, reports []models.TorrentReportJSON, users []models.User, comments []models.Comment) { variables := NewPanelCommonvariables(c) variables.Set("Torrents", torrent) variables.Set("TorrentReports", reports) variables.Set("Users", users) variables.Set("Comments", comments) Render(c, path.Join(ModeratorDir, "index.jet.html"), variables) } func isAdminTemplate(templateName string) bool { if templateName != "" && len(templateName) > len(ModeratorDir) { return templateName[:5] == ModeratorDir } return false }