Fixed a bug where it would use the wrong templates for Tempra Simple, Tempra Cursive, and Shadow
Likes are now done over AJAX. Posts you have liked are now visually differentiated from those which you have not. Added support for OR to the where parser. || and && now get translated to OR and AND in the where parser. Added support for ( and ) in the where parser. Added an adapter and builder method for getting the database version. Multiple wheres can now be chained with the micro and accumulator builders. Added the In method to the accumulator select builder. Added the GetConn method to the builder. /uploads/ files should now get cached properly. Added more tooltips for topic titles and usernames. Fixed a bug in the runners where old stale templates would be served. Fixed a bug where liking topics didn't work. Began moving the database initialisation logic out of {adapter}.go and into querygen. Tweaked the alert direction to show the newest alerts rather than the oldest. Tweaked the WS JS to have it handle messages more efficiently. Partially fixed an issue where inline edited posts would lack newlines until the page is refreshed. Used arrow functions in a few places in global.js to save a few characters. Schema: Added the liked, oldestItemLikedCreatedAt and lastLiked columns to the users table. Added the createdAt column to the likes table. MySQL Update Queries: ALTER TABLE `users` ADD COLUMN `liked` INT NOT NULL DEFAULT '0' AFTER `topics`; ALTER TABLE `users` ADD COLUMN `oldestItemLikedCreatedAt` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP AFTER `liked`; ALTER TABLE `users` ADD COLUMN `lastLiked` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP AFTER `oldestItemLikedCreatedAt`; ALTER TABLE `likes` ADD COLUMN `createdAt` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP AFTER `sentBy`; delete from `likes`; delete from `activity_stream` where `event` = 'like'; delete from `activity_stream_matches` where `asid` not in(select `asid` from `activity_stream`); update `topics` set `likeCount` = 0; update `replies` set `likeCount` = 0;
This commit is contained in:
parent
2b86a17478
commit
74e09efb63
|
@ -20,3 +20,4 @@ logs/*
|
||||||
*.log
|
*.log
|
||||||
.DS_Store
|
.DS_Store
|
||||||
.vscode/launch.json
|
.vscode/launch.json
|
||||||
|
config.go
|
||||||
|
|
|
@ -44,6 +44,11 @@ We recommend changing the root password (that is the password for the user 'root
|
||||||
It's entirely possible that your host might already have MySQL, so you might be able to skip this step, particularly if it's a managed VPS or a shared host (contrary to popular belief, it is possible, although the ecosystem in this regard is extremely immature). Or they might have a quicker and easier method of setting up MySQL.
|
It's entirely possible that your host might already have MySQL, so you might be able to skip this step, particularly if it's a managed VPS or a shared host (contrary to popular belief, it is possible, although the ecosystem in this regard is extremely immature). Or they might have a quicker and easier method of setting up MySQL.
|
||||||
|
|
||||||
|
|
||||||
|
# Downloading
|
||||||
|
|
||||||
|
At some point, we'll have releases which you can download, but right now, you'll have to use the `git clone` command as mentioned down in the advanced setup section to download a copy of Gosora.
|
||||||
|
|
||||||
|
|
||||||
# Installation Instructions
|
# Installation Instructions
|
||||||
|
|
||||||
*Linux*
|
*Linux*
|
||||||
|
|
|
@ -1,2 +1,11 @@
|
||||||
|
echo Building the templates
|
||||||
gosora.exe -build-templates
|
gosora.exe -build-templates
|
||||||
|
|
||||||
|
echo Rebuilding the executable
|
||||||
|
go build -o gosora.exe
|
||||||
|
if %errorlevel% neq 0 (
|
||||||
|
pause
|
||||||
|
exit /b %errorlevel%
|
||||||
|
)
|
||||||
|
|
||||||
pause
|
pause
|
|
@ -104,6 +104,10 @@ func (reply *Reply) Like(uid int) (err error) {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
_, err = replyStmts.addLikesToReply.Exec(1, reply.ID)
|
_, err = replyStmts.addLikesToReply.Exec(1, reply.ID)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
_, err = userStmts.incrementLiked.Exec(1, uid)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -132,10 +132,10 @@ func CompileTemplates() error {
|
||||||
|
|
||||||
// Schemas to train the template compiler on what to expect
|
// Schemas to train the template compiler on what to expect
|
||||||
// TODO: Add support for interface{}s
|
// TODO: Add support for interface{}s
|
||||||
user := User{62, BuildProfileURL("fake-user", 62), "Fake User", "compiler@localhost", 0, false, false, false, false, false, false, GuestPerms, make(map[string]bool), "", false, BuildAvatar(62, ""), "", "", "", "", 0, 0, "0.0.0.0.0", 0}
|
user := User{62, BuildProfileURL("fake-user", 62), "Fake User", "compiler@localhost", 0, false, false, false, false, false, false, GuestPerms, make(map[string]bool), "", false, BuildAvatar(62, ""), "", "", "", "", 0, 0, 0, "0.0.0.0.0", 0}
|
||||||
// TODO: Do a more accurate level calculation for this?
|
// TODO: Do a more accurate level calculation for this?
|
||||||
user2 := User{1, BuildProfileURL("admin-alice", 1), "Admin Alice", "alice@localhost", 1, true, true, true, true, false, false, AllPerms, make(map[string]bool), "", true, BuildAvatar(1, ""), "", "", "", "", 58, 1000, "127.0.0.1", 0}
|
user2 := User{1, BuildProfileURL("admin-alice", 1), "Admin Alice", "alice@localhost", 1, true, true, true, true, false, false, AllPerms, make(map[string]bool), "", true, BuildAvatar(1, ""), "", "", "", "", 58, 1000, 0, "127.0.0.1", 0}
|
||||||
user3 := User{2, BuildProfileURL("admin-fred", 62), "Admin Fred", "fred@localhost", 1, true, true, true, true, false, false, AllPerms, make(map[string]bool), "", true, BuildAvatar(2, ""), "", "", "", "", 42, 900, "::1", 0}
|
user3 := User{2, BuildProfileURL("admin-fred", 62), "Admin Fred", "fred@localhost", 1, true, true, true, true, false, false, AllPerms, make(map[string]bool), "", true, BuildAvatar(2, ""), "", "", "", "", 42, 900, 0, "::1", 0}
|
||||||
headerVars := &HeaderVars{
|
headerVars := &HeaderVars{
|
||||||
Site: Site,
|
Site: Site,
|
||||||
Settings: SettingBox.Load().(SettingMap),
|
Settings: SettingBox.Load().(SettingMap),
|
||||||
|
@ -373,6 +373,10 @@ func InitTemplates() error {
|
||||||
return GetTmplPhrase(phraseName) // TODO: Log non-existent phrases?
|
return GetTmplPhrase(phraseName) // TODO: Log non-existent phrases?
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fmap["scope"] = func(name interface{}) interface{} {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
// The interpreted templates...
|
// The interpreted templates...
|
||||||
DebugLog("Loading the template files...")
|
DebugLog("Loading the template files...")
|
||||||
Templates.Funcs(fmap)
|
Templates.Funcs(fmap)
|
||||||
|
|
|
@ -90,6 +90,7 @@ func (c *CTemplateSet) Compile(name string, fileDir string, expects string, expe
|
||||||
"divide": true,
|
"divide": true,
|
||||||
"dock": true,
|
"dock": true,
|
||||||
"lang": true,
|
"lang": true,
|
||||||
|
"scope": true,
|
||||||
}
|
}
|
||||||
|
|
||||||
c.importMap = map[string]string{
|
c.importMap = map[string]string{
|
||||||
|
@ -687,6 +688,9 @@ ArgLoop:
|
||||||
out = "w.Write(phrases[" + strconv.Itoa(len(c.langIndexToName)-1) + "])\n"
|
out = "w.Write(phrases[" + strconv.Itoa(len(c.langIndexToName)-1) + "])\n"
|
||||||
literal = true
|
literal = true
|
||||||
break ArgLoop
|
break ArgLoop
|
||||||
|
case "scope":
|
||||||
|
literal = true
|
||||||
|
break ArgLoop
|
||||||
default:
|
default:
|
||||||
c.detail("Variable!")
|
c.detail("Variable!")
|
||||||
if len(node.Args) > (pos + 1) {
|
if len(node.Args) > (pos + 1) {
|
||||||
|
|
|
@ -141,7 +141,7 @@ func init() {
|
||||||
stick: acc.Update("topics").Set("sticky = 1").Where("tid = ?").Prepare(),
|
stick: acc.Update("topics").Set("sticky = 1").Where("tid = ?").Prepare(),
|
||||||
unstick: acc.Update("topics").Set("sticky = 0").Where("tid = ?").Prepare(),
|
unstick: acc.Update("topics").Set("sticky = 0").Where("tid = ?").Prepare(),
|
||||||
hasLikedTopic: acc.Select("likes").Columns("targetItem").Where("sentBy = ? and targetItem = ? and targetType = 'topics'").Prepare(),
|
hasLikedTopic: acc.Select("likes").Columns("targetItem").Where("sentBy = ? and targetItem = ? and targetType = 'topics'").Prepare(),
|
||||||
createLike: acc.Insert("likes").Columns("weight, targetItem, targetType, sentBy").Fields("?,?,?,?").Prepare(),
|
createLike: acc.Insert("likes").Columns("weight, targetItem, targetType, sentBy, createdAt").Fields("?,?,?,?,UTC_TIMESTAMP()").Prepare(),
|
||||||
addLikesToTopic: acc.Update("topics").Set("likeCount = likeCount + ?").Where("tid = ?").Prepare(),
|
addLikesToTopic: acc.Update("topics").Set("likeCount = likeCount + ?").Where("tid = ?").Prepare(),
|
||||||
delete: acc.Delete("topics").Where("tid = ?").Prepare(),
|
delete: acc.Delete("topics").Where("tid = ?").Prepare(),
|
||||||
edit: acc.Update("topics").Set("title = ?, content = ?, parsed_content = ?").Where("tid = ?").Prepare(), // TODO: Only run the content update bits on non-polls, does this matter?
|
edit: acc.Update("topics").Set("title = ?, content = ?, parsed_content = ?").Where("tid = ?").Prepare(), // TODO: Only run the content update bits on non-polls, does this matter?
|
||||||
|
@ -205,20 +205,24 @@ func (topic *Topic) Unstick() (err error) {
|
||||||
// TODO: Test this
|
// TODO: Test this
|
||||||
// TODO: Use a transaction for this
|
// TODO: Use a transaction for this
|
||||||
func (topic *Topic) Like(score int, uid int) (err error) {
|
func (topic *Topic) Like(score int, uid int) (err error) {
|
||||||
var tid int // Unused
|
var disp int // Unused
|
||||||
err = topicStmts.hasLikedTopic.QueryRow(uid, topic.ID).Scan(&tid)
|
err = topicStmts.hasLikedTopic.QueryRow(uid, topic.ID).Scan(&disp)
|
||||||
if err != nil && err != ErrNoRows {
|
if err != nil && err != ErrNoRows {
|
||||||
return err
|
return err
|
||||||
} else if err != ErrNoRows {
|
} else if err != ErrNoRows {
|
||||||
return ErrAlreadyLiked
|
return ErrAlreadyLiked
|
||||||
}
|
}
|
||||||
|
|
||||||
_, err = topicStmts.createLike.Exec(score, tid, "topics", uid)
|
_, err = topicStmts.createLike.Exec(score, topic.ID, "topics", uid)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
_, err = topicStmts.addLikesToTopic.Exec(1, tid)
|
_, err = topicStmts.addLikesToTopic.Exec(1, topic.ID)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
_, err = userStmts.incrementLiked.Exec(1, uid)
|
||||||
topic.cacheRemove()
|
topic.cacheRemove()
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
|
@ -54,6 +54,7 @@ type User struct {
|
||||||
Tag string
|
Tag string
|
||||||
Level int
|
Level int
|
||||||
Score int
|
Score int
|
||||||
|
Liked int
|
||||||
LastIP string // ! This part of the UserCache data might fall out of date
|
LastIP string // ! This part of the UserCache data might fall out of date
|
||||||
TempGroup int
|
TempGroup int
|
||||||
}
|
}
|
||||||
|
@ -71,6 +72,8 @@ type UserStmts struct {
|
||||||
incrementPosts *sql.Stmt
|
incrementPosts *sql.Stmt
|
||||||
incrementBigposts *sql.Stmt
|
incrementBigposts *sql.Stmt
|
||||||
incrementMegaposts *sql.Stmt
|
incrementMegaposts *sql.Stmt
|
||||||
|
incrementLiked *sql.Stmt
|
||||||
|
decrementLiked *sql.Stmt
|
||||||
updateLastIP *sql.Stmt
|
updateLastIP *sql.Stmt
|
||||||
|
|
||||||
setPassword *sql.Stmt
|
setPassword *sql.Stmt
|
||||||
|
@ -92,7 +95,10 @@ func init() {
|
||||||
incrementPosts: acc.SimpleUpdate("users", "posts = posts + ?", "uid = ?"),
|
incrementPosts: acc.SimpleUpdate("users", "posts = posts + ?", "uid = ?"),
|
||||||
incrementBigposts: acc.SimpleUpdate("users", "posts = posts + ?, bigposts = bigposts + ?", "uid = ?"),
|
incrementBigposts: acc.SimpleUpdate("users", "posts = posts + ?, bigposts = bigposts + ?", "uid = ?"),
|
||||||
incrementMegaposts: acc.SimpleUpdate("users", "posts = posts + ?, bigposts = bigposts + ?, megaposts = megaposts + ?", "uid = ?"),
|
incrementMegaposts: acc.SimpleUpdate("users", "posts = posts + ?, bigposts = bigposts + ?, megaposts = megaposts + ?", "uid = ?"),
|
||||||
updateLastIP: acc.SimpleUpdate("users", "last_ip = ?", "uid = ?"),
|
incrementLiked: acc.SimpleUpdate("users", "liked = liked + ?, lastLiked = UTC_TIMESTAMP()", "uid = ?"),
|
||||||
|
decrementLiked: acc.SimpleUpdate("users", "liked = liked - ?", "uid = ?"),
|
||||||
|
//recalcLastLiked: acc...
|
||||||
|
updateLastIP: acc.SimpleUpdate("users", "last_ip = ?", "uid = ?"),
|
||||||
|
|
||||||
setPassword: acc.SimpleUpdate("users", "password = ?, salt = ?", "uid = ?"),
|
setPassword: acc.SimpleUpdate("users", "password = ?, salt = ?", "uid = ?"),
|
||||||
}
|
}
|
||||||
|
|
|
@ -50,7 +50,7 @@ func NewDefaultUserStore(cache UserCache) (*DefaultUserStore, error) {
|
||||||
// TODO: Add an admin version of registerStmt with more flexibility?
|
// TODO: Add an admin version of registerStmt with more flexibility?
|
||||||
return &DefaultUserStore{
|
return &DefaultUserStore{
|
||||||
cache: cache,
|
cache: cache,
|
||||||
get: acc.SimpleSelect("users", "name, group, active, is_super_admin, session, email, avatar, message, url_prefix, url_name, level, score, last_ip, temp_group", "uid = ?", "", ""),
|
get: acc.SimpleSelect("users", "name, group, active, is_super_admin, session, email, avatar, message, url_prefix, url_name, level, score, liked, last_ip, temp_group", "uid = ?", "", ""),
|
||||||
exists: acc.SimpleSelect("users", "uid", "uid = ?", "", ""),
|
exists: acc.SimpleSelect("users", "uid", "uid = ?", "", ""),
|
||||||
register: acc.SimpleInsert("users", "name, email, password, salt, group, is_super_admin, session, active, message, createdAt, lastActiveAt", "?,?,?,?,?,0,'',?,'',UTC_TIMESTAMP(),UTC_TIMESTAMP()"), // TODO: Implement user_count on users_groups here
|
register: acc.SimpleInsert("users", "name, email, password, salt, group, is_super_admin, session, active, message, createdAt, lastActiveAt", "?,?,?,?,?,0,'',?,'',UTC_TIMESTAMP(),UTC_TIMESTAMP()"), // TODO: Implement user_count on users_groups here
|
||||||
usernameExists: acc.SimpleSelect("users", "name", "name = ?", "", ""),
|
usernameExists: acc.SimpleSelect("users", "name", "name = ?", "", ""),
|
||||||
|
@ -65,7 +65,7 @@ func (mus *DefaultUserStore) DirtyGet(id int) *User {
|
||||||
}
|
}
|
||||||
|
|
||||||
user = &User{ID: id, Loggedin: true}
|
user = &User{ID: id, Loggedin: true}
|
||||||
err = mus.get.QueryRow(id).Scan(&user.Name, &user.Group, &user.Active, &user.IsSuperAdmin, &user.Session, &user.Email, &user.Avatar, &user.Message, &user.URLPrefix, &user.URLName, &user.Level, &user.Score, &user.LastIP, &user.TempGroup)
|
err = mus.get.QueryRow(id).Scan(&user.Name, &user.Group, &user.Active, &user.IsSuperAdmin, &user.Session, &user.Email, &user.Avatar, &user.Message, &user.URLPrefix, &user.URLName, &user.Level, &user.Score, &user.Liked, &user.LastIP, &user.TempGroup)
|
||||||
|
|
||||||
user.Init()
|
user.Init()
|
||||||
if err == nil {
|
if err == nil {
|
||||||
|
@ -83,7 +83,7 @@ func (mus *DefaultUserStore) Get(id int) (*User, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
user = &User{ID: id, Loggedin: true}
|
user = &User{ID: id, Loggedin: true}
|
||||||
err = mus.get.QueryRow(id).Scan(&user.Name, &user.Group, &user.Active, &user.IsSuperAdmin, &user.Session, &user.Email, &user.Avatar, &user.Message, &user.URLPrefix, &user.URLName, &user.Level, &user.Score, &user.LastIP, &user.TempGroup)
|
err = mus.get.QueryRow(id).Scan(&user.Name, &user.Group, &user.Active, &user.IsSuperAdmin, &user.Session, &user.Email, &user.Avatar, &user.Message, &user.URLPrefix, &user.URLName, &user.Level, &user.Score, &user.Liked, &user.LastIP, &user.TempGroup)
|
||||||
|
|
||||||
user.Init()
|
user.Init()
|
||||||
if err == nil {
|
if err == nil {
|
||||||
|
@ -127,14 +127,14 @@ func (mus *DefaultUserStore) BulkGetMap(ids []int) (list map[int]*User, err erro
|
||||||
qlist = qlist[0 : len(qlist)-1]
|
qlist = qlist[0 : len(qlist)-1]
|
||||||
|
|
||||||
acc := qgen.Builder.Accumulator()
|
acc := qgen.Builder.Accumulator()
|
||||||
rows, err := acc.Select("users").Columns("uid, name, group, active, is_super_admin, session, email, avatar, message, url_prefix, url_name, level, score, last_ip, temp_group").Where("uid IN(" + qlist + ")").Query(uidList...)
|
rows, err := acc.Select("users").Columns("uid, name, group, active, is_super_admin, session, email, avatar, message, url_prefix, url_name, level, score, liked, last_ip, temp_group").Where("uid IN(" + qlist + ")").Query(uidList...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return list, err
|
return list, err
|
||||||
}
|
}
|
||||||
|
|
||||||
for rows.Next() {
|
for rows.Next() {
|
||||||
user := &User{Loggedin: true}
|
user := &User{Loggedin: true}
|
||||||
err := rows.Scan(&user.ID, &user.Name, &user.Group, &user.Active, &user.IsSuperAdmin, &user.Session, &user.Email, &user.Avatar, &user.Message, &user.URLPrefix, &user.URLName, &user.Level, &user.Score, &user.LastIP, &user.TempGroup)
|
err := rows.Scan(&user.ID, &user.Name, &user.Group, &user.Active, &user.IsSuperAdmin, &user.Session, &user.Email, &user.Avatar, &user.Message, &user.URLPrefix, &user.URLName, &user.Level, &user.Score, &user.Liked, &user.LastIP, &user.TempGroup)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return list, err
|
return list, err
|
||||||
}
|
}
|
||||||
|
@ -175,7 +175,7 @@ func (mus *DefaultUserStore) BulkGetMap(ids []int) (list map[int]*User, err erro
|
||||||
|
|
||||||
func (mus *DefaultUserStore) BypassGet(id int) (*User, error) {
|
func (mus *DefaultUserStore) BypassGet(id int) (*User, error) {
|
||||||
user := &User{ID: id, Loggedin: true}
|
user := &User{ID: id, Loggedin: true}
|
||||||
err := mus.get.QueryRow(id).Scan(&user.Name, &user.Group, &user.Active, &user.IsSuperAdmin, &user.Session, &user.Email, &user.Avatar, &user.Message, &user.URLPrefix, &user.URLName, &user.Level, &user.Score, &user.LastIP, &user.TempGroup)
|
err := mus.get.QueryRow(id).Scan(&user.Name, &user.Group, &user.Active, &user.IsSuperAdmin, &user.Session, &user.Email, &user.Avatar, &user.Message, &user.URLPrefix, &user.URLName, &user.Level, &user.Score, &user.Liked, &user.LastIP, &user.TempGroup)
|
||||||
|
|
||||||
user.Init()
|
user.Init()
|
||||||
return user, err
|
return user, err
|
||||||
|
@ -183,7 +183,7 @@ func (mus *DefaultUserStore) BypassGet(id int) (*User, error) {
|
||||||
|
|
||||||
func (mus *DefaultUserStore) Reload(id int) error {
|
func (mus *DefaultUserStore) Reload(id int) error {
|
||||||
user := &User{ID: id, Loggedin: true}
|
user := &User{ID: id, Loggedin: true}
|
||||||
err := mus.get.QueryRow(id).Scan(&user.Name, &user.Group, &user.Active, &user.IsSuperAdmin, &user.Session, &user.Email, &user.Avatar, &user.Message, &user.URLPrefix, &user.URLName, &user.Level, &user.Score, &user.LastIP, &user.TempGroup)
|
err := mus.get.QueryRow(id).Scan(&user.Name, &user.Group, &user.Active, &user.IsSuperAdmin, &user.Session, &user.Email, &user.Avatar, &user.Message, &user.URLPrefix, &user.URLName, &user.Level, &user.Score, &user.Liked, &user.LastIP, &user.TempGroup)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
mus.cache.Remove(id)
|
mus.cache.Remove(id)
|
||||||
return err
|
return err
|
||||||
|
|
|
@ -10,7 +10,6 @@ import (
|
||||||
var stmts *Stmts
|
var stmts *Stmts
|
||||||
|
|
||||||
var db *sql.DB
|
var db *sql.DB
|
||||||
var dbVersion string
|
|
||||||
var dbAdapter string
|
var dbAdapter string
|
||||||
|
|
||||||
// ErrNoRows is an alias of sql.ErrNoRows, just in case we end up with non-database/sql datastores
|
// ErrNoRows is an alias of sql.ErrNoRows, just in case we end up with non-database/sql datastores
|
||||||
|
|
|
@ -462,6 +462,32 @@ func init() {
|
||||||
counters.SetReverseOSMapEnum(reverseOSMapEnum)
|
counters.SetReverseOSMapEnum(reverseOSMapEnum)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type WriterIntercept struct {
|
||||||
|
w http.ResponseWriter
|
||||||
|
code int
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewWriterIntercept(w http.ResponseWriter) *WriterIntercept {
|
||||||
|
return &WriterIntercept{w:w,code:200}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (writ *WriterIntercept) Header() http.Header {
|
||||||
|
return writ.w.Header()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (writ *WriterIntercept) Write(pieces []byte) (int, error) {
|
||||||
|
return writ.w.Write(pieces)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (writ *WriterIntercept) WriteHeader(code int) {
|
||||||
|
writ.w.WriteHeader(code)
|
||||||
|
writ.code = code
|
||||||
|
}
|
||||||
|
|
||||||
|
func (writ *WriterIntercept) GetCode() int {
|
||||||
|
return writ.code
|
||||||
|
}
|
||||||
|
|
||||||
type GenRouter struct {
|
type GenRouter struct {
|
||||||
UploadHandler func(http.ResponseWriter, *http.Request)
|
UploadHandler func(http.ResponseWriter, *http.Request)
|
||||||
extraRoutes map[string]func(http.ResponseWriter, *http.Request, common.User) common.RouteError
|
extraRoutes map[string]func(http.ResponseWriter, *http.Request, common.User) common.RouteError
|
||||||
|
@ -471,7 +497,14 @@ type GenRouter struct {
|
||||||
|
|
||||||
func NewGenRouter(uploads http.Handler) *GenRouter {
|
func NewGenRouter(uploads http.Handler) *GenRouter {
|
||||||
return &GenRouter{
|
return &GenRouter{
|
||||||
UploadHandler: http.StripPrefix("/uploads/",uploads).ServeHTTP,
|
UploadHandler: func(w http.ResponseWriter, req *http.Request) {
|
||||||
|
writ := NewWriterIntercept(w)
|
||||||
|
http.StripPrefix("/uploads/",uploads).ServeHTTP(writ,req)
|
||||||
|
if writ.GetCode() == 200 {
|
||||||
|
w.Header().Set("Cache-Control", "max-age=" + strconv.Itoa(common.Day))
|
||||||
|
w.Header().Set("Vary", "Accept-Encoding")
|
||||||
|
}
|
||||||
|
},
|
||||||
extraRoutes: make(map[string]func(http.ResponseWriter, *http.Request, common.User) common.RouteError),
|
extraRoutes: make(map[string]func(http.ResponseWriter, *http.Request, common.User) common.RouteError),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1514,6 +1547,12 @@ func (router *GenRouter) ServeHTTP(w http.ResponseWriter, req *http.Request) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
err = common.ParseForm(w,req,user)
|
||||||
|
if err != nil {
|
||||||
|
router.handleError(err,w,req,user)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
counters.RouteViewCounter.Bump(83)
|
counters.RouteViewCounter.Bump(83)
|
||||||
err = routeLikeTopicSubmit(w,req,user,extraData)
|
err = routeLikeTopicSubmit(w,req,user,extraData)
|
||||||
default:
|
default:
|
||||||
|
@ -1588,6 +1627,12 @@ func (router *GenRouter) ServeHTTP(w http.ResponseWriter, req *http.Request) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
err = common.ParseForm(w,req,user)
|
||||||
|
if err != nil {
|
||||||
|
router.handleError(err,w,req,user)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
counters.RouteViewCounter.Bump(88)
|
counters.RouteViewCounter.Bump(88)
|
||||||
err = routeReplyLikeSubmit(w,req,user,extraData)
|
err = routeReplyLikeSubmit(w,req,user,extraData)
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,16 +16,17 @@ import (
|
||||||
|
|
||||||
// TODO: Refactor this
|
// TODO: Refactor this
|
||||||
func routeLikeTopicSubmit(w http.ResponseWriter, r *http.Request, user common.User, stid string) common.RouteError {
|
func routeLikeTopicSubmit(w http.ResponseWriter, r *http.Request, user common.User, stid string) common.RouteError {
|
||||||
|
isJs := (r.PostFormValue("isJs") == "1")
|
||||||
tid, err := strconv.Atoi(stid)
|
tid, err := strconv.Atoi(stid)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return common.PreError("Topic IDs can only ever be numbers.", w, r)
|
return common.PreErrorJSQ("Topic IDs can only ever be numbers.", w, r, isJs)
|
||||||
}
|
}
|
||||||
|
|
||||||
topic, err := common.Topics.Get(tid)
|
topic, err := common.Topics.Get(tid)
|
||||||
if err == ErrNoRows {
|
if err == ErrNoRows {
|
||||||
return common.PreError("The requested topic doesn't exist.", w, r)
|
return common.PreErrorJSQ("The requested topic doesn't exist.", w, r, isJs)
|
||||||
} else if err != nil {
|
} else if err != nil {
|
||||||
return common.InternalError(err, w, r)
|
return common.InternalErrorJSQ(err, w, r, isJs)
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Add hooks to make use of headerLite
|
// TODO: Add hooks to make use of headerLite
|
||||||
|
@ -34,55 +35,62 @@ func routeLikeTopicSubmit(w http.ResponseWriter, r *http.Request, user common.Us
|
||||||
return ferr
|
return ferr
|
||||||
}
|
}
|
||||||
if !user.Perms.ViewTopic || !user.Perms.LikeItem {
|
if !user.Perms.ViewTopic || !user.Perms.LikeItem {
|
||||||
return common.NoPermissions(w, r, user)
|
return common.NoPermissionsJSQ(w, r, user, isJs)
|
||||||
}
|
}
|
||||||
if topic.CreatedBy == user.ID {
|
if topic.CreatedBy == user.ID {
|
||||||
return common.LocalError("You can't like your own topics", w, r, user)
|
return common.LocalErrorJSQ("You can't like your own topics", w, r, user, isJs)
|
||||||
}
|
}
|
||||||
|
|
||||||
_, err = common.Users.Get(topic.CreatedBy)
|
_, err = common.Users.Get(topic.CreatedBy)
|
||||||
if err != nil && err == ErrNoRows {
|
if err != nil && err == ErrNoRows {
|
||||||
return common.LocalError("The target user doesn't exist", w, r, user)
|
return common.LocalErrorJSQ("The target user doesn't exist", w, r, user, isJs)
|
||||||
} else if err != nil {
|
} else if err != nil {
|
||||||
return common.InternalError(err, w, r)
|
return common.InternalErrorJSQ(err, w, r, isJs)
|
||||||
}
|
}
|
||||||
|
|
||||||
score := 1
|
score := 1
|
||||||
err = topic.Like(score, user.ID)
|
err = topic.Like(score, user.ID)
|
||||||
|
//log.Print("likeErr: ", err)
|
||||||
if err == common.ErrAlreadyLiked {
|
if err == common.ErrAlreadyLiked {
|
||||||
return common.LocalError("You already liked this", w, r, user)
|
return common.LocalErrorJSQ("You already liked this", w, r, user, isJs)
|
||||||
} else if err != nil {
|
} else if err != nil {
|
||||||
return common.InternalError(err, w, r)
|
return common.InternalErrorJSQ(err, w, r, isJs)
|
||||||
}
|
}
|
||||||
|
|
||||||
err = common.AddActivityAndNotifyTarget(user.ID, topic.CreatedBy, "like", "topic", tid)
|
err = common.AddActivityAndNotifyTarget(user.ID, topic.CreatedBy, "like", "topic", tid)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return common.InternalError(err, w, r)
|
return common.InternalErrorJSQ(err, w, r, isJs)
|
||||||
}
|
}
|
||||||
|
|
||||||
http.Redirect(w, r, "/topic/"+strconv.Itoa(tid), http.StatusSeeOther)
|
if !isJs {
|
||||||
|
http.Redirect(w, r, "/topic/"+strconv.Itoa(tid), http.StatusSeeOther)
|
||||||
|
} else {
|
||||||
|
_, _ = w.Write(successJSONBytes)
|
||||||
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func routeReplyLikeSubmit(w http.ResponseWriter, r *http.Request, user common.User, srid string) common.RouteError {
|
func routeReplyLikeSubmit(w http.ResponseWriter, r *http.Request, user common.User, srid string) common.RouteError {
|
||||||
|
isJs := (r.PostFormValue("isJs") == "1")
|
||||||
|
|
||||||
rid, err := strconv.Atoi(srid)
|
rid, err := strconv.Atoi(srid)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return common.PreError("The provided Reply ID is not a valid number.", w, r)
|
return common.PreErrorJSQ("The provided Reply ID is not a valid number.", w, r, isJs)
|
||||||
}
|
}
|
||||||
|
|
||||||
reply, err := common.Rstore.Get(rid)
|
reply, err := common.Rstore.Get(rid)
|
||||||
if err == ErrNoRows {
|
if err == ErrNoRows {
|
||||||
return common.PreError("You can't like something which doesn't exist!", w, r)
|
return common.PreErrorJSQ("You can't like something which doesn't exist!", w, r, isJs)
|
||||||
} else if err != nil {
|
} else if err != nil {
|
||||||
return common.InternalError(err, w, r)
|
return common.InternalErrorJSQ(err, w, r, isJs)
|
||||||
}
|
}
|
||||||
|
|
||||||
var fid int
|
var fid int
|
||||||
err = stmts.getTopicFID.QueryRow(reply.ParentID).Scan(&fid)
|
err = stmts.getTopicFID.QueryRow(reply.ParentID).Scan(&fid)
|
||||||
if err == ErrNoRows {
|
if err == ErrNoRows {
|
||||||
return common.PreError("The parent topic doesn't exist.", w, r)
|
return common.PreErrorJSQ("The parent topic doesn't exist.", w, r, isJs)
|
||||||
} else if err != nil {
|
} else if err != nil {
|
||||||
return common.InternalError(err, w, r)
|
return common.InternalErrorJSQ(err, w, r, isJs)
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Add hooks to make use of headerLite
|
// TODO: Add hooks to make use of headerLite
|
||||||
|
@ -91,32 +99,36 @@ func routeReplyLikeSubmit(w http.ResponseWriter, r *http.Request, user common.Us
|
||||||
return ferr
|
return ferr
|
||||||
}
|
}
|
||||||
if !user.Perms.ViewTopic || !user.Perms.LikeItem {
|
if !user.Perms.ViewTopic || !user.Perms.LikeItem {
|
||||||
return common.NoPermissions(w, r, user)
|
return common.NoPermissionsJSQ(w, r, user, isJs)
|
||||||
}
|
}
|
||||||
if reply.CreatedBy == user.ID {
|
if reply.CreatedBy == user.ID {
|
||||||
return common.LocalError("You can't like your own replies", w, r, user)
|
return common.LocalErrorJSQ("You can't like your own replies", w, r, user, isJs)
|
||||||
}
|
}
|
||||||
|
|
||||||
_, err = common.Users.Get(reply.CreatedBy)
|
_, err = common.Users.Get(reply.CreatedBy)
|
||||||
if err != nil && err != ErrNoRows {
|
if err != nil && err != ErrNoRows {
|
||||||
return common.LocalError("The target user doesn't exist", w, r, user)
|
return common.LocalErrorJSQ("The target user doesn't exist", w, r, user, isJs)
|
||||||
} else if err != nil {
|
} else if err != nil {
|
||||||
return common.InternalError(err, w, r)
|
return common.InternalErrorJSQ(err, w, r, isJs)
|
||||||
}
|
}
|
||||||
|
|
||||||
err = reply.Like(user.ID)
|
err = reply.Like(user.ID)
|
||||||
if err == common.ErrAlreadyLiked {
|
if err == common.ErrAlreadyLiked {
|
||||||
return common.LocalError("You've already liked this!", w, r, user)
|
return common.LocalErrorJSQ("You've already liked this!", w, r, user, isJs)
|
||||||
} else if err != nil {
|
} else if err != nil {
|
||||||
return common.InternalError(err, w, r)
|
return common.InternalErrorJSQ(err, w, r, isJs)
|
||||||
}
|
}
|
||||||
|
|
||||||
err = common.AddActivityAndNotifyTarget(user.ID, reply.CreatedBy, "like", "post", rid)
|
err = common.AddActivityAndNotifyTarget(user.ID, reply.CreatedBy, "like", "post", rid)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return common.InternalError(err, w, r)
|
return common.InternalErrorJSQ(err, w, r, isJs)
|
||||||
}
|
}
|
||||||
|
|
||||||
http.Redirect(w, r, "/topic/"+strconv.Itoa(reply.ParentID), http.StatusSeeOther)
|
if !isJs {
|
||||||
|
http.Redirect(w, r, "/topic/"+strconv.Itoa(reply.ParentID), http.StatusSeeOther)
|
||||||
|
} else {
|
||||||
|
_, _ = w.Write(successJSONBytes)
|
||||||
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
4
mssql.go
4
mssql.go
|
@ -47,8 +47,6 @@ func initMSSQL() (err error) {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Fetch the database version
|
|
||||||
|
|
||||||
// Set the number of max open connections
|
// Set the number of max open connections
|
||||||
db.SetMaxOpenConns(64)
|
db.SetMaxOpenConns(64)
|
||||||
db.SetMaxIdleConns(32)
|
db.SetMaxIdleConns(32)
|
||||||
|
@ -76,7 +74,7 @@ func initMSSQL() (err error) {
|
||||||
|
|
||||||
// TODO: Is there a less noisy way of doing this for tests?
|
// TODO: Is there a less noisy way of doing this for tests?
|
||||||
log.Print("Preparing getActivityFeedByWatcher statement.")
|
log.Print("Preparing getActivityFeedByWatcher statement.")
|
||||||
getActivityFeedByWatcherStmt, err = db.Prepare("SELECT activity_stream_matches.asid, activity_stream.actor, activity_stream.targetUser, activity_stream.event, activity_stream.elementType, activity_stream.elementID FROM [activity_stream_matches] INNER JOIN [activity_stream] ON activity_stream_matches.asid = activity_stream.asid AND activity_stream_matches.watcher != activity_stream.actor WHERE [watcher] = ? ORDER BY activity_stream.asid ASC OFFSET 0 ROWS FETCH NEXT 8 ROWS ONLY")
|
getActivityFeedByWatcherStmt, err = db.Prepare("SELECT activity_stream_matches.asid, activity_stream.actor, activity_stream.targetUser, activity_stream.event, activity_stream.elementType, activity_stream.elementID FROM [activity_stream_matches] INNER JOIN [activity_stream] ON activity_stream_matches.asid = activity_stream.asid AND activity_stream_matches.watcher != activity_stream.actor WHERE [watcher] = ? ORDER BY activity_stream.asid DESC OFFSET 0 ROWS FETCH NEXT 8 ROWS ONLY")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
31
mysql.go
31
mysql.go
|
@ -9,11 +9,8 @@
|
||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"database/sql"
|
|
||||||
"log"
|
"log"
|
||||||
|
|
||||||
//import "time"
|
|
||||||
|
|
||||||
"./common"
|
"./common"
|
||||||
"./query_gen/lib"
|
"./query_gen/lib"
|
||||||
_ "github.com/go-sql-driver/mysql"
|
_ "github.com/go-sql-driver/mysql"
|
||||||
|
@ -27,28 +24,20 @@ func init() {
|
||||||
}
|
}
|
||||||
|
|
||||||
func initMySQL() (err error) {
|
func initMySQL() (err error) {
|
||||||
var _dbpassword string
|
err = qgen.Builder.Init("mysql", map[string]string{
|
||||||
if common.DbConfig.Password != "" {
|
"host": common.DbConfig.Host,
|
||||||
_dbpassword = ":" + common.DbConfig.Password
|
"port": common.DbConfig.Port,
|
||||||
}
|
"name": common.DbConfig.Dbname,
|
||||||
|
"username": common.DbConfig.Username,
|
||||||
// TODO: Move this bit to the query gen lib
|
"password": common.DbConfig.Password,
|
||||||
// Open the database connection
|
"collation": dbCollation,
|
||||||
db, err = sql.Open("mysql", common.DbConfig.Username+_dbpassword+"@tcp("+common.DbConfig.Host+":"+common.DbConfig.Port+")/"+common.DbConfig.Dbname+"?collation="+dbCollation+"&parseTime=true")
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// Make sure that the connection is alive
|
|
||||||
err = db.Ping()
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// Fetch the database version
|
|
||||||
db.QueryRow("SELECT VERSION()").Scan(&dbVersion)
|
|
||||||
|
|
||||||
// Set the number of max open connections
|
// Set the number of max open connections
|
||||||
|
db = qgen.Builder.GetConn()
|
||||||
db.SetMaxOpenConns(64)
|
db.SetMaxOpenConns(64)
|
||||||
db.SetMaxIdleConns(32)
|
db.SetMaxIdleConns(32)
|
||||||
|
|
||||||
|
@ -70,7 +59,7 @@ func initMySQL() (err error) {
|
||||||
|
|
||||||
// TODO: Is there a less noisy way of doing this for tests?
|
// TODO: Is there a less noisy way of doing this for tests?
|
||||||
log.Print("Preparing getActivityFeedByWatcher statement.")
|
log.Print("Preparing getActivityFeedByWatcher statement.")
|
||||||
stmts.getActivityFeedByWatcher, err = db.Prepare("SELECT activity_stream_matches.asid, activity_stream.actor, activity_stream.targetUser, activity_stream.event, activity_stream.elementType, activity_stream.elementID FROM `activity_stream_matches` INNER JOIN `activity_stream` ON activity_stream_matches.asid = activity_stream.asid AND activity_stream_matches.watcher != activity_stream.actor WHERE `watcher` = ? ORDER BY activity_stream.asid ASC LIMIT 8")
|
stmts.getActivityFeedByWatcher, err = db.Prepare("SELECT activity_stream_matches.asid, activity_stream.actor, activity_stream.targetUser, activity_stream.event, activity_stream.elementType, activity_stream.elementID FROM `activity_stream_matches` INNER JOIN `activity_stream` ON activity_stream_matches.asid = activity_stream.asid AND activity_stream_matches.watcher != activity_stream.actor WHERE `watcher` = ? ORDER BY activity_stream.asid DESC LIMIT 8")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,88 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bufio"
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
"runtime/debug"
|
||||||
|
|
||||||
|
"../query_gen/lib"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
scanner := bufio.NewScanner(os.Stdin)
|
||||||
|
|
||||||
|
// Capture panics instead of closing the window at a superhuman speed before the user can read the message on Windows
|
||||||
|
defer func() {
|
||||||
|
r := recover()
|
||||||
|
if r != nil {
|
||||||
|
fmt.Println(r)
|
||||||
|
debug.PrintStack()
|
||||||
|
pressAnyKey(scanner)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
err := patcher(scanner)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func pressAnyKey(scanner *bufio.Scanner) {
|
||||||
|
fmt.Println("Please press enter to exit...")
|
||||||
|
for scanner.Scan() {
|
||||||
|
_ = scanner.Text()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func patcher(scanner *bufio.Scanner) error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
/*func eachUserQuick(handle func(int)) error {
|
||||||
|
stmt, err := qgen.Builder.Select("users").Orderby("uid desc").Limit(1).Prepare()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
var topID int
|
||||||
|
err := stmt.QueryRow(topID)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
for i := 1; i <= topID; i++ {
|
||||||
|
err = handle(i)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}*/
|
||||||
|
|
||||||
|
func eachUser(handle func(int)) error {
|
||||||
|
stmt, err := qgen.Builder.Select("users").Prepare()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
rows, err := stmt.Query()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
defer rows.Close()
|
||||||
|
|
||||||
|
for rows.Next() {
|
||||||
|
var uid int
|
||||||
|
err := rows.Scan(&uid)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
err = handle(uid)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return rows.Err()
|
||||||
|
}
|
9
pgsql.go
9
pgsql.go
|
@ -14,10 +14,10 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
// TODO: Add support for SSL for all database drivers, not just pgsql
|
// TODO: Add support for SSL for all database drivers, not just pgsql
|
||||||
var db_sslmode = "disable" // verify-full
|
var dbSslmode = "disable" // verify-full
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
db_adapter = "pgsql"
|
dbAdapter = "pgsql"
|
||||||
_initDatabase = initPgsql
|
_initDatabase = initPgsql
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -28,7 +28,7 @@ func initPgsql() (err error) {
|
||||||
_dbpassword = " password='" + _escape_bit(common.DbConfig.Password) + "'"
|
_dbpassword = " password='" + _escape_bit(common.DbConfig.Password) + "'"
|
||||||
}
|
}
|
||||||
// TODO: Move this bit to the query gen lib
|
// TODO: Move this bit to the query gen lib
|
||||||
db, err = sql.Open("postgres", "host='"+_escape_bit(common.DbConfig.Host)+"' port='"+_escape_bit(common.DbConfig.Port)+"' user='"+_escape_bit(common.DbConfig.Username)+"' dbname='"+_escape_bit(common.Config.Dbname)+"'"+_dbpassword+" sslmode='"+db_sslmode+"'")
|
db, err = sql.Open("postgres", "host='"+_escape_bit(common.DbConfig.Host)+"' port='"+_escape_bit(common.DbConfig.Port)+"' user='"+_escape_bit(common.DbConfig.Username)+"' dbname='"+_escape_bit(common.Config.Dbname)+"'"+_dbpassword+" sslmode='"+dbSslmode+"'")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -39,9 +39,6 @@ func initPgsql() (err error) {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// Fetch the database version
|
|
||||||
db.QueryRow("SELECT VERSION()").Scan(&db_version)
|
|
||||||
|
|
||||||
// Set the number of max open connections. How many do we need? Might need to do some tests.
|
// Set the number of max open connections. How many do we need? Might need to do some tests.
|
||||||
db.SetMaxOpenConns(64)
|
db.SetMaxOpenConns(64)
|
||||||
db.SetMaxIdleConns(32)
|
db.SetMaxIdleConns(32)
|
||||||
|
|
|
@ -153,7 +153,7 @@ function runWebSockets() {
|
||||||
console.log("The WebSockets connection was closed");
|
console.log("The WebSockets connection was closed");
|
||||||
}
|
}
|
||||||
conn.onmessage = function(event) {
|
conn.onmessage = function(event) {
|
||||||
//console.log("WS_Message:", event.data);
|
//console.log("WSMessage:", event.data);
|
||||||
if(event.data[0] == "{") {
|
if(event.data[0] == "{") {
|
||||||
try {
|
try {
|
||||||
var data = JSON.parse(event.data);
|
var data = JSON.parse(event.data);
|
||||||
|
@ -200,14 +200,15 @@ function runWebSockets() {
|
||||||
|
|
||||||
var messages = event.data.split('\r');
|
var messages = event.data.split('\r');
|
||||||
for(var i = 0; i < messages.length; i++) {
|
for(var i = 0; i < messages.length; i++) {
|
||||||
//console.log("Message: ",messages[i]);
|
let message = messages[i];
|
||||||
if(messages[i].startsWith("set ")) {
|
//console.log("Message: ",message);
|
||||||
//msgblocks = messages[i].split(' ',3);
|
if(message.startsWith("set ")) {
|
||||||
let msgblocks = SplitN(messages[i]," ",3);
|
//msgblocks = message.split(' ',3);
|
||||||
|
let msgblocks = SplitN(message," ",3);
|
||||||
if(msgblocks.length < 3) continue;
|
if(msgblocks.length < 3) continue;
|
||||||
document.querySelector(msgblocks[1]).innerHTML = msgblocks[2];
|
document.querySelector(msgblocks[1]).innerHTML = msgblocks[2];
|
||||||
} else if(messages[i].startsWith("set-class ")) {
|
} else if(message.startsWith("set-class ")) {
|
||||||
let msgblocks = SplitN(messages[i]," ",3);
|
let msgblocks = SplitN(message," ",3);
|
||||||
if(msgblocks.length < 3) continue;
|
if(msgblocks.length < 3) continue;
|
||||||
document.querySelector(msgblocks[1]).className = msgblocks[2];
|
document.querySelector(msgblocks[1]).className = msgblocks[2];
|
||||||
}
|
}
|
||||||
|
@ -220,8 +221,45 @@ $(document).ready(function(){
|
||||||
if(window["WebSocket"]) runWebSockets();
|
if(window["WebSocket"]) runWebSockets();
|
||||||
else conn = false;
|
else conn = false;
|
||||||
|
|
||||||
$(".open_edit").click(function(event){
|
$(".add_like").click(function(event) {
|
||||||
//console.log("clicked on .open_edit");
|
event.preventDefault();
|
||||||
|
let likeButton = this;
|
||||||
|
let target = this.closest("a").getAttribute("href");
|
||||||
|
console.log("target: ", target);
|
||||||
|
likeButton.classList.remove("add_like");
|
||||||
|
likeButton.classList.add("remove_like");
|
||||||
|
let controls = likeButton.closest(".controls");
|
||||||
|
let hadLikes = controls.classList.contains("has_likes");
|
||||||
|
if(!hadLikes) controls.classList.add("has_likes");
|
||||||
|
let likeCountNode = controls.getElementsByClassName("like_count")[0];
|
||||||
|
console.log("likeCountNode",likeCountNode);
|
||||||
|
likeCountNode.innerHTML = parseInt(likeCountNode.innerHTML) + 1;
|
||||||
|
|
||||||
|
$.ajax({
|
||||||
|
url: target,
|
||||||
|
type: "POST",
|
||||||
|
dataType: "json",
|
||||||
|
data: { isJs: 1 },
|
||||||
|
error: ajaxError,
|
||||||
|
success: function (data, status, xhr) {
|
||||||
|
if("success" in data) {
|
||||||
|
if(data["success"] == "1") {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// addNotice("Failed to add a like: {err}")
|
||||||
|
likeButton.classList.add("add_like");
|
||||||
|
likeButton.classList.remove("remove_like");
|
||||||
|
if(!hadLikes) controls.classList.remove("has_likes");
|
||||||
|
likeCountNode.innerHTML = parseInt(likeCountNode.innerHTML) - 1;
|
||||||
|
console.log("data", data);
|
||||||
|
console.log("status", status);
|
||||||
|
console.log("xhr", xhr);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
$(".open_edit").click((event) => {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
$(".hide_on_edit").hide();
|
$(".hide_on_edit").hide();
|
||||||
$(".show_on_edit").show();
|
$(".show_on_edit").show();
|
||||||
|
@ -229,17 +267,17 @@ $(document).ready(function(){
|
||||||
|
|
||||||
$(".topic_item .submit_edit").click(function(event){
|
$(".topic_item .submit_edit").click(function(event){
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
//console.log("clicked on .topic_item .submit_edit");
|
let topicNameInput = $(".topic_name_input").val();
|
||||||
$(".topic_name").html($(".topic_name_input").val());
|
$(".topic_name").html(topicNameInput);
|
||||||
$(".topic_content").html($(".topic_content_input").val());
|
$(".topic_name").attr(topicNameInput);
|
||||||
$(".topic_status_e:not(.open_edit)").html($(".topic_status_input").val());
|
let topicContentInput = $('.topic_content_input').val();
|
||||||
|
$(".topic_content").html(topicContentInput.replace(/(\n)+/g,"<br />"));
|
||||||
|
let topicStatusInput = $('.topic_status_input').val();
|
||||||
|
$(".topic_status_e:not(.open_edit)").html(topicStatusInput);
|
||||||
|
|
||||||
$(".hide_on_edit").show();
|
$(".hide_on_edit").show();
|
||||||
$(".show_on_edit").hide();
|
$(".show_on_edit").hide();
|
||||||
|
|
||||||
let topicNameInput = $('.topic_name_input').val();
|
|
||||||
let topicStatusInput = $('.topic_status_input').val();
|
|
||||||
let topicContentInput = $('.topic_content_input').val();
|
|
||||||
let formAction = this.form.getAttribute("action");
|
let formAction = this.form.getAttribute("action");
|
||||||
//console.log("New Topic Name: ", topicNameInput);
|
//console.log("New Topic Name: ", topicNameInput);
|
||||||
//console.log("New Topic Status: ", topicStatusInput);
|
//console.log("New Topic Status: ", topicStatusInput);
|
||||||
|
@ -284,8 +322,7 @@ $(document).ready(function(){
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
$(".edit_field").click(function(event)
|
$(".edit_field").click(function(event) {
|
||||||
{
|
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
let blockParent = $(this).closest('.editable_parent');
|
let blockParent = $(this).closest('.editable_parent');
|
||||||
let block = blockParent.find('.editable_block').eq(0);
|
let block = blockParent.find('.editable_block').eq(0);
|
||||||
|
@ -395,7 +432,7 @@ $(document).ready(function(){
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
$(this).click(function() {
|
$(this).click(() => {
|
||||||
$(".selectedAlert").removeClass("selectedAlert");
|
$(".selectedAlert").removeClass("selectedAlert");
|
||||||
$("#back").removeClass("alertActive");
|
$("#back").removeClass("alertActive");
|
||||||
});
|
});
|
||||||
|
@ -421,9 +458,7 @@ $(document).ready(function(){
|
||||||
document.getElementById("back").className += " alertActive"
|
document.getElementById("back").className += " alertActive"
|
||||||
});
|
});
|
||||||
|
|
||||||
$("input,textarea,select,option").keyup(function(event){
|
$("input,textarea,select,option").keyup(event => event.stopPropagation())
|
||||||
event.stopPropagation();
|
|
||||||
})
|
|
||||||
|
|
||||||
$(".create_topic_link").click((event) => {
|
$(".create_topic_link").click((event) => {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
|
|
|
@ -1,6 +1,9 @@
|
||||||
package qgen
|
package qgen
|
||||||
|
|
||||||
import "database/sql"
|
import (
|
||||||
|
"database/sql"
|
||||||
|
"strconv"
|
||||||
|
)
|
||||||
|
|
||||||
type accDeleteBuilder struct {
|
type accDeleteBuilder struct {
|
||||||
table string
|
table string
|
||||||
|
@ -10,7 +13,10 @@ type accDeleteBuilder struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (delete *accDeleteBuilder) Where(where string) *accDeleteBuilder {
|
func (delete *accDeleteBuilder) Where(where string) *accDeleteBuilder {
|
||||||
delete.where = where
|
if delete.where != "" {
|
||||||
|
delete.where += " AND "
|
||||||
|
}
|
||||||
|
delete.where += where
|
||||||
return delete
|
return delete
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -32,7 +38,10 @@ func (update *accUpdateBuilder) Set(set string) *accUpdateBuilder {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (update *accUpdateBuilder) Where(where string) *accUpdateBuilder {
|
func (update *accUpdateBuilder) Where(where string) *accUpdateBuilder {
|
||||||
update.where = where
|
if update.where != "" {
|
||||||
|
update.where += " AND "
|
||||||
|
}
|
||||||
|
update.where += where
|
||||||
return update
|
return update
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -59,6 +68,28 @@ func (selectItem *accSelectBuilder) Columns(columns string) *accSelectBuilder {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (selectItem *accSelectBuilder) Where(where string) *accSelectBuilder {
|
func (selectItem *accSelectBuilder) Where(where string) *accSelectBuilder {
|
||||||
|
if selectItem.where != "" {
|
||||||
|
selectItem.where += " AND "
|
||||||
|
}
|
||||||
|
selectItem.where += where
|
||||||
|
return selectItem
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: Don't implement the SQL at the accumulator level but the adapter level
|
||||||
|
func (selectItem *accSelectBuilder) In(column string, inList []int) *accSelectBuilder {
|
||||||
|
if len(inList) == 0 {
|
||||||
|
return selectItem
|
||||||
|
}
|
||||||
|
|
||||||
|
var where = column + " IN("
|
||||||
|
for _, item := range inList {
|
||||||
|
where += strconv.Itoa(item) + ","
|
||||||
|
}
|
||||||
|
where = where[:len(where)-1] + ")"
|
||||||
|
if selectItem.where != "" {
|
||||||
|
where += " AND " + selectItem.where
|
||||||
|
}
|
||||||
|
|
||||||
selectItem.where = where
|
selectItem.where = where
|
||||||
return selectItem
|
return selectItem
|
||||||
}
|
}
|
||||||
|
@ -140,7 +171,10 @@ type accCountBuilder struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (count *accCountBuilder) Where(where string) *accCountBuilder {
|
func (count *accCountBuilder) Where(where string) *accCountBuilder {
|
||||||
count.where = where
|
if count.where != "" {
|
||||||
|
count.where += " AND "
|
||||||
|
}
|
||||||
|
count.where += where
|
||||||
return count
|
return count
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -19,10 +19,25 @@ func (build *builder) Accumulator() *Accumulator {
|
||||||
return &Accumulator{build.conn, build.adapter, nil}
|
return &Accumulator{build.conn, build.adapter, nil}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: Move this method out of builder?
|
||||||
|
func (build *builder) Init(adapter string, config map[string]string) error {
|
||||||
|
err := build.SetAdapter(adapter)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
conn, err := build.adapter.BuildConn(config)
|
||||||
|
build.conn = conn
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
func (build *builder) SetConn(conn *sql.DB) {
|
func (build *builder) SetConn(conn *sql.DB) {
|
||||||
build.conn = conn
|
build.conn = conn
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (build *builder) GetConn() *sql.DB {
|
||||||
|
return build.conn
|
||||||
|
}
|
||||||
|
|
||||||
func (build *builder) SetAdapter(name string) error {
|
func (build *builder) SetAdapter(name string) error {
|
||||||
adap, err := GetAdapter(name)
|
adap, err := GetAdapter(name)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -36,6 +51,11 @@ func (build *builder) GetAdapter() Adapter {
|
||||||
return build.adapter
|
return build.adapter
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (build *builder) DbVersion() (dbVersion string) {
|
||||||
|
build.conn.QueryRow(build.adapter.DbVersion()).Scan(&dbVersion)
|
||||||
|
return dbVersion
|
||||||
|
}
|
||||||
|
|
||||||
func (build *builder) Begin() (*sql.Tx, error) {
|
func (build *builder) Begin() (*sql.Tx, error) {
|
||||||
return build.conn.Begin()
|
return build.conn.Begin()
|
||||||
}
|
}
|
||||||
|
|
|
@ -44,7 +44,10 @@ func (delete *deletePrebuilder) Table(table string) *deletePrebuilder {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (delete *deletePrebuilder) Where(where string) *deletePrebuilder {
|
func (delete *deletePrebuilder) Where(where string) *deletePrebuilder {
|
||||||
delete.where = where
|
if delete.where != "" {
|
||||||
|
delete.where += " AND "
|
||||||
|
}
|
||||||
|
delete.where += where
|
||||||
return delete
|
return delete
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -76,7 +79,10 @@ func (update *updatePrebuilder) Set(set string) *updatePrebuilder {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (update *updatePrebuilder) Where(where string) *updatePrebuilder {
|
func (update *updatePrebuilder) Where(where string) *updatePrebuilder {
|
||||||
update.where = where
|
if update.where != "" {
|
||||||
|
update.where += " AND "
|
||||||
|
}
|
||||||
|
update.where += where
|
||||||
return update
|
return update
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -113,7 +119,10 @@ func (selectItem *selectPrebuilder) Columns(columns string) *selectPrebuilder {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (selectItem *selectPrebuilder) Where(where string) *selectPrebuilder {
|
func (selectItem *selectPrebuilder) Where(where string) *selectPrebuilder {
|
||||||
selectItem.where = where
|
if selectItem.where != "" {
|
||||||
|
selectItem.where += " AND "
|
||||||
|
}
|
||||||
|
selectItem.where += where
|
||||||
return selectItem
|
return selectItem
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -205,7 +214,10 @@ func (count *countPrebuilder) Table(table string) *countPrebuilder {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (count *countPrebuilder) Where(where string) *countPrebuilder {
|
func (count *countPrebuilder) Where(where string) *countPrebuilder {
|
||||||
count.where = where
|
if count.where != "" {
|
||||||
|
count.where += " AND "
|
||||||
|
}
|
||||||
|
count.where += where
|
||||||
return count
|
return count
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
package qgen
|
package qgen
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"database/sql"
|
||||||
"errors"
|
"errors"
|
||||||
"log"
|
"log"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
@ -34,6 +35,15 @@ func (adapter *MssqlAdapter) GetStmts() map[string]DBStmt {
|
||||||
return adapter.Buffer
|
return adapter.Buffer
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: Implement this
|
||||||
|
func (adapter *MssqlAdapter) BuildConn(config map[string]string) (*sql.DB, error) {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (adapter *MssqlAdapter) DbVersion() string {
|
||||||
|
return "SELECT CONCAT(SERVERPROPERTY('productversion'), SERVERPROPERTY ('productlevel'), SERVERPROPERTY ('edition'))"
|
||||||
|
}
|
||||||
|
|
||||||
// TODO: Convert any remaining stringy types to nvarchar
|
// TODO: Convert any remaining stringy types to nvarchar
|
||||||
// We may need to change the CreateTable API to better suit Mssql and the other database drivers which are coming up
|
// We may need to change the CreateTable API to better suit Mssql and the other database drivers which are coming up
|
||||||
func (adapter *MssqlAdapter) CreateTable(name string, table string, charset string, collation string, columns []DBTableColumn, keys []DBTableKey) (string, error) {
|
func (adapter *MssqlAdapter) CreateTable(name string, table string, charset string, collation string, columns []DBTableColumn, keys []DBTableKey) (string, error) {
|
||||||
|
@ -249,7 +259,7 @@ func (adapter *MssqlAdapter) SimpleUpsert(name string, table string, columns str
|
||||||
switch token.Type {
|
switch token.Type {
|
||||||
case "substitute":
|
case "substitute":
|
||||||
querystr += " ?"
|
querystr += " ?"
|
||||||
case "function", "operator", "number":
|
case "function", "operator", "number", "or":
|
||||||
// TODO: Split the function case off to speed things up
|
// TODO: Split the function case off to speed things up
|
||||||
if strings.ToUpper(token.Contents) == "UTC_TIMESTAMP()" {
|
if strings.ToUpper(token.Contents) == "UTC_TIMESTAMP()" {
|
||||||
token.Contents = "GETUTCDATE()"
|
token.Contents = "GETUTCDATE()"
|
||||||
|
@ -314,7 +324,7 @@ func (adapter *MssqlAdapter) SimpleUpdate(name string, table string, set string,
|
||||||
switch token.Type {
|
switch token.Type {
|
||||||
case "substitute":
|
case "substitute":
|
||||||
querystr += " ?"
|
querystr += " ?"
|
||||||
case "function", "operator", "number":
|
case "function", "operator", "number", "or":
|
||||||
// TODO: Split the function case off to speed things up
|
// TODO: Split the function case off to speed things up
|
||||||
if strings.ToUpper(token.Contents) == "UTC_TIMESTAMP()" {
|
if strings.ToUpper(token.Contents) == "UTC_TIMESTAMP()" {
|
||||||
token.Contents = "GETUTCDATE()"
|
token.Contents = "GETUTCDATE()"
|
||||||
|
@ -339,7 +349,7 @@ func (adapter *MssqlAdapter) SimpleUpdate(name string, table string, set string,
|
||||||
for _, loc := range processWhere(where) {
|
for _, loc := range processWhere(where) {
|
||||||
for _, token := range loc.Expr {
|
for _, token := range loc.Expr {
|
||||||
switch token.Type {
|
switch token.Type {
|
||||||
case "function", "operator", "number", "substitute":
|
case "function", "operator", "number", "substitute", "or":
|
||||||
// TODO: Split the function case off to speed things up
|
// TODO: Split the function case off to speed things up
|
||||||
if strings.ToUpper(token.Contents) == "UTC_TIMESTAMP()" {
|
if strings.ToUpper(token.Contents) == "UTC_TIMESTAMP()" {
|
||||||
token.Contents = "GETUTCDATE()"
|
token.Contents = "GETUTCDATE()"
|
||||||
|
@ -381,7 +391,7 @@ func (adapter *MssqlAdapter) SimpleDelete(name string, table string, where strin
|
||||||
switch token.Type {
|
switch token.Type {
|
||||||
case "substitute":
|
case "substitute":
|
||||||
querystr += " ?"
|
querystr += " ?"
|
||||||
case "function", "operator", "number":
|
case "function", "operator", "number", "or":
|
||||||
// TODO: Split the function case off to speed things up
|
// TODO: Split the function case off to speed things up
|
||||||
if strings.ToUpper(token.Contents) == "UTC_TIMESTAMP()" {
|
if strings.ToUpper(token.Contents) == "UTC_TIMESTAMP()" {
|
||||||
token.Contents = "GETUTCDATE()"
|
token.Contents = "GETUTCDATE()"
|
||||||
|
@ -451,7 +461,7 @@ func (adapter *MssqlAdapter) SimpleSelect(name string, table string, columns str
|
||||||
case "substitute":
|
case "substitute":
|
||||||
substituteCount++
|
substituteCount++
|
||||||
querystr += " ?" + strconv.Itoa(substituteCount)
|
querystr += " ?" + strconv.Itoa(substituteCount)
|
||||||
case "function", "operator", "number":
|
case "function", "operator", "number", "or":
|
||||||
// TODO: Split the function case off to speed things up
|
// TODO: Split the function case off to speed things up
|
||||||
// MSSQL seems to convert the formats? so we'll compare it with a regular date. Do this with the other methods too?
|
// MSSQL seems to convert the formats? so we'll compare it with a regular date. Do this with the other methods too?
|
||||||
if strings.ToUpper(token.Contents) == "UTC_TIMESTAMP()" {
|
if strings.ToUpper(token.Contents) == "UTC_TIMESTAMP()" {
|
||||||
|
@ -576,7 +586,7 @@ func (adapter *MssqlAdapter) SimpleLeftJoin(name string, table1 string, table2 s
|
||||||
case "substitute":
|
case "substitute":
|
||||||
substituteCount++
|
substituteCount++
|
||||||
querystr += " ?" + strconv.Itoa(substituteCount)
|
querystr += " ?" + strconv.Itoa(substituteCount)
|
||||||
case "function", "operator", "number":
|
case "function", "operator", "number", "or":
|
||||||
// TODO: Split the function case off to speed things up
|
// TODO: Split the function case off to speed things up
|
||||||
if strings.ToUpper(token.Contents) == "UTC_TIMESTAMP()" {
|
if strings.ToUpper(token.Contents) == "UTC_TIMESTAMP()" {
|
||||||
token.Contents = "GETUTCDATE()"
|
token.Contents = "GETUTCDATE()"
|
||||||
|
@ -706,7 +716,7 @@ func (adapter *MssqlAdapter) SimpleInnerJoin(name string, table1 string, table2
|
||||||
case "substitute":
|
case "substitute":
|
||||||
substituteCount++
|
substituteCount++
|
||||||
querystr += " ?" + strconv.Itoa(substituteCount)
|
querystr += " ?" + strconv.Itoa(substituteCount)
|
||||||
case "function", "operator", "number":
|
case "function", "operator", "number", "or":
|
||||||
// TODO: Split the function case off to speed things up
|
// TODO: Split the function case off to speed things up
|
||||||
if strings.ToUpper(token.Contents) == "UTC_TIMESTAMP()" {
|
if strings.ToUpper(token.Contents) == "UTC_TIMESTAMP()" {
|
||||||
token.Contents = "GETUTCDATE()"
|
token.Contents = "GETUTCDATE()"
|
||||||
|
@ -827,7 +837,7 @@ func (adapter *MssqlAdapter) SimpleInsertSelect(name string, ins DBInsert, sel D
|
||||||
case "substitute":
|
case "substitute":
|
||||||
substituteCount++
|
substituteCount++
|
||||||
querystr += " ?" + strconv.Itoa(substituteCount)
|
querystr += " ?" + strconv.Itoa(substituteCount)
|
||||||
case "function", "operator", "number":
|
case "function", "operator", "number", "or":
|
||||||
// TODO: Split the function case off to speed things up
|
// TODO: Split the function case off to speed things up
|
||||||
if strings.ToUpper(token.Contents) == "UTC_TIMESTAMP()" {
|
if strings.ToUpper(token.Contents) == "UTC_TIMESTAMP()" {
|
||||||
token.Contents = "GETUTCDATE()"
|
token.Contents = "GETUTCDATE()"
|
||||||
|
@ -951,7 +961,7 @@ func (adapter *MssqlAdapter) simpleJoin(name string, ins DBInsert, sel DBJoin, j
|
||||||
case "substitute":
|
case "substitute":
|
||||||
substituteCount++
|
substituteCount++
|
||||||
querystr += " ?" + strconv.Itoa(substituteCount)
|
querystr += " ?" + strconv.Itoa(substituteCount)
|
||||||
case "function", "operator", "number":
|
case "function", "operator", "number", "or":
|
||||||
// TODO: Split the function case off to speed things up
|
// TODO: Split the function case off to speed things up
|
||||||
if strings.ToUpper(token.Contents) == "UTC_TIMESTAMP()" {
|
if strings.ToUpper(token.Contents) == "UTC_TIMESTAMP()" {
|
||||||
token.Contents = "GETUTCDATE()"
|
token.Contents = "GETUTCDATE()"
|
||||||
|
@ -1046,7 +1056,7 @@ func (adapter *MssqlAdapter) SimpleCount(name string, table string, where string
|
||||||
for _, loc := range processWhere(where) {
|
for _, loc := range processWhere(where) {
|
||||||
for _, token := range loc.Expr {
|
for _, token := range loc.Expr {
|
||||||
switch token.Type {
|
switch token.Type {
|
||||||
case "function", "operator", "number", "substitute":
|
case "function", "operator", "number", "substitute", "or":
|
||||||
if strings.ToUpper(token.Contents) == "UTC_TIMESTAMP()" {
|
if strings.ToUpper(token.Contents) == "UTC_TIMESTAMP()" {
|
||||||
token.Contents = "GETUTCDATE()"
|
token.Contents = "GETUTCDATE()"
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,13 +1,17 @@
|
||||||
/* WIP Under Construction */
|
/* WIP Under Construction */
|
||||||
package qgen
|
package qgen
|
||||||
|
|
||||||
//import "fmt"
|
|
||||||
import (
|
import (
|
||||||
|
"database/sql"
|
||||||
"errors"
|
"errors"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
_ "github.com/go-sql-driver/mysql"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
var ErrNoCollation = errors.New("You didn't provide a collation")
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
Registry = append(Registry,
|
Registry = append(Registry,
|
||||||
&MysqlAdapter{Name: "mysql", Buffer: make(map[string]DBStmt)},
|
&MysqlAdapter{Name: "mysql", Buffer: make(map[string]DBStmt)},
|
||||||
|
@ -33,6 +37,30 @@ func (adapter *MysqlAdapter) GetStmts() map[string]DBStmt {
|
||||||
return adapter.Buffer
|
return adapter.Buffer
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (adapter *MysqlAdapter) BuildConn(config map[string]string) (*sql.DB, error) {
|
||||||
|
dbCollation, ok := config["collation"]
|
||||||
|
if !ok {
|
||||||
|
return nil, ErrNoCollation
|
||||||
|
}
|
||||||
|
var dbpassword string
|
||||||
|
if config["password"] != "" {
|
||||||
|
dbpassword = ":" + config["password"]
|
||||||
|
}
|
||||||
|
|
||||||
|
// Open the database connection
|
||||||
|
db, err := sql.Open("mysql", config["username"]+dbpassword+"@tcp("+config["host"]+":"+config["port"]+")/"+config["name"]+"?collation="+dbCollation+"&parseTime=true")
|
||||||
|
if err != nil {
|
||||||
|
return db, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Make sure that the connection is alive
|
||||||
|
return db, db.Ping()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (adapter *MysqlAdapter) DbVersion() string {
|
||||||
|
return "SELECT VERSION()"
|
||||||
|
}
|
||||||
|
|
||||||
func (adapter *MysqlAdapter) CreateTable(name string, table string, charset string, collation string, columns []DBTableColumn, keys []DBTableKey) (string, error) {
|
func (adapter *MysqlAdapter) CreateTable(name string, table string, charset string, collation string, columns []DBTableColumn, keys []DBTableKey) (string, error) {
|
||||||
if name == "" {
|
if name == "" {
|
||||||
return "", errors.New("You need a name for this statement")
|
return "", errors.New("You need a name for this statement")
|
||||||
|
@ -239,7 +267,7 @@ func (adapter *MysqlAdapter) SimpleUpdate(name string, table string, set string,
|
||||||
querystr += "`" + item.Column + "` ="
|
querystr += "`" + item.Column + "` ="
|
||||||
for _, token := range item.Expr {
|
for _, token := range item.Expr {
|
||||||
switch token.Type {
|
switch token.Type {
|
||||||
case "function", "operator", "number", "substitute":
|
case "function", "operator", "number", "substitute", "or":
|
||||||
querystr += " " + token.Contents
|
querystr += " " + token.Contents
|
||||||
case "column":
|
case "column":
|
||||||
querystr += " `" + token.Contents + "`"
|
querystr += " `" + token.Contents + "`"
|
||||||
|
@ -278,7 +306,7 @@ func (adapter *MysqlAdapter) SimpleDelete(name string, table string, where strin
|
||||||
for _, loc := range processWhere(where) {
|
for _, loc := range processWhere(where) {
|
||||||
for _, token := range loc.Expr {
|
for _, token := range loc.Expr {
|
||||||
switch token.Type {
|
switch token.Type {
|
||||||
case "function", "operator", "number", "substitute":
|
case "function", "operator", "number", "substitute", "or":
|
||||||
querystr += " " + token.Contents
|
querystr += " " + token.Contents
|
||||||
case "column":
|
case "column":
|
||||||
querystr += " `" + token.Contents + "`"
|
querystr += " `" + token.Contents + "`"
|
||||||
|
@ -316,7 +344,7 @@ func (adapter *MysqlAdapter) buildWhere(where string) (querystr string, err erro
|
||||||
for _, loc := range processWhere(where) {
|
for _, loc := range processWhere(where) {
|
||||||
for _, token := range loc.Expr {
|
for _, token := range loc.Expr {
|
||||||
switch token.Type {
|
switch token.Type {
|
||||||
case "function", "operator", "number", "substitute":
|
case "function", "operator", "number", "substitute", "or":
|
||||||
querystr += " " + token.Contents
|
querystr += " " + token.Contents
|
||||||
case "column":
|
case "column":
|
||||||
querystr += " `" + token.Contents + "`"
|
querystr += " `" + token.Contents + "`"
|
||||||
|
@ -344,7 +372,7 @@ func (adapter *MysqlAdapter) buildFlexiWhere(where string, dateCutoff *dateCutof
|
||||||
for _, loc := range processWhere(where) {
|
for _, loc := range processWhere(where) {
|
||||||
for _, token := range loc.Expr {
|
for _, token := range loc.Expr {
|
||||||
switch token.Type {
|
switch token.Type {
|
||||||
case "function", "operator", "number", "substitute":
|
case "function", "operator", "number", "substitute", "or":
|
||||||
querystr += " " + token.Contents
|
querystr += " " + token.Contents
|
||||||
case "column":
|
case "column":
|
||||||
querystr += " `" + token.Contents + "`"
|
querystr += " `" + token.Contents + "`"
|
||||||
|
@ -544,7 +572,7 @@ func (adapter *MysqlAdapter) buildJoinWhere(where string) (querystr string, err
|
||||||
for _, loc := range processWhere(where) {
|
for _, loc := range processWhere(where) {
|
||||||
for _, token := range loc.Expr {
|
for _, token := range loc.Expr {
|
||||||
switch token.Type {
|
switch token.Type {
|
||||||
case "function", "operator", "number", "substitute":
|
case "function", "operator", "number", "substitute", "or":
|
||||||
querystr += " " + token.Contents
|
querystr += " " + token.Contents
|
||||||
case "column":
|
case "column":
|
||||||
halves := strings.Split(token.Contents, ".")
|
halves := strings.Split(token.Contents, ".")
|
||||||
|
|
|
@ -1,9 +1,12 @@
|
||||||
/* WIP Under Really Heavy Construction */
|
/* WIP Under Really Heavy Construction */
|
||||||
package qgen
|
package qgen
|
||||||
|
|
||||||
import "strings"
|
import (
|
||||||
import "strconv"
|
"database/sql"
|
||||||
import "errors"
|
"errors"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
Registry = append(Registry,
|
Registry = append(Registry,
|
||||||
|
@ -30,6 +33,16 @@ func (adapter *PgsqlAdapter) GetStmts() map[string]DBStmt {
|
||||||
return adapter.Buffer
|
return adapter.Buffer
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: Implement this
|
||||||
|
func (adapter *PgsqlAdapter) BuildConn(config map[string]string) (*sql.DB, error) {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: Implement this
|
||||||
|
func (adapter *PgsqlAdapter) DbVersion() string {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
// TODO: Implement this
|
// TODO: Implement this
|
||||||
// We may need to change the CreateTable API to better suit PGSQL and the other database drivers which are coming up
|
// We may need to change the CreateTable API to better suit PGSQL and the other database drivers which are coming up
|
||||||
func (adapter *PgsqlAdapter) CreateTable(name string, table string, charset string, collation string, columns []DBTableColumn, keys []DBTableKey) (string, error) {
|
func (adapter *PgsqlAdapter) CreateTable(name string, table string, charset string, collation string, columns []DBTableColumn, keys []DBTableKey) (string, error) {
|
||||||
|
@ -167,7 +180,7 @@ func (adapter *PgsqlAdapter) SimpleUpdate(name string, table string, set string,
|
||||||
token.Contents = "LOCALTIMESTAMP()"
|
token.Contents = "LOCALTIMESTAMP()"
|
||||||
}
|
}
|
||||||
querystr += " " + token.Contents
|
querystr += " " + token.Contents
|
||||||
case "operator", "number", "substitute":
|
case "operator", "number", "substitute", "or":
|
||||||
querystr += " " + token.Contents
|
querystr += " " + token.Contents
|
||||||
case "column":
|
case "column":
|
||||||
querystr += " `" + token.Contents + "`"
|
querystr += " `" + token.Contents + "`"
|
||||||
|
@ -193,7 +206,7 @@ func (adapter *PgsqlAdapter) SimpleUpdate(name string, table string, set string,
|
||||||
token.Contents = "LOCALTIMESTAMP()"
|
token.Contents = "LOCALTIMESTAMP()"
|
||||||
}
|
}
|
||||||
querystr += " " + token.Contents
|
querystr += " " + token.Contents
|
||||||
case "operator", "number", "substitute":
|
case "operator", "number", "substitute", "or":
|
||||||
querystr += " " + token.Contents
|
querystr += " " + token.Contents
|
||||||
case "column":
|
case "column":
|
||||||
querystr += " `" + token.Contents + "`"
|
querystr += " `" + token.Contents + "`"
|
||||||
|
|
|
@ -98,6 +98,9 @@ type DBStmt struct {
|
||||||
|
|
||||||
type Adapter interface {
|
type Adapter interface {
|
||||||
GetName() string
|
GetName() string
|
||||||
|
BuildConn(config map[string]string) (*sql.DB, error)
|
||||||
|
DbVersion() string
|
||||||
|
|
||||||
CreateTable(name string, table string, charset string, collation string, columns []DBTableColumn, keys []DBTableKey) (string, error)
|
CreateTable(name string, table string, charset string, collation string, columns []DBTableColumn, keys []DBTableKey) (string, error)
|
||||||
SimpleInsert(name string, table string, columns string, fields string) (string, error)
|
SimpleInsert(name string, table string, columns string, fields string) (string, error)
|
||||||
SimpleUpdate(name string, table string, set string, where string) (string, error)
|
SimpleUpdate(name string, table string, set string, where string) (string, error)
|
||||||
|
|
|
@ -166,7 +166,12 @@ func (where *DBWhere) parseOperator(segment string, i int) int {
|
||||||
|
|
||||||
// TODO: Make this case insensitive
|
// TODO: Make this case insensitive
|
||||||
func normalizeAnd(in string) string {
|
func normalizeAnd(in string) string {
|
||||||
return strings.Replace(in, " and ", " AND ", -1)
|
in = strings.Replace(in, " and ", " AND ", -1)
|
||||||
|
return strings.Replace(in, " && ", " AND ", -1)
|
||||||
|
}
|
||||||
|
func normalizeOr(in string) string {
|
||||||
|
in = strings.Replace(in, " or ", " OR ", -1)
|
||||||
|
return strings.Replace(in, " || ", " OR ", -1)
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Write tests for this
|
// TODO: Write tests for this
|
||||||
|
@ -175,6 +180,7 @@ func processWhere(wherestr string) (where []DBWhere) {
|
||||||
return where
|
return where
|
||||||
}
|
}
|
||||||
wherestr = normalizeAnd(wherestr)
|
wherestr = normalizeAnd(wherestr)
|
||||||
|
wherestr = normalizeOr(wherestr)
|
||||||
|
|
||||||
for _, segment := range strings.Split(wherestr, " AND ") {
|
for _, segment := range strings.Split(wherestr, " AND ") {
|
||||||
var tmpWhere = &DBWhere{[]DBToken{}}
|
var tmpWhere = &DBWhere{[]DBToken{}}
|
||||||
|
@ -184,10 +190,16 @@ func processWhere(wherestr string) (where []DBWhere) {
|
||||||
switch {
|
switch {
|
||||||
case '0' <= char && char <= '9':
|
case '0' <= char && char <= '9':
|
||||||
i = tmpWhere.parseNumber(segment, i)
|
i = tmpWhere.parseNumber(segment, i)
|
||||||
|
// TODO: Sniff the third byte offset from char or it's non-existent to avoid matching uppercase strings which start with OR
|
||||||
|
case char == 'O' && (i+1) < len(segment) && segment[i+1] == 'R':
|
||||||
|
tmpWhere.Expr = append(tmpWhere.Expr, DBToken{"OR", "or"})
|
||||||
|
i += 1
|
||||||
case ('a' <= char && char <= 'z') || ('A' <= char && char <= 'Z') || char == '_':
|
case ('a' <= char && char <= 'z') || ('A' <= char && char <= 'Z') || char == '_':
|
||||||
i = tmpWhere.parseColumn(segment, i)
|
i = tmpWhere.parseColumn(segment, i)
|
||||||
case char == '\'':
|
case char == '\'':
|
||||||
i = tmpWhere.parseString(segment, i)
|
i = tmpWhere.parseString(segment, i)
|
||||||
|
case char == ')' && i < (len(segment)-1):
|
||||||
|
tmpWhere.Expr = append(tmpWhere.Expr, DBToken{")", "operator"})
|
||||||
case isOpByte(char):
|
case isOpByte(char):
|
||||||
i = tmpWhere.parseOperator(segment, i)
|
i = tmpWhere.parseOperator(segment, i)
|
||||||
case char == '?':
|
case char == '?':
|
||||||
|
@ -335,11 +347,11 @@ func processLimit(limitstr string) (limiter DBLimit) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func isOpByte(char byte) bool {
|
func isOpByte(char byte) bool {
|
||||||
return char == '<' || char == '>' || char == '=' || char == '!' || char == '*' || char == '%' || char == '+' || char == '-' || char == '/'
|
return char == '<' || char == '>' || char == '=' || char == '!' || char == '*' || char == '%' || char == '+' || char == '-' || char == '/' || char == '(' || char == ')'
|
||||||
}
|
}
|
||||||
|
|
||||||
func isOpRune(char rune) bool {
|
func isOpRune(char rune) bool {
|
||||||
return char == '<' || char == '>' || char == '=' || char == '!' || char == '*' || char == '%' || char == '+' || char == '-' || char == '/'
|
return char == '<' || char == '>' || char == '=' || char == '!' || char == '*' || char == '%' || char == '+' || char == '-' || char == '/' || char == '(' || char == ')'
|
||||||
}
|
}
|
||||||
|
|
||||||
func processFields(fieldstr string) (fields []DBField) {
|
func processFields(fieldstr string) (fields []DBField) {
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
/* WIP Under Construction */
|
|
||||||
package main
|
package main
|
||||||
|
|
||||||
import "./lib"
|
import "./lib"
|
||||||
|
@ -11,7 +10,7 @@ func createTables(adapter qgen.Adapter) error {
|
||||||
qgen.DBTableColumn{"password", "varchar", 100, false, false, ""},
|
qgen.DBTableColumn{"password", "varchar", 100, false, false, ""},
|
||||||
|
|
||||||
qgen.DBTableColumn{"salt", "varchar", 80, false, false, "''"},
|
qgen.DBTableColumn{"salt", "varchar", 80, false, false, "''"},
|
||||||
qgen.DBTableColumn{"group", "int", 0, false, false, ""},
|
qgen.DBTableColumn{"group", "int", 0, false, false, ""}, // TODO: Make this a foreign key
|
||||||
qgen.DBTableColumn{"active", "boolean", 0, false, false, "0"},
|
qgen.DBTableColumn{"active", "boolean", 0, false, false, "0"},
|
||||||
qgen.DBTableColumn{"is_super_admin", "boolean", 0, false, false, "0"},
|
qgen.DBTableColumn{"is_super_admin", "boolean", 0, false, false, "0"},
|
||||||
qgen.DBTableColumn{"createdAt", "createdAt", 0, false, false, ""},
|
qgen.DBTableColumn{"createdAt", "createdAt", 0, false, false, ""},
|
||||||
|
@ -30,6 +29,12 @@ func createTables(adapter qgen.Adapter) error {
|
||||||
qgen.DBTableColumn{"bigposts", "int", 0, false, false, "0"},
|
qgen.DBTableColumn{"bigposts", "int", 0, false, false, "0"},
|
||||||
qgen.DBTableColumn{"megaposts", "int", 0, false, false, "0"},
|
qgen.DBTableColumn{"megaposts", "int", 0, false, false, "0"},
|
||||||
qgen.DBTableColumn{"topics", "int", 0, false, false, "0"},
|
qgen.DBTableColumn{"topics", "int", 0, false, false, "0"},
|
||||||
|
qgen.DBTableColumn{"liked", "int", 0, false, false, "0"},
|
||||||
|
|
||||||
|
// These two are to bound liked queries with little bits of information we know about the user to reduce the server load
|
||||||
|
qgen.DBTableColumn{"oldestItemLikedCreatedAt", "datetime", 0, false, false, ""}, // For internal use only, semantics may change
|
||||||
|
qgen.DBTableColumn{"lastLiked", "datetime", 0, false, false, ""}, // For internal use only, semantics may change
|
||||||
|
|
||||||
//qgen.DBTableColumn{"penalty_count","int",0,false,false,"0"},
|
//qgen.DBTableColumn{"penalty_count","int",0,false,false,"0"},
|
||||||
qgen.DBTableColumn{"temp_group", "int", 0, false, false, "0"}, // For temporary groups, set this to zero when a temporary group isn't in effect
|
qgen.DBTableColumn{"temp_group", "int", 0, false, false, "0"}, // For temporary groups, set this to zero when a temporary group isn't in effect
|
||||||
},
|
},
|
||||||
|
@ -106,7 +111,7 @@ func createTables(adapter qgen.Adapter) error {
|
||||||
qgen.Install.CreateTable("emails", "", "",
|
qgen.Install.CreateTable("emails", "", "",
|
||||||
[]qgen.DBTableColumn{
|
[]qgen.DBTableColumn{
|
||||||
qgen.DBTableColumn{"email", "varchar", 200, false, false, ""},
|
qgen.DBTableColumn{"email", "varchar", 200, false, false, ""},
|
||||||
qgen.DBTableColumn{"uid", "int", 0, false, false, ""},
|
qgen.DBTableColumn{"uid", "int", 0, false, false, ""}, // TODO: Make this a foreign key
|
||||||
qgen.DBTableColumn{"validated", "boolean", 0, false, false, "0"},
|
qgen.DBTableColumn{"validated", "boolean", 0, false, false, "0"},
|
||||||
qgen.DBTableColumn{"token", "varchar", 200, false, false, "''"},
|
qgen.DBTableColumn{"token", "varchar", 200, false, false, "''"},
|
||||||
},
|
},
|
||||||
|
@ -153,7 +158,7 @@ func createTables(adapter qgen.Adapter) error {
|
||||||
qgen.DBTableColumn{"createdAt", "createdAt", 0, false, false, ""},
|
qgen.DBTableColumn{"createdAt", "createdAt", 0, false, false, ""},
|
||||||
qgen.DBTableColumn{"lastReplyAt", "datetime", 0, false, false, ""},
|
qgen.DBTableColumn{"lastReplyAt", "datetime", 0, false, false, ""},
|
||||||
qgen.DBTableColumn{"lastReplyBy", "int", 0, false, false, ""},
|
qgen.DBTableColumn{"lastReplyBy", "int", 0, false, false, ""},
|
||||||
qgen.DBTableColumn{"createdBy", "int", 0, false, false, ""},
|
qgen.DBTableColumn{"createdBy", "int", 0, false, false, ""}, // TODO: Make this a foreign key
|
||||||
qgen.DBTableColumn{"is_closed", "boolean", 0, false, false, "0"},
|
qgen.DBTableColumn{"is_closed", "boolean", 0, false, false, "0"},
|
||||||
qgen.DBTableColumn{"sticky", "boolean", 0, false, false, "0"},
|
qgen.DBTableColumn{"sticky", "boolean", 0, false, false, "0"},
|
||||||
qgen.DBTableColumn{"parentID", "int", 0, false, false, "2"},
|
qgen.DBTableColumn{"parentID", "int", 0, false, false, "2"},
|
||||||
|
@ -178,7 +183,7 @@ func createTables(adapter qgen.Adapter) error {
|
||||||
qgen.DBTableColumn{"content", "text", 0, false, false, ""},
|
qgen.DBTableColumn{"content", "text", 0, false, false, ""},
|
||||||
qgen.DBTableColumn{"parsed_content", "text", 0, false, false, ""},
|
qgen.DBTableColumn{"parsed_content", "text", 0, false, false, ""},
|
||||||
qgen.DBTableColumn{"createdAt", "createdAt", 0, false, false, ""},
|
qgen.DBTableColumn{"createdAt", "createdAt", 0, false, false, ""},
|
||||||
qgen.DBTableColumn{"createdBy", "int", 0, false, false, ""},
|
qgen.DBTableColumn{"createdBy", "int", 0, false, false, ""}, // TODO: Make this a foreign key
|
||||||
qgen.DBTableColumn{"lastEdit", "int", 0, false, false, "0"},
|
qgen.DBTableColumn{"lastEdit", "int", 0, false, false, "0"},
|
||||||
qgen.DBTableColumn{"lastEditBy", "int", 0, false, false, "0"},
|
qgen.DBTableColumn{"lastEditBy", "int", 0, false, false, "0"},
|
||||||
qgen.DBTableColumn{"lastUpdated", "datetime", 0, false, false, ""},
|
qgen.DBTableColumn{"lastUpdated", "datetime", 0, false, false, ""},
|
||||||
|
@ -200,7 +205,7 @@ func createTables(adapter qgen.Adapter) error {
|
||||||
qgen.DBTableColumn{"sectionTable", "varchar", 200, false, false, "forums"},
|
qgen.DBTableColumn{"sectionTable", "varchar", 200, false, false, "forums"},
|
||||||
qgen.DBTableColumn{"originID", "int", 0, false, false, ""},
|
qgen.DBTableColumn{"originID", "int", 0, false, false, ""},
|
||||||
qgen.DBTableColumn{"originTable", "varchar", 200, false, false, "replies"},
|
qgen.DBTableColumn{"originTable", "varchar", 200, false, false, "replies"},
|
||||||
qgen.DBTableColumn{"uploadedBy", "int", 0, false, false, ""},
|
qgen.DBTableColumn{"uploadedBy", "int", 0, false, false, ""}, // TODO; Make this a foreign key
|
||||||
qgen.DBTableColumn{"path", "varchar", 200, false, false, ""},
|
qgen.DBTableColumn{"path", "varchar", 200, false, false, ""},
|
||||||
},
|
},
|
||||||
[]qgen.DBTableKey{
|
[]qgen.DBTableKey{
|
||||||
|
@ -215,6 +220,7 @@ func createTables(adapter qgen.Adapter) error {
|
||||||
qgen.DBTableColumn{"contentID", "int", 0, false, false, ""},
|
qgen.DBTableColumn{"contentID", "int", 0, false, false, ""},
|
||||||
qgen.DBTableColumn{"contentType", "varchar", 100, false, false, "replies"},
|
qgen.DBTableColumn{"contentType", "varchar", 100, false, false, "replies"},
|
||||||
qgen.DBTableColumn{"createdAt", "createdAt", 0, false, false, ""},
|
qgen.DBTableColumn{"createdAt", "createdAt", 0, false, false, ""},
|
||||||
|
// TODO: Add a createdBy column?
|
||||||
},
|
},
|
||||||
[]qgen.DBTableKey{
|
[]qgen.DBTableKey{
|
||||||
qgen.DBTableKey{"reviseID", "primary"},
|
qgen.DBTableKey{"reviseID", "primary"},
|
||||||
|
@ -247,7 +253,7 @@ func createTables(adapter qgen.Adapter) error {
|
||||||
qgen.Install.CreateTable("polls_votes", "utf8mb4", "utf8mb4_general_ci",
|
qgen.Install.CreateTable("polls_votes", "utf8mb4", "utf8mb4_general_ci",
|
||||||
[]qgen.DBTableColumn{
|
[]qgen.DBTableColumn{
|
||||||
qgen.DBTableColumn{"pollID", "int", 0, false, false, ""},
|
qgen.DBTableColumn{"pollID", "int", 0, false, false, ""},
|
||||||
qgen.DBTableColumn{"uid", "int", 0, false, false, ""},
|
qgen.DBTableColumn{"uid", "int", 0, false, false, ""}, // TODO: Make this a foreign key
|
||||||
qgen.DBTableColumn{"option", "int", 0, false, false, "0"},
|
qgen.DBTableColumn{"option", "int", 0, false, false, "0"},
|
||||||
qgen.DBTableColumn{"castAt", "createdAt", 0, false, false, ""},
|
qgen.DBTableColumn{"castAt", "createdAt", 0, false, false, ""},
|
||||||
qgen.DBTableColumn{"ipaddress", "varchar", 200, false, false, "0.0.0.0.0"},
|
qgen.DBTableColumn{"ipaddress", "varchar", 200, false, false, "0.0.0.0.0"},
|
||||||
|
@ -258,11 +264,11 @@ func createTables(adapter qgen.Adapter) error {
|
||||||
qgen.Install.CreateTable("users_replies", "utf8mb4", "utf8mb4_general_ci",
|
qgen.Install.CreateTable("users_replies", "utf8mb4", "utf8mb4_general_ci",
|
||||||
[]qgen.DBTableColumn{
|
[]qgen.DBTableColumn{
|
||||||
qgen.DBTableColumn{"rid", "int", 0, false, true, ""},
|
qgen.DBTableColumn{"rid", "int", 0, false, true, ""},
|
||||||
qgen.DBTableColumn{"uid", "int", 0, false, false, ""},
|
qgen.DBTableColumn{"uid", "int", 0, false, false, ""}, // TODO: Make this a foreign key
|
||||||
qgen.DBTableColumn{"content", "text", 0, false, false, ""},
|
qgen.DBTableColumn{"content", "text", 0, false, false, ""},
|
||||||
qgen.DBTableColumn{"parsed_content", "text", 0, false, false, ""},
|
qgen.DBTableColumn{"parsed_content", "text", 0, false, false, ""},
|
||||||
qgen.DBTableColumn{"createdAt", "createdAt", 0, false, false, ""},
|
qgen.DBTableColumn{"createdAt", "createdAt", 0, false, false, ""},
|
||||||
qgen.DBTableColumn{"createdBy", "int", 0, false, false, ""},
|
qgen.DBTableColumn{"createdBy", "int", 0, false, false, ""}, // TODO: Make this a foreign key
|
||||||
qgen.DBTableColumn{"lastEdit", "int", 0, false, false, ""},
|
qgen.DBTableColumn{"lastEdit", "int", 0, false, false, ""},
|
||||||
qgen.DBTableColumn{"lastEditBy", "int", 0, false, false, ""},
|
qgen.DBTableColumn{"lastEditBy", "int", 0, false, false, ""},
|
||||||
qgen.DBTableColumn{"ipaddress", "varchar", 200, false, false, "0.0.0.0.0"},
|
qgen.DBTableColumn{"ipaddress", "varchar", 200, false, false, "0.0.0.0.0"},
|
||||||
|
@ -277,7 +283,8 @@ func createTables(adapter qgen.Adapter) error {
|
||||||
qgen.DBTableColumn{"weight", "tinyint", 0, false, false, "1"},
|
qgen.DBTableColumn{"weight", "tinyint", 0, false, false, "1"},
|
||||||
qgen.DBTableColumn{"targetItem", "int", 0, false, false, ""},
|
qgen.DBTableColumn{"targetItem", "int", 0, false, false, ""},
|
||||||
qgen.DBTableColumn{"targetType", "varchar", 50, false, false, "replies"},
|
qgen.DBTableColumn{"targetType", "varchar", 50, false, false, "replies"},
|
||||||
qgen.DBTableColumn{"sentBy", "int", 0, false, false, ""},
|
qgen.DBTableColumn{"sentBy", "int", 0, false, false, ""}, // TODO: Make this a foreign key
|
||||||
|
qgen.DBTableColumn{"createdAt", "createdAt", 0, false, false, ""},
|
||||||
qgen.DBTableColumn{"recalc", "tinyint", 0, false, false, "0"},
|
qgen.DBTableColumn{"recalc", "tinyint", 0, false, false, "0"},
|
||||||
},
|
},
|
||||||
[]qgen.DBTableKey{},
|
[]qgen.DBTableKey{},
|
||||||
|
@ -285,8 +292,8 @@ func createTables(adapter qgen.Adapter) error {
|
||||||
|
|
||||||
qgen.Install.CreateTable("activity_stream_matches", "", "",
|
qgen.Install.CreateTable("activity_stream_matches", "", "",
|
||||||
[]qgen.DBTableColumn{
|
[]qgen.DBTableColumn{
|
||||||
qgen.DBTableColumn{"watcher", "int", 0, false, false, ""},
|
qgen.DBTableColumn{"watcher", "int", 0, false, false, ""}, // TODO: Make this a foreign key
|
||||||
qgen.DBTableColumn{"asid", "int", 0, false, false, ""},
|
qgen.DBTableColumn{"asid", "int", 0, false, false, ""}, // TODO: Make this a foreign key
|
||||||
},
|
},
|
||||||
[]qgen.DBTableKey{},
|
[]qgen.DBTableKey{},
|
||||||
)
|
)
|
||||||
|
@ -294,7 +301,7 @@ func createTables(adapter qgen.Adapter) error {
|
||||||
qgen.Install.CreateTable("activity_stream", "", "",
|
qgen.Install.CreateTable("activity_stream", "", "",
|
||||||
[]qgen.DBTableColumn{
|
[]qgen.DBTableColumn{
|
||||||
qgen.DBTableColumn{"asid", "int", 0, false, true, ""},
|
qgen.DBTableColumn{"asid", "int", 0, false, true, ""},
|
||||||
qgen.DBTableColumn{"actor", "int", 0, false, false, ""}, /* the one doing the act */
|
qgen.DBTableColumn{"actor", "int", 0, false, false, ""}, /* the one doing the act */ // TODO: Make this a foreign key
|
||||||
qgen.DBTableColumn{"targetUser", "int", 0, false, false, ""}, /* the user who created the item the actor is acting on, some items like forums may lack a targetUser field */
|
qgen.DBTableColumn{"targetUser", "int", 0, false, false, ""}, /* the user who created the item the actor is acting on, some items like forums may lack a targetUser field */
|
||||||
qgen.DBTableColumn{"event", "varchar", 50, false, false, ""}, /* mention, like, reply (as in the act of replying to an item, not the reply item type, you can "reply" to a forum by making a topic in it), friend_invite */
|
qgen.DBTableColumn{"event", "varchar", 50, false, false, ""}, /* mention, like, reply (as in the act of replying to an item, not the reply item type, you can "reply" to a forum by making a topic in it), friend_invite */
|
||||||
qgen.DBTableColumn{"elementType", "varchar", 50, false, false, ""}, /* topic, post (calling it post here to differentiate it from the 'reply' event), forum, user */
|
qgen.DBTableColumn{"elementType", "varchar", 50, false, false, ""}, /* topic, post (calling it post here to differentiate it from the 'reply' event), forum, user */
|
||||||
|
@ -307,7 +314,7 @@ func createTables(adapter qgen.Adapter) error {
|
||||||
|
|
||||||
qgen.Install.CreateTable("activity_subscriptions", "", "",
|
qgen.Install.CreateTable("activity_subscriptions", "", "",
|
||||||
[]qgen.DBTableColumn{
|
[]qgen.DBTableColumn{
|
||||||
qgen.DBTableColumn{"user", "int", 0, false, false, ""},
|
qgen.DBTableColumn{"user", "int", 0, false, false, ""}, // TODO: Make this a foreign key
|
||||||
qgen.DBTableColumn{"targetID", "int", 0, false, false, ""}, /* the ID of the element being acted upon */
|
qgen.DBTableColumn{"targetID", "int", 0, false, false, ""}, /* the ID of the element being acted upon */
|
||||||
qgen.DBTableColumn{"targetType", "varchar", 50, false, false, ""}, /* topic, post (calling it post here to differentiate it from the 'reply' event), forum, user */
|
qgen.DBTableColumn{"targetType", "varchar", 50, false, false, ""}, /* topic, post (calling it post here to differentiate it from the 'reply' event), forum, user */
|
||||||
qgen.DBTableColumn{"level", "int", 0, false, false, "0"}, /* 0: Mentions (aka the global default for any post), 1: Replies To You, 2: All Replies*/
|
qgen.DBTableColumn{"level", "int", 0, false, false, "0"}, /* 0: Mentions (aka the global default for any post), 1: Replies To You, 2: All Replies*/
|
||||||
|
@ -378,7 +385,7 @@ func createTables(adapter qgen.Adapter) error {
|
||||||
qgen.DBTableColumn{"elementID", "int", 0, false, false, ""},
|
qgen.DBTableColumn{"elementID", "int", 0, false, false, ""},
|
||||||
qgen.DBTableColumn{"elementType", "varchar", 100, false, false, ""},
|
qgen.DBTableColumn{"elementType", "varchar", 100, false, false, ""},
|
||||||
qgen.DBTableColumn{"ipaddress", "varchar", 200, false, false, ""},
|
qgen.DBTableColumn{"ipaddress", "varchar", 200, false, false, ""},
|
||||||
qgen.DBTableColumn{"actorID", "int", 0, false, false, ""},
|
qgen.DBTableColumn{"actorID", "int", 0, false, false, ""}, // TODO: Make this a foreign key
|
||||||
qgen.DBTableColumn{"doneAt", "datetime", 0, false, false, ""},
|
qgen.DBTableColumn{"doneAt", "datetime", 0, false, false, ""},
|
||||||
},
|
},
|
||||||
[]qgen.DBTableKey{},
|
[]qgen.DBTableKey{},
|
||||||
|
@ -390,7 +397,7 @@ func createTables(adapter qgen.Adapter) error {
|
||||||
qgen.DBTableColumn{"elementID", "int", 0, false, false, ""},
|
qgen.DBTableColumn{"elementID", "int", 0, false, false, ""},
|
||||||
qgen.DBTableColumn{"elementType", "varchar", 100, false, false, ""},
|
qgen.DBTableColumn{"elementType", "varchar", 100, false, false, ""},
|
||||||
qgen.DBTableColumn{"ipaddress", "varchar", 200, false, false, ""},
|
qgen.DBTableColumn{"ipaddress", "varchar", 200, false, false, ""},
|
||||||
qgen.DBTableColumn{"actorID", "int", 0, false, false, ""},
|
qgen.DBTableColumn{"actorID", "int", 0, false, false, ""}, // TODO: Make this a foreign key
|
||||||
qgen.DBTableColumn{"doneAt", "datetime", 0, false, false, ""},
|
qgen.DBTableColumn{"doneAt", "datetime", 0, false, false, ""},
|
||||||
},
|
},
|
||||||
[]qgen.DBTableKey{},
|
[]qgen.DBTableKey{},
|
||||||
|
|
|
@ -302,6 +302,32 @@ func init() {
|
||||||
counters.SetReverseOSMapEnum(reverseOSMapEnum)
|
counters.SetReverseOSMapEnum(reverseOSMapEnum)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type WriterIntercept struct {
|
||||||
|
w http.ResponseWriter
|
||||||
|
code int
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewWriterIntercept(w http.ResponseWriter) *WriterIntercept {
|
||||||
|
return &WriterIntercept{w:w,code:200}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (writ *WriterIntercept) Header() http.Header {
|
||||||
|
return writ.w.Header()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (writ *WriterIntercept) Write(pieces []byte) (int, error) {
|
||||||
|
return writ.w.Write(pieces)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (writ *WriterIntercept) WriteHeader(code int) {
|
||||||
|
writ.w.WriteHeader(code)
|
||||||
|
writ.code = code
|
||||||
|
}
|
||||||
|
|
||||||
|
func (writ *WriterIntercept) GetCode() int {
|
||||||
|
return writ.code
|
||||||
|
}
|
||||||
|
|
||||||
type GenRouter struct {
|
type GenRouter struct {
|
||||||
UploadHandler func(http.ResponseWriter, *http.Request)
|
UploadHandler func(http.ResponseWriter, *http.Request)
|
||||||
extraRoutes map[string]func(http.ResponseWriter, *http.Request, common.User) common.RouteError
|
extraRoutes map[string]func(http.ResponseWriter, *http.Request, common.User) common.RouteError
|
||||||
|
@ -311,7 +337,14 @@ type GenRouter struct {
|
||||||
|
|
||||||
func NewGenRouter(uploads http.Handler) *GenRouter {
|
func NewGenRouter(uploads http.Handler) *GenRouter {
|
||||||
return &GenRouter{
|
return &GenRouter{
|
||||||
UploadHandler: http.StripPrefix("/uploads/",uploads).ServeHTTP,
|
UploadHandler: func(w http.ResponseWriter, req *http.Request) {
|
||||||
|
writ := NewWriterIntercept(w)
|
||||||
|
http.StripPrefix("/uploads/",uploads).ServeHTTP(writ,req)
|
||||||
|
if writ.GetCode() == 200 {
|
||||||
|
w.Header().Set("Cache-Control", "max-age=" + strconv.Itoa(common.Day))
|
||||||
|
w.Header().Set("Vary", "Accept-Encoding")
|
||||||
|
}
|
||||||
|
},
|
||||||
extraRoutes: make(map[string]func(http.ResponseWriter, *http.Request, common.User) common.RouteError),
|
extraRoutes: make(map[string]func(http.ResponseWriter, *http.Request, common.User) common.RouteError),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -74,7 +74,7 @@ func buildTopicRoutes() {
|
||||||
Action("routes.LockTopicSubmit", "/topic/lock/submit/").LitBefore("req.URL.Path += extraData"),
|
Action("routes.LockTopicSubmit", "/topic/lock/submit/").LitBefore("req.URL.Path += extraData"),
|
||||||
Action("routes.UnlockTopicSubmit", "/topic/unlock/submit/", "extraData"),
|
Action("routes.UnlockTopicSubmit", "/topic/unlock/submit/", "extraData"),
|
||||||
Action("routes.MoveTopicSubmit", "/topic/move/submit/", "extraData"),
|
Action("routes.MoveTopicSubmit", "/topic/move/submit/", "extraData"),
|
||||||
Action("routeLikeTopicSubmit", "/topic/like/submit/", "extraData"),
|
Action("routeLikeTopicSubmit", "/topic/like/submit/", "extraData").Before("ParseForm"),
|
||||||
)
|
)
|
||||||
addRouteGroup(topicGroup)
|
addRouteGroup(topicGroup)
|
||||||
}
|
}
|
||||||
|
@ -88,7 +88,7 @@ func buildReplyRoutes() {
|
||||||
UploadAction("routes.CreateReplySubmit", "/reply/create/").MaxSizeVar("common.Config.MaxRequestSize"), // TODO: Rename the route so it's /reply/create/submit/
|
UploadAction("routes.CreateReplySubmit", "/reply/create/").MaxSizeVar("common.Config.MaxRequestSize"), // TODO: Rename the route so it's /reply/create/submit/
|
||||||
Action("routes.ReplyEditSubmit", "/reply/edit/submit/", "extraData"),
|
Action("routes.ReplyEditSubmit", "/reply/edit/submit/", "extraData"),
|
||||||
Action("routes.ReplyDeleteSubmit", "/reply/delete/submit/", "extraData"),
|
Action("routes.ReplyDeleteSubmit", "/reply/delete/submit/", "extraData"),
|
||||||
Action("routeReplyLikeSubmit", "/reply/like/submit/", "extraData"),
|
Action("routeReplyLikeSubmit", "/reply/like/submit/", "extraData").Before("ParseForm"),
|
||||||
)
|
)
|
||||||
addRouteGroup(replyGroup)
|
addRouteGroup(replyGroup)
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,7 +20,8 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
type TopicStmts struct {
|
type TopicStmts struct {
|
||||||
getReplies *sql.Stmt
|
getReplies *sql.Stmt
|
||||||
|
getLikedTopic *sql.Stmt
|
||||||
}
|
}
|
||||||
|
|
||||||
var topicStmts TopicStmts
|
var topicStmts TopicStmts
|
||||||
|
@ -29,7 +30,8 @@ var topicStmts TopicStmts
|
||||||
func init() {
|
func init() {
|
||||||
common.DbInits.Add(func(acc *qgen.Accumulator) error {
|
common.DbInits.Add(func(acc *qgen.Accumulator) error {
|
||||||
topicStmts = TopicStmts{
|
topicStmts = TopicStmts{
|
||||||
getReplies: acc.SimpleLeftJoin("replies", "users", "replies.rid, replies.content, replies.createdBy, replies.createdAt, replies.lastEdit, replies.lastEditBy, users.avatar, users.name, users.group, users.url_prefix, users.url_name, users.level, replies.ipaddress, replies.likeCount, replies.actionType", "replies.createdBy = users.uid", "replies.tid = ?", "replies.rid ASC", "?,?"),
|
getReplies: acc.SimpleLeftJoin("replies", "users", "replies.rid, replies.content, replies.createdBy, replies.createdAt, replies.lastEdit, replies.lastEditBy, users.avatar, users.name, users.group, users.url_prefix, users.url_name, users.level, replies.ipaddress, replies.likeCount, replies.actionType", "replies.createdBy = users.uid", "replies.tid = ?", "replies.rid ASC", "?,?"),
|
||||||
|
getLikedTopic: acc.Select("likes").Columns("targetItem").Where("sentBy = ? && targetItem = ? && targetType = 'topics'").Prepare(),
|
||||||
}
|
}
|
||||||
return acc.FirstError()
|
return acc.FirstError()
|
||||||
})
|
})
|
||||||
|
@ -107,12 +109,25 @@ func ViewTopic(w http.ResponseWriter, r *http.Request, user common.User, urlBit
|
||||||
poll = pPoll.Copy()
|
poll = pPoll.Copy()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if topic.LikeCount > 0 && user.Liked > 0 {
|
||||||
|
var disp int // Discard this value
|
||||||
|
err = topicStmts.getLikedTopic.QueryRow(user.ID, topic.ID).Scan(&disp)
|
||||||
|
if err == nil {
|
||||||
|
topic.Liked = true
|
||||||
|
} else if err != nil && err != sql.ErrNoRows {
|
||||||
|
return common.InternalError(err, w, r)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Calculate the offset
|
// Calculate the offset
|
||||||
offset, page, lastPage := common.PageOffset(topic.PostCount, page, common.Config.ItemsPerPage)
|
offset, page, lastPage := common.PageOffset(topic.PostCount, page, common.Config.ItemsPerPage)
|
||||||
tpage := common.TopicPage{topic.Title, user, headerVars, []common.ReplyUser{}, topic, poll, page, lastPage}
|
tpage := common.TopicPage{topic.Title, user, headerVars, []common.ReplyUser{}, topic, poll, page, lastPage}
|
||||||
|
|
||||||
// Get the replies if we have any...
|
// Get the replies if we have any...
|
||||||
if topic.PostCount > 0 {
|
if topic.PostCount > 0 {
|
||||||
|
var likedMap = make(map[int]int)
|
||||||
|
var likedQueryList = []int{user.ID}
|
||||||
|
|
||||||
rows, err := topicStmts.getReplies.Query(topic.ID, offset, common.Config.ItemsPerPage)
|
rows, err := topicStmts.getReplies.Query(topic.ID, offset, common.Config.ItemsPerPage)
|
||||||
if err == sql.ErrNoRows {
|
if err == sql.ErrNoRows {
|
||||||
return common.LocalError("Bad Page. Some of the posts may have been deleted or you got here by directly typing in the page number.", w, r, user)
|
return common.LocalError("Bad Page. Some of the posts may have been deleted or you got here by directly typing in the page number.", w, r, user)
|
||||||
|
@ -171,7 +186,11 @@ func ViewTopic(w http.ResponseWriter, r *http.Request, user common.User, urlBit
|
||||||
replyItem.ActionIcon = ""
|
replyItem.ActionIcon = ""
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
replyItem.Liked = false
|
|
||||||
|
if replyItem.LikeCount > 0 {
|
||||||
|
likedMap[replyItem.ID] = len(tpage.ItemList)
|
||||||
|
likedQueryList = append(likedQueryList, replyItem.ID)
|
||||||
|
}
|
||||||
|
|
||||||
common.RunVhook("topic_reply_row_assign", &tpage, &replyItem)
|
common.RunVhook("topic_reply_row_assign", &tpage, &replyItem)
|
||||||
// TODO: Use a pointer instead to make it easier to abstract this loop? What impact would this have on escape analysis?
|
// TODO: Use a pointer instead to make it easier to abstract this loop? What impact would this have on escape analysis?
|
||||||
|
@ -181,6 +200,28 @@ func ViewTopic(w http.ResponseWriter, r *http.Request, user common.User, urlBit
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return common.InternalError(err, w, r)
|
return common.InternalError(err, w, r)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: Add a config setting to disable the liked query for a burst of extra speed
|
||||||
|
if user.Liked > 0 && len(likedQueryList) > 1 /*&& user.LastLiked <= time.Now()*/ {
|
||||||
|
rows, err := qgen.Builder.Accumulator().Select("likes").Columns("targetItem").Where("sentBy = ? AND targetType = 'replies'").In("targetItem", likedQueryList[1:]).Query(user.ID)
|
||||||
|
if err != nil && err != sql.ErrNoRows {
|
||||||
|
return common.InternalError(err, w, r)
|
||||||
|
}
|
||||||
|
defer rows.Close()
|
||||||
|
|
||||||
|
for rows.Next() {
|
||||||
|
var likeRid int
|
||||||
|
err := rows.Scan(&likeRid)
|
||||||
|
if err != nil {
|
||||||
|
return common.InternalError(err, w, r)
|
||||||
|
}
|
||||||
|
tpage.ItemList[likedMap[likeRid]].Liked = true
|
||||||
|
}
|
||||||
|
err = rows.Err()
|
||||||
|
if err != nil {
|
||||||
|
return common.InternalError(err, w, r)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if common.RunPreRenderHook("pre_render_view_topic", w, r, &user, &tpage) {
|
if common.RunPreRenderHook("pre_render_view_topic", w, r, &user, &tpage) {
|
||||||
|
|
|
@ -1,8 +1,14 @@
|
||||||
echo "Generating the dynamic code"
|
echo "Generating the dynamic code"
|
||||||
go generate
|
go generate
|
||||||
|
|
||||||
echo "Building Gosora"
|
echo "Building Gosora"
|
||||||
go build -o Gosora
|
go build -o Gosora
|
||||||
|
|
||||||
echo "Building the templates"
|
echo "Building the templates"
|
||||||
./Gosora -build-templates
|
./Gosora -build-templates
|
||||||
|
|
||||||
|
echo "Building Gosora... Again"
|
||||||
|
go build -o Gosora
|
||||||
|
|
||||||
echo "Running Gosora"
|
echo "Running Gosora"
|
||||||
./Gosora
|
./Gosora
|
|
@ -1,8 +1,14 @@
|
||||||
echo "Generating the dynamic code"
|
echo "Generating the dynamic code"
|
||||||
go generate
|
go generate
|
||||||
|
|
||||||
echo "Building Gosora"
|
echo "Building Gosora"
|
||||||
go build -o Gosora -tags no_ws
|
go build -o Gosora -tags no_ws
|
||||||
|
|
||||||
echo "Building the templates"
|
echo "Building the templates"
|
||||||
./Gosora -build-templates
|
./Gosora -build-templates
|
||||||
|
|
||||||
|
echo "Building Gosora... Again"
|
||||||
|
go build -o Gosora -tags no_ws
|
||||||
|
|
||||||
echo "Running Gosora"
|
echo "Running Gosora"
|
||||||
./Gosora
|
./Gosora
|
||||||
|
|
|
@ -46,6 +46,13 @@ if %errorlevel% neq 0 (
|
||||||
exit /b %errorlevel%
|
exit /b %errorlevel%
|
||||||
)
|
)
|
||||||
|
|
||||||
|
echo Building the executable... again
|
||||||
|
go build -o gosora.exe -tags no_ws
|
||||||
|
if %errorlevel% neq 0 (
|
||||||
|
pause
|
||||||
|
exit /b %errorlevel%
|
||||||
|
)
|
||||||
|
|
||||||
echo Running Gosora
|
echo Running Gosora
|
||||||
gosora.exe
|
gosora.exe
|
||||||
pause
|
pause
|
7
run.bat
7
run.bat
|
@ -46,6 +46,13 @@ if %errorlevel% neq 0 (
|
||||||
exit /b %errorlevel%
|
exit /b %errorlevel%
|
||||||
)
|
)
|
||||||
|
|
||||||
|
echo Building the executable... again
|
||||||
|
go build -o gosora.exe
|
||||||
|
if %errorlevel% neq 0 (
|
||||||
|
pause
|
||||||
|
exit /b %errorlevel%
|
||||||
|
)
|
||||||
|
|
||||||
echo Running Gosora
|
echo Running Gosora
|
||||||
gosora.exe
|
gosora.exe
|
||||||
rem Or you could redirect the output to a file
|
rem Or you could redirect the output to a file
|
||||||
|
|
|
@ -46,6 +46,13 @@ if %errorlevel% neq 0 (
|
||||||
exit /b %errorlevel%
|
exit /b %errorlevel%
|
||||||
)
|
)
|
||||||
|
|
||||||
|
echo Building the executable... again
|
||||||
|
go build -o gosora.exe -tags mssql
|
||||||
|
if %errorlevel% neq 0 (
|
||||||
|
pause
|
||||||
|
exit /b %errorlevel%
|
||||||
|
)
|
||||||
|
|
||||||
echo Running Gosora
|
echo Running Gosora
|
||||||
gosora.exe
|
gosora.exe
|
||||||
pause
|
pause
|
|
@ -3,5 +3,6 @@ CREATE TABLE [likes] (
|
||||||
[targetItem] int not null,
|
[targetItem] int not null,
|
||||||
[targetType] nvarchar (50) DEFAULT 'replies' not null,
|
[targetType] nvarchar (50) DEFAULT 'replies' not null,
|
||||||
[sentBy] int not null,
|
[sentBy] int not null,
|
||||||
|
[createdAt] datetime not null,
|
||||||
[recalc] tinyint DEFAULT 0 not null
|
[recalc] tinyint DEFAULT 0 not null
|
||||||
);
|
);
|
|
@ -21,6 +21,9 @@ CREATE TABLE [users] (
|
||||||
[bigposts] int DEFAULT 0 not null,
|
[bigposts] int DEFAULT 0 not null,
|
||||||
[megaposts] int DEFAULT 0 not null,
|
[megaposts] int DEFAULT 0 not null,
|
||||||
[topics] int DEFAULT 0 not null,
|
[topics] int DEFAULT 0 not null,
|
||||||
|
[liked] int DEFAULT 0 not null,
|
||||||
|
[oldestItemLikedCreatedAt] datetime not null,
|
||||||
|
[lastLiked] datetime not null,
|
||||||
[temp_group] int DEFAULT 0 not null,
|
[temp_group] int DEFAULT 0 not null,
|
||||||
primary key([uid]),
|
primary key([uid]),
|
||||||
unique([name])
|
unique([name])
|
||||||
|
|
|
@ -3,5 +3,6 @@ CREATE TABLE `likes` (
|
||||||
`targetItem` int not null,
|
`targetItem` int not null,
|
||||||
`targetType` varchar(50) DEFAULT 'replies' not null,
|
`targetType` varchar(50) DEFAULT 'replies' not null,
|
||||||
`sentBy` int not null,
|
`sentBy` int not null,
|
||||||
|
`createdAt` datetime not null,
|
||||||
`recalc` tinyint DEFAULT 0 not null
|
`recalc` tinyint DEFAULT 0 not null
|
||||||
);
|
);
|
|
@ -21,6 +21,9 @@ CREATE TABLE `users` (
|
||||||
`bigposts` int DEFAULT 0 not null,
|
`bigposts` int DEFAULT 0 not null,
|
||||||
`megaposts` int DEFAULT 0 not null,
|
`megaposts` int DEFAULT 0 not null,
|
||||||
`topics` int DEFAULT 0 not null,
|
`topics` int DEFAULT 0 not null,
|
||||||
|
`liked` int DEFAULT 0 not null,
|
||||||
|
`oldestItemLikedCreatedAt` datetime not null,
|
||||||
|
`lastLiked` datetime not null,
|
||||||
`temp_group` int DEFAULT 0 not null,
|
`temp_group` int DEFAULT 0 not null,
|
||||||
primary key(`uid`),
|
primary key(`uid`),
|
||||||
unique(`name`)
|
unique(`name`)
|
||||||
|
|
|
@ -3,5 +3,6 @@ CREATE TABLE `likes` (
|
||||||
`targetItem` int not null,
|
`targetItem` int not null,
|
||||||
`targetType` varchar (50) DEFAULT 'replies' not null,
|
`targetType` varchar (50) DEFAULT 'replies' not null,
|
||||||
`sentBy` int not null,
|
`sentBy` int not null,
|
||||||
|
`createdAt` timestamp not null,
|
||||||
`recalc` tinyint DEFAULT 0 not null
|
`recalc` tinyint DEFAULT 0 not null
|
||||||
);
|
);
|
|
@ -21,6 +21,9 @@ CREATE TABLE `users` (
|
||||||
`bigposts` int DEFAULT 0 not null,
|
`bigposts` int DEFAULT 0 not null,
|
||||||
`megaposts` int DEFAULT 0 not null,
|
`megaposts` int DEFAULT 0 not null,
|
||||||
`topics` int DEFAULT 0 not null,
|
`topics` int DEFAULT 0 not null,
|
||||||
|
`liked` int DEFAULT 0 not null,
|
||||||
|
`oldestItemLikedCreatedAt` timestamp not null,
|
||||||
|
`lastLiked` timestamp not null,
|
||||||
`temp_group` int DEFAULT 0 not null,
|
`temp_group` int DEFAULT 0 not null,
|
||||||
primary key(`uid`),
|
primary key(`uid`),
|
||||||
unique(`name`)
|
unique(`name`)
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
{
|
{
|
||||||
"Version":"0"
|
"DBVersion":"0",
|
||||||
|
"DynamicFileVersion":"0"
|
||||||
}
|
}
|
|
@ -3,9 +3,9 @@
|
||||||
// Code generated by Gosora. More below:
|
// Code generated by Gosora. More below:
|
||||||
/* This file was automatically generated by the software. Please don't edit it as your changes may be overwritten at any moment. */
|
/* This file was automatically generated by the software. Please don't edit it as your changes may be overwritten at any moment. */
|
||||||
package main
|
package main
|
||||||
import "strconv"
|
|
||||||
import "net/http"
|
import "net/http"
|
||||||
import "./common"
|
import "./common"
|
||||||
|
import "strconv"
|
||||||
|
|
||||||
var forum_tmpl_phrase_id int
|
var forum_tmpl_phrase_id int
|
||||||
|
|
||||||
|
@ -307,61 +307,67 @@ w.Write([]byte(item.Link))
|
||||||
w.Write(forum_frags[58])
|
w.Write(forum_frags[58])
|
||||||
w.Write([]byte(item.Title))
|
w.Write([]byte(item.Title))
|
||||||
w.Write(forum_frags[59])
|
w.Write(forum_frags[59])
|
||||||
w.Write([]byte(item.Creator.Link))
|
w.Write([]byte(item.Title))
|
||||||
w.Write(forum_frags[60])
|
w.Write(forum_frags[60])
|
||||||
w.Write([]byte(item.Creator.Name))
|
w.Write([]byte(item.Creator.Link))
|
||||||
w.Write(forum_frags[61])
|
w.Write(forum_frags[61])
|
||||||
if item.IsClosed {
|
w.Write([]byte(item.Creator.Name))
|
||||||
w.Write(forum_frags[62])
|
w.Write(forum_frags[62])
|
||||||
w.Write(phrases[44])
|
w.Write([]byte(item.Creator.Name))
|
||||||
w.Write(forum_frags[63])
|
w.Write(forum_frags[63])
|
||||||
}
|
if item.IsClosed {
|
||||||
if item.Sticky {
|
|
||||||
w.Write(forum_frags[64])
|
w.Write(forum_frags[64])
|
||||||
w.Write(phrases[45])
|
w.Write(phrases[44])
|
||||||
w.Write(forum_frags[65])
|
w.Write(forum_frags[65])
|
||||||
}
|
}
|
||||||
w.Write(forum_frags[66])
|
|
||||||
w.Write([]byte(strconv.Itoa(item.PostCount)))
|
|
||||||
w.Write(forum_frags[67])
|
|
||||||
w.Write([]byte(strconv.Itoa(item.LikeCount)))
|
|
||||||
w.Write(forum_frags[68])
|
|
||||||
if item.Sticky {
|
if item.Sticky {
|
||||||
|
w.Write(forum_frags[66])
|
||||||
|
w.Write(phrases[45])
|
||||||
|
w.Write(forum_frags[67])
|
||||||
|
}
|
||||||
|
w.Write(forum_frags[68])
|
||||||
|
w.Write([]byte(strconv.Itoa(item.PostCount)))
|
||||||
w.Write(forum_frags[69])
|
w.Write(forum_frags[69])
|
||||||
|
w.Write([]byte(strconv.Itoa(item.LikeCount)))
|
||||||
|
w.Write(forum_frags[70])
|
||||||
|
if item.Sticky {
|
||||||
|
w.Write(forum_frags[71])
|
||||||
} else {
|
} else {
|
||||||
if item.IsClosed {
|
if item.IsClosed {
|
||||||
w.Write(forum_frags[70])
|
|
||||||
}
|
|
||||||
}
|
|
||||||
w.Write(forum_frags[71])
|
|
||||||
w.Write([]byte(item.LastUser.Link))
|
|
||||||
w.Write(forum_frags[72])
|
w.Write(forum_frags[72])
|
||||||
w.Write([]byte(item.LastUser.Avatar))
|
}
|
||||||
|
}
|
||||||
w.Write(forum_frags[73])
|
w.Write(forum_frags[73])
|
||||||
w.Write([]byte(item.LastUser.Name))
|
|
||||||
w.Write(forum_frags[74])
|
|
||||||
w.Write([]byte(item.LastUser.Name))
|
|
||||||
w.Write(forum_frags[75])
|
|
||||||
w.Write([]byte(item.LastUser.Link))
|
w.Write([]byte(item.LastUser.Link))
|
||||||
|
w.Write(forum_frags[74])
|
||||||
|
w.Write([]byte(item.LastUser.Avatar))
|
||||||
|
w.Write(forum_frags[75])
|
||||||
|
w.Write([]byte(item.LastUser.Name))
|
||||||
w.Write(forum_frags[76])
|
w.Write(forum_frags[76])
|
||||||
w.Write([]byte(item.LastUser.Name))
|
w.Write([]byte(item.LastUser.Name))
|
||||||
w.Write(forum_frags[77])
|
w.Write(forum_frags[77])
|
||||||
w.Write([]byte(item.RelativeLastReplyAt))
|
w.Write([]byte(item.LastUser.Link))
|
||||||
w.Write(forum_frags[78])
|
w.Write(forum_frags[78])
|
||||||
|
w.Write([]byte(item.LastUser.Name))
|
||||||
|
w.Write(forum_frags[79])
|
||||||
|
w.Write([]byte(item.LastUser.Name))
|
||||||
|
w.Write(forum_frags[80])
|
||||||
|
w.Write([]byte(item.RelativeLastReplyAt))
|
||||||
|
w.Write(forum_frags[81])
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
w.Write(forum_frags[79])
|
w.Write(forum_frags[82])
|
||||||
w.Write(phrases[46])
|
w.Write(phrases[46])
|
||||||
if tmpl_forum_vars.CurrentUser.Perms.CreateTopic {
|
if tmpl_forum_vars.CurrentUser.Perms.CreateTopic {
|
||||||
w.Write(forum_frags[80])
|
|
||||||
w.Write([]byte(strconv.Itoa(tmpl_forum_vars.Forum.ID)))
|
|
||||||
w.Write(forum_frags[81])
|
|
||||||
w.Write(phrases[47])
|
|
||||||
w.Write(forum_frags[82])
|
|
||||||
}
|
|
||||||
w.Write(forum_frags[83])
|
w.Write(forum_frags[83])
|
||||||
}
|
w.Write([]byte(strconv.Itoa(tmpl_forum_vars.Forum.ID)))
|
||||||
w.Write(forum_frags[84])
|
w.Write(forum_frags[84])
|
||||||
|
w.Write(phrases[47])
|
||||||
|
w.Write(forum_frags[85])
|
||||||
|
}
|
||||||
|
w.Write(forum_frags[86])
|
||||||
|
}
|
||||||
|
w.Write(forum_frags[87])
|
||||||
if tmpl_forum_vars.LastPage > 1 {
|
if tmpl_forum_vars.LastPage > 1 {
|
||||||
w.Write(paginator_frags[0])
|
w.Write(paginator_frags[0])
|
||||||
if tmpl_forum_vars.Page > 1 {
|
if tmpl_forum_vars.Page > 1 {
|
||||||
|
@ -397,7 +403,7 @@ w.Write(paginator_frags[13])
|
||||||
}
|
}
|
||||||
w.Write(paginator_frags[14])
|
w.Write(paginator_frags[14])
|
||||||
}
|
}
|
||||||
w.Write(forum_frags[85])
|
w.Write(forum_frags[88])
|
||||||
w.Write(footer_frags[0])
|
w.Write(footer_frags[0])
|
||||||
w.Write([]byte(common.BuildWidget("footer",tmpl_forum_vars.Header)))
|
w.Write([]byte(common.BuildWidget("footer",tmpl_forum_vars.Header)))
|
||||||
w.Write(footer_frags[1])
|
w.Write(footer_frags[1])
|
||||||
|
|
984
template_list.go
984
template_list.go
File diff suppressed because it is too large
Load Diff
|
@ -187,73 +187,77 @@ w.Write([]byte(tmpl_profile_vars.ProfileOwner.Name))
|
||||||
w.Write(profile_frags[3])
|
w.Write(profile_frags[3])
|
||||||
w.Write([]byte(tmpl_profile_vars.ProfileOwner.Name))
|
w.Write([]byte(tmpl_profile_vars.ProfileOwner.Name))
|
||||||
w.Write(profile_frags[4])
|
w.Write(profile_frags[4])
|
||||||
if tmpl_profile_vars.ProfileOwner.Tag != "" {
|
w.Write([]byte(tmpl_profile_vars.ProfileOwner.Name))
|
||||||
w.Write(profile_frags[5])
|
w.Write(profile_frags[5])
|
||||||
w.Write([]byte(tmpl_profile_vars.ProfileOwner.Tag))
|
if tmpl_profile_vars.ProfileOwner.Tag != "" {
|
||||||
w.Write(profile_frags[6])
|
w.Write(profile_frags[6])
|
||||||
}
|
w.Write([]byte(tmpl_profile_vars.ProfileOwner.Tag))
|
||||||
w.Write(profile_frags[7])
|
w.Write(profile_frags[7])
|
||||||
if !tmpl_profile_vars.CurrentUser.Loggedin {
|
w.Write([]byte(tmpl_profile_vars.ProfileOwner.Tag))
|
||||||
w.Write(profile_frags[8])
|
w.Write(profile_frags[8])
|
||||||
w.Write(phrases[19])
|
}
|
||||||
w.Write(profile_frags[9])
|
w.Write(profile_frags[9])
|
||||||
} else {
|
if !tmpl_profile_vars.CurrentUser.Loggedin {
|
||||||
w.Write(profile_frags[10])
|
w.Write(profile_frags[10])
|
||||||
w.Write(phrases[20])
|
w.Write(phrases[19])
|
||||||
w.Write(profile_frags[11])
|
w.Write(profile_frags[11])
|
||||||
if tmpl_profile_vars.CurrentUser.IsSuperMod && !tmpl_profile_vars.ProfileOwner.IsSuperMod {
|
|
||||||
w.Write(profile_frags[12])
|
|
||||||
if tmpl_profile_vars.ProfileOwner.IsBanned {
|
|
||||||
w.Write(profile_frags[13])
|
|
||||||
w.Write([]byte(strconv.Itoa(tmpl_profile_vars.ProfileOwner.ID)))
|
|
||||||
w.Write(profile_frags[14])
|
|
||||||
w.Write([]byte(tmpl_profile_vars.CurrentUser.Session))
|
|
||||||
w.Write(profile_frags[15])
|
|
||||||
w.Write(phrases[21])
|
|
||||||
w.Write(profile_frags[16])
|
|
||||||
} else {
|
} else {
|
||||||
|
w.Write(profile_frags[12])
|
||||||
|
w.Write(phrases[20])
|
||||||
|
w.Write(profile_frags[13])
|
||||||
|
if tmpl_profile_vars.CurrentUser.IsSuperMod && !tmpl_profile_vars.ProfileOwner.IsSuperMod {
|
||||||
|
w.Write(profile_frags[14])
|
||||||
|
if tmpl_profile_vars.ProfileOwner.IsBanned {
|
||||||
|
w.Write(profile_frags[15])
|
||||||
|
w.Write([]byte(strconv.Itoa(tmpl_profile_vars.ProfileOwner.ID)))
|
||||||
|
w.Write(profile_frags[16])
|
||||||
|
w.Write([]byte(tmpl_profile_vars.CurrentUser.Session))
|
||||||
w.Write(profile_frags[17])
|
w.Write(profile_frags[17])
|
||||||
w.Write(phrases[22])
|
w.Write(phrases[21])
|
||||||
w.Write(profile_frags[18])
|
w.Write(profile_frags[18])
|
||||||
}
|
} else {
|
||||||
w.Write(profile_frags[19])
|
w.Write(profile_frags[19])
|
||||||
}
|
w.Write(phrases[22])
|
||||||
w.Write(profile_frags[20])
|
w.Write(profile_frags[20])
|
||||||
w.Write([]byte(strconv.Itoa(tmpl_profile_vars.ProfileOwner.ID)))
|
}
|
||||||
w.Write(profile_frags[21])
|
w.Write(profile_frags[21])
|
||||||
w.Write([]byte(tmpl_profile_vars.CurrentUser.Session))
|
}
|
||||||
w.Write(profile_frags[22])
|
w.Write(profile_frags[22])
|
||||||
w.Write(phrases[23])
|
|
||||||
w.Write(profile_frags[23])
|
|
||||||
w.Write(phrases[24])
|
|
||||||
w.Write(profile_frags[24])
|
|
||||||
}
|
|
||||||
w.Write(profile_frags[25])
|
|
||||||
if tmpl_profile_vars.CurrentUser.Perms.BanUsers {
|
|
||||||
w.Write(profile_frags[26])
|
|
||||||
w.Write(phrases[25])
|
|
||||||
w.Write(profile_frags[27])
|
|
||||||
w.Write([]byte(strconv.Itoa(tmpl_profile_vars.ProfileOwner.ID)))
|
w.Write([]byte(strconv.Itoa(tmpl_profile_vars.ProfileOwner.ID)))
|
||||||
w.Write(profile_frags[28])
|
w.Write(profile_frags[23])
|
||||||
w.Write([]byte(tmpl_profile_vars.CurrentUser.Session))
|
w.Write([]byte(tmpl_profile_vars.CurrentUser.Session))
|
||||||
w.Write(profile_frags[29])
|
w.Write(profile_frags[24])
|
||||||
w.Write(profile_frags[30])
|
w.Write(phrases[23])
|
||||||
w.Write(phrases[26])
|
w.Write(profile_frags[25])
|
||||||
w.Write(profile_frags[31])
|
w.Write(phrases[24])
|
||||||
w.Write(phrases[27])
|
w.Write(profile_frags[26])
|
||||||
w.Write(profile_frags[32])
|
|
||||||
w.Write(phrases[28])
|
|
||||||
w.Write(profile_frags[33])
|
|
||||||
w.Write(phrases[29])
|
|
||||||
w.Write(profile_frags[34])
|
|
||||||
w.Write(phrases[30])
|
|
||||||
w.Write(profile_frags[35])
|
|
||||||
w.Write(phrases[31])
|
|
||||||
w.Write(profile_frags[36])
|
|
||||||
}
|
}
|
||||||
|
w.Write(profile_frags[27])
|
||||||
|
if tmpl_profile_vars.CurrentUser.Perms.BanUsers {
|
||||||
|
w.Write(profile_frags[28])
|
||||||
|
w.Write(phrases[25])
|
||||||
|
w.Write(profile_frags[29])
|
||||||
|
w.Write([]byte(strconv.Itoa(tmpl_profile_vars.ProfileOwner.ID)))
|
||||||
|
w.Write(profile_frags[30])
|
||||||
|
w.Write([]byte(tmpl_profile_vars.CurrentUser.Session))
|
||||||
|
w.Write(profile_frags[31])
|
||||||
|
w.Write(profile_frags[32])
|
||||||
|
w.Write(phrases[26])
|
||||||
|
w.Write(profile_frags[33])
|
||||||
|
w.Write(phrases[27])
|
||||||
|
w.Write(profile_frags[34])
|
||||||
|
w.Write(phrases[28])
|
||||||
|
w.Write(profile_frags[35])
|
||||||
|
w.Write(phrases[29])
|
||||||
|
w.Write(profile_frags[36])
|
||||||
|
w.Write(phrases[30])
|
||||||
w.Write(profile_frags[37])
|
w.Write(profile_frags[37])
|
||||||
w.Write(phrases[32])
|
w.Write(phrases[31])
|
||||||
w.Write(profile_frags[38])
|
w.Write(profile_frags[38])
|
||||||
|
}
|
||||||
|
w.Write(profile_frags[39])
|
||||||
|
w.Write(phrases[32])
|
||||||
|
w.Write(profile_frags[40])
|
||||||
if tmpl_profile_vars.Header.Theme.BgAvatars {
|
if tmpl_profile_vars.Header.Theme.BgAvatars {
|
||||||
if len(tmpl_profile_vars.ItemList) != 0 {
|
if len(tmpl_profile_vars.ItemList) != 0 {
|
||||||
for _, item := range tmpl_profile_vars.ItemList {
|
for _, item := range tmpl_profile_vars.ItemList {
|
||||||
|
@ -363,20 +367,20 @@ w.Write(profile_comments_row_frags[49])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
w.Write(profile_frags[39])
|
|
||||||
if !tmpl_profile_vars.CurrentUser.IsBanned {
|
|
||||||
w.Write(profile_frags[40])
|
|
||||||
w.Write([]byte(tmpl_profile_vars.CurrentUser.Session))
|
|
||||||
w.Write(profile_frags[41])
|
w.Write(profile_frags[41])
|
||||||
w.Write([]byte(strconv.Itoa(tmpl_profile_vars.ProfileOwner.ID)))
|
if !tmpl_profile_vars.CurrentUser.IsBanned {
|
||||||
w.Write(profile_frags[42])
|
w.Write(profile_frags[42])
|
||||||
w.Write(phrases[45])
|
w.Write([]byte(tmpl_profile_vars.CurrentUser.Session))
|
||||||
w.Write(profile_frags[43])
|
w.Write(profile_frags[43])
|
||||||
w.Write(phrases[46])
|
w.Write([]byte(strconv.Itoa(tmpl_profile_vars.ProfileOwner.ID)))
|
||||||
w.Write(profile_frags[44])
|
w.Write(profile_frags[44])
|
||||||
}
|
w.Write(phrases[45])
|
||||||
w.Write(profile_frags[45])
|
w.Write(profile_frags[45])
|
||||||
|
w.Write(phrases[46])
|
||||||
w.Write(profile_frags[46])
|
w.Write(profile_frags[46])
|
||||||
|
}
|
||||||
|
w.Write(profile_frags[47])
|
||||||
|
w.Write(profile_frags[48])
|
||||||
w.Write(footer_frags[0])
|
w.Write(footer_frags[0])
|
||||||
w.Write([]byte(common.BuildWidget("footer",tmpl_profile_vars.Header)))
|
w.Write([]byte(common.BuildWidget("footer",tmpl_profile_vars.Header)))
|
||||||
w.Write(footer_frags[1])
|
w.Write(footer_frags[1])
|
||||||
|
|
|
@ -3,9 +3,9 @@
|
||||||
// Code generated by Gosora. More below:
|
// Code generated by Gosora. More below:
|
||||||
/* This file was automatically generated by the software. Please don't edit it as your changes may be overwritten at any moment. */
|
/* This file was automatically generated by the software. Please don't edit it as your changes may be overwritten at any moment. */
|
||||||
package main
|
package main
|
||||||
import "strconv"
|
|
||||||
import "net/http"
|
import "net/http"
|
||||||
import "./common"
|
import "./common"
|
||||||
|
import "strconv"
|
||||||
|
|
||||||
var topic_tmpl_phrase_id int
|
var topic_tmpl_phrase_id int
|
||||||
|
|
||||||
|
@ -245,376 +245,385 @@ w.Write(phrases[22])
|
||||||
w.Write(topic_frags[16])
|
w.Write(topic_frags[16])
|
||||||
}
|
}
|
||||||
w.Write(topic_frags[17])
|
w.Write(topic_frags[17])
|
||||||
w.Write(phrases[23])
|
|
||||||
w.Write(topic_frags[18])
|
w.Write(topic_frags[18])
|
||||||
if tmpl_topic_vars.Topic.Sticky {
|
w.Write(phrases[23])
|
||||||
w.Write(topic_frags[19])
|
w.Write(topic_frags[19])
|
||||||
|
if tmpl_topic_vars.Topic.Sticky {
|
||||||
|
w.Write(topic_frags[20])
|
||||||
} else {
|
} else {
|
||||||
if tmpl_topic_vars.Topic.IsClosed {
|
if tmpl_topic_vars.Topic.IsClosed {
|
||||||
w.Write(topic_frags[20])
|
|
||||||
}
|
|
||||||
}
|
|
||||||
w.Write(topic_frags[21])
|
w.Write(topic_frags[21])
|
||||||
w.Write([]byte(tmpl_topic_vars.Topic.Title))
|
}
|
||||||
|
}
|
||||||
w.Write(topic_frags[22])
|
w.Write(topic_frags[22])
|
||||||
if tmpl_topic_vars.Topic.IsClosed {
|
w.Write([]byte(tmpl_topic_vars.Topic.Title))
|
||||||
w.Write(topic_frags[23])
|
w.Write(topic_frags[23])
|
||||||
w.Write(phrases[24])
|
w.Write([]byte(tmpl_topic_vars.Topic.Title))
|
||||||
w.Write(topic_frags[24])
|
w.Write(topic_frags[24])
|
||||||
w.Write(phrases[25])
|
if tmpl_topic_vars.Topic.IsClosed {
|
||||||
w.Write(topic_frags[25])
|
w.Write(topic_frags[25])
|
||||||
|
w.Write(phrases[24])
|
||||||
|
w.Write(topic_frags[26])
|
||||||
|
w.Write(phrases[25])
|
||||||
|
w.Write(topic_frags[27])
|
||||||
}
|
}
|
||||||
if tmpl_topic_vars.CurrentUser.Perms.EditTopic {
|
if tmpl_topic_vars.CurrentUser.Perms.EditTopic {
|
||||||
w.Write(topic_frags[26])
|
|
||||||
w.Write([]byte(tmpl_topic_vars.Topic.Title))
|
|
||||||
w.Write(topic_frags[27])
|
|
||||||
w.Write(phrases[26])
|
|
||||||
w.Write(topic_frags[28])
|
w.Write(topic_frags[28])
|
||||||
w.Write(phrases[27])
|
w.Write([]byte(tmpl_topic_vars.Topic.Title))
|
||||||
w.Write(topic_frags[29])
|
w.Write(topic_frags[29])
|
||||||
}
|
w.Write(phrases[26])
|
||||||
w.Write(topic_frags[30])
|
w.Write(topic_frags[30])
|
||||||
if tmpl_topic_vars.Poll.ID > 0 {
|
w.Write(phrases[27])
|
||||||
w.Write(topic_frags[31])
|
w.Write(topic_frags[31])
|
||||||
w.Write(phrases[28])
|
|
||||||
w.Write(topic_frags[32])
|
|
||||||
w.Write([]byte(tmpl_topic_vars.Topic.ClassName))
|
|
||||||
w.Write(topic_frags[33])
|
|
||||||
w.Write([]byte(tmpl_topic_vars.Topic.Avatar))
|
|
||||||
w.Write(topic_frags[34])
|
|
||||||
w.Write([]byte(tmpl_topic_vars.Header.Theme.Name))
|
|
||||||
w.Write(topic_frags[35])
|
|
||||||
if tmpl_topic_vars.Topic.ContentLines <= 5 {
|
|
||||||
w.Write(topic_frags[36])
|
|
||||||
}
|
}
|
||||||
|
w.Write(topic_frags[32])
|
||||||
|
if tmpl_topic_vars.Poll.ID > 0 {
|
||||||
|
w.Write(topic_frags[33])
|
||||||
|
w.Write(phrases[28])
|
||||||
|
w.Write(topic_frags[34])
|
||||||
|
w.Write([]byte(tmpl_topic_vars.Topic.ClassName))
|
||||||
|
w.Write(topic_frags[35])
|
||||||
|
w.Write([]byte(tmpl_topic_vars.Topic.Avatar))
|
||||||
|
w.Write(topic_frags[36])
|
||||||
|
w.Write([]byte(tmpl_topic_vars.Header.Theme.Name))
|
||||||
w.Write(topic_frags[37])
|
w.Write(topic_frags[37])
|
||||||
|
if tmpl_topic_vars.Topic.ContentLines <= 5 {
|
||||||
|
w.Write(topic_frags[38])
|
||||||
|
}
|
||||||
|
w.Write(topic_frags[39])
|
||||||
if len(tmpl_topic_vars.Poll.QuickOptions) != 0 {
|
if len(tmpl_topic_vars.Poll.QuickOptions) != 0 {
|
||||||
for _, item := range tmpl_topic_vars.Poll.QuickOptions {
|
for _, item := range tmpl_topic_vars.Poll.QuickOptions {
|
||||||
w.Write(topic_frags[38])
|
|
||||||
w.Write([]byte(strconv.Itoa(tmpl_topic_vars.Poll.ID)))
|
|
||||||
w.Write(topic_frags[39])
|
|
||||||
w.Write([]byte(strconv.Itoa(item.ID)))
|
|
||||||
w.Write(topic_frags[40])
|
w.Write(topic_frags[40])
|
||||||
w.Write([]byte(strconv.Itoa(item.ID)))
|
w.Write([]byte(strconv.Itoa(tmpl_topic_vars.Poll.ID)))
|
||||||
w.Write(topic_frags[41])
|
w.Write(topic_frags[41])
|
||||||
w.Write([]byte(strconv.Itoa(item.ID)))
|
w.Write([]byte(strconv.Itoa(item.ID)))
|
||||||
w.Write(topic_frags[42])
|
w.Write(topic_frags[42])
|
||||||
w.Write([]byte(strconv.Itoa(item.ID)))
|
w.Write([]byte(strconv.Itoa(item.ID)))
|
||||||
w.Write(topic_frags[43])
|
w.Write(topic_frags[43])
|
||||||
w.Write([]byte(item.Value))
|
w.Write([]byte(strconv.Itoa(item.ID)))
|
||||||
w.Write(topic_frags[44])
|
w.Write(topic_frags[44])
|
||||||
}
|
w.Write([]byte(strconv.Itoa(item.ID)))
|
||||||
}
|
|
||||||
w.Write(topic_frags[45])
|
w.Write(topic_frags[45])
|
||||||
w.Write([]byte(strconv.Itoa(tmpl_topic_vars.Poll.ID)))
|
w.Write([]byte(item.Value))
|
||||||
w.Write(topic_frags[46])
|
w.Write(topic_frags[46])
|
||||||
w.Write(phrases[29])
|
}
|
||||||
|
}
|
||||||
w.Write(topic_frags[47])
|
w.Write(topic_frags[47])
|
||||||
w.Write([]byte(strconv.Itoa(tmpl_topic_vars.Poll.ID)))
|
w.Write([]byte(strconv.Itoa(tmpl_topic_vars.Poll.ID)))
|
||||||
w.Write(topic_frags[48])
|
w.Write(topic_frags[48])
|
||||||
w.Write(phrases[30])
|
w.Write(phrases[29])
|
||||||
w.Write(topic_frags[49])
|
w.Write(topic_frags[49])
|
||||||
w.Write(phrases[31])
|
|
||||||
w.Write(topic_frags[50])
|
|
||||||
w.Write([]byte(strconv.Itoa(tmpl_topic_vars.Poll.ID)))
|
w.Write([]byte(strconv.Itoa(tmpl_topic_vars.Poll.ID)))
|
||||||
|
w.Write(topic_frags[50])
|
||||||
|
w.Write(phrases[30])
|
||||||
w.Write(topic_frags[51])
|
w.Write(topic_frags[51])
|
||||||
}
|
w.Write(phrases[31])
|
||||||
w.Write(topic_frags[52])
|
w.Write(topic_frags[52])
|
||||||
w.Write(phrases[32])
|
w.Write([]byte(strconv.Itoa(tmpl_topic_vars.Poll.ID)))
|
||||||
w.Write(topic_frags[53])
|
w.Write(topic_frags[53])
|
||||||
w.Write([]byte(tmpl_topic_vars.Topic.ClassName))
|
}
|
||||||
w.Write(topic_frags[54])
|
w.Write(topic_frags[54])
|
||||||
w.Write([]byte(tmpl_topic_vars.Topic.Avatar))
|
|
||||||
w.Write(topic_frags[55])
|
w.Write(topic_frags[55])
|
||||||
w.Write([]byte(tmpl_topic_vars.Header.Theme.Name))
|
w.Write(phrases[32])
|
||||||
w.Write(topic_frags[56])
|
w.Write(topic_frags[56])
|
||||||
if tmpl_topic_vars.Topic.ContentLines <= 5 {
|
w.Write([]byte(tmpl_topic_vars.Topic.ClassName))
|
||||||
w.Write(topic_frags[57])
|
w.Write(topic_frags[57])
|
||||||
}
|
w.Write([]byte(tmpl_topic_vars.Topic.Avatar))
|
||||||
w.Write(topic_frags[58])
|
w.Write(topic_frags[58])
|
||||||
w.Write([]byte(tmpl_topic_vars.Topic.ContentHTML))
|
w.Write([]byte(tmpl_topic_vars.Header.Theme.Name))
|
||||||
w.Write(topic_frags[59])
|
w.Write(topic_frags[59])
|
||||||
w.Write([]byte(tmpl_topic_vars.Topic.Content))
|
if tmpl_topic_vars.Topic.ContentLines <= 5 {
|
||||||
w.Write(topic_frags[60])
|
w.Write(topic_frags[60])
|
||||||
w.Write(phrases[33])
|
}
|
||||||
w.Write(topic_frags[61])
|
w.Write(topic_frags[61])
|
||||||
w.Write([]byte(tmpl_topic_vars.Topic.UserLink))
|
w.Write([]byte(tmpl_topic_vars.Topic.ContentHTML))
|
||||||
w.Write(topic_frags[62])
|
w.Write(topic_frags[62])
|
||||||
w.Write([]byte(tmpl_topic_vars.Topic.CreatedByName))
|
w.Write([]byte(tmpl_topic_vars.Topic.Content))
|
||||||
w.Write(topic_frags[63])
|
w.Write(topic_frags[63])
|
||||||
if tmpl_topic_vars.CurrentUser.Perms.LikeItem {
|
if tmpl_topic_vars.Topic.LikeCount > 0 {
|
||||||
w.Write(topic_frags[64])
|
w.Write(topic_frags[64])
|
||||||
w.Write([]byte(strconv.Itoa(tmpl_topic_vars.Topic.ID)))
|
}
|
||||||
w.Write(topic_frags[65])
|
w.Write(topic_frags[65])
|
||||||
w.Write([]byte(tmpl_topic_vars.CurrentUser.Session))
|
w.Write(phrases[33])
|
||||||
w.Write(topic_frags[66])
|
w.Write(topic_frags[66])
|
||||||
if tmpl_topic_vars.Topic.Liked {
|
w.Write([]byte(tmpl_topic_vars.Topic.UserLink))
|
||||||
w.Write(topic_frags[67])
|
w.Write(topic_frags[67])
|
||||||
w.Write(phrases[34])
|
w.Write([]byte(tmpl_topic_vars.Topic.CreatedByName))
|
||||||
w.Write(topic_frags[68])
|
w.Write(topic_frags[68])
|
||||||
w.Write(phrases[35])
|
if tmpl_topic_vars.CurrentUser.Perms.LikeItem {
|
||||||
w.Write(topic_frags[69])
|
w.Write(topic_frags[69])
|
||||||
} else {
|
w.Write([]byte(strconv.Itoa(tmpl_topic_vars.Topic.ID)))
|
||||||
w.Write(topic_frags[70])
|
w.Write(topic_frags[70])
|
||||||
w.Write(phrases[36])
|
w.Write([]byte(tmpl_topic_vars.CurrentUser.Session))
|
||||||
w.Write(topic_frags[71])
|
w.Write(topic_frags[71])
|
||||||
w.Write(phrases[37])
|
|
||||||
w.Write(topic_frags[72])
|
|
||||||
}
|
|
||||||
w.Write(topic_frags[73])
|
|
||||||
if tmpl_topic_vars.Topic.Liked {
|
if tmpl_topic_vars.Topic.Liked {
|
||||||
|
w.Write(topic_frags[72])
|
||||||
|
w.Write(phrases[34])
|
||||||
|
w.Write(topic_frags[73])
|
||||||
|
w.Write(phrases[35])
|
||||||
w.Write(topic_frags[74])
|
w.Write(topic_frags[74])
|
||||||
}
|
} else {
|
||||||
w.Write(topic_frags[75])
|
w.Write(topic_frags[75])
|
||||||
|
w.Write(phrases[36])
|
||||||
|
w.Write(topic_frags[76])
|
||||||
|
w.Write(phrases[37])
|
||||||
|
w.Write(topic_frags[77])
|
||||||
|
}
|
||||||
|
w.Write(topic_frags[78])
|
||||||
|
if tmpl_topic_vars.Topic.Liked {
|
||||||
|
w.Write(topic_frags[79])
|
||||||
|
} else {
|
||||||
|
w.Write(topic_frags[80])
|
||||||
|
}
|
||||||
|
w.Write(topic_frags[81])
|
||||||
}
|
}
|
||||||
if tmpl_topic_vars.CurrentUser.Perms.EditTopic {
|
if tmpl_topic_vars.CurrentUser.Perms.EditTopic {
|
||||||
w.Write(topic_frags[76])
|
w.Write(topic_frags[82])
|
||||||
w.Write([]byte(strconv.Itoa(tmpl_topic_vars.Topic.ID)))
|
w.Write([]byte(strconv.Itoa(tmpl_topic_vars.Topic.ID)))
|
||||||
w.Write(topic_frags[77])
|
w.Write(topic_frags[83])
|
||||||
w.Write(phrases[38])
|
w.Write(phrases[38])
|
||||||
w.Write(topic_frags[78])
|
w.Write(topic_frags[84])
|
||||||
w.Write(phrases[39])
|
w.Write(phrases[39])
|
||||||
w.Write(topic_frags[79])
|
w.Write(topic_frags[85])
|
||||||
}
|
}
|
||||||
if tmpl_topic_vars.CurrentUser.Perms.DeleteTopic {
|
if tmpl_topic_vars.CurrentUser.Perms.DeleteTopic {
|
||||||
w.Write(topic_frags[80])
|
w.Write(topic_frags[86])
|
||||||
w.Write([]byte(strconv.Itoa(tmpl_topic_vars.Topic.ID)))
|
w.Write([]byte(strconv.Itoa(tmpl_topic_vars.Topic.ID)))
|
||||||
w.Write(topic_frags[81])
|
w.Write(topic_frags[87])
|
||||||
w.Write([]byte(tmpl_topic_vars.CurrentUser.Session))
|
w.Write([]byte(tmpl_topic_vars.CurrentUser.Session))
|
||||||
w.Write(topic_frags[82])
|
w.Write(topic_frags[88])
|
||||||
w.Write(phrases[40])
|
w.Write(phrases[40])
|
||||||
w.Write(topic_frags[83])
|
w.Write(topic_frags[89])
|
||||||
w.Write(phrases[41])
|
w.Write(phrases[41])
|
||||||
w.Write(topic_frags[84])
|
w.Write(topic_frags[90])
|
||||||
}
|
}
|
||||||
if tmpl_topic_vars.CurrentUser.Perms.CloseTopic {
|
if tmpl_topic_vars.CurrentUser.Perms.CloseTopic {
|
||||||
if tmpl_topic_vars.Topic.IsClosed {
|
if tmpl_topic_vars.Topic.IsClosed {
|
||||||
w.Write(topic_frags[85])
|
|
||||||
w.Write([]byte(strconv.Itoa(tmpl_topic_vars.Topic.ID)))
|
|
||||||
w.Write(topic_frags[86])
|
|
||||||
w.Write([]byte(tmpl_topic_vars.CurrentUser.Session))
|
|
||||||
w.Write(topic_frags[87])
|
|
||||||
w.Write(phrases[42])
|
|
||||||
w.Write(topic_frags[88])
|
|
||||||
w.Write(phrases[43])
|
|
||||||
w.Write(topic_frags[89])
|
|
||||||
} else {
|
|
||||||
w.Write(topic_frags[90])
|
|
||||||
w.Write([]byte(strconv.Itoa(tmpl_topic_vars.Topic.ID)))
|
|
||||||
w.Write(topic_frags[91])
|
w.Write(topic_frags[91])
|
||||||
w.Write([]byte(tmpl_topic_vars.CurrentUser.Session))
|
w.Write([]byte(strconv.Itoa(tmpl_topic_vars.Topic.ID)))
|
||||||
w.Write(topic_frags[92])
|
w.Write(topic_frags[92])
|
||||||
w.Write(phrases[44])
|
w.Write([]byte(tmpl_topic_vars.CurrentUser.Session))
|
||||||
w.Write(topic_frags[93])
|
w.Write(topic_frags[93])
|
||||||
w.Write(phrases[45])
|
w.Write(phrases[42])
|
||||||
w.Write(topic_frags[94])
|
w.Write(topic_frags[94])
|
||||||
|
w.Write(phrases[43])
|
||||||
|
w.Write(topic_frags[95])
|
||||||
|
} else {
|
||||||
|
w.Write(topic_frags[96])
|
||||||
|
w.Write([]byte(strconv.Itoa(tmpl_topic_vars.Topic.ID)))
|
||||||
|
w.Write(topic_frags[97])
|
||||||
|
w.Write([]byte(tmpl_topic_vars.CurrentUser.Session))
|
||||||
|
w.Write(topic_frags[98])
|
||||||
|
w.Write(phrases[44])
|
||||||
|
w.Write(topic_frags[99])
|
||||||
|
w.Write(phrases[45])
|
||||||
|
w.Write(topic_frags[100])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if tmpl_topic_vars.CurrentUser.Perms.PinTopic {
|
if tmpl_topic_vars.CurrentUser.Perms.PinTopic {
|
||||||
if tmpl_topic_vars.Topic.Sticky {
|
if tmpl_topic_vars.Topic.Sticky {
|
||||||
w.Write(topic_frags[95])
|
|
||||||
w.Write([]byte(strconv.Itoa(tmpl_topic_vars.Topic.ID)))
|
|
||||||
w.Write(topic_frags[96])
|
|
||||||
w.Write([]byte(tmpl_topic_vars.CurrentUser.Session))
|
|
||||||
w.Write(topic_frags[97])
|
|
||||||
w.Write(phrases[46])
|
|
||||||
w.Write(topic_frags[98])
|
|
||||||
w.Write(phrases[47])
|
|
||||||
w.Write(topic_frags[99])
|
|
||||||
} else {
|
|
||||||
w.Write(topic_frags[100])
|
|
||||||
w.Write([]byte(strconv.Itoa(tmpl_topic_vars.Topic.ID)))
|
|
||||||
w.Write(topic_frags[101])
|
w.Write(topic_frags[101])
|
||||||
w.Write([]byte(tmpl_topic_vars.CurrentUser.Session))
|
w.Write([]byte(strconv.Itoa(tmpl_topic_vars.Topic.ID)))
|
||||||
w.Write(topic_frags[102])
|
w.Write(topic_frags[102])
|
||||||
w.Write(phrases[48])
|
w.Write([]byte(tmpl_topic_vars.CurrentUser.Session))
|
||||||
w.Write(topic_frags[103])
|
w.Write(topic_frags[103])
|
||||||
w.Write(phrases[49])
|
w.Write(phrases[46])
|
||||||
w.Write(topic_frags[104])
|
w.Write(topic_frags[104])
|
||||||
|
w.Write(phrases[47])
|
||||||
|
w.Write(topic_frags[105])
|
||||||
|
} else {
|
||||||
|
w.Write(topic_frags[106])
|
||||||
|
w.Write([]byte(strconv.Itoa(tmpl_topic_vars.Topic.ID)))
|
||||||
|
w.Write(topic_frags[107])
|
||||||
|
w.Write([]byte(tmpl_topic_vars.CurrentUser.Session))
|
||||||
|
w.Write(topic_frags[108])
|
||||||
|
w.Write(phrases[48])
|
||||||
|
w.Write(topic_frags[109])
|
||||||
|
w.Write(phrases[49])
|
||||||
|
w.Write(topic_frags[110])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if tmpl_topic_vars.CurrentUser.Perms.ViewIPs {
|
if tmpl_topic_vars.CurrentUser.Perms.ViewIPs {
|
||||||
w.Write(topic_frags[105])
|
|
||||||
w.Write([]byte(tmpl_topic_vars.Topic.IPAddress))
|
|
||||||
w.Write(topic_frags[106])
|
|
||||||
w.Write(phrases[50])
|
|
||||||
w.Write(topic_frags[107])
|
|
||||||
w.Write([]byte(tmpl_topic_vars.Topic.IPAddress))
|
|
||||||
w.Write(topic_frags[108])
|
|
||||||
}
|
|
||||||
w.Write(topic_frags[109])
|
|
||||||
w.Write([]byte(strconv.Itoa(tmpl_topic_vars.Topic.ID)))
|
|
||||||
w.Write(topic_frags[110])
|
|
||||||
w.Write([]byte(tmpl_topic_vars.CurrentUser.Session))
|
|
||||||
w.Write(topic_frags[111])
|
w.Write(topic_frags[111])
|
||||||
w.Write(phrases[51])
|
w.Write([]byte(tmpl_topic_vars.Topic.IPAddress))
|
||||||
w.Write(topic_frags[112])
|
w.Write(topic_frags[112])
|
||||||
w.Write(phrases[52])
|
w.Write(phrases[50])
|
||||||
w.Write(topic_frags[113])
|
w.Write(topic_frags[113])
|
||||||
if tmpl_topic_vars.Topic.LikeCount > 0 {
|
w.Write([]byte(tmpl_topic_vars.Topic.IPAddress))
|
||||||
w.Write(topic_frags[114])
|
w.Write(topic_frags[114])
|
||||||
w.Write(phrases[53])
|
}
|
||||||
w.Write(topic_frags[115])
|
w.Write(topic_frags[115])
|
||||||
w.Write([]byte(strconv.Itoa(tmpl_topic_vars.Topic.LikeCount)))
|
w.Write([]byte(strconv.Itoa(tmpl_topic_vars.Topic.ID)))
|
||||||
w.Write(topic_frags[116])
|
w.Write(topic_frags[116])
|
||||||
w.Write(phrases[54])
|
w.Write([]byte(tmpl_topic_vars.CurrentUser.Session))
|
||||||
w.Write(topic_frags[117])
|
w.Write(topic_frags[117])
|
||||||
}
|
w.Write(phrases[51])
|
||||||
if tmpl_topic_vars.Topic.Tag != "" {
|
|
||||||
w.Write(topic_frags[118])
|
w.Write(topic_frags[118])
|
||||||
w.Write([]byte(tmpl_topic_vars.Topic.Tag))
|
w.Write(phrases[52])
|
||||||
w.Write(topic_frags[119])
|
w.Write(topic_frags[119])
|
||||||
} else {
|
w.Write(phrases[53])
|
||||||
w.Write(topic_frags[120])
|
w.Write(topic_frags[120])
|
||||||
w.Write(phrases[55])
|
w.Write([]byte(strconv.Itoa(tmpl_topic_vars.Topic.LikeCount)))
|
||||||
w.Write(topic_frags[121])
|
w.Write(topic_frags[121])
|
||||||
w.Write([]byte(strconv.Itoa(tmpl_topic_vars.Topic.Level)))
|
w.Write(phrases[54])
|
||||||
w.Write(topic_frags[122])
|
w.Write(topic_frags[122])
|
||||||
w.Write(phrases[56])
|
if tmpl_topic_vars.Topic.Tag != "" {
|
||||||
w.Write(topic_frags[123])
|
w.Write(topic_frags[123])
|
||||||
}
|
w.Write([]byte(tmpl_topic_vars.Topic.Tag))
|
||||||
w.Write(topic_frags[124])
|
w.Write(topic_frags[124])
|
||||||
w.Write(phrases[57])
|
} else {
|
||||||
w.Write(topic_frags[125])
|
w.Write(topic_frags[125])
|
||||||
|
w.Write(phrases[55])
|
||||||
|
w.Write(topic_frags[126])
|
||||||
|
w.Write([]byte(strconv.Itoa(tmpl_topic_vars.Topic.Level)))
|
||||||
|
w.Write(topic_frags[127])
|
||||||
|
w.Write(phrases[56])
|
||||||
|
w.Write(topic_frags[128])
|
||||||
|
}
|
||||||
|
w.Write(topic_frags[129])
|
||||||
|
w.Write(phrases[57])
|
||||||
|
w.Write(topic_frags[130])
|
||||||
if len(tmpl_topic_vars.ItemList) != 0 {
|
if len(tmpl_topic_vars.ItemList) != 0 {
|
||||||
for _, item := range tmpl_topic_vars.ItemList {
|
for _, item := range tmpl_topic_vars.ItemList {
|
||||||
if item.ActionType != "" {
|
if item.ActionType != "" {
|
||||||
w.Write(topic_frags[126])
|
|
||||||
w.Write([]byte(item.ActionIcon))
|
|
||||||
w.Write(topic_frags[127])
|
|
||||||
w.Write([]byte(item.ActionType))
|
|
||||||
w.Write(topic_frags[128])
|
|
||||||
} else {
|
|
||||||
w.Write(topic_frags[129])
|
|
||||||
w.Write([]byte(item.ClassName))
|
|
||||||
w.Write(topic_frags[130])
|
|
||||||
w.Write([]byte(item.Avatar))
|
|
||||||
w.Write(topic_frags[131])
|
w.Write(topic_frags[131])
|
||||||
w.Write([]byte(tmpl_topic_vars.Header.Theme.Name))
|
w.Write([]byte(item.ActionIcon))
|
||||||
w.Write(topic_frags[132])
|
w.Write(topic_frags[132])
|
||||||
if item.ContentLines <= 5 {
|
w.Write([]byte(item.ActionType))
|
||||||
w.Write(topic_frags[133])
|
w.Write(topic_frags[133])
|
||||||
}
|
} else {
|
||||||
w.Write(topic_frags[134])
|
w.Write(topic_frags[134])
|
||||||
w.Write(topic_frags[135])
|
w.Write(topic_frags[135])
|
||||||
w.Write([]byte(item.ContentHtml))
|
w.Write([]byte(item.ClassName))
|
||||||
w.Write(topic_frags[136])
|
w.Write(topic_frags[136])
|
||||||
w.Write([]byte(item.UserLink))
|
w.Write([]byte(item.Avatar))
|
||||||
w.Write(topic_frags[137])
|
w.Write(topic_frags[137])
|
||||||
w.Write([]byte(item.CreatedByName))
|
w.Write([]byte(tmpl_topic_vars.Header.Theme.Name))
|
||||||
w.Write(topic_frags[138])
|
w.Write(topic_frags[138])
|
||||||
|
if item.ContentLines <= 5 {
|
||||||
|
w.Write(topic_frags[139])
|
||||||
|
}
|
||||||
|
w.Write(topic_frags[140])
|
||||||
|
w.Write(topic_frags[141])
|
||||||
|
w.Write([]byte(item.ContentHtml))
|
||||||
|
w.Write(topic_frags[142])
|
||||||
|
if item.LikeCount > 0 {
|
||||||
|
w.Write(topic_frags[143])
|
||||||
|
}
|
||||||
|
w.Write(topic_frags[144])
|
||||||
|
w.Write([]byte(item.UserLink))
|
||||||
|
w.Write(topic_frags[145])
|
||||||
|
w.Write([]byte(item.CreatedByName))
|
||||||
|
w.Write(topic_frags[146])
|
||||||
if tmpl_topic_vars.CurrentUser.Perms.LikeItem {
|
if tmpl_topic_vars.CurrentUser.Perms.LikeItem {
|
||||||
if item.Liked {
|
if item.Liked {
|
||||||
w.Write(topic_frags[139])
|
|
||||||
w.Write([]byte(strconv.Itoa(item.ID)))
|
|
||||||
w.Write(topic_frags[140])
|
|
||||||
w.Write([]byte(tmpl_topic_vars.CurrentUser.Session))
|
|
||||||
w.Write(topic_frags[141])
|
|
||||||
w.Write(phrases[58])
|
|
||||||
w.Write(topic_frags[142])
|
|
||||||
w.Write(phrases[59])
|
|
||||||
w.Write(topic_frags[143])
|
|
||||||
} else {
|
|
||||||
w.Write(topic_frags[144])
|
|
||||||
w.Write([]byte(strconv.Itoa(item.ID)))
|
|
||||||
w.Write(topic_frags[145])
|
|
||||||
w.Write([]byte(tmpl_topic_vars.CurrentUser.Session))
|
|
||||||
w.Write(topic_frags[146])
|
|
||||||
w.Write(phrases[60])
|
|
||||||
w.Write(topic_frags[147])
|
w.Write(topic_frags[147])
|
||||||
w.Write(phrases[61])
|
w.Write([]byte(strconv.Itoa(item.ID)))
|
||||||
w.Write(topic_frags[148])
|
w.Write(topic_frags[148])
|
||||||
|
w.Write([]byte(tmpl_topic_vars.CurrentUser.Session))
|
||||||
|
w.Write(topic_frags[149])
|
||||||
|
w.Write(phrases[58])
|
||||||
|
w.Write(topic_frags[150])
|
||||||
|
w.Write(phrases[59])
|
||||||
|
w.Write(topic_frags[151])
|
||||||
|
} else {
|
||||||
|
w.Write(topic_frags[152])
|
||||||
|
w.Write([]byte(strconv.Itoa(item.ID)))
|
||||||
|
w.Write(topic_frags[153])
|
||||||
|
w.Write([]byte(tmpl_topic_vars.CurrentUser.Session))
|
||||||
|
w.Write(topic_frags[154])
|
||||||
|
w.Write(phrases[60])
|
||||||
|
w.Write(topic_frags[155])
|
||||||
|
w.Write(phrases[61])
|
||||||
|
w.Write(topic_frags[156])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if tmpl_topic_vars.CurrentUser.Perms.EditReply {
|
if tmpl_topic_vars.CurrentUser.Perms.EditReply {
|
||||||
w.Write(topic_frags[149])
|
w.Write(topic_frags[157])
|
||||||
w.Write([]byte(strconv.Itoa(item.ID)))
|
w.Write([]byte(strconv.Itoa(item.ID)))
|
||||||
w.Write(topic_frags[150])
|
w.Write(topic_frags[158])
|
||||||
w.Write([]byte(tmpl_topic_vars.CurrentUser.Session))
|
w.Write([]byte(tmpl_topic_vars.CurrentUser.Session))
|
||||||
w.Write(topic_frags[151])
|
w.Write(topic_frags[159])
|
||||||
w.Write(phrases[62])
|
w.Write(phrases[62])
|
||||||
w.Write(topic_frags[152])
|
w.Write(topic_frags[160])
|
||||||
w.Write(phrases[63])
|
w.Write(phrases[63])
|
||||||
w.Write(topic_frags[153])
|
w.Write(topic_frags[161])
|
||||||
}
|
}
|
||||||
if tmpl_topic_vars.CurrentUser.Perms.DeleteReply {
|
if tmpl_topic_vars.CurrentUser.Perms.DeleteReply {
|
||||||
w.Write(topic_frags[154])
|
w.Write(topic_frags[162])
|
||||||
w.Write([]byte(strconv.Itoa(item.ID)))
|
w.Write([]byte(strconv.Itoa(item.ID)))
|
||||||
w.Write(topic_frags[155])
|
w.Write(topic_frags[163])
|
||||||
w.Write([]byte(tmpl_topic_vars.CurrentUser.Session))
|
w.Write([]byte(tmpl_topic_vars.CurrentUser.Session))
|
||||||
w.Write(topic_frags[156])
|
w.Write(topic_frags[164])
|
||||||
w.Write(phrases[64])
|
w.Write(phrases[64])
|
||||||
w.Write(topic_frags[157])
|
w.Write(topic_frags[165])
|
||||||
w.Write(phrases[65])
|
w.Write(phrases[65])
|
||||||
w.Write(topic_frags[158])
|
w.Write(topic_frags[166])
|
||||||
}
|
}
|
||||||
if tmpl_topic_vars.CurrentUser.Perms.ViewIPs {
|
if tmpl_topic_vars.CurrentUser.Perms.ViewIPs {
|
||||||
w.Write(topic_frags[159])
|
|
||||||
w.Write([]byte(item.IPAddress))
|
|
||||||
w.Write(topic_frags[160])
|
|
||||||
w.Write(phrases[66])
|
|
||||||
w.Write(topic_frags[161])
|
|
||||||
w.Write([]byte(item.IPAddress))
|
|
||||||
w.Write(topic_frags[162])
|
|
||||||
}
|
|
||||||
w.Write(topic_frags[163])
|
|
||||||
w.Write([]byte(strconv.Itoa(item.ID)))
|
|
||||||
w.Write(topic_frags[164])
|
|
||||||
w.Write([]byte(tmpl_topic_vars.CurrentUser.Session))
|
|
||||||
w.Write(topic_frags[165])
|
|
||||||
w.Write(phrases[67])
|
|
||||||
w.Write(topic_frags[166])
|
|
||||||
w.Write(phrases[68])
|
|
||||||
w.Write(topic_frags[167])
|
w.Write(topic_frags[167])
|
||||||
if item.LikeCount > 0 {
|
w.Write([]byte(item.IPAddress))
|
||||||
w.Write(topic_frags[168])
|
w.Write(topic_frags[168])
|
||||||
w.Write([]byte(strconv.Itoa(item.LikeCount)))
|
w.Write(phrases[66])
|
||||||
w.Write(topic_frags[169])
|
w.Write(topic_frags[169])
|
||||||
w.Write(phrases[69])
|
w.Write([]byte(item.IPAddress))
|
||||||
w.Write(topic_frags[170])
|
w.Write(topic_frags[170])
|
||||||
}
|
}
|
||||||
if item.Tag != "" {
|
|
||||||
w.Write(topic_frags[171])
|
w.Write(topic_frags[171])
|
||||||
w.Write([]byte(item.Tag))
|
w.Write([]byte(strconv.Itoa(item.ID)))
|
||||||
w.Write(topic_frags[172])
|
w.Write(topic_frags[172])
|
||||||
} else {
|
|
||||||
w.Write(topic_frags[173])
|
|
||||||
w.Write(phrases[70])
|
|
||||||
w.Write(topic_frags[174])
|
|
||||||
w.Write([]byte(strconv.Itoa(item.Level)))
|
|
||||||
w.Write(topic_frags[175])
|
|
||||||
w.Write(phrases[71])
|
|
||||||
w.Write(topic_frags[176])
|
|
||||||
}
|
|
||||||
w.Write(topic_frags[177])
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
w.Write(topic_frags[178])
|
|
||||||
if tmpl_topic_vars.CurrentUser.Perms.CreateReply {
|
|
||||||
w.Write(topic_frags[179])
|
|
||||||
w.Write(phrases[72])
|
|
||||||
w.Write(topic_frags[180])
|
|
||||||
w.Write([]byte(tmpl_topic_vars.CurrentUser.Session))
|
w.Write([]byte(tmpl_topic_vars.CurrentUser.Session))
|
||||||
|
w.Write(topic_frags[173])
|
||||||
|
w.Write(phrases[67])
|
||||||
|
w.Write(topic_frags[174])
|
||||||
|
w.Write(phrases[68])
|
||||||
|
w.Write(topic_frags[175])
|
||||||
|
w.Write([]byte(strconv.Itoa(item.LikeCount)))
|
||||||
|
w.Write(topic_frags[176])
|
||||||
|
w.Write(phrases[69])
|
||||||
|
w.Write(topic_frags[177])
|
||||||
|
if item.Tag != "" {
|
||||||
|
w.Write(topic_frags[178])
|
||||||
|
w.Write([]byte(item.Tag))
|
||||||
|
w.Write(topic_frags[179])
|
||||||
|
} else {
|
||||||
|
w.Write(topic_frags[180])
|
||||||
|
w.Write(phrases[70])
|
||||||
w.Write(topic_frags[181])
|
w.Write(topic_frags[181])
|
||||||
w.Write([]byte(strconv.Itoa(tmpl_topic_vars.Topic.ID)))
|
w.Write([]byte(strconv.Itoa(item.Level)))
|
||||||
w.Write(topic_frags[182])
|
w.Write(topic_frags[182])
|
||||||
w.Write(phrases[73])
|
w.Write(phrases[71])
|
||||||
w.Write(topic_frags[183])
|
w.Write(topic_frags[183])
|
||||||
w.Write(phrases[74])
|
}
|
||||||
w.Write(topic_frags[184])
|
w.Write(topic_frags[184])
|
||||||
w.Write(phrases[75])
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
w.Write(topic_frags[185])
|
w.Write(topic_frags[185])
|
||||||
w.Write(phrases[76])
|
if tmpl_topic_vars.CurrentUser.Perms.CreateReply {
|
||||||
w.Write(topic_frags[186])
|
w.Write(topic_frags[186])
|
||||||
if tmpl_topic_vars.CurrentUser.Perms.UploadFiles {
|
w.Write(phrases[72])
|
||||||
w.Write(topic_frags[187])
|
w.Write(topic_frags[187])
|
||||||
w.Write(phrases[77])
|
w.Write([]byte(tmpl_topic_vars.CurrentUser.Session))
|
||||||
w.Write(topic_frags[188])
|
w.Write(topic_frags[188])
|
||||||
}
|
w.Write([]byte(strconv.Itoa(tmpl_topic_vars.Topic.ID)))
|
||||||
w.Write(topic_frags[189])
|
w.Write(topic_frags[189])
|
||||||
}
|
w.Write(phrases[73])
|
||||||
w.Write(topic_frags[190])
|
w.Write(topic_frags[190])
|
||||||
|
w.Write(phrases[74])
|
||||||
|
w.Write(topic_frags[191])
|
||||||
|
w.Write(phrases[75])
|
||||||
|
w.Write(topic_frags[192])
|
||||||
|
w.Write(phrases[76])
|
||||||
|
w.Write(topic_frags[193])
|
||||||
|
if tmpl_topic_vars.CurrentUser.Perms.UploadFiles {
|
||||||
|
w.Write(topic_frags[194])
|
||||||
|
w.Write(phrases[77])
|
||||||
|
w.Write(topic_frags[195])
|
||||||
|
}
|
||||||
|
w.Write(topic_frags[196])
|
||||||
|
}
|
||||||
|
w.Write(topic_frags[197])
|
||||||
w.Write(footer_frags[0])
|
w.Write(footer_frags[0])
|
||||||
w.Write([]byte(common.BuildWidget("footer",tmpl_topic_vars.Header)))
|
w.Write([]byte(common.BuildWidget("footer",tmpl_topic_vars.Header)))
|
||||||
w.Write(footer_frags[1])
|
w.Write(footer_frags[1])
|
||||||
|
|
|
@ -227,178 +227,173 @@ w.Write(phrases[22])
|
||||||
w.Write(topic_alt_frags[13])
|
w.Write(topic_alt_frags[13])
|
||||||
}
|
}
|
||||||
w.Write(topic_alt_frags[14])
|
w.Write(topic_alt_frags[14])
|
||||||
w.Write(phrases[23])
|
|
||||||
w.Write(topic_alt_frags[15])
|
w.Write(topic_alt_frags[15])
|
||||||
w.Write([]byte(strconv.Itoa(tmpl_topic_alt_vars.Topic.ID)))
|
w.Write(phrases[23])
|
||||||
w.Write(topic_alt_frags[16])
|
w.Write(topic_alt_frags[16])
|
||||||
w.Write([]byte(tmpl_topic_alt_vars.CurrentUser.Session))
|
w.Write([]byte(strconv.Itoa(tmpl_topic_alt_vars.Topic.ID)))
|
||||||
w.Write(topic_alt_frags[17])
|
w.Write(topic_alt_frags[17])
|
||||||
if tmpl_topic_alt_vars.Topic.Sticky {
|
w.Write([]byte(tmpl_topic_alt_vars.CurrentUser.Session))
|
||||||
w.Write(topic_alt_frags[18])
|
w.Write(topic_alt_frags[18])
|
||||||
|
if tmpl_topic_alt_vars.Topic.Sticky {
|
||||||
|
w.Write(topic_alt_frags[19])
|
||||||
} else {
|
} else {
|
||||||
if tmpl_topic_alt_vars.Topic.IsClosed {
|
if tmpl_topic_alt_vars.Topic.IsClosed {
|
||||||
w.Write(topic_alt_frags[19])
|
|
||||||
}
|
|
||||||
}
|
|
||||||
w.Write(topic_alt_frags[20])
|
w.Write(topic_alt_frags[20])
|
||||||
w.Write([]byte(tmpl_topic_alt_vars.Topic.Title))
|
}
|
||||||
|
}
|
||||||
w.Write(topic_alt_frags[21])
|
w.Write(topic_alt_frags[21])
|
||||||
if tmpl_topic_alt_vars.Topic.IsClosed {
|
w.Write([]byte(tmpl_topic_alt_vars.Topic.Title))
|
||||||
w.Write(topic_alt_frags[22])
|
w.Write(topic_alt_frags[22])
|
||||||
w.Write(phrases[24])
|
w.Write([]byte(tmpl_topic_alt_vars.Topic.Title))
|
||||||
w.Write(topic_alt_frags[23])
|
w.Write(topic_alt_frags[23])
|
||||||
w.Write(phrases[25])
|
if tmpl_topic_alt_vars.Topic.IsClosed {
|
||||||
w.Write(topic_alt_frags[24])
|
w.Write(topic_alt_frags[24])
|
||||||
|
w.Write(phrases[24])
|
||||||
|
w.Write(topic_alt_frags[25])
|
||||||
|
w.Write(phrases[25])
|
||||||
|
w.Write(topic_alt_frags[26])
|
||||||
}
|
}
|
||||||
if tmpl_topic_alt_vars.CurrentUser.Perms.EditTopic {
|
if tmpl_topic_alt_vars.CurrentUser.Perms.EditTopic {
|
||||||
w.Write(topic_alt_frags[25])
|
|
||||||
w.Write([]byte(tmpl_topic_alt_vars.Topic.Title))
|
|
||||||
w.Write(topic_alt_frags[26])
|
|
||||||
w.Write(phrases[26])
|
|
||||||
w.Write(topic_alt_frags[27])
|
w.Write(topic_alt_frags[27])
|
||||||
w.Write(phrases[27])
|
w.Write([]byte(tmpl_topic_alt_vars.Topic.Title))
|
||||||
w.Write(topic_alt_frags[28])
|
w.Write(topic_alt_frags[28])
|
||||||
}
|
w.Write(phrases[26])
|
||||||
w.Write(topic_alt_frags[29])
|
w.Write(topic_alt_frags[29])
|
||||||
if tmpl_topic_alt_vars.Poll.ID > 0 {
|
w.Write(phrases[27])
|
||||||
w.Write(topic_alt_frags[30])
|
w.Write(topic_alt_frags[30])
|
||||||
w.Write([]byte(strconv.Itoa(tmpl_topic_alt_vars.Poll.ID)))
|
}
|
||||||
w.Write(topic_alt_frags[31])
|
w.Write(topic_alt_frags[31])
|
||||||
w.Write([]byte(strconv.Itoa(tmpl_topic_alt_vars.Poll.ID)))
|
if tmpl_topic_alt_vars.Poll.ID > 0 {
|
||||||
w.Write(topic_alt_frags[32])
|
w.Write(topic_alt_frags[32])
|
||||||
w.Write([]byte(tmpl_topic_alt_vars.CurrentUser.Session))
|
w.Write([]byte(strconv.Itoa(tmpl_topic_alt_vars.Poll.ID)))
|
||||||
w.Write(topic_alt_frags[33])
|
w.Write(topic_alt_frags[33])
|
||||||
w.Write(phrases[28])
|
w.Write([]byte(strconv.Itoa(tmpl_topic_alt_vars.Poll.ID)))
|
||||||
w.Write(topic_alt_frags[34])
|
w.Write(topic_alt_frags[34])
|
||||||
w.Write([]byte(tmpl_topic_alt_vars.Topic.Avatar))
|
w.Write([]byte(tmpl_topic_alt_vars.CurrentUser.Session))
|
||||||
w.Write(topic_alt_frags[35])
|
w.Write(topic_alt_frags[35])
|
||||||
w.Write([]byte(tmpl_topic_alt_vars.Topic.UserLink))
|
w.Write(phrases[28])
|
||||||
w.Write(topic_alt_frags[36])
|
w.Write(topic_alt_frags[36])
|
||||||
w.Write([]byte(tmpl_topic_alt_vars.Topic.CreatedByName))
|
w.Write([]byte(tmpl_topic_alt_vars.Topic.Avatar))
|
||||||
w.Write(topic_alt_frags[37])
|
w.Write(topic_alt_frags[37])
|
||||||
if tmpl_topic_alt_vars.Topic.Tag != "" {
|
w.Write([]byte(tmpl_topic_alt_vars.Topic.UserLink))
|
||||||
w.Write(topic_alt_frags[38])
|
w.Write(topic_alt_frags[38])
|
||||||
w.Write([]byte(tmpl_topic_alt_vars.Topic.Tag))
|
w.Write([]byte(tmpl_topic_alt_vars.Topic.CreatedByName))
|
||||||
w.Write(topic_alt_frags[39])
|
w.Write(topic_alt_frags[39])
|
||||||
} else {
|
if tmpl_topic_alt_vars.Topic.Tag != "" {
|
||||||
w.Write(topic_alt_frags[40])
|
w.Write(topic_alt_frags[40])
|
||||||
|
w.Write([]byte(tmpl_topic_alt_vars.Topic.Tag))
|
||||||
|
w.Write(topic_alt_frags[41])
|
||||||
|
} else {
|
||||||
|
w.Write(topic_alt_frags[42])
|
||||||
w.Write(phrases[29])
|
w.Write(phrases[29])
|
||||||
w.Write([]byte(strconv.Itoa(tmpl_topic_alt_vars.Topic.Level)))
|
w.Write([]byte(strconv.Itoa(tmpl_topic_alt_vars.Topic.Level)))
|
||||||
w.Write(topic_alt_frags[41])
|
|
||||||
}
|
|
||||||
w.Write(topic_alt_frags[42])
|
|
||||||
w.Write([]byte(strconv.Itoa(tmpl_topic_alt_vars.Poll.ID)))
|
|
||||||
w.Write(topic_alt_frags[43])
|
w.Write(topic_alt_frags[43])
|
||||||
if len(tmpl_topic_alt_vars.Poll.QuickOptions) != 0 {
|
}
|
||||||
for _, item := range tmpl_topic_alt_vars.Poll.QuickOptions {
|
|
||||||
w.Write(topic_alt_frags[44])
|
w.Write(topic_alt_frags[44])
|
||||||
w.Write([]byte(strconv.Itoa(tmpl_topic_alt_vars.Poll.ID)))
|
w.Write([]byte(strconv.Itoa(tmpl_topic_alt_vars.Poll.ID)))
|
||||||
w.Write(topic_alt_frags[45])
|
w.Write(topic_alt_frags[45])
|
||||||
w.Write([]byte(strconv.Itoa(item.ID)))
|
if len(tmpl_topic_alt_vars.Poll.QuickOptions) != 0 {
|
||||||
|
for _, item := range tmpl_topic_alt_vars.Poll.QuickOptions {
|
||||||
w.Write(topic_alt_frags[46])
|
w.Write(topic_alt_frags[46])
|
||||||
w.Write([]byte(strconv.Itoa(item.ID)))
|
w.Write([]byte(strconv.Itoa(tmpl_topic_alt_vars.Poll.ID)))
|
||||||
w.Write(topic_alt_frags[47])
|
w.Write(topic_alt_frags[47])
|
||||||
w.Write([]byte(strconv.Itoa(item.ID)))
|
w.Write([]byte(strconv.Itoa(item.ID)))
|
||||||
w.Write(topic_alt_frags[48])
|
w.Write(topic_alt_frags[48])
|
||||||
w.Write([]byte(strconv.Itoa(item.ID)))
|
w.Write([]byte(strconv.Itoa(item.ID)))
|
||||||
w.Write(topic_alt_frags[49])
|
w.Write(topic_alt_frags[49])
|
||||||
w.Write([]byte(item.Value))
|
w.Write([]byte(strconv.Itoa(item.ID)))
|
||||||
w.Write(topic_alt_frags[50])
|
w.Write(topic_alt_frags[50])
|
||||||
}
|
w.Write([]byte(strconv.Itoa(item.ID)))
|
||||||
}
|
|
||||||
w.Write(topic_alt_frags[51])
|
w.Write(topic_alt_frags[51])
|
||||||
w.Write([]byte(strconv.Itoa(tmpl_topic_alt_vars.Poll.ID)))
|
w.Write([]byte(item.Value))
|
||||||
w.Write(topic_alt_frags[52])
|
w.Write(topic_alt_frags[52])
|
||||||
w.Write(phrases[30])
|
}
|
||||||
|
}
|
||||||
w.Write(topic_alt_frags[53])
|
w.Write(topic_alt_frags[53])
|
||||||
w.Write([]byte(strconv.Itoa(tmpl_topic_alt_vars.Poll.ID)))
|
w.Write([]byte(strconv.Itoa(tmpl_topic_alt_vars.Poll.ID)))
|
||||||
w.Write(topic_alt_frags[54])
|
w.Write(topic_alt_frags[54])
|
||||||
w.Write(phrases[31])
|
w.Write(phrases[30])
|
||||||
w.Write(topic_alt_frags[55])
|
w.Write(topic_alt_frags[55])
|
||||||
w.Write(phrases[32])
|
|
||||||
w.Write(topic_alt_frags[56])
|
|
||||||
w.Write([]byte(strconv.Itoa(tmpl_topic_alt_vars.Poll.ID)))
|
w.Write([]byte(strconv.Itoa(tmpl_topic_alt_vars.Poll.ID)))
|
||||||
|
w.Write(topic_alt_frags[56])
|
||||||
|
w.Write(phrases[31])
|
||||||
w.Write(topic_alt_frags[57])
|
w.Write(topic_alt_frags[57])
|
||||||
}
|
w.Write(phrases[32])
|
||||||
w.Write(topic_alt_frags[58])
|
w.Write(topic_alt_frags[58])
|
||||||
w.Write(phrases[33])
|
w.Write([]byte(strconv.Itoa(tmpl_topic_alt_vars.Poll.ID)))
|
||||||
w.Write(topic_alt_frags[59])
|
w.Write(topic_alt_frags[59])
|
||||||
w.Write(phrases[34])
|
}
|
||||||
w.Write(topic_alt_frags[60])
|
w.Write(topic_alt_frags[60])
|
||||||
w.Write([]byte(tmpl_topic_alt_vars.Topic.Avatar))
|
|
||||||
w.Write(topic_alt_frags[61])
|
w.Write(topic_alt_frags[61])
|
||||||
w.Write([]byte(tmpl_topic_alt_vars.Topic.UserLink))
|
w.Write(phrases[33])
|
||||||
w.Write(topic_alt_frags[62])
|
w.Write(topic_alt_frags[62])
|
||||||
w.Write([]byte(tmpl_topic_alt_vars.Topic.CreatedByName))
|
w.Write(phrases[34])
|
||||||
w.Write(topic_alt_frags[63])
|
w.Write(topic_alt_frags[63])
|
||||||
if tmpl_topic_alt_vars.Topic.Tag != "" {
|
w.Write([]byte(tmpl_topic_alt_vars.Topic.Avatar))
|
||||||
w.Write(topic_alt_frags[64])
|
w.Write(topic_alt_frags[64])
|
||||||
w.Write([]byte(tmpl_topic_alt_vars.Topic.Tag))
|
w.Write([]byte(tmpl_topic_alt_vars.Topic.UserLink))
|
||||||
w.Write(topic_alt_frags[65])
|
w.Write(topic_alt_frags[65])
|
||||||
} else {
|
w.Write([]byte(tmpl_topic_alt_vars.Topic.CreatedByName))
|
||||||
w.Write(topic_alt_frags[66])
|
w.Write(topic_alt_frags[66])
|
||||||
|
if tmpl_topic_alt_vars.Topic.Tag != "" {
|
||||||
|
w.Write(topic_alt_frags[67])
|
||||||
|
w.Write([]byte(tmpl_topic_alt_vars.Topic.Tag))
|
||||||
|
w.Write(topic_alt_frags[68])
|
||||||
|
} else {
|
||||||
|
w.Write(topic_alt_frags[69])
|
||||||
w.Write(phrases[35])
|
w.Write(phrases[35])
|
||||||
w.Write([]byte(strconv.Itoa(tmpl_topic_alt_vars.Topic.Level)))
|
w.Write([]byte(strconv.Itoa(tmpl_topic_alt_vars.Topic.Level)))
|
||||||
w.Write(topic_alt_frags[67])
|
|
||||||
}
|
|
||||||
w.Write(topic_alt_frags[68])
|
|
||||||
w.Write([]byte(tmpl_topic_alt_vars.Topic.ContentHTML))
|
|
||||||
w.Write(topic_alt_frags[69])
|
|
||||||
w.Write([]byte(tmpl_topic_alt_vars.Topic.Content))
|
|
||||||
w.Write(topic_alt_frags[70])
|
w.Write(topic_alt_frags[70])
|
||||||
if tmpl_topic_alt_vars.CurrentUser.Loggedin {
|
}
|
||||||
if tmpl_topic_alt_vars.CurrentUser.Perms.LikeItem {
|
|
||||||
w.Write(topic_alt_frags[71])
|
w.Write(topic_alt_frags[71])
|
||||||
w.Write([]byte(strconv.Itoa(tmpl_topic_alt_vars.Topic.ID)))
|
w.Write([]byte(tmpl_topic_alt_vars.Topic.ContentHTML))
|
||||||
w.Write(topic_alt_frags[72])
|
w.Write(topic_alt_frags[72])
|
||||||
w.Write([]byte(tmpl_topic_alt_vars.CurrentUser.Session))
|
w.Write([]byte(tmpl_topic_alt_vars.Topic.Content))
|
||||||
w.Write(topic_alt_frags[73])
|
w.Write(topic_alt_frags[73])
|
||||||
w.Write(phrases[36])
|
if tmpl_topic_alt_vars.Topic.LikeCount > 0 {
|
||||||
w.Write(topic_alt_frags[74])
|
w.Write(topic_alt_frags[74])
|
||||||
}
|
}
|
||||||
if tmpl_topic_alt_vars.CurrentUser.Perms.EditTopic {
|
|
||||||
w.Write(topic_alt_frags[75])
|
w.Write(topic_alt_frags[75])
|
||||||
w.Write([]byte(strconv.Itoa(tmpl_topic_alt_vars.Topic.ID)))
|
if tmpl_topic_alt_vars.CurrentUser.Loggedin {
|
||||||
|
if tmpl_topic_alt_vars.CurrentUser.Perms.LikeItem {
|
||||||
w.Write(topic_alt_frags[76])
|
w.Write(topic_alt_frags[76])
|
||||||
w.Write(phrases[37])
|
w.Write([]byte(strconv.Itoa(tmpl_topic_alt_vars.Topic.ID)))
|
||||||
w.Write(topic_alt_frags[77])
|
w.Write(topic_alt_frags[77])
|
||||||
|
w.Write([]byte(tmpl_topic_alt_vars.CurrentUser.Session))
|
||||||
|
w.Write(topic_alt_frags[78])
|
||||||
|
if tmpl_topic_alt_vars.Topic.Liked {
|
||||||
|
w.Write(topic_alt_frags[79])
|
||||||
|
} else {
|
||||||
|
w.Write(topic_alt_frags[80])
|
||||||
|
}
|
||||||
|
w.Write(topic_alt_frags[81])
|
||||||
|
w.Write(phrases[36])
|
||||||
|
w.Write(topic_alt_frags[82])
|
||||||
|
}
|
||||||
|
if tmpl_topic_alt_vars.CurrentUser.Perms.EditTopic {
|
||||||
|
w.Write(topic_alt_frags[83])
|
||||||
|
w.Write([]byte(strconv.Itoa(tmpl_topic_alt_vars.Topic.ID)))
|
||||||
|
w.Write(topic_alt_frags[84])
|
||||||
|
w.Write(phrases[37])
|
||||||
|
w.Write(topic_alt_frags[85])
|
||||||
}
|
}
|
||||||
if tmpl_topic_alt_vars.CurrentUser.Perms.DeleteTopic {
|
if tmpl_topic_alt_vars.CurrentUser.Perms.DeleteTopic {
|
||||||
w.Write(topic_alt_frags[78])
|
|
||||||
w.Write([]byte(strconv.Itoa(tmpl_topic_alt_vars.Topic.ID)))
|
|
||||||
w.Write(topic_alt_frags[79])
|
|
||||||
w.Write([]byte(tmpl_topic_alt_vars.CurrentUser.Session))
|
|
||||||
w.Write(topic_alt_frags[80])
|
|
||||||
w.Write(phrases[38])
|
|
||||||
w.Write(topic_alt_frags[81])
|
|
||||||
}
|
|
||||||
if tmpl_topic_alt_vars.CurrentUser.Perms.CloseTopic {
|
|
||||||
if tmpl_topic_alt_vars.Topic.IsClosed {
|
|
||||||
w.Write(topic_alt_frags[82])
|
|
||||||
w.Write([]byte(strconv.Itoa(tmpl_topic_alt_vars.Topic.ID)))
|
|
||||||
w.Write(topic_alt_frags[83])
|
|
||||||
w.Write([]byte(tmpl_topic_alt_vars.CurrentUser.Session))
|
|
||||||
w.Write(topic_alt_frags[84])
|
|
||||||
w.Write(phrases[39])
|
|
||||||
w.Write(topic_alt_frags[85])
|
|
||||||
} else {
|
|
||||||
w.Write(topic_alt_frags[86])
|
w.Write(topic_alt_frags[86])
|
||||||
w.Write([]byte(strconv.Itoa(tmpl_topic_alt_vars.Topic.ID)))
|
w.Write([]byte(strconv.Itoa(tmpl_topic_alt_vars.Topic.ID)))
|
||||||
w.Write(topic_alt_frags[87])
|
w.Write(topic_alt_frags[87])
|
||||||
w.Write([]byte(tmpl_topic_alt_vars.CurrentUser.Session))
|
w.Write([]byte(tmpl_topic_alt_vars.CurrentUser.Session))
|
||||||
w.Write(topic_alt_frags[88])
|
w.Write(topic_alt_frags[88])
|
||||||
w.Write(phrases[40])
|
w.Write(phrases[38])
|
||||||
w.Write(topic_alt_frags[89])
|
w.Write(topic_alt_frags[89])
|
||||||
}
|
}
|
||||||
}
|
if tmpl_topic_alt_vars.CurrentUser.Perms.CloseTopic {
|
||||||
if tmpl_topic_alt_vars.CurrentUser.Perms.PinTopic {
|
if tmpl_topic_alt_vars.Topic.IsClosed {
|
||||||
if tmpl_topic_alt_vars.Topic.Sticky {
|
|
||||||
w.Write(topic_alt_frags[90])
|
w.Write(topic_alt_frags[90])
|
||||||
w.Write([]byte(strconv.Itoa(tmpl_topic_alt_vars.Topic.ID)))
|
w.Write([]byte(strconv.Itoa(tmpl_topic_alt_vars.Topic.ID)))
|
||||||
w.Write(topic_alt_frags[91])
|
w.Write(topic_alt_frags[91])
|
||||||
w.Write([]byte(tmpl_topic_alt_vars.CurrentUser.Session))
|
w.Write([]byte(tmpl_topic_alt_vars.CurrentUser.Session))
|
||||||
w.Write(topic_alt_frags[92])
|
w.Write(topic_alt_frags[92])
|
||||||
w.Write(phrases[41])
|
w.Write(phrases[39])
|
||||||
w.Write(topic_alt_frags[93])
|
w.Write(topic_alt_frags[93])
|
||||||
} else {
|
} else {
|
||||||
w.Write(topic_alt_frags[94])
|
w.Write(topic_alt_frags[94])
|
||||||
|
@ -406,208 +401,222 @@ w.Write([]byte(strconv.Itoa(tmpl_topic_alt_vars.Topic.ID)))
|
||||||
w.Write(topic_alt_frags[95])
|
w.Write(topic_alt_frags[95])
|
||||||
w.Write([]byte(tmpl_topic_alt_vars.CurrentUser.Session))
|
w.Write([]byte(tmpl_topic_alt_vars.CurrentUser.Session))
|
||||||
w.Write(topic_alt_frags[96])
|
w.Write(topic_alt_frags[96])
|
||||||
w.Write(phrases[42])
|
w.Write(phrases[40])
|
||||||
w.Write(topic_alt_frags[97])
|
w.Write(topic_alt_frags[97])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if tmpl_topic_alt_vars.CurrentUser.Perms.ViewIPs {
|
if tmpl_topic_alt_vars.CurrentUser.Perms.PinTopic {
|
||||||
|
if tmpl_topic_alt_vars.Topic.Sticky {
|
||||||
w.Write(topic_alt_frags[98])
|
w.Write(topic_alt_frags[98])
|
||||||
w.Write([]byte(tmpl_topic_alt_vars.Topic.IPAddress))
|
w.Write([]byte(strconv.Itoa(tmpl_topic_alt_vars.Topic.ID)))
|
||||||
w.Write(topic_alt_frags[99])
|
w.Write(topic_alt_frags[99])
|
||||||
w.Write(phrases[43])
|
w.Write([]byte(tmpl_topic_alt_vars.CurrentUser.Session))
|
||||||
w.Write(topic_alt_frags[100])
|
w.Write(topic_alt_frags[100])
|
||||||
w.Write(phrases[44])
|
w.Write(phrases[41])
|
||||||
w.Write(topic_alt_frags[101])
|
w.Write(topic_alt_frags[101])
|
||||||
}
|
} else {
|
||||||
w.Write(topic_alt_frags[102])
|
w.Write(topic_alt_frags[102])
|
||||||
w.Write([]byte(strconv.Itoa(tmpl_topic_alt_vars.Topic.ID)))
|
w.Write([]byte(strconv.Itoa(tmpl_topic_alt_vars.Topic.ID)))
|
||||||
w.Write(topic_alt_frags[103])
|
w.Write(topic_alt_frags[103])
|
||||||
w.Write([]byte(tmpl_topic_alt_vars.CurrentUser.Session))
|
w.Write([]byte(tmpl_topic_alt_vars.CurrentUser.Session))
|
||||||
w.Write(topic_alt_frags[104])
|
w.Write(topic_alt_frags[104])
|
||||||
w.Write(phrases[45])
|
w.Write(phrases[42])
|
||||||
w.Write(topic_alt_frags[105])
|
w.Write(topic_alt_frags[105])
|
||||||
}
|
}
|
||||||
w.Write(topic_alt_frags[106])
|
|
||||||
if tmpl_topic_alt_vars.Topic.LikeCount > 0 {
|
|
||||||
w.Write(topic_alt_frags[107])
|
|
||||||
}
|
}
|
||||||
w.Write(topic_alt_frags[108])
|
|
||||||
if tmpl_topic_alt_vars.Topic.LikeCount > 0 {
|
|
||||||
w.Write(topic_alt_frags[109])
|
|
||||||
w.Write(phrases[46])
|
|
||||||
w.Write(topic_alt_frags[110])
|
|
||||||
w.Write([]byte(strconv.Itoa(tmpl_topic_alt_vars.Topic.LikeCount)))
|
|
||||||
w.Write(topic_alt_frags[111])
|
|
||||||
}
|
|
||||||
w.Write(topic_alt_frags[112])
|
|
||||||
w.Write([]byte(tmpl_topic_alt_vars.Topic.RelativeCreatedAt))
|
|
||||||
w.Write(topic_alt_frags[113])
|
|
||||||
if tmpl_topic_alt_vars.CurrentUser.Perms.ViewIPs {
|
if tmpl_topic_alt_vars.CurrentUser.Perms.ViewIPs {
|
||||||
w.Write(topic_alt_frags[114])
|
w.Write(topic_alt_frags[106])
|
||||||
w.Write([]byte(tmpl_topic_alt_vars.Topic.IPAddress))
|
w.Write([]byte(tmpl_topic_alt_vars.Topic.IPAddress))
|
||||||
w.Write(topic_alt_frags[115])
|
w.Write(topic_alt_frags[107])
|
||||||
w.Write(phrases[47])
|
w.Write(phrases[43])
|
||||||
w.Write(topic_alt_frags[116])
|
w.Write(topic_alt_frags[108])
|
||||||
w.Write([]byte(tmpl_topic_alt_vars.Topic.IPAddress))
|
w.Write(phrases[44])
|
||||||
w.Write(topic_alt_frags[117])
|
w.Write(topic_alt_frags[109])
|
||||||
}
|
}
|
||||||
|
w.Write(topic_alt_frags[110])
|
||||||
|
w.Write([]byte(strconv.Itoa(tmpl_topic_alt_vars.Topic.ID)))
|
||||||
|
w.Write(topic_alt_frags[111])
|
||||||
|
w.Write([]byte(tmpl_topic_alt_vars.CurrentUser.Session))
|
||||||
|
w.Write(topic_alt_frags[112])
|
||||||
|
w.Write(phrases[45])
|
||||||
|
w.Write(topic_alt_frags[113])
|
||||||
|
}
|
||||||
|
w.Write(topic_alt_frags[114])
|
||||||
|
w.Write(phrases[46])
|
||||||
|
w.Write(topic_alt_frags[115])
|
||||||
|
w.Write([]byte(strconv.Itoa(tmpl_topic_alt_vars.Topic.LikeCount)))
|
||||||
|
w.Write(topic_alt_frags[116])
|
||||||
|
w.Write([]byte(tmpl_topic_alt_vars.Topic.RelativeCreatedAt))
|
||||||
|
w.Write(topic_alt_frags[117])
|
||||||
|
if tmpl_topic_alt_vars.CurrentUser.Perms.ViewIPs {
|
||||||
w.Write(topic_alt_frags[118])
|
w.Write(topic_alt_frags[118])
|
||||||
|
w.Write([]byte(tmpl_topic_alt_vars.Topic.IPAddress))
|
||||||
|
w.Write(topic_alt_frags[119])
|
||||||
|
w.Write(phrases[47])
|
||||||
|
w.Write(topic_alt_frags[120])
|
||||||
|
w.Write([]byte(tmpl_topic_alt_vars.Topic.IPAddress))
|
||||||
|
w.Write(topic_alt_frags[121])
|
||||||
|
}
|
||||||
|
w.Write(topic_alt_frags[122])
|
||||||
if len(tmpl_topic_alt_vars.ItemList) != 0 {
|
if len(tmpl_topic_alt_vars.ItemList) != 0 {
|
||||||
for _, item := range tmpl_topic_alt_vars.ItemList {
|
for _, item := range tmpl_topic_alt_vars.ItemList {
|
||||||
w.Write(topic_alt_frags[119])
|
|
||||||
if item.ActionType != "" {
|
|
||||||
w.Write(topic_alt_frags[120])
|
|
||||||
}
|
|
||||||
w.Write(topic_alt_frags[121])
|
|
||||||
w.Write(phrases[48])
|
|
||||||
w.Write(topic_alt_frags[122])
|
|
||||||
w.Write([]byte(item.Avatar))
|
|
||||||
w.Write(topic_alt_frags[123])
|
w.Write(topic_alt_frags[123])
|
||||||
w.Write([]byte(item.UserLink))
|
|
||||||
w.Write(topic_alt_frags[124])
|
w.Write(topic_alt_frags[124])
|
||||||
w.Write([]byte(item.CreatedByName))
|
if item.ActionType != "" {
|
||||||
w.Write(topic_alt_frags[125])
|
w.Write(topic_alt_frags[125])
|
||||||
if item.Tag != "" {
|
}
|
||||||
w.Write(topic_alt_frags[126])
|
w.Write(topic_alt_frags[126])
|
||||||
w.Write([]byte(item.Tag))
|
w.Write(phrases[48])
|
||||||
w.Write(topic_alt_frags[127])
|
w.Write(topic_alt_frags[127])
|
||||||
} else {
|
w.Write([]byte(item.Avatar))
|
||||||
w.Write(topic_alt_frags[128])
|
w.Write(topic_alt_frags[128])
|
||||||
|
w.Write([]byte(item.UserLink))
|
||||||
|
w.Write(topic_alt_frags[129])
|
||||||
|
w.Write([]byte(item.CreatedByName))
|
||||||
|
w.Write(topic_alt_frags[130])
|
||||||
|
if item.Tag != "" {
|
||||||
|
w.Write(topic_alt_frags[131])
|
||||||
|
w.Write([]byte(item.Tag))
|
||||||
|
w.Write(topic_alt_frags[132])
|
||||||
|
} else {
|
||||||
|
w.Write(topic_alt_frags[133])
|
||||||
w.Write(phrases[49])
|
w.Write(phrases[49])
|
||||||
w.Write([]byte(strconv.Itoa(item.Level)))
|
w.Write([]byte(strconv.Itoa(item.Level)))
|
||||||
w.Write(topic_alt_frags[129])
|
|
||||||
}
|
|
||||||
w.Write(topic_alt_frags[130])
|
|
||||||
if item.ActionType != "" {
|
|
||||||
w.Write(topic_alt_frags[131])
|
|
||||||
}
|
|
||||||
w.Write(topic_alt_frags[132])
|
|
||||||
if item.ActionType != "" {
|
|
||||||
w.Write(topic_alt_frags[133])
|
|
||||||
w.Write([]byte(item.ActionIcon))
|
|
||||||
w.Write(topic_alt_frags[134])
|
w.Write(topic_alt_frags[134])
|
||||||
w.Write([]byte(item.ActionType))
|
}
|
||||||
w.Write(topic_alt_frags[135])
|
w.Write(topic_alt_frags[135])
|
||||||
} else {
|
if item.ActionType != "" {
|
||||||
w.Write(topic_alt_frags[136])
|
w.Write(topic_alt_frags[136])
|
||||||
w.Write([]byte(item.ContentHtml))
|
}
|
||||||
w.Write(topic_alt_frags[137])
|
w.Write(topic_alt_frags[137])
|
||||||
|
if item.ActionType != "" {
|
||||||
|
w.Write(topic_alt_frags[138])
|
||||||
|
w.Write([]byte(item.ActionIcon))
|
||||||
|
w.Write(topic_alt_frags[139])
|
||||||
|
w.Write([]byte(item.ActionType))
|
||||||
|
w.Write(topic_alt_frags[140])
|
||||||
|
} else {
|
||||||
|
w.Write(topic_alt_frags[141])
|
||||||
|
w.Write([]byte(item.ContentHtml))
|
||||||
|
w.Write(topic_alt_frags[142])
|
||||||
|
if item.LikeCount > 0 {
|
||||||
|
w.Write(topic_alt_frags[143])
|
||||||
|
}
|
||||||
|
w.Write(topic_alt_frags[144])
|
||||||
if tmpl_topic_alt_vars.CurrentUser.Loggedin {
|
if tmpl_topic_alt_vars.CurrentUser.Loggedin {
|
||||||
if tmpl_topic_alt_vars.CurrentUser.Perms.LikeItem {
|
if tmpl_topic_alt_vars.CurrentUser.Perms.LikeItem {
|
||||||
w.Write(topic_alt_frags[138])
|
|
||||||
w.Write([]byte(strconv.Itoa(item.ID)))
|
|
||||||
w.Write(topic_alt_frags[139])
|
|
||||||
w.Write([]byte(tmpl_topic_alt_vars.CurrentUser.Session))
|
|
||||||
w.Write(topic_alt_frags[140])
|
|
||||||
w.Write(phrases[50])
|
|
||||||
w.Write(topic_alt_frags[141])
|
|
||||||
}
|
|
||||||
if tmpl_topic_alt_vars.CurrentUser.Perms.EditReply {
|
|
||||||
w.Write(topic_alt_frags[142])
|
|
||||||
w.Write([]byte(strconv.Itoa(item.ID)))
|
|
||||||
w.Write(topic_alt_frags[143])
|
|
||||||
w.Write([]byte(tmpl_topic_alt_vars.CurrentUser.Session))
|
|
||||||
w.Write(topic_alt_frags[144])
|
|
||||||
w.Write(phrases[51])
|
|
||||||
w.Write(topic_alt_frags[145])
|
w.Write(topic_alt_frags[145])
|
||||||
}
|
|
||||||
if tmpl_topic_alt_vars.CurrentUser.Perms.DeleteReply {
|
|
||||||
w.Write(topic_alt_frags[146])
|
|
||||||
w.Write([]byte(strconv.Itoa(item.ID)))
|
w.Write([]byte(strconv.Itoa(item.ID)))
|
||||||
w.Write(topic_alt_frags[147])
|
w.Write(topic_alt_frags[146])
|
||||||
w.Write([]byte(tmpl_topic_alt_vars.CurrentUser.Session))
|
w.Write([]byte(tmpl_topic_alt_vars.CurrentUser.Session))
|
||||||
|
w.Write(topic_alt_frags[147])
|
||||||
|
if item.Liked {
|
||||||
w.Write(topic_alt_frags[148])
|
w.Write(topic_alt_frags[148])
|
||||||
w.Write(phrases[52])
|
} else {
|
||||||
w.Write(topic_alt_frags[149])
|
w.Write(topic_alt_frags[149])
|
||||||
}
|
}
|
||||||
if tmpl_topic_alt_vars.CurrentUser.Perms.ViewIPs {
|
|
||||||
w.Write(topic_alt_frags[150])
|
w.Write(topic_alt_frags[150])
|
||||||
w.Write([]byte(item.IPAddress))
|
w.Write(phrases[50])
|
||||||
w.Write(topic_alt_frags[151])
|
w.Write(topic_alt_frags[151])
|
||||||
w.Write(phrases[53])
|
}
|
||||||
|
if tmpl_topic_alt_vars.CurrentUser.Perms.EditReply {
|
||||||
w.Write(topic_alt_frags[152])
|
w.Write(topic_alt_frags[152])
|
||||||
w.Write(phrases[54])
|
|
||||||
w.Write(topic_alt_frags[153])
|
|
||||||
}
|
|
||||||
w.Write(topic_alt_frags[154])
|
|
||||||
w.Write([]byte(strconv.Itoa(item.ID)))
|
w.Write([]byte(strconv.Itoa(item.ID)))
|
||||||
w.Write(topic_alt_frags[155])
|
w.Write(topic_alt_frags[153])
|
||||||
w.Write([]byte(tmpl_topic_alt_vars.CurrentUser.Session))
|
w.Write([]byte(tmpl_topic_alt_vars.CurrentUser.Session))
|
||||||
w.Write(topic_alt_frags[156])
|
w.Write(topic_alt_frags[154])
|
||||||
w.Write(phrases[55])
|
w.Write(phrases[51])
|
||||||
w.Write(topic_alt_frags[157])
|
w.Write(topic_alt_frags[155])
|
||||||
}
|
}
|
||||||
|
if tmpl_topic_alt_vars.CurrentUser.Perms.DeleteReply {
|
||||||
|
w.Write(topic_alt_frags[156])
|
||||||
|
w.Write([]byte(strconv.Itoa(item.ID)))
|
||||||
|
w.Write(topic_alt_frags[157])
|
||||||
|
w.Write([]byte(tmpl_topic_alt_vars.CurrentUser.Session))
|
||||||
w.Write(topic_alt_frags[158])
|
w.Write(topic_alt_frags[158])
|
||||||
if item.LikeCount > 0 {
|
w.Write(phrases[52])
|
||||||
w.Write(topic_alt_frags[159])
|
w.Write(topic_alt_frags[159])
|
||||||
}
|
}
|
||||||
|
if tmpl_topic_alt_vars.CurrentUser.Perms.ViewIPs {
|
||||||
w.Write(topic_alt_frags[160])
|
w.Write(topic_alt_frags[160])
|
||||||
if item.LikeCount > 0 {
|
w.Write([]byte(item.IPAddress))
|
||||||
w.Write(topic_alt_frags[161])
|
w.Write(topic_alt_frags[161])
|
||||||
w.Write(phrases[56])
|
w.Write(phrases[53])
|
||||||
w.Write(topic_alt_frags[162])
|
w.Write(topic_alt_frags[162])
|
||||||
w.Write([]byte(strconv.Itoa(item.LikeCount)))
|
w.Write(phrases[54])
|
||||||
w.Write(topic_alt_frags[163])
|
w.Write(topic_alt_frags[163])
|
||||||
}
|
}
|
||||||
w.Write(topic_alt_frags[164])
|
w.Write(topic_alt_frags[164])
|
||||||
w.Write([]byte(item.RelativeCreatedAt))
|
w.Write([]byte(strconv.Itoa(item.ID)))
|
||||||
w.Write(topic_alt_frags[165])
|
w.Write(topic_alt_frags[165])
|
||||||
if tmpl_topic_alt_vars.CurrentUser.Perms.ViewIPs {
|
w.Write([]byte(tmpl_topic_alt_vars.CurrentUser.Session))
|
||||||
w.Write(topic_alt_frags[166])
|
w.Write(topic_alt_frags[166])
|
||||||
w.Write([]byte(item.IPAddress))
|
w.Write(phrases[55])
|
||||||
w.Write(topic_alt_frags[167])
|
w.Write(topic_alt_frags[167])
|
||||||
w.Write([]byte(item.IPAddress))
|
}
|
||||||
w.Write(topic_alt_frags[168])
|
w.Write(topic_alt_frags[168])
|
||||||
}
|
w.Write(phrases[56])
|
||||||
w.Write(topic_alt_frags[169])
|
w.Write(topic_alt_frags[169])
|
||||||
}
|
w.Write([]byte(strconv.Itoa(item.LikeCount)))
|
||||||
w.Write(topic_alt_frags[170])
|
w.Write(topic_alt_frags[170])
|
||||||
}
|
w.Write([]byte(item.RelativeCreatedAt))
|
||||||
}
|
|
||||||
w.Write(topic_alt_frags[171])
|
w.Write(topic_alt_frags[171])
|
||||||
if tmpl_topic_alt_vars.CurrentUser.Perms.CreateReply {
|
if tmpl_topic_alt_vars.CurrentUser.Perms.ViewIPs {
|
||||||
w.Write(topic_alt_frags[172])
|
w.Write(topic_alt_frags[172])
|
||||||
w.Write(phrases[57])
|
w.Write([]byte(item.IPAddress))
|
||||||
w.Write(topic_alt_frags[173])
|
w.Write(topic_alt_frags[173])
|
||||||
w.Write([]byte(tmpl_topic_alt_vars.CurrentUser.Avatar))
|
w.Write([]byte(item.IPAddress))
|
||||||
w.Write(topic_alt_frags[174])
|
w.Write(topic_alt_frags[174])
|
||||||
w.Write([]byte(tmpl_topic_alt_vars.CurrentUser.Link))
|
}
|
||||||
w.Write(topic_alt_frags[175])
|
w.Write(topic_alt_frags[175])
|
||||||
w.Write([]byte(tmpl_topic_alt_vars.CurrentUser.Name))
|
}
|
||||||
w.Write(topic_alt_frags[176])
|
w.Write(topic_alt_frags[176])
|
||||||
if tmpl_topic_alt_vars.CurrentUser.Tag != "" {
|
}
|
||||||
|
}
|
||||||
w.Write(topic_alt_frags[177])
|
w.Write(topic_alt_frags[177])
|
||||||
w.Write([]byte(tmpl_topic_alt_vars.CurrentUser.Tag))
|
if tmpl_topic_alt_vars.CurrentUser.Perms.CreateReply {
|
||||||
w.Write(topic_alt_frags[178])
|
w.Write(topic_alt_frags[178])
|
||||||
} else {
|
w.Write(phrases[57])
|
||||||
w.Write(topic_alt_frags[179])
|
w.Write(topic_alt_frags[179])
|
||||||
|
w.Write([]byte(tmpl_topic_alt_vars.CurrentUser.Avatar))
|
||||||
|
w.Write(topic_alt_frags[180])
|
||||||
|
w.Write([]byte(tmpl_topic_alt_vars.CurrentUser.Link))
|
||||||
|
w.Write(topic_alt_frags[181])
|
||||||
|
w.Write([]byte(tmpl_topic_alt_vars.CurrentUser.Name))
|
||||||
|
w.Write(topic_alt_frags[182])
|
||||||
|
if tmpl_topic_alt_vars.CurrentUser.Tag != "" {
|
||||||
|
w.Write(topic_alt_frags[183])
|
||||||
|
w.Write([]byte(tmpl_topic_alt_vars.CurrentUser.Tag))
|
||||||
|
w.Write(topic_alt_frags[184])
|
||||||
|
} else {
|
||||||
|
w.Write(topic_alt_frags[185])
|
||||||
w.Write(phrases[58])
|
w.Write(phrases[58])
|
||||||
w.Write([]byte(strconv.Itoa(tmpl_topic_alt_vars.CurrentUser.Level)))
|
w.Write([]byte(strconv.Itoa(tmpl_topic_alt_vars.CurrentUser.Level)))
|
||||||
w.Write(topic_alt_frags[180])
|
|
||||||
}
|
|
||||||
w.Write(topic_alt_frags[181])
|
|
||||||
w.Write(phrases[59])
|
|
||||||
w.Write(topic_alt_frags[182])
|
|
||||||
w.Write([]byte(tmpl_topic_alt_vars.CurrentUser.Session))
|
|
||||||
w.Write(topic_alt_frags[183])
|
|
||||||
w.Write([]byte(strconv.Itoa(tmpl_topic_alt_vars.Topic.ID)))
|
|
||||||
w.Write(topic_alt_frags[184])
|
|
||||||
w.Write(phrases[60])
|
|
||||||
w.Write(topic_alt_frags[185])
|
|
||||||
w.Write(phrases[61])
|
|
||||||
w.Write(topic_alt_frags[186])
|
w.Write(topic_alt_frags[186])
|
||||||
w.Write(phrases[62])
|
}
|
||||||
w.Write(topic_alt_frags[187])
|
w.Write(topic_alt_frags[187])
|
||||||
w.Write(phrases[63])
|
w.Write(phrases[59])
|
||||||
w.Write(topic_alt_frags[188])
|
w.Write(topic_alt_frags[188])
|
||||||
if tmpl_topic_alt_vars.CurrentUser.Perms.UploadFiles {
|
w.Write([]byte(tmpl_topic_alt_vars.CurrentUser.Session))
|
||||||
w.Write(topic_alt_frags[189])
|
w.Write(topic_alt_frags[189])
|
||||||
w.Write(phrases[64])
|
w.Write([]byte(strconv.Itoa(tmpl_topic_alt_vars.Topic.ID)))
|
||||||
w.Write(topic_alt_frags[190])
|
w.Write(topic_alt_frags[190])
|
||||||
}
|
w.Write(phrases[60])
|
||||||
w.Write(topic_alt_frags[191])
|
w.Write(topic_alt_frags[191])
|
||||||
}
|
w.Write(phrases[61])
|
||||||
w.Write(topic_alt_frags[192])
|
w.Write(topic_alt_frags[192])
|
||||||
|
w.Write(phrases[62])
|
||||||
|
w.Write(topic_alt_frags[193])
|
||||||
|
w.Write(phrases[63])
|
||||||
|
w.Write(topic_alt_frags[194])
|
||||||
|
if tmpl_topic_alt_vars.CurrentUser.Perms.UploadFiles {
|
||||||
|
w.Write(topic_alt_frags[195])
|
||||||
|
w.Write(phrases[64])
|
||||||
|
w.Write(topic_alt_frags[196])
|
||||||
|
}
|
||||||
|
w.Write(topic_alt_frags[197])
|
||||||
|
}
|
||||||
|
w.Write(topic_alt_frags[198])
|
||||||
w.Write(footer_frags[0])
|
w.Write(footer_frags[0])
|
||||||
w.Write([]byte(common.BuildWidget("footer",tmpl_topic_alt_vars.Header)))
|
w.Write([]byte(common.BuildWidget("footer",tmpl_topic_alt_vars.Header)))
|
||||||
w.Write(footer_frags[1])
|
w.Write(footer_frags[1])
|
||||||
|
|
|
@ -317,67 +317,75 @@ w.Write([]byte(item.Link))
|
||||||
w.Write(topics_frags[62])
|
w.Write(topics_frags[62])
|
||||||
w.Write([]byte(item.Title))
|
w.Write([]byte(item.Title))
|
||||||
w.Write(topics_frags[63])
|
w.Write(topics_frags[63])
|
||||||
if item.ForumName != "" {
|
w.Write([]byte(item.Title))
|
||||||
w.Write(topics_frags[64])
|
w.Write(topics_frags[64])
|
||||||
w.Write([]byte(item.ForumLink))
|
if item.ForumName != "" {
|
||||||
w.Write(topics_frags[65])
|
w.Write(topics_frags[65])
|
||||||
w.Write([]byte(item.ForumName))
|
w.Write([]byte(item.ForumLink))
|
||||||
w.Write(topics_frags[66])
|
w.Write(topics_frags[66])
|
||||||
}
|
w.Write([]byte(item.ForumName))
|
||||||
w.Write(topics_frags[67])
|
w.Write(topics_frags[67])
|
||||||
w.Write([]byte(item.Creator.Link))
|
w.Write([]byte(item.ForumName))
|
||||||
w.Write(topics_frags[68])
|
w.Write(topics_frags[68])
|
||||||
w.Write([]byte(item.Creator.Name))
|
}
|
||||||
w.Write(topics_frags[69])
|
w.Write(topics_frags[69])
|
||||||
if item.IsClosed {
|
w.Write([]byte(item.Creator.Link))
|
||||||
w.Write(topics_frags[70])
|
w.Write(topics_frags[70])
|
||||||
w.Write(phrases[44])
|
w.Write([]byte(item.Creator.Name))
|
||||||
w.Write(topics_frags[71])
|
w.Write(topics_frags[71])
|
||||||
}
|
w.Write([]byte(item.Creator.Name))
|
||||||
if item.Sticky {
|
|
||||||
w.Write(topics_frags[72])
|
w.Write(topics_frags[72])
|
||||||
w.Write(phrases[45])
|
if item.IsClosed {
|
||||||
w.Write(topics_frags[73])
|
w.Write(topics_frags[73])
|
||||||
}
|
w.Write(phrases[44])
|
||||||
w.Write(topics_frags[74])
|
w.Write(topics_frags[74])
|
||||||
w.Write([]byte(strconv.Itoa(item.PostCount)))
|
}
|
||||||
w.Write(topics_frags[75])
|
|
||||||
w.Write([]byte(strconv.Itoa(item.LikeCount)))
|
|
||||||
w.Write(topics_frags[76])
|
|
||||||
if item.Sticky {
|
if item.Sticky {
|
||||||
|
w.Write(topics_frags[75])
|
||||||
|
w.Write(phrases[45])
|
||||||
|
w.Write(topics_frags[76])
|
||||||
|
}
|
||||||
w.Write(topics_frags[77])
|
w.Write(topics_frags[77])
|
||||||
|
w.Write([]byte(strconv.Itoa(item.PostCount)))
|
||||||
|
w.Write(topics_frags[78])
|
||||||
|
w.Write([]byte(strconv.Itoa(item.LikeCount)))
|
||||||
|
w.Write(topics_frags[79])
|
||||||
|
if item.Sticky {
|
||||||
|
w.Write(topics_frags[80])
|
||||||
} else {
|
} else {
|
||||||
if item.IsClosed {
|
if item.IsClosed {
|
||||||
w.Write(topics_frags[78])
|
|
||||||
}
|
|
||||||
}
|
|
||||||
w.Write(topics_frags[79])
|
|
||||||
w.Write([]byte(item.LastUser.Link))
|
|
||||||
w.Write(topics_frags[80])
|
|
||||||
w.Write([]byte(item.LastUser.Avatar))
|
|
||||||
w.Write(topics_frags[81])
|
w.Write(topics_frags[81])
|
||||||
w.Write([]byte(item.LastUser.Name))
|
}
|
||||||
|
}
|
||||||
w.Write(topics_frags[82])
|
w.Write(topics_frags[82])
|
||||||
w.Write([]byte(item.LastUser.Name))
|
|
||||||
w.Write(topics_frags[83])
|
|
||||||
w.Write([]byte(item.LastUser.Link))
|
w.Write([]byte(item.LastUser.Link))
|
||||||
|
w.Write(topics_frags[83])
|
||||||
|
w.Write([]byte(item.LastUser.Avatar))
|
||||||
w.Write(topics_frags[84])
|
w.Write(topics_frags[84])
|
||||||
w.Write([]byte(item.LastUser.Name))
|
w.Write([]byte(item.LastUser.Name))
|
||||||
w.Write(topics_frags[85])
|
w.Write(topics_frags[85])
|
||||||
w.Write([]byte(item.RelativeLastReplyAt))
|
w.Write([]byte(item.LastUser.Name))
|
||||||
w.Write(topics_frags[86])
|
w.Write(topics_frags[86])
|
||||||
}
|
w.Write([]byte(item.LastUser.Link))
|
||||||
} else {
|
|
||||||
w.Write(topics_frags[87])
|
w.Write(topics_frags[87])
|
||||||
w.Write(phrases[46])
|
w.Write([]byte(item.LastUser.Name))
|
||||||
if tmpl_topics_vars.CurrentUser.Perms.CreateTopic {
|
|
||||||
w.Write(topics_frags[88])
|
w.Write(topics_frags[88])
|
||||||
w.Write(phrases[47])
|
w.Write([]byte(item.LastUser.Name))
|
||||||
w.Write(topics_frags[89])
|
w.Write(topics_frags[89])
|
||||||
}
|
w.Write([]byte(item.RelativeLastReplyAt))
|
||||||
w.Write(topics_frags[90])
|
w.Write(topics_frags[90])
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
w.Write(topics_frags[91])
|
w.Write(topics_frags[91])
|
||||||
|
w.Write(phrases[46])
|
||||||
|
if tmpl_topics_vars.CurrentUser.Perms.CreateTopic {
|
||||||
|
w.Write(topics_frags[92])
|
||||||
|
w.Write(phrases[47])
|
||||||
|
w.Write(topics_frags[93])
|
||||||
|
}
|
||||||
|
w.Write(topics_frags[94])
|
||||||
|
}
|
||||||
|
w.Write(topics_frags[95])
|
||||||
if tmpl_topics_vars.LastPage > 1 {
|
if tmpl_topics_vars.LastPage > 1 {
|
||||||
w.Write(paginator_frags[0])
|
w.Write(paginator_frags[0])
|
||||||
if tmpl_topics_vars.Page > 1 {
|
if tmpl_topics_vars.Page > 1 {
|
||||||
|
@ -413,7 +421,7 @@ w.Write(paginator_frags[13])
|
||||||
}
|
}
|
||||||
w.Write(paginator_frags[14])
|
w.Write(paginator_frags[14])
|
||||||
}
|
}
|
||||||
w.Write(topics_frags[92])
|
w.Write(topics_frags[96])
|
||||||
w.Write(footer_frags[0])
|
w.Write(footer_frags[0])
|
||||||
w.Write([]byte(common.BuildWidget("footer",tmpl_topics_vars.Header)))
|
w.Write([]byte(common.BuildWidget("footer",tmpl_topics_vars.Header)))
|
||||||
w.Write(footer_frags[1])
|
w.Write(footer_frags[1])
|
||||||
|
|
|
@ -82,8 +82,8 @@
|
||||||
<span class="selector"></span>
|
<span class="selector"></span>
|
||||||
<a href="{{.Creator.Link}}"><img src="{{.Creator.Avatar}}" height="64" alt="{{.Creator.Name}}'s Avatar" title="{{.Creator.Name}}'s Avatar" /></a>
|
<a href="{{.Creator.Link}}"><img src="{{.Creator.Avatar}}" height="64" alt="{{.Creator.Name}}'s Avatar" title="{{.Creator.Name}}'s Avatar" /></a>
|
||||||
<span class="topic_inner_left">
|
<span class="topic_inner_left">
|
||||||
<a class="rowtopic" href="{{.Link}}" itemprop="itemListElement"><span>{{.Title}}</span></a>
|
<a class="rowtopic" href="{{.Link}}" itemprop="itemListElement" title="{{.Title}}"><span>{{.Title}}</span></a>
|
||||||
<br /><a class="rowsmall starter" href="{{.Creator.Link}}">{{.Creator.Name}}</a>
|
<br /><a class="rowsmall starter" href="{{.Creator.Link}}" title="{{.Creator.Name}}">{{.Creator.Name}}</a>
|
||||||
{{/** TODO: Avoid the double '|' when both .IsClosed and .Sticky are set to true. We could probably do this with CSS **/}}
|
{{/** TODO: Avoid the double '|' when both .IsClosed and .Sticky are set to true. We could probably do this with CSS **/}}
|
||||||
{{if .IsClosed}}<span class="rowsmall topic_status_e topic_status_closed" title="{{lang "status_closed_tooltip"}}"> | 🔒︎</span>{{end}}
|
{{if .IsClosed}}<span class="rowsmall topic_status_e topic_status_closed" title="{{lang "status_closed_tooltip"}}"> | 🔒︎</span>{{end}}
|
||||||
{{if .Sticky}}<span class="rowsmall topic_status_e topic_status_sticky" title="{{lang "status_pinned_tooltip"}}"> | 📍︎</span>{{end}}
|
{{if .Sticky}}<span class="rowsmall topic_status_e topic_status_sticky" title="{{lang "status_pinned_tooltip"}}"> | 📍︎</span>{{end}}
|
||||||
|
@ -96,7 +96,7 @@
|
||||||
<div class="rowitem topic_right passive datarow {{if .Sticky}}topic_sticky{{else if .IsClosed}}topic_closed{{end}}">
|
<div class="rowitem topic_right passive datarow {{if .Sticky}}topic_sticky{{else if .IsClosed}}topic_closed{{end}}">
|
||||||
<a href="{{.LastUser.Link}}"><img src="{{.LastUser.Avatar}}" height="64" alt="{{.LastUser.Name}}'s Avatar" title="{{.LastUser.Name}}'s Avatar" /></a>
|
<a href="{{.LastUser.Link}}"><img src="{{.LastUser.Avatar}}" height="64" alt="{{.LastUser.Name}}'s Avatar" title="{{.LastUser.Name}}'s Avatar" /></a>
|
||||||
<span>
|
<span>
|
||||||
<a href="{{.LastUser.Link}}" class="lastName" style="font-size: 14px;">{{.LastUser.Name}}</a><br>
|
<a href="{{.LastUser.Link}}" class="lastName" style="font-size: 14px;" title="{{.LastUser.Name}}">{{.LastUser.Name}}</a><br>
|
||||||
<span class="rowsmall lastReplyAt">{{.RelativeLastReplyAt}}</span>
|
<span class="rowsmall lastReplyAt">{{.RelativeLastReplyAt}}</span>
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -9,7 +9,7 @@
|
||||||
<img src="{{.ProfileOwner.Avatar}}" class="avatar" alt="{{.ProfileOwner.Name}}'s Avatar" title="{{.ProfileOwner.Name}}'s Avatar" />
|
<img src="{{.ProfileOwner.Avatar}}" class="avatar" alt="{{.ProfileOwner.Name}}'s Avatar" title="{{.ProfileOwner.Name}}'s Avatar" />
|
||||||
</div>
|
</div>
|
||||||
<div class="rowitem nameRow">
|
<div class="rowitem nameRow">
|
||||||
<span class="profileName">{{.ProfileOwner.Name}}</span>{{if .ProfileOwner.Tag}}<span class="username">{{.ProfileOwner.Tag}}</span>{{end}}
|
<span class="profileName" title="{{.ProfileOwner.Name}}">{{.ProfileOwner.Name}}</span>{{if .ProfileOwner.Tag}}<span class="username" title="{{.ProfileOwner.Tag}}">{{.ProfileOwner.Tag}}</span>{{end}}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="passiveBlock">
|
<div class="passiveBlock">
|
||||||
|
|
|
@ -11,9 +11,9 @@
|
||||||
|
|
||||||
<main>
|
<main>
|
||||||
|
|
||||||
<div class="rowblock rowhead topic_block" aria-label="{{lang "topic_opening_post_aria"}}">
|
<div {{scope "topic_title_block"}} class="rowblock rowhead topic_block" aria-label="{{lang "topic_opening_post_aria"}}">
|
||||||
<div class="rowitem topic_item{{if .Topic.Sticky}} topic_sticky_head{{else if .Topic.IsClosed}} topic_closed_head{{end}}">
|
<div class="rowitem topic_item{{if .Topic.Sticky}} topic_sticky_head{{else if .Topic.IsClosed}} topic_closed_head{{end}}">
|
||||||
<h1 class='topic_name hide_on_edit'>{{.Topic.Title}}</h1>
|
<h1 class='topic_name hide_on_edit' title='{{.Topic.Title}}'>{{.Topic.Title}}</h1>
|
||||||
{{if .Topic.IsClosed}}<span class='username hide_on_micro topic_status_e topic_status_closed hide_on_edit' title='{{lang "status_closed_tooltip"}}' aria-label='{{lang "topic_status_closed_aria"}}'>🔒︎</span>{{end}}
|
{{if .Topic.IsClosed}}<span class='username hide_on_micro topic_status_e topic_status_closed hide_on_edit' title='{{lang "status_closed_tooltip"}}' aria-label='{{lang "topic_status_closed_aria"}}'>🔒︎</span>{{end}}
|
||||||
{{if .CurrentUser.Perms.EditTopic}}
|
{{if .CurrentUser.Perms.EditTopic}}
|
||||||
<input form='edit_topic_form' class='show_on_edit topic_name_input' name="topic_name" value='{{.Topic.Title}}' type="text" aria-label="{{lang "topic_title_input_aria"}}" />
|
<input form='edit_topic_form' class='show_on_edit topic_name_input' name="topic_name" value='{{.Topic.Title}}' type="text" aria-label="{{lang "topic_title_input_aria"}}" />
|
||||||
|
@ -47,16 +47,16 @@
|
||||||
</article>
|
</article>
|
||||||
{{end}}
|
{{end}}
|
||||||
|
|
||||||
<article itemscope itemtype="http://schema.org/CreativeWork" class="rowblock post_container top_post" aria-label="{{lang "topic_opening_post_aria"}}">
|
<article {{scope "opening_post"}} itemscope itemtype="http://schema.org/CreativeWork" class="rowblock post_container top_post" aria-label="{{lang "topic_opening_post_aria"}}">
|
||||||
<div class="rowitem passive editable_parent post_item {{.Topic.ClassName}}" style="background-image: url({{.Topic.Avatar}}), url(/static/{{.Header.Theme.Name}}/post-avatar-bg.jpg);background-position: 0px {{if le .Topic.ContentLines 5}}-1{{end}}0px;background-repeat:no-repeat, repeat-y;">
|
<div class="rowitem passive editable_parent post_item {{.Topic.ClassName}}" style="background-image: url({{.Topic.Avatar}}), url(/static/{{.Header.Theme.Name}}/post-avatar-bg.jpg);background-position: 0px {{if le .Topic.ContentLines 5}}-1{{end}}0px;background-repeat:no-repeat, repeat-y;">
|
||||||
<p class="hide_on_edit topic_content user_content" itemprop="text" style="margin:0;padding:0;">{{.Topic.ContentHTML}}</p>
|
<p class="hide_on_edit topic_content user_content" itemprop="text" style="margin:0;padding:0;">{{.Topic.ContentHTML}}</p>
|
||||||
<textarea name="topic_content" class="show_on_edit topic_content_input">{{.Topic.Content}}</textarea>
|
<textarea name="topic_content" class="show_on_edit topic_content_input">{{.Topic.Content}}</textarea>
|
||||||
|
|
||||||
<span class="controls" aria-label="{{lang "topic_post_controls_aria"}}">
|
<span class="controls{{if .Topic.LikeCount}} has_likes{{end}}" aria-label="{{lang "topic_post_controls_aria"}}">
|
||||||
|
|
||||||
<a href="{{.Topic.UserLink}}" class="username real_username" rel="author">{{.Topic.CreatedByName}}</a>
|
<a href="{{.Topic.UserLink}}" class="username real_username" rel="author">{{.Topic.CreatedByName}}</a>
|
||||||
{{if .CurrentUser.Perms.LikeItem}}<a href="/topic/like/submit/{{.Topic.ID}}?session={{.CurrentUser.Session}}" class="mod_button"{{if .Topic.Liked}} title="{{lang "topic_unlike_tooltip"}}" aria-label="{{lang "topic_unlike_aria"}}"{{else}} title="{{lang "topic_like_tooltip"}}" aria-label="{{lang "topic_like_aria"}}"{{end}} style="color:#202020;">
|
{{if .CurrentUser.Perms.LikeItem}}<a href="/topic/like/submit/{{.Topic.ID}}?session={{.CurrentUser.Session}}" class="mod_button"{{if .Topic.Liked}} title="{{lang "topic_unlike_tooltip"}}" aria-label="{{lang "topic_unlike_aria"}}"{{else}} title="{{lang "topic_like_tooltip"}}" aria-label="{{lang "topic_like_aria"}}"{{end}} style="color:#202020;">
|
||||||
<button class="username like_label"{{if .Topic.Liked}} style="background-color:#D6FFD6;"{{end}}></button></a>{{end}}
|
<button class="username like_label {{if .Topic.Liked}}remove_like{{else}}add_like{{end}}"></button></a>{{end}}
|
||||||
|
|
||||||
{{if .CurrentUser.Perms.EditTopic}}<a href='/topic/edit/{{.Topic.ID}}' class="mod_button open_edit" style="font-weight:normal;" title="{{lang "topic_edit_tooltip"}}" aria-label="{{lang "topic_edit_aria"}}"><button class="username edit_label"></button></a>{{end}}
|
{{if .CurrentUser.Perms.EditTopic}}<a href='/topic/edit/{{.Topic.ID}}' class="mod_button open_edit" style="font-weight:normal;" title="{{lang "topic_edit_tooltip"}}" aria-label="{{lang "topic_edit_aria"}}"><button class="username edit_label"></button></a>{{end}}
|
||||||
|
|
||||||
|
@ -68,7 +68,7 @@
|
||||||
{{if .CurrentUser.Perms.ViewIPs}}<a class="mod_button" href='/users/ips/?ip={{.Topic.IPAddress}}' style="font-weight:normal;" title="{{lang "topic_ip_tooltip"}}" aria-label="The poster's IP is {{.Topic.IPAddress}}"><button class="username ip_label"></button></a>{{end}}
|
{{if .CurrentUser.Perms.ViewIPs}}<a class="mod_button" href='/users/ips/?ip={{.Topic.IPAddress}}' style="font-weight:normal;" title="{{lang "topic_ip_tooltip"}}" aria-label="The poster's IP is {{.Topic.IPAddress}}"><button class="username ip_label"></button></a>{{end}}
|
||||||
<a href="/report/submit/{{.Topic.ID}}?session={{.CurrentUser.Session}}&type=topic" class="mod_button report_item" style="font-weight:normal;" title="{{lang "topic_flag_tooltip"}}" aria-label="{{lang "topic_flag_aria"}}" rel="nofollow"><button class="username flag_label"></button></a>
|
<a href="/report/submit/{{.Topic.ID}}?session={{.CurrentUser.Session}}&type=topic" class="mod_button report_item" style="font-weight:normal;" title="{{lang "topic_flag_tooltip"}}" aria-label="{{lang "topic_flag_aria"}}" rel="nofollow"><button class="username flag_label"></button></a>
|
||||||
|
|
||||||
{{if .Topic.LikeCount}}<a class="username hide_on_micro like_count" aria-label="{{lang "topic_like_count_aria"}}">{{.Topic.LikeCount}}</a><a class="username hide_on_micro like_count_label" title="{{lang "topic_like_count_tooltip"}}"></a>{{end}}
|
<a class="username hide_on_micro like_count" aria-label="{{lang "topic_like_count_aria"}}">{{.Topic.LikeCount}}</a><a class="username hide_on_micro like_count_label" title="{{lang "topic_like_count_tooltip"}}"></a>
|
||||||
|
|
||||||
{{if .Topic.Tag}}<a class="username hide_on_micro user_tag">{{.Topic.Tag}}</a>{{else}}<a class="username hide_on_micro level" aria-label="{{lang "topic_level_aria"}}">{{.Topic.Level}}</a><a class="username hide_on_micro level_label" style="float:right;" title="{{lang "topic_level_tooltip"}}"></a>{{end}}
|
{{if .Topic.Tag}}<a class="username hide_on_micro user_tag">{{.Topic.Tag}}</a>{{else}}<a class="username hide_on_micro level" aria-label="{{lang "topic_level_aria"}}">{{.Topic.Level}}</a><a class="username hide_on_micro level_label" style="float:right;" title="{{lang "topic_level_tooltip"}}"></a>{{end}}
|
||||||
|
|
||||||
|
@ -82,14 +82,14 @@
|
||||||
<span itemprop="text">{{.ActionType}}</span>
|
<span itemprop="text">{{.ActionType}}</span>
|
||||||
</article>
|
</article>
|
||||||
{{else}}
|
{{else}}
|
||||||
<article itemscope itemtype="http://schema.org/CreativeWork" class="rowitem passive deletable_block editable_parent post_item {{.ClassName}}" style="background-image: url({{.Avatar}}), url(/static/{{$.Header.Theme.Name}}/post-avatar-bg.jpg);background-position: 0px {{if le .ContentLines 5}}-1{{end}}0px;background-repeat:no-repeat, repeat-y;">
|
<article {{scope "post"}} itemscope itemtype="http://schema.org/CreativeWork" class="rowitem passive deletable_block editable_parent post_item {{.ClassName}}" style="background-image: url({{.Avatar}}), url(/static/{{$.Header.Theme.Name}}/post-avatar-bg.jpg);background-position: 0px {{if le .ContentLines 5}}-1{{end}}0px;background-repeat:no-repeat, repeat-y;">
|
||||||
{{/** TODO: We might end up with <br>s in the inline editor, fix this **/}}
|
{{/** TODO: We might end up with <br>s in the inline editor, fix this **/}}
|
||||||
<p class="editable_block user_content" itemprop="text" style="margin:0;padding:0;">{{.ContentHtml}}</p>
|
<p class="editable_block user_content" itemprop="text" style="margin:0;padding:0;">{{.ContentHtml}}</p>
|
||||||
|
|
||||||
<span class="controls">
|
<span class="controls{{if .LikeCount}} has_likes{{end}}">
|
||||||
|
|
||||||
<a href="{{.UserLink}}" class="username real_username" rel="author">{{.CreatedByName}}</a>
|
<a href="{{.UserLink}}" class="username real_username" rel="author">{{.CreatedByName}}</a>
|
||||||
{{if $.CurrentUser.Perms.LikeItem}}{{if .Liked}}<a href="/reply/like/submit/{{.ID}}?session={{$.CurrentUser.Session}}" class="mod_button" title="{{lang "topic_post_like_tooltip"}}" aria-label="{{lang "topic_post_like_aria"}}" style="color:#202020;"><button class="username like_label" style="background-color:#D6FFD6;"></button></a>{{else}}<a href="/reply/like/submit/{{.ID}}?session={{$.CurrentUser.Session}}" class="mod_button" title="{{lang "topic_post_unlike_tooltip"}}" aria-label="{{lang "topic_post_unlike_aria"}}" style="color:#202020;"><button class="username like_label"></button></a>{{end}}{{end}}
|
{{if $.CurrentUser.Perms.LikeItem}}{{if .Liked}}<a href="/reply/like/submit/{{.ID}}?session={{$.CurrentUser.Session}}" class="mod_button" title="{{lang "topic_post_like_tooltip"}}" aria-label="{{lang "topic_post_like_aria"}}" style="color:#202020;"><button class="username like_label remove_like"></button></a>{{else}}<a href="/reply/like/submit/{{.ID}}?session={{$.CurrentUser.Session}}" class="mod_button" title="{{lang "topic_post_unlike_tooltip"}}" aria-label="{{lang "topic_post_unlike_aria"}}" style="color:#202020;"><button class="username like_label add_like"></button></a>{{end}}{{end}}
|
||||||
|
|
||||||
{{if $.CurrentUser.Perms.EditReply}}<a href="/reply/edit/submit/{{.ID}}?session={{$.CurrentUser.Session}}" class="mod_button" title="{{lang "topic_post_edit_tooltip"}}" aria-label="{{lang "topic_post_edit_aria"}}"><button class="username edit_item edit_label"></button></a>{{end}}
|
{{if $.CurrentUser.Perms.EditReply}}<a href="/reply/edit/submit/{{.ID}}?session={{$.CurrentUser.Session}}" class="mod_button" title="{{lang "topic_post_edit_tooltip"}}" aria-label="{{lang "topic_post_edit_aria"}}"><button class="username edit_item edit_label"></button></a>{{end}}
|
||||||
|
|
||||||
|
@ -97,7 +97,7 @@
|
||||||
{{if $.CurrentUser.Perms.ViewIPs}}<a class="mod_button" href='/users/ips/?ip={{.IPAddress}}' style="font-weight:normal;" title="{{lang "topic_post_ip_tooltip"}}" aria-label="The poster's IP is {{.IPAddress}}"><button class="username ip_label"></button></a>{{end}}
|
{{if $.CurrentUser.Perms.ViewIPs}}<a class="mod_button" href='/users/ips/?ip={{.IPAddress}}' style="font-weight:normal;" title="{{lang "topic_post_ip_tooltip"}}" aria-label="The poster's IP is {{.IPAddress}}"><button class="username ip_label"></button></a>{{end}}
|
||||||
<a href="/report/submit/{{.ID}}?session={{$.CurrentUser.Session}}&type=reply" class="mod_button report_item" title="{{lang "topic_post_flag_tooltip"}}" aria-label="{{lang "topic_post_flag_aria"}}" rel="nofollow"><button class="username report_item flag_label"></button></a>
|
<a href="/report/submit/{{.ID}}?session={{$.CurrentUser.Session}}&type=reply" class="mod_button report_item" title="{{lang "topic_post_flag_tooltip"}}" aria-label="{{lang "topic_post_flag_aria"}}" rel="nofollow"><button class="username report_item flag_label"></button></a>
|
||||||
|
|
||||||
{{if .LikeCount}}<a class="username hide_on_micro like_count">{{.LikeCount}}</a><a class="username hide_on_micro like_count_label" title="{{lang "topic_post_like_count_tooltip"}}"></a>{{end}}
|
<a class="username hide_on_micro like_count">{{.LikeCount}}</a><a class="username hide_on_micro like_count_label" title="{{lang "topic_post_like_count_tooltip"}}"></a>
|
||||||
|
|
||||||
{{if .Tag}}<a class="username hide_on_micro user_tag">{{.Tag}}</a>{{else}}<a class="username hide_on_micro level" aria-label="{{lang "topic_post_level_aria"}}">{{.Level}}</a><a class="username hide_on_micro level_label" style="float:right;" title="{{lang "topic_post_level_tooltip"}}"></a>{{end}}
|
{{if .Tag}}<a class="username hide_on_micro user_tag">{{.Tag}}</a>{{else}}<a class="username hide_on_micro level" aria-label="{{lang "topic_post_level_aria"}}">{{.Level}}</a><a class="username hide_on_micro level_label" style="float:right;" title="{{lang "topic_post_level_tooltip"}}"></a>{{end}}
|
||||||
|
|
||||||
|
|
|
@ -8,10 +8,10 @@
|
||||||
|
|
||||||
<main>
|
<main>
|
||||||
|
|
||||||
<div class="rowblock rowhead topic_block" aria-label="{{lang "topic_opening_post_aria"}}">
|
<div {{scope "topic_title_block"}} class="rowblock rowhead topic_block" aria-label="{{lang "topic_opening_post_aria"}}">
|
||||||
<form action='/topic/edit/submit/{{.Topic.ID}}?session={{.CurrentUser.Session}}' method="post">
|
<form action='/topic/edit/submit/{{.Topic.ID}}?session={{.CurrentUser.Session}}' method="post">
|
||||||
<div class="rowitem topic_item{{if .Topic.Sticky}} topic_sticky_head{{else if .Topic.IsClosed}} topic_closed_head{{end}}">
|
<div class="rowitem topic_item{{if .Topic.Sticky}} topic_sticky_head{{else if .Topic.IsClosed}} topic_closed_head{{end}}">
|
||||||
<h1 class='topic_name hide_on_edit'>{{.Topic.Title}}</h1>
|
<h1 class='topic_name hide_on_edit' title='{{.Topic.Title}}'>{{.Topic.Title}}</h1>
|
||||||
{{/** TODO: Inline this CSS **/}}
|
{{/** TODO: Inline this CSS **/}}
|
||||||
{{if .Topic.IsClosed}}<span class='username hide_on_micro topic_status_e topic_status_closed hide_on_edit' title='{{lang "status_closed_tooltip"}}' aria-label='{{lang "topic_status_closed_aria"}}' style="font-weight:normal;float: right;position:relative;top:-5px;">🔒︎</span>{{end}}
|
{{if .Topic.IsClosed}}<span class='username hide_on_micro topic_status_e topic_status_closed hide_on_edit' title='{{lang "status_closed_tooltip"}}' aria-label='{{lang "topic_status_closed_aria"}}' style="font-weight:normal;float: right;position:relative;top:-5px;">🔒︎</span>{{end}}
|
||||||
{{if .CurrentUser.Perms.EditTopic}}
|
{{if .CurrentUser.Perms.EditTopic}}
|
||||||
|
@ -54,7 +54,7 @@
|
||||||
</div>
|
</div>
|
||||||
</article>
|
</article>
|
||||||
{{end}}
|
{{end}}
|
||||||
<article itemscope itemtype="http://schema.org/CreativeWork" class="rowitem passive deletable_block editable_parent post_item top_post" aria-label="{{lang "topic_opening_post_aria"}}">
|
<article {{scope "opening_post"}} itemscope itemtype="http://schema.org/CreativeWork" class="rowitem passive deletable_block editable_parent post_item top_post" aria-label="{{lang "topic_opening_post_aria"}}">
|
||||||
<div class="userinfo" aria-label="{{lang "topic_userinfo_aria"}}">
|
<div class="userinfo" aria-label="{{lang "topic_userinfo_aria"}}">
|
||||||
<div class="avatar_item" style="background-image: url({{.Topic.Avatar}}), url(/static/white-dot.jpg);background-position: 0px -10px;"> </div>
|
<div class="avatar_item" style="background-image: url({{.Topic.Avatar}}), url(/static/white-dot.jpg);background-position: 0px -10px;"> </div>
|
||||||
<a href="{{.Topic.UserLink}}" class="the_name" rel="author">{{.Topic.CreatedByName}}</a>
|
<a href="{{.Topic.UserLink}}" class="the_name" rel="author">{{.Topic.CreatedByName}}</a>
|
||||||
|
@ -63,9 +63,9 @@
|
||||||
<div class="content_container">
|
<div class="content_container">
|
||||||
<div class="hide_on_edit topic_content user_content" itemprop="text">{{.Topic.ContentHTML}}</div>
|
<div class="hide_on_edit topic_content user_content" itemprop="text">{{.Topic.ContentHTML}}</div>
|
||||||
<textarea name="topic_content" class="show_on_edit topic_content_input">{{.Topic.Content}}</textarea>
|
<textarea name="topic_content" class="show_on_edit topic_content_input">{{.Topic.Content}}</textarea>
|
||||||
<div class="button_container">
|
<div class="controls button_container{{if .Topic.LikeCount}} has_likes{{end}}">
|
||||||
{{if .CurrentUser.Loggedin}}
|
{{if .CurrentUser.Loggedin}}
|
||||||
{{if .CurrentUser.Perms.LikeItem}}<a href="/topic/like/submit/{{.Topic.ID}}?session={{.CurrentUser.Session}}" class="action_button like_item add_like" aria-label="{{lang "topic_like_aria"}}" data-action="like"></a>{{end}}
|
{{if .CurrentUser.Perms.LikeItem}}<a href="/topic/like/submit/{{.Topic.ID}}?session={{.CurrentUser.Session}}" class="action_button like_item {{if .Topic.Liked}}remove_like{{else}}add_like{{end}}" aria-label="{{lang "topic_like_aria"}}" data-action="like"></a>{{end}}
|
||||||
{{if .CurrentUser.Perms.EditTopic}}<a href="/topic/edit/{{.Topic.ID}}" class="action_button open_edit" aria-label="{{lang "topic_edit_aria"}}" data-action="edit"></a>{{end}}
|
{{if .CurrentUser.Perms.EditTopic}}<a href="/topic/edit/{{.Topic.ID}}" class="action_button open_edit" aria-label="{{lang "topic_edit_aria"}}" data-action="edit"></a>{{end}}
|
||||||
{{if .CurrentUser.Perms.DeleteTopic}}<a href="/topic/delete/submit/{{.Topic.ID}}?session={{.CurrentUser.Session}}" class="action_button delete_item" aria-label="{{lang "topic_delete_aria"}}" data-action="delete"></a>{{end}}
|
{{if .CurrentUser.Perms.DeleteTopic}}<a href="/topic/delete/submit/{{.Topic.ID}}?session={{.CurrentUser.Session}}" class="action_button delete_item" aria-label="{{lang "topic_delete_aria"}}" data-action="delete"></a>{{end}}
|
||||||
{{if .CurrentUser.Perms.CloseTopic}}
|
{{if .CurrentUser.Perms.CloseTopic}}
|
||||||
|
@ -76,8 +76,8 @@
|
||||||
<a href="/report/submit/{{.Topic.ID}}?session={{.CurrentUser.Session}}&type=topic" class="action_button report_item" aria-label="{{lang "topic_report_aria"}}" data-action="report"></a>
|
<a href="/report/submit/{{.Topic.ID}}?session={{.CurrentUser.Session}}&type=topic" class="action_button report_item" aria-label="{{lang "topic_report_aria"}}" data-action="report"></a>
|
||||||
<a href="#" class="action_button button_menu"></a>
|
<a href="#" class="action_button button_menu"></a>
|
||||||
{{end}}
|
{{end}}
|
||||||
<div class="action_button_right{{if .Topic.LikeCount}} has_likes{{end}}">
|
<div class="action_button_right">
|
||||||
{{if .Topic.LikeCount}}<a class="action_button like_count hide_on_micro" aria-label="{{lang "topic_like_count_aria"}}">{{.Topic.LikeCount}}</a>{{end}}
|
<a class="action_button like_count hide_on_micro" aria-label="{{lang "topic_like_count_aria"}}">{{.Topic.LikeCount}}</a>
|
||||||
<a class="action_button created_at hide_on_mobile">{{.Topic.RelativeCreatedAt}}</a>
|
<a class="action_button created_at hide_on_mobile">{{.Topic.RelativeCreatedAt}}</a>
|
||||||
{{if .CurrentUser.Perms.ViewIPs}}<a href="/users/ips/?ip={{.Topic.IPAddress}}" title="{{lang "topic_ip_full_tooltip"}}" class="action_button ip_item hide_on_mobile" aria-hidden="true">{{.Topic.IPAddress}}</a>{{end}}
|
{{if .CurrentUser.Perms.ViewIPs}}<a href="/users/ips/?ip={{.Topic.IPAddress}}" title="{{lang "topic_ip_full_tooltip"}}" class="action_button ip_item hide_on_mobile" aria-hidden="true">{{.Topic.IPAddress}}</a>{{end}}
|
||||||
</div>
|
</div>
|
||||||
|
@ -86,7 +86,7 @@
|
||||||
</article>
|
</article>
|
||||||
|
|
||||||
{{range .ItemList}}
|
{{range .ItemList}}
|
||||||
<article itemscope itemtype="http://schema.org/CreativeWork" class="rowitem passive deletable_block editable_parent post_item {{if .ActionType}}action_item{{end}}">
|
<article {{scope "post"}} itemscope itemtype="http://schema.org/CreativeWork" class="rowitem passive deletable_block editable_parent post_item {{if .ActionType}}action_item{{end}}">
|
||||||
<div class="userinfo" aria-label="{{lang "topic_userinfo_aria"}}">
|
<div class="userinfo" aria-label="{{lang "topic_userinfo_aria"}}">
|
||||||
<div class="avatar_item" style="background-image: url({{.Avatar}}), url(/static/white-dot.jpg);background-position: 0px -10px;"> </div>
|
<div class="avatar_item" style="background-image: url({{.Avatar}}), url(/static/white-dot.jpg);background-position: 0px -10px;"> </div>
|
||||||
<a href="{{.UserLink}}" class="the_name" rel="author">{{.CreatedByName}}</a>
|
<a href="{{.UserLink}}" class="the_name" rel="author">{{.CreatedByName}}</a>
|
||||||
|
@ -99,17 +99,17 @@
|
||||||
{{else}}
|
{{else}}
|
||||||
{{/** TODO: We might end up with <br>s in the inline editor, fix this **/}}
|
{{/** TODO: We might end up with <br>s in the inline editor, fix this **/}}
|
||||||
<div class="editable_block user_content" itemprop="text">{{.ContentHtml}}</div>
|
<div class="editable_block user_content" itemprop="text">{{.ContentHtml}}</div>
|
||||||
<div class="button_container">
|
<div class="controls button_container{{if .LikeCount}} has_likes{{end}}">
|
||||||
{{if $.CurrentUser.Loggedin}}
|
{{if $.CurrentUser.Loggedin}}
|
||||||
{{if $.CurrentUser.Perms.LikeItem}}<a href="/reply/like/submit/{{.ID}}?session={{$.CurrentUser.Session}}" class="action_button like_item add_like" aria-label="{{lang "topic_post_like_aria"}}" data-action="like"></a>{{end}}
|
{{if $.CurrentUser.Perms.LikeItem}}<a href="/reply/like/submit/{{.ID}}?session={{$.CurrentUser.Session}}" class="action_button like_item {{if .Liked}}remove_like{{else}}add_like{{end}}" aria-label="{{lang "topic_post_like_aria"}}" data-action="like"></a>{{end}}
|
||||||
{{if $.CurrentUser.Perms.EditReply}}<a href="/reply/edit/submit/{{.ID}}?session={{$.CurrentUser.Session}}" class="action_button edit_item" aria-label="{{lang "topic_post_edit_aria"}}" data-action="edit"></a>{{end}}
|
{{if $.CurrentUser.Perms.EditReply}}<a href="/reply/edit/submit/{{.ID}}?session={{$.CurrentUser.Session}}" class="action_button edit_item" aria-label="{{lang "topic_post_edit_aria"}}" data-action="edit"></a>{{end}}
|
||||||
{{if $.CurrentUser.Perms.DeleteReply}}<a href="/reply/delete/submit/{{.ID}}?session={{$.CurrentUser.Session}}" class="action_button delete_item" aria-label="{{lang "topic_post_delete_aria"}}" data-action="delete"></a>{{end}}
|
{{if $.CurrentUser.Perms.DeleteReply}}<a href="/reply/delete/submit/{{.ID}}?session={{$.CurrentUser.Session}}" class="action_button delete_item" aria-label="{{lang "topic_post_delete_aria"}}" data-action="delete"></a>{{end}}
|
||||||
{{if $.CurrentUser.Perms.ViewIPs}}<a href="/users/ips/?ip={{.IPAddress}}" title="{{lang "topic_ip_full_tooltip"}}" class="action_button ip_item_button hide_on_big" aria-label="{{lang "topic_ip_full_aria"}}" data-action="ip"></a>{{end}}
|
{{if $.CurrentUser.Perms.ViewIPs}}<a href="/users/ips/?ip={{.IPAddress}}" title="{{lang "topic_ip_full_tooltip"}}" class="action_button ip_item_button hide_on_big" aria-label="{{lang "topic_ip_full_aria"}}" data-action="ip"></a>{{end}}
|
||||||
<a href="/report/submit/{{.ID}}?session={{$.CurrentUser.Session}}&type=reply" class="action_button report_item" aria-label="{{lang "topic_report_aria"}}" data-action="report"></a>
|
<a href="/report/submit/{{.ID}}?session={{$.CurrentUser.Session}}&type=reply" class="action_button report_item" aria-label="{{lang "topic_report_aria"}}" data-action="report"></a>
|
||||||
<a href="#" class="action_button button_menu"></a>
|
<a href="#" class="action_button button_menu"></a>
|
||||||
{{end}}
|
{{end}}
|
||||||
<div class="action_button_right{{if .LikeCount}} has_likes{{end}}">
|
<div class="action_button_right">
|
||||||
{{if .LikeCount}}<a class="action_button like_count hide_on_micro" aria-label="{{lang "topic_post_like_count_tooltip"}}">{{.LikeCount}}</a>{{end}}
|
<a class="action_button like_count hide_on_micro" aria-label="{{lang "topic_post_like_count_tooltip"}}">{{.LikeCount}}</a>
|
||||||
<a class="action_button created_at hide_on_mobile">{{.RelativeCreatedAt}}</a>
|
<a class="action_button created_at hide_on_mobile">{{.RelativeCreatedAt}}</a>
|
||||||
{{if $.CurrentUser.Perms.ViewIPs}}<a href="/users/ips/?ip={{.IPAddress}}" title="IP Address" class="action_button ip_item hide_on_mobile" aria-hidden="true">{{.IPAddress}}</a>{{end}}
|
{{if $.CurrentUser.Perms.ViewIPs}}<a href="/users/ips/?ip={{.IPAddress}}" title="IP Address" class="action_button ip_item hide_on_mobile" aria-hidden="true">{{.IPAddress}}</a>{{end}}
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -107,8 +107,8 @@
|
||||||
<span class="selector"></span>
|
<span class="selector"></span>
|
||||||
<a href="{{.Creator.Link}}"><img src="{{.Creator.Avatar}}" height="64" alt="{{.Creator.Name}}'s Avatar" title="{{.Creator.Name}}'s Avatar" /></a>
|
<a href="{{.Creator.Link}}"><img src="{{.Creator.Avatar}}" height="64" alt="{{.Creator.Name}}'s Avatar" title="{{.Creator.Name}}'s Avatar" /></a>
|
||||||
<span class="topic_inner_left">
|
<span class="topic_inner_left">
|
||||||
<a class="rowtopic" href="{{.Link}}" itemprop="itemListElement"><span>{{.Title}}</span></a> {{if .ForumName}}<a class="rowsmall parent_forum" href="{{.ForumLink}}">{{.ForumName}}</a>{{end}}
|
<a class="rowtopic" href="{{.Link}}" itemprop="itemListElement" title="{{.Title}}"><span>{{.Title}}</span></a> {{if .ForumName}}<a class="rowsmall parent_forum" href="{{.ForumLink}}" title="{{.ForumName}}">{{.ForumName}}</a>{{end}}
|
||||||
<br /><a class="rowsmall starter" href="{{.Creator.Link}}">{{.Creator.Name}}</a>
|
<br /><a class="rowsmall starter" href="{{.Creator.Link}}" title="{{.Creator.Name}}">{{.Creator.Name}}</a>
|
||||||
{{/** TODO: Avoid the double '|' when both .IsClosed and .Sticky are set to true. We could probably do this with CSS **/}}
|
{{/** TODO: Avoid the double '|' when both .IsClosed and .Sticky are set to true. We could probably do this with CSS **/}}
|
||||||
{{if .IsClosed}}<span class="rowsmall topic_status_e topic_status_closed" title="{{lang "status_closed_tooltip"}}"> | 🔒︎</span>{{end}}
|
{{if .IsClosed}}<span class="rowsmall topic_status_e topic_status_closed" title="{{lang "status_closed_tooltip"}}"> | 🔒︎</span>{{end}}
|
||||||
{{if .Sticky}}<span class="rowsmall topic_status_e topic_status_sticky" title="{{lang "status_pinned_tooltip"}}"> | 📍︎</span>{{end}}
|
{{if .Sticky}}<span class="rowsmall topic_status_e topic_status_sticky" title="{{lang "status_pinned_tooltip"}}"> | 📍︎</span>{{end}}
|
||||||
|
@ -121,7 +121,7 @@
|
||||||
<div class="rowitem topic_right passive datarow {{if .Sticky}}topic_sticky{{else if .IsClosed}}topic_closed{{end}}">
|
<div class="rowitem topic_right passive datarow {{if .Sticky}}topic_sticky{{else if .IsClosed}}topic_closed{{end}}">
|
||||||
<a href="{{.LastUser.Link}}"><img src="{{.LastUser.Avatar}}" height="64" alt="{{.LastUser.Name}}'s Avatar" title="{{.LastUser.Name}}'s Avatar" /></a>
|
<a href="{{.LastUser.Link}}"><img src="{{.LastUser.Avatar}}" height="64" alt="{{.LastUser.Name}}'s Avatar" title="{{.LastUser.Name}}'s Avatar" /></a>
|
||||||
<span>
|
<span>
|
||||||
<a href="{{.LastUser.Link}}" class="lastName" style="font-size: 14px;">{{.LastUser.Name}}</a><br>
|
<a href="{{.LastUser.Link}}" class="lastName" style="font-size: 14px;" title="{{.LastUser.Name}}">{{.LastUser.Name}}</a><br>
|
||||||
<span class="rowsmall lastReplyAt">{{.RelativeLastReplyAt}}</span>
|
<span class="rowsmall lastReplyAt">{{.RelativeLastReplyAt}}</span>
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -1002,12 +1002,18 @@ textarea {
|
||||||
display: inline-flex;
|
display: inline-flex;
|
||||||
margin-left: auto;
|
margin-left: auto;
|
||||||
}
|
}
|
||||||
|
.like_count {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
.has_likes .like_count {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
.like_count:after {
|
.like_count:after {
|
||||||
content: "{{index .Phrases "topic_like_count_suffix"}}";
|
content: "{{index .Phrases "topic_like_count_suffix"}}";
|
||||||
margin-right: 6px;
|
margin-right: 6px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.post_item .add_like:after,
|
.post_item .add_like:after, .post_item .remove_like:after,
|
||||||
.created_at:before,
|
.created_at:before,
|
||||||
.ip_item:before {
|
.ip_item:before {
|
||||||
border-left: 1px solid var(--element-border-color);
|
border-left: 1px solid var(--element-border-color);
|
||||||
|
@ -1018,15 +1024,19 @@ textarea {
|
||||||
.created_at:before, .ip_item:before {
|
.created_at:before, .ip_item:before {
|
||||||
margin-right: 10px;
|
margin-right: 10px;
|
||||||
}
|
}
|
||||||
.post_item .add_like:after {
|
.post_item .add_like:after, .post_item .remove_like:after {
|
||||||
margin-left: 10px;
|
margin-left: 10px;
|
||||||
margin-right: 5px;
|
margin-right: 5px;
|
||||||
}
|
}
|
||||||
|
/* TODO: Use a less bold bold */
|
||||||
|
.post_item .remove_like:before {
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
.created_at {
|
.created_at {
|
||||||
margin-right: 10px;
|
margin-right: 10px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.add_like:before {
|
.add_like:before, .remove_like:before {
|
||||||
content: "{{index .Phrases "topic_plus_one"}}";
|
content: "{{index .Phrases "topic_plus_one"}}";
|
||||||
}
|
}
|
||||||
.button_container .open_edit:after, .edit_item:after{
|
.button_container .open_edit:after, .edit_item:after{
|
||||||
|
@ -1651,10 +1661,10 @@ textarea {
|
||||||
padding-top: 15px;
|
padding-top: 15px;
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
}
|
}
|
||||||
.action_button:not(.add_like) {
|
.action_button:not(.add_like):not(.remove_like) {
|
||||||
font: normal normal normal 14px/1 FontAwesome;
|
font: normal normal normal 14px/1 FontAwesome;
|
||||||
}
|
}
|
||||||
.action_button_right.has_likes {
|
.has_likes .action_button_right {
|
||||||
margin-left: 0px;
|
margin-left: 0px;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
|
@ -1664,7 +1674,7 @@ textarea {
|
||||||
.post_item:not(.top_post) .like_item {
|
.post_item:not(.top_post) .like_item {
|
||||||
border-bottom: 1px solid var(--element-border-color);
|
border-bottom: 1px solid var(--element-border-color);
|
||||||
}
|
}
|
||||||
.post_item .add_like:after {
|
.post_item .add_like:after, .post_item .remove_like:after {
|
||||||
border-left: none;
|
border-left: none;
|
||||||
margin: inherit;
|
margin: inherit;
|
||||||
}
|
}
|
||||||
|
@ -1810,7 +1820,7 @@ textarea {
|
||||||
.button_menu_pane .action_button:nth-last-child(-n+8) {
|
.button_menu_pane .action_button:nth-last-child(-n+8) {
|
||||||
border-bottom: none;
|
border-bottom: none;
|
||||||
}
|
}
|
||||||
.button_menu_pane .action_button:after, .button_menu_pane .add_like:before {
|
.button_menu_pane .action_button:after, .button_menu_pane .add_like:before, .button_menu_pane .remove_like:before {
|
||||||
margin-left: auto;
|
margin-left: auto;
|
||||||
margin-right: auto;
|
margin-right: auto;
|
||||||
}
|
}
|
||||||
|
|
|
@ -336,16 +336,19 @@ a {
|
||||||
content: "{{index .Phrases "topic_level"}}";
|
content: "{{index .Phrases "topic_level"}}";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.like_count_label, .like_count {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
.like_count_label:before {
|
.like_count_label:before {
|
||||||
content: "{{index .Phrases "topics_likes_suffix"}}";
|
content: "{{index .Phrases "topics_likes_suffix"}}";
|
||||||
}
|
}
|
||||||
.like_count_label {
|
.has_likes .like_count_label {
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
display: block;
|
display: block;
|
||||||
float: left;
|
float: left;
|
||||||
line-height: 19px;
|
line-height: 19px;
|
||||||
}
|
}
|
||||||
.like_count {
|
.has_likes .like_count {
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
display: block;
|
display: block;
|
||||||
float: left;
|
float: left;
|
||||||
|
|
|
@ -6,6 +6,12 @@
|
||||||
"FullImage": "shadow.png",
|
"FullImage": "shadow.png",
|
||||||
"URL": "github.com/Azareal/Gosora",
|
"URL": "github.com/Azareal/Gosora",
|
||||||
"BgAvatars":true,
|
"BgAvatars":true,
|
||||||
|
"Templates": [
|
||||||
|
{
|
||||||
|
"Name": "topic",
|
||||||
|
"Source": "topic"
|
||||||
|
}
|
||||||
|
],
|
||||||
"Resources": [
|
"Resources": [
|
||||||
{
|
{
|
||||||
"Name":"shadow/misc.js",
|
"Name":"shadow/misc.js",
|
||||||
|
|
|
@ -716,6 +716,12 @@ button.username {
|
||||||
margin-right: auto;
|
margin-right: auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.like_count {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
.has_likes .like_count {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
.like_label:before {
|
.like_label:before {
|
||||||
content: "😀";
|
content: "😀";
|
||||||
}
|
}
|
||||||
|
@ -961,7 +967,7 @@ input[type=checkbox]:checked + label.poll_option_label .sel {
|
||||||
margin-bottom: 6px !important;
|
margin-bottom: 6px !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
.add_like:before {
|
.add_like:before, .remove_like:before {
|
||||||
content: "{{index .Phrases "topic_plus_one"}}";
|
content: "{{index .Phrases "topic_plus_one"}}";
|
||||||
}
|
}
|
||||||
.button_container .open_edit:after, .edit_item:after {
|
.button_container .open_edit:after, .edit_item:after {
|
||||||
|
|
|
@ -9,5 +9,11 @@
|
||||||
"HideFromThemes": true,
|
"HideFromThemes": true,
|
||||||
"BgAvatars":true,
|
"BgAvatars":true,
|
||||||
"URL": "github.com/Azareal/Gosora",
|
"URL": "github.com/Azareal/Gosora",
|
||||||
|
"Templates": [
|
||||||
|
{
|
||||||
|
"Name": "topic",
|
||||||
|
"Source": "topic"
|
||||||
|
}
|
||||||
|
],
|
||||||
"Docks":["rightSidebar"]
|
"Docks":["rightSidebar"]
|
||||||
}
|
}
|
||||||
|
|
|
@ -647,6 +647,12 @@ button.username {
|
||||||
.mod_button {
|
.mod_button {
|
||||||
margin-right: 4px;
|
margin-right: 4px;
|
||||||
}
|
}
|
||||||
|
.like_count_label, .like_count {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
.has_likes .like_count_label, .has_likes .like_count {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
.like_label:before, .like_count_label:before {
|
.like_label:before, .like_count_label:before {
|
||||||
content: "😀";
|
content: "😀";
|
||||||
}
|
}
|
||||||
|
@ -674,7 +680,7 @@ button.username {
|
||||||
.pin_label:before, .unpin_label:before {
|
.pin_label:before, .unpin_label:before {
|
||||||
content: "📌";
|
content: "📌";
|
||||||
}
|
}
|
||||||
.unpin_label, .unlock_label {
|
.remove_like, .unpin_label, .unlock_label {
|
||||||
background-color: #D6FFD6;
|
background-color: #D6FFD6;
|
||||||
}
|
}
|
||||||
.lock_label:before, .unlock_label:before {
|
.lock_label:before, .unlock_label:before {
|
||||||
|
|
|
@ -8,6 +8,12 @@
|
||||||
"URL": "github.com/Azareal/Gosora",
|
"URL": "github.com/Azareal/Gosora",
|
||||||
"BgAvatars":true,
|
"BgAvatars":true,
|
||||||
"Docks":["rightSidebar"],
|
"Docks":["rightSidebar"],
|
||||||
|
"Templates": [
|
||||||
|
{
|
||||||
|
"Name": "topic",
|
||||||
|
"Source": "topic"
|
||||||
|
}
|
||||||
|
],
|
||||||
"Resources": [
|
"Resources": [
|
||||||
{
|
{
|
||||||
"Name":"tempra-simple/misc.js",
|
"Name":"tempra-simple/misc.js",
|
||||||
|
|
Loading…
Reference in New Issue