add nsfw emojis

pull/211/head
Aevann 2023-09-29 10:15:29 +03:00
parent 109b91e977
commit 43822b3322
10 changed files with 121 additions and 69 deletions

View File

@ -4,6 +4,7 @@ function approve_emoji(t, name) {
"tags": document.getElementById(`${name}-tags`).value,
"name": document.getElementById(`${name}-name`).value,
"kind": document.getElementById(`${name}-kind`).value,
"over_18": document.getElementById(`${name}-over-18`).value,
},
() => {
document.getElementById(`${name}-emoji`).remove()

View File

@ -15,6 +15,7 @@ class Emoji(Base):
count = Column(Integer, default=0)
submitter_id = Column(Integer, ForeignKey("users.id"))
created_utc = Column(Integer)
over_18 = Column(Boolean, default=False)
def __init__(self, *args, **kwargs):
if "created_utc" not in kwargs: kwargs["created_utc"] = int(time.time())

View File

@ -12,15 +12,16 @@ SNAPPY_QUOTES = []
SNAPPY_QUOTES_FISTMAS = []
SNAPPY_QUOTES_HOMOWEEN = []
STEALTH_HOLES = []
OVER_18_EMOJIS = []
def const_initialize():
global MARSEYS_CONST, MARSEYS_CONST2, MARSEY_MAPPINGS, SNAPPY_KONGS, SNAPPY_MARSEYS, SNAPPY_QUOTES, SNAPPY_QUOTES_FISTMAS, SNAPPY_QUOTES_HOMOWEEN, STEALTH_HOLES
global MARSEYS_CONST, MARSEYS_CONST2, MARSEY_MAPPINGS, SNAPPY_KONGS, SNAPPY_MARSEYS, SNAPPY_QUOTES, SNAPPY_QUOTES_FISTMAS, SNAPPY_QUOTES_HOMOWEEN, STEALTH_HOLES, OVER_18_EMOJIS
db = db_session()
MARSEYS_CONST = [x[0] for x in db.query(Emoji.name).filter(Emoji.kind=="Marsey", Emoji.submitter_id==None, Emoji.name!='chudsey')]
MARSEYS_CONST = [x[0] for x in db.query(Emoji.name).filter(Emoji.kind == "Marsey", Emoji.submitter_id == None, Emoji.name != 'chudsey', Emoji.over_18 == False)]
MARSEYS_CONST2 = MARSEYS_CONST + ['chudsey','a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z','0','1','2','3','4','5','6','7','8','9','exclamationpoint','period','questionmark']
marseys = db.query(Emoji).filter(Emoji.kind=="Marsey", Emoji.submitter_id==None).all()
marseys = db.query(Emoji).filter(Emoji.kind=="Marsey", Emoji.submitter_id == None, Emoji.over_18 == False).all()
for marsey in marseys:
for tag in marsey.tags.split():
if tag in MARSEY_MAPPINGS:
@ -28,11 +29,13 @@ def const_initialize():
else:
MARSEY_MAPPINGS[tag] = [marsey.name]
SNAPPY_KONGS = db.query(Emoji.name).filter(Emoji.kind=="Donkey Kong", Emoji.submitter_id==None).all()
SNAPPY_KONGS = db.query(Emoji.name).filter(Emoji.kind=="Donkey Kong", Emoji.submitter_id==None, Emoji.over_18 == False).all()
SNAPPY_KONGS = [f':#{x[0]}:' for x in SNAPPY_KONGS]
STEALTH_HOLES = [x[0] for x in db.query(Sub.name).filter_by(stealth=True)]
OVER_18_EMOJIS = [x[0] for x in db.query(Emoji.name).filter_by(over_18=True)]
db.commit()
db.close()

View File

@ -218,58 +218,58 @@ 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):
def find_all_emote_endings(emoji):
endings = []
if path.isfile(f'files/assets/images/emojis/{word}.webp'):
return endings, word
if path.isfile(f'files/assets/images/emojis/{emoji}.webp'):
return endings, emoji
is_non_ending_found = False
while not is_non_ending_found:
if word.endswith('pat'):
if emoji.endswith('pat'):
if 'pat' in endings:
is_non_ending_found = True
continue
endings.append('pat')
word = word[:-3]
emoji = emoji[:-3]
continue
if word.endswith('talking'):
if emoji.endswith('talking'):
if 'talking' in endings:
is_non_ending_found = True
continue
endings.append('talking')
word = word[:-7]
emoji = emoji[:-7]
continue
if word.endswith('genocide'):
if emoji.endswith('genocide'):
if 'genocide' in endings:
is_non_ending_found = True
continue
endings.append('genocide')
word = word[:-8]
emoji = emoji[:-8]
continue
if word.endswith('love'):
if emoji.endswith('love'):
if 'love' in endings:
is_non_ending_found = True
continue
endings.append('love')
word = word[:-4]
emoji = emoji[:-4]
continue
is_non_ending_found = True
if word.endswith('random'):
kind = word.split('random')[0].title()
if emoji.endswith('random'):
kind = emoji.split('random')[0].title()
if kind == 'Donkeykong': kind = 'Donkey Kong'
elif kind == 'Marseyflag': kind = 'Marsey Flags'
elif kind == 'Marseyalphabet': kind = 'Marsey Alphabet'
if kind in EMOJI_KINDS:
word = g.db.query(Emoji.name).filter_by(kind=kind).order_by(func.random()).first()[0]
emoji = g.db.query(Emoji.name).filter_by(kind=kind, over_18=False).order_by(func.random()).first()[0]
return endings, word
return endings, emoji
def render_emoji(html, regexp, golden, emojis_used, b=False, is_title=False):
@ -411,7 +411,7 @@ def handle_youtube_links(url):
return html
@with_sigalrm_timeout(10)
def sanitize(sanitized, golden=True, limit_pings=0, showmore=False, count_emojis=False, snappy=False, chat=False, blackjack=None, post_mention_notif=False, commenters_ping_post_id=None):
def sanitize(sanitized, golden=True, limit_pings=0, showmore=False, count_emojis=False, snappy=False, chat=False, blackjack=None, post_mention_notif=False, commenters_ping_post_id=None, obj=None):
def error(error):
if chat:
return error, 403
@ -563,6 +563,12 @@ def sanitize(sanitized, golden=True, limit_pings=0, showmore=False, count_emojis
emoji.count += 1
g.db.add(emoji)
if obj:
for emoji in emojis_used:
if emoji in OVER_18_EMOJIS:
obj.over_18 = True
break
sanitized = sanitized.replace('<p></p>', '')
allowed_css_properties = allowed_styles.copy()
@ -704,7 +710,7 @@ def allowed_attributes_emojis(tag, name, value):
@with_sigalrm_timeout(2)
def filter_emojis_only(title, golden=True, count_emojis=False):
def filter_emojis_only(title, golden=True, count_emojis=False, obj=None):
title = title.replace("\n", "").replace("\r", "").replace("\t", "").replace('<','&lt;').replace('>','&gt;')
@ -719,6 +725,12 @@ def filter_emojis_only(title, golden=True, count_emojis=False):
emoji.count += 1
g.db.add(emoji)
if obj:
for emoji in emojis_used:
if emoji in OVER_18_EMOJIS:
obj.over_18 = True
break
title = strikethrough_regex.sub(r'\1<del>\2</del>', title)
title = bleach.clean(title, tags=['img','del','span'], attributes=allowed_attributes_emojis, protocols=['http','https']).replace('\n','')

View File

@ -48,6 +48,7 @@ def submit_emoji(v):
tags = request.values.get('tags', '').lower().strip()
username = request.values.get('author', '').lower().strip()
kind = request.values.get('kind', '').strip()
over_18 = request.values.get("over_18", False, bool)
for modifier in emoji_modifiers:
if name.endswith(modifier):
@ -91,7 +92,15 @@ def submit_emoji(v):
copyfile(highquality, filename)
process_image(filename, v, resize=300, trim=True)
emoji = Emoji(name=name, kind=kind, author_id=author.id, tags=tags, count=0, submitter_id=v.id)
emoji = Emoji(
name=name,
kind=kind,
author_id=author.id,
tags=tags,
count=0,
submitter_id=v.id,
over_18=over_18,
)
g.db.add(emoji)
return {"message": f"'{name}' submitted successfully!"}
@ -139,10 +148,12 @@ def approve_emoji(v, name):
if new_kind not in EMOJI_KINDS:
abort(400, "Invalid kind!")
over_18 = request.values.get("over_18", False, bool)
emoji.name = new_name
emoji.kind = new_kind
emoji.tags = tags
emoji.over_18 = over_18
g.db.add(emoji)
author = get_account(emoji.author_id)
@ -177,9 +188,9 @@ def approve_emoji(v, name):
badge_grant(badge_id=113, user=author)
badge_grant(badge_id=112, user=author)
cache.delete("emojis")
cache.delete(f"emoji_list_{emoji.kind}")
if not Emoji.over_18:
cache.delete("emojis")
cache.delete(f"emoji_list_{emoji.kind}")
purge_files_in_cloudflare_cache(f"{SITE_FULL_IMAGES}/e/{emoji.name}/webp")
@ -210,6 +221,9 @@ def approve_emoji(v, name):
)
g.db.add(ma)
if emoji.over_18:
OVER_18_EMOJIS.append(emoji.name)
return {"message": f"'{emoji.name}' approved!"}
def remove_asset(cls, type_name, v, name):
@ -474,8 +488,9 @@ def update_emoji(v):
)
g.db.add(ma)
cache.delete("emojis")
cache.delete(f"emoji_list_{existing.kind}")
if not Emoji.over_18:
cache.delete("emojis")
cache.delete(f"emoji_list_{existing.kind}")
return {"message": f"'{name}' updated successfully!"}

View File

@ -260,7 +260,29 @@ def comment(v):
if v.marsify and not v.chud: body_for_sanitize = marsify(body_for_sanitize)
if v.sharpen: body_for_sanitize = sharpen(body_for_sanitize)
body_html = sanitize(body_for_sanitize, limit_pings=5, showmore=(not v.marseyawarded), count_emojis=not v.marsify, commenters_ping_post_id=commenters_ping_post_id)
is_bot = v.client is not None and v.id not in BOT_SYMBOL_HIDDEN
chudded = v.chud and not (posting_to_post and post_target.sub == 'chudrama')
c = Comment(author_id=v.id,
parent_post=post_target.id if posting_to_post else None,
wall_user_id=post_target.id if not posting_to_post else None,
parent_comment_id=parent_comment_id,
level=level,
over_18=post_target.over_18 if posting_to_post else False,
is_bot=is_bot,
app_id=v.client.application.id if v.client else None,
body=body,
ghost=ghost,
chudded=chudded,
rainbowed=bool(v.rainbow),
queened=bool(v.queen),
sharpened=bool(v.sharpen),
)
c.upvotes = 1
body_html = sanitize(body_for_sanitize, limit_pings=5, showmore=(not v.marseyawarded), count_emojis=not v.marsify, commenters_ping_post_id=commenters_ping_post_id, obj=c)
if post_target.id not in ADMIGGER_THREADS and not (v.chud and v.chud_phrase in body.lower()):
existing = g.db.query(Comment.id).filter(
@ -282,28 +304,8 @@ def comment(v):
if len(body_html) > COMMENT_BODY_HTML_LENGTH_LIMIT:
abort(400, "Comment too long!")
is_bot = v.client is not None and v.id not in BOT_SYMBOL_HIDDEN
c.body_html = body_html
chudded = v.chud and not (posting_to_post and post_target.sub == 'chudrama')
c = Comment(author_id=v.id,
parent_post=post_target.id if posting_to_post else None,
wall_user_id=post_target.id if not posting_to_post else None,
parent_comment_id=parent_comment_id,
level=level,
over_18=post_target.over_18 if posting_to_post else False,
is_bot=is_bot,
app_id=v.client.application.id if v.client else None,
body_html=body_html,
body=body,
ghost=ghost,
chudded=chudded,
rainbowed=bool(v.rainbow),
queened=bool(v.queen),
sharpened=bool(v.sharpen),
)
c.upvotes = 1
g.db.add(c)
g.db.flush()
@ -683,7 +685,7 @@ def edit_comment(cid, v):
if c.sharpened:
body_for_sanitize = sharpen(body_for_sanitize)
body_html = sanitize(body_for_sanitize, golden=False, limit_pings=5, showmore=(not v.marseyawarded), commenters_ping_post_id=c.parent_post)
body_html = sanitize(body_for_sanitize, golden=False, limit_pings=5, showmore=(not v.marseyawarded), commenters_ping_post_id=c.parent_post, obj=c)
if len(body_html) > COMMENT_BODY_HTML_LENGTH_LIMIT: abort(400)

View File

@ -457,11 +457,6 @@ def submit_post(v, sub=None):
if SITE == 'rdrama.net' and v.id == 10947:
sub = 'mnn'
title_html = filter_emojis_only(title, count_emojis=True)
if v.marseyawarded and not marseyaward_title_regex.fullmatch(title_html):
abort(400, "You can only type marseys!")
if sub == 'changelog':
abort(400, "/h/changelog is archived")
@ -541,14 +536,6 @@ def submit_post(v, sub=None):
body_for_sanitize = body
if v.sharpen: body_for_sanitize = sharpen(body_for_sanitize)
body_html = sanitize(body_for_sanitize, count_emojis=True, limit_pings=100)
if v.marseyawarded and marseyaward_body_regex.search(body_html):
abort(400, "You can only type marseys!")
if len(body_html) > POST_BODY_HTML_LENGTH_LIMIT:
abort(400, "Post body_html too long!")
flag_notify = (request.values.get("notify", "on") == "on")
flag_new = request.values.get("new", False, bool) or 'megathread' in title.lower()
flag_over_18 = FEATURES['NSFW_MARKING'] and request.values.get("over_18", False, bool)
@ -577,10 +564,8 @@ def submit_post(v, sub=None):
is_bot=(v.client is not None),
url=url,
body=body,
body_html=body_html,
embed=embed,
title=title,
title_html=title_html,
sub=sub,
ghost=flag_ghost,
chudded=flag_chudded,
@ -589,6 +574,23 @@ def submit_post(v, sub=None):
sharpened=bool(v.sharpen),
)
title_html = filter_emojis_only(title, count_emojis=True, obj=p)
if v.marseyawarded and not marseyaward_title_regex.fullmatch(title_html):
abort(400, "You can only type marseys!")
p.title_html = title_html
body_html = sanitize(body_for_sanitize, count_emojis=True, limit_pings=100, obj=p)
if v.marseyawarded and marseyaward_body_regex.search(body_html):
abort(400, "You can only type marseys!")
if len(body_html) > POST_BODY_HTML_LENGTH_LIMIT:
abort(400, "Post body_html too long!")
p.body_html = body_html
g.db.add(p)
g.db.flush()
@ -1015,7 +1017,7 @@ def edit_post(pid, v):
if title != p.title:
title_html = filter_emojis_only(title, golden=False)
title_html = filter_emojis_only(title, golden=False, obj=p)
if p.author.marseyawarded and not marseyaward_title_regex.fullmatch(title_html):
abort(403, "You can only type marseys!")
@ -1033,7 +1035,7 @@ def edit_post(pid, v):
body_for_sanitize = body
if p.sharpened: body_for_sanitize = sharpen(body_for_sanitize)
body_html = sanitize(body_for_sanitize, golden=False, limit_pings=100)
body_html = sanitize(body_for_sanitize, golden=False, limit_pings=100, obj=p)
if p.author.marseyawarded and marseyaward_body_regex.search(body_html):
abort(403, "You can only type marseys!")

View File

@ -45,7 +45,7 @@ def reddit_post(subreddit, v, path):
@cache.cached(make_cache_key=lambda kind:f"emoji_list_{kind}")
def get_emoji_list(kind):
emojis = []
for emoji, author in g.db.query(Emoji, User).join(User, Emoji.author_id == User.id).filter(Emoji.submitter_id == None, Emoji.kind == kind).order_by(Emoji.count.desc()):
for emoji, author in g.db.query(Emoji, User).join(User, Emoji.author_id == User.id).filter(Emoji.submitter_id == None, Emoji.kind == kind, Emoji.over_18 == False).order_by(Emoji.count.desc()):
emoji.author = author.username if FEATURES['ASSET_SUBMISSIONS'] else None
emojis.append(emoji)
return emojis
@ -83,7 +83,7 @@ def emoji_list(v, kind):
@cache.cached(make_cache_key=lambda:"emojis")
def get_emojis():
emojis = g.db.query(Emoji, User).join(User, Emoji.author_id == User.id).filter(Emoji.submitter_id == None)
emojis = g.db.query(Emoji, User).join(User, Emoji.author_id == User.id).filter(Emoji.submitter_id == None, Emoji.over_18 == False)
emojis1 = emojis.filter(Emoji.kind != 'Marsey Alphabet').order_by(Emoji.count.desc()).all()
emojis2 = emojis.filter(Emoji.kind == 'Marsey Alphabet').order_by(func.length(Emoji.name), Emoji.name).all()
emojis = emojis1 + emojis2

View File

@ -43,6 +43,13 @@
<label class="mt-3" for="tags">Tags (must be separated by spaces)</label>
<input autocomplete="off" type="text" id="tags" class="form-control" name="tags" maxlength="200" pattern='[a-zA-Z0-9: ]{1,200}' placeholder="Required" value="{{tags}}" required>
{% if FEATURES['NSFW_MARKING'] %}
<div class="custom-control custom-checkbox mt-4">
<input autocomplete="off" type="checkbox" class="custom-control-input" id="emoji-over-18" name="over_18" data-nonce="{{g.nonce}}" data-onchange="savetext()">
<label class="custom-control-label" for="emoji-over-18">+18</label>
</div>
{% endif %}
<div class="footer mt-5">
<div class="d-flex">
<input id="submit-btn" disabled type="submit" class="btn btn-primary ml-auto" value="Submit Emoji">
@ -91,6 +98,13 @@
<label class="mt-3" for="{{emoji.name}}-tags">Tags</label>
<input autocomplete="off" type="text" id="{{emoji.name}}-tags" class="form-control" name="tags" maxlength="200" value="{{emoji.tags}}" pattern='[a-z0-9: ]{1,200}' placeholder="Required" required {% if v.admin_level < PERMS['MODERATE_PENDING_SUBMITTED_ASSETS'] %}readonly{% endif %}>
{% if FEATURES['NSFW_MARKING'] %}
<div class="custom-control custom-checkbox mt-4">
<input autocomplete="off" type="checkbox" class="custom-control-input" id="{{emoji.name}}-over-18" name="over_18" data-nonce="{{g.nonce}}" data-onchange="savetext()" {% if v.admin_level < PERMS['MODERATE_PENDING_SUBMITTED_ASSETS'] %}readonly{% endif %} {% if emoji.over_18 %}checked{% endif %}>
<label class="custom-control-label" for="{{emoji.name}}-over-18">+18</label>
</div>
{% endif %}
</div>
</div>
{% if v.admin_level >= PERMS['MODERATE_PENDING_SUBMITTED_ASSETS'] or v.id == emoji.submitter_id %}

View File

@ -0,0 +1,2 @@
alter table emojis add column over_18 bool default false not null;
alter table emojis alter column over_18 drop default;