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: rDrama/rDrama#182
Co-authored-by: top <top@noreply.fsdfsd.net>
Co-committed-by: top <top@noreply.fsdfsd.net>
master
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) }
}
@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. */
.post-body li > p:first-child,
.comment-text li > p:first-child,

View File

@ -72,8 +72,51 @@ const MODIFIERS = {
REVERSED: 4,
USER: 5,
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) {
let input = t.value;
@ -110,8 +153,8 @@ function markdown(t) {
const modifiers = new Set();
let length = emoji.length
if (emoji.includes('!!')) modifiers.add(MODIFIERS.REVERSED_MODIFIER);
let length = emoji.length;
if(emoji.includes('!!')) modifiers.add(MODIFIERS.REVERSED_MODIFIER);
emoji = emoji.replaceAll('!', '');
if (length !== emoji.length) {
modifiers.add(MODIFIERS.REVERSED);
@ -121,15 +164,11 @@ function markdown(t) {
if (length !== emoji.length) {
modifiers.add(MODIFIERS.LARGE);
}
const isTalkingFirst = !(emoji.endsWith('pat') && emoji.slice(0, -3).endsWith('talking'));
if (emoji.endsWith('talking') || (emoji.endsWith('pat') && emoji.slice(0, -3).endsWith('talking'))) {
modifiers.add(MODIFIERS.TALKING);
emoji = emoji.endsWith('pat') ? [emoji.slice(0, -10), emoji.slice(-3)].join('') : emoji.slice(0, -7);
}
if (emoji.endsWith('pat')) {
modifiers.add(MODIFIERS.PAT);
emoji = emoji.slice(0, -3);
}
let endingModifiers;
[endingModifiers, emoji] = findAllEmoteEndings(emoji);
const isTalkingFirst = endingModifiers.indexOf(MODIFIERS.PAT) > endingModifiers.indexOf(MODIFIERS.TALKING);
endingModifiers.forEach(modifiers.add, modifiers)
if (emoji.startsWith('@')) {
emoji = emoji.slice(1);
@ -145,18 +184,19 @@ function markdown(t) {
}
const mirroredClass = 'mirrored';
const genocideClass = modifiers.has(MODIFIERS.GENOCIDE) ? 'cide' : '';
const emojiClass = modifiers.has(MODIFIERS.LARGE) ? 'emoji-lg' : 'emoji';
// 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 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 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 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 {
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 == 'title': return True
if name == 'alt': return True
if name == 'cide' and not value: return True
if tag == 'table':
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}")
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):
emojis = list(regexp.finditer(html))
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_html = None
is_talking = emoji.endswith('talking') or (emoji[:-3].endswith('talking') and emoji.endswith('pat'))
is_talking_first = emoji.endswith('talking')
emoji = emoji[:-7] if emoji.endswith('talking') else emoji
emoji = f'{emoji[:-10]}pat' if emoji[:-3].endswith('talking') and emoji.endswith('pat') else emoji
is_patted = emoji.endswith('pat')
emoji = emoji[:-3] if is_patted else emoji
ending_modifiers, emoji = find_all_emote_endings(emoji)
is_talking = 'talking' in ending_modifiers
is_patted = 'pat' in ending_modifiers
is_talking_first = ending_modifiers.index('pat') > ending_modifiers.index('talking') if is_talking and is_patted else False
is_genocided = 'genocide' in ending_modifiers
is_user = emoji.startswith('@')
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 ''
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):
modifier_html = f'{talking_html}{hand_html}' if is_talking_first else f'{hand_html}{talking_html}'
elif (is_patted):
@ -267,12 +306,12 @@ def render_emoji(html, regexp, golden, emojis_used, b=False, is_title=False):
elif (is_talking):
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"):
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:
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'):
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 == 'title': return True
if name == 'alt': return True
if name == 'cide' and not value: return True
return False

View File

@ -38,6 +38,10 @@
<input type="checkbox" id="emoji-sel-3" value="talking" class="emoji-postfix">
<label class="emoji-option" for="emoji-sel-3">Talking</label>
</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>
</div>