Skip to content

NodeBB Plugins

Discussion regarding NodeBB Plugin development.

1.8k Topics 15.0k Posts
Most Voted Plugins

Subcategories


  • Have a question about building a plugin? Ask here
    424 Topics
    2k Posts
    barisB

    https://community.nodebb.org/post/88242 I think this answers your question. Let me know if it doesn't work.

  • Need a plugin developed? Ask here!
    222 Topics
    1k Posts
    barisB

    Plugin doesn't show usernames if they set their status to offline AFAIK

  • How send var from method to method

    4
    0 Votes
    4 Posts
    1k Views
    B

    In order for your code to work you have to be sure that 1) categoryGet and widgetGet are always called in context of the same request and 2) none of them are called with another request in between.

  • 0 Votes
    2 Posts
    1k Views
    nhl.plN

    I would start by checking how tags system is implemented. They probably can be easily disabled or modified for other purpose.

  • 0 Votes
    2 Posts
    1k Views
    nhl.plN

    It could be useful. In the past I have used Opera's built-in voice engine and it worked great.

    If you think about naturally sounding voices it would be nice to add language selection.
    http://www.ivona.com/en/about-us/voice-portfolio/

  • 0 Votes
    1 Posts
    884 Views
    BobberB

    I would like to add an icon that can decode from latin to Cyrillic.
    Who can help ?

  • 0 Votes
    9 Posts
    4k Views
    S

    @baris thanks!!!

  • [nodebb-plugin-spotify] Spotify embedder

    14
    0 Votes
    14 Posts
    5k Views
    BobberB

    @a_5mith Found it..... Ghostery was blocking Spotify !

  • Working smtp / mandrill emailer for 0.7-dev

    12
    0 Votes
    12 Posts
    4k Views
    PakornP

    After several restart. The plugin works now. 👍

  • 0 Votes
    4 Posts
    2k Views
    belstgutB

    @limker said:

    Looks like your plugin will reject any user with a non-gmail account. Maybe you should check with a list of valid email domains, i'm sure you can find one easily on google.

    Actually I think this is a bad idea. Because anyone can run their own mailserver.

    Just check if the email contains an @ is enough for valid email testing. Most regex solutions will fail on stuff like:

    "this email contains spaces"@example.org which is a valid email address. An email address may even contain a @ character in the local part in some odd configurations.

  • [nodebb-plugin-youtube] Youtube Embed Plugin

    66
    5 Votes
    66 Posts
    47k Views
    BobberB

    @julian @a_5mith and this only happening when i use the code from below, when i switch back
    everything works as a charm.

    (function(module) { "use strict"; var YoutubeLite = {}, embed = '<div class="js-lazyYT" data-youtube-id="$1" data-width="800" data-height="450"><iframe class="lazytube" src="//www.youtube.com/embed/$1"></iframe></div>'; var regularUrl = /<a href="(?:https?:\/\/)?(?:www\.)?(?:youtube\.com)\/(?:watch\?v=)(.+)">.+<\/a>/g; var shortUrl = /<a href="(?:https?:\/\/)?(?:www\.)?(?:youtu\.be)\/(.+)">.+<\/a>/g; var embedUrl = /<a href="(?:https?:\/\/)?(?:www\.)youtube.com\/embed\/([\w\-_]+)">.+<\/a>/; YoutubeLite.parse = function(data, callback) { if (!data || !data.postData || !data.postData.content) { return callback(null, data); } if (data.postData.content.match(embedUrl)) { data.postData.content = data.postData.content.replace(embedUrl, embed); } if (data.postData.content.match(regularUrl)) { data.postData.content = data.postData.content.replace(regularUrl, embed); } if (data.postData.content.match(shortUrl)) { data.postData.content = data.postData.content.replace(shortUrl, embed); } callback(null, data); }; module.exports = YoutubeLite; }(module));
  • 0 Votes
    7 Posts
    4k Views
    julianJ

    Yes, as @Schamper recommends, do not use relative paths to break out of the plugin's root directory, just use module.parent.require to require from the context of plugins.js, or require.main.require to require from the context of app.js

    To answer OP, I use npm link to link my folders together. I have one big messy NodeBB install ( 😉 ) and next to it is a plugins/ folder where all the plugins live.

    @psychobunny integrated grunt into NodeBB, so I just use grunt --verbose to develop now, instead of ./nodebb dev 😄

  • Plugin viability question

    9
    1 Votes
    9 Posts
    4k Views
    jareyJ

    @Schamper oh I understand. Well i suppose I will dive a lot into the code and learning a lot about the system in the process. I'm sure a will post a lot of questions in the forum, at least i'll try to implement it succesfully.
    Thanks a lot for your suggestions. 🙂

  • Need help with my plugin

    7
    0 Votes
    7 Posts
    2k Views
    G

    @Mega Omg your freaking genius! Thats where the mistake was. Haha
    Thank you 🙂

  • Plugin not available in ACP

    2
    0 Votes
    2 Posts
    1k Views
    jareyJ

    @gvimlan said:

    Hi everyone
    I followed the tutorial online on how to create NodeBB plugins. After following all the steps, the plugin is not visible under installed plugins in ACP. I tried to restart but there's no changes.
    BurnAfterCompiling LINK

    Thank you

    Can you see any errors in the log when starting up?

  • 0 Votes
    5 Posts
    2k Views
    R

    @baris
    cheers, let me work on it after the weekend

  • How to get "Client IP address" in plugin.

    4
    0 Votes
    4 Posts
    2k Views
    julianJ

    @akumbhare In that case, you're probably missing this line in your nginx config:

    proxy_set_header X-Real-IP $remote_addr;

  • [nodebb-plugin-facebook] Facebook posts

    23
    1 Votes
    23 Posts
    13k Views
    codejetC

    @Oroton said:

    @Codejet said:

    @Mega , have uploaded this pic, simply these are 3 dif screenshots in the one pic.

    First is initial reload pushes all adjacent horizontal categories downwards leaving gap in masonary, middle is after 2 reloads (perfect, what we want), last one is after navigating and coming back to the front page.

    masonaryfbembedplugin.png

    I have a solution to cause a page reload whenever condition is met in

    $(document).on('ready', function() {}

    if condition matches front page url. But obviously you would not advise this

    EDIT: scratch that can't even get that to work since a root url link just doesn't exist. lol I'll keep trying

    Have you got this facebook plugin working?

    Working correctly in 0.7.0-dev. Both in the Masonry and Widgets.

  • [nodebb-plugin-twitch] Twitch Embed Plugin

    10
    3 Votes
    10 Posts
    5k Views
    X

    teehee @psychobunny

    Will try finish the gameservers one next haha

    In all honesty, when i tried @a_5mith twitch plugin on SSL it doesnt work, so i was like im making my own xD

    Then i realised why @a_5mith plugin wasnt working, as twitch was being called over http not https xD

    Theres the story of this plugin xD

  • Routing

    8
    0 Votes
    8 Posts
    5k Views
    S

    I commented string //categoryRoutes(router, middleware, controllers); in src/routes/index.js file and add all of this file in index.js my plugin:

    (function(Preparsed) { 'use strict'; var nconf = module.parent.require('nconf'), path = module.parent.require('path'), winston = module.parent.require('winston'), controllers = require.main.require('./src/controllers'), meta = require.main.require('./src/meta'), plugins = require.main.require('./src/plugins'), express = module.parent.require('express'), metaRoutes = require.main.require('./src/routes/meta'), apiRoutes = require.main.require('./src/routes/api'), adminRoutes = require.main.require('./src/routes/admin'), feedRoutes = require.main.require('./src/routes/feeds'), pluginRoutes = require.main.require('./src/routes/plugins'), authRoutes = require.main.require('./src/routes/authentication'), helpers = require.main.require('./src/routes/helpers'); var setupPageRoute = helpers.setupPageRoute; function mainRoutes(app, middleware, controllers) { setupPageRoute(app, '/', middleware, [], controllers.home); var loginRegisterMiddleware = [middleware.redirectToAccountIfLoggedIn]; setupPageRoute(app, '/login', middleware, loginRegisterMiddleware, controllers.login); setupPageRoute(app, '/register', middleware, loginRegisterMiddleware, controllers.register); setupPageRoute(app, '/confirm/:code', middleware, [], controllers.confirmEmail); setupPageRoute(app, '/outgoing', middleware, [], controllers.outgoing); setupPageRoute(app, '/search/:term?', middleware, [middleware.guestSearchingAllowed], controllers.search.search); setupPageRoute(app, '/reset/:code?', middleware, [], controllers.reset); setupPageRoute(app, '/tos', middleware, [], controllers.termsOfUse); } function staticRoutes(app, middleware, controllers) { setupPageRoute(app, '/404', middleware, [], controllers.static['404']); setupPageRoute(app, '/403', middleware, [], controllers.static['403']); setupPageRoute(app, '/500', middleware, [], controllers.static['500']); } function topicRoutes(app, middleware, controllers) { app.get('/api/topic/teaser/:topic_id', controllers.topics.teaser); setupPageRoute(app, '/topic/:topic_id/:slug/:post_index?', middleware, [], controllers.topics.get); setupPageRoute(app, '/topic/:topic_id/:slug?', middleware, [middleware.addSlug], controllers.topics.get); } function tagRoutes(app, middleware, controllers) { setupPageRoute(app, '/tags/:tag', middleware, [middleware.publicTagListing], controllers.tags.getTag); setupPageRoute(app, '/tags', middleware, [middleware.publicTagListing], controllers.tags.getTags); } function categoryRoutes(app, middleware, controllers) { setupPageRoute(app, '/categories', middleware, [], controllers.categories.list); setupPageRoute(app, '/popular/:term?', middleware, [], controllers.categories.popular); setupPageRoute(app, '/recent', middleware, [], controllers.categories.recent); setupPageRoute(app, '/unread', middleware, [middleware.authenticate], controllers.categories.unread); app.get('/api/unread/total', middleware.authenticate, controllers.categories.unreadTotal); setupPageRoute(app, '/category/:category_id/:slug/:topic_index', middleware, [], controllers.categories.get); setupPageRoute(app, '/category/:category_id/:slug?', middleware, [middleware.addSlug], controllers.categories.get); } function accountRoutes(app, middleware, controllers) { var middlewares = [middleware.checkGlobalPrivacySettings]; var accountMiddlewares = [middleware.checkGlobalPrivacySettings, middleware.checkAccountPermissions]; setupPageRoute(app, '/user/:userslug', middleware, middlewares, controllers.accounts.getAccount); setupPageRoute(app, '/user/:userslug/following', middleware, middlewares, controllers.accounts.getFollowing); setupPageRoute(app, '/user/:userslug/followers', middleware, middlewares, controllers.accounts.getFollowers); setupPageRoute(app, '/user/:userslug/posts', middleware, middlewares, controllers.accounts.getPosts); setupPageRoute(app, '/user/:userslug/topics', middleware, middlewares, controllers.accounts.getTopics); setupPageRoute(app, '/user/:userslug/groups', middleware, middlewares, controllers.accounts.getGroups); setupPageRoute(app, '/user/:userslug/favourites', middleware, accountMiddlewares, controllers.accounts.getFavourites); setupPageRoute(app, '/user/:userslug/watched', middleware, accountMiddlewares, controllers.accounts.getWatchedTopics); setupPageRoute(app, '/user/:userslug/edit', middleware, accountMiddlewares, controllers.accounts.accountEdit); setupPageRoute(app, '/user/:userslug/settings', middleware, accountMiddlewares, controllers.accounts.accountSettings); setupPageRoute(app, '/notifications', middleware, [middleware.authenticate], controllers.accounts.getNotifications); setupPageRoute(app, '/chats/:userslug?', middleware, [middleware.redirectToLoginIfGuest], controllers.accounts.getChats); } function userRoutes(app, middleware, controllers) { var middlewares = [middleware.checkGlobalPrivacySettings]; setupPageRoute(app, '/users', middleware, middlewares, controllers.users.getOnlineUsers); setupPageRoute(app, '/users/online', middleware, middlewares, controllers.users.getOnlineUsers); setupPageRoute(app, '/users/sort-posts', middleware, middlewares, controllers.users.getUsersSortedByPosts); setupPageRoute(app, '/users/sort-reputation', middleware, middlewares, controllers.users.getUsersSortedByReputation); setupPageRoute(app, '/users/latest', middleware, middlewares, controllers.users.getUsersSortedByJoinDate); setupPageRoute(app, '/users/search', middleware, middlewares, controllers.users.getUsersForSearch); } function groupRoutes(app, middleware, controllers) { var middlewares = [middleware.checkGlobalPrivacySettings, middleware.exposeGroupName]; setupPageRoute(app, '/groups', middleware, middlewares, controllers.groups.list); setupPageRoute(app, '/groups/:slug', middleware, middlewares, controllers.groups.details); setupPageRoute(app, '/groups/:slug/members', middleware, middlewares, controllers.groups.members); } Preparsed.init = function(params, callback){ var app = params.router, middleware = params.middleware, controllers = params.controllers; var router = express.Router(), pluginRouter = express.Router(), authRouter = express.Router(), relativePath = nconf.get('relative_path'); pluginRouter.render = function() { app.render.apply(app, arguments); }; // Set-up for hotswapping (when NodeBB reloads) pluginRouter.hotswapId = 'plugins'; authRouter.hotswapId = 'auth'; app.use(middleware.maintenanceMode); app.all(relativePath + '/api/?*', middleware.prepareAPI); app.all(relativePath + '/api/admin/?*', middleware.isAdmin); app.all(relativePath + '/admin/?*', middleware.ensureLoggedIn, middleware.applyCSRF, middleware.isAdmin); adminRoutes(router, middleware, controllers); metaRoutes(router, middleware, controllers); apiRoutes(router, middleware, controllers); feedRoutes(router, middleware, controllers); pluginRoutes(router, middleware, controllers); /** * Every view has an associated API route. * */ mainRoutes(router, middleware, controllers); staticRoutes(router, middleware, controllers); topicRoutes(router, middleware, controllers); tagRoutes(router, middleware, controllers); categoryRoutes(router, middleware, controllers); accountRoutes(router, middleware, controllers); userRoutes(router, middleware, controllers); groupRoutes(router, middleware, controllers); app.use(relativePath, pluginRouter); app.use(relativePath, router); app.use(relativePath, authRouter); if (process.env.NODE_ENV === 'development') { require('./debug')(app, middleware, controllers); } app.use(function(req, res, next) { if (req.user || parseInt(meta.config.privateUploads, 10) !== 1) { return next(); } if (req.path.indexOf('/uploads/files') === 0) { return res.status(403).json('not-allowed'); } next(); }); app.use(relativePath, express.static(path.join(__dirname, '../../', 'public'), { maxAge: app.enabled('cache') ? 5184000000 : 0 })); handle404(app, middleware); handleErrors(app, middleware); // Add plugin routes plugins.init(app, middleware); authRoutes.reloadRoutes(); callback(); }; function handle404(app, middleware) { app.use(function(req, res, next) { if (plugins.hasListeners('action:meta.override404')) { return plugins.fireHook('action:meta.override404', { req: req, res: res, error: {} }); } var relativePath = nconf.get('relative_path'); var isLanguage = new RegExp('^' + relativePath + '/language/[\\w]{2,}/.*.json'), isClientScript = new RegExp('^' + relativePath + '\\/src\\/.+\\.js'); if (isClientScript.test(req.url)) { res.type('text/javascript').status(200).send(''); } else if (isLanguage.test(req.url)) { res.status(200).json({}); } else if (req.accepts('html')) { if (process.env.NODE_ENV === 'development') { winston.warn('Route requested but not found: ' + req.url); } res.status(404); if (res.locals.isAPI) { return res.json({path: req.path, error: 'not-found'}); } middleware.buildHeader(req, res, function() { res.render('404', {path: req.path}); }); } else { res.status(404).type('txt').send('Not found'); } }); } function handleErrors(app, middleware) { app.use(function(err, req, res, next) { if (err.code === 'EBADCSRFTOKEN') { winston.error(req.path + '\n', err.message) return res.sendStatus(403); } winston.error(req.path + '\n', err.stack); if (parseInt(err.status, 10) === 302 && err.path) { return res.locals.isAPI ? res.status(302).json(err.path) : res.redirect(err.path); } res.status(err.status || 500); if (res.locals.isAPI) { return res.json({path: req.path, error: err.message}); } else { middleware.buildHeader(req, res, function() { res.render('500', {path: req.path, error: err.message}); }); } }); } }(module.exports));

    Changing accordingly all paths and replaced var app, middleware and controllers. But not work:
    Снимок экрана от 2015-03-17 00:30:46.png
    Tried on action:app.load and action:init.

  • 0 Votes
    9 Posts
    3k Views
    A

    Hey!!! Thanks for the reply.... We have completed our task.

  • [solved] Plugin not work

    3
    0 Votes
    3 Posts
    1k Views
    S

    All is well! I helped @psychobunny https://github.com/NodeBB/NodeBB/issues/2869#event-255546006