rDrama/files/helpers/config/const.py
Ben Rog-Wilhelm 310c6c4424
Rig up chat to be suitable for a Doge election. (Hopefully.) (#692)
* Integrate chat from upstream

Substantially borrowed from upstream ref: 13a208ee88e55 (before they
started editing generated artefacts instead of source).

Integrated, including:
  - Remove previously removed features: emoji, hats, and name colors
  - Compensate for lack of unified root template
  - Add React build process to Dockerfile and `bootstrap/init.sh`
  - Preliminary integration of chat websocket workers

For testing, modify `supervisord.conf.dev` to put chat on port 80 and
the site service on some other port. Then visit: http://localhost/chat

Still to do:
  - Access control for specific small-groups (and admins probably):
    Set the values somewhere (site_settings.json? Redis?) and use for
    authorization in `chat_is_allowed`.
  - Proxying only /chat to the websocket workers
  - Chat persistance across restarts: either Redis devops or to DB

* Add nginx server to do appropriate redirection.

* Add necessary columns to User.

* Wire up chat permissions.

* Reload chat on source change.

* Add a better structure for slash commands and add/remove functionality.

* Stop putting up previews of slash commands.

* We require more whitespace.

* Strip DMs out entirely, I currently do not want to deal with them.

* Change "Users Online" to just "Users".

* Clean up a little more DM detritus.

* Save chat history in database.

* Remove unnecessary hefty query to the DB.

* Clean up optimistic messages.

* Initial implementation of notification icon.

* Update readme a little bit.

* Fix notification highlight (mostly).

* Remove chat version number that will never be updated.

* Fix: Errors on logged-out users.

* Add function to nuke the chat state.

* Update DB.

* Add a dedicated deployable docker image.

* Fix: init_build.sh execute bit not set.

* Whoops, screwed up the abort() call.

* Relax chat rate limiter.

* Remove a somewhat silly comment.

* Remove an unnecessary g.db.add().

---------

Co-authored-by: TLSM <duolsm@outlook.com>
2023-09-04 12:42:20 -05:00

246 lines
7.2 KiB
Python

import re
import sys
from copy import deepcopy
from enum import IntEnum
from typing import Final
from flask import request
class Service(IntEnum):
'''
An enumeration of services provided by this application
'''
THEMOTTE = 0
'''
TheMotte web application. Handles most routes and tasks performed,
including all non-chat web requests.
'''
CRON = 1
'''
Runs tasks periodicially on a set schedule
'''
CHAT = 2
'''
Chat application.
'''
MIGRATION = 3
'''
Migration mode. Used for performing database migrations
'''
@classmethod
def from_argv(cls):
if "db" in sys.argv:
return cls.MIGRATION
if "cron" in sys.argv:
return cls.CRON
if "load_chat" in sys.argv:
return cls.CHAT
return cls.THEMOTTE
@property
def enable_services(self) -> bool:
return self not in {self.CRON, self.MIGRATION}
NOTIFICATIONS_ID = 1
AUTOJANNY_ID = 2
MODMAIL_ID = 2
SNAPPY_ID = 3
LONGPOSTBOT_ID = 4
ZOZBOT_ID = 5
AUTOPOLLER_ID = 6
AUTOBETTER_ID = 7
AUTOCHOICE_ID = 8
BASEDBOT_ID = 0
GIFT_NOTIF_ID = 9
OWNER_ID = 9
BUG_THREAD = 0
ROLES={}
LEADERBOARD_LIMIT: Final[int] = 25
THEMES = ["TheMotte", "dramblr", "reddit", "win98", "dark",
"light", "coffee", "tron", "4chan", "midnight"]
SORTS_COMMON = {
"top": 'fa-arrow-alt-circle-up',
"bottom": 'fa-arrow-alt-circle-down',
"new": 'fa-sparkles',
"old": 'fa-book',
"controversial": 'fa-bullhorn',
"comments": 'fa-comments'
}
SORTS_POSTS = {
"hot": "fa-fire",
"bump": "fa-arrow-up"
}
SORTS_POSTS.update(SORTS_COMMON)
SORTS_COMMENTS = SORTS_COMMON
MAX_CONTENT_LENGTH = 16 * 1024 * 1024
SESSION_COOKIE_SAMESITE = "Lax"
PERMANENT_SESSION_LIFETIME = 60 * 60 * 24 * 365
DEFAULT_THEME = "TheMotte"
FORCE_HTTPS = 1
COLORS = {'ff66ac','805ad5','62ca56','38a169','80ffff','2a96f3','eb4963','ff0000','f39731','30409f','3e98a7','e4432d','7b9ae4','ec72de','7f8fa6', 'f8db58','8cdbe6', 'fff'}
SUBMISSION_FLAIR_LENGTH_MAXIMUM: Final[int] = 350
SUBMISSION_TITLE_LENGTH_MAXIMUM: Final[int] = 500
SUBMISSION_URL_LENGTH_MAXIMUM: Final[int] = 2048
SUBMISSION_BODY_LENGTH_MAXIMUM: Final[int] = 20000
COMMENT_BODY_LENGTH_MAXIMUM: Final[int] = 500000
COMMENT_BODY_LENGTH_MAXIMUM_UNFILTERED: Final[int] = 50000
MESSAGE_BODY_LENGTH_MAXIMUM: Final[int] = 10000
CSS_LENGTH_MAXIMUM: Final[int] = 4000
CHAT_LENGTH_LIMIT: Final[int] = 1000
ERROR_MESSAGES = {
400: "That request was bad and you should feel bad",
401: "You need an account for this. Please make one!",
403: "You don't have access to this page.",
404: "That page doesn't exist. If you got here from a link on the website, please report this issue. Thanks!",
405: "Something went wrong and it's probably my fault. If you can do it reliably, or it's causing problems for you, please report it!",
409: "There's a conflict between what you're trying to do and what you or someone else has done and because of that you can't do what you're trying to do.",
413: "Max file size is 8 MB",
415: "That file type isn't allowed to be uploaded here",
422: "Something is wrong about your request. If you keep getting this unexpectedly, please report it!",
429: "Are you hammering the site? Stop that, yo.",
500: "Something went wrong and it's probably my fault. If you can do it reliably, or it's causing problems for you, please report it!",
}
LOGGEDIN_ACTIVE_TIME = 15 * 60
RENDER_DEPTH_LIMIT = 9
'''
The maximum depth at which a comment tree is rendered
'''
WERKZEUG_ERROR_DESCRIPTIONS = {
400: "The browser (or proxy) sent a request that this server could not understand.",
401: "The server could not verify that you are authorized to access the URL requested. You either supplied the wrong credentials (e.g. a bad password), or your browser doesn't understand how to supply the credentials required.",
403: "You don't have the permission to access the requested resource. It is either read-protected or not readable by the server.",
404: "The requested URL was not found on the server. If you entered the URL manually please check your spelling and try again.",
405: "The method is not allowed for the requested URL.",
409: "A conflict happened while processing the request. The resource might have been modified while the request was being processed.",
413: "The data value transmitted exceeds the capacity limit.",
415: "The server does not support the media type transmitted in the request.",
422: "The request was well-formed but was unable to be followed due to semantic errors.",
429: "This user has exceeded an allotted request count. Try again later.",
500: "The server encountered an internal error and was unable to complete your request. Either the server is overloaded or there is an error in the application.",
}
IMAGE_FORMATS = ['png','gif','jpg','jpeg','webp']
IMAGE_URL_ENDINGS = IMAGE_FORMATS + ['.webp', '.jpg', '.png', '.gif', '.jpeg', '?maxwidth=9999', '&fidelity=high']
VIDEO_FORMATS = ['mp4','webm','mov','avi','mkv','flv','m4v','3gp']
AUDIO_FORMATS = ['mp3','wav','ogg','aac','m4a','flac']
NO_TITLE_EXTENSIONS = IMAGE_FORMATS + VIDEO_FORMATS + AUDIO_FORMATS
FEATURES = {
"AWARDS": False,
}
PERMS = {
"DEBUG_LOGIN_TO_OTHERS": 3,
"CHAT_BYPASS_MUTE": 2,
"CHAT_MODERATION": 2,
"CHAT_FULL_CONTROL": 3,
"PERFORMANCE_KILL_PROCESS": 3,
"PERFORMANCE_SCALE_UP_DOWN": 3,
"PERFORMANCE_RELOAD": 3,
"PERFORMANCE_STATS": 3,
"POST_COMMENT_MODERATION": 2,
"POST_EDITING": 3,
"SCHEDULER": 2,
"SCHEDULER_POSTS": 2,
"SCHEDULER_TASK_TRACEBACK": 3,
"USER_SHADOWBAN": 2,
'USER_SET_PROFILE_PRIVACY': 2,
}
AWARDS = {}
if FEATURES['AWARDS']:
AWARDS_ENABLED = deepcopy(AWARDS)
for k, val in AWARDS.items():
if val['description'] == '???': AWARDS_ENABLED.pop(k)
AWARDS_JL2_PRINTABLE = {}
for k, val in AWARDS_ENABLED.items():
if val['price'] == 300: AWARDS_JL2_PRINTABLE[k] = val
else:
AWARDS_ENABLED = {}
AWARDS_JL2_PRINTABLE = {}
NOTIFIED_USERS = {
# format: 'substring' ↦ User ID to notify
}
patron = 'Patron'
proxies = {}
approved_embed_hosts = [
'rdrama.net',
'pcmemes.net',
'cringetopia.org',
'devrama.xyz',
'imgur.com',
'ibb.co',
'lain.la',
'pngfind.com',
'kym-cdn.com',
'redd.it',
'substack.com',
'blogspot.com',
'catbox.moe',
'pinimg.com',
'kindpng.com',
'shopify.com',
'discordapp.com',
'discordapp.net',
'twimg.com',
'wikimedia.org',
'wp.com',
'wordpress.com',
'seekpng.com',
'dailymail.co.uk',
'cdc.gov',
'media-amazon.com',
'ssl-images-amazon.com',
'washingtonpost.com',
'imgflip.com',
'flickr.com',
'9cache.com',
'ytimg.com',
'foxnews.com',
'duckduckgo.com',
'forbes.com',
'gr-assets.com',
'tenor.com',
'giphy.com',
'makeagif.com',
'gfycat.com',
'tumblr.com',
'yarn.co',
'gifer.com',
'prnt.sc',
'staticflickr.com',
'kiwifarms.net',
'amazonaws.com',
'githubusercontent.com',
'unilad.co.uk',
'grrrgraphics.com',
'redditmedia.com'
]
hosts = "|".join(approved_embed_hosts).replace('.','\\.')
image_check_regex = re.compile(f'!\\[\\]\\(((?!(https:\\/\\/([a-z0-9-]+\\.)*({hosts})\\/|\\/)).*?)\\)', flags=re.A)
embed_fullmatch_regex = re.compile(f'https:\\/\\/([a-z0-9-]+\\.)*({hosts})\\/[\\w:~,()\\-.#&\\/=?@%;+]*', flags=re.A)
video_sub_regex = re.compile(f'(<p>[^<]*)(https:\\/\\/([a-z0-9-]+\\.)*({hosts})\\/[\\w:~,()\\-.#&\\/=?@%;+]*?\\.(mp4|webm|mov))', flags=re.A)
procoins_li = (0,2500,5000,10000,25000,50000,125000,250000)
from files.helpers.config.regex import *
def make_name(*args, **kwargs): return request.base_url