Yet another sync commit

This commit is contained in:
Tulir Asokan
2017-11-16 22:05:08 +02:00
parent e95873b4ec
commit 8a1ed209f1
6 changed files with 91 additions and 50 deletions
+6 -2
View File
@@ -82,10 +82,14 @@ class MautrixTelegram {
return portal
}
const entries = await this.bridge.getRoomStore().select({
const query = {
type: "portal",
id: peer.id,
})
}
if (peer.type === "user") {
query.receiverID = peer.receiverID
}
const entries = await this.bridge.getRoomStore().select(query)
// Handle possible db query race conditions
portal = this.portalsByPeerID.get(peer.id)
+13 -13
View File
@@ -18,17 +18,17 @@ const makePasswordHash = require("telegram-mtproto").plugins.makePasswordHash
const commands = {}
function run(sender, command, args, reply, app) {
if (sender.commandStatus) {
if (command === "cancel") {
reply(`${sender.commandStatus.action} cancelled.`)
sender.commandStatus = undefined
return
}
args.unshift(command)
return sender.commandStatus.next(sender, args, reply, app)
}
command = this.commands[command]
if (!command) {
if (sender.commandStatus) {
if (command === "cancel") {
reply(`${sender.commandStatus.action} cancelled.`)
sender.commandStatus = undefined
return
}
args.unshift(command)
return sender.commandStatus.next(sender, args, reply, app)
}
reply("Unknown command. Try \"$cmdprefix help\" for help.")
return
}
@@ -60,7 +60,7 @@ syncUsers <type> <id> - Sync user info and join status in the given portal. Same
/**
* Two-factor authentication handler.
*/
const enterPassword = async (sender, args, reply) => {
commands.enterPassword = async (sender, args, reply) => {
if (args.length === 0) {
reply("Usage: $cmdprefix <password>")
return
@@ -80,7 +80,7 @@ const enterPassword = async (sender, args, reply) => {
/*
* Login code send handler.
*/
const enterCode = async (sender, args, reply) => {
commands.enterCode = async (sender, args, reply) => {
if (args.length === 0) {
reply("Usage: $cmdprefix <authentication code>")
return
@@ -95,7 +95,7 @@ const enterCode = async (sender, args, reply) => {
reply(`You have two-factor authentication enabled. Password hint: ${data.hint}\nEnter your password using "$cmdprefix <password>"`)
sender.commandStatus = {
action: "Two-factor authentication",
next: enterPassword,
next: commands.enterPassword,
salt: data.salt,
}
} else {
@@ -122,7 +122,7 @@ commands.login = async (sender, args, reply) => {
reply(`Login code sent to ${args[0]}.\nEnter the code using "$cmdprefix <code>"`)
sender.commandStatus = {
action: "Phone code authentication",
next: enterCode,
next: commands.enterCode ,
}
} catch (err) {
reply(`Failed to send code: ${err}`)
+22 -6
View File
@@ -29,6 +29,10 @@ class Portal {
return this.peer.id
}
get receiverID() {
return this.peer.receiverID
}
static fromEntry(app, entry) {
if (entry.type !== "portal") {
throw new Error("MatrixUser can only be created from entry type \"portal\"")
@@ -51,7 +55,7 @@ class Portal {
}
for (const userData of users) {
const user = await this.app.getTelegramUser(userData.id)
await user.updateInfo(telegramPOV, userData)
await user.updateInfo(telegramPOV, userData, true)
await user.intent.join(this.roomID)
}
return true
@@ -92,11 +96,20 @@ class Portal {
return undefined
}
const {info, users} = await this.peer.getInfo(telegramPOV)
let title, info, users
if (this.peer.type !== "user") {
({info, users} = await this.peer.getInfo(telegramPOV))
title = info.title
} else {
({info} = await this.peer.getInfo(telegramPOV))
users = await this.app.getTelegramUser(info.id)
await users.updateInfo(telegramPOV, info)
title = users.getDisplayName()
}
const room = await this.app.botIntent.createRoom({
options: {
name: info.title,
name: title,
visibility: "private",
}
})
@@ -104,9 +117,11 @@ class Portal {
this.roomID = room.room_id
this.app.portalsByRoomID.set(this.roomID, this)
await this.save()
await this.syncTelegramUsers(telegramPOV, users)
if (this.peer.type !== "user") {
await this.syncTelegramUsers(telegramPOV, users)
} else {
await users.intent.join(this.roomID)
}
return this.roomID
} catch (err) {
console.error(err)
@@ -134,6 +149,7 @@ class Portal {
return {
type: this.type,
id: this.id,
receiverID: this.receiverID,
data: {
roomID: this.roomID,
peer: this.peer.toSubentry(),
+29 -15
View File
@@ -15,20 +15,21 @@
// along with this program. If not, see <http://www.gnu.org/licenses/>.
class TelegramPeer {
constructor(type, id, accessHash) {
constructor(type, id, accessHash, receiverID) {
this.type = type
this.id = id
this.accessHash = accessHash
this.receiverID = receiverID
this.username = undefined
this.title = undefined
}
static fromTelegramData(peer) {
static fromTelegramData(peer, receiverID) {
switch(peer._) {
case "peerChat":
return new TelegramPeer("chat", peer.chat_id)
case "peerUser":
return new TelegramPeer("user", peer.user_id, peer.access_hash)
return new TelegramPeer("user", peer.user_id, peer.access_hash, receiverID)
case "peerChannel":
return new TelegramPeer("channel", peer.channel_id, peer.access_hash)
default:
@@ -86,7 +87,11 @@ class TelegramPeer {
let info, users
switch(this.type) {
case "user":
throw new Error("Can't get chat info of user")
info = await telegramPOV.client("users.getFullUser", {
id: this.toInputObject()
})
users = [info.user]
info = info.user
case "chat":
info = await telegramPOV.client("messages.getFullChat", {
chat_id: this.id,
@@ -95,10 +100,10 @@ class TelegramPeer {
break
case "channel":
info = await telegramPOV.client("channels.getFullChannel", {
channel: this.toInputChannel(),
channel: this.toInputObject(),
})
const participants = await telegramPOV.client("channels.getParticipants", {
channel: this.toInputChannel(),
channel: this.toInputObject(),
filter: { _: "channelParticipantsRecent" },
offset: 0,
limit: 1000,
@@ -138,15 +143,22 @@ class TelegramPeer {
}
}
toInputChannel() {
if (this.type !== "channel") {
throw new Error(`Cannot convert peer of type ${this.type} into an inputChannel`)
}
return {
_: "inputChannel",
channel_id: this.id,
access_hash: this.accessHash,
toInputObject() {
switch(this.type) {
case "user":
return {
_: "inputUser",
user_id: this.id,
access_hash: this.accessHash,
}
case "channel":
return {
_: "inputChannel",
channel_id: this.id,
access_hash: this.accessHash,
}
default:
throw new Error(`Unrecognized type ${this.type}`)
}
}
@@ -154,6 +166,7 @@ class TelegramPeer {
const peer = new TelegramPeer(entry.type, entry.id)
peer.username = entry.username
peer.title = entry.title
peer.receiverID = entry.receiverID
return peer
}
@@ -163,6 +176,7 @@ class TelegramPeer {
id: this.id,
username: this.username,
title: this.title,
receiverID: this.receiverID,
}
}
+21 -12
View File
@@ -56,6 +56,7 @@ class TelegramPuppet {
return value
},
set: async (key, value) => {
console.warn("SET", key, "=", JSON.stringify(value))
if (this.data[key] === value) {
return
}
@@ -64,10 +65,12 @@ class TelegramPuppet {
await this.matrixUser.save()
},
remove: async (...keys) => {
console.warn("DEL", JSON.stringify(value))
keys.forEach((key) => delete this.data[key])
await this.matrixUser.save()
},
clear: async () => {
console.warn("CLR")
this.data = {}
await this.matrixUser.save()
},
@@ -225,6 +228,7 @@ class TelegramPuppet {
console.log("Oh noes! Empty update")
return
}
let peer, portal
switch(update._) {
case "updateUserStatus":
const user = await this.app.getTelegramUser(update.user_id)
@@ -237,25 +241,29 @@ class TelegramPuppet {
default:
status = "offline"
}
user.intent.getClient().setPresence({presence: status})
await user.intent.getClient().setPresence({presence: status})
break
case "updateUserTyping":
console.log(update.user_id, "is typing in a 1-1 chat")
break
peer = new TelegramPeer("user", update.user_id, undefined, this.userID)
case "updateChatUserTyping":
console.log(update.user_id, "is typing in", update.chat_id)
peer = peer || new TelegramPeer("chat", update.chat_id)
portal = await this.app.getPortalByPeer(peer)
if (portal.isMatrixRoomCreated()) {
const sender = await this.app.getTelegramUser(update.user_id)
// The Intent API currently doesn't allow you to set the
// typing timeout. If it does, we should set it to ~5.5s as
// Telegram resends typing notifications every 5 seconds.
await sender.intent.sendTyping(portal.roomID, true/*, 5500*/)
}
break
case "updateShortMessage":
await this.handleMessage({
from: update.user_id,
to: new TelegramPeer("user", update.user_id),
text: update.message,
})
break
peer = new TelegramPeer("user", update.user_id, undefined, this.userID)
case "updateShortChatMessage":
peer = peer || new TelegramPeer("chat", update.chat_id)
await this.handleMessage({
from: update.user_id,
to: new TelegramPeer("chat", update.chat_id),
to: peer,
text: update.message,
})
break
@@ -265,7 +273,7 @@ class TelegramPuppet {
update = update.message // Message defined at message#90dddc11 in layer 71
await this.handleMessage({
from: update.from_id,
to: TelegramPeer.fromTelegramData(update.to_id),
to: TelegramPeer.fromTelegramData(update.to_id, this.userID),
text: update.message,
})
break
@@ -275,6 +283,7 @@ class TelegramPuppet {
}
handleUpdate(data) {
console.log("UPDATE", data)
try {
switch (data._) {
case "updateShort":
-2
View File
@@ -88,10 +88,8 @@ class TelegramUser {
const userInfo = await this.intent.getProfileInfo(this.mxid, "displayname")
if (userInfo.displayname !== this.getDisplayName()) {
console.log(userInfo.displayname)
this.intent.setDisplayName(
this.app.config.bridge.displayname_template.replace("${DISPLAYNAME}", this.getDisplayName()))
console.log((await this.intent.getProfileInfo(this.mxid, "displayname")).displayname)
}
if (!dontUpdateAvatar && this.updateAvatarImageFrom(telegramPOV, user)) {
changed = true