2020-05-07 13:50:46 +00:00
|
|
|
const simpleGet = require('simple-get')
|
|
|
|
|
|
|
|
const store = {
|
|
|
|
urls: [],
|
|
|
|
checkIntervalSeconds: null,
|
|
|
|
alreadyAdded: new Set(),
|
|
|
|
alreadyRemoved: new Set(),
|
2020-05-07 14:27:42 +00:00
|
|
|
serverAccountId: null,
|
|
|
|
timeout: null
|
2020-05-07 13:50:46 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
async function register ({
|
|
|
|
settingsManager,
|
2020-05-07 15:05:35 +00:00
|
|
|
storageManager,
|
2020-05-07 13:50:46 +00:00
|
|
|
peertubeHelpers,
|
|
|
|
registerSetting
|
|
|
|
}) {
|
|
|
|
const { logger } = peertubeHelpers
|
|
|
|
|
|
|
|
registerSetting({
|
|
|
|
name: 'blocklist-urls',
|
|
|
|
label: 'Blocklist URLs (one per line)',
|
|
|
|
type: 'input-textarea',
|
|
|
|
private: true
|
|
|
|
})
|
|
|
|
|
|
|
|
registerSetting({
|
|
|
|
name: 'check-seconds-interval',
|
|
|
|
label: 'Blocklist check frequency (seconds)',
|
2020-05-07 13:57:12 +00:00
|
|
|
type: 'input',
|
2020-05-07 13:50:46 +00:00
|
|
|
private: true,
|
|
|
|
default: 3600 // 1 Hour
|
|
|
|
})
|
|
|
|
|
|
|
|
const serverActor = await peertubeHelpers.server.getServerActor()
|
|
|
|
store.serverAccountId = serverActor.Account.id
|
|
|
|
|
|
|
|
const settings = await settingsManager.getSettings([ 'check-seconds-interval', 'blocklist-urls' ])
|
|
|
|
|
2020-05-07 15:05:35 +00:00
|
|
|
await load(peertubeHelpers, storageManager, settings['blocklist-urls'], settings['check-seconds-interval'])
|
2020-05-07 13:50:46 +00:00
|
|
|
|
|
|
|
settingsManager.onSettingsChange(settings => {
|
2020-05-07 15:05:35 +00:00
|
|
|
load(peertubeHelpers, storageManager, settings['blocklist-urls'], settings['check-seconds-interval'])
|
2020-05-07 13:50:46 +00:00
|
|
|
.catch(err => logger.error('Cannot load auto mute plugin.', { err }))
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
async function unregister () {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
module.exports = {
|
|
|
|
register,
|
|
|
|
unregister
|
|
|
|
}
|
|
|
|
|
|
|
|
// ############################################################################
|
|
|
|
|
2020-05-07 15:05:35 +00:00
|
|
|
async function load (peertubeHelpers, storageManager, blocklistUrls, checkIntervalSeconds) {
|
2020-05-07 13:50:46 +00:00
|
|
|
const { logger } = peertubeHelpers
|
|
|
|
|
2020-05-07 14:27:42 +00:00
|
|
|
if (store.timeout) clearTimeout(store.timeout)
|
|
|
|
|
2020-05-07 13:50:46 +00:00
|
|
|
store.checkIntervalSeconds = checkIntervalSeconds
|
|
|
|
|
|
|
|
store.urls = (blocklistUrls || '').split('\n')
|
|
|
|
.filter(url => !!url)
|
|
|
|
|
|
|
|
if (store.urls.length === 0) {
|
|
|
|
logger.info('Do not load auto mute plugin because of empty blocklist URLs.')
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
logger.info('Loaded %d blocklist URLs for auto mute plugin.', store.urls.length, { urls: store.urls })
|
2020-05-07 14:27:42 +00:00
|
|
|
|
2020-05-07 15:05:35 +00:00
|
|
|
runLater(peertubeHelpers, storageManager)
|
2020-05-07 13:50:46 +00:00
|
|
|
}
|
|
|
|
|
2020-05-07 15:05:35 +00:00
|
|
|
async function runCheck (peertubeHelpers, storageManager) {
|
2020-05-07 13:50:46 +00:00
|
|
|
const { logger } = peertubeHelpers
|
|
|
|
|
2020-05-07 15:05:35 +00:00
|
|
|
if (store.urls.length === 0) return runLater(peertubeHelpers, storageManager)
|
|
|
|
|
|
|
|
let lastChecks = await storageManager.getData('last-checks')
|
|
|
|
if (!lastChecks) lastChecks = {}
|
|
|
|
|
|
|
|
const newLastCheck = {}
|
2020-05-07 13:50:46 +00:00
|
|
|
|
|
|
|
for (const url of store.urls) {
|
|
|
|
try {
|
|
|
|
const { data } = await get(url)
|
2020-05-07 15:05:35 +00:00
|
|
|
newLastCheck[url] = new Date().toISOString()
|
|
|
|
|
|
|
|
const lastCheckTime = lastChecks[url]
|
|
|
|
? new Date(lastChecks[url]).getTime()
|
|
|
|
: 0
|
2020-05-07 13:50:46 +00:00
|
|
|
|
|
|
|
if (Array.isArray(data.data) === false) {
|
|
|
|
throw new Error('JSON response is not valid.')
|
|
|
|
}
|
|
|
|
|
|
|
|
for (const entity of data.data) {
|
|
|
|
if (!entity.value) throw new Error('JSON entity is not valid.')
|
|
|
|
|
2020-05-07 15:05:35 +00:00
|
|
|
// We already checked this entity?
|
|
|
|
if (entity.updatedAt) {
|
|
|
|
const updatedAtTime = new Date(entity.updatedAt).getTime()
|
|
|
|
|
|
|
|
if (updatedAtTime < lastCheckTime) continue
|
|
|
|
}
|
|
|
|
|
2020-05-07 13:50:46 +00:00
|
|
|
if (entity.action === 'remove') await removeEntity(peertubeHelpers, entity.value)
|
|
|
|
else await addEntity(peertubeHelpers, entity.value)
|
|
|
|
}
|
|
|
|
} catch (err) {
|
|
|
|
logger.warn('Cannot get mute blocklist from %s.', url, { err })
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-05-07 15:05:35 +00:00
|
|
|
await storageManager.storeData('last-checks', newLastCheck)
|
|
|
|
|
|
|
|
runLater(peertubeHelpers, storageManager)
|
2020-05-07 13:50:46 +00:00
|
|
|
}
|
|
|
|
|
2020-05-07 15:05:35 +00:00
|
|
|
function runLater (peertubeHelpers, storageManager) {
|
2020-05-07 14:27:42 +00:00
|
|
|
const { logger } = peertubeHelpers
|
|
|
|
|
|
|
|
logger.debug('Will run auto mute check in %d seconds.', store.checkIntervalSeconds)
|
|
|
|
|
2020-05-07 15:05:35 +00:00
|
|
|
store.timeout = setTimeout(() => {
|
|
|
|
runCheck(peertubeHelpers, storageManager)
|
|
|
|
}, store.checkIntervalSeconds * 1000)
|
2020-05-07 13:50:46 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
function get (url) {
|
|
|
|
return new Promise((resolve, reject) => {
|
2020-05-07 13:57:12 +00:00
|
|
|
simpleGet.concat({ url, method: 'GET', json: true }, function (err, res, data) {
|
2020-05-07 13:50:46 +00:00
|
|
|
if (err) return reject(err)
|
|
|
|
|
|
|
|
return resolve({ res, data })
|
|
|
|
})
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
function addEntity (peertubeHelpers, value) {
|
2020-05-07 13:57:12 +00:00
|
|
|
const { moderation, logger } = peertubeHelpers
|
2020-05-07 13:50:46 +00:00
|
|
|
|
|
|
|
if (store.alreadyAdded.has(value)) return
|
|
|
|
|
|
|
|
store.alreadyRemoved.delete(value)
|
|
|
|
store.alreadyAdded.add(value)
|
|
|
|
|
2020-05-07 13:57:12 +00:00
|
|
|
logger.info('Auto mute %s from blocklist.', value)
|
|
|
|
|
2020-05-07 13:50:46 +00:00
|
|
|
// Account
|
|
|
|
if (value.includes('@')) {
|
|
|
|
return moderation.blockAccount({ byAccountId: store.serverAccountId, handleToBlock: value })
|
|
|
|
}
|
|
|
|
|
|
|
|
// Server
|
|
|
|
return moderation.blockServer({ byAccountId: store.serverAccountId, hostToBlock: value })
|
|
|
|
}
|
|
|
|
|
|
|
|
function removeEntity (peertubeHelpers, value) {
|
2020-05-07 13:57:12 +00:00
|
|
|
const { moderation, logger } = peertubeHelpers
|
2020-05-07 13:50:46 +00:00
|
|
|
|
|
|
|
if (store.alreadyRemoved.has(value)) return
|
|
|
|
|
|
|
|
store.alreadyAdded.delete(value)
|
|
|
|
store.alreadyRemoved.add(value)
|
|
|
|
|
2020-05-07 13:57:12 +00:00
|
|
|
logger.info('Auto removing mute %s from blocklist.', value)
|
|
|
|
|
2020-05-07 13:50:46 +00:00
|
|
|
// Account
|
|
|
|
if (value.includes('@')) {
|
2020-05-07 14:27:42 +00:00
|
|
|
return moderation.unblockAccount({ byAccountId: store.serverAccountId, handleToUnblock: value })
|
2020-05-07 13:50:46 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Server
|
2020-05-07 14:27:42 +00:00
|
|
|
return moderation.unblockServer({ byAccountId: store.serverAccountId, hostToUnblock: value })
|
2020-05-07 13:50:46 +00:00
|
|
|
}
|