a cache for slack profile pictures and emojis

feat: add endpoint to list all emoji

Changed files
+85
src
+59
src/cache.ts
···
}
/**
+
* Batch inserts multiple emojis into the cache
+
* @param emojis Array of {name, imageUrl} objects to insert
+
* @param expirationHours Optional custom expiration time in hours for all emojis
+
* @returns boolean indicating if all insertions were successful
+
*/
+
async batchInsertEmoji(
+
emojis: Array<{ name: string; imageUrl: string }>,
+
expirationHours?: number,
+
): Promise<boolean> {
+
try {
+
const expiration =
+
Date.now() + (expirationHours || this.defaultExpiration) * 3600000;
+
+
this.db.transaction(() => {
+
for (const emoji of emojis) {
+
const id = crypto.randomUUID();
+
this.db.run(
+
`INSERT INTO emojis (id, name, imageUrl, expiration)
+
VALUES (?, ?, ?, ?)
+
ON CONFLICT(name)
+
DO UPDATE SET imageUrl = ?, expiration = ?`,
+
[
+
id,
+
emoji.name,
+
emoji.imageUrl,
+
expiration,
+
emoji.imageUrl,
+
expiration,
+
],
+
);
+
}
+
})();
+
+
return true;
+
} catch (error) {
+
console.error("Error batch inserting emojis:", error);
+
return false;
+
}
+
}
+
+
/**
+
* Lists all emoji in the cache
+
* @returns Array of Emoji objects that haven't expired
+
*/
+
async listEmoji(): Promise<Emoji[]> {
+
const results = this.db
+
.query("SELECT * FROM emojis WHERE expiration > ?")
+
.all(Date.now()) as Emoji[];
+
+
return results.map((result) => ({
+
type: "emoji",
+
id: result.id,
+
name: result.name,
+
imageUrl: result.imageUrl,
+
expiration: new Date(result.expiration),
+
}));
+
}
+
+
/**
* Retrieves a user from the cache
* @param userId Unique identifier of the user
* @returns User object if found and not expired, null otherwise
+26
src/index.ts
···
},
)
.get(
+
"/emojis",
+
async () => {
+
const emojis = await cache.listEmoji();
+
+
return emojis.map((emoji) => ({
+
id: emoji.id,
+
expiration: emoji.expiration.toISOString(),
+
name: emoji.name,
+
image: emoji.imageUrl,
+
}));
+
},
+
{
+
tags: ["Slack"],
+
response: {
+
200: t.Array(
+
t.Object({
+
id: t.String(),
+
expiration: t.String(),
+
name: t.String(),
+
image: t.String(),
+
}),
+
),
+
},
+
},
+
)
+
.get(
"/emojis/:emoji",
async ({ params, error }) => {
const emoji = await cache.getEmoji(params.emoji);