From 4c30d867f8c8492a852c476a09a2ff08cae8716b Mon Sep 17 00:00:00 2001 From: Yami Date: Wed, 19 Oct 2016 14:36:24 +0000 Subject: [PATCH 1/5] feat: Naive, single-string capability support --- docs/Development/Providers/index.md | 13 +++++++++ providers/nodebb/index.js | 20 ++++++++++++++ test/providers/nodebb/indexTest.js | 41 +++++++++++++++++++++++++++++ 3 files changed, 74 insertions(+) diff --git a/docs/Development/Providers/index.md b/docs/Development/Providers/index.md index d3f19fff..7cfe50e3 100644 --- a/docs/Development/Providers/index.md +++ b/docs/Development/Providers/index.md @@ -59,6 +59,19 @@ A function must be exposed named `activate`. This function will be given no para A function must be exposed named `deactivate`. This function will be given no parameters. It should call `deactivate` on all registered plugins. It must return a promise that will resolve if and when the forum object is succesfully deactivated. +### supports + +A function must be exposed named `supports`. This function will be given either a functionality string or an array of functionality strings. It should return true if the forum supports the requested functionality, or false otherwise. + +A functionality string is a string that obeys the following rules: +- The string contains up to ten tokens +- These tokens are separated by periods +- Each token is considered a hierarchical list of capabilities; tokens to the right are considered sub-capabilities of tokens to the left + +This method must return false if any token in the string is not supported. For example, if the forum supports users but not avatars, it may accept `Users` but must reject `Users.Avatars`. + +If an array of functionality strings is supplied, this method must reject if any of them are unsupported. + ## Objects The following pages have more detail about the types of objects a Forum can instantiate: diff --git a/providers/nodebb/index.js b/providers/nodebb/index.js index fbe1fd64..caa4164e 100644 --- a/providers/nodebb/index.js +++ b/providers/nodebb/index.js @@ -391,6 +391,26 @@ class Forum extends EventEmitter { return new Promise(promiser) .then(() => this); } + + supports(supportString) { + const supported = [ + 'Chats', + 'Forums', + 'Users', 'Users.Avatars', + 'Posts', 'Posts.Editing', + 'Topics', + 'Categories', + 'Notifications', + 'Formatting', 'Formatting.Markdown' + ] + let support = false; + + if (supported.indexOf(supportString) > -1) { + support = true; + } + + return support; + } /** * Emit a websocket event diff --git a/test/providers/nodebb/indexTest.js b/test/providers/nodebb/indexTest.js index e61dcca9..c22c1662 100644 --- a/test/providers/nodebb/indexTest.js +++ b/test/providers/nodebb/indexTest.js @@ -857,6 +857,47 @@ describe('providers/nodebb', () => { return forum.deactivate().should.be.rejected; }); }); + describe.only('supports', () => { + let forum = null, + sandbox = null; + beforeEach(() => { + sandbox = sinon.sandbox.create(); + forum = new Forum({ + core: {} + }); + sandbox.stub(forum.Notification, 'deactivate'); + sandbox.stub(forum.Chat, 'deactivate'); + }); + afterEach(() => sandbox.restore()); + + it('must expose a method named supports', () => { + forum.supports.should.be.a('function'); + }); + + it('must return false if a capability is unsupported', () => { + forum.supports('Jack').should.be.false; + forum.supports('PMs').should.be.false; + }); + + it('must return true if a capability is supported', () => { + forum.supports('Chats').should.be.true; + forum.supports('Users').should.be.true; + forum.supports('Posts').should.be.true; + forum.supports('Topics').should.be.true; + forum.supports('Categories').should.be.true; + forum.supports('Notifications').should.be.true; + forum.supports('Formatting').should.be.true; + }); + + it('must return false if a sub-capability is not supported', () => { + forum.supports('Jack.Skellington').should.be.false; + forum.supports('Chats.WithJackSkellington').should.be.false; + }); + + it('must return true if a sub-capability is supported', () => { + forum.supports('Users.Avatars').should.be.true; + }) + }); describe('_emit', () => { let forum = null; beforeEach(() => { From fb9333dd0c7e00427693b0e8a23a6dda98d06d27 Mon Sep 17 00:00:00 2001 From: Yami Date: Wed, 19 Oct 2016 14:40:55 +0000 Subject: [PATCH 2/5] feat: Allow arrays --- providers/nodebb/index.js | 5 +++++ test/providers/nodebb/indexTest.js | 36 ++++++++++++++++++------------ 2 files changed, 27 insertions(+), 14 deletions(-) diff --git a/providers/nodebb/index.js b/providers/nodebb/index.js index caa4164e..2e4d20ef 100644 --- a/providers/nodebb/index.js +++ b/providers/nodebb/index.js @@ -405,6 +405,11 @@ class Forum extends EventEmitter { ] let support = false; + if (Array.isArray(supportString)) { + support = supportString.reduce((value, item) => { return value && this.supports(item) }, true); + return support; + } + if (supported.indexOf(supportString) > -1) { support = true; } diff --git a/test/providers/nodebb/indexTest.js b/test/providers/nodebb/indexTest.js index c22c1662..8e2ee5e3 100644 --- a/test/providers/nodebb/indexTest.js +++ b/test/providers/nodebb/indexTest.js @@ -870,16 +870,16 @@ describe('providers/nodebb', () => { }); afterEach(() => sandbox.restore()); - it('must expose a method named supports', () => { + it('must expose a method named supports', () => { forum.supports.should.be.a('function'); - }); - - it('must return false if a capability is unsupported', () => { + }); + + it('must return false if a capability is unsupported', () => { forum.supports('Jack').should.be.false; forum.supports('PMs').should.be.false; - }); - - it('must return true if a capability is supported', () => { + }); + + it('must return true if a capability is supported', () => { forum.supports('Chats').should.be.true; forum.supports('Users').should.be.true; forum.supports('Posts').should.be.true; @@ -887,16 +887,24 @@ describe('providers/nodebb', () => { forum.supports('Categories').should.be.true; forum.supports('Notifications').should.be.true; forum.supports('Formatting').should.be.true; - }); - - it('must return false if a sub-capability is not supported', () => { + }); + + it('must return false if a sub-capability is not supported', () => { forum.supports('Jack.Skellington').should.be.false; forum.supports('Chats.WithJackSkellington').should.be.false; - }); - - it('must return true if a sub-capability is supported', () => { + }); + + it('must return true if a sub-capability is supported', () => { forum.supports('Users.Avatars').should.be.true; - }) + }); + + it('should return true if all items in an array are supported', () => { + forum.supports(['Users', 'Chats']).should.be.true; + }); + + it('must return false if any items in an array are not supported', () => { + forum.supports(['Users', 'Chats', 'Halloween']).should.be.false; + }); }); describe('_emit', () => { let forum = null; From 7a28f6c91d49c3f035e08a62b951af6a87b8749f Mon Sep 17 00:00:00 2001 From: Yami Date: Wed, 19 Oct 2016 14:45:27 +0000 Subject: [PATCH 3/5] style(NodeBB): Fixed eslint issues --- providers/nodebb/index.js | 17 ++++++++------ test/providers/nodebb/indexTest.js | 37 +++++++++++++++--------------- 2 files changed, 29 insertions(+), 25 deletions(-) diff --git a/providers/nodebb/index.js b/providers/nodebb/index.js index 2e4d20ef..9389d8e5 100644 --- a/providers/nodebb/index.js +++ b/providers/nodebb/index.js @@ -394,19 +394,22 @@ class Forum extends EventEmitter { supports(supportString) { const supported = [ - 'Chats', - 'Forums', + 'Chats', + 'Forums', 'Users', 'Users.Avatars', 'Posts', 'Posts.Editing', - 'Topics', - 'Categories', - 'Notifications', + 'Topics', + 'Categories', + 'Notifications', 'Formatting', 'Formatting.Markdown' - ] + ]; + let support = false; if (Array.isArray(supportString)) { - support = supportString.reduce((value, item) => { return value && this.supports(item) }, true); + support = supportString.reduce((value, item) => { + return value && this.supports(item); + }, true); return support; } diff --git a/test/providers/nodebb/indexTest.js b/test/providers/nodebb/indexTest.js index 8e2ee5e3..83212572 100644 --- a/test/providers/nodebb/indexTest.js +++ b/test/providers/nodebb/indexTest.js @@ -857,9 +857,10 @@ describe('providers/nodebb', () => { return forum.deactivate().should.be.rejected; }); }); - describe.only('supports', () => { + describe('supports', () => { let forum = null, - sandbox = null; + sandbox = null; + beforeEach(() => { sandbox = sinon.sandbox.create(); forum = new Forum({ @@ -871,40 +872,40 @@ describe('providers/nodebb', () => { afterEach(() => sandbox.restore()); it('must expose a method named supports', () => { - forum.supports.should.be.a('function'); + forum.supports.should.be.a('function'); }); it('must return false if a capability is unsupported', () => { - forum.supports('Jack').should.be.false; - forum.supports('PMs').should.be.false; + forum.supports('Jack').should.be.false; + forum.supports('PMs').should.be.false; }); it('must return true if a capability is supported', () => { - forum.supports('Chats').should.be.true; - forum.supports('Users').should.be.true; - forum.supports('Posts').should.be.true; - forum.supports('Topics').should.be.true; - forum.supports('Categories').should.be.true; - forum.supports('Notifications').should.be.true; - forum.supports('Formatting').should.be.true; + forum.supports('Chats').should.be.true; + forum.supports('Users').should.be.true; + forum.supports('Posts').should.be.true; + forum.supports('Topics').should.be.true; + forum.supports('Categories').should.be.true; + forum.supports('Notifications').should.be.true; + forum.supports('Formatting').should.be.true; }); it('must return false if a sub-capability is not supported', () => { - forum.supports('Jack.Skellington').should.be.false; - forum.supports('Chats.WithJackSkellington').should.be.false; + forum.supports('Jack.Skellington').should.be.false; + forum.supports('Chats.WithJackSkellington').should.be.false; }); it('must return true if a sub-capability is supported', () => { - forum.supports('Users.Avatars').should.be.true; + forum.supports('Users.Avatars').should.be.true; }); it('should return true if all items in an array are supported', () => { - forum.supports(['Users', 'Chats']).should.be.true; + forum.supports(['Users', 'Chats']).should.be.true; }); it('must return false if any items in an array are not supported', () => { - forum.supports(['Users', 'Chats', 'Halloween']).should.be.false; - }); + forum.supports(['Users', 'Chats', 'Halloween']).should.be.false; + }); }); describe('_emit', () => { let forum = null; From 69972861df13642a350ced40ebd5034141f9ce9a Mon Sep 17 00:00:00 2001 From: Yami Date: Wed, 19 Oct 2016 17:41:15 +0000 Subject: [PATCH 4/5] feat(NodeBB): Added complete list of capabilities This includes docs as well closes #345 --- docs/Development/plugin creation.md | 44 ++++++++++++++++++++++++++++- providers/nodebb/index.js | 12 ++++---- 2 files changed, 49 insertions(+), 7 deletions(-) diff --git a/docs/Development/plugin creation.md b/docs/Development/plugin creation.md index b15835e4..a64e60d8 100644 --- a/docs/Development/plugin creation.md +++ b/docs/Development/plugin creation.md @@ -1,3 +1,45 @@ # Plugin Creation -Coming soon: Plugin creation instructions for Sockbot 3.0! \ No newline at end of file +Coming soon: Plugin creation instructions for Sockbot 3.0! + + +## Topic: Cross-Platform Support + +When creating a plugin that can work across platforms, it can be helpful to use the `Forum.supports()` function to query for specific capabilities your plugin needs. + +A plugin should refuse to activate on a platform that does not support key functionalty. If extra functionality is unsupported, it can be disabled at activation time. Plugins should use the `Formatting` capability key to determine what sort of output to produce and adjust to the platform. + +### Known Capabilities + +- Chats +- PMs +- Users + - Avatars + - Follow + - URL + - Seen + - PostCount +- Posts + - Edit + - Delete + - Bookmark + - Vote + - URL +- Topics + - URL + - Watch + - Mute +- Categories + - Management +- Notifications + - URL +- Formatting + - Markup + - Markdown + - BBCode + - HTML + - Multiline + - Colors + - Links + - Images + - Spoilers \ No newline at end of file diff --git a/providers/nodebb/index.js b/providers/nodebb/index.js index 9389d8e5..4692857e 100644 --- a/providers/nodebb/index.js +++ b/providers/nodebb/index.js @@ -395,13 +395,13 @@ class Forum extends EventEmitter { supports(supportString) { const supported = [ 'Chats', - 'Forums', - 'Users', 'Users.Avatars', - 'Posts', 'Posts.Editing', - 'Topics', + 'Users', 'Users.Avatars', 'Users.Follow', 'Users.URL', 'Users.Seen', 'Users.PostCount', + 'Posts', 'Posts.Edit', 'Posts.Vote', 'Posts.Delete', 'Posts.Bookmark', 'Posts.URL', + 'Topics', 'Topics.URL', 'Topics.Watch', 'Topics.Mute', 'Categories', - 'Notifications', - 'Formatting', 'Formatting.Markdown' + 'Notifications', 'Notifications.URL', + 'Formatting', 'Formatting.Markup', 'Formatting.Markup.Markdown', + 'Formatting.Multiline', 'Formatting.Links', 'Formatting.Images', 'Formatting.Spoilers' ]; let support = false; From bf7dbc4eda9a7a63ed9a44e6958f7b99be5e2869 Mon Sep 17 00:00:00 2001 From: Accalia de Elementia Date: Thu, 20 Oct 2016 11:46:26 +0000 Subject: [PATCH 5/5] style: Remove trailing whitespace --- providers/nodebb/index.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/providers/nodebb/index.js b/providers/nodebb/index.js index 4692857e..3f1af61a 100644 --- a/providers/nodebb/index.js +++ b/providers/nodebb/index.js @@ -400,14 +400,14 @@ class Forum extends EventEmitter { 'Topics', 'Topics.URL', 'Topics.Watch', 'Topics.Mute', 'Categories', 'Notifications', 'Notifications.URL', - 'Formatting', 'Formatting.Markup', 'Formatting.Markup.Markdown', + 'Formatting', 'Formatting.Markup', 'Formatting.Markup.Markdown', 'Formatting.Multiline', 'Formatting.Links', 'Formatting.Images', 'Formatting.Spoilers' ]; let support = false; if (Array.isArray(supportString)) { - support = supportString.reduce((value, item) => { + support = supportString.reduce((value, item) => { return value && this.supports(item); }, true); return support;