Message sending

This commit is contained in:
Andrew Ferrazzutti 2021-02-20 03:47:26 -05:00
parent fc05a8f832
commit fdd3a1d6b7
3 changed files with 92 additions and 47 deletions

View File

@ -127,10 +127,14 @@ class Portal(DBPortal, BasePortal):
# TODO media # TODO media
return return
message_id = await sender.client.send(self.chat_id, text) message_id = await sender.client.send(self.chat_id, text)
# TODO Handle message-send timeouts better
if message_id != -1:
msg = DBMessage(mxid=event_id, mx_room=self.mxid, mid=message_id, chat_id=self.chat_id) msg = DBMessage(mxid=event_id, mx_room=self.mxid, mid=message_id, chat_id=self.chat_id)
await msg.insert() await msg.insert()
await self._send_delivery_receipt(event_id) await self._send_delivery_receipt(event_id)
self.log.debug(f"Handled Matrix message {event_id} -> {message_id}") self.log.debug(f"Handled Matrix message {event_id} -> {message_id}")
else:
self.log.warning(f"Handled Matrix message {event_id} -> {message_id}")
async def handle_matrix_leave(self, user: 'u.User') -> None: async def handle_matrix_leave(self, user: 'u.User') -> None:
if self.is_direct: if self.is_direct:
@ -355,20 +359,20 @@ class Portal(DBPortal, BasePortal):
"type": "m.room.related_groups", "type": "m.room.related_groups",
"content": {"groups": [self.config["appservice.community_id"]]}, "content": {"groups": [self.config["appservice.community_id"]]},
}) })
initial_state.append({ #initial_state.append({
"type": str(EventType.ROOM_POWER_LEVELS), # "type": str(EventType.ROOM_POWER_LEVELS),
"content": { # "content": {
"users": { # "users": {
self.az.bot_mxid: 100, # self.az.bot_mxid: 100,
self.main_intent.mxid: 9001, # self.main_intent.mxid: 100,
}, # },
"events": {}, # "events": {},
"events_default": 100, # "events_default": 100,
"state_default": 50, # "state_default": 50,
"invite": 50, # "invite": 50,
"redact": 0 # "redact": 0
} # }
}) #})
# We lock backfill lock here so any messages that come between the room being created # We lock backfill lock here so any messages that come between the room being created
# and the initial backfill finishing wouldn't be bridged before the backfill messages. # and the initial backfill finishing wouldn't be bridged before the backfill messages.

View File

@ -135,29 +135,51 @@ class MautrixController {
return messageData return messageData
} }
waitForMessage(elem) {
return new Promise(resolve => { promiseOwnMessage() {
let msgID = null let observer
const observer = new MutationObserver(changes => { let msgID = -1
let resolve
let reject
const invisibleTimeCallback = (changes) => {
for (const change of changes) { for (const change of changes) {
if (change.type === "attributes" && change.attributeName === "msg-id") { for (const addedNode of change.addedNodes) {
msgID = +elem.getAttribute("msg-id") if (addedNode.classList.contains("mdRGT07Own")) {
window.__mautrixReceiveMessageID(msgID) const timeElement = addedNode.querySelector("time.MdNonDisp")
} else if (change.type === "childList" if (timeElement) {
&& change.target.nodeName.toLowerCase() === "mws-relative-timestamp" msgID = addedNode.getAttribute("data-local-id")
&& change.addedNodes.length > 0
&& change.addedNodes[0] instanceof Text) {
resolve(msgID)
observer.disconnect() observer.disconnect()
observer = new MutationObserver(visibleTimeCallback)
observer.observe(timeElement, { attributes: true, attributeFilter: ["class"] })
return return
} }
} }
}) }
observer.observe(elem, { attributes: true, attributeFilter: ["msg-id"] }) }
observer.observe(elem.querySelector("mws-message-status"), { }
childList: true,
subtree: true, const visibleTimeCallback = (changes) => {
}) for (const change of changes) {
if (!change.target.classList.contains("MdNonDisp")) {
window.__mautrixReceiveMessageID(msgID)
observer.disconnect()
resolve(msgID)
return
}
}
}
observer = new MutationObserver(invisibleTimeCallback)
observer.observe(
document.querySelector("#_chat_room_msg_list"),
{ childList: true })
return new Promise((realResolve, realReject) => {
resolve = realResolve
reject = realReject
// TODO Handle a timeout better than this
setTimeout(() => { observer.disconnect(); reject() }, 10000)
}) })
} }

View File

@ -93,9 +93,9 @@ export default class MessagesPuppeteer {
await this.page.exposeFunction("__mautrixSendEmailCredentials", this._sendEmailCredentials.bind(this)) await this.page.exposeFunction("__mautrixSendEmailCredentials", this._sendEmailCredentials.bind(this))
await this.page.exposeFunction("__mautrixReceivePIN", this._receivePIN.bind(this)) await this.page.exposeFunction("__mautrixReceivePIN", this._receivePIN.bind(this))
await this.page.exposeFunction("__mautrixExpiry", this._receiveExpiry.bind(this)) await this.page.exposeFunction("__mautrixExpiry", this._receiveExpiry.bind(this))
/* TODO
await this.page.exposeFunction("__mautrixReceiveMessageID", await this.page.exposeFunction("__mautrixReceiveMessageID",
id => this.sentMessageIDs.add(id)) id => this.sentMessageIDs.add(id))
/* TODO
await this.page.exposeFunction("__mautrixReceiveChanges", await this.page.exposeFunction("__mautrixReceiveChanges",
this._receiveChatListChanges.bind(this)) this._receiveChatListChanges.bind(this))
await this.page.exposeFunction("__chronoParseDate", chrono.parseDate) await this.page.exposeFunction("__chronoParseDate", chrono.parseDate)
@ -469,16 +469,35 @@ export default class MessagesPuppeteer {
} }
} }
// TODO Catch "An error has occurred" dialog
// Selector is just "dialog", then "button"
// Child of "#layer_contents"
// Always present, just made visible via classes
async _sendMessageUnsafe(chatID, text) { async _sendMessageUnsafe(chatID, text) {
await this._switchChatUnsafe(chatID) await this._switchChatUnsafe(chatID)
await this.page.focus("mws-message-compose .input-box textarea") const promise = this.page.evaluate(
await this.page.keyboard.type(text) () => window.__mautrixController.promiseOwnMessage())
await this.page.click(".compose-container > mws-message-send-button > button")
const id = await this.page.$eval("mws-message-wrapper.outgoing[msg-id^='tmp_']", const input = await this.page.$("#_chat_room_input")
elem => window.__mautrixController.waitForMessage(elem)) await input.click()
this.log("Successfully sent message", id, "to", chatID) await input.type(text)
await input.press("Enter")
try {
this.log("Waiting for message to be sent")
const id = await promise
this.log(`Successfully sent message ${id} to ${chatID}`)
return id return id
} catch (e) {
// TODO Handle a timeout better than this
this.error(`Timed out waiting for message to ${chatID}`)
return -1
} }
}
// TODO Inbound read receipts
// Probably use a MutationObserver mapped to msgID
async _getMessagesUnsafe(id, minID = 0) { async _getMessagesUnsafe(id, minID = 0) {
/* TODO Also handle "decrypting" state /* TODO Also handle "decrypting" state