Files
mautrix-telegram/src/telegram-user.js
T
2017-11-16 11:54:01 +02:00

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