2024-05-28 15:56:24 +00:00
|
|
|
// SPDX-FileCopyrightText: 2024 John Livingston <https://www.john-livingston.fr/>
|
|
|
|
//
|
|
|
|
// SPDX-License-Identifier: AGPL-3.0-only
|
|
|
|
|
|
|
|
import type { CustomEmojiDefinition, ChannelEmojis } from 'shared/lib/types'
|
|
|
|
|
|
|
|
/**
|
|
|
|
* livechat emojis ConverseJS plugin:
|
|
|
|
* this plugin handles custom channel emojis (if enabled).
|
|
|
|
*/
|
|
|
|
export const livechatEmojisPlugin = {
|
|
|
|
dependencies: ['converse-emoji'],
|
|
|
|
initialize: function (this: any) {
|
|
|
|
const _converse = this._converse
|
|
|
|
|
|
|
|
_converse.api.settings.extend({
|
|
|
|
livechat_custom_emojis_url: false
|
|
|
|
})
|
|
|
|
|
2024-09-09 18:01:25 +00:00
|
|
|
_converse.api.listen.on('loadEmojis', async (_context: object, json: Record<string, Record<string, unknown>>) => {
|
|
|
|
const url = _converse.api.settings.get('livechat_custom_emojis_url') as string | undefined
|
2024-05-28 15:56:24 +00:00
|
|
|
if (!url) {
|
|
|
|
return json
|
|
|
|
}
|
|
|
|
|
2024-09-09 18:01:25 +00:00
|
|
|
let customs: CustomEmojiDefinition[] | undefined
|
2024-05-28 15:56:24 +00:00
|
|
|
try {
|
|
|
|
customs = await loadCustomEmojis(url)
|
|
|
|
} catch (err) {
|
|
|
|
console.error(err)
|
|
|
|
}
|
2024-09-09 18:01:25 +00:00
|
|
|
if (!customs?.length) {
|
2024-05-28 15:56:24 +00:00
|
|
|
return json
|
|
|
|
}
|
|
|
|
|
2024-06-06 13:03:12 +00:00
|
|
|
// Now we must clone json, to avoid side effects when navigating between several videos.
|
|
|
|
json = JSON.parse(JSON.stringify(json))
|
2024-05-28 15:56:24 +00:00
|
|
|
json.custom = {}
|
|
|
|
|
|
|
|
let defaultDef: CustomEmojiDefinition | undefined
|
|
|
|
|
|
|
|
for (const def of customs) {
|
|
|
|
json.custom[def.sn] = {
|
|
|
|
sn: def.sn,
|
|
|
|
url: def.url,
|
|
|
|
c: 'custom'
|
|
|
|
}
|
|
|
|
if (def.isCategoryEmoji) {
|
|
|
|
defaultDef ??= def
|
|
|
|
}
|
2024-06-06 13:03:12 +00:00
|
|
|
|
|
|
|
// We must also remove any existing emojis in category other than custom
|
|
|
|
for (const type of Object.keys(json)) {
|
2024-09-09 18:01:25 +00:00
|
|
|
const v: Record<string, any> = json[type]
|
2024-06-06 13:03:12 +00:00
|
|
|
if (type !== 'custom' && type !== 'modifiers' && (def.sn in v)) {
|
|
|
|
// eslint-disable-next-line @typescript-eslint/no-dynamic-delete
|
|
|
|
delete v[def.sn]
|
|
|
|
}
|
|
|
|
}
|
2024-05-28 15:56:24 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// And if there was a default definition, using it for the custom cat icon.
|
2024-06-07 10:25:04 +00:00
|
|
|
// Else we fallback to the first.
|
|
|
|
// If none... just keep custom to null!
|
|
|
|
defaultDef ??= customs[0]
|
2024-05-28 15:56:24 +00:00
|
|
|
if (defaultDef) {
|
|
|
|
const cat = _converse.api.settings.get('emoji_categories')
|
|
|
|
cat.custom = defaultDef.sn
|
2024-06-07 10:25:04 +00:00
|
|
|
_converse.api.settings.set('emoji_categories', cat)
|
2024-05-28 15:56:24 +00:00
|
|
|
}
|
|
|
|
return json
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
async function loadCustomEmojis (url: string): Promise<CustomEmojiDefinition[]> {
|
|
|
|
const response = await fetch(
|
|
|
|
url,
|
|
|
|
{
|
|
|
|
method: 'GET',
|
|
|
|
// Note: no need to be authenticated here, this is a public API
|
|
|
|
headers: {
|
|
|
|
'content-type': 'application/json;charset=UTF-8'
|
|
|
|
}
|
|
|
|
}
|
|
|
|
)
|
|
|
|
|
|
|
|
if (!response.ok) {
|
|
|
|
throw new Error('Can\'t get channel emojis options.')
|
|
|
|
}
|
|
|
|
|
|
|
|
const customEmojis = (await response.json()) as ChannelEmojis
|
|
|
|
return customEmojis.customEmojis
|
|
|
|
}
|