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
dramacache/
cache/
__pycache__/
*.py[cod]
*$py.class

View File

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

View File

@ -1,7 +1,7 @@
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()
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)
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)

View File

@ -1,36 +1,43 @@
version: '2.3'
services:
drama:
files:
build:
context: .
volumes:
- "./:/drama/service"
- "./:/service"
environment:
- PYTHONPATH="drama/service"
- PYTHONPATH="/service"
- REDIS_URL=redis://redis
- DATABASE_URL=postgresql://postgres@postgres:5432/postgres
- DATABASE_CONNECTION_POOL_URL=postgresql://postgres@postgres:5432/postgres
- MASTER_KEY=${MASTER_KEY:-KTVciAUQFpFh2WdJ/oiHJlxl6FvzRZp8kYzAAv3l2OA=}
- domain=localhost
- DOMAIN=localhost
- SITE_NAME=Drama
- CLOUDFLARE_ZONE=vcxvdfgfc6r554etrgd
- CLOUDFLARE_KEY=vcxvdfgfc6r554etrgd
- TENOR_KEY=vcxvdfgfc6r554etrgd
- MAILGUN_KEY=vcxvdfgfc6r554etrgd
- MAILGUN_DOMAIN=rdrama.net
- admin_email=drama@rdrama.net
- FORCE_HTTPS=0
- DISCORD_SERVER_ID=vcxvdfgfc6r554etrgd
- DISCORD_CLIENT_ID=vcxvdfgfc6r554etrgd
- DISCORD_CLIENT_SECRET=vcxvdfgfc6r554etrgd
- DISCORD_BOT_TOKEN=vcxvdfgfc6r554etrgd
- imgurkey=vcxvdfgfc6r554etrgd
- IMGUR_KEY=vcxvdfgfc6r554etrgd
- FACEBOOK_TOKEN=vcxvdfgfc6r554etrgd
#- HCAPTCHA_SITEKEY=vcxvdfgfc6r554etrgd
#- HCAPTCHA_SITEKEY=vcxvdfgfc6r554etrgd
- HCAPTCHA_SECRET=vcxvdfgfc6r554etrgd
- youtubekey=vcxvdfgfc6r554etrgd
- YOUTUBE_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:
- "redis"
- "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.url_map.strict_slashes = False
app.config["SITE_NAME"]=environ.get("SITE_NAME", "Drama").strip()
app.config["SITE_COLOR"]=environ.get("SITE_COLOR", "805ad5").strip()
app.config["DRAMAPATH"]=environ.get("DRAMAPATH", path.dirname(path.realpath(__file__)))
app.config["SITE_NAME"]=environ.get("SITE_NAME").strip()
app.config["COINS_NAME"]=environ.get("COINS_NAME").strip()
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
app.config['DATABASE_URL'] = environ.get(
"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['DATABASE_URL'] = environ.get("DATABASE_CONNECTION_POOL_URL",environ.get("DATABASE_URL"))
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_drama"
app.config["SESSION_COOKIE_NAME"] = "session_" + environ.get("SITE_NAME").strip().lower()
app.config["VERSION"] = "1.0.0"
app.config['MAX_CONTENT_LENGTH'] = 64 * 1024 * 1024
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["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 = {}
@ -70,34 +56,26 @@ app.config["UserAgent"] = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit
if "localhost" in app.config["SERVER_NAME"]:
app.config["CACHE_TYPE"] = "null"
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
app.config["HCAPTCHA_SITEKEY"] = environ.get("HCAPTCHA_SITEKEY","").strip()
app.config["HCAPTCHA_SECRET"] = environ.get(
"HCAPTCHA_SECRET","").strip()
app.config["SIGNUP_HOURLY_LIMIT"]=int(environ.get("SIGNUP_HOURLY_LIMIT",0))
app.config["HCAPTCHA_SECRET"] = environ.get("HCAPTCHA_SECRET","").strip()
# antispam configs
app.config["SPAM_SIMILARITY_THRESHOLD"] = float(
environ.get("SPAM_SIMILARITY_THRESHOLD", 0.5))
app.config["SPAM_SIMILAR_COUNT_THRESHOLD"] = int(
environ.get("SPAM_SIMILAR_COUNT_THRESHOLD", 5))
app.config["SPAM_URL_SIMILARITY_THRESHOLD"] = float(
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["SPAM_SIMILARITY_THRESHOLD"] = float(environ.get("SPAM_SIMILARITY_THRESHOLD"))
app.config["SPAM_SIMILAR_COUNT_THRESHOLD"] = int(environ.get("SPAM_SIMILAR_COUNT_THRESHOLD"))
app.config["SPAM_URL_SIMILARITY_THRESHOLD"] = float(environ.get("SPAM_URL_SIMILARITY_THRESHOLD"))
app.config["COMMENT_SPAM_SIMILAR_THRESHOLD"] = float(environ.get("COMMENT_SPAM_SIMILAR_THRESHOLD"))
app.config["COMMENT_SPAM_COUNT_THRESHOLD"] = int(environ.get("COMMENT_SPAM_COUNT_THRESHOLD"))
app.config["CACHE_REDIS_URL"] = environ.get(
"REDIS_URL").strip().lstrip() if environ.get("REDIS_URL") else None
app.config["CACHE_REDIS_URL"] = environ.get("REDIS_URL").strip()
app.config["CACHE_DEFAULT_TIMEOUT"] = 60
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(
max_connections=app.config["REDIS_POOL_SIZE"],
@ -105,7 +83,7 @@ redispool=ConnectionPool(
) if app.config["CACHE_TYPE"]=="redis" else None
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["TENOR_KEY"]=environ.get("TENOR_KEY",'').strip()
@ -115,18 +93,15 @@ Markdown(app)
cache = Cache(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_ENABLED"] = True
app.config["RATELIMIT_DEFAULTS_DEDUCT_WHEN"]=lambda:True
app.config["RATELIMIT_DEFAULTS_EXEMPT_WHEN"]=lambda:False
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(
@ -196,9 +171,9 @@ UA_BAN_CACHE_TTL = int(environ.get("UA_BAN_CACHE_TTL", 3600))
# import and bind all routing functions
import drama.classes
from drama.routes import *
import drama.helpers.jinja2
import files.classes
from files.routes import *
import files.helpers.jinja2
@cache.memoize(UA_BAN_CACHE_TTL)
def get_useragent_ban_response(user_agent_str):
@ -210,8 +185,8 @@ def get_useragent_ban_response(user_agent_str):
# return False, (None, None)
result = g.db.query(
drama.classes.Agent).filter(
drama.classes.Agent.kwd.in_(
files.classes.Agent).filter(
files.classes.Agent.kwd.in_(
user_agent_str.split())).first()
if result:
return True, (result.mock or "Follow the robots.txt, dumbass",
@ -267,26 +242,6 @@ def before_request():
else:
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
def after_request(response):

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -1,6 +1,6 @@
from sqlalchemy import *
from flask import g
from drama.__main__ import Base
from files.__main__ import 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 random
import time

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -1,7 +1,7 @@
from bs4 import BeautifulSoup
from flask import *
from urllib.parse import urlparse
from drama.classes import BannedDomain
from files.classes import BannedDomain
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 sqlalchemy.orm import joinedload, aliased

View File

@ -2,11 +2,11 @@ import requests
from os import environ
from PIL import Image as IImage, ImageSequence
import base64
from drama.classes.images import *
from files.classes.images import *
CF_KEY = environ.get("CLOUDFLARE_KEY").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):
@ -35,12 +35,10 @@ def upload_file(file=None, resize=False, png=False):
try:
with open(filedir, 'rb') as f:
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']
url = resp['link'].replace(".png", "_d.png").replace(".jpg", "_d.jpg").replace(".jpeg", "_d.jpeg") + "?maxwidth=9999"
except:
print(req.text)
return
except: return
new_image = Image(text=url, deletehash=resp["deletehash"])
g.db.add(new_image)

View File

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

View File

@ -6,7 +6,7 @@ from functools import partial
from .get import *
from os import path
site = environ.get("domain").strip()
site = environ.get("DOMAIN").strip()
_allowed_tags = tags = ['b',
'blockquote',
@ -72,7 +72,7 @@ def a_modify(attrs, new=False):
attrs[(None, "rel")] = "nofollow noopener"
# 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",
netloc=parsed_url.netloc,
path=parsed_url.path,
@ -178,12 +178,12 @@ def sanitize(text, linkgen=False, flair=False):
start = '<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
else: emojisize = 30
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("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 .get import *
from .alerts import send_notification
from drama.__main__ import app
from files.__main__ import app
def get_logged_in_user():
@ -48,7 +48,7 @@ def check_ban_evade(v):
if random.randint(0,30) < v.ban_evade:
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():
if post.is_banned:

View File

@ -4,16 +4,17 @@ import time
from flask import *
from urllib.parse import quote
from drama.helpers.security import *
from drama.helpers.wrappers import *
from drama.classes import *
from drama.__main__ import app
from files.helpers.security import *
from files.helpers.wrappers import *
from files.classes import *
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()
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"
@ -49,7 +50,7 @@ def send_verification_email(user, email=None):
html=render_template("email/email_verify.html",
action_url=link,
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 PIL import Image as IMAGE
from drama.helpers.wrappers import *
from drama.helpers.alerts import *
from drama.helpers.sanitize import *
from drama.helpers.markdown import *
from drama.helpers.security import *
from drama.helpers.get import *
from drama.helpers.images import *
from drama.classes import *
from files.helpers.wrappers import *
from files.helpers.alerts import *
from files.helpers.sanitize import *
from files.helpers.markdown import *
from files.helpers.security import *
from files.helpers.get import *
from files.helpers.images import *
from files.classes import *
from flask import *
import matplotlib.pyplot as plt
from drama.__main__ import app, cache
from files.__main__ import app, cache
from .front import frontlist
@app.get("/admin/shadowbanned")
@ -443,7 +443,7 @@ def admin_image_purge(v):
name = request.form.get("url")
image = g.db.query(Image).filter(Image.text == name).first()
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"}
data = {'files': [name]}
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 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:
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)
else:
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:
text = "Your Drama account has been permanently suspended."
text = "Your account has been permanently suspended."
user.ban(admin=v, reason=reason)
@ -701,7 +701,7 @@ def unban_user(user_id, v):
x.unban()
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(
kind="unexile_user",
@ -907,7 +907,7 @@ def refund(v):
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()])
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)
return "sex"
@ -931,7 +931,7 @@ def admin_banned_domains(v):
@validate_formkey
def admin_toggle_ban_domain(v):
domain=request.form.get("domain").strip()
domain=request.form.get("DOMAIN").strip()
if not domain: abort(400)
reason=request.form.get("reason", "").strip()

View File

@ -1,8 +1,8 @@
from drama.__main__ import app
from drama.helpers.wrappers import *
from drama.helpers.alerts import *
from drama.helpers.get import *
from drama.classes.award import *
from files.__main__ import app
from files.helpers.wrappers import *
from files.helpers.alerts import *
from files.helpers.get import *
from files.classes.award import *
from flask import g, request
@ -15,13 +15,12 @@ def banaward_trigger(post=None, comment=None):
if not author.is_suspended:
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:
author.unban_utc += 24*60*60
g.db.add(author)
send_notification(1046, author,
f"Your Drama account has been suspended for yet another day for {link}. Seriously man?")
send_notification(1046, author, f"Your account has been suspended for yet another day for {link}. Seriously man?")
ACTIONS = {

View File

@ -1,19 +1,19 @@
import traceback
import sys
from drama.helpers.wrappers import *
from drama.helpers.filters import *
from drama.helpers.alerts import *
from drama.helpers.images import *
from drama.helpers.session import *
from drama.classes import *
from drama.routes.front import comment_idlist
from files.helpers.wrappers import *
from files.helpers.filters import *
from files.helpers.alerts import *
from files.helpers.images import *
from files.helpers.session import *
from files.classes import *
from files.routes.front import comment_idlist
from pusher_push_notifications import PushNotifications, PusherAuthError
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."]
@ -259,7 +259,7 @@ def api_comment(v):
threshold *= 2
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)
v.ban(reason="Spamming.",
@ -539,7 +539,7 @@ def api_comment(v):
},
)
except PusherAuthError as e:
traceback.print_tb(e.__traceback__)
sys.stderr.write(traceback.format_exc())
sys.stderr.flush()
@ -656,7 +656,7 @@ def edit_comment(cid, v):
threshold *= 2
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)
v.ban(reason="Spamming.",

View File

@ -1,15 +1,14 @@
from drama.helpers.wrappers import *
from drama.helpers.security import *
from drama.helpers.discord import add_role
from drama.__main__ import app
from files.helpers.wrappers import *
from files.helpers.security import *
from files.helpers.discord import add_role
from files.__main__ import app
SERVER_ID = environ.get("DISCORD_SERVER_ID",'').strip()
CLIENT_ID = environ.get("DISCORD_CLIENT_ID",'').strip()
CLIENT_SECRET = environ.get("DISCORD_CLIENT_SECRET",'').strip()
BOT_TOKEN = environ.get("DISCORD_BOT_TOKEN").strip()
COINS_NAME = environ.get("COINS_NAME").strip()
DISCORD_ENDPOINT = "https://discordapp.com/api/v6"
WELCOME_CHANNEL="846509313941700618"
@app.get("/discord")
@ -17,7 +16,7 @@ WELCOME_CHANNEL="846509313941700618"
def join_discord(v):
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())
@ -126,7 +125,7 @@ def discord_redirect(v):
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:

View File

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

View File

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

View File

@ -1,8 +1,8 @@
from drama.helpers.wrappers import *
from drama.helpers.get import *
from files.helpers.wrappers import *
from files.helpers.get import *
from flask import g
from drama.__main__ import app
from drama.helpers.sanitize import sanitize
from files.__main__ import app
from files.helpers.sanitize import sanitize
@app.post("/flag/post/<pid>")
@auth_desired
@ -11,11 +11,10 @@ def api_flag_post(pid, v):
post = get_post(pid)
if v:
existing = g.db.query(Flag).filter_by(
user_id=v.id, post_id=post.id).first()
existing = g.db.query(Flag).filter_by(user_id=v.id, post_id=post.id).first()
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,
user_id=v.id,

View File

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

View File

@ -1,6 +1,6 @@
from urllib.parse import urlencode
from drama.mail import *
from drama.__main__ import app, limiter
from files.mail import *
from files.__main__ import app, limiter
valid_username_regex = re.compile("^[a-zA-Z0-9_\-]{3,25}$")
valid_password_regex = re.compile("^.{8,100}$")
@ -135,8 +135,8 @@ def login_post():
@app.get("/@me")
@auth_required
def me(v):
if request.headers.get("Authorization"): v.json
else: redirect(v.url)
if request.headers.get("Authorization"): return v.json
else: return redirect(v.url)
@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}"
send_mail(to_address=user.email,
subject="Drama - Password Reset Request",
subject="Password Reset Request",
html=render_template("email/password_reset.html",
action_url=url,
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}"
send_mail(to_address=user.email,
subject="Drama - 2FA Removal Request",
subject="2FA Removal Request",
html=render_template("email/2fa_remove.html",
action_url=action_url,
v=user)

View File

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

View File

@ -3,22 +3,22 @@ import mistletoe
import urllib.parse
import gevent
from drama.helpers.wrappers import *
from drama.helpers.sanitize import *
from drama.helpers.filters import *
from drama.helpers.markdown import *
from drama.helpers.session import *
from drama.helpers.thumbs import *
from drama.helpers.alerts import send_notification
from drama.helpers.discord import send_message
from drama.classes import *
from files.helpers.wrappers import *
from files.helpers.sanitize import *
from files.helpers.filters import *
from files.helpers.markdown import *
from files.helpers.session import *
from files.helpers.thumbs import *
from files.helpers.alerts import send_notification
from files.helpers.discord import send_message
from files.classes import *
from flask import *
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 .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]}")
@ -266,7 +266,7 @@ def edit_post(pid, v):
BadLink.link)).first()
if badlink:
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)
v.ban(days=1, reason="spam")
@ -422,7 +422,6 @@ def thumbs(new_post):
#iterate through desired meta tags
meta_tags = [
"drama:thumbnail",
"twitter:image",
"og:image",
"thumbnail"
@ -508,6 +507,22 @@ def archiveorg(url):
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")
@limiter.limit("6/minute")
@is_not_banned
@ -604,8 +619,9 @@ 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
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:
yt_id = re.match(re.compile("^.*(youtu.be\/|v\/|u\/\w\/|embed\/|watch\?v=|shorts\/|\&v=)([^#\&\?]*).*"), url).group(2)
if not yt_id or len(yt_id) != 11: embed = None
@ -616,7 +632,7 @@ def submit_post(v):
else: embed = f"https://youtube.com/embed/{yt_id}"
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:
try:
@ -681,7 +697,7 @@ def submit_post(v):
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)
v.ban(reason="Spamming.",
@ -761,7 +777,7 @@ def submit_post(v):
BadLink.link)).first()
if badlink:
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)
v.ban(days=1, reason="spam")
@ -789,7 +805,7 @@ def submit_post(v):
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)

View File

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

View File

@ -1,11 +1,11 @@
from __future__ import unicode_literals
from drama.helpers.alerts import *
from drama.helpers.sanitize import *
from drama.helpers.filters import filter_comment_html
from drama.helpers.markdown import *
from drama.helpers.discord import remove_user, set_nick
from drama.mail import *
from drama.__main__ import app, cache
from files.helpers.alerts import *
from files.helpers.sanitize import *
from files.helpers.filters import filter_comment_html
from files.helpers.markdown import *
from files.helpers.discord import remove_user, set_nick
from files.mail import *
from files.__main__ import app, cache
import youtube_dl
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_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")
@auth_required
@ -51,7 +52,7 @@ def settings_profile_post(v):
if request.values.get("animatedname", v.animatedname) != v.animatedname:
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]
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
@ -425,13 +426,13 @@ def settings_css(v):
@auth_required
def settings_profilecss_get(v):
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)
@app.post("/settings/profilecss")
@auth_required
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]
v.profilecss = profilecss
g.db.add(v)
@ -454,7 +455,7 @@ def settings_block_user(v):
return {"error": f"You have already blocked @{user.username}."}, 409
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,
target_id=user.id,
@ -613,7 +614,7 @@ def settings_song_change(v):
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']
except:
print(req)

View File

@ -1,8 +1,8 @@
from drama.mail import *
from drama.__main__ import app, limiter
from drama.helpers.alerts import *
from files.mail import *
from files.__main__ import app, limiter
from files.helpers.alerts import *
site = environ.get("domain").strip()
site = environ.get("DOMAIN").strip()
@app.get("/patrons")
@auth_desired
@ -14,7 +14,7 @@ def patrons(v):
@app.get("/badmins")
@auth_desired
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)
@app.get("/log")

View File

@ -4,16 +4,16 @@ import time
import traceback
import sys
from drama.classes.user import ViewerRelationship
from drama.helpers.alerts import *
from drama.helpers.sanitize import *
from drama.helpers.markdown import *
from drama.mail import *
from files.classes.user import ViewerRelationship
from files.helpers.alerts import *
from files.helpers.sanitize import *
from files.helpers.markdown import *
from files.mail import *
from flask import *
from drama.__main__ import app, limiter
from files.__main__ import app, limiter
from pusher_push_notifications import PushNotifications, PusherAuthError
site = environ.get("domain").strip()
site = environ.get("DOMAIN").strip()
PUSHER_KEY = environ.get("PUSHER_KEY", "").strip()
@ -28,7 +28,7 @@ def suicide(v, username):
t = int(time.time())
if v.admin_level == 0 and t - v.suicide_utc < 86400: return "", 204
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)
v.suicide_utc = t
g.db.add(v)
@ -39,7 +39,7 @@ def suicide(v, username):
def leaderboard(v):
if v and v.is_banned and not v.unban_utc:return render_template("seized.html")
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()
users3 = users.order_by(User.post_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:
traceback.print_tb(e.__traceback__)
sys.stderr.write(traceback.format_exc())
sys.stderr.flush()
return redirect('/notifications?all=true')
@ -171,7 +171,7 @@ def mfa_qr(secret, v):
qr = qrcode.QRCode(
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")
mem = io.BytesIO()
@ -284,11 +284,11 @@ def u_username(username, v=None):
# paidrent = False
# if v and u.id == 253:
# if int(time.time()) - v.rent_utc < 600: paidrent = True
# elif request.args.get("rent") == "true" and v.dramacoins > 500:
# v.dramacoins -= 500
# elif request.args.get("rent") == "true" and v.coins > 500:
# v.coins -= 500
# v.rent_utc = int(time.time())
# g.db.add(v)
# u.dramacoins += 500
# u.coins += 500
# g.db.add(u)
# send_notification(1046, u, f"@{v.username} has paid rent!")
# paidrent = True
@ -386,11 +386,11 @@ def u_username_comments(username, v=None):
# paidrent = False
# if v and u.id == 253:
# if int(time.time()) - v.rent_utc < 600: paidrent = True
# elif request.args.get("rent") == "true" and v.dramacoins > 500:
# v.dramacoins -= 500
# elif request.args.get("rent") == "true" and v.coins > 500:
# v.coins -= 500
# v.rent_utc = int(time.time())
# g.db.add(v)
# u.dramacoins += 500
# u.coins += 500
# g.db.add(u)
# send_notification(1046, u, f"@{v.username} has paid rent!")
# paidrent = True

View File

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

View File

@ -43,7 +43,7 @@ Python example:
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)
@ -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
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.
@ -112,7 +112,7 @@ Python example:
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)

View File

@ -5,10 +5,10 @@
<meta charset="utf-8">
<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="">
<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">

View File

@ -16,7 +16,7 @@
{% for user in badmins %}
<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 style="font-weight:bold; text-align:right;">{{user.dramacoins}}</td>
<td style="font-weight:bold; text-align:right;">{{user.coins}}</td>
</tr>
{% endfor %}
</table>

View File

@ -9,15 +9,6 @@
{% block content %}
<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>
<ul>

View File

@ -807,13 +807,13 @@
<meta property="og:image" content="{{'/assets/images/preview.png' | full_link}}" />
<meta property="og:url" content="{{request.path | full_link}}">
<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 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:creator" content="@drama">
<meta name="twitter:creator" content="@{{request.host_url}}">
<meta name="twitter:description" content="Dude bussy lmao" />
<meta name="twitter:image" content="/assets/images/preview.png" />
<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