@geekity/cms 0.8.0 → 0.10.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +344 -47
- package/admin/components/admin-bar.njk +26 -0
- package/admin/components/public-admin-bar.njk +41 -0
- package/admin/layouts/base.njk +1 -0
- package/admin/layouts/shell.njk +8 -19
- package/admin/pages/comments/all.njk +3 -0
- package/admin/pages/settings/discussion.njk +53 -0
- package/admin/pages/settings/email.njk +20 -0
- package/admin/pages/tools/personal-data.njk +67 -0
- package/admin/pages/users/edit.njk +1 -1
- package/admin/static/admin-bar.css +137 -0
- package/admin/static/admin.css +1 -102
- package/dist/admin/comments.d.ts +5 -0
- package/dist/admin/comments.d.ts.map +1 -1
- package/dist/admin/comments.js +15 -1
- package/dist/admin/comments.js.map +1 -1
- package/dist/admin/headers.d.ts +14 -5
- package/dist/admin/headers.d.ts.map +1 -1
- package/dist/admin/headers.js +18 -6
- package/dist/admin/headers.js.map +1 -1
- package/dist/admin/index.d.ts +2 -2
- package/dist/admin/index.d.ts.map +1 -1
- package/dist/admin/index.js +1 -1
- package/dist/admin/index.js.map +1 -1
- package/dist/admin/menu.d.ts.map +1 -1
- package/dist/admin/menu.js +5 -1
- package/dist/admin/menu.js.map +1 -1
- package/dist/admin/personal-data.d.ts +35 -0
- package/dist/admin/personal-data.d.ts.map +1 -0
- package/dist/admin/personal-data.js +94 -0
- package/dist/admin/personal-data.js.map +1 -0
- package/dist/admin/preview.d.ts.map +1 -1
- package/dist/admin/preview.js +1 -1
- package/dist/admin/preview.js.map +1 -1
- package/dist/admin/routes.d.ts.map +1 -1
- package/dist/admin/routes.js +20 -3
- package/dist/admin/routes.js.map +1 -1
- package/dist/admin/session.d.ts +42 -1
- package/dist/admin/session.d.ts.map +1 -1
- package/dist/admin/session.js +74 -4
- package/dist/admin/session.js.map +1 -1
- package/dist/admin/settings-discussion.d.ts.map +1 -1
- package/dist/admin/settings-discussion.js +9 -1
- package/dist/admin/settings-discussion.js.map +1 -1
- package/dist/admin/settings-email.d.ts.map +1 -1
- package/dist/admin/settings-email.js +10 -1
- package/dist/admin/settings-email.js.map +1 -1
- package/dist/admin/settings.d.ts +39 -0
- package/dist/admin/settings.d.ts.map +1 -1
- package/dist/admin/settings.js +144 -0
- package/dist/admin/settings.js.map +1 -1
- package/dist/admin/store.d.ts +65 -0
- package/dist/admin/store.d.ts.map +1 -1
- package/dist/admin/store.js +130 -5
- package/dist/admin/store.js.map +1 -1
- package/dist/admin/templates.d.ts +2 -0
- package/dist/admin/templates.d.ts.map +1 -1
- package/dist/admin/templates.js +2 -0
- package/dist/admin/templates.js.map +1 -1
- package/dist/admin/tools.d.ts +2 -0
- package/dist/admin/tools.d.ts.map +1 -1
- package/dist/admin/tools.js +3 -2
- package/dist/admin/tools.js.map +1 -1
- package/dist/avatars/avatars.d.ts +112 -0
- package/dist/avatars/avatars.d.ts.map +1 -0
- package/dist/avatars/avatars.js +259 -0
- package/dist/avatars/avatars.js.map +1 -0
- package/dist/avatars/index.d.ts +4 -0
- package/dist/avatars/index.d.ts.map +1 -0
- package/dist/avatars/index.js +3 -0
- package/dist/avatars/index.js.map +1 -0
- package/dist/avatars/routes.d.ts +11 -0
- package/dist/avatars/routes.d.ts.map +1 -0
- package/dist/avatars/routes.js +33 -0
- package/dist/avatars/routes.js.map +1 -0
- package/dist/comments/index.d.ts +2 -2
- package/dist/comments/index.d.ts.map +1 -1
- package/dist/comments/index.js +1 -1
- package/dist/comments/index.js.map +1 -1
- package/dist/comments/records.d.ts +58 -2
- package/dist/comments/records.d.ts.map +1 -1
- package/dist/comments/records.js +244 -47
- package/dist/comments/records.js.map +1 -1
- package/dist/comments/routes.d.ts.map +1 -1
- package/dist/comments/routes.js +8 -2
- package/dist/comments/routes.js.map +1 -1
- package/dist/comments/viewer.d.ts +13 -0
- package/dist/comments/viewer.d.ts.map +1 -1
- package/dist/comments/viewer.js +13 -1
- package/dist/comments/viewer.js.map +1 -1
- package/dist/config.d.ts +35 -0
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +58 -0
- package/dist/config.js.map +1 -1
- package/dist/contact/index.d.ts +1 -1
- package/dist/contact/index.d.ts.map +1 -1
- package/dist/contact/index.js +1 -1
- package/dist/contact/index.js.map +1 -1
- package/dist/contact/records.d.ts +8 -2
- package/dist/contact/records.d.ts.map +1 -1
- package/dist/contact/records.js +13 -6
- package/dist/contact/records.js.map +1 -1
- package/dist/env.d.ts +25 -0
- package/dist/env.d.ts.map +1 -1
- package/dist/federation/delivery.d.ts +3 -1
- package/dist/federation/delivery.d.ts.map +1 -1
- package/dist/federation/delivery.js +6 -1
- package/dist/federation/delivery.js.map +1 -1
- package/dist/federation/federation.d.ts +3 -0
- package/dist/federation/federation.d.ts.map +1 -1
- package/dist/federation/federation.js.map +1 -1
- package/dist/federation/inbox.d.ts +7 -5
- package/dist/federation/inbox.d.ts.map +1 -1
- package/dist/federation/inbox.js +15 -32
- package/dist/federation/inbox.js.map +1 -1
- package/dist/federation/index.d.ts +2 -0
- package/dist/federation/index.d.ts.map +1 -1
- package/dist/federation/index.js +1 -0
- package/dist/federation/index.js.map +1 -1
- package/dist/federation/mount.js +6 -1
- package/dist/federation/mount.js.map +1 -1
- package/dist/federation/profiles.d.ts +95 -0
- package/dist/federation/profiles.d.ts.map +1 -0
- package/dist/federation/profiles.js +171 -0
- package/dist/federation/profiles.js.map +1 -0
- package/dist/federation/quotes.d.ts +2 -0
- package/dist/federation/quotes.d.ts.map +1 -1
- package/dist/federation/quotes.js +4 -0
- package/dist/federation/quotes.js.map +1 -1
- package/dist/federation/relays.d.ts +3 -1
- package/dist/federation/relays.d.ts.map +1 -1
- package/dist/federation/relays.js +6 -1
- package/dist/federation/relays.js.map +1 -1
- package/dist/federation/replies.d.ts +36 -4
- package/dist/federation/replies.d.ts.map +1 -1
- package/dist/federation/replies.js +71 -15
- package/dist/federation/replies.js.map +1 -1
- package/dist/images/icons.d.ts.map +1 -1
- package/dist/images/icons.js +3 -2
- package/dist/images/icons.js.map +1 -1
- package/dist/images/index.d.ts +2 -2
- package/dist/images/index.d.ts.map +1 -1
- package/dist/images/markup.d.ts +15 -4
- package/dist/images/markup.d.ts.map +1 -1
- package/dist/images/markup.js +24 -15
- package/dist/images/markup.js.map +1 -1
- package/dist/images/paths.d.ts +11 -0
- package/dist/images/paths.d.ts.map +1 -1
- package/dist/images/paths.js +17 -1
- package/dist/images/paths.js.map +1 -1
- package/dist/images/variants.d.ts +13 -3
- package/dist/images/variants.d.ts.map +1 -1
- package/dist/images/variants.js +13 -11
- package/dist/images/variants.js.map +1 -1
- package/dist/index.d.ts +34 -7
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +91 -18
- package/dist/index.js.map +1 -1
- package/dist/notifications/index.d.ts +1 -1
- package/dist/notifications/index.d.ts.map +1 -1
- package/dist/notifications/index.js +1 -1
- package/dist/notifications/index.js.map +1 -1
- package/dist/notifications/optouts.d.ts +6 -0
- package/dist/notifications/optouts.d.ts.map +1 -1
- package/dist/notifications/optouts.js +17 -0
- package/dist/notifications/optouts.js.map +1 -1
- package/dist/notifications/routes.js +1 -1
- package/dist/notifications/routes.js.map +1 -1
- package/dist/privacy/erase.d.ts +45 -0
- package/dist/privacy/erase.d.ts.map +1 -0
- package/dist/privacy/erase.js +76 -0
- package/dist/privacy/erase.js.map +1 -0
- package/dist/privacy/policy.d.ts +32 -0
- package/dist/privacy/policy.d.ts.map +1 -0
- package/dist/privacy/policy.js +37 -0
- package/dist/privacy/policy.js.map +1 -0
- package/dist/privacy/retention.d.ts +79 -0
- package/dist/privacy/retention.d.ts.map +1 -0
- package/dist/privacy/retention.js +133 -0
- package/dist/privacy/retention.js.map +1 -0
- package/dist/web/admin-bar.d.ts +21 -0
- package/dist/web/admin-bar.d.ts.map +1 -0
- package/dist/web/admin-bar.js +145 -0
- package/dist/web/admin-bar.js.map +1 -0
- package/dist/web/assets.d.ts +29 -1
- package/dist/web/assets.d.ts.map +1 -1
- package/dist/web/assets.js +48 -3
- package/dist/web/assets.js.map +1 -1
- package/dist/web/compression.d.ts +19 -0
- package/dist/web/compression.d.ts.map +1 -0
- package/dist/web/compression.js +160 -0
- package/dist/web/compression.js.map +1 -0
- package/dist/web/context.d.ts +5 -1
- package/dist/web/context.d.ts.map +1 -1
- package/dist/web/context.js +5 -2
- package/dist/web/context.js.map +1 -1
- package/dist/web/conversation.d.ts +9 -1
- package/dist/web/conversation.d.ts.map +1 -1
- package/dist/web/conversation.js +79 -17
- package/dist/web/conversation.js.map +1 -1
- package/dist/web/index.d.ts +1 -0
- package/dist/web/index.d.ts.map +1 -1
- package/dist/web/index.js +1 -0
- package/dist/web/index.js.map +1 -1
- package/dist/web/maintenance.d.ts.map +1 -1
- package/dist/web/maintenance.js +7 -2
- package/dist/web/maintenance.js.map +1 -1
- package/dist/web/render.d.ts +27 -0
- package/dist/web/render.d.ts.map +1 -1
- package/dist/web/render.js +77 -38
- package/dist/web/render.js.map +1 -1
- package/dist/web/routes.d.ts.map +1 -1
- package/dist/web/routes.js +67 -28
- package/dist/web/routes.js.map +1 -1
- package/dist/web/templates.d.ts.map +1 -1
- package/dist/web/templates.js +9 -2
- package/dist/web/templates.js.map +1 -1
- package/dist/web/well-known.d.ts +21 -0
- package/dist/web/well-known.d.ts.map +1 -0
- package/dist/web/well-known.js +66 -0
- package/dist/web/well-known.js.map +1 -0
- package/dist/webmention/fetch-public.d.ts +34 -0
- package/dist/webmention/fetch-public.d.ts.map +1 -0
- package/dist/webmention/fetch-public.js +101 -0
- package/dist/webmention/fetch-public.js.map +1 -0
- package/dist/webmention/reply-context.d.ts.map +1 -1
- package/dist/webmention/reply-context.js +12 -89
- package/dist/webmention/reply-context.js.map +1 -1
- package/dist/webmention/service.d.ts.map +1 -1
- package/dist/webmention/service.js +5 -1
- package/dist/webmention/service.js.map +1 -1
- package/package.json +1 -1
- package/templates/site/content/_data/site.json +7 -1
- package/templates/site/content/pages/privacy.md +127 -0
- package/themes/default/README.md +165 -22
- package/themes/default/layouts/base.njk +51 -10
|
@@ -48,12 +48,14 @@ export declare const ADMIN_TEMPLATES: {
|
|
|
48
48
|
readonly settingsDiscussion: 'pages/settings/discussion.njk';
|
|
49
49
|
readonly settingsEmail: 'pages/settings/email.njk';
|
|
50
50
|
readonly toolsContentIndex: 'pages/tools/content-index.njk';
|
|
51
|
+
readonly toolsPersonalData: 'pages/tools/personal-data.njk';
|
|
51
52
|
readonly usersList: 'pages/users/list.njk';
|
|
52
53
|
readonly usersNew: 'pages/users/new.njk';
|
|
53
54
|
readonly usersEdit: 'pages/users/edit.njk';
|
|
54
55
|
readonly federation: 'pages/federation/followers.njk';
|
|
55
56
|
readonly federationSettings: 'pages/federation/settings.njk';
|
|
56
57
|
readonly serverError: 'pages/error.njk';
|
|
58
|
+
readonly publicAdminBar: 'components/public-admin-bar.njk';
|
|
57
59
|
};
|
|
58
60
|
/** How to build an {@link createAdminTemplateEnvironment}. */
|
|
59
61
|
export interface CreateAdminTemplateEnvironmentOptions {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"templates.d.ts","sourceRoot":"","sources":["../../src/admin/templates.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,WAAW,EAAoB,MAAM,UAAU,CAAC;AAIzD;;;;;;;;;;;;;;;;;GAiBG;AACH,eAAO,MAAM,kBAAkB,EAAE,MAAgE,CAAC;AAElG;;;;;;;GAOG;AACH,eAAO,MAAM,eAAe;aAC1B,KAAK,EAAE,yBAAyB;aAChC,KAAK,EAAE,yBAAyB;aAChC,MAAM,EAAE,0BAA0B;aAClC,KAAK,EAAE,yBAAyB;aAChC,SAAS,EAAE,0BAA0B;aACrC,WAAW,EAAE,uBAAuB;aACpC,YAAY,EAAE,0BAA0B;aACxC,cAAc,EAAE,4BAA4B;aAC5C,gBAAgB,EAAE,8BAA8B;aAChD,QAAQ,EAAE,8BAA8B;aACxC,UAAU,EAAE,4BAA4B;aACxC,KAAK,EAAE,yBAAyB;aAChC,MAAM,EAAE,6BAA6B;aACrC,QAAQ,EAAE,wBAAwB;aAClC,QAAQ,EAAE,wBAAwB;aAClC,eAAe,EAAE,4BAA4B;aAC7C,eAAe,EAAE,4BAA4B;aAC7C,kBAAkB,EAAE,+BAA+B;aACnD,kBAAkB,EAAE,+BAA+B;aACnD,aAAa,EAAE,0BAA0B;aACzC,iBAAiB,EAAE,+BAA+B;aAClD,SAAS,EAAE,sBAAsB;aACjC,QAAQ,EAAE,qBAAqB;aAC/B,SAAS,EAAE,sBAAsB;aACjC,UAAU,EAAE,gCAAgC;aAC5C,kBAAkB,EAAE,+BAA+B;aACnD,WAAW,EAAE,iBAAiB;
|
|
1
|
+
{"version":3,"file":"templates.d.ts","sourceRoot":"","sources":["../../src/admin/templates.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,WAAW,EAAoB,MAAM,UAAU,CAAC;AAIzD;;;;;;;;;;;;;;;;;GAiBG;AACH,eAAO,MAAM,kBAAkB,EAAE,MAAgE,CAAC;AAElG;;;;;;;GAOG;AACH,eAAO,MAAM,eAAe;aAC1B,KAAK,EAAE,yBAAyB;aAChC,KAAK,EAAE,yBAAyB;aAChC,MAAM,EAAE,0BAA0B;aAClC,KAAK,EAAE,yBAAyB;aAChC,SAAS,EAAE,0BAA0B;aACrC,WAAW,EAAE,uBAAuB;aACpC,YAAY,EAAE,0BAA0B;aACxC,cAAc,EAAE,4BAA4B;aAC5C,gBAAgB,EAAE,8BAA8B;aAChD,QAAQ,EAAE,8BAA8B;aACxC,UAAU,EAAE,4BAA4B;aACxC,KAAK,EAAE,yBAAyB;aAChC,MAAM,EAAE,6BAA6B;aACrC,QAAQ,EAAE,wBAAwB;aAClC,QAAQ,EAAE,wBAAwB;aAClC,eAAe,EAAE,4BAA4B;aAC7C,eAAe,EAAE,4BAA4B;aAC7C,kBAAkB,EAAE,+BAA+B;aACnD,kBAAkB,EAAE,+BAA+B;aACnD,aAAa,EAAE,0BAA0B;aACzC,iBAAiB,EAAE,+BAA+B;aAClD,iBAAiB,EAAE,+BAA+B;aAClD,SAAS,EAAE,sBAAsB;aACjC,QAAQ,EAAE,qBAAqB;aAC/B,SAAS,EAAE,sBAAsB;aACjC,UAAU,EAAE,gCAAgC;aAC5C,kBAAkB,EAAE,+BAA+B;aACnD,WAAW,EAAE,iBAAiB;aAC9B,cAAc,EAAE,iCAAiC;CACzC,CAAC;AAEX,8DAA8D;AAC9D,MAAM,WAAW,qCAAqC;IACpD;;;;OAIG;IACH,OAAO,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;CAC/B;AAED,+EAA+E;AAC/E,wBAAgB,8BAA8B,CAC5C,OAAO,GAAE,qCAA0C,GAClD,WAAW,CAmBb"}
|
package/dist/admin/templates.js
CHANGED
|
@@ -50,12 +50,14 @@ export const ADMIN_TEMPLATES = {
|
|
|
50
50
|
settingsDiscussion: 'pages/settings/discussion.njk',
|
|
51
51
|
settingsEmail: 'pages/settings/email.njk',
|
|
52
52
|
toolsContentIndex: 'pages/tools/content-index.njk',
|
|
53
|
+
toolsPersonalData: 'pages/tools/personal-data.njk',
|
|
53
54
|
usersList: 'pages/users/list.njk',
|
|
54
55
|
usersNew: 'pages/users/new.njk',
|
|
55
56
|
usersEdit: 'pages/users/edit.njk',
|
|
56
57
|
federation: 'pages/federation/followers.njk',
|
|
57
58
|
federationSettings: 'pages/federation/settings.njk',
|
|
58
59
|
serverError: 'pages/error.njk',
|
|
60
|
+
publicAdminBar: 'components/public-admin-bar.njk',
|
|
59
61
|
};
|
|
60
62
|
/** A Nunjucks environment over {@link PACKAGED_ADMIN_DIR} and nothing else. */
|
|
61
63
|
export function createAdminTemplateEnvironment(options = {}) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"templates.js","sourceRoot":"","sources":["../../src/admin/templates.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAEzC,OAAO,EAAE,WAAW,EAAE,gBAAgB,EAAE,MAAM,UAAU,CAAC;AAEzD,OAAO,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AAEjD;;;;;;;;;;;;;;;;;GAiBG;AACH,MAAM,CAAC,MAAM,kBAAkB,GAAW,aAAa,CAAC,IAAI,GAAG,CAAC,cAAc,EAAE,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;AAElG;;;;;;;GAOG;AACH,MAAM,CAAC,MAAM,eAAe,GAAG;IAC7B,KAAK,EAAE,yBAAyB;IAChC,KAAK,EAAE,yBAAyB;IAChC,MAAM,EAAE,0BAA0B;IAClC,KAAK,EAAE,yBAAyB;IAChC,SAAS,EAAE,0BAA0B;IACrC,WAAW,EAAE,uBAAuB;IACpC,YAAY,EAAE,0BAA0B;IACxC,cAAc,EAAE,4BAA4B;IAC5C,gBAAgB,EAAE,8BAA8B;IAChD,QAAQ,EAAE,8BAA8B;IACxC,UAAU,EAAE,4BAA4B;IACxC,KAAK,EAAE,yBAAyB;IAChC,MAAM,EAAE,6BAA6B;IACrC,QAAQ,EAAE,wBAAwB;IAClC,QAAQ,EAAE,wBAAwB;IAClC,eAAe,EAAE,4BAA4B;IAC7C,eAAe,EAAE,4BAA4B;IAC7C,kBAAkB,EAAE,+BAA+B;IACnD,kBAAkB,EAAE,+BAA+B;IACnD,aAAa,EAAE,0BAA0B;IACzC,iBAAiB,EAAE,+BAA+B;IAClD,SAAS,EAAE,sBAAsB;IACjC,QAAQ,EAAE,qBAAqB;IAC/B,SAAS,EAAE,sBAAsB;IACjC,UAAU,EAAE,gCAAgC;IAC5C,kBAAkB,EAAE,+BAA+B;IACnD,WAAW,EAAE,iBAAiB;
|
|
1
|
+
{"version":3,"file":"templates.js","sourceRoot":"","sources":["../../src/admin/templates.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAEzC,OAAO,EAAE,WAAW,EAAE,gBAAgB,EAAE,MAAM,UAAU,CAAC;AAEzD,OAAO,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AAEjD;;;;;;;;;;;;;;;;;GAiBG;AACH,MAAM,CAAC,MAAM,kBAAkB,GAAW,aAAa,CAAC,IAAI,GAAG,CAAC,cAAc,EAAE,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;AAElG;;;;;;;GAOG;AACH,MAAM,CAAC,MAAM,eAAe,GAAG;IAC7B,KAAK,EAAE,yBAAyB;IAChC,KAAK,EAAE,yBAAyB;IAChC,MAAM,EAAE,0BAA0B;IAClC,KAAK,EAAE,yBAAyB;IAChC,SAAS,EAAE,0BAA0B;IACrC,WAAW,EAAE,uBAAuB;IACpC,YAAY,EAAE,0BAA0B;IACxC,cAAc,EAAE,4BAA4B;IAC5C,gBAAgB,EAAE,8BAA8B;IAChD,QAAQ,EAAE,8BAA8B;IACxC,UAAU,EAAE,4BAA4B;IACxC,KAAK,EAAE,yBAAyB;IAChC,MAAM,EAAE,6BAA6B;IACrC,QAAQ,EAAE,wBAAwB;IAClC,QAAQ,EAAE,wBAAwB;IAClC,eAAe,EAAE,4BAA4B;IAC7C,eAAe,EAAE,4BAA4B;IAC7C,kBAAkB,EAAE,+BAA+B;IACnD,kBAAkB,EAAE,+BAA+B;IACnD,aAAa,EAAE,0BAA0B;IACzC,iBAAiB,EAAE,+BAA+B;IAClD,iBAAiB,EAAE,+BAA+B;IAClD,SAAS,EAAE,sBAAsB;IACjC,QAAQ,EAAE,qBAAqB;IAC/B,SAAS,EAAE,sBAAsB;IACjC,UAAU,EAAE,gCAAgC;IAC5C,kBAAkB,EAAE,+BAA+B;IACnD,WAAW,EAAE,iBAAiB;IAC9B,cAAc,EAAE,iCAAiC;CACzC,CAAC;AAYX,+EAA+E;AAC/E,MAAM,UAAU,8BAA8B,CAC5C,OAAO,GAA0C,EAAE;IAEnD,MAAM,MAAM,GAAG,IAAI,gBAAgB,CAAC,CAAC,kBAAkB,CAAC,EAAE;QACxD,OAAO,EAAE,OAAO,CAAC,OAAO,KAAK,IAAI;KAClC,CAAC,CAAC;IAEH,MAAM,WAAW,GAAG,IAAI,WAAW,CAAC,MAAM,EAAE;QAC1C,UAAU,EAAE,IAAI;QAChB,gBAAgB,EAAE,KAAK;QACvB,UAAU,EAAE,IAAI;QAChB,YAAY,EAAE,IAAI;KACnB,CAAC,CAAC;IAEH,yEAAyE;IACzE,sEAAsE;IACtE,WAAW,CAAC,SAAS,CAAC,MAAM,EAAE,CAAC,KAAc,EAAE,MAAM,GAAY,UAAU,EAAE,EAAE,CAC7E,UAAU,CAAC,KAAK,EAAE,OAAO,MAAM,KAAK,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,UAAU,CAAC,CACpE,CAAC;IAEF,OAAO,WAAW,CAAC;AACrB,CAAC"}
|
package/dist/admin/tools.d.ts
CHANGED
|
@@ -62,6 +62,8 @@ export interface RebuildContentIndexOptions {
|
|
|
62
62
|
admin: AdminStore;
|
|
63
63
|
/** The content directory every one of them is read from. */
|
|
64
64
|
contentDir: string;
|
|
65
|
+
/** The data directory the commenters' emails are read from. */
|
|
66
|
+
dataDir: string;
|
|
65
67
|
/** The full scan, which is `cms.sync()`: see {@link GeekityEnv} `rescan`. */
|
|
66
68
|
rescan: () => Promise<SyncResult>;
|
|
67
69
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tools.d.ts","sourceRoot":"","sources":["../../src/admin/tools.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAEH,OAAO,KAAK,EAAW,IAAI,EAAE,MAAM,MAAM,CAAC;AAG1C,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACxD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AACrD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC;AAE5C,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAGlD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAG7C;;;;;;GAMG;AACH,eAAO,MAAM,UAAU,iBAA0B,CAAC;AAElD,sCAAsC;AACtC,eAAO,MAAM,kBAAkB,+BAAwC,CAAC;AAExE,0DAA0D;AAC1D,eAAO,MAAM,aAAa,UAAU,CAAC;AAErC,uCAAuC;AACvC,eAAO,MAAM,mBAAmB,UAAU,CAAC;AAE3C,iDAAiD;AACjD,eAAO,MAAM,YAAY;IACvB,4EAA4E;aAC5E,OAAO,EAAE,SAAS;CACV,CAAC;AAEX,0CAA0C;AAC1C,MAAM,WAAW,mBAAmB;IAClC,2EAA2E;IAC3E,IAAI,EAAE,UAAU,CAAC;IACjB,oDAAoD;IACpD,SAAS,EAAE,MAAM,CAAC;IAClB,8CAA8C;IAC9C,UAAU,EAAE,MAAM,CAAC;IACnB,gDAAgD;IAChD,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,8CAA8C;AAC9C,MAAM,WAAW,0BAA0B;IACzC,yCAAyC;IACzC,KAAK,EAAE,YAAY,CAAC;IACpB,+DAA+D;IAC/D,KAAK,EAAE,UAAU,CAAC;IAClB,4DAA4D;IAC5D,UAAU,EAAE,MAAM,CAAC;IACnB,6EAA6E;IAC7E,MAAM,EAAE,MAAM,OAAO,CAAC,UAAU,CAAC,CAAC;CACnC;AAED;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,wBAAsB,mBAAmB,CACvC,OAAO,EAAE,0BAA0B,GAClC,OAAO,CAAC,mBAAmB,CAAC,CAe9B;AAED,oEAAoE;AACpE,MAAM,WAAW,iBAAiB;IAChC,oFAAoF;IACpF,MAAM,EAAE,WAAW,CAAC;CACrB;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,IAAI,CAAC,UAAU,CAAC,EAAE,OAAO,EAAE,iBAAiB,GAAG,IAAI,
|
|
1
|
+
{"version":3,"file":"tools.d.ts","sourceRoot":"","sources":["../../src/admin/tools.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAEH,OAAO,KAAK,EAAW,IAAI,EAAE,MAAM,MAAM,CAAC;AAG1C,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACxD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AACrD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC;AAE5C,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAGlD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAG7C;;;;;;GAMG;AACH,eAAO,MAAM,UAAU,iBAA0B,CAAC;AAElD,sCAAsC;AACtC,eAAO,MAAM,kBAAkB,+BAAwC,CAAC;AAExE,0DAA0D;AAC1D,eAAO,MAAM,aAAa,UAAU,CAAC;AAErC,uCAAuC;AACvC,eAAO,MAAM,mBAAmB,UAAU,CAAC;AAE3C,iDAAiD;AACjD,eAAO,MAAM,YAAY;IACvB,4EAA4E;aAC5E,OAAO,EAAE,SAAS;CACV,CAAC;AAEX,0CAA0C;AAC1C,MAAM,WAAW,mBAAmB;IAClC,2EAA2E;IAC3E,IAAI,EAAE,UAAU,CAAC;IACjB,oDAAoD;IACpD,SAAS,EAAE,MAAM,CAAC;IAClB,8CAA8C;IAC9C,UAAU,EAAE,MAAM,CAAC;IACnB,gDAAgD;IAChD,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,8CAA8C;AAC9C,MAAM,WAAW,0BAA0B;IACzC,yCAAyC;IACzC,KAAK,EAAE,YAAY,CAAC;IACpB,+DAA+D;IAC/D,KAAK,EAAE,UAAU,CAAC;IAClB,4DAA4D;IAC5D,UAAU,EAAE,MAAM,CAAC;IACnB,+DAA+D;IAC/D,OAAO,EAAE,MAAM,CAAC;IAChB,6EAA6E;IAC7E,MAAM,EAAE,MAAM,OAAO,CAAC,UAAU,CAAC,CAAC;CACnC;AAED;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,wBAAsB,mBAAmB,CACvC,OAAO,EAAE,0BAA0B,GAClC,OAAO,CAAC,mBAAmB,CAAC,CAe9B;AAED,oEAAoE;AACpE,MAAM,WAAW,iBAAiB;IAChC,oFAAoF;IACpF,MAAM,EAAE,WAAW,CAAC;CACrB;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,IAAI,CAAC,UAAU,CAAC,EAAE,OAAO,EAAE,iBAAiB,GAAG,IAAI,CA8ExF;AAED,iDAAiD;AACjD,wBAAgB,cAAc,CAAC,MAAM,EAAE,mBAAmB,GAAG,MAAM,CAYlE"}
|
package/dist/admin/tools.js
CHANGED
|
@@ -65,10 +65,10 @@ export const TOOLS_FIELDS = {
|
|
|
65
65
|
* reason a boot scan is silent.
|
|
66
66
|
*/
|
|
67
67
|
export async function rebuildContentIndex(options) {
|
|
68
|
-
const { store, admin, contentDir, rescan } = options;
|
|
68
|
+
const { store, admin, contentDir, dataDir, rescan } = options;
|
|
69
69
|
store.clear();
|
|
70
70
|
const federation = rebuildFederationIndexes({ admin, contentDir });
|
|
71
|
-
const comments = rebuildCommentIndexes({ admin, contentDir });
|
|
71
|
+
const comments = rebuildCommentIndexes({ admin, contentDir, dataDir });
|
|
72
72
|
const scan = await rescan();
|
|
73
73
|
return {
|
|
74
74
|
scan,
|
|
@@ -118,6 +118,7 @@ export function mountToolsScreen(app, options) {
|
|
|
118
118
|
store: c.var.store,
|
|
119
119
|
admin: c.var.admin,
|
|
120
120
|
contentDir: c.var.config.contentDir,
|
|
121
|
+
dataDir: c.var.config.dataDir,
|
|
121
122
|
rescan: c.var.rescan,
|
|
122
123
|
});
|
|
123
124
|
let report;
|
package/dist/admin/tools.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tools.js","sourceRoot":"","sources":["../../src/admin/tools.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAIH,OAAO,EAAE,qBAAqB,EAAE,MAAM,wBAAwB,CAAC;AAI/D,OAAO,EAAE,wBAAwB,EAAE,MAAM,0BAA0B,CAAC;AAEpE,OAAO,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AACnC,OAAO,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAE5C,OAAO,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;AAEjD;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,UAAU,GAAG,GAAG,YAAY,QAAQ,CAAC;AAElD,sCAAsC;AACtC,MAAM,CAAC,MAAM,kBAAkB,GAAG,GAAG,YAAY,sBAAsB,CAAC;AAExE,0DAA0D;AAC1D,MAAM,CAAC,MAAM,aAAa,GAAG,OAAO,CAAC;AAErC,uCAAuC;AACvC,MAAM,CAAC,MAAM,mBAAmB,GAAG,OAAO,CAAC;AAE3C,iDAAiD;AACjD,MAAM,CAAC,MAAM,YAAY,GAAG;IAC1B,4EAA4E;IAC5E,OAAO,EAAE,SAAS;CACV,CAAC;
|
|
1
|
+
{"version":3,"file":"tools.js","sourceRoot":"","sources":["../../src/admin/tools.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAIH,OAAO,EAAE,qBAAqB,EAAE,MAAM,wBAAwB,CAAC;AAI/D,OAAO,EAAE,wBAAwB,EAAE,MAAM,0BAA0B,CAAC;AAEpE,OAAO,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AACnC,OAAO,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAE5C,OAAO,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;AAEjD;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,UAAU,GAAG,GAAG,YAAY,QAAQ,CAAC;AAElD,sCAAsC;AACtC,MAAM,CAAC,MAAM,kBAAkB,GAAG,GAAG,YAAY,sBAAsB,CAAC;AAExE,0DAA0D;AAC1D,MAAM,CAAC,MAAM,aAAa,GAAG,OAAO,CAAC;AAErC,uCAAuC;AACvC,MAAM,CAAC,MAAM,mBAAmB,GAAG,OAAO,CAAC;AAE3C,iDAAiD;AACjD,MAAM,CAAC,MAAM,YAAY,GAAG;IAC1B,4EAA4E;IAC5E,OAAO,EAAE,SAAS;CACV,CAAC;AA4BX;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,MAAM,CAAC,KAAK,UAAU,mBAAmB,CACvC,OAAmC;IAEnC,MAAM,EAAE,KAAK,EAAE,KAAK,EAAE,UAAU,EAAE,OAAO,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC;IAE9D,KAAK,CAAC,KAAK,EAAE,CAAC;IAEd,MAAM,UAAU,GAAG,wBAAwB,CAAC,EAAE,KAAK,EAAE,UAAU,EAAE,CAAC,CAAC;IACnE,MAAM,QAAQ,GAAG,qBAAqB,CAAC,EAAE,KAAK,EAAE,UAAU,EAAE,OAAO,EAAE,CAAC,CAAC;IACvE,MAAM,IAAI,GAAG,MAAM,MAAM,EAAE,CAAC;IAE5B,OAAO;QACL,IAAI;QACJ,SAAS,EAAE,UAAU,CAAC,SAAS;QAC/B,UAAU,EAAE,UAAU,CAAC,UAAU;QACjC,QAAQ,EAAE,QAAQ,CAAC,QAAQ;KAC5B,CAAC;AACJ,CAAC;AAQD;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,gBAAgB,CAAC,GAAqB,EAAE,OAA0B;IAChF,MAAM,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC;IAE3B;;;;;;;;OAQG;IACH,IAAI,OAAiD,CAAC;IAEtD,GAAG,CAAC,GAAG,CAAC,UAAU,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,MAAM,CAAC,CAAC,EAAE,eAAe,CAAC,iBAAiB,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IAEpF,GAAG,CAAC,IAAI,CAAC,kBAAkB,EAAE,KAAK,EAAE,CAAC,EAAE,EAAE;QACvC,MAAM,IAAI,GAAG,MAAM,CAAC,CAAC,GAAG,CAAC,SAAS,EAAE,CAAC;QAErC,wEAAwE;QACxE,wEAAwE;QACxE,0DAA0D;QAC1D,IAAI,KAAK,CAAC,IAAI,CAAC,YAAY,CAAC,OAAO,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC;YAC7C,OAAO,MAAM,CAAC,CAAC,EAAE,eAAe,CAAC,iBAAiB,EAAE,EAAE,GAAG,MAAM,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC;QACvF,CAAC;QAED,IAAI,OAAO,KAAK,SAAS,EAAE,CAAC;YAC1B,KAAK,CACH,CAAC,EACD,OAAO,EACP,+FAA+F,CAChG,CAAC;YACF,OAAO,CAAC,CAAC,QAAQ,CAAC,UAAU,EAAE,GAAG,CAAC,CAAC;QACrC,CAAC;QAED,OAAO,GAAG,mBAAmB,CAAC;YAC5B,KAAK,EAAE,CAAC,CAAC,GAAG,CAAC,KAAK;YAClB,KAAK,EAAE,CAAC,CAAC,GAAG,CAAC,KAAK;YAClB,UAAU,EAAE,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,UAAU;YACnC,OAAO,EAAE,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,OAAO;YAC7B,MAAM,EAAE,CAAC,CAAC,GAAG,CAAC,MAAM;SACrB,CAAC,CAAC;QAEH,IAAI,MAA2B,CAAC;QAChC,IAAI,CAAC;YACH,MAAM,GAAG,MAAM,OAAO,CAAC;QACzB,CAAC;gBAAS,CAAC;YACT,OAAO,GAAG,SAAS,CAAC;QACtB,CAAC;QAED,KAAK,CAAC,CAAC,EAAE,MAAM,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,QAAQ,EAAE,cAAc,CAAC,MAAM,CAAC,CAAC,CAAC;QAC9E,OAAO,CAAC,CAAC,QAAQ,CAAC,UAAU,EAAE,GAAG,CAAC,CAAC;IACrC,CAAC,CAAC,CAAC;IAEH,qCAAqC;IACrC,SAAS,MAAM,CAAC,CAAsB;QACpC,MAAM,MAAM,GAAG,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,MAAM,EAAE,CAAC;QAEpC,OAAO;YACL,OAAO,EAAE,aAAa;YACtB,KAAK,EAAE,mBAAmB;YAC1B,OAAO,EAAE,eAAe;YACxB,UAAU,EAAE,kBAAkB;YAC9B,QAAQ,EAAE,UAAU;YACpB,MAAM,EAAE,YAAY;YACpB,OAAO,EAAE,KAAK;YACd,wEAAwE;YACxE,uEAAuE;YACvE,mEAAmE;YACnE,OAAO,EAAE;gBACP,SAAS,EAAE,MAAM,CAAC,KAAK;gBACvB,SAAS,EAAE,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,cAAc,EAAE;gBACvC,UAAU,EAAE,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,oBAAoB,EAAE;gBAC9C,QAAQ,EAAE,aAAa,CAAC,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC;aACrC;YACD,UAAU,EAAE,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,UAAU;SACpC,CAAC;IACJ,CAAC;AACH,CAAC;AAED,iDAAiD;AACjD,MAAM,UAAU,cAAc,CAAC,MAA2B;IACxD,MAAM,EAAE,IAAI,EAAE,GAAG,MAAM,CAAC;IACxB,MAAM,OAAO,GACX,6CAA6C,KAAK,CAAC,IAAI,CAAC,OAAO,EAAE,MAAM,CAAC,IAAI;QAC5E,GAAG,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,aAAa,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,YAAY;QACpE,GAAG,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,sBAAsB,KAAK,CAAC,MAAM,CAAC,SAAS,EAAE,UAAU,CAAC,IAAI;QACnF,GAAG,KAAK,CAAC,MAAM,CAAC,UAAU,EAAE,gBAAgB,EAAE,kBAAkB,CAAC,OAAO;QACxE,GAAG,KAAK,CAAC,MAAM,CAAC,QAAQ,EAAE,SAAS,CAAC,GAAG,CAAC;IAE1C,OAAO,IAAI,CAAC,MAAM,KAAK,CAAC;QACtB,CAAC,CAAC,OAAO;QACT,CAAC,CAAC,GAAG,OAAO,mFAAmF,CAAC;AACpG,CAAC;AAED,0EAA0E;AAC1E,SAAS,KAAK,CAAC,OAAe,EAAE,QAAgB,EAAE,MAAM,GAAG,GAAG,QAAQ,GAAG;IACvE,OAAO,GAAG,MAAM,CAAC,OAAO,CAAC,IAAI,OAAO,KAAK,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC;AACnE,CAAC;AAED,kFAAkF;AAClF,SAAS,aAAa,CAAC,KAAiB;IACtC,MAAM,MAAM,GAAG,KAAK,CAAC,qBAAqB,EAAE,CAAC;IAC7C,OAAO,MAAM,CAAC,OAAO,GAAG,MAAM,CAAC,QAAQ,GAAG,MAAM,CAAC,IAAI,CAAC;AACxD,CAAC;AAED,uCAAuC;AACvC,SAAS,KAAK,CAAC,KAAc;IAC3B,OAAO,OAAO,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC;AAChD,CAAC"}
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
import type { AdminStore } from '../admin/store.ts';
|
|
2
|
+
import type { ResolvedConfig } from '../config.ts';
|
|
3
|
+
import type { NotificationTimers } from '../notifications/digest.ts';
|
|
4
|
+
import type { StaticAsset } from '../web/assets.ts';
|
|
5
|
+
/**
|
|
6
|
+
* Remote avatars, served from this site (TASK-134).
|
|
7
|
+
*
|
|
8
|
+
* A face in a facepile is somebody else's picture on somebody else's server.
|
|
9
|
+
* Hotlinked, every reader who opens a post sends that server their address
|
|
10
|
+
* and their user agent. So a page never names the remote URL: it names
|
|
11
|
+
* `/_geekity/avatars/<key>`, and this module fetches the picture, shrinks it to
|
|
12
|
+
* the size the theme shows it at and keeps the result.
|
|
13
|
+
*
|
|
14
|
+
* The key is the source URL itself, base64url-encoded, and it is only a
|
|
15
|
+
* spelling: a request is answered only when the index says the URL is an
|
|
16
|
+
* avatar the site has recorded ({@link AdminStore.isAvatarSource}). Anything
|
|
17
|
+
* else is a 404 that fetches nothing, so this is not an open proxy, and there
|
|
18
|
+
* is no table or secret to lose.
|
|
19
|
+
*
|
|
20
|
+
* The files under `<dataDir>/avatars/` are a disposable cache (decision-9):
|
|
21
|
+
* every one of them is named by the hash of a URL the index holds and can be
|
|
22
|
+
* fetched again. A sweep on a timer fetches the ones that are missing or old
|
|
23
|
+
* and removes the ones nobody shows any more, so a page is almost never the
|
|
24
|
+
* thing that waits on a stranger's server.
|
|
25
|
+
*/
|
|
26
|
+
/** Where an avatar is served, followed by its key. */
|
|
27
|
+
export declare const AVATAR_PATH_PREFIX = "/_geekity/avatars/";
|
|
28
|
+
/** The directory under `dataDir` the cache lives in. */
|
|
29
|
+
export declare const AVATAR_DIRECTORY = "avatars";
|
|
30
|
+
/**
|
|
31
|
+
* The width and height of a cached avatar, in pixels: twice the 40 the
|
|
32
|
+
* default theme shows a commenter at, so it is sharp on a high-density screen,
|
|
33
|
+
* and the facepile's 32 is a downscale of it.
|
|
34
|
+
*/
|
|
35
|
+
export declare const AVATAR_SIZE = 80;
|
|
36
|
+
/** The largest picture that is read. A bigger one is the placeholder. */
|
|
37
|
+
export declare const AVATAR_MAX_BYTES = 2000000;
|
|
38
|
+
/** How long one fetch is given, body included. */
|
|
39
|
+
export declare const AVATAR_FETCH_TIMEOUT_MS = 10000;
|
|
40
|
+
/**
|
|
41
|
+
* How long the first request for a picture nobody has fetched yet waits for
|
|
42
|
+
* it before it is answered with the placeholder. The fetch carries on and the
|
|
43
|
+
* next request gets the picture.
|
|
44
|
+
*/
|
|
45
|
+
export declare const AVATAR_FIRST_VIEW_WAIT_MS = 2000;
|
|
46
|
+
/** How old a cached picture gets before the sweep fetches it again. */
|
|
47
|
+
export declare const AVATAR_MAX_AGE_MS: number;
|
|
48
|
+
/** How long a URL that could not be fetched is left alone. */
|
|
49
|
+
export declare const AVATAR_RETRY_MS: number;
|
|
50
|
+
/** How often the sweep runs. */
|
|
51
|
+
export declare const AVATAR_SWEEP_MS: number;
|
|
52
|
+
/** How long a browser keeps a picture, in seconds. */
|
|
53
|
+
export declare const AVATAR_MAX_AGE_SECONDS = 86400;
|
|
54
|
+
/** How long a browser keeps the placeholder, so the next view asks again. */
|
|
55
|
+
export declare const AVATAR_PLACEHOLDER_MAX_AGE_SECONDS = 300;
|
|
56
|
+
/** What a picture with no fetched face is: a grey head and shoulders. */
|
|
57
|
+
export declare const AVATAR_PLACEHOLDER_SVG = "<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 80 80\" width=\"80\" height=\"80\"><rect width=\"80\" height=\"80\" fill=\"#d7d7d7\"/><circle cx=\"40\" cy=\"31\" r=\"15\" fill=\"#f5f5f5\"/><path d=\"M12 80c0-17 12.5-27 28-27s28 10 28 27z\" fill=\"#f5f5f5\"/></svg>\n";
|
|
58
|
+
/** The same-origin URL a theme is handed for an avatar at `source`. */
|
|
59
|
+
export declare function avatarHref(source: string): string;
|
|
60
|
+
/** The source URL a key spells, or `undefined` when it spells no web URL. */
|
|
61
|
+
export declare function avatarSourceOf(key: string): string | undefined;
|
|
62
|
+
/** What a request for an avatar is answered with. */
|
|
63
|
+
export type AvatarAnswer = {
|
|
64
|
+
readonly kind: 'image';
|
|
65
|
+
readonly asset: StaticAsset;
|
|
66
|
+
} | {
|
|
67
|
+
readonly kind: 'placeholder';
|
|
68
|
+
} | {
|
|
69
|
+
readonly kind: 'unknown';
|
|
70
|
+
};
|
|
71
|
+
/** Where the service reports a picture it could not fetch. */
|
|
72
|
+
export interface AvatarLogger {
|
|
73
|
+
warn(message: string): void;
|
|
74
|
+
}
|
|
75
|
+
/** What {@link createAvatarService} needs. */
|
|
76
|
+
export interface CreateAvatarServiceOptions {
|
|
77
|
+
/** The index, asked which URLs are avatars the site shows. */
|
|
78
|
+
readonly admin: Pick<AdminStore, 'isAvatarSource' | 'listAvatarSources'>;
|
|
79
|
+
/** The data directory the cache lives in, the resolver and the clock. */
|
|
80
|
+
readonly config: Pick<ResolvedConfig, 'dataDir' | 'hostLookup' | 'now'>;
|
|
81
|
+
/** Defaults to the real interval timer. */
|
|
82
|
+
readonly timers?: NotificationTimers | undefined;
|
|
83
|
+
/** Defaults to {@link AVATAR_FIRST_VIEW_WAIT_MS}. */
|
|
84
|
+
readonly firstViewWaitMs?: number | undefined;
|
|
85
|
+
/** Defaults to `console`. */
|
|
86
|
+
readonly logger?: AvatarLogger | undefined;
|
|
87
|
+
}
|
|
88
|
+
/** Fetches, shrinks, keeps and serves the avatars the site shows. */
|
|
89
|
+
export interface AvatarService {
|
|
90
|
+
/**
|
|
91
|
+
* The answer to a request for the avatar at `source`: the cached picture,
|
|
92
|
+
* the placeholder when there is none to be had yet, or `unknown` for a URL
|
|
93
|
+
* the site has not recorded. Fetches only for a recorded URL with nothing
|
|
94
|
+
* cached, and waits for that fetch no longer than the first-view bound.
|
|
95
|
+
*/
|
|
96
|
+
answer(source: string): Promise<AvatarAnswer>;
|
|
97
|
+
/**
|
|
98
|
+
* Fetch every recorded avatar that is missing or older than
|
|
99
|
+
* {@link AVATAR_MAX_AGE_MS}, and delete every cached file no recorded URL
|
|
100
|
+
* names. Queued behind any sweep already running.
|
|
101
|
+
*/
|
|
102
|
+
sweep(): Promise<void>;
|
|
103
|
+
/** Sweep now and then every {@link AVATAR_SWEEP_MS}. Safe twice. */
|
|
104
|
+
start(): void;
|
|
105
|
+
/** Stop the timer. Safe before starting and safe twice. */
|
|
106
|
+
stop(): void;
|
|
107
|
+
/** Resolve once every fetch and sweep in flight has finished. */
|
|
108
|
+
settled(): Promise<void>;
|
|
109
|
+
}
|
|
110
|
+
/** Build the avatar service for one site. */
|
|
111
|
+
export declare function createAvatarService(options: CreateAvatarServiceOptions): AvatarService;
|
|
112
|
+
//# sourceMappingURL=avatars.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"avatars.d.ts","sourceRoot":"","sources":["../../src/avatars/avatars.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AACpD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAEnD,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,4BAA4B,CAAC;AAGrE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAGpD;;;;;;;;;;;;;;;;;;;;GAoBG;AAEH,sDAAsD;AACtD,eAAO,MAAM,kBAAkB,uBAAuB,CAAC;AAEvD,wDAAwD;AACxD,eAAO,MAAM,gBAAgB,YAAY,CAAC;AAE1C;;;;GAIG;AACH,eAAO,MAAM,WAAW,KAAK,CAAC;AAE9B,yEAAyE;AACzE,eAAO,MAAM,gBAAgB,UAAY,CAAC;AAE1C,kDAAkD;AAClD,eAAO,MAAM,uBAAuB,QAAS,CAAC;AAE9C;;;;GAIG;AACH,eAAO,MAAM,yBAAyB,OAAQ,CAAC;AAE/C,uEAAuE;AACvE,eAAO,MAAM,iBAAiB,QAA0B,CAAC;AAEzD,8DAA8D;AAC9D,eAAO,MAAM,eAAe,QAAiB,CAAC;AAE9C,gCAAgC;AAChC,eAAO,MAAM,eAAe,QAAqB,CAAC;AAElD,sDAAsD;AACtD,eAAO,MAAM,sBAAsB,QAAS,CAAC;AAE7C,6EAA6E;AAC7E,eAAO,MAAM,kCAAkC,MAAM,CAAC;AAEtD,yEAAyE;AACzE,eAAO,MAAM,sBAAsB,uRAA6P,CAAC;AAWjS,uEAAuE;AACvE,wBAAgB,UAAU,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAEjD;AAED,6EAA6E;AAC7E,wBAAgB,cAAc,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAO9D;AAED,qDAAqD;AACrD,MAAM,MAAM,YAAY,GACpB;IAAE,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC;IAAC,QAAQ,CAAC,KAAK,EAAE,WAAW,CAAA;CAAE,GACvD;IAAE,QAAQ,CAAC,IAAI,EAAE,aAAa,CAAA;CAAE,GAChC;IAAE,QAAQ,CAAC,IAAI,EAAE,SAAS,CAAA;CAAE,CAAC;AAEjC,8DAA8D;AAC9D,MAAM,WAAW,YAAY;IAC3B,IAAI,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;CAC7B;AAED,8CAA8C;AAC9C,MAAM,WAAW,0BAA0B;IACzC,8DAA8D;IAC9D,QAAQ,CAAC,KAAK,EAAE,IAAI,CAAC,UAAU,EAAE,gBAAgB,GAAG,mBAAmB,CAAC,CAAC;IACzE,yEAAyE;IACzE,QAAQ,CAAC,MAAM,EAAE,IAAI,CAAC,cAAc,EAAE,SAAS,GAAG,YAAY,GAAG,KAAK,CAAC,CAAC;IACxE,2CAA2C;IAC3C,QAAQ,CAAC,MAAM,CAAC,EAAE,kBAAkB,GAAG,SAAS,CAAC;IACjD,qDAAqD;IACrD,QAAQ,CAAC,eAAe,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC9C,6BAA6B;IAC7B,QAAQ,CAAC,MAAM,CAAC,EAAE,YAAY,GAAG,SAAS,CAAC;CAC5C;AAED,qEAAqE;AACrE,MAAM,WAAW,aAAa;IAC5B;;;;;OAKG;IACH,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,CAAC,CAAC;IAC9C;;;;OAIG;IACH,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IACvB,oEAAoE;IACpE,KAAK,IAAI,IAAI,CAAC;IACd,2DAA2D;IAC3D,IAAI,IAAI,IAAI,CAAC;IACb,iEAAiE;IACjE,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CAC1B;AAED,6CAA6C;AAC7C,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,0BAA0B,GAAG,aAAa,CA2HtF"}
|
|
@@ -0,0 +1,259 @@
|
|
|
1
|
+
import { createHash } from 'node:crypto';
|
|
2
|
+
import { readdir, rm, stat, utimes } from 'node:fs/promises';
|
|
3
|
+
import path from 'node:path';
|
|
4
|
+
import sharp from 'sharp';
|
|
5
|
+
import { writeFileAtomically } from '../files/atomic.js';
|
|
6
|
+
import { systemNotificationTimers } from '../notifications/digest.js';
|
|
7
|
+
import { findAsset } from '../web/assets.js';
|
|
8
|
+
import { fetchPublic, webUrl } from '../webmention/fetch-public.js';
|
|
9
|
+
/**
|
|
10
|
+
* Remote avatars, served from this site (TASK-134).
|
|
11
|
+
*
|
|
12
|
+
* A face in a facepile is somebody else's picture on somebody else's server.
|
|
13
|
+
* Hotlinked, every reader who opens a post sends that server their address
|
|
14
|
+
* and their user agent. So a page never names the remote URL: it names
|
|
15
|
+
* `/_geekity/avatars/<key>`, and this module fetches the picture, shrinks it to
|
|
16
|
+
* the size the theme shows it at and keeps the result.
|
|
17
|
+
*
|
|
18
|
+
* The key is the source URL itself, base64url-encoded, and it is only a
|
|
19
|
+
* spelling: a request is answered only when the index says the URL is an
|
|
20
|
+
* avatar the site has recorded ({@link AdminStore.isAvatarSource}). Anything
|
|
21
|
+
* else is a 404 that fetches nothing, so this is not an open proxy, and there
|
|
22
|
+
* is no table or secret to lose.
|
|
23
|
+
*
|
|
24
|
+
* The files under `<dataDir>/avatars/` are a disposable cache (decision-9):
|
|
25
|
+
* every one of them is named by the hash of a URL the index holds and can be
|
|
26
|
+
* fetched again. A sweep on a timer fetches the ones that are missing or old
|
|
27
|
+
* and removes the ones nobody shows any more, so a page is almost never the
|
|
28
|
+
* thing that waits on a stranger's server.
|
|
29
|
+
*/
|
|
30
|
+
/** Where an avatar is served, followed by its key. */
|
|
31
|
+
export const AVATAR_PATH_PREFIX = '/_geekity/avatars/';
|
|
32
|
+
/** The directory under `dataDir` the cache lives in. */
|
|
33
|
+
export const AVATAR_DIRECTORY = 'avatars';
|
|
34
|
+
/**
|
|
35
|
+
* The width and height of a cached avatar, in pixels: twice the 40 the
|
|
36
|
+
* default theme shows a commenter at, so it is sharp on a high-density screen,
|
|
37
|
+
* and the facepile's 32 is a downscale of it.
|
|
38
|
+
*/
|
|
39
|
+
export const AVATAR_SIZE = 80;
|
|
40
|
+
/** The largest picture that is read. A bigger one is the placeholder. */
|
|
41
|
+
export const AVATAR_MAX_BYTES = 2_000_000;
|
|
42
|
+
/** How long one fetch is given, body included. */
|
|
43
|
+
export const AVATAR_FETCH_TIMEOUT_MS = 10_000;
|
|
44
|
+
/**
|
|
45
|
+
* How long the first request for a picture nobody has fetched yet waits for
|
|
46
|
+
* it before it is answered with the placeholder. The fetch carries on and the
|
|
47
|
+
* next request gets the picture.
|
|
48
|
+
*/
|
|
49
|
+
export const AVATAR_FIRST_VIEW_WAIT_MS = 2_000;
|
|
50
|
+
/** How old a cached picture gets before the sweep fetches it again. */
|
|
51
|
+
export const AVATAR_MAX_AGE_MS = 7 * 24 * 60 * 60 * 1000;
|
|
52
|
+
/** How long a URL that could not be fetched is left alone. */
|
|
53
|
+
export const AVATAR_RETRY_MS = 60 * 60 * 1000;
|
|
54
|
+
/** How often the sweep runs. */
|
|
55
|
+
export const AVATAR_SWEEP_MS = 6 * 60 * 60 * 1000;
|
|
56
|
+
/** How long a browser keeps a picture, in seconds. */
|
|
57
|
+
export const AVATAR_MAX_AGE_SECONDS = 86_400;
|
|
58
|
+
/** How long a browser keeps the placeholder, so the next view asks again. */
|
|
59
|
+
export const AVATAR_PLACEHOLDER_MAX_AGE_SECONDS = 300;
|
|
60
|
+
/** What a picture with no fetched face is: a grey head and shoulders. */
|
|
61
|
+
export const AVATAR_PLACEHOLDER_SVG = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 80 80" width="80" height="80"><rect width="80" height="80" fill="#d7d7d7"/><circle cx="40" cy="31" r="15" fill="#f5f5f5"/><path d="M12 80c0-17 12.5-27 28-27s28 10 28 27z" fill="#f5f5f5"/></svg>\n`;
|
|
62
|
+
/** The content types a picture may arrive as. SVG is not one: it is a document. */
|
|
63
|
+
const ACCEPTED_TYPES = /^\s*image\/(jpeg|png|gif|webp|avif)\s*(;|$)/i;
|
|
64
|
+
/** What sharp must find the bytes to be, whatever the header said. AVIF reads as `heif`. */
|
|
65
|
+
const ACCEPTED_FORMATS = new Set(['jpeg', 'png', 'gif', 'webp', 'heif']);
|
|
66
|
+
/** The most pixels a picture may have before sharp will not decode it. */
|
|
67
|
+
const MAX_INPUT_PIXELS = 4096 * 4096;
|
|
68
|
+
/** The same-origin URL a theme is handed for an avatar at `source`. */
|
|
69
|
+
export function avatarHref(source) {
|
|
70
|
+
return `${AVATAR_PATH_PREFIX}${Buffer.from(source, 'utf8').toString('base64url')}`;
|
|
71
|
+
}
|
|
72
|
+
/** The source URL a key spells, or `undefined` when it spells no web URL. */
|
|
73
|
+
export function avatarSourceOf(key) {
|
|
74
|
+
if (!/^[A-Za-z0-9_-]+$/.test(key))
|
|
75
|
+
return undefined;
|
|
76
|
+
const source = Buffer.from(key, 'base64url').toString('utf8');
|
|
77
|
+
// The key has to be the one `avatarHref` would mint, so one URL has one key
|
|
78
|
+
// and one cached file.
|
|
79
|
+
if (avatarHref(source) !== `${AVATAR_PATH_PREFIX}${key}`)
|
|
80
|
+
return undefined;
|
|
81
|
+
return webUrl(source) === undefined ? undefined : source;
|
|
82
|
+
}
|
|
83
|
+
/** Build the avatar service for one site. */
|
|
84
|
+
export function createAvatarService(options) {
|
|
85
|
+
const { admin, config } = options;
|
|
86
|
+
const timers = options.timers ?? systemNotificationTimers;
|
|
87
|
+
const firstViewWaitMs = options.firstViewWaitMs ?? AVATAR_FIRST_VIEW_WAIT_MS;
|
|
88
|
+
const logger = options.logger ?? console;
|
|
89
|
+
const directory = path.join(config.dataDir, AVATAR_DIRECTORY);
|
|
90
|
+
const inFlight = new Map();
|
|
91
|
+
let sweeping = Promise.resolve();
|
|
92
|
+
let handle;
|
|
93
|
+
const imageName = (source) => `${hashOf(source)}.webp`;
|
|
94
|
+
const failedName = (source) => `${hashOf(source)}.failed`;
|
|
95
|
+
/** How long ago a cache file was written, or `undefined` when there is none. */
|
|
96
|
+
async function ageOf(name) {
|
|
97
|
+
try {
|
|
98
|
+
return config.now().getTime() - (await stat(path.join(directory, name))).mtimeMs;
|
|
99
|
+
}
|
|
100
|
+
catch {
|
|
101
|
+
return undefined;
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
/** Fetch one picture into the cache, once at a time per URL. */
|
|
105
|
+
function refresh(source) {
|
|
106
|
+
const running = inFlight.get(source);
|
|
107
|
+
if (running !== undefined)
|
|
108
|
+
return running;
|
|
109
|
+
const started = fetchInto(source).finally(() => inFlight.delete(source));
|
|
110
|
+
inFlight.set(source, started);
|
|
111
|
+
return started;
|
|
112
|
+
}
|
|
113
|
+
async function fetchInto(source) {
|
|
114
|
+
const shrunk = await fetchAvatar(source, config);
|
|
115
|
+
if (!shrunk.ok) {
|
|
116
|
+
logger.warn(`Could not fetch the avatar at ${source}: ${shrunk.reason}`);
|
|
117
|
+
await touch(path.join(directory, failedName(source)), config.now());
|
|
118
|
+
return false;
|
|
119
|
+
}
|
|
120
|
+
await writeFileAtomically(path.join(directory, imageName(source)), shrunk.image);
|
|
121
|
+
// The write is stamped with the site's clock rather than the machine's, so
|
|
122
|
+
// the age the sweep reads is the one the rest of the site agrees on.
|
|
123
|
+
const at = config.now();
|
|
124
|
+
await utimes(path.join(directory, imageName(source)), at, at);
|
|
125
|
+
await rm(path.join(directory, failedName(source)), { force: true });
|
|
126
|
+
return true;
|
|
127
|
+
}
|
|
128
|
+
async function sweepOnce() {
|
|
129
|
+
const sources = admin.listAvatarSources();
|
|
130
|
+
const keep = new Set();
|
|
131
|
+
for (const source of sources) {
|
|
132
|
+
keep.add(imageName(source));
|
|
133
|
+
keep.add(failedName(source));
|
|
134
|
+
if (webUrl(source) === undefined)
|
|
135
|
+
continue;
|
|
136
|
+
const age = await ageOf(imageName(source));
|
|
137
|
+
if (age !== undefined && age < AVATAR_MAX_AGE_MS)
|
|
138
|
+
continue;
|
|
139
|
+
const failedAge = await ageOf(failedName(source));
|
|
140
|
+
if (age === undefined && failedAge !== undefined && failedAge < AVATAR_RETRY_MS)
|
|
141
|
+
continue;
|
|
142
|
+
await refresh(source);
|
|
143
|
+
}
|
|
144
|
+
let names;
|
|
145
|
+
try {
|
|
146
|
+
names = await readdir(directory);
|
|
147
|
+
}
|
|
148
|
+
catch {
|
|
149
|
+
return;
|
|
150
|
+
}
|
|
151
|
+
for (const name of names) {
|
|
152
|
+
if (!keep.has(name))
|
|
153
|
+
await rm(path.join(directory, name), { force: true });
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
function cached(source) {
|
|
157
|
+
return findAsset(imageName(source), [directory]);
|
|
158
|
+
}
|
|
159
|
+
return {
|
|
160
|
+
async answer(source) {
|
|
161
|
+
if (webUrl(source) === undefined || !admin.isAvatarSource(source)) {
|
|
162
|
+
return { kind: 'unknown' };
|
|
163
|
+
}
|
|
164
|
+
const held = cached(source);
|
|
165
|
+
if (held !== undefined)
|
|
166
|
+
return { kind: 'image', asset: held };
|
|
167
|
+
const failedAge = await ageOf(failedName(source));
|
|
168
|
+
if (failedAge !== undefined && failedAge < AVATAR_RETRY_MS && !inFlight.has(source)) {
|
|
169
|
+
return { kind: 'placeholder' };
|
|
170
|
+
}
|
|
171
|
+
const fetched = await within(refresh(source), firstViewWaitMs);
|
|
172
|
+
const now = fetched === true ? cached(source) : undefined;
|
|
173
|
+
return now === undefined ? { kind: 'placeholder' } : { kind: 'image', asset: now };
|
|
174
|
+
},
|
|
175
|
+
sweep() {
|
|
176
|
+
const next = sweeping.then(sweepOnce).catch((thrown) => {
|
|
177
|
+
logger.warn(`The avatar sweep failed: ${messageOf(thrown)}`);
|
|
178
|
+
});
|
|
179
|
+
sweeping = next;
|
|
180
|
+
return next;
|
|
181
|
+
},
|
|
182
|
+
start() {
|
|
183
|
+
if (handle !== undefined)
|
|
184
|
+
return;
|
|
185
|
+
void this.sweep();
|
|
186
|
+
handle = timers.set(() => void this.sweep(), AVATAR_SWEEP_MS);
|
|
187
|
+
},
|
|
188
|
+
stop() {
|
|
189
|
+
if (handle !== undefined)
|
|
190
|
+
timers.clear(handle);
|
|
191
|
+
handle = undefined;
|
|
192
|
+
},
|
|
193
|
+
async settled() {
|
|
194
|
+
await sweeping;
|
|
195
|
+
await Promise.all([...inFlight.values()]);
|
|
196
|
+
},
|
|
197
|
+
};
|
|
198
|
+
}
|
|
199
|
+
/**
|
|
200
|
+
* Fetch the picture at `source` and shrink it to {@link AVATAR_SIZE} square,
|
|
201
|
+
* as WebP. Its bytes are decoded and encoded again, so nothing but pixels of
|
|
202
|
+
* the stranger's file reaches a reader: no metadata, no second image, no
|
|
203
|
+
* script.
|
|
204
|
+
*/
|
|
205
|
+
async function fetchAvatar(source, config) {
|
|
206
|
+
const fetched = await fetchPublic(source, {
|
|
207
|
+
lookup: config.hostLookup,
|
|
208
|
+
timeoutMs: AVATAR_FETCH_TIMEOUT_MS,
|
|
209
|
+
maxBytes: AVATAR_MAX_BYTES,
|
|
210
|
+
accept: 'image/avif, image/webp, image/png, image/jpeg, image/gif;q=0.8',
|
|
211
|
+
contentType: { pattern: ACCEPTED_TYPES, name: 'a JPEG, PNG, GIF, WebP or AVIF picture' },
|
|
212
|
+
});
|
|
213
|
+
if (!fetched.ok)
|
|
214
|
+
return fetched;
|
|
215
|
+
try {
|
|
216
|
+
const decoder = sharp(fetched.body, { autoOrient: true, limitInputPixels: MAX_INPUT_PIXELS });
|
|
217
|
+
const { format } = await decoder.metadata();
|
|
218
|
+
if (format === undefined || !ACCEPTED_FORMATS.has(format)) {
|
|
219
|
+
return { ok: false, reason: `a ${String(format)} file, not a picture this site shows` };
|
|
220
|
+
}
|
|
221
|
+
const image = await decoder
|
|
222
|
+
.resize({ width: AVATAR_SIZE, height: AVATAR_SIZE, fit: 'cover', position: 'centre' })
|
|
223
|
+
.webp({ quality: 80 })
|
|
224
|
+
.toBuffer();
|
|
225
|
+
return { ok: true, image };
|
|
226
|
+
}
|
|
227
|
+
catch (thrown) {
|
|
228
|
+
return { ok: false, reason: `not a readable picture: ${messageOf(thrown)}` };
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
/** The cache file name for one URL: nothing a request can choose. */
|
|
232
|
+
function hashOf(source) {
|
|
233
|
+
return createHash('sha256').update(source).digest('hex');
|
|
234
|
+
}
|
|
235
|
+
/** Create an empty file, or move its modification time to `at`. */
|
|
236
|
+
async function touch(file, at) {
|
|
237
|
+
await writeFileAtomically(file, '');
|
|
238
|
+
await utimes(file, at, at);
|
|
239
|
+
}
|
|
240
|
+
/** What `promise` resolved to within `ms`, else `undefined`. */
|
|
241
|
+
async function within(promise, ms) {
|
|
242
|
+
let timer;
|
|
243
|
+
const timeout = new Promise((resolve) => {
|
|
244
|
+
timer = setTimeout(() => {
|
|
245
|
+
resolve(undefined);
|
|
246
|
+
}, ms);
|
|
247
|
+
timer.unref();
|
|
248
|
+
});
|
|
249
|
+
try {
|
|
250
|
+
return await Promise.race([promise, timeout]);
|
|
251
|
+
}
|
|
252
|
+
finally {
|
|
253
|
+
clearTimeout(timer);
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
function messageOf(thrown) {
|
|
257
|
+
return thrown instanceof Error ? thrown.message : String(thrown);
|
|
258
|
+
}
|
|
259
|
+
//# sourceMappingURL=avatars.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"avatars.js","sourceRoot":"","sources":["../../src/avatars/avatars.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
export { AVATAR_DIRECTORY, AVATAR_FETCH_TIMEOUT_MS, AVATAR_FIRST_VIEW_WAIT_MS, AVATAR_MAX_AGE_MS, AVATAR_MAX_BYTES, AVATAR_PATH_PREFIX, AVATAR_RETRY_MS, AVATAR_SIZE, AVATAR_SWEEP_MS, avatarHref, avatarSourceOf, createAvatarService, } from './avatars.ts';
|
|
2
|
+
export type { AvatarAnswer, AvatarLogger, AvatarService, CreateAvatarServiceOptions, } from './avatars.ts';
|
|
3
|
+
export { mountAvatars } from './routes.ts';
|
|
4
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/avatars/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,gBAAgB,EAChB,uBAAuB,EACvB,yBAAyB,EACzB,iBAAiB,EACjB,gBAAgB,EAChB,kBAAkB,EAClB,eAAe,EACf,WAAW,EACX,eAAe,EACf,UAAU,EACV,cAAc,EACd,mBAAmB,GACpB,MAAM,cAAc,CAAC;AACtB,YAAY,EACV,YAAY,EACZ,YAAY,EACZ,aAAa,EACb,0BAA0B,GAC3B,MAAM,cAAc,CAAC;AACtB,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC"}
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
export { AVATAR_DIRECTORY, AVATAR_FETCH_TIMEOUT_MS, AVATAR_FIRST_VIEW_WAIT_MS, AVATAR_MAX_AGE_MS, AVATAR_MAX_BYTES, AVATAR_PATH_PREFIX, AVATAR_RETRY_MS, AVATAR_SIZE, AVATAR_SWEEP_MS, avatarHref, avatarSourceOf, createAvatarService, } from './avatars.js';
|
|
2
|
+
export { mountAvatars } from './routes.js';
|
|
3
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/avatars/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,gBAAgB,EAChB,uBAAuB,EACvB,yBAAyB,EACzB,iBAAiB,EACjB,gBAAgB,EAChB,kBAAkB,EAClB,eAAe,EACf,WAAW,EACX,eAAe,EACf,UAAU,EACV,cAAc,EACd,mBAAmB,GACpB,MAAM,cAAc,CAAC;AAOtB,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { Hono } from 'hono';
|
|
2
|
+
import type { GeekityEnv } from '../env.ts';
|
|
3
|
+
/**
|
|
4
|
+
* Register the avatar route. Mounted by the public site, under `/_geekity/`
|
|
5
|
+
* like its other endpoints, so no permalink can take it.
|
|
6
|
+
*
|
|
7
|
+
* It is not exempt from maintenance mode: the only pages that show an avatar
|
|
8
|
+
* are posts, and those are a 503 then too.
|
|
9
|
+
*/
|
|
10
|
+
export declare function mountAvatars(app: Hono<GeekityEnv>): void;
|
|
11
|
+
//# sourceMappingURL=routes.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"routes.d.ts","sourceRoot":"","sources":["../../src/avatars/routes.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAEjC,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC;AAU5C;;;;;;GAMG;AACH,wBAAgB,YAAY,CAAC,GAAG,EAAE,IAAI,CAAC,UAAU,CAAC,GAAG,IAAI,CAwBxD"}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { assetNotModified, assetResponse, matchesEtag } from '../web/assets.js';
|
|
2
|
+
import { AVATAR_MAX_AGE_SECONDS, AVATAR_PATH_PREFIX, AVATAR_PLACEHOLDER_MAX_AGE_SECONDS, AVATAR_PLACEHOLDER_SVG, avatarSourceOf, } from './avatars.js';
|
|
3
|
+
/**
|
|
4
|
+
* Register the avatar route. Mounted by the public site, under `/_geekity/`
|
|
5
|
+
* like its other endpoints, so no permalink can take it.
|
|
6
|
+
*
|
|
7
|
+
* It is not exempt from maintenance mode: the only pages that show an avatar
|
|
8
|
+
* are posts, and those are a 503 then too.
|
|
9
|
+
*/
|
|
10
|
+
export function mountAvatars(app) {
|
|
11
|
+
app.get(`${AVATAR_PATH_PREFIX}:key`, async (c) => {
|
|
12
|
+
const source = avatarSourceOf(c.req.param('key'));
|
|
13
|
+
const answer = source === undefined ? { kind: 'unknown' } : await c.var.avatars.answer(source);
|
|
14
|
+
switch (answer.kind) {
|
|
15
|
+
case 'unknown':
|
|
16
|
+
return c.text('Not Found', 404);
|
|
17
|
+
case 'placeholder':
|
|
18
|
+
return new Response(AVATAR_PLACEHOLDER_SVG, {
|
|
19
|
+
headers: {
|
|
20
|
+
'content-type': 'image/svg+xml',
|
|
21
|
+
'cache-control': `public, max-age=${String(AVATAR_PLACEHOLDER_MAX_AGE_SECONDS)}`,
|
|
22
|
+
},
|
|
23
|
+
});
|
|
24
|
+
case 'image': {
|
|
25
|
+
const options = { maxAge: AVATAR_MAX_AGE_SECONDS };
|
|
26
|
+
return matchesEtag(c.req.header('if-none-match'), answer.asset.etag)
|
|
27
|
+
? assetNotModified(answer.asset, options)
|
|
28
|
+
: assetResponse(answer.asset, options);
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
});
|
|
32
|
+
}
|
|
33
|
+
//# sourceMappingURL=routes.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"routes.js","sourceRoot":"","sources":["../../src/avatars/routes.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,gBAAgB,EAAE,aAAa,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAChF,OAAO,EACL,sBAAsB,EACtB,kBAAkB,EAClB,kCAAkC,EAClC,sBAAsB,EACtB,cAAc,GACf,MAAM,cAAc,CAAC;AAEtB;;;;;;GAMG;AACH,MAAM,UAAU,YAAY,CAAC,GAAqB;IAChD,GAAG,CAAC,GAAG,CAAC,GAAG,kBAAkB,MAAM,EAAE,KAAK,EAAE,CAAC,EAAE,EAAE;QAC/C,MAAM,MAAM,GAAG,cAAc,CAAC,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC;QAClD,MAAM,MAAM,GACV,MAAM,KAAK,SAAS,CAAC,CAAC,CAAE,EAAE,IAAI,EAAE,SAAS,EAAY,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;QAE7F,QAAQ,MAAM,CAAC,IAAI,EAAE,CAAC;YACpB,KAAK,SAAS;gBACZ,OAAO,CAAC,CAAC,IAAI,CAAC,WAAW,EAAE,GAAG,CAAC,CAAC;YAClC,KAAK,aAAa;gBAChB,OAAO,IAAI,QAAQ,CAAC,sBAAsB,EAAE;oBAC1C,OAAO,EAAE;wBACP,cAAc,EAAE,eAAe;wBAC/B,eAAe,EAAE,mBAAmB,MAAM,CAAC,kCAAkC,CAAC,EAAE;qBACjF;iBACF,CAAC,CAAC;YACL,KAAK,OAAO,EAAE,CAAC;gBACb,MAAM,OAAO,GAAG,EAAE,MAAM,EAAE,sBAAsB,EAAE,CAAC;gBACnD,OAAO,WAAW,CAAC,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,eAAe,CAAC,EAAE,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC;oBAClE,CAAC,CAAC,gBAAgB,CAAC,MAAM,CAAC,KAAK,EAAE,OAAO,CAAC;oBACzC,CAAC,CAAC,aAAa,CAAC,MAAM,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC;YAC3C,CAAC;QACH,CAAC;IACH,CAAC,CAAC,CAAC;AACL,CAAC"}
|
package/dist/comments/index.d.ts
CHANGED
|
@@ -7,8 +7,8 @@ export { isModerationAction, moderateComment, MODERATION_ACTIONS } from './moder
|
|
|
7
7
|
export type { ModerateCommentOptions, ModerationAction, ModerationOutcome } from './moderate.ts';
|
|
8
8
|
export { COMMENTS_FRONT_MATTER_KEY, commentPolicyOf, commentsOpen, DEFAULT_COMMENTS_CLOSE_AFTER_DAYS, } from './policy.ts';
|
|
9
9
|
export type { CommentPolicy } from './policy.ts';
|
|
10
|
-
export { addComment, COMMENTS_DATA_DIRECTORY, commentsDirectory, commentsFile, deleteComment, heldWebmention, intakeComment, readComments, rebuildCommentIndexes, updateComment, } from './records.ts';
|
|
11
|
-
export type { CommentIndexReport, CommentIntakeOutcome, CommentNotices, CommentOrigin, CommentRecords, IntakeCommentOptions, NewComment, ProposedComment, } from './records.ts';
|
|
10
|
+
export { addComment, COMMENT_EMAILS_DIRECTORY, COMMENT_EMAILS_FILE_MODE, commentEmailsFile, COMMENTS_DATA_DIRECTORY, commentsDirectory, commentsFile, deleteComment, heldWebmention, intakeComment, migrateCommentEmails, readComments, rebuildCommentIndexes, updateComment, } from './records.ts';
|
|
11
|
+
export type { CommentEmailMigrationReport, CommentIndexReport, CommentIntakeOutcome, CommentNotices, CommentOrigin, CommentRecords, IntakeCommentOptions, NewComment, ProposedComment, } from './records.ts';
|
|
12
12
|
export { commentFormFor, commentNoticeFor, mountComments } from './routes.ts';
|
|
13
13
|
export { COMMENT_FIELDS, COMMENT_RATE_LIMIT, COMMENT_RATE_WINDOW_SECONDS, COMMENT_SALT_FILE, commentKeys, commentProblems, hashClientAddress, MAXIMUM_BODY_LENGTH, MAXIMUM_NAME_LENGTH, MAXIMUM_URL_LENGTH, MAXIMUM_FORM_AGE_SECONDS, MINIMUM_SUBMIT_SECONDS, normalizeWebsite, submitComment, } from './submission.ts';
|
|
14
14
|
export type { CommentChecker, CommentForm, CommentOutcome, CommentProblems, CommentRefusal, CommentReport, CommentSubmission, SubmissionType, CommentThrottle, CommentVerdict, SignedInAuthor, SubmitCommentOptions, } from './submission.ts';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/comments/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,gBAAgB,EAChB,gBAAgB,EAChB,kBAAkB,EAClB,kBAAkB,EAClB,cAAc,EACd,oBAAoB,EACpB,cAAc,EACd,gBAAgB,EAChB,gBAAgB,EAChB,eAAe,GAChB,MAAM,cAAc,CAAC;AACtB,YAAY,EACV,qBAAqB,EACrB,gBAAgB,EAChB,gBAAgB,EAChB,uBAAuB,GACxB,MAAM,cAAc,CAAC;AACtB,OAAO,EACL,WAAW,EACX,oBAAoB,EACpB,eAAe,EACf,iBAAiB,EACjB,mBAAmB,EACnB,WAAW,EACX,mBAAmB,EACnB,mBAAmB,EACnB,QAAQ,GACT,MAAM,WAAW,CAAC;AACnB,YAAY,EAAE,kBAAkB,EAAE,aAAa,EAAE,MAAM,WAAW,CAAC;AACnE,OAAO,EAAE,qBAAqB,EAAE,MAAM,eAAe,CAAC;AACtD,OAAO,EAAE,kBAAkB,EAAE,eAAe,EAAE,kBAAkB,EAAE,MAAM,eAAe,CAAC;AACxF,YAAY,EAAE,sBAAsB,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAC;AACjG,OAAO,EACL,yBAAyB,EACzB,eAAe,EACf,YAAY,EACZ,iCAAiC,GAClC,MAAM,aAAa,CAAC;AACrB,YAAY,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AACjD,OAAO,EACL,UAAU,EACV,uBAAuB,EACvB,iBAAiB,EACjB,YAAY,EACZ,aAAa,EACb,cAAc,EACd,aAAa,EACb,YAAY,EACZ,qBAAqB,EACrB,aAAa,GACd,MAAM,cAAc,CAAC;AACtB,YAAY,EACV,kBAAkB,EAClB,oBAAoB,EACpB,cAAc,EACd,aAAa,EACb,cAAc,EACd,oBAAoB,EACpB,UAAU,EACV,eAAe,GAChB,MAAM,cAAc,CAAC;AACtB,OAAO,EAAE,cAAc,EAAE,gBAAgB,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAC9E,OAAO,EACL,cAAc,EACd,kBAAkB,EAClB,2BAA2B,EAC3B,iBAAiB,EACjB,WAAW,EACX,eAAe,EACf,iBAAiB,EACjB,mBAAmB,EACnB,mBAAmB,EACnB,kBAAkB,EAClB,wBAAwB,EACxB,sBAAsB,EACtB,gBAAgB,EAChB,aAAa,GACd,MAAM,iBAAiB,CAAC;AACzB,YAAY,EACV,cAAc,EACd,WAAW,EACX,cAAc,EACd,eAAe,EACf,cAAc,EACd,aAAa,EACb,iBAAiB,EACjB,cAAc,EACd,eAAe,EACf,cAAc,EACd,cAAc,EACd,oBAAoB,GACrB,MAAM,iBAAiB,CAAC;AACzB,OAAO,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/comments/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,gBAAgB,EAChB,gBAAgB,EAChB,kBAAkB,EAClB,kBAAkB,EAClB,cAAc,EACd,oBAAoB,EACpB,cAAc,EACd,gBAAgB,EAChB,gBAAgB,EAChB,eAAe,GAChB,MAAM,cAAc,CAAC;AACtB,YAAY,EACV,qBAAqB,EACrB,gBAAgB,EAChB,gBAAgB,EAChB,uBAAuB,GACxB,MAAM,cAAc,CAAC;AACtB,OAAO,EACL,WAAW,EACX,oBAAoB,EACpB,eAAe,EACf,iBAAiB,EACjB,mBAAmB,EACnB,WAAW,EACX,mBAAmB,EACnB,mBAAmB,EACnB,QAAQ,GACT,MAAM,WAAW,CAAC;AACnB,YAAY,EAAE,kBAAkB,EAAE,aAAa,EAAE,MAAM,WAAW,CAAC;AACnE,OAAO,EAAE,qBAAqB,EAAE,MAAM,eAAe,CAAC;AACtD,OAAO,EAAE,kBAAkB,EAAE,eAAe,EAAE,kBAAkB,EAAE,MAAM,eAAe,CAAC;AACxF,YAAY,EAAE,sBAAsB,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAC;AACjG,OAAO,EACL,yBAAyB,EACzB,eAAe,EACf,YAAY,EACZ,iCAAiC,GAClC,MAAM,aAAa,CAAC;AACrB,YAAY,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AACjD,OAAO,EACL,UAAU,EACV,wBAAwB,EACxB,wBAAwB,EACxB,iBAAiB,EACjB,uBAAuB,EACvB,iBAAiB,EACjB,YAAY,EACZ,aAAa,EACb,cAAc,EACd,aAAa,EACb,oBAAoB,EACpB,YAAY,EACZ,qBAAqB,EACrB,aAAa,GACd,MAAM,cAAc,CAAC;AACtB,YAAY,EACV,2BAA2B,EAC3B,kBAAkB,EAClB,oBAAoB,EACpB,cAAc,EACd,aAAa,EACb,cAAc,EACd,oBAAoB,EACpB,UAAU,EACV,eAAe,GAChB,MAAM,cAAc,CAAC;AACtB,OAAO,EAAE,cAAc,EAAE,gBAAgB,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAC9E,OAAO,EACL,cAAc,EACd,kBAAkB,EAClB,2BAA2B,EAC3B,iBAAiB,EACjB,WAAW,EACX,eAAe,EACf,iBAAiB,EACjB,mBAAmB,EACnB,mBAAmB,EACnB,kBAAkB,EAClB,wBAAwB,EACxB,sBAAsB,EACtB,gBAAgB,EAChB,aAAa,GACd,MAAM,iBAAiB,CAAC;AACzB,YAAY,EACV,cAAc,EACd,WAAW,EACX,cAAc,EACd,eAAe,EACf,cAAc,EACd,aAAa,EACb,iBAAiB,EACjB,cAAc,EACd,eAAe,EACf,cAAc,EACd,cAAc,EACd,oBAAoB,GACrB,MAAM,iBAAiB,CAAC;AACzB,OAAO,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC"}
|
package/dist/comments/index.js
CHANGED
|
@@ -3,7 +3,7 @@ export { blankValues, COMMENT_NOTICE_PARAM, COMMENT_NOTICES, COMMENT_POST_PATH,
|
|
|
3
3
|
export { renderCommentMarkdown } from './markdown.js';
|
|
4
4
|
export { isModerationAction, moderateComment, MODERATION_ACTIONS } from './moderate.js';
|
|
5
5
|
export { COMMENTS_FRONT_MATTER_KEY, commentPolicyOf, commentsOpen, DEFAULT_COMMENTS_CLOSE_AFTER_DAYS, } from './policy.js';
|
|
6
|
-
export { addComment, COMMENTS_DATA_DIRECTORY, commentsDirectory, commentsFile, deleteComment, heldWebmention, intakeComment, readComments, rebuildCommentIndexes, updateComment, } from './records.js';
|
|
6
|
+
export { addComment, COMMENT_EMAILS_DIRECTORY, COMMENT_EMAILS_FILE_MODE, commentEmailsFile, COMMENTS_DATA_DIRECTORY, commentsDirectory, commentsFile, deleteComment, heldWebmention, intakeComment, migrateCommentEmails, readComments, rebuildCommentIndexes, updateComment, } from './records.js';
|
|
7
7
|
export { commentFormFor, commentNoticeFor, mountComments } from './routes.js';
|
|
8
8
|
export { COMMENT_FIELDS, COMMENT_RATE_LIMIT, COMMENT_RATE_WINDOW_SECONDS, COMMENT_SALT_FILE, commentKeys, commentProblems, hashClientAddress, MAXIMUM_BODY_LENGTH, MAXIMUM_NAME_LENGTH, MAXIMUM_URL_LENGTH, MAXIMUM_FORM_AGE_SECONDS, MINIMUM_SUBMIT_SECONDS, normalizeWebsite, submitComment, } from './submission.js';
|
|
9
9
|
export { signedInCommenter } from './viewer.js';
|