const discord = require("discord.js"); require("dotenv").config(); // for some reason, node.js's built-in fetch function doesn't work for this // also node-fetch doesn't like being required const fetch = (...args) => import("node-fetch").then(n => n.default(...args)); const client = new discord.Client({ intents: [ discord.GatewayIntentBits.Guilds, discord.GatewayIntentBits.GuildMessages, discord.GatewayIntentBits.MessageContent, ], sweepers: { messages: { lifetime: 3600, interval: 3600, } } }); // grab data from an instagram url async function fetchData(url) { const res = await fetch(url, { headers: { 'User-Agent': 'curl/8.0.1', 'Accept': '*/*' }, credentials: "omit", }); if(!res.ok) { console.log("oops. fetching instagram link returned bad status", res.statusText); return; } const text = await res.text(); // here's where the wacky stuff happens // okay so instagram for some reason includes a full JSON-LD dump of // the post in the html returned, in this script tag // i just need to find the boundaries and parse the json let index = text.indexOf(''); if(index < 0) { console.log("couldn't find end of json data in html"); return; } json = json.substring(0, index+1); let data; try { data = JSON.parse(json); } catch(err) { console.log("couldn't parse json", err); return; } return data; } client.on("messageCreate", async message => { if(message.author.bot) { return; } if(!/^https?:\/\/(www\.)?instagram\.com\/reel/.test(message.content)) { return; } const data = await fetchData(message.content.split(" ")[0]); if(!data) { return; } message.channel.send({ embeds: [{ author: { name: data.author.alternateName, icon_url: data.author.image, }, title: data.author.name, description: data.headline, }], files: data.video.map(d => d.contentUrl) }); }); client.login(process.env.TOKEN).then(() => console.log("Logged into Discord as", client.user.username + "#" + client.user.discriminator));