Add image/audio/file/location bridging. Fixes #9
This commit is contained in:
Generated
+5
@@ -1652,6 +1652,11 @@
|
||||
"object-assign": "4.1.1"
|
||||
}
|
||||
},
|
||||
"file-type": {
|
||||
"version": "7.3.0",
|
||||
"resolved": "https://registry.npmjs.org/file-type/-/file-type-7.3.0.tgz",
|
||||
"integrity": "sha1-GIaXYOEMNsBBbVMINoT8/A1Z3zo="
|
||||
},
|
||||
"finalhandler": {
|
||||
"version": "0.3.6",
|
||||
"resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-0.3.6.tgz",
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
"colors": "1.1.x",
|
||||
"commander": "2.12.x",
|
||||
"escape-html": "1.0.x",
|
||||
"file-type": "^7.3.0",
|
||||
"marked": "0.3.x",
|
||||
"matrix-appservice-bridge": "1.x.x",
|
||||
"matrix-js-sdk": "0.x.x",
|
||||
|
||||
+45
-7
@@ -64,8 +64,36 @@ class Portal {
|
||||
return true
|
||||
}
|
||||
|
||||
|
||||
async copyPhotoSize(telegramPOV, sender, photo) {
|
||||
const size = photo.sizes.slice(-1)[0]
|
||||
const uploaded = await this.copyFile(telegramPOV, sender, size.location, photo.id)
|
||||
uploaded.info.h = size.h
|
||||
uploaded.info.w = size.w
|
||||
uploaded.info.size = size.size
|
||||
uploaded.info.orientation = 0
|
||||
return uploaded
|
||||
}
|
||||
|
||||
async copyFile(telegramPOV, sender, location, id) {
|
||||
console.log(JSON.stringify(location, "", " "))
|
||||
id = id || location.id
|
||||
const file = await telegramPOV.getFile(location)
|
||||
const uploaded = await sender.intent.getClient().uploadContent({
|
||||
stream: file.buffer,
|
||||
name: `${id}.${file.extension}`,
|
||||
type: file.mimetype,
|
||||
}, { rawResponse: false })
|
||||
uploaded.matrixtype = file.matrixtype
|
||||
uploaded.info = {
|
||||
mimetype: file.mimetype,
|
||||
size: location.size,
|
||||
}
|
||||
return uploaded
|
||||
}
|
||||
|
||||
async updateAvatar(telegramPOV, chat) {
|
||||
if (!chat.photo) {
|
||||
if (!chat.photo || this.peer.type === "user") {
|
||||
return false
|
||||
}
|
||||
|
||||
@@ -80,12 +108,11 @@ class Portal {
|
||||
const file = await telegramPOV.getFile(photo)
|
||||
const name = `${photo.volume_id}_${photo.local_id}.${file.extension}`
|
||||
|
||||
const uploaded = await this.app.botIntent.getClient()
|
||||
.uploadContent({
|
||||
stream: Buffer.from(file.bytes),
|
||||
name,
|
||||
type: file.mimetype,
|
||||
}, { rawResponse: false })
|
||||
const uploaded = await this.app.botIntent.getClient().uploadContent({
|
||||
stream: file.buffer,
|
||||
name,
|
||||
type: file.mimetype,
|
||||
}, { rawResponse: false })
|
||||
|
||||
this.avatarURL = uploaded.content_uri
|
||||
this.photo = {
|
||||
@@ -113,6 +140,17 @@ class Portal {
|
||||
if (evt.text.length > 0) {
|
||||
sender.sendText(this.roomID, evt.text)
|
||||
}
|
||||
if (evt.photo) {
|
||||
const photo = await this.copyPhoto(evt.source, sender, evt.photo)
|
||||
photo.name = evt.caption || "Photo"
|
||||
sender.sendFile(this.roomID, photo)
|
||||
} else if (evt.document) {
|
||||
const file = await this.copyFile(evt.source, sender, evt.document)
|
||||
file.name = evt.caption || "File upload"
|
||||
sender.sendFile(this.roomID, file)
|
||||
} else if (evt.geo) {
|
||||
sender.sendLocation(this.roomID, evt.geo)
|
||||
}
|
||||
}
|
||||
|
||||
async handleMatrixEvent(sender, evt) {
|
||||
|
||||
+87
-20
@@ -14,25 +14,56 @@
|
||||
// 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 telegram = require("telegram-mtproto")
|
||||
const fileType = require("file-type")
|
||||
const pkg = require("../package.json")
|
||||
const TelegramPeer = require("./telegram-peer")
|
||||
|
||||
/*
|
||||
* Mapping from Telegram file types to MIME types and extensions.
|
||||
*/
|
||||
const META_FROM_FILETYPE = {
|
||||
"storage.fileGif": {
|
||||
mimetype: "image/gif",
|
||||
extension: "gif",
|
||||
},
|
||||
"storage.fileJpeg": {
|
||||
mimetype: "image/jpeg",
|
||||
extension: "jpeg",
|
||||
},
|
||||
"storage.filePng": {
|
||||
mimetype: "image/png",
|
||||
extension: "png",
|
||||
},
|
||||
function metaFromFileType(type) {
|
||||
const extension = type.substr("storage.file".length).toLowerCase()
|
||||
let fileClass, mimetype, matrixtype
|
||||
/*eslint no-fallthrough: "off"*/
|
||||
switch (type) {
|
||||
case "storage.fileGif":
|
||||
case "storage.fileJpeg":
|
||||
case "storage.filePng":
|
||||
case "storage.fileWebp":
|
||||
fileClass = "image"
|
||||
break
|
||||
case "storage.fileMov":
|
||||
mimetype = "quicktime"
|
||||
case "storage.fileMp4":
|
||||
fileClass = "video"
|
||||
break
|
||||
case "storage.fileMp3":
|
||||
mimetype = "mpeg"
|
||||
fileClass = "audio"
|
||||
break
|
||||
case "storage.filePartial":
|
||||
throw new Error("Partial files should be completed before fetching their type.")
|
||||
case "storage.fileUnknown":
|
||||
fileClass = "application"
|
||||
mimetype = "octet-stream"
|
||||
matrixtype = "m.file"
|
||||
break
|
||||
default:
|
||||
return undefined
|
||||
}
|
||||
mimetype = `${fileClass}/${mimetype || extension}`
|
||||
matrixtype = matrixtype || `m.${fileClass}`
|
||||
return { mimetype, extension, matrixtype }
|
||||
}
|
||||
|
||||
function matrixFromMime(mime) {
|
||||
if (mime.startsWith("audio/")) {
|
||||
return "m.audio"
|
||||
} else if (mime.startsWith("video/")) {
|
||||
return "m.video"
|
||||
} else if (mime.startsWith("image/")) {
|
||||
return "m.image"
|
||||
}
|
||||
return "m.file"
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -278,6 +309,18 @@ class TelegramPuppet {
|
||||
to,
|
||||
source: this,
|
||||
text: update.message,
|
||||
photo: update.media && update.media._ === "messageMediaPhoto"
|
||||
? update.media.photo
|
||||
: undefined,
|
||||
document: update.media && update.media._ === "messageMediaDocument"
|
||||
? update.media.document
|
||||
: undefined,
|
||||
geo: update.media && update.media._ === "messageMediaGeo"
|
||||
? update.media.geo
|
||||
: undefined,
|
||||
caption: update.media ?
|
||||
update.media.caption
|
||||
: undefined,
|
||||
})
|
||||
}
|
||||
|
||||
@@ -352,17 +395,41 @@ class TelegramPuppet {
|
||||
}
|
||||
|
||||
async getFile(location) {
|
||||
location = Object.assign({}, location, { _: "inputFileLocation" })
|
||||
delete location.dc_id
|
||||
if (location.volume_id && location.local_id) {
|
||||
location = {
|
||||
_: "inputFileLocation",
|
||||
volume_id: location.volume_id,
|
||||
local_id: location.local_id,
|
||||
secret: location.secret,
|
||||
}
|
||||
} else if (location.id && location.access_hash) {
|
||||
location = {
|
||||
_: "inputDocumentFileLocation",
|
||||
id: location.id,
|
||||
access_hash: location.access_hash,
|
||||
}
|
||||
} else {
|
||||
throw new Error("Unrecognized file location type.")
|
||||
}
|
||||
const file = await this.client("upload.getFile", {
|
||||
location,
|
||||
offset: 0,
|
||||
// Max download size: 100mb
|
||||
limit: 100 * 1024 * 1024,
|
||||
})
|
||||
const meta = META_FROM_FILETYPE[file.type._]
|
||||
if (meta) {
|
||||
file.mimetype = meta.mimetype
|
||||
file.extension = meta.extension
|
||||
file.buffer = Buffer.from(file.bytes)
|
||||
if (file.type._ === "storage.filePartial") {
|
||||
const { mime, ext } = fileType(file.buffer)
|
||||
file.mimetype = mime
|
||||
file.extension = ext
|
||||
file.matrixtype = matrixFromMime(mime)
|
||||
} else {
|
||||
const meta = metaFromFileType(file.type._)
|
||||
if (meta) {
|
||||
file.mimetype = meta.mimetype
|
||||
file.extension = meta.extension
|
||||
file.matrixtype = meta.matrixtype
|
||||
}
|
||||
}
|
||||
return file
|
||||
}
|
||||
|
||||
+13
-5
@@ -138,12 +138,20 @@ class TelegramUser {
|
||||
return this.intent.sendText(roomID, text)
|
||||
}
|
||||
|
||||
sendImage(roomID, opts) {
|
||||
sendFile(roomID, file) {
|
||||
return this.intent.sendMessage(roomID, {
|
||||
msgtype: "m.image",
|
||||
url: opts.content_uri,
|
||||
body: opts.name,
|
||||
info: opts.info,
|
||||
msgtype: file.matrixtype || "m.file",
|
||||
url: file.content_uri,
|
||||
body: file.name || "Uploaded file",
|
||||
info: file.info,
|
||||
})
|
||||
}
|
||||
|
||||
sendLocation(roomID, { long = 0.0, lat = 0.0, body = "Location" } = {}) {
|
||||
return this.intent.sendMessage(roomID, {
|
||||
msgtype: "m.location",
|
||||
geo_uri: `geo:${lat},${long}`,
|
||||
body,
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user