Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

network blocking #61

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,8 @@
"qrcode": "^1.4.4",
"random-access-memory": "^3.1.1",
"strftime": "^0.10.0",
"to2": "^1.0.0"
"to2": "^1.0.0",
"uniq": "^1.0.1"
},
"devDependencies": {
"jsdoc-to-markdown": "^5.0.2",
Expand Down
8 changes: 6 additions & 2 deletions src/cabal-details.js
Original file line number Diff line number Diff line change
Expand Up @@ -688,8 +688,8 @@ class CabalDetails extends EventEmitter {
this.users = new Map()
Object.keys(users).forEach(key => {
this.users[key] = new User(users[key])
})
this._initializeLocalUser(() => {
})
this._initializeLocalUser(() => {
loadModerationState(() => {
this.registerListener(cabal.moderation.events, 'update', (info) => {
let user = this.users[info.id]
Expand Down Expand Up @@ -719,6 +719,10 @@ class CabalDetails extends EventEmitter {
const changeOccurred = Object.keys(changedRole).filter(r => changedRole[r]).length > 0
if (!changeOccurred) {
this._emitUpdate('user-updated', { key: info.id, user })
if ((user.flags.get('@') || []).includes('block')) {
// drop the connection to blocked users immediately
this.core.removeConnection(info.id)
}
return
}
const type = doc.type.replace(/^flags\//, '')
Expand Down
12 changes: 11 additions & 1 deletion src/client.js
Original file line number Diff line number Diff line change
Expand Up @@ -191,7 +191,17 @@ class Client {
aliases: this.aliases
}, done)
this.cabals.set(cabal, details)
if (!opts.noSwarm) cabal.swarm()
if (!opts.noSwarm) cabal.swarm({
verify: function (remotePubKey, cb) {
cabal.moderation.getFlags({
id: remotePubKey.toString('hex'),
channel: '@'
}, function (err, flags) {
if (err) cb(err)
else cb(null, !flags.includes('block'))
})
}
})
function done () {
details._emitUpdate('init')
cb()
Expand Down
126 changes: 80 additions & 46 deletions src/commands.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ const qr = require('qrcode')
const pump = require('pump')
const to = require('to2')
const strftime = require('strftime')
const uniq = require('uniq')

module.exports = {
add: {
Expand Down Expand Up @@ -328,8 +329,8 @@ module.exports = {
actions: {
help: () => 'print out a historic log of the moderation actions applied by you, and your active moderators & admins',
call: (cabal, res, arg) => {
const promises = [cabal.moderation.getAdmins(), cabal.moderation.getMods()]
// get all moderation actions issued by our current mods & admins
const promises = [cabal.moderation.getAdmins(), cabal.moderation.getMods()]
// get all moderation actions issued by our current mods & admins
const messages = []
function processMessages (messages) {
res.info('moderation actions')
Expand All @@ -341,7 +342,7 @@ module.exports = {
res.info(message.text)
})
}
Promise.all(promises).then(results => {
Promise.all(promises).then(results => {
const keys = results[0].concat(results[1])
listNextKey()
function listNextKey () {
Expand All @@ -350,44 +351,44 @@ module.exports = {
return res.end()
}
var key = keys.shift()
const write = (row, enc, next) => {
const write = (row, enc, next) => {
if (!row) return
const name = cabal.users[key] ? cabal.users[key].name : key.slice(0, 8)
const target = cabal.users[row.content.id] ? cabal.users[row.content.id].name : row.content.id.slice(0, 8)
const type = row.type.split('/')[1]
const reason = row.content.reason
const role = row.content.flags[0]
const datestr = strftime('[%F %T] ', new Date(row.timestamp))
let text, action
if (['admin', 'mod'].includes(role)) { action = (type === 'add' ? 'added' : 'removed') }
if (role === 'hide') { action = (type === 'add' ? 'hid' : 'unhid') }
if (role === 'hide') {
text = `${datestr} ${name} ${action} ${target} ${reason}`
} else {
text = `${datestr} ${name} ${action} ${target} as ${role} ${reason}`
}
const flags = row.content.flags
const datestr = strftime('[%F %T]', new Date(row.timestamp))
const action = {
add: 'added',
remove: 'removed',
set: 'set'
}[type]
text = `${datestr} ${name} ${
formatAction({ type, flags, id: target, cabal})
} ${reason ? ': ' + reason : ''}`
messages.push({ text, timestamp: parseFloat(row.timestamp) })
next()
}
const end = (next) => {
}
const end = (next) => {
listNextKey()
next()
}
pump(cabal.core.moderation.listModerationBy(key), to.obj(write, end))
pump(cabal.core.moderation.listModerationBy(key), to.obj(write, end))
}
})
}
},
roles: {
help: () => 'list all your current moderators and admins',
call: (cabal, res, arg) => {
const promises = [cabal.moderation.getAdmins(), cabal.moderation.getMods()]
Promise.all(promises).then(results => {
const promises = [cabal.moderation.getAdmins(), cabal.moderation.getMods()]
Promise.all(promises).then(results => {
const keys = results[0].concat(results[1])
const print = (type) => {
return (k) => {
return (k) => {
res.info(`${cabal.users[k] ? cabal.users[k].name : k.slice(0, 8)}: ${type}`)
}
}
}
res.info('moderation roles')
if (keys.length === 1 && keys[0] === cabal.getLocalUser().key) {
Expand All @@ -400,7 +401,7 @@ module.exports = {
results[0].map(printAdmins)
results[1].map(printMods)
res.end()
})
})
}
},
inspect: {
Expand Down Expand Up @@ -586,31 +587,34 @@ function flagCmd (cmd, cabal, res, arg) {
var type = /^un/.test(cmd) ? 'remove' : 'add'
var flag = cmd.replace(/^un/, '')
var reason = args.slice(1).join(' ')
const reasonstr = reason ? '(reason: ' + reason + ')' : ''
cabal.moderation.setFlag(flag, type, channel, id, reason).then(() => {
if (['admin', 'mod'].includes(flag)) {
if (/^un/.test(cmd) && flag === 'mod' && !cabal.users[id].isModerator()) {
res.error(`${getPeerName(cabal, id)} is not a mod`)
} else if (/^un/.test(cmd) && flag === 'admin' && !cabal.users[id].isAdmin()) {
res.error(`${getPeerName(cabal, id)} is not an admin`)
} else if (!/^un/.test(cmd) && flag === 'mod' && cabal.users[id].isModerator()) {
res.error(`${getPeerName(cabal, id)} is already a mod`)
} else if (!/^un/.test(cmd) && flag === 'admin' && cabal.users[id].isAdmin()) {
res.error(`${getPeerName(cabal, id)} is already an admin`)
}
} else {
if (/^un/.test(cmd)) {
if (!cabal.users[id].isHidden()) {
res.error(`cannot unhide ${getPeerName(cabal, id)}: they are not hidden`)
}
} else {
if (cabal.users[id].isHidden()) {
res.error(`${getPeerName(cabal, id)} is already hidden`)
}
cabal.core.moderation.getFlags({ id, channel }, function (err, flags) {
if (err) return res.error(err)
if (type === 'remove' && !flags.includes(flag)) {
res.error(`user ${getPeerName(cabal, id)} does not have the flag: ${flag}`)
} else if (type === 'add' && flags.includes(flag)) {
res.error(`user ${getPeerName(cabal, id)} already has the flag: ${flag}`)
} else {
if (type === 'add') {
flags.push(flag)
uniq(flags)
} else if (type === 'remove') {
uniq(flags)
var i = flags.indexOf(flag)
if (i >= 0) flags.splice(i, 1)
}
}
res.end()
}).catch((err) => { res.error(err) })
var fname = { add: 'addFlags', remove: 'removeFlags' }[type]
cabal.core.moderation[fname]({
id,
channel,
flags: [flag],
reason
}, function (err) {
if (err) return res.error(err)
//res.info(formatAction({ type, flags: [flag], id, cabal }))
res.end()
})
}
})
}

function listCmd (cmd, cabal, res, arg) {
Expand Down Expand Up @@ -645,3 +649,33 @@ function listCmd (cmd, cabal, res, arg) {
function ucfirst (s) {
return s.replace(/^[a-z]/, function (c) { return c.toUpperCase() })
}

function formatAction ({ cabal, type, flags, id }) {
var verb = {
add: 'added',
remove: 'removed',
set: 'set'
}[type]
if (type === 'set') {
return `${verb} flags [${flags}] for user ${getPeerName(cabal, id)}`
} else if (type === 'add' && flags.length === 1 && flags[0] === 'hide') {
return `hid user ${getPeerName(cabal, id)}`
} else if (type === 'remove' && flags.length === 1 && flags[0] === 'hide') {
return `unhid user ${getPeerName(cabal, id)}`
} else if (type === 'add' && flags.length === 1 && flags[0] === 'block') {
return `blocked user ${getPeerName(cabal, id)}`
} else if (type === 'remove' && flags.length === 1 && flags[0] === 'block') {
return `unblocked user ${getPeerName(cabal, id)}`
} else if (type === 'add' && flags.length === 1 && flags[0] === 'admin') {
return `added user ${getPeerName(cabal, id)} as admin`
} else if (type === 'remove' && flags.length === 1 && flags[0] === 'admin') {
return `removed user ${getPeerName(cabal, id)} as admin`
} else if (type === 'add' && flags.length === 1 && flags[0] === 'mod') {
return `added user ${getPeerName(cabal, id)} as mod`
} else if (type === 'remove' && flags.length === 1 && flags[0] === 'mod') {
return `removed user ${getPeerName(cabal, id)} as mod`
} else {
var flag = flags.length === 1 ? 'flag ' + flags[0] : 'flags ['+flags+']'
return `${verb} ${flag} for user ${getPeerName(cabal, id)}`
}
}
10 changes: 5 additions & 5 deletions src/moderation.js
Original file line number Diff line number Diff line change
Expand Up @@ -65,14 +65,14 @@ class Moderation {
setFlag (flag, type, channel = '@', id, reason = '') {
// a list of [[id, reason]] was passed in
if (typeof id === 'object' && typeof id[Symbol.iterator] === 'function') {
const promises = id.map((entry) => {
const promises = id.map((entry) => {
return new Promise((resolve, reject) => {
this._flagCmd(flag, type, channel, entry[0], entry[1], (err) => {
this._flagCmd(flag, type, channel, entry[0], entry[1], (err) => {
if (err) { return reject(err) } else { resolve() }
})
})
})
})
return Promise.all(promises)
})
return Promise.all(promises)
}
return new Promise((resolve, reject) => {
this._flagCmd(flag, type, channel, id, reason, (err) => {
Expand Down