Improve and/or break things

This commit is contained in:
Tulir Asokan
2017-11-15 22:43:55 +02:00
parent 667421c727
commit eb2de79a4b
7 changed files with 117 additions and 39 deletions
+2
View File
@@ -19,6 +19,8 @@ appservice:
bridge: bridge:
# ${ID} is replaced with the user ID of the Telegram user. # ${ID} is replaced with the user ID of the Telegram user.
username_template: "telegram_${ID}" username_template: "telegram_${ID}"
# ${DISPLAYNAME} is replaced with the display name of the Telegram user.
displayname_template: "${DISPLAYNAME} (Telegram)"
bot_username: telegrambot bot_username: telegrambot
# The displayname to set to the bot automatically. # The displayname to set to the bot automatically.
bot_displayname: Telegram Bridge bot_displayname: Telegram Bridge
+21 -13
View File
@@ -56,6 +56,7 @@ class MautrixTelegram {
const user = MatrixUser.fromEntry(this, entry) const user = MatrixUser.fromEntry(this, entry)
this.matrixUsersByID.set(entry.id, user) this.matrixUsersByID.set(entry.id, user)
} }
// FIXME this doesn't work for setting the displayname of the bot.
// .then(() => // .then(() =>
// this.botIntent.setDisplayName(this.config.bridge.bot_displayname)) // this.botIntent.setDisplayName(this.config.bridge.bot_displayname))
} }
@@ -198,13 +199,13 @@ class MautrixTelegram {
putRoom(room) { putRoom(room) {
const entry = room.toEntry() const entry = room.toEntry()
return this.bridge.getUserStore().upsert({ return this.bridge.getRoomStore().upsert({
type: entry.type, type: entry.type,
id: entry.id, id: entry.id,
}, entry) }, entry)
} }
handleMatrixEvent(evt) { async handleMatrixEvent(evt) {
const asBotID = this.bridge.getBot().getUserId() const asBotID = this.bridge.getBot().getUserId()
if (evt.type === "m.room.member" && evt.state_key === asBotID) { if (evt.type === "m.room.member" && evt.state_key === asBotID) {
if (evt.content.membership === "invite") { if (evt.content.membership === "invite") {
@@ -219,27 +220,34 @@ class MautrixTelegram {
} }
return return
} }
if (evt.sender === asBotID || evt.type !== "m.room.message" || !evt.content) { if (evt.sender === asBotID || evt.type !== "m.room.message" || !evt.content) {
// Ignore own messages and non-message events. // Ignore own messages and non-message events.
return; return;
} }
const cmdprefix = this.config.bridge.command_prefix const cmdprefix = this.config.bridge.command_prefix
if (evt.content.body.startsWith(cmdprefix + " ")) { if (evt.content.body.startsWith(cmdprefix + " ")) {
this.getMatrixUser(evt.sender).then(user => { const user = await this.getMatrixUser(evt.sender)
if (!user.whitelisted) { if (!user.whitelisted) {
this.botIntent.sendText(evt.room_id, "You are not authorized to use this bridge.") this.botIntent.sendText(evt.room_id, "You are not authorized to use this bridge.")
return return
} }
const prefixLength = cmdprefix.length + 1 const prefixLength = cmdprefix.length + 1
const args = evt.content.body.substr(prefixLength).split(" ") const args = evt.content.body.substr(prefixLength).split(" ")
const command = args.shift() const command = args.shift()
commands.run(user, command, args, reply => commands.run(user, command, args, reply =>
this.botIntent.sendText( this.botIntent.sendText(
evt.room_id, evt.room_id,
reply.replace("$cmdprefix", cmdprefix)), reply.replace("$cmdprefix", cmdprefix)),
this) this)
}) return
}
const portal = await this.getPortalByRoomID(evt.room_id)
if (portal) {
portal.handleMatrixEvent(evt)
return return
} }
} }
-1
View File
@@ -113,7 +113,6 @@ commands.login = async (sender, args, reply) => {
action: "Phone code authentication", action: "Phone code authentication",
next: enterCode, next: enterCode,
} }
console.log(data)
} catch (err) { } catch (err) {
reply(`Failed to send code: ${err}`) reply(`Failed to send code: ${err}`)
console.log(err) console.log(err)
+6
View File
@@ -116,13 +116,19 @@ class MatrixUser {
async syncDialogs() { async syncDialogs() {
const dialogs = await this.telegramPuppet.client("messages.getDialogs", {}) const dialogs = await this.telegramPuppet.client("messages.getDialogs", {})
let changed = false
for (const dialog of dialogs.chats) { for (const dialog of dialogs.chats) {
if (dialog._ === "chatForbidden" || dialog.deactivated) {
continue
}
const peer = new TelegramPeer(dialog._, dialog.id) const peer = new TelegramPeer(dialog._, dialog.id)
const portal = await this.app.getPortalByPeer(peer) const portal = await this.app.getPortalByPeer(peer)
if (portal.updateInfo(this.telegramPuppet, dialog)) { if (portal.updateInfo(this.telegramPuppet, dialog)) {
portal.save() portal.save()
changed = true
} }
} }
return changed
} }
async sendTelegramCode(phoneNumber) { async sendTelegramCode(phoneNumber) {
+52 -17
View File
@@ -25,6 +25,10 @@ class Portal {
this.accessHashes = new Map() this.accessHashes = new Map()
} }
get id() {
return this.peer.id
}
static fromEntry(app, entry) { static fromEntry(app, entry) {
if (entry.type !== "portal") { if (entry.type !== "portal") {
throw new Error("MatrixUser can only be created from entry type \"portal\"") throw new Error("MatrixUser can only be created from entry type \"portal\"")
@@ -37,43 +41,74 @@ class Portal {
return portal return portal
} }
async syncParticipants(participants) {
for (const participant of participants) {
const user = this.app.getTelegramUser(participant.id)
if (user.updateInfo(participant)) {
user.save()
}
user.intent.join(this.roomID)
}
}
handleMatrixEvent(evt) {
console.log("Received message from Matrix to portal with room ID", this.roomID)
console.log(evt)
}
async createMatrixRoom(telegramPOV) { async createMatrixRoom(telegramPOV) {
if (this.roomID) { if (this.roomID) {
return return this.roomID
} }
try { try {
await this.peer.getInfo(telegramPOV) const {info, participants} = await this.peer.getInfo(telegramPOV)
console.log(JSON.stringify(info, "", " "))
console.log(JSON.stringify(participants, "", " "))
const room = await this.app.botIntent.createRoom({
options: {
name: info.title,
visibility: "private",
}
})
this.roomID = room.room_id
this.app.portalsByRoomID.set(this.roomID, this)
await this.save()
// TODO other things?
return this.roomID
} catch (err) { } catch (err) {
console.error(err) console.error(err)
console.error(err.stack) console.error(err.stack)
return undefined
} }
} }
updateInfo(telegramPOV, dialog) { updateInfo(telegramPOV, dialog) {
let changed = false let changed = false
if (this.peer.type === "channel") { if (this.peer.type === "channel") {
if (telegramPOV && this.accessHashes.get(telegramPOV.userID) !== +dialog.access_hash) {
this.accessHashes.set(telegramPOV.userID, +dialog.access_hash)
changed = true
}
} }
if (telegramPOV && this.accessHashes.get(telegramPOV.userID) !== +dialog.access_hash) { return this.peer.updateInfo(dialog) || changed
this.accessHashes.set(telegramPOV.userID, +dialog.access_hash)
changed = true
}
if (this.title !== dialog.title) {
this.title = dialog.title
changed = true
}
return changed
} }
toEntry() { toEntry() {
return { return {
type: this.type, type: this.type,
id: this.roomID, id: this.id,
peer: this.peer.toSubentry(), data: {
accessHashes: this.peer.type === "channel" roomID: this.roomID,
? Array.from(this.accessHashes) peer: this.peer.toSubentry(),
: undefined, accessHashes: this.peer.type === "channel"
? Array.from(this.accessHashes)
: undefined,
}
} }
} }
+24 -3
View File
@@ -19,6 +19,8 @@ class TelegramPeer {
this.type = type this.type = type
this.id = id this.id = id
this.accessHash = +(accessHash || 0) this.accessHash = +(accessHash || 0)
this.username = undefined
this.title = undefined
} }
static fromTelegramData(peer) { static fromTelegramData(peer) {
@@ -52,7 +54,21 @@ class TelegramPeer {
} }
return false return false
} }
}
updateInfo(dialog) {
let changed = false
if (this.type === "channel") {
if (this.username !== dialog.username) {
this.username = dialog.username
changed = true
}
}
if (this.title !== dialog.title) {
this.title = dialog.title
changed = true
}
return changed
} }
async getInfo(telegramPOV) { async getInfo(telegramPOV) {
@@ -64,6 +80,7 @@ class TelegramPeer {
info = await telegramPOV.client("messages.getFullChat", { info = await telegramPOV.client("messages.getFullChat", {
chat_id: this.id, chat_id: this.id,
}) })
participants = info.users
break break
case "channel": case "channel":
// FIXME I'm broken (Error: CHANNEL_INVALID) // FIXME I'm broken (Error: CHANNEL_INVALID)
@@ -80,8 +97,7 @@ class TelegramPeer {
default: default:
throw new Error(`Unknown peer type ${this.type}`) throw new Error(`Unknown peer type ${this.type}`)
} }
console.log(JSON.stringify(info, "", " ")) return { info, participants }
console.log(JSON.stringify(participants, "", " "))
} }
toInputPeer() { toInputPeer() {
@@ -121,13 +137,18 @@ class TelegramPeer {
} }
static fromSubentry(entry) { static fromSubentry(entry) {
return new TelegramPeer(entry.type, entry.id) const peer = new TelegramPeer(entry.type, entry.id)
peer.username = entry.username
peer.title = entry.title
return peer
} }
toSubentry() { toSubentry() {
return { return {
type: this.type, type: this.type,
id: this.id, id: this.id,
username: this.username,
title: this.title,
} }
} }
+12 -5
View File
@@ -136,7 +136,8 @@ class TelegramPuppet {
}) })
return this.signInComplete(result) return this.signInComplete(result)
} catch (err) { } catch (err) {
if (err.message !== "SESSION_PASSWORD_NEEDED") { if (err.type !== "SESSION_PASSWORD_NEEDED" && err.message !== "SESSION_PASSWORD_NEEDED") {
console.error("Unknown login error:", JSON.stringify(err, "", " "))
throw err throw err
} }
const password = await const password = await
@@ -156,7 +157,8 @@ class TelegramPuppet {
getDisplayName() { getDisplayName() {
if (this.data.firstName || this.data.lastName) { if (this.data.firstName || this.data.lastName) {
return `${this.data.firstName} ${this.data.lastName}` return [this.firstName, this.lastName].filter(s => !!s)
.join(" ")
} else if (this.data.username) { } else if (this.data.username) {
return this.data.username return this.data.username
} }
@@ -285,10 +287,15 @@ class TelegramPuppet {
console.error("Failed to update contacts:", err) console.error("Failed to update contacts:", err)
} }
try { try {
console.log("Syncing dialogs...") console.log("Updating dialogs...")
await this.matrixUser.syncDialogs() const changed = await this.matrixUser.syncDialogs()
if (!changed) {
console.log("Dialogs were up-to-date")
} else {
console.log("Dialogs updated")
}
} catch (err) { } catch (err) {
console.error("Failed to sync dialogs:", err) console.error("Failed to update dialogs:", err)
} }
setInterval(async () => { setInterval(async () => {
try { try {