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 (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
"time"
|
"time"
|
||||||
|
//"log"
|
||||||
|
|
||||||
//"strconv"
|
"strconv"
|
||||||
"database/sql"
|
"database/sql"
|
||||||
|
|
||||||
qgen "github.com/Azareal/Gosora/query_gen"
|
qgen "github.com/Azareal/Gosora/query_gen"
|
||||||
|
@ -20,7 +21,7 @@ type ConvoStmts struct {
|
||||||
edit *sql.Stmt
|
edit *sql.Stmt
|
||||||
create *sql.Stmt
|
create *sql.Stmt
|
||||||
delete *sql.Stmt
|
delete *sql.Stmt
|
||||||
has *sql.Stmt
|
has *sql.Stmt
|
||||||
|
|
||||||
editPost *sql.Stmt
|
editPost *sql.Stmt
|
||||||
createPost *sql.Stmt
|
createPost *sql.Stmt
|
||||||
|
@ -37,7 +38,7 @@ func init() {
|
||||||
countPosts: acc.Count("conversations_posts").Where("cid = ?").Prepare(),
|
countPosts: acc.Count("conversations_posts").Where("cid = ?").Prepare(),
|
||||||
edit: acc.Update("conversations").Set("lastReplyBy = ?, lastReplyAt = ?").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(),
|
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(),
|
editPost: acc.Update("conversations_posts").Set("body = ?, post = ?").Where("pid = ?").Prepare(),
|
||||||
createPost: acc.Insert("conversations_posts").Columns("cid, body, post, createdBy").Fields("?,?,?,?").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
|
return int(lastID), err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type ConversationExtra struct {
|
||||||
|
*Conversation
|
||||||
|
Users []*User
|
||||||
|
}
|
||||||
|
|
||||||
type ConversationStore interface {
|
type ConversationStore interface {
|
||||||
Get(id int) (*Conversation, error)
|
Get(id int) (*Conversation, error)
|
||||||
GetUser(uid int, offset int) (cos []*Conversation, err error)
|
GetUser(uid int, offset int) (cos []*Conversation, err error)
|
||||||
|
GetUserExtra(uid int, offset int) (cos []*ConversationExtra, err error)
|
||||||
GetUserCount(uid int) (count int)
|
GetUserCount(uid int) (count int)
|
||||||
Delete(id int) error
|
Delete(id int) error
|
||||||
Count() (count int)
|
Count() (count int)
|
||||||
|
@ -140,35 +147,35 @@ type ConversationStore interface {
|
||||||
}
|
}
|
||||||
|
|
||||||
type DefaultConversationStore struct {
|
type DefaultConversationStore struct {
|
||||||
get *sql.Stmt
|
get *sql.Stmt
|
||||||
getUser *sql.Stmt
|
getUser *sql.Stmt
|
||||||
getUserCount *sql.Stmt
|
getUserCount *sql.Stmt
|
||||||
delete *sql.Stmt
|
delete *sql.Stmt
|
||||||
deletePosts *sql.Stmt
|
deletePosts *sql.Stmt
|
||||||
deleteParticipants *sql.Stmt
|
deleteParticipants *sql.Stmt
|
||||||
create *sql.Stmt
|
create *sql.Stmt
|
||||||
addParticipant *sql.Stmt
|
addParticipant *sql.Stmt
|
||||||
count *sql.Stmt
|
count *sql.Stmt
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewDefaultConversationStore(acc *qgen.Accumulator) (*DefaultConversationStore, error) {
|
func NewDefaultConversationStore(acc *qgen.Accumulator) (*DefaultConversationStore, error) {
|
||||||
return &DefaultConversationStore{
|
return &DefaultConversationStore{
|
||||||
get: acc.Select("conversations").Columns("createdBy, createdAt, lastReplyBy, lastReplyAt").Where("cid = ?").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", "?,?"),
|
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(),
|
getUserCount: acc.Count("conversations_participants").Where("uid = ?").Prepare(),
|
||||||
delete: acc.Delete("conversations").Where("cid = ?").Prepare(),
|
delete: acc.Delete("conversations").Where("cid = ?").Prepare(),
|
||||||
deletePosts: acc.Delete("conversations_posts").Where("cid = ?").Prepare(),
|
deletePosts: acc.Delete("conversations_posts").Where("cid = ?").Prepare(),
|
||||||
deleteParticipants: acc.Delete("conversations_participants").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(),
|
create: acc.Insert("conversations").Columns("createdBy, createdAt, lastReplyAt").Fields("?,UTC_TIMESTAMP(),UTC_TIMESTAMP()").Prepare(),
|
||||||
addParticipant: acc.Insert("conversations_participants").Columns("uid, cid").Fields("?,?").Prepare(),
|
addParticipant: acc.Insert("conversations_participants").Columns("uid, cid").Fields("?,?").Prepare(),
|
||||||
count: acc.Count("conversations").Prepare(),
|
count: acc.Count("conversations").Prepare(),
|
||||||
}, acc.FirstError()
|
}, acc.FirstError()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *DefaultConversationStore) Get(id int) (*Conversation, error) {
|
func (s *DefaultConversationStore) Get(id int) (*Conversation, error) {
|
||||||
convo := &Conversation{ID: id}
|
co := &Conversation{ID: id}
|
||||||
err := s.get.QueryRow(id).Scan(&convo.CreatedBy, &convo.CreatedAt, &convo.LastReplyBy, &convo.LastReplyAt)
|
err := s.get.QueryRow(id).Scan(&co.CreatedBy, &co.CreatedAt, &co.LastReplyBy, &co.LastReplyAt)
|
||||||
return convo, err
|
return co, err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *DefaultConversationStore) GetUser(uid int, offset int) (cos []*Conversation, err error) {
|
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()
|
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) {
|
func (s *DefaultConversationStore) GetUserCount(uid int) (count int) {
|
||||||
err := s.getUserCount.QueryRow(uid).Scan(&count)
|
err := s.getUserCount.QueryRow(uid).Scan(&count)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -225,10 +335,7 @@ func (s *DefaultConversationStore) Create(content string, createdBy int, partici
|
||||||
return 0, err
|
return 0, err
|
||||||
}
|
}
|
||||||
|
|
||||||
post := &ConversationPost{}
|
post := &ConversationPost{CID: int(lastID), Body: content, CreatedBy: createdBy}
|
||||||
post.CID = int(lastID)
|
|
||||||
post.Body = content
|
|
||||||
post.CreatedBy = createdBy
|
|
||||||
_, err = post.Create()
|
_, err = post.Create()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, err
|
return 0, err
|
||||||
|
|
|
@ -81,7 +81,7 @@ func (s *MemoryForumPermsStore) Reload(fid int) error {
|
||||||
}
|
}
|
||||||
defer rows.Close()
|
defer rows.Close()
|
||||||
|
|
||||||
var forumPerms = make(map[int]*ForumPerms)
|
forumPerms := make(map[int]*ForumPerms)
|
||||||
for rows.Next() {
|
for rows.Next() {
|
||||||
var gid int
|
var gid int
|
||||||
var perms []byte
|
var perms []byte
|
||||||
|
|
|
@ -265,7 +265,7 @@ type ResetPage struct {
|
||||||
|
|
||||||
type ConvoListPage struct {
|
type ConvoListPage struct {
|
||||||
*Header
|
*Header
|
||||||
Convos []*Conversation
|
Convos []*ConversationExtra
|
||||||
Paginator
|
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
|
// TODO: Add a function for the qlist stuff
|
||||||
var qlist string
|
var q string
|
||||||
idList := make([]interface{},len(ids))
|
idList := make([]interface{},len(ids))
|
||||||
for i, id := range ids {
|
for i, id := range ids {
|
||||||
idList[i] = strconv.Itoa(id)
|
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 {
|
if err != nil {
|
||||||
return list, err
|
return list, err
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,7 +16,6 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
// TODO: Add the watchdog goroutine
|
// TODO: Add the watchdog goroutine
|
||||||
// TODO: Add BulkGetMap
|
|
||||||
// TODO: Add some sort of update method
|
// 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
|
// ? - Should we add stick, lock, unstick, and unlock methods? These might be better on the Topics not the TopicStore
|
||||||
var Topics 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
|
// TODO: Avoid duplicating much of this logic from user_store.go
|
||||||
func (s *DefaultTopicStore) BulkGetMap(ids []int) (list map[int]*Topic, err error) {
|
func (s *DefaultTopicStore) BulkGetMap(ids []int) (list map[int]*Topic, err error) {
|
||||||
var idCount = len(ids)
|
idCount := len(ids)
|
||||||
list = make(map[int]*Topic)
|
list = make(map[int]*Topic)
|
||||||
if idCount == 0 {
|
if idCount == 0 {
|
||||||
return list, nil
|
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
|
// TODO: Add a function for the qlist stuff
|
||||||
var qlist string
|
var q string
|
||||||
idList := make([]interface{},len(ids))
|
idList := make([]interface{},len(ids))
|
||||||
for i, id := range ids {
|
for i, id := range ids {
|
||||||
idList[i] = strconv.Itoa(id)
|
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 {
|
if err != nil {
|
||||||
return list, err
|
return list, err
|
||||||
}
|
}
|
||||||
|
|
|
@ -63,78 +63,67 @@ func NewDefaultUserStore(cache UserCache) (*DefaultUserStore, error) {
|
||||||
}, acc.FirstError()
|
}, acc.FirstError()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (mus *DefaultUserStore) DirtyGet(id int) *User {
|
func (s *DefaultUserStore) DirtyGet(id int) *User {
|
||||||
user, err := mus.cache.Get(id)
|
user, err := s.Get(id)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
return user
|
return user
|
||||||
}
|
}
|
||||||
/*if mus.OutOfBounds(id) {
|
/*if s.OutOfBounds(id) {
|
||||||
return BlankUser()
|
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()
|
return BlankUser()
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Log weird cache errors? Not just here but in every *Cache?
|
// TODO: Log weird cache errors? Not just here but in every *Cache?
|
||||||
func (mus *DefaultUserStore) Get(id int) (*User, error) {
|
func (s *DefaultUserStore) Get(id int) (*User, error) {
|
||||||
user, err := mus.cache.Get(id)
|
u, err := s.cache.Get(id)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
//log.Print("cached user")
|
//log.Print("cached user")
|
||||||
//log.Print(string(debug.Stack()))
|
//log.Print(string(debug.Stack()))
|
||||||
//log.Println("")
|
//log.Println("")
|
||||||
return user, nil
|
return u, nil
|
||||||
}
|
}
|
||||||
//log.Print("uncached user")
|
//log.Print("uncached user")
|
||||||
|
|
||||||
user = &User{ID: id, Loggedin: true}
|
u = &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)
|
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)
|
||||||
|
|
||||||
user.Init()
|
|
||||||
if err == nil {
|
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?
|
// TODO: Log weird cache errors? Not just here but in every *Cache?
|
||||||
// ! This bypasses the cache, use frugally
|
// ! This bypasses the cache, use frugally
|
||||||
func (mus *DefaultUserStore) GetByName(name string) (*User, error) {
|
func (s *DefaultUserStore) GetByName(name string) (*User, error) {
|
||||||
user := &User{Loggedin: true}
|
u := &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)
|
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)
|
||||||
|
|
||||||
user.Init()
|
|
||||||
if err == nil {
|
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: 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
|
// TODO: Make this a little more consistent with DefaultGroupStore's GetRange method
|
||||||
func (store *DefaultUserStore) GetOffset(offset int, perPage int) (users []*User, err error) {
|
func (s *DefaultUserStore) GetOffset(offset int, perPage int) (users []*User, err error) {
|
||||||
rows, err := store.getOffset.Query(offset, perPage)
|
rows, err := s.getOffset.Query(offset, perPage)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return users, err
|
return users, err
|
||||||
}
|
}
|
||||||
defer rows.Close()
|
defer rows.Close()
|
||||||
|
|
||||||
for rows.Next() {
|
for rows.Next() {
|
||||||
user := &User{Loggedin: true}
|
u := &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)
|
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 {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
user.Init()
|
u.Init()
|
||||||
store.cache.Set(user)
|
s.cache.Set(u)
|
||||||
users = append(users, user)
|
users = append(users, u)
|
||||||
}
|
}
|
||||||
return users, rows.Err()
|
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: 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?
|
// TODO: ID of 0 should always error?
|
||||||
func (s *DefaultUserStore) BulkGetMap(ids []int) (list map[int]*User, err 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)
|
list = make(map[int]*User)
|
||||||
if idCount == 0 {
|
if idCount == 0 {
|
||||||
return list, nil
|
return list, nil
|
||||||
|
@ -173,16 +162,16 @@ func (s *DefaultUserStore) BulkGetMap(ids []int) (list map[int]*User, err error)
|
||||||
return list, nil
|
return list, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Add a function for the qlist stuff
|
// TODO: Add a function for the q stuff
|
||||||
var qlist string
|
var q string
|
||||||
idList := make([]interface{},len(ids))
|
idList := make([]interface{},len(ids))
|
||||||
for i, id := range ids {
|
for i, id := range ids {
|
||||||
idList[i] = strconv.Itoa(id)
|
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 {
|
if err != nil {
|
||||||
return list, err
|
return list, err
|
||||||
}
|
}
|
||||||
|
@ -221,29 +210,28 @@ func (s *DefaultUserStore) BulkGetMap(ids []int) (list map[int]*User, err error)
|
||||||
return list, err
|
return list, err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (mus *DefaultUserStore) BypassGet(id int) (*User, error) {
|
func (s *DefaultUserStore) BypassGet(id int) (*User, error) {
|
||||||
user := &User{ID: id, Loggedin: true}
|
u := &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)
|
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()
|
||||||
user.Init()
|
return u, err
|
||||||
return user, err
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (mus *DefaultUserStore) Reload(id int) error {
|
func (s *DefaultUserStore) Reload(id int) error {
|
||||||
user := &User{ID: id, Loggedin: true}
|
u := &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)
|
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 {
|
if err != nil {
|
||||||
mus.cache.Remove(id)
|
s.cache.Remove(id)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
user.Init()
|
u.Init()
|
||||||
_ = mus.cache.Set(user)
|
_ = s.cache.Set(u)
|
||||||
TopicListThaw.Thaw()
|
TopicListThaw.Thaw()
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (mus *DefaultUserStore) Exists(id int) bool {
|
func (s *DefaultUserStore) Exists(id int) bool {
|
||||||
err := mus.exists.QueryRow(id).Scan(&id)
|
err := s.exists.QueryRow(id).Scan(&id)
|
||||||
if err != nil && err != ErrNoRows {
|
if err != nil && err != ErrNoRows {
|
||||||
LogError(err)
|
LogError(err)
|
||||||
}
|
}
|
||||||
|
@ -252,7 +240,7 @@ func (mus *DefaultUserStore) Exists(id int) bool {
|
||||||
|
|
||||||
// TODO: Change active to a bool?
|
// TODO: Change active to a bool?
|
||||||
// TODO: Use unique keys for the usernames
|
// 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?
|
// 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?
|
// ? 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..?
|
// Is this username already taken..?
|
||||||
err := mus.usernameExists.QueryRow(username).Scan(&username)
|
err := s.usernameExists.QueryRow(username).Scan(&username)
|
||||||
if err != ErrNoRows {
|
if err != ErrNoRows {
|
||||||
return 0, ErrAccountExists
|
return 0, ErrAccountExists
|
||||||
}
|
}
|
||||||
|
@ -274,7 +262,7 @@ func (mus *DefaultUserStore) Create(username string, password string, email stri
|
||||||
return 0, err
|
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 {
|
if err != nil {
|
||||||
return 0, err
|
return 0, err
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,24 +16,24 @@ func NewDefaultWidgetStore() *DefaultWidgetStore {
|
||||||
return &DefaultWidgetStore{widgets: make(map[int]*Widget)}
|
return &DefaultWidgetStore{widgets: make(map[int]*Widget)}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (widgets *DefaultWidgetStore) Get(id int) (*Widget, error) {
|
func (w *DefaultWidgetStore) Get(id int) (*Widget, error) {
|
||||||
widgets.RLock()
|
w.RLock()
|
||||||
defer widgets.RUnlock()
|
defer w.RUnlock()
|
||||||
widget, ok := widgets.widgets[id]
|
widget, ok := w.widgets[id]
|
||||||
if !ok {
|
if !ok {
|
||||||
return widget, sql.ErrNoRows
|
return widget, sql.ErrNoRows
|
||||||
}
|
}
|
||||||
return widget, nil
|
return widget, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (widgets *DefaultWidgetStore) set(widget *Widget) {
|
func (w *DefaultWidgetStore) set(widget *Widget) {
|
||||||
widgets.Lock()
|
w.Lock()
|
||||||
defer widgets.Unlock()
|
defer w.Unlock()
|
||||||
widgets.widgets[widget.ID] = widget
|
w.widgets[widget.ID] = widget
|
||||||
}
|
}
|
||||||
|
|
||||||
func (widgets *DefaultWidgetStore) delete(id int) {
|
func (w *DefaultWidgetStore) delete(id int) {
|
||||||
widgets.Lock()
|
w.Lock()
|
||||||
defer widgets.Unlock()
|
defer w.Unlock()
|
||||||
delete(widgets.widgets, id)
|
delete(w.widgets, id)
|
||||||
}
|
}
|
||||||
|
|
|
@ -538,6 +538,7 @@
|
||||||
|
|
||||||
"convos_head":"Conversations",
|
"convos_head":"Conversations",
|
||||||
"convo_head":"Conversation",
|
"convo_head":"Conversation",
|
||||||
|
"convo_users":"Participants",
|
||||||
"create_convo_head":"Create Conversation",
|
"create_convo_head":"Create Conversation",
|
||||||
"create_convo_button":"Create Convo",
|
"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))
|
return b.build.prepare(b.build.adapter.SimpleUpdate(b.up))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (u *accUpdateBuilder) Exec(args ...interface{}) (res sql.Result, err error) {
|
func (b *accUpdateBuilder) Exec(args ...interface{}) (res sql.Result, err error) {
|
||||||
query, err := u.build.adapter.SimpleUpdate(u.up)
|
query, err := b.build.adapter.SimpleUpdate(b.up)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return res, err
|
return res, err
|
||||||
}
|
}
|
||||||
return u.build.exec(query, args...)
|
return b.build.exec(query, args...)
|
||||||
}
|
}
|
||||||
|
|
||||||
type AccSelectBuilder struct {
|
type AccSelectBuilder struct {
|
||||||
|
@ -145,7 +145,8 @@ func (b *AccSelectBuilder) In(column string, inList []int) *AccSelectBuilder {
|
||||||
return b
|
return b
|
||||||
}
|
}
|
||||||
|
|
||||||
var where = column + " IN("
|
// TODO: Optimise this
|
||||||
|
where := column + " IN("
|
||||||
for _, item := range inList {
|
for _, item := range inList {
|
||||||
where += strconv.Itoa(item) + ","
|
where += strconv.Itoa(item) + ","
|
||||||
}
|
}
|
||||||
|
@ -158,6 +159,29 @@ func (b *AccSelectBuilder) In(column string, inList []int) *AccSelectBuilder {
|
||||||
return b
|
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 {
|
func (b *AccSelectBuilder) InQ(column string, subBuilder *AccSelectBuilder) *AccSelectBuilder {
|
||||||
b.inChain = subBuilder
|
b.inChain = subBuilder
|
||||||
b.inColumn = column
|
b.inColumn = column
|
||||||
|
|
|
@ -2,10 +2,11 @@ package routes
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"database/sql"
|
"database/sql"
|
||||||
|
"errors"
|
||||||
"net/http"
|
"net/http"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
"errors"
|
//"log"
|
||||||
|
|
||||||
c "github.com/Azareal/Gosora/common"
|
c "github.com/Azareal/Gosora/common"
|
||||||
p "github.com/Azareal/Gosora/common/phrases"
|
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 {
|
func Convos(w http.ResponseWriter, r *http.Request, user c.User, header *c.Header) c.RouteError {
|
||||||
accountEditHead("convos", w, r, &user, header)
|
accountEditHead("convos", w, r, &user, header)
|
||||||
|
header.AddSheet(header.Theme.Name + "/convo.css")
|
||||||
header.AddNotice("convo_dev")
|
header.AddNotice("convo_dev")
|
||||||
ccount := c.Convos.GetUserCount(user.ID)
|
ccount := c.Convos.GetUserCount(user.ID)
|
||||||
page, _ := strconv.Atoi(r.FormValue("page"))
|
page, _ := strconv.Atoi(r.FormValue("page"))
|
||||||
offset, page, lastPage := c.PageOffset(ccount, page, c.Config.ItemsPerPage)
|
offset, page, lastPage := c.PageOffset(ccount, page, c.Config.ItemsPerPage)
|
||||||
pageList := c.Paginate(page, lastPage, 5)
|
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 {
|
if err == sql.ErrNoRows {
|
||||||
return c.NotFound(w, r, header)
|
return c.NotFound(w, r, header)
|
||||||
} else if err != nil {
|
} 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 {
|
} else if err != nil {
|
||||||
return c.InternalError(err, w, r)
|
return c.InternalError(err, w, r)
|
||||||
}
|
}
|
||||||
users := make([]*c.User,len(umap))
|
users := make([]*c.User, len(umap))
|
||||||
i := 0
|
i := 0
|
||||||
for _, user := range umap {
|
for _, user := range umap {
|
||||||
users[i] = user
|
users[i] = user
|
||||||
|
|
|
@ -5,11 +5,11 @@
|
||||||
</div>
|
</div>
|
||||||
<div class="colstack_item parti">
|
<div class="colstack_item parti">
|
||||||
<div class="rowitem">
|
<div class="rowitem">
|
||||||
<div>Participants: </div>
|
<div>{{lang "convo_users"}}: </div>
|
||||||
{{range .Users}}<div class="parti_user"><a href="{{.Link}}">{{.Name}}</a></div> {{end}}
|
{{range .Users}}<div class="parti_user"><a href="{{.Link}}">{{.Name}}</a></div> {{end}}
|
||||||
</div>
|
</div>
|
||||||
</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}}
|
{{if not .CurrentUser.IsBanned}}
|
||||||
<form action="/user/convo/create/submit/{{.Convo.ID}}?s={{.CurrentUser.Session}}" method="post">
|
<form action="/user/convo/create/submit/{{.Convo.ID}}?s={{.CurrentUser.Session}}" method="post">
|
||||||
<div class="colstack_item topic_reply_form" style="border-top:none;">
|
<div class="colstack_item topic_reply_form" style="border-top:none;">
|
||||||
|
|
|
@ -8,7 +8,7 @@
|
||||||
{{range .Convos}}
|
{{range .Convos}}
|
||||||
<div class="rowitem">
|
<div class="rowitem">
|
||||||
<span class="to_left">
|
<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>
|
||||||
<span title="{{abstime .LastReplyAt}}" class="to_right">{{reltime .LastReplyAt}}</span>
|
<span title="{{abstime .LastReplyAt}}" class="to_right">{{reltime .LastReplyAt}}</span>
|
||||||
</div>{{end}}
|
</div>{{end}}
|
||||||
|
|
|
@ -1,3 +1,7 @@
|
||||||
|
.convos_item_user:not(:last-child):after {
|
||||||
|
content: ",";
|
||||||
|
}
|
||||||
|
|
||||||
.parti {
|
.parti {
|
||||||
margin-bottom: 8px;
|
margin-bottom: 8px;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue