From 6d02c8183abec680beee08f8d6532aefcd6aa3f5 Mon Sep 17 00:00:00 2001
From: harryob <55142896+harryob@users.noreply.github.com>
Date: Fri, 4 Aug 2023 15:28:18 +0100
Subject: [PATCH 1/4] autowiki and gun example
---
.github/workflows/autowiki.yml | 52 ++
code/_compile_options.dm | 2 +
code/game/world.dm | 6 +-
code/modules/autowiki/autowiki.dm | 36 +
code/modules/autowiki/pages/_page.dm | 54 ++
code/modules/autowiki/pages/guns.dm | 118 +++
code/modules/projectiles/gun.dm | 2 +-
colonialmarines.dme | 3 +
tools/autowiki/autowiki.js | 83 ++
tools/autowiki/package-lock.json | 1043 ++++++++++++++++++++++++++
tools/autowiki/package.json | 10 +
11 files changed, 1407 insertions(+), 2 deletions(-)
create mode 100644 .github/workflows/autowiki.yml
create mode 100644 code/modules/autowiki/autowiki.dm
create mode 100644 code/modules/autowiki/pages/_page.dm
create mode 100644 code/modules/autowiki/pages/guns.dm
create mode 100644 tools/autowiki/autowiki.js
create mode 100644 tools/autowiki/package-lock.json
create mode 100644 tools/autowiki/package.json
diff --git a/.github/workflows/autowiki.yml b/.github/workflows/autowiki.yml
new file mode 100644
index 000000000000..82d0ac76f32f
--- /dev/null
+++ b/.github/workflows/autowiki.yml
@@ -0,0 +1,52 @@
+name: Autowiki
+on:
+ schedule:
+ - cron: "5 4 * * *"
+ workflow_dispatch:
+permissions:
+ contents: read
+
+jobs:
+ autowiki:
+ runs-on: ubuntu-20.04
+ steps:
+ - name: "Check for AUTOWIKI_USERNAME"
+ id: secrets_set
+ env:
+ ENABLER_SECRET: ${{ secrets.AUTOWIKI_USERNAME }}
+ run: |
+ unset SECRET_EXISTS
+ if [ -n "$ENABLER_SECRET" ]; then SECRET_EXISTS=true ; fi
+ echo "SECRETS_ENABLED=$SECRET_EXISTS" >> $GITHUB_OUTPUT
+ - name: Checkout
+ if: steps.secrets_set.outputs.SECRETS_ENABLED
+ uses: actions/checkout@v3
+ - name: Restore BYOND cache
+ if: steps.secrets_set.outputs.SECRETS_ENABLED
+ uses: actions/cache@v3
+ with:
+ path: ~/BYOND
+ key: ${{ runner.os }}-byond-${{ secrets.CACHE_PURGE_KEY }}
+ - name: Install rust-g
+ if: steps.secrets_set.outputs.SECRETS_ENABLED
+ run: |
+ sudo dpkg --add-architecture i386
+ sudo apt update || true
+ sudo apt install -o APT::Immediate-Configure=false libssl1.1:i386
+ bash tools/ci/install_rust_g.sh
+ - name: Compile and generate Autowiki files
+ if: steps.secrets_set.outputs.SECRETS_ENABLED
+ run: |
+ bash tools/ci/install_byond.sh
+ source $HOME/BYOND/byond/bin/byondsetup
+ tools/build/build --ci autowiki
+ - name: Run Autowiki
+ if: steps.secrets_set.outputs.SECRETS_ENABLED
+ env:
+ USERNAME: ${{ secrets.AUTOWIKI_USERNAME }}
+ PASSWORD: ${{ secrets.AUTOWIKI_PASSWORD }}
+ run: |
+ cd tools/autowiki
+ npm install
+ cd ../..
+ node tools/autowiki/autowiki.js data/autowiki_edits.txt data/autowiki_files/
diff --git a/code/_compile_options.dm b/code/_compile_options.dm
index 0f81b0173ac1..09ec3429daf3 100644
--- a/code/_compile_options.dm
+++ b/code/_compile_options.dm
@@ -41,3 +41,5 @@
// #define TESTING
// #define REFERENCE_TRACKING
// #define GC_FAILURE_HARD_LOOKUP
+
+#define AUTOWIKI
diff --git a/code/game/world.dm b/code/game/world.dm
index 25cd609646da..cff799800a49 100644
--- a/code/game/world.dm
+++ b/code/game/world.dm
@@ -61,7 +61,7 @@ var/list/reboot_sfx = file2list("config/reboot_sfx.txt")
var/testing_locally = (world.params && world.params["local_test"])
var/running_tests = (world.params && world.params["run_tests"])
- #ifdef UNIT_TESTS
+ #if defined(AUTOWIKI) || defined(UNIT_TESTS)
running_tests = TRUE
#endif
// Only do offline sleeping when the server isn't running unit tests or hosting a local dev test
@@ -84,6 +84,10 @@ var/list/reboot_sfx = file2list("config/reboot_sfx.txt")
HandleTestRun()
#endif
+ #ifdef AUTOWIKI
+ setup_autowiki()
+ #endif
+
update_status()
//Scramble the coords obsfucator
diff --git a/code/modules/autowiki/autowiki.dm b/code/modules/autowiki/autowiki.dm
new file mode 100644
index 000000000000..8b38ec76706b
--- /dev/null
+++ b/code/modules/autowiki/autowiki.dm
@@ -0,0 +1,36 @@
+/// When the `AUTOWIKI` define is enabled, will generate an output file for tools/autowiki/autowiki.js to consume.
+/// Autowiki code intentionally still *exists* even without the define, to ensure developers notice
+/// when they break it immediately, rather than until CI or worse, call time.
+#if defined(AUTOWIKI) || defined(UNIT_TESTS)
+/proc/setup_autowiki()
+ Master.sleep_offline_after_initializations = FALSE
+ UNTIL(SSticker.current_state == GAME_STATE_PREGAME)
+
+ //trigger things to run the whole process
+ SSticker.request_start()
+ CONFIG_SET(number/round_end_countdown, 0)
+ SSticker.OnRoundstart(CALLBACK(GLOBAL_PROC, GLOBAL_PROC_REF(generate_autowiki)))
+
+/proc/generate_autowiki()
+ var/output = generate_autowiki_output()
+ rustg_file_write(output, "data/autowiki_edits.txt")
+ qdel(world)
+#endif
+
+/// Returns a string of the autowiki output file
+/proc/generate_autowiki_output()
+ var/total_output = ""
+
+ for (var/datum/autowiki/autowiki_type as anything in subtypesof(/datum/autowiki))
+ var/datum/autowiki/autowiki = new autowiki_type
+ var/output = autowiki.generate()
+
+ if (!istext(output))
+ CRASH("[autowiki_type] does not generate a proper output!")
+
+ total_output += json_encode(list(
+ "title" = autowiki.page,
+ "text" = output,
+ )) + "\n"
+
+ return total_output
diff --git a/code/modules/autowiki/pages/_page.dm b/code/modules/autowiki/pages/_page.dm
new file mode 100644
index 000000000000..8e745ace61c2
--- /dev/null
+++ b/code/modules/autowiki/pages/_page.dm
@@ -0,0 +1,54 @@
+/// A representation of an automated wiki page.
+/datum/autowiki
+ /// The page on the wiki to be replaced.
+ /// This should never be a user-facing page, like "Guide to circuits".
+ /// It should always be a template that only Autowiki should touch.
+ /// For example: "Template:Autowiki/CircuitInfo".
+ var/page
+
+/// Override and return the new text of the page.
+/// This proc can be impure, usually to call `upload_file`.
+/datum/autowiki/proc/generate()
+ SHOULD_CALL_PARENT(FALSE)
+ CRASH("[type] does not implement generate()!")
+
+/// Generates an auto formatted template user.
+/// Your autowiki should ideally be a *lot* of these.
+/// It lets wiki editors edit it much easier later, without having to enter repo.
+/// Parameters will be passed in by name. That means your template should expect
+/// something that looks like `{{ Autowiki_Circuit|name=Combiner|description=This combines }}`
+/// Lists, which must be array-like (no keys), will be turned into a flat list with their key and a number,
+/// such that list("food" = list("fruit", "candy")) -> food1=fruit|food2=candy
+/datum/autowiki/proc/include_template(name, parameters)
+ var/template_text = "{{[name]"
+
+ var/list/prepared_parameters = list()
+ for (var/key in parameters)
+ var/value = parameters[key]
+ if (islist(value))
+ for (var/index in 1 to length(value))
+ prepared_parameters["[key][index]"] = "[value[index]]"
+ else
+ prepared_parameters[key] = value
+
+ for (var/parameter_name in prepared_parameters)
+ template_text += "|[parameter_name]="
+ template_text += "[prepared_parameters[parameter_name]]"
+
+ template_text += "}}"
+
+ return template_text
+
+/// Takes an icon and uploads it to Autowiki-name.png.
+/// Do your best to make sure this is unique, so it doesn't clash with other autowiki icons.
+/datum/autowiki/proc/upload_icon(icon/icon, name)
+ // Fuck you
+ if (IsAdminAdvancedProcCall())
+ return
+
+ fcopy(icon, "data/autowiki_files/[name].png")
+
+/// Escape a parameter such that it can be correctly put inside a wiki output
+/datum/autowiki/proc/escape_value(parameter)
+ // | is a special character in MediaWiki, and must be escaped by...using another template.
+ return replacetextEx(parameter, "|", "{{!}}")
diff --git a/code/modules/autowiki/pages/guns.dm b/code/modules/autowiki/pages/guns.dm
new file mode 100644
index 000000000000..0946b552fe31
--- /dev/null
+++ b/code/modules/autowiki/pages/guns.dm
@@ -0,0 +1,118 @@
+/datum/autowiki/guns
+ page = "Template:Autowiki/Content/GunData"
+
+
+/datum/autowiki/guns/generate()
+ var/output = ""
+
+ var/list/gun_to_ammo = list()
+
+ for(var/obj/item/ammo_magazine/typepath as anything in subtypesof(/obj/item/ammo_magazine) - subtypesof(/obj/item/ammo_magazine/internal))
+ LAZYADD(gun_to_ammo[initial(typepath.gun_type)], typepath)
+
+ for(var/typepath in sort_list(subtypesof(/obj/item/weapon/gun), GLOBAL_PROC_REF(cmp_typepaths_asc)))
+ var/obj/item/weapon/gun/generating_gun = new typepath()
+
+ var/filename = SANITIZE_FILENAME(escape_value(format_text(generating_gun.name)))
+
+ var/list/gun_data = generating_gun.ui_data()
+
+ var/list/valid_mag_types = list()
+ for(var/path in gun_to_ammo)
+ if(!istype(generating_gun, path))
+ continue
+
+ valid_mag_types += gun_to_ammo[path]
+
+ var/ammo = ""
+ var/damage_table = ""
+ for(var/ammo_typepath in valid_mag_types)
+ var/obj/item/ammo_magazine/generating_mag = new ammo_typepath()
+
+ var/ammo_filename = SANITIZE_FILENAME(escape_value(format_text(generating_mag.name)))
+
+ if(!fexists("data/autowiki_files/[ammo_filename].png"))
+ upload_icon(getFlatIcon(generating_mag, no_anim = TRUE), ammo_filename)
+
+ var/datum/ammo/current_ammo = GLOB.ammo_list[generating_mag.default_ammo]
+
+ ammo += include_template("Autowiki/AmmoMagazine", list(
+ "icon" = escape_value(ammo_filename),
+ "name" = escape_value(generating_mag.name),
+ "capacity" = escape_value(generating_mag.max_rounds),
+ "damage" = escape_value(current_ammo.damage),
+ "max_range" = escape_value(current_ammo.max_range),
+ "fall_off" = escape_value(current_ammo.damage_falloff),
+ "penetration" = escape_value(current_ammo.penetration),
+ "punch" = escape_value(current_ammo.pen_armor_punch),
+ ))
+
+ generating_gun.current_mag = generating_mag
+
+ var/list/gun_ammo_data = generating_gun.ui_data()
+ var/list/armor_data = list()
+
+ var/iterator = 1
+ for(var/header in gun_ammo_data["damage_armor_profile_headers"])
+ var/damage = gun_ammo_data["damage_armor_profile_marine"][iterator]
+ armor_data["armor-[header]"] = damage
+ iterator++
+
+ var/list/damage = list("ammo_name" = escape_value(generating_mag.name))
+ damage += armor_data
+
+ damage_table += include_template("Autowiki/DamageVersusArmorRow", damage)
+
+ qdel(generating_mag)
+
+ gun_data["ammo_types"] = ammo
+ gun_data["damage_table"] = damage_table
+
+ var/list/attachments_by_slot = list()
+ for(var/obj/item/attachable/attachment_typepath as anything in generating_gun.attachable_allowed)
+ LAZYADD(attachments_by_slot[capitalize(initial(attachment_typepath.slot))], attachment_typepath)
+
+ var/attachments = ""
+ for(var/slot in attachments_by_slot)
+ var/list/attachments_in_slot = ""
+
+ for(var/attachment_typepath in attachments_by_slot[slot])
+ var/obj/item/attachable/generating_attachment = new attachment_typepath()
+
+ var/attachment_filename = SANITIZE_FILENAME(escape_value(format_text(generating_attachment.name)))
+
+ if(!fexists("data/autowiki_files/[attachment_filename].png"))
+ upload_icon(getFlatIcon(generating_attachment, no_anim = TRUE), attachment_filename)
+
+ attachments_in_slot += include_template("Autowiki/AvailableAttachment", list(
+ "icon" = escape_value(attachment_filename),
+ "name" = escape_value(generating_attachment.name),
+ ))
+
+ qdel(generating_attachment)
+
+ attachments += include_template("Autowiki/AttachmentsBySlot", list(
+ "slot" = escape_value(slot),
+ "attachments" = attachments_in_slot,
+ ))
+ gun_data["attachments"] = attachments
+
+
+ upload_icon(getFlatIcon(generating_gun, no_anim = TRUE), filename)
+ gun_data["icon"] = filename
+
+ output += include_template("Autowiki/Gun", gun_data)
+
+ qdel(generating_gun)
+
+ return output
+
+/datum/autowiki/guns/proc/wiki_sanitize_assoc(list/sanitizing_list)
+ var/list/sanitized = list()
+
+ for(var/key in sanitizing_list)
+ var/value = sanitizing_list[key]
+
+ sanitized[escape_value(key)] = escape_value(value)
+
+ return sanitized
diff --git a/code/modules/projectiles/gun.dm b/code/modules/projectiles/gun.dm
index 6b948b9debe2..1bd98e5b258e 100644
--- a/code/modules/projectiles/gun.dm
+++ b/code/modules/projectiles/gun.dm
@@ -616,7 +616,7 @@ As sniper rifles have both and weapon mods can change them as well. ..() deals w
if(in_chamber && in_chamber.ammo)
in_ammo = in_chamber.ammo
else if(current_mag && current_mag.current_rounds > 0)
- if(istype(current_mag) && current_mag.chamber_contents[current_mag.chamber_position] != "empty")
+ if(istype(current_mag) && length(current_mag.chamber_contents) && current_mag.chamber_contents[current_mag.chamber_position] != "empty")
in_ammo = GLOB.ammo_list[current_mag.chamber_contents[current_mag.chamber_position]]
if(!istype(in_ammo))
in_ammo = GLOB.ammo_list[current_mag.default_ammo]
diff --git a/colonialmarines.dme b/colonialmarines.dme
index 2b3b08984dfa..9549d80d237d 100644
--- a/colonialmarines.dme
+++ b/colonialmarines.dme
@@ -1399,6 +1399,9 @@
#include "code\modules\asset_cache\assets\vending.dm"
#include "code\modules\asset_cache\transports\asset_transport.dm"
#include "code\modules\asset_cache\transports\webroot_transport.dm"
+#include "code\modules\autowiki\autowiki.dm"
+#include "code\modules\autowiki\pages\_page.dm"
+#include "code\modules\autowiki\pages\guns.dm"
#include "code\modules\buildmode\bm-mode.dm"
#include "code\modules\buildmode\buildmode.dm"
#include "code\modules\buildmode\buttons.dm"
diff --git a/tools/autowiki/autowiki.js b/tools/autowiki/autowiki.js
new file mode 100644
index 000000000000..8b5c5fc9f00a
--- /dev/null
+++ b/tools/autowiki/autowiki.js
@@ -0,0 +1,83 @@
+const fs = require("fs").promises
+const MWBot = require("mwbot")
+
+const { USERNAME, PASSWORD } = process.env
+
+if (!USERNAME) {
+ console.error("USERNAME was not set.")
+ process.exit(1)
+}
+
+if (!PASSWORD) {
+ console.error("PASSWORD was not set.")
+ process.exit(1)
+}
+
+const PAGE_EDIT_FILENAME = process.argv[2]
+
+if (!PAGE_EDIT_FILENAME) {
+ console.error("No filename specified to edit pages")
+ process.exit(1)
+}
+
+const FILE_EDIT_FILENAME = process.argv[3]
+
+if (!FILE_EDIT_FILENAME) {
+ console.error("No filename specified to edit files")
+ process.exit(1)
+}
+
+async function main() {
+ console.log(`Reading from ${PAGE_EDIT_FILENAME}`)
+ const editFile = await (await fs.readFile(PAGE_EDIT_FILENAME, "utf8")).split("\n")
+
+ console.log(`Logging in as ${USERNAME}`)
+
+ const bot = new MWBot()
+
+ await bot.loginGetEditToken({
+ apiUrl: "https://tgstation13.org/wiki/api.php",
+ username: USERNAME,
+ password: PASSWORD,
+ })
+
+ console.log("Logged in")
+
+ // This is not Promise.all as to not flood with a bunch of traffic at once
+ for (const editLine of editFile) {
+ if (editLine.length === 0) {
+ continue
+ }
+
+ let { title, text } = JSON.parse(editLine)
+ text = "This page is automated by Autowiki. Do NOT edit it manually." + text
+
+ console.log(`Editing ${title}...`)
+ await bot.edit(
+ title,
+ text,
+ `Autowiki edit @ ${ new Date().toISOString() }`,
+ )
+ }
+
+ // Same here
+ for (const asset of await fs.readdir(FILE_EDIT_FILENAME)) {
+ const assetPath = `${FILE_EDIT_FILENAME}/${asset}`
+ const assetName = `Autowiki-${asset}`
+
+ console.log(`Replacing ${assetName}...`)
+ await bot.upload(
+ assetName,
+ assetPath,
+ `Autowiki upload @ ${ new Date().toISOString() }`,
+ ).catch(error => {
+ if (error.code === "fileexists-no-change") {
+ console.log(`${assetName} is an exact duplicate`)
+ } else {
+ return Promise.reject(error)
+ }
+ })
+ }
+}
+
+main().catch(console.error)
diff --git a/tools/autowiki/package-lock.json b/tools/autowiki/package-lock.json
new file mode 100644
index 000000000000..ab2b4493025e
--- /dev/null
+++ b/tools/autowiki/package-lock.json
@@ -0,0 +1,1043 @@
+{
+ "name": "autowiki",
+ "version": "1.0.0",
+ "lockfileVersion": 2,
+ "requires": true,
+ "packages": {
+ "": {
+ "name": "autowiki",
+ "version": "1.0.0",
+ "dependencies": {
+ "mwbot": "^2.0.0"
+ }
+ },
+ "node_modules/ajv": {
+ "version": "6.12.6",
+ "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz",
+ "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==",
+ "dependencies": {
+ "fast-deep-equal": "^3.1.1",
+ "fast-json-stable-stringify": "^2.0.0",
+ "json-schema-traverse": "^0.4.1",
+ "uri-js": "^4.2.2"
+ },
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/epoberezkin"
+ }
+ },
+ "node_modules/ansi-regex": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz",
+ "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/ansi-styles": {
+ "version": "2.2.1",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz",
+ "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/asn1": {
+ "version": "0.2.6",
+ "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.6.tgz",
+ "integrity": "sha512-ix/FxPn0MDjeyJ7i/yoHGFt/EX6LyNbxSEhPPXODPL+KB0VPk86UYfL0lMdy+KCnv+fmvIzySwaK5COwqVbWTQ==",
+ "dependencies": {
+ "safer-buffer": "~2.1.0"
+ }
+ },
+ "node_modules/assert-plus": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz",
+ "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=",
+ "engines": {
+ "node": ">=0.8"
+ }
+ },
+ "node_modules/asynckit": {
+ "version": "0.4.0",
+ "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
+ "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k="
+ },
+ "node_modules/aws-sign2": {
+ "version": "0.7.0",
+ "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz",
+ "integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=",
+ "engines": {
+ "node": "*"
+ }
+ },
+ "node_modules/aws4": {
+ "version": "1.11.0",
+ "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.11.0.tgz",
+ "integrity": "sha512-xh1Rl34h6Fi1DC2WWKfxUTVqRsNnr6LsKz2+hfwDxQJWmrx8+c7ylaqBMcHfl1U1r2dsifOvKX3LQuLNZ+XSvA=="
+ },
+ "node_modules/bcrypt-pbkdf": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz",
+ "integrity": "sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4=",
+ "dependencies": {
+ "tweetnacl": "^0.14.3"
+ }
+ },
+ "node_modules/bluebird": {
+ "version": "3.7.2",
+ "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz",
+ "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg=="
+ },
+ "node_modules/caseless": {
+ "version": "0.12.0",
+ "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz",
+ "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw="
+ },
+ "node_modules/chalk": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz",
+ "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=",
+ "dependencies": {
+ "ansi-styles": "^2.2.1",
+ "escape-string-regexp": "^1.0.2",
+ "has-ansi": "^2.0.0",
+ "strip-ansi": "^3.0.0",
+ "supports-color": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/colors": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/colors/-/colors-1.4.0.tgz",
+ "integrity": "sha512-a+UqTh4kgZg/SlGvfbzDHpgRu7AAQOmmqRHJnxhRZICKFUT91brVhNNt58CMWU9PsBbv3PDCZUHbVxuDiH2mtA==",
+ "engines": {
+ "node": ">=0.1.90"
+ }
+ },
+ "node_modules/combined-stream": {
+ "version": "1.0.8",
+ "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz",
+ "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==",
+ "dependencies": {
+ "delayed-stream": "~1.0.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/dashdash": {
+ "version": "1.14.1",
+ "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz",
+ "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=",
+ "dependencies": {
+ "assert-plus": "^1.0.0"
+ },
+ "engines": {
+ "node": ">=0.10"
+ }
+ },
+ "node_modules/delayed-stream": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
+ "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=",
+ "engines": {
+ "node": ">=0.4.0"
+ }
+ },
+ "node_modules/ecc-jsbn": {
+ "version": "0.1.2",
+ "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz",
+ "integrity": "sha1-OoOpBOVDUyh4dMVkt1SThoSamMk=",
+ "dependencies": {
+ "jsbn": "~0.1.0",
+ "safer-buffer": "^2.1.0"
+ }
+ },
+ "node_modules/escape-string-regexp": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
+ "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=",
+ "engines": {
+ "node": ">=0.8.0"
+ }
+ },
+ "node_modules/extend": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz",
+ "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g=="
+ },
+ "node_modules/extsprintf": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz",
+ "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=",
+ "engines": [
+ "node >=0.6.0"
+ ]
+ },
+ "node_modules/fast-deep-equal": {
+ "version": "3.1.3",
+ "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
+ "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q=="
+ },
+ "node_modules/fast-json-stable-stringify": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz",
+ "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw=="
+ },
+ "node_modules/forever-agent": {
+ "version": "0.6.1",
+ "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz",
+ "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=",
+ "engines": {
+ "node": "*"
+ }
+ },
+ "node_modules/form-data": {
+ "version": "2.3.3",
+ "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz",
+ "integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==",
+ "dependencies": {
+ "asynckit": "^0.4.0",
+ "combined-stream": "^1.0.6",
+ "mime-types": "^2.1.12"
+ },
+ "engines": {
+ "node": ">= 0.12"
+ }
+ },
+ "node_modules/getpass": {
+ "version": "0.1.7",
+ "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz",
+ "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=",
+ "dependencies": {
+ "assert-plus": "^1.0.0"
+ }
+ },
+ "node_modules/har-schema": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz",
+ "integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=",
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/har-validator": {
+ "version": "5.1.5",
+ "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.5.tgz",
+ "integrity": "sha512-nmT2T0lljbxdQZfspsno9hgrG3Uir6Ks5afism62poxqBM6sDnMEuPmzTq8XN0OEwqKLLdh1jQI3qyE66Nzb3w==",
+ "deprecated": "this library is no longer supported",
+ "dependencies": {
+ "ajv": "^6.12.3",
+ "har-schema": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/has-ansi": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz",
+ "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=",
+ "dependencies": {
+ "ansi-regex": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/http-signature": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz",
+ "integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=",
+ "dependencies": {
+ "assert-plus": "^1.0.0",
+ "jsprim": "^1.2.2",
+ "sshpk": "^1.7.0"
+ },
+ "engines": {
+ "node": ">=0.8",
+ "npm": ">=1.3.7"
+ }
+ },
+ "node_modules/is-typedarray": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz",
+ "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo="
+ },
+ "node_modules/isstream": {
+ "version": "0.1.2",
+ "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz",
+ "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo="
+ },
+ "node_modules/jsbn": {
+ "version": "0.1.1",
+ "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz",
+ "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM="
+ },
+ "node_modules/json-schema": {
+ "version": "0.4.0",
+ "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.4.0.tgz",
+ "integrity": "sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA=="
+ },
+ "node_modules/json-schema-traverse": {
+ "version": "0.4.1",
+ "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz",
+ "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg=="
+ },
+ "node_modules/json-stringify-safe": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz",
+ "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus="
+ },
+ "node_modules/jsprim": {
+ "version": "1.4.2",
+ "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.2.tgz",
+ "integrity": "sha512-P2bSOMAc/ciLz6DzgjVlGJP9+BrJWu5UDGK70C2iweC5QBIeFf0ZXRvGjEj2uYgrY2MkAAhsSWHDWlFtEroZWw==",
+ "dependencies": {
+ "assert-plus": "1.0.0",
+ "extsprintf": "1.3.0",
+ "json-schema": "0.4.0",
+ "verror": "1.10.0"
+ },
+ "engines": {
+ "node": ">=0.6.0"
+ }
+ },
+ "node_modules/lru-cache": {
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz",
+ "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==",
+ "dependencies": {
+ "yallist": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/mime-db": {
+ "version": "1.51.0",
+ "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.51.0.tgz",
+ "integrity": "sha512-5y8A56jg7XVQx2mbv1lu49NR4dokRnhZYTtL+KGfaa27uq4pSTXkwQkFJl4pkRMyNFz/EtYDSkiiEHx3F7UN6g==",
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/mime-types": {
+ "version": "2.1.34",
+ "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.34.tgz",
+ "integrity": "sha512-6cP692WwGIs9XXdOO4++N+7qjqv0rqxxVvJ3VHPh/Sc9mVZcQP+ZGhkKiTvWMQRr2tbHkJP/Yn7Y0npb3ZBs4A==",
+ "dependencies": {
+ "mime-db": "1.51.0"
+ },
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/minimist": {
+ "version": "1.2.7",
+ "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.7.tgz",
+ "integrity": "sha512-bzfL1YUZsP41gmu/qjrEk0Q6i2ix/cVeAhbCbqH9u3zYutS1cLg00qhrD0M2MVdCcx4Sc0UpP2eBWo9rotpq6g==",
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/mwbot": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/mwbot/-/mwbot-2.0.0.tgz",
+ "integrity": "sha512-9iTx8oFMntC60yyaPJjN4GEgiQlal7i03jATu7kq5b9BGW5aNz7YbrpjaciLNr0Z33PTdQe0hRTJ0JdUJi2WQg==",
+ "dependencies": {
+ "bluebird": "^3.7.2",
+ "request": "^2.88.2",
+ "semlog": "^0.6.10",
+ "semver": "7.3.4"
+ },
+ "engines": {
+ "node": ">=10.0.0"
+ }
+ },
+ "node_modules/oauth-sign": {
+ "version": "0.9.0",
+ "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz",
+ "integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==",
+ "engines": {
+ "node": "*"
+ }
+ },
+ "node_modules/performance-now": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz",
+ "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns="
+ },
+ "node_modules/prettyjson": {
+ "version": "1.2.5",
+ "resolved": "https://registry.npmjs.org/prettyjson/-/prettyjson-1.2.5.tgz",
+ "integrity": "sha512-rksPWtoZb2ZpT5OVgtmy0KHVM+Dca3iVwWY9ifwhcexfjebtgjg3wmrUt9PvJ59XIYBcknQeYHD8IAnVlh9lAw==",
+ "dependencies": {
+ "colors": "1.4.0",
+ "minimist": "^1.2.0"
+ },
+ "bin": {
+ "prettyjson": "bin/prettyjson"
+ }
+ },
+ "node_modules/psl": {
+ "version": "1.8.0",
+ "resolved": "https://registry.npmjs.org/psl/-/psl-1.8.0.tgz",
+ "integrity": "sha512-RIdOzyoavK+hA18OGGWDqUTsCLhtA7IcZ/6NCs4fFJaHBDab+pDDmDIByWFRQJq2Cd7r1OoQxBGKOaztq+hjIQ=="
+ },
+ "node_modules/punycode": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz",
+ "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==",
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/qs": {
+ "version": "6.5.3",
+ "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.3.tgz",
+ "integrity": "sha512-qxXIEh4pCGfHICj1mAJQ2/2XVZkjCDTcEgfoSQxc/fYivUZxTkk7L3bDBJSoNrEzXI17oUO5Dp07ktqE5KzczA==",
+ "engines": {
+ "node": ">=0.6"
+ }
+ },
+ "node_modules/request": {
+ "version": "2.88.2",
+ "resolved": "https://registry.npmjs.org/request/-/request-2.88.2.tgz",
+ "integrity": "sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw==",
+ "deprecated": "request has been deprecated, see https://github.com/request/request/issues/3142",
+ "dependencies": {
+ "aws-sign2": "~0.7.0",
+ "aws4": "^1.8.0",
+ "caseless": "~0.12.0",
+ "combined-stream": "~1.0.6",
+ "extend": "~3.0.2",
+ "forever-agent": "~0.6.1",
+ "form-data": "~2.3.2",
+ "har-validator": "~5.1.3",
+ "http-signature": "~1.2.0",
+ "is-typedarray": "~1.0.0",
+ "isstream": "~0.1.2",
+ "json-stringify-safe": "~5.0.1",
+ "mime-types": "~2.1.19",
+ "oauth-sign": "~0.9.0",
+ "performance-now": "^2.1.0",
+ "qs": "~6.5.2",
+ "safe-buffer": "^5.1.2",
+ "tough-cookie": "~2.5.0",
+ "tunnel-agent": "^0.6.0",
+ "uuid": "^3.3.2"
+ },
+ "engines": {
+ "node": ">= 6"
+ }
+ },
+ "node_modules/safe-buffer": {
+ "version": "5.2.1",
+ "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz",
+ "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==",
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/feross"
+ },
+ {
+ "type": "patreon",
+ "url": "https://www.patreon.com/feross"
+ },
+ {
+ "type": "consulting",
+ "url": "https://feross.org/support"
+ }
+ ]
+ },
+ "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/semlog": {
+ "version": "0.6.10",
+ "resolved": "https://registry.npmjs.org/semlog/-/semlog-0.6.10.tgz",
+ "integrity": "sha1-DyJa6o6zwvJM6TWNhnjQ9Bp/4Fs=",
+ "dependencies": {
+ "chalk": "^1.1.3",
+ "prettyjson": "^1.1.3"
+ }
+ },
+ "node_modules/semver": {
+ "version": "7.3.4",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.4.tgz",
+ "integrity": "sha512-tCfb2WLjqFAtXn4KEdxIhalnRtoKFN7nAwj0B3ZXCbQloV2tq5eDbcTmT68JJD3nRJq24/XgxtQKFIpQdtvmVw==",
+ "dependencies": {
+ "lru-cache": "^6.0.0"
+ },
+ "bin": {
+ "semver": "bin/semver.js"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/sshpk": {
+ "version": "1.17.0",
+ "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.17.0.tgz",
+ "integrity": "sha512-/9HIEs1ZXGhSPE8X6Ccm7Nam1z8KcoCqPdI7ecm1N33EzAetWahvQWVqLZtaZQ+IDKX4IyA2o0gBzqIMkAagHQ==",
+ "dependencies": {
+ "asn1": "~0.2.3",
+ "assert-plus": "^1.0.0",
+ "bcrypt-pbkdf": "^1.0.0",
+ "dashdash": "^1.12.0",
+ "ecc-jsbn": "~0.1.1",
+ "getpass": "^0.1.1",
+ "jsbn": "~0.1.0",
+ "safer-buffer": "^2.0.2",
+ "tweetnacl": "~0.14.0"
+ },
+ "bin": {
+ "sshpk-conv": "bin/sshpk-conv",
+ "sshpk-sign": "bin/sshpk-sign",
+ "sshpk-verify": "bin/sshpk-verify"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/strip-ansi": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz",
+ "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=",
+ "dependencies": {
+ "ansi-regex": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/supports-color": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz",
+ "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=",
+ "engines": {
+ "node": ">=0.8.0"
+ }
+ },
+ "node_modules/tough-cookie": {
+ "version": "2.5.0",
+ "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.5.0.tgz",
+ "integrity": "sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g==",
+ "dependencies": {
+ "psl": "^1.1.28",
+ "punycode": "^2.1.1"
+ },
+ "engines": {
+ "node": ">=0.8"
+ }
+ },
+ "node_modules/tunnel-agent": {
+ "version": "0.6.0",
+ "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz",
+ "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=",
+ "dependencies": {
+ "safe-buffer": "^5.0.1"
+ },
+ "engines": {
+ "node": "*"
+ }
+ },
+ "node_modules/tweetnacl": {
+ "version": "0.14.5",
+ "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz",
+ "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q="
+ },
+ "node_modules/uri-js": {
+ "version": "4.4.1",
+ "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz",
+ "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==",
+ "dependencies": {
+ "punycode": "^2.1.0"
+ }
+ },
+ "node_modules/uuid": {
+ "version": "3.4.0",
+ "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz",
+ "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==",
+ "deprecated": "Please upgrade to version 7 or higher. Older versions may use Math.random() in certain circumstances, which is known to be problematic. See https://v8.dev/blog/math-random for details.",
+ "bin": {
+ "uuid": "bin/uuid"
+ }
+ },
+ "node_modules/verror": {
+ "version": "1.10.0",
+ "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz",
+ "integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=",
+ "engines": [
+ "node >=0.6.0"
+ ],
+ "dependencies": {
+ "assert-plus": "^1.0.0",
+ "core-util-is": "1.0.2",
+ "extsprintf": "^1.2.0"
+ }
+ },
+ "node_modules/yallist": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
+ "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A=="
+ }
+ },
+ "dependencies": {
+ "ajv": {
+ "version": "6.12.6",
+ "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz",
+ "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==",
+ "requires": {
+ "fast-deep-equal": "^3.1.1",
+ "fast-json-stable-stringify": "^2.0.0",
+ "json-schema-traverse": "^0.4.1",
+ "uri-js": "^4.2.2"
+ }
+ },
+ "ansi-regex": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz",
+ "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8="
+ },
+ "ansi-styles": {
+ "version": "2.2.1",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz",
+ "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4="
+ },
+ "asn1": {
+ "version": "0.2.6",
+ "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.6.tgz",
+ "integrity": "sha512-ix/FxPn0MDjeyJ7i/yoHGFt/EX6LyNbxSEhPPXODPL+KB0VPk86UYfL0lMdy+KCnv+fmvIzySwaK5COwqVbWTQ==",
+ "requires": {
+ "safer-buffer": "~2.1.0"
+ }
+ },
+ "assert-plus": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz",
+ "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU="
+ },
+ "asynckit": {
+ "version": "0.4.0",
+ "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
+ "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k="
+ },
+ "aws-sign2": {
+ "version": "0.7.0",
+ "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz",
+ "integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg="
+ },
+ "aws4": {
+ "version": "1.11.0",
+ "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.11.0.tgz",
+ "integrity": "sha512-xh1Rl34h6Fi1DC2WWKfxUTVqRsNnr6LsKz2+hfwDxQJWmrx8+c7ylaqBMcHfl1U1r2dsifOvKX3LQuLNZ+XSvA=="
+ },
+ "bcrypt-pbkdf": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz",
+ "integrity": "sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4=",
+ "requires": {
+ "tweetnacl": "^0.14.3"
+ }
+ },
+ "bluebird": {
+ "version": "3.7.2",
+ "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz",
+ "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg=="
+ },
+ "caseless": {
+ "version": "0.12.0",
+ "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz",
+ "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw="
+ },
+ "chalk": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz",
+ "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=",
+ "requires": {
+ "ansi-styles": "^2.2.1",
+ "escape-string-regexp": "^1.0.2",
+ "has-ansi": "^2.0.0",
+ "strip-ansi": "^3.0.0",
+ "supports-color": "^2.0.0"
+ }
+ },
+ "colors": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/colors/-/colors-1.4.0.tgz",
+ "integrity": "sha512-a+UqTh4kgZg/SlGvfbzDHpgRu7AAQOmmqRHJnxhRZICKFUT91brVhNNt58CMWU9PsBbv3PDCZUHbVxuDiH2mtA=="
+ },
+ "combined-stream": {
+ "version": "1.0.8",
+ "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz",
+ "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==",
+ "requires": {
+ "delayed-stream": "~1.0.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="
+ },
+ "dashdash": {
+ "version": "1.14.1",
+ "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz",
+ "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=",
+ "requires": {
+ "assert-plus": "^1.0.0"
+ }
+ },
+ "delayed-stream": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
+ "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk="
+ },
+ "ecc-jsbn": {
+ "version": "0.1.2",
+ "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz",
+ "integrity": "sha1-OoOpBOVDUyh4dMVkt1SThoSamMk=",
+ "requires": {
+ "jsbn": "~0.1.0",
+ "safer-buffer": "^2.1.0"
+ }
+ },
+ "escape-string-regexp": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
+ "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ="
+ },
+ "extend": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz",
+ "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g=="
+ },
+ "extsprintf": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz",
+ "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU="
+ },
+ "fast-deep-equal": {
+ "version": "3.1.3",
+ "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
+ "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q=="
+ },
+ "fast-json-stable-stringify": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz",
+ "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw=="
+ },
+ "forever-agent": {
+ "version": "0.6.1",
+ "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz",
+ "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE="
+ },
+ "form-data": {
+ "version": "2.3.3",
+ "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz",
+ "integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==",
+ "requires": {
+ "asynckit": "^0.4.0",
+ "combined-stream": "^1.0.6",
+ "mime-types": "^2.1.12"
+ }
+ },
+ "getpass": {
+ "version": "0.1.7",
+ "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz",
+ "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=",
+ "requires": {
+ "assert-plus": "^1.0.0"
+ }
+ },
+ "har-schema": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz",
+ "integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI="
+ },
+ "har-validator": {
+ "version": "5.1.5",
+ "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.5.tgz",
+ "integrity": "sha512-nmT2T0lljbxdQZfspsno9hgrG3Uir6Ks5afism62poxqBM6sDnMEuPmzTq8XN0OEwqKLLdh1jQI3qyE66Nzb3w==",
+ "requires": {
+ "ajv": "^6.12.3",
+ "har-schema": "^2.0.0"
+ }
+ },
+ "has-ansi": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz",
+ "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=",
+ "requires": {
+ "ansi-regex": "^2.0.0"
+ }
+ },
+ "http-signature": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz",
+ "integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=",
+ "requires": {
+ "assert-plus": "^1.0.0",
+ "jsprim": "^1.2.2",
+ "sshpk": "^1.7.0"
+ }
+ },
+ "is-typedarray": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz",
+ "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo="
+ },
+ "isstream": {
+ "version": "0.1.2",
+ "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz",
+ "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo="
+ },
+ "jsbn": {
+ "version": "0.1.1",
+ "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz",
+ "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM="
+ },
+ "json-schema": {
+ "version": "0.4.0",
+ "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.4.0.tgz",
+ "integrity": "sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA=="
+ },
+ "json-schema-traverse": {
+ "version": "0.4.1",
+ "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz",
+ "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg=="
+ },
+ "json-stringify-safe": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz",
+ "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus="
+ },
+ "jsprim": {
+ "version": "1.4.2",
+ "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.2.tgz",
+ "integrity": "sha512-P2bSOMAc/ciLz6DzgjVlGJP9+BrJWu5UDGK70C2iweC5QBIeFf0ZXRvGjEj2uYgrY2MkAAhsSWHDWlFtEroZWw==",
+ "requires": {
+ "assert-plus": "1.0.0",
+ "extsprintf": "1.3.0",
+ "json-schema": "0.4.0",
+ "verror": "1.10.0"
+ }
+ },
+ "lru-cache": {
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz",
+ "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==",
+ "requires": {
+ "yallist": "^4.0.0"
+ }
+ },
+ "mime-db": {
+ "version": "1.51.0",
+ "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.51.0.tgz",
+ "integrity": "sha512-5y8A56jg7XVQx2mbv1lu49NR4dokRnhZYTtL+KGfaa27uq4pSTXkwQkFJl4pkRMyNFz/EtYDSkiiEHx3F7UN6g=="
+ },
+ "mime-types": {
+ "version": "2.1.34",
+ "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.34.tgz",
+ "integrity": "sha512-6cP692WwGIs9XXdOO4++N+7qjqv0rqxxVvJ3VHPh/Sc9mVZcQP+ZGhkKiTvWMQRr2tbHkJP/Yn7Y0npb3ZBs4A==",
+ "requires": {
+ "mime-db": "1.51.0"
+ }
+ },
+ "minimist": {
+ "version": "1.2.7",
+ "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.7.tgz",
+ "integrity": "sha512-bzfL1YUZsP41gmu/qjrEk0Q6i2ix/cVeAhbCbqH9u3zYutS1cLg00qhrD0M2MVdCcx4Sc0UpP2eBWo9rotpq6g=="
+ },
+ "mwbot": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/mwbot/-/mwbot-2.0.0.tgz",
+ "integrity": "sha512-9iTx8oFMntC60yyaPJjN4GEgiQlal7i03jATu7kq5b9BGW5aNz7YbrpjaciLNr0Z33PTdQe0hRTJ0JdUJi2WQg==",
+ "requires": {
+ "bluebird": "^3.7.2",
+ "request": "^2.88.2",
+ "semlog": "^0.6.10",
+ "semver": "7.3.4"
+ }
+ },
+ "oauth-sign": {
+ "version": "0.9.0",
+ "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz",
+ "integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ=="
+ },
+ "performance-now": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz",
+ "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns="
+ },
+ "prettyjson": {
+ "version": "1.2.5",
+ "resolved": "https://registry.npmjs.org/prettyjson/-/prettyjson-1.2.5.tgz",
+ "integrity": "sha512-rksPWtoZb2ZpT5OVgtmy0KHVM+Dca3iVwWY9ifwhcexfjebtgjg3wmrUt9PvJ59XIYBcknQeYHD8IAnVlh9lAw==",
+ "requires": {
+ "colors": "1.4.0",
+ "minimist": "^1.2.0"
+ }
+ },
+ "psl": {
+ "version": "1.8.0",
+ "resolved": "https://registry.npmjs.org/psl/-/psl-1.8.0.tgz",
+ "integrity": "sha512-RIdOzyoavK+hA18OGGWDqUTsCLhtA7IcZ/6NCs4fFJaHBDab+pDDmDIByWFRQJq2Cd7r1OoQxBGKOaztq+hjIQ=="
+ },
+ "punycode": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz",
+ "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A=="
+ },
+ "qs": {
+ "version": "6.5.3",
+ "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.3.tgz",
+ "integrity": "sha512-qxXIEh4pCGfHICj1mAJQ2/2XVZkjCDTcEgfoSQxc/fYivUZxTkk7L3bDBJSoNrEzXI17oUO5Dp07ktqE5KzczA=="
+ },
+ "request": {
+ "version": "2.88.2",
+ "resolved": "https://registry.npmjs.org/request/-/request-2.88.2.tgz",
+ "integrity": "sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw==",
+ "requires": {
+ "aws-sign2": "~0.7.0",
+ "aws4": "^1.8.0",
+ "caseless": "~0.12.0",
+ "combined-stream": "~1.0.6",
+ "extend": "~3.0.2",
+ "forever-agent": "~0.6.1",
+ "form-data": "~2.3.2",
+ "har-validator": "~5.1.3",
+ "http-signature": "~1.2.0",
+ "is-typedarray": "~1.0.0",
+ "isstream": "~0.1.2",
+ "json-stringify-safe": "~5.0.1",
+ "mime-types": "~2.1.19",
+ "oauth-sign": "~0.9.0",
+ "performance-now": "^2.1.0",
+ "qs": "~6.5.2",
+ "safe-buffer": "^5.1.2",
+ "tough-cookie": "~2.5.0",
+ "tunnel-agent": "^0.6.0",
+ "uuid": "^3.3.2"
+ }
+ },
+ "safe-buffer": {
+ "version": "5.2.1",
+ "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz",
+ "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ=="
+ },
+ "safer-buffer": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
+ "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="
+ },
+ "semlog": {
+ "version": "0.6.10",
+ "resolved": "https://registry.npmjs.org/semlog/-/semlog-0.6.10.tgz",
+ "integrity": "sha1-DyJa6o6zwvJM6TWNhnjQ9Bp/4Fs=",
+ "requires": {
+ "chalk": "^1.1.3",
+ "prettyjson": "^1.1.3"
+ }
+ },
+ "semver": {
+ "version": "7.3.4",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.4.tgz",
+ "integrity": "sha512-tCfb2WLjqFAtXn4KEdxIhalnRtoKFN7nAwj0B3ZXCbQloV2tq5eDbcTmT68JJD3nRJq24/XgxtQKFIpQdtvmVw==",
+ "requires": {
+ "lru-cache": "^6.0.0"
+ }
+ },
+ "sshpk": {
+ "version": "1.17.0",
+ "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.17.0.tgz",
+ "integrity": "sha512-/9HIEs1ZXGhSPE8X6Ccm7Nam1z8KcoCqPdI7ecm1N33EzAetWahvQWVqLZtaZQ+IDKX4IyA2o0gBzqIMkAagHQ==",
+ "requires": {
+ "asn1": "~0.2.3",
+ "assert-plus": "^1.0.0",
+ "bcrypt-pbkdf": "^1.0.0",
+ "dashdash": "^1.12.0",
+ "ecc-jsbn": "~0.1.1",
+ "getpass": "^0.1.1",
+ "jsbn": "~0.1.0",
+ "safer-buffer": "^2.0.2",
+ "tweetnacl": "~0.14.0"
+ }
+ },
+ "strip-ansi": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz",
+ "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=",
+ "requires": {
+ "ansi-regex": "^2.0.0"
+ }
+ },
+ "supports-color": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz",
+ "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc="
+ },
+ "tough-cookie": {
+ "version": "2.5.0",
+ "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.5.0.tgz",
+ "integrity": "sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g==",
+ "requires": {
+ "psl": "^1.1.28",
+ "punycode": "^2.1.1"
+ }
+ },
+ "tunnel-agent": {
+ "version": "0.6.0",
+ "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz",
+ "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=",
+ "requires": {
+ "safe-buffer": "^5.0.1"
+ }
+ },
+ "tweetnacl": {
+ "version": "0.14.5",
+ "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz",
+ "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q="
+ },
+ "uri-js": {
+ "version": "4.4.1",
+ "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz",
+ "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==",
+ "requires": {
+ "punycode": "^2.1.0"
+ }
+ },
+ "uuid": {
+ "version": "3.4.0",
+ "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz",
+ "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A=="
+ },
+ "verror": {
+ "version": "1.10.0",
+ "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz",
+ "integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=",
+ "requires": {
+ "assert-plus": "^1.0.0",
+ "core-util-is": "1.0.2",
+ "extsprintf": "^1.2.0"
+ }
+ },
+ "yallist": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
+ "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A=="
+ }
+ }
+}
diff --git a/tools/autowiki/package.json b/tools/autowiki/package.json
new file mode 100644
index 000000000000..39ac2bc7d5d6
--- /dev/null
+++ b/tools/autowiki/package.json
@@ -0,0 +1,10 @@
+{
+ "name": "autowiki",
+ "version": "1.0.0",
+ "description": "Automatically publish generated pages to the tg wiki",
+ "main": "autowiki.js",
+ "author": "Mothblocks",
+ "dependencies": {
+ "mwbot": "^2.0.0"
+ }
+}
From e7e86c4451d96ac8999071e0d6e536c4e09ebb21 Mon Sep 17 00:00:00 2001
From: harryob <55142896+harryob@users.noreply.github.com>
Date: Fri, 4 Aug 2023 15:33:04 +0100
Subject: [PATCH 2/4] added mothblocks unit test
---
code/modules/unit_tests/_unit_tests.dm | 1 +
code/modules/unit_tests/autowiki.dm | 35 ++++++++++++++++++++++++++
2 files changed, 36 insertions(+)
create mode 100644 code/modules/unit_tests/autowiki.dm
diff --git a/code/modules/unit_tests/_unit_tests.dm b/code/modules/unit_tests/_unit_tests.dm
index 7e620b6bc1fa..9ed3183e5b3d 100644
--- a/code/modules/unit_tests/_unit_tests.dm
+++ b/code/modules/unit_tests/_unit_tests.dm
@@ -74,6 +74,7 @@
/// A trait source when adding traits through unit tests
#define TRAIT_SOURCE_UNIT_TESTS "unit_tests"
+#include "autowiki.dm"
#include "create_and_destroy.dm"
#include "focus_only_tests.dm"
#include "missing_icons.dm"
diff --git a/code/modules/unit_tests/autowiki.dm b/code/modules/unit_tests/autowiki.dm
new file mode 100644
index 000000000000..65ec2e228dd2
--- /dev/null
+++ b/code/modules/unit_tests/autowiki.dm
@@ -0,0 +1,35 @@
+/// Tests that all autowikis generate something without runtiming
+/datum/unit_test/autowiki
+
+/datum/unit_test/autowiki/Run()
+ TEST_ASSERT(istext(generate_autowiki_output()), "generate_autowiki_output() did not finish successfully!")
+
+/// Test that `include_template` produces reasonable results
+/datum/unit_test/autowiki_include_template
+
+/datum/unit_test/autowiki_include_template/Run()
+ var/datum/autowiki/autowiki_api = new
+
+ TEST_ASSERT_EQUAL( \
+ autowiki_api.include_template("Template"), \
+ "{{Template}}", \
+ "Basic template did not format correctly" \
+ )
+
+ TEST_ASSERT_EQUAL( \
+ autowiki_api.include_template("Template", list("name" = "Mothblocks")), \
+ "{{Template|name=Mothblocks}}", \
+ "Template with basic arguments did not format correctly" \
+ )
+
+ TEST_ASSERT_EQUAL( \
+ autowiki_api.include_template("Template", list("name" = autowiki_api.escape_value("P|peline"))), \
+ "{{Template|name=P{{!}}peline}}", \
+ "Template with escaped arguments did not format correctly" \
+ )
+
+ TEST_ASSERT_EQUAL( \
+ autowiki_api.include_template("Template", list("food" = list("fruit", "candy"))), \
+ "{{Template|food1=fruit|food2=candy}}", \
+ "Template with array arguments did not format correctly" \
+ )
From a71b91a73ec36476d3321eef947e317bed40ce5d Mon Sep 17 00:00:00 2001
From: harryob <55142896+harryob@users.noreply.github.com>
Date: Fri, 4 Aug 2023 15:39:10 +0100
Subject: [PATCH 3/4] =?UTF-8?q?hehe,,,=20no=20i=20didn't=20=F0=9F=A4=AD?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
code/_compile_options.dm | 2 --
1 file changed, 2 deletions(-)
diff --git a/code/_compile_options.dm b/code/_compile_options.dm
index 09ec3429daf3..0f81b0173ac1 100644
--- a/code/_compile_options.dm
+++ b/code/_compile_options.dm
@@ -41,5 +41,3 @@
// #define TESTING
// #define REFERENCE_TRACKING
// #define GC_FAILURE_HARD_LOOKUP
-
-#define AUTOWIKI
From de5dbd47e34c373354ecb651d196bdd9866368ab Mon Sep 17 00:00:00 2001
From: harryob <55142896+harryob@users.noreply.github.com>
Date: Fri, 4 Aug 2023 16:30:41 +0100
Subject: [PATCH 4/4] updates the api url
---
tools/autowiki/autowiki.js | 90 ++++++++++++++++++++------------------
1 file changed, 48 insertions(+), 42 deletions(-)
diff --git a/tools/autowiki/autowiki.js b/tools/autowiki/autowiki.js
index 8b5c5fc9f00a..a9a2ab29eb1f 100644
--- a/tools/autowiki/autowiki.js
+++ b/tools/autowiki/autowiki.js
@@ -1,83 +1,89 @@
-const fs = require("fs").promises
-const MWBot = require("mwbot")
+const fs = require("fs").promises;
+const MWBot = require("mwbot");
-const { USERNAME, PASSWORD } = process.env
+const { USERNAME, PASSWORD } = process.env;
if (!USERNAME) {
- console.error("USERNAME was not set.")
- process.exit(1)
+ console.error("USERNAME was not set.");
+ process.exit(1);
}
if (!PASSWORD) {
- console.error("PASSWORD was not set.")
- process.exit(1)
+ console.error("PASSWORD was not set.");
+ process.exit(1);
}
-const PAGE_EDIT_FILENAME = process.argv[2]
+const PAGE_EDIT_FILENAME = process.argv[2];
if (!PAGE_EDIT_FILENAME) {
- console.error("No filename specified to edit pages")
- process.exit(1)
+ console.error("No filename specified to edit pages");
+ process.exit(1);
}
-const FILE_EDIT_FILENAME = process.argv[3]
+const FILE_EDIT_FILENAME = process.argv[3];
if (!FILE_EDIT_FILENAME) {
- console.error("No filename specified to edit files")
- process.exit(1)
+ console.error("No filename specified to edit files");
+ process.exit(1);
}
async function main() {
- console.log(`Reading from ${PAGE_EDIT_FILENAME}`)
- const editFile = await (await fs.readFile(PAGE_EDIT_FILENAME, "utf8")).split("\n")
+ console.log(`Reading from ${PAGE_EDIT_FILENAME}`);
+ const editFile = await (
+ await fs.readFile(PAGE_EDIT_FILENAME, "utf8")
+ ).split("\n");
- console.log(`Logging in as ${USERNAME}`)
+ console.log(`Logging in as ${USERNAME}`);
- const bot = new MWBot()
+ const bot = new MWBot();
await bot.loginGetEditToken({
- apiUrl: "https://tgstation13.org/wiki/api.php",
+ apiUrl: "https://cm-ss13.com/w/api.php",
username: USERNAME,
password: PASSWORD,
- })
+ });
- console.log("Logged in")
+ console.log("Logged in");
// This is not Promise.all as to not flood with a bunch of traffic at once
for (const editLine of editFile) {
if (editLine.length === 0) {
- continue
+ continue;
}
- let { title, text } = JSON.parse(editLine)
- text = "This page is automated by Autowiki. Do NOT edit it manually." + text
+ let { title, text } = JSON.parse(editLine);
+ text =
+ "This page is automated by Autowiki. Do NOT edit it manually." +
+ text;
- console.log(`Editing ${title}...`)
+ console.log(`Editing ${title}...`);
await bot.edit(
title,
text,
- `Autowiki edit @ ${ new Date().toISOString() }`,
- )
+ `Autowiki edit @ ${new Date().toISOString()}`
+ );
}
// Same here
for (const asset of await fs.readdir(FILE_EDIT_FILENAME)) {
- const assetPath = `${FILE_EDIT_FILENAME}/${asset}`
- const assetName = `Autowiki-${asset}`
-
- console.log(`Replacing ${assetName}...`)
- await bot.upload(
- assetName,
- assetPath,
- `Autowiki upload @ ${ new Date().toISOString() }`,
- ).catch(error => {
- if (error.code === "fileexists-no-change") {
- console.log(`${assetName} is an exact duplicate`)
- } else {
- return Promise.reject(error)
- }
- })
+ const assetPath = `${FILE_EDIT_FILENAME}/${asset}`;
+ const assetName = `Autowiki-${asset}`;
+
+ console.log(`Replacing ${assetName}...`);
+ await bot
+ .upload(
+ assetName,
+ assetPath,
+ `Autowiki upload @ ${new Date().toISOString()}`
+ )
+ .catch((error) => {
+ if (error.code === "fileexists-no-change") {
+ console.log(`${assetName} is an exact duplicate`);
+ } else {
+ return Promise.reject(error);
+ }
+ });
}
}
-main().catch(console.error)
+main().catch(console.error);