Show the names of the participants on the convo list instead of the placeholder text.
Shorten some things to save a bit of memory and to standardise things.
This commit is contained in:
parent
cae7e00b0c
commit
ddb917761f
|
@ -3,8 +3,9 @@ package common
|
|||
import (
|
||||
"errors"
|
||||
"time"
|
||||
//"log"
|
||||
|
||||
//"strconv"
|
||||
"strconv"
|
||||
"database/sql"
|
||||
|
||||
qgen "github.com/Azareal/Gosora/query_gen"
|
||||
|
@ -20,7 +21,7 @@ type ConvoStmts struct {
|
|||
edit *sql.Stmt
|
||||
create *sql.Stmt
|
||||
delete *sql.Stmt
|
||||
has *sql.Stmt
|
||||
has *sql.Stmt
|
||||
|
||||
editPost *sql.Stmt
|
||||
createPost *sql.Stmt
|
||||
|
@ -37,7 +38,7 @@ func init() {
|
|||
countPosts: acc.Count("conversations_posts").Where("cid = ?").Prepare(),
|
||||
edit: acc.Update("conversations").Set("lastReplyBy = ?, lastReplyAt = ?").Where("cid = ?").Prepare(),
|
||||
create: acc.Insert("conversations").Columns("createdAt, lastReplyAt").Fields("UTC_TIMESTAMP(),UTC_TIMESTAMP()").Prepare(),
|
||||
has: acc.Count("conversations_participants").Where("uid = ? AND cid = ?").Prepare(),
|
||||
has: acc.Count("conversations_participants").Where("uid = ? AND cid = ?").Prepare(),
|
||||
|
||||
editPost: acc.Update("conversations_posts").Set("body = ?, post = ?").Where("pid = ?").Prepare(),
|
||||
createPost: acc.Insert("conversations_posts").Columns("cid, body, post, createdBy").Fields("?,?,?,?").Prepare(),
|
||||
|
@ -130,9 +131,15 @@ func (co *Conversation) Create() (int, error) {
|
|||
return int(lastID), err
|
||||
}
|
||||
|
||||
type ConversationExtra struct {
|
||||
*Conversation
|
||||
Users []*User
|
||||
}
|
||||
|
||||
type ConversationStore interface {
|
||||
Get(id int) (*Conversation, error)
|
||||
GetUser(uid int, offset int) (cos []*Conversation, err error)
|
||||
GetUserExtra(uid int, offset int) (cos []*ConversationExtra, err error)
|
||||
GetUserCount(uid int) (count int)
|
||||
Delete(id int) error
|
||||
Count() (count int)
|
||||
|
@ -140,35 +147,35 @@ type ConversationStore interface {
|
|||
}
|
||||
|
||||
type DefaultConversationStore struct {
|
||||
get *sql.Stmt
|
||||
getUser *sql.Stmt
|
||||
getUserCount *sql.Stmt
|
||||
delete *sql.Stmt
|
||||
deletePosts *sql.Stmt
|
||||
get *sql.Stmt
|
||||
getUser *sql.Stmt
|
||||
getUserCount *sql.Stmt
|
||||
delete *sql.Stmt
|
||||
deletePosts *sql.Stmt
|
||||
deleteParticipants *sql.Stmt
|
||||
create *sql.Stmt
|
||||
addParticipant *sql.Stmt
|
||||
count *sql.Stmt
|
||||
create *sql.Stmt
|
||||
addParticipant *sql.Stmt
|
||||
count *sql.Stmt
|
||||
}
|
||||
|
||||
func NewDefaultConversationStore(acc *qgen.Accumulator) (*DefaultConversationStore, error) {
|
||||
return &DefaultConversationStore{
|
||||
get: acc.Select("conversations").Columns("createdBy, createdAt, lastReplyBy, lastReplyAt").Where("cid = ?").Prepare(),
|
||||
getUser: acc.SimpleInnerJoin("conversations_participants AS cp", "conversations AS c", "cp.cid, c.createdBy, c.createdAt, c.lastReplyBy, c.lastReplyAt", "cp.cid = c.cid", "cp.uid = ?", "c.lastReplyAt DESC, c.createdAt DESC, c.cid DESC", "?,?"),
|
||||
getUserCount: acc.Count("conversations_participants").Where("uid = ?").Prepare(),
|
||||
delete: acc.Delete("conversations").Where("cid = ?").Prepare(),
|
||||
deletePosts: acc.Delete("conversations_posts").Where("cid = ?").Prepare(),
|
||||
deleteParticipants: acc.Delete("conversations_participants").Where("cid = ?").Prepare(),
|
||||
create: acc.Insert("conversations").Columns("createdBy, createdAt, lastReplyAt").Fields("?,UTC_TIMESTAMP(),UTC_TIMESTAMP()").Prepare(),
|
||||
addParticipant: acc.Insert("conversations_participants").Columns("uid, cid").Fields("?,?").Prepare(),
|
||||
count: acc.Count("conversations").Prepare(),
|
||||
get: acc.Select("conversations").Columns("createdBy, createdAt, lastReplyBy, lastReplyAt").Where("cid = ?").Prepare(),
|
||||
getUser: acc.SimpleInnerJoin("conversations_participants AS cp", "conversations AS c", "cp.cid, c.createdBy, c.createdAt, c.lastReplyBy, c.lastReplyAt", "cp.cid = c.cid", "cp.uid = ?", "c.lastReplyAt DESC, c.createdAt DESC, c.cid DESC", "?,?"),
|
||||
getUserCount: acc.Count("conversations_participants").Where("uid = ?").Prepare(),
|
||||
delete: acc.Delete("conversations").Where("cid = ?").Prepare(),
|
||||
deletePosts: acc.Delete("conversations_posts").Where("cid = ?").Prepare(),
|
||||
deleteParticipants: acc.Delete("conversations_participants").Where("cid = ?").Prepare(),
|
||||
create: acc.Insert("conversations").Columns("createdBy, createdAt, lastReplyAt").Fields("?,UTC_TIMESTAMP(),UTC_TIMESTAMP()").Prepare(),
|
||||
addParticipant: acc.Insert("conversations_participants").Columns("uid, cid").Fields("?,?").Prepare(),
|
||||
count: acc.Count("conversations").Prepare(),
|
||||
}, acc.FirstError()
|
||||
}
|
||||
|
||||
func (s *DefaultConversationStore) Get(id int) (*Conversation, error) {
|
||||
convo := &Conversation{ID: id}
|
||||
err := s.get.QueryRow(id).Scan(&convo.CreatedBy, &convo.CreatedAt, &convo.LastReplyBy, &convo.LastReplyAt)
|
||||
return convo, err
|
||||
co := &Conversation{ID: id}
|
||||
err := s.get.QueryRow(id).Scan(&co.CreatedBy, &co.CreatedAt, &co.LastReplyBy, &co.LastReplyAt)
|
||||
return co, err
|
||||
}
|
||||
|
||||
func (s *DefaultConversationStore) GetUser(uid int, offset int) (cos []*Conversation, err error) {
|
||||
|
@ -190,6 +197,109 @@ func (s *DefaultConversationStore) GetUser(uid int, offset int) (cos []*Conversa
|
|||
return cos, rows.Err()
|
||||
}
|
||||
|
||||
func (s *DefaultConversationStore) GetUserExtra(uid int, offset int) (cos []*ConversationExtra, err error) {
|
||||
raw, err := s.GetUser(uid, offset)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
//log.Printf("raw: %+v\n", raw)
|
||||
|
||||
if len(raw) == 0 {
|
||||
//log.Println("r0")
|
||||
return nil, sql.ErrNoRows
|
||||
}
|
||||
if len(raw) == 1 {
|
||||
//log.Print("r0b2")
|
||||
uids, err := raw[0].Uids()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
//log.Println("r1b2")
|
||||
umap, err := Users.BulkGetMap(uids)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
//log.Println("r2b2")
|
||||
users := make([]*User,len(umap))
|
||||
var i int
|
||||
for _, user := range umap {
|
||||
users[i] = user
|
||||
i++
|
||||
}
|
||||
return []*ConversationExtra{&ConversationExtra{raw[0],users}}, nil
|
||||
}
|
||||
//log.Println("1")
|
||||
|
||||
cmap := make(map[int]*ConversationExtra,len(raw))
|
||||
for _, co := range raw {
|
||||
cmap[co.ID] = &ConversationExtra{co,nil}
|
||||
}
|
||||
|
||||
// TODO: Add a function for the q stuff
|
||||
var q string
|
||||
idList := make([]interface{},len(raw))
|
||||
for i, co := range raw {
|
||||
idList[i] = strconv.Itoa(co.ID)
|
||||
q += "?,"
|
||||
}
|
||||
q = q[0 : len(q)-1]
|
||||
|
||||
rows, err := qgen.NewAcc().Select("conversations_participants").Columns("uid,cid").Where("cid IN(" + q + ")").Query(idList...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer rows.Close()
|
||||
//log.Println("2")
|
||||
|
||||
idmap := make(map[int][]int) // cid: []uid
|
||||
puidmap := make(map[int]struct{})
|
||||
for rows.Next() {
|
||||
var uid, cid int
|
||||
err := rows.Scan(&uid, &cid)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
idmap[cid] = append(idmap[cid],uid)
|
||||
puidmap[uid] = struct{}{}
|
||||
}
|
||||
err = rows.Err()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
//log.Println("3")
|
||||
//log.Printf("idmap: %+v\n", idmap)
|
||||
//log.Printf("puidmap: %+v\n",puidmap)
|
||||
|
||||
puids := make([]int,len(puidmap))
|
||||
var i int
|
||||
for puid, _ := range puidmap {
|
||||
puids[i] = puid
|
||||
i++
|
||||
}
|
||||
umap, err := Users.BulkGetMap(puids)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
//log.Println("4")
|
||||
//log.Printf("umap: %+v\n", umap)
|
||||
for cid, uids := range idmap {
|
||||
co := cmap[cid]
|
||||
for _, uid := range uids {
|
||||
co.Users = append(co.Users,umap[uid])
|
||||
}
|
||||
//log.Printf("co.Conversation: %+v\n", co.Conversation)
|
||||
//log.Printf("co.Users: %+v\n", co.Users)
|
||||
cmap[cid] = co
|
||||
}
|
||||
//log.Printf("cmap: %+v\n", cmap)
|
||||
for _, ra := range raw {
|
||||
cos = append(cos,cmap[ra.ID])
|
||||
}
|
||||
//log.Printf("cos: %+v\n", cos)
|
||||
|
||||
return cos, rows.Err()
|
||||
}
|
||||
|
||||
func (s *DefaultConversationStore) GetUserCount(uid int) (count int) {
|
||||
err := s.getUserCount.QueryRow(uid).Scan(&count)
|
||||
if err != nil {
|
||||
|
@ -225,10 +335,7 @@ func (s *DefaultConversationStore) Create(content string, createdBy int, partici
|
|||
return 0, err
|
||||
}
|
||||
|
||||
post := &ConversationPost{}
|
||||
post.CID = int(lastID)
|
||||
post.Body = content
|
||||
post.CreatedBy = createdBy
|
||||
post := &ConversationPost{CID: int(lastID), Body: content, CreatedBy: createdBy}
|
||||
_, err = post.Create()
|
||||
if err != nil {
|
||||
return 0, err
|
||||
|
|
|
@ -81,7 +81,7 @@ func (s *MemoryForumPermsStore) Reload(fid int) error {
|
|||
}
|
||||
defer rows.Close()
|
||||
|
||||
var forumPerms = make(map[int]*ForumPerms)
|
||||
forumPerms := make(map[int]*ForumPerms)
|
||||
for rows.Next() {
|
||||
var gid int
|
||||
var perms []byte
|
||||
|
|
|
@ -265,7 +265,7 @@ type ResetPage struct {
|
|||
|
||||
type ConvoListPage struct {
|
||||
*Header
|
||||
Convos []*Conversation
|
||||
Convos []*ConversationExtra
|
||||
Paginator
|
||||
}
|
||||
|
||||
|
|
|
@ -145,15 +145,15 @@ func (s *DefaultPollStore) BulkGetMap(ids []int) (list map[int]*Poll, err error)
|
|||
}
|
||||
|
||||
// TODO: Add a function for the qlist stuff
|
||||
var qlist string
|
||||
var q string
|
||||
idList := make([]interface{},len(ids))
|
||||
for i, id := range ids {
|
||||
idList[i] = strconv.Itoa(id)
|
||||
qlist += "?,"
|
||||
q += "?,"
|
||||
}
|
||||
qlist = qlist[0 : len(qlist)-1]
|
||||
q = q[0 : len(q)-1]
|
||||
|
||||
rows, err := qgen.NewAcc().Select("polls").Columns("pollID, parentID, parentTable, type, options, votes").Where("pollID IN(" + qlist + ")").Query(idList...)
|
||||
rows, err := qgen.NewAcc().Select("polls").Columns("pollID,parentID,parentTable,type,options,votes").Where("pollID IN(" + q + ")").Query(idList...)
|
||||
if err != nil {
|
||||
return list, err
|
||||
}
|
||||
|
|
|
@ -16,7 +16,6 @@ import (
|
|||
)
|
||||
|
||||
// TODO: Add the watchdog goroutine
|
||||
// TODO: Add BulkGetMap
|
||||
// TODO: Add some sort of update method
|
||||
// ? - Should we add stick, lock, unstick, and unlock methods? These might be better on the Topics not the TopicStore
|
||||
var Topics TopicStore
|
||||
|
@ -104,7 +103,7 @@ func (s *DefaultTopicStore) BypassGet(id int) (*Topic, error) {
|
|||
|
||||
// TODO: Avoid duplicating much of this logic from user_store.go
|
||||
func (s *DefaultTopicStore) BulkGetMap(ids []int) (list map[int]*Topic, err error) {
|
||||
var idCount = len(ids)
|
||||
idCount := len(ids)
|
||||
list = make(map[int]*Topic)
|
||||
if idCount == 0 {
|
||||
return list, nil
|
||||
|
@ -136,15 +135,15 @@ func (s *DefaultTopicStore) BulkGetMap(ids []int) (list map[int]*Topic, err erro
|
|||
}
|
||||
|
||||
// TODO: Add a function for the qlist stuff
|
||||
var qlist string
|
||||
var q string
|
||||
idList := make([]interface{},len(ids))
|
||||
for i, id := range ids {
|
||||
idList[i] = strconv.Itoa(id)
|
||||
qlist += "?,"
|
||||
q += "?,"
|
||||
}
|
||||
qlist = qlist[0 : len(qlist)-1]
|
||||
q = q[0 : len(q)-1]
|
||||
|
||||
rows, err := qgen.NewAcc().Select("topics").Columns("tid, title, content, createdBy, createdAt, lastReplyBy, lastReplyAt, lastReplyID, is_closed, sticky, parentID, ipaddress, views, postCount, likeCount, attachCount, poll, data").Where("tid IN(" + qlist + ")").Query(idList...)
|
||||
rows, err := qgen.NewAcc().Select("topics").Columns("tid,title,content,createdBy,createdAt,lastReplyBy,lastReplyAt,lastReplyID,is_closed,sticky,parentID,ipaddress,views,postCount,likeCount,attachCount,poll,data").Where("tid IN(" + q + ")").Query(idList...)
|
||||
if err != nil {
|
||||
return list, err
|
||||
}
|
||||
|
|
|
@ -63,78 +63,67 @@ func NewDefaultUserStore(cache UserCache) (*DefaultUserStore, error) {
|
|||
}, acc.FirstError()
|
||||
}
|
||||
|
||||
func (mus *DefaultUserStore) DirtyGet(id int) *User {
|
||||
user, err := mus.cache.Get(id)
|
||||
func (s *DefaultUserStore) DirtyGet(id int) *User {
|
||||
user, err := s.Get(id)
|
||||
if err == nil {
|
||||
return user
|
||||
}
|
||||
/*if mus.OutOfBounds(id) {
|
||||
/*if s.OutOfBounds(id) {
|
||||
return BlankUser()
|
||||
}*/
|
||||
|
||||
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.RawAvatar, &user.Message, &user.URLPrefix, &user.URLName, &user.Level, &user.Score, &user.Liked, &user.LastIP, &user.TempGroup)
|
||||
|
||||
user.Init()
|
||||
if err == nil {
|
||||
mus.cache.Set(user)
|
||||
return user
|
||||
}
|
||||
return BlankUser()
|
||||
}
|
||||
|
||||
// TODO: Log weird cache errors? Not just here but in every *Cache?
|
||||
func (mus *DefaultUserStore) Get(id int) (*User, error) {
|
||||
user, err := mus.cache.Get(id)
|
||||
func (s *DefaultUserStore) Get(id int) (*User, error) {
|
||||
u, err := s.cache.Get(id)
|
||||
if err == nil {
|
||||
//log.Print("cached user")
|
||||
//log.Print(string(debug.Stack()))
|
||||
//log.Println("")
|
||||
return user, nil
|
||||
return u, nil
|
||||
}
|
||||
//log.Print("uncached user")
|
||||
|
||||
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.RawAvatar, &user.Message, &user.URLPrefix, &user.URLName, &user.Level, &user.Score, &user.Liked, &user.LastIP, &user.TempGroup)
|
||||
|
||||
user.Init()
|
||||
u = &User{ID: id, Loggedin: true}
|
||||
err = s.get.QueryRow(id).Scan(&u.Name, &u.Group, &u.Active, &u.IsSuperAdmin, &u.Session, &u.Email, &u.RawAvatar, &u.Message, &u.URLPrefix, &u.URLName, &u.Level, &u.Score,&u.Liked, &u.LastIP, &u.TempGroup)
|
||||
if err == nil {
|
||||
mus.cache.Set(user)
|
||||
u.Init()
|
||||
s.cache.Set(u)
|
||||
}
|
||||
return user, err
|
||||
return u, err
|
||||
}
|
||||
|
||||
// TODO: Log weird cache errors? Not just here but in every *Cache?
|
||||
// ! This bypasses the cache, use frugally
|
||||
func (mus *DefaultUserStore) GetByName(name string) (*User, error) {
|
||||
user := &User{Loggedin: true}
|
||||
err := mus.getByName.QueryRow(name).Scan(&user.ID, &user.Name, &user.Group, &user.Active, &user.IsSuperAdmin, &user.Session, &user.Email, &user.RawAvatar, &user.Message, &user.URLPrefix, &user.URLName, &user.Level, &user.Score, &user.Liked, &user.LastIP, &user.TempGroup)
|
||||
|
||||
user.Init()
|
||||
func (s *DefaultUserStore) GetByName(name string) (*User, error) {
|
||||
u := &User{Loggedin: true}
|
||||
err := s.getByName.QueryRow(name).Scan(&u.ID, &u.Name, &u.Group, &u.Active, &u.IsSuperAdmin, &u.Session, &u.Email, &u.RawAvatar, &u.Message, &u.URLPrefix, &u.URLName, &u.Level, &u.Score, &u.Liked, &u.LastIP, &u.TempGroup)
|
||||
if err == nil {
|
||||
mus.cache.Set(user)
|
||||
u.Init()
|
||||
s.cache.Set(u)
|
||||
}
|
||||
return user, err
|
||||
return u, err
|
||||
}
|
||||
|
||||
// TODO: Optimise this, so we don't wind up hitting the database every-time for small gaps
|
||||
// TODO: Make this a little more consistent with DefaultGroupStore's GetRange method
|
||||
func (store *DefaultUserStore) GetOffset(offset int, perPage int) (users []*User, err error) {
|
||||
rows, err := store.getOffset.Query(offset, perPage)
|
||||
func (s *DefaultUserStore) GetOffset(offset int, perPage int) (users []*User, err error) {
|
||||
rows, err := s.getOffset.Query(offset, perPage)
|
||||
if err != nil {
|
||||
return users, err
|
||||
}
|
||||
defer rows.Close()
|
||||
|
||||
for rows.Next() {
|
||||
user := &User{Loggedin: true}
|
||||
err := rows.Scan(&user.ID, &user.Name, &user.Group, &user.Active, &user.IsSuperAdmin, &user.Session, &user.Email, &user.RawAvatar, &user.Message, &user.URLPrefix, &user.URLName, &user.Level, &user.Score, &user.Liked, &user.LastIP, &user.TempGroup)
|
||||
u := &User{Loggedin: true}
|
||||
err := rows.Scan(&u.ID, &u.Name, &u.Group, &u.Active, &u.IsSuperAdmin, &u.Session, &u.Email, &u.RawAvatar, &u.Message, &u.URLPrefix, &u.URLName, &u.Level, &u.Score, &u.Liked, &u.LastIP, &u.TempGroup)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
user.Init()
|
||||
store.cache.Set(user)
|
||||
users = append(users, user)
|
||||
u.Init()
|
||||
s.cache.Set(u)
|
||||
users = append(users, u)
|
||||
}
|
||||
return users, rows.Err()
|
||||
}
|
||||
|
@ -142,7 +131,7 @@ func (store *DefaultUserStore) GetOffset(offset int, perPage int) (users []*User
|
|||
// TODO: Optimise the query to avoid preparing it on the spot? Maybe, use knowledge of the most common IN() parameter counts?
|
||||
// TODO: ID of 0 should always error?
|
||||
func (s *DefaultUserStore) BulkGetMap(ids []int) (list map[int]*User, err error) {
|
||||
var idCount = len(ids)
|
||||
idCount := len(ids)
|
||||
list = make(map[int]*User)
|
||||
if idCount == 0 {
|
||||
return list, nil
|
||||
|
@ -173,16 +162,16 @@ func (s *DefaultUserStore) BulkGetMap(ids []int) (list map[int]*User, err error)
|
|||
return list, nil
|
||||
}
|
||||
|
||||
// TODO: Add a function for the qlist stuff
|
||||
var qlist string
|
||||
// TODO: Add a function for the q stuff
|
||||
var q string
|
||||
idList := make([]interface{},len(ids))
|
||||
for i, id := range ids {
|
||||
idList[i] = strconv.Itoa(id)
|
||||
qlist += "?,"
|
||||
q += "?,"
|
||||
}
|
||||
qlist = qlist[0 : len(qlist)-1]
|
||||
q = q[0 : len(q)-1]
|
||||
|
||||
rows, err := qgen.NewAcc().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(idList...)
|
||||
rows, err := qgen.NewAcc().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(" + q + ")").Query(idList...)
|
||||
if err != nil {
|
||||
return list, err
|
||||
}
|
||||
|
@ -221,29 +210,28 @@ func (s *DefaultUserStore) BulkGetMap(ids []int) (list map[int]*User, err error)
|
|||
return list, err
|
||||
}
|
||||
|
||||
func (mus *DefaultUserStore) BypassGet(id int) (*User, error) {
|
||||
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.RawAvatar, &user.Message, &user.URLPrefix, &user.URLName, &user.Level, &user.Score, &user.Liked, &user.LastIP, &user.TempGroup)
|
||||
|
||||
user.Init()
|
||||
return user, err
|
||||
func (s *DefaultUserStore) BypassGet(id int) (*User, error) {
|
||||
u := &User{ID: id, Loggedin: true}
|
||||
err := s.get.QueryRow(id).Scan(&u.Name, &u.Group, &u.Active, &u.IsSuperAdmin, &u.Session, &u.Email, &u.RawAvatar, &u.Message, &u.URLPrefix, &u.URLName, &u.Level, &u.Score, &u.Liked, &u.LastIP, &u.TempGroup)
|
||||
u.Init()
|
||||
return u, err
|
||||
}
|
||||
|
||||
func (mus *DefaultUserStore) Reload(id int) error {
|
||||
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.RawAvatar, &user.Message, &user.URLPrefix, &user.URLName, &user.Level, &user.Score, &user.Liked, &user.LastIP, &user.TempGroup)
|
||||
func (s *DefaultUserStore) Reload(id int) error {
|
||||
u := &User{ID: id, Loggedin: true}
|
||||
err := s.get.QueryRow(id).Scan(&u.Name, &u.Group, &u.Active, &u.IsSuperAdmin, &u.Session, &u.Email, &u.RawAvatar, &u.Message, &u.URLPrefix, &u.URLName, &u.Level, &u.Score, &u.Liked, &u.LastIP, &u.TempGroup)
|
||||
if err != nil {
|
||||
mus.cache.Remove(id)
|
||||
s.cache.Remove(id)
|
||||
return err
|
||||
}
|
||||
user.Init()
|
||||
_ = mus.cache.Set(user)
|
||||
u.Init()
|
||||
_ = s.cache.Set(u)
|
||||
TopicListThaw.Thaw()
|
||||
return nil
|
||||
}
|
||||
|
||||
func (mus *DefaultUserStore) Exists(id int) bool {
|
||||
err := mus.exists.QueryRow(id).Scan(&id)
|
||||
func (s *DefaultUserStore) Exists(id int) bool {
|
||||
err := s.exists.QueryRow(id).Scan(&id)
|
||||
if err != nil && err != ErrNoRows {
|
||||
LogError(err)
|
||||
}
|
||||
|
@ -252,7 +240,7 @@ func (mus *DefaultUserStore) Exists(id int) bool {
|
|||
|
||||
// TODO: Change active to a bool?
|
||||
// TODO: Use unique keys for the usernames
|
||||
func (mus *DefaultUserStore) Create(username string, password string, email string, group int, active bool) (int, error) {
|
||||
func (s *DefaultUserStore) Create(username string, password string, email string, group int, active bool) (int, error) {
|
||||
// TODO: Strip spaces?
|
||||
|
||||
// ? This number might be a little screwy with Unicode, but it's the only consistent thing we have, as Unicode characters can be any number of bytes in theory?
|
||||
|
@ -261,7 +249,7 @@ func (mus *DefaultUserStore) Create(username string, password string, email stri
|
|||
}
|
||||
|
||||
// Is this username already taken..?
|
||||
err := mus.usernameExists.QueryRow(username).Scan(&username)
|
||||
err := s.usernameExists.QueryRow(username).Scan(&username)
|
||||
if err != ErrNoRows {
|
||||
return 0, ErrAccountExists
|
||||
}
|
||||
|
@ -274,7 +262,7 @@ func (mus *DefaultUserStore) Create(username string, password string, email stri
|
|||
return 0, err
|
||||
}
|
||||
|
||||
res, err := mus.register.Exec(username, email, string(hashedPassword), salt, group, active)
|
||||
res, err := s.register.Exec(username, email, string(hashedPassword), salt, group, active)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
|
|
@ -16,24 +16,24 @@ func NewDefaultWidgetStore() *DefaultWidgetStore {
|
|||
return &DefaultWidgetStore{widgets: make(map[int]*Widget)}
|
||||
}
|
||||
|
||||
func (widgets *DefaultWidgetStore) Get(id int) (*Widget, error) {
|
||||
widgets.RLock()
|
||||
defer widgets.RUnlock()
|
||||
widget, ok := widgets.widgets[id]
|
||||
func (w *DefaultWidgetStore) Get(id int) (*Widget, error) {
|
||||
w.RLock()
|
||||
defer w.RUnlock()
|
||||
widget, ok := w.widgets[id]
|
||||
if !ok {
|
||||
return widget, sql.ErrNoRows
|
||||
}
|
||||
return widget, nil
|
||||
}
|
||||
|
||||
func (widgets *DefaultWidgetStore) set(widget *Widget) {
|
||||
widgets.Lock()
|
||||
defer widgets.Unlock()
|
||||
widgets.widgets[widget.ID] = widget
|
||||
func (w *DefaultWidgetStore) set(widget *Widget) {
|
||||
w.Lock()
|
||||
defer w.Unlock()
|
||||
w.widgets[widget.ID] = widget
|
||||
}
|
||||
|
||||
func (widgets *DefaultWidgetStore) delete(id int) {
|
||||
widgets.Lock()
|
||||
defer widgets.Unlock()
|
||||
delete(widgets.widgets, id)
|
||||
func (w *DefaultWidgetStore) delete(id int) {
|
||||
w.Lock()
|
||||
defer w.Unlock()
|
||||
delete(w.widgets, id)
|
||||
}
|
||||
|
|
|
@ -538,6 +538,7 @@
|
|||
|
||||
"convos_head":"Conversations",
|
||||
"convo_head":"Conversation",
|
||||
"convo_users":"Participants",
|
||||
"create_convo_head":"Create Conversation",
|
||||
"create_convo_button":"Create Convo",
|
||||
|
||||
|
|
|
@ -100,12 +100,12 @@ func (b *accUpdateBuilder) Prepare() *sql.Stmt {
|
|||
return b.build.prepare(b.build.adapter.SimpleUpdate(b.up))
|
||||
}
|
||||
|
||||
func (u *accUpdateBuilder) Exec(args ...interface{}) (res sql.Result, err error) {
|
||||
query, err := u.build.adapter.SimpleUpdate(u.up)
|
||||
func (b *accUpdateBuilder) Exec(args ...interface{}) (res sql.Result, err error) {
|
||||
query, err := b.build.adapter.SimpleUpdate(b.up)
|
||||
if err != nil {
|
||||
return res, err
|
||||
}
|
||||
return u.build.exec(query, args...)
|
||||
return b.build.exec(query, args...)
|
||||
}
|
||||
|
||||
type AccSelectBuilder struct {
|
||||
|
@ -145,7 +145,8 @@ func (b *AccSelectBuilder) In(column string, inList []int) *AccSelectBuilder {
|
|||
return b
|
||||
}
|
||||
|
||||
var where = column + " IN("
|
||||
// TODO: Optimise this
|
||||
where := column + " IN("
|
||||
for _, item := range inList {
|
||||
where += strconv.Itoa(item) + ","
|
||||
}
|
||||
|
@ -158,6 +159,29 @@ func (b *AccSelectBuilder) In(column string, inList []int) *AccSelectBuilder {
|
|||
return b
|
||||
}
|
||||
|
||||
// TODO: Don't implement the SQL at the accumulator level but the adapter level
|
||||
func (b *AccSelectBuilder) InPQuery(column string, inList []int) (*sql.Rows, error) {
|
||||
if len(inList) == 0 {
|
||||
return nil, sql.ErrNoRows
|
||||
}
|
||||
// TODO: Optimise this
|
||||
where := column + " IN("
|
||||
|
||||
idList := make([]interface{},len(inList))
|
||||
for i, id := range inList {
|
||||
idList[i] = strconv.Itoa(id)
|
||||
where += "?,"
|
||||
}
|
||||
where = where[0 : len(where)-1] + ")"
|
||||
|
||||
if b.where != "" {
|
||||
where += " AND " + b.where
|
||||
}
|
||||
|
||||
b.where = where
|
||||
return b.Query(idList...)
|
||||
}
|
||||
|
||||
func (b *AccSelectBuilder) InQ(column string, subBuilder *AccSelectBuilder) *AccSelectBuilder {
|
||||
b.inChain = subBuilder
|
||||
b.inColumn = column
|
||||
|
|
|
@ -2,10 +2,11 @@ package routes
|
|||
|
||||
import (
|
||||
"database/sql"
|
||||
"errors"
|
||||
"net/http"
|
||||
"strconv"
|
||||
"strings"
|
||||
"errors"
|
||||
//"log"
|
||||
|
||||
c "github.com/Azareal/Gosora/common"
|
||||
p "github.com/Azareal/Gosora/common/phrases"
|
||||
|
@ -13,13 +14,15 @@ import (
|
|||
|
||||
func Convos(w http.ResponseWriter, r *http.Request, user c.User, header *c.Header) c.RouteError {
|
||||
accountEditHead("convos", w, r, &user, header)
|
||||
header.AddSheet(header.Theme.Name + "/convo.css")
|
||||
header.AddNotice("convo_dev")
|
||||
ccount := c.Convos.GetUserCount(user.ID)
|
||||
page, _ := strconv.Atoi(r.FormValue("page"))
|
||||
offset, page, lastPage := c.PageOffset(ccount, page, c.Config.ItemsPerPage)
|
||||
pageList := c.Paginate(page, lastPage, 5)
|
||||
|
||||
convos, err := c.Convos.GetUser(user.ID, offset)
|
||||
convos, err := c.Convos.GetUserExtra(user.ID, offset)
|
||||
//log.Printf("convos: %+v\n", convos)
|
||||
if err == sql.ErrNoRows {
|
||||
return c.NotFound(w, r, header)
|
||||
} else if err != nil {
|
||||
|
@ -74,7 +77,7 @@ func Convo(w http.ResponseWriter, r *http.Request, user c.User, header *c.Header
|
|||
} else if err != nil {
|
||||
return c.InternalError(err, w, r)
|
||||
}
|
||||
users := make([]*c.User,len(umap))
|
||||
users := make([]*c.User, len(umap))
|
||||
i := 0
|
||||
for _, user := range umap {
|
||||
users[i] = user
|
||||
|
|
|
@ -5,11 +5,11 @@
|
|||
</div>
|
||||
<div class="colstack_item parti">
|
||||
<div class="rowitem">
|
||||
<div>Participants: </div>
|
||||
<div>{{lang "convo_users"}}: </div>
|
||||
{{range .Users}}<div class="parti_user"><a href="{{.Link}}">{{.Name}}</a></div> {{end}}
|
||||
</div>
|
||||
</div>
|
||||
<div class="colstack_item">{{template "convo_row.html" .}}</div>
|
||||
<div class="colstack_item convo_row_box">{{template "convo_row.html" .}}</div>
|
||||
{{if not .CurrentUser.IsBanned}}
|
||||
<form action="/user/convo/create/submit/{{.Convo.ID}}?s={{.CurrentUser.Session}}" method="post">
|
||||
<div class="colstack_item topic_reply_form" style="border-top:none;">
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
{{range .Convos}}
|
||||
<div class="rowitem">
|
||||
<span class="to_left">
|
||||
<a href="/user/convo/{{.ID}}">Message</a>
|
||||
<a href="/user/convo/{{.ID}}">{{range .Users}}<span class="convos_item_user">{{.Name}}</span> {{end}}</a></span></a>
|
||||
</span>
|
||||
<span title="{{abstime .LastReplyAt}}" class="to_right">{{reltime .LastReplyAt}}</span>
|
||||
</div>{{end}}
|
||||
|
|
|
@ -1,3 +1,7 @@
|
|||
.convos_item_user:not(:last-child):after {
|
||||
content: ",";
|
||||
}
|
||||
|
||||
.parti {
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue