gosora/common/conversations.go

234 lines
7.3 KiB
Go

package common
import (
"time"
"errors"
//"strconv"
"database/sql"
qgen "github.com/Azareal/Gosora/query_gen"
)
/*
conversations
conversations_posts
*/
var Convos ConversationStore
var convoStmts ConvoStmts
type ConvoStmts struct {
getPosts *sql.Stmt
countPosts *sql.Stmt
edit *sql.Stmt
create *sql.Stmt
delete *sql.Stmt
editPost *sql.Stmt
createPost *sql.Stmt
}
/*func init() {
DbInits.Add(func(acc *qgen.Accumulator) error {
convoStmts = ConvoStmts{
getPosts: acc.Select("conversations_posts").Columns("pid, body, post, createdBy").Where("cid = ?").Limit("?,?").Prepare(),
countPosts: acc.Count("conversations_posts").Where("cid = ?").Prepare(),
//edit: acc.Update("conversations").Set("participants = ?, lastReplyBy = ?, lastReplyAt = ?").Where("cid = ?").Prepare(),
edit: acc.Update("conversations").Set("lastReplyBy = ?, lastReplyAt = ?").Where("cid = ?").Prepare(),
//create: acc.Insert("conversations").Columns("participants, createdAt, lastReplyAt").Fields("?,UTC_TIMESTAMP(),UTC_TIMESTAMP()").Prepare(),
create: acc.Insert("conversations").Columns("createdAt, lastReplyAt").Fields("UTC_TIMESTAMP(),UTC_TIMESTAMP()").Prepare(),
editPost: acc.Update("conversations_posts").Set("body = ?, post = ?").Where("cid = ?").Prepare(),
createPost: acc.Insert("conversations_posts").Columns("cid, body, post, createdBy").Fields("?,?,?,?").Prepare(),
}
return acc.FirstError()
})
}*/
type Conversation struct {
ID int
//Participants string
CreatedBy int
CreatedAt time.Time
LastReplyBy int
LastReplyAt time.Time
}
func (co *Conversation) Posts(offset int) (posts []*ConversationPost, err error) {
rows, err := convoStmts.getPosts.Query(co.ID, offset, Config.ItemsPerPage)
if err != nil {
return nil, err
}
defer rows.Close()
for rows.Next() {
convo := &ConversationPost{CID: co.ID}
err := rows.Scan(&convo.ID, &convo.Body, &convo.Post, &convo.CreatedBy)
if err != nil {
return nil, err
}
convo, err = ConvoPostProcess.OnLoad(convo)
if err != nil {
return nil, err
}
posts = append(posts, convo)
}
return posts, rows.Err()
}
func (co *Conversation) PostsCount() (count int) {
err := convoStmts.countPosts.QueryRow(co.ID).Scan(&count)
if err != nil {
LogError(err)
}
return count
}
func (co *Conversation) Update() error {
_, err := convoStmts.edit.Exec(/*co.Participants, */co.CreatedAt, co.LastReplyBy, co.LastReplyAt, co.ID)
return err
}
func (co *Conversation) Create() (int, error) {
res, err := convoStmts.create.Exec(/*co.Participants*/)
if err != nil {
return 0, err
}
lastID, err := res.LastInsertId()
return int(lastID), err
}
type ConversationStore interface {
Get(id int) (*Conversation, error)
GetUser(uid int, offset int) (cos []*Conversation, err error)
GetUserCount(uid int) (count int)
Delete(id int) error
Count() (count int)
Create(content string, createdBy int, participants []int) (int, error)
}
type DefaultConversationStore struct {
get *sql.Stmt
getUser *sql.Stmt
getUserCount *sql.Stmt
delete *sql.Stmt
deletePosts *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("participants, createdBy, createdAt, lastReplyBy, lastReplyAt").Where("cid = ?").Prepare(),
get: acc.Select("conversations").Columns("createdBy, createdAt, lastReplyBy, lastReplyAt").Where("cid = ?").Prepare(),
//("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.attachCount, replies.actionType", "replies.createdBy = users.uid", "replies.tid = ?", "replies.rid ASC", "?,?")
//(name string, table1 string, table2 string, columns string, joiners string, where string, orderby string, limit string)
//getUser: acc.SimpleLeftJoin("conversations_participants AS cp","conversations AS c","c.cid, c.participants, 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.SimpleLeftJoin("conversations_participants AS cp","conversations AS c","c.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(),
//create: acc.Insert("conversations").Columns("participants, 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(),
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.Participants, */&convo.CreatedBy, &convo.CreatedAt, &convo.LastReplyBy, &convo.LastReplyAt)
return convo, err
}
func (s *DefaultConversationStore) GetUser(uid int, offset int) (cos []*Conversation, err error) {
rows, err := s.getUser.Query(uid, offset, Config.ItemsPerPage)
if err != nil {
return nil, err
}
defer rows.Close()
for rows.Next() {
co := &Conversation{}
err := rows.Scan(&co.ID, /*&co.Participants,*/ &co.CreatedBy, &co.CreatedAt, &co.LastReplyBy, &co.LastReplyAt)
if err != nil {
return nil, err
}
cos = append(cos, co)
}
return cos, rows.Err()
}
func (s *DefaultConversationStore) GetUserCount(uid int) (count int) {
err := s.getUserCount.QueryRow(uid).Scan(&count)
if err != nil {
LogError(err)
}
return count
}
// TODO: Use a foreign key or transaction
func (s *DefaultConversationStore) Delete(id int) error {
_, err := s.delete.Exec(id)
if err != nil {
return err
}
_, err = s.deletePosts.Exec(id)
return err
}
func (s *DefaultConversationStore) Create(content string, createdBy int, participants []int) (int, error) {
if len(participants) == 0 {
return 0, errors.New("no participants set")
}
/*var pstr string
for _, parti := range participants {
pstr += strconv.Itoa(parti) + ","
}
pstr = pstr[:len(pstr)-1]*/
res, err := s.create.Exec(createdBy/*, pstr*/)
if err != nil {
return 0, err
}
lastID, err := res.LastInsertId()
if err != nil {
return 0, err
}
post := &ConversationPost{}
post.CID = int(lastID)
post.Body = content
post.CreatedBy = createdBy
_, err = post.Create()
if err != nil {
return 0, err
}
for _, p := range participants {
_, err := s.addParticipant.Exec(p,lastID)
if err != nil {
return 0, err
}
}
_, err = s.addParticipant.Exec(createdBy,lastID)
if err != nil {
return 0, err
}
return int(lastID), err
}
// Count returns the total number of topics on these forums
func (s *DefaultConversationStore) Count() (count int) {
err := s.count.QueryRow().Scan(&count)
if err != nil {
LogError(err)
}
return count
}