Fix revUserId (messenger) and implement search (messenger only for now)

This commit is contained in:
Alex 2020-03-09 17:41:53 +01:00
parent 0d6fa02a78
commit f9e0c58f3c
7 changed files with 86 additions and 11 deletions

View File

@ -59,6 +59,9 @@ type Connector interface {
// Leave a channel // Leave a channel
Leave(roomId RoomID) Leave(roomId RoomID)
// Search for users
SearchForUsers(query string) ([]UserSearchResult, error)
// Send an event. Returns the ID of the created remote message. // Send an event. Returns the ID of the created remote message.
// This ID is used to deduplicate messages: if it comes back, it should have the same Id // This ID is used to deduplicate messages: if it comes back, it should have the same Id
// than the one returned here. // than the one returned here.
@ -153,6 +156,11 @@ type RoomInfo struct {
Picture SMediaObject `json:"picture"` Picture SMediaObject `json:"picture"`
} }
type UserSearchResult struct {
ID UserID `json:"id"`
DisplayName string `json:"display_name"`
}
type MediaObject interface { type MediaObject interface {
Filename() string Filename() string
Size() int64 Size() int64

View File

@ -49,6 +49,7 @@ const (
JOIN = "join" JOIN = "join"
INVITE = "invite" INVITE = "invite"
LEAVE = "leave" LEAVE = "leave"
SEARCH = "search"
SEND = "send" SEND = "send"
CLOSE = "close" CLOSE = "close"
@ -64,8 +65,9 @@ const (
// reply messages // reply messages
// ezbr -> external: all must wait for a reply! // ezbr -> external: all must wait for a reply!
// external -> ezbr: only CACHE_GET produces a reply // external -> ezbr: only CACHE_GET produces a reply
REP_OK = "rep_ok" REP_OK = "rep_ok"
REP_ERROR = "rep_error" REP_SEARCH_RESULTS = "rep_search_results"
REP_ERROR = "rep_error"
) )
// ---- // ----
@ -226,6 +228,16 @@ func (m *extMessageWithData) UnmarshalJSON(jj []byte) error {
} }
m.Data = &ev.Data m.Data = &ev.Data
return nil return nil
case REP_SEARCH_RESULTS:
var ev struct {
Data []UserSearchResult `json:"data"`
}
err := json.Unmarshal(jj, &ev)
if err != nil {
return err
}
m.Data = ev.Data
return nil
case JOINED, LEFT, CACHE_PUT, CACHE_GET, REP_OK, REP_ERROR: case JOINED, LEFT, CACHE_PUT, CACHE_GET, REP_OK, REP_ERROR:
return nil return nil
default: default:
@ -428,6 +440,19 @@ func (ext *External) Leave(room RoomID) {
} }
} }
func (ext *External) SearchForUsers(query string) ([]UserSearchResult, error) {
rep, err := ext.cmd(extMessage{
MsgType: SEARCH,
}, query)
if err != nil {
return nil, err
}
if rep.MsgType != REP_SEARCH_RESULTS {
return nil, fmt.Errorf("Invalid result type from external: %s", rep.MsgType)
}
return rep.Data.([]UserSearchResult), nil
}
func (ext *External) Send(event *Event) (string, error) { func (ext *External) Send(event *Event) (string, error) {
rep, err := ext.cmd(extMessage{ rep, err := ext.cmd(extMessage{
MsgType: SEND, MsgType: SEND,

View File

@ -198,6 +198,11 @@ func (irc *IRC) Leave(roomId RoomID) {
irc.conn.Cmd.Part(ch) irc.conn.Cmd.Part(ch)
} }
func (irc *IRC) SearchForUsers(query string) ([]UserSearchResult, error) {
// TODO
return nil, fmt.Errorf("Not implemented")
}
func (irc *IRC) Send(event *Event) (string, error) { func (irc *IRC) Send(event *Event) (string, error) {
if irc.conn == nil { if irc.conn == nil {
return "", fmt.Errorf("Not connected") return "", fmt.Errorf("Not connected")

View File

@ -253,6 +253,11 @@ func (mm *Mattermost) Leave(roomId RoomID) {
// Not supported? TODO // Not supported? TODO
} }
func (mm *Mattermost) SearchForUsers(query string) ([]UserSearchResult, error) {
// TODO
return nil, fmt.Errorf("Not implemented")
}
func (mm *Mattermost) Send(event *Event) (string, error) { func (mm *Mattermost) Send(event *Event) (string, error) {
post := &model.Post{ post := &model.Post{
Message: event.Text, Message: event.Text,

View File

@ -306,6 +306,11 @@ func (xm *XMPP) Leave(roomId RoomID) {
xm.conn.LeaveMUC(string(roomId)) xm.conn.LeaveMUC(string(roomId))
} }
func (xm *XMPP) SearchForUsers(query string) ([]UserSearchResult, error) {
// TODO: search roster
return nil, fmt.Errorf("Not implemented")
}
func (xm *XMPP) Send(event *Event) (string, error) { func (xm *XMPP) Send(event *Event) (string, error) {
if event.Attachments != nil && len(event.Attachments) > 0 { if event.Attachments != nil && len(event.Attachments) > 0 {
for _, at := range event.Attachments { for _, at := range event.Attachments {

29
external/messenger.py vendored
View File

@ -1,8 +1,6 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
# @FIXME: make revUserId work correctly (e.g.: talking to a contact not in your top 20 recent threads will fail) - could we do this with a search request?
# @FIXME: store the client pickle in the config automatically # @FIXME: store the client pickle in the config automatically
# @FIXME: add a way to search for users and initiate a discussion
import sys import sys
import json import json
@ -31,6 +29,7 @@ SET_ROOM_INFO = "set_room_info"
JOIN = "join" JOIN = "join"
INVITE = "invite" INVITE = "invite"
LEAVE = "leave" LEAVE = "leave"
SEARCH = "search"
SEND = "send" SEND = "send"
CLOSE = "close" CLOSE = "close"
@ -47,6 +46,7 @@ CACHE_GET = "cache_get"
# ezbr -> external: all must wait for a reply! # ezbr -> external: all must wait for a reply!
# external -> ezbr: only CACHE_GET produces a reply # external -> ezbr: only CACHE_GET produces a reply
REP_OK = "rep_ok" REP_OK = "rep_ok"
REP_SEARCH_RESULTS = "rep_search_results"
REP_ERROR = "rep_error" REP_ERROR = "rep_error"
# Event types # Event types
@ -168,13 +168,14 @@ class MessengerBridge:
return self.getUserId(user) return self.getUserId(user)
def revUserId(self, user_id): def revUserId(self, user_id):
if user_id in self.rev_uid: if user_id not in self.rev_uid:
return self.rev_uid[user_id] for user in self.client.searchForUsers(user_id):
else: self.getUserId(user)
# TODO this doesn't work always...
# we should try to find the api endpoint that resolves usernames ? if user_id not in self.rev_uid:
# or do a search request and try to find a user that has that username raise ValueError("User not found: {}".format(user_id))
return user_id
return self.rev_uid[user_id]
def getUserShortName(self, user): def getUserShortName(self, user):
if user.first_name != None: if user.first_name != None:
@ -277,6 +278,16 @@ class MessengerBridge:
uid = self.revUserId(cmd["user"]) uid = self.revUserId(cmd["user"])
self.client.addUsersToGroup([uid], cmd["room"]) self.client.addUsersToGroup([uid], cmd["room"])
elif ty == SEARCH:
users = self.client.searchForUsers(cmd["data"])
rep = []
for user in users:
rep.append({
"id": self.getUserId(user),
"display_name": user.name,
})
return {"_type": REP_SEARCH_RESULTS, "data": rep}
elif ty == SEND: elif ty == SEND:
event = cmd["data"] event = cmd["data"]
if event["type"] in [EVENT_MESSAGE, EVENT_ACTION]: if event["type"] in [EVENT_MESSAGE, EVENT_ACTION]:

View File

@ -228,6 +228,7 @@ func handleSystemMessage(mxid string, msg string) {
ezbrSystemSend(mxid, "- accounts: list accounts") ezbrSystemSend(mxid, "- accounts: list accounts")
ezbrSystemSend(mxid, "- join <protocol or account> <room id>: join public chat room") ezbrSystemSend(mxid, "- join <protocol or account> <room id>: join public chat room")
ezbrSystemSend(mxid, "- talk <protocol or account> <user id>: open private conversation to contact") ezbrSystemSend(mxid, "- talk <protocol or account> <user id>: open private conversation to contact")
ezbrSystemSend(mxid, "- search <protocol or account> <name>: search for users by name")
case "list", "account", "accounts": case "list", "account", "accounts":
one := false one := false
if accts, ok := registeredAccounts[mxid]; ok { if accts, ok := registeredAccounts[mxid]; ok {
@ -271,6 +272,21 @@ func handleSystemMessage(mxid string, msg string) {
} else { } else {
ezbrSystemSendf(mxid, "No account with name or using protocol %s", cmd[1]) ezbrSystemSendf(mxid, "No account with name or using protocol %s", cmd[1])
} }
case "search":
account := findAccount(mxid, cmd[1])
if account != nil {
rep, err := account.Conn.SearchForUsers(cmd[2])
if err != nil {
ezbrSystemSendf(mxid, "Search error: %s", err)
} else {
ezbrSystemSendf(mxid, "%d users found", len(rep))
for i, user := range rep {
ezbrSystemSendf(mxid, "- %s (%s)", i+1, user.DisplayName, user.ID)
}
}
} else {
ezbrSystemSendf(mxid, "No account with name or using protocol %s", cmd[1])
}
default: default:
ezbrSystemSend(mxid, "Unrecognized command. Type `help` if you need some help!") ezbrSystemSend(mxid, "Unrecognized command. Type `help` if you need some help!")
} }