diff --git a/.gitignore b/.gitignore index b7d4aa3..6da04de 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,2 @@ node_modules -config.js -package-lock.json +config.js \ No newline at end of file diff --git a/backup.sql b/backup.sql deleted file mode 100644 index dae32d0..0000000 --- a/backup.sql +++ /dev/null @@ -1,109 +0,0 @@ -INSERT INTO `blog` (`date`, `category`, `title`, `body`) -VALUES - ( - "2020-07-28 16:51:00", 1, "Banners.", - "Konnichiwa. I made banners for my websites of 88x31 and 240x60 sizes."), - ( - "2020-07-29 00:00:00", 1, "Quick rundown on what happened since the december of the last year.", - "At first I moved off to aravs.ru domain in december 2019 that I was gonna change with, maybe, old arav.icu if it'll be available for cheap because renewal prices are too high for me. But then I found a new registrar with dirt cheap renewal price and now I have arav.top domain I've payed for 2 years and if nothing change I'll renew it again and again. So, yes, I finally found my domain that I'm not gonna switch if only I will be forced to.n" - "And mostly because of my lazyness I wasn't updating arav.neocities.org for fucking 3 months. That's also because I was trying to reduce its about page.n" - "Then at July 13th my RPi suddenly stopped working. It didn't take much time to realise that the problem was a dying HDD. Hopefully, fsck fixed filesystem and I successfully moved all the stuff onto another drive I took from a laptop that was holding my data. And at July 16th a new SSD arrivedto replace old laptop's system drive that now holds all my stuff and I came back online."), - ( - "2020-11-07 00:40:00", 1, "Looks like I'm back to work on this website.", - "And maybe I'll finally do something with my neocities' website. Maybe..."), - ( - "2020-11-10 14:54:00", 1, "New banners.", - "I made new banners. They're pretty much the same as was before. I fixed frames order and logo now takes all width."), - ( - "2020-11-14 00:50:00", 1, "Oh, PGP key wasn't accessible... Shite.", - "I just found that my PGP key isn't available. Now it is. I apologise to those who wanted it. According to logs this was a problem since the second half of september. :/"), - ( - "2020-11-16 00:10:00", 1, "Dark theme flickering fixed.", - "Now a check for a current theme is inside a DOMContentLoaded event listener and script itself is now in a <head>.\n" - "I also added an async attribute to a guestbook's script so page won't wait for guestbook posts to load and won't flicker light theme because of that.\n" - "And I remade 88x31 banner and made banner's dark counterparts as well. So you have what to choose from. :)"), - ( - "2020-11-16 11:28:00", 1, "Maintanance.", - "It's time to replace a thermal compound in the laptop, so radio, FTP and Gitea would be down for a while today."), - ( - "2020-11-16 13:40:00", 1, "Maintanance complete.", - "Thermal compound replaced, not much dust there was. It used to work at 62°C. Will see later. :) Now it runs on 49°C after 11 minutes. That only means I did everything right.\n" - "P.S.: Now it runs on 49-52°C. Nice."), - ( - "2020-11-16 15:59:00", 1, "Uuhh, this motherfucker still flickers...", - "Is there a cure for it ... ? At least, I managed to reduce this soykaf."), - ( - "2020-11-17 18:13:00", 1, "Dark theme is default from now.", - "Ok, in order to make flickering less painful I made dark theme default."), - ( - "2020-11-17 21:57:00", 1, "Yay, fuck JS!", - "I rewrote the guestbook without JS. Hooray!"), - ( - "2020-11-19 00:12:00", 1, "ScrapTheChan ver. 0.4.0 released.", - "Today I fixed most of noticed problems and released it. Changelog is behind the link."), - ( - "2020-11-19 22:51:00", 2, "Yesterday I was replacing a thermal compound on my PC.", - "Yesterday (19 Nov for me is it :)) I replaced a thermal compound on my PC, and, of course, it just couldn't be an ordinary procedure.\n" - "When I assembled everything back and turned on the PC it started swearing at me with 26 beeps and rebooting. I knew that it could be a problem with a RAM stick, but I didn't believe it. And I dissassembled it again and found that a few pins were bended and one missing (!). I fixed them all (around 5 didn't count) and was thinking what to do with that missing pin. I thought it was causing problem but searching led me to a pinout of the socket 1150 and that pin was doing something called VDDQ, and I found that it isn't a problem at all. There was a questionable pin SA_DQ57 (whatever it means), but I bended it a little and it's fine.\n" - "Oh, why I even took it from the socket? To clean it from an old thermal compound.\n" - "Well, I almost give in to a thought of taking a motherboard to a service and then I tried to put a RAM stick to the second slot and ... it worked! Shit, I don't know what happened. I've vacuumed the motherboard and was absolutely careful. No doubt I didn't break anything, yet, fuck. That vacuum cleaner isn't even powerful enough to suck in anything soldered.\n" - "But there's one breakage for sure. One of fixators of a cooler has broken. Shit. Now radiator isn't attached well to the CPU. Hopefully it led to the same temperatures as they was before at least. xD Don't want to whip up it with shit and bricks a zip tie, so I'd better get a new one. And I already ordered it, a little smaller, but supports socket AM4, so I will reuse it in the future, great.\n" - "What's next after all the stress I got? I'm going to replace a compound on my graphics card! Ahahahahaha! xDD\n" - "P.S.: I made a mindflow.html after I wrote this post.\n" - "Update: Okay, SA_DQ is a data bus for memory, so by bending that pin I lost first ram slot. Well, that's not because of cleaning at least.\n"), - ( - "2020-11-23 00:30:00", 1, "Recent updates.", - "I did a good work at this website. Especially I love that heading with a name of a site's section under the nav menu. And I finally made this section. I keep moving on. Next major step is to make a links page. My banners are ready, but no one would add me if I won't have a place for theirs banners. :)\n" - "Yeah, still no updates to Neocities' website. Now I'm working on a design of this place, and once I'll be satisfied that place will get an update. I work on it too, especially on an about page's content. Last not noticeable update was changing link of a guestbook to a JS-free new one."), - ( - "2020-11-26 23:54:00", 1, "Article on userdir in NGiNX.", - "I thought why not to make an article on how to implement a userdir functionality in NGiNX. Maybe, someone will want to implement this on their server.\n" - "And, an article on e-mail server is hard to finish, because every time I sit on it I find flaws in e-mail server's configuration, LMAO."), - ( - "2020-11-27 15:07:00", 1, "Tor and I2P access for this site and files.", - "I was thinking why not to make my place available through Tor and I2P. So after minor links fixing I made this place work like a charm through darkweb. Currently only main website and file share are available.\n" - "I2P site: t42fkp6zp5dfqywantq3zp427ig3q2onrmfv246tyaztpg4ckb5a.b32.i2p\n" - "I2P radio: plkybcgxt4cdanot75cy3pbnqlbqcsrib2fmrpsnug4bqphqvfda.b32.i2p\n" - "I2P files: gajftpr47ze6ao7e3q2tb5xmcqneyaczu4edzvwwg2qzmnernpka.b32.i2p\n" - "Tor site: moq7aejnf4xk5k2bkaltli3ftkhusy2mbrd3pj23nrca343ku2mgk4yd.onion\n" - "Tor radio: wsmkgnmhmzqm7kyzv7jnzzafvgm7xlmlfvzhgorpapd5or2arnhuktqd.onion\n" - "Tor files: qf5e43nlhvnrutmikuvbdfj3cmtthokpbaxtkm6mjlslttzvtgm4fxid.onion\n" - "Updated on 2021-02-10."), - ( - "2020-12-01 20:30:00", 1, "Laptop's RAM update.", - "Today I replaced old 1333MHz 2GB stick with a new 8GB 1600MHz. Now laptop has 10 gigs. I am to figure out what to fill it with. :)"), - ( - "2020-12-04 22:27:00", 1, "Article on userdir in NGiNX rewrote to be an article with recipes for it.", - "Yep, I think whole article for such a small thing is too much, so now there is an article with recipes and tips for NGiNX.\n" - "Now there is info on how to implement userdir functionality and a note about how NGiNX works with HTTP headers."), - ( - "2021-02-08 22:19:00", 1, "New year. Big changes.", - "All this time I was working on a look of a website. And just for a last week I said to myself that I'm tired of editing every single thingy across all pages. So I came to conclusion that it's time to try NodeJS. So I took Koa and Pug and ported my website to it. Well, it's really amazing. Code's so clean now (if you only saw a code of a PHP version of guestbook... xD). Template engines are an invaluably great invention. :)\n" - "Yeah, I got rid of Javascript on the outside, but instead, bring it inside. xD Anyway, I was always thinking that Javascript itself never was a problem. Problem is that it is often used where absolutely unnecessary. And browser's APIs brings many convenient tools for us alongside with the ways of doing malicious deeds as well (like fingerprinting, crypto-mining, viruses, etc.). Alas, this is one of the laws of life, everything could be used for evil.\n" - "There's one project I'm working on (now developing database). It's a service for file uploading, but files could be downloaded just one time. Yeah, I called it "One-Time File". It'll be available by otf.arav.top link. A file would be kept for 7 days until it won't be downloaded, and size limit is 120MB. That'll be a really interesting experience, since I'll've to figure out how to be sure that file was fully downloaded before it can be deleted. :)\n" - "And speaking of my Neocities' site. Well, it looks like that I move out of there, but I definitely don't. That place would be my outpost with links to my website and services. :/"), - ( - "2021-03-04 17:03:00", 1, "Radio playlist update #1", - "From now on I will post what music I've added to the radio. And what I've added are: André Rieu - The Second Waltz, Cake - Hem Of Your Garment and Dernière Volonté - L'Appel."), - ( - "2021-03-05 18:26:51", 1, "Radio playlist update #2", - "Beborn Beton - New Born King and 相対性理論 - チャイナアドバイス were added."), - ( - "2021-03-11 14:31:55", 1, "Now git is available as a hidden service.", - "Now you can browse my Gitea instance via Tor and I2P. Alas, it requires you to have a fixed domain and root URL specified in a config. So some links are pointing to git.arav.top, like files in releases and a cloning URL.\n" - "Tor: qqitm7qlsbbubwmjos4cqzmvkqidg34rfnbyhuydhalep33fbvh22xyd.onion\n" - "I2P: p5nkflgogwv4esy3ainup6mgurpugmdyufizhuufauznreyvprsa.b32.i2p"); - - -INSERT INTO `guestbook` -VALUES - (1, "2020-09-01 00:15:22", "Serana", "", "", "hey whats up! i recently found that out neocities is actually really cool and have spent the past few hours looking through whatever sites i can find (yours included!). figured i'd drop a message and say to keep up what you're doing! this is all really cool and i'm feeling all motivated to make something becuase of it. hope you have a nice day <3", 1, 1), - (2, "2020-11-09 04:18:27", "duli", "", "", "your website is super cool! hope you're having a good day <3", 1, 1), - (3, "2021-02-15 18:44:39", "Anonymous", "", "", "Cool website design, dig the .onion address, enjoying the radio station!", 1, 1); - -INSERT INTO `guestbook_feedback` -VALUES - (1, "2020-11-10 00:17:31", "Well, better late than never. :) Hope feedbacks now work fine. Dunno when and if you ever read it again, but still, hope you're doing good as well. :) I'm so glad to read that I motivate others. Personal website is indeed a great thing that allows us to show who we are immeasuarably better than soulless social media. <3"), - (2, "2020-11-10 00:17:31", "Hi! Yeah, hope and you do so! <3 Great, that means I'm defenitely moving in a right direction. :) Need to dedicate more time for the websites, especially neocities' one literally begs to be updated, heh. But I have to rethink this first."), - (3, "2021-02-16 23:21:34", "Thank you! Glad to read that! :)", 1, 1); - \ No newline at end of file diff --git a/config.example.js b/config.example.js deleted file mode 100644 index 76aea0d..0000000 --- a/config.example.js +++ /dev/null @@ -1,30 +0,0 @@ -const base_host = "127.0.0.1"; - -exports.dwelling = {} - -exports.dwelling.port = 3200; -exports.dwelling.host = base_host; - -exports.dwelling.database = { - host: "192.168.0.1", - database: "db", - user: "user", - password: "password", - timezone: "Z" }; - -exports.dwelling.guestbook = {} - -exports.dwelling.guestbook.owner = "Owner"; -exports.dwelling.guestbook.pageSize = 30; - -exports.radio = {} - -exports.radio.port = 3201; -exports.radio.host = base_host; - -exports.files = {} - -exports.files.port = 3202; -exports.files.host = base_host; - -exports.files.file_path = "/srv/ftp"; \ No newline at end of file diff --git a/dwelling/mindflow.js b/dwelling/mindflow.js deleted file mode 100644 index e319367..0000000 --- a/dwelling/mindflow.js +++ /dev/null @@ -1,49 +0,0 @@ -const mysql = require("mysql"); - -const config = require("../config"); -const util = require("../util"); - - -let connection = mysql.createConnection(config.dwelling.database); - - -connection.config.queryFormat = util.mysqlQueryFormat; - -exports.closeConnection = () => connection.end(); - -exports.getPosts = category => { - return new Promise((resolve, reject) => { - let query = "\ - SELECT\ - `blog`.`entry_id` AS `post_id`,\ - `blog`.`date`,\ - `blog`.`title`,\ - `blog`.`body`\ - FROM `blog`\ - LEFT JOIN `blog_categories` ON `blog_categories`.`category_id` = `blog`.`category`\ - WHERE `blog_categories`.`category` = :category\ - ORDER BY `blog`.`date` DESC;"; - - connection.query(query, { category: category }, (err, results) => { - if (err) reject(err); - resolve(results); }); - }); -}; - -exports.getPostsForRSS = () => { - return new Promise((resolve, reject) => { - let query = "\ - SELECT\ - `blog`.`date`,\ - `blog_categories`.`category`,\ - `blog`.`title`,\ - `blog`.`body`\ - FROM `blog`\ - LEFT JOIN `blog_categories` ON `blog_categories`.`category_id` = `blog`.`category`\ - ORDER BY `blog`.`date` DESC;"; - - connection.query(query, (err, results) => { - if (err) reject(err); - resolve(results); }); - }); -}; \ No newline at end of file diff --git a/files.js b/files.js deleted file mode 100644 index 44822c2..0000000 --- a/files.js +++ /dev/null @@ -1,119 +0,0 @@ -const fs = require("fs"); -const path = require("path"); - -const Koa = require("koa"); -const koaPug = require("koa-pug"); -const koaRouter = require("koa-router"); -const koaRange = require("koa-range"); - -const config = require("./config"); -const util = require("./util"); -const { ENOENT, ECONNRESET } = require("constants"); - -const SIZE_UNITS = [ "B", "KiB", "MiB", "GiB" ]; - -function makeCurrentPathField(path) { - let current = `root`; - if (path.endsWith("/")) - path = path.slice(1, path.length-1); - const path_parts = path.split("/"); - - for (i = 0; i < path_parts.length; ++i) { - let lnk = ""; - for (j = 0; j < i+1; ++j) { - lnk += `/${path_parts[j]}`; - } - current += `/${path_parts[i]}`; - } - - return current; -} - -function convertSize(size) { - let i = 0; - for (; size > 1024; size /= 1024) { ++i; } - return [i > 0 ? size.toFixed(2) : size, SIZE_UNITS[i]]; -} - -function sortByNameField(a, b) { - if (a.name > b.name) - return 1; - else if (a.name < b.name) - return -1; - return 0; -} - -async function getDirectoryList(dir_path, orig_url) { - let dirs = []; - let files = []; - let total_files_size = 0; - let d = await fs.promises.opendir(dir_path); - for await (const dirent of d) { - const stat = fs.lstatSync(path.join(dir_path, dirent.name)); - const [s, u] = convertSize(stat.size); - if (stat.isDirectory()) - dirs.push({ - name: dirent.name, - link: `${encodeURIComponent(dirent.name)}/`, - datetime: util.datetime(stat.mtime, util.formats.file_date), - size: "DIR", - size_unit: '' }); - else { - total_files_size += stat.size; - files.push({ - name: dirent.name, - link: `/files${orig_url}${encodeURIComponent(dirent.name)}`, - datetime: util.datetime(stat.mtime, util.formats.file_date), - size: +s, - size_unit: u }); - } - } - - dirs.sort(sortByNameField); - files.sort(sortByNameField); - - return [dirs.concat(files), dirs.length, files.length, - convertSize(total_files_size).join(' ')]; -} - -function setRoutes(router) { - router.get('/(.*)?', async ctx => { - const file_path = path.join(config.files.file_path, decodeURI(ctx.originalUrl)); - let stat = fs.lstatSync(file_path); - if (stat.isDirectory()) { - const [items, total_directories, total_files, total_files_size] - = await getDirectoryList(file_path, decodeURI(ctx.originalUrl)); - await ctx.render('index', { - title: "/ Files", - description: "File share.", - main_site: util.getServiceByHost(ctx.header.host), - current_path: makeCurrentPathField(decodeURI(ctx.originalUrl)), - total_files: total_files, - total_files_size: total_files_size, - total_directories: total_directories, - items: items }); - } - }); -} - -module.exports = () => { - const app = new Koa(); - const pug = new koaPug({ - viewPath: path.join(__dirname, "views", "files"), - locals: { - moment: date => util.datetime(date, util.formats.file_date) }, - app: app - }); - - const radio_router = koaRouter(); - setRoutes(radio_router); - - app.proxy = true; - app - .use(koaRange) - .use(radio_router.routes()) - .on("error", err => { if (!err.code == ECONNRESET || !err.code == ENOENT) console.log(err.code); }) - .listen(config.files.port, config.files.host); - - return app; -} \ No newline at end of file diff --git a/files/config.example.js b/files/config.example.js new file mode 100644 index 0000000..1a61c58 --- /dev/null +++ b/files/config.example.js @@ -0,0 +1,3 @@ +exports.host = "0.0.0.0"; +exports.port = 32202; +exports.share_path = "/srv/ftp"; \ No newline at end of file diff --git a/files/index.js b/files/index.js new file mode 100644 index 0000000..22fbc77 --- /dev/null +++ b/files/index.js @@ -0,0 +1,119 @@ +const fs = require("fs"); +const path = require("path"); +const { ENOENT, ECONNRESET } = require("constants"); + +const Koa = require("koa"); +const koaPug = require("koa-pug"); +const koaRouter = require("koa-router"); + +const config = require("./config"); +const util = require("../shared/util"); + + + +const SIZE_UNITS = [ "B", "KiB", "MiB", "GiB" ]; + +function addFileSizeUnit(size) { + let i = 0; + for (; size > 1024; size /= 1024) ++i; + return [i > 0 ? size.toFixed(2) : size, SIZE_UNITS[i]]; +} + + +function buildCurrentPathLink(path) { + let currentPath = `root`; + + if (path.endsWith("/")) + path = path.slice(1, path.length-1); + + const path_parts = path.split("/"); + + for (let i = 0; i < path_parts.length; ++i) { + let lnk = ""; + + for (let j = 0; j < i+1; ++j) + lnk += `/${path_parts[j]}`; + + currentPath += `/${path_parts[i]}`; + } + + return currentPath; +} + +function sortFuncByNameField(a, b) { + return (a.name > b.name) ? 1 : (a.name < b.name) ? -1 : 0; +} + +async function getDirectoryList(dir_path, orig_url) { + let directories = []; + let files = []; + let total_files_size = 0; + let directory = await fs.promises.opendir(dir_path); + + for await (const dirent of directory) { + const stat = await fs.promises.stat(path.join(dir_path, dirent.name)); + const [s, u] = addFileSizeUnit(stat.size); + + if (stat.isDirectory()) + directories.push({ + name: dirent.name, + link: `${encodeURIComponent(dirent.name)}/`, + datetime: stat.mtime, + size: "DIR" }); + else { + total_files_size += stat.size; + files.push({ + name: dirent.name, + link: `/files${orig_url}${encodeURIComponent(dirent.name)}`, + datetime: stat.mtime, + size: `${s} ${u}` }); + } + } + + directories.sort(sortFuncByNameField); + files.sort(sortFuncByNameField); + + return [directories.concat(files), directories.length, files.length, + addFileSizeUnit(total_files_size).join(' ')]; +} + +function setRoutes() { + return koaRouter().get('/(.*)?', async ctx => { + const file_path = path.join(config.share_path, decodeURI(ctx.originalUrl)); + + let stat = await fs.promises.stat(file_path); + + if (stat.isDirectory()) { + const [items, total_directories, total_files, total_files_size] + = await getDirectoryList(file_path, decodeURI(ctx.originalUrl)); + + await ctx.render('index', { + title: "/ Files", + description: "File share.", + clientTZ: util.getClientTimezone(ctx), + main_site: util.getServiceByHost(ctx.header.host), + current_path: buildCurrentPathLink(decodeURI(ctx.originalUrl)), + total_files: total_files, + total_files_size: total_files_size, + total_directories: total_directories, + items: items }); + } + }); +} + + +const app = new Koa(); +const pug = new koaPug({ + viewPath: path.join(__dirname, "views"), + locals: { + moment: (date, tz) => util.datetime(date, util.formats.file_date, tz), }, + app: app +}); + +app.proxy = true; +app + .use(setRoutes().routes()) + // .on("error", err => { if (!err.code == ECONNRESET || !err.code == ENOENT) console.log(err.code); }) + .listen(config.port, config.host); + +console.log("Arav's dwelling / Files is up."); \ No newline at end of file diff --git a/static/files/assets/css/main.css b/files/static/assets/css/main.css similarity index 100% rename from static/files/assets/css/main.css rename to files/static/assets/css/main.css diff --git a/files/static/robots.txt b/files/static/robots.txt new file mode 100644 index 0000000..8811370 --- /dev/null +++ b/files/static/robots.txt @@ -0,0 +1,2 @@ +User-agent: * +Disallow: /assets/ \ No newline at end of file diff --git a/files/views/index.pug b/files/views/index.pug new file mode 100644 index 0000000..389f3b7 --- /dev/null +++ b/files/views/index.pug @@ -0,0 +1,36 @@ +doctype html +html(lang='en') + head + title Arav's dwelling #{title} + meta(charset='utf-8') + meta(http-equiv='X-UA-Compatible' content='IE=edge') + meta(name='viewport' content='width=device-width, initial-scale=1.0') + meta(name='theme-color' content='#cd2682') + meta(name='description' content=description) + link(rel='icon' type='image/svg+xml' href='/shared/img/favicon.svg' sizes='any') + link(href='/assets/css/main.css' rel='stylesheet') + body + header + svg#logo(viewBox='0 -25 216 40') + text.logo Arav's dwelling + text.under(y='11') Welcome to my sacred place, wanderer + nav + a(href=main_site) Back to main website + h1 Files + section#files + span#current-path!= current_path + p Files: #{total_files} (#{total_files_size}); Directories: #{total_directories}. + table + thead + tr + th Name + th Date + th Size + tbody + tr + td #[a(href="../") ../] + each item in items + tr + td #[a(href=item.link)= item.name] + td!= moment(item.datetime, clientTZ) + td= item.size \ No newline at end of file diff --git a/homepage/config.example.js b/homepage/config.example.js new file mode 100644 index 0000000..a3ecf46 --- /dev/null +++ b/homepage/config.example.js @@ -0,0 +1,14 @@ +exports.port = 32250; +exports.host = "127.0.0.1"; + +exports.database = { + host: "127.0.0.1", + database: "db", + user: "db", + password: "dbpass", + timezone: "Z" }; + +exports.guestbook = { + owner: "Owner", + pageSize: 30 +} \ No newline at end of file diff --git a/dwelling/guestbook.js b/homepage/guestbook.js similarity index 55% rename from dwelling/guestbook.js rename to homepage/guestbook.js index 9d7e5cf..328f30f 100644 --- a/dwelling/guestbook.js +++ b/homepage/guestbook.js @@ -1,44 +1,44 @@ const mysql = require("mysql"); -const config = require("../config"); -const util = require("../util"); +const config = require("./config"); +const util = require("../shared/util"); -let connection = mysql.createConnection(config.dwelling.database); +let connection = mysql.createConnection(config.database); connection.config.queryFormat = util.mysqlQueryFormat; -exports.pageSize = config.dwelling.guestbook.pageSize !== undefined - ? config.dwelling.guestbook.pageSize : 20; +exports.pageSize = config.guestbook.pageSize !== undefined + ? config.guestbook.pageSize : 20; exports.closeConnection = () => connection.end(); exports.getPosts = async (page = 1, page_size = exports.pageSize) => { return new Promise((resolve, reject) => { - let query = "\ - SELECT \ - `guestbook`.`post_id`, \ - `guestbook`.`created`, \ - `guestbook`.`name`, \ - (CASE \ - WHEN `guestbook`.`hide_email` IS false \ - THEN `guestbook`.`email` \ - ELSE NULL \ - END) AS `email`, \ - (CASE \ - WHEN `guestbook`.`hide_website` IS false \ - THEN `guestbook`.`website` \ - ELSE NULL \ - END) AS `website`, \ - `guestbook`.`message`, \ - `guestbook_feedback`.`comment` AS `feedback`, \ - `guestbook_feedback`.`created` AS `feedback_created` \ - FROM `guestbook` \ - LEFT JOIN `guestbook_feedback` ON `guestbook`.`post_id` = `guestbook_feedback`.`post_id` \ - ORDER BY `guestbook`.`created` DESC \ - LIMIT :page_size \ - OFFSET :page_offset;"; + let query = ` + SELECT + guestbook.post_id, + guestbook.created, + guestbook.name, + (CASE + WHEN guestbook.hide_email IS false + THEN guestbook.email + ELSE NULL + END) AS email, + (CASE + WHEN guestbook.hide_website IS false + THEN guestbook.website + ELSE NULL + END) AS website, + guestbook.message, + guestbook_feedback.comment AS feedback, + guestbook_feedback.created AS feedback_created + FROM guestbook + LEFT JOIN guestbook_feedback ON guestbook.post_id = guestbook_feedback.post_id + ORDER BY guestbook.created DESC + LIMIT :page_size + OFFSET :page_offset;`; connection.query(query, { page_size: page_size, page_offset: (page-1) * page_size }, (err, results) => { @@ -63,10 +63,10 @@ exports.addPost = async (post) => { VALUES (:name, :email, :website, :message, :hide_website, :hide_email);"; if (post.message === undefined || post.message === "") - reject("empty message"); + return reject("empty message"); - if (post.message.includes("://")) - reject("spam"); + if (post.message.includes("")) + return reject("spam"); if (post.name === undefined || post.name === "") post.name = "Anonymous"; @@ -76,7 +76,7 @@ exports.addPost = async (post) => { post.message = post.message.replace(/(?:\n\n|\n \n)/g, "\n"); connection.query(query, post, (err, results, fields) => { - if (err) reject(err); - resolve(true); }); + if (err) return reject(err); + return resolve(true); }); }); } \ No newline at end of file diff --git a/dwelling.js b/homepage/index.js similarity index 77% rename from dwelling.js rename to homepage/index.js index 3abbaeb..3e9c602 100644 --- a/dwelling.js +++ b/homepage/index.js @@ -1,16 +1,16 @@ const path = require("path"); +const bodyParser = require("koa-body")({multipart: true}); +const fetch = require("node-fetch"); const Koa = require("koa"); const koaPug = require("koa-pug"); const koaRouter = require("koa-router"); -const bodyParser = require("koa-body")({multipart: true}); -const mysql = require("mysql"); -const fetch = require("node-fetch"); +const { MysqlError } = require("mysql"); const config = require("./config"); -const util = require("./util"); -const guestbook = require("./dwelling/guestbook"); -const mindflow = require("./dwelling/mindflow"); +const guestbook = require("./guestbook"); +const mindflow = require("./mindflow"); +const util = require("../shared/util"); const articles_meta = { @@ -38,8 +38,8 @@ async function getProcesses() { return Object.fromEntries(Object.entries(reimu).concat(Object.entries(sakuya))); } -function setRoutes(router) { - router.get('/', async ctx => { +function setRoutes() { + return koaRouter().get('/', async ctx => { await ctx.render('index', { description: "A homepage of a russian guy Arav. Not just homepage, but FTP, radio, and smth more as well." }); @@ -65,7 +65,7 @@ function setRoutes(router) { title: "/ Mindflow", description: "Here I will post updates on my infrastructure, my very important opinions and thoughts.", files_site: util.getServiceByHost(ctx.request.host, "files"), - tz: util.getTimezone(ctx), + tz: util.getClientTimezone(ctx), diary: await mindflow.getPosts("Diary"), updates: await mindflow.getPosts("Update") }) @@ -103,8 +103,8 @@ function setRoutes(router) { return await ctx.render('guestbook', { title: "/ Guestbook", description: "This is my guestbook. Welcome.", - tz: util.getTimezone(ctx), - owner: config.dwelling.guestbook.owner, + tz: util.getClientTimezone(ctx), + owner: config.guestbook.owner, posts: posts, error: posts === null, pages_count: Math.ceil(await guestbook.getPostsCount() / page_size) }); @@ -120,7 +120,7 @@ function setRoutes(router) { ctx.redirect("/guestbook"); } catch(err) { ctx.type = "text/plain"; - if (err instanceof mysql.MysqlError) + if (err instanceof MysqlError) ctx.body = `Database failed so your post wasn't added. So your time wasn't wasted here's your message:\n${post.message}`; else ctx.body = `Your post was rejected because of "${err}". So your time wasn't wasted here's your message:\n${post.message}`; @@ -129,35 +129,31 @@ function setRoutes(router) { } -module.exports = () => { - const app = new Koa(); - const pug = new koaPug({ - viewPath: path.join(__dirname, "views", "dwelling"), - locals: { - date_: (date, tz) => util.datetime(date, util.formats.post_date, tz), - mindflowDateToId: (date, tz) => util.datetime(date, util.formats.id_date, tz), - rssLink: util.rssLink }, - app: app - }); +const app = new Koa(); +const pug = new koaPug({ + viewPath: path.join(__dirname, "views"), + locals: { + date_: (date, tz) => util.datetime(date, util.formats.post_date, tz), + mindflowDateToId: (date, tz) => util.datetime(date, util.formats.id_date, tz), + rssLink: util.rssLink }, + app: app +}); - const dwelling_router = koaRouter(); - setRoutes(dwelling_router); - app.proxy = true; - app - .use(async (ctx, next) => { - try { - await next(); - if (ctx.status === 404) ctx.throw(404); - } catch (err) { - if (ctx.status === 404) - await ctx.render('404'); - else - await ctx.render('500'); - } - }) - .use(dwelling_router.routes()) - .listen(config.dwelling.port, config.dwelling.host); +app.proxy = true; +app + .use(async (ctx, next) => { + try { + await next(); + if (ctx.status === 404) ctx.throw(404); + } catch (err) { + if (ctx.status === 404) + await ctx.render('404'); + else + await ctx.render('500'); + } + }) + .use(setRoutes().routes()) + .listen(config.port, config.host); - return app; -}; \ No newline at end of file + console.log("Arav's dwelling / Homepage is up."); \ No newline at end of file diff --git a/homepage/mindflow.js b/homepage/mindflow.js new file mode 100644 index 0000000..796f728 --- /dev/null +++ b/homepage/mindflow.js @@ -0,0 +1,49 @@ +const mysql = require("mysql"); + +const config = require("./config"); +const util = require("../shared/util"); + + +let connection = mysql.createConnection(config.database); + + +connection.config.queryFormat = util.mysqlQueryFormat; + +exports.closeConnection = () => connection.end(); + +exports.getPosts = category => { + return new Promise((resolve, reject) => { + let query = ` + SELECT + blog.entry_id AS post_id, + blog.date, + blog.title, + blog.body + FROM blog + LEFT JOIN blog_categories ON blog_categories.category_id = blog.category + WHERE blog_categories.category = :category + ORDER BY blog.date DESC;`; + + connection.query(query, { category: category }, (err, results) => { + if (err) reject(err); + resolve(results); }); + }); +}; + +exports.getPostsForRSS = () => { + return new Promise((resolve, reject) => { + let query = ` + SELECT + blog.date, + blog_categories.category, + blog.title, + blog.body + FROM blog + LEFT JOIN blog_categories ON blog_categories.category_id = blog.category + ORDER BY blog.date DESC;`; + + connection.query(query, (err, results) => { + if (err) reject(err); + resolve(results); }); + }); +}; \ No newline at end of file diff --git a/sitemap.xml b/homepage/sitemap.xml similarity index 100% rename from sitemap.xml rename to homepage/sitemap.xml diff --git a/static/dwelling/assets/css/articles.css b/homepage/static/assets/css/articles.css similarity index 100% rename from static/dwelling/assets/css/articles.css rename to homepage/static/assets/css/articles.css diff --git a/static/dwelling/assets/css/guestbook.css b/homepage/static/assets/css/guestbook.css similarity index 100% rename from static/dwelling/assets/css/guestbook.css rename to homepage/static/assets/css/guestbook.css diff --git a/static/dwelling/assets/css/guestbook.js.css b/homepage/static/assets/css/guestbook.js.css similarity index 100% rename from static/dwelling/assets/css/guestbook.js.css rename to homepage/static/assets/css/guestbook.js.css diff --git a/static/dwelling/assets/css/index.css b/homepage/static/assets/css/index.css similarity index 100% rename from static/dwelling/assets/css/index.css rename to homepage/static/assets/css/index.css diff --git a/static/dwelling/assets/css/main.css b/homepage/static/assets/css/main.css similarity index 100% rename from static/dwelling/assets/css/main.css rename to homepage/static/assets/css/main.css diff --git a/static/dwelling/assets/css/mindflow.css b/homepage/static/assets/css/mindflow.css similarity index 100% rename from static/dwelling/assets/css/mindflow.css rename to homepage/static/assets/css/mindflow.css diff --git a/static/dwelling/assets/img/acer.webp b/homepage/static/assets/img/acer.webp similarity index 100% rename from static/dwelling/assets/img/acer.webp rename to homepage/static/assets/img/acer.webp diff --git a/static/dwelling/assets/img/acer_thumb.webp b/homepage/static/assets/img/acer_thumb.webp similarity index 100% rename from static/dwelling/assets/img/acer_thumb.webp rename to homepage/static/assets/img/acer_thumb.webp diff --git a/static/dwelling/assets/img/my_cat.webp b/homepage/static/assets/img/my_cat.webp similarity index 100% rename from static/dwelling/assets/img/my_cat.webp rename to homepage/static/assets/img/my_cat.webp diff --git a/static/dwelling/assets/img/my_cat_thumb.webp b/homepage/static/assets/img/my_cat_thumb.webp similarity index 100% rename from static/dwelling/assets/img/my_cat_thumb.webp rename to homepage/static/assets/img/my_cat_thumb.webp diff --git a/static/dwelling/assets/img/raspi.webp b/homepage/static/assets/img/raspi.webp similarity index 100% rename from static/dwelling/assets/img/raspi.webp rename to homepage/static/assets/img/raspi.webp diff --git a/static/dwelling/assets/img/raspi_thumb.webp b/homepage/static/assets/img/raspi_thumb.webp similarity index 100% rename from static/dwelling/assets/img/raspi_thumb.webp rename to homepage/static/assets/img/raspi_thumb.webp diff --git a/static/dwelling/robots.txt b/homepage/static/robots.txt similarity index 100% rename from static/dwelling/robots.txt rename to homepage/static/robots.txt diff --git a/views/dwelling/404.pug b/homepage/views/404.pug similarity index 100% rename from views/dwelling/404.pug rename to homepage/views/404.pug diff --git a/views/dwelling/500.pug b/homepage/views/500.pug similarity index 100% rename from views/dwelling/500.pug rename to homepage/views/500.pug diff --git a/views/dwelling/about.pug b/homepage/views/about.pug similarity index 100% rename from views/dwelling/about.pug rename to homepage/views/about.pug diff --git a/views/dwelling/articles/article.pug b/homepage/views/articles/article.pug similarity index 100% rename from views/dwelling/articles/article.pug rename to homepage/views/articles/article.pug diff --git a/views/dwelling/articles/nginx_recipes_and_tips.pug b/homepage/views/articles/nginx_recipes_and_tips.pug similarity index 100% rename from views/dwelling/articles/nginx_recipes_and_tips.pug rename to homepage/views/articles/nginx_recipes_and_tips.pug diff --git a/views/dwelling/articles/rpi_root_on_external_drive.pug b/homepage/views/articles/rpi_root_on_external_drive.pug similarity index 100% rename from views/dwelling/articles/rpi_root_on_external_drive.pug rename to homepage/views/articles/rpi_root_on_external_drive.pug diff --git a/views/dwelling/articles/setting_up_a_mail_server.pug b/homepage/views/articles/setting_up_a_mail_server.pug similarity index 100% rename from views/dwelling/articles/setting_up_a_mail_server.pug rename to homepage/views/articles/setting_up_a_mail_server.pug diff --git a/views/dwelling/articles/setting_up_a_tor_proxy_relay_hiddenserv.pug b/homepage/views/articles/setting_up_a_tor_proxy_relay_hiddenserv.pug similarity index 100% rename from views/dwelling/articles/setting_up_a_tor_proxy_relay_hiddenserv.pug rename to homepage/views/articles/setting_up_a_tor_proxy_relay_hiddenserv.pug diff --git a/views/dwelling/base.pug b/homepage/views/base.pug similarity index 100% rename from views/dwelling/base.pug rename to homepage/views/base.pug diff --git a/views/dwelling/guestbook.pug b/homepage/views/guestbook.pug similarity index 100% rename from views/dwelling/guestbook.pug rename to homepage/views/guestbook.pug diff --git a/views/dwelling/index.pug b/homepage/views/index.pug similarity index 100% rename from views/dwelling/index.pug rename to homepage/views/index.pug diff --git a/views/dwelling/mindflow.pug b/homepage/views/mindflow.pug similarity index 100% rename from views/dwelling/mindflow.pug rename to homepage/views/mindflow.pug diff --git a/views/dwelling/rss.pug b/homepage/views/rss.pug similarity index 100% rename from views/dwelling/rss.pug rename to homepage/views/rss.pug diff --git a/views/dwelling/stuff.pug b/homepage/views/stuff.pug similarity index 100% rename from views/dwelling/stuff.pug rename to homepage/views/stuff.pug diff --git a/index.js b/index.js deleted file mode 100644 index b21a21f..0000000 --- a/index.js +++ /dev/null @@ -1,9 +0,0 @@ - -const app_dwelling = require("./dwelling")(); -console.log("Arav's dwelling / Main website is up."); - -const app_radio = require("./radio")(); -console.log("Arav's dwelling / Radio is up."); - -const app_files = require("./files")(); -console.log("Arav's dwelling / Files is up."); \ No newline at end of file diff --git a/install.sql b/install.sql deleted file mode 100644 index 9d5ec19..0000000 --- a/install.sql +++ /dev/null @@ -1,53 +0,0 @@ --- Was meant to work on MySQL/MariaDB - - CREATE DATABASE `dwelling` -COLLATE utf8mb4_unicode_ci; - -USE `dwelling`; - - CREATE USER `dweller`@`%` -IDENTIFIED BY 'password'; - -GRANT ALL PRIVILEGES - ON `dwelling`.* - TO `dweller`@`%`; - -CREATE TABLE `blog_categories` ( - `category_id` MEDIUMINT PRIMARY KEY AUTO_INCREMENT, - `category` VARCHAR(40) NOT NULL UNIQUE ); - -INSERT INTO `blog_categories` (`category`) -VALUES ('Update'), ('Diary'); - -CREATE INDEX `blog_categories_ix_category` - ON `blog_categories` (`category`); - -CREATE TABLE `blog` ( - `entry_id` SERIAL PRIMARY KEY, - `date` DATETIME DEFAULT CURRENT_TIMESTAMP NOT NULL, - `category` MEDIUMINT NOT NULL, - `title` VARCHAR(255) NOT NULL, - `body` MEDIUMTEXT NOT NULL, - FOREIGN KEY (`category`) REFERENCES `blog_categories` (`category_id`) - ON UPDATE CASCADE ); - -CREATE TABLE IF NOT EXISTS `guestbook` ( - `post_id` SERIAL PRIMARY KEY, - `created` DATETIME DEFAULT CURRENT_TIMESTAMP NOT NULL, - `name` VARCHAR(80) NOT NULL, - `email` VARCHAR(255), - `website` VARCHAR(255), - `message` VARCHAR(4096) NOT NULL, - `hide_website` BOOLEAN DEFAULT TRUE NOT NULL, - `hide_email` BOOLEAN DEFAULT TRUE NOT NULL); - -CREATE INDEX IF NOT EXISTS `guestbook_ix_created` - ON `guestbook` (`created`); - -CREATE TABLE IF NOT EXISTS `guestbook_feedback` ( - `post_id` SERIAL PRIMARY KEY, - `created` DATETIME DEFAULT CURRENT_TIMESTAMP NOT NULL, - `comment` VARCHAR(4096) NOT NULL, - FOREIGN KEY (`post_id`) REFERENCES `guestbook` (`post_id`) - ON DELETE CASCADE - ON UPDATE CASCADE ); \ No newline at end of file diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 0000000..098d57c --- /dev/null +++ b/package-lock.json @@ -0,0 +1,2330 @@ +{ + "name": "arav-dwelling", + "version": "21.22.0", + "lockfileVersion": 2, + "requires": true, + "packages": { + "": { + "name": "arav-dwelling", + "version": "21.22.0", + "license": "GPLv3", + "dependencies": { + "koa": "^2.13.1", + "koa-body": "^4.2.0", + "koa-pug": "^5.0.0", + "koa-range": "^0.3.0", + "koa-router": "^10.0.0", + "koa-static": "^5.0.0", + "moment": "^2.29.1", + "moment-timezone": "^0.5.33", + "mysql": "^2.18.1", + "node-fetch": "^2.6.1" + } + }, + "node_modules/@babel/helper-validator-identifier": { + "version": "7.14.0", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.14.0.tgz", + "integrity": "sha512-V3ts7zMSu5lfiwWDVWzRDGIN+lnCEUdaXgtVHJgLb1rGaA6jMrtB9EmE7L18foXJIE8Un/A/h6NJfGQp/e1J4A==" + }, + "node_modules/@babel/parser": { + "version": "7.14.4", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.14.4.tgz", + "integrity": "sha512-ArliyUsWDUqEGfWcmzpGUzNfLxTdTp6WU4IuP6QFSp9gGfWS6boxFCkJSJ/L4+RG8z/FnIU3WxCk6hPL9SSWeA==", + "bin": { + "parser": "bin/babel-parser.js" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@babel/types": { + "version": "7.14.4", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.14.4.tgz", + "integrity": "sha512-lCj4aIs0xUefJFQnwwQv2Bxg7Omd6bgquZ6LGC+gGMh6/s5qDVfjuCMlDmYQ15SLsWHd9n+X3E75lKIhl5Lkiw==", + "dependencies": { + "@babel/helper-validator-identifier": "^7.14.0", + "to-fast-properties": "^2.0.0" + } + }, + "node_modules/@types/formidable": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/@types/formidable/-/formidable-1.2.2.tgz", + "integrity": "sha512-8RDAMnMHOh7QrY1xuQ7s6/Xre9pMvJ2zT2VgATiz5cIE71Q/6N3+P8sr3z/dNWNmvX5/aX9x8uJlG0MZiMZXoA==", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/node": { + "version": "15.12.1", + "resolved": "https://registry.npmjs.org/@types/node/-/node-15.12.1.tgz", + "integrity": "sha512-zyxJM8I1c9q5sRMtVF+zdd13Jt6RU4r4qfhTd7lQubyThvLfx6yYekWSQjGCGV2Tkecgxnlpl/DNlb6Hg+dmEw==" + }, + "node_modules/accepts": { + "version": "1.3.7", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.7.tgz", + "integrity": "sha512-Il80Qs2WjYlJIBNzNkK6KYqlVMTbZLXgHx2oT0pU/fjRHyEp+PEfEPY0R3WCwAGVOtauxh1hOxNgIf5bv7dQpA==", + "dependencies": { + "mime-types": "~2.1.24", + "negotiator": "0.6.2" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/acorn": { + "version": "7.4.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz", + "integrity": "sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==", + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/any-promise": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz", + "integrity": "sha1-q8av7tzqUugJzcA3au0845Y10X8=" + }, + "node_modules/asap": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz", + "integrity": "sha1-5QNHYR1+aQlDIIu9r+vLwvuGbUY=" + }, + "node_modules/assert-never": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/assert-never/-/assert-never-1.2.1.tgz", + "integrity": "sha512-TaTivMB6pYI1kXwrFlEhLeGfOqoDNdTxjCdwRfFFkEA30Eu+k48W34nlok2EYWJfFFzqaEmichdNM7th6M5HNw==" + }, + "node_modules/at-least-node": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/at-least-node/-/at-least-node-1.0.0.tgz", + "integrity": "sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg==", + "engines": { + "node": ">= 4.0.0" + } + }, + "node_modules/babel-walk": { + "version": "3.0.0-canary-5", + "resolved": "https://registry.npmjs.org/babel-walk/-/babel-walk-3.0.0-canary-5.tgz", + "integrity": "sha512-GAwkz0AihzY5bkwIY5QDR+LvsRQgB/B+1foMPvi0FZPMl5fjD7ICiznUiBdLYMH1QYe6vqu4gWYytZOccLouFw==", + "dependencies": { + "@babel/types": "^7.9.6" + }, + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/bignumber.js": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-9.0.0.tgz", + "integrity": "sha512-t/OYhhJ2SD+YGBQcjY8GzzDHEk9f3nerxjtfa6tlMXfe7frs/WozhvCNoGvpM0P3bNf3Gq5ZRMlGr5f3r4/N8A==", + "engines": { + "node": "*" + } + }, + "node_modules/bytes": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.0.tgz", + "integrity": "sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/cache-content-type": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/cache-content-type/-/cache-content-type-1.0.1.tgz", + "integrity": "sha512-IKufZ1o4Ut42YUrZSo8+qnMTrFuKkvyoLXUywKz9GJ5BrhOFGhLdkx9sG4KAnVvbY6kEcSFjLQul+DVmBm2bgA==", + "dependencies": { + "mime-types": "^2.1.18", + "ylru": "^1.2.0" + }, + "engines": { + "node": ">= 6.0.0" + } + }, + "node_modules/call-bind": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", + "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", + "dependencies": { + "function-bind": "^1.1.1", + "get-intrinsic": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/character-parser": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/character-parser/-/character-parser-2.2.0.tgz", + "integrity": "sha1-x84o821LzZdE5f/CxfzeHHMmH8A=", + "dependencies": { + "is-regex": "^1.0.3" + } + }, + "node_modules/co": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", + "integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ=", + "engines": { + "iojs": ">= 1.0.0", + "node": ">= 0.12.0" + } + }, + "node_modules/co-body": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/co-body/-/co-body-5.2.0.tgz", + "integrity": "sha512-sX/LQ7LqUhgyaxzbe7IqwPeTr2yfpfUIQ/dgpKo6ZI4y4lpQA0YxAomWIY+7I7rHWcG02PG+OuPREzMW/5tszQ==", + "dependencies": { + "inflation": "^2.0.0", + "qs": "^6.4.0", + "raw-body": "^2.2.0", + "type-is": "^1.6.14" + } + }, + "node_modules/constantinople": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/constantinople/-/constantinople-4.0.1.tgz", + "integrity": "sha512-vCrqcSIq4//Gx74TXXCGnHpulY1dskqLTFGDmhrGxzeXL8lF8kvXv6mpNWlJj1uD4DW23D4ljAqbY4RRaaUZIw==", + "dependencies": { + "@babel/parser": "^7.6.0", + "@babel/types": "^7.6.1" + } + }, + "node_modules/content-disposition": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.3.tgz", + "integrity": "sha512-ExO0774ikEObIAEV9kDo50o+79VCUdEB6n6lzKgGwupcVeRlhrj3qGAfwq8G6uBJjkqLrhT0qEYFcWng8z1z0g==", + "dependencies": { + "safe-buffer": "5.1.2" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/content-type": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz", + "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/cookies": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/cookies/-/cookies-0.8.0.tgz", + "integrity": "sha512-8aPsApQfebXnuI+537McwYsDtjVxGm8gTIzQI3FDW6t5t/DAhERxtnbEPN/8RX+uZthoz4eCOgloXaE5cYyNow==", + "dependencies": { + "depd": "~2.0.0", + "keygrip": "~1.1.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/core-util-is": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" + }, + "node_modules/debug": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/deep-equal": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-1.0.1.tgz", + "integrity": "sha1-9dJgKStmDghO/0zbyfCK0yR0SLU=" + }, + "node_modules/delegates": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", + "integrity": "sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o=" + }, + "node_modules/depd": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", + "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/destroy": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz", + "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=" + }, + "node_modules/doctypes": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/doctypes/-/doctypes-1.1.0.tgz", + "integrity": "sha1-6oCxBqh1OHdOijpKWv4pPeSJ4Kk=" + }, + "node_modules/ee-first": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", + "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=" + }, + "node_modules/encodeurl": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", + "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/escape-html": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", + "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=" + }, + "node_modules/formidable": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/formidable/-/formidable-1.2.2.tgz", + "integrity": "sha512-V8gLm+41I/8kguQ4/o1D3RIHRmhYFG4pnNyonvua+40rqcEmT4+V71yaZ3B457xbbgCsCfjSPi65u/W6vK1U5Q==", + "funding": { + "url": "https://ko-fi.com/tunnckoCore/commissions" + } + }, + "node_modules/fresh": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", + "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/fs-extra": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz", + "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==", + "dependencies": { + "at-least-node": "^1.0.0", + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/function-bind": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" + }, + "node_modules/get-intrinsic": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.1.tgz", + "integrity": "sha512-kWZrnVM42QCiEA2Ig1bG8zjoIMOgxWwYCEeNdwY6Tv/cOSeGpcoX4pXHfKUxNKVoArnrEr2e9srnAxxGIraS9Q==", + "dependencies": { + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-symbols": "^1.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/graceful-fs": { + "version": "4.2.6", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.6.tgz", + "integrity": "sha512-nTnJ528pbqxYanhpDYsi4Rd8MAeaBA67+RZ10CM1m3bTAVFEDcd5AuA4a6W5YkGZ1iNXHzZz8T6TBKLeBuNriQ==" + }, + "node_modules/has": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", + "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", + "dependencies": { + "function-bind": "^1.1.1" + }, + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/has-symbols": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.2.tgz", + "integrity": "sha512-chXa79rL/UC2KlX17jo3vRGz0azaWEx5tGqZg5pO3NUyEJVB17dMruQlzCCOfUvElghKcm5194+BCRvi2Rv/Gw==", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/http-assert": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/http-assert/-/http-assert-1.4.1.tgz", + "integrity": "sha512-rdw7q6GTlibqVVbXr0CKelfV5iY8G2HqEUkhSk297BMbSpSL8crXC+9rjKoMcZZEsksX30le6f/4ul4E28gegw==", + "dependencies": { + "deep-equal": "~1.0.1", + "http-errors": "~1.7.2" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/http-assert/node_modules/depd": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", + "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/http-assert/node_modules/http-errors": { + "version": "1.7.3", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.7.3.tgz", + "integrity": "sha512-ZTTX0MWrsQ2ZAhA1cejAwDLycFsd7I7nVtnkT3Ol0aqodaKW+0CTZDQ1uBv5whptCnc8e8HeRRJxRs0kmm/Qfw==", + "dependencies": { + "depd": "~1.1.2", + "inherits": "2.0.4", + "setprototypeof": "1.1.1", + "statuses": ">= 1.5.0 < 2", + "toidentifier": "1.0.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/http-assert/node_modules/setprototypeof": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.1.tgz", + "integrity": "sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw==" + }, + "node_modules/http-errors": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.8.0.tgz", + "integrity": "sha512-4I8r0C5JDhT5VkvI47QktDW75rNlGVsUf/8hzjCC/wkWI/jdTRmBb9aI7erSG82r1bjKY3F6k28WnsVxB1C73A==", + "dependencies": { + "depd": "~1.1.2", + "inherits": "2.0.4", + "setprototypeof": "1.2.0", + "statuses": ">= 1.5.0 < 2", + "toidentifier": "1.0.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/http-errors/node_modules/depd": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", + "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/inflation": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/inflation/-/inflation-2.0.0.tgz", + "integrity": "sha1-i0F+R8KPklpFEz2RTKH9OJEH8w8=", + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + }, + "node_modules/is-core-module": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.4.0.tgz", + "integrity": "sha512-6A2fkfq1rfeQZjxrZJGerpLCTHRNEBiSgnu0+obeJpEPZRUooHgsizvzv0ZjJwOz3iWIHdJtVWJ/tmPr3D21/A==", + "dependencies": { + "has": "^1.0.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-expression": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/is-expression/-/is-expression-4.0.0.tgz", + "integrity": "sha512-zMIXX63sxzG3XrkHkrAPvm/OVZVSCPNkwMHU8oTX7/U3AL78I0QXCEICXUM13BIa8TYGZ68PiTKfQz3yaTNr4A==", + "dependencies": { + "acorn": "^7.1.1", + "object-assign": "^4.1.1" + } + }, + "node_modules/is-generator-function": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.0.9.tgz", + "integrity": "sha512-ZJ34p1uvIfptHCN7sFTjGibB9/oBg17sHqzDLfuwhvmN/qLVvIQXRQ8licZQ35WJ8KuEQt/etnnzQFI9C9Ue/A==", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-promise": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-2.2.2.tgz", + "integrity": "sha512-+lP4/6lKUBfQjZ2pdxThZvLUAafmZb8OAxFb8XXtiQmS35INgr85hdOGoEs124ez1FCnZJt6jau/T+alh58QFQ==" + }, + "node_modules/is-regex": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.3.tgz", + "integrity": "sha512-qSVXFz28HM7y+IWX6vLCsexdlvzT1PJNFSBuaQLQ5o0IEw8UDYW6/2+eCMVyIsbM8CNLX2a/QWmSpyxYEHY7CQ==", + "dependencies": { + "call-bind": "^1.0.2", + "has-symbols": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" + }, + "node_modules/js-stringify": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/js-stringify/-/js-stringify-1.0.2.tgz", + "integrity": "sha1-Fzb939lyTyijaCrcYjCufk6Weds=" + }, + "node_modules/jsonfile": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", + "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", + "dependencies": { + "universalify": "^2.0.0" + }, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/jstransformer": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/jstransformer/-/jstransformer-1.0.0.tgz", + "integrity": "sha1-7Yvwkh4vPx7U1cGkT2hwntJHIsM=", + "dependencies": { + "is-promise": "^2.0.0", + "promise": "^7.0.1" + } + }, + "node_modules/keygrip": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/keygrip/-/keygrip-1.1.0.tgz", + "integrity": "sha512-iYSchDJ+liQ8iwbSI2QqsQOvqv58eJCEanyJPJi+Khyu8smkcKSFUCbPwzFcL7YVtZ6eONjqRX/38caJ7QjRAQ==", + "dependencies": { + "tsscmp": "1.0.6" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/koa": { + "version": "2.13.1", + "resolved": "https://registry.npmjs.org/koa/-/koa-2.13.1.tgz", + "integrity": "sha512-Lb2Dloc72auj5vK4X4qqL7B5jyDPQaZucc9sR/71byg7ryoD1NCaCm63CShk9ID9quQvDEi1bGR/iGjCG7As3w==", + "dependencies": { + "accepts": "^1.3.5", + "cache-content-type": "^1.0.0", + "content-disposition": "~0.5.2", + "content-type": "^1.0.4", + "cookies": "~0.8.0", + "debug": "~3.1.0", + "delegates": "^1.0.0", + "depd": "^2.0.0", + "destroy": "^1.0.4", + "encodeurl": "^1.0.2", + "escape-html": "^1.0.3", + "fresh": "~0.5.2", + "http-assert": "^1.3.0", + "http-errors": "^1.6.3", + "is-generator-function": "^1.0.7", + "koa-compose": "^4.1.0", + "koa-convert": "^1.2.0", + "on-finished": "^2.3.0", + "only": "~0.0.2", + "parseurl": "^1.3.2", + "statuses": "^1.5.0", + "type-is": "^1.6.16", + "vary": "^1.1.2" + }, + "engines": { + "node": "^4.8.4 || ^6.10.1 || ^7.10.1 || >= 8.1.4" + } + }, + "node_modules/koa-body": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/koa-body/-/koa-body-4.2.0.tgz", + "integrity": "sha512-wdGu7b9amk4Fnk/ytH8GuWwfs4fsB5iNkY8kZPpgQVb04QZSv85T0M8reb+cJmvLE8cjPYvBzRikD3s6qz8OoA==", + "dependencies": { + "@types/formidable": "^1.0.31", + "co-body": "^5.1.1", + "formidable": "^1.1.1" + } + }, + "node_modules/koa-compose": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/koa-compose/-/koa-compose-4.1.0.tgz", + "integrity": "sha512-8ODW8TrDuMYvXRwra/Kh7/rJo9BtOfPc6qO8eAfC80CnCvSjSl0bkRM24X6/XBBEyj0v1nRUQ1LyOy3dbqOWXw==" + }, + "node_modules/koa-convert": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/koa-convert/-/koa-convert-1.2.0.tgz", + "integrity": "sha1-2kCHXfSd4FOQmNFwC1CCDOvNIdA=", + "dependencies": { + "co": "^4.6.0", + "koa-compose": "^3.0.0" + }, + "engines": { + "node": ">= 4" + } + }, + "node_modules/koa-convert/node_modules/koa-compose": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/koa-compose/-/koa-compose-3.2.1.tgz", + "integrity": "sha1-qFzLQLfZhtjlo0Wzoazo6rz1Tec=", + "dependencies": { + "any-promise": "^1.1.0" + } + }, + "node_modules/koa-pug": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/koa-pug/-/koa-pug-5.0.0.tgz", + "integrity": "sha512-ahBlssndp76ijVqrPurD5BCHEAYcRZc9G1OEZJDRE7ZUQouVDTuzIc/ovVTSafdxDHMsVS7AemmzUAoEAwAVDQ==", + "dependencies": { + "fs-extra": "^9.1.0", + "lodash.camelcase": "^4.3.0", + "lodash.forin": "^4.4.0", + "lodash.isobject": "^3.0.2", + "lodash.isplainobject": "^4.0.6", + "lodash.merge": "^4.6.2", + "pug": "^3.0.2" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/koa-range": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/koa-range/-/koa-range-0.3.0.tgz", + "integrity": "sha1-NYjjSWRzqDmhvSZNKkKx2FvX/qw=", + "dependencies": { + "stream-slice": "^0.1.2" + }, + "engines": { + "node": ">=7" + } + }, + "node_modules/koa-router": { + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/koa-router/-/koa-router-10.0.0.tgz", + "integrity": "sha512-gAE5J1gBQTvfR8rMMtMUkE26+1MbO3DGpGmvfmM2pR9Z7w2VIb2Ecqeal98yVO7+4ltffby7gWOzpCmdNOQe0w==", + "dependencies": { + "debug": "^4.1.1", + "http-errors": "^1.7.3", + "koa-compose": "^4.1.0", + "methods": "^1.1.2", + "path-to-regexp": "^6.1.0" + }, + "engines": { + "node": ">= 8.0.0" + } + }, + "node_modules/koa-router/node_modules/debug": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz", + "integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==", + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/koa-router/node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + }, + "node_modules/koa-send": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/koa-send/-/koa-send-5.0.1.tgz", + "integrity": "sha512-tmcyQ/wXXuxpDxyNXv5yNNkdAMdFRqwtegBXUaowiQzUKqJehttS0x2j0eOZDQAyloAth5w6wwBImnFzkUz3pQ==", + "dependencies": { + "debug": "^4.1.1", + "http-errors": "^1.7.3", + "resolve-path": "^1.4.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/koa-send/node_modules/debug": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz", + "integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==", + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/koa-send/node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + }, + "node_modules/koa-static": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/koa-static/-/koa-static-5.0.0.tgz", + "integrity": "sha512-UqyYyH5YEXaJrf9S8E23GoJFQZXkBVJ9zYYMPGz919MSX1KuvAcycIuS0ci150HCoPf4XQVhQ84Qf8xRPWxFaQ==", + "dependencies": { + "debug": "^3.1.0", + "koa-send": "^5.0.0" + }, + "engines": { + "node": ">= 7.6.0" + } + }, + "node_modules/lodash.camelcase": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz", + "integrity": "sha1-soqmKIorn8ZRA1x3EfZathkDMaY=" + }, + "node_modules/lodash.forin": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/lodash.forin/-/lodash.forin-4.4.0.tgz", + "integrity": "sha1-XT8grlZAEfvog4H32YlJyclRlzE=" + }, + "node_modules/lodash.isobject": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/lodash.isobject/-/lodash.isobject-3.0.2.tgz", + "integrity": "sha1-PI+41bW/S/kK4G4U8qUwpO2TXh0=" + }, + "node_modules/lodash.isplainobject": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz", + "integrity": "sha1-fFJqUtibRcRcxpC4gWO+BJf1UMs=" + }, + "node_modules/lodash.merge": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", + "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==" + }, + "node_modules/media-typer": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", + "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/methods": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", + "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-db": { + "version": "1.48.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.48.0.tgz", + "integrity": "sha512-FM3QwxV+TnZYQ2aRqhlKBMHxk10lTbMt3bBkMAp54ddrNeVSfcQYOOKuGuy3Ddrm38I04If834fOUSq1yzslJQ==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "2.1.31", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.31.tgz", + "integrity": "sha512-XGZnNzm3QvgKxa8dpzyhFTHmpP3l5YNusmne07VUOXxou9CqUqYa/HBy124RqtVh/O2pECas/MOcsDgpilPOPg==", + "dependencies": { + "mime-db": "1.48.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/moment": { + "version": "2.29.1", + "resolved": "https://registry.npmjs.org/moment/-/moment-2.29.1.tgz", + "integrity": "sha512-kHmoybcPV8Sqy59DwNDY3Jefr64lK/by/da0ViFcuA4DH0vQg5Q6Ze5VimxkfQNSC+Mls/Kx53s7TjP1RhFEDQ==", + "engines": { + "node": "*" + } + }, + "node_modules/moment-timezone": { + "version": "0.5.33", + "resolved": "https://registry.npmjs.org/moment-timezone/-/moment-timezone-0.5.33.tgz", + "integrity": "sha512-PTc2vcT8K9J5/9rDEPe5czSIKgLoGsH8UNpA4qZTVw0Vd/Uz19geE9abbIOQKaAQFcnQ3v5YEXrbSc5BpshH+w==", + "dependencies": { + "moment": ">= 2.9.0" + }, + "engines": { + "node": "*" + } + }, + "node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" + }, + "node_modules/mysql": { + "version": "2.18.1", + "resolved": "https://registry.npmjs.org/mysql/-/mysql-2.18.1.tgz", + "integrity": "sha512-Bca+gk2YWmqp2Uf6k5NFEurwY/0td0cpebAucFpY/3jhrwrVGuxU2uQFCHjU19SJfje0yQvi+rVWdq78hR5lig==", + "dependencies": { + "bignumber.js": "9.0.0", + "readable-stream": "2.3.7", + "safe-buffer": "5.1.2", + "sqlstring": "2.3.1" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/negotiator": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.2.tgz", + "integrity": "sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/node-fetch": { + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.1.tgz", + "integrity": "sha512-V4aYg89jEoVRxRb2fJdAg8FHvI7cEyYdVAh94HH0UIK8oJxUfkjlDQN9RbMx+bEjP7+ggMiFRprSti032Oipxw==", + "engines": { + "node": "4.x || >=6.0.0" + } + }, + "node_modules/object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-inspect": { + "version": "1.10.3", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.10.3.tgz", + "integrity": "sha512-e5mCJlSH7poANfC8z8S9s9S2IN5/4Zb3aZ33f5s8YqoazCFzNLloLU8r5VCG+G7WoqLvAAZoVMcy3tp/3X0Plw==", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/on-finished": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", + "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=", + "dependencies": { + "ee-first": "1.1.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/only": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/only/-/only-0.0.2.tgz", + "integrity": "sha1-Kv3oTQPlC5qO3EROMGEKcCle37Q=" + }, + "node_modules/parseurl": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", + "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/path-parse": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==" + }, + "node_modules/path-to-regexp": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-6.2.0.tgz", + "integrity": "sha512-f66KywYG6+43afgE/8j/GoiNyygk/bnoCbps++3ErRKsIYkGGupyv07R2Ok5m9i67Iqc+T2g1eAUGUPzWhYTyg==" + }, + "node_modules/process-nextick-args": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==" + }, + "node_modules/promise": { + "version": "7.3.1", + "resolved": "https://registry.npmjs.org/promise/-/promise-7.3.1.tgz", + "integrity": "sha512-nolQXZ/4L+bP/UGlkfaIujX9BKxGwmQ9OT4mOt5yvy8iK1h3wqTEJCijzGANTCCl9nWjY41juyAn2K3Q1hLLTg==", + "dependencies": { + "asap": "~2.0.3" + } + }, + "node_modules/pug": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/pug/-/pug-3.0.2.tgz", + "integrity": "sha512-bp0I/hiK1D1vChHh6EfDxtndHji55XP/ZJKwsRqrz6lRia6ZC2OZbdAymlxdVFwd1L70ebrVJw4/eZ79skrIaw==", + "dependencies": { + "pug-code-gen": "^3.0.2", + "pug-filters": "^4.0.0", + "pug-lexer": "^5.0.1", + "pug-linker": "^4.0.0", + "pug-load": "^3.0.0", + "pug-parser": "^6.0.0", + "pug-runtime": "^3.0.1", + "pug-strip-comments": "^2.0.0" + } + }, + "node_modules/pug-attrs": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pug-attrs/-/pug-attrs-3.0.0.tgz", + "integrity": "sha512-azINV9dUtzPMFQktvTXciNAfAuVh/L/JCl0vtPCwvOA21uZrC08K/UnmrL+SXGEVc1FwzjW62+xw5S/uaLj6cA==", + "dependencies": { + "constantinople": "^4.0.1", + "js-stringify": "^1.0.2", + "pug-runtime": "^3.0.0" + } + }, + "node_modules/pug-code-gen": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/pug-code-gen/-/pug-code-gen-3.0.2.tgz", + "integrity": "sha512-nJMhW16MbiGRiyR4miDTQMRWDgKplnHyeLvioEJYbk1RsPI3FuA3saEP8uwnTb2nTJEKBU90NFVWJBk4OU5qyg==", + "dependencies": { + "constantinople": "^4.0.1", + "doctypes": "^1.1.0", + "js-stringify": "^1.0.2", + "pug-attrs": "^3.0.0", + "pug-error": "^2.0.0", + "pug-runtime": "^3.0.0", + "void-elements": "^3.1.0", + "with": "^7.0.0" + } + }, + "node_modules/pug-error": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/pug-error/-/pug-error-2.0.0.tgz", + "integrity": "sha512-sjiUsi9M4RAGHktC1drQfCr5C5eriu24Lfbt4s+7SykztEOwVZtbFk1RRq0tzLxcMxMYTBR+zMQaG07J/btayQ==" + }, + "node_modules/pug-filters": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/pug-filters/-/pug-filters-4.0.0.tgz", + "integrity": "sha512-yeNFtq5Yxmfz0f9z2rMXGw/8/4i1cCFecw/Q7+D0V2DdtII5UvqE12VaZ2AY7ri6o5RNXiweGH79OCq+2RQU4A==", + "dependencies": { + "constantinople": "^4.0.1", + "jstransformer": "1.0.0", + "pug-error": "^2.0.0", + "pug-walk": "^2.0.0", + "resolve": "^1.15.1" + } + }, + "node_modules/pug-lexer": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/pug-lexer/-/pug-lexer-5.0.1.tgz", + "integrity": "sha512-0I6C62+keXlZPZkOJeVam9aBLVP2EnbeDw3An+k0/QlqdwH6rv8284nko14Na7c0TtqtogfWXcRoFE4O4Ff20w==", + "dependencies": { + "character-parser": "^2.2.0", + "is-expression": "^4.0.0", + "pug-error": "^2.0.0" + } + }, + "node_modules/pug-linker": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/pug-linker/-/pug-linker-4.0.0.tgz", + "integrity": "sha512-gjD1yzp0yxbQqnzBAdlhbgoJL5qIFJw78juN1NpTLt/mfPJ5VgC4BvkoD3G23qKzJtIIXBbcCt6FioLSFLOHdw==", + "dependencies": { + "pug-error": "^2.0.0", + "pug-walk": "^2.0.0" + } + }, + "node_modules/pug-load": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pug-load/-/pug-load-3.0.0.tgz", + "integrity": "sha512-OCjTEnhLWZBvS4zni/WUMjH2YSUosnsmjGBB1An7CsKQarYSWQ0GCVyd4eQPMFJqZ8w9xgs01QdiZXKVjk92EQ==", + "dependencies": { + "object-assign": "^4.1.1", + "pug-walk": "^2.0.0" + } + }, + "node_modules/pug-parser": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/pug-parser/-/pug-parser-6.0.0.tgz", + "integrity": "sha512-ukiYM/9cH6Cml+AOl5kETtM9NR3WulyVP2y4HOU45DyMim1IeP/OOiyEWRr6qk5I5klpsBnbuHpwKmTx6WURnw==", + "dependencies": { + "pug-error": "^2.0.0", + "token-stream": "1.0.0" + } + }, + "node_modules/pug-runtime": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/pug-runtime/-/pug-runtime-3.0.1.tgz", + "integrity": "sha512-L50zbvrQ35TkpHwv0G6aLSuueDRwc/97XdY8kL3tOT0FmhgG7UypU3VztfV/LATAvmUfYi4wNxSajhSAeNN+Kg==" + }, + "node_modules/pug-strip-comments": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/pug-strip-comments/-/pug-strip-comments-2.0.0.tgz", + "integrity": "sha512-zo8DsDpH7eTkPHCXFeAk1xZXJbyoTfdPlNR0bK7rpOMuhBYb0f5qUVCO1xlsitYd3w5FQTK7zpNVKb3rZoUrrQ==", + "dependencies": { + "pug-error": "^2.0.0" + } + }, + "node_modules/pug-walk": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/pug-walk/-/pug-walk-2.0.0.tgz", + "integrity": "sha512-yYELe9Q5q9IQhuvqsZNwA5hfPkMJ8u92bQLIMcsMxf/VADjNtEYptU+inlufAFYcWdHlwNfZOEnOOQrZrcyJCQ==" + }, + "node_modules/qs": { + "version": "6.10.1", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.10.1.tgz", + "integrity": "sha512-M528Hph6wsSVOBiYUnGf+K/7w0hNshs/duGsNXPUCLH5XAqjEtiPGwNONLV0tBH8NoGb0mvD5JubnUTrujKDTg==", + "dependencies": { + "side-channel": "^1.0.4" + }, + "engines": { + "node": ">=0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/raw-body": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.4.1.tgz", + "integrity": "sha512-9WmIKF6mkvA0SLmA2Knm9+qj89e+j1zqgyn8aXGd7+nAduPoqgI9lO57SAZNn/Byzo5P7JhXTyg9PzaJbH73bA==", + "dependencies": { + "bytes": "3.1.0", + "http-errors": "1.7.3", + "iconv-lite": "0.4.24", + "unpipe": "1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/raw-body/node_modules/depd": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", + "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/raw-body/node_modules/http-errors": { + "version": "1.7.3", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.7.3.tgz", + "integrity": "sha512-ZTTX0MWrsQ2ZAhA1cejAwDLycFsd7I7nVtnkT3Ol0aqodaKW+0CTZDQ1uBv5whptCnc8e8HeRRJxRs0kmm/Qfw==", + "dependencies": { + "depd": "~1.1.2", + "inherits": "2.0.4", + "setprototypeof": "1.1.1", + "statuses": ">= 1.5.0 < 2", + "toidentifier": "1.0.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/raw-body/node_modules/setprototypeof": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.1.tgz", + "integrity": "sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw==" + }, + "node_modules/readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/resolve": { + "version": "1.20.0", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.20.0.tgz", + "integrity": "sha512-wENBPt4ySzg4ybFQW2TT1zMQucPK95HSh/nq2CFTZVOGut2+pQvSsgtda4d26YrYcr067wjbmzOG8byDPBX63A==", + "dependencies": { + "is-core-module": "^2.2.0", + "path-parse": "^1.0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/resolve-path": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/resolve-path/-/resolve-path-1.4.0.tgz", + "integrity": "sha1-xL2p9e+y/OZSR4c6s2u02DT+Fvc=", + "dependencies": { + "http-errors": "~1.6.2", + "path-is-absolute": "1.0.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/resolve-path/node_modules/depd": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", + "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/resolve-path/node_modules/http-errors": { + "version": "1.6.3", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.3.tgz", + "integrity": "sha1-i1VoC7S+KDoLW/TqLjhYC+HZMg0=", + "dependencies": { + "depd": "~1.1.2", + "inherits": "2.0.3", + "setprototypeof": "1.1.0", + "statuses": ">= 1.4.0 < 2" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/resolve-path/node_modules/inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" + }, + "node_modules/resolve-path/node_modules/setprototypeof": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.0.tgz", + "integrity": "sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ==" + }, + "node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + }, + "node_modules/safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" + }, + "node_modules/setprototypeof": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", + "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==" + }, + "node_modules/side-channel": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", + "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==", + "dependencies": { + "call-bind": "^1.0.0", + "get-intrinsic": "^1.0.2", + "object-inspect": "^1.9.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/sqlstring": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/sqlstring/-/sqlstring-2.3.1.tgz", + "integrity": "sha1-R1OT/56RR5rqYtyvDKPRSYOn+0A=", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/statuses": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", + "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/stream-slice": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/stream-slice/-/stream-slice-0.1.2.tgz", + "integrity": "sha1-LcT04bk2+xPz6zmi3vGTJ5jQeks=" + }, + "node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, + "node_modules/to-fast-properties": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", + "integrity": "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=", + "engines": { + "node": ">=4" + } + }, + "node_modules/toidentifier": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.0.tgz", + "integrity": "sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw==", + "engines": { + "node": ">=0.6" + } + }, + "node_modules/token-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/token-stream/-/token-stream-1.0.0.tgz", + "integrity": "sha1-zCAOqyYT9BZtJ/+a/HylbUnfbrQ=" + }, + "node_modules/tsscmp": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/tsscmp/-/tsscmp-1.0.6.tgz", + "integrity": "sha512-LxhtAkPDTkVCMQjt2h6eBVY28KCjikZqZfMcC15YBeNjkgUpdCfBu5HoiOTDu86v6smE8yOjyEktJ8hlbANHQA==", + "engines": { + "node": ">=0.6.x" + } + }, + "node_modules/type-is": { + "version": "1.6.18", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", + "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", + "dependencies": { + "media-typer": "0.3.0", + "mime-types": "~2.1.24" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/universalify": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", + "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==", + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/unpipe": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", + "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" + }, + "node_modules/vary": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", + "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/void-elements": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/void-elements/-/void-elements-3.1.0.tgz", + "integrity": "sha1-YU9/v42AHwu18GYfWy9XhXUOTwk=", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/with": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/with/-/with-7.0.2.tgz", + "integrity": "sha512-RNGKj82nUPg3g5ygxkQl0R937xLyho1J24ItRCBTr/m1YnZkzJy1hUiHUJrc/VlsDQzsCnInEGSg3bci0Lmd4w==", + "dependencies": { + "@babel/parser": "^7.9.6", + "@babel/types": "^7.9.6", + "assert-never": "^1.2.1", + "babel-walk": "3.0.0-canary-5" + }, + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/ylru": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/ylru/-/ylru-1.2.1.tgz", + "integrity": "sha512-faQrqNMzcPCHGVC2aaOINk13K+aaBDUPjGWl0teOXywElLjyVAB6Oe2jj62jHYtwsU49jXhScYbvPENK+6zAvQ==", + "engines": { + "node": ">= 4.0.0" + } + } + }, + "dependencies": { + "@babel/helper-validator-identifier": { + "version": "7.14.0", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.14.0.tgz", + "integrity": "sha512-V3ts7zMSu5lfiwWDVWzRDGIN+lnCEUdaXgtVHJgLb1rGaA6jMrtB9EmE7L18foXJIE8Un/A/h6NJfGQp/e1J4A==" + }, + "@babel/parser": { + "version": "7.14.4", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.14.4.tgz", + "integrity": "sha512-ArliyUsWDUqEGfWcmzpGUzNfLxTdTp6WU4IuP6QFSp9gGfWS6boxFCkJSJ/L4+RG8z/FnIU3WxCk6hPL9SSWeA==" + }, + "@babel/types": { + "version": "7.14.4", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.14.4.tgz", + "integrity": "sha512-lCj4aIs0xUefJFQnwwQv2Bxg7Omd6bgquZ6LGC+gGMh6/s5qDVfjuCMlDmYQ15SLsWHd9n+X3E75lKIhl5Lkiw==", + "requires": { + "@babel/helper-validator-identifier": "^7.14.0", + "to-fast-properties": "^2.0.0" + } + }, + "@types/formidable": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/@types/formidable/-/formidable-1.2.2.tgz", + "integrity": "sha512-8RDAMnMHOh7QrY1xuQ7s6/Xre9pMvJ2zT2VgATiz5cIE71Q/6N3+P8sr3z/dNWNmvX5/aX9x8uJlG0MZiMZXoA==", + "requires": { + "@types/node": "*" + } + }, + "@types/node": { + "version": "15.12.1", + "resolved": "https://registry.npmjs.org/@types/node/-/node-15.12.1.tgz", + "integrity": "sha512-zyxJM8I1c9q5sRMtVF+zdd13Jt6RU4r4qfhTd7lQubyThvLfx6yYekWSQjGCGV2Tkecgxnlpl/DNlb6Hg+dmEw==" + }, + "accepts": { + "version": "1.3.7", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.7.tgz", + "integrity": "sha512-Il80Qs2WjYlJIBNzNkK6KYqlVMTbZLXgHx2oT0pU/fjRHyEp+PEfEPY0R3WCwAGVOtauxh1hOxNgIf5bv7dQpA==", + "requires": { + "mime-types": "~2.1.24", + "negotiator": "0.6.2" + } + }, + "acorn": { + "version": "7.4.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz", + "integrity": "sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==" + }, + "any-promise": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz", + "integrity": "sha1-q8av7tzqUugJzcA3au0845Y10X8=" + }, + "asap": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz", + "integrity": "sha1-5QNHYR1+aQlDIIu9r+vLwvuGbUY=" + }, + "assert-never": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/assert-never/-/assert-never-1.2.1.tgz", + "integrity": "sha512-TaTivMB6pYI1kXwrFlEhLeGfOqoDNdTxjCdwRfFFkEA30Eu+k48W34nlok2EYWJfFFzqaEmichdNM7th6M5HNw==" + }, + "at-least-node": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/at-least-node/-/at-least-node-1.0.0.tgz", + "integrity": "sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg==" + }, + "babel-walk": { + "version": "3.0.0-canary-5", + "resolved": "https://registry.npmjs.org/babel-walk/-/babel-walk-3.0.0-canary-5.tgz", + "integrity": "sha512-GAwkz0AihzY5bkwIY5QDR+LvsRQgB/B+1foMPvi0FZPMl5fjD7ICiznUiBdLYMH1QYe6vqu4gWYytZOccLouFw==", + "requires": { + "@babel/types": "^7.9.6" + } + }, + "bignumber.js": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-9.0.0.tgz", + "integrity": "sha512-t/OYhhJ2SD+YGBQcjY8GzzDHEk9f3nerxjtfa6tlMXfe7frs/WozhvCNoGvpM0P3bNf3Gq5ZRMlGr5f3r4/N8A==" + }, + "bytes": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.0.tgz", + "integrity": "sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg==" + }, + "cache-content-type": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/cache-content-type/-/cache-content-type-1.0.1.tgz", + "integrity": "sha512-IKufZ1o4Ut42YUrZSo8+qnMTrFuKkvyoLXUywKz9GJ5BrhOFGhLdkx9sG4KAnVvbY6kEcSFjLQul+DVmBm2bgA==", + "requires": { + "mime-types": "^2.1.18", + "ylru": "^1.2.0" + } + }, + "call-bind": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", + "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", + "requires": { + "function-bind": "^1.1.1", + "get-intrinsic": "^1.0.2" + } + }, + "character-parser": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/character-parser/-/character-parser-2.2.0.tgz", + "integrity": "sha1-x84o821LzZdE5f/CxfzeHHMmH8A=", + "requires": { + "is-regex": "^1.0.3" + } + }, + "co": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", + "integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ=" + }, + "co-body": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/co-body/-/co-body-5.2.0.tgz", + "integrity": "sha512-sX/LQ7LqUhgyaxzbe7IqwPeTr2yfpfUIQ/dgpKo6ZI4y4lpQA0YxAomWIY+7I7rHWcG02PG+OuPREzMW/5tszQ==", + "requires": { + "inflation": "^2.0.0", + "qs": "^6.4.0", + "raw-body": "^2.2.0", + "type-is": "^1.6.14" + } + }, + "constantinople": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/constantinople/-/constantinople-4.0.1.tgz", + "integrity": "sha512-vCrqcSIq4//Gx74TXXCGnHpulY1dskqLTFGDmhrGxzeXL8lF8kvXv6mpNWlJj1uD4DW23D4ljAqbY4RRaaUZIw==", + "requires": { + "@babel/parser": "^7.6.0", + "@babel/types": "^7.6.1" + } + }, + "content-disposition": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.3.tgz", + "integrity": "sha512-ExO0774ikEObIAEV9kDo50o+79VCUdEB6n6lzKgGwupcVeRlhrj3qGAfwq8G6uBJjkqLrhT0qEYFcWng8z1z0g==", + "requires": { + "safe-buffer": "5.1.2" + } + }, + "content-type": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz", + "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==" + }, + "cookies": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/cookies/-/cookies-0.8.0.tgz", + "integrity": "sha512-8aPsApQfebXnuI+537McwYsDtjVxGm8gTIzQI3FDW6t5t/DAhERxtnbEPN/8RX+uZthoz4eCOgloXaE5cYyNow==", + "requires": { + "depd": "~2.0.0", + "keygrip": "~1.1.0" + } + }, + "core-util-is": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" + }, + "debug": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "requires": { + "ms": "2.0.0" + } + }, + "deep-equal": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-1.0.1.tgz", + "integrity": "sha1-9dJgKStmDghO/0zbyfCK0yR0SLU=" + }, + "delegates": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", + "integrity": "sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o=" + }, + "depd": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", + "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==" + }, + "destroy": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz", + "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=" + }, + "doctypes": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/doctypes/-/doctypes-1.1.0.tgz", + "integrity": "sha1-6oCxBqh1OHdOijpKWv4pPeSJ4Kk=" + }, + "ee-first": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", + "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=" + }, + "encodeurl": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", + "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=" + }, + "escape-html": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", + "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=" + }, + "formidable": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/formidable/-/formidable-1.2.2.tgz", + "integrity": "sha512-V8gLm+41I/8kguQ4/o1D3RIHRmhYFG4pnNyonvua+40rqcEmT4+V71yaZ3B457xbbgCsCfjSPi65u/W6vK1U5Q==" + }, + "fresh": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", + "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=" + }, + "fs-extra": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz", + "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==", + "requires": { + "at-least-node": "^1.0.0", + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + } + }, + "function-bind": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" + }, + "get-intrinsic": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.1.tgz", + "integrity": "sha512-kWZrnVM42QCiEA2Ig1bG8zjoIMOgxWwYCEeNdwY6Tv/cOSeGpcoX4pXHfKUxNKVoArnrEr2e9srnAxxGIraS9Q==", + "requires": { + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-symbols": "^1.0.1" + } + }, + "graceful-fs": { + "version": "4.2.6", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.6.tgz", + "integrity": "sha512-nTnJ528pbqxYanhpDYsi4Rd8MAeaBA67+RZ10CM1m3bTAVFEDcd5AuA4a6W5YkGZ1iNXHzZz8T6TBKLeBuNriQ==" + }, + "has": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", + "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", + "requires": { + "function-bind": "^1.1.1" + } + }, + "has-symbols": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.2.tgz", + "integrity": "sha512-chXa79rL/UC2KlX17jo3vRGz0azaWEx5tGqZg5pO3NUyEJVB17dMruQlzCCOfUvElghKcm5194+BCRvi2Rv/Gw==" + }, + "http-assert": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/http-assert/-/http-assert-1.4.1.tgz", + "integrity": "sha512-rdw7q6GTlibqVVbXr0CKelfV5iY8G2HqEUkhSk297BMbSpSL8crXC+9rjKoMcZZEsksX30le6f/4ul4E28gegw==", + "requires": { + "deep-equal": "~1.0.1", + "http-errors": "~1.7.2" + }, + "dependencies": { + "depd": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", + "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=" + }, + "http-errors": { + "version": "1.7.3", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.7.3.tgz", + "integrity": "sha512-ZTTX0MWrsQ2ZAhA1cejAwDLycFsd7I7nVtnkT3Ol0aqodaKW+0CTZDQ1uBv5whptCnc8e8HeRRJxRs0kmm/Qfw==", + "requires": { + "depd": "~1.1.2", + "inherits": "2.0.4", + "setprototypeof": "1.1.1", + "statuses": ">= 1.5.0 < 2", + "toidentifier": "1.0.0" + } + }, + "setprototypeof": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.1.tgz", + "integrity": "sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw==" + } + } + }, + "http-errors": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.8.0.tgz", + "integrity": "sha512-4I8r0C5JDhT5VkvI47QktDW75rNlGVsUf/8hzjCC/wkWI/jdTRmBb9aI7erSG82r1bjKY3F6k28WnsVxB1C73A==", + "requires": { + "depd": "~1.1.2", + "inherits": "2.0.4", + "setprototypeof": "1.2.0", + "statuses": ">= 1.5.0 < 2", + "toidentifier": "1.0.0" + }, + "dependencies": { + "depd": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", + "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=" + } + } + }, + "iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "requires": { + "safer-buffer": ">= 2.1.2 < 3" + } + }, + "inflation": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/inflation/-/inflation-2.0.0.tgz", + "integrity": "sha1-i0F+R8KPklpFEz2RTKH9OJEH8w8=" + }, + "inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + }, + "is-core-module": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.4.0.tgz", + "integrity": "sha512-6A2fkfq1rfeQZjxrZJGerpLCTHRNEBiSgnu0+obeJpEPZRUooHgsizvzv0ZjJwOz3iWIHdJtVWJ/tmPr3D21/A==", + "requires": { + "has": "^1.0.3" + } + }, + "is-expression": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/is-expression/-/is-expression-4.0.0.tgz", + "integrity": "sha512-zMIXX63sxzG3XrkHkrAPvm/OVZVSCPNkwMHU8oTX7/U3AL78I0QXCEICXUM13BIa8TYGZ68PiTKfQz3yaTNr4A==", + "requires": { + "acorn": "^7.1.1", + "object-assign": "^4.1.1" + } + }, + "is-generator-function": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.0.9.tgz", + "integrity": "sha512-ZJ34p1uvIfptHCN7sFTjGibB9/oBg17sHqzDLfuwhvmN/qLVvIQXRQ8licZQ35WJ8KuEQt/etnnzQFI9C9Ue/A==" + }, + "is-promise": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-2.2.2.tgz", + "integrity": "sha512-+lP4/6lKUBfQjZ2pdxThZvLUAafmZb8OAxFb8XXtiQmS35INgr85hdOGoEs124ez1FCnZJt6jau/T+alh58QFQ==" + }, + "is-regex": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.3.tgz", + "integrity": "sha512-qSVXFz28HM7y+IWX6vLCsexdlvzT1PJNFSBuaQLQ5o0IEw8UDYW6/2+eCMVyIsbM8CNLX2a/QWmSpyxYEHY7CQ==", + "requires": { + "call-bind": "^1.0.2", + "has-symbols": "^1.0.2" + } + }, + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" + }, + "js-stringify": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/js-stringify/-/js-stringify-1.0.2.tgz", + "integrity": "sha1-Fzb939lyTyijaCrcYjCufk6Weds=" + }, + "jsonfile": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", + "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", + "requires": { + "graceful-fs": "^4.1.6", + "universalify": "^2.0.0" + } + }, + "jstransformer": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/jstransformer/-/jstransformer-1.0.0.tgz", + "integrity": "sha1-7Yvwkh4vPx7U1cGkT2hwntJHIsM=", + "requires": { + "is-promise": "^2.0.0", + "promise": "^7.0.1" + } + }, + "keygrip": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/keygrip/-/keygrip-1.1.0.tgz", + "integrity": "sha512-iYSchDJ+liQ8iwbSI2QqsQOvqv58eJCEanyJPJi+Khyu8smkcKSFUCbPwzFcL7YVtZ6eONjqRX/38caJ7QjRAQ==", + "requires": { + "tsscmp": "1.0.6" + } + }, + "koa": { + "version": "2.13.1", + "resolved": "https://registry.npmjs.org/koa/-/koa-2.13.1.tgz", + "integrity": "sha512-Lb2Dloc72auj5vK4X4qqL7B5jyDPQaZucc9sR/71byg7ryoD1NCaCm63CShk9ID9quQvDEi1bGR/iGjCG7As3w==", + "requires": { + "accepts": "^1.3.5", + "cache-content-type": "^1.0.0", + "content-disposition": "~0.5.2", + "content-type": "^1.0.4", + "cookies": "~0.8.0", + "debug": "~3.1.0", + "delegates": "^1.0.0", + "depd": "^2.0.0", + "destroy": "^1.0.4", + "encodeurl": "^1.0.2", + "escape-html": "^1.0.3", + "fresh": "~0.5.2", + "http-assert": "^1.3.0", + "http-errors": "^1.6.3", + "is-generator-function": "^1.0.7", + "koa-compose": "^4.1.0", + "koa-convert": "^1.2.0", + "on-finished": "^2.3.0", + "only": "~0.0.2", + "parseurl": "^1.3.2", + "statuses": "^1.5.0", + "type-is": "^1.6.16", + "vary": "^1.1.2" + } + }, + "koa-body": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/koa-body/-/koa-body-4.2.0.tgz", + "integrity": "sha512-wdGu7b9amk4Fnk/ytH8GuWwfs4fsB5iNkY8kZPpgQVb04QZSv85T0M8reb+cJmvLE8cjPYvBzRikD3s6qz8OoA==", + "requires": { + "@types/formidable": "^1.0.31", + "co-body": "^5.1.1", + "formidable": "^1.1.1" + } + }, + "koa-compose": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/koa-compose/-/koa-compose-4.1.0.tgz", + "integrity": "sha512-8ODW8TrDuMYvXRwra/Kh7/rJo9BtOfPc6qO8eAfC80CnCvSjSl0bkRM24X6/XBBEyj0v1nRUQ1LyOy3dbqOWXw==" + }, + "koa-convert": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/koa-convert/-/koa-convert-1.2.0.tgz", + "integrity": "sha1-2kCHXfSd4FOQmNFwC1CCDOvNIdA=", + "requires": { + "co": "^4.6.0", + "koa-compose": "^3.0.0" + }, + "dependencies": { + "koa-compose": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/koa-compose/-/koa-compose-3.2.1.tgz", + "integrity": "sha1-qFzLQLfZhtjlo0Wzoazo6rz1Tec=", + "requires": { + "any-promise": "^1.1.0" + } + } + } + }, + "koa-pug": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/koa-pug/-/koa-pug-5.0.0.tgz", + "integrity": "sha512-ahBlssndp76ijVqrPurD5BCHEAYcRZc9G1OEZJDRE7ZUQouVDTuzIc/ovVTSafdxDHMsVS7AemmzUAoEAwAVDQ==", + "requires": { + "fs-extra": "^9.1.0", + "lodash.camelcase": "^4.3.0", + "lodash.forin": "^4.4.0", + "lodash.isobject": "^3.0.2", + "lodash.isplainobject": "^4.0.6", + "lodash.merge": "^4.6.2", + "pug": "^3.0.2" + } + }, + "koa-range": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/koa-range/-/koa-range-0.3.0.tgz", + "integrity": "sha1-NYjjSWRzqDmhvSZNKkKx2FvX/qw=", + "requires": { + "stream-slice": "^0.1.2" + } + }, + "koa-router": { + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/koa-router/-/koa-router-10.0.0.tgz", + "integrity": "sha512-gAE5J1gBQTvfR8rMMtMUkE26+1MbO3DGpGmvfmM2pR9Z7w2VIb2Ecqeal98yVO7+4ltffby7gWOzpCmdNOQe0w==", + "requires": { + "debug": "^4.1.1", + "http-errors": "^1.7.3", + "koa-compose": "^4.1.0", + "methods": "^1.1.2", + "path-to-regexp": "^6.1.0" + }, + "dependencies": { + "debug": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz", + "integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==", + "requires": { + "ms": "2.1.2" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + } + } + }, + "koa-send": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/koa-send/-/koa-send-5.0.1.tgz", + "integrity": "sha512-tmcyQ/wXXuxpDxyNXv5yNNkdAMdFRqwtegBXUaowiQzUKqJehttS0x2j0eOZDQAyloAth5w6wwBImnFzkUz3pQ==", + "requires": { + "debug": "^4.1.1", + "http-errors": "^1.7.3", + "resolve-path": "^1.4.0" + }, + "dependencies": { + "debug": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz", + "integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==", + "requires": { + "ms": "2.1.2" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + } + } + }, + "koa-static": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/koa-static/-/koa-static-5.0.0.tgz", + "integrity": "sha512-UqyYyH5YEXaJrf9S8E23GoJFQZXkBVJ9zYYMPGz919MSX1KuvAcycIuS0ci150HCoPf4XQVhQ84Qf8xRPWxFaQ==", + "requires": { + "debug": "^3.1.0", + "koa-send": "^5.0.0" + } + }, + "lodash.camelcase": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz", + "integrity": "sha1-soqmKIorn8ZRA1x3EfZathkDMaY=" + }, + "lodash.forin": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/lodash.forin/-/lodash.forin-4.4.0.tgz", + "integrity": "sha1-XT8grlZAEfvog4H32YlJyclRlzE=" + }, + "lodash.isobject": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/lodash.isobject/-/lodash.isobject-3.0.2.tgz", + "integrity": "sha1-PI+41bW/S/kK4G4U8qUwpO2TXh0=" + }, + "lodash.isplainobject": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz", + "integrity": "sha1-fFJqUtibRcRcxpC4gWO+BJf1UMs=" + }, + "lodash.merge": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", + "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==" + }, + "media-typer": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", + "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=" + }, + "methods": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", + "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=" + }, + "mime-db": { + "version": "1.48.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.48.0.tgz", + "integrity": "sha512-FM3QwxV+TnZYQ2aRqhlKBMHxk10lTbMt3bBkMAp54ddrNeVSfcQYOOKuGuy3Ddrm38I04If834fOUSq1yzslJQ==" + }, + "mime-types": { + "version": "2.1.31", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.31.tgz", + "integrity": "sha512-XGZnNzm3QvgKxa8dpzyhFTHmpP3l5YNusmne07VUOXxou9CqUqYa/HBy124RqtVh/O2pECas/MOcsDgpilPOPg==", + "requires": { + "mime-db": "1.48.0" + } + }, + "moment": { + "version": "2.29.1", + "resolved": "https://registry.npmjs.org/moment/-/moment-2.29.1.tgz", + "integrity": "sha512-kHmoybcPV8Sqy59DwNDY3Jefr64lK/by/da0ViFcuA4DH0vQg5Q6Ze5VimxkfQNSC+Mls/Kx53s7TjP1RhFEDQ==" + }, + "moment-timezone": { + "version": "0.5.33", + "resolved": "https://registry.npmjs.org/moment-timezone/-/moment-timezone-0.5.33.tgz", + "integrity": "sha512-PTc2vcT8K9J5/9rDEPe5czSIKgLoGsH8UNpA4qZTVw0Vd/Uz19geE9abbIOQKaAQFcnQ3v5YEXrbSc5BpshH+w==", + "requires": { + "moment": ">= 2.9.0" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" + }, + "mysql": { + "version": "2.18.1", + "resolved": "https://registry.npmjs.org/mysql/-/mysql-2.18.1.tgz", + "integrity": "sha512-Bca+gk2YWmqp2Uf6k5NFEurwY/0td0cpebAucFpY/3jhrwrVGuxU2uQFCHjU19SJfje0yQvi+rVWdq78hR5lig==", + "requires": { + "bignumber.js": "9.0.0", + "readable-stream": "2.3.7", + "safe-buffer": "5.1.2", + "sqlstring": "2.3.1" + } + }, + "negotiator": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.2.tgz", + "integrity": "sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw==" + }, + "node-fetch": { + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.1.tgz", + "integrity": "sha512-V4aYg89jEoVRxRb2fJdAg8FHvI7cEyYdVAh94HH0UIK8oJxUfkjlDQN9RbMx+bEjP7+ggMiFRprSti032Oipxw==" + }, + "object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=" + }, + "object-inspect": { + "version": "1.10.3", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.10.3.tgz", + "integrity": "sha512-e5mCJlSH7poANfC8z8S9s9S2IN5/4Zb3aZ33f5s8YqoazCFzNLloLU8r5VCG+G7WoqLvAAZoVMcy3tp/3X0Plw==" + }, + "on-finished": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", + "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=", + "requires": { + "ee-first": "1.1.1" + } + }, + "only": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/only/-/only-0.0.2.tgz", + "integrity": "sha1-Kv3oTQPlC5qO3EROMGEKcCle37Q=" + }, + "parseurl": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", + "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==" + }, + "path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=" + }, + "path-parse": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==" + }, + "path-to-regexp": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-6.2.0.tgz", + "integrity": "sha512-f66KywYG6+43afgE/8j/GoiNyygk/bnoCbps++3ErRKsIYkGGupyv07R2Ok5m9i67Iqc+T2g1eAUGUPzWhYTyg==" + }, + "process-nextick-args": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==" + }, + "promise": { + "version": "7.3.1", + "resolved": "https://registry.npmjs.org/promise/-/promise-7.3.1.tgz", + "integrity": "sha512-nolQXZ/4L+bP/UGlkfaIujX9BKxGwmQ9OT4mOt5yvy8iK1h3wqTEJCijzGANTCCl9nWjY41juyAn2K3Q1hLLTg==", + "requires": { + "asap": "~2.0.3" + } + }, + "pug": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/pug/-/pug-3.0.2.tgz", + "integrity": "sha512-bp0I/hiK1D1vChHh6EfDxtndHji55XP/ZJKwsRqrz6lRia6ZC2OZbdAymlxdVFwd1L70ebrVJw4/eZ79skrIaw==", + "requires": { + "pug-code-gen": "^3.0.2", + "pug-filters": "^4.0.0", + "pug-lexer": "^5.0.1", + "pug-linker": "^4.0.0", + "pug-load": "^3.0.0", + "pug-parser": "^6.0.0", + "pug-runtime": "^3.0.1", + "pug-strip-comments": "^2.0.0" + } + }, + "pug-attrs": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pug-attrs/-/pug-attrs-3.0.0.tgz", + "integrity": "sha512-azINV9dUtzPMFQktvTXciNAfAuVh/L/JCl0vtPCwvOA21uZrC08K/UnmrL+SXGEVc1FwzjW62+xw5S/uaLj6cA==", + "requires": { + "constantinople": "^4.0.1", + "js-stringify": "^1.0.2", + "pug-runtime": "^3.0.0" + } + }, + "pug-code-gen": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/pug-code-gen/-/pug-code-gen-3.0.2.tgz", + "integrity": "sha512-nJMhW16MbiGRiyR4miDTQMRWDgKplnHyeLvioEJYbk1RsPI3FuA3saEP8uwnTb2nTJEKBU90NFVWJBk4OU5qyg==", + "requires": { + "constantinople": "^4.0.1", + "doctypes": "^1.1.0", + "js-stringify": "^1.0.2", + "pug-attrs": "^3.0.0", + "pug-error": "^2.0.0", + "pug-runtime": "^3.0.0", + "void-elements": "^3.1.0", + "with": "^7.0.0" + } + }, + "pug-error": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/pug-error/-/pug-error-2.0.0.tgz", + "integrity": "sha512-sjiUsi9M4RAGHktC1drQfCr5C5eriu24Lfbt4s+7SykztEOwVZtbFk1RRq0tzLxcMxMYTBR+zMQaG07J/btayQ==" + }, + "pug-filters": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/pug-filters/-/pug-filters-4.0.0.tgz", + "integrity": "sha512-yeNFtq5Yxmfz0f9z2rMXGw/8/4i1cCFecw/Q7+D0V2DdtII5UvqE12VaZ2AY7ri6o5RNXiweGH79OCq+2RQU4A==", + "requires": { + "constantinople": "^4.0.1", + "jstransformer": "1.0.0", + "pug-error": "^2.0.0", + "pug-walk": "^2.0.0", + "resolve": "^1.15.1" + } + }, + "pug-lexer": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/pug-lexer/-/pug-lexer-5.0.1.tgz", + "integrity": "sha512-0I6C62+keXlZPZkOJeVam9aBLVP2EnbeDw3An+k0/QlqdwH6rv8284nko14Na7c0TtqtogfWXcRoFE4O4Ff20w==", + "requires": { + "character-parser": "^2.2.0", + "is-expression": "^4.0.0", + "pug-error": "^2.0.0" + } + }, + "pug-linker": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/pug-linker/-/pug-linker-4.0.0.tgz", + "integrity": "sha512-gjD1yzp0yxbQqnzBAdlhbgoJL5qIFJw78juN1NpTLt/mfPJ5VgC4BvkoD3G23qKzJtIIXBbcCt6FioLSFLOHdw==", + "requires": { + "pug-error": "^2.0.0", + "pug-walk": "^2.0.0" + } + }, + "pug-load": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pug-load/-/pug-load-3.0.0.tgz", + "integrity": "sha512-OCjTEnhLWZBvS4zni/WUMjH2YSUosnsmjGBB1An7CsKQarYSWQ0GCVyd4eQPMFJqZ8w9xgs01QdiZXKVjk92EQ==", + "requires": { + "object-assign": "^4.1.1", + "pug-walk": "^2.0.0" + } + }, + "pug-parser": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/pug-parser/-/pug-parser-6.0.0.tgz", + "integrity": "sha512-ukiYM/9cH6Cml+AOl5kETtM9NR3WulyVP2y4HOU45DyMim1IeP/OOiyEWRr6qk5I5klpsBnbuHpwKmTx6WURnw==", + "requires": { + "pug-error": "^2.0.0", + "token-stream": "1.0.0" + } + }, + "pug-runtime": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/pug-runtime/-/pug-runtime-3.0.1.tgz", + "integrity": "sha512-L50zbvrQ35TkpHwv0G6aLSuueDRwc/97XdY8kL3tOT0FmhgG7UypU3VztfV/LATAvmUfYi4wNxSajhSAeNN+Kg==" + }, + "pug-strip-comments": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/pug-strip-comments/-/pug-strip-comments-2.0.0.tgz", + "integrity": "sha512-zo8DsDpH7eTkPHCXFeAk1xZXJbyoTfdPlNR0bK7rpOMuhBYb0f5qUVCO1xlsitYd3w5FQTK7zpNVKb3rZoUrrQ==", + "requires": { + "pug-error": "^2.0.0" + } + }, + "pug-walk": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/pug-walk/-/pug-walk-2.0.0.tgz", + "integrity": "sha512-yYELe9Q5q9IQhuvqsZNwA5hfPkMJ8u92bQLIMcsMxf/VADjNtEYptU+inlufAFYcWdHlwNfZOEnOOQrZrcyJCQ==" + }, + "qs": { + "version": "6.10.1", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.10.1.tgz", + "integrity": "sha512-M528Hph6wsSVOBiYUnGf+K/7w0hNshs/duGsNXPUCLH5XAqjEtiPGwNONLV0tBH8NoGb0mvD5JubnUTrujKDTg==", + "requires": { + "side-channel": "^1.0.4" + } + }, + "raw-body": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.4.1.tgz", + "integrity": "sha512-9WmIKF6mkvA0SLmA2Knm9+qj89e+j1zqgyn8aXGd7+nAduPoqgI9lO57SAZNn/Byzo5P7JhXTyg9PzaJbH73bA==", + "requires": { + "bytes": "3.1.0", + "http-errors": "1.7.3", + "iconv-lite": "0.4.24", + "unpipe": "1.0.0" + }, + "dependencies": { + "depd": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", + "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=" + }, + "http-errors": { + "version": "1.7.3", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.7.3.tgz", + "integrity": "sha512-ZTTX0MWrsQ2ZAhA1cejAwDLycFsd7I7nVtnkT3Ol0aqodaKW+0CTZDQ1uBv5whptCnc8e8HeRRJxRs0kmm/Qfw==", + "requires": { + "depd": "~1.1.2", + "inherits": "2.0.4", + "setprototypeof": "1.1.1", + "statuses": ">= 1.5.0 < 2", + "toidentifier": "1.0.0" + } + }, + "setprototypeof": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.1.tgz", + "integrity": "sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw==" + } + } + }, + "readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "resolve": { + "version": "1.20.0", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.20.0.tgz", + "integrity": "sha512-wENBPt4ySzg4ybFQW2TT1zMQucPK95HSh/nq2CFTZVOGut2+pQvSsgtda4d26YrYcr067wjbmzOG8byDPBX63A==", + "requires": { + "is-core-module": "^2.2.0", + "path-parse": "^1.0.6" + } + }, + "resolve-path": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/resolve-path/-/resolve-path-1.4.0.tgz", + "integrity": "sha1-xL2p9e+y/OZSR4c6s2u02DT+Fvc=", + "requires": { + "http-errors": "~1.6.2", + "path-is-absolute": "1.0.1" + }, + "dependencies": { + "depd": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", + "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=" + }, + "http-errors": { + "version": "1.6.3", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.3.tgz", + "integrity": "sha1-i1VoC7S+KDoLW/TqLjhYC+HZMg0=", + "requires": { + "depd": "~1.1.2", + "inherits": "2.0.3", + "setprototypeof": "1.1.0", + "statuses": ">= 1.4.0 < 2" + } + }, + "inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" + }, + "setprototypeof": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.0.tgz", + "integrity": "sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ==" + } + } + }, + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + }, + "safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" + }, + "setprototypeof": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", + "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==" + }, + "side-channel": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", + "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==", + "requires": { + "call-bind": "^1.0.0", + "get-intrinsic": "^1.0.2", + "object-inspect": "^1.9.0" + } + }, + "sqlstring": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/sqlstring/-/sqlstring-2.3.1.tgz", + "integrity": "sha1-R1OT/56RR5rqYtyvDKPRSYOn+0A=" + }, + "statuses": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", + "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=" + }, + "stream-slice": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/stream-slice/-/stream-slice-0.1.2.tgz", + "integrity": "sha1-LcT04bk2+xPz6zmi3vGTJ5jQeks=" + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "requires": { + "safe-buffer": "~5.1.0" + } + }, + "to-fast-properties": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", + "integrity": "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=" + }, + "toidentifier": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.0.tgz", + "integrity": "sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw==" + }, + "token-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/token-stream/-/token-stream-1.0.0.tgz", + "integrity": "sha1-zCAOqyYT9BZtJ/+a/HylbUnfbrQ=" + }, + "tsscmp": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/tsscmp/-/tsscmp-1.0.6.tgz", + "integrity": "sha512-LxhtAkPDTkVCMQjt2h6eBVY28KCjikZqZfMcC15YBeNjkgUpdCfBu5HoiOTDu86v6smE8yOjyEktJ8hlbANHQA==" + }, + "type-is": { + "version": "1.6.18", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", + "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", + "requires": { + "media-typer": "0.3.0", + "mime-types": "~2.1.24" + } + }, + "universalify": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", + "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==" + }, + "unpipe": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", + "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=" + }, + "util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" + }, + "vary": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", + "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=" + }, + "void-elements": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/void-elements/-/void-elements-3.1.0.tgz", + "integrity": "sha1-YU9/v42AHwu18GYfWy9XhXUOTwk=" + }, + "with": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/with/-/with-7.0.2.tgz", + "integrity": "sha512-RNGKj82nUPg3g5ygxkQl0R937xLyho1J24ItRCBTr/m1YnZkzJy1hUiHUJrc/VlsDQzsCnInEGSg3bci0Lmd4w==", + "requires": { + "@babel/parser": "^7.9.6", + "@babel/types": "^7.9.6", + "assert-never": "^1.2.1", + "babel-walk": "3.0.0-canary-5" + } + }, + "ylru": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/ylru/-/ylru-1.2.1.tgz", + "integrity": "sha512-faQrqNMzcPCHGVC2aaOINk13K+aaBDUPjGWl0teOXywElLjyVAB6Oe2jj62jHYtwsU49jXhScYbvPENK+6zAvQ==" + } + } +} diff --git a/package.json b/package.json index 073e0c0..0ca3bff 100644 --- a/package.json +++ b/package.json @@ -1,33 +1,31 @@ { - "name": "arav-dwelling", - "version": "21.10.0", - "description": "Arav's dwelling", - "homepage": "https://git.arav.top/Arav/Dwelling", - "repository": { - "type": "git", - "url": "https://git.arav.top/Arav/Dwelling" - }, - "main": "index.js", - "scripts": { - "test": "echo \"Error: no test specified\" && exit 1" - }, - "keywords": [ - "homepage", - "dwelling", - "Arav" - ], - "author": "Alexander \"Arav\" Andreev (https://arav.top)", - "license": "GPLv3", - "dependencies": { - "koa": "^2.13.1", - "koa-body": "^4.2.0", - "koa-pug": "^4.0.4", - "koa-range": "^0.3.0", - "koa-router": "^10.0.0", - "koa-static": "^5.0.0", - "moment": "^2.29.1", - "moment-timezone": "^0.5.33", - "mysql": "^2.18.1", - "node-fetch": "^2.6.1" - } + "name": "arav-dwelling", + "description": "Arav's dwelling", + "version": "21.22.0", + "author": "Alexander \"Arav\" Andreev (https://arav.top)", + "license": "GPLv3", + "homepage": "https://git.arav.top/Arav/Dwelling", + "repository": { + "type": "git", + "url": "https://git.arav.top/Arav/Dwelling.git" + }, + "private": true, + "main": "./homepage/index.js", + "exports": { + "./homepage": "./homepage/index.js", + "./files": "./files/index.js", + "./radio": "./radio/index.js" + }, + "dependencies": { + "koa": "^2.13.1", + "koa-body": "^4.2.0", + "koa-pug": "^5.0.0", + "koa-range": "^0.3.0", + "koa-router": "^10.0.0", + "koa-static": "^5.0.0", + "moment": "^2.29.1", + "moment-timezone": "^0.5.33", + "mysql": "^2.18.1", + "node-fetch": "^2.6.1" + } } diff --git a/radio/config.example.js b/radio/config.example.js new file mode 100644 index 0000000..692db11 --- /dev/null +++ b/radio/config.example.js @@ -0,0 +1,2 @@ +exports.port = 32251; +exports.host = "127.0.0.1"; diff --git a/radio.js b/radio/index.js similarity index 69% rename from radio.js rename to radio/index.js index 01beb5f..5113c12 100644 --- a/radio.js +++ b/radio/index.js @@ -7,7 +7,7 @@ const koaRouter = require("koa-router"); const fetch = require("node-fetch"); const config = require("./config"); -const util = require("./util"); +const util = require("../shared/util"); async function getRadioStatus() { try { @@ -30,8 +30,8 @@ async function getRadioStatus() { } } -function setRoutes(router) { - router.get('/', async ctx => { +function setRoutes() { + return koaRouter().get('/', async ctx => { await ctx.render('index', { title: "/ Radio", description: "Internet-radio broadcasting from under my desk.", @@ -42,34 +42,27 @@ function setRoutes(router) { .get('/filelist', async ctx => { ctx.type = 'text/html'; ctx.body = fs.readFileSync( - path.join(__dirname, '/static/radio/assets/files/radio_filelist.html')); + path.join(__dirname, '/static/radio_filelist.html')); }) .get('/playlist', async ctx => { ctx.attachment('radio.arav.top.m3u'); ctx.body = fs.readFileSync( - path.join(__dirname, '/static/radio/assets/files/radio.arav.top.m3u')); + path.join(__dirname, '/static/assets/files/radio.arav.top.m3u')); }) .get('/stats', async ctx => { ctx.body = await getRadioStatus(); }); } -module.exports = () => { - const app = new Koa(); - const pug = new koaPug({ - viewPath: path.join(__dirname, "views", "radio"), - locals: { - moment: util.datetime }, - app: app - }); +const app = new Koa(); +const pug = new koaPug({ + viewPath: path.join(__dirname, "views"), + locals: { + moment: util.datetime }, + app: app +}); - const radio_router = koaRouter(); - setRoutes(radio_router); - - app.proxy = true; - app - .use(radio_router.routes()) - .listen(config.radio.port, config.radio.host); - - return app; -} \ No newline at end of file +app.proxy = true; +app + .use(setRoutes().routes()) + .listen(config.port, config.host); diff --git a/static/radio/assets/css/main.css b/radio/static/assets/css/main.css similarity index 100% rename from static/radio/assets/css/main.css rename to radio/static/assets/css/main.css diff --git a/static/radio/assets/files/radio.arav.top.m3u b/radio/static/assets/files/radio.arav.top.m3u similarity index 100% rename from static/radio/assets/files/radio.arav.top.m3u rename to radio/static/assets/files/radio.arav.top.m3u diff --git a/static/radio/assets/js/main.js b/radio/static/assets/js/main.js similarity index 100% rename from static/radio/assets/js/main.js rename to radio/static/assets/js/main.js diff --git a/static/radio/assets/files/radio_filelist.html b/radio/static/assets/radio_filelist.html similarity index 100% rename from static/radio/assets/files/radio_filelist.html rename to radio/static/assets/radio_filelist.html diff --git a/radio/static/robots.txt b/radio/static/robots.txt new file mode 100644 index 0000000..b92443b --- /dev/null +++ b/radio/static/robots.txt @@ -0,0 +1,3 @@ +User-agent: * +Disallow: /.well-known/ +Disallow: /assets/ \ No newline at end of file diff --git a/radio/views/index.pug b/radio/views/index.pug new file mode 100644 index 0000000..054b19c --- /dev/null +++ b/radio/views/index.pug @@ -0,0 +1,54 @@ +mixin radioStatus(date, iso) + if (date != "n/a") + p #[span#radio-status On-air since #[time(datetime=iso)= date]] + else + p #[span#radio-status Radio is offline.] + +doctype html +html(lang='en') + head + title Arav's dwelling #{title} + meta(charset='utf-8') + meta(http-equiv='X-UA-Compatible' content='IE=edge') + meta(name='viewport' content='width=device-width, initial-scale=1.0') + meta(name='theme-color' content='#cd2682') + meta(name='description' content=description) + link(rel='icon' href='/shared/img/favicon.svg' sizes='any' type='image/svg+xml') + link(href='/assets/css/main.css' rel='stylesheet') + script(src='/assets/js/main.js' defer) + body + header + svg#logo(viewBox='0 -25 216 40') + text.logo Arav's dwelling + text.under(y='11') Welcome to my sacred place, wanderer + nav + a(href=main_site) Back to main website + h1 Radio + section + small.player-links + a(href="/filelist") file list + a(href="/playlist") playlist (.m3u) + a(href="/live/stream.ogg") direct link + a(href="http://radio.arav.top:8000/stream.ogg") direct link (http) + a(href="http://moq7aejnf4xk5k2bkaltli3ftkhusy2mbrd3pj23nrca343ku2mgk4yd.onion/radio/live/stream.ogg") direct link (Tor) + a(href="http://t42fkp6zp5dfqywantq3zp427ig3q2onrmfv246tyaztpg4ckb5a.b32.i2p/radio/live/stream.ogg") direct link (I2P) + | OGG 128 Kb/s + audio(preload='none' controls) + source(src="/live/stream.ogg" type="audio/ogg") + | Your browser doesn't support an audio element, it's sad... But you always can take the #[a(href="/playlist") playlist]! + +radioStatus(radio_status.server_start_date, radio_status.server_start_iso8601) + p Now playing: #[span#radio-song= radio_status.song] + p Current/peak listeners: #[span#radio-listeners= radio_status.listeners] / #[span#radio-listener-peak= radio_status.listener_peak] + p + small Notice: information updates every 45 seconds. But you can #[a(href="javascript:getRadioStats()") update] it forcibly. + section + h2 About the radio + p This project grew from MPD I used to stream music over LAN for myself. Then I let it out and placed a player on my neocities website. Then I added Icecast to see if there are listeners. I wasn't happy on how MPD was nearly overloading CPU, and later on, when I moved radio off to a laptop, I found a great tool for streams called Liquidsoap. + p Radio is also available through HTTP port 8000, but browsers may try to redirect to HTTPS. Any other applications should work fine. + p Radio is listed in #[a(href="https://dir.xiph.org/search?q=arav's+dwelling") Xiph directory]. + section + h2 Privacy statements + p I collect access logs that include access date and time, IP-address, User-Agent, referer URL that tells me where have you came from, request that you sent to me. In addition there are GeoIP information added based on your IP-address that includes country, region, and city for my convenience. + p This website makes use of JavaScript to show you information on a radio. + footer + | 2017—2021 Arav <#[a(href='mailto:me@arav.top') me@arav.top]> diff --git a/static/shared/fonts/RobotoCondensed-Regular.ttf b/shared/assets/fonts/RobotoCondensed-Regular.ttf similarity index 100% rename from static/shared/fonts/RobotoCondensed-Regular.ttf rename to shared/assets/fonts/RobotoCondensed-Regular.ttf diff --git a/static/shared/fonts/ShareTechMono-Regular.ttf b/shared/assets/fonts/ShareTechMono-Regular.ttf similarity index 100% rename from static/shared/fonts/ShareTechMono-Regular.ttf rename to shared/assets/fonts/ShareTechMono-Regular.ttf diff --git a/static/dwelling/assets/img/banner_240x60.gif b/shared/assets/img/banner_240x60.gif similarity index 100% rename from static/dwelling/assets/img/banner_240x60.gif rename to shared/assets/img/banner_240x60.gif diff --git a/static/dwelling/assets/img/banner_88x31.gif b/shared/assets/img/banner_88x31.gif similarity index 100% rename from static/dwelling/assets/img/banner_88x31.gif rename to shared/assets/img/banner_88x31.gif diff --git a/static/dwelling/assets/img/banner_dark_240x60.gif b/shared/assets/img/banner_dark_240x60.gif similarity index 100% rename from static/dwelling/assets/img/banner_dark_240x60.gif rename to shared/assets/img/banner_dark_240x60.gif diff --git a/static/dwelling/assets/img/banner_dark_88x31.gif b/shared/assets/img/banner_dark_88x31.gif similarity index 100% rename from static/dwelling/assets/img/banner_dark_88x31.gif rename to shared/assets/img/banner_dark_88x31.gif diff --git a/static/dwelling/assets/img/favicon.ico b/shared/assets/img/favicon.ico similarity index 100% rename from static/dwelling/assets/img/favicon.ico rename to shared/assets/img/favicon.ico diff --git a/static/shared/img/favicon.svg b/shared/assets/img/favicon.svg similarity index 100% rename from static/shared/img/favicon.svg rename to shared/assets/img/favicon.svg diff --git a/static/dwelling/assets/img/favicon_128.png b/shared/assets/img/favicon_128.png similarity index 100% rename from static/dwelling/assets/img/favicon_128.png rename to shared/assets/img/favicon_128.png diff --git a/static/dwelling/assets/img/ts3_banner_960.png b/shared/assets/img/ts3_banner_960.png similarity index 100% rename from static/dwelling/assets/img/ts3_banner_960.png rename to shared/assets/img/ts3_banner_960.png diff --git a/util.js b/shared/util.js similarity index 98% rename from util.js rename to shared/util.js index 1db237b..dd31eb9 100644 --- a/util.js +++ b/shared/util.js @@ -5,10 +5,21 @@ const formats = Object.freeze({ file_date: "YYYY-MM-DD HH:mm:ss z", id_date: "YYYYMMDD-HHmm" }); +exports.formats = formats; + function datetime(date, format=formats.post_date, timezone="UTC") { return moment.utc(date).tz(timezone).format(format); } +exports.datetime = datetime; + +exports.getClientTimezone = ctx => { + if (ctx.header['x-client-timezone'] !== undefined) + return ctx.header['x-client-timezone']; + else + return "UTC"; +}; + exports.getServiceByHost = (host, service="") => { if (host.endsWith("onion")) switch (service) { @@ -30,16 +41,6 @@ exports.getServiceByHost = (host, service="") => { } } -exports.getTimezone = ctx => { - if (ctx.header['x-client-timezone'] !== undefined) - return ctx.header['x-client-timezone']; - else - return "UTC"; -}; - -exports.formats = formats; -exports.datetime = datetime; - exports.rssLink = (proto, host, date, category, timezone="UTC") => `${proto}://${host}/mindflow#${category}-${datetime(date, formats.id_date, timezone)}`; diff --git a/static/files/robots.txt b/static/files/robots.txt deleted file mode 100644 index 4617157..0000000 --- a/static/files/robots.txt +++ /dev/null @@ -1,3 +0,0 @@ -User-agent: * -Disallow: /assets/ -Disallow: /files/ \ No newline at end of file diff --git a/static/radio/robots.txt b/static/radio/robots.txt deleted file mode 100644 index ce3d0e7..0000000 --- a/static/radio/robots.txt +++ /dev/null @@ -1,3 +0,0 @@ -User-agent: * -Disallow: /assets/ -Disallow: /stream.ogg \ No newline at end of file diff --git a/static/shared/img/favicon.ico b/static/shared/img/favicon.ico deleted file mode 100644 index 2fef958..0000000 Binary files a/static/shared/img/favicon.ico and /dev/null differ diff --git a/static/shared/img/favicon_128.png b/static/shared/img/favicon_128.png deleted file mode 100644 index c7d066e..0000000 Binary files a/static/shared/img/favicon_128.png and /dev/null differ diff --git a/views/files/base.pug b/views/files/base.pug deleted file mode 100644 index b6a3222..0000000 --- a/views/files/base.pug +++ /dev/null @@ -1,21 +0,0 @@ -doctype html -html(lang='en') - head - title Arav's dwelling #{title} - meta(charset='utf-8') - meta(http-equiv='X-UA-Compatible' content='IE=edge') - meta(name='viewport' content='width=device-width, initial-scale=1.0') - meta(name='theme-color' content='#cd2682') - meta(name='description' content=description) - link(rel='icon' href='/shared/img/favicon.svg' sizes='any' type='image/svg+xml') - link(href='/assets/css/main.css' rel='stylesheet') - block head - body - header - svg#logo(viewBox='0 -25 216 40') - text.logo Arav's dwelling - text.under(y='11') Welcome to my sacred place, wanderer - block nav - block content - footer - | 2017—2021 Arav <#[a(href='mailto:me@arav.top') me@arav.top]> \ No newline at end of file diff --git a/views/files/index.pug b/views/files/index.pug deleted file mode 100644 index e229d19..0000000 --- a/views/files/index.pug +++ /dev/null @@ -1,25 +0,0 @@ -extends base.pug - -block nav - nav - a(href=main_site) Back to main website - h1 Files - -block content - section#files - span#current-path!= current_path - p Files: #{total_files} (#{total_files_size}); Directories: #{total_directories}. - table - thead - tr - th Name - th Date - th Size - tbody - tr - td #[a(href="../") ../] - each item in items - tr - td #[a(href=item.link)= item.name] - td!= item.datetime - td= item.size + ' ' + item.size_unit \ No newline at end of file diff --git a/views/radio/base.pug b/views/radio/base.pug deleted file mode 100644 index b6a3222..0000000 --- a/views/radio/base.pug +++ /dev/null @@ -1,21 +0,0 @@ -doctype html -html(lang='en') - head - title Arav's dwelling #{title} - meta(charset='utf-8') - meta(http-equiv='X-UA-Compatible' content='IE=edge') - meta(name='viewport' content='width=device-width, initial-scale=1.0') - meta(name='theme-color' content='#cd2682') - meta(name='description' content=description) - link(rel='icon' href='/shared/img/favicon.svg' sizes='any' type='image/svg+xml') - link(href='/assets/css/main.css' rel='stylesheet') - block head - body - header - svg#logo(viewBox='0 -25 216 40') - text.logo Arav's dwelling - text.under(y='11') Welcome to my sacred place, wanderer - block nav - block content - footer - | 2017—2021 Arav <#[a(href='mailto:me@arav.top') me@arav.top]> \ No newline at end of file diff --git a/views/radio/index.pug b/views/radio/index.pug deleted file mode 100644 index 7db4f4d..0000000 --- a/views/radio/index.pug +++ /dev/null @@ -1,43 +0,0 @@ -extends base.pug - -block head - script(src='/assets/js/main.js' defer) - -block nav - nav - a(href=main_site) Back to main website - h1 Radio - -mixin radioStatus(date, iso) - if (date != "n/a") - p #[span#radio-status On-air since #[time(datetime=iso)= date]] - else - p #[span#radio-status Radio is offline.] - -block content - section - small.player-links - a(href="/filelist") file list - a(href="/playlist") playlist (.m3u) - a(href="/live/stream.ogg") direct link - a(href="http://radio.arav.top:8000/stream.ogg") direct link (http) - a(href="http://moq7aejnf4xk5k2bkaltli3ftkhusy2mbrd3pj23nrca343ku2mgk4yd.onion/radio/live/stream.ogg") direct link (Tor) - a(href="http://t42fkp6zp5dfqywantq3zp427ig3q2onrmfv246tyaztpg4ckb5a.b32.i2p/radio/live/stream.ogg") direct link (I2P) - | OGG 128 Kb/s - audio(preload='none' controls) - source(src="/live/stream.ogg" type="audio/ogg") - | Your browser doesn't support an audio element, it's sad... But you always can take the #[a(href="/playlist") playlist]! - +radioStatus(radio_status.server_start_date, radio_status.server_start_iso8601) - p Now playing: #[span#radio-song= radio_status.song] - p Current/peak listeners: #[span#radio-listeners= radio_status.listeners] / #[span#radio-listener-peak= radio_status.listener_peak] - p - small Notice: information updates every 45 seconds. But you can #[a(href="javascript:getRadioStats()") update] it forcibly. - section - h2 About the radio - p This project grew from MPD I used to stream music over LAN for myself. Then I let it out and placed a player on my neocities website. Then I added Icecast to see if there are listeners. I wasn't happy on how MPD was nearly overloading CPU, and later on, when I moved radio off to a laptop, I found a great tool for streams called Liquidsoap. - p Radio is also available through HTTP port 8000, but browsers may try to redirect to HTTPS. Any other applications should work fine. - p Radio is listed in #[a(href="https://dir.xiph.org/search?q=arav's+dwelling") Xiph directory]. - section - h2 Privacy statements - p I collect access logs that include access date and time, IP-address, User-Agent, referer URL that tells me where have you came from, request that you sent to me. In addition there are GeoIP information added based on your IP-address that includes country, region, and city for my convenience. - p This website makes use of JavaScript to show you information on a radio. \ No newline at end of file diff --git a/yandex_83cb7680b026e750.html b/yandex_83cb7680b026e750.html new file mode 100644 index 0000000..22c4dc8 --- /dev/null +++ b/yandex_83cb7680b026e750.html @@ -0,0 +1,6 @@ + + + + + Verification: 83cb7680b026e750 + \ No newline at end of file