diff --git a/files/assets/css/main.css b/files/assets/css/main.css index fc0087579..bbea59438 100644 --- a/files/assets/css/main.css +++ b/files/assets/css/main.css @@ -6043,6 +6043,10 @@ g { .fa-sitemap:before{content:"\f0e8"} .fa-grid:before{content:"\e195"} .fa-x:before{content:"\58"} +.fa-paw-simple:before{content:"\f701"} +.fa-bat:before{content:"\f6b5"} +.fa-star-of-david:before{content:"\f69a"} +.fa-kiss-wink-heart:before{content:"\f598"} .pronouns { font-size: 9px; @@ -6239,4 +6243,7 @@ blockquote + blockquote, div > blockquote:first-child, blockquote:last-child { .contain { -o-object-fit: contain; object-fit: contain; +} +.text-gray { + color: gray !important; } \ No newline at end of file diff --git a/files/classes/award.py b/files/classes/award.py index e8e0389f0..c8080024d 100644 --- a/files/classes/award.py +++ b/files/classes/award.py @@ -26,7 +26,8 @@ class AwardRelationship(Base): @property @lazy def type(self): - return AWARDS[self.kind] + try: return AWARDS[self.kind] + except: return HOUSE_AWARDS[self.kind] @property @lazy diff --git a/files/classes/comment.py b/files/classes/comment.py index bb0e7dc70..d0890ae65 100644 --- a/files/classes/comment.py +++ b/files/classes/comment.py @@ -263,11 +263,12 @@ class Comment(Base): @lazy def author_name(self): if self.ghost: return '👻' - else: return self.author.username + if self.author.earlylife: return f'((({self.author.username})))' + return self.author.username @lazy def award_count(self, kind, v): - if v and v.poor: return 0 + if v and v.poor and kind.islower(): return 0 return len([x for x in self.awards if x.kind == kind]) @property diff --git a/files/classes/submission.py b/files/classes/submission.py index adaf2da03..dc34fe476 100644 --- a/files/classes/submission.py +++ b/files/classes/submission.py @@ -207,7 +207,8 @@ class Submission(Base): @lazy def author_name(self): if self.ghost: return '👻' - else: return self.author.username + if self.author.earlylife: return f'((({self.author.username})))' + return self.author.username @property @lazy diff --git a/files/classes/user.py b/files/classes/user.py index e4e037811..69d4139a0 100644 --- a/files/classes/user.py +++ b/files/classes/user.py @@ -131,6 +131,8 @@ class User(Base): last_viewed_post_notifs = Column(Integer, default=0) last_viewed_log_notifs = Column(Integer, default=0) pronouns = Column(String, default='they/them') + bite = Column(Integer) + earlylife = Column(Integer) badges = relationship("Badge", order_by="Badge.created_utc", back_populates="user") subscriptions = relationship("Subscription", back_populates="user") @@ -162,6 +164,12 @@ class User(Base): return f"" + @property + @lazy + def name_color(self): + if self.bite: return "565656" + return self.namecolor + @lazy def mods(self, sub): return self.admin_level == 3 or bool(g.db.query(Mod.user_id).filter_by(user_id=self.id, sub=sub).one_or_none()) @@ -264,6 +272,9 @@ class User(Base): def user_awards(self): return_value = list(AWARDS2.values()) + if self.house: + return_value.append(HOUSE_AWARDS[self.house]) + awards_owned = g.db.query(AwardRelationship.kind, func.count()) \ .filter_by(user_id=self.id, submission_id=None, comment_id=None) \ .group_by(AwardRelationship.kind).all() @@ -611,7 +622,10 @@ class User(Base): @property @lazy def profile_url(self): - if self.agendaposter: return f"{SITE_FULL}/assets/images/pfps/agendaposter/{random.randint(1, 57)}.webp?v=1" + if self.agendaposter: + return f"{SITE_FULL}/assets/images/pfps/agendaposter/{random.randint(1, 57)}.webp?v=1" + if self.bite: + return f"{SITE_FULL}/e/marseyvampire.webp" if self.profileurl: if self.profileurl.startswith('/'): return SITE_FULL + self.profileurl return self.profileurl diff --git a/files/helpers/awards.py b/files/helpers/awards.py index d7e6e652b..3b1e802b9 100644 --- a/files/helpers/awards.py +++ b/files/helpers/awards.py @@ -73,6 +73,15 @@ def award_timers(v, bot=False): v.deflector = None notify_if_not_bot("Your deflector has expired!") dirty = True + if v.bite and v.bite < now: + v.bite = None + notify_if_not_bot("Your vampire status has ended!") + v.house = v.old_house + dirty = True + if v.earlylife and v.earlylife < now: + v.earlylife = None + notify_if_not_bot("Your earlylife status has expired!") + dirty = True if dirty: g.db.add(v) diff --git a/files/helpers/const.py b/files/helpers/const.py index 04f6824cf..d2826ce33 100644 --- a/files/helpers/const.py +++ b/files/helpers/const.py @@ -460,14 +460,6 @@ AWARDS = { "color": "text-gray", "price": 200 }, - "lootbox": { - "kind": "lootbox", - "title": "Lootbox", - "description": "", - "icon": "fas fa-box-open", - "color": "text-blue", - "price": 1000 - }, "shit": { "kind": "shit", "title": "Shit", @@ -556,6 +548,14 @@ AWARDS = { "color": "text-black", "price": 777 }, + "lootbox": { + "kind": "lootbox", + "title": "Lootbox", + "description": "", + "icon": "fas fa-box-open", + "color": "text-blue", + "price": 1000 + }, "beano": { "kind": "beano", "title": "Beano", @@ -770,6 +770,74 @@ AWARDS_DISABLED = [ 'grinch', 'haunt', 'upsidedown', 'stab', 'spiders', 'fog', # Homoween ] + +HOUSE_AWARDS = { + "Furry": { + "kind": "Furry", + "title": "OwOify", + "description": "OwOifies the comment. Does not work on posts.", + "icon": "fas fa-paw-simple", + "color": "text-purple", + "price": 400 + }, + "Femboy": { + "kind": "Femboy", + "title": "Marsify", + "description": "Emojifies the comment. Does not work on threads.", + "icon": "fas fa-cat", + "color": "text-white", + "price": 400 + }, + "Vampire": { + "kind": "Vampire", + "title": "Bite", + "description": "Turns the recipient into a vampire minion for 24 hours.", + "icon": "fas fa-bat", + "color": "text-gray", + "price": 400 + }, + "Racist": { + "kind": "Racist", + "title": "Early Life", + "description": "Checks the recipient’s Early Life section on Wikipedia. Notices.", + "icon": "fas fa-star-of-david", + "color": "text-yellow", + "price": 400 + }, + "Furry Founder": { + "kind": "Furry Founder", + "title": "OwOify", + "description": "OwOifies the comment. Does not work on posts.", + "icon": "fas fa-paw-simple", + "color": "text-purple", + "price": 300 + }, + "Femboy Founder": { + "kind": "Femboy Founder", + "title": "Marsify", + "description": "Emojifies the comment. Does not work on threads.", + "icon": "fas fa-kiss-wink-heart", + "color": "text-white", + "price": 300 + }, + "Vampire Founder": { + "kind": "Vampire Founder", + "title": "Bite", + "description": "Turns the recipient into a vampire for 24 hours.", + "icon": "fas fa-bat", + "color": "text-gray", + "price": 500 + }, + "Racist Founder": { + "kind": "Racist Founder", + "title": "Early Life", + "description": "Checks the recipient’s Early Life section on Wikipedia. Notices.", + "icon": "fas fa-star-of-david", + "color": "text-yellow", + "price": 300 + }, +} + if SITE_NAME != 'rDrama': AWARDS_DISABLED.append('progressivestack') @@ -877,6 +945,15 @@ christian_emojis = [':#marseyjesus:',':#marseyimmaculate:',':#marseymothermary:' db = db_session() marseys_const = [x[0] for x in db.query(Marsey.name).filter(Marsey.name!='chudsey').all()] 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(Marsey).all() +marsey_mappings = {} +for marsey in marseys: + for tag in marsey.tags.split(): + if tag in marsey_mappings: + marsey_mappings[tag].append(f':{marsey.name}:') + else: + marsey_mappings[tag] = [f':{marsey.name}:'] db.close() SNAPPY_MARSEYS = [] diff --git a/files/helpers/marsify.py b/files/helpers/marsify.py new file mode 100644 index 000000000..770ce83fc --- /dev/null +++ b/files/helpers/marsify.py @@ -0,0 +1,56 @@ +import random +import io +import json +import re +from .const import marsey_mappings + +WORD_DELIMITER = " " +MAX_EMOJIS_PER_BLOCK = 2 +BLOCK_REGEX = re.compile(r"\s*[^\s]*") +TRIM_REGEX = re.compile(r"^\W*|\W*$") + +def split_into_blocks(text): + if text == "" or BLOCK_REGEX.search(text) is None: + return [text] + blocks = [] + start = 0 + while start < len(text): + block_match = BLOCK_REGEX.search(text, start) + blocks.append(block_match.group()) + start = block_match.end() + return blocks + +def trim_nonalphabetical_characters(text): + return TRIM_REGEX.sub("", text) + +def marsify(text): + blocks = split_into_blocks(text) + new_blocks = [] + for i, block in enumerate(blocks): + new_blocks.append(block) + emojis = generate_emojis_from(block) + if emojis: + new_blocks.append(" " + emojis) + return "".join(new_blocks) + +def generate_emojis_from(block): + trimmed_block = trim_nonalphabetical_characters(block) + matching_emojis = get_matching_emojis(trimmed_block) + emojis = [] + if matching_emojis: + num_emojis = random.randint(0, MAX_EMOJIS_PER_BLOCK) + for x in range(num_emojis): + emojis.append(random.choice(matching_emojis)) + return "".join(emojis) + +def get_matching_emojis(trimmed_block): + key = get_alphanumeric_prefix(trimmed_block.lower()) + if key in marsey_mappings: + return marsey_mappings[get_alphanumeric_prefix(key)] + return [] + +def get_alphanumeric_prefix(s): + i = 0 + while i < len(s) and s[i].isalnum(): + i += 1 + return s[:i] \ No newline at end of file diff --git a/files/routes/admin.py b/files/routes/admin.py index 3d6558c32..8249c1a9c 100644 --- a/files/routes/admin.py +++ b/files/routes/admin.py @@ -20,7 +20,6 @@ import datetime import requests from urllib.parse import quote, urlencode - @app.post('/kippy') @admin_level_required(3) def kippy(v): diff --git a/files/routes/awards.py b/files/routes/awards.py index e97c1a443..3ebcb081f 100644 --- a/files/routes/awards.py +++ b/files/routes/awards.py @@ -10,6 +10,8 @@ from files.classes.award import * from .front import frontlist from flask import g, request from files.helpers.sanitize import filter_emojis_only +from files.helpers.marsify import marsify +import owoify from copy import deepcopy @app.get("/shop") @@ -21,6 +23,9 @@ def shop(v): AWARDS = deepcopy(AWARDS2) + if v.house: + AWARDS[v.house] = HOUSE_AWARDS[v.house] + for val in AWARDS.values(): val["owned"] = 0 for useraward in g.db.query(AwardRelationship).filter(AwardRelationship.user_id == v.id, AwardRelationship.submission_id == None, AwardRelationship.comment_id == None).all(): @@ -44,10 +49,13 @@ def buy(v, award): return {"error": "You can only buy the Benefactor award with marseybux."}, 403 if award == 'ghost' and v.admin_level < 2: - return {"error": "Only admins can buy that award."}, 403 + return {"error": "Only admins can buy this award."}, 403 AWARDS = deepcopy(AWARDS2) + if v.house: + AWARDS[v.house] = HOUSE_AWARDS[v.house] + if award not in AWARDS: abort(400) og_price = AWARDS[award]["price"] @@ -118,14 +126,18 @@ def award_thing(v, thing_type, id): if thing_type == 'post': thing = get_post(id) else: thing = get_comment(id) - if not thing: return {"error": f"That {thing_type} doesn't exist."}, 404 + if not thing: return {"error": f"This {thing_type} doesn't exist."}, 404 if v.shadowbanned: return render_template('errors/500.html', err=True, v=v), 500 kind = request.values.get("kind", "").strip() + AWARDS = deepcopy(AWARDS2) + if v.house: + AWARDS[v.house] = HOUSE_AWARDS[v.house] + if kind not in AWARDS: - return {"error": "That award doesn't exist."}, 404 + return {"error": "This award doesn't exist."}, 404 award = g.db.query(AwardRelationship).filter( AwardRelationship.kind == kind, @@ -327,6 +339,28 @@ def award_thing(v, thing_type, id): elif kind == "checkmark": author.verified = "Verified" badge_grant(user=author, badge_id=150) + elif "Vampire" in kind and kind == v.house: + if author.bite: author.bite += 21600 + else: author.bite = int(time.time()) + 21600 + author.old_house = author.house + author.house = 'Vampire' + elif "Racist" in kind and kind == v.house: + if author.earlylife: author.earlylife += 21600 + else: author.earlylife = int(time.time()) + 21600 + elif "Furry" in kind and kind == v.house and thing_type == 'comment': + body = thing.body + body = owoify.owoify(body) + if thing.award_count('Femboy', v) or thing.award_count('Femboy Founder', v): + body = marsify(body) + thing.body_html = sanitize(body, limit_pings=5) + g.db.add(thing) + elif "Femboy" in kind and kind == v.house and thing_type == 'comment': + body = thing.body + if thing.award_count('Furry', v) or thing.award_count('Furry Founder', v): + body = owoify.owoify(body) + body = marsify(body) + thing.body_html = sanitize(body, limit_pings=5) + g.db.add(thing) if author.received_award_count: author.received_award_count += 1 else: author.received_award_count = 1 diff --git a/files/routes/comments.py b/files/routes/comments.py index bf6e57b54..2d69c6e51 100644 --- a/files/routes/comments.py +++ b/files/routes/comments.py @@ -14,6 +14,8 @@ from files.routes.static import marsey_list from flask import * from files.__main__ import app, limiter from files.helpers.sanitize import filter_emojis_only +from files.helpers.marsify import marsify +import owoify import requests from shutil import copyfile from json import loads @@ -719,7 +721,13 @@ def edit_comment(cid, v): body = body.strip() - body_html = sanitize(body, edit=True, limit_pings=5) + body_for_sanitize = body + if c.award_count('Furry', v) or c.award_count('Furry Founder', v): + body_for_sanitize = owoify.owoify(body_for_sanitize) + if c.award_count('Femboy', v) or c.award_count('Femboy Founder', v): + body_for_sanitize = marsify(body_for_sanitize) + + body_html = sanitize(body_for_sanitize, edit=True, limit_pings=5) if len(body_html) > 20000: abort(400) diff --git a/files/routes/settings.py b/files/routes/settings.py index 19d244609..980850e6e 100644 --- a/files/routes/settings.py +++ b/files/routes/settings.py @@ -262,6 +262,8 @@ def settings_profile_post(v): house = request.values.get("house") if house and house in ("None","Furry","Femboy","Vampire","Racist") and FEATURES['HOUSES']: + if v.bite: abort(403) + if v.house: cost = 2000 else: cost = 500 diff --git a/files/templates/admin/lottery.html b/files/templates/admin/lottery.html index 5c0067887..03475ccaa 100644 --- a/files/templates/admin/lottery.html +++ b/files/templates/admin/lottery.html @@ -15,7 +15,7 @@ {% for user in participants %} {{loop.index}} - {{user.username}} + {{user.username}} {{user.currently_held_lottery_tickets}} {% endfor %} diff --git a/files/templates/admins.html b/files/templates/admins.html index f00b635c0..c530ead5f 100644 --- a/files/templates/admins.html +++ b/files/templates/admins.html @@ -21,7 +21,7 @@ {% for user in admins %} {{loop.index}} - {{user.username}} + {{user.username}} {{user.truecoins}} {{user.modaction_num}} diff --git a/files/templates/agendaposters.html b/files/templates/agendaposters.html index a73acfd93..ee3a87042 100644 --- a/files/templates/agendaposters.html +++ b/files/templates/agendaposters.html @@ -11,7 +11,7 @@ {% for user in users %} {{loop.index}} - {{user.username}} + {{user.username}} {% endfor %} diff --git a/files/templates/authforms.html b/files/templates/authforms.html index 49ffe08d4..dbd9e143e 100644 --- a/files/templates/authforms.html +++ b/files/templates/authforms.html @@ -44,6 +44,17 @@ {{v.css | safe}} {% endif %} + + {% if v.earlylife %} + + {% endif %} {% else %} diff --git a/files/templates/banned.html b/files/templates/banned.html index 87cbeea9b..17ce5b30e 100644 --- a/files/templates/banned.html +++ b/files/templates/banned.html @@ -13,9 +13,9 @@ {% for user in users %} {{loop.index}} - {{user.username}} + {{user.username}} {% if user.ban_reason %}{{user.ban_reason}}{% endif %} - {{user.banned_by.username}} + {{user.banned_by.username}} {% endfor %} diff --git a/files/templates/blocks.html b/files/templates/blocks.html index 29609a083..59fcae673 100644 --- a/files/templates/blocks.html +++ b/files/templates/blocks.html @@ -16,8 +16,8 @@ {% for user in users %} {{loop.index}} - {{user.username}} - {{targets[loop.index-1].username}} + {{user.username}} + {{targets[loop.index-1].username}} {% endfor %} diff --git a/files/templates/chat.html b/files/templates/chat.html index f35959d8b..0a4c49a2b 100644 --- a/files/templates/chat.html +++ b/files/templates/chat.html @@ -189,7 +189,7 @@ - + diff --git a/files/templates/comments.html b/files/templates/comments.html index e59391113..c7976b27b 100644 --- a/files/templates/comments.html +++ b/files/templates/comments.html @@ -73,7 +73,7 @@ {% if c.is_blocking and not c.ghost or (c.is_banned or c.deleted_utc) and not (v and v.admin_level > 1) and not (v and v.id==c.author_id) %}
- +
@@ -157,9 +157,9 @@ {% set isreply = False %} {% endif %} -
+
{% if not isreply %} - + {% endif %}
@@ -208,14 +208,14 @@ {% if c.author.verified %} {% endif %} - +
{% if c.author.hat_active -%} {%- endif %}
- {{c.author_name}} + {{c.author_name}}
{% if FEATURES['PRONOUNS'] %} {{c.author.pronouns}} @@ -327,7 +327,7 @@   - +