diff --git a/admin/bando/Bandolier.svelte b/admin/bando/Bandolier.svelte
index 6b3057c..ed40434 100644
--- a/admin/bando/Bandolier.svelte
+++ b/admin/bando/Bandolier.svelte
@@ -109,7 +109,13 @@
{#each errors as error, i}
- - { error.location.file}
+ {#if error.location}
+ - { error.location.file}
+ {:else if error.filename}
+ - { error.filename }
+ {:else}
+ - Weird error, check console.
+ {/if}
{/each}
diff --git a/admin/pages/Errors.svelte b/admin/pages/Errors.svelte
index d2c703a..e9008c3 100644
--- a/admin/pages/Errors.svelte
+++ b/admin/pages/Errors.svelte
@@ -66,7 +66,7 @@
{#each errors as error}
- error_selected = error }>{ error.location.file}
+ error_selected = error }>{ error.location ? error.location.file : error.filename}
{:else}
No Errors
You currently have no errors that are shown. Try refreshing.
@@ -75,7 +75,8 @@
- {#if error_selected}
+ {#if error_selected}
+ {#if error_selected.location}
{error_selected.location.file}
{ error_selected.text }
@@ -96,7 +97,17 @@
{/each}
- {/if}
+ {:else if error_selected.filename}
+ {error_selected.filename}
+ { error_selected.message }
+ {error_selected.code}
+
+ Stack
+ { error_selected.stack }
+ {:else}
+ Unknown error I've never seen before. Look in console and in `debug/` for error output files.
+ {/if}
+ {/if}
{/await}
diff --git a/commands/indexnow.js b/commands/indexnow.js
new file mode 100644
index 0000000..6e3e368
--- /dev/null
+++ b/commands/indexnow.js
@@ -0,0 +1,71 @@
+// you may not need all of these but they come up a lot
+import fs from "fs";
+import logging from '../lib/logging.js';
+import { og_base_host } from "../client/config.js";
+import axios from "axios";
+import crypto from "crypto";
+import { glob, write } from "../lib/builderator.js";
+
+const log = logging.create(import.meta.url);
+
+const KEY_SIZE = 32;
+const DEFAULT_ENGINE = "https://yandex.com";
+
+export const description = "Uses IndexNow.org to submit your site for reindex. You'll need to configure your IndexNow.org account before doing this."
+
+// your command uses the npm package commander's options format
+export const options = [
+ ["--gen-key", "If you don't have a key this will generate one."],
+ ["--key-size ", "Key size to use with --gen-key", KEY_SIZE],
+ ["--key ", "key to use"],
+ ["--url ", "URL to submit", og_base_host],
+ ["--key-path ", "Path to where the [key].txt should be stored. Command will ensure it's there or create it if not."],
+ ["--search-engine ", "Company to notify, they're required to tell others.", DEFAULT_ENGINE],
+]
+
+const random_hex = (size) => {
+ return crypto.randomBytes(size).toString("hex");
+}
+
+// handy function for checking things are good and aborting
+const check = (test, fail_message) => {
+ if(!test) {
+ log.error(fail_message);
+ process.exit(1);
+ }
+}
+
+export const main = async (opts) => {
+ if(opts.genKey) {
+ console.log(random_hex(parseInt(opts.keySize, 10)));
+ } else {
+ check(opts.key, "--key is required.");
+ check(opts.url, "--url is required.");
+
+ const keyfile = `${opts.keyPath}/${opts.key}.txt`;
+
+ // confirm the key file is in the right place
+ if(opts.keyPath && !fs.existsSync(keyfile)) {
+ console.log("WRITING KEY FILE", keyfile);
+ write(keyfile, opts.key);
+ }
+
+ const in_url = `${opts.searchEngine}/indexnow`;
+
+ const request = {
+ method: 'get', url: in_url,
+ data: { url: opts.url, key: opts.key}
+ };
+
+ try {
+ const result = await axios(request);
+
+ console.log("STATUS", result.status, "TEXT", result.statusText);
+ } catch(error) {
+ console.error(error.message, "REQUEST", request);
+ process.exit(1);
+ }
+ }
+
+ process.exit(0);
+}
diff --git a/static/djenterator/command.js b/static/djenterator/command.js
index c41fa51..93ad646 100644
--- a/static/djenterator/command.js
+++ b/static/djenterator/command.js
@@ -32,6 +32,16 @@ const check = (test, fail_message) => {
}
}
+/*
+ + FOOTGUN: commander tries to be "fancy" and if you don't have
+ an `arguments` setting for positional arguments then you
+ have to change this to `(opts)` instead of `(arg, opts)`.
+ The reason is if your command doesn't have an argument, then
+ commander will call your main with only opts, and if it does
+ then it calls your main with arg, and opts. If you get weird
+ errors and `opts` looks like a `Command` object then this is
+ what happened.
+ */
export const main = async (arg, opts) => {
// if they give an numeric option this is how you can convert it
// yes, this is annoying and commander should handle it but oh well