Merge branch 'master' into fix-seed-db

remotes/1693045480750635534/spooky-22
atrc445 2021-08-05 21:23:32 +02:00
commit 62a7ef70ed
180 changed files with 566 additions and 351 deletions

3
.gitignore vendored
View File

@ -1,5 +1,6 @@
image.png
image.gif image.gif
dramacache/ cache/
__pycache__/ __pycache__/
*.py[cod] *.py[cod]
*$py.class *$py.class

View File

@ -2,12 +2,12 @@ version: 0.0
os: linux os: linux
files: files:
- source: / - source: /
destination: drama destination: files
permissions: permissions:
- object: drama/* - object: files/*
mode: 4755 mode: 4755
hooks: hooks:
AfterInstall: AfterInstall:
- location: scripts/install_pip - location: scripts/install_pip
ApplicationStart: ApplicationStart:
- location: scripts/start_drama - location: scripts/start_files

View File

@ -1,7 +1,7 @@
for theme in ['midnight', 'dark', 'light', 'coffee', 'tron', '4chan']: for theme in ['midnight', 'dark', 'light', 'coffee', 'tron', '4chan']:
with open(f"./drama/assets/style/{theme}_ff66ac.css", encoding='utf-8') as t: with open(f"./files/assets/style/{theme}_ff66ac.css", encoding='utf-8') as t:
text = t.read() text = t.read()
for color in ['ff66ac','805ad5','62ca56','38a169','80ffff','2a96f3','62ca56','eb4963','ff0000','f39731','30409f','3e98a7','e4432d','7b9ae4','ec72de','7f8fa6', 'f8db58']: for color in ['ff66ac','805ad5','62ca56','38a169','80ffff','2a96f3','62ca56','eb4963','ff0000','f39731','30409f','3e98a7','e4432d','7b9ae4','ec72de','7f8fa6', 'f8db58']:
newtext = text.replace("ff66ac", color).replace("ff4097", color).replace("ff1a83", color).replace("ff3390", color).replace("rgba(255, 102, 172, 0.25)", color) newtext = text.replace("ff66ac", color).replace("ff4097", color).replace("ff1a83", color).replace("ff3390", color).replace("rgba(255, 102, 172, 0.25)", color)
with open(f"./drama/assets/style/{theme}_{color}.css", encoding='utf-8', mode='w') as nt: with open(f"./files/assets/style/{theme}_{color}.css", encoding='utf-8', mode='w') as nt:
nt.write(newtext) nt.write(newtext)

View File

@ -1,36 +1,43 @@
version: '2.3' version: '2.3'
services: services:
drama: files:
build: build:
context: . context: .
volumes: volumes:
- "./:/drama/service" - "./:/service"
environment: environment:
- PYTHONPATH="drama/service" - PYTHONPATH="/service"
- REDIS_URL=redis://redis - REDIS_URL=redis://redis
- DATABASE_URL=postgresql://postgres@postgres:5432/postgres - DATABASE_URL=postgresql://postgres@postgres:5432/postgres
- DATABASE_CONNECTION_POOL_URL=postgresql://postgres@postgres:5432/postgres - DATABASE_CONNECTION_POOL_URL=postgresql://postgres@postgres:5432/postgres
- MASTER_KEY=${MASTER_KEY:-KTVciAUQFpFh2WdJ/oiHJlxl6FvzRZp8kYzAAv3l2OA=} - MASTER_KEY=${MASTER_KEY:-KTVciAUQFpFh2WdJ/oiHJlxl6FvzRZp8kYzAAv3l2OA=}
- domain=localhost - DOMAIN=localhost
- SITE_NAME=Drama - SITE_NAME=Drama
- CLOUDFLARE_ZONE=vcxvdfgfc6r554etrgd - CLOUDFLARE_ZONE=vcxvdfgfc6r554etrgd
- CLOUDFLARE_KEY=vcxvdfgfc6r554etrgd - CLOUDFLARE_KEY=vcxvdfgfc6r554etrgd
- TENOR_KEY=vcxvdfgfc6r554etrgd - TENOR_KEY=vcxvdfgfc6r554etrgd
- MAILGUN_KEY=vcxvdfgfc6r554etrgd - MAILGUN_KEY=vcxvdfgfc6r554etrgd
- MAILGUN_DOMAIN=rdrama.net - MAILGUN_DOMAIN=rdrama.net
- admin_email=drama@rdrama.net
- FORCE_HTTPS=0 - FORCE_HTTPS=0
- DISCORD_SERVER_ID=vcxvdfgfc6r554etrgd - DISCORD_SERVER_ID=vcxvdfgfc6r554etrgd
- DISCORD_CLIENT_ID=vcxvdfgfc6r554etrgd - DISCORD_CLIENT_ID=vcxvdfgfc6r554etrgd
- DISCORD_CLIENT_SECRET=vcxvdfgfc6r554etrgd - DISCORD_CLIENT_SECRET=vcxvdfgfc6r554etrgd
- DISCORD_BOT_TOKEN=vcxvdfgfc6r554etrgd - DISCORD_BOT_TOKEN=vcxvdfgfc6r554etrgd
- imgurkey=vcxvdfgfc6r554etrgd - IMGUR_KEY=vcxvdfgfc6r554etrgd
- FACEBOOK_TOKEN=vcxvdfgfc6r554etrgd - FACEBOOK_TOKEN=vcxvdfgfc6r554etrgd
#- HCAPTCHA_SITEKEY=vcxvdfgfc6r554etrgd #- HCAPTCHA_SITEKEY=vcxvdfgfc6r554etrgd
- HCAPTCHA_SECRET=vcxvdfgfc6r554etrgd - HCAPTCHA_SECRET=vcxvdfgfc6r554etrgd
- youtubekey=vcxvdfgfc6r554etrgd - YOUTUBE_KEY=vcxvdfgfc6r554etrgd
- PUSHER_KEY=vcxvdfgfc6r554etrgd - PUSHER_KEY=vcxvdfgfc6r554etrgd
- SPAM_SIMILARITY_THRESHOLD=0.5
- SPAM_SIMILAR_COUNT_THRESHOLD=5
- SPAM_URL_SIMILARITY_THRESHOLD=0.1
- COMMENT_SPAM_SIMILAR_THRESHOLD=0.5
- COMMENT_SPAM_COUNT_THRESHOLD=5
- READ_ONLY=0
- BOT_DISABLE=0
- COINS_NAME=Dramacoins
links: links:
- "redis" - "redis"
- "postgres" - "postgres"

View File

@ -1,2 +0,0 @@
from drama.__main__ import Base, app

View File

@ -30,28 +30,15 @@ app = Flask(__name__,
app.wsgi_app = ProxyFix(app.wsgi_app, x_for=3) app.wsgi_app = ProxyFix(app.wsgi_app, x_for=3)
app.url_map.strict_slashes = False app.url_map.strict_slashes = False
app.config["SITE_NAME"]=environ.get("SITE_NAME", "Drama").strip() app.config["SITE_NAME"]=environ.get("SITE_NAME").strip()
app.config["COINS_NAME"]=environ.get("COINS_NAME").strip()
app.config["SITE_COLOR"]=environ.get("SITE_COLOR", "805ad5").strip()
app.config["DRAMAPATH"]=environ.get("DRAMAPATH", path.dirname(path.realpath(__file__)))
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
app.config['DATABASE_URL'] = environ.get( app.config['DATABASE_URL'] = environ.get("DATABASE_CONNECTION_POOL_URL",environ.get("DATABASE_URL"))
"DATABASE_CONNECTION_POOL_URL",
environ.get("DATABASE_URL"))
app.config['SQLALCHEMY_READ_URIS'] = [
environ.get("DATABASE_CONNECTION_READ_01_URL"),
environ.get("DATABASE_CONNECTION_READ_02_URL"),
environ.get("DATABASE_CONNECTION_READ_03_URL")
]
app.config['SECRET_KEY'] = environ.get('MASTER_KEY') app.config['SECRET_KEY'] = environ.get('MASTER_KEY')
app.config["SERVER_NAME"] = environ.get("domain").strip() app.config["SERVER_NAME"] = environ.get("DOMAIN").strip()
app.config["SHORT_DOMAIN"]=environ.get("SHORT_DOMAIN","").strip() app.config["SESSION_COOKIE_NAME"] = "session_" + environ.get("SITE_NAME").strip().lower()
app.config["SESSION_COOKIE_NAME"] = "session_drama"
app.config["VERSION"] = "1.0.0" app.config["VERSION"] = "1.0.0"
app.config['MAX_CONTENT_LENGTH'] = 64 * 1024 * 1024 app.config['MAX_CONTENT_LENGTH'] = 64 * 1024 * 1024
app.config["SESSION_COOKIE_SECURE"] = bool(int(environ.get("FORCE_HTTPS", 1))) app.config["SESSION_COOKIE_SECURE"] = bool(int(environ.get("FORCE_HTTPS", 1)))
@ -61,7 +48,6 @@ app.config["PERMANENT_SESSION_LIFETIME"] = 60 * 60 * 24 * 365
app.config["SESSION_REFRESH_EACH_REQUEST"] = True app.config["SESSION_REFRESH_EACH_REQUEST"] = True
app.config["FORCE_HTTPS"] = int(environ.get("FORCE_HTTPS", 1)) if ("localhost" not in app.config["SERVER_NAME"] and "127.0.0.1" not in app.config["SERVER_NAME"]) else 0 app.config["FORCE_HTTPS"] = int(environ.get("FORCE_HTTPS", 1)) if ("localhost" not in app.config["SERVER_NAME"] and "127.0.0.1" not in app.config["SERVER_NAME"]) else 0
app.config["DISABLE_SIGNUPS"]=int(environ.get("DISABLE_SIGNUPS",0))
app.jinja_env.cache = {} app.jinja_env.cache = {}
@ -70,34 +56,26 @@ app.config["UserAgent"] = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit
if "localhost" in app.config["SERVER_NAME"]: if "localhost" in app.config["SERVER_NAME"]:
app.config["CACHE_TYPE"] = "null" app.config["CACHE_TYPE"] = "null"
else: else:
app.config["CACHE_TYPE"] = environ.get("CACHE_TYPE", 'filesystem').strip() app.config["CACHE_TYPE"] = "filesystem"
app.config["CACHE_DIR"] = environ.get("CACHE_DIR", "dramacache") app.config["CACHE_DIR"] = environ.get("CACHE_DIR", "cache")
# captcha configs # captcha configs
app.config["HCAPTCHA_SITEKEY"] = environ.get("HCAPTCHA_SITEKEY","").strip() app.config["HCAPTCHA_SITEKEY"] = environ.get("HCAPTCHA_SITEKEY","").strip()
app.config["HCAPTCHA_SECRET"] = environ.get( app.config["HCAPTCHA_SECRET"] = environ.get("HCAPTCHA_SECRET","").strip()
"HCAPTCHA_SECRET","").strip()
app.config["SIGNUP_HOURLY_LIMIT"]=int(environ.get("SIGNUP_HOURLY_LIMIT",0))
# antispam configs # antispam configs
app.config["SPAM_SIMILARITY_THRESHOLD"] = float( app.config["SPAM_SIMILARITY_THRESHOLD"] = float(environ.get("SPAM_SIMILARITY_THRESHOLD"))
environ.get("SPAM_SIMILARITY_THRESHOLD", 0.5)) app.config["SPAM_SIMILAR_COUNT_THRESHOLD"] = int(environ.get("SPAM_SIMILAR_COUNT_THRESHOLD"))
app.config["SPAM_SIMILAR_COUNT_THRESHOLD"] = int( app.config["SPAM_URL_SIMILARITY_THRESHOLD"] = float(environ.get("SPAM_URL_SIMILARITY_THRESHOLD"))
environ.get("SPAM_SIMILAR_COUNT_THRESHOLD", 5)) app.config["COMMENT_SPAM_SIMILAR_THRESHOLD"] = float(environ.get("COMMENT_SPAM_SIMILAR_THRESHOLD"))
app.config["SPAM_URL_SIMILARITY_THRESHOLD"] = float( app.config["COMMENT_SPAM_COUNT_THRESHOLD"] = int(environ.get("COMMENT_SPAM_COUNT_THRESHOLD"))
environ.get("SPAM_URL_SIMILARITY_THRESHOLD", 0.1))
app.config["COMMENT_SPAM_SIMILAR_THRESHOLD"] = float(
environ.get("COMMENT_SPAM_SIMILAR_THRESHOLD", 0.5))
app.config["COMMENT_SPAM_COUNT_THRESHOLD"] = int(
environ.get("COMMENT_SPAM_COUNT_THRESHOLD", 5))
app.config["CACHE_REDIS_URL"] = environ.get( app.config["CACHE_REDIS_URL"] = environ.get("REDIS_URL").strip()
"REDIS_URL").strip().lstrip() if environ.get("REDIS_URL") else None
app.config["CACHE_DEFAULT_TIMEOUT"] = 60 app.config["CACHE_DEFAULT_TIMEOUT"] = 60
app.config["CACHE_KEY_PREFIX"] = "flask_caching_" app.config["CACHE_KEY_PREFIX"] = "flask_caching_"
app.config["REDIS_POOL_SIZE"]=int(environ.get("REDIS_POOL_SIZE", 10)) app.config["REDIS_POOL_SIZE"] = 10
redispool=ConnectionPool( redispool=ConnectionPool(
max_connections=app.config["REDIS_POOL_SIZE"], max_connections=app.config["REDIS_POOL_SIZE"],
@ -105,7 +83,7 @@ redispool=ConnectionPool(
) if app.config["CACHE_TYPE"]=="redis" else None ) if app.config["CACHE_TYPE"]=="redis" else None
app.config["CACHE_OPTIONS"]={'connection_pool':redispool} if app.config["CACHE_TYPE"]=="redis" else {} app.config["CACHE_OPTIONS"]={'connection_pool':redispool} if app.config["CACHE_TYPE"]=="redis" else {}
app.config["READ_ONLY"]=bool(int(environ.get("READ_ONLY", False))) app.config["READ_ONLY"]=bool(int(environ.get("READ_ONLY")))
app.config["BOT_DISABLE"]=bool(int(environ.get("BOT_DISABLE", False))) app.config["BOT_DISABLE"]=bool(int(environ.get("BOT_DISABLE", False)))
app.config["TENOR_KEY"]=environ.get("TENOR_KEY",'').strip() app.config["TENOR_KEY"]=environ.get("TENOR_KEY",'').strip()
@ -115,18 +93,15 @@ Markdown(app)
cache = Cache(app) cache = Cache(app)
Compress(app) Compress(app)
app.config["RATELIMIT_STORAGE_URL"] = environ.get("REDIS_URL").strip() if environ.get("REDIS_URL") else 'memory://' app.config["RATELIMIT_STORAGE_URL"] = environ.get("REDIS_URL").strip()
app.config["RATELIMIT_KEY_PREFIX"] = "flask_limiting_" app.config["RATELIMIT_KEY_PREFIX"] = "flask_limiting_"
app.config["RATELIMIT_ENABLED"] = True app.config["RATELIMIT_ENABLED"] = True
app.config["RATELIMIT_DEFAULTS_DEDUCT_WHEN"]=lambda:True app.config["RATELIMIT_DEFAULTS_DEDUCT_WHEN"]=lambda:True
app.config["RATELIMIT_DEFAULTS_EXEMPT_WHEN"]=lambda:False app.config["RATELIMIT_DEFAULTS_EXEMPT_WHEN"]=lambda:False
app.config["RATELIMIT_HEADERS_ENABLED"]=True app.config["RATELIMIT_HEADERS_ENABLED"]=True
#app.config["DISABLESIGNUPS"] = bool(int(environ.get("DISABLESIGNUPS", "0")))
def limiter_key_func(): return request.remote_addr
def limiter_key_func():
return request.remote_addr
limiter = Limiter( limiter = Limiter(
@ -196,9 +171,9 @@ UA_BAN_CACHE_TTL = int(environ.get("UA_BAN_CACHE_TTL", 3600))
# import and bind all routing functions # import and bind all routing functions
import drama.classes import files.classes
from drama.routes import * from files.routes import *
import drama.helpers.jinja2 import files.helpers.jinja2
@cache.memoize(UA_BAN_CACHE_TTL) @cache.memoize(UA_BAN_CACHE_TTL)
def get_useragent_ban_response(user_agent_str): def get_useragent_ban_response(user_agent_str):
@ -210,8 +185,8 @@ def get_useragent_ban_response(user_agent_str):
# return False, (None, None) # return False, (None, None)
result = g.db.query( result = g.db.query(
drama.classes.Agent).filter( files.classes.Agent).filter(
drama.classes.Agent.kwd.in_( files.classes.Agent.kwd.in_(
user_agent_str.split())).first() user_agent_str.split())).first()
if result: if result:
return True, (result.mock or "Follow the robots.txt, dumbass", return True, (result.mock or "Follow the robots.txt, dumbass",
@ -267,26 +242,6 @@ def before_request():
else: else:
g.system="other/other" g.system="other/other"
def log_event(name, link):
x = requests.get(link)
if x.status_code != 200:
return
text = f'> **{name}**\r> {link}'
url = environ.get("DISCORD_WEBHOOK")
headers = {"Content-Type": "application/json"}
data = {"username": "drama",
"content": text
}
x = requests.post(url, headers=headers, json=data)
print(x.status_code)
@app.after_request @app.after_request
def after_request(response): def after_request(response):

View File

@ -1,5 +1,5 @@
from sqlalchemy import * from sqlalchemy import *
from drama.__main__ import Base from files.__main__ import Base
class Agent(Base): class Agent(Base):

View File

@ -1,5 +1,5 @@
from sqlalchemy import * from sqlalchemy import *
from drama.__main__ import Base from files.__main__ import Base
class Alt(Base): class Alt(Base):

View File

@ -1,6 +1,6 @@
from sqlalchemy import * from sqlalchemy import *
from sqlalchemy.orm import relationship from sqlalchemy.orm import relationship
from drama.__main__ import Base from files.__main__ import Base
AWARDS = { AWARDS = {
"ban": { "ban": {

View File

@ -1,7 +1,7 @@
from sqlalchemy import * from sqlalchemy import *
from sqlalchemy.orm import relationship from sqlalchemy.orm import relationship
from drama.__main__ import Base, app from files.__main__ import Base, app
class BadgeDef(Base): class BadgeDef(Base):

View File

@ -5,7 +5,7 @@ from sqlalchemy.orm import relationship, lazyload
from .mix_ins import Stndrd from .mix_ins import Stndrd
from .submission import Submission from .submission import Submission
from .comment import Comment from .comment import Comment
from drama.__main__ import Base from files.__main__ import Base
class OauthApp(Base, Stndrd): class OauthApp(Base, Stndrd):

View File

@ -1,8 +1,8 @@
from flask import * from flask import *
from sqlalchemy import * from sqlalchemy import *
from sqlalchemy.orm import relationship, deferred from sqlalchemy.orm import relationship, deferred
from drama.helpers.lazy import lazy from files.helpers.lazy import lazy
from drama.__main__ import Base from files.__main__ import Base
from .mix_ins import * from .mix_ins import *
from .flags import CommentFlag from .flags import CommentFlag

View File

@ -1,5 +1,5 @@
from sqlalchemy import * from sqlalchemy import *
from drama.__main__ import Base from files.__main__ import Base
class BannedDomain(Base): class BannedDomain(Base):

View File

@ -1,6 +1,6 @@
from sqlalchemy import * from sqlalchemy import *
from sqlalchemy.orm import relationship from sqlalchemy.orm import relationship
from drama.__main__ import Base from files.__main__ import Base
from .mix_ins import * from .mix_ins import *
class Flag(Base, Stndrd): class Flag(Base, Stndrd):

View File

@ -1,6 +1,6 @@
from sqlalchemy import * from sqlalchemy import *
from flask import g from flask import g
from drama.__main__ import Base from files.__main__ import Base
class Image(Base): class Image(Base):

View File

@ -0,0 +1,2 @@
from files.__main__ import Base, app

View File

@ -1,4 +1,4 @@
from drama.helpers.lazy import lazy from files.helpers.lazy import lazy
import math import math
import random import random
import time import time

View File

@ -1,6 +1,6 @@
from sqlalchemy import * from sqlalchemy import *
from sqlalchemy.orm import relationship from sqlalchemy.orm import relationship
from drama.__main__ import Base from files.__main__ import Base
from .mix_ins import * from .mix_ins import *
import time import time

View File

@ -3,13 +3,13 @@ from sqlalchemy import *
from sqlalchemy.orm import relationship, deferred from sqlalchemy.orm import relationship, deferred
import re, random import re, random
from urllib.parse import urlparse from urllib.parse import urlparse
from drama.helpers.lazy import lazy from files.helpers.lazy import lazy
from drama.__main__ import Base from files.__main__ import Base
from .mix_ins import * from .mix_ins import *
from .flags import * from .flags import *
from os import environ from os import environ
site = environ.get("domain").strip() site = environ.get("DOMAIN").strip()
class SubmissionAux(Base): class SubmissionAux(Base):

View File

@ -1,6 +1,6 @@
from sqlalchemy import * from sqlalchemy import *
from sqlalchemy.orm import relationship from sqlalchemy.orm import relationship
from drama.__main__ import Base from files.__main__ import Base
import time import time

View File

@ -2,8 +2,8 @@ from sqlalchemy.orm import deferred, contains_eager, aliased
from secrets import token_hex from secrets import token_hex
import pyotp import pyotp
from drama.helpers.discord import delete_role from files.helpers.discord import delete_role
from drama.helpers.images import * from files.helpers.images import *
from .alts import Alt from .alts import Alt
from .submission import SaveRelationship from .submission import SaveRelationship
from .comment import Notification from .comment import Notification
@ -11,10 +11,10 @@ from .subscriptions import *
from .userblock import * from .userblock import *
from .badges import * from .badges import *
from .clients import * from .clients import *
from drama.__main__ import Base, cache from files.__main__ import Base, cache
from drama.helpers.security import * from files.helpers.security import *
site = environ.get("domain").strip() site = environ.get("DOMAIN").strip()
class User(Base, Stndrd, Age_times): class User(Base, Stndrd, Age_times):
__tablename__ = "users" __tablename__ = "users"
@ -79,7 +79,7 @@ class User(Base, Stndrd, Age_times):
ban_reason = Column(String, default="") ban_reason = Column(String, default="")
login_nonce = Column(Integer, default=0) login_nonce = Column(Integer, default=0)
reserved = Column(String(256)) reserved = Column(String(256))
dramacoins = Column(Integer, default=0) coins = Column(Integer, default=0)
mfa_secret = deferred(Column(String(16))) mfa_secret = deferred(Column(String(16)))
is_private = Column(Boolean, default=False) is_private = Column(Boolean, default=False)
stored_subscriber_count = Column(Integer, default=0) stored_subscriber_count = Column(Integer, default=0)
@ -491,7 +491,7 @@ class User(Base, Stndrd, Age_times):
data = self.json_core data = self.json_core
data["badges"] = [x.json_core for x in self.badges] data["badges"] = [x.json_core for x in self.badges]
data['dramacoins'] = int(self.dramacoins) data['coins'] = int(self.coins)
data['post_count'] = self.post_count data['post_count'] = self.post_count
data['comment_count'] = self.comment_count data['comment_count'] = self.comment_count

View File

@ -1,7 +1,7 @@
from sqlalchemy import * from sqlalchemy import *
from sqlalchemy.orm import relationship from sqlalchemy.orm import relationship
from .mix_ins import * from .mix_ins import *
from drama.__main__ import Base from files.__main__ import Base
class UserBlock(Base, Stndrd, Age_times): class UserBlock(Base, Stndrd, Age_times):

View File

@ -1,7 +1,7 @@
from flask import * from flask import *
from sqlalchemy import * from sqlalchemy import *
from sqlalchemy.orm import relationship from sqlalchemy.orm import relationship
from drama.__main__ import Base from files.__main__ import Base
class Vote(Base): class Vote(Base):

View File

@ -1,6 +1,6 @@
import mistletoe import mistletoe
from drama.classes import * from files.classes import *
from flask import g from flask import g
from .markdown import * from .markdown import *
from .sanitize import * from .sanitize import *

View File

@ -1,7 +1,7 @@
from bs4 import BeautifulSoup from bs4 import BeautifulSoup
from flask import * from flask import *
from urllib.parse import urlparse from urllib.parse import urlparse
from drama.classes import BannedDomain from files.classes import BannedDomain
def filter_comment_html(html_text): def filter_comment_html(html_text):

View File

@ -1,4 +1,4 @@
from drama.classes import * from files.classes import *
from flask import g from flask import g
from sqlalchemy.orm import joinedload, aliased from sqlalchemy.orm import joinedload, aliased

View File

@ -2,11 +2,11 @@ import requests
from os import environ from os import environ
from PIL import Image as IImage, ImageSequence from PIL import Image as IImage, ImageSequence
import base64 import base64
from drama.classes.images import * from files.classes.images import *
CF_KEY = environ.get("CLOUDFLARE_KEY").strip() CF_KEY = environ.get("CLOUDFLARE_KEY").strip()
CF_ZONE = environ.get("CLOUDFLARE_ZONE").strip() CF_ZONE = environ.get("CLOUDFLARE_ZONE").strip()
imgurkey = environ.get("imgurkey").strip() IMGUR_KEY = environ.get("IMGUR_KEY").strip()
def upload_file(file=None, resize=False, png=False): def upload_file(file=None, resize=False, png=False):
@ -35,12 +35,10 @@ def upload_file(file=None, resize=False, png=False):
try: try:
with open(filedir, 'rb') as f: with open(filedir, 'rb') as f:
data={'image': base64.b64encode(f.read())} data={'image': base64.b64encode(f.read())}
req = requests.post('https://api.imgur.com/3/upload.json', headers = {"Authorization": f"Client-ID {imgurkey}"}, data=data) req = requests.post('https://api.imgur.com/3/upload.json', headers = {"Authorization": f"Client-ID {IMGUR_KEY}"}, data=data)
resp = req.json()['data'] resp = req.json()['data']
url = resp['link'].replace(".png", "_d.png").replace(".jpg", "_d.jpg").replace(".jpeg", "_d.jpeg") + "?maxwidth=9999" url = resp['link'].replace(".png", "_d.png").replace(".jpg", "_d.jpg").replace(".jpeg", "_d.jpeg") + "?maxwidth=9999"
except: except: return
print(req.text)
return
new_image = Image(text=url, deletehash=resp["deletehash"]) new_image = Image(text=url, deletehash=resp["deletehash"])
g.db.add(new_image) g.db.add(new_image)

View File

@ -1,6 +1,6 @@
from os import environ, path from os import environ, path
from .get import * from .get import *
from drama.__main__ import app, cache from files.__main__ import app, cache
@app.template_filter("total_users") @app.template_filter("total_users")
@ -14,7 +14,7 @@ def total_users(x):
@cache.memoize(timeout=60 * 60 * 24) @cache.memoize(timeout=60 * 60 * 24)
def source_code(file_name): def source_code(file_name):
return open(path.expanduser('~') + '/drama/' + return open(path.expanduser('~') + '/files/' +
file_name, mode="r+").read() file_name, mode="r+").read()

View File

@ -6,7 +6,7 @@ from functools import partial
from .get import * from .get import *
from os import path from os import path
site = environ.get("domain").strip() site = environ.get("DOMAIN").strip()
_allowed_tags = tags = ['b', _allowed_tags = tags = ['b',
'blockquote', 'blockquote',
@ -72,7 +72,7 @@ def a_modify(attrs, new=False):
attrs[(None, "rel")] = "nofollow noopener" attrs[(None, "rel")] = "nofollow noopener"
# Force https for all external links in comments # Force https for all external links in comments
# (Drama already forces its own https) # (Website already forces its own https)
new_url = ParseResult(scheme="https", new_url = ParseResult(scheme="https",
netloc=parsed_url.netloc, netloc=parsed_url.netloc,
path=parsed_url.path, path=parsed_url.path,
@ -178,12 +178,12 @@ def sanitize(text, linkgen=False, flair=False):
start = '<s>' start = '<s>'
end = '</s>' end = '</s>'
if start in sanitized and end in sanitized and start in sanitized.split(end)[0] and end in sanitized.split(start)[1]: sanitized = sanitized.replace(start, '<span class="spoiler">').replace(end, '</span>') if start in sanitized and end in sanitized and start in sanitized.split(end)[0] and end in sanitized.split(start)[1]: sanitized = sanitized.replace(start, '<span class="spoiler">').replace(end, '</span>')
if flair: emojisize = 20 if flair: emojisize = 20
else: emojisize = 30 else: emojisize = 30
for i in re.finditer(':(.{1,30}?):', sanitized): for i in re.finditer(':(.{1,30}?):', sanitized):
if path.isfile(f'./drama/assets/images/emojis/{i.group(1)}.gif'): if path.isfile(f'./files/assets/images/emojis/{i.group(1)}.gif'):
sanitized = sanitized.replace(f':{i.group(1)}:', f'<img data-toggle="tooltip" title="{i.group(1)}" delay="0" height={emojisize} src="https://{site}/assets/images/emojis/{i.group(1)}.gif"<span>') sanitized = sanitized.replace(f':{i.group(1)}:', f'<img data-toggle="tooltip" title="{i.group(1)}" delay="0" height={emojisize} src="https://{site}/assets/images/emojis/{i.group(1)}.gif"<span>')
sanitized = sanitized.replace("https://www.", "https://").replace("https://youtu.be/", "https://youtube.com/embed/").replace("https://music.youtube.com/watch?v=", "https://youtube.com/embed/").replace("/watch?v=", "/embed/").replace("https://open.spotify.com/", "https://open.spotify.com/embed/").replace("https://streamable.com/", "https://streamable.com/e/").replace("https://youtube.com/shorts/", "https://youtube.com/embed/") sanitized = sanitized.replace("https://www.", "https://").replace("https://youtu.be/", "https://youtube.com/embed/").replace("https://music.youtube.com/watch?v=", "https://youtube.com/embed/").replace("/watch?v=", "/embed/").replace("https://open.spotify.com/", "https://open.spotify.com/embed/").replace("https://streamable.com/", "https://streamable.com/e/").replace("https://youtube.com/shorts/", "https://youtube.com/embed/")

View File

@ -3,7 +3,7 @@ from sqlalchemy.sql import visitors
from werkzeug.wrappers.response import Response as RespObj from werkzeug.wrappers.response import Response as RespObj
from .get import * from .get import *
from .alerts import send_notification from .alerts import send_notification
from drama.__main__ import app from files.__main__ import app
def get_logged_in_user(): def get_logged_in_user():
@ -48,7 +48,7 @@ def check_ban_evade(v):
if random.randint(0,30) < v.ban_evade: if random.randint(0,30) < v.ban_evade:
v.ban(reason="ban evasion") v.ban(reason="ban evasion")
send_notification(1046, v, "Your Drama account has been permanently suspended for the following reason:\n\n> ban evasion") send_notification(1046, v, "Your account has been permanently suspended for the following reason:\n\n> ban evasion")
for post in g.db.query(Submission).filter_by(author_id=v.id).all(): for post in g.db.query(Submission).filter_by(author_id=v.id).all():
if post.is_banned: if post.is_banned:

View File

@ -4,16 +4,17 @@ import time
from flask import * from flask import *
from urllib.parse import quote from urllib.parse import quote
from drama.helpers.security import * from files.helpers.security import *
from drama.helpers.wrappers import * from files.helpers.wrappers import *
from drama.classes import * from files.classes import *
from drama.__main__ import app from files.__main__ import app
site = environ.get("domain").strip() site = environ.get("DOMAIN").strip()
name = environ.get("SITE_NAME").strip()
mailgun_domain = environ.get("MAILGUN_DOMAIN").strip() mailgun_domain = environ.get("MAILGUN_DOMAIN").strip()
def send_mail(to_address, subject, html, plaintext=None, files={}, def send_mail(to_address, subject, html, plaintext=None, files={},
from_address=f"Drama <noreply@mail.{site}>"): from_address=f"{name} <noreply@mail.{site}>"):
url = f"https://api.mailgun.net/v3/{mailgun_domain}/messages" url = f"https://api.mailgun.net/v3/{mailgun_domain}/messages"
@ -49,7 +50,7 @@ def send_verification_email(user, email=None):
html=render_template("email/email_verify.html", html=render_template("email/email_verify.html",
action_url=link, action_url=link,
v=user), v=user),
subject="Validate your Drama account email." subject=f"Validate your {name} account email."
) )

View File

@ -5,17 +5,17 @@ import imagehash
from os import remove from os import remove
from PIL import Image as IMAGE from PIL import Image as IMAGE
from drama.helpers.wrappers import * from files.helpers.wrappers import *
from drama.helpers.alerts import * from files.helpers.alerts import *
from drama.helpers.sanitize import * from files.helpers.sanitize import *
from drama.helpers.markdown import * from files.helpers.markdown import *
from drama.helpers.security import * from files.helpers.security import *
from drama.helpers.get import * from files.helpers.get import *
from drama.helpers.images import * from files.helpers.images import *
from drama.classes import * from files.classes import *
from flask import * from flask import *
import matplotlib.pyplot as plt import matplotlib.pyplot as plt
from drama.__main__ import app, cache from files.__main__ import app, cache
from .front import frontlist from .front import frontlist
@app.get("/admin/shadowbanned") @app.get("/admin/shadowbanned")
@ -443,7 +443,7 @@ def admin_image_purge(v):
name = request.form.get("url") name = request.form.get("url")
image = g.db.query(Image).filter(Image.text == name).first() image = g.db.query(Image).filter(Image.text == name).first()
if image: if image:
requests.delete(f'https://api.imgur.com/3/image/{image.deletehash}', headers = {"Authorization": f"Client-ID {imgurkey}"}) requests.delete(f'https://api.imgur.com/3/image/{image.deletehash}', headers = {"Authorization": f"Client-ID {IMGUR_KEY}"})
headers = {"Authorization": f"Bearer {CF_KEY}", "Content-Type": "application/json"} headers = {"Authorization": f"Bearer {CF_KEY}", "Content-Type": "application/json"}
data = {'files': [name]} data = {'files': [name]}
url = f"https://api.cloudflare.com/client/v4/zones/{CF_ZONE}/purge_cache" url = f"https://api.cloudflare.com/client/v4/zones/{CF_ZONE}/purge_cache"
@ -646,16 +646,16 @@ def ban_user(user_id, v):
if days > 0: if days > 0:
if message: if message:
text = f"Your Drama account has been suspended for {days} days for the following reason:\n\n> {message}" text = f"Your account has been suspended for {days} days for the following reason:\n\n> {message}"
else: else:
text = f"Your Drama account has been suspended for {days} days." text = f"Your account has been suspended for {days} days."
user.ban(admin=v, reason=reason, days=days) user.ban(admin=v, reason=reason, days=days)
else: else:
if message: if message:
text = f"Your Drama account has been permanently suspended for the following reason:\n\n> {message}" text = f"Your account has been permanently suspended for the following reason:\n\n> {message}"
else: else:
text = "Your Drama account has been permanently suspended." text = "Your account has been permanently suspended."
user.ban(admin=v, reason=reason) user.ban(admin=v, reason=reason)
@ -701,7 +701,7 @@ def unban_user(user_id, v):
x.unban() x.unban()
send_notification(1046, user, send_notification(1046, user,
"Your Drama account has been reinstated. Please carefully review and abide by the [rules](/post/2510) to ensure that you don't get suspended again.") "Your account has been reinstated. Please carefully review and abide by the [rules](/post/2510) to ensure that you don't get suspended again.")
ma=ModAction( ma=ModAction(
kind="unexile_user", kind="unexile_user",
@ -907,7 +907,7 @@ def refund(v):
if u.id == 253: continue if u.id == 253: continue
posts=sum([x[0]+x[1]-1 for x in g.db.query(Submission.upvotes, Submission.downvotes).options(lazyload('*')).filter_by(author_id = u.id, is_banned = False, deleted_utc = 0).all()]) posts=sum([x[0]+x[1]-1 for x in g.db.query(Submission.upvotes, Submission.downvotes).options(lazyload('*')).filter_by(author_id = u.id, is_banned = False, deleted_utc = 0).all()])
comments=sum([x[0]+x[1]-1 for x in g.db.query(Comment.upvotes, Comment.downvotes).options(lazyload('*')).filter_by(author_id = u.id, is_banned = False, deleted_utc = 0).all()]) comments=sum([x[0]+x[1]-1 for x in g.db.query(Comment.upvotes, Comment.downvotes).options(lazyload('*')).filter_by(author_id = u.id, is_banned = False, deleted_utc = 0).all()])
u.dramacoins = int(posts+comments) u.coins = int(posts+comments)
g.db.add(u) g.db.add(u)
return "sex" return "sex"
@ -931,7 +931,7 @@ def admin_banned_domains(v):
@validate_formkey @validate_formkey
def admin_toggle_ban_domain(v): def admin_toggle_ban_domain(v):
domain=request.form.get("domain").strip() domain=request.form.get("DOMAIN").strip()
if not domain: abort(400) if not domain: abort(400)
reason=request.form.get("reason", "").strip() reason=request.form.get("reason", "").strip()

View File

@ -1,8 +1,8 @@
from drama.__main__ import app from files.__main__ import app
from drama.helpers.wrappers import * from files.helpers.wrappers import *
from drama.helpers.alerts import * from files.helpers.alerts import *
from drama.helpers.get import * from files.helpers.get import *
from drama.classes.award import * from files.classes.award import *
from flask import g, request from flask import g, request
@ -15,13 +15,12 @@ def banaward_trigger(post=None, comment=None):
if not author.is_suspended: if not author.is_suspended:
author.ban(reason="1-day ban award used", days=1) author.ban(reason="1-day ban award used", days=1)
send_notification(1046, author, f"Your Drama account has been suspended for a day for {link}. It sucked and you should feel bad.") send_notification(1046, author, f"Your account has been suspended for a day for {link}. It sucked and you should feel bad.")
elif author.unban_utc > 0: elif author.unban_utc > 0:
author.unban_utc += 24*60*60 author.unban_utc += 24*60*60
g.db.add(author) g.db.add(author)
send_notification(1046, author, send_notification(1046, author, f"Your account has been suspended for yet another day for {link}. Seriously man?")
f"Your Drama account has been suspended for yet another day for {link}. Seriously man?")
ACTIONS = { ACTIONS = {

View File

@ -1,19 +1,19 @@
import traceback import traceback
import sys import sys
from drama.helpers.wrappers import * from files.helpers.wrappers import *
from drama.helpers.filters import * from files.helpers.filters import *
from drama.helpers.alerts import * from files.helpers.alerts import *
from drama.helpers.images import * from files.helpers.images import *
from drama.helpers.session import * from files.helpers.session import *
from drama.classes import * from files.classes import *
from drama.routes.front import comment_idlist from files.routes.front import comment_idlist
from pusher_push_notifications import PushNotifications, PusherAuthError from pusher_push_notifications import PushNotifications, PusherAuthError
from flask import * from flask import *
from drama.__main__ import app, limiter from files.__main__ import app, limiter
site = environ.get("domain").strip() site = environ.get("DOMAIN").strip()
choices = ['Wow, you must be a JP fan.', 'This is one of the worst posts I have EVER seen. Delete it.', "No, don't reply like this, please do another wall of unhinged rant please.", '# 😴😴😴', "Ma'am we've been over this before. You need to stop.", "I've known more coherent downies.", "Your pulitzer's in the mail", "That's great and all, but I asked for my burger without cheese.", 'That degree finally paying off', "That's nice sweaty. Why don't you have a seat in the time out corner with Pizzashill until you calm down, then you can have your Capri Sun.", "All them words won't bring your pa back.", "You had a chance to not be completely worthless, but it looks like you threw it away. At least you're consistent.", 'Some people are able to display their intelligence by going on at length on a subject and never actually saying anything. This ability is most common in trades such as politics, public relations, and law. You have impressed me by being able to best them all, while still coming off as an absolute idiot.', "You can type 10,000 characters and you decided that these were the one's that you wanted.", 'Have you owned the libs yet?', "I don't know what you said, because I've seen another human naked.", 'Impressive. Normally people with such severe developmental disabilities struggle to write much more than a sentence or two. He really has exceded our expectations for the writing portion. Sadly the coherency of his writing, along with his abilities in the social skills and reading portions, are far behind his peers with similar disabilities.', "This is a really long way of saying you don't fuck.", "Sorry ma'am, looks like his delusions have gotten worse. We'll have to admit him,", '![](https://i.kym-cdn.com/photos/images/newsfeed/001/038/094/0a1.jpg)', 'If only you could put that energy into your relationships', 'Posts like this is why I do Heroine.', 'still unemployed then?', 'K', 'look im gunna have 2 ask u 2 keep ur giant dumps in the toilet not in my replys 😷😷😷', "Mommy is soooo proud of you, sweaty. Let's put this sperg out up on the fridge with all your other failures.", "Good job bobby, here's a star", "That was a mistake. You're about to find out the hard way why.", 'You sat down and wrote all this shit. You could have done so many other things with your life. What happened to your life that made you decide writing novels of bullshit on reddit was the best option?', "I don't have enough spoons to read this shit", "All those words won't bring daddy back.", 'OUT!', "Mommy is soooo proud of you, sweaty. Let's put this sperg out up on the fridge with all your other failures."] choices = ['Wow, you must be a JP fan.', 'This is one of the worst posts I have EVER seen. Delete it.', "No, don't reply like this, please do another wall of unhinged rant please.", '# 😴😴😴', "Ma'am we've been over this before. You need to stop.", "I've known more coherent downies.", "Your pulitzer's in the mail", "That's great and all, but I asked for my burger without cheese.", 'That degree finally paying off', "That's nice sweaty. Why don't you have a seat in the time out corner with Pizzashill until you calm down, then you can have your Capri Sun.", "All them words won't bring your pa back.", "You had a chance to not be completely worthless, but it looks like you threw it away. At least you're consistent.", 'Some people are able to display their intelligence by going on at length on a subject and never actually saying anything. This ability is most common in trades such as politics, public relations, and law. You have impressed me by being able to best them all, while still coming off as an absolute idiot.', "You can type 10,000 characters and you decided that these were the one's that you wanted.", 'Have you owned the libs yet?', "I don't know what you said, because I've seen another human naked.", 'Impressive. Normally people with such severe developmental disabilities struggle to write much more than a sentence or two. He really has exceded our expectations for the writing portion. Sadly the coherency of his writing, along with his abilities in the social skills and reading portions, are far behind his peers with similar disabilities.', "This is a really long way of saying you don't fuck.", "Sorry ma'am, looks like his delusions have gotten worse. We'll have to admit him,", '![](https://i.kym-cdn.com/photos/images/newsfeed/001/038/094/0a1.jpg)', 'If only you could put that energy into your relationships', 'Posts like this is why I do Heroine.', 'still unemployed then?', 'K', 'look im gunna have 2 ask u 2 keep ur giant dumps in the toilet not in my replys 😷😷😷', "Mommy is soooo proud of you, sweaty. Let's put this sperg out up on the fridge with all your other failures.", "Good job bobby, here's a star", "That was a mistake. You're about to find out the hard way why.", 'You sat down and wrote all this shit. You could have done so many other things with your life. What happened to your life that made you decide writing novels of bullshit on reddit was the best option?', "I don't have enough spoons to read this shit", "All those words won't bring daddy back.", 'OUT!', "Mommy is soooo proud of you, sweaty. Let's put this sperg out up on the fridge with all your other failures."]
@ -259,7 +259,7 @@ def api_comment(v):
threshold *= 2 threshold *= 2
if len(similar_comments) > threshold: if len(similar_comments) > threshold:
text = "Your Drama account has been suspended for 1 day for the following reason:\n\n> Too much spam!" text = "Your account has been suspended for 1 day for the following reason:\n\n> Too much spam!"
send_notification(1046, v, text) send_notification(1046, v, text)
v.ban(reason="Spamming.", v.ban(reason="Spamming.",
@ -539,7 +539,7 @@ def api_comment(v):
}, },
) )
except PusherAuthError as e: except PusherAuthError as e:
traceback.print_tb(e.__traceback__) sys.stderr.write(traceback.format_exc())
sys.stderr.flush() sys.stderr.flush()
@ -656,7 +656,7 @@ def edit_comment(cid, v):
threshold *= 2 threshold *= 2
if len(similar_comments) > threshold: if len(similar_comments) > threshold:
text = "Your Drama account has been suspended for 1 day for the following reason:\n\n> Too much spam!" text = "Your account has been suspended for 1 day for the following reason:\n\n> Too much spam!"
send_notification(1046, v, text) send_notification(1046, v, text)
v.ban(reason="Spamming.", v.ban(reason="Spamming.",

View File

@ -1,15 +1,14 @@
from drama.helpers.wrappers import * from files.helpers.wrappers import *
from drama.helpers.security import * from files.helpers.security import *
from drama.helpers.discord import add_role from files.helpers.discord import add_role
from drama.__main__ import app from files.__main__ import app
SERVER_ID = environ.get("DISCORD_SERVER_ID",'').strip() SERVER_ID = environ.get("DISCORD_SERVER_ID",'').strip()
CLIENT_ID = environ.get("DISCORD_CLIENT_ID",'').strip() CLIENT_ID = environ.get("DISCORD_CLIENT_ID",'').strip()
CLIENT_SECRET = environ.get("DISCORD_CLIENT_SECRET",'').strip() CLIENT_SECRET = environ.get("DISCORD_CLIENT_SECRET",'').strip()
BOT_TOKEN = environ.get("DISCORD_BOT_TOKEN").strip() BOT_TOKEN = environ.get("DISCORD_BOT_TOKEN").strip()
COINS_NAME = environ.get("COINS_NAME").strip()
DISCORD_ENDPOINT = "https://discordapp.com/api/v6" DISCORD_ENDPOINT = "https://discordapp.com/api/v6"
WELCOME_CHANNEL="846509313941700618" WELCOME_CHANNEL="846509313941700618"
@app.get("/discord") @app.get("/discord")
@ -17,7 +16,7 @@ WELCOME_CHANNEL="846509313941700618"
def join_discord(v): def join_discord(v):
if v.is_banned != 0: return "You're banned" if v.is_banned != 0: return "You're banned"
if v.admin_level == 0 and v.dramacoins < 150: return "You must earn 150 dramacoins before entering the Discord server. You earn dramacoins by making posts/comments and getting upvoted." if v.admin_level == 0 and v.coins < 150: return f"You must earn 150 {COINS_NAME} before entering the Discord server. You earn {COINS_NAME} by making posts/comments and getting upvoted."
now=int(time.time()) now=int(time.time())
@ -126,7 +125,7 @@ def discord_redirect(v):
time.sleep(0.1) time.sleep(0.1)
if v.dramacoins > 100: add_role(v, "linked") if v.coins > 100: add_role(v, "linked")
else: add_role(v, "norep") else: add_role(v, "norep")
else: else:

View File

@ -1,11 +1,11 @@
import jinja2.exceptions import jinja2.exceptions
from drama.helpers.wrappers import * from files.helpers.wrappers import *
from drama.helpers.session import * from files.helpers.session import *
from flask import * from flask import *
from urllib.parse import quote, urlencode from urllib.parse import quote, urlencode
import time import time
from drama.__main__ import app from files.__main__ import app
# Errors # Errors

View File

@ -1,11 +1,11 @@
import html import html
from .front import frontlist from .front import frontlist
from datetime import datetime from datetime import datetime
from drama.helpers.jinja2 import full_link from files.helpers.jinja2 import full_link
from drama.helpers.get import * from files.helpers.get import *
from yattag import Doc from yattag import Doc
from drama.__main__ import app from files.__main__ import app
@app.get('/rss/<sort>/<t>') @app.get('/rss/<sort>/<t>')
def feeds_user(sort='hot', t='all'): def feeds_user(sort='hot', t='all'):

View File

@ -1,8 +1,8 @@
from drama.helpers.wrappers import * from files.helpers.wrappers import *
from drama.helpers.get import * from files.helpers.get import *
from flask import g from flask import g
from drama.__main__ import app from files.__main__ import app
from drama.helpers.sanitize import sanitize from files.helpers.sanitize import sanitize
@app.post("/flag/post/<pid>") @app.post("/flag/post/<pid>")
@auth_desired @auth_desired
@ -11,11 +11,10 @@ def api_flag_post(pid, v):
post = get_post(pid) post = get_post(pid)
if v: if v:
existing = g.db.query(Flag).filter_by( existing = g.db.query(Flag).filter_by(user_id=v.id, post_id=post.id).first()
user_id=v.id, post_id=post.id).first()
if existing: return "", 409 if existing: return "", 409
reason = sanitize(request.form.get("reason", "")[:100].strip(), flair=True) reason = sanitize(request.form.get("reason", "").strip()[:100], flair=True)
flag = Flag(post_id=post.id, flag = Flag(post_id=post.id,
user_id=v.id, user_id=v.id,

View File

@ -1,8 +1,8 @@
from drama.helpers.wrappers import * from files.helpers.wrappers import *
from drama.helpers.get import * from files.helpers.get import *
from drama.__main__ import app, cache from files.__main__ import app, cache
from drama.classes.submission import Submission from files.classes.submission import Submission
@app.get("/post/") @app.get("/post/")
def slash_post(): def slash_post():

View File

@ -1,6 +1,6 @@
from urllib.parse import urlencode from urllib.parse import urlencode
from drama.mail import * from files.mail import *
from drama.__main__ import app, limiter from files.__main__ import app, limiter
valid_username_regex = re.compile("^[a-zA-Z0-9_\-]{3,25}$") valid_username_regex = re.compile("^[a-zA-Z0-9_\-]{3,25}$")
valid_password_regex = re.compile("^.{8,100}$") valid_password_regex = re.compile("^.{8,100}$")
@ -135,8 +135,8 @@ def login_post():
@app.get("/@me") @app.get("/@me")
@auth_required @auth_required
def me(v): def me(v):
if request.headers.get("Authorization"): v.json if request.headers.get("Authorization"): return v.json
else: redirect(v.url) else: return redirect(v.url)
@app.post("/logout") @app.post("/logout")
@ -404,7 +404,7 @@ def post_forgot():
url = f"https://{app.config['SERVER_NAME']}/reset?id={user.id}&time={now}&token={token}" url = f"https://{app.config['SERVER_NAME']}/reset?id={user.id}&time={now}&token={token}"
send_mail(to_address=user.email, send_mail(to_address=user.email,
subject="Drama - Password Reset Request", subject="Password Reset Request",
html=render_template("email/password_reset.html", html=render_template("email/password_reset.html",
action_url=url, action_url=url,
v=user) v=user)
@ -537,7 +537,7 @@ def request_2fa_disable():
action_url=f"https://{app.config['SERVER_NAME']}/reset_2fa?id={user.id}&t={valid}&token={token}" action_url=f"https://{app.config['SERVER_NAME']}/reset_2fa?id={user.id}&t={valid}&token={token}"
send_mail(to_address=user.email, send_mail(to_address=user.email,
subject="Drama - 2FA Removal Request", subject="2FA Removal Request",
html=render_template("email/2fa_remove.html", html=render_template("email/2fa_remove.html",
action_url=action_url, action_url=action_url,
v=user) v=user)

View File

@ -1,9 +1,9 @@
from drama.helpers.wrappers import * from files.helpers.wrappers import *
from drama.helpers.alerts import * from files.helpers.alerts import *
from drama.helpers.get import * from files.helpers.get import *
from drama.classes import * from files.classes import *
from flask import * from flask import *
from drama.__main__ import app from files.__main__ import app
@app.get("/authorize") @app.get("/authorize")
@auth_required @auth_required

View File

@ -3,22 +3,22 @@ import mistletoe
import urllib.parse import urllib.parse
import gevent import gevent
from drama.helpers.wrappers import * from files.helpers.wrappers import *
from drama.helpers.sanitize import * from files.helpers.sanitize import *
from drama.helpers.filters import * from files.helpers.filters import *
from drama.helpers.markdown import * from files.helpers.markdown import *
from drama.helpers.session import * from files.helpers.session import *
from drama.helpers.thumbs import * from files.helpers.thumbs import *
from drama.helpers.alerts import send_notification from files.helpers.alerts import send_notification
from drama.helpers.discord import send_message from files.helpers.discord import send_message
from drama.classes import * from files.classes import *
from flask import * from flask import *
from io import BytesIO from io import BytesIO
from drama.__main__ import app, limiter, cache from files.__main__ import app, limiter, cache
from PIL import Image as PILimage from PIL import Image as PILimage
from .front import frontlist from .front import frontlist
site = environ.get("domain").strip() site = environ.get("DOMAIN").strip()
with open("snappy.txt", "r") as f: snappyquotes = f.read().split("{[para]}") with open("snappy.txt", "r") as f: snappyquotes = f.read().split("{[para]}")
@ -266,7 +266,7 @@ def edit_post(pid, v):
BadLink.link)).first() BadLink.link)).first()
if badlink: if badlink:
if badlink.autoban: if badlink.autoban:
text = "Your Drama account has been suspended for 1 day for the following reason:\n\n> Too much spam!" text = "Your account has been suspended for 1 day for the following reason:\n\n> Too much spam!"
send_notification(1046, v, text) send_notification(1046, v, text)
v.ban(days=1, reason="spam") v.ban(days=1, reason="spam")
@ -422,7 +422,6 @@ def thumbs(new_post):
#iterate through desired meta tags #iterate through desired meta tags
meta_tags = [ meta_tags = [
"drama:thumbnail",
"twitter:image", "twitter:image",
"og:image", "og:image",
"thumbnail" "thumbnail"
@ -508,6 +507,22 @@ def archiveorg(url):
except Exception as e: print(e) except Exception as e: print(e)
@app.route("/embed/post/<pid>", methods=["GET"])
def embed_post_pid(pid):
post = get_post(pid)
return render_template("embeds/post.html", p=post)
@app.route("/embed/comment/<cid>", methods=["GET"])
def embed_comment_cid(cid, pid=None):
comment = get_comment(cid)
return render_template("embeds/comment.html", c=comment)
@app.post("/submit") @app.post("/submit")
@limiter.limit("6/minute") @limiter.limit("6/minute")
@is_not_banned @is_not_banned
@ -604,7 +619,8 @@ def submit_post(v):
else: return render_template("submit.html", v=v, error="ToS Violation", title=title, url=url, body=request.form.get("body", "")), 400 else: return render_template("submit.html", v=v, error="ToS Violation", title=title, url=url, body=request.form.get("body", "")), 400
if "twitter.com" in domain: if "twitter.com" in domain:
embed = requests.get("https://publish.twitter.com/oembed", params={"url":url, "omit_script":"t"}).json()["html"] try: embed = requests.get("https://publish.twitter.com/oembed", params={"url":url, "omit_script":"t"}).json()["html"]
except: embed = None
elif "youtu" in domain: elif "youtu" in domain:
yt_id = re.match(re.compile("^.*(youtu.be\/|v\/|u\/\w\/|embed\/|watch\?v=|shorts\/|\&v=)([^#\&\?]*).*"), url).group(2) yt_id = re.match(re.compile("^.*(youtu.be\/|v\/|u\/\w\/|embed\/|watch\?v=|shorts\/|\&v=)([^#\&\?]*).*"), url).group(2)
@ -616,7 +632,7 @@ def submit_post(v):
else: embed = f"https://youtube.com/embed/{yt_id}" else: embed = f"https://youtube.com/embed/{yt_id}"
elif "instagram.com" in domain: elif "instagram.com" in domain:
embed = requests.get("https://graph.facebook.com/v9.0/instagram_oembed", params={"url":url,"access_token":environ.get("FACEBOOK_TOKEN","").strip(),"omitscript":'true'}, headers={"User-Agent":"Instagram embedder for Drama"}).json()["html"] embed = requests.get("https://graph.facebook.com/v9.0/instagram_oembed", params={"url":url,"access_token":environ.get("FACEBOOK_TOKEN","").strip(),"omitscript":'true'}, headers={"User-Agent": app.config["UserAgent"]}).json()["html"]
elif app.config['SERVER_NAME'] in domain: elif app.config['SERVER_NAME'] in domain:
try: try:
@ -681,7 +697,7 @@ def submit_post(v):
if max(len(similar_urls), len(similar_posts)) >= threshold: if max(len(similar_urls), len(similar_posts)) >= threshold:
text = "Your Drama account has been suspended for 1 day for the following reason:\n\n> Too much spam!" text = "Your account has been suspended for 1 day for the following reason:\n\n> Too much spam!"
send_notification(1046, v, text) send_notification(1046, v, text)
v.ban(reason="Spamming.", v.ban(reason="Spamming.",
@ -761,7 +777,7 @@ def submit_post(v):
BadLink.link)).first() BadLink.link)).first()
if badlink: if badlink:
if badlink.autoban: if badlink.autoban:
text = "Your Drama account has been suspended for 1 day for the following reason:\n\n> Too much spam!" text = "Your account has been suspended for 1 day for the following reason:\n\n> Too much spam!"
send_notification(1046, v, text) send_notification(1046, v, text)
v.ban(days=1, reason="spam") v.ban(days=1, reason="spam")
@ -789,7 +805,7 @@ def submit_post(v):
url = url.replace("https://mobile.twitter.com", "https://twitter.com") url = url.replace("https://mobile.twitter.com", "https://twitter.com")
if url.startswith("https://old.reddit.com/") and '/comments/' in url and '?sort=' not in url: url += "?sort=controversial" # if url.startswith("https://old.reddit.com/") and '/comments/' in url and '?' not in url: url += "?sort=controversial"
title_html = sanitize(title, linkgen=True, flair=True) title_html = sanitize(title, linkgen=True, flair=True)

View File

@ -1,8 +1,8 @@
from drama.helpers.wrappers import * from files.helpers.wrappers import *
import re import re
from sqlalchemy import * from sqlalchemy import *
from flask import * from flask import *
from drama.__main__ import app, cache from files.__main__ import app, cache
import random import random
query_regex=re.compile("(\w+):(\S+)") query_regex=re.compile("(\w+):(\S+)")

View File

@ -1,11 +1,11 @@
from __future__ import unicode_literals from __future__ import unicode_literals
from drama.helpers.alerts import * from files.helpers.alerts import *
from drama.helpers.sanitize import * from files.helpers.sanitize import *
from drama.helpers.filters import filter_comment_html from files.helpers.filters import filter_comment_html
from drama.helpers.markdown import * from files.helpers.markdown import *
from drama.helpers.discord import remove_user, set_nick from files.helpers.discord import remove_user, set_nick
from drama.mail import * from files.mail import *
from drama.__main__ import app, cache from files.__main__ import app, cache
import youtube_dl import youtube_dl
from .front import frontlist from .front import frontlist
@ -13,7 +13,8 @@ valid_username_regex = re.compile("^[a-zA-Z0-9_\-]{3,25}$")
valid_title_regex = re.compile("^((?!<).){3,100}$") valid_title_regex = re.compile("^((?!<).){3,100}$")
valid_password_regex = re.compile("^.{8,100}$") valid_password_regex = re.compile("^.{8,100}$")
youtubekey = environ.get("youtubekey").strip() YOUTUBE_KEY = environ.get("YOUTUBE_KEY").strip()
COINS_NAME = environ.get("COINS_NAME").strip()
@app.post("/settings/profile") @app.post("/settings/profile")
@auth_required @auth_required
@ -51,7 +52,7 @@ def settings_profile_post(v):
if request.values.get("animatedname", v.animatedname) != v.animatedname: if request.values.get("animatedname", v.animatedname) != v.animatedname:
if v.animatedname == False: if v.animatedname == False:
users = g.db.query(User.id).options(lazyload('*')).order_by(User.dramacoins.desc()).limit(25).all() users = g.db.query(User.id).options(lazyload('*')).order_by(User.coins.desc()).limit(25).all()
users = [x[0] for x in users] users = [x[0] for x in users]
if v.id not in users: return {"error": "You must be in the top 25 leaderboard or be a patron to apply an animated name!"}, 403 if v.id not in users: return {"error": "You must be in the top 25 leaderboard or be a patron to apply an animated name!"}, 403
updated = True updated = True
@ -425,13 +426,13 @@ def settings_css(v):
@auth_required @auth_required
def settings_profilecss_get(v): def settings_profilecss_get(v):
if v and v.is_banned and not v.unban_utc: return render_template("seized.html") if v and v.is_banned and not v.unban_utc: return render_template("seized.html")
if v.dramacoins < 1000 and not v.patron: return "You must have +1000 dramacoins or be a patron to set profile css." if v.coins < 1000 and not v.patron: return f"You must have +1000 {COINS_NAME} or be a patron to set profile css."
return render_template("settings_profilecss.html", v=v) return render_template("settings_profilecss.html", v=v)
@app.post("/settings/profilecss") @app.post("/settings/profilecss")
@auth_required @auth_required
def settings_profilecss(v): def settings_profilecss(v):
if v.dramacoins < 1000 and not v.patron: return "You must have +1000 dramacoins or be a patron to set profile css." if v.coins < 1000 and not v.patron: return f"You must have +1000 {COINS_NAME} or be a patron to set profile css."
profilecss = request.form.get("profilecss").replace('\\', '')[:50000] profilecss = request.form.get("profilecss").replace('\\', '')[:50000]
v.profilecss = profilecss v.profilecss = profilecss
g.db.add(v) g.db.add(v)
@ -454,7 +455,7 @@ def settings_block_user(v):
return {"error": f"You have already blocked @{user.username}."}, 409 return {"error": f"You have already blocked @{user.username}."}, 409
if user.id == 1046: if user.id == 1046:
return {"error": "You can't block @Drama."}, 409 return {"error": "You can't block @files."}, 409
new_block = UserBlock(user_id=v.id, new_block = UserBlock(user_id=v.id,
target_id=user.id, target_id=user.id,
@ -613,7 +614,7 @@ def settings_song_change(v):
return redirect("/settings/profile") return redirect("/settings/profile")
req = requests.get(f"https://www.googleapis.com/youtube/v3/videos?id={id}&key={youtubekey}&part=contentDetails").json() req = requests.get(f"https://www.googleapis.com/youtube/v3/videos?id={id}&key={YOUTUBE_KEY}&part=contentDetails").json()
try: duration = req['items'][0]['contentDetails']['duration'] try: duration = req['items'][0]['contentDetails']['duration']
except: except:
print(req) print(req)

View File

@ -1,8 +1,8 @@
from drama.mail import * from files.mail import *
from drama.__main__ import app, limiter from files.__main__ import app, limiter
from drama.helpers.alerts import * from files.helpers.alerts import *
site = environ.get("domain").strip() site = environ.get("DOMAIN").strip()
@app.get("/patrons") @app.get("/patrons")
@auth_desired @auth_desired
@ -14,7 +14,7 @@ def patrons(v):
@app.get("/badmins") @app.get("/badmins")
@auth_desired @auth_desired
def badmins(v): def badmins(v):
badmins = g.db.query(User).filter_by(admin_level=6).order_by(User.dramacoins.desc()).all() badmins = g.db.query(User).filter_by(admin_level=6).order_by(User.coins.desc()).all()
return render_template("badmins.html", v=v, badmins=badmins) return render_template("badmins.html", v=v, badmins=badmins)
@app.get("/log") @app.get("/log")

View File

@ -4,16 +4,16 @@ import time
import traceback import traceback
import sys import sys
from drama.classes.user import ViewerRelationship from files.classes.user import ViewerRelationship
from drama.helpers.alerts import * from files.helpers.alerts import *
from drama.helpers.sanitize import * from files.helpers.sanitize import *
from drama.helpers.markdown import * from files.helpers.markdown import *
from drama.mail import * from files.mail import *
from flask import * from flask import *
from drama.__main__ import app, limiter from files.__main__ import app, limiter
from pusher_push_notifications import PushNotifications, PusherAuthError from pusher_push_notifications import PushNotifications, PusherAuthError
site = environ.get("domain").strip() site = environ.get("DOMAIN").strip()
PUSHER_KEY = environ.get("PUSHER_KEY", "").strip() PUSHER_KEY = environ.get("PUSHER_KEY", "").strip()
@ -28,7 +28,7 @@ def suicide(v, username):
t = int(time.time()) t = int(time.time())
if v.admin_level == 0 and t - v.suicide_utc < 86400: return "", 204 if v.admin_level == 0 and t - v.suicide_utc < 86400: return "", 204
user = get_user(username) user = get_user(username)
suicide = f"Hi there,\n\nA [concerned dramatard]({v.url}) reached out to us about you.\n\nWhen you're in the middle of something painful, it may feel like you don't have a lot of options. But whatever you're going through, you deserve help and there are people who are here for you.\n\nThere are resources available in your area that are free, confidential, and available 24/7:\n\n- Call, Text, or Chat with Canada's [Crisis Services Canada](https://www.crisisservicescanada.ca/en/)\n- Call, Email, or Visit the UK's [Samaritans](https://www.samaritans.org/)\n- Text CHAT to America's [Crisis Text Line](https://www.crisistextline.org/) at 741741.\nIf you don't see a resource in your area above, the moderators at r/SuicideWatch keep a comprehensive list of resources and hotlines for people organized by location. Find Someone Now\n\nIf you think you may be depressed or struggling in another way, don't ignore it or brush it aside. Take yourself and your feelings seriously, and reach out to someone.\n\nIt may not feel like it, but you have options. There are people available to listen to you, and ways to move forward.\n\nYour fellow dramatards care about you and there are people who want to help." suicide = f"Hi there,\n\nA [concerned user]({v.url}) reached out to us about you.\n\nWhen you're in the middle of something painful, it may feel like you don't have a lot of options. But whatever you're going through, you deserve help and there are people who are here for you.\n\nThere are resources available in your area that are free, confidential, and available 24/7:\n\n- Call, Text, or Chat with Canada's [Crisis Services Canada](https://www.crisisservicescanada.ca/en/)\n- Call, Email, or Visit the UK's [Samaritans](https://www.samaritans.org/)\n- Text CHAT to America's [Crisis Text Line](https://www.crisistextline.org/) at 741741.\nIf you don't see a resource in your area above, the moderators at r/SuicideWatch keep a comprehensive list of resources and hotlines for people organized by location. Find Someone Now\n\nIf you think you may be depressed or struggling in another way, don't ignore it or brush it aside. Take yourself and your feelings seriously, and reach out to someone.\n\nIt may not feel like it, but you have options. There are people available to listen to you, and ways to move forward.\n\nYour fellow users care about you and there are people who want to help."
send_notification(1046, user, suicide) send_notification(1046, user, suicide)
v.suicide_utc = t v.suicide_utc = t
g.db.add(v) g.db.add(v)
@ -39,7 +39,7 @@ def suicide(v, username):
def leaderboard(v): def leaderboard(v):
if v and v.is_banned and not v.unban_utc:return render_template("seized.html") if v and v.is_banned and not v.unban_utc:return render_template("seized.html")
users = g.db.query(User).options(lazyload('*')) users = g.db.query(User).options(lazyload('*'))
users1 = users.order_by(User.dramacoins.desc()).limit(25).all() users1 = users.order_by(User.coins.desc()).limit(25).all()
users2 = users.order_by(User.stored_subscriber_count.desc()).limit(10).all() users2 = users.order_by(User.stored_subscriber_count.desc()).limit(10).all()
users3 = users.order_by(User.post_count.desc()).limit(10).all() users3 = users.order_by(User.post_count.desc()).limit(10).all()
users4 = users.order_by(User.comment_count.desc()).limit(10).all() users4 = users.order_by(User.comment_count.desc()).limit(10).all()
@ -159,7 +159,7 @@ def message2(v, username):
}, },
) )
except PusherAuthError as e: except PusherAuthError as e:
traceback.print_tb(e.__traceback__) sys.stderr.write(traceback.format_exc())
sys.stderr.flush() sys.stderr.flush()
return redirect('/notifications?all=true') return redirect('/notifications?all=true')
@ -171,7 +171,7 @@ def mfa_qr(secret, v):
qr = qrcode.QRCode( qr = qrcode.QRCode(
error_correction=qrcode.constants.ERROR_CORRECT_L error_correction=qrcode.constants.ERROR_CORRECT_L
) )
qr.add_data(x.provisioning_uri(v.username, issuer_name="Drama")) qr.add_data(x.provisioning_uri(v.username, issuer_name=app.config["SITE_NAME"]))
img = qr.make_image(fill_color="#000000", back_color="white") img = qr.make_image(fill_color="#000000", back_color="white")
mem = io.BytesIO() mem = io.BytesIO()
@ -284,11 +284,11 @@ def u_username(username, v=None):
# paidrent = False # paidrent = False
# if v and u.id == 253: # if v and u.id == 253:
# if int(time.time()) - v.rent_utc < 600: paidrent = True # if int(time.time()) - v.rent_utc < 600: paidrent = True
# elif request.args.get("rent") == "true" and v.dramacoins > 500: # elif request.args.get("rent") == "true" and v.coins > 500:
# v.dramacoins -= 500 # v.coins -= 500
# v.rent_utc = int(time.time()) # v.rent_utc = int(time.time())
# g.db.add(v) # g.db.add(v)
# u.dramacoins += 500 # u.coins += 500
# g.db.add(u) # g.db.add(u)
# send_notification(1046, u, f"@{v.username} has paid rent!") # send_notification(1046, u, f"@{v.username} has paid rent!")
# paidrent = True # paidrent = True
@ -386,11 +386,11 @@ def u_username_comments(username, v=None):
# paidrent = False # paidrent = False
# if v and u.id == 253: # if v and u.id == 253:
# if int(time.time()) - v.rent_utc < 600: paidrent = True # if int(time.time()) - v.rent_utc < 600: paidrent = True
# elif request.args.get("rent") == "true" and v.dramacoins > 500: # elif request.args.get("rent") == "true" and v.coins > 500:
# v.dramacoins -= 500 # v.coins -= 500
# v.rent_utc = int(time.time()) # v.rent_utc = int(time.time())
# g.db.add(v) # g.db.add(v)
# u.dramacoins += 500 # u.coins += 500
# g.db.add(u) # g.db.add(u)
# send_notification(1046, u, f"@{v.username} has paid rent!") # send_notification(1046, u, f"@{v.username} has paid rent!")
# paidrent = True # paidrent = True

View File

@ -1,8 +1,8 @@
from drama.helpers.wrappers import * from files.helpers.wrappers import *
from drama.helpers.get import * from files.helpers.get import *
from drama.classes import * from files.classes import *
from flask import * from flask import *
from drama.__main__ import app from files.__main__ import app
@app.get("/votes") @app.get("/votes")
@ -73,16 +73,16 @@ def api_vote_post(post_id, new, v):
if existing: if existing:
if existing.vote_type == 0 and new != 0: if existing.vote_type == 0 and new != 0:
post.author.dramacoins += 1 post.author.coins += 1
g.db.add(post.author) g.db.add(post.author)
elif existing.vote_type != 0 and new == 0: elif existing.vote_type != 0 and new == 0:
post.author.dramacoins -= 1 post.author.coins -= 1
g.db.add(post.author) g.db.add(post.author)
existing.vote_type = new existing.vote_type = new
g.db.add(existing) g.db.add(existing)
else: else:
if new != 0: if new != 0:
post.author.dramacoins += 1 post.author.coins += 1
g.db.add(post.author) g.db.add(post.author)
vote = Vote(user_id=v.id, vote = Vote(user_id=v.id,
vote_type=new, vote_type=new,
@ -121,16 +121,16 @@ def api_vote_comment(comment_id, new, v):
if existing: if existing:
if existing.vote_type == 0 and new != 0: if existing.vote_type == 0 and new != 0:
comment.author.dramacoins += 1 comment.author.coins += 1
g.db.add(comment.author) g.db.add(comment.author)
elif existing.vote_type != 0 and new == 0: elif existing.vote_type != 0 and new == 0:
comment.author.dramacoins -= 1 comment.author.coins -= 1
g.db.add(comment.author) g.db.add(comment.author)
existing.vote_type = new existing.vote_type = new
g.db.add(existing) g.db.add(existing)
else: else:
if new != 0: if new != 0:
comment.author.dramacoins += 1 comment.author.coins += 1
g.db.add(comment.author) g.db.add(comment.author)
vote = CommentVote(user_id=v.id, vote = CommentVote(user_id=v.id,
vote_type=new, vote_type=new,

View File

@ -43,7 +43,7 @@ Python example:
headers={"Authorization": "access_token_goes_here", "User-Agent": "sex"} headers={"Authorization": "access_token_goes_here", "User-Agent": "sex"}
url="https://rdrama.net/@carpathianflorist" url="{{request.host_url}}@carpathianflorist"
r=requests.get(url, headers=headers) r=requests.get(url, headers=headers)
@ -93,7 +93,7 @@ DO NOT reveal your Client ID or Access Token. Anyone with these information will
## Step 2: Prompt Your User for Authorization ## Step 2: Prompt Your User for Authorization
Send your user to `https://rdrama.net/authorize/?client_id=YOUR_CLIENT_ID` Send your user to `{{request.host_url}}authorize/?client_id=YOUR_CLIENT_ID`
If done correctly, the user will see that your application wants to access their {{"SITE_NAME" | app_config}} account, and be prompted to approve or deny the request. If done correctly, the user will see that your application wants to access their {{"SITE_NAME" | app_config}} account, and be prompted to approve or deny the request.
@ -112,7 +112,7 @@ Python example:
headers={"Authorization": "access_token_goes_here", "User-Agent": "sex"} headers={"Authorization": "access_token_goes_here", "User-Agent": "sex"}
url="https://rdrama.net/@carpathianflorist" url="{{request.host_url}}@carpathianflorist"
r=requests.get(url, headers=headers) r=requests.get(url, headers=headers)

View File

@ -5,10 +5,10 @@
<meta charset="utf-8"> <meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no"> <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<meta name="description" content="{% block pagedesc %}{{"SITE_NAME" | app_config}} - the free speech social platform{% endblock %}"> <meta name="description" content="{% block pagedesc %}{{"SITE_NAME" | app_config}}{% endblock %}">
<meta name="author" content=""> <meta name="author" content="">
<title>{% block pagetitle %}{{"SITE_NAME" | app_config}} - the open, free-speech social platform{% endblock %}</title> <title>{% block pagetitle %}{{"SITE_NAME" | app_config}}{% endblock %}</title>
<link href="https://fonts.googleapis.com/css?family=Open+Sans:400,600&display=swap" rel="stylesheet"> <link href="https://fonts.googleapis.com/css?family=Open+Sans:400,600&display=swap" rel="stylesheet">

View File

@ -16,7 +16,7 @@
{% for user in badmins %} {% for user in badmins %}
<tr> <tr>
<td><a {% if user.animatedname %}class="{% if user.patron %}patron{% else %}leaderboard{% endif %}"{% endif %} style="color:#{{user.namecolor}}; font-weight:bold;" href="/@{{user.username}}"><img src="/uid/{{user.id}}/pic/profile" class="profile-pic-20 mr-1">{{user.username}}</a></td> <td><a {% if user.animatedname %}class="{% if user.patron %}patron{% else %}leaderboard{% endif %}"{% endif %} style="color:#{{user.namecolor}}; font-weight:bold;" href="/@{{user.username}}"><img src="/uid/{{user.id}}/pic/profile" class="profile-pic-20 mr-1">{{user.username}}</a></td>
<td style="font-weight:bold; text-align:right;">{{user.dramacoins}}</td> <td style="font-weight:bold; text-align:right;">{{user.coins}}</td>
</tr> </tr>
{% endfor %} {% endfor %}
</table> </table>

View File

@ -9,15 +9,6 @@
{% block content %} {% block content %}
<div class=""> <div class="">
<h1>Whoops!</h1>
<p class="text-left">Although {{"SITE_NAME" | app_config}} puts your freedom of speech first, there are a few things that we don't allow here:</p>
<ul>
<li>Digitally malicious content</li>
<li>URL shorteners</li>
<li>Copyright infringement</li>
<li>Spam</li>
</ul>
<p>Please remove the following link(s) from your comment, and then you will be able to post it:</p> <p>Please remove the following link(s) from your comment, and then you will be able to post it:</p>
<ul> <ul>

View File

@ -807,13 +807,13 @@
<meta property="og:image" content="{{'/assets/images/preview.png' | full_link}}" /> <meta property="og:image" content="{{'/assets/images/preview.png' | full_link}}" />
<meta property="og:url" content="{{request.path | full_link}}"> <meta property="og:url" content="{{request.path | full_link}}">
<meta property="og:description" name="description" content="Dude bussy lmao"> <meta property="og:description" name="description" content="Dude bussy lmao">
<meta property="og:author" name="author" content="@drama" /> <meta property="og:author" name="author" content="@{{request.host_url}}" />
<meta property="og:site_name" content="{{request.host}}" /> <meta property="og:site_name" content="{{request.host}}" />
<meta name="twitter:card" content="summary_large_image"/> <meta name="twitter:card" content="summary_large_image"/>
<meta name="twitter:site" content="@drama"> <meta name="twitter:site" content="@{{request.host_url}}">
<meta name="twitter:title" content="{{"SITE_NAME" | app_config}}" /> <meta name="twitter:title" content="{{"SITE_NAME" | app_config}}" />
<meta name="twitter:creator" content="@drama"> <meta name="twitter:creator" content="@{{request.host_url}}">
<meta name="twitter:description" content="Dude bussy lmao" /> <meta name="twitter:description" content="Dude bussy lmao" />
<meta name="twitter:image" content="/assets/images/preview.png" /> <meta name="twitter:image" content="/assets/images/preview.png" />
<meta name="twitter:url" content="{{request.path | full_link}}" /> <meta name="twitter:url" content="{{request.path | full_link}}" />

View File

@ -0,0 +1,122 @@
{% extends "embeds/embed_default.html" %}
{% set score=c.score_fuzzed %}
{% block title %}
<title>@{{ c.author.username }} comments on "{{ c.post.title }}"</title>
<meta name="description" content="{{ c.body }}">
{% endblock %}
{% block content %}
<div class="post-info font-weight-bold">
<span class="align-top"><a href="{{ c.permalink }}?context=1">{{ c.post.title | safe }}</a></span>
</div>
<div id="comment-{{ c.base36id }}" class="comment rounded">
<span class="mr-2 d-block d-md-none"><a href="{{ c.author.permalink }}"><img src="{{ c.author.profile_url }}" class="profile-pic-25"></a></span>
<span class="comment-collapse d-md-block d-none" onclick="collapse_comment('{{ c.base36id }}')"></span>
<div class="comment-body">
<div id="comment-{{ c.base36id }}-only">
<div class="user-info">{% if c.over_18 %}<span class="badge badge-danger">nsfw</span> {% endif %}{% if c.author.title and c.author.title.is_before %}<span style="color:#{{ c.author.title.color }}">{{ c.author.title.text }}</span> {% endif %}<a href="{{ c.author.permalink }}" class="user-name {% if c.post.author_id==c.author_id %}text-info{% endif %}">{{ c.author.username }}</a>{% if c.author.title and not c.author.title.is_before %}<span style="color:#{{ c.author.title.color }}">{{ c.author.title.text }}</span>{% endif %}
{% if c.distinguish_level or c.author_id==c.post.author_id %}
<span> </span>
{% if c.distinguish_level %}
<i class="fas fa-shield text-admin" data-toggle="tooltip" data-placement="bottom" title="" data-original-title="Administrator, speaking officially"></i>
{% endif %}
{% if c.post.author_id==c.author_id %}
<i class="fas fa-microphone-stand text-info" data-toggle="tooltip" data-placement="bottom" title="" data-original-title="Submitter"></i>
{% endif %}
<span> </span>
{% endif %}
<span class="time-stamp" data-toggle="tooltip" data-placement="bottom" data-delay='{"show":"700", "hide":"300"}' title="{{ c.created_datetime }}"><span>&#183;</span> {{ c.age_string }}</span>
{% if c.edited_utc %}
<span class="time-edited" data-toggle="tooltip" data-placement="bottom" data-delay='{"show":"700", "hide":"300"}' title="{{ p.edited_datetime }}"><span>&#183;</span> <span class="font-italic">Edited {{ c.edited_string }}</span></span>
{% endif %}
<span class="comment-collapse d-md-none" onclick="collapse_comment('{{ c.base36id }}')"></span>
</div>
<div id="comment-text-{{ c.base36id }}" class="comment-text">
{{ c.body_html | safe }}
</div>
<div id="comment-{{ c.base36id }}-actions" class="comment-actions">
<ul class="list-inline text-right text-md-left">
<li id="comment-{{ c.base36id }}-up" class="list-inline-item arrow-up d-none d-md-inline-block mr-2">
</li>
<li class="list-inline-item d-none d-md-inline-block mr-2">
<span id="comment-{{ c.base36id }}-score-none"class="d-none text-black">{{ score }}</span> </li>
<li class="list-inline-item text-muted d-none d-md-inline-block"><a href="javascript:void(0);" role="button" class="copy-link" data-clipboard-text="{{ c.permalink | full_link}}"><i class="fas fa-link"></i><span>Copy link</span></a>
</li>
<li class="list-inline-item d-none d-md-inline-block">
<div class="dropdown show">
<a href="#" role="button" id="dropdownMoreLink" data-toggle="dropdown" aria-haspopup="true"
aria-expanded="false">
<i class="fas fa-ellipsis-h"></i>
</a>
<div class="dropdown-menu border-0 shadow" aria-labelledby="dropdownMoreLink">
<a class="dropdown-item" href="{{ c.parent.permalink }}"><i class="fas fa-dna"></i>Parent</a>
<a class="dropdown-item d-none" href="#"><i class="fas fa-save"></i>Save</a>
</div>
</div>
</li>
<li class="list-inline-item d-inline-block d-md-none">
<a href="#" data-toggle="modal" data-target="#actionsModal-{{ c.base36id }}" data-focus="false"><i class="fas fa-ellipsis-h"></i></a>
</li>
<li id="comment-{{ c.base36id }}-up" class="list-inline-item arrow-up d-inline-block d-md-none mr-2">
</li>
<li class="list-inline-item d-inline-block d-md-none mr-2">
<span id="comment-{{ c.base36id }}-score-none" class="d-none text-black">{{ score }}</span>
</li>
<li id="comment-{{ c.base36id }}-down" class="list-inline-item arrow-down d-inline-block d-md-none">
</li>
</ul>
</div>
</div>
<!-- Comment Actions Modal -->
<div class="modal fade d-md-none" id="actionsModal-{{ c.base36id }}" tabindex="-1" role="dialog" aria-labelledby="actionsModalTitle" aria-hidden="true">
<div class="modal-dialog modal-dialog-centered" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title h6">More options</h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true"><i class="far fa-times"></i></span>
</button>
</div>
<div class="modal-body">
<ul class="list-group comment-actions">
<li class="list-group-item"><a href="javascript:void(0);" role="button" class="d-block copy-link" data-dismiss="modal" data-clipboard-text="{{ c.permalink | full_link}}"><i class="fas fa-link"></i><span>Share</span></a>
<li class="list-group-item"><a class="d-block" href="{{ c.parent.permalink }}"><i class="fas fa-dna"></i>Parent</a></li>
<li class="list-group-item d-none"><a href="#" class="d-block"><i class="fas fa-save"></i>Save</a></li>
</ul>
</div>
</div>
</div>
</div>
</div>
{% endblock %}

View File

@ -0,0 +1,111 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<meta name="author" content="">
{% block title %}
{% endblock %}
<!-- Bootstrap core CSS -->
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css"
integrity="sha384-Gn5384xqQ1aoWXA+058RXPxPg6fy4IWvTNh0E263XmFcJlSAwiGgFAW/dAiS6JXm" crossorigin="anonymous">
{% block stylesheets %}
{% if v %}
<link rel="stylesheet" href="/assets/style/{{v.theme}}_{{v.themecolor}}.css">
{% if v.agendaposter %}<link rel="stylesheet" href="/assets/style/agendaposter.css">{% elif v.css %}<link rel="stylesheet" href="/@{{v.username}}/css">{% endif %}
{% else %}
<link rel="stylesheet" href="/assets/style/dark_ff66ac.css">
{% endif %}
{% endblock %}
<!-- Font Awesome -->
<link href="/assets/fontawesome/css/all.css" rel="stylesheet"> <!--load all styles -->
</head>
<body id="{% block pagetype %}frontpage{% endblock %}" class="p-1">
<div class="container">
<div class="row justify-content-around" id="main-content-row">
<div class="col h-100 custom-gutters" id="main-content-col">
{% block content %}
{% endblock %}
</div>
<!-- Clipboard Toast -->
<div class="toast clipboard" id="toast-success" role="alert" aria-live="assertive" aria-atomic="true" data-animation="true" data-autohide="true" data-delay="5000">
<div class="toast-body text-center">
<i class="fas fa-check-circle text-success mr-2"></i>Link copied to clipboard
</div>
</div>
<div class="toast clipboard" id="toast-error" role="alert" aria-live="assertive" aria-atomic="true" data-animation="true" data-autohide="true" data-delay="5000">
<div class="toast-body text-center">
<i class="fas fa-exclamation-circle text-danger mr-2"></i>Unable to copy link
</div>
</div>
{% include "bootstrap.html" %}
<!-- ClipboardJS -->
<script src="https://cdn.jsdelivr.net/npm/clipboard@2/dist/clipboard.min.js"></script>
<!-- Instantiate clipboard by passing a string selector -->
<script type="text/javascript">
var clipboard = new ClipboardJS('.copy-link');
clipboard.on('success', function(e) {
jQuery(function($) {
$('#toast-success').toast('show');
})
console.log(e);
});
clipboard.on('error', function(e) {
jQuery(function($) {
$('#toast-error').toast('show');
})
console.log(e);
});
</script>
{% block enlargeThumbJS %}
{% endblock %}
{% block toggleView %}
{% endblock %}
{% block embedJS %}
{% endblock %}
{% block formatJS %}
{% endblock %}
<script src="/assets/js/all_js.js"></script>
</body>
</html>

View File

@ -0,0 +1,21 @@
{% extends "embeds/embed_default.html" %}
{% block title %}
<title>{{ p.title | safe}}</title>
<meta name="description" content="posted {{ p.age_string }} by @{{ p.author.username }}">
{% endblock %}
{% block pagetype %}thread{% endblock %}
{% block content %}
<div class="row no-gutters mt-md-3">
<div class="col-12">
<div class="posts" id="posts">
{% with listing = [p] %}
{% include "submission_listing.html" %}
{% endwith %}
</div>
</div>
</div>
{% endblock %}

Some files were not shown because too many files have changed in this diff Show More