Skip to content

NodeBB Plugins

Discussion regarding NodeBB Plugin development.

1.8k Topics 15.2k Posts
Most Voted Plugins

Subcategories


  • Have a question about building a plugin? Ask here
    444 Topics
    2k Posts
    Sky FoxxS
    Perfect! Does the job super elegantly thank you
  • Need a plugin developed? Ask here!
    225 Topics
    1k Posts
    julianJ
    Considering its localized popularity, I think it would be an idea candidate for a plugin. The easiest way would be to utilise an existing askbox service and embed it into a user profile or something.
  • Working smtp / mandrill emailer for 0.7-dev

    12
    0 Votes
    12 Posts
    5k Views
    PakornP
    After several restart. The plugin works now.
  • [nodebb-plugin-email] Check user's email if it is valid to sign up

    4
    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
    52k 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));
  • Plugin development: environment setup

    7
    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
    3k 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?
  • Issue displaying custom_profile_info when loading posts

    5
    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
    3k 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
    15k 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. [image: M9VI7CN.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: [image: 0ZRJoUb.png] Tried on action:app.load and action:init.
  • Access Logged In user Information on Server side.

    9
    0 Votes
    9 Posts
    4k Views
    A
    Hey!!! Thanks for the reply.... We have completed our task.
  • [solved] Plugin not work

    3
    0 Votes
    3 Posts
    2k Views
    S
    All is well! I helped @psychobunny https://github.com/NodeBB/NodeBB/issues/2869#event-255546006
  • 1 Votes
    3 Posts
    3k Views
    OrotonO
    Is it even possible to integrate a plug in that posts to a 'group' I'm sure FB only allows posting to fan pages and walls. That being said, I know you can do 'Canvas' app for NodeBB on FB, but this only integrates with FB notifiactions On the Browser, where as you'll find most of the time they check FB via mobile. And FB mobile is not compatible with Canvas or any external FB notifications. So you are probably going to be disappointed with it's results. Also, on that note. I've found it susccefull for mobile users, using a push notification app. That notifies users on events. And when they are notified, it refers them back to your forum. via a webui Browser in the app. This works great with a Responsive design or a dedicated mobile browser.
  • 0 Votes
    4 Posts
    2k Views
    X
    how does this plugin work? I installed it but cannot find in anywhere in ACP
  • How to Get Domain Name.

    2
    0 Votes
    2 Posts
    1k Views
    julianJ
    var nconf = require.main.require('nconf'); console.log(nconf.get('url'));
  • Use Custom Template to send Email

    2
    0 Votes
    2 Posts
    2k Views
    julianJ
    No dependencies required, just have your plugin serve templates (add the template option into plugin.json), and in that template folder, have a folder called emails, and place your template in there. Also place a corresponding plaintext one with the suffix _plaintext.
  • Is there plugin to auto embed COUBs?

    8
    0 Votes
    8 Posts
    3k Views
    BobberB
    @kosyak it works, thanks!
  • What's the current theme's less path

    7
    0 Votes
    7 Posts
    3k Views
    PitaJP
    @julian but, how would I pass the less path of the theme into my plugin's less file without knowing what theme will be used? I'm trying to use mixins to style my plugin's pages the same as the rest of the site.