feat(matrix/fediverse): allow users to directly reply on Fediverse posts from Matrix, using <mx-reply> on our new meta field.
feat(matrix/fediverse): allow users to favorite, reblog, and redact Fediverse posts from Matrix, using m.reaction on our new meta field. feat(fediverse): add suggestions for follow/unfollow commands. refactor(matrix/fediverse): add meta field for commands by reaction, and commands by reply. refactor(fediverse): relax polling on timeline/notifs thru new handling.
This commit is contained in:
parent
430fb350c1
commit
42563ebc35
26 changed files with 619 additions and 375 deletions
|
@ -1,19 +1,15 @@
|
|||
exports.runQuery = function (matrixClient, room) {
|
||||
exports.runQuery = function (roomId, event) {
|
||||
axios({
|
||||
method: 'POST',
|
||||
url: `${config.fediverse.domain}/api/v1/statuses`,
|
||||
headers: { Authorization: `Bearer ${fediverse_auth.access_token}` },
|
||||
data: { status: `@10grans@fedi.cc beg` },
|
||||
}).then((response) => {
|
||||
matrixClient.sendHtmlNotice(room.roomId,
|
||||
'',
|
||||
`<b>
|
||||
<blockquote><i>You have begged for 10grans.<br>
|
||||
(id: ${response.data.id}</a>)
|
||||
</blockquote><br>`);
|
||||
headers: { Authorization: `Bearer ${fediverse.auth.access_token}` },
|
||||
data: { status: '@10grans@fedi.cc beg' },
|
||||
})
|
||||
.then(() => {
|
||||
matrix.utils.addReact(event, '✅');
|
||||
})
|
||||
.catch((e) => {
|
||||
matrixClient.sendHtmlNotice(room.roomId,
|
||||
'', `${e}`);
|
||||
matrix.utils.addReact(event, '❌');
|
||||
matrix.utils.sendError(event, roomId, e);
|
||||
});
|
||||
};
|
||||
|
|
|
@ -1,16 +1,14 @@
|
|||
exports.runQuery = function (matrixClient, room, userInput) {
|
||||
exports.runQuery = function (roomId, event, userInput) {
|
||||
axios({
|
||||
method: 'POST',
|
||||
url: `${config.fediverse.domain}/api/v1/statuses/${userInput}/unfavourite`,
|
||||
headers: { Authorization: `Bearer ${fediverse_auth.access_token}` },
|
||||
}).then((response) => {
|
||||
matrixClient.sendHtmlNotice(room.roomId,
|
||||
'',
|
||||
`You have boo'd: <a href="${response.data.url}">${response.data.account.acct}</a>
|
||||
<blockquote>${response.data.content}`);
|
||||
headers: { Authorization: `Bearer ${fediverse.auth.access_token}` },
|
||||
})
|
||||
.then(() => {
|
||||
matrix.utils.addReact(event, '✅');
|
||||
})
|
||||
.catch((e) => {
|
||||
matrixClient.sendHtmlNotice(room.roomId,
|
||||
'', `${e}`);
|
||||
matrix.utils.addReact(event, '❌');
|
||||
matrix.utils.sendError(event, roomId, e);
|
||||
});
|
||||
};
|
||||
|
|
|
@ -1,16 +1,14 @@
|
|||
exports.runQuery = function (matrixClient, room, userInput) {
|
||||
exports.runQuery = function (roomId, event, userInput) {
|
||||
axios({
|
||||
method: 'POST',
|
||||
url: `${config.fediverse.domain}/api/v1/statuses/${userInput}/favourite`,
|
||||
headers: { Authorization: `Bearer ${fediverse_auth.access_token}` },
|
||||
}).then((response) => {
|
||||
matrixClient.sendHtmlNotice(room.roomId,
|
||||
'',
|
||||
`You have clapped: <a href="${response.data.url}">${response.data.account.acct}</a>:
|
||||
<blockquote>${response.data.content}`);
|
||||
headers: { Authorization: `Bearer ${fediverse.auth.access_token}` },
|
||||
})
|
||||
.then(() => {
|
||||
matrix.utils.addReact(event, '✅');
|
||||
})
|
||||
.catch((e) => {
|
||||
matrixClient.sendHtmlNotice(room.roomId,
|
||||
'', `${e}`);
|
||||
matrix.utils.addReact(event, '❌');
|
||||
matrix.utils.sendError(event, roomId, e);
|
||||
});
|
||||
};
|
||||
|
|
|
@ -1,16 +1,14 @@
|
|||
exports.runQuery = function (matrixClient, room, userInput) {
|
||||
exports.runQuery = function (roomId, event, userInput) {
|
||||
axios({
|
||||
method: 'POST',
|
||||
url: `${config.fediverse.domain}/api/v1/statuses/${userInput}/reblog`,
|
||||
headers: { Authorization: `Bearer ${fediverse_auth.access_token}` },
|
||||
}).then((response) => {
|
||||
matrixClient.sendHtmlNotice(room.roomId,
|
||||
'',
|
||||
`You have repeated:
|
||||
<blockquote>${response.data.content}`);
|
||||
headers: { Authorization: `Bearer ${fediverse.auth.access_token}` },
|
||||
})
|
||||
.then(() => {
|
||||
matrix.utils.addReact(event, '✅');
|
||||
})
|
||||
.catch((e) => {
|
||||
matrixClient.sendHtmlNotice(room.roomId,
|
||||
'', `${e}`);
|
||||
matrix.utils.addReact(event, '❌');
|
||||
matrix.utils.sendError(event, roomId, e);
|
||||
});
|
||||
};
|
||||
|
|
|
@ -1,39 +1,26 @@
|
|||
exports.runQuery = function (matrixClient, room) {
|
||||
exports.runQuery = function (roomId) {
|
||||
setInterval(() => {
|
||||
axios({
|
||||
method: 'GET',
|
||||
url: `${config.fediverse.domain}/api/v1/timelines/home`,
|
||||
headers: { Authorization: `Bearer ${fediverse_auth.access_token}` },
|
||||
}).then((events) => {
|
||||
let lastEvent = JSON.parse(localStorage.getItem('timeline'));
|
||||
localStorage.setItem('timeline', JSON.stringify(events.data[0].created_at, null, 2));
|
||||
|
||||
if (lastEvent !== events.data[0].created_at) {
|
||||
if (events.data[0].reblog === null) {
|
||||
matrixClient.sendHtmlNotice(room.roomId,
|
||||
'',
|
||||
`<b><a href="${config.fediverse.domain}/notice/${events.data[0].id}">${events.data[0].account.acct}</a>
|
||||
<blockquote><i>${events.data[0].content}</i><br>
|
||||
${events.data[0].media_attachments.map(media =>
|
||||
`<a href="${media.remote_url}">`+`${media.description}`+'</a>'
|
||||
).join('<br>')}
|
||||
(id: ${events.data[0].id}) ${registrar.media.visibilityEmoji(events.data[0].visibility)}
|
||||
</blockquote>`);
|
||||
} else {
|
||||
matrixClient.sendHtmlNotice(room.roomId,
|
||||
'',
|
||||
`<b><a href="${config.fediverse.domain}/${events.data[0].account.id}">
|
||||
${events.data[0].account.acct}</a>
|
||||
<font color="#7886D7">has <a href="${config.fediverse.domain}/notice/${events.data[0].id}">repeated</a>:
|
||||
<blockquote><a href="${events.data[0].reblog.account.url}">${events.data[0].reblog.account.acct}</a></blockquote>
|
||||
<blockquote>${events.data[0].content}<br>
|
||||
${events.data[0].media_attachments.map(media =>
|
||||
`<a href="${media.remote_url}">`+`Proxied image, no description available.`+'</a>'
|
||||
).join('<br>')}
|
||||
<br>(id: ${events.data[0].id}) ${registrar.media.visibilityEmoji(events.data[0].visibility)}
|
||||
</blockquote>`);
|
||||
headers: { Authorization: `Bearer ${fediverse.auth.access_token}` },
|
||||
})
|
||||
.then((res) => {
|
||||
let past = JSON.parse(localStorage.getItem('timeline'));
|
||||
if (past.length === 0) past = res.data;
|
||||
const events = res.data;
|
||||
const len = events.length;
|
||||
for (let i = len - 1; i >= 0; i--) {
|
||||
if (past.findIndex((x) => x.created_at === events[i].created_at) === -1) {
|
||||
if (events[i].created_at < past.slice(18, 19)[0].created_at) return;
|
||||
events[i].label = 'status';
|
||||
fediverse.utils.formatter(events[i], roomId);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}, 8000);
|
||||
localStorage.setItem('timeline', JSON.stringify(events, null, 2));
|
||||
})
|
||||
.catch((e) => {
|
||||
matrix.utils.sendError(null, roomId, e);
|
||||
});
|
||||
}, 30000);
|
||||
};
|
||||
|
|
|
@ -1,21 +1,19 @@
|
|||
const axios = require('axios');
|
||||
const fediverse_auth = JSON.parse(localStorage.getItem('fediverse_auth'));
|
||||
|
||||
exports.runQuery = function (matrixClient, room, userInput) {
|
||||
axios.get(`${config.fediverse.domain}/api/v1/accounts/${userInput}`).then((findUID) => {
|
||||
axios({
|
||||
method: 'POST',
|
||||
url: `${config.fediverse.domain}/api/v1/accounts/${findUID.data.id}/follow`,
|
||||
headers: { Authorization: `Bearer ${fediverse_auth.access_token}` },
|
||||
})
|
||||
.then((response) => {
|
||||
matrixClient.sendHtmlNotice(room.roomId,
|
||||
'',
|
||||
`Subscribed:
|
||||
<blockquote>${config.fediverse.domain}/${response.data.id}`);
|
||||
});
|
||||
}).catch((e) => {
|
||||
matrixClient.sendHtmlNotice(room.roomId,
|
||||
'', `${e}`);
|
||||
exports.runQuery = async function (roomId, event, userInput) {
|
||||
const loadingString = `Searching for ${userInput}...`;
|
||||
const original = await matrixClient.sendHtmlNotice(roomId, `${loadingString}`, `<code>${loadingString}</code>`);
|
||||
const found = [];
|
||||
const suggest = [];
|
||||
axios({
|
||||
method: 'GET',
|
||||
url: `${config.fediverse.domain}/api/v2/search?q=${userInput}&type=accounts`,
|
||||
headers: { Authorization: `Bearer ${fediverse.auth.access_token}` },
|
||||
}).then((findUserId) => {
|
||||
const results = findUserId.data.accounts;
|
||||
const len = results.length;
|
||||
for (let i = 0; i < len; i++) results[i].acct !== userInput ? suggest.push(results[i].acct) : found.push(results[i]);
|
||||
if (found.length > 0) return fediverse.utils.follow(roomId, found, event, original);
|
||||
if (suggest.length > 0) msg = `<code>${userInput} was not found, suggesting:</code><blockquote>${suggest.join('<br>')}</blockquote>`;
|
||||
if (suggest.length === 0) msg = `<code>No results found for: ${userInput}.</code>`;
|
||||
return matrix.utils.editNoticeHTML(roomId, original, msg);
|
||||
});
|
||||
};
|
||||
|
|
|
@ -1,24 +1,20 @@
|
|||
exports.runQuery = function (matrixClient, room, userInput) {
|
||||
exports.runQuery = function (roomId, event, userInput) {
|
||||
axios({
|
||||
method: 'POST',
|
||||
url: `${config.fediverse.domain}/api/v1/statuses`,
|
||||
headers: { Authorization: `Bearer ${fediverse_auth.access_token}` },
|
||||
headers: { Authorization: `Bearer ${fediverse.auth.access_token}` },
|
||||
data: {
|
||||
status: `@mordekai ${userInput}`,
|
||||
content_type: `text/markdown`,
|
||||
content_type: 'text/markdown',
|
||||
visibility: 'unlisted',
|
||||
expires_in: '7200'
|
||||
expires_in: '7200',
|
||||
},
|
||||
}).then((response) => {
|
||||
matrixClient.sendHtmlNotice(room.roomId,
|
||||
'',
|
||||
`<b>
|
||||
<blockquote><i>${response.data.content}<br>
|
||||
(id: ${response.data.id}</a>)
|
||||
</blockquote><br>`);
|
||||
})
|
||||
.then(() => {
|
||||
matrix.utils.addReact(event, '✅');
|
||||
})
|
||||
.catch((e) => {
|
||||
matrixClient.sendHtmlNotice(room.roomId,
|
||||
'', `${e}`);
|
||||
matrix.utils.addReact(event, '❌');
|
||||
matrix.utils.sendError(event, roomId, e);
|
||||
});
|
||||
};
|
||||
|
|
|
@ -1,47 +1,26 @@
|
|||
exports.runQuery = function (matrixClient, room) {
|
||||
exports.runQuery = function (roomId) {
|
||||
setInterval(() => {
|
||||
axios({
|
||||
method: 'GET',
|
||||
url: `${config.fediverse.domain}/api/v1/notifications`,
|
||||
headers: { Authorization: `Bearer ${fediverse_auth.access_token}` },
|
||||
}).then((events) => {
|
||||
let lastEvent = JSON.parse(localStorage.getItem('notifications'));
|
||||
localStorage.setItem('notifications', JSON.stringify(events.data[0].created_at, null, 2));
|
||||
if (lastEvent !== events.data[0].created_at) {
|
||||
if (events.data[0].type === 'follow') {
|
||||
matrixClient.sendHtmlNotice(room.roomId,
|
||||
'',
|
||||
`<b><a href="${config.fediverse.domain}/${events.data[0].account.id}">
|
||||
${events.data[0].account.acct}</a></b>
|
||||
<font color="#03b381"><b>has followed you.</b></font>
|
||||
<br><i>${events.data[0].account.note}</i>`);
|
||||
} else if (events.data[0].type === 'favourite') {
|
||||
matrixClient.sendHtmlNotice(room.roomId,
|
||||
'',
|
||||
`<b><a href="${config.fediverse.domain}/${events.data[0].account.id}">
|
||||
${events.data[0].account.acct}</a></b>
|
||||
<font color="#03b381"><b>has <a href="${events.data[0].status.uri}">favorited</a>
|
||||
your post:</b></font>
|
||||
<br><blockquote><i><b>${events.data[0].status.content}</i></b></blockquote>`);
|
||||
} else if (events.data[0].type === 'mention') {
|
||||
matrixClient.sendHtmlNotice(room.roomId,
|
||||
'',
|
||||
`<b><a href="${config.fediverse.domain}/${events.data[0].account.id}">
|
||||
${events.data[0].account.acct}</a></b>
|
||||
<font color="#03b381"><b>has <a href="${events.data[0].status.uri}">mentioned</a>
|
||||
you:</b></font><br><blockquote><i><b>${events.data[0].status.content}
|
||||
<br>(id: ${events.data[0].status.id}) ${registrar.media.visibilityEmoji(events.data[0].status.visibility)}</i></b>
|
||||
</blockquote>`);
|
||||
} else if (events.data[0].type === 'reblog') {
|
||||
matrixClient.sendHtmlNotice(room.roomId,
|
||||
'',
|
||||
`<b><a href="${config.fediverse.domain}/${events.data[0].account.id}">
|
||||
${events.data[0].account.acct}</a></b>
|
||||
<font color="#03b381"><b>has <a href="${events.data[0].status.uri}">repeated</a>
|
||||
your post:</b></font><br>
|
||||
<blockquote><i><b>${events.data[0].status.content}</i></b></blockquote>`);
|
||||
headers: { Authorization: `Bearer ${fediverse.auth.access_token}` },
|
||||
})
|
||||
.then((res) => {
|
||||
let past = JSON.parse(localStorage.getItem('notifications'));
|
||||
if (past.length === 0) past = res.data;
|
||||
const events = res.data;
|
||||
const len = events.length;
|
||||
for (let i = len - 1; i >= 0; i--) {
|
||||
if (past.findIndex((x) => x.created_at === events[i].created_at) === -1) {
|
||||
if (events[i].created_at < past.slice(18, 19)[0].created_at) return;
|
||||
events[i].label = 'notifications';
|
||||
fediverse.utils.formatter(events[i], roomId);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}, 8000);
|
||||
localStorage.setItem('notifications', JSON.stringify(events, null, 2));
|
||||
})
|
||||
.catch((e) => {
|
||||
matrix.utils.sendError(null, roomId, e);
|
||||
});
|
||||
}, 30000);
|
||||
};
|
||||
|
|
|
@ -1,18 +1,14 @@
|
|||
exports.runQuery = function (matrixClient, room, userInput) {
|
||||
exports.runQuery = function (roomId, event, userInput) {
|
||||
axios({
|
||||
method: 'POST',
|
||||
url: `${config.fediverse.domain}/api/v1/statuses/${userInput}/pin`,
|
||||
headers: { Authorization: `Bearer ${fediverse_auth.access_token}` },
|
||||
}).then((response) => {
|
||||
matrixClient.sendHtmlNotice(room.roomId,
|
||||
'',
|
||||
`Pinned:
|
||||
<blockquote><i><a href="${config.fediverse.domain}/notice/${response.data.id}">
|
||||
${response.data.content}</a></i>
|
||||
</blockquote>`);
|
||||
headers: { Authorization: `Bearer ${fediverse.auth.access_token}` },
|
||||
})
|
||||
.then(() => {
|
||||
matrix.utils.addReact(event, '✅');
|
||||
})
|
||||
.catch((e) => {
|
||||
matrixClient.sendHtmlNotice(room.roomId,
|
||||
'', `${e}`);
|
||||
matrix.utils.addReact(event, '❌');
|
||||
matrix.utils.sendError(event, roomId, e);
|
||||
});
|
||||
};
|
||||
|
|
|
@ -1,19 +1,90 @@
|
|||
exports.runQuery = function (matrixClient, room, userInput) {
|
||||
axios({
|
||||
const qs = require('qs');
|
||||
const FormData = require('form-data');
|
||||
|
||||
const emojis = { public: '🌐', unlisted: '📝', private: '🔒️', direct: '✉️' };
|
||||
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;
|
||||
}
|
||||
};
|
||||
|
||||
const mediaDownload = async (url, { whitelist, blacklist }) => {
|
||||
const media = await axios({ method: 'GET', url, responseType: 'arraybuffer' });
|
||||
if (media.statusText !== 'OK' || blacklist.includes(media.headers['content-type'])) throw media;
|
||||
if (whitelist.length && !whitelist.includes(media.headers['content-type'])) throw media;
|
||||
return {
|
||||
data: media.data,
|
||||
filename: getFilename(media.headers['content-disposition']),
|
||||
mimetype: media.headers['content-type'],
|
||||
};
|
||||
};
|
||||
|
||||
const mediaUpload = async ({ domain }, { data, filename, mimetype }) => {
|
||||
const form = new FormData();
|
||||
form.append('file', data, {
|
||||
filename: filename || 'upload',
|
||||
contentType: mimetype,
|
||||
});
|
||||
const upload = await axios({
|
||||
method: 'POST',
|
||||
url: `${domain}/api/v1/media`,
|
||||
headers: form.getHeaders({ Authorization: `Bearer ${fediverse.auth.access_token}` }),
|
||||
data: form,
|
||||
});
|
||||
if (upload.statusText !== 'OK') throw upload;
|
||||
return upload.data.id;
|
||||
};
|
||||
|
||||
const run = async (roomId, content, replyId, mediaURL, subject) => {
|
||||
let mediaId = null;
|
||||
if (mediaURL) {
|
||||
const media = await mediaDownload(mediaURL, config.fediverse.mimetypes);
|
||||
mediaId = await mediaUpload(config.fediverse, media);
|
||||
}
|
||||
const response = await axios({
|
||||
method: 'POST',
|
||||
url: `${config.fediverse.domain}/api/v1/statuses`,
|
||||
headers: { Authorization: `Bearer ${fediverse_auth.access_token}` },
|
||||
data: { status: userInput, content_type: `text/markdown` },
|
||||
}).then((response) => {
|
||||
matrixClient.sendHtmlNotice(room.roomId,
|
||||
'',
|
||||
`<b>
|
||||
<blockquote><i>${response.data.content}<br>
|
||||
(id: ${response.data.id}</a>)
|
||||
</blockquote><br>`);
|
||||
})
|
||||
.catch((e) => {
|
||||
matrixClient.sendHtmlNotice(room.roomId,
|
||||
'', `${e}`);
|
||||
});
|
||||
headers: { Authorization: `Bearer ${fediverse.auth.access_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,
|
||||
}, { arrayFormat: 'brackets' }),
|
||||
});
|
||||
return fediverse.utils.sendEventWithMeta(roomId, `<a href="${response.data.url}">${response.data.id}</a>`, `redact ${response.data.id}`);
|
||||
};
|
||||
|
||||
exports.runQuery = async (roomId, userInput, { isReply, hasMedia, hasSubject }) => {
|
||||
try {
|
||||
const chunks = userInput.trim().split(' ');
|
||||
if (!chunks.length || chunks.length < !!isReply + !!hasMedia) throw '';
|
||||
let replyId = null;
|
||||
let mediaURL = null;
|
||||
const subject = hasSubject ? config.fediverse.subject : null;
|
||||
if (isReply) {
|
||||
replyId = chunks[0];
|
||||
chunks.shift();
|
||||
}
|
||||
if (hasMedia) {
|
||||
let url = new URL(chunks[0]);
|
||||
chunks.shift();
|
||||
if (url.protocol === 'mxc:' && url.hostname && url.pathname)
|
||||
url = new URL(`${config.matrix.domain}/_matrix/media/r0/download/${url.hostname}${url.pathname}`);
|
||||
if (url.protocol !== 'https:') throw '';
|
||||
if (!config.matrix.domains.includes(url.hostname)) throw '';
|
||||
if (!/^\/_matrix\/media\/r0\/download\/[^/]+\/[^/]+\/?$/.test(url.pathname)) throw '';
|
||||
mediaURL = url.toString();
|
||||
}
|
||||
return await run(roomId, chunks.join(' '), replyId, mediaURL, subject);
|
||||
} catch (e) {
|
||||
return matrixClient.sendHtmlNotice(roomId, 'Sad!', '<strong>Sad!</strong>').catch(() => {});
|
||||
}
|
||||
};
|
||||
|
|
|
@ -1,15 +1,14 @@
|
|||
exports.runQuery = function (matrixClient, room, userInput) {
|
||||
exports.runQuery = function (roomId, event, userInput) {
|
||||
axios({
|
||||
method: 'DELETE',
|
||||
url: `${config.fediverse.domain}/api/v1/statuses/${userInput}`,
|
||||
headers: { Authorization: `Bearer ${fediverse_auth.access_token}` },
|
||||
}).then((response) => {
|
||||
matrixClient.sendHtmlNotice(room.roomId,
|
||||
'',
|
||||
'<blockquote>Redacted.</blockquote');
|
||||
headers: { Authorization: `Bearer ${fediverse.auth.access_token}` },
|
||||
})
|
||||
.then(() => {
|
||||
matrix.utils.addReact(event, '✅');
|
||||
})
|
||||
.catch((e) => {
|
||||
matrixClient.sendHtmlNotice(room.roomId,
|
||||
'', `${e}`);
|
||||
matrix.utils.addReact(event, '❌');
|
||||
matrix.utils.sendError(event, roomId, e);
|
||||
});
|
||||
};
|
||||
|
|
|
@ -1,17 +1,15 @@
|
|||
exports.runQuery = function (matrixClient, room, userInput, ) {
|
||||
exports.runQuery = function (roomId, event, userInput) {
|
||||
axios({
|
||||
method: 'GET',
|
||||
url: `${config.fediverse.domain}/api/v1/statuses/${userInput}`,
|
||||
headers: { Authorization: `Bearer ${fediverse_auth.access_token}` },
|
||||
}).then((response) => {
|
||||
matrixClient.sendHtmlNotice(room.roomId,
|
||||
'',
|
||||
`<b><a href="${config.fediverse.domain}/notice/${response.data.id}">${response.data.account.acct}</a>
|
||||
<blockquote><i>${response.data.content}<br>
|
||||
${response.data.media_attachments.map(media =>
|
||||
`<a href="${media.remote_url}"><b>${media.description}</b></a>`)
|
||||
.join('<br>')}
|
||||
(id: ${response.data.id}</a>)
|
||||
</blockquote>`);
|
||||
headers: { Authorization: `Bearer ${fediverse.auth.access_token}` },
|
||||
})
|
||||
.then((response) => {
|
||||
response.label = 'status';
|
||||
fediverse.utils.formatter(response, roomId);
|
||||
})
|
||||
.catch((e) => {
|
||||
matrix.utils.addReact(event, '❌');
|
||||
matrix.utils.sendError(event, roomId, e);
|
||||
});
|
||||
};
|
||||
|
|
|
@ -1,19 +1,15 @@
|
|||
exports.runQuery = function (matrixClient, room, address, flaggedInput) {
|
||||
exports.runQuery = function (roomId, address, flaggedInput, event) {
|
||||
axios({
|
||||
method: 'POST',
|
||||
url: `${config.fediverse.domain}/api/v1/statuses`,
|
||||
headers: { Authorization: `Bearer ${fediverse_auth.access_token}` },
|
||||
data: { status: `@10grans@fedi.cc tip `+ flaggedInput + ` to `+address },
|
||||
}).then((response) => {
|
||||
matrixClient.sendHtmlNotice(room.roomId,
|
||||
'',
|
||||
`<b>
|
||||
<blockquote><i>Tipping ${response.data.content}<br>
|
||||
(id: ${response.data.id}</a>)
|
||||
</blockquote><br>`);
|
||||
headers: { Authorization: `Bearer ${fediverse.auth.access_token}` },
|
||||
data: { status: `@10grans@fedi.cc tip ${flaggedInput} to ${address}` },
|
||||
})
|
||||
.then(() => {
|
||||
matrix.utils.addReact(event, '✅');
|
||||
})
|
||||
.catch((e) => {
|
||||
matrixClient.sendHtmlNotice(room.roomId,
|
||||
'', `${e}`);
|
||||
matrix.utils.addReact(event, '❌');
|
||||
matrix.utils.sendError(event, roomId, e);
|
||||
});
|
||||
};
|
||||
|
|
|
@ -1,18 +1,19 @@
|
|||
exports.runQuery = function (matrixClient, room, userInput) {
|
||||
axios.get(`${config.fediverse.domain}/api/v1/accounts/${userInput}`).then((findUID) => {
|
||||
axios({
|
||||
method: 'POST',
|
||||
url: `${config.fediverse.domain}/api/v1/accounts/${findUID.data.id}/unfollow`,
|
||||
headers: { Authorization: `Bearer ${fediverse_auth.access_token}` },
|
||||
})
|
||||
.then((response) => {
|
||||
matrixClient.sendHtmlNotice(room.roomId,
|
||||
'',
|
||||
`Unsubscribed:
|
||||
<blockquote>${config.fediverse.domain}/${response.data.id}`);
|
||||
});
|
||||
}).catch((e) => {
|
||||
matrixClient.sendHtmlNotice(room.roomId,
|
||||
'', `${e}`);
|
||||
exports.runQuery = async function (roomId, event, userInput) {
|
||||
const loadingString = `Searching for ${userInput}...`;
|
||||
const original = await matrixClient.sendHtmlNotice(roomId, `${loadingString}`, `<code>${loadingString}</code>`);
|
||||
const found = [];
|
||||
const suggest = [];
|
||||
axios({
|
||||
method: 'GET',
|
||||
url: `${config.fediverse.domain}/api/v2/search?q=${userInput}&type=accounts`,
|
||||
headers: { Authorization: `Bearer ${fediverse.auth.access_token}` },
|
||||
}).then((findUserId) => {
|
||||
const results = findUserId.data.accounts;
|
||||
const len = results.length;
|
||||
for (let i = 0; i < len; i++) results[i].acct !== userInput ? suggest.push(results[i].acct) : found.push(results[i]);
|
||||
if (found.length > 0) return fediverse.utils.unfollow(roomId, found, event, original);
|
||||
if (suggest.length > 0) msg = `<code>${userInput} was not found, suggesting:</code><blockquote>${suggest.join('<br>')}</blockquote>`;
|
||||
if (suggest.length === 0) msg = `<code>No results found for: ${userInput}.</code>`;
|
||||
return matrix.utils.editNoticeHTML(roomId, original, msg);
|
||||
});
|
||||
};
|
||||
|
|
|
@ -1,18 +1,14 @@
|
|||
exports.runQuery = function (matrixClient, room, userInput) {
|
||||
exports.runQuery = function (roomId, event, userInput) {
|
||||
axios({
|
||||
method: 'POST',
|
||||
url: `${config.fediverse.domain}/api/v1/statuses/${userInput}/unpin`,
|
||||
headers: { Authorization: `Bearer ${fediverse_auth.access_token}` },
|
||||
}).then((response) => {
|
||||
matrixClient.sendHtmlNotice(room.roomId,
|
||||
'',
|
||||
`Unpinned:
|
||||
<blockquote><i><a href="${config.fediverse.domain}/notice/${response.data.id}">
|
||||
${response.data.content}</a></i>
|
||||
</blockquote>`);
|
||||
headers: { Authorization: `Bearer ${fediverse.auth.access_token}` },
|
||||
})
|
||||
.then(() => {
|
||||
matrix.utils.addReact(event, '✅');
|
||||
})
|
||||
.catch((e) => {
|
||||
matrixClient.sendHtmlNotice(room.roomId,
|
||||
'', `${e}`);
|
||||
matrix.utils.addReact(event, '❌');
|
||||
matrix.utils.sendError(event, roomId, e);
|
||||
});
|
||||
};
|
||||
|
|
14
commands/fediverse/unreblog.js
Normal file
14
commands/fediverse/unreblog.js
Normal file
|
@ -0,0 +1,14 @@
|
|||
exports.runQuery = function (roomId, event, userInput) {
|
||||
axios({
|
||||
method: 'POST',
|
||||
url: `${config.fediverse.domain}/api/v1/statuses/${userInput}/unreblog`,
|
||||
headers: { Authorization: `Bearer ${fediverse.auth.access_token}` },
|
||||
})
|
||||
.then(() => {
|
||||
matrix.utils.addReact(event, '✅');
|
||||
})
|
||||
.catch((e) => {
|
||||
matrix.utils.addReact(event, '❌');
|
||||
matrix.utils.sendError(event, roomId, e);
|
||||
});
|
||||
};
|
136
commands/fediverse/utils.js
Normal file
136
commands/fediverse/utils.js
Normal file
|
@ -0,0 +1,136 @@
|
|||
const sendEventWithMeta = async (roomId, content, meta) => {
|
||||
await matrixClient.sendEvent(roomId, 'm.room.message', {
|
||||
body: content.replace(/<[^<]+?>/g, ''),
|
||||
msgtype: 'm.notice',
|
||||
formatted_body: content,
|
||||
meta: meta,
|
||||
format: 'org.matrix.custom.html',
|
||||
});
|
||||
};
|
||||
|
||||
const hasAttachment = (res) => {
|
||||
if (!res.media_attachments) return '<br>';
|
||||
return res.media_attachments.map((media) => {
|
||||
const mediaURL = new URL(media.remote_url);
|
||||
media.name = new URLSearchParams(mediaURL.search).get('name') || 'Unknown file name.';
|
||||
return `File attachment: <a href="${media.remote_url}">${media.name}</a><br>`;
|
||||
}).join('<br>');
|
||||
};
|
||||
|
||||
const notifyFormatter = (res, roomId) => {
|
||||
userDetails = `<b><a href="${config.fediverse.domain}/${res.account.id}">
|
||||
${res.account.acct}</a></b>`;
|
||||
switch (res.type) {
|
||||
case 'follow':
|
||||
fediverse.auth.me !== res.account.url ? res.meta = 'follow' : res.meta = 'redact';
|
||||
meta = `${res.meta} ${res.account.id}`;
|
||||
content = `${userDetails}
|
||||
<font color="#03b381"><b>has followed you.</b></font>
|
||||
<br><blockquote><i>${res.account.note}</i></blockquote>`;
|
||||
sendEventWithMeta(roomId, content, meta);
|
||||
break;
|
||||
case 'favourite':
|
||||
fediverse.auth.me !== res.account.url ? res.meta = 'favourite' : res.meta = 'redact';
|
||||
meta = `${res.meta} ${res.status.id}`;
|
||||
content = `${userDetails}
|
||||
<font color="#03b381"><b>has <a href="${res.status.uri}">favorited</a>
|
||||
your post:</b></font>
|
||||
<br><blockquote><i><b>${res.status.content}</i></b></blockquote>`;
|
||||
sendEventWithMeta(roomId, content, res.meta);
|
||||
break;
|
||||
case 'mention':
|
||||
fediverse.auth.me !== res.account.url ? res.meta = 'mention' : res.meta = 'redact';
|
||||
meta = `${res.meta} ${res.status.id}`;
|
||||
content = `${userDetails}
|
||||
<font color="#03b381"><b>has <a href="${res.status.uri}">mentioned</a>
|
||||
you:</b></font><br><blockquote><i><b>${res.status.content}
|
||||
<br>(id: ${res.status.id}) ${registrar.post.visibilityEmoji(res.status.visibility)}</i></b>
|
||||
</blockquote>`;
|
||||
sendEventWithMeta(roomId, content, meta);
|
||||
break;
|
||||
case 'reblog':
|
||||
fediverse.auth.me !== res.account.url ? res.meta = 'reblog' : res.meta = 'redact';
|
||||
meta = `${res.meta} ${res.status.id}`;
|
||||
content = `${userDetails}
|
||||
<font color="#03b381"><b>has <a href="${res.status.uri}">repeated</a>
|
||||
your post:</b></font><br>
|
||||
<blockquote><i><b>${res.status.content}</i></b></blockquote>`;
|
||||
sendEventWithMeta(roomId, content, meta);
|
||||
break;
|
||||
default:
|
||||
throw 'Unknown notification type.';
|
||||
}
|
||||
};
|
||||
|
||||
const isOriginal = (res, roomId) => {
|
||||
if (res.data) res = res.data;
|
||||
userDetails = `<b><a href="${config.fediverse.domain}/${res.account.id}">
|
||||
${res.account.acct}</a>`;
|
||||
fediverse.auth.me !== res.account.url ? res.meta = 'status' : res.meta = 'redact';
|
||||
meta = `${res.meta} ${res.id}`;
|
||||
content = `${userDetails}
|
||||
<blockquote><i>${res.content}</i><br>
|
||||
${hasAttachment(res)}
|
||||
<br>(id: ${res.id}) ${registrar.post.visibilityEmoji(res.visibility)}
|
||||
</blockquote>`;
|
||||
sendEventWithMeta(roomId, content, meta);
|
||||
};
|
||||
|
||||
const isReblog = (res, roomId) => {
|
||||
if (res.data) res = res.data;
|
||||
userDetails = `<b><a href="${config.fediverse.domain}/${res.account.id}">
|
||||
${res.account.acct}</a>`;
|
||||
fediverse.auth.me !== res.account.url ? res.meta = 'status' : res.meta = 'unreblog';
|
||||
meta = `${res.meta} ${res.reblog.id}`;
|
||||
content = `${userDetails}
|
||||
<font color="#7886D7"><b>has <a href="${config.fediverse.domain}/${res.reblog.id}">repeated</a>
|
||||
${res.reblog.account.acct}'s post:</b></font>
|
||||
<blockquote><i>${res.content}</i><br>
|
||||
${hasAttachment(res)}
|
||||
<br>(id: ${res.reblog.id}) ${registrar.post.visibilityEmoji(res.visibility)}
|
||||
</blockquote>`;
|
||||
sendEventWithMeta(roomId, content, meta);
|
||||
};
|
||||
|
||||
module.exports.sendEventWithMeta = sendEventWithMeta;
|
||||
|
||||
module.exports.formatter = (res, roomId) => {
|
||||
const filtered = (res.label === 'notifications')
|
||||
? notifyFormatter(res, roomId)
|
||||
: (res.reblog == null)
|
||||
? isOriginal(res, roomId)
|
||||
: isReblog(res, roomId);
|
||||
return filtered;
|
||||
};
|
||||
|
||||
module.exports.follow = (roomId, account, event, original) => {
|
||||
axios({
|
||||
method: 'POST',
|
||||
url: `${config.fediverse.domain}/api/v1/accounts/${account[0].id}/follow`,
|
||||
headers: { Authorization: `Bearer ${fediverse.auth.access_token}` },
|
||||
})
|
||||
.then(() => {
|
||||
matrix.utils.addReact(event, '✅');
|
||||
matrix.utils.editNoticeHTML(roomId, original, `<code>Followed ${account[0].acct}.</code>`);
|
||||
})
|
||||
.catch((e) => {
|
||||
matrix.utils.addReact(event, '❌');
|
||||
matrix.utils.sendError(event, roomId, e);
|
||||
});
|
||||
};
|
||||
|
||||
module.exports.unfollow = (roomId, account, event, original) => {
|
||||
axios({
|
||||
method: 'POST',
|
||||
url: `${config.fediverse.domain}/api/v1/accounts/${account[0].id}/unfollow`,
|
||||
headers: { Authorization: `Bearer ${fediverse.auth.access_token}` },
|
||||
})
|
||||
.then(() => {
|
||||
matrix.utils.addReact(event, '✅');
|
||||
matrix.utils.editNoticeHTML(roomId, original, `<code>Unfollowed ${account[0].acct}.</code>`);
|
||||
})
|
||||
.catch((e) => {
|
||||
matrix.utils.addReact(event, '❌');
|
||||
matrix.utils.sendError(event, roomId, e);
|
||||
});
|
||||
};
|
Loading…
Add table
Add a link
Reference in a new issue