Move away from an enricher in favour of the chatMessage hook handling (closes #23)
This commit is contained in:
parent
97f8e293d2
commit
064b4c1304
1 changed files with 64 additions and 61 deletions
|
|
@ -3,8 +3,6 @@ import { __ID__ } from "../consts.mjs";
|
|||
import { Logger } from "../utils/Logger.mjs";
|
||||
import { preventTweakRegistration } from "../utils/preRegisterTweak.mjs";
|
||||
|
||||
// const { DialogV2 } = foundry.applications.api;
|
||||
|
||||
const key = `chatImageLinks`;
|
||||
const IMAGE_TYPES = [
|
||||
`png`,
|
||||
|
|
@ -18,6 +16,9 @@ export function chatImageLinks() {
|
|||
status[key] = SettingStatusEnum.Unknown;
|
||||
if (preventTweakRegistration(key)) { return };
|
||||
|
||||
/** @type {number|null} */
|
||||
let hookID = null;
|
||||
|
||||
// #region Registration
|
||||
Logger.log(`Registering setting: ${key}`);
|
||||
game.settings.register(__ID__, key, {
|
||||
|
|
@ -28,6 +29,13 @@ export function chatImageLinks() {
|
|||
default: true,
|
||||
config: true,
|
||||
requiresReload: true,
|
||||
onChange: (newValue) => {
|
||||
if (newValue) {
|
||||
hookID = Hooks.on(`chatMessage`, chatMessageHandler);
|
||||
} else if (hookID != null) {
|
||||
Hooks.off(`chatMessage`, hookID);
|
||||
};
|
||||
},
|
||||
});
|
||||
|
||||
game.settings.register(__ID__, key + `-showPromptAgain`, {
|
||||
|
|
@ -40,76 +48,71 @@ export function chatImageLinks() {
|
|||
|
||||
// #region Implementation
|
||||
if (game.settings.get(__ID__, key)) {
|
||||
Logger.log(`setting:${key} | Adding text enricher`);
|
||||
|
||||
// MARK: Enricher
|
||||
const pattern = new RegExp(
|
||||
`(?<!=|")(image:\\/\\/.*\\.(?:${IMAGE_TYPES.join(`|`)}))`,
|
||||
`gi`,
|
||||
);
|
||||
|
||||
CONFIG.TextEditor.enrichers.push({
|
||||
pattern,
|
||||
replaceParent: true,
|
||||
enricher: async (url) => {
|
||||
Logger.debug(url);
|
||||
url = url[0].replace(/^image:\/\//, ``);
|
||||
const secure = `https://${url}`;
|
||||
const insecure = `http://${url}`;
|
||||
|
||||
if (await isAcceptableImage(secure)) {
|
||||
const img = document.createElement(`img`);
|
||||
img.src = secure;
|
||||
img.alt = secure;
|
||||
return img;
|
||||
};
|
||||
|
||||
if (await isAcceptableImage(insecure)) {
|
||||
const img = document.createElement(`img`);
|
||||
img.src = insecure;
|
||||
img.alt = insecure;
|
||||
return img;
|
||||
};
|
||||
|
||||
return null;
|
||||
},
|
||||
});
|
||||
|
||||
// MARK: Chat Input
|
||||
// Hooks.on(`chatMessage`, (chatLog, message, options) => {
|
||||
// if (!game.settings.get(__ID__, key)) { return };
|
||||
|
||||
// const match = message.match(pattern);
|
||||
// if (!match) { return };
|
||||
|
||||
// DialogV2.wait({
|
||||
// rejectClose: false,
|
||||
// content: game.i18n.localize(`OFT.dialogs.chatImageLinks.didYouKnowImageLink`),
|
||||
// buttons: [
|
||||
// { action: ``, label: `OFT.dialogs.chatImageLinks.convertAndDontShowAgain` },
|
||||
// { action: ``, label: `OFT.dialogs.chatImageLinks.justConvert` },
|
||||
// { action: ``, label: `OFT.dialogs.chatImageLinks.ignoreAndDontShowAgain` },
|
||||
// { action: ``, label: `OFT.dialogs.chatImageLinks.disableEntirely` },
|
||||
// ],
|
||||
// })
|
||||
// .then((selected) => {
|
||||
// chatLog.processMessage(message, options);
|
||||
// });
|
||||
|
||||
// return false;
|
||||
// });
|
||||
}
|
||||
Logger.log(`setting:${key} | Adding chat message listener`);
|
||||
Hooks.on(`chatMessage`, chatMessageHandler);
|
||||
};
|
||||
// #endregion Implementation
|
||||
|
||||
status[key] = SettingStatusEnum.Registered;
|
||||
};
|
||||
|
||||
// #region Helpers
|
||||
const pattern = new RegExp(
|
||||
`https?:\\/\\/\\S*\\.(?:${IMAGE_TYPES.join(`|`)})`,
|
||||
`gi`,
|
||||
);
|
||||
|
||||
// MARK: Mutate & Resend
|
||||
const handled = new Set();
|
||||
async function mutateAndResendMessage(chatLog, message, options) {
|
||||
const match = message.match(pattern);
|
||||
if (!match) { return };
|
||||
|
||||
const validMatches = new Set();
|
||||
|
||||
const matches = message.match(pattern);
|
||||
for (const match of matches) {
|
||||
if (await isAcceptableImage(match)) {
|
||||
validMatches.add(match);
|
||||
};
|
||||
};
|
||||
|
||||
message = message.replaceAll(
|
||||
pattern,
|
||||
(url) => {
|
||||
if (!validMatches.has(url)) {
|
||||
return url;
|
||||
};
|
||||
return `<img src="${url}" alt="${url}">`;
|
||||
},
|
||||
);
|
||||
|
||||
handled.add(message);
|
||||
chatLog.processMessage(message, options);
|
||||
};
|
||||
|
||||
// MARK: Chat Message
|
||||
/**
|
||||
* Must be synchronous since it is a hook handler, but the mutation +
|
||||
* resending can be done asynchronously since it doesn't matter how
|
||||
* long it takes.
|
||||
*/
|
||||
function chatMessageHandler(chatLog, message, options) {
|
||||
if (!game.settings.get(__ID__, key)) { return };
|
||||
if (handled.has(message)) { return };
|
||||
mutateAndResendMessage(chatLog, message, options);
|
||||
return false;
|
||||
};
|
||||
|
||||
// MARK: isAcceptableImage
|
||||
async function isAcceptableImage(url) {
|
||||
if (!URL.canParse(url)) { return false };
|
||||
|
||||
try {
|
||||
const response = await fetch(url, { method: `HEAD` });
|
||||
const contentType = response.headers.get(`Content-Type`);
|
||||
Logger.debug(`Image data:`, { url, contentType });
|
||||
|
||||
let [ superType, subtype ] = contentType.split(`/`);
|
||||
if (superType !== `image`) {
|
||||
return false;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue