djcas9 / komanda

The IRC Client For Developers
http://komanda.io
MIT License
1.78k stars 75 forks source link

Modular plugins #157

Open xqwzts opened 10 years ago

xqwzts commented 10 years ago

Overview:

This pull request creates a basic plugin system.

The main components of the PR are:

Plugins must be valid node modules located in a plugins folder under the application's datapath. To be included the plugin has to be registered in the plugins.json file.

plugins.json example:

[
  {
    "name": "github-feed",
    "location": "github-feed",
    "main": "main.js",
    "channel": true
    "stylesheet": "/styles/github-feed.css"
  }
]

name: the plugin name, should be unique to this plugin. location: plugin folder's location. main: script the plugin is located in. channel: [boolean] flag determining if this is a channel plugin and should be loaded/initialized when a new channel is open. stylesheet: [optional] location of stylesheet that should be injected when the plugin is loaded [relative to the plugin's location] disabled: [optional][boolean] If set to true the plugin will not be loaded by komanda.

The loadPlugins() function in helpers.js is responsible for checking the plugins.json file and reading each plugin's settings before loading it. It checks to make sure that the plugin file specified under main exists in the specified location, and does the same for the stylesheet if one is specified.

A JSON definition for each plugin is then pushed to the Komanda.settings.plugins array.

When a new ChannelView is created it instantiates each plugin that has defined channel: true in its settings.

Channel API:

The ChannelView module defines a ChannelAPI with the following methods:

getTimestamp: Returns a Komanda formatted timestamp, using the timestamp helper. addChannelMessage: Appends the provided HTML to the channel's message attach point and scrolls the view to display the full message. setToolbar: Prepends the provided HTML to the channel's toolbar attach point and sets the toolbar-attached class. This will replace any other toolbar currently attached. removeToolbar: Removes the toolbar attached at the channel's toolbar attach point. onChannelTopicChange: Registers a callback to be triggered when the channel's topic changes.

When a new plugin is loaded, the ChannelView creates a new instance of the ChannelAPI and provides it to the plugin. The plugin is required to provided an initialize() method which gets called by the ChannelView and to which the ChannelAPI will be passed.

Github Plugins:

The github functionality that was previously part of the ChannelView has been extracted into two github plugins.

github-feed:

A plugin that handles feed changes and adds them as channel messages.

github-toolbar:

A plugin that displays a toolbar at the top of the channel with the github repo's metadata.

Each plugin is a node module with its own package.json definition as well as a stylesheet [extracted from komanda.css] and template.

There is an issue here when using hbs/handlerbars that people should be aware of: The handlebars context used when rendering a plugin template will not be the same context that the plugin itself has, so while this can be used to compile the template, any helpers [and partials?] will not be available at runtime. To work around this helper functions can be defined in the module and passed in manually to the template when resolving it.

Installing Plugins:

The github plugins are included in the /plugins directory in the source. These should be copied to the app's data path and installed there individually [with npm install] in order to pull their node dependencies. The plugins.json file should be in the root plugins directory.

Plugin Contract:

Plugins are required to proved the following functionality, and accessible methods:

initialize: An initialize method will be called when the plugin is loaded, and a copy of the channel API will be provided to it. close: The close method will be called when the channel is closed, the plugin should gracefully terminate when called.

Improvements:

Some places this can be improved:

seiyria commented 10 years ago

I have some questions (forgive me if these are answered) - do you have any plans for a package manager (like sublime text), or perhaps a "download from url" bar? If you don't have any plans for a package manager, what are your limitations?

Also, will you be extending this to load new screens outside of channels (perhaps, like a script editor so we can make plugins from inside komanda, or edit existing plugins)? Maybe I could add new settings screens for my plugins?

Will we be able to develop plugins live while komanda is running? I don't want to restart komanda every time I make changes, that'd take forever.

How much do plugins encompass? For example, say I want a plugin that pushes a pnotify onto the client, can I do that? Can I make custom commands with modules as well? I know it'd be nice to be able to make a /rainbow <text> and have it make rainbow-colored text.

eugene-bulkin commented 10 years ago

@seiyria:

do you have any plans for a package manager (like sublime text), or perhaps a "download from url" bar? If you don't have any plans for a package manager, what are your limitations?

I personally would like this to happen at some point. Hopefully it is doable.

Also, will you be extending this to load new screens outside of channels (perhaps, like a script editor so we can make plugins from inside komanda, or edit existing plugins)? Maybe I could add new settings screens for my plugins?

This is definitely a feature that we'll try to include (I'm pushing for it, anyway).

Will we be able to develop plugins live while komanda is running? I don't want to restart komanda every time I make changes, that'd take forever.

This I do not know. While hot swapping code would be nice, I'm not sure how feasible it would be. It's certainly doable in some cases but I'm not sure how it would work with Komanda.

How much do plugins encompass? For example, say I want a plugin that pushes a pnotify onto the client, can I do that?

Probably would be possible. We have not yet decided the scope of plugins, especially because we need to see which release we put features in.

Can I make custom commands with modules as well?

This will be supported.

seiyria commented 10 years ago

@eugene-bulkin Thanks for getting back to me.

package manager

I suspect it's easily doable, and I'm not sure what your limitations are at present, but that's something I wouldn't mind helping with.

new screens

I would really like for this to be a thing, especially for plugin configuration. However, with new screens entirely, it would be possible to integrate other features like google music, right into komanda.

hot swapping

Yeah, it's tricky. We do it with our IRC bot by clearing the require cache for anything that changes, but I haven't looked at komandas architecture to say much about how it could be done there.

plugin scope

Great. I'm just checking what it will eventually be. It sounds like it'll be pretty good to start, and it will only get better from there.

custom commands

Fabulous.

rahatarmanahmed commented 10 years ago

One thing to note about hot swapping, we haven't yet figured out a good way to hot swap modules (our name for our bot's plugins) with multiple files.

eugene-bulkin commented 10 years ago

One thing to note about hot swapping, we haven't yet figured out a good way to hot swap modules (our name for our bot's plugins) with multiple files.

What do you mean by multiple files? I've done the clearing the require cache for my bot too, and I feel like multiple files would not cause an issue.

rahatarmanahmed commented 10 years ago

I'm not familiar with the issue, maybe @raymond-h can explain better.

Question about plugins.json: is that something the user has to edit to add plugins, since its shared among all plugins? If so, I feel that makes the plugin install process way too involved. Why not check folders in the plugin dir for individual plugin.jsons so you can just drop in a folder and be done with it?

seiyria commented 10 years ago

Still no word on this?