]> Sergey Matveev's repositories - mmc.git/blobdiff - cmd/mmc/main.go
Channel name can be missing
[mmc.git] / cmd / mmc / main.go
index 99e9f3aba5f48cdcf0cc08c4fe907d1a801b7d35..f3faa860dcd223a08dde9535eba9885da22cb6a9 100644 (file)
@@ -30,6 +30,7 @@ import (
        "os/exec"
        "os/signal"
        "path"
+       "sort"
        "strings"
        "syscall"
        "time"
@@ -39,14 +40,11 @@ import (
        "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
 )
@@ -61,9 +59,10 @@ func rewriteIfChanged(fn string, data string) {
 }
 
 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)
@@ -112,30 +111,18 @@ func main() {
        }
        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(
@@ -152,10 +139,23 @@ func main() {
                                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)
@@ -206,6 +206,7 @@ func main() {
                                if err != nil {
                                        continue
                                }
+                               dc = UsersDC[u.Id]
                                if dc == nil {
                                        dc, resp, err = c.CreateDirectChannel(me.Id, u.Id)
                                        if err != nil {
@@ -215,6 +216,7 @@ func main() {
                                                log.Println("CreateDirectChannel:", err)
                                                continue
                                        }
+                                       UsersDC[u.Id] = dc
                                        if DebugFd != nil {
                                                spew.Fdump(DebugFd, dc)
                                        }
@@ -227,6 +229,50 @@ func main() {
                }(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, "")
@@ -278,8 +324,8 @@ func main() {
                                        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)
@@ -294,7 +340,7 @@ func main() {
                                        for _, u := range users {
                                                fmt.Fprintf(fd, "%s\n", u.Username)
                                        }
-                                       if len(users) < PerPage {
+                                       if len(users) < mmc.PerPage {
                                                break
                                        }
                                }
@@ -326,17 +372,18 @@ func main() {
                }(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)
@@ -399,6 +446,7 @@ func main() {
                                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,
@@ -432,6 +480,7 @@ func main() {
                for {
                        select {
                        case <-t.C:
+                               updateUserStatus()
                                if time.Now().Before(LastSent.Add(time.Minute)) {
                                        continue
                                }
@@ -451,10 +500,10 @@ func main() {
                                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)]
@@ -471,7 +520,10 @@ func main() {
                                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)),
@@ -502,11 +554,11 @@ func main() {
                                                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: