Importing Forum Updates to Discord - Integration Guide

Tobi

Well-known member
Aug 31, 2018
316
291
63
Germany

This still works, but it is recommended you use the Discord bot instead!





77fEUGb.png


After the removal of the AriesMS Discord I was asked by a friend to create a way to get notifications inside Discord everytime a new update is created on the forums.

I made a very simple and free automation using google spreadsheets and appscripts to scrape the forums, that posts notifications to a discord channel of your choice via discord webhooks.

Setting it up is quite fast.

To get started you only require 2 things:
1. A google account
- If you don't already have one, you can create one here: https://google.com/accounts/Newaccount

2. A discord server that you have administrative rights on.
- To be precise, you need permissions to create webhooks for discord channels.


How to set everything up
1. Make a copy of the spreadsheet

- You can give the spreadsheet any name you want. Just don't rename any Sheets/Pages.
Spreadsheet URL: https://docs.google.com/spreadsheets/d/1ZWtS986rFlzm4Mo1Ebt9-vwJ1gb0EohKcXMvkjUd9LE/
5JjlAUH.png

Svfa0Gr.png

2. Create a webhook URL for the discord channel you want the notifications to get posted in.
PKAkRkB.png

OUWOBgt.png

YzfPgo3.png

oI3cvhV.png

3. Enter ID and Webhook URL in the App Script.
- On the spreadsheet page click "Extensions" -> "Apps Script"
2OFcWa2.png

Discord Webhook:
84QC7uh.png

gNvITCn.png

u6nZFre.png

Spreadsheet ID:
XN8nxtq.png

8MB4IpS.png

uVZ1sU8.png

4. Set up timed triggers.
Click on the Clock icon on the left hand side.
dmVIDtO.png
Click on "Add Trigger" on the bottom right hand side.
6pvVWoN.png
For the "Select event source" option select "Time-driven" and set the interval to "Every minute".
PZDTDkp.png
Click "Save".
Note: If this is your first time setting up a trigger or running the script, you may need to give the script access to certain functions related to this whole topic.
Xr9KSYr.png

3Rd6Omj.png

zLtXh5b.png


5. You're done!
Update posts on the forums SHOULD get posted to your discord channel automatically now.
k8CwXei.png


Note:
Since not much time was spent to bugtest this there may or may not still be some bugs. Feel free to report any bugs to me or fix them yourself.🤷‍♂️

1. How do I disable the script again if I don't want it to run anymore?
- Either delete the timed trigger, the webhook or the entire spreadsheet.

2. What exactly gets posted to discord?
- All starterposts from the "Updates" subforum and 2 additional posts per thread. I feel like that should cover enough information from the forums to be useful. Edits do not get pushed to discord.

3. Have you ever learned to follow something that's called "best practice"?
- No hablo inglés

4. Why did you not create a bot that I can invite to my server for this?
- Because I didn't want to invest more time into this than needed. Spreadsheet + App Script is easy and fast to set up stuff like this with...and it's free.

5. Can I edit the script/spreadsheet?
- Sure. If you know what you're doing go for it. I won't troubleshoot your stuff though.

6. Why write X in your code and not Y?
- Feel free to do edit stuff yourself. Now here: 🚪

7. Will this work forever?
- Theoretically yes. Some stuff on the forums might change though, which would require some edits in the script and/or spreadsheet for it to work again.
 
Last edited:

Tobi

Well-known member
Aug 31, 2018
316
291
63
Germany
Added another error catch to the refreshing cells.
Just copy/paste the following code into your AppScript or remake the sheet.
Make sure to re-enter your Discord URL and Spreadsheet ID!
JavaScript:
function checkAndPost(message) {

  //DISCORD WEBHOOK
  var discordWebhookUrl = 'DISCORD URL HERE';
  // SPREADSHEET ID
  var DATA_SPREADSHEET_ID = "SPREADSHEET ID HERE";
 
 
  /* DON'T TOUCH */
  //grabbing both sheets/tables/pages/whatever
  var table = SpreadsheetApp.openById(DATA_SPREADSHEET_ID).getSheetByName("RAW");
  var checksheet = SpreadsheetApp.openById(DATA_SPREADSHEET_ID).getSheetByName("Threads");

  //Rereshing the cells by re-entering the formulas and refreshing a bunch of times...this whole section is so dumb.;
  var flushrange3 = table.getRange("B8");
  var cellFunction3 = '=REGEXREPLACE(IMPORTXML(B6,"//title"),"\\| Elluel Network","")';
  var flushrange4 = table.getRange("B15");
  var cellFunction4 = '=IFERROR(LEFT(RIGHT(IMPORTXML($B$6,B14),LEN(IMPORTXML($B$6,B14))-18),LEN(RIGHT(IMPORTXML($B$6,B14),LEN(IMPORTXML($B$6,B14))-18))-26),"")';
  var flushrange5 = table.getRange("B18");
  var cellFunction5 = '=IFERROR(LEFT(RIGHT(IMPORTXML($B$6,B17),LEN(IMPORTXML($B$6,B17))-18),LEN(RIGHT(IMPORTXML($B$6,B17),LEN(IMPORTXML($B$6,B17))-18))-26),"")';
  var flushrange6 = table.getRange("B21");
  var cellFunction6 = '=IFERROR(LEFT(RIGHT(IMPORTXML($B$6,B20),LEN(IMPORTXML($B$6,B20))-18),LEN(RIGHT(IMPORTXML($B$6,B20),LEN(IMPORTXML($B$6,B20))-18))-26),"")';
  var flushrange7 = table.getRange("B30");
  var cellFunction7 = '=IMPORTXML($B$1,B29)';
 
  flushrange3.clearContent;
  flushrange4.clearContent;
  flushrange5.clearContent;
  flushrange6.clearContent;
  flushrange7.clearContent;
  SpreadsheetApp.flush();
  flushrange3.setFormula(cellFunction3);
  flushrange4.setFormula(cellFunction4);
  flushrange5.setFormula(cellFunction5);
  flushrange6.setFormula(cellFunction6);
  flushrange7.setFormula(cellFunction7);
  SpreadsheetApp.flush();
  SpreadsheetApp.flush();
  SpreadsheetApp.flush();
 
  //eh
  var threadurl = table.getRange("B6").getValue().toString();
  var title = table.getRange("B12").getValue().toString();
  var post1 = table.getRange("B15").getValue().toString();
  var post2 = table.getRange("B18").getValue().toString();
  var post3 = table.getRange("B21").getValue().toString();

  //eh 2
  var lastrow = checksheet.getLastRow();
  var data = checksheet.getDataRange().getValues();
  var exists = false;

  //im dead inside
  function checkIfTopicExists (title) {
    for (n in data) {
      Logger.log("Checking '" + title + "' against '" + data[n][0] + "'");
      if (data[n][0].indexOf(title)>-1) {
        Logger.log(title + " matches entry.");
        exists = true;
      }  
    }
    if (exists == false) {
        Logger.log("No matching entry found. Creating new.")
        checksheet.getRange(lastrow+1,1).setValue(title);
        checksheet.getRange(lastrow+1,5).setValue(threadurl);
        return false;
    } else {
        Logger.log("Match was found. Not creating entry!")
        return true;
    }
  }

  //Discord webhook stuff
  function discordWebhook(txt) {
    Logger.log('posting...');

    var payload = {
        "avatar_url": "https://aries.elluel.net/assets/leaf.png",
        "content": txt
      };
 
    var options = {
      'method': 'post',
      'payload': JSON.stringify(payload),
      'headers': {
        'Content-Type': 'application/json',
        },
      "muteHttpExceptions" : true
      };

    Logger.log(options);

  try {
    let response = UrlFetchApp.fetch(discordWebhookUrl, options);

      if(response.getResponseCode() === 200) {
        // das good
        Logger.log('Success');
        Logger.log(response);
      } else{
        Logger.log('Issues');
        Logger.log(response);
      }
    } catch (err) {
      // das bad
      Logger.log('Error');
      Logger.log(err);
    }
  }
 
  var returncode = checkIfTopicExists(title);
  //Logger.log(returncode);
  //Logger.log(secondpost.length);
  Logger.log(checksheet.getRange(lastrow,4).getValue());
  Logger.log(post3);
  //First/Initial post
  if (returncode == false) {
      if (post1.length >= 2000) {
        discordWebhook("There seems to be a new update available.\r\nSadly the post is longer than I can post here. \r\n\r\nPlease check the forums: "
        + threadurl
        + " \r\n@everyone");
        checksheet.getRange(lastrow+1,2).setValue(true);
      } else {
        discordWebhook(post1 + "\r\n\r\nThread-URL: <" + threadurl + "> \r\n@everyone");
        checksheet.getRange(lastrow+1,2).setValue(true);
      }
    };

  if (returncode == true) {
    if (checksheet.getRange(lastrow,3).getValue() != true) {
      if (post2.length >= 2000) {
        discordWebhook("There seems to be a new update available.\r\nSadly the post is longer message than I can post here. \r\n\r\nPlease check the forums: "
        + threadurl
        + " \r\n@everyone");
        checksheet.getRange(lastrow,3).setValue(true);
      } else {
        if (post2.length >= 2) {
          discordWebhook(post2 + "\r\n\r\nThread-URL: <" + threadurl + "> \r\n@everyone");
          checksheet.getRange(lastrow,3).setValue(true);
          }
        }
    }
    if (checksheet.getRange(lastrow,4).getValue() != true) {
      if (post3.length >= 2000) {
        discordWebhook("There seems to be a new update available.\r\nSadly the post is longer message than I can post here. \r\n\r\nPlease check the forums: "
        + threadurl
        + " \r\n@everyone");
        checksheet.getRange(lastrow,4).setValue(true);
      } else {
        if (post3.length >= 2) {
          discordWebhook(post3 + "\r\n\r\nThread-URL: <" + threadurl + "> \r\n@everyone");
          checksheet.getRange(lastrow,4).setValue(true);
          }
        }
    }
  }
}
 
  • Like
Reactions: poly