refactor: mastodon (#5373)
* fix: mastodon reblog media * fix: mastodon rm html filter * refactor: mastodon extract & rename function * feat: mastodon remove html tags for title * fix: mastodon rm filtering of toots with media * feat: include spoiler_text in content * feat: trivial format
This commit is contained in:
commit
3518fc64ea
|
|
@ -1,39 +1,17 @@
|
|||
const got = require('@/utils/got');
|
||||
const utils = require('./utils');
|
||||
|
||||
module.exports = async (ctx) => {
|
||||
const site = ctx.params.site;
|
||||
const account_id = ctx.params.account_id;
|
||||
const only_media = ctx.params.only_media ? true : false;
|
||||
const only_media = ctx.params.only_media ? 'true' : 'false';
|
||||
|
||||
const statuses_url = `http://${site}/api/v1/accounts/${account_id}/statuses`;
|
||||
const statuses_response = await got({
|
||||
method: 'get',
|
||||
url: statuses_url,
|
||||
});
|
||||
let data = statuses_response.data;
|
||||
|
||||
let account_data;
|
||||
if (data.length !== 0 && data[0].account !== null) {
|
||||
account_data = data[0].account;
|
||||
} else {
|
||||
const account_url = `http://${site}/api/v1/accounts/${account_id}`;
|
||||
const account_response = await got({
|
||||
method: 'get',
|
||||
url: account_url,
|
||||
});
|
||||
account_data = account_response.data;
|
||||
}
|
||||
|
||||
if (only_media === true) {
|
||||
data = data.filter((item) => item.media_attachments.length !== 0);
|
||||
}
|
||||
const { account_data, data } = await utils.getAccountStatuses(site, account_id, only_media);
|
||||
|
||||
ctx.state.data = {
|
||||
title: `${account_data.display_name} (@${account_data.acct})`,
|
||||
link: `${account_data.url}`,
|
||||
description: `${account_data.note}`,
|
||||
item: utils.ProcessFeed(data),
|
||||
item: utils.parseStatuses(data),
|
||||
allowEmpty: true,
|
||||
};
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1,87 +1,18 @@
|
|||
const got = require('@/utils/got');
|
||||
const utils = require('./utils');
|
||||
const config = require('@/config').value;
|
||||
const mastodonConfig = config.mastodon;
|
||||
|
||||
module.exports = async (ctx) => {
|
||||
const getAccountIdByAcct = async (acct) => {
|
||||
if (!(mastodonConfig.apiHost && mastodonConfig.accessToken && mastodonConfig.acctDomain)) {
|
||||
throw 'this route require api configuration, please check <a href="https://docs.rsshub.app/en/install/#configuration">documentation</a>';
|
||||
}
|
||||
|
||||
const site = mastodonConfig.apiHost;
|
||||
|
||||
const search_url = `http://${site}/api/v2/search`;
|
||||
const cacheUid = `mastodon_acct_id/${site}/${acct}`;
|
||||
|
||||
return await ctx.cache.tryGet(cacheUid, async () => {
|
||||
const search_response = await got({
|
||||
method: 'get',
|
||||
url: search_url,
|
||||
headers: {
|
||||
Authorization: `Bearer ${mastodonConfig.accessToken}`,
|
||||
},
|
||||
searchParams: {
|
||||
q: acct,
|
||||
type: 'accounts',
|
||||
},
|
||||
});
|
||||
const [acctUser, acctHost] = acct.split('@').filter((e) => e);
|
||||
let acctOnServer;
|
||||
|
||||
if (acctHost) {
|
||||
if (acctHost === mastodonConfig.acctDomain) {
|
||||
acctOnServer = acctUser;
|
||||
} else {
|
||||
acctOnServer = acctUser + '@' + acctHost;
|
||||
}
|
||||
} else {
|
||||
acctOnServer = acctUser;
|
||||
}
|
||||
|
||||
const accountData = search_response.data.accounts.filter((item) => item.acct === acctOnServer);
|
||||
|
||||
if (accountData.length === 0) {
|
||||
throw `acct ${acct} not found`;
|
||||
}
|
||||
return accountData[0].id;
|
||||
});
|
||||
};
|
||||
|
||||
const acct = ctx.params.acct;
|
||||
const only_media = ctx.params.only_media ? true : false;
|
||||
const only_media = ctx.params.only_media ? 'true' : 'false';
|
||||
|
||||
const site = mastodonConfig.apiHost;
|
||||
const account_id = await getAccountIdByAcct(acct);
|
||||
const { site, account_id } = await utils.getAccountIdByAcct(acct, ctx);
|
||||
|
||||
const statuses_url = `http://${site}/api/v1/accounts/${account_id}/statuses`;
|
||||
const statuses_response = await got({
|
||||
method: 'get',
|
||||
url: statuses_url,
|
||||
});
|
||||
let data = statuses_response.data;
|
||||
|
||||
let account_data;
|
||||
if (data.length !== 0 && data[0].account !== null) {
|
||||
account_data = data[0].account;
|
||||
} else {
|
||||
const account_url = `http://${site}/api/v1/accounts/${account_id}`;
|
||||
const account_response = await got({
|
||||
method: 'get',
|
||||
url: account_url,
|
||||
});
|
||||
account_data = account_response.data;
|
||||
}
|
||||
|
||||
if (only_media === true) {
|
||||
data = data.filter((item) => item.media_attachments.length !== 0);
|
||||
}
|
||||
const { account_data, data } = await utils.getAccountStatuses(site, account_id, only_media);
|
||||
|
||||
ctx.state.data = {
|
||||
title: `${account_data.display_name} (@${account_data.acct})`,
|
||||
link: `${account_data.url}`,
|
||||
description: `${account_data.note}`,
|
||||
item: utils.ProcessFeed(data),
|
||||
item: utils.parseStatuses(data),
|
||||
allowEmpty: true,
|
||||
};
|
||||
};
|
||||
|
|
|
|||
|
|
@ -13,6 +13,6 @@ module.exports = async (ctx) => {
|
|||
ctx.state.data = {
|
||||
title: `Local Public${ctx.params.only_media ? ' Media' : ''} Timeline on ${site}`,
|
||||
link: `http://${site}`,
|
||||
item: utils.ProcessFeed(list),
|
||||
item: utils.parseStatuses(list),
|
||||
};
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1,50 +1,123 @@
|
|||
const ProcessFeed = (data) =>
|
||||
const got = require('@/utils/got');
|
||||
|
||||
const parseStatuses = (data) =>
|
||||
data.map((item) => {
|
||||
const content = item.content
|
||||
? item.content
|
||||
.replace(/<span.*?>|<\/span.*?>/gm, '')
|
||||
.replace(/<(?:.|\n)*?>/gm, '\n')
|
||||
.split('\n')
|
||||
.filter((s) => s !== '')[0]
|
||||
: '';
|
||||
const content = item.content ? item.content.replace(/<span.*?>|<\/span.*?>/gm, '') : '';
|
||||
const contentRemovedHtml = content.replace(/<(?:.|\n)*?>/gm, '\n');
|
||||
|
||||
const media = item.media_attachments
|
||||
.map((item) => {
|
||||
switch (item.type) {
|
||||
case 'gifv':
|
||||
return `<br><video src="${item.url}" autoplay loop>GIF</video>`;
|
||||
case 'video':
|
||||
return `<br><video src="${item.url}" controls loop>Video</video>`;
|
||||
case 'image':
|
||||
return `<br><img src="${item.url}">`;
|
||||
default:
|
||||
return '';
|
||||
}
|
||||
})
|
||||
.join('');
|
||||
const mediaParse = (media_attachments) =>
|
||||
media_attachments
|
||||
.map((item) => {
|
||||
switch (item.type) {
|
||||
case 'gifv':
|
||||
return `<br><video src="${item.url}" autoplay loop>GIF</video>`;
|
||||
case 'video':
|
||||
return `<br><video src="${item.url}" controls loop>Video</video>`;
|
||||
case 'image':
|
||||
return `<br><img src="${item.url}">`;
|
||||
default:
|
||||
return '';
|
||||
}
|
||||
})
|
||||
.join('');
|
||||
|
||||
let author, link, titleAuthor;
|
||||
let author, link, titleAuthor, media;
|
||||
if (item.reblog !== null) {
|
||||
author = `${item.reblog.account.display_name} (@${item.reblog.account.acct})`;
|
||||
link = item.reblog.url;
|
||||
titleAuthor = `Re @${item.reblog.account.username}`;
|
||||
media = mediaParse(item.reblog.media_attachments);
|
||||
} else {
|
||||
author = `${item.account.display_name} (@${item.account.acct})`;
|
||||
link = item.url;
|
||||
titleAuthor = `@${item.account.username}`;
|
||||
media = mediaParse(item.media_attachments);
|
||||
}
|
||||
const titleText = item.sentitive === true ? `(CW) ${item.spoiler_text}` : content;
|
||||
const titleText = item.sentitive === true ? `(CW) ${item.spoiler_text}` : contentRemovedHtml;
|
||||
|
||||
return {
|
||||
title: `${titleAuthor}: "${titleText}"`,
|
||||
author: author,
|
||||
description: content + media,
|
||||
description: item.spoiler_text + '<hr />' + content + media,
|
||||
pubDate: new Date(item.created_at).toUTCString(),
|
||||
link: link,
|
||||
guid: item.uri,
|
||||
};
|
||||
});
|
||||
|
||||
async function getAccountStatuses(site, account_id, only_media) {
|
||||
const statuses_url = `http://${site}/api/v1/accounts/${account_id}/statuses?only_media=${only_media}`;
|
||||
const statuses_response = await got({
|
||||
method: 'get',
|
||||
url: statuses_url,
|
||||
});
|
||||
const data = statuses_response.data;
|
||||
|
||||
let account_data;
|
||||
if (data.length !== 0 && data[0].account !== null) {
|
||||
account_data = data[0].account;
|
||||
} else {
|
||||
const account_url = `http://${site}/api/v1/accounts/${account_id}`;
|
||||
const account_response = await got({
|
||||
method: 'get',
|
||||
url: account_url,
|
||||
});
|
||||
account_data = account_response.data;
|
||||
}
|
||||
|
||||
return { account_data, data };
|
||||
}
|
||||
|
||||
async function getAccountIdByAcct(acct, ctx) {
|
||||
const config = require('@/config').value;
|
||||
const mastodonConfig = config.mastodon;
|
||||
|
||||
if (!(mastodonConfig.apiHost && mastodonConfig.accessToken && mastodonConfig.acctDomain)) {
|
||||
throw 'this route require api configuration, please check <a href="https://docs.rsshub.app/en/install/#configuration">documentation</a>';
|
||||
}
|
||||
|
||||
const site = mastodonConfig.apiHost;
|
||||
|
||||
const search_url = `http://${site}/api/v2/search`;
|
||||
const cacheUid = `mastodon_acct_id/${site}/${acct}`;
|
||||
|
||||
const account_id = await ctx.cache.tryGet(cacheUid, async () => {
|
||||
const search_response = await got({
|
||||
method: 'get',
|
||||
url: search_url,
|
||||
headers: {
|
||||
Authorization: `Bearer ${mastodonConfig.accessToken}`,
|
||||
},
|
||||
searchParams: {
|
||||
q: acct,
|
||||
type: 'accounts',
|
||||
},
|
||||
});
|
||||
const [acctUser, acctHost] = acct.split('@').filter((e) => e);
|
||||
let acctOnServer;
|
||||
|
||||
if (acctHost) {
|
||||
if (acctHost === mastodonConfig.acctDomain) {
|
||||
acctOnServer = acctUser;
|
||||
} else {
|
||||
acctOnServer = acctUser + '@' + acctHost;
|
||||
}
|
||||
} else {
|
||||
acctOnServer = acctUser;
|
||||
}
|
||||
|
||||
const accountData = search_response.data.accounts.filter((item) => item.acct === acctOnServer);
|
||||
|
||||
if (accountData.length === 0) {
|
||||
throw `acct ${acct} not found`;
|
||||
}
|
||||
return accountData[0].id;
|
||||
});
|
||||
return { site, account_id };
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
ProcessFeed: ProcessFeed,
|
||||
parseStatuses: parseStatuses,
|
||||
getAccountStatuses: getAccountStatuses,
|
||||
getAccountIdByAcct: getAccountIdByAcct,
|
||||
};
|
||||
|
|
|
|||
Loading…
Reference in New Issue