ligh7hau5/commands/fediverse/media.js

93 lines
3.4 KiB
JavaScript
Raw Normal View History

2020-07-03 12:10:55 +03:00
const qs = require('qs');
const axios = require('axios');
const FormData = require('form-data');
2021-01-01 12:30:26 +03:00
const emojis = { public: '🌐', unlisted: '📝', private: '🔒️', direct: '✉️' };
2020-12-27 12:27:48 +03:00
exports.visibilityEmoji = v => emojis[v] || v;
const getFilename = header => {
if(typeof header !== 'string') return null;
try {
const m = header.match(/inline; filename(?:=(.+)|\*=utf-8''(.+))/);
return !m ? null : m[2] && decodeURIComponent(m[2]) || m[1];
} catch(e) {
return null;
}
};
2020-11-08 09:44:00 +03:00
const mediaDownload = async (url, { whitelist, blacklist }) => {
2020-07-03 12:10:55 +03:00
const media = await axios({ method: 'GET', url, responseType: 'arraybuffer' });
2020-11-08 09:44:00 +03:00
if (media.statusText !== 'OK' || blacklist.includes(media.headers['content-type'])) throw media;
if(whitelist.length && !whitelist.includes(media.headers['content-type'])) throw media;
2020-07-03 12:10:55 +03:00
return {
data: media.data,
filename: getFilename(media.headers['content-disposition']),
2020-07-03 12:10:55 +03:00
mimetype: media.headers['content-type']
};
};
const mediaUpload = async ({ domain, token }, { data, filename, mimetype }) => {
2020-07-03 12:10:55 +03:00
const form = new FormData();
form.append('file', data, {
filename: filename || 'upload',
2020-07-03 12:10:55 +03:00
contentType: mimetype,
});
const upload = await axios({
method: 'POST',
url: `${domain}/api/v1/media`,
headers: form.getHeaders({ Authorization: `Bearer ${token}` }),
data: form,
});
if(upload.statusText !== 'OK') throw upload;
return upload.data.id;
};
const run = async (matrixClient, { roomId }, content, replyId, mediaURL, subject, registrar) => {
let mediaId = null;
2020-07-03 12:10:55 +03:00
const fediverse = registrar.config.fediverse;
if(mediaURL) {
const media = await mediaDownload(mediaURL, registrar.config.matrix.mimetypes);
mediaId = await mediaUpload(fediverse, media);
}
2020-07-03 12:10:55 +03:00
const response = await axios({
method: 'POST',
url: `${fediverse.domain}/api/v1/statuses`,
headers: { Authorization: `Bearer ${fediverse.token}`, 'Content-Type': 'application/x-www-form-urlencoded' },
data : qs.stringify({
status: content,
content_type: `text/markdown`,
media_ids: mediaURL && [ mediaId ] || undefined,
in_reply_to_id: replyId || undefined,
spoiler_text: subject || undefined
2020-07-03 12:10:55 +03:00
}, { arrayFormat: 'brackets' })
});
return matrixClient.sendHtmlNotice(roomId, '', `<a href="${response.data.url}">${response.data.id}</a>`);
}
exports.runQuery = async (client, room, userInput, registrar, { isReply, hasMedia, hasSubject }) => {
2020-07-03 12:10:55 +03:00
try {
2020-09-06 18:11:23 +03:00
const chunks = userInput.trim().split(' ');
if(!chunks.length || chunks.length < !!isReply + !!hasMedia) throw '';
2020-09-06 18:11:23 +03:00
let replyId = null;
let mediaURL = null;
const subject = hasSubject ? registrar.config.matrix.subject : null;
2020-09-06 18:11:23 +03:00
if(isReply) {
replyId = chunks[0];
chunks.shift();
}
if(hasMedia) {
2021-01-14 13:52:37 +03:00
let url = new URL(chunks[0]);
chunks.shift();
2021-01-14 13:52:37 +03:00
if(url.protocol === 'mxc:' && url.hostname && url.pathname)
url = new URL(`${registrar.config.matrix.domain}/_matrix/media/r0/download/${url.hostname}${url.pathname}`);
if(url.protocol !== 'https:') throw '';
if(!registrar.config.matrix.domains.includes(url.hostname)) throw '';
if(!/^\/_matrix\/media\/r0\/download\/[^/]+\/[^/]+\/?$/.test(url.pathname)) throw '';
mediaURL = url.toString();
}
return await run(client, room, chunks.join(' '), replyId, mediaURL, subject, registrar);
2020-07-03 12:10:55 +03:00
} catch(e) {
return client.sendHtmlNotice(room.roomId, 'Sad!', `<strong>Sad!</strong>`).catch(()=>{});
}
};