Message sending

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

View File

@ -127,10 +127,14 @@ class Portal(DBPortal, BasePortal):
# TODO media
return
message_id = await sender.client.send(self.chat_id, text)
msg = DBMessage(mxid=event_id, mx_room=self.mxid, mid=message_id, chat_id=self.chat_id)
await msg.insert()
await self._send_delivery_receipt(event_id)
self.log.debug(f"Handled Matrix message {event_id} -> {message_id}")
# 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)
await msg.insert()
await self._send_delivery_receipt(event_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:
if self.is_direct:
@ -355,20 +359,20 @@ class Portal(DBPortal, BasePortal):
"type": "m.room.related_groups",
"content": {"groups": [self.config["appservice.community_id"]]},
})
initial_state.append({
"type": str(EventType.ROOM_POWER_LEVELS),
"content": {
"users": {
self.az.bot_mxid: 100,
self.main_intent.mxid: 9001,
},
"events": {},
"events_default": 100,
"state_default": 50,
"invite": 50,
"redact": 0
}
})
#initial_state.append({
# "type": str(EventType.ROOM_POWER_LEVELS),
# "content": {
# "users": {
# self.az.bot_mxid: 100,
# self.main_intent.mxid: 100,
# },
# "events": {},
# "events_default": 100,
# "state_default": 50,
# "invite": 50,
# "redact": 0
# }
#})
# 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.

View File

@ -135,29 +135,51 @@ class MautrixController {
return messageData
}
waitForMessage(elem) {
return new Promise(resolve => {
let msgID = null
const observer = new MutationObserver(changes => {
for (const change of changes) {
if (change.type === "attributes" && change.attributeName === "msg-id") {
msgID = +elem.getAttribute("msg-id")
window.__mautrixReceiveMessageID(msgID)
} else if (change.type === "childList"
&& change.target.nodeName.toLowerCase() === "mws-relative-timestamp"
&& change.addedNodes.length > 0
&& change.addedNodes[0] instanceof Text) {
resolve(msgID)
observer.disconnect()
return
promiseOwnMessage() {
let observer
let msgID = -1
let resolve
let reject
const invisibleTimeCallback = (changes) => {
for (const change of changes) {
for (const addedNode of change.addedNodes) {
if (addedNode.classList.contains("mdRGT07Own")) {
const timeElement = addedNode.querySelector("time.MdNonDisp")
if (timeElement) {
msgID = addedNode.getAttribute("data-local-id")
observer.disconnect()
observer = new MutationObserver(visibleTimeCallback)
observer.observe(timeElement, { attributes: true, attributeFilter: ["class"] })
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("__mautrixReceivePIN", this._receivePIN.bind(this))
await this.page.exposeFunction("__mautrixExpiry", this._receiveExpiry.bind(this))
/* TODO
await this.page.exposeFunction("__mautrixReceiveMessageID",
id => this.sentMessageIDs.add(id))
/* TODO
await this.page.exposeFunction("__mautrixReceiveChanges",
this._receiveChatListChanges.bind(this))
await this.page.exposeFunction("__chronoParseDate", chrono.parseDate)
@ -469,17 +469,36 @@ 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) {
await this._switchChatUnsafe(chatID)
await this.page.focus("mws-message-compose .input-box textarea")
await this.page.keyboard.type(text)
await this.page.click(".compose-container > mws-message-send-button > button")
const id = await this.page.$eval("mws-message-wrapper.outgoing[msg-id^='tmp_']",
elem => window.__mautrixController.waitForMessage(elem))
this.log("Successfully sent message", id, "to", chatID)
return id
const promise = this.page.evaluate(
() => window.__mautrixController.promiseOwnMessage())
const input = await this.page.$("#_chat_room_input")
await input.click()
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
} 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) {
/* TODO Also handle "decrypting" state
await this._switchChatUnsafe(id)