Giter VIP home page Giter VIP logo

yuuko's Introduction

Pixel art of a shiny Umbreon doing a run

pronouns: she/her site: eritbh.me npm: eritbh donate on github sponsors donate on ko-fi

yuuko's People

Contributors

dependabot[bot] avatar eritbh avatar reboxer avatar skillz4killz avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar

yuuko's Issues

Allow Command Editing

Sometimes a user can make a silly typo and to prevent them from having to remake the entire command again, having the ability to reprocess a message on messageUpdate would be really cool.

From a developer perspective, this becomes really useful for the debug command as you can easily, edit the message incase you want to go 1 layer deeper into the object.

Duplicate PreCommand Event Listeners

image

The bottom should probably be changed to command but i think the whole thing should be named postCommand as it is consistent with preCommand and invalidCommand

More lenient roll behavior

  • Basic numbers (~roll 10 = ~roll 1d10)
  • Default d6 roll if no args present (~roll = ~roll 1d6)

Relevant: Should rewrite the dice roll command to use d20.js which makes the first one much easier. It also supports roll modifiers which would get rid of a thing I have on my whiteboard.

Have `processCommand` return more information about command execution

Discord conversation

Currently, custom messageCreate listeners can't get too much information about run commands when calling client.processCommand. It only returns a true or false value that indicates whether a command was run; it doesn't indicate what command was run, and it also treats a command's failing permission checks identically to a message not containing a command at all. The only way around this at the moment is to copy-paste the implementation of processCommand into the custom handler, which isn't well documented and isn't easy to work with.

Ideally, processCommand would return some object describing the execution that's occurred, including the command that was specified (if any), the arguments passed to it (*), and whether or not it was executed (and if not, maybe the permission check that caused the command not to run?). This would be a breaking change.

(* This might cause confusion paired with #25/#68, since the method I'm going with for argument parsing is to do the parsing within the command process rather than before the command is executed. This might result in confusing behavior, and given command arguments can basically be obtained by msg.content.split(' ').slice(1) (as long as your prefix doesn't have spaces), I'm not super convinced it would be worth it to provide the used arguments outside the actual command process.)

Redo documentation site entirely

this is dumb just do it, everything is outdated and its ur fault

TODOs:

  • Go through and make sure all important facets of the lib are documented
    • Make sure relevant doclets are supported
  • Make sure fetching info for different versions works
  • Eventually: clean up the code and make it less awful hopefully

Database integration

Configuration must be able to integrate with a database rather than a JSON store, though #5 will likely be developed with JSON first since it's easier.

Blocked on #5

Commands as a Map instead of Array.

Putting it here, so it could be useful to remember.
Making the client.commands as a map, this can be really good when getting a command by name for example, so instead of doing:

const command = client.commands.find(cmd => cmd.names[0].toLowerCase() === "commandname");

you can just do:

const command = client.commands.get("commandname");

Include a library of default commands

Being able to require('yuuko/commands/help') to get a reliable default help command would make things much easier for newcomers.

This will also involve restructuring things slightly so the compiled JS files live in the root of the project. That way you won't need /dist in the require path or whatever. Not a huge deal but it's something.

Make .reload work under ts-node

needs investigation, ts node might not work with require.cache the same way as node does. not sure how that will work exactly, hopefully it isn't literally impossible

Commands Inside Folder/Subfolders Don't Load

When you organize commands inside folders, they no longer load up. The bot does not register anything that is nested inside the commands folder. Ideally, this should go as many folders as nested until it loads all the files.

Per-guild configuration system

Needs to be flexible - possibly allow for storing configuration data on multiple databases.

Things we definitely want to store here for each guild:

  • Requirements for system
    • config command to manage options
    • options should store predefined data types
      • string (prefix)
      • number
      • channel, role, user (stores as ID, can be referenced by user via mention, ID, exact match for name or user#0000
  • Core config options
    • prefix
    • enabledCommands/disabledCommands
    • ignoredChannels/listenedChannels

Sandboxed evals for scripting languages

Can probably be done for js, python, ruby, etc. Can also be done all in one command probably. May want to rename existing eval to debug or something.

  • rename existing eval to debug (f967030)
  • create new stuff (ec10ab0)
    • ruby
    • js
    • python

Optional command argument parsing

Argument types with options that influence how they're parsed.

  • Users
    • by mention
    • by name#discrim
    • by id
    • by just name?
    • Options:
      • Is in server? (reject without running command process if not)
      • Is fuzzy? (enables the "just name" matching and takes nearest match, maybe?)
    • Resolve to: User instance (Member instance?)
  • Channels
    • by mention
    • by exact name
    • by id
    • Options:
      • Is visible to caller? (should probably be default)
      • Is text/voice/announcement/etc? (default to accepting any channel) (or maybe do this with separate types for text channels/voice channels?)
    • Resolve to: Channel object
  • Roles
    • by mention
    • by name (exact)
    • by id
    • Options:
      • User can edit? (reject if the user isn't higher than that role, or if the user doesn't have "manage roles" permission)
      • Mentionable? (meh)
    • Resolve to: Role object
  • Dates & Times
    • Probably use moment as a peerdep to parse time strings; without moment, do basic 2d 3h 15m parsing for times
    • absolute dates/times should also take time deltas from the current time and resolve to the corresponding date
    • Resolve to: Date objects or moment instances
  • Number
    • as you expect
    • maybe a separate type for integers? idk
    • options:
      • min/max
    • resolves to: a number duh (bigint for very large numbers?)
  • Text
    • Text with no line breaks or anything else fancy
    • Handle quoting as expected; try not to let the user do stupid shit by mistake
    • Interesting idea: If there's another argument after text, let the text expand until the next argument is met (make text the "default" argument type that fills in everything else as a single argument
    • Resolves to a string
  • LongText
    • Text that can have line breaks and stuff
    • Dunno how this should be formatted
  • Word
    • Like text but with no spaces or quoting or whatever
  • Colors? Other stuff?

Also how do I make this extensible so others can define their own argument types?

Deprecation: ClientOAuthApplication type

ClientOAuthApplication was deprecated in #56, which updated it to be a direct alias of the Eris type OAuthApplicationInfo. Yuuko's ClientOAuthApplication type was initially introduced before Eris included typings for OAuth application details, but it is now unnecessary; the Eris type can be swapped directly into consumer code.

The ClientOAuthApplication type will be removed in the 3.0.0 release (#94).

Deprecation: Client#addCommandDir, Client#addCommandFile, Client#reloadCommands

The Client methods addCommandDir, addCommandFile, and reloadCommands were all deprecated in #29, when the EventListener class was added. These functions now serve only as aliases for addDir, addFile, and reloadFiles respectively, which means that despite their names, they are not actually limited to working on commands, but impact both commands and event listeners loaded from files. These methods can be directly replaced in consumer code.

addCommandDir, addCommandFile, and reloadCommands will be removed in the 3.0.0 release (#94).

Remove specific version requirements from Eris peer dependency

I still need more time to evaluate whether a caught-require strategy and no declared peer dependency is a good way to go for Typescript projects, but given so much Eris development is happening on branches and I don't trust npm's semver resolver, we should switch to a version specifier of * or >=0.15.0 for better compatibility.

Related to #77

Pre-run condition checks on commands

Allow commands to set permissions that are required to execute the command. This could be done by a list of flags or a function which returns true or false based on the message that contains the command.

Slash commands/application commands

I've started messing around with the structures for application commands and it seems pretty viable to integrate them into Yuuko, though I'm not exactly sure how much of the existing Command structure they can share if any. Here's my initial notes.

Key differences and some thoughts on how we could unify the two structures:

  • Application commands can be global or per-guild, Yuuko commands only apply globally unless a custom requirement restricts them to a particular guild
    • Yuuko commands could be set up to be per-guild pretty easily, it should be trivial to have them share an option for that functionality
  • Application command handlers work with interactions, traditional commands are triggered by messages
    • Some core methods like createMessage exist on both structures in Eris, which helps, but ultimately there's no working around this difference
  • Application commands can be triggered by multiple sources (slash command, context buttons), traditional commands are triggered only by messages
    • More types of "traditional" commands built into Yuuko for events like reactions being added? I don't really see many ways to do anything about this though
    • Since context button commands take a single argument, it should probably be pretty easy to emulate those actions via a text-based traditional command that specifies the argument value
  • Application commands have structured arguments, Yuuko commands work solely on text content
    • Yuuko's argument parsing has been in the works for a while, but I wanted to take the route of throwing some parsing methods inside the command body rather than storing the argument types directly as parts of the command, so that's kinda out the window now
    • That said, the structured types Discord has are relatively simple, so it shouldn't be difficult to implement their parsing functionality
    • In order to avoid limiting the possible argument types for existing text-based commands, I think it's important that using structured arguments for text-based commands is optional
  • Application command subcommands can be triggered from any argument position, Yuuko subcommands are limited to the first argument position
    • Frankly Discord's idea for subcommands here is just better, Yuuko should take inspiration from this for its own command system regardless of these changes

So essentially I think what I want is a new Command-like class that can handle app commands as well as traditional commands, more or less providing a compatibility layer between application commands and text-based commands.

Something absolutely necessary for supporting application commands: When commands are registered to the client, the client is responsible for verifying that the commands exist in the right place on the server and updating things if not. Consumers shouldn't have to worry about posting to the API to update their commands when changes are made, that's the library's job.

Allow exporting multiple commands/event listeners from a single file

Thought I had an issue for this already, guess not. Files loaded via addCommandFile/addFile should be able to export multiple commands or event listeners for registration.

Easiest way to go would probably be to support default exports being arrays; named exports are inconsistent between JS and TS and will make things a pain, but can be investigated later. Ultimately though I don't think translating named exports is a great idea since the actual names are unused by Yuuko.

Remove setavatar command

Reimplement the existing command with http/https builtin modules, having a peer dep for this is annoying.

Export `CommandWithHelp` for use with default help command

Adding help to a command is not great in Typescript right now.

const command = new Command(...);
(command as Command & {help: any}).help = {...};
export default command;

It would be nice if the default help command exported a subclass that could be used to create a command with help preattached.

class CommandWithHelp extends Command {
  constructor (name, help, process, requirements) {
    super(name, help, requirements);
    this.help = help;
  }
}

Move to npm

Yarn has started being more annoying than plain npm, let's just switch back to using npm as our package manager

Subcommands

Let commands have other commands in them. e.g. ~tag tagname != ~tag create tagname etc.

Some concerns:

  • Should subcommands be full-blown Command instances, or just plain objects passed to the constructor? Or should subcommands just be done with a space in the name or something like that?
  • Will we need a breaking API change to modify the constructor for this? If a command has subcommands, its process should be optional and should print a list of subcommands by default I think.
  • some other stuff I'll write down in a bit when I get to work

TODOs:

  • Plan structure/interface
  • Actually implement

An idea for generic "hooks"

I have an idea for adding generic "hooks" to the bot that can run code when certain things happen (like events) and influence the execution flow by returning values (not like events). This needs research, but the idea is to have an event-like system that doesn't just emit when things happen, but also has the capability of asking the library consumer for information when it needs it.

Areas where this would be useful:

  • Setting custom prefixes: This could be done as a hook that returns an array of valid prefixes. The current implementation of custom prefixes is similar to what I see happening with the "hook" system in general, and I basically want to make it more generic.
  • Preventing commands from executing before commands are even processed: A hook into the early stages of the handleMessage method (which is currently run from inside messageCreate event) that lets you return a specific value if you don't want to execute commands from the created message. Or something like that.
  • there's probably more but I can't think of any others atm rip

Things to think about:

  • Is there a well-established way to do stuff like this?
  • How will hooks and existing events coexist?
  • Is this even a good idea??????

Command Names Casing

Would it be possible to .toLowerCase() in the command handler. Some of my users prefer to use capitals and are getting frustrated they can't.

image

Deprecation: Client#setGlobalRequirements, Client ignoreGlobalRequirements option

The Client#setGlobalRequirements method and the ignoreGlobalRequirements client option were both deprecated in #75, with the addition of the globalCommandRequirements client option.

Uses of Client#setGlobalRequirements can be replaced with usage of the globalCommandRequirements option like so:

// old
import {Client} from 'yuuko';
const bot = new Client({
  ...
});
bot.setGlobalRequirements(yourGlobalRequirements);

// new
import {Client} from 'yuuko';
const bot = new Client({
  globalCommandRequirements: yourGlobalRequirements,
  ...
});

Uses of the ignoreGlobalRequirements option can be replaced with conditionally setting globalCommandRequirements, like so:

// old
import {Client} from 'yuuko';
const bot = new Client({
  globalCommandRequirements: yourGlobalRequirements,
  ignoreGlobalRequirements: process.env.NODE_ENV !== 'production',
  ...
});

// new
import {Client} from 'yuuko';
const bot = new Client({
  globalCommandRequirements: process.env.NODE_ENV !== 'production' ? {} : yourGlobalRequirements,
  ...
});

Client#setGlobalRequirements and the ignoreGlobalRequirements client option will be removed in the 3.0.0 release (#94).

`reloadFiles()` not working

Couple reports of Client#reloadFiles() not reloading properly, making an issue now because I keep forgetting to look into it

Deprecation: Client#defaultPrefix

The Client#defaultPrefix property was deprecated in 7a4c65d when it was replaced with Client#prefix. defaultPrefix is now a getter/setter pair that aliases directly to prefix, so it can be directly replaced in consumer code.

Client#defaultPrefix will be removed in the 3.0.0 release (#94).

Make color command even more lenient about color parsing

For function colors (rgb, hsl, hsv):

  • Values can be separated by commas, whitespace, or both
  • Parens are optional
  • If the function name is hsl or hsv, percent signs are optional
  • If there is no function name and there are percent signs, assume hsl, else assume rgb

For hex colors:

  • Allow 000000 --> #000000 (3380f27)
  • Allow #0 --> #000000
  • Allow #01 --> #010101

Eris Verisons

Is this version of Yuuko compatible with the new Discord API and the new dev version of Eris?

Generic plugins

const {Plugin, Command} = require('yuuko')

module.exports = new Plugin('pluginName', {
  init (client) {},
  listeners: {
    messageCreate (client, msg) {
      console.log(msg.content)
    }
  },
  commands: [
    new Command('mycommand', function (msg) {
      msg.channel.createMessage('test')
    })
  ]
})

idfk what im doing with this lol

Move options object arguments before function arguments in Command/EventListener

Instead of

export default new Command('ping', msg => {
  // this could be long...
}, {
  guildOnly: true,
});

we should support putting options at the beginning before the potentially long function body:

export default new Command('ping', {
  guildOnly: true,
}, msg => {
  // this could be long...
});

Same goes for EventListener - especially important for this one since the once option changes the meaning of the listener body significantly.

Will require deprecation for the old form - both should be supported until v3. Runtime checks will need to be present past v3 to support the options being optional but coming before another required parameter.

old idea

shower thought: instead of

new EventListener('ready', /* ... */, {once: true})

it would be trivial to allow

new EventListener('ready:once', /* ... */);

Is this a good idea? I don't know of any other options we'd want to put on an event listener, so is the options object even necessary? I feel like allowing it via options is a cleaner way to do it, but requiring a full options object for a single property that will always be true or not present seems kinda eh. But I also don't think I would want the :ready method to be the only way to do it, because it's pretty different from how anything else handles one-time listeners.

As far as typings go it should be pretty easy I think - can make a new interface for the events that uses template literal string types for the additional keys I think

Emit deprecation warnings

When using deprecated methods, e.g. client.addCommandFile, emit a warning. The warning code should be somehow related to the issue that discusses the deprecation so migration paths are accessible, and the warning message should also contain a short description of how to resolve it.

Make the repo just for the library, not for the bot implementation itself

Remove bot-specific commands from the repo. Some commands will stay as optional defaults under #18 (probably just remove them for now and add help, etc. back later after 1.0 is released).

  • Meta: Remove references to the running bot from the readme, etc.
  • Create my own repo for my bot stuff that uses this lib
  • probably more

Fixes #2 (made out of scope)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.