Adds marseycide! (#182)

Fun modifier for emotes that some people had asked about here: https://rdrama.net/post/194966/ricecop-gets-5-years-for-watching/4753853#context

-Doesn't work with reverse due to the way transform works. Might come up with a solution to that later but doesn't matter much for this one since it's hard to tell it's turned with the animation anyways
-This breaks current emotes just like talking did since they have the same ending unfortunately.

Mostly did this to clean up the ending logic for emotes since it was not extensible, this should scale better (could still be improved). Let me know if you don't like it and I will keep just those changes.

Co-authored-by: Chuck <dude@bussy.com>
Reviewed-on: #182
Co-authored-by: top <top@noreply.fsdfsd.net>
Co-committed-by: top <top@noreply.fsdfsd.net>
pull/183/head
top 2023-08-09 08:33:14 +00:00 committed by Aevann
parent 78c608b129
commit 3558a41860
4 changed files with 118 additions and 23 deletions

View File

@ -5594,6 +5594,17 @@ img[src$="/i/hand.webp"]+img[src^="/pp/"], img[src$="/i/hand.webp"]+img[src$="/p
100% { transform: scale(1, 0.8) } 100% { transform: scale(1, 0.8) }
} }
@keyframes cide-anim {
0% { transform: scale(1,1) rotate(0deg) }
100% { transform: scale(0, 0) rotate(360deg) }
}
.cide, span[cide] {
display: inline-block;
animation: cide-anim 2s infinite;
animation-timing-function: linear;
}
/* Fix for <ol> being populated with <li><p></p></li> in many contexts. */ /* Fix for <ol> being populated with <li><p></p></li> in many contexts. */
.post-body li > p:first-child, .post-body li > p:first-child,
.comment-text li > p:first-child, .comment-text li > p:first-child,

View File

@ -72,8 +72,51 @@ const MODIFIERS = {
REVERSED: 4, REVERSED: 4,
USER: 5, USER: 5,
REVERSED_MODIFIER: 6, REVERSED_MODIFIER: 6,
GENOCIDE: 7,
}; };
const findAllEmoteEndings = (word) => {
let hasReachedNonModifer = false;
let currWord = word;
const currEndings = [];
while(!hasReachedNonModifer) {
if(currWord.endsWith('pat')) {
if(currEndings.indexOf(MODIFIERS.PAT) !== -1) {
hasReachedNonModifer = true;
continue;
}
currWord = currWord.slice(0, -3);
currEndings.push(MODIFIERS.PAT);
continue;
}
if(currWord.endsWith('talking')) {
if(currEndings.indexOf(MODIFIERS.TALKING) !== -1) {
hasReachedNonModifer = true;
continue;
}
currWord = currWord.slice(0, -7);
currEndings.push(MODIFIERS.TALKING);
continue;
}
if(currWord.endsWith('genocide')) {
if(currEndings.indexOf(MODIFIERS.GENOCIDE) !== -1) {
hasReachedNonModifer = true;
continue;
}
currWord = currWord.slice(0, -8);
currEndings.push(MODIFIERS.GENOCIDE);
continue;
}
hasReachedNonModifer = true;
}
return [currEndings, currWord];
}
function markdown(t) { function markdown(t) {
let input = t.value; let input = t.value;
@ -110,8 +153,8 @@ function markdown(t) {
const modifiers = new Set(); const modifiers = new Set();
let length = emoji.length let length = emoji.length;
if (emoji.includes('!!')) modifiers.add(MODIFIERS.REVERSED_MODIFIER); if(emoji.includes('!!')) modifiers.add(MODIFIERS.REVERSED_MODIFIER);
emoji = emoji.replaceAll('!', ''); emoji = emoji.replaceAll('!', '');
if (length !== emoji.length) { if (length !== emoji.length) {
modifiers.add(MODIFIERS.REVERSED); modifiers.add(MODIFIERS.REVERSED);
@ -121,15 +164,11 @@ function markdown(t) {
if (length !== emoji.length) { if (length !== emoji.length) {
modifiers.add(MODIFIERS.LARGE); modifiers.add(MODIFIERS.LARGE);
} }
const isTalkingFirst = !(emoji.endsWith('pat') && emoji.slice(0, -3).endsWith('talking')); let endingModifiers;
if (emoji.endsWith('talking') || (emoji.endsWith('pat') && emoji.slice(0, -3).endsWith('talking'))) { [endingModifiers, emoji] = findAllEmoteEndings(emoji);
modifiers.add(MODIFIERS.TALKING); const isTalkingFirst = endingModifiers.indexOf(MODIFIERS.PAT) > endingModifiers.indexOf(MODIFIERS.TALKING);
emoji = emoji.endsWith('pat') ? [emoji.slice(0, -10), emoji.slice(-3)].join('') : emoji.slice(0, -7);
} endingModifiers.forEach(modifiers.add, modifiers)
if (emoji.endsWith('pat')) {
modifiers.add(MODIFIERS.PAT);
emoji = emoji.slice(0, -3);
}
if (emoji.startsWith('@')) { if (emoji.startsWith('@')) {
emoji = emoji.slice(1); emoji = emoji.slice(1);
@ -145,18 +184,19 @@ function markdown(t) {
} }
const mirroredClass = 'mirrored'; const mirroredClass = 'mirrored';
const genocideClass = modifiers.has(MODIFIERS.GENOCIDE) ? 'cide' : '';
const emojiClass = modifiers.has(MODIFIERS.LARGE) ? 'emoji-lg' : 'emoji'; const emojiClass = modifiers.has(MODIFIERS.LARGE) ? 'emoji-lg' : 'emoji';
// patted emotes cannot be flipped back easily so they don't support double flipping // patted emotes cannot be flipped back easily so they don't support double flipping
const spanClass = modifiers.has(MODIFIERS.REVERSED) && (modifiers.has(MODIFIERS.PAT) || !modifiers.has(MODIFIERS.REVERSED_MODIFIER)) ? mirroredClass : ''; const spanClass = modifiers.has(MODIFIERS.REVERSED) && (modifiers.has(MODIFIERS.PAT) || !modifiers.has(MODIFIERS.REVERSED_MODIFIER)) ? mirroredClass : '';
const imgClass = modifiers.has(MODIFIERS.REVERSED) && modifiers.has(MODIFIERS.REVERSED_MODIFIER) ? mirroredClass : '' const imgClass = modifiers.has(MODIFIERS.REVERSED) && modifiers.has(MODIFIERS.REVERSED_MODIFIER) ? mirroredClass : ''
if (modifiers.has(MODIFIERS.PAT) || modifiers.has(MODIFIERS.TALKING)) { if (modifiers.has(MODIFIERS.PAT) || modifiers.has(MODIFIERS.TALKING) || modifiers.has(MODIFIERS.GENOCIDE)) {
const talkingHtml = modifiers.has(MODIFIERS.TALKING) ? `<img loading="lazy" src="${SITE_FULL_IMAGES}/i/talking.webp">` : ''; const talkingHtml = modifiers.has(MODIFIERS.TALKING) ? `<img loading="lazy" src="${SITE_FULL_IMAGES}/i/talking.webp">` : '';
const patHtml = modifiers.has(MODIFIERS.PAT) ? `<img loading="lazy" src="${SITE_FULL_IMAGES}/i/hand.webp">` : ''; const patHtml = modifiers.has(MODIFIERS.PAT) ? `<img loading="lazy" src="${SITE_FULL_IMAGES}/i/hand.webp">` : '';
const url = modifiers.has(MODIFIERS.USER) ? `/@${emoji}/pic` : `${SITE_FULL_IMAGES}/e/${emoji}.webp`; const url = modifiers.has(MODIFIERS.USER) ? `/@${emoji}/pic` : `${SITE_FULL_IMAGES}/e/${emoji}.webp`;
const modifierHtml = isTalkingFirst ? `${talkingHtml}${patHtml}` : `${patHtml}${talkingHtml}`; const modifierHtml = isTalkingFirst ? `${talkingHtml}${patHtml}` : `${patHtml}${talkingHtml}`;
input = input.replace(old, `<span class="pat-preview ${spanClass}" data-bs-toggle="tooltip">${modifierHtml}<img loading="lazy" class="${emojiClass} ${imgClass}" src="${url}"></span>`); input = input.replace(old, `<span class="pat-preview ${spanClass} ${genocideClass}" data-bs-toggle="tooltip">${modifierHtml}<img loading="lazy" class="${emojiClass} ${imgClass} " src="${url}"></span>`);
} else { } else {
input = input.replace(old, `<img loading="lazy" class="${emojiClass} ${modifiers.has(MODIFIERS.REVERSED) ? mirroredClass : ''}" src="${SITE_FULL_IMAGES}/e/${emoji}.webp">`); input = input.replace(old, `<img loading="lazy" class="${emojiClass} ${modifiers.has(MODIFIERS.REVERSED) ? mirroredClass : ''}" src="${SITE_FULL_IMAGES}/e/${emoji}.webp">`);
} }

View File

@ -99,6 +99,7 @@ def allowed_attributes(tag, name, value):
if name == 'data-bs-toggle' and value == 'tooltip': return True if name == 'data-bs-toggle' and value == 'tooltip': return True
if name == 'title': return True if name == 'title': return True
if name == 'alt': return True if name == 'alt': return True
if name == 'cide' and not value: return True
if tag == 'table': if tag == 'table':
if name == 'class' and value == 'table': return True if name == 'class' and value == 'table': return True
@ -212,6 +213,42 @@ def execute_blackjack(v, target, body, kind):
send_repeatable_notification_duplicated(id, f"Blackjack by @{v.username}: {extra_info}") send_repeatable_notification_duplicated(id, f"Blackjack by @{v.username}: {extra_info}")
return True return True
def find_all_emote_endings(word):
endings = list()
curr_word = word
is_non_ending_found = False
while not is_non_ending_found:
print(curr_word)
if curr_word.endswith('pat'):
if 'pat' in endings:
is_non_ending_found = True
continue
endings.append('pat')
curr_word = curr_word[:-3]
continue
if curr_word.endswith('talking'):
if 'talking' in endings:
is_non_ending_found = True
continue
endings.append('talking')
curr_word = curr_word[:-7]
continue
if curr_word.endswith('genocide'):
if 'genocide' in endings:
is_non_ending_found = True
continue
endings.append('genocide')
curr_word = curr_word[:-8]
continue
is_non_ending_found = True
return endings, curr_word
def render_emoji(html, regexp, golden, emojis_used, b=False, is_title=False): def render_emoji(html, regexp, golden, emojis_used, b=False, is_title=False):
emojis = list(regexp.finditer(html)) emojis = list(regexp.finditer(html))
captured = set() captured = set()
@ -245,12 +282,13 @@ def render_emoji(html, regexp, golden, emojis_used, b=False, is_title=False):
emoji_partial = '<img alt=":{0}:" data-bs-toggle="tooltip" loading="lazy" src="{1}" title=":{0}:"{2}>' emoji_partial = '<img alt=":{0}:" data-bs-toggle="tooltip" loading="lazy" src="{1}" title=":{0}:"{2}>'
emoji_html = None emoji_html = None
is_talking = emoji.endswith('talking') or (emoji[:-3].endswith('talking') and emoji.endswith('pat')) ending_modifiers, emoji = find_all_emote_endings(emoji)
is_talking_first = emoji.endswith('talking')
emoji = emoji[:-7] if emoji.endswith('talking') else emoji is_talking = 'talking' in ending_modifiers
emoji = f'{emoji[:-10]}pat' if emoji[:-3].endswith('talking') and emoji.endswith('pat') else emoji is_patted = 'pat' in ending_modifiers
is_patted = emoji.endswith('pat') is_talking_first = ending_modifiers.index('pat') > ending_modifiers.index('talking') if is_talking and is_patted else False
emoji = emoji[:-3] if is_patted else emoji
is_genocided = 'genocide' in ending_modifiers
is_user = emoji.startswith('@') is_user = emoji.startswith('@')
end_modifier_length = 3 if is_patted else 0 end_modifier_length = 3 if is_patted else 0
@ -258,8 +296,9 @@ def render_emoji(html, regexp, golden, emojis_used, b=False, is_title=False):
hand_html = f'<img loading="lazy" src="{SITE_FULL_IMAGES}/i/hand.webp">' if is_patted and emoji != 'marseyunpettable' else '' hand_html = f'<img loading="lazy" src="{SITE_FULL_IMAGES}/i/hand.webp">' if is_patted and emoji != 'marseyunpettable' else ''
talking_html = f'<img loading="lazy" src="{SITE_FULL_IMAGES}/i/talking.webp">' if is_talking else '' talking_html = f'<img loading="lazy" src="{SITE_FULL_IMAGES}/i/talking.webp">' if is_talking else ''
genocide_attr = ' cide' if is_genocided else ''
modifier_html = None modifier_html = ''
if (is_talking and is_patted): if (is_talking and is_patted):
modifier_html = f'{talking_html}{hand_html}' if is_talking_first else f'{hand_html}{talking_html}' modifier_html = f'{talking_html}{hand_html}' if is_talking_first else f'{hand_html}{talking_html}'
elif (is_patted): elif (is_patted):
@ -267,12 +306,12 @@ def render_emoji(html, regexp, golden, emojis_used, b=False, is_title=False):
elif (is_talking): elif (is_talking):
modifier_html = talking_html modifier_html = talking_html
if (is_patted and emoji != 'marseyunpettable') or is_talking: if (is_patted and emoji != 'marseyunpettable') or is_talking or is_genocided:
if path.isfile(f"files/assets/images/emojis/{emoji}.webp"): if path.isfile(f"files/assets/images/emojis/{emoji}.webp"):
emoji_html = f'<span alt=":{old}:" data-bs-toggle="tooltip" title=":{old}:">{modifier_html}{emoji_partial_pat.format(old, f"{SITE_FULL_IMAGES}/e/{emoji}.webp", attrs)}</span>' emoji_html = f'<span alt=":{old}:" data-bs-toggle="tooltip" title=":{old}:"{genocide_attr}>{modifier_html}{emoji_partial_pat.format(old, f"{SITE_FULL_IMAGES}/e/{emoji}.webp", attrs)}</span>'
elif is_user: elif is_user:
if u := get_user(emoji[1:], graceful=True): if u := get_user(emoji[1:], graceful=True):
emoji_html = f'<span alt=":{old}:" data-bs-toggle="tooltip" title=":{old}:">{modifier_html}{emoji_partial_pat.format(old, f"/pp/{u.id}", attrs)}</span>' emoji_html = f'<span alt=":{old}:" data-bs-toggle="tooltip" title=":{old}:"{genocide_attr}>{modifier_html}{emoji_partial_pat.format(old, f"/pp/{u.id}", attrs)}</span>'
elif path.isfile(f'files/assets/images/emojis/{emoji}.webp'): elif path.isfile(f'files/assets/images/emojis/{emoji}.webp'):
emoji_html = emoji_partial.format(old, f'{SITE_FULL_IMAGES}/e/{emoji}.webp', attrs) emoji_html = emoji_partial.format(old, f'{SITE_FULL_IMAGES}/e/{emoji}.webp', attrs)
@ -634,6 +673,7 @@ def allowed_attributes_emojis(tag, name, value):
if name == 'data-bs-toggle' and value == 'tooltip': return True if name == 'data-bs-toggle' and value == 'tooltip': return True
if name == 'title': return True if name == 'title': return True
if name == 'alt': return True if name == 'alt': return True
if name == 'cide' and not value: return True
return False return False

View File

@ -38,6 +38,10 @@
<input type="checkbox" id="emoji-sel-3" value="talking" class="emoji-postfix"> <input type="checkbox" id="emoji-sel-3" value="talking" class="emoji-postfix">
<label class="emoji-option" for="emoji-sel-3">Talking</label> <label class="emoji-option" for="emoji-sel-3">Talking</label>
</div> </div>
<div style="display: inline" data-bs-toggle="tooltip" data-bs-placement="bottom" title="Sends the emoji away">
<input type="checkbox" id="emoji-sel-4" value="genocide" class="emoji-postfix">
<label class="emoji-option" for="emoji-sel-4">Genocide</label>
</div>
</fieldset> </fieldset>
</div> </div>