95 lines
2.4 KiB
JavaScript
95 lines
2.4 KiB
JavaScript
|
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('<script type="application/ld+json"');
|
||
|
if(index < 0) {
|
||
|
console.log("couldn't find json data in html");
|
||
|
return;
|
||
|
}
|
||
|
let json = text.substring(index);
|
||
|
json = json.replace(/^<script type="application\/ld\+json" nonce="[^"]+">/, "");
|
||
|
|
||
|
index = json.indexOf('}</script>');
|
||
|
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));
|
||
|
|