How to add main post content of topic to topic lists?

Moved Solved Developer FAQ
  • Hello, I am creating a custom frontend using nodebb API. I want to get all the topics inside a category, along with the main post of that topic. Currently I can get all the topics inside a category using this endpoint:

    http://localhost:4567/api/category/1
    

    And I got this json response:

      ...
      ...
    
    "topics": [
    		{
    			"cid": 1,
    			"lastposttime": 1670832226781,
    			"mainPid": 7,
    			"postcount": 4,
    			"slug": "5/bbca-mencapai-ath-di-harga-9000",
    			"tid": 5,
    			"timestamp": 1670829972612,
    			"title": "$BBCA mencapai ATH di harga 9000",
    			"uid": 3,
    			"viewcount": 11,
    			"postercount": 3,
    			"teaserPid": 11,
    
      ...
      ...
    

    This response only give me the mainPid that forces me to make another API call to get the post detail content. How can I modify this response, so I can get the whole content of the main post (not only the mainPid)? or at least the complete post content?

    Please give me some advice. Thank you.

  • nullpointerN nullpointer marked this topic as a question on
  • This is fairly easy to do in a plugin by using the hook filter:topics.get. This hook gets triggered whenever a list of topics is loaded. So you will have to add the parsed post content of mainPid to each topic object. Here is some sample code that does that.

    const posts = require.main.require('./src/posts');
    myPlugin.filterTopicsGet = async function (hookData) {
    	// get all mainPids
    	const mainPids = hookData.topics.map(t => t.mainPid);
    	// load all mainPosts
    	const mainPosts = await posts.getPostsByPids(mainPids, hookData.uid);
    	// set a mainPost object on all topics returned
    	hookData.topics.forEach((topic, index) => {
    		topic.mainPost = mainPosts[index];
    	});
    	return hookData;
    };
    

    Once you have a plugin with that hook, you should see a mainPost object inside each topic object on places like /recent and /category/1.

  • barisB baris moved this topic from NodeBB Development on
  • @baris thank you! I'll try your solution and update here

  • nullpointerN nullpointer has marked this topic as solved on
  • barisB baris referenced this topic on

Suggested Topics


  • 1 Votes
    8 Posts
    280 Views

    @crazycells said in Total vote count on topic list:

    but this calculation makes more sense to us than the first post only.

    And for me.

  • 0 Votes
    1 Posts
    82 Views

    If you have a custom theme that introduces custom user fields into the edit page, you might have noticed that the fields don't seem to show up on the frontend even if they're saved in the database.
    Likewise, if you have some custom data you want to maintain on a per-user basis, and you tried using user.updateProfile, you might've noticed that your fields don't seem to save.

    The reason for this behaviour is that the the user fields getter and setter are protected so that values in the user hash are not unintentionally overwritten, or that fields are retrieved that should not be.

    For example:

    nodebb-plugin-foobar saves a private user token in the user's hash. It is not meant to be retrieved. Another plugin calls user.getUsersFields() and that method naively returns everything in the user hash. The private key would then be considered leaked if it is accidentally exposed to the end user, even if unintentionally.

    Getter (retrieving user data)

    If you've saved a custom field into the user hash and you wish to retrieve it via User.getUsersFields(), you will have to explicitly whitelist it by attaching a hook listener to filter:user.whitelistFields. That plugin hook sends in { uids, whitelist }, where uids is an array of uids (requested by the calling script), and whitelist, which is an array containing user field properties.

    You can add a new entry to the whitelist thusly:

    plugin.json

    { ... "hooks": [ { "hook": "filter:user.whitelistFields", "method": "addUserField" }, ] ... }

    library.js

    library.addUserField = async ({ uids, whitelist }) => { whitelist.push('customField'); return { uids, whitelist }; };

    After doing so, a call to user.getUsersFields(uids, ['customField']); will have the customField property show up as it has been explicitly allowed.

    Setter (saving user data)

    Setting user data is comparatively simpler. We recommend using the user.updateProfile() method, as that has some sanity checks and special handling for certain fields. To allow the saving of a certain field, you will need to pass it in to the third argument of user.updateProfile():

    await User.updateProfile(callerUid, { uid, customField: 'value', }, ['customField']);
  • 0 Votes
    7 Posts
    188 Views

    @шЫкель-грубый said in How can I backdate topics and posts (for migration purposes)?:

    I'll also try to comment date changing in sources. I'm not familiar with JS but it looks obviously enough.

    Yes, this is probably the most direct solution. It'll get your script working with the correct timestamps, all you have to do is comment out that line in the file, and restart NodeBB.

  • 0 Votes
    4 Posts
    194 Views

    Awesome! Thank you.

  • 3 Votes
    7 Posts
    2k Views

    That's awesome @baris 😄 I'm assuming backwards compatible with the old method, though that ought to be deprecated?