rDrama/files/routes/chat.py

347 lines
9.8 KiB
Python
Raw Normal View History

[DO NOT MERGE] import detanglation (#442) * move Base definition to files.classes.__init__.py * fix ImportError * move userpage listing to users.py * don't import the app from classes * consts: set default values to avoid crashes consts: warn if the secret key is the default config value * card view: sneed (user db schema) * cloudflare: use DEFAULT_CONFIG_VALUE * const: set default values * decouple media.py from __main__ * pass database to avoid imports * import cleanup and import request not in const, but in the requests mega import * move asset_submissions site check to __init__ * asset submissions feature flag * flag * g.is_tor * don't import request where it's not needed * i think this is fine * mail: move to own routes and helper * wrappers * required wrappers move * unfuck wrappers a bit * move snappy quotes and marseys to stateful consts * marsify * :pepodrool: * fix missing import * import cache * ...and settings.py * and static.py * static needs cache * route * lmao all of the jinja shit was in feeds.py amazing * classes should only import what they need from flask * import Response * hdjbjdhbhjf * ... * dfdfdfdf * make get a non-required import * isort imports (mostly) * but actually * configs * reload config on import * fgfgfgfg * config * config * initialize snappy and test * cookie of doom debug * edfjnkf * xikscdfd * debug config * set session cookie domain, i think this fixes the can't login bug * sdfbgnhvfdsghbnjfbdvvfghnn * hrsfxgf * dump the entire config on a request * kyskyskyskyskyskyskyskyskys * duifhdskfjdfd * dfdfdfdfdfdfdfdfdfdfdfdf * dfdfdfdf * imoprt all of the consts beacuse fuck it * 😭 * dfdfdfdfdfdfsdasdf * print the entire session * rffdfdfjkfksj * fgbhffh * not the secret keys * minor bug fixes * be helpful in the warning * gfgfgfg * move warning lower * isort main imports (i hope this doesn't fuck something up) * test * session cookie domain redux * dfdfdfd * try only importing Flask * formkeys fix * y * :pepodrool: * route helper * remove before flight * dfdfdfdfdf * isort classes * isort helpers * move check_for_alts to routehelpers and also sort imports and get rid of unused ones * that previous commit but actkally * readd the cache in a dozen places they were implicitly imported * use g.is_tor instead of request.headers. bla bla bla * upgrade streamers to their own route file * get rid of unused imports in __main__ * fgfgf * don't pull in the entire ORM where we don't need it * features * explicit imports for the get helper * explicit imports for the get helper redux * testing allroutes * remove unused import * decouple flask from classes * syntax fix also remember these have side fx for some reason (why?) * move side effects out of the class * posts * testing on devrama * settings * reloading * settingssdsdsds * streamer features * site settings * testing settings on devrama * import * fix modlog * remove debug stuff * revert commit 67275b21ab6e2f2520819e84d10bfc1c746a15b6 * archiveorg to _archiveorg * skhudkfkjfd * fix cron for PCM * fix bugs that snekky wants me to * Fix call to realbody passing db, standardize kwarg * test * import check_for_alts from the right place * cloudflare * testing on devrama * fix cron i think * shadow properly * tasks * Remove print which will surely be annoying in prod. * v and create new session * use files.classes * make errors import little and fix rare 500 in /allow_nsfw * Revert "use files.classes" This reverts commit 98c10b876cf86ce058b7fb955cf1ec0bfb9996c6. * pass v to media functions rather than using g * fix * dfdfdfdfd * cleanup, py type checking is dumb so don't use it where it causes issues * Fix some merge bugs, add DEFAULT_RATELIMIT to main. * Fix imports on sqlalchemy expressions. * `from random import random` is an error. * Fix replies db param. * errors: fix missing import * fix rare 500: only send to GIFT_NOTIF_ID if it exists, and send them the right text * Fix signup formkey. * fix 2 500s * propagate db to submissions * fix replies * dfdfdfdf * Fix verifiedcolor. * is_manual * can't use getters outside of an app context * don't attempt to do gumroad on sites where it's not enabled * don't attempt to do gumraod on sites's where it's unnecessary * Revert "don't attempt to do gumroad on sites where it's not enabled" This reverts commit 6f8a6331878655492dfaf1907b27f8be513c14d3. * fix 500 * validate media type Co-authored-by: TLSM <duolsm@outlook.com>
2022-11-15 09:19:08 +00:00
import atexit
2022-03-24 19:44:12 +00:00
import time
2022-09-24 22:05:50 +00:00
import uuid
from hashlib import md5
[DO NOT MERGE] import detanglation (#442) * move Base definition to files.classes.__init__.py * fix ImportError * move userpage listing to users.py * don't import the app from classes * consts: set default values to avoid crashes consts: warn if the secret key is the default config value * card view: sneed (user db schema) * cloudflare: use DEFAULT_CONFIG_VALUE * const: set default values * decouple media.py from __main__ * pass database to avoid imports * import cleanup and import request not in const, but in the requests mega import * move asset_submissions site check to __init__ * asset submissions feature flag * flag * g.is_tor * don't import request where it's not needed * i think this is fine * mail: move to own routes and helper * wrappers * required wrappers move * unfuck wrappers a bit * move snappy quotes and marseys to stateful consts * marsify * :pepodrool: * fix missing import * import cache * ...and settings.py * and static.py * static needs cache * route * lmao all of the jinja shit was in feeds.py amazing * classes should only import what they need from flask * import Response * hdjbjdhbhjf * ... * dfdfdfdf * make get a non-required import * isort imports (mostly) * but actually * configs * reload config on import * fgfgfgfg * config * config * initialize snappy and test * cookie of doom debug * edfjnkf * xikscdfd * debug config * set session cookie domain, i think this fixes the can't login bug * sdfbgnhvfdsghbnjfbdvvfghnn * hrsfxgf * dump the entire config on a request * kyskyskyskyskyskyskyskyskys * duifhdskfjdfd * dfdfdfdfdfdfdfdfdfdfdfdf * dfdfdfdf * imoprt all of the consts beacuse fuck it * 😭 * dfdfdfdfdfdfsdasdf * print the entire session * rffdfdfjkfksj * fgbhffh * not the secret keys * minor bug fixes * be helpful in the warning * gfgfgfg * move warning lower * isort main imports (i hope this doesn't fuck something up) * test * session cookie domain redux * dfdfdfd * try only importing Flask * formkeys fix * y * :pepodrool: * route helper * remove before flight * dfdfdfdfdf * isort classes * isort helpers * move check_for_alts to routehelpers and also sort imports and get rid of unused ones * that previous commit but actkally * readd the cache in a dozen places they were implicitly imported * use g.is_tor instead of request.headers. bla bla bla * upgrade streamers to their own route file * get rid of unused imports in __main__ * fgfgf * don't pull in the entire ORM where we don't need it * features * explicit imports for the get helper * explicit imports for the get helper redux * testing allroutes * remove unused import * decouple flask from classes * syntax fix also remember these have side fx for some reason (why?) * move side effects out of the class * posts * testing on devrama * settings * reloading * settingssdsdsds * streamer features * site settings * testing settings on devrama * import * fix modlog * remove debug stuff * revert commit 67275b21ab6e2f2520819e84d10bfc1c746a15b6 * archiveorg to _archiveorg * skhudkfkjfd * fix cron for PCM * fix bugs that snekky wants me to * Fix call to realbody passing db, standardize kwarg * test * import check_for_alts from the right place * cloudflare * testing on devrama * fix cron i think * shadow properly * tasks * Remove print which will surely be annoying in prod. * v and create new session * use files.classes * make errors import little and fix rare 500 in /allow_nsfw * Revert "use files.classes" This reverts commit 98c10b876cf86ce058b7fb955cf1ec0bfb9996c6. * pass v to media functions rather than using g * fix * dfdfdfdfd * cleanup, py type checking is dumb so don't use it where it causes issues * Fix some merge bugs, add DEFAULT_RATELIMIT to main. * Fix imports on sqlalchemy expressions. * `from random import random` is an error. * Fix replies db param. * errors: fix missing import * fix rare 500: only send to GIFT_NOTIF_ID if it exists, and send them the right text * Fix signup formkey. * fix 2 500s * propagate db to submissions * fix replies * dfdfdfdf * Fix verifiedcolor. * is_manual * can't use getters outside of an app context * don't attempt to do gumroad on sites where it's not enabled * don't attempt to do gumraod on sites's where it's unnecessary * Revert "don't attempt to do gumroad on sites where it's not enabled" This reverts commit 6f8a6331878655492dfaf1907b27f8be513c14d3. * fix 500 * validate media type Co-authored-by: TLSM <duolsm@outlook.com>
2022-11-15 09:19:08 +00:00
2023-09-05 15:32:57 +00:00
from flask_socketio import SocketIO, emit, join_room, leave_room
from flask import request
[DO NOT MERGE] import detanglation (#442) * move Base definition to files.classes.__init__.py * fix ImportError * move userpage listing to users.py * don't import the app from classes * consts: set default values to avoid crashes consts: warn if the secret key is the default config value * card view: sneed (user db schema) * cloudflare: use DEFAULT_CONFIG_VALUE * const: set default values * decouple media.py from __main__ * pass database to avoid imports * import cleanup and import request not in const, but in the requests mega import * move asset_submissions site check to __init__ * asset submissions feature flag * flag * g.is_tor * don't import request where it's not needed * i think this is fine * mail: move to own routes and helper * wrappers * required wrappers move * unfuck wrappers a bit * move snappy quotes and marseys to stateful consts * marsify * :pepodrool: * fix missing import * import cache * ...and settings.py * and static.py * static needs cache * route * lmao all of the jinja shit was in feeds.py amazing * classes should only import what they need from flask * import Response * hdjbjdhbhjf * ... * dfdfdfdf * make get a non-required import * isort imports (mostly) * but actually * configs * reload config on import * fgfgfgfg * config * config * initialize snappy and test * cookie of doom debug * edfjnkf * xikscdfd * debug config * set session cookie domain, i think this fixes the can't login bug * sdfbgnhvfdsghbnjfbdvvfghnn * hrsfxgf * dump the entire config on a request * kyskyskyskyskyskyskyskyskys * duifhdskfjdfd * dfdfdfdfdfdfdfdfdfdfdfdf * dfdfdfdf * imoprt all of the consts beacuse fuck it * 😭 * dfdfdfdfdfdfsdasdf * print the entire session * rffdfdfjkfksj * fgbhffh * not the secret keys * minor bug fixes * be helpful in the warning * gfgfgfg * move warning lower * isort main imports (i hope this doesn't fuck something up) * test * session cookie domain redux * dfdfdfd * try only importing Flask * formkeys fix * y * :pepodrool: * route helper * remove before flight * dfdfdfdfdf * isort classes * isort helpers * move check_for_alts to routehelpers and also sort imports and get rid of unused ones * that previous commit but actkally * readd the cache in a dozen places they were implicitly imported * use g.is_tor instead of request.headers. bla bla bla * upgrade streamers to their own route file * get rid of unused imports in __main__ * fgfgf * don't pull in the entire ORM where we don't need it * features * explicit imports for the get helper * explicit imports for the get helper redux * testing allroutes * remove unused import * decouple flask from classes * syntax fix also remember these have side fx for some reason (why?) * move side effects out of the class * posts * testing on devrama * settings * reloading * settingssdsdsds * streamer features * site settings * testing settings on devrama * import * fix modlog * remove debug stuff * revert commit 67275b21ab6e2f2520819e84d10bfc1c746a15b6 * archiveorg to _archiveorg * skhudkfkjfd * fix cron for PCM * fix bugs that snekky wants me to * Fix call to realbody passing db, standardize kwarg * test * import check_for_alts from the right place * cloudflare * testing on devrama * fix cron i think * shadow properly * tasks * Remove print which will surely be annoying in prod. * v and create new session * use files.classes * make errors import little and fix rare 500 in /allow_nsfw * Revert "use files.classes" This reverts commit 98c10b876cf86ce058b7fb955cf1ec0bfb9996c6. * pass v to media functions rather than using g * fix * dfdfdfdfd * cleanup, py type checking is dumb so don't use it where it causes issues * Fix some merge bugs, add DEFAULT_RATELIMIT to main. * Fix imports on sqlalchemy expressions. * `from random import random` is an error. * Fix replies db param. * errors: fix missing import * fix rare 500: only send to GIFT_NOTIF_ID if it exists, and send them the right text * Fix signup formkey. * fix 2 500s * propagate db to submissions * fix replies * dfdfdfdf * Fix verifiedcolor. * is_manual * can't use getters outside of an app context * don't attempt to do gumroad on sites where it's not enabled * don't attempt to do gumraod on sites's where it's unnecessary * Revert "don't attempt to do gumroad on sites where it's not enabled" This reverts commit 6f8a6331878655492dfaf1907b27f8be513c14d3. * fix 500 * validate media type Co-authored-by: TLSM <duolsm@outlook.com>
2022-11-15 09:19:08 +00:00
from files.helpers.actions import *
2022-07-11 09:52:59 +00:00
from files.helpers.alerts import *
from files.helpers.config.const import *
from files.helpers.slurs_and_profanities import censor_slurs_profanities
from files.helpers.regex import *
2023-03-06 19:52:31 +00:00
from files.helpers.media import *
2023-02-07 03:31:49 +00:00
from files.helpers.sanitize import *
2022-12-26 03:14:02 +00:00
from files.helpers.alerts import push_notif
2023-10-05 10:09:58 +00:00
from files.helpers.can_see import *
[DO NOT MERGE] import detanglation (#442) * move Base definition to files.classes.__init__.py * fix ImportError * move userpage listing to users.py * don't import the app from classes * consts: set default values to avoid crashes consts: warn if the secret key is the default config value * card view: sneed (user db schema) * cloudflare: use DEFAULT_CONFIG_VALUE * const: set default values * decouple media.py from __main__ * pass database to avoid imports * import cleanup and import request not in const, but in the requests mega import * move asset_submissions site check to __init__ * asset submissions feature flag * flag * g.is_tor * don't import request where it's not needed * i think this is fine * mail: move to own routes and helper * wrappers * required wrappers move * unfuck wrappers a bit * move snappy quotes and marseys to stateful consts * marsify * :pepodrool: * fix missing import * import cache * ...and settings.py * and static.py * static needs cache * route * lmao all of the jinja shit was in feeds.py amazing * classes should only import what they need from flask * import Response * hdjbjdhbhjf * ... * dfdfdfdf * make get a non-required import * isort imports (mostly) * but actually * configs * reload config on import * fgfgfgfg * config * config * initialize snappy and test * cookie of doom debug * edfjnkf * xikscdfd * debug config * set session cookie domain, i think this fixes the can't login bug * sdfbgnhvfdsghbnjfbdvvfghnn * hrsfxgf * dump the entire config on a request * kyskyskyskyskyskyskyskyskys * duifhdskfjdfd * dfdfdfdfdfdfdfdfdfdfdfdf * dfdfdfdf * imoprt all of the consts beacuse fuck it * 😭 * dfdfdfdfdfdfsdasdf * print the entire session * rffdfdfjkfksj * fgbhffh * not the secret keys * minor bug fixes * be helpful in the warning * gfgfgfg * move warning lower * isort main imports (i hope this doesn't fuck something up) * test * session cookie domain redux * dfdfdfd * try only importing Flask * formkeys fix * y * :pepodrool: * route helper * remove before flight * dfdfdfdfdf * isort classes * isort helpers * move check_for_alts to routehelpers and also sort imports and get rid of unused ones * that previous commit but actkally * readd the cache in a dozen places they were implicitly imported * use g.is_tor instead of request.headers. bla bla bla * upgrade streamers to their own route file * get rid of unused imports in __main__ * fgfgf * don't pull in the entire ORM where we don't need it * features * explicit imports for the get helper * explicit imports for the get helper redux * testing allroutes * remove unused import * decouple flask from classes * syntax fix also remember these have side fx for some reason (why?) * move side effects out of the class * posts * testing on devrama * settings * reloading * settingssdsdsds * streamer features * site settings * testing settings on devrama * import * fix modlog * remove debug stuff * revert commit 67275b21ab6e2f2520819e84d10bfc1c746a15b6 * archiveorg to _archiveorg * skhudkfkjfd * fix cron for PCM * fix bugs that snekky wants me to * Fix call to realbody passing db, standardize kwarg * test * import check_for_alts from the right place * cloudflare * testing on devrama * fix cron i think * shadow properly * tasks * Remove print which will surely be annoying in prod. * v and create new session * use files.classes * make errors import little and fix rare 500 in /allow_nsfw * Revert "use files.classes" This reverts commit 98c10b876cf86ce058b7fb955cf1ec0bfb9996c6. * pass v to media functions rather than using g * fix * dfdfdfdfd * cleanup, py type checking is dumb so don't use it where it causes issues * Fix some merge bugs, add DEFAULT_RATELIMIT to main. * Fix imports on sqlalchemy expressions. * `from random import random` is an error. * Fix replies db param. * errors: fix missing import * fix rare 500: only send to GIFT_NOTIF_ID if it exists, and send them the right text * Fix signup formkey. * fix 2 500s * propagate db to submissions * fix replies * dfdfdfdf * Fix verifiedcolor. * is_manual * can't use getters outside of an app context * don't attempt to do gumroad on sites where it's not enabled * don't attempt to do gumraod on sites's where it's unnecessary * Revert "don't attempt to do gumroad on sites where it's not enabled" This reverts commit 6f8a6331878655492dfaf1907b27f8be513c14d3. * fix 500 * validate media type Co-authored-by: TLSM <duolsm@outlook.com>
2022-11-15 09:19:08 +00:00
from files.routes.wrappers import *
Bring back orgies (watchparties), now controllable by admins, and generally better in all ways (#165) This PR adds orgies back into rdrama. Long ago, snakes made the original orgy code, and it was super fun. But he had to rush it out, and ended up making it a bit unsustainable, and had a couple questionable coding decisions, which meant that it had to be removed. Hey, the man literally did it in a few hours before the DB trial continued, lmao. Anyways, I took my own approach to it. I do not use iframes, i just just repurpose code from /chat window. Because I had that freedom, I also moved things around to make the user experience a bit better. I also added a title to give users some context about what's happening. Check it out ![image](/attachments/6719146c-4922-4d75-967d-8d424a09b198) Most importantly, this is all configurable from the site. Admins with the permission "ORGIES" will see this in their control panel ![image](/attachments/423d6046-a11d-4e84-bd2c-a2a641afd552) Nigga, idk where to put it, so I made my own category. If there is no orgy in progress, admins will see this: ![image](/attachments/7c64b9fa-cdf4-4986-a0c4-f2324878062e) Click the button, and, viola, the orgy begins. If there is an orgy in progress, the page will look like this: ![image](/attachments/b65be4b3-5db1-43cb-8857-7d3a8ea24ca7) Click the button, and the orgy stops. If an orgy is in progress, navigating to /chat will take the user to the orgy seemlessly. But what if they don't want to participate, liek some kind of spoilsport? Just navigate to /old_chat. That's just about it, it's really that simple. I have lots of ideas for the future, but I'll let that wait til later :). A few notes about implementation: - I moved some functionality out of /templates/chat.html and into /templates/util/macros.html. This is just so I could reference the code directly from my new template, /templates/orgy.html. - The orgy is stored as a single row in the new table "orgies". Okay, I know this is a little silly, but you know what they say: "if it's stupid and it works, it's not stupid". (tbf the oceangate ceo also said that) Co-authored-by: Chuck Sneed <sneed@formerlychucks.net> Reviewed-on: https://fsdfsd.net/rDrama/rDrama/pulls/165 Co-authored-by: HeyMoon <heymoon@noreply.fsdfsd.net> Co-committed-by: HeyMoon <heymoon@noreply.fsdfsd.net>
2023-07-02 23:55:37 +00:00
from files.classes.orgy import *
[DO NOT MERGE] import detanglation (#442) * move Base definition to files.classes.__init__.py * fix ImportError * move userpage listing to users.py * don't import the app from classes * consts: set default values to avoid crashes consts: warn if the secret key is the default config value * card view: sneed (user db schema) * cloudflare: use DEFAULT_CONFIG_VALUE * const: set default values * decouple media.py from __main__ * pass database to avoid imports * import cleanup and import request not in const, but in the requests mega import * move asset_submissions site check to __init__ * asset submissions feature flag * flag * g.is_tor * don't import request where it's not needed * i think this is fine * mail: move to own routes and helper * wrappers * required wrappers move * unfuck wrappers a bit * move snappy quotes and marseys to stateful consts * marsify * :pepodrool: * fix missing import * import cache * ...and settings.py * and static.py * static needs cache * route * lmao all of the jinja shit was in feeds.py amazing * classes should only import what they need from flask * import Response * hdjbjdhbhjf * ... * dfdfdfdf * make get a non-required import * isort imports (mostly) * but actually * configs * reload config on import * fgfgfgfg * config * config * initialize snappy and test * cookie of doom debug * edfjnkf * xikscdfd * debug config * set session cookie domain, i think this fixes the can't login bug * sdfbgnhvfdsghbnjfbdvvfghnn * hrsfxgf * dump the entire config on a request * kyskyskyskyskyskyskyskyskys * duifhdskfjdfd * dfdfdfdfdfdfdfdfdfdfdfdf * dfdfdfdf * imoprt all of the consts beacuse fuck it * 😭 * dfdfdfdfdfdfsdasdf * print the entire session * rffdfdfjkfksj * fgbhffh * not the secret keys * minor bug fixes * be helpful in the warning * gfgfgfg * move warning lower * isort main imports (i hope this doesn't fuck something up) * test * session cookie domain redux * dfdfdfd * try only importing Flask * formkeys fix * y * :pepodrool: * route helper * remove before flight * dfdfdfdfdf * isort classes * isort helpers * move check_for_alts to routehelpers and also sort imports and get rid of unused ones * that previous commit but actkally * readd the cache in a dozen places they were implicitly imported * use g.is_tor instead of request.headers. bla bla bla * upgrade streamers to their own route file * get rid of unused imports in __main__ * fgfgf * don't pull in the entire ORM where we don't need it * features * explicit imports for the get helper * explicit imports for the get helper redux * testing allroutes * remove unused import * decouple flask from classes * syntax fix also remember these have side fx for some reason (why?) * move side effects out of the class * posts * testing on devrama * settings * reloading * settingssdsdsds * streamer features * site settings * testing settings on devrama * import * fix modlog * remove debug stuff * revert commit 67275b21ab6e2f2520819e84d10bfc1c746a15b6 * archiveorg to _archiveorg * skhudkfkjfd * fix cron for PCM * fix bugs that snekky wants me to * Fix call to realbody passing db, standardize kwarg * test * import check_for_alts from the right place * cloudflare * testing on devrama * fix cron i think * shadow properly * tasks * Remove print which will surely be annoying in prod. * v and create new session * use files.classes * make errors import little and fix rare 500 in /allow_nsfw * Revert "use files.classes" This reverts commit 98c10b876cf86ce058b7fb955cf1ec0bfb9996c6. * pass v to media functions rather than using g * fix * dfdfdfdfd * cleanup, py type checking is dumb so don't use it where it causes issues * Fix some merge bugs, add DEFAULT_RATELIMIT to main. * Fix imports on sqlalchemy expressions. * `from random import random` is an error. * Fix replies db param. * errors: fix missing import * fix rare 500: only send to GIFT_NOTIF_ID if it exists, and send them the right text * Fix signup formkey. * fix 2 500s * propagate db to submissions * fix replies * dfdfdfdf * Fix verifiedcolor. * is_manual * can't use getters outside of an app context * don't attempt to do gumroad on sites where it's not enabled * don't attempt to do gumraod on sites's where it's unnecessary * Revert "don't attempt to do gumroad on sites where it's not enabled" This reverts commit 6f8a6331878655492dfaf1907b27f8be513c14d3. * fix 500 * validate media type Co-authored-by: TLSM <duolsm@outlook.com>
2022-11-15 09:19:08 +00:00
from files.__main__ import app, cache, limiter
2022-03-20 20:41:54 +00:00
from engineio.payload import Payload
Payload.max_decode_packets = 50
2023-01-21 10:36:21 +00:00
socketio = SocketIO(
app,
async_mode='gevent',
2023-10-26 16:17:50 +00:00
max_http_buffer_size=8388608, #for images
2023-01-21 10:36:21 +00:00
)
2022-03-24 19:44:12 +00:00
2023-01-23 06:04:02 +00:00
muted = cache.get(f'muted') or {}
2023-09-05 15:32:57 +00:00
2023-10-10 19:30:52 +00:00
messages = cache.get(f'messages') or {}
online = {}
typing = []
cache.set('loggedin_chat', len(online), timeout=86400)
2023-10-07 18:25:22 +00:00
2023-09-14 17:20:44 +00:00
def auth_required_socketio(f):
2023-07-24 10:33:04 +00:00
def wrapper(*args, **kwargs):
v = get_logged_in_user()
if not v: return '', 401
2023-09-14 17:20:44 +00:00
if v.is_permabanned: return '', 403
2023-07-24 10:33:04 +00:00
return make_response(f(*args, v=v, **kwargs))
wrapper.__name__ = f.__name__
return wrapper
2023-09-14 17:20:44 +00:00
def is_not_banned_socketio(f):
2023-07-24 10:33:04 +00:00
def wrapper(*args, **kwargs):
v = get_logged_in_user()
if not v: return '', 401
2023-09-14 17:20:44 +00:00
if v.is_suspended: return '', 403
2023-07-24 10:33:04 +00:00
return make_response(f(*args, v=v, **kwargs))
wrapper.__name__ = f.__name__
return wrapper
2023-10-05 13:44:31 +00:00
CHAT_ERROR_MESSAGE = f"To prevent spam, you'll need {TRUESCORE_MINIMUM} truescore (this is {TRUESCORE_MINIMUM} votes, either up or down, on any threads or comments you've made) in order to access chat. Sorry! I love you 💖"
2023-08-13 15:13:09 +00:00
2023-09-26 15:19:29 +00:00
@app.post('/refresh_chat')
def refresh_chat():
2023-10-10 19:30:52 +00:00
emit('refresh_chat', namespace='/', to="chat")
return ''
2022-03-24 19:44:12 +00:00
@app.get("/chat")
@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400)
@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400, key_func=get_ID)
@auth_required
2022-08-17 20:30:07 +00:00
def chat(v):
2023-08-13 15:13:09 +00:00
if not v.allowed_in_chat:
abort(403, CHAT_ERROR_MESSAGE)
2023-10-10 19:30:52 +00:00
displayed_messages = {k: val for k, val in messages.items() if val["user_id"] not in v.userblocks}
2023-09-05 15:32:57 +00:00
2023-10-13 15:56:12 +00:00
orgy = get_running_orgy(v)
if orgy:
2023-10-13 14:15:27 +00:00
x = secrets.token_urlsafe(8)
2024-03-04 02:06:11 +00:00
orgies = g.db.query(Orgy).order_by(Orgy.start_utc).all()
return render_template("orgy.html", v=v, messages=displayed_messages, orgy=orgy, x=x, orgies=orgies)
2023-09-24 22:12:42 +00:00
return render_template("chat.html", v=v, messages=displayed_messages)
2022-03-24 19:44:12 +00:00
@socketio.on('speak')
2023-07-24 10:33:04 +00:00
@is_not_banned_socketio
2022-03-24 19:44:12 +00:00
def speak(data, v):
2023-01-21 10:36:21 +00:00
image = None
if data['file']:
name = f'/chat_images/{time.time()}'.replace('.','') + '.webp'
with open(name, 'wb') as f:
f.write(data['file'])
image = process_image(name, v)
2023-08-13 15:13:09 +00:00
if not v.allowed_in_chat:
return '', 403
2022-03-24 21:01:04 +00:00
global messages
2022-08-14 02:38:07 +00:00
text = data['message'][:CHAT_LENGTH_LIMIT]
2023-03-12 13:02:31 +00:00
if image: text += f'\n\n{image}'
2022-11-16 14:00:04 +00:00
if not text: return '', 400
2022-08-14 02:38:07 +00:00
2023-03-19 12:01:54 +00:00
text_html = sanitize(text, count_emojis=True, chat=True)
2023-01-27 07:07:58 +00:00
if isinstance(text_html , tuple):
return text_html
2022-09-24 22:05:50 +00:00
quotes = data['quotes']
2023-09-29 04:44:47 +00:00
id = secrets.token_urlsafe(5)
2023-01-23 02:45:34 +00:00
2023-01-23 06:04:02 +00:00
self_only = False
vname = v.username.lower()
if vname in muted:
if time.time() < muted[vname]:
self_only = True
else:
del muted[vname]
refresh_online()
2023-01-23 06:04:02 +00:00
if SITE == 'rdrama.net' and v.admin_level < PERMS['BYPASS_ANTISPAM_CHECKS']:
2023-01-24 05:28:56 +00:00
def shut_up():
self_only = True
muted_until = int(time.time() + 600)
2023-01-24 05:28:56 +00:00
muted[vname] = muted_until
refresh_online()
2023-01-23 06:04:02 +00:00
2023-01-24 05:28:56 +00:00
if not self_only:
2023-10-10 19:30:52 +00:00
identical = [x for x in list(messages.values())[-5:] if v.id == x['user_id'] and text == x['text']]
2023-01-24 05:28:56 +00:00
if len(identical) >= 3: shut_up()
2023-01-23 06:04:02 +00:00
2023-01-24 05:28:56 +00:00
if not self_only:
2023-10-10 19:30:52 +00:00
count = len([x for x in list(messages.values())[-12:] if v.id == x['user_id']])
2023-01-24 05:28:56 +00:00
if count >= 10: shut_up()
2023-01-23 06:04:02 +00:00
2023-01-24 05:28:56 +00:00
if not self_only:
2023-10-10 19:30:52 +00:00
count = len([x for x in list(messages.values())[-25:] if v.id == x['user_id']])
2023-01-24 05:28:56 +00:00
if count >= 20: shut_up()
2023-01-23 02:45:34 +00:00
2022-11-16 14:00:04 +00:00
data = {
2023-01-22 06:00:50 +00:00
"id": id,
2023-10-10 19:30:52 +00:00
"quotes": quotes if messages.get(quotes) else '',
2022-12-24 22:21:49 +00:00
"hat": v.hat_active(v)[0],
2022-09-27 05:15:22 +00:00
"user_id": v.id,
2022-03-28 10:06:57 +00:00
"username": v.username,
"namecolor": v.name_color,
2023-08-14 12:26:42 +00:00
"patron": v.patron,
2023-10-26 19:16:27 +00:00
"pride_username": bool(v.has_badge(303)),
2022-03-28 10:06:57 +00:00
"text": text,
"text_censored": censor_slurs_profanities(text, 'chat', True),
2022-03-28 10:06:57 +00:00
"text_html": text_html,
"text_html_censored": censor_slurs_profanities(text_html, 'chat'),
2022-09-24 20:36:56 +00:00
"time": int(time.time()),
2022-03-24 19:44:12 +00:00
}
2023-01-01 11:36:20 +00:00
2022-03-24 21:01:04 +00:00
if v.admin_level >= PERMS['USER_BAN']:
2022-03-24 21:01:04 +00:00
text = text.lower()
for i in mute_regex.finditer(text):
2022-08-13 09:24:56 +00:00
username = i.group(1).lower()
2023-01-23 06:04:02 +00:00
muted_until = int(int(i.group(2)) * 60 + time.time())
muted[username] = muted_until
refresh_online()
2023-01-23 06:04:02 +00:00
2023-02-07 03:31:49 +00:00
if self_only or v.shadowbanned or execute_blackjack(v, None, text, "chat"):
emit('speak', data)
2023-01-23 06:04:02 +00:00
else:
2023-10-10 19:30:52 +00:00
emit('speak', data, room="chat", broadcast=True)
messages[id] = data
messages = dict(list(messages.items())[-250:])
2022-03-24 21:01:04 +00:00
typing = []
2022-12-25 20:30:50 +00:00
2023-10-10 19:30:52 +00:00
return ''
2022-03-24 19:44:12 +00:00
2023-01-24 05:28:56 +00:00
def refresh_online():
2023-10-10 19:30:52 +00:00
for k, val in list(online.items()):
if time.time() > val[0]:
del online[k]
if val[1] in typing:
typing.remove(val[1])
2023-10-10 19:30:52 +00:00
data = [list(online.values()), muted]
emit("online", data, room="chat", broadcast=True)
cache.set('loggedin_chat', len(online), timeout=86400)
2022-03-24 19:44:12 +00:00
@socketio.on('connect')
@auth_required_socketio
2022-03-24 19:44:12 +00:00
def connect(v):
2023-10-10 19:30:52 +00:00
if request.referrer == f'{SITE_FULL}/notifications/messages':
2023-09-26 20:05:39 +00:00
join_room(v.id)
return ''
2023-10-10 19:30:52 +00:00
join_room("chat")
2023-09-05 15:32:57 +00:00
2023-10-10 19:30:52 +00:00
if v.username in typing:
typing.remove(v.username)
2023-10-10 19:30:52 +00:00
emit('typing', typing, room="chat")
return ''
2023-10-04 19:02:53 +00:00
2022-03-24 19:44:12 +00:00
@socketio.on('disconnect')
@auth_required_socketio
2022-03-24 19:44:12 +00:00
def disconnect(v):
2023-10-10 19:30:52 +00:00
if request.referrer == f'{SITE_FULL}/notifications/messages':
leave_room(v.id)
return ''
2023-10-10 19:30:52 +00:00
online.pop(v.id, None)
2023-09-06 14:29:31 +00:00
2023-10-10 19:30:52 +00:00
if v.username in typing:
typing.remove(v.username)
2023-09-07 15:26:31 +00:00
2023-10-10 19:30:52 +00:00
leave_room("chat")
refresh_online()
return ''
2022-03-24 19:44:12 +00:00
@socketio.on('heartbeat')
@auth_required_socketio
def heartbeat(v):
expire_utc = int(time.time()) + 3610
2023-10-10 19:30:52 +00:00
already_there = online.get(v.id)
2023-10-26 19:16:27 +00:00
online[v.id] = (expire_utc, v.username, v.name_color, v.patron, v.id, bool(v.has_badge(303)))
if not already_there:
refresh_online()
2023-10-10 19:30:52 +00:00
return ''
2022-03-24 19:44:12 +00:00
@socketio.on('typing')
2023-07-24 10:33:04 +00:00
@is_not_banned_socketio
2022-03-24 19:44:12 +00:00
def typing_indicator(data, v):
2023-10-10 19:30:52 +00:00
if data and v.username not in typing:
typing.append(v.username)
elif not data and v.username in typing:
typing.remove(v.username)
2022-03-24 19:44:12 +00:00
2023-10-10 19:30:52 +00:00
emit('typing', typing, room="chat", broadcast=True)
return ''
2022-03-24 19:44:12 +00:00
2022-09-10 09:31:51 +00:00
@socketio.on('delete')
@admin_level_required(PERMS['POST_COMMENT_MODERATION'])
2023-01-21 10:36:21 +00:00
def delete(id, v):
2023-10-10 19:30:52 +00:00
messages.pop(id, None)
emit('delete', id, room="chat", broadcast=True)
return ''
2022-09-10 09:31:51 +00:00
2022-03-24 19:44:12 +00:00
def close_running_threads():
cache.set('messages', messages, timeout=86400)
cache.set('muted', muted, timeout=86400)
2022-09-24 04:26:44 +00:00
atexit.register(close_running_threads)
2023-09-26 20:05:39 +00:00
@app.post("/reply")
@limiter.limit('1/second', scope=rpath)
@limiter.limit('1/second', scope=rpath, key_func=get_ID)
@limiter.limit("6/minute;50/hour;200/day", deduct_when=lambda response: response.status_code < 400)
@limiter.limit("6/minute;50/hour;200/day", deduct_when=lambda response: response.status_code < 400, key_func=get_ID)
@auth_required
def messagereply(v):
2024-02-14 09:27:00 +00:00
body = request.values.get("body", "").strip()
if len(body) > COMMENT_BODY_LENGTH_LIMIT:
2024-02-14 09:34:49 +00:00
abort(400, f'Message is too long (max {COMMENT_BODY_LENGTH_LIMIT} characters)')
2023-09-26 20:05:39 +00:00
id = request.values.get("parent_id")
parent = get_comment(id, v=v)
if parent.parent_post or parent.wall_user_id:
abort(403, "You can only reply to messages!")
user_id = parent.author.id
if v.is_permabanned and parent.sentto != MODMAIL_ID:
abort(403, "You are permabanned and may not reply to messages!")
elif v.is_muted and parent.sentto == MODMAIL_ID:
abort(403, "You are muted!")
2023-09-26 20:05:39 +00:00
if parent.sentto == MODMAIL_ID: user_id = None
elif v.id == user_id: user_id = parent.sentto
user = None
if user_id:
user = get_account(user_id, v=v, include_blocks=True)
if hasattr(user, 'is_blocking') and user.is_blocking:
abort(403, f"You're blocking @{user.username}")
elif (v.admin_level <= PERMS['MESSAGE_BLOCKED_USERS']
and hasattr(user, 'is_blocked') and user.is_blocked):
abort(403, f"You're blocked by @{user.username}")
if user.has_muted(v):
abort(403, f"@{user.username} is muting notifications from you, so messaging them is pointless!")
if not g.is_tor and get_setting("dm_media"):
body = process_files(request.files, v, body, is_dm=True, dm_user=user)
2024-02-14 09:27:00 +00:00
if len(body) > COMMENT_BODY_LENGTH_LIMIT:
2024-02-14 09:34:49 +00:00
abort(400, f'Message is too long (max {COMMENT_BODY_LENGTH_LIMIT} characters)')
2023-09-26 20:05:39 +00:00
if not body: abort(400, "Message is empty!")
body_html = sanitize(body)
if len(body_html) > COMMENT_BODY_HTML_LENGTH_LIMIT:
2024-02-14 09:34:49 +00:00
abort(400, "Rendered message is too long!")
2023-09-26 20:05:39 +00:00
if parent.sentto == MODMAIL_ID:
sentto = MODMAIL_ID
else:
sentto = user_id
c = Comment(author_id=v.id,
parent_post=None,
parent_comment_id=id,
top_comment_id=parent.top_comment_id,
level=parent.level + 1,
sentto=sentto,
body=body,
body_html=body_html,
)
g.db.add(c)
g.db.flush()
2024-01-31 22:36:52 +00:00
execute_blackjack(v, c, c.body_html, 'chat')
execute_under_siege(v, c, c.body_html, 'chat')
2023-09-26 20:05:39 +00:00
if user_id and user_id not in {v.id, MODMAIL_ID} | BOT_IDs:
2023-10-05 10:09:58 +00:00
if can_see(user, v):
2024-03-08 08:10:23 +00:00
notif = g.db.query(Notification).filter_by(comment_id=c.id, user_id=user_id).one_or_none()
if not notif:
notif = Notification(comment_id=c.id, user_id=user_id)
g.db.add(notif)
2023-09-26 20:05:39 +00:00
title = f'New message from @{c.author_name}'
url = f'{SITE_FULL}/notifications/messages'
push_notif({user_id}, title, body, url)
top_comment = c.top_comment
if top_comment.sentto == MODMAIL_ID:
if parent.author.id != v.id and parent.author.admin_level < PERMS['VIEW_MODMAIL']:
notif = Notification(comment_id=c.id, user_id=parent.author.id)
2023-09-26 20:05:39 +00:00
g.db.add(notif)
elif user_id and user_id not in {v.id, MODMAIL_ID} | BOT_IDs:
2023-09-26 20:05:39 +00:00
c.unread = True
2024-03-08 08:10:23 +00:00
rendered = render_template("comments.html", v=get_account(user_id), comments=[c])
emit('insert_reply', [parent.id, rendered], namespace='/', to=user_id)
2023-09-26 20:05:39 +00:00
return {"comment": render_template("comments.html", v=v, comments=[c])}