1450 lines
41 KiB
Go
1450 lines
41 KiB
Go
package localserver
|
|
|
|
import (
|
|
"context"
|
|
"encoding/json"
|
|
"fmt"
|
|
"io/fs"
|
|
"os"
|
|
"path/filepath"
|
|
"strconv"
|
|
"time"
|
|
|
|
"github.com/dgraph-io/badger/v3"
|
|
"github.com/pion/webrtc/v3"
|
|
)
|
|
|
|
const (
|
|
LIST_LATEST_CHATS = "list_latest_chats"
|
|
READ_LATEST_MESSAGE = "read_latest_message"
|
|
LIST_LATEST_FILES = "list_latest_files"
|
|
LIST_CHATS = "list_chats"
|
|
GET_CHATS = "get_chats"
|
|
GET_CHAT = "get_chat"
|
|
CREATE_CHAT = "create_chat"
|
|
DELETE_CHAT = "delete_chat"
|
|
EDIT_CHAT_TYPE = "edit_chat_type"
|
|
EDIT_CHAT_NAME = "edit_chat_name"
|
|
ADD_CHAT_MEMBERS = "add_chat_members"
|
|
REMOVE_CHAT_MEMBER = "remove_chat_member"
|
|
ADD_CHAT_MESSAGE = "add_chat_message"
|
|
ZONE_UPLOAD_CHAT_FILE = "zone_upload_chat_file"
|
|
ZONE_DOWNLOAD_CHAT_FILE = "zone_download_chat_file"
|
|
DELETE_CHAT_FILE = "delete_chat_file"
|
|
DELETE_CHAT_MESSAGE = "delete_chat_message"
|
|
EDIT_CHAT_MESSAGE = "edit_chat_message"
|
|
ZONE_UPLOAD_CHAT_FILE_DONE = "zone_upload_chat_file_done"
|
|
)
|
|
|
|
const (
|
|
CHAT_NAME_EDITED = "chat_name_edited"
|
|
CHAT_TYPE_EDITED = "chat_type_edited"
|
|
CHAT_MESSAGE_LIST = "chat_messages_list"
|
|
CHAT_FILES_LIST = "chat_files_list"
|
|
CHAT_MEMBER_ADDED = "chat_member_added"
|
|
CHAT_MEMBER_REMOVED = "chat_member_removed"
|
|
REMOVED_FROM_CHAT = "removed_from_chat"
|
|
ADDED_IN_CHAT = "added_in_chat"
|
|
GET_CHATS_RESPONSE = "get_chats_response"
|
|
NEW_CHAT_MESSAGE = "new_chat_message"
|
|
CHAT_MESSAGE_DELETED = "chat_message_deleted"
|
|
CHAT_MESSAGE_EDITED = "chat_message_edited"
|
|
CHAT_FILE_DELETED = "chat_file_deleted"
|
|
NEW_CHAT_FILE = "new_chat_file"
|
|
)
|
|
|
|
const (
|
|
GENERAL = "general"
|
|
PUBLIC = "public"
|
|
PRIVATE = "private"
|
|
BROADCAST = "broadcast"
|
|
)
|
|
|
|
type ChatConfig struct {
|
|
ChatId string `json:"chatId"`
|
|
ChatType string `json:"chatType"`
|
|
Owner string `json:"owner"`
|
|
Members []string `json:"members"`
|
|
}
|
|
|
|
type Chat struct {
|
|
ChatId string `json:"chatId"`
|
|
ChatType string `json:"chatType"`
|
|
Owner string `json:"owner"`
|
|
Members []string `json:"members"`
|
|
LastReadIndex uint `json:"lastReadIndex"`
|
|
Unread uint `json:"unread"`
|
|
DB *ZoneChatDBHandler `json:"-"`
|
|
Tracking *ZoneChatTrackingDB `json:"-"`
|
|
}
|
|
|
|
type ZoneChatsHandler struct {
|
|
ZoneId string
|
|
HostId string
|
|
ChatFSInstance *ChatFSInstance
|
|
ZoneMembersId []string
|
|
DataChannels map[string]*DataChannel
|
|
Flag *uint32
|
|
ChatFSInstanceFlag *uint32
|
|
ChatFlag *uint32
|
|
Chats map[string]*Chat
|
|
reqChans []chan<- *ZoneRequest
|
|
init bool
|
|
}
|
|
|
|
func NewZoneChatsHandler(hostId, zoneId, owner string, authorizedMembers []string, dataChannels map[string]*DataChannel, flag *uint32) (zoneChatsHandler *ZoneChatsHandler, err error) {
|
|
var dirs []fs.DirEntry
|
|
dirs, err = os.ReadDir(filepath.Join("data", "zones", zoneId, "chats"))
|
|
if err != nil {
|
|
if os.IsNotExist(err) {
|
|
logger.Printf("creating chat directory for zone %s...\n", zoneId)
|
|
mkdirErr := os.MkdirAll(filepath.Join("data", "zones", zoneId, "chats", "general"), 0700)
|
|
if mkdirErr != nil {
|
|
return nil, mkdirErr
|
|
}
|
|
file, ferr := os.Create(filepath.Join("data", "zones", zoneId, "chats", "general", "chatConfig.json"))
|
|
if ferr != nil {
|
|
return nil, ferr
|
|
}
|
|
baseConfig := ChatConfig{
|
|
ChatId: GENERAL,
|
|
Owner: owner,
|
|
ChatType: "public",
|
|
Members: authorizedMembers,
|
|
}
|
|
bs, jsonErr := json.Marshal(baseConfig)
|
|
if jsonErr != nil {
|
|
return nil, jsonErr
|
|
}
|
|
if _, writeErr := file.WriteString(string(bs)); writeErr != nil {
|
|
return nil, writeErr
|
|
}
|
|
_ = file.Close()
|
|
dirs, err = os.ReadDir(filepath.Join("data", "zones", zoneId, "chats"))
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
} else {
|
|
return
|
|
}
|
|
}
|
|
chats := make(map[string]*Chat)
|
|
for _, chat := range dirs {
|
|
zoneChatDBHandler, err := NewZoneChatDBHandler(zoneId, chat.Name())
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
zoneChatTracking,err := NewZoneChatTracking(zoneId, chat.Name())
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
var bs []byte
|
|
bs, err = os.ReadFile(filepath.Join("data", "zones", zoneId, "chats", chat.Name(), "chatConfig.json"))
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
logger.Println(string(bs))
|
|
var c Chat
|
|
if err = json.Unmarshal(bs, &c); err != nil {
|
|
return nil, err
|
|
}
|
|
if err = zoneChatTracking.Initialize(0,c.Members...); err != nil {
|
|
return nil,err
|
|
}
|
|
logger.Println("chats data :", c.ChatId, c.ChatType, c.Owner, c.Members)
|
|
c.DB = zoneChatDBHandler
|
|
c.Tracking = zoneChatTracking
|
|
chats[c.ChatId] = &c
|
|
}
|
|
chatFlag := uint32(0)
|
|
chatFSFlag := uint32(0)
|
|
zoneChatsHandler = &ZoneChatsHandler{
|
|
HostId: hostId,
|
|
ChatFSInstance: NewChatFSInstance(zoneId, owner, authorizedMembers),
|
|
ChatFSInstanceFlag: &chatFSFlag,
|
|
ZoneId: zoneId,
|
|
ZoneMembersId: authorizedMembers,
|
|
DataChannels: dataChannels,
|
|
Flag: flag,
|
|
Chats: chats,
|
|
ChatFlag: &chatFlag,
|
|
init: false,
|
|
}
|
|
return
|
|
}
|
|
|
|
func (zch *ZoneChatsHandler) sendZoneRequest(reqType string, from string, payload map[string]interface{}) {
|
|
go func() {
|
|
for _, rc := range zch.reqChans {
|
|
rc <- &ZoneRequest{
|
|
ReqType: reqType,
|
|
From: from,
|
|
Payload: payload,
|
|
}
|
|
}
|
|
}()
|
|
}
|
|
|
|
func (zch *ZoneChatsHandler) sendDataChannelMessage(reqType string, from string, to string, payload map[string]interface{}) (<-chan struct{}, <-chan error) {
|
|
done, errCh := make(chan struct{}), make(chan error)
|
|
go func() {
|
|
if err := atomicallyExecute(zch.Flag, func() (err error) {
|
|
if _, ok := zch.DataChannels[to]; ok {
|
|
bs, jsonErr := json.Marshal(&ZoneResponse{
|
|
Type: reqType,
|
|
From: from,
|
|
To: to,
|
|
Payload: payload,
|
|
})
|
|
if jsonErr != nil {
|
|
return jsonErr
|
|
}
|
|
err = zch.DataChannels[to].DataChannel.SendText(string(bs))
|
|
}
|
|
return
|
|
}); err != nil {
|
|
errCh <- err
|
|
return
|
|
}
|
|
done <- struct{}{}
|
|
}()
|
|
return done, errCh
|
|
}
|
|
|
|
func (zch *ZoneChatsHandler) Init(ctx context.Context, authorizedMembers []string) (err error) {
|
|
for _, member := range authorizedMembers {
|
|
if serr := zch.SetAllPublicChatForUser(member); serr != nil {
|
|
logger.Println(serr)
|
|
}
|
|
}
|
|
zch.init = true
|
|
return
|
|
}
|
|
|
|
func (zch *ZoneChatsHandler) Subscribe(ctx context.Context, publisher <-chan *ZoneRequest) (reqChan chan *ZoneRequest, done chan struct{}, errCh chan error) {
|
|
reqChan, done, errCh = make(chan *ZoneRequest), make(chan struct{}), make(chan error)
|
|
zch.reqChans = append(zch.reqChans, reqChan)
|
|
go func() {
|
|
for {
|
|
select {
|
|
case <-ctx.Done():
|
|
done <- struct{}{}
|
|
return
|
|
case req := <-publisher:
|
|
if err := zch.handleZoneRequest(ctx, req); err != nil {
|
|
errCh <- err
|
|
}
|
|
}
|
|
}
|
|
}()
|
|
return
|
|
}
|
|
|
|
func (zch *ZoneChatsHandler) signalCandidate(from string, to string, candidate *webrtc.ICECandidate) (err error) {
|
|
d, e := zch.sendDataChannelMessage(string(ZONE_CHAT_WEBRTC_CANDIDATE), from, to, map[string]interface{}{
|
|
"from": from,
|
|
"to": to,
|
|
"candidate": candidate.ToJSON().Candidate,
|
|
"sdpMid": *candidate.ToJSON().SDPMid,
|
|
"sdpMLineIndex": strconv.Itoa(int(*candidate.ToJSON().SDPMLineIndex)),
|
|
})
|
|
select {
|
|
case <-d:
|
|
case err = <-e:
|
|
}
|
|
return
|
|
}
|
|
|
|
func (zch *ZoneChatsHandler) GetChats(userId string, chatsId ...interface{}) (err error) {
|
|
chats := make([]*Chat, 0, len(chatsId))
|
|
for _, id := range chatsId {
|
|
if _, ok := id.(string); !ok {
|
|
err = fmt.Errorf("id of wrong type")
|
|
return
|
|
}
|
|
fmt.Println("chat from get chats", id.(string))
|
|
_ = atomicallyExecute(zch.ChatFlag, func() (err error) {
|
|
if _, ok := zch.Chats[id.(string)]; ok {
|
|
logger.Println(zch.Chats[id.(string)])
|
|
chats = append(chats, zch.Chats[id.(string)])
|
|
}
|
|
return
|
|
})
|
|
}
|
|
fmt.Println("first loop done")
|
|
for _, chat := range chats {
|
|
fmt.Println(chat.ChatId)
|
|
index,err := chat.Tracking.GetUserLastIndex(userId)
|
|
if err != nil {
|
|
fmt.Println("there")
|
|
fmt.Println(err)
|
|
return err
|
|
}
|
|
chat.DB.lock.RLock()
|
|
defer chat.DB.lock.RUnlock()
|
|
unread,err := chat.DB.calculateNewChatCount(uint64(index))
|
|
if err != nil {
|
|
fmt.Println("over there")
|
|
fmt.Println(err)
|
|
return err
|
|
}
|
|
chat.LastReadIndex = index
|
|
chat.Unread = unread
|
|
}
|
|
fmt.Println(chats)
|
|
done,e := zch.sendDataChannelMessage(GET_CHATS_RESPONSE,"node",userId,map[string]interface{}{
|
|
"chats": chats,
|
|
})
|
|
select {
|
|
case <-done:
|
|
fmt.Println("done")
|
|
case terr :=<-e:
|
|
fmt.Println(terr)
|
|
}
|
|
return
|
|
}
|
|
|
|
func (zch *ZoneChatsHandler) ListChats() (chats []*Chat, err error) {
|
|
chats = make([]*Chat, 0)
|
|
_ = atomicallyExecute(zch.ChatFlag, func() (err error) {
|
|
for _, chat := range zch.Chats {
|
|
chats = append(chats, chat)
|
|
}
|
|
return
|
|
})
|
|
return
|
|
}
|
|
|
|
func (zch *ZoneChatsHandler) AddNewChat(chatName string, owner string, chatType string, members []interface{}) (err error) {
|
|
if _, ok := zch.Chats[chatName]; ok {
|
|
err = fmt.Errorf("a chat with this name already exist")
|
|
return
|
|
}
|
|
mkdirErr := os.MkdirAll(filepath.Join("data", "zones", zch.ZoneId, "chats", chatName), 0700)
|
|
if mkdirErr != nil {
|
|
return mkdirErr
|
|
}
|
|
mkdirErr = os.Mkdir(filepath.Join("data", "zones", zch.ZoneId, "chats", chatName,"__tracking__"), 0700)
|
|
if mkdirErr != nil {
|
|
return mkdirErr
|
|
}
|
|
file, ferr := os.Create(filepath.Join("data", "zones", zch.ZoneId, "chats", chatName, "chatConfig.json"))
|
|
if ferr != nil {
|
|
return ferr
|
|
}
|
|
m := make([]string, 0, len(members))
|
|
for _, member := range members {
|
|
if mbr, ok := member.(string); ok && mbr != owner {
|
|
m = append(m, mbr)
|
|
}
|
|
}
|
|
baseConfig := &ChatConfig{
|
|
ChatId: chatName,
|
|
Owner: owner,
|
|
ChatType: chatType,
|
|
Members: append(m,owner),
|
|
}
|
|
bs, jsonErr := json.Marshal(baseConfig)
|
|
if jsonErr != nil {
|
|
return jsonErr
|
|
}
|
|
if _, writeErr := file.WriteString(string(bs)); writeErr != nil {
|
|
return writeErr
|
|
}
|
|
err = file.Close()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
zoneChatDBHandler, err := NewZoneChatDBHandler(zch.ZoneId, chatName)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
zoneChatTrackingDB,err := NewZoneChatTracking(zch.ZoneId,chatName)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if err = zoneChatTrackingDB.Initialize(1,baseConfig.Members...); err != nil {
|
|
return err
|
|
}
|
|
var c Chat
|
|
if err = json.Unmarshal(bs, &c); err != nil {
|
|
return err
|
|
}
|
|
c.DB = zoneChatDBHandler
|
|
c.Tracking = zoneChatTrackingDB
|
|
_ = atomicallyExecute(zch.ChatFlag, func() (err error) {
|
|
zch.Chats[c.ChatId] = &c
|
|
return
|
|
})
|
|
newChatForMembers := func(members []string) (err error) {
|
|
for _, member := range members {
|
|
zch.sendZoneRequest(ADD_KNOWN_CHAT, "node", map[string]interface{}{
|
|
"userId": member,
|
|
"chatId": chatName,
|
|
})
|
|
done, e := zch.sendDataChannelMessage(GET_CHATS_RESPONSE, "node", member, map[string]interface{}{
|
|
"chats": []*Chat{zch.Chats[chatName]},
|
|
})
|
|
select {
|
|
case <-done:
|
|
case err = <-e:
|
|
return
|
|
}
|
|
}
|
|
return
|
|
}
|
|
switch c.ChatType {
|
|
case BROADCAST:
|
|
fallthrough
|
|
case PUBLIC:
|
|
err = atomicallyExecute(zch.ChatFlag, func() (err error) {
|
|
err = newChatForMembers(zch.ZoneMembersId)
|
|
return
|
|
})
|
|
case PRIVATE:
|
|
err = newChatForMembers(c.Members)
|
|
}
|
|
return
|
|
}
|
|
|
|
func (zch *ZoneChatsHandler) DeleteChat(chatId string) (err error) {
|
|
if err = atomicallyExecute(zch.ChatFlag, func() (err error) {
|
|
defer delete(zch.Chats, chatId)
|
|
if _, ok := zch.Chats[chatId]; !ok {
|
|
err = fmt.Errorf("no corresponding chat")
|
|
return
|
|
}
|
|
removeKnownChats := func(members []string) (err error) {
|
|
for _, member := range members {
|
|
zch.sendZoneRequest(REMOVE_KNOWN_CHAT, "node", map[string]interface{}{
|
|
"userId": member,
|
|
"chatId": chatId,
|
|
})
|
|
done, e := zch.sendDataChannelMessage(REMOVED_FROM_CHAT, "node", member, map[string]interface{}{
|
|
"chatId": chatId,
|
|
"userId": member,
|
|
})
|
|
select {
|
|
case <-done:
|
|
continue
|
|
case err = <-e:
|
|
return
|
|
}
|
|
}
|
|
return
|
|
}
|
|
switch zch.Chats[chatId].ChatType {
|
|
case BROADCAST:
|
|
fallthrough
|
|
case PUBLIC:
|
|
err = removeKnownChats(zch.ZoneMembersId)
|
|
case PRIVATE:
|
|
err = removeKnownChats(zch.Chats[chatId].Members)
|
|
}
|
|
return
|
|
}); err != nil {
|
|
return
|
|
}
|
|
if err = os.RemoveAll(filepath.Join("data", "zones", zch.ZoneId, "chats", chatId)); err != nil {
|
|
return
|
|
}
|
|
return
|
|
}
|
|
|
|
func (zch *ZoneChatsHandler) EditChatName(chatId string, newChatId string) (err error) {
|
|
if _, ok := zch.Chats[chatId]; !ok {
|
|
err = fmt.Errorf("no coresponding chat")
|
|
return
|
|
}
|
|
bs, err := os.ReadFile(filepath.Join("data", "zones", zch.ZoneId, "chats", chatId, "chatConfig.json"))
|
|
if err != nil {
|
|
return
|
|
}
|
|
var chatConfig ChatConfig
|
|
if err = json.Unmarshal(bs, &chatConfig); err != nil {
|
|
return
|
|
}
|
|
chatConfig.ChatId = newChatId
|
|
bs, err = json.Marshal(&chatConfig)
|
|
if err = os.Rename(filepath.Join("data", "zones", zch.ZoneId, "chats", chatId), filepath.Join("data", "zones", zch.ZoneId, "chats", newChatId)); err != nil {
|
|
return
|
|
}
|
|
f, err := os.OpenFile(filepath.Join("data", "zones", zch.ZoneId, "chats", newChatId, "chatConfig.json"), os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0755)
|
|
defer func() {
|
|
_ = f.Close()
|
|
}()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if _, err = f.Write(bs); err != nil {
|
|
return err
|
|
}
|
|
chat := &Chat{
|
|
Owner: chatConfig.Owner,
|
|
ChatId: chatConfig.ChatId,
|
|
ChatType: chatConfig.ChatType,
|
|
Members: chatConfig.Members,
|
|
DB: zch.Chats[chatId].DB,
|
|
Tracking:zch.Chats[chatId].Tracking,
|
|
}
|
|
chat.DB.updateDbCallbackFolder(newChatId)
|
|
_ = atomicallyExecute(zch.ChatFlag, func() (err error) {
|
|
defer delete(zch.Chats, chatId)
|
|
zch.Chats[newChatId] = chat
|
|
updateKnownChats := func(members []string) (err error) {
|
|
for _, member := range members {
|
|
zch.sendZoneRequest(ADD_KNOWN_CHAT, "node", map[string]interface{}{
|
|
"userId": member,
|
|
"chatId": newChatId,
|
|
})
|
|
zch.sendZoneRequest(REMOVE_KNOWN_CHAT, "node", map[string]interface{}{
|
|
"userId": member,
|
|
"chatId": chatId,
|
|
})
|
|
done, e := zch.sendDataChannelMessage(CHAT_NAME_EDITED, "node", member, map[string]interface{}{
|
|
"formerChatId": chatId,
|
|
"newChatId": newChatId,
|
|
})
|
|
select {
|
|
case <-done:
|
|
case channelErr := <-e:
|
|
logger.Println(channelErr)
|
|
}
|
|
}
|
|
return
|
|
}
|
|
switch chat.ChatType {
|
|
case BROADCAST:
|
|
fallthrough
|
|
case PUBLIC:
|
|
err = updateKnownChats(zch.ZoneMembersId)
|
|
case PRIVATE:
|
|
err = updateKnownChats(chat.Members)
|
|
}
|
|
return
|
|
})
|
|
return
|
|
}
|
|
|
|
func (zch *ZoneChatsHandler) EditChatType(chatId string, chatType string) (err error) {
|
|
if _, ok := zch.Chats[chatId]; !ok {
|
|
err = fmt.Errorf("no coresponding chat")
|
|
return
|
|
}
|
|
bs, err := os.ReadFile(filepath.Join("data", "zones", zch.ZoneId, "chats", chatId, "chatConfig.json"))
|
|
if err != nil {
|
|
return
|
|
}
|
|
var chatConfig ChatConfig
|
|
if err = json.Unmarshal(bs, &chatConfig); err != nil {
|
|
return
|
|
}
|
|
chatConfig.ChatType = chatType
|
|
bs, err = json.Marshal(&chatConfig)
|
|
f, err := os.OpenFile(filepath.Join("data", "zones", zch.ZoneId, "chats", chatId, "chatConfig.json"), os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0755)
|
|
defer func() {
|
|
_ = f.Close()
|
|
}()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if _, err = f.Write(bs); err != nil {
|
|
return err
|
|
}
|
|
chat := &Chat{
|
|
Owner: chatConfig.Owner,
|
|
ChatId: chatConfig.ChatId,
|
|
ChatType: chatType,
|
|
Members: chatConfig.Members,
|
|
DB: zch.Chats[chatId].DB,
|
|
Tracking:zch.Chats[chatId].Tracking,
|
|
}
|
|
switch chatType {
|
|
case BROADCAST:
|
|
fallthrough
|
|
case PUBLIC:
|
|
var members = []string{}
|
|
_ = atomicallyExecute(zch.ChatFlag, func() (err error) {
|
|
members = append(members, zch.ZoneMembersId...)
|
|
return
|
|
})
|
|
for _, member := range zch.ZoneMembersId {
|
|
if pubErr := zch.SetChatPublicForUser(chatId, member); pubErr != nil {
|
|
logger.Println(pubErr)
|
|
}
|
|
zch.sendDataChannelMessage(CHAT_TYPE_EDITED, "node", member, map[string]interface{}{
|
|
"chatId": chatId,
|
|
"chatType": chatType,
|
|
})
|
|
}
|
|
case PRIVATE:
|
|
var members = []string{}
|
|
_ = atomicallyExecute(zch.ChatFlag, func() (err error) {
|
|
members = append(members, zch.ZoneMembersId...)
|
|
return
|
|
})
|
|
for _, member := range zch.ZoneMembersId {
|
|
if pubErr := zch.SetChatPrivateForUser(chatId, member); pubErr != nil {
|
|
logger.Println(pubErr)
|
|
}
|
|
zch.sendDataChannelMessage(CHAT_TYPE_EDITED, "node", member, map[string]interface{}{
|
|
"chatId": chatId,
|
|
"chatType": chatType,
|
|
})
|
|
}
|
|
}
|
|
_ = atomicallyExecute(zch.ChatFlag, func() (err error) {
|
|
zch.Chats[chatId] = chat
|
|
return
|
|
})
|
|
return
|
|
}
|
|
|
|
func (zch *ZoneChatsHandler) AddChatMembers(chatId string, chatMembers []interface{}) (err error) {
|
|
if _, ok := zch.Chats[chatId]; !ok {
|
|
err = fmt.Errorf("no coresponding chat")
|
|
return
|
|
}
|
|
bs, err := os.ReadFile(filepath.Join("data", "zones", zch.ZoneId, "chats", chatId, "chatConfig.json"))
|
|
if err != nil {
|
|
return
|
|
}
|
|
var chatConfig ChatConfig
|
|
if err = json.Unmarshal(bs, &chatConfig); err != nil {
|
|
return
|
|
}
|
|
logger.Printf("%s - %s - %s -%v\n", chatConfig.ChatId, chatConfig.ChatType, chatConfig.Owner, chatMembers)
|
|
addedMembers := make([]string, 0)
|
|
memberLoop:
|
|
for _, chatMember := range chatMembers {
|
|
if _, ok := chatMember.(string); !ok {
|
|
continue
|
|
}
|
|
for _, member := range chatConfig.Members {
|
|
if member == chatMember {
|
|
zch.sendZoneRequest(ADD_KNOWN_CHAT, "node", map[string]interface{}{
|
|
"userId": chatMember,
|
|
"chatId": chatId,
|
|
})
|
|
continue memberLoop
|
|
}
|
|
}
|
|
chatConfig.Members = append(chatConfig.Members, chatMember.(string))
|
|
addedMembers = append(addedMembers, chatMember.(string))
|
|
zch.sendZoneRequest(ADD_KNOWN_CHAT, "node", map[string]interface{}{
|
|
"userId": chatMember,
|
|
"chatId": chatId,
|
|
})
|
|
}
|
|
bs, err = json.Marshal(&chatConfig)
|
|
f, err := os.OpenFile(filepath.Join("data", "zones", zch.ZoneId, "chats", chatId, "chatConfig.json"), os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0755)
|
|
defer func() {
|
|
_ = f.Close()
|
|
}()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if _, err = f.Write(bs); err != nil {
|
|
return err
|
|
}
|
|
chat := &Chat{
|
|
Owner: chatConfig.Owner,
|
|
ChatId: chatConfig.ChatId,
|
|
ChatType: chatConfig.ChatType,
|
|
Members: chatConfig.Members,
|
|
DB: zch.Chats[chatId].DB,
|
|
Tracking: zch.Chats[chatId].Tracking,
|
|
}
|
|
chat.DB.lock.Lock()
|
|
lastIndex := chat.DB.PreviousId
|
|
chat.DB.lock.Unlock()
|
|
_ = atomicallyExecute(zch.ChatFlag, func() (err error) {
|
|
zch.Chats[chatId] = chat
|
|
return
|
|
})
|
|
var chmb []string
|
|
if chat.ChatType == PRIVATE {
|
|
chmb = chat.Members
|
|
} else {
|
|
chmb = zch.ZoneMembersId
|
|
}
|
|
broadcastLoop:
|
|
for _, member := range chmb {
|
|
for _, m := range addedMembers {
|
|
if err = chat.Tracking.SetUserLastIndex(member,lastIndex); err != nil {
|
|
return
|
|
}
|
|
if member == m {
|
|
done, e := zch.sendDataChannelMessage(ADDED_IN_CHAT, "node", member, map[string]interface{}{
|
|
"chat": chat,
|
|
})
|
|
select {
|
|
case <-done:
|
|
case err = <-e:
|
|
logger.Println(err)
|
|
}
|
|
continue broadcastLoop
|
|
}
|
|
if _, ok := zch.DataChannels[member]; ok {
|
|
done, e := zch.sendDataChannelMessage(CHAT_MEMBER_ADDED, "node", member, map[string]interface{}{
|
|
"userId": m,
|
|
"chatId": chat.ChatId,
|
|
})
|
|
select {
|
|
case <-done:
|
|
case err = <-e:
|
|
logger.Println(err)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return
|
|
}
|
|
|
|
func (zch *ZoneChatsHandler) RemoveChatMember(chatId string, chatMember string) (err error) {
|
|
if _, ok := zch.Chats[chatId]; !ok {
|
|
err = fmt.Errorf("no coresponding chat")
|
|
return
|
|
}
|
|
bs, err := os.ReadFile(filepath.Join("data", "zones", zch.ZoneId, "chats", chatId, "chatConfig.json"))
|
|
if err != nil {
|
|
return
|
|
}
|
|
var chatConfig ChatConfig
|
|
if err = json.Unmarshal(bs, &chatConfig); err != nil {
|
|
logger.Println(string(bs))
|
|
logger.Println("json error right here")
|
|
return
|
|
}
|
|
if chatMember == chatConfig.Owner {
|
|
err = fmt.Errorf("you cannot remove the owner from the chat")
|
|
return
|
|
}
|
|
var index int
|
|
var contain bool
|
|
for i, member := range chatConfig.Members {
|
|
if member == chatMember {
|
|
index = i
|
|
contain = true
|
|
break
|
|
}
|
|
}
|
|
if !contain {
|
|
err = fmt.Errorf("member %s not in the channel %s", chatMember, chatId)
|
|
return
|
|
}
|
|
chatConfig.Members = append(chatConfig.Members[:index], chatConfig.Members[index+1:]...)
|
|
bs, err = json.Marshal(&chatConfig)
|
|
if err != nil {
|
|
logger.Println("json error there")
|
|
return
|
|
}
|
|
f, err := os.OpenFile(filepath.Join("data", "zones", zch.ZoneId, "chats", chatId, "chatConfig.json"), os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0755)
|
|
defer func() {
|
|
_ = f.Close()
|
|
}()
|
|
if err != nil {
|
|
return
|
|
}
|
|
logger.Println(string(bs))
|
|
if _, err = f.Write(bs); err != nil {
|
|
return
|
|
}
|
|
var chat *Chat
|
|
_ = atomicallyExecute(zch.ChatFlag, func() (err error) {
|
|
chat = &Chat{
|
|
Owner: chatConfig.Owner,
|
|
ChatId: chatConfig.ChatId,
|
|
ChatType: chatConfig.ChatType,
|
|
Members: chatConfig.Members,
|
|
DB: zch.Chats[chatId].DB,
|
|
Tracking: zch.Chats[chatId].Tracking,
|
|
}
|
|
zch.Chats[chatId] = chat
|
|
return
|
|
})
|
|
if err = chat.Tracking.DeleteUserTracking(chatMember); err != nil {
|
|
return
|
|
}
|
|
zch.sendZoneRequest(REMOVE_KNOWN_CHAT, "node", map[string]interface{}{
|
|
"userId": chatMember,
|
|
"chatId": chatId,
|
|
})
|
|
done, e := zch.sendDataChannelMessage(REMOVED_FROM_CHAT, "node", chatMember, map[string]interface{}{
|
|
"chatId": chatId,
|
|
"userId": chatMember,
|
|
})
|
|
select {
|
|
case <-done:
|
|
case err = <-e:
|
|
logger.Println(err)
|
|
}
|
|
var chmb []string
|
|
if chat.ChatType == PRIVATE {
|
|
chmb = chat.Members
|
|
} else {
|
|
chmb = zch.ZoneMembersId
|
|
}
|
|
broadcastLoop:
|
|
for _, member := range chmb {
|
|
if member == chatMember {
|
|
continue broadcastLoop
|
|
}
|
|
done, e := zch.sendDataChannelMessage(CHAT_MEMBER_REMOVED, "node", member, map[string]interface{}{
|
|
"userId": chatMember,
|
|
"chatId": chat.ChatId,
|
|
})
|
|
select {
|
|
case <-done:
|
|
case err = <-e:
|
|
logger.Println(err)
|
|
}
|
|
}
|
|
return
|
|
}
|
|
|
|
func(zch *ZoneChatsHandler) ReadLastMessage(userId,chatId string) (err error) {
|
|
err = atomicallyExecute(zch.ChatFlag, func() (err error) {
|
|
if chat, ok := zch.Chats[chatId]; ok {
|
|
err = chat.Tracking.SetUserLastIndex(userId,chat.DB.PreviousId)
|
|
}
|
|
return
|
|
})
|
|
return
|
|
}
|
|
|
|
func (zch *ZoneChatsHandler) ListLatestChatMessages(userId, chatId string, lastIndex, limit float64) (err error) {
|
|
var list []*ChatMessage
|
|
var i int
|
|
var done bool
|
|
if err = atomicallyExecute(zch.ChatFlag, func() (err error) {
|
|
if chat, ok := zch.Chats[chatId]; ok {
|
|
list, i, done, err = zch.Chats[chatId].DB.ListChatMessages(int(lastIndex), int(limit))
|
|
if err != nil {
|
|
return
|
|
}
|
|
err = chat.Tracking.SetUserLastIndex(userId,chat.DB.PreviousId)
|
|
}
|
|
return
|
|
}); err != nil {
|
|
return
|
|
}
|
|
success, e := zch.sendDataChannelMessage(CHAT_MESSAGE_LIST, "node", userId, map[string]interface{}{
|
|
"done": done || i <= 0,
|
|
"lastIndex": i - 1,
|
|
"chatId": chatId,
|
|
"chatMessages": list,
|
|
})
|
|
select {
|
|
case <-success:
|
|
case err = <-e:
|
|
}
|
|
return
|
|
}
|
|
|
|
func (zch *ZoneChatsHandler) ListLatestChatFiles(userId, chatId string, lastIndex, limit float64) (err error) {
|
|
var list []*ChatFile
|
|
var i int
|
|
if err = atomicallyExecute(zch.ChatFlag, func() (err error) {
|
|
if _, ok := zch.Chats[chatId]; ok {
|
|
list, i, err = zch.Chats[chatId].DB.ListChatFiles(int(lastIndex), int(limit))
|
|
}
|
|
return
|
|
}); err != nil {
|
|
return
|
|
}
|
|
done, e := zch.sendDataChannelMessage(CHAT_FILES_LIST, "node", userId, map[string]interface{}{
|
|
"done": i <= 0,
|
|
"lastIndex": i,
|
|
"chatId": chatId,
|
|
"chatMessages": list,
|
|
})
|
|
select {
|
|
case <-done:
|
|
case err = <-e:
|
|
}
|
|
return
|
|
}
|
|
|
|
func (zch *ZoneChatsHandler) AddChatMessage(userId, chatId, content string, isResponse bool, chatResponseId uint64, file *ChatFile) (err error) {
|
|
chatMessage := &ChatMessage{
|
|
Content: content,
|
|
From: userId,
|
|
IsResponse: isResponse,
|
|
ResponseOf: nil,
|
|
File: file,
|
|
Tags: make([]string, 0),
|
|
Date: time.Now().Format("Mon, 02 Jan 2006 15:04:05 MST"),
|
|
}
|
|
|
|
if err = atomicallyExecute(zch.ChatFlag, func() (err error) {
|
|
if chat, ok := zch.Chats[chatId]; ok {
|
|
if isResponse {
|
|
parentMessage, getErr := chat.DB.GetChatMessage(chatResponseId)
|
|
if err != nil {
|
|
if getErr != badger.ErrKeyNotFound {
|
|
return getErr
|
|
}
|
|
}
|
|
chatMessage.ResponseOf = parentMessage
|
|
}
|
|
if err = zch.Chats[chatId].DB.AddNewChatMessage(chatMessage); err != nil {
|
|
return
|
|
}
|
|
chatMessage.ID = zch.Chats[chatId].DB.PreviousId
|
|
|
|
} else {
|
|
err = fmt.Errorf("no corresponding chats")
|
|
}
|
|
return
|
|
}); err != nil {
|
|
return
|
|
}
|
|
_ = atomicallyExecute(zch.ChatFlag, func() (err error) {
|
|
chat := zch.Chats[chatId]
|
|
logger.Println(chat.ChatType)
|
|
switch chat.ChatType {
|
|
case BROADCAST:
|
|
fallthrough
|
|
case PUBLIC:
|
|
for _, v := range zch.ZoneMembersId {
|
|
done, e := zch.sendDataChannelMessage(NEW_CHAT_MESSAGE, "node", v, map[string]interface{}{
|
|
"chatMessage": chatMessage,
|
|
"chatId": chatId,
|
|
})
|
|
select {
|
|
case <-done:
|
|
case err = <-e:
|
|
}
|
|
}
|
|
case PRIVATE:
|
|
for _, v := range chat.Members {
|
|
done, e := zch.sendDataChannelMessage(NEW_CHAT_MESSAGE, "node", v, map[string]interface{}{
|
|
"chatMessage": chatMessage,
|
|
"chatId": chatId,
|
|
})
|
|
select {
|
|
case <-done:
|
|
case err = <-e:
|
|
}
|
|
}
|
|
}
|
|
return
|
|
})
|
|
return
|
|
}
|
|
|
|
func (zch *ZoneChatsHandler) SetChatPrivateForUser(chatId string, member string) (err error) {
|
|
err = atomicallyExecute(zch.ChatFlag, func() (err error) {
|
|
if chat, ok := zch.Chats[chatId]; ok {
|
|
var contain bool
|
|
for _, m := range chat.Members {
|
|
if m == member {
|
|
contain = true
|
|
break
|
|
}
|
|
}
|
|
if !contain {
|
|
zch.sendZoneRequest(REMOVE_KNOWN_CHAT, "node", map[string]interface{}{
|
|
"userId": member,
|
|
"chatId": chatId,
|
|
})
|
|
done, e := zch.sendDataChannelMessage(REMOVED_FROM_CHAT, "node", member, map[string]interface{}{
|
|
"chatId": chatId,
|
|
"userId": member,
|
|
})
|
|
select {
|
|
case <-done:
|
|
case err = <-e:
|
|
}
|
|
}
|
|
}
|
|
return
|
|
})
|
|
return
|
|
}
|
|
|
|
func (zch *ZoneChatsHandler) SetChatPublicForUser(chatId string, member string) (err error) {
|
|
err = atomicallyExecute(zch.ChatFlag, func() (err error) {
|
|
if chat, ok := zch.Chats[chatId]; ok {
|
|
var contain bool
|
|
for _, m := range chat.Members {
|
|
if m == member {
|
|
contain = true
|
|
break
|
|
}
|
|
}
|
|
if !contain {
|
|
zch.sendZoneRequest(ADD_KNOWN_CHAT, "node", map[string]interface{}{
|
|
"userId": member,
|
|
"chatId": chatId,
|
|
})
|
|
done, e := zch.sendDataChannelMessage(ADDED_IN_CHAT, "node", member, map[string]interface{}{
|
|
"chat": chat,
|
|
})
|
|
select {
|
|
case <-done:
|
|
case err = <-e:
|
|
}
|
|
}
|
|
}
|
|
return
|
|
})
|
|
return
|
|
}
|
|
|
|
func (zch *ZoneChatsHandler) SetAllPublicChatForUser(userId string) (err error) {
|
|
for _, chat := range zch.Chats {
|
|
logger.Println("--------------- public chat for all : ", chat)
|
|
if chat.ChatType == PUBLIC || chat.ChatType == BROADCAST {
|
|
if chat.ChatId == GENERAL {
|
|
if err = zch.AddChatMembers(chat.ChatId, []interface{}{userId}); err != nil {
|
|
logger.Println(err)
|
|
}
|
|
continue
|
|
}
|
|
if err = zch.SetChatPublicForUser(chat.ChatId, userId); err != nil {
|
|
continue
|
|
}
|
|
}
|
|
}
|
|
return
|
|
}
|
|
|
|
func (zch *ZoneChatsHandler) RemoveUserFromAllChats(userId string) (err error) {
|
|
chats, err := zch.ListChats()
|
|
if err != nil {
|
|
logger.Println("an error occured -----------------*")
|
|
return
|
|
}
|
|
for _, chat := range chats {
|
|
if err = zch.RemoveChatMember(chat.ChatId, userId); err != nil {
|
|
logger.Println("-------------------*", err)
|
|
continue
|
|
}
|
|
}
|
|
return
|
|
}
|
|
|
|
func (zch *ZoneChatsHandler) RemoveAllUserChat(userId string) (err error) {
|
|
chats, err := zch.ListChats()
|
|
if err != nil {
|
|
return
|
|
}
|
|
for _, chat := range chats {
|
|
logger.Println("$$$$$$$$$$ chat owner :", chat.Owner, userId)
|
|
if chat.Owner == userId {
|
|
if derr := zch.DeleteChat(chat.ChatId); derr != nil {
|
|
logger.Println("**************", derr)
|
|
}
|
|
logger.Println("deleted chat", chat.ChatId)
|
|
}
|
|
}
|
|
return
|
|
}
|
|
|
|
func (zch *ZoneChatsHandler) ConnectToChatFSInstance(channelId string, userId string, sdp string) (err error) {
|
|
err = atomicallyExecute(zch.ChatFSInstanceFlag, func() (err error) {
|
|
d, e := zch.ChatFSInstance.HandleOffer(context.Background(), channelId, userId, sdp, zch.HostId, zch.sendDataChannelMessage, zch.signalCandidate)
|
|
select {
|
|
case <-d:
|
|
case err = <-e:
|
|
}
|
|
return
|
|
})
|
|
return
|
|
}
|
|
|
|
func (zch *ZoneChatsHandler) LeaveChatFSInstance(
|
|
userId string) (err error) {
|
|
zch.ChatFSInstance.HandleLeavingMember(userId)
|
|
return
|
|
}
|
|
|
|
func (zch *ZoneChatsHandler) DeleteChatMessage(key uint64, chatId string) (err error) {
|
|
err = atomicallyExecute(zch.ChatFlag, func() (err error) {
|
|
if _, ok := zch.Chats[chatId]; !ok {
|
|
err = fmt.Errorf("no file corresponding to id %s", chatId)
|
|
return
|
|
}
|
|
if err = zch.Chats[chatId].DB.DeleteChatMessage(key); err != nil {
|
|
return
|
|
}
|
|
if zch.Chats[chatId].ChatType == PRIVATE {
|
|
for _, member := range zch.Chats[chatId].Members {
|
|
d, e := zch.sendDataChannelMessage(CHAT_MESSAGE_DELETED, "node", member, map[string]interface{}{
|
|
"chatId": chatId,
|
|
"messageId": key,
|
|
})
|
|
select {
|
|
case <-d:
|
|
case tempErr := <-e:
|
|
logger.Println(tempErr)
|
|
}
|
|
}
|
|
} else {
|
|
for _, member := range zch.ZoneMembersId {
|
|
d, e := zch.sendDataChannelMessage(CHAT_MESSAGE_DELETED, "node", member, map[string]interface{}{
|
|
"chatId": chatId,
|
|
"messageId": key,
|
|
})
|
|
select {
|
|
case <-d:
|
|
case tempErr := <-e:
|
|
logger.Println(tempErr)
|
|
}
|
|
}
|
|
}
|
|
previousId := zch.Chats[chatId].DB.PreviousId
|
|
if previousId == key {
|
|
if err = zch.Chats[chatId].DB.revertPreviousId(); err != nil {
|
|
return
|
|
}
|
|
previousId = zch.Chats[chatId].DB.PreviousId
|
|
if previousId == 1 {
|
|
previousId = 0
|
|
}
|
|
if err = zch.Chats[chatId].Tracking.RevertTrackingLastIndex(previousId); err != nil {
|
|
return
|
|
}
|
|
}
|
|
return
|
|
})
|
|
return
|
|
}
|
|
|
|
func (zch *ZoneChatsHandler) UpdateChatMessage(key uint64, chatId, newContent string) (err error) {
|
|
err = atomicallyExecute(zch.ChatFlag, func() (err error) {
|
|
if _, ok := zch.Chats[chatId]; !ok {
|
|
err = fmt.Errorf("no file corresponding to id %s", chatId)
|
|
return
|
|
}
|
|
if err = zch.Chats[chatId].DB.ModifyChatMessage(key, newContent); err != nil {
|
|
return
|
|
}
|
|
if zch.Chats[chatId].ChatType == PRIVATE {
|
|
for _, member := range zch.Chats[chatId].Members {
|
|
d, e := zch.sendDataChannelMessage(CHAT_MESSAGE_EDITED, "node", member, map[string]interface{}{
|
|
"chatId": chatId,
|
|
"messageId": key,
|
|
"newContent": newContent,
|
|
})
|
|
select {
|
|
case <-d:
|
|
case tempErr := <-e:
|
|
logger.Println(tempErr)
|
|
}
|
|
}
|
|
} else {
|
|
for _, member := range zch.ZoneMembersId {
|
|
d, e := zch.sendDataChannelMessage(CHAT_MESSAGE_EDITED, "node", member, map[string]interface{}{
|
|
"chatId": chatId,
|
|
"messageId": key,
|
|
"newContent": newContent,
|
|
})
|
|
select {
|
|
case <-d:
|
|
case tempErr := <-e:
|
|
logger.Println(tempErr)
|
|
}
|
|
}
|
|
}
|
|
return
|
|
})
|
|
return
|
|
}
|
|
|
|
func (zch *ZoneChatsHandler) DeleteChatFile(key uint64, fileName, chatId string) (err error) {
|
|
err = atomicallyExecute(zch.ChatFlag, func() (err error) {
|
|
if _, ok := zch.Chats[chatId]; !ok {
|
|
err = fmt.Errorf("no file corresponding to id %s", chatId)
|
|
return
|
|
}
|
|
if err = zch.Chats[chatId].DB.DeleteChatFile(fileName, key); err != nil {
|
|
return
|
|
}
|
|
if zch.Chats[chatId].ChatType == PRIVATE {
|
|
for _, member := range zch.Chats[chatId].Members {
|
|
d, e := zch.sendDataChannelMessage(CHAT_FILE_DELETED, "node", member, map[string]interface{}{
|
|
"chatId": chatId,
|
|
"fileId": key,
|
|
"fileName": fileName,
|
|
})
|
|
select {
|
|
case <-d:
|
|
case tempErr := <-e:
|
|
logger.Println(tempErr)
|
|
}
|
|
}
|
|
} else {
|
|
for _, member := range zch.ZoneMembersId {
|
|
d, e := zch.sendDataChannelMessage(CHAT_FILE_DELETED, "node", member, map[string]interface{}{
|
|
"chatId": chatId,
|
|
"fileId": key,
|
|
"fileName": fileName,
|
|
})
|
|
select {
|
|
case <-d:
|
|
case tempErr := <-e:
|
|
logger.Println(tempErr)
|
|
}
|
|
}
|
|
}
|
|
return
|
|
})
|
|
return
|
|
}
|
|
|
|
func (zch *ZoneChatsHandler) handleZoneRequest(ctx context.Context, req *ZoneRequest) (err error) {
|
|
logger.Println("got request in zone chat handler", req)
|
|
switch req.ReqType {
|
|
case LEAVE_ZONE:
|
|
if err = verifyFieldsString(req.Payload, "userId"); err != nil {
|
|
return
|
|
}
|
|
err = zch.LeaveChatFSInstance(req.Payload["userId"].(string))
|
|
case string(REMOVED_ZONE_AUTHORIZED_MEMBER):
|
|
if err = verifyFieldsString(req.Payload, "userId"); err != nil {
|
|
return
|
|
}
|
|
var index int
|
|
for i, m := range zch.ZoneMembersId {
|
|
if m == req.Payload["userId"].(string) {
|
|
index = i
|
|
break
|
|
}
|
|
}
|
|
zch.ZoneMembersId = append(zch.ZoneMembersId[:index], zch.ZoneMembersId[index+1:]...)
|
|
if err = zch.RemoveAllUserChat(req.Payload["userId"].(string)); err != nil {
|
|
logger.Println("****______________", err)
|
|
}
|
|
err = zch.RemoveUserFromAllChats(req.Payload["userId"].(string))
|
|
case string(NEW_AUTHORIZED_ZONE_MEMBER):
|
|
if err = verifyFieldsString(req.Payload, "userId"); err != nil {
|
|
return
|
|
}
|
|
var contain bool
|
|
for _, m := range zch.ZoneMembersId {
|
|
if m == req.Payload["userId"].(string) {
|
|
contain = true
|
|
break
|
|
}
|
|
}
|
|
if !contain {
|
|
zch.ZoneMembersId = append(zch.ZoneMembersId, req.Payload["userId"].(string))
|
|
}
|
|
err = zch.SetAllPublicChatForUser(req.Payload["userId"].(string))
|
|
case ADD_CHAT_MEMBERS:
|
|
if err = verifyFieldsString(req.Payload, "chatId"); err != nil {
|
|
return
|
|
}
|
|
if err = verifyFieldsSliceInterface(req.Payload, "members"); err != nil {
|
|
return
|
|
}
|
|
err = zch.AddChatMembers(req.Payload["chatId"].(string), req.Payload["members"].([]interface{}))
|
|
case REMOVE_CHAT_MEMBER:
|
|
if err = verifyFieldsString(req.Payload, "chatId", "userId"); err != nil {
|
|
return
|
|
}
|
|
err = zch.RemoveChatMember(req.Payload["chatId"].(string), req.Payload["userId"].(string))
|
|
if err != nil {
|
|
logger.Println("an error occured in add known chat", err)
|
|
return
|
|
}
|
|
case EDIT_CHAT_NAME:
|
|
if err = verifyFieldsString(req.Payload, "chatId", "newChatId"); err != nil {
|
|
return
|
|
}
|
|
if err = zch.EditChatName(req.Payload["chatId"].(string), req.Payload["newChatId"].(string)); err != nil {
|
|
return
|
|
}
|
|
case EDIT_CHAT_TYPE:
|
|
if err = verifyFieldsString(req.Payload, "chatId", "chatType"); err != nil {
|
|
return
|
|
}
|
|
if err = zch.EditChatType(req.Payload["chatId"].(string), req.Payload["chatType"].(string)); err != nil {
|
|
return
|
|
}
|
|
case DELETE_CHAT:
|
|
if err = verifyFieldsString(req.Payload, "chatId"); err != nil {
|
|
return
|
|
}
|
|
err = zch.DeleteChat(req.Payload["chatId"].(string))
|
|
case CREATE_CHAT:
|
|
if err = verifyFieldsString(req.Payload, "chatId", "owner", "chatType"); err != nil {
|
|
return
|
|
}
|
|
if err = verifyFieldsSliceInterface(req.Payload, "members"); err != nil {
|
|
return
|
|
}
|
|
err = zch.AddNewChat(req.Payload["chatId"].(string), req.Payload["owner"].(string), req.Payload["chatType"].(string), req.Payload["members"].([]interface{}))
|
|
case GET_CHATS:
|
|
fmt.Println("got a get chat req")
|
|
if err = verifyFieldsSliceInterface(req.Payload, "chatsId"); err != nil {
|
|
return
|
|
}
|
|
fmt.Println("calling get chat")
|
|
err = zch.GetChats(req.From, req.Payload["chatsId"].([]interface{})...)
|
|
fmt.Println("get chat done")
|
|
case LIST_LATEST_CHATS:
|
|
if err = verifyFieldsString(req.Payload, "chatId"); err != nil {
|
|
return
|
|
}
|
|
if err = verifyFieldsFloat64(req.Payload, "lastIndex", "limit"); err != nil {
|
|
return
|
|
}
|
|
err = zch.ListLatestChatMessages(req.From, req.Payload["chatId"].(string), req.Payload["lastIndex"].(float64), req.Payload["limit"].(float64))
|
|
return
|
|
case LIST_LATEST_FILES:
|
|
if err = verifyFieldsString(req.Payload, "chatId"); err != nil {
|
|
return
|
|
}
|
|
if err = verifyFieldsFloat64(req.Payload, "lastIndex", "limit"); err != nil {
|
|
return
|
|
}
|
|
err = zch.ListLatestChatFiles(req.From, req.Payload["chatId"].(string), req.Payload["lastIndex"].(float64), req.Payload["limit"].(float64))
|
|
return
|
|
case READ_LATEST_MESSAGE:
|
|
if err = verifyFieldsString(req.Payload, "chatId"); err != nil {
|
|
return
|
|
}
|
|
err = zch.ReadLastMessage(req.From,req.Payload["chatId"].(string))
|
|
case ADD_CHAT_MESSAGE:
|
|
logger.Println("got request in zone chat handler", req)
|
|
if err = verifyFieldsString(req.Payload, "chatId", "content"); err != nil {
|
|
return
|
|
}
|
|
if err = verifyFieldsBool(req.Payload, "isResponse"); err != nil {
|
|
return
|
|
}
|
|
var parentChatId uint64
|
|
if req.Payload["isResponse"].(bool) {
|
|
if err = verifyFieldsFloat64(req.Payload, "parentChatId"); err != nil {
|
|
return
|
|
}
|
|
parentChatId = uint64(req.Payload["parentChatId"].(float64))
|
|
}
|
|
var file *ChatFile = nil
|
|
if _, ok := req.Payload["file"]; ok {
|
|
bs, jsonErr := json.Marshal(req.Payload["file"])
|
|
if jsonErr != nil {
|
|
return jsonErr
|
|
}
|
|
var f ChatFile
|
|
if err = json.Unmarshal(bs, &f); err != nil {
|
|
err = fmt.Errorf("the file payload dont match ChatFile struct pattern : %v", err)
|
|
return
|
|
}
|
|
file = &f
|
|
}
|
|
err = zch.AddChatMessage(req.From, req.Payload["chatId"].(string), req.Payload["content"].(string), req.Payload["isResponse"].(bool), parentChatId, file)
|
|
case DELETE_CHAT_MESSAGE:
|
|
if err = verifyFieldsString(req.Payload, "chatId"); err != nil {
|
|
return
|
|
}
|
|
if err = verifyFieldsFloat64(req.Payload, "messageId"); err != nil {
|
|
return
|
|
}
|
|
err = zch.DeleteChatMessage(uint64(req.Payload["messageId"].(float64)), req.Payload["chatId"].(string))
|
|
case EDIT_CHAT_MESSAGE:
|
|
if err = verifyFieldsString(req.Payload, "chatId", "newContent"); err != nil {
|
|
return
|
|
}
|
|
if err = verifyFieldsFloat64(req.Payload, "messageId"); err != nil {
|
|
return
|
|
}
|
|
err = zch.UpdateChatMessage(uint64(req.Payload["messageId"].(float64)), req.Payload["chatId"].(string), req.Payload["newContent"].(string))
|
|
case DELETE_CHAT_FILE:
|
|
if err = verifyFieldsString(req.Payload, "chatId", "fileName"); err != nil {
|
|
return
|
|
}
|
|
if err = verifyFieldsFloat64(req.Payload, "fileId"); err != nil {
|
|
return
|
|
}
|
|
err = zch.DeleteChatFile(uint64(req.Payload["fileId"].(float64)), req.Payload["fileName"].(string), req.Payload["chatId"].(string))
|
|
case ZONE_UPLOAD_CHAT_FILE:
|
|
if err = verifyFieldsString(req.Payload, "chatId", "userId", "fileName"); err != nil {
|
|
return
|
|
}
|
|
err = zch.ChatFSInstance.SetupFileUpload(req.Payload["chatId"].(string), req.Payload["fileName"].(string), req.Payload["userId"].(string))
|
|
case ZONE_DOWNLOAD_CHAT_FILE:
|
|
if err = verifyFieldsString(req.Payload, "chatId", "userId", "fileName"); err != nil {
|
|
return
|
|
}
|
|
err = zch.ChatFSInstance.SetupFileDownload(req.Payload["chatId"].(string), req.Payload["fileName"].(string), req.Payload["userId"].(string))
|
|
case ZONE_UPLOAD_CHAT_FILE_DONE:
|
|
if err = verifyFieldsBool(req.Payload, "failed"); err != nil {
|
|
return
|
|
}
|
|
if err = verifyFieldsString(req.Payload, "path", "userId", "fileName", "type"); err != nil {
|
|
return
|
|
}
|
|
if err = verifyFieldsFloat64(req.Payload, "size"); err != nil {
|
|
return
|
|
}
|
|
if _, ok := req.Payload["chatFile"]; !ok {
|
|
err = fmt.Errorf("no field chatFile in request payload")
|
|
return
|
|
}
|
|
if req.Payload["failed"].(bool) {
|
|
logger.Println(zch.ChatFSInstance.FileUploadFailed(req.Payload["path"].(string), req.Payload["fileName"].(string), req.Payload["userId"].(string)))
|
|
} else {
|
|
defer func() {
|
|
logger.Println(zch.ChatFSInstance.FileUploadDone(req.Payload["path"].(string), req.Payload["fileName"].(string), req.Payload["userId"].(string)))
|
|
}()
|
|
}
|
|
case string(ZONE_CHAT_WEBRTC_OFFER):
|
|
if err = verifyFieldsString(req.Payload, "channelId", "userId", "sdp"); err != nil {
|
|
return
|
|
}
|
|
err = zch.ConnectToChatFSInstance(req.Payload["channelId"].(string), req.Payload["userId"].(string), req.Payload["sdp"].(string))
|
|
case string(ZONE_CHAT_WEBRTC_COUNTER_OFFER):
|
|
logger.Println("handling fs instance counter offer")
|
|
if err = verifyFieldsString(req.Payload, "channelId", "userId"); err != nil {
|
|
return
|
|
}
|
|
err = atomicallyExecute(zch.ChatFSInstanceFlag, func() (err error) {
|
|
err = zch.ChatFSInstance.HandleCounterOffer(context.Background(), req.Payload["userId"].(string), zch.sendDataChannelMessage)
|
|
return
|
|
})
|
|
case string(ZONE_CHAT_WEBRTC_RENNEGOTIATION_OFFER):
|
|
if err = verifyFieldsString(req.Payload, "channelId", "userId", "sdp"); err != nil {
|
|
return
|
|
}
|
|
err = atomicallyExecute(zch.ChatFSInstanceFlag, func() (err error) {
|
|
err = zch.ChatFSInstance.HandleRennegotiationOffer(req.Payload["userId"].(string), req.Payload["sdp"].(string), zch.sendDataChannelMessage)
|
|
return
|
|
})
|
|
case string(ZONE_CHAT_WEBRTC_RENNEGOTIATION_ANSWER):
|
|
if err = verifyFieldsString(req.Payload, "channelId", "userId", "sdp"); err != nil {
|
|
return
|
|
}
|
|
err = atomicallyExecute(zch.ChatFSInstanceFlag, func() (err error) {
|
|
err = zch.ChatFSInstance.HandleRennegotiationAnswer(req.Payload["userId"].(string), req.Payload["sdp"].(string))
|
|
return
|
|
})
|
|
case string(ZONE_CHAT_WEBRTC_CANDIDATE):
|
|
logger.Println("handling fs instance webrtc candidate")
|
|
logger.Println(req.Payload)
|
|
if err = verifyFieldsString(req.Payload, FROM, "candidate", "sdpMLineIndex", "sdpMid", "channelId", "userId"); err != nil {
|
|
return
|
|
}
|
|
logger.Println(req.Payload)
|
|
i, convErr := strconv.Atoi(req.Payload["sdpMLineIndex"].(string))
|
|
if convErr != nil {
|
|
return convErr
|
|
}
|
|
SDPMLineIndex := uint16(i)
|
|
sdpMid := req.Payload["sdpMid"].(string)
|
|
logger.Println(sdpMid, SDPMLineIndex)
|
|
err = atomicallyExecute(zch.ChatFSInstanceFlag, func() (err error) {
|
|
err = zch.ChatFSInstance.AddCandidate(&webrtc.ICECandidateInit{
|
|
Candidate: req.Payload["candidate"].(string),
|
|
SDPMid: &sdpMid,
|
|
SDPMLineIndex: &SDPMLineIndex,
|
|
}, req.Payload["userId"].(string))
|
|
return
|
|
})
|
|
}
|
|
return
|
|
} |