Skip to content

Commit

Permalink
Update material-ui, revert AVA update (see desc) and port more commands.
Browse files Browse the repository at this point in the history
More commands have been ported to the newer, custom architecture.
Next.js uses Babel 7.0.0-beta.47 and AVA used Babel 7.0.0-rc.1 (approx).
Somehow there was a conflict, which is why AVA version is reverted.
Latest AVA and Next.js 7 (canary) both use Babel 7 stable.
When Next.js 7 is released we will update and resolve conflict.

Breakage: bot callback does not run if no command was evaluated.
Fix: move callback for the client into the main callback.
Breakage: warn command non-functional.
Fix: N/A
  • Loading branch information
retrixe committed Sep 8, 2018
1 parent f603b5f commit b9ac400
Show file tree
Hide file tree
Showing 14 changed files with 1,117 additions and 1,028 deletions.
8 changes: 4 additions & 4 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,8 @@
"node": ">=6.5.0"
},
"dependencies": {
"@material-ui/core": "^1.2.0",
"@material-ui/icons": "^1.1.0",
"@material-ui/core": "^3.0.1",
"@material-ui/icons": "^3.0.1",
"apollo-boost": "^0.1.4",
"eris": "retrixe/eris",
"graphql": "^0.13.2",
Expand All @@ -28,7 +28,7 @@
"json5": "^0.5.1",
"mathjs": "^4.1.1",
"mongodb": "^3.0.6",
"next": "^6.1.1",
"next": "^6.1.2",
"react": "^16.2.0",
"react-apollo": "^2.1.3",
"react-dom": "^16.2.0"
Expand All @@ -39,7 +39,7 @@
"@types/node": "^8.0.53",
"@types/react": "^16.0.36",
"@zeit/next-typescript": "^1.1.0",
"ava": "^1.0.0-beta.6",
"ava": "1.0.0-beta.5",
"eslint": "^5.1.0",
"eslint-config-standard": "^11.0.0",
"eslint-config-standard-react": "^6.0.0",
Expand Down
65 changes: 46 additions & 19 deletions server/bot/client.ts
Original file line number Diff line number Diff line change
@@ -1,16 +1,37 @@
// eslint-disable-next-line standard/object-curly-even-spacing
import { Message, Client, MessageContent, CommandGeneratorFunction } from 'eris'
import { Message, MessageContent, CommandGeneratorFunction } from 'eris'
import { DB, Command as IveBotCommand, IveBotCommandGenerator } from './imports/types'
import { Db } from 'mongodb'
import Client from './imports/CustomClient'
import { getInsult } from './imports/tools'
import botCallback from '.'

function isEquivalent (a: { [index: string]: boolean }, b: { [index: string]: boolean }) {
// Create arrays of property names
var aProps = Object.getOwnPropertyNames(a)
var bProps = Object.getOwnPropertyNames(b)

// If number of properties is different, objects are not equivalent
if (aProps.length !== bProps.length) return false

for (var i = 0; i < aProps.length; i++) {
var propName = aProps[i]

// If values of same property are not equal, objects are not equivalent
if (a[propName] !== b[propName]) return false
}

// If we made it this far, objects are considered equivalent
return true
}

export class Command {
name: string // eslint-disable-next-line no-undef
aliases: string[] // eslint-disable-next-line no-undef
generators: (client: Client, db?: DB, mongoDB?: Db) => ({ // eslint-disable-next-line no-undef
generator: IveBotCommandGenerator,
// eslint-disable-next-line no-undef
postGenerator: (message: Message, args: string[], sent?: Message) => void
postGenerator?: (message: Message, args: string[], sent?: Message) => void
})
argsRequired: boolean // eslint-disable-line no-undef
caseInsensitive: boolean // eslint-disable-line no-undef
Expand All @@ -24,7 +45,11 @@ export class Command {
hidden: boolean // eslint-disable-line no-undef
// eslint-disable-next-line no-undef
requirements: { // eslint-disable-next-line no-undef
userIDs: string[], roleNames: string[], custom: Function, permissions: {}, roleIDs: string[]
userIDs?: string[] // eslint-disable-next-line no-undef
roleNames?: string[], // eslint-disable-next-line no-undef
custom?: (message: Message) => boolean, // eslint-disable-next-line no-undef
permissions?: {}, // eslint-disable-next-line no-undef
roleIDs?: string[]
}

constructor (command: IveBotCommand) {
Expand Down Expand Up @@ -52,7 +77,7 @@ export class Command {
}
}

export class CommandParser {
export default class CommandParser {
commands: { [name: string]: Command } // eslint-disable-line no-undef
client: Client // eslint-disable-line no-undef
tempDB: DB // eslint-disable-line no-undef
Expand All @@ -62,6 +87,7 @@ export class CommandParser {
this.client = client
this.tempDB = tempDB
this.db = db
this.onMessage = this.onMessage.bind(this)
}

registerCommand = (command: IveBotCommand) => { // eslint-disable-line no-undef
Expand All @@ -73,23 +99,23 @@ export class CommandParser {
// No role name or ID impl.
const userIDs = command.requirements.userIDs // If it doesn't exist it's a pass.
? command.requirements.userIDs.includes(message.author.id)
: true // Next line calls custom if it exists.
const custom = command.requirements.custom ? command.requirements.custom() : true
: false // Next line calls custom if it exists.
const custom = command.requirements.custom ? command.requirements.custom(message) : false
// If it's not a guild there are no permissions.
if (message.channel.type !== 0) return userIDs || custom
const permissions = command.requirements.permissions
? Object.assign( // Assign the required permissions onto the member's permission.
? isEquivalent(Object.assign( // Assign the required permissions onto the member's permission.
message.member.permission.json, command.requirements.permissions
) === message.member.permission.json // This should eval true if user has permissions.
: true
), message.member.permission.json) // This should eval true if user has permissions.
: false
// If any of these are true, it's a go.
return userIDs || custom || permissions
}

async fixCommand (session: { // eslint-disable-next-line indent
generator: IveBotCommandGenerator, // eslint-disable-next-line indent
postGenerator: (message: Message, args: string[], sent?: Message) => void
}, message: Message, args: string[]) {
postGenerator?: (message: Message, args: string[], sent?: Message) => void
}, message: Message, args: string[]) { // eslint-disable-line indent
// Define 2 vars.
let messageToSend: MessageContent|void|Promise<MessageContent>|Promise<void>
let toProcess: MessageContent|void|Promise<MessageContent>|Promise<void>|MessageContent[]
Expand Down Expand Up @@ -127,17 +153,17 @@ export class CommandParser {
// We define a sent variable to keep track.
let sent
if ( // No permission protection is here as well.
messageToSend && message.member.guild.channels.find(i => i.id === message.channel.id)
messageToSend && message.member &&
message.member.guild.channels.find(i => i.id === message.channel.id)
.permissionsOf(this.client.user.id).has('sendMessages')
) sent = await message.channel.createMessage(messageToSend)
if (session.postGenerator) session.postGenerator(message, args, sent)
if (command.deleteCommand) message.delete('Automatically deleted by IveBot.')
}

onMessage (message: Message) {
// We need to add calls for the other message callback.
if (!message.content.split(' ')[0].startsWith('/')) return // Don't process it if it's not a command.
const commandExec = message.content.split(' ')[0].substr(1).toLowerCase()
if (!commandExec.startsWith('/')) return // Don't process it if it's not a command.
// Webhook and bot protection.
try { if (message.author.bot) return } catch (e) { return }
// Check for the commands in this.commands.
Expand All @@ -148,16 +174,17 @@ export class CommandParser {
try {
this.executeCommand(this.commands[keys[i]], message)
} catch (e) { message.channel.createMessage('IveBot has experienced an internal error.') }
break
} else if (this.commands[keys[i]].aliases.includes(commandExec)) {
return
} else if (
this.commands[keys[i]].aliases && this.commands[keys[i]].aliases.includes(commandExec)
) {
// Execute command.
try {
this.executeCommand(this.commands[keys[i]], message)
} catch (e) { message.channel.createMessage('IveBot has experienced an internal error.') }
break
return
}
}
botCallback(message, this.client, this.tempDB, this.db)
}
}
// if no command call the other callback in index.ts just cuz yeah
// go port everything in bot/commands to oldCommands and get forwardporting.. :v
87 changes: 87 additions & 0 deletions server/bot/commands/admin.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
import { Command } from '../imports/types'
import { getInsult, getUser } from '../imports/tools'
import { checkRolePosition } from '../imports/permissions'
import { Message } from 'eris'
// export { handleGiverole, handleTakerole } from './admin/roles'
export { handleWarn, handleWarnings, handleClearwarns, handleRemovewarn } from './admin/warn'
// export { handleMute, handleUnmute } from './admin/mute'
export { handleBan, handleUnban } from './admin/ban'

export const handlePurge: Command = {
name: 'purge',
opts: {
description: 'Bulk delete a set of messages.',
fullDescription: 'Bulk delete messages newer than 2 weeks.',
usage: '/purge <number greater than 0 and less than 100>',
example: '/purge 10',
guildOnly: true,
deleteCommand: true,
requirements: {
permissions: { 'manageMessages': true },
custom: (message) => (
message.member.guild.channels.find(i => i.id === message.channel.id)
.permissionsOf(message.author.id).has('manageMessages')
)
}
},
generators: (client) => ({
generator: async (message, args) => {
// Check if usage is correct.
if (
isNaN(+args[0]) || args.length !== 1 || +args[0] <= 0 || +args[0] > 100
) { return 'Correct usage: /purge <number greater than 0 and less than 100>' }
// Pre-defined variables.
let messages: Array<Message>
// Get the list of messages.
try {
messages = await client.getMessages(message.channel.id, +args.shift(), message.id)
} catch (e) { return 'Could not retrieve messages.' }
// Delete the messages.
try {
client.deleteMessages(message.channel.id, messages.map(i => i.id), args.join(' ') || 'Purge')
} catch (e) { return 'Could not delete messages. Are the messages older than 2 weeks?' }
}
})
}

export const handleKick: Command = {
name: 'kick',
opts: {
description: 'Kick someone.',
fullDescription: 'Kick someone.',
usage: '/kick <user by ID/username/mention> (reason)',
guildOnly: true,
example: '/kick voldemort you is suck',
requirements: { permissions: { 'kickMembers': true } }
},
generators: (client) => ({
generator: async (message, args) => {
// Find the user ID.
let user = getUser(message, args.shift())
if (!user) return `Specify a valid member of this guild, ${getInsult()}.`
// If the user cannot kick the person..
if (
checkRolePosition(message.member.guild.members.find(i => i.user === user)) >=
checkRolePosition(message.member)
) {
return `You cannot kick this person, you ${getInsult()}.`
}
// Now we kick the person.
try {
await client.kickGuildMember(message.member.guild.id, user.id, args.join(' '))
} catch (e) { return 'I am unable to kick that user.' }
client.createMessage((await client.getDMChannel(user.id)).id, args.length !== 0
? `You have been kicked from ${message.member.guild.name} for ${args.join(' ')}.`
: `You have been kicked from ${message.member.guild.name}.`
)
// WeChill
if (message.member.guild.id === '402423671551164416') {
client.createMessage('402437089557217290', args.length !== 0
? `**${user.username}#${user.discriminator}** has been kicked for **${args.join(' ')}**.`
: `**${user.username}#${user.discriminator}** has been kicked for not staying chill >:L `
)
}
return `**${user.username}#${user.discriminator}** has been kicked. **rip.**`
}
})
}
84 changes: 84 additions & 0 deletions server/bot/commands/admin/ban.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
import { User } from 'eris'
import { Command, FalseUser } from '../../imports/types'
import { checkRolePosition } from '../../imports/permissions'
import { getInsult, getUser } from '../../imports/tools'

export const handleBan: Command = {
name: 'ban',
opts: {
description: 'Ban someone.',
fullDescription: 'Ban someone.',
usage: '/ban <user by ID/username/mention> (reason)',
guildOnly: true,
example: '/ban voldemort you is suck',
requirements: { permissions: { 'banMembers': true } }
},
aliases: ['banana', 'nuke'],
generators: (client) => ({
generator: async (message, args) => {
// Find the user ID.
const userSpecified = args.shift()
let user: FalseUser|User = getUser(message, userSpecified)
if (!user && client.users.find(i => i.username === userSpecified)) {
user = client.users.find(i => i.username === userSpecified)
} else if (!user && client.users.find(i => i.id === userSpecified)) {
user = client.users.find(i => i.id === userSpecified)
} else if (!user && userSpecified.length === 18 && !isNaN(+userSpecified)) {
user = { id: userSpecified, username: 'Unknown', discriminator: 'user' }
} else return 'I cannot find that user.'
if (!user) return `Specify a valid member of this guild, ${getInsult()}.`
// If the user cannot ban the person..
if (
checkRolePosition(message.member.guild.members.find(i => i.user === user)) >=
checkRolePosition(message.member)
) {
return `You cannot ban this person, you ${getInsult()}.`
}
// Now we ban the person.
try {
await client.banGuildMember(message.member.guild.id, user.id, 0, args.join(' '))
} catch (e) { return 'That person could not be banned.' }
client.createMessage((await client.getDMChannel(user.id)).id, args.length !== 0
? `You have been banned from ${message.member.guild.name} for ${args.join(' ')}.`
: `You have been banned from ${message.member.guild.name}.`
)
// WeChill
if (message.member.guild.id === '402423671551164416') {
client.createMessage('402437089557217290', args.length !== 0
? `**${user.username}#${user.discriminator}** has been banned for **${args.join(' ')}**.`
: `**${user.username}#${user.discriminator}** has been banned for not staying chill >:L `
)
}
return `**${user.username}#${user.discriminator}** has been banned. **rip.**`
}
})
}

export const handleUnban: Command = {
name: 'unban',
opts: {
description: 'Unban someone.',
fullDescription: 'Unban someone.',
usage: '/unban <user by ID/username/mention> (reason)',
example: '/unban voldemort wrong person',
guildOnly: true,
requirements: { permissions: { 'banMembers': true } }
},
generators: (client) => ({
generator: async (message, args) => {
// Find the user ID.
const userSpecified = args.shift()
let user: User
if (client.users.find(i => i.username === userSpecified)) {
user = client.users.find(i => i.username === userSpecified)
} else if (client.users.find(i => i.id === userSpecified)) {
user = client.users.find(i => i.id === userSpecified)
} else return 'I cannot find that user.'
// Now we unban the person.
try {
await client.unbanGuildMember(message.member.guild.id, user.id, args.join(' '))
} catch (e) { return 'That user could not be unbanned.' }
return `**${user.username}#${user.discriminator}** has been unbanned.`
}
})
}
Loading

0 comments on commit b9ac400

Please sign in to comment.