2023-04-19 21:45:19 +00:00
|
|
|
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: {
|
2023-06-12 00:55:35 +00:00
|
|
|
'User-Agent': 'curl/8.1.0',
|
2023-04-19 21:45:19 +00:00
|
|
|
'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);
|
2023-06-12 00:55:35 +00:00
|
|
|
json = json.replace(/^<script type="application\/ld\+json"( nonce="[^"]+")?>/, "");
|
|
|
|
console.log("Found JSON");
|
2023-04-19 21:45:19 +00:00
|
|
|
|
|
|
|
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;
|
|
|
|
}
|
2023-06-12 00:55:35 +00:00
|
|
|
const url = message.content.split(" ")[0];
|
|
|
|
console.log("Fetching content for URL: " + url);
|
2023-04-19 21:45:19 +00:00
|
|
|
|
2023-06-12 00:55:35 +00:00
|
|
|
let data;
|
|
|
|
try {
|
|
|
|
data = await fetchData(url);
|
|
|
|
} catch(err) {
|
|
|
|
console.log("Error fetching, retrying:", err);
|
|
|
|
try {
|
|
|
|
data = await fetchData(url);
|
|
|
|
} catch(err) {
|
|
|
|
console.log("Error fetching URL: " + url);
|
|
|
|
console.log("Error:", err);
|
|
|
|
message.channel.send("Failed to fetch data for link");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-04-19 21:45:19 +00:00
|
|
|
if(!data) {
|
2023-06-12 00:55:35 +00:00
|
|
|
console.log("data is empty");
|
|
|
|
message.channel.send("Link had no data, or something went wrong");
|
2023-04-19 21:45:19 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2023-06-12 00:55:35 +00:00
|
|
|
const sendObj = {
|
2023-04-19 21:45:19 +00:00
|
|
|
embeds: [{
|
|
|
|
author: {
|
2023-06-12 00:55:35 +00:00
|
|
|
name: data?.author?.alternateName,
|
|
|
|
icon_url: data?.author?.image,
|
2023-04-19 21:45:19 +00:00
|
|
|
},
|
2023-06-12 00:55:35 +00:00
|
|
|
title: data?.author?.name,
|
|
|
|
description: data?.headline,
|
2023-04-19 21:45:19 +00:00
|
|
|
}],
|
2023-06-12 00:55:35 +00:00
|
|
|
files: (data.video || []).map(d => d.contentUrl)
|
|
|
|
};
|
|
|
|
|
|
|
|
const interval = setInterval(() => message.channel.sendTyping().catch(() => {}), 3000);
|
|
|
|
let success = true;
|
|
|
|
try {
|
|
|
|
console.log("posting...");
|
|
|
|
message.channel.sendTyping().catch(() => {});
|
|
|
|
await message.channel.send(sendObj);
|
|
|
|
} catch(err) {
|
|
|
|
console.log("Error posting to discord, attempting backup:", err);
|
|
|
|
sendObj.content = sendObj.files.join(" ");
|
|
|
|
delete sendObj.files;
|
|
|
|
try {
|
|
|
|
await message.channel.send(sendObj);
|
|
|
|
} catch(err) {
|
|
|
|
console.log("error posting backup", err);
|
|
|
|
success = false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if(success) console.log("posted!");
|
|
|
|
clearInterval(interval);
|
2023-04-19 21:45:19 +00:00
|
|
|
});
|
|
|
|
|
|
|
|
client.login(process.env.TOKEN).then(() => console.log("Logged into Discord as", client.user.username + "#" + client.user.discriminator));
|
|
|
|
|