index.js (2601B)
1 // npm imports 2 const fetch = require("node-fetch"); 3 const wikiapi = require("wikiapi"); 4 const irc = require("irc"); 5 6 // constants 7 const { 8 channels, 9 maintainers, 10 nick, 11 password, 12 server, 13 wiki_api_endpoint, 14 } = require("./config.json"); 15 16 const wiki = new wikiapi(wiki_api_endpoint); 17 const ircClient = new irc.Client(server, nick, { 18 channels, 19 userName: "archivesrcbot", 20 realName: "archivesrcbot", 21 sasl: true, 22 password, 23 floodProtection: true, 24 floodProtectionDelay: 1000, 25 }); 26 27 // irc event-listeners 28 ircClient.addListener("error", errorHandler); 29 ircClient.addListener("message", normalMsg); 30 ircClient.addListener("pm", pmHandler); 31 32 // event listener functions 33 function errorHandler(msg) { 34 const err = JSON.stringify(msg); 35 for (const maintainer of maintainers) 36 ircClient.say(maintainer, `${nick} error: ${err}`); 37 } 38 39 async function normalMsg(sender, channel, msg) { 40 if (msg.startsWith(`${nick} `) || msg.startsWith(`${nick}: `)) 41 await start_archiveing(msg, channel); 42 } 43 44 function pmHandler(sender, msg) { 45 handleKill(sender, msg); 46 } 47 48 // helper fns 49 async function archive_sources(headline = "", channel) { 50 try { 51 const page = await wiki.page(headline); 52 if (!page.pageid) throw new Error("Page does not exist."); 53 const sources = []; 54 page.parse().each("template", function (token) { 55 if (token.name == "Source") { 56 const src = token.parameters.url; 57 sources.push(src); 58 } 59 }); 60 ircClient.say(channel, `${sources.length} sources were found.`); 61 sources.forEach(async (src) => await archiveURI(src, channel)); 62 } catch (err) { 63 ircClient.say(channel, err); 64 } 65 } 66 67 async function archiveURI(uri = "", channel) { 68 try { 69 ircClient.say(channel, `working on ${uri}.`); 70 const final_url = "https://web.archive.org/save/" + uri; 71 const res = await fetch(final_url); 72 const { url, status } = res; 73 if (!url) throw new Error("Missing URL"); 74 let sanitised_url = url.replace( 75 /https:\/\/web.archive.org\/web\/\d+\//, 76 "" 77 ); 78 const msg = sanitised_url + " " + status; 79 ircClient.say(channel, msg); 80 } catch (err) { 81 throw new Error(err); 82 } 83 } 84 85 function getHeadline(str = "") { 86 const regex = new RegExp(`${nick}:? (.*)`); 87 return str.match(regex)[1]; 88 } 89 90 function handleKill(sender, msg) { 91 if (msg != "KILL") return; 92 if (!maintainers.includes(sender)) return; 93 process.abort(); 94 } 95 96 async function start_archiveing(msg, channel) { 97 try { 98 const headline = getHeadline(msg); 99 await archive_sources(headline, channel); 100 } catch (err) { 101 ircClient.say(channel, err); 102 } 103 }