// mautrix-telegram - A Matrix-Telegram puppeting bridge // Copyright (C) 2017 Tulir Asokan // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program. If not, see . class TelegramPeer { constructor(type, id, accessHash) { this.type = type this.id = id this.accessHash = accessHash this.username = undefined this.title = undefined } static fromTelegramData(peer) { switch(peer._) { case "peerChat": return new TelegramPeer("chat", peer.chat_id) case "peerUser": return new TelegramPeer("user", peer.user_id, peer.access_hash) case "peerChannel": return new TelegramPeer("channel", peer.channel_id, peer.access_hash) default: throw new Error(`Unrecognized peer type ${peer._}`) } } /** * Load the access hash for a specific puppeted Telegram user from the channel portal or TelegramUser info. * * @param {MautrixTelegram} app The instance of {@link MautrixTelegram} to use. * @param {TelegramPuppet} telegramPOV The puppeted Telegram user for whom the access hash is needed. * @param {Portal} [portal] Optional channel {@link Portal} instance to avoid calling {@link app#getPortalByPeer(peer)}. * Only used if {@link #type} is {@linkplain user}. * @param {TelegramUser} [user] Optional {@link TelegramUser} instance to avoid calling {@link app#getTelegramUser(id)}. * Only used if {@link #type} is {@linkplain channel}. * @returns {Promise} Whether or not the access hash was found and loaded. */ async loadAccessHash(app, telegramPOV, { portal, user }) { if (this.type === "chat") { return true } else if (this.type === "user") { user = user || await app.getTelegramUser(this.id) if (user.accessHashes.has(telegramPOV.userID)) { this.accessHash = user.accessHashes.get(telegramPOV.userID) return true } return false } else if (this.type === "channel") { portal = portal || await app.getPortalByPeer(this) if (portal.accessHashes.has(telegramPOV.userID)) { this.accessHash = portal.accessHashes.get(telegramPOV.userID) return true } return false } } async 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) { let info, users switch(this.type) { case "user": throw new Error("Can't get chat info of user") case "chat": info = await telegramPOV.client("messages.getFullChat", { chat_id: this.id, }) users = info.users break case "channel": info = await telegramPOV.client("channels.getFullChannel", { channel: this.toInputChannel(), }) const participants = await telegramPOV.client("channels.getParticipants", { channel: this.toInputChannel(), filter: { _: "channelParticipantsRecent" }, offset: 0, limit: 1000, }) users = participants.users break default: throw new Error(`Unknown peer type ${this.type}`) } return { info: info.chats[0], users } } toInputPeer() { switch(this.type) { case "chat": return { _: "inputPeerChat", chat_id: this.id, } case "user": return { _: "inputPeerUser", user_id: this.id, access_hash: this.accessHash, } case "channel": return { _: "inputPeerChannel", channel_id: this.id, access_hash: this.accessHash, } default: throw new Error(`Unrecognized peer type ${this.type}`) } } 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, } } static fromSubentry(entry) { const peer = new TelegramPeer(entry.type, entry.id) peer.username = entry.username peer.title = entry.title return peer } toSubentry() { return { type: this.type, id: this.id, username: this.username, title: this.title, } } get key() { return `${this.type} ${this.id}` } } module.exports = TelegramPeer