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(roomId RoomID)
// Search for users
SearchForUsers(query string) ([]UserSearchResult, error)
// 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
// than the one returned here.
@ -153,6 +156,11 @@ type RoomInfo struct {
Picture SMediaObject `json:"picture"`
}
type UserSearchResult struct {
ID UserID `json:"id"`
DisplayName string `json:"display_name"`
}
type MediaObject interface {
Filename() string
Size() int64

View File

@ -49,6 +49,7 @@ const (
JOIN = "join"
INVITE = "invite"
LEAVE = "leave"
SEARCH = "search"
SEND = "send"
CLOSE = "close"
@ -64,8 +65,9 @@ const (
// reply messages
// ezbr -> external: all must wait for a reply!
// external -> ezbr: only CACHE_GET produces a reply
REP_OK = "rep_ok"
REP_ERROR = "rep_error"
REP_OK = "rep_ok"
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
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:
return nil
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) {
rep, err := ext.cmd(extMessage{
MsgType: SEND,

View File

@ -198,6 +198,11 @@ func (irc *IRC) Leave(roomId RoomID) {
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) {
if irc.conn == nil {
return "", fmt.Errorf("Not connected")

View File

@ -253,6 +253,11 @@ func (mm *Mattermost) Leave(roomId RoomID) {
// 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) {
post := &model.Post{
Message: event.Text,

View File

@ -306,6 +306,11 @@ func (xm *XMPP) Leave(roomId 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) {
if event.Attachments != nil && len(event.Attachments) > 0 {
for _, at := range event.Attachments {

29
external/messenger.py vendored
View File

@ -1,8 +1,6 @@
#!/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: add a way to search for users and initiate a discussion
import sys
import json
@ -31,6 +29,7 @@ SET_ROOM_INFO = "set_room_info"
JOIN = "join"
INVITE = "invite"
LEAVE = "leave"
SEARCH = "search"
SEND = "send"
CLOSE = "close"
@ -47,6 +46,7 @@ CACHE_GET = "cache_get"
# ezbr -> external: all must wait for a reply!
# external -> ezbr: only CACHE_GET produces a reply
REP_OK = "rep_ok"
REP_SEARCH_RESULTS = "rep_search_results"
REP_ERROR = "rep_error"
# Event types
@ -168,13 +168,14 @@ class MessengerBridge:
return self.getUserId(user)
def revUserId(self, user_id):
if user_id in self.rev_uid:
return self.rev_uid[user_id]
else:
# TODO this doesn't work always...
# we should try to find the api endpoint that resolves usernames ?
# or do a search request and try to find a user that has that username
return user_id
if user_id not in self.rev_uid:
for user in self.client.searchForUsers(user_id):
self.getUserId(user)
if user_id not in self.rev_uid:
raise ValueError("User not found: {}".format(user_id))
return self.rev_uid[user_id]
def getUserShortName(self, user):
if user.first_name != None:
@ -277,6 +278,16 @@ class MessengerBridge:
uid = self.revUserId(cmd["user"])
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:
event = cmd["data"]
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, "- 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, "- search <protocol or account> <name>: search for users by name")
case "list", "account", "accounts":
one := false
if accts, ok := registeredAccounts[mxid]; ok {
@ -271,6 +272,21 @@ func handleSystemMessage(mxid string, msg string) {
} else {
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:
ezbrSystemSend(mxid, "Unrecognized command. Type `help` if you need some help!")
}