# Rich Deployment Messages on Discord

By [n4n0](https://paragraph.com/@n4n0) · 2022-09-21

---

Currently we're using [discord-action](https://github.com/sebastianpopp/discord-action) to post successful deployments on our IPFS gateway in our Discord. The messages are a simple string and lack information:

![Yeah okay but uh... huh?](https://storage.googleapis.com/papyrus_images/0cf3fe8fda06216b6ee428513cd589dfe719bd542c33b177d37a635a943c160b.png)

Yeah okay but uh... huh?

It gives users a simple information without enabling less technically adept users to understand what they are supposed to do with this message. The basic idea was to enrich the message with information about how to host your own IPFS node and pin the CID so it becomes redundantly available in the IPFS network.

Discord-Action
--------------

The action is using a webhook to push updates to our Discord's `change-logs` channel. It takes a simple string argument to craft the payload so it's not possible to post rich messages:

    const core = require('@actions/core');
    const axios = require('axios');
    
    try {
      const webhook = core.getInput('webhook');
      const message = core.getInput('message');
    
      const options = {
        method: 'POST',
        url: webhook,
        headers: {'Content-Type': 'application/json'},
        data: {content: message}
      };
    
      axios
        .request(options)
        .then(() => {
          core.info('Message was sent successfully');
        });
    } catch (error) {
      core.setFailed(error.message);
    }
    

As can be seen the `data` key inside the `options` object only contains the Github input `message`, which is not strictly defined as a string, but everything passed into the action through that input will be treated as such. So to enable a rich message, we need to fork the action and modify it to allow us to post our desired output.

Rich Messages
-------------

According to [Discord Developer Portal](https://discord.com/developers/docs/resources/channel#embed-object) we can pass a specific object called "Embed Object" as our webhook message to create rich previews that allow for interactive content:

![Built with https://autocode.com/tools/discord/embed-builder/](https://storage.googleapis.com/papyrus_images/a8bbe6699ed1ccacd306ffeb7b2c7e4388b6b6d899b61fcd0b992cf23c4135f6.png)

Built with https://autocode.com/tools/discord/embed-builder/

Generated code for the above screenshot:

    const lib = require('lib')({token: process.env.STDLIB_SECRET_TOKEN});
    
    await lib.discord.channels['@0.3.0'].messages.create({
      "channel_id": `${context.params.event.channel_id}`,
      "content": "",
      "tts": false,
      "components": [
        {
          "type": 1,
          "components": [
            {
              "style": 5,
              "label": `Learn about IPFS`,
              "url": `https://en.wikipedia.org/wiki/InterPlanetary_File_System`,
              "disabled": false,
              "type": 2
            },
            {
              "style": 5,
              "label": `Run your own node`,
              "url": `https://docs.ipfs.tech/install/ipfs-desktop/`,
              "disabled": false,
              "type": 2
            }
          ]
        }
      ],
      "embeds": [
        {
          "type": "rich",
          "title": `New IPFS deployment successful!`,
          "description": "",
          "color": 0xa100c1,
          "fields": [
            {
              "name": `CID`,
              "value": `QmexvqKGREpf2hhvpUpCXGjPQhvnDLDRibqZcxh4ffk2CQ`,
              "inline": true
            },
            {
              "name": `Commit`,
              "value": `c576b9fdcd3fef8330de38af4f86b5f6e6f8e31f`,
              "inline": true
            }
          ],
          "url": `https://ipfs.alchemix.fi/`
        }
      ]
    });
    

So all we have to do is to adjust the `data` value from the forked repo like so:

    const core = require('@actions/core');
    const axios = require('axios');
    
    try {
      const webhook = core.getInput('webhook');
      const cid = core.getInput('cid');
      const commit = core.getInput('commit');
    
      const options = {
        method: 'POST',
        url: webhook,
        headers: {'Content-Type': 'application/json'},
        data: {
            embeds: [
                {
                    "type": "rich",
                    "title": `New IPFS deployment successful!`,
                    "description": "",
                    "color": 0xee3da4,
                    "fields": [
                        {
                            "name": `CID`,
                            "value": cid,
                            "inline": true
                        },
                        {
                            "name": `Commit`,
                            "value": commit,
                            "inline": true
                        }
                    ],
                    "url": `https://ipfs.alchemix.fi/`
                }
            ]
        }
      };
    

We now have two new constants `cid` and `commit` which receive values from the inputs which we also have to adjust inside the `action.yml` of the forked repo:

    ...
    inputs:
      webhook:
        description: 'Discord webhook URL'
        required: true
      cid:
        description: 'CID of the deployment'
        required: true
      commit:
        description: 'Github commit that triggered this deployment'
        required: true
    ...
    

Now all that's left to do is to publish the action on the marketplace and adjust the CD pipeline to make use of the new action:

    ...  
      deploy:
        name: Deploy
        needs: build
        runs-on: ubuntu-latest
    
        steps:
          - name: Fetch artifact
            uses: actions/download-artifact@v2
            with:
              name: production-files
              path: ./dist
          
          - name: Managa Pinata pin and gateway
            id: pinata-manager
            uses: n4n0GH/pinata-manager@main
            with:
              path: ./dist
              secret: ${{secrets.PINATA_SECRET}}
              key: ${{secrets.PINATA_KEY}}
              token: ${{secrets.PINATA_TOKEN}}
              pinName: "Alchemix v2"
              unpinOld: "true"
              gatewayName: "alchemix"
              gatewayId: ${{secrets.PINATA_GATEWAY_ID}}
              
          - name: Notify Discord Channel
            uses: n4n0GH/discord-ipfs-action@v1.0.0
            with:
              webhook: ${{secrets.DISCORD_WEBHOOK}}
              cid: ${{steps.pinata-manager.outputs.cid}}
              commit: ${{github.sha}}
    ...
    

And we're done!

![Aah... but something is off...](https://storage.googleapis.com/papyrus_images/66ac39f6b80c16fa3ec2253ffe78ad2b4604be3e1f8ffd52f6946a32c6729efd.png)

Aah... but something is off...

But What About The Buttons?
---------------------------

Ah, the buttons. You see, we properly implemented the buttons using Discord's `components` parameter [here](https://github.com/n4n0GH/discord-ipfs-action/blob/v1.0.0/index.js#L14) but because the webhook is made by a user and not application-owned (i.e. created by a bot), Discord is not rendering buttons as a security measure, as documented on the [Discord Developer Portal](https://discord.com/developers/docs/resources/webhook#execute-webhook). So if at some point we'll switch the webhook to an application-owned one, the buttons will show up as well.

---

*Originally published on [n4n0](https://paragraph.com/@n4n0/rich-deployment-messages-on-discord)*
