Kinda work dms

This commit is contained in:
Karmanyaah Malhotra 2021-04-27 22:49:01 -04:00
parent b35a6be635
commit 0ff534c2df
7 changed files with 155 additions and 106 deletions

View File

@ -654,7 +654,7 @@ func (handler *CommandHandler) CommandHelp(ce *CommandEvent) {
cmdPrefix + cmdSyncHelp, cmdPrefix + cmdSyncHelp,
cmdPrefix + cmdListHelp, cmdPrefix + cmdListHelp,
cmdPrefix + cmdOpenHelp, cmdPrefix + cmdOpenHelp,
// cmdPrefix + cmdPMHelp, cmdPrefix + cmdPMHelp,
// cmdPrefix + cmdInviteLinkHelp, // cmdPrefix + cmdInviteLinkHelp,
// cmdPrefix + cmdJoinHelp, // cmdPrefix + cmdJoinHelp,
// cmdPrefix + cmdCreateHelp, // cmdPrefix + cmdCreateHelp,
@ -762,21 +762,11 @@ func (handler *CommandHandler) CommandDeleteAllPortals(ce *CommandEvent) {
}() }()
} }
const cmdListHelp = `list groups [page] [items per page] - Get a list of all contacts and groups.` const cmdListHelp = `list <contacts|groups> [page] [items per page] - Get a list of all contacts and groups.`
//<contacts|groups> //TODO
func formatContacts(contacts bool, input map[string]string) (result []string) { func formatContacts(contacts bool, input map[string]string) (result []string) {
for jid, contact := range input { for jid, contact := range input {
if strings.HasSuffix(jid, whatsappExt.NewUserSuffix) != contacts { result = append(result, fmt.Sprintf("* %s - `%s`", contact, jid))
continue
}
if contacts {
result = append(result, fmt.Sprintf("* %s / %s - `%s`", contact, jid))
} else {
result = append(result, fmt.Sprintf("* %s - `%s`", contact, jid))
}
} }
sort.Sort(sort.StringSlice(result)) sort.Sort(sort.StringSlice(result))
return return
@ -886,44 +876,36 @@ func (handler *CommandHandler) CommandOpen(ce *CommandEvent) {
_, _ = portal.MainIntent().InviteUser(portal.MXID, &mautrix.ReqInviteUser{UserID: user.MXID}) _, _ = portal.MainIntent().InviteUser(portal.MXID, &mautrix.ReqInviteUser{UserID: user.MXID})
} }
const cmdPMHelp = `pm [--force] <_international phone number_> - Open a private chat with the given phone number.` const cmdPMHelp = `pm - To direct message someone already in a shared group start a direct chat with them in Matrix`
func (handler *CommandHandler) CommandPM(ce *CommandEvent) { func (handler *CommandHandler) CommandPM(ce *CommandEvent) {
// if len(ce.Args) == 0 { ce.Reply(fmt.Sprintf("**DEPRECATED COMMAND:** `%s`", cmdPMHelp))
// ce.Reply("**Usage:** `pm [--force] <international phone number>`") return
// return if len(ce.Args) == 0 {
// } ce.Reply(fmt.Sprintf("**DEPRECATED COMMAND:** `%s`", cmdPMHelp))
return
}
// force := ce.Args[0] == "--force" // force := ce.Args[0] == "--force"
// if force { // if force {
// ce.Args = ce.Args[1:] // ce.Args = ce.Args[1:]
// } // }
//
// user := ce.User // user := ce.User
//
// number := strings.Join(ce.Args, "") // jid := ce.Args[0]
// if number[0] == '+' { //
// number = number[1:] // handler.log.Debugln("Importing", jid, "for", user.MXID)
// } //
// for _, char := range number { // contact, ok := user.Conn.Store.Contacts[jid]
// if char < '0' || char > '9' { // if !ok {
// ce.Reply("Invalid phone number.") // if !force {
// return // ce.Reply("Phone number not found in contacts. Try syncing contacts with `sync` first. " +
// } // "To create a portal anyway, use `pm --force <number>`.")
// } // return
// jid := number + whatsappExt.NewUserSuffix // }
// contact = whatsapp.Contact{Jid: jid}
// handler.log.Debugln("Importing", jid, "for", user) // }
// contact, ok := user.Conn.Store.Contacts[jid]
// if !ok {
// if !force {
// ce.Reply("Phone number not found in contacts. Try syncing contacts with `sync` first. " +
// "To create a portal anyway, use `pm --force <number>`.")
// return
// }
// contact = whatsapp.Contact{Jid: jid}
// }
// puppet := user.bridge.GetPuppetByJID(contact.Jid) // puppet := user.bridge.GetPuppetByJID(contact.Jid)
// puppet.Sync(user, contact) // puppet.Sync(user, contact)
// portal := user.bridge.GetPortalByJID(database.NewPortalKey(contact.Jid, user.JID)) // portal := user.bridge.GetPortalByJID(database.NewPortalKey(contact.Jid, user.JID))

View File

@ -57,7 +57,7 @@ func New(dbType string, uri string, baseLog log.Logger) (*Database, error) {
} }
gdb, err := gorm.Open(conn, &gorm.Config{ gdb, err := gorm.Open(conn, &gorm.Config{
//Logger: logger.Default.LogMode(logger.Info), // Logger: logger.Default.LogMode(logger.Info),
// Logger: baseLog, // Logger: baseLog,
DisableForeignKeyConstraintWhenMigrating: true, DisableForeignKeyConstraintWhenMigrating: true,

View File

@ -24,6 +24,8 @@ import (
"github.com/karmanyaahm/matrix-groupme-go/types" "github.com/karmanyaahm/matrix-groupme-go/types"
) )
// JID is the puppet or the group
// Receiver is the "Other Person" in a DM or the group itself in a group
type PortalKey struct { type PortalKey struct {
JID types.GroupMeID `gorm:"primaryKey"` JID types.GroupMeID `gorm:"primaryKey"`
Receiver types.GroupMeID `gorm:"primaryKey"` Receiver types.GroupMeID `gorm:"primaryKey"`
@ -50,6 +52,11 @@ func (key PortalKey) String() string {
return key.JID + "-" + key.Receiver return key.JID + "-" + key.Receiver
} }
func (key PortalKey) IsPrivate() bool {
//also see FindPrivateChats
return key.JID != key.Receiver
}
type PortalQuery struct { type PortalQuery struct {
db *Database db *Database
log log.Logger log log.Logger
@ -82,8 +89,8 @@ func (pq *PortalQuery) GetAllByJID(jid types.GroupMeID) []*Portal {
} }
func (pq *PortalQuery) FindPrivateChats(receiver types.GroupMeID) []*Portal { func (pq *PortalQuery) FindPrivateChats(receiver types.GroupMeID) []*Portal {
print("aaaaaaaaaaaaaaaaaa wrong portal stuff") //also see IsPrivate
return pq.getAll(pq.db.DB.Where("receiver = ? AND jid LIKE '%@s.whatsapp.net'", receiver)) return pq.getAll(pq.db.DB.Where("receiver = ? AND receiver <> jid", receiver))
} }

View File

@ -178,8 +178,8 @@ type UserPortal struct {
func (user *User) SetPortalKeys(newKeys []PortalKeyWithMeta) error { func (user *User) SetPortalKeys(newKeys []PortalKeyWithMeta) error {
tx := user.db.Begin() tx := user.db.Begin()
ans := tx.Where("user_jid = ?", *user.jidPtr()).Delete(&UserPortal{}) ans := tx.Where("user_jid = ?", *user.jidPtr()).Delete(UserPortal{})
print("make sure all are deletede")
if ans.Error != nil { if ans.Error != nil {
_ = tx.Rollback() _ = tx.Rollback()
return ans.Error return ans.Error

View File

@ -25,30 +25,61 @@ func (c Client) IndexAllGroups() ([]*groupme.Group, error) {
}) })
} }
func (c Client) LoadMessagesAfter(groupID, lastMessageID string, lastMessageFromMe bool, num int) ([]*groupme.Message, error) { func (c Client) IndexAllChats() ([]*groupme.Chat, error) {
//TODO: limit max 100 return c.IndexChats(context.TODO(), &groupme.IndexChatsQuery{
i, e := c.IndexMessages(context.TODO(), groupme.ID(groupID), &groupme.IndexMessagesQuery{ PerPage: 100, //TODO?
AfterID: groupme.ID(lastMessageID),
Limit: num,
}) })
if e != nil {
return nil, e
}
return i.Messages, nil
} }
func (c Client) LoadMessagesBefore(groupID, lastMessageID string, num int) ([]*groupme.Message, error) { func (c Client) LoadMessagesAfter(groupID, lastMessageID string, lastMessageFromMe bool, private bool) ([]*groupme.Message, error) {
//TODO: limit max 100 if private {
i, e := c.IndexMessages(context.TODO(), groupme.ID(groupID), &groupme.IndexMessagesQuery{ i, e := c.IndexDirectMessages(context.TODO(), groupID, &groupme.IndexDirectMessagesQuery{
BeforeID: groupme.ID(lastMessageID), SinceID: groupme.ID(lastMessageID),
Limit: num, //Limit: num,
}) })
//fmt.Println(groupID, lastMessageID, num, i.Count, e) //fmt.Println(groupID, lastMessageID, num, i.Count, e)
if e != nil { if e != nil {
return nil, e return nil, e
}
return i.Messages, nil
} else {
i, e := c.IndexMessages(context.TODO(), groupme.ID(groupID), &groupme.IndexMessagesQuery{
AfterID: groupme.ID(lastMessageID),
//20 for consistency with dms
Limit: 20,
})
//fmt.Println(groupID, lastMessageID, num, i.Count, e)
if e != nil {
return nil, e
}
return i.Messages, nil
}
}
func (c Client) LoadMessagesBefore(groupID, lastMessageID string, private bool) ([]*groupme.Message, error) {
if private {
i, e := c.IndexDirectMessages(context.TODO(), groupID, &groupme.IndexDirectMessagesQuery{
BeforeID: groupme.ID(lastMessageID),
//Limit: num,
})
//fmt.Println(groupID, lastMessageID, num, i.Count, e)
if e != nil {
return nil, e
}
return i.Messages, nil
} else {
//TODO: limit max 100
i, e := c.IndexMessages(context.TODO(), groupme.ID(groupID), &groupme.IndexMessagesQuery{
BeforeID: groupme.ID(lastMessageID),
//20 for consistency with dms
Limit: 20,
})
//fmt.Println(groupID, lastMessageID, num, i.Count, e)
if e != nil {
return nil, e
}
return i.Messages, nil
} }
return i.Messages, nil
} }
func (c *Client) RemoveFromGroup(uid, groupID types.GroupMeID) error { func (c *Client) RemoveFromGroup(uid, groupID types.GroupMeID) error {

View File

@ -186,7 +186,6 @@ type Portal struct {
messages chan PortalMessage messages chan PortalMessage
isPrivate *bool
hasRelaybot *bool hasRelaybot *bool
} }
@ -549,7 +548,12 @@ func (portal *Portal) Sync(user *User, group groupme.Group) {
portal.hasRelaybot = &yes portal.hasRelaybot = &yes
} }
err := user.Conn.SubscribeToGroup(context.TODO(), group.ID, user.Token) var err error
if portal.IsPrivateChat() {
err = user.Conn.SubscribeToUser(context.TODO(), groupme.ID(portal.Key.JID), user.Token)
} else {
err = user.Conn.SubscribeToGroup(context.TODO(), groupme.ID(portal.Key.JID), user.Token)
}
if err != nil { if err != nil {
portal.log.Errorln("Subscribing failed, live metadata updates won't work", err) portal.log.Errorln("Subscribing failed, live metadata updates won't work", err)
} }
@ -698,7 +702,7 @@ func (portal *Portal) BackfillHistory(user *User, lastMessageTime uint64) error
portal.log.Infoln("Backfilling history since", lastMessageID, "for", user.MXID) portal.log.Infoln("Backfilling history since", lastMessageID, "for", user.MXID)
for len(lastMessageID) > 0 { for len(lastMessageID) > 0 {
portal.log.Debugln("Fetching 50 messages of history after", lastMessageID) portal.log.Debugln("Fetching 50 messages of history after", lastMessageID)
messages, err := user.Client.LoadMessagesAfter(portal.Key.JID, lastMessageID, lastMessageFromMe, 50) messages, err := user.Client.LoadMessagesAfter(portal.Key.JID, lastMessageID, lastMessageFromMe, portal.IsPrivateChat())
if err != nil { if err != nil {
return err return err
} }
@ -799,12 +803,12 @@ func (portal *Portal) FillInitialHistory(user *User) error {
before := "" before := ""
chunkNum := 1 chunkNum := 1
for n > 0 { for n > 0 {
count := 50 count := 20
if n < count { if n < count {
count = n count = n
} }
portal.log.Debugfln("Fetching chunk %d (%d messages / %d cap) before message %s", chunkNum, count, n, before) portal.log.Debugfln("Fetching chunk %d (%d messages / %d cap) before message %s", chunkNum, count, n, before)
chunk, err := user.Client.LoadMessagesBefore(portal.Key.JID, before, count) chunk, err := user.Client.LoadMessagesBefore(portal.Key.JID, before, portal.IsPrivateChat())
if err != nil { if err != nil {
return err return err
} }
@ -1062,11 +1066,7 @@ func (portal *Portal) CreateMatrixRoom(user *User) error {
} }
func (portal *Portal) IsPrivateChat() bool { func (portal *Portal) IsPrivateChat() bool {
if portal.isPrivate == nil { return portal.Key.IsPrivate()
val := strings.HasSuffix(portal.Key.JID, whatsappExt.NewUserSuffix)
portal.isPrivate = &val
}
return *portal.isPrivate
} }
func (portal *Portal) HasRelaybot() bool { func (portal *Portal) HasRelaybot() bool {

75
user.go
View File

@ -378,9 +378,15 @@ func (user *User) Login(ce *CommandEvent) {
type Chat struct { type Chat struct {
Portal *Portal Portal *Portal
LastMessageTime uint64 LastMessageTime uint64
Group groupme.Group Group *groupme.Group
DM *groupme.Chat
} }
////returns private chat assuming one of group or dm have been initialized properly
//func (c Chat) IsPrivate() bool {
// return c.Group == nil
//}
type ChatList []Chat type ChatList []Chat
func (cl ChatList) Len() int { func (cl ChatList) Len() int {
@ -536,44 +542,67 @@ func (user *User) HandleChatList() {
chatMap := make(map[string]groupme.Group) chatMap := make(map[string]groupme.Group)
chats, err := user.Client.IndexAllGroups() chats, err := user.Client.IndexAllGroups()
if err != nil { if err != nil {
log.Fatal(err) //TODO: handle user.log.Errorln("chat sync error", err) //TODO: handle
return
} }
for _, chat := range chats { for _, chat := range chats {
chatMap[chat.ID.String()] = *chat chatMap[chat.ID.String()] = *chat
} }
user.chatListReceived <- struct{}{}
user.log.Infoln("Chat list received")
user.GroupList = chatMap user.GroupList = chatMap
go user.syncPortals(chatMap, false)
dmMap := make(map[string]groupme.Chat)
dms, err := user.Client.IndexAllChats()
if err != nil {
user.log.Errorln("chat sync error", err) //TODO: handle
return
}
for _, dm := range dms {
dmMap[dm.OtherUser.ID.String()] = *dm
}
user.ChatList = dmMap
user.log.Infoln("Chat list received")
user.chatListReceived <- struct{}{}
go user.syncPortals(false)
} }
func (user *User) syncPortals(chatMap map[string]groupme.Group, createAll bool) { func (user *User) syncPortals(createAll bool) {
if chatMap == nil {
// chatMap = user.Conn.Store.Chats
log.Fatal("chatmap nil major oops")
}
user.log.Infoln("Reading chat list") user.log.Infoln("Reading chat list")
chats := make(ChatList, 0, len(chatMap)) chats := make(ChatList, 0, len(user.GroupList)+len(user.ChatList))
existingKeys := user.GetInCommunityMap() existingKeys := user.GetInCommunityMap()
portalKeys := make([]database.PortalKeyWithMeta, 0, len(chatMap)) portalKeys := make([]database.PortalKeyWithMeta, 0, cap(chats))
for _, chat := range chatMap {
portal := user.bridge.GetPortalByJID(database.GroupPortalKey(chat.ID.String())) for _, group := range user.GroupList {
portal := user.bridge.GetPortalByJID(database.GroupPortalKey(group.ID.String()))
chats = append(chats, Chat{ chats = append(chats, Chat{
Portal: portal, Portal: portal,
LastMessageTime: uint64(chat.UpdatedAt.ToTime().Unix()), LastMessageTime: uint64(group.UpdatedAt.ToTime().Unix()),
Group: chat, Group: &group,
}) })
}
for _, dm := range user.ChatList {
portal := user.bridge.GetPortalByJID(database.NewPortalKey(dm.OtherUser.ID.String(), user.JID))
chats = append(chats, Chat{
Portal: portal,
LastMessageTime: uint64(dm.UpdatedAt.ToTime().Unix()),
DM: &dm,
})
}
for _, chat := range chats {
var inCommunity, ok bool var inCommunity, ok bool
if inCommunity, ok = existingKeys[portal.Key]; !ok || !inCommunity { if inCommunity, ok = existingKeys[chat.Portal.Key]; !ok || !inCommunity {
inCommunity = user.addPortalToCommunity(portal) inCommunity = user.addPortalToCommunity(chat.Portal)
if portal.IsPrivateChat() { if chat.Portal.IsPrivateChat() {
puppet := user.bridge.GetPuppetByJID(portal.Key.JID) puppet := user.bridge.GetPuppetByJID(chat.Portal.Key.JID)
user.addPuppetToCommunity(puppet) user.addPuppetToCommunity(puppet)
} }
} }
portalKeys = append(portalKeys, database.PortalKeyWithMeta{PortalKey: portal.Key, InCommunity: inCommunity}) portalKeys = append(portalKeys, database.PortalKeyWithMeta{PortalKey: chat.Portal.Key, InCommunity: inCommunity})
} }
user.log.Infoln("Read chat list, updating user-portal mapping") user.log.Infoln("Read chat list, updating user-portal mapping")
@ -594,11 +623,11 @@ func (user *User) syncPortals(chatMap map[string]groupme.Group, createAll bool)
if chat.LastMessageTime+user.bridge.Config.Bridge.SyncChatMaxAge < now { if chat.LastMessageTime+user.bridge.Config.Bridge.SyncChatMaxAge < now {
break break
} }
wg.Add(1)
go func(chat Chat) { go func(chat Chat) {
wg.Add(1)
create := (chat.LastMessageTime >= user.LastConnection && user.LastConnection > 0) || i < limit create := (chat.LastMessageTime >= user.LastConnection && user.LastConnection > 0) || i < limit
if len(chat.Portal.MXID) > 0 || create || createAll { if len(chat.Portal.MXID) > 0 || create || createAll {
chat.Portal.Sync(user, chat.Group) chat.Portal.Sync(user, *chat.Group)
err := chat.Portal.BackfillHistory(user, chat.LastMessageTime) err := chat.Portal.BackfillHistory(user, chat.LastMessageTime)
if err != nil { if err != nil {
chat.Portal.log.Errorln("Error backfilling history:", err) chat.Portal.log.Errorln("Error backfilling history:", err)