"os/exec"
"os/signal"
"path"
+ "sort"
"strings"
"syscall"
"time"
"go.stargrave.org/mmc"
)
-const (
- PerPage = 100
- CmdFile = "/FILE "
-)
+const CmdFile = "/FILE "
var (
Newwin = flag.String("newwin", "cmd/newwin", "Path to newwin command")
- DebugFifo = flag.String("debug", "debug", "Path to debug FIFO to be created")
+ DebugFifo = flag.String("debug", "", "Path to debug FIFO to be created")
DebugFd *os.File
UmaskCur int
)
}
func main() {
- entrypoint := flag.String("entrypoint", "mm.rnd.stcnet.ru", "Entrypoint")
+ entrypoint := flag.String("entrypoint", mmc.GetEntrypoint(), "Entrypoint")
notifyCmd := flag.String("notify", "cmd/notify", "Path to notification handler")
heartbeatCh := flag.String("heartbeat-ch", "town-square", "Channel for heartbeating")
+ userStatusFifo := flag.String("user-status", "", "Path to FIFO for user statuses")
flag.Parse()
log.SetFlags(log.Lshortfile)
log.SetOutput(os.Stdout)
}
Team := teams[0]
- Users := make(map[string]*model.User)
- for pageNum := 0; ; pageNum++ {
- time.Sleep(mmc.SleepTime)
- page, resp, err := c.GetUsers(pageNum, PerPage, "")
- if err != nil {
- if DebugFd != nil {
- spew.Fdump(DebugFd, resp)
- }
- log.Fatalln(err)
- }
- if DebugFd != nil {
- spew.Fdump(DebugFd, page)
- }
- for _, u := range page {
- Users[u.Id] = u
- }
- if len(page) < PerPage {
- break
- }
- }
-
var updateQueue []string
LastSent := time.Now()
+
+ Users, err := mmc.GetUsers(c, DebugFd)
+ if err != nil {
+ log.Fatalln(err)
+ }
+
+ UsersDC := make(map[string]*model.Channel, len(Users))
+ userIds := make([]string, 0, len(Users))
for _, u := range Users {
+ userIds = append(userIds, u.Id)
pth := path.Join("users", strings.ReplaceAll(u.Username, ".", "_"))
os.MkdirAll(pth, 0777)
rewriteIfChanged(
log.Fatalln(err)
}
}
- updateQueue = append(updateQueue,
- pth, u.Id+"__"+me.Id,
- pth, me.Id+"__"+u.Id,
- )
+
+ if fi, err := os.Stat(path.Join(pth, mmc.OutRec)); err == nil && fi.Size() > 0 {
+ time.Sleep(mmc.SleepTime)
+ dc, resp, err := c.CreateDirectChannel(me.Id, u.Id)
+ if err != nil {
+ if DebugFd != nil {
+ spew.Fdump(DebugFd, resp)
+ }
+ log.Println("CreateDirectChannel:", err)
+ continue
+ }
+ if DebugFd != nil {
+ spew.Fdump(DebugFd, dc)
+ }
+ UsersDC[u.Id] = dc
+ updateQueue = append(updateQueue, pth, dc.Id)
+ }
statusPth := path.Join(pth, "status")
os.Remove(statusPth)
if err != nil {
continue
}
+ dc = UsersDC[u.Id]
if dc == nil {
dc, resp, err = c.CreateDirectChannel(me.Id, u.Id)
if err != nil {
log.Println("CreateDirectChannel:", err)
continue
}
+ UsersDC[u.Id] = dc
if DebugFd != nil {
spew.Fdump(DebugFd, dc)
}
}(u)
}
+ UserStatus := make(map[string]string)
+ updateUserStatus := func() {
+ statuses, resp, err := c.GetUsersStatusesByIds(userIds)
+ if err != nil {
+ if DebugFd != nil {
+ spew.Fdump(DebugFd, resp)
+ }
+ log.Fatalln(err)
+ }
+ if DebugFd != nil {
+ spew.Fdump(DebugFd, teams)
+ }
+ for _, s := range statuses {
+ UserStatus[Users[s.UserId].Username] = s.Status
+ }
+ }
+ if *userStatusFifo != "" {
+ updateUserStatus()
+ go func() {
+ for {
+ time.Sleep(mmc.SleepTime)
+ fd, err := os.OpenFile(
+ *userStatusFifo, os.O_WRONLY|os.O_APPEND, os.FileMode(0666),
+ )
+ if err != nil {
+ log.Println("OpenFile:", *userStatusFifo, err)
+ continue
+ }
+ statuses := make(map[string][]string)
+ for name, status := range UserStatus {
+ statuses[status] = append(statuses[status], name)
+ }
+ for status := range statuses {
+ if status == "offline" {
+ continue
+ }
+ sort.Strings(statuses[status])
+ fmt.Fprintln(fd, status+":", strings.Join(statuses[status], " "))
+ }
+ fd.Close()
+ }
+ }()
+ }
+
Chans := make(map[string]*model.Channel)
time.Sleep(mmc.SleepTime)
page, resp, err := c.GetChannelsForTeamForUser(Team.Id, me.Id, false, "")
log.Println("OpenFile:", usersPth, err)
continue
}
- for pageNum := 0; ; pageNum++ {
- users, resp, err := c.GetUsersInChannel(ch.Id, pageNum, PerPage, "")
+ for n := 0; ; n++ {
+ users, resp, err := c.GetUsersInChannel(ch.Id, n, mmc.PerPage, "")
if err != nil {
if DebugFd != nil {
spew.Fdump(DebugFd, resp)
for _, u := range users {
fmt.Fprintf(fd, "%s\n", u.Username)
}
- if len(users) < PerPage {
+ if len(users) < mmc.PerPage {
break
}
}
}(ch)
}
- go func() {
- log.Println("syncing", len(Chans)+len(Users), "rooms")
- for len(updateQueue) > 0 {
- err := updatePosts(c, Users, updateQueue[0], updateQueue[1])
- if err != nil {
- log.Println("updatePosts:", err)
- }
- updateQueue = updateQueue[2:]
+ log.Println("syncing", len(updateQueue)/2, "rooms")
+ for len(updateQueue) > 0 {
+ err := updatePosts(c, Users, updateQueue[0], updateQueue[1])
+ if err != nil {
+ log.Println("updatePosts:", err)
}
- log.Println("sync done")
- }()
+ updateQueue = updateQueue[2:]
+ }
+ log.Println("sync done")
+ if *notifyCmd != "" {
+ exec.Command(*notifyCmd, "sync done").Run()
+ }
go func() {
os.MkdirAll("file", 0777)
Name: fi.Name,
Size: int64(len(data)),
Mode: 0o666,
+ ModTime: time.Unix(fi.CreateAt/1000, 0),
PAXRecords: map[string]string{
"MM.FileId": fi.Id,
"MM.MIMEType": fi.MimeType,
for {
select {
case <-t.C:
+ updateUserStatus()
if time.Now().Before(LastSent.Add(time.Minute)) {
continue
}
if e == nil || !e.IsValid() {
continue
}
- data := e.GetData()
if DebugFd != nil {
- spew.Fdump(DebugFd, e.EventType(), data)
+ spew.Fdump(DebugFd, e)
}
+ data := e.GetData()
var user *model.User
if userId, ok := data["user_id"]; ok && userId.(string) != "" {
user = Users[userId.(string)]
case model.WebsocketEventPostEdited,
model.WebsocketEventPostDeleted,
model.WebsocketEventPosted:
- chName := data["channel_name"].(string)
+ chName, ok := data["channel_name"].(string)
+ if !ok {
+ continue
+ }
var post model.Post
if err = json.NewDecoder(
strings.NewReader(data["post"].(string)),
log.Fatalln(err)
}
case model.WebsocketEventStatusChange:
- log.Println("status change:", user.Username, "->", data["status"].(string))
+ status := data["status"].(string)
+ UserStatus[user.Username] = status
if *notifyCmd != "" {
exec.Command(*notifyCmd, fmt.Sprintf(
- "status: %s -> %s",
- user.Username, data["status"].(string),
+ "status: %s -> %s", user.Username, status,
)).Run()
}
case model.WebsocketEventHello: