Discord Embed Bot

A 39-line Node.js bot that scrapes iFunny video links and auto-embeds them in Discord.

The Problem

Links from the social media site ifunny.co don't auto-embed within Discord. When sharing links to videos it is inconvenient to be redirected to your browser on PC or be forced into a different app on mobile just to view them.

The Solution

Just because ifunny.co doesn't have embed handling for link sharing doesn't stop us from handling the data ourselves from their CDN. Hidden inside the data returned from the HTTPS request to ifunny.co is an .mp4 file we can sniff and scrape out.


Research

Inspecting the Data

iFunny doesn't give us any APIs to work with to efficiently retrieve data, so we have to work with the source HTML given through the HTTPS request. Let's take a look at the <video> tag to see what hints we can find.

Screenshot of iFunny page source showing video tag with data-src attribute

This looks like visual garbage. Our mp4 is inside the video tag though. The HTML data can be treated as a giant string, and we can search for .mp4. This yields ~5 results per page, some of which are bogus.

This isn't a consistent enough approach and would require conditional logic. Luckily the data-src attribute (possibly used for lazy loading) is the only occurrence on the page and contains our proper data. This allows us to do only 1 search, and no conditional logic.
Implementation

Scraping the Data

Since we know what we're looking for we can use String.search() to find our substring.

let index = data.search("data-src=");

Once we have the starting index, we walk forward character by character until we hit the closing quote, building the URL as we go:

// data-src="https://img.ifunny.co/videos/ec20...e46b664c3499d820_1.mp4"

for (index += 10; index < data.length; index++) {
    if (data[index] != "\"")
        tempstr += data[index];
    else
        break;
}
Discord.js

Sending the Link

DiscordJS makes this easy. We can pass our link data with the original message object to reply with our scraped link in the same channel.

message.channel.send("" + string);
The final product is 39 lines of simple, but effective code. Software doesn't have to be complicated — it just has to serve its purpose.

Full Source

const { Client, Intents } = require("discord.js");
const client = new Client({
    intents: [Intents.FLAGS.GUILDS, Intents.FLAGS.GUILD_MESSAGES],
});
const request = require("request");
const ifunnyLink = "https://ifunny.co/video";

client.once("ready", () => {
    console.log("Discord bot operational");
});

client.on("message", message => {
    if (!message.content.startsWith(ifunnyLink) || message.author.bot) return;
    queryAndSend("" + message.content, message);
});

client.login("Super Secret Key");

function queryAndSend(link, message) {
    let tempstr = "";
    request(
        `` + link,
        (err, response, body) => {
            let data = body;
            dataLength = data.length;
            let index = data.search("data-src=");
            for (let i = index + 10; i < data.length; i++) {
                if (data[i] != "\"")
                    tempstr += data[i];
                else
                    break;
            }
            sendMessage(tempstr, message);
        }
    );
}

function sendMessage(string, message) {
    message.channel.send("" + string);
}