1
0
Fork 0
mirror of https://github.com/FrankerFaceZ/FrankerFaceZ.git synced 2025-06-27 21:05:53 +00:00
* Fixed: Bug displaying rich content errors when no data is returned from the link information service.
* API Changed: The `site.chat.addNotice()` method now supports rich content and localization.
This commit is contained in:
SirStendec 2024-01-17 14:28:21 -05:00
parent 44e30e985d
commit 8688d1a41b
4 changed files with 143 additions and 52 deletions

View file

@ -1,7 +1,7 @@
{
"name": "frankerfacez",
"author": "Dan Salvato LLC",
"version": "4.66.0",
"version": "4.67.0",
"description": "FrankerFaceZ is a Twitch enhancement suite.",
"private": true,
"license": "Apache-2.0",

View file

@ -2644,58 +2644,59 @@ export default class Chat extends Module {
handleLinkToS(data) {
if ( ! Array.isArray(data?.urls) )
return data;
// Check for YouTube
const agreed = this.settings.provider.get('agreed-tos', []),
rejected = this.settings.provider.get('declined-tos', []);
const resolvers = data.urls ? new Set(data.urls.map(x => x.resolver).filter(x => x)) : null;
if ( resolvers ) {
for(const [key, info] of Object.entries(RESOLVERS_REQUIRE_TOS)) {
if ( resolvers.has(key) && ! agreed.includes(key) ) {
const declined = rejected.includes(key);
const resolvers = new Set(data.urls.map(x => x.resolver).filter(x => x));
for(const [key, info] of Object.entries(RESOLVERS_REQUIRE_TOS)) {
if ( resolvers.has(key) && ! agreed.includes(key) ) {
const declined = rejected.includes(key);
return {
...data,
url: null,
short: [
{
type: 'box',
content: [
info.i18n_key
? {type: 'i18n', key: info.i18n_key, phrase: info.label}
: info.label,
declined ? null : ' ',
declined ? null : {
type: 'conditional',
tooltip: false,
return {
...data,
url: null,
short: [
{
type: 'box',
content: [
info.i18n_key
? {type: 'i18n', key: info.i18n_key, phrase: info.label}
: info.label,
declined ? null : ' ',
declined ? null : {
type: 'conditional',
tooltip: false,
content: {
type: 'i18n',
key: 'embed.tos-open-settings',
phrase: '{link} to open your settings.',
content: {
type: 'i18n',
key: 'embed.tos-open-settings',
phrase: '{link} to open your settings.',
content: {
link: {
type: 'open_settings',
item: 'chat.tooltips',
content: {
type: 'i18n',
key: 'embed.tos-open-settings.click',
phrase: 'Click here'
}
link: {
type: 'open_settings',
item: 'chat.tooltips',
content: {
type: 'i18n',
key: 'embed.tos-open-settings.click',
phrase: 'Click here'
}
}
},
alternative: {
type: 'i18n',
key: 'embed.tos-settings',
phrase: 'Open the FFZ Control Center and navigate to Chat > Tooltips to agree.'
}
},
alternative: {
type: 'i18n',
key: 'embed.tos-settings',
phrase: 'Open the FFZ Control Center and navigate to Chat > Tooltips to agree.'
}
]
},
],
mid: null,
full: null
}
}
]
},
],
mid: null,
full: null
}
}
}

View file

@ -5,11 +5,11 @@
// ============================================================================
import {Color, ColorAdjuster} from 'utilities/color';
import {get, has, make_enum, shallow_object_equals, set_equals, deep_equals, glob_to_regex, escape_regex} from 'utilities/object';
import {get, has, make_enum, shallow_object_equals, set_equals, deep_equals, glob_to_regex, escape_regex, generateUUID} from 'utilities/object';
import {WEBKIT_CSS as WEBKIT} from 'utilities/constants';
import {useFont} from 'utilities/fonts';
import awaitMD, { getMD } from 'utilities/markdown';
import Module from 'utilities/module';
import Twilight from 'site';
@ -2389,10 +2389,40 @@ export default class ChatHook extends Module {
for(const inst of this.ChatService.instances) {
if ( room === '*' || inst.props.channelLogin.toLowerCase() === room ) {
inst.addMessage({
type: this.chat_types.Notice,
message
});
if ( typeof message === 'string' )
inst.addMessage({
type: this.chat_types.Notice,
message
});
else {
const props = inst.props,
login = props.channelLogin,
id = props.channelID;
if ( message.markdown ) {
const md = getMD();
if ( ! md )
awaitMD();
}
inst.addMessage({
type: this.chat_types.Message,
channel: `#${login}`,
roomID: id,
roomLogin: login,
id: `ffz_notice_${generateUUID()}`,
ffz_type: 'notice',
ffz_no_actions: true,
ffz_data: message,
message: null,
messageParts: [],
timestamp: Date.now(),
user: {
userID: id,
userLogin: login
}
})
}
return true;
}

View file

@ -13,6 +13,7 @@ import { KEYS, RERENDER_SETTINGS, UPDATE_BADGE_SETTINGS, UPDATE_TOKEN_SETTINGS }
import { print_duration } from 'utilities/time';
import { getRewardTitle, getRewardCost } from './points';
import awaitMD, {getMD} from 'utilities/markdown';
const SUB_TIERS = {
1000: 1,
@ -45,6 +46,65 @@ export default class ChatLine extends Module {
}
};
this.line_types.notice = {
renderNotice: (msg, current_user, room, inst, e) => {
const data = msg.ffz_data;
let content = this.line_types.notice.renderContent(msg, current_user, room, inst, e);
if ( ! data.icon )
return content;
if ( typeof content === 'string' )
content = e('span', {}, content);
content.ffz_icon = e('span', {
className: `${data.icon} tw-mg-r-05`
});
return content;
},
renderContent: (msg, current_user, room, inst, e) => {
const data = msg.ffz_data;
if ( data.renderer )
try {
return data.renderer(data, inst, e);
} catch(err) {
this.log.capture(err);
this.log.error('Error using custom renderer for notice:', err);
return `Error rendering notice.`
}
const text = data.i18n ? this.i18n.t(data.i18n, data.messgae, data) : data.message;
if ( data.markdown ) {
const md = getMD();
if ( ! md ) {
awaitMD().then(() => inst.forceUpdate());
return 'Loading...';
}
return e('span', {
dangerouslySetInnerHTML: {
__html: getMD().renderInline(text)
}
});
}
if ( data.tokenize ) {
const tokens = data.ffz_tokens = data.ffz_tokens || this.chat.tokenizeMessage({
message: text,
id: msg.id,
user: msg.user
}, current_user);
return this.chat.renderTokens(tokens, e);
}
return text;
}
};
this.line_types.hype = {
renderNotice: (msg, current_user, room, inst, e) => {
const setting = this.chat.context.get('chat.hype.message-style');
@ -1058,7 +1118,7 @@ other {# messages were deleted by a moderator.}
// The preamble
timestamp,
t.actions.renderInline(msg, this.props.showModerationIcons, current_user, current_room, e, this),
msg.ffz_no_actions ? null : t.actions.renderInline(msg, this.props.showModerationIcons, current_user, current_room, e, this),
this.renderInlineHighlight ? this.renderInlineHighlight() : null,
hl_position === 2 ? highlight_tags : null,
@ -1121,7 +1181,7 @@ other {# messages were deleted by a moderator.}
? e('span', { className: 'chat-line__timestamp' }, t.chat.formatTime(msg.timestamp))
: null;
const actions = t.actions.renderInline(msg, this.props.showModerationIcons, current_user, current_room, e, this);
const actions = msg.ffz_no_actions ? null : t.actions.renderInline(msg, this.props.showModerationIcons, current_user, current_room, e, this);
if ( is_raw ) {
notice.ffz_target.unshift(
@ -1187,7 +1247,7 @@ other {# messages were deleted by a moderator.}
}
// Check for hover actions, as those require we wrap the output in a few extra elements.
const hover_actions = (user && msg.id)
const hover_actions = (user && msg.id && ! msg.ffz_no_actions)
? t.actions.renderHover(msg, this.props.showModerationIcons, current_user, current_room, e, this)
: null;