196 lines
4.8 KiB
JavaScript
196 lines
4.8 KiB
JavaScript
// 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 <http://www.gnu.org/licenses/>.
|
|
const TelegramPeer = require("./telegram-peer")
|
|
|
|
/**
|
|
* TelegramUser represents a Telegram user who probably has an
|
|
* appservice-managed Matrix account.
|
|
*/
|
|
class TelegramUser {
|
|
constructor(app, id, user) {
|
|
this.app = app
|
|
this.id = id
|
|
this.accessHashes = new Map()
|
|
this._intent = undefined
|
|
if (user) {
|
|
this.updateInfo(undefined, user)
|
|
}
|
|
}
|
|
|
|
static fromEntry(app, entry) {
|
|
if (entry.type !== "remote") {
|
|
throw new Error("TelegramUser can only be created from entry type \"remote\"")
|
|
}
|
|
|
|
const user = new TelegramUser(app, entry.id)
|
|
const data = entry.data
|
|
user.firstName = data.firstName
|
|
user.lastName = data.lastName
|
|
user.username = data.username
|
|
user.phoneNumber = data.phoneNumber
|
|
user.photo = data.photo
|
|
user.avatarURL = data.avatarURL
|
|
user.accessHashes = new Map(data.accessHashes)
|
|
return user
|
|
}
|
|
|
|
toPeer(telegramPOV) {
|
|
return new TelegramPeer("user", this.id, this.accessHashes.get(telegramPOV.userID))
|
|
}
|
|
|
|
toEntry() {
|
|
return {
|
|
type: "remote",
|
|
id: this.id,
|
|
data: {
|
|
firstName: this.firstName,
|
|
lastName: this.lastName,
|
|
username: this.username,
|
|
phoneNumber: this.phoneNumber,
|
|
photo: this.photo,
|
|
avatarURL: this.avatarURL,
|
|
accessHashes: Array.from(this.accessHashes),
|
|
},
|
|
}
|
|
}
|
|
|
|
async updateInfo(telegramPOV, user) {
|
|
let changed = false
|
|
if (this.firstName !== user.first_name) {
|
|
this.firstName = user.first_name
|
|
changed = true
|
|
}
|
|
if (this.lastName !== user.last_name) {
|
|
this.lastName = user.last_name
|
|
changed = true
|
|
}
|
|
if (this.username !== user.username) {
|
|
this.username = user.username
|
|
changed = true
|
|
}
|
|
if (await this.updateAvatarImageFrom(telegramPOV, user)) {
|
|
changed = true
|
|
}
|
|
if (telegramPOV && this.accessHashes.get(telegramPOV.userID) !== user.access_hash) {
|
|
this.accessHashes.set(telegramPOV.userID, user.access_hash)
|
|
changed = true
|
|
}
|
|
|
|
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 (changed) {
|
|
this.save()
|
|
}
|
|
return changed
|
|
}
|
|
|
|
get intent() {
|
|
if (!this._intent) {
|
|
this._intent = this.app.getIntentForTelegramUser(this.id)
|
|
}
|
|
return this._intent
|
|
}
|
|
|
|
get mxid() {
|
|
return this.intent.client.credentials.userId
|
|
}
|
|
|
|
getDisplayName() {
|
|
if (this.firstName || this.lastName) {
|
|
return [this.firstName, this.lastName].filter(s => !!s)
|
|
.join(" ")
|
|
} else if (this.username) {
|
|
return this.username
|
|
} else if (this.phoneNumber) {
|
|
return this.phoneNumber
|
|
}
|
|
return this.id
|
|
}
|
|
|
|
save() {
|
|
return this.app.putUser(this)
|
|
}
|
|
|
|
sendText(roomID, text) {
|
|
return this.intent.sendText(roomID, text)
|
|
}
|
|
|
|
sendImage(roomID, opts) {
|
|
return this.intent.sendMessage(roomID, {
|
|
msgtype: "m.image",
|
|
url: opts.content_uri,
|
|
body: opts.name,
|
|
info: opts.info,
|
|
})
|
|
}
|
|
|
|
sendSelfStateEvent(roomID, type, content) {
|
|
return this.intent.sendStateEvent(roomID, type, this.getMxid(), content)
|
|
}
|
|
|
|
uploadContent(opts) {
|
|
return this.intent.getClient()
|
|
.uploadContent({
|
|
stream: opts.stream,
|
|
name: opts.name,
|
|
type: opts.type,
|
|
}, {
|
|
rawResponse: false,
|
|
})
|
|
}
|
|
|
|
async updateAvatarImageFrom(telegramPOV, user) {
|
|
if (!user.photo) {
|
|
return false
|
|
}
|
|
|
|
const photo = user.photo.photo_big
|
|
if (this.photo && this.avatarURL &&
|
|
this.photo.dc_id === photo.dc_id &&
|
|
this.photo.volume_id === photo.volume_id &&
|
|
this.photo.local_id === photo.local_id) {
|
|
return false
|
|
}
|
|
|
|
const file = await telegramPOV.getFile(photo)
|
|
const name = `${photo.volume_id}_${photo.local_id}.${file.extension}`
|
|
|
|
const uploaded = await this.uploadContent({
|
|
stream: new Buffer(file.bytes),
|
|
name: name,
|
|
type: file.mimetype,
|
|
})
|
|
|
|
this.avatarURL = uploaded.content_uri
|
|
this.photo = {
|
|
dc_id: photo.dc_id,
|
|
volume_id: photo.volume_id,
|
|
local_id: photo.local_id,
|
|
}
|
|
|
|
await this.intent.setAvatarUrl(this.avatarURL)
|
|
return true
|
|
}
|
|
}
|
|
|
|
module.exports = TelegramUser
|