Skip to content

Commit

Permalink
Better testing, improvement to the identifier regular expression. Mis…
Browse files Browse the repository at this point in the history
…c. minor improvements.
  • Loading branch information
chrisdenman committed Jun 3, 2024
1 parent fe1457c commit 8c0f3d9
Show file tree
Hide file tree
Showing 9 changed files with 106 additions and 117 deletions.
13 changes: 12 additions & 1 deletion src/__tests__/application.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,17 @@ describe("Application startup and shutdown", () => {
vi.restoreAllMocks();
});

it("That login errors as swallowed.", () => {
application.start(TOKEN);
client.login = vi.fn().mockImplementationOnce(() => {
console.log("WOT");
new Promise((_, error) => {
error("login failed");
throw new Error("logg-in failed");
});
});
});

it("That messages authored by other bots are ignored even if they contain attachments that could be prompted in respect of.", () => {
application.start(TOKEN);
discordInterfaceHarness.onClientReady();
Expand Down Expand Up @@ -237,7 +248,7 @@ describe("Application startup and shutdown", () => {
await new Promise(resolve => setTimeout(resolve, 2000));
discordInterfaceHarness.onMessageUpdate(userMessage, updatedUserMessage);
expect(updatedUserMessage.channel.messages.delete).not.toHaveBeenCalled();

application.stop();
}
);
Expand Down
168 changes: 70 additions & 98 deletions src/__tests__/id-bot-message.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,114 +6,86 @@ import {Factory} from "../js/factory";
const factory = new Factory();

describe(
"Emoji character counting in message content",
"Emoji, custom-emoji and image-identifier counting..",
() => [
["", 0, 0],
[" ", 0, 0],
["\u{0023}", 0, 0],
["\u{0030}", 0, 0],
["\u{0039}", 0, 0],
["\u{00AE}", 0, 0],
["🫸", 1, 0],
["🫸🫸", 2, 0],
[" 🫸🫸", 2, 0],
["🫸🫸 ", 2, 0],
[" 🫸🫸 ", 2, 0],
["<:blah:345802398509358903485093>🫸", 1, 1],
["<:name:1245079798410121307>", 0, 1],
["<a:name:1245079798410121307>", 0, 1],
["<:n:1245079798410121307>", 0, 1],
["<a:n:1245079798410121307>", 0, 1],
["<:name:1>", 0, 1],
["<a:name:1>", 0, 1],
["<:n:1>", 0, 1],
["<a:n:1>", 0, 1],
["<a:-:a>", 0, 0],
["<a:n:a>", 0, 0],
["<b:n:1>", 0, 0],
["<ab:n:1>", 0, 0],
["<ba:n:1>", 0, 0],
["<::1245079798410121307>", 0, 0],
["<a::1245079798410121307>", 0, 0],
["<::1>", 0, 0],
["<a::1>", 0, 0],
["<:name:>", 0, 0],
["<a:name:>", 0, 0],
["<:n:>", 0, 0],
["<a:n:>", 0, 0],
[":name:1245079798410121307>", 0, 0],
["a:name:1245079798410121307>", 0, 0],
[":n:1245079798410121307>", 0, 0],
["a:n:1245079798410121307>", 0, 0],
[":name:1>", 0, 0],
["a:name:1>", 0, 0],
[":n:1>", 0, 0],
["a:n:1>", 0, 0],
["<:name:1245079798410121307", 0, 0],
["<a:name:1245079798410121307", 0, 0],
["<:n:1245079798410121307", 0, 0],
["<a:n:1245079798410121307", 0, 0],
["<:name:1", 0, 0],
["<a:name:1", 0, 0],
["<:n:1", 0, 0],
["<a:n:1", 0, 0],
[":name:1245079798410121307", 0, 0],
["a:name:1245079798410121307", 0, 0],
[":n:1245079798410121307", 0, 0],
["a:n:1245079798410121307", 0, 0],
[":name:1", 0, 0],
["a:name:1", 0, 0],
[":n:1", 0, 0],
["a:n:1", 0, 0],
["🫸<:id:3458>", 1, 1],
["🫸<:custom_emoji:3458>🫸", 2, 1],
["<:custom:3454458>🫸<:fish:3453453453458>🫸<:something:3458>", 2, 3],
].forEach(([messageContent, expectedEmojiCount, expectedCustomEmojiCount]) =>
["", 0, 0, 0],
[" ID:", 0, 0, 0],
// ["\u{0023}ID: a", 0, 0, 0],
["\u{0030}ID: a", 0, 0, 0],
["\u{0039}id: ", 0, 0, 0],
["\u{00AE}iD: a", 0, 0, 0],
["ID: a🫸", 1, 0, 1],
["ID: 🫸 ID: 🫸", 2, 0, 0],
["ID: a🫸 ID: a🫸", 2, 0, 2],
[" 🫸🫸ID: ", 2, 0, 0],
["🫸ID: x🫸 ", 2, 0, 1],
[" 🫸ID: 🫸ID: ", 2, 0, 0],
["<:blah:345802398509358903485093> ID: a🫸", 1, 1, 1],
["<:name:1245079798410121307>ID: ", 0, 1, 0],
["ID: something <a:name:1245079798410121307>", 0, 1, 1],
["ID: s <:n:1245079798410121307> ID: d", 0, 1, 2],
["<a:n:1245079798410121307>WID: ", 0, 1, 0],
["<:name:1>", 0, 1, 0],
["<a:name:1>", 0, 1, 0],
["<:n:1>", 0, 1, 0],
["<a:n:1>", 0, 1, 0],
["<a:-:a>", 0, 0, 0],
["<a:n:a>", 0, 0, 0],
["<b:n:1>", 0, 0, 0],
["<ab:n:1>", 0, 0, 0],
["<ba:n:1>", 0, 0, 0],
["<::1245079798410121307>", 0, 0, 0],
["<a::1245079798410121307>ID: abcsID: abcd.", 0, 0, 1],
["<::1>", 0, 0, 0],
["<a::1>", 0, 0, 0],
["<:name:>", 0, 0, 0],
["<a:name:>", 0, 0, 0],
["<:n:>", 0, 0, 0],
["<a:n:>", 0, 0, 0],
[":name:1245079798410121307>", 0, 0, 0],
["a:name:1245079798410121307>", 0, 0, 0],
[":n:1245079798410121307>", 0, 0, 0],
["a:n:1245079798410121307>", 0, 0, 0],
[":name:1>", 0, 0, 0],
["a:name:1>", 0, 0, 0],
[":n:1>", 0, 0, 0],
["a:n:1>", 0, 0, 0],
["<:name:1245079798410121307", 0, 0, 0],
["<a:name:1245079798410121307", 0, 0, 0],
["<:n:1245079798410121307", 0, 0, 0],
["<a:n:1245079798410121307", 0, 0, 0],
["<:name:1", 0, 0, 0],
["<a:name:1", 0, 0, 0],
["<:n:1", 0, 0, 0],
["<a:n:1", 0, 0, 0],
[":name:1245079798410121307", 0, 0, 0],
["a:name:1245079798410121307", 0, 0, 0],
[":n:1245079798410121307", 0, 0, 0],
["a:n:1245079798410121307", 0, 0, 0],
[":name:1", 0, 0, 0],
["a:name:1 ID: abcs.ID: abcd.", 0, 0, 2],
[":n:1", 0, 0, 0],
["a:n:1", 0, 0, 0],
["🫸<:id:3458>", 1, 1, 0],
["🫸<:custom_emoji:3458>🫸", 2, 1, 0],
["<:custom:3454458>🫸<:fish:3453453453458>🫸<:something:3458>", 2, 3, 0],
[`<:custom:3454458> ID: a custom emoji ID: whoopee
🐈ID: an emoji of a cat. ID: an emoji of a castle
🏰`, 2, 1, 4],
].forEach(([content, expectedEmojiCount, expectedCustomEmojiCount, expectedImageIdCount]) =>
it(
`That "${messageContent}" contains ${expectedEmojiCount} emoji characters and ${expectedCustomEmojiCount} custom emoji references.`,
`That "${content}" contains ${expectedEmojiCount} emoji characters and ${expectedCustomEmojiCount} custom emoji references and ${expectedImageIdCount} image ids.`,
() => {
const imageIdStats = factory
.createIdBotMessage({
id: createUuid(),
attachments: new Map(),
content: messageContent
content
}).imageIdStats;
expect(imageIdStats.emojiCount).toBe(expectedEmojiCount);
expect(imageIdStats.customEmojiCount).toBe(expectedCustomEmojiCount);
}
)
)
);


describe(
"Image ID counting in message content",
() => [
["", 0],
[" ", 0],
["ID:", 0],
["ID: a", 1],
["ID: ab", 1],
["ID: abc", 1],
["ID: abcd", 1],
["ID: abcd. ID: abcd.", 2],
["ID: abcd. ID: a", 2],
["ID: aID: abcd.", 1],
["ID: abcsID: abcd.", 1],
["ID: abcs. ID: abcd.", 2],
["ID: abcs ID: abcd. ID: abcd", 3]
].forEach(([messageContent, expectedImageIdCount]) =>
it(
`That "${messageContent}" contains ${expectedImageIdCount} identifiers`,
() => {
const discordMessage = factory
.createIdBotMessage({
id: createUuid(),
attachments: new Map(),
content: messageContent
});

expect(discordMessage.imageIdStats.imageIdentifierCount).toBe(expectedImageIdCount);
expect(imageIdStats.imageIdentifierCount).toBe(expectedImageIdCount);
}
)
)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
class MaxStaleCacheManager {
class CacheMaxStaleManager {

/**
* @type {Cache}
Expand Down Expand Up @@ -98,5 +98,5 @@ class MaxStaleCacheManager {
}

export {
MaxStaleCacheManager
CacheMaxStaleManager
};
2 changes: 1 addition & 1 deletion src/js/cache.js
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@ class Cache {
}

toString() {
return `Cache(ktv=${this.#keyToValue}, ktm=${this.#keyToMetaData}, )`;
return `Cache(ktv=${[...this.#keyToValue.entries()]}, ktm=${[...this.#keyToMetaData.entries()]}, )`;
}
}

Expand Down
1 change: 1 addition & 0 deletions src/js/durations-ms.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ const SECONDS_PER_MINUTE = 60;
const MINUTES_PER_HOUR = 60;
const HOURS_PER_DAY = 24;

// noinspection PointlessArithmeticExpressionJS
const ONE_SECOND_MILLI_SECONDS = 1 * MS_PER_SECOND;
const ONE_MINUTE_MILLI_SECONDS = ONE_SECOND_MILLI_SECONDS * SECONDS_PER_MINUTE;
const ONE_HOUR_MILLI_SECONDS = ONE_MINUTE_MILLI_SECONDS * MINUTES_PER_HOUR;
Expand Down
6 changes: 3 additions & 3 deletions src/js/factory.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import {Client} from "discord.js";
import {GatewayIntentBits} from "discord-api-types/v10";
import {DiscordInterface} from "./discord-interface.js";
import {Application} from "./application.js";
import {MaxStaleCacheManager} from "./max-stale-cache-manager.js";
import {CacheMaxStaleManager} from "./cache-max-stale-manager.js";

const CLIENT_OPTIONS = {
intents: [
Expand All @@ -29,10 +29,10 @@ class Factory {
* @param {Cache} cache
* @param {number} tickIntervalDurationMilliSeconds
* @param {number} maxStaleLifetimeMilliSeconds
* @returns {MaxStaleCacheManager}
* @returns {CacheMaxStaleManager}
*/
createCacheExpirator(cache, tickIntervalDurationMilliSeconds = 100, maxStaleLifetimeMilliSeconds = undefined) {
return new MaxStaleCacheManager(
return new CacheMaxStaleManager(
cache, this.createLogger("MaxStaleCacheManager"),
this,
tickIntervalDurationMilliSeconds,
Expand Down
5 changes: 3 additions & 2 deletions src/js/id-bot-message.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ class IdBotMessage {
/**
* @type RegExp
*/
#MESSAGE_ID_VALIDATING_REGEXP = /(?<=(^|\s|\W)ID:\s*)(\w+)(?!\WID:)/svg;
#MESSAGE_ID_REGEXP = /(?<=(^|\s|\W)ID:\s*)(\w+)(?!\WID:)/svg;

/**
* @type RegExp
Expand All @@ -41,6 +41,7 @@ class IdBotMessage {
}

get referencedMessageId() {
// noinspection JSUnresolvedReference
return this.#discordJsMessage?.reference?.messageId;
}

Expand Down Expand Up @@ -118,7 +119,7 @@ class IdBotMessage {
const contentStrippedOfCustomEmoji = content.replaceAll(this.#CUSTOM_EMOJI_REGEX, "");
const numberOfEmoji = numberOfEmojiContained(contentStrippedOfCustomEmoji);

const idMatches = [...content.matchAll(this.#MESSAGE_ID_VALIDATING_REGEXP)];
const idMatches = [...content.matchAll(this.#MESSAGE_ID_REGEXP)];

this.#imageIdStats = factory.createImageIdStats(
[...discordJsMessage.attachments.values()]
Expand Down
20 changes: 12 additions & 8 deletions src/js/id-bot.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,14 +14,16 @@ class IdBot {
#discordInterface;

/**
* A cache that maps: the original message id to reminder message id.
*
* @type Cache
*/
#cache;

/**
* @type MaxStaleCacheManager
* @type CacheMaxStaleManager
*/
#maxStaleCacheManager;
#cacheMaxStaleManager;

/**
* @type Logger
Expand Down Expand Up @@ -55,14 +57,15 @@ class IdBot {
if (replyId) {
this.#deleteChannelMessage(message.channel, replyId);
this.#cache.remove(messageId);
this.#logger.debug(this.#cache);
} else {
this.#logger.warn(`${message.toIdString()} has no known replies`);
}
}

#onClientReady() {
this.#logger.info(`Ready`);
this.#maxStaleCacheManager.start();
this.#cacheMaxStaleManager.start();
}

/**
Expand Down Expand Up @@ -95,6 +98,7 @@ class IdBot {
this.#logger.debug(`${message.toIdString()} is our new reminder reply to ${referencedMessageId}."`);

this.#cache.set(referencedMessageId, message.id);
this.#logger.debug(this.#cache);
}
}
};
Expand All @@ -112,9 +116,9 @@ class IdBot {
const imageIdStats = updatedMessage.imageIdStats;

if (!imageIdStats.isCorrectlyIdentified) {
this.#deleteOurReplyTo(updatedMessage);
const replyMessageContent = this.#reminderMessage(imageIdStats);
this.#logger.debug(`${updatedMessage.toIdString()} not correctly identified, replying with "${replyMessageContent}"`);
this.#deleteOurReplyTo(updatedMessage);
this.#discordInterface.replyTo(updatedMessage, replyMessageContent);
} else {
this.#deleteOurReplyTo(updatedMessage);
Expand All @@ -136,18 +140,18 @@ class IdBot {

/**
* @param {Cache} cache
* @param {MaxStaleCacheManager} maxStaleCacheManager
* @param {CacheMaxStaleManager} cacheMaxStaleManager
* @param {DiscordInterface} discordInterface
* @param {Logger} logger
*/
constructor(
cache,
maxStaleCacheManager,
cacheMaxStaleManager,
discordInterface,
logger
) {
this.#cache = cache;
this.#maxStaleCacheManager = maxStaleCacheManager;
this.#cacheMaxStaleManager = cacheMaxStaleManager;
this.#discordInterface = discordInterface
.setClientReadyHandler(this.#onClientReady.bind(this))
.setMessageCreateHandler(this.#onMessageCreate.bind(this))
Expand All @@ -165,7 +169,7 @@ class IdBot {

close() {
this.#discordInterface.close();
this.#maxStaleCacheManager.stop();
this.#cacheMaxStaleManager.stop();
}
}

Expand Down
4 changes: 2 additions & 2 deletions src/js/logger.js
Original file line number Diff line number Diff line change
Expand Up @@ -35,12 +35,12 @@ class Logger {

/**
* @param {*} message
* @param {*} [error]
* @param {Error} [error]
*/
error = ((message, error) => {
this.#console.error(this.#format(message, "ERROR"));
if (error) {
this.#console.error(error);
this.#console.error(this.#format(error, "ERROR"));
}
});

Expand Down

0 comments on commit 8c0f3d9

Please sign in to comment.