get rid of useless tabs and spaces

pull/83/head
Aevann 2023-01-01 13:36:20 +02:00
parent b0b70d2f0f
commit 044664a25e
108 changed files with 729 additions and 729 deletions

View File

@ -4,7 +4,7 @@ ARG DEBIAN_FRONTEND=noninteractive
RUN apt update
RUN apt -y upgrade
RUN apt install -y supervisor
RUN apt install -y supervisor
RUN apt install -y python3-pip
RUN apt install -y ffmpeg
RUN apt install -y postgresql

View File

@ -174,7 +174,7 @@ blockquote {
}
blockquote a {
color: skyblue;
color: skyblue;
}
.unread {

View File

@ -106,7 +106,7 @@ blockquote {
}
.comment-collapse-icon::before {
color: var(--gray-500) !important
color: var(--gray-500) !important
}
.text-admin {

View File

@ -6,7 +6,7 @@
--secondary: #c7c7c7;
--gray: #c7c7c7;
--gray-300: #c7c7c7;
--gray-400: #cfcfcf;
--gray-400: #cfcfcf;
--gray-500: #ffffff;
--gray-600: #ffffff;
--gray-700: #ffffff;

View File

@ -6574,7 +6574,7 @@ body > .container {
.emoji2 {
/*background: None!important;*/
width:60px;
width:60px;
height: 85px;
overflow: hidden;
border: none

View File

@ -35,7 +35,7 @@ body, .navbar-light, .navbar-dark, .card, .modal-content, .comment-write textare
}
.modal .comment-actions .list-group-item {
background-color: var(--gray-600)!important;
background-color: var(--gray-600)!important;
}
.page-link {

View File

@ -33,7 +33,7 @@ h1, h2, h3, h4, h5, h6 {
}
.button {
background-color: rgb(var(--background))!important;
background-color: rgb(var(--background))!important;
background: 0 0;
font-weight: 600;
font-size: 1rem;

View File

@ -133,7 +133,7 @@
{"name":"oplus", "class":"Marsey Alphabet", "tags": ["⊕","xor","circled","sum"]},
{"name":"otimes", "class":"Marsey Alphabet", "tags": ["⊗","tensor","circled","product"]},
{"name":"trianglelefteq", "class":"Marsey Alphabet", "tags": ["⊴"]},
{"name":"marseyflagmaryland","class":"Marsey Flags"},
{"name":"marseyflagcalifornia","class":"Marsey Flags"},
{"name":"marseyflagtexas","class":"Marsey Flags"},

View File

@ -213,40 +213,40 @@ body {
background-color: #1f1f1f;
background-blend-mode: soft-light;
}
.color {
width: 20%;
height: 100%;
float: left
}
.color p {
position: relative;
z-index: 1231231;
text-align: center;
line-height: 90vh;
}
.color:nth-child(1){
background-color: #F5624D;
}
.color:nth-child(2){
background-color: #CC231E;
}
.color:nth-child(3){
background-color: #34A65F;
}
.color:nth-child(4){
background-color: #0F8A5F;
}
.color:nth-child(5){
background-color: #235E6F;
}
#snow:not([data-nonce]) {
height: 100%;
color: #FFF;

View File

@ -13,7 +13,7 @@
function snow(flakesMax) {
// --- common properties ---
this.autoStart = true; // Whether the snow should start automatically or not.
this.excludeMobile = false; // Snow is likely to be bad news for mobile phones' CPUs (and batteries.) Enable at your own risk.
this.flakesMax = flakesMax; // Limit total amount of snow made (falling + sticking)
@ -32,9 +32,9 @@ function snow(flakesMax) {
this.useTwinkleEffect = false; // Allow snow to randomly "flicker" in and out of view while falling
this.usePositionFixed = false; // true = snow does not shift vertically when scrolling. May increase CPU load, disabled by default - if enabled, used only where supported
this.usePixelPosition = false; // Whether to use pixel values for snow top/left vs. percentages. Auto-enabled if body is position:relative or targetElement is specified.
// --- less-used bits ---
this.freezeOnBlur = true; // Only snow when the window is in focus (foreground.) Saves CPU.
this.flakeLeftOffset = 0; // Left margin/gutter space on edge of container (eg. browser window.) Bump up these values if seeing horizontal scrollbars.
this.flakeRightOffset = 0; // Right margin/gutter space on edge of container
@ -43,9 +43,9 @@ function snow(flakesMax) {
this.vMaxX = 5; // Maximum X velocity range for snow
this.vMaxY = 4; // Maximum Y velocity range for snow
this.zIndex = 0; // CSS stacking order applied to each snowflake
// --- "No user-serviceable parts inside" past this point, yadda yadda ---
var storm = this,
features,
// UA sniffing and backCompat rendering mode checks for fixed position, etc.
@ -76,20 +76,20 @@ function snow(flakesMax) {
})(),
didInit = false,
docFrag = document.createDocumentFragment();
features = (function () {
var getAnimationFrame;
/**
* hat tip: paul irish
* http://paulirish.com/2011/requestanimationframe-for-smart-animating/
* https://gist.github.com/838785
*/
function timeoutShim(callback) {
window.setTimeout(callback, 1000 / (storm.animationInterval || 20));
}
var _animationFrame =
window.requestAnimationFrame ||
window.webkitRequestAnimationFrame ||
@ -97,24 +97,24 @@ function snow(flakesMax) {
window.oRequestAnimationFrame ||
window.msRequestAnimationFrame ||
timeoutShim;
// apply to window, avoid "illegal invocation" errors in Chrome
getAnimationFrame = _animationFrame
? function () {
return _animationFrame.apply(window, arguments);
}
: null;
var testDiv;
testDiv = document.createElement("div");
function has(prop) {
// test for feature support
var result = testDiv.style[prop];
return result !== undefined ? prop : null;
}
// note local scope.
var localFeatures = {
transform: {
@ -125,34 +125,34 @@ function snow(flakesMax) {
w3: has("transform"),
prop: null // the normalized property value
},
getAnimationFrame: getAnimationFrame
};
localFeatures.transform.prop =
localFeatures.transform.w3 ||
localFeatures.transform.moz ||
localFeatures.transform.webkit ||
localFeatures.transform.ie ||
localFeatures.transform.opera;
testDiv = null;
return localFeatures;
})();
this.timer = null;
this.flakes = [];
this.disabled = false;
this.active = false;
this.meltFrameCount = 20;
this.meltFrames = [];
this.setXY = function (o, x, y) {
if (!o) {
return false;
}
if (storm.usePixelPosition || targetElementIsRelative) {
o.style.left = x - storm.flakeWidth + "px";
o.style.top = y - storm.flakeHeight + "px";
@ -172,7 +172,7 @@ function snow(flakesMax) {
}
}
};
this.events = (function () {
var old = !window.addEventListener && window.attachEvent,
slice = Array.prototype.slice,
@ -180,7 +180,7 @@ function snow(flakesMax) {
add: old ? "attachEvent" : "addEventListener",
remove: old ? "detachEvent" : "removeEventListener"
};
function getArgs(oArgs) {
var args = slice.call(oArgs),
len = args.length;
@ -194,7 +194,7 @@ function snow(flakesMax) {
}
return args;
}
function apply(args, sType) {
var element = args.shift(),
method = [evt[sType]];
@ -204,32 +204,32 @@ function snow(flakesMax) {
element[method].apply(element, args);
}
}
function addEvent() {
apply(getArgs(arguments), "add");
}
function removeEvent() {
apply(getArgs(arguments), "remove");
}
return {
add: addEvent,
remove: removeEvent
};
})();
function rnd(n, min) {
if (isNaN(min)) {
min = 0;
}
return Math.random() * n + min;
}
function plusMinus(n) {
return parseInt(rnd(2), 10) === 1 ? n * -1 : n;
}
this.randomizeWind = function () {
var i;
vRndX = plusMinus(rnd(storm.vMaxX, 0.2));
@ -242,7 +242,7 @@ function snow(flakesMax) {
}
}
};
this.scrollHandler = function () {
var i;
// "attach" snowflakes to bottom of window if no absolute bottom value was given
@ -265,7 +265,7 @@ function snow(flakesMax) {
}
}
};
this.resizeHandler = function () {
if (window.innerWidth || window.innerHeight) {
screenX = window.innerWidth - 16 - storm.flakeRightOffset;
@ -286,14 +286,14 @@ function snow(flakesMax) {
docHeight = document.body.offsetHeight;
screenX2 = parseInt(screenX / 2, 10);
};
this.resizeHandlerAlt = function () {
screenX = storm.targetElement.offsetWidth - storm.flakeRightOffset;
screenY = storm.flakeBottom || storm.targetElement.offsetHeight;
screenX2 = parseInt(screenX / 2, 10);
docHeight = document.body.offsetHeight;
};
this.freeze = function () {
// pause animation
if (!storm.disabled) {
@ -303,7 +303,7 @@ function snow(flakesMax) {
}
storm.timer = null;
};
this.resume = function () {
if (storm.disabled) {
storm.disabled = 0;
@ -312,7 +312,7 @@ function snow(flakesMax) {
}
storm.timerInit();
};
this.toggleSnow = function () {
if (!storm.flakes.length) {
// first run
@ -328,7 +328,7 @@ function snow(flakesMax) {
}
}
};
this.stop = function () {
var i;
this.freeze();
@ -347,14 +347,14 @@ function snow(flakesMax) {
}
}
};
this.show = function () {
var i;
for (i = 0; i < this.flakes.length; i++) {
this.flakes[i].o.style.display = "block";
}
};
this.SnowFlake = function (type, x, y) {
var s = this;
this.type = type;
@ -390,7 +390,7 @@ function snow(flakesMax) {
this.o.style.fontWeight = "normal";
this.o.style.zIndex = storm.zIndex;
docFrag.appendChild(this.o);
this.refresh = function () {
if (isNaN(s.x) || isNaN(s.y)) {
// safety check
@ -398,7 +398,7 @@ function snow(flakesMax) {
}
storm.setXY(s.o, s.x, s.y);
};
this.stick = function () {
if (
noFixed ||
@ -415,7 +415,7 @@ function snow(flakesMax) {
s.o.style.display = "block";
}
};
this.vCheck = function () {
if (s.vX >= 0 && s.vX < 0.2) {
s.vX = 0.2;
@ -426,7 +426,7 @@ function snow(flakesMax) {
s.vY = 0.2;
}
};
this.move = function () {
var vX = s.vX * windOffset,
yDiff;
@ -481,25 +481,25 @@ function snow(flakesMax) {
}
}
};
this.animate = function () {
// main animation loop
// move, check status, die etc.
s.move();
};
this.setVelocities = function () {
s.vX = vRndX + rnd(storm.vMaxX * 0.12, 0.1);
s.vY = vRndY + rnd(storm.vMaxY * 0.12, 0.1);
};
this.setOpacity = function (o, opacity) {
if (!opacitySupported) {
return false;
}
o.style.opacity = opacity;
};
this.melt = function () {
if (!storm.useMeltEffect || !s.melting) {
s.recycle();
@ -519,7 +519,7 @@ function snow(flakesMax) {
}
}
};
this.recycle = function () {
s.o.style.display = "none";
s.o.style.position = fixedForEverything ? "fixed" : "absolute";
@ -541,11 +541,11 @@ function snow(flakesMax) {
s.o.style.display = "block";
s.active = 1;
};
this.recycle(); // set up x/y coords etc.
this.refresh();
};
this.snow = function () {
var active = 0,
flake = null,
@ -570,7 +570,7 @@ function snow(flakesMax) {
features.getAnimationFrame(storm.snow);
}
};
this.mouseMove = function (e) {
if (!storm.followMouse) {
return true;
@ -583,7 +583,7 @@ function snow(flakesMax) {
windOffset = (x / screenX2) * windMultiplier;
}
};
this.createSnow = function (limit, allowInactive) {
var i;
for (i = 0; i < limit; i++) {
@ -596,12 +596,12 @@ function snow(flakesMax) {
}
storm.targetElement.appendChild(docFrag);
};
this.timerInit = function () {
storm.timer = true;
storm.snow();
};
this.init = function () {
var i;
for (i = 0; i < storm.meltFrameCount; i++) {
@ -628,7 +628,7 @@ function snow(flakesMax) {
storm.animationInterval = Math.max(20, storm.animationInterval);
storm.timerInit();
};
this.start = function (bFromOnLoad) {
if (!didInit) {
didInit = true;
@ -678,7 +678,7 @@ function snow(flakesMax) {
storm.active = true;
}
};
function doDelayedStart() {
window.setTimeout(function () {
storm.start(true);
@ -686,7 +686,7 @@ function snow(flakesMax) {
// event cleanup
storm.events.remove(isIE ? document : window, "mousemove", doDelayedStart);
}
function doStart() {
if (!storm.excludeMobile || !isMobile) {
doDelayedStart();
@ -694,12 +694,12 @@ function snow(flakesMax) {
// event cleanup
storm.events.remove(window, "load", doStart);
}
// hooks for starting the snow
if (storm.autoStart) {
storm.events.add(window, "load", doStart, false);
}
return this;
}

View File

@ -86,7 +86,7 @@ function vote(type, id, dir) {
}
}
}
const xhr = createXhrWithFormKey("/vote/" + type.replace('-mobile','') + "/" + id + "/" + votedirection);
xhr[0].send(xhr[1]);
}
@ -144,7 +144,7 @@ function buy(mb) {
document.getElementById('giveaward').disabled=false;
let owned = document.getElementById(`${kind}-owned`)
let ownednum = Number(owned.textContent) + 1;
owned.textContent = ownednum
owned.textContent = ownednum
}
}
};
@ -166,7 +166,7 @@ function giveaward(t) {
owned.textContent = ownednum
if (ownednum == 0)
document.getElementById('giveaward').disabled=true;
}
}
);
}

View File

@ -108,7 +108,7 @@ function buildRouletteTable() {
for (let i = 25; i < 37; i++) {
const correctNumber = CELL_TO_NUMBER_LOOKUP[i];
const isRed = reds.includes(correctNumber);
html += `<div
id="STRAIGHT_UP_BET#${correctNumber}"
data-nonce="${nonce}"
@ -238,7 +238,7 @@ function buildRouletteBets(bets) {
data-bs-placement="bottom"
title=""
aria-label="Marseybux"
width="32" class="mr-1 ml-1"
width="32" class="mr-1 ml-1"
data-bs-original-title="Marseybux">
`;
const { participants, coin, marseybux } = flatBets.reduce((prev, next) => {

View File

@ -98,7 +98,7 @@ function delete_commentModal(t, id) {
document.getElementById("comment-"+id).remove()
}
else
{
{
document.getElementsByClassName(`comment-${id}-only`)[0].classList.add('deleted');
document.getElementById(`delete-${id}`).classList.add('d-none');
document.getElementById(`undelete-${id}`).classList.remove('d-none');
@ -123,7 +123,7 @@ function post_reply(id){
form.append('file', e);
}
catch(e) {}
const xhr = createXhrWithFormKey("/reply", "POST", form);
xhr[0].onload=function(){
let data

View File

@ -63,7 +63,7 @@ function postToast(t, url, data, extraActionsOnSuccess, method="POST") {
showToast(success, message);
if (!isShopConfirm) {
t.disabled = false;
t.classList.remove("disabled");
t.classList.remove("disabled");
}
return success;
};

View File

@ -4,6 +4,6 @@ let audio = new Audio(`/assets/images/${fart}.webp`);
audio.play();
if (audio.paused) {
document.addEventListener('click', () => {
if (audio.paused) audio.play();
if (audio.paused) audio.play();
}, {once : true})
}

View File

@ -43,7 +43,7 @@ async function getGifs(form) {
noGIFs.innerHTML = null;
loadGIFs.innerHTML = null;
container.innerHTML = `
container.innerHTML = `
<div class="card">
<div class="gif-cat-overlay"><div>Agree</div></div>
<img loading="lazy" src="https://media.giphy.com/media/wGhYz3FHaRJgk/200w.webp">

View File

@ -65,7 +65,7 @@ function registerServiceWorker(serviceWorkerUrl, applicationServerPublicKey, api
.catch(function() {
});
} else {
}
}
return swRegistration;
}

View File

@ -75,4 +75,4 @@ self.addEventListener('notificationclick', (e) => {
const hadWindowToFocus = clientsArr.some((windowClient) => windowClient.url === e.notification.data.url ? (windowClient.focus(), true) : false);
if (!hadWindowToFocus) clients.openWindow(e.notification.data.url).then((windowClient) => windowClient ? windowClient.focus() : null);
}));
});
});

View File

@ -13,7 +13,7 @@ function updatebgselection(){
const backgrounds = [
{
folder: "glitter",
backgrounds:
backgrounds:
[
"1.webp",
"2.webp",
@ -109,7 +109,7 @@ document.onpaste = function(event) {
alert("You can't upload more than 4 files at one time!")
return
}
if (files.length)
{
f=document.getElementById('file-upload');

View File

@ -38,7 +38,7 @@ function unblock_user(t, url) {
},
() => {
t.parentElement.parentElement.remove();
}
}
);
}

View File

@ -12,12 +12,12 @@ function highlight_unread(localstoragevar) {
catch(e) {}
}
}
}
}
}
highlight_unread("comment-counts")
if (!location.href.includes("?context")) {
if (!location.href.includes("?context")) {
localStorage.setItem("old-comment-counts", localStorage.getItem("comment-counts"))
const comments = JSON.parse(localStorage.getItem("comment-counts")) || {}

View File

@ -82,7 +82,7 @@ class Badge(Base):
text = self.badge.description
else:
return self.name
return f'{self.name} - {text}'
@property

View File

@ -285,7 +285,7 @@ class Comment(Base):
body += f''' data-nonce="{{g.nonce}}" data-onclick="poll_vote_no_v()"'''
body += f'''><label class="custom-control-label" for="comment-{o.id}">{o.body_html}<span class="presult-{self.id}'''
if not self.total_poll_voted(v): body += ' d-none'
if not self.total_poll_voted(v): body += ' d-none'
body += f'"> - <a href="/votes/comment/option/{o.id}"><span id="score-comment-{o.id}">{o.upvotes}</span> votes</a></label></div>'''
if not self.ghost and self.author.show_sig(v):
@ -322,15 +322,15 @@ class Comment(Base):
if self.author.shadowbanned and not (v and v.shadowbanned): return True
if (self.wordle_result) and (not self.body or len(self.body_html) <= 100) and 9 > self.level > 1: return True
if v and v.filter_words and self.body and any(x in self.body for x in v.filter_words): return True
return False
@property
@lazy
def is_op(self): return self.author_id==self.post.author_id
@lazy
def filtered_flags(self, v):
return [f for f in self.flags if (v and v.shadowbanned) or not f.user.shadowbanned]
@ -356,7 +356,7 @@ class Comment(Base):
body += "<strong class='ml-2'>Correct!</strong>"
elif wordle_status == 'lost':
body += f"<strong class='ml-2'>Lost. The answer was: {wordle_answer}</strong>"
body += '</span>'
return body

View File

@ -22,8 +22,8 @@ class Leaderboard:
user_func = None
value_func = None
def __init__(self, header_name:str, table_header_name:str, html_id:str, table_column_name:str,
user_relative_url:Optional[str], query_function:Callable[..., Tuple[Any, Any, Any]],
def __init__(self, header_name:str, table_header_name:str, html_id:str, table_column_name:str,
user_relative_url:Optional[str], query_function:Callable[..., Tuple[Any, Any, Any]],
criteria, v:User, value_func:Optional[Callable[[User], Union[int, Column]]], db:scoped_session, users, limit=LEADERBOARD_LIMIT):
self.header_name = header_name
self.table_header_name = table_header_name
@ -52,11 +52,11 @@ class Leaderboard:
sq = db.query(User.id, func.rank().over(order_by=order_by.desc()).label("rank")).subquery()
position = db.query(sq.c.id, sq.c.rank).filter(sq.c.id == v.id).limit(1).one()[1]
return (leaderboard, position, None)
@classmethod
def count_and_label(cls, criteria):
return func.count(criteria).label("count")
@classmethod
def rank_filtered_rank_label_by_desc(cls, criteria):
return func.rank().over(order_by=func.count(criteria).desc()).label("rank")
@ -71,27 +71,27 @@ class Leaderboard:
sq_criteria = User.id == sq.c.author_id
else:
raise ValueError("This leaderboard function only supports Badge.user_id and Marsey.author_id")
leaderboard = db.query(User, sq.c.count).join(sq, sq_criteria).order_by(sq.c.count.desc())
position = db.query(User.id, sq.c.rank, sq.c.count).join(sq, sq_criteria).filter(User.id == v.id).one_or_none()
if position: position = (position[1], position[2])
else: position = (leaderboard.count() + 1, 0)
leaderboard = leaderboard.limit(limit).all()
return (leaderboard, position[0], position[1])
@classmethod
def get_blockers_lb(cls, lb_criteria, v:User, db:scoped_session, users:Any, limit):
if lb_criteria != UserBlock.target_id:
raise ValueError("This leaderboard function only supports UserBlock.target_id")
sq = db.query(lb_criteria, cls.count_and_label(lb_criteria)).group_by(lb_criteria).subquery()
leaderboard = db.query(User, sq.c.count).join(User, User.id == sq.c.target_id).order_by(sq.c.count.desc())
sq = db.query(lb_criteria, cls.count_and_label(lb_criteria), cls.rank_filtered_rank_label_by_desc(lb_criteria)).group_by(lb_criteria).subquery()
position = db.query(sq.c.rank, sq.c.count).join(User, User.id == sq.c.target_id).filter(sq.c.target_id == v.id).limit(1).one_or_none()
if not position: position = (leaderboard.count() + 1, 0)
leaderboard = leaderboard.limit(limit).all()
return (leaderboard, position[0], position[1])
@classmethod
def get_hat_lb(cls, lb_criteria, v:User, db:scoped_session, users:Any, limit):
leaderboard = db.query(User, func.count(lb_criteria)).join(lb_criteria).group_by(User).order_by(func.count(lb_criteria).desc())

View File

@ -13,7 +13,7 @@ class SubRelationship(Base):
@declared_attr
def user_id(self):
return Column(Integer, ForeignKey("users.id"), primary_key=True)
@declared_attr
def sub(self):
return Column(String(20), ForeignKey("subs.name"), primary_key=True)
@ -28,7 +28,7 @@ class SubRelationship(Base):
def __repr__(self):
return f"<{self.__class__.__name__}(user_id={self.user_id}, sub={self.sub})>"
class SubJoin(SubRelationship):
__tablename__ = "sub_joins"

View File

@ -145,14 +145,14 @@ class Submission(Base):
@property
@lazy
def is_youtube(self):
return self.domain == "youtube.com" and self.embed_url and self.embed_url.startswith('<lite-youtube')
return self.domain == "youtube.com" and self.embed_url and self.embed_url.startswith('<lite-youtube')
@property
@lazy
def thumb_url(self):
if self.over_18: return f"{SITE_FULL}/i/nsfw.webp?v=1"
elif not self.url: return f"{SITE_FULL}/i/{SITE_NAME}/default_text.webp?v=2"
elif self.thumburl:
elif self.thumburl:
if self.thumburl.startswith('/'): return SITE_FULL + self.thumburl
return self.thumburl
elif self.is_youtube or self.is_video: return f"{SITE_FULL}/i/default_thumb_video.webp?v=2"
@ -171,7 +171,7 @@ class Submission(Base):
'title': self.title,
'permalink': self.permalink,
}
if self.deleted_utc:
return {'is_banned': bool(self.is_banned),
'deleted_utc': True,
@ -240,7 +240,7 @@ class Submission(Base):
url = normalize_urls_runtime(url, v)
if url.startswith("https://old.reddit.com/r/") and '/comments/' in url and "sort=" not in url:
if "?" in url: url += "&context=9"
if "?" in url: url += "&context=9"
else: url += "?context=8"
if not v or v.controversial: url += "&sort=controversial"
elif url.startswith("https://watchpeopledie.tv/videos/"):
@ -249,7 +249,7 @@ class Submission(Base):
"https://videos.watchpeopledie.tv/", 1)
return url
@lazy
def total_bet_voted(self, v):
if "closed" in self.body.lower(): return True
@ -297,7 +297,7 @@ class Submission(Base):
if o.exclusive == 3:
body += " - <b>WINNER!</b>"
if not winner and v and v.admin_level >= PERMS['POST_BETS_DISTRIBUTE']:
body += f'''<button class="btn btn-primary distribute" data-areyousure="postToastReload(this,'/distribute/{o.id}')" data-nonce="{{g.nonce}}" data-onclick="areyousure(this)">Declare winner</button>'''
body += "</div>"
@ -314,7 +314,7 @@ class Submission(Base):
body += f''' data-nonce="{{g.nonce}}" data-onclick="poll_vote_no_v()"'''
body += f'''><label class="custom-control-label" for="post-{o.id}">{o.body_html}<span class="presult-{self.id}'''
if not self.total_poll_voted(v): body += ' d-none'
if not self.total_poll_voted(v): body += ' d-none'
body += f'"> - <a href="/votes/post/option/{o.id}"><span id="score-post-{o.id}">{o.upvotes}</span> votes</a></label></div>'''

View File

@ -204,7 +204,7 @@ class User(Base):
g.db.query(User).filter(User.id == self.id).update({ User.marseybux: User.marseybux + amount })
g.db.flush()
def charge_account(self, currency, amount, **kwargs):
in_db = g.db.query(User).filter(User.id == self.id).with_for_update().one()
@ -214,19 +214,19 @@ class User(Base):
if currency == 'coins':
account_balance = in_db.coins
if not should_check_balance or account_balance >= amount:
g.db.query(User).filter(User.id == self.id).update({ User.coins: User.coins - amount })
succeeded = True
elif currency == 'marseybux':
account_balance = in_db.marseybux
if not should_check_balance or account_balance >= amount:
g.db.query(User).filter(User.id == self.id).update({ User.marseybux: User.marseybux - amount })
succeeded = True
if succeeded: g.db.flush()
return succeeded
@property
@ -417,7 +417,7 @@ class User(Base):
if badge in owned_badges: discount -= discounts[badge]
return discount
@property
@lazy
def can_view_offsitementions(self):
@ -586,14 +586,14 @@ class User(Base):
Notification.user_id == self.id,
not_(and_(Comment.sentto != None, Comment.sentto == MODMAIL_ID, User.is_muted)),
))
if not self.can_see_shadowbanned:
notifs = notifs.filter(
User.shadowbanned == None,
Comment.is_banned == False,
Comment.deleted_utc == 0,
)
return notifs.count() + self.post_notifications_count + self.modaction_notifications_count + self.reddit_notifications_count
@property
@ -603,7 +603,7 @@ class User(Base):
- self.message_notifications_count \
- self.post_notifications_count \
- self.modaction_notifications_count \
- self.reddit_notifications_count
- self.reddit_notifications_count
@property
@lazy
@ -659,7 +659,7 @@ class User(Base):
SubAction.user_id != self.id,
SubAction.sub.in_(self.moderated_subs),
).count()
return 0
@ -669,8 +669,8 @@ class User(Base):
if not self.can_view_offsitementions or self.id == AEVANN_ID: return 0
return g.db.query(Comment).filter(
Comment.created_utc > self.last_viewed_reddit_notifs,
Comment.is_banned == False, Comment.deleted_utc == 0,
Comment.body_html.like('%<p>New site mention%<a href="https://old.reddit.com/r/%'),
Comment.is_banned == False, Comment.deleted_utc == 0,
Comment.body_html.like('%<p>New site mention%<a href="https://old.reddit.com/r/%'),
Comment.parent_submission == None, Comment.author_id == AUTOJANNY_ID).count()
@property
@ -730,7 +730,7 @@ class User(Base):
def has_follower(self, user):
if not user or self.id == user.id: return False # users can't follow themselves
return g.db.query(Follow).filter_by(target_id=self.id, user_id=user.id).one_or_none()
@lazy
def is_visible_to(self, user) -> bool:
if not self.is_private: return True
@ -752,7 +752,7 @@ class User(Base):
return f"{SITE_FULL}/e/chudsey.webp"
if self.rainbow:
return f"{SITE_FULL}/e/marseysalutepride.webp"
if self.profileurl:
if self.profileurl:
if self.profileurl.startswith('/'): return SITE_FULL + self.profileurl
return self.profileurl
return f"{SITE_FULL}/i/default-profile-pic.webp?v=1008"
@ -927,7 +927,7 @@ class User(Base):
if self.patron == 6:
return 'Contributed at least $200'
return ''
@classmethod
def can_see_content(cls, user:Optional["User"], other:Union[Submission, Comment, Sub]) -> bool:
'''

View File

@ -35,7 +35,7 @@ def _archiveorg(url):
except: pass
def archive_url(url):
def archive_url(url):
gevent.spawn(_archiveorg, url)
if url.startswith('https://twitter.com/'):
url = url.replace('https://twitter.com/', 'https://nitter.lacontrevoie.fr/')
@ -64,7 +64,7 @@ def execute_snappy(post:Submission, v:User):
if SNAPPY_MARSEYS and SNAPPY_QUOTES:
if IS_FISTMAS() or random.random() > 0.5:
SNAPPY_CHOICES = SNAPPY_QUOTES
else:
else:
SNAPPY_CHOICES = SNAPPY_MARSEYS
elif SNAPPY_MARSEYS: SNAPPY_CHOICES = SNAPPY_MARSEYS
elif SNAPPY_QUOTES: SNAPPY_CHOICES = SNAPPY_QUOTES
@ -350,7 +350,7 @@ def execute_blackjack_custom(v, target, body, type):
def execute_blackjack(v, target, body, type):
if not execute_blackjack_custom(v, target, body, type):
return False
if not body: return True
execute = False
@ -510,8 +510,8 @@ def execute_lawlz_actions(v:User, p:Submission):
g.db.add(ma_2)
g.db.add(ma_3)
def process_poll_options(target:Union[Submission, Comment],
cls:Union[Type[SubmissionOption], Type[CommentOption]],
def process_poll_options(target:Union[Submission, Comment],
cls:Union[Type[SubmissionOption], Type[CommentOption]],
options:Iterable[str], exclusive:int, friendly_name:str,
db:scoped_session) -> None:
for option in options:

View File

@ -66,7 +66,7 @@ def notif_comment2(p):
search_html = f'%</a> has mentioned you: <a href="/post/{p.id}">%'
existing = g.db.query(Comment.id).filter(Comment.author_id == AUTOJANNY_ID, Comment.parent_submission == None, Comment.body_html.like(search_html)).first()
if existing: return existing[0]
else:
text = f"@{p.author.username} has mentioned you: [{p.title}](/post/{p.id})"

View File

@ -85,7 +85,7 @@ CASINO_RELEASE_DAY = 1662825600
AJ_REPLACEMENTS = {
' your ': " you're ",
' to ': " too ",
' to ': " too ",
' Your ': " You're ",
' To ': " Too ",
@ -986,7 +986,7 @@ forced_hats = {
"earlylife": ("The Merchant", "SHUT IT DOWN, the goys know!"),
"marsify": ("Marsified", "I can't pick my own Marseys, help!"),
"is_suspended": ("Behind Bars", "This user is banned and needs to do better!"),
"agendaposter": (("Egg_irl", "This user is getting in touch with xir identity!"),
"agendaposter": (("Egg_irl", "This user is getting in touch with xir identity!"),
("Trans Flag", "Just in case you forgot, trans lives matter."),
("Trans Flag II", "Your egg is cracked; wear it with pride!"),
("Pride Flag", "Never forget that this is a primarily gay community. Dude bussy lmao."),

View File

@ -2,78 +2,78 @@ from copy import deepcopy
MODACTION_TYPES = {
'chud': {
"str": 'chudded {self.target_link}',
"icon": 'fa-snooze',
"str": 'chudded {self.target_link}',
"icon": 'fa-snooze',
"color": 'bg-danger'
},
'approve_app': {
"str": 'approved an application by {self.target_link}',
"icon": 'fa-robot',
"str": 'approved an application by {self.target_link}',
"icon": 'fa-robot',
"color": 'bg-success'
},
'badge_grant': {
"str": 'granted badge to {self.target_link}',
"icon": 'fa-badge',
"str": 'granted badge to {self.target_link}',
"icon": 'fa-badge',
"color": 'bg-success'
},
'badge_remove': {
"str": 'removed badge from {self.target_link}',
"icon": 'fa-badge',
"str": 'removed badge from {self.target_link}',
"icon": 'fa-badge',
"color": 'bg-danger'
},
'ban_comment': {
"str": 'removed {self.target_link}',
"icon": 'fa-comment',
"str": 'removed {self.target_link}',
"icon": 'fa-comment',
"color": 'bg-danger'
},
'ban_domain': {
"str": 'banned a domain',
"icon": 'fa-globe',
"str": 'banned a domain',
"icon": 'fa-globe',
"color": 'bg-danger'
},
'ban_post': {
"str": 'removed post {self.target_link}',
"icon": 'fa-feather-alt',
"str": 'removed post {self.target_link}',
"icon": 'fa-feather-alt',
"color": 'bg-danger'
},
'ban_user': {
"str": 'banned user {self.target_link}',
"icon": 'fa-user-slash',
"str": 'banned user {self.target_link}',
"icon": 'fa-user-slash',
"color": 'bg-danger'
},
'delete_report': {
"str": 'deleted report on {self.target_link}',
"icon": 'fa-flag',
"str": 'deleted report on {self.target_link}',
"icon": 'fa-flag',
"color": 'bg-danger'
},
'disable_bots': {
"str": 'disabled bots',
"icon": 'fa-robot',
"str": 'disabled bots',
"icon": 'fa-robot',
"color": 'bg-danger'
},
'disable_fart_mode': {
"str": 'disabled fart mode',
"icon": 'fa-gas-pump-slash',
"str": 'disabled fart mode',
"icon": 'fa-gas-pump-slash',
"color": 'bg-danger'
},
'disable_read_only_mode': {
"str": 'disabled read only mode',
"icon": 'fa-book',
"str": 'disabled read only mode',
"icon": 'fa-book',
"color": 'bg-danger'
},
'disable_signups': {
"str": 'disabled signups',
"icon": 'fa-users',
"str": 'disabled signups',
"icon": 'fa-users',
"color": 'bg-danger'
},
'disable_login_required': {
"str": 'disabled login required',
"icon": 'fa-users',
"str": 'disabled login required',
"icon": 'fa-users',
"color": 'bg-danger'
},
'disable_under_attack': {
"str": 'disabled under attack mode',
"icon": 'fa-shield',
"str": 'disabled under attack mode',
"icon": 'fa-shield',
"color": 'bg-muted'
},
'disable_under_siege': {
@ -82,58 +82,58 @@ MODACTION_TYPES = {
"color": 'bg-muted'
},
'distinguish_comment': {
"str": 'distinguished {self.target_link}',
"icon": 'fa-crown',
"str": 'distinguished {self.target_link}',
"icon": 'fa-crown',
"color": 'bg-success'
},
'distinguish_post': {
"str": 'distinguished {self.target_link}',
"icon": 'fa-crown',
"str": 'distinguished {self.target_link}',
"icon": 'fa-crown',
"color": 'bg-success'
},
'distribute': {
"str": 'distributed bet winnings to voters on {self.target_link}',
"icon": 'fa-dollar-sign',
"str": 'distributed bet winnings to voters on {self.target_link}',
"icon": 'fa-dollar-sign',
"color": 'bg-success'
},
'edit_post': {
"str": 'edited {self.target_link}',
"icon": 'fa-edit',
"str": 'edited {self.target_link}',
"icon": 'fa-edit',
"color": 'bg-primary'
},
'edit_rules': {
"str": 'edited the rules',
"icon": 'fa-columns',
"str": 'edited the rules',
"icon": 'fa-columns',
"color": 'bg-primary'
},
'enable_bots': {
"str": 'enabled bots',
"icon": 'fa-robot',
"str": 'enabled bots',
"icon": 'fa-robot',
"color": 'bg-success'
},
'enable_fart_mode': {
"str": 'enabled fart mode',
"icon": 'fa-gas-pump',
"str": 'enabled fart mode',
"icon": 'fa-gas-pump',
"color": 'bg-success'
},
'enable_read_only_mode': {
"str": 'enabled read only mode',
"icon": 'fa-book',
"str": 'enabled read only mode',
"icon": 'fa-book',
"color": 'bg-success'
},
'enable_signups': {
"str": 'enabled signups',
"icon": 'fa-users',
"str": 'enabled signups',
"icon": 'fa-users',
"color": 'bg-success'
},
'enable_login_required': {
"str": 'enabled login required',
"icon": 'fa-users',
"str": 'enabled login required',
"icon": 'fa-users',
"color": 'bg-success'
},
'enable_under_attack': {
"str": 'enabled under attack mode',
"icon": 'fa-shield',
"str": 'enabled under attack mode',
"icon": 'fa-shield',
"color": 'bg-success'
},
'enable_under_siege': {
@ -142,13 +142,13 @@ MODACTION_TYPES = {
"color": 'bg-success',
},
'flair_post': {
"str": 'set a flair on {self.target_link}',
"icon": 'fa-tag',
"str": 'set a flair on {self.target_link}',
"icon": 'fa-tag',
"color": 'bg-primary'
},
'link_accounts': {
"str": 'linked {self.target_link}',
"icon": 'fa-link',
"str": 'linked {self.target_link}',
"icon": 'fa-link',
"color": 'bg-success'
},
'delink_accounts': {
@ -157,8 +157,8 @@ MODACTION_TYPES = {
"color": 'bg-danger'
},
'make_admin': {
"str": 'made {self.target_link} an admin',
"icon": 'fa-user-crown',
"str": 'made {self.target_link} an admin',
"icon": 'fa-user-crown',
"color": 'bg-success'
},
'mod_mute_user': {
@ -172,169 +172,169 @@ MODACTION_TYPES = {
"color": 'bg-success'
},
'monthly': {
"str": 'distributed monthly marseybux',
"icon": 'fa-sack-dollar',
"str": 'distributed monthly marseybux',
"icon": 'fa-sack-dollar',
"color": 'bg-success'
},
'move_hole': {
"str": 'changed hole of {self.target_link}',
"icon": 'fa-manhole',
"str": 'changed hole of {self.target_link}',
"icon": 'fa-manhole',
"color": 'bg-primary'
},
'nuke_user': {
"str": 'removed all content of {self.target_link}',
"icon": 'fa-radiation-alt',
"str": 'removed all content of {self.target_link}',
"icon": 'fa-radiation-alt',
"color": 'bg-danger'
},
'pin_comment': {
"str": 'pinned {self.target_link}',
"icon": 'fa-thumbtack fa-rotate--45',
"str": 'pinned {self.target_link}',
"icon": 'fa-thumbtack fa-rotate--45',
"color": 'bg-success'
},
'pin_post': {
"str": 'pinned post {self.target_link}',
"icon": 'fa-thumbtack fa-rotate--45',
"str": 'pinned post {self.target_link}',
"icon": 'fa-thumbtack fa-rotate--45',
"color": 'bg-success'
},
'clear_cloudflare_cache': {
"str": 'cleared cloudflare cache',
"str": 'cleared cloudflare cache',
"icon": 'fab fa-cloudflare',
"color": 'bg-muted'
},
'reject_app': {
"str": 'rejected an application request by {self.target_link}',
"icon": 'fa-robot',
"str": 'rejected an application request by {self.target_link}',
"icon": 'fa-robot',
"color": 'bg-muted'
},
'remove_admin': {
"str": 'removed {self.target_link} as admin',
"icon": 'fa-user-crown',
"str": 'removed {self.target_link} as admin',
"icon": 'fa-user-crown',
"color": 'bg-danger'
},
'revert': {
"str": 'reverted {self.target_link} mod actions',
"icon": 'fa-history',
"str": 'reverted {self.target_link} mod actions',
"icon": 'fa-history',
"color": 'bg-danger'
},
'revoke_app': {
"str": 'revoked an application by {self.target_link}',
"icon": 'fa-robot',
"str": 'revoked an application by {self.target_link}',
"icon": 'fa-robot',
"color": 'bg-muted'
},
'set_flair_locked': {
"str": "set {self.target_link}'s flair (locked)",
"icon": 'fa-award',
"str": "set {self.target_link}'s flair (locked)",
"icon": 'fa-award',
"color": 'bg-primary'
},
'set_flair_notlocked': {
"str": "set {self.target_link}'s flair (not locked)",
"icon": 'fa-award',
"str": "set {self.target_link}'s flair (not locked)",
"icon": 'fa-award',
"color": 'bg-primary'
},
'set_new': {
"str": 'changed the default sorting of comments on {self.target_link} to `new`',
"icon": 'fa-sparkles',
"str": 'changed the default sorting of comments on {self.target_link} to `new`',
"icon": 'fa-sparkles',
"color": 'bg-primary'
},
'set_hot': {
"str": 'changed the default sorting of comments on {self.target_link} to `hot`',
"icon": 'fa-fire',
"str": 'changed the default sorting of comments on {self.target_link} to `hot`',
"icon": 'fa-fire',
"color": 'bg-primary'
},
'set_nsfw': {
"str": 'set {self.target_link} as +18',
"icon": 'fa-eye-evil',
"str": 'set {self.target_link} as +18',
"icon": 'fa-eye-evil',
"color": 'bg-danger'
},
'set_nsfw_comment': {
"str": 'set {self.target_link} as +18',
"icon": 'fa-eye-evil',
"str": 'set {self.target_link} as +18',
"icon": 'fa-eye-evil',
"color": 'bg-danger'
},
'shadowban': {
"str": 'shadowbanned {self.target_link}',
"icon": 'fa-eye-slash',
"str": 'shadowbanned {self.target_link}',
"icon": 'fa-eye-slash',
"color": 'bg-danger'
},
'unchud': {
"str": 'unchudded {self.target_link}',
"icon": 'fa-snooze',
"str": 'unchudded {self.target_link}',
"icon": 'fa-snooze',
"color": 'bg-success'
},
'unban_comment': {
"str": 'reinstated {self.target_link}',
"icon": 'fa-comment',
"str": 'reinstated {self.target_link}',
"icon": 'fa-comment',
"color": 'bg-success'
},
'unban_domain': {
"str": 'unbanned a domain',
"icon": 'fa-globe',
"str": 'unbanned a domain',
"icon": 'fa-globe',
"color": 'bg-success'
},
'unban_post': {
"str": 'reinstated post {self.target_link}',
"icon": 'fa-feather-alt',
"str": 'reinstated post {self.target_link}',
"icon": 'fa-feather-alt',
"color": 'bg-success'
},
'unban_user': {
"str": 'unbanned user {self.target_link}',
"icon": 'fa-user',
"str": 'unbanned user {self.target_link}',
"icon": 'fa-user',
"color": 'bg-success'
},
'undistinguish_comment': {
"str": 'un-distinguished {self.target_link}',
"icon": 'fa-crown',
"str": 'un-distinguished {self.target_link}',
"icon": 'fa-crown',
"color": 'bg-muted'
},
'undistinguish_post': {
"str": 'un-distinguished {self.target_link}',
"icon": 'fa-crown',
"str": 'un-distinguished {self.target_link}',
"icon": 'fa-crown',
"color": 'bg-muted'
},
'unnuke_user': {
"str": 'approved all content of {self.target_link}',
"icon": 'fa-radiation-alt',
"str": 'approved all content of {self.target_link}',
"icon": 'fa-radiation-alt',
"color": 'bg-success'
},
'unpin_comment': {
"str": 'unpinned {self.target_link}',
"icon": 'fa-thumbtack fa-rotate--45',
"str": 'unpinned {self.target_link}',
"icon": 'fa-thumbtack fa-rotate--45',
"color": 'bg-muted'
},
'unpin_post': {
"str": 'unpinned post {self.target_link}',
"icon": 'fa-thumbtack fa-rotate--45',
"str": 'unpinned post {self.target_link}',
"icon": 'fa-thumbtack fa-rotate--45',
"color": 'bg-muted'
},
'unset_nsfw': {
"str": 'unset {self.target_link} as +18',
"icon": 'fa-eye-evil',
"str": 'unset {self.target_link} as +18',
"icon": 'fa-eye-evil',
"color": 'bg-success'
},
'unset_nsfw_comment': {
"str": 'unset {self.target_link} as +18',
"icon": 'fa-eye-evil',
"str": 'unset {self.target_link} as +18',
"icon": 'fa-eye-evil',
"color": 'bg-success'
},
'unshadowban': {
"str": 'unshadowbanned {self.target_link}',
"icon": 'fa-eye',
"str": 'unshadowbanned {self.target_link}',
"icon": 'fa-eye',
"color": 'bg-success'
},
'update_hat': {
"str": 'updated hat image',
"icon": 'fa-hat-cowboy',
"str": 'updated hat image',
"icon": 'fa-hat-cowboy',
"color": 'bg-success'
},
'update_marsey': {
"str": 'updated marsey',
"icon": 'fa-cat',
"str": 'updated marsey',
"icon": 'fa-cat',
"color": 'bg-success'
},
}
MODACTION_PRIVILEGED_TYPES = {'shadowban', 'unshadowban',
MODACTION_PRIVILEGED_TYPES = {'shadowban', 'unshadowban',
'mod_mute_user', 'mod_unmute_user',
'link_accounts', 'delink_accounts'}
MODACTION_TYPES_FILTERED = deepcopy({t:v for t,v in MODACTION_TYPES.items()
MODACTION_TYPES_FILTERED = deepcopy({t:v for t,v in MODACTION_TYPES.items()
if not t in MODACTION_PRIVILEGED_TYPES})

View File

@ -1,52 +1,52 @@
SUBACTION_TYPES = {
'exile_user': {
"str": 'exiled user {self.target_link}',
"icon": 'fa-user-slash',
"str": 'exiled user {self.target_link}',
"icon": 'fa-user-slash',
"color": 'bg-danger'
},
'unexile_user': {
"str": 'unexiled user {self.target_link}',
"icon": 'fa-user',
"str": 'unexiled user {self.target_link}',
"icon": 'fa-user',
"color": 'bg-success'
},
'make_mod': {
"str": 'made {self.target_link} a mod',
"icon": 'fa-user-crown',
"str": 'made {self.target_link} a mod',
"icon": 'fa-user-crown',
"color": 'bg-success'
},
'remove_mod': {
"str": 'removed {self.target_link} as mod',
"icon": 'fa-user-crown',
"str": 'removed {self.target_link} as mod',
"icon": 'fa-user-crown',
"color": 'bg-danger'
},
'kick_post': {
"str": 'kicked post {self.target_link}',
"icon": 'fa-feather-alt',
"str": 'kicked post {self.target_link}',
"icon": 'fa-feather-alt',
"color": 'bg-danger'
},
'move_chudrama': {
"str": 'moved post {self.target_link} to <a href="/h/chudrama">/h/chudrama</a>',
"icon": 'fa-feather-alt',
"str": 'moved post {self.target_link} to <a href="/h/chudrama">/h/chudrama</a>',
"icon": 'fa-feather-alt',
"color": 'bg-danger'
},
'flair_post': {
"str": 'set a flair on {self.target_link}',
"icon": 'fa-tag',
"str": 'set a flair on {self.target_link}',
"icon": 'fa-tag',
"color": 'bg-primary'
},
'edit_sidebar': {
"str": 'edited the sidebar',
"icon": 'fa-columns',
"str": 'edited the sidebar',
"icon": 'fa-columns',
"color": 'bg-primary'
},
'edit_css': {
"str": 'edited the css',
"icon": 'fa-css3-alt',
"str": 'edited the css',
"icon": 'fa-css3-alt',
"color": 'bg-primary'
},
'upload_banner': {
"str": 'uploaded a banner',
"icon": 'fa-landscape',
"str": 'uploaded a banner',
"icon": 'fa-landscape',
"color": 'bg-primary'
},
'delete_banner': {
@ -55,63 +55,63 @@ SUBACTION_TYPES = {
"color": 'bg-danger',
},
'change_sidebar_image': {
"str": 'changed the sidebar image',
"icon": 'fa-image',
"str": 'changed the sidebar image',
"icon": 'fa-image',
"color": 'bg-primary'
},
'change_marsey': {
"str": 'changed the hole marsey',
"icon": 'fa-cat',
"str": 'changed the hole marsey',
"icon": 'fa-cat',
"color": 'bg-primary'
},
'pin_post': {
"str": 'pinned post {self.target_link}',
"icon": 'fa-thumbtack fa-rotate--45',
"str": 'pinned post {self.target_link}',
"icon": 'fa-thumbtack fa-rotate--45',
"color": 'bg-success'
},
'unpin_post': {
"str": 'unpinned post {self.target_link}',
"icon": 'fa-thumbtack fa-rotate--45',
"str": 'unpinned post {self.target_link}',
"icon": 'fa-thumbtack fa-rotate--45',
"color": 'bg-muted'
},
'pin_comment': {
"str": 'pinned {self.target_link}',
"icon": 'fa-thumbtack fa-rotate--45',
"str": 'pinned {self.target_link}',
"icon": 'fa-thumbtack fa-rotate--45',
"color": 'bg-success'
},
'unpin_comment': {
"str": 'unpinned {self.target_link}',
"icon": 'fa-thumbtack fa-rotate--45',
"str": 'unpinned {self.target_link}',
"icon": 'fa-thumbtack fa-rotate--45',
"color": 'bg-muted'
},
'enable_stealth': {
"str": 'enabled stealth mode',
"icon": 'fa-user-ninja',
"str": 'enabled stealth mode',
"icon": 'fa-user-ninja',
"color": 'bg-primary'
},
'disable_stealth': {
"str": 'disabled stealth mode',
"icon": 'fa-user-ninja',
"str": 'disabled stealth mode',
"icon": 'fa-user-ninja',
"color": 'bg-muted'
},
'set_nsfw': {
"str": 'set nsfw on post {self.target_link}',
"icon": 'fa-eye-evil',
"str": 'set nsfw on post {self.target_link}',
"icon": 'fa-eye-evil',
"color": 'bg-danger'
},
'unset_nsfw': {
"str": 'un-set nsfw on post {self.target_link}',
"icon": 'fa-eye-evil',
"str": 'un-set nsfw on post {self.target_link}',
"icon": 'fa-eye-evil',
"color": 'bg-success'
},
'set_nsfw_comment': {
"str": 'set nsfw on a {self.target_link}',
"icon": 'fa-eye-evil',
"str": 'set nsfw on a {self.target_link}',
"icon": 'fa-eye-evil',
"color": 'bg-danger'
},
'unset_nsfw_comment': {
"str": 'un-set nsfw on a {self.target_link}',
"icon": 'fa-eye-evil',
"str": 'un-set nsfw on a {self.target_link}',
"icon": 'fa-eye-evil',
"color": 'bg-success'
},
}

View File

@ -78,7 +78,7 @@ def get_users(usernames:Iterable[str], graceful=False) -> List[User]:
return users
def get_account(id:Union[str, int], v:Optional[User]=None, graceful=False, include_blocks=False, include_shadowbanned=True) -> Optional[User]:
try:
try:
id = int(id)
except:
if graceful: return None
@ -97,7 +97,7 @@ def get_account(id:Union[str, int], v:Optional[User]=None, graceful=False, inclu
def get_accounts_dict(ids:Union[Iterable[str], Iterable[int]], v:Optional[User]=None, graceful=False, include_shadowbanned=True) -> Optional[dict[int, User]]:
if not ids: return {}
try:
try:
ids = set([int(id) for id in ids])
except:
if graceful: return None
@ -132,15 +132,15 @@ def get_post(i:Union[str, int], v:Optional[User]=None, graceful=False) -> Option
post=post.filter(Submission.id == i
).outerjoin(
vt,
vt.c.submission_id == Submission.id,
vt,
vt.c.submission_id == Submission.id,
).outerjoin(
blocking,
blocking.c.target_id == Submission.author_id,
blocking,
blocking.c.target_id == Submission.author_id,
)
post=post.one_or_none()
if not post:
if graceful: return None
else: abort(404)
@ -163,7 +163,7 @@ def get_posts(pids:Iterable[int], v:Optional[User]=None, eager:bool=False, extra
if v:
vt = g.db.query(Vote.vote_type, Vote.submission_id).filter(
Vote.submission_id.in_(pids),
Vote.submission_id.in_(pids),
Vote.user_id==v.id
).subquery()
@ -180,11 +180,11 @@ def get_posts(pids:Iterable[int], v:Optional[User]=None, eager:bool=False, extra
).outerjoin(
vt, vt.c.submission_id==Submission.id
).outerjoin(
blocking,
blocking.c.target_id == Submission.author_id,
blocking,
blocking.c.target_id == Submission.author_id,
).outerjoin(
blocked,
blocked.c.user_id == Submission.author_id,
blocked,
blocked.c.user_id == Submission.author_id,
)
else:
query = g.db.query(Submission).filter(Submission.id.in_(pids))
@ -245,7 +245,7 @@ def add_block_props(target:Union[Submission, Comment, User], v:Optional[User]):
id = target.id
else:
raise TypeError("add_block_props only supports non-None submissions, comments, and users")
if hasattr(target, 'is_blocking') and hasattr(target, 'is_blocked'):
return target

View File

@ -57,7 +57,7 @@ def end_lottery_session():
chance_to_win = str(chance_to_win)[:3]
if user.id == winner:
notification_text = f'You won {active_lottery.prize} coins in the lottershe! ' \
+ f'Congratulations!\nYour odds of winning were: {chance_to_win}%'
+ f'Congratulations!\nYour odds of winning were: {chance_to_win}%'
else:
notification_text = f'You did not win the lottershe. Better luck next time!\n' \
+ f'Your odds of winning were: {chance_to_win}%\nWinner: @{winning_user.username} (won {active_lottery.prize} coins)'

View File

@ -16,8 +16,8 @@ from files.classes.notifications import Notification
# Note: while https://api.pushshift.io/meta provides the key
# server_ratelimit_per_minute, in practice Cloudflare puts stricter,
# unofficially documented limits at around 60/minute. We get nowhere near this
# with current keyword quantities. If this ever changes, consider reading the
# unofficially documented limits at around 60/minute. We get nowhere near this
# with current keyword quantities. If this ever changes, consider reading the
# value from /meta (or just guessing) and doing a random selection of keywords.
def offsite_mentions_task(cache:Cache):
@ -83,7 +83,7 @@ def get_mentions(cache:Cache, queries:Iterable[str], reddit_notifs_users=False):
'text': text,
})
try:
if not reddit_notifs_users:
if not reddit_notifs_users:
cache.set(const.REDDIT_NOTIFS_CACHE_KEY, after + 1)
except:
print("Failed to set cache value; there may be duplication of reddit notifications", flush=True)

View File

@ -150,7 +150,7 @@ def censor_slurs(body:Optional[str], logged_user):
def replace_re(body:str, regex:re.Pattern, regex_upper:re.Pattern, sub_func, sub_func_upper):
body = regex_upper.sub(sub_func_upper, body)
return regex.sub(sub_func, body)
if not logged_user or logged_user == 'chat' or logged_user.slurreplacer:
body = replace_re(body, slur_regex, slur_regex_upper, sub_matcher_slurs, sub_matcher_slurs_upper)
if SITE_NAME == 'rDrama':

View File

@ -10,7 +10,7 @@ from files.helpers.alerts import *
from files.helpers.get import get_account
class RouletteAction(str, Enum):
STRAIGHT_UP_BET = "STRAIGHT_UP_BET",
STRAIGHT_UP_BET = "STRAIGHT_UP_BET",
LINE_BET = "LINE_BET"
COLUMN_BET = "COLUMN_BET"
DOZEN_BET = "DOZEN_BET"

View File

@ -96,7 +96,7 @@ def allowed_attributes(tag, name, value):
if tag == 'table':
if name == 'class' and value == 'table': return True
return False
def build_url_re(tlds, protocols):

View File

@ -54,7 +54,7 @@ def casino_slot_pull(gambler, wager_value, currency):
return casino_game.id, casino_game.game_state
else:
return None, "{}",
return None, "{}",
def build_symbols(for_payout):
@ -132,7 +132,7 @@ def check_slots_command(c:Comment, v:User, u:User):
currency = 'coins'
else:
return
if u.rehab:
if v.id == u.id:
abort(403, "You are under Rehab award effect!")
@ -146,7 +146,7 @@ def check_slots_command(c:Comment, v:User, u:User):
abort(400, "Invalid wager.")
return
if wager < 100:
if wager < 100:
if v.id == u.id:
abort(400, f"Wager must be 100 {currency} or more")
return

View File

@ -38,25 +38,25 @@ def chart(kind, site):
day_cutoffs = [today_cutoff - 86400 * 7 * i for i in range(num_of_weeks)][1:]
day_cutoffs.insert(0, calendar.timegm(now))
daily_times = [time.strftime('%d/%m', time.gmtime(day_cutoffs[i + 1]))
daily_times = [time.strftime('%d/%m', time.gmtime(day_cutoffs[i + 1]))
for i in range(len(day_cutoffs) - 1)][::-1]
daily_signups = [g.db.query(User).filter(
User.created_utc < day_cutoffs[i],
User.created_utc > day_cutoffs[i + 1]).count()
User.created_utc < day_cutoffs[i],
User.created_utc > day_cutoffs[i + 1]).count()
for i in range(len(day_cutoffs) - 1)][::-1]
post_stats = [g.db.query(Submission).filter(
Submission.created_utc < day_cutoffs[i],
Submission.created_utc > day_cutoffs[i + 1],
Submission.is_banned == False).count()
Submission.created_utc < day_cutoffs[i],
Submission.created_utc > day_cutoffs[i + 1],
Submission.is_banned == False).count()
for i in range(len(day_cutoffs) - 1)][::-1]
comment_stats = [g.db.query(Comment).filter(
Comment.created_utc < day_cutoffs[i],
Comment.created_utc < day_cutoffs[i],
Comment.created_utc > day_cutoffs[i + 1],
Comment.is_banned == False,
Comment.author_id != AUTOJANNY_ID).count()
Comment.is_banned == False,
Comment.author_id != AUTOJANNY_ID).count()
for i in range(len(day_cutoffs) - 1)][::-1]
plt.rcParams['figure.figsize'] = (chart_width, 20)

View File

@ -83,7 +83,7 @@ def get_active_twentyone_game_state(gambler):
def charge_gambler(gambler, amount, currency):
charged = gambler.charge_account(currency, amount)
if not charged:
raise Exception("Gambler cannot afford charge.")
@ -244,7 +244,7 @@ def handle_payout(gambler, state, game):
raise Exception("Attempted to payout a game that has not finished.")
gambler.pay_account(game.currency, payout)
if game.currency == 'coins':
if status in {BlackjackStatus.BLACKJACK, BlackjackStatus.WON}:
distribute_wager_badges(gambler, game.wager, won=True)
@ -259,7 +259,7 @@ def handle_payout(gambler, state, game):
def remove_exploitable_information(state):
safe_state = state
if len(safe_state['dealer']) >= 2:
safe_state['dealer'][1] = '?'

View File

@ -51,7 +51,7 @@ def move_acc(v:User, new_id, old_id):
old_id = int(old_id)
new_id = int(new_id)
olduser = g.db.get(User, old_id)
newuser = g.db.get(User, new_id)
@ -307,7 +307,7 @@ def distribute(v:User, option_id):
losing_voters.extend([x.user_id for x in o.votes])
for uid in losing_voters:
add_notif(cid, uid)
ma = ModAction(
kind="distribute",
user_id=v.id,
@ -455,7 +455,7 @@ def admin_home(v):
if v.admin_level >= PERMS['SITE_SETTINGS_UNDER_ATTACK']:
under_attack = (get_security_level() or 'high') == 'under_attack'
return render_template("admin/admin_home.html", v=v,
return render_template("admin/admin_home.html", v=v,
under_attack=under_attack)
@app.post("/admin/site_settings/<setting>")
@ -575,7 +575,7 @@ def badge_grant_post(v):
if v.id != user.id:
text = f"@{v.username} (a site admin) has given you the following profile badge:\n\n![]({new_badge.path})\n\n**{new_badge.name}**\n\n{new_badge.badge.description}"
send_repeatable_notification(user.id, text)
ma = ModAction(
kind="badge_grant",
user_id=v.id,
@ -851,7 +851,7 @@ def admin_removed(v):
def admin_removed_comments(v):
try: page = int(request.values.get("page", 1))
except: page = 1
ids = g.db.query(Comment.id).join(Comment.author).filter(or_(Comment.is_banned==True, User.shadowbanned != None)).order_by(Comment.id.desc()).offset(PAGE_SIZE * (page - 1)).limit(PAGE_SIZE + 1).all()
ids=[x[0] for x in ids]
next_exists = len(ids) > PAGE_SIZE
@ -926,7 +926,7 @@ def shadowban(user_id, v):
_note=f'reason: "{reason}"'
)
g.db.add(ma)
cache.delete_memoized(frontlist)
return {"message": f"@{user.username} has been shadowbanned!"}
@ -951,7 +951,7 @@ def unshadowban(user_id, v):
target_user_id=user.id,
)
g.db.add(ma)
cache.delete_memoized(frontlist)
return {"message": f"@{user.username} has been unshadowbanned!"}
@ -982,7 +982,7 @@ def admin_title_change(user_id, v):
if user.flairchanged: kind = "set_flair_locked"
else: kind = "set_flair_notlocked"
ma=ModAction(
kind=kind,
user_id=v.id,
@ -1379,7 +1379,7 @@ def unsticky_post(post_id, v):
if post.stickied:
if FEATURES['AWARDS'] and post.stickied.endswith(PIN_AWARD_TEXT): abort(403, "Can't unpin award pins!")
if post.author_id == LAWLZ_ID and post.stickied_utc and SITE_NAME == 'rDrama': abort(403, "Can't unpin lawlzposts!")
post.stickied = None
post.stickied_utc = None
g.db.add(post)
@ -1424,13 +1424,13 @@ def sticky_comment(cid, v):
g.db.add(c)
return {"message": "Comment pinned!"}
@app.post("/unsticky_comment/<int:cid>")
@admin_level_required(PERMS['POST_COMMENT_MODERATION'])
def unsticky_comment(cid, v):
comment = get_comment(cid, v=v)
if comment.stickied:
if FEATURES['AWARDS'] and comment.stickied.endswith(PIN_AWARD_TEXT): abort(403, "Can't unpin award pins!")
@ -1481,7 +1481,7 @@ def remove_comment(c_id, v):
@admin_level_required(PERMS['POST_COMMENT_MODERATION'])
def approve_comment(c_id, v):
comment = get_comment(c_id)
if comment.author.id == v.id and comment.author.agendaposter and AGENDAPOSTER_PHRASE not in comment.body.lower() and not (comment.parent_submission and comment.post.sub == 'chudrama'):
abort(400, "You can't bypass the chud award!")
@ -1572,7 +1572,7 @@ def ban_domain(v):
def unban_domain(v:User, domain):
existing = g.db.get(BannedDomain, domain)
if not existing: abort(400, 'Domain is not banned!')
g.db.delete(existing)
ma = ModAction(
kind="unban_domain",
@ -1595,7 +1595,7 @@ def admin_nuke_user(v):
for post in g.db.query(Submission).filter_by(author_id=user.id).all():
if post.is_banned:
continue
post.is_banned = True
post.ban_reason = v.username
g.db.add(post)
@ -1628,7 +1628,7 @@ def admin_nunuke_user(v):
for post in g.db.query(Submission).filter_by(author_id=user.id).all():
if not post.is_banned:
continue
post.is_banned = False
post.ban_reason = None
post.is_approved = v.id

View File

@ -63,7 +63,7 @@ def after_request(response:Response):
if response.status_code < 400:
_set_cloudflare_cookie(response)
_commit_and_close_db()
return response
@ -82,7 +82,7 @@ def _set_cloudflare_cookie(response:Response) -> None:
if not logged_in and request.cookies.get("lo"):
response.delete_cookie("lo", domain=app.config["COOKIE_DOMAIN"], samesite="Lax")
elif logged_in and not request.cookies.get("lo"):
response.set_cookie("lo", CLOUDFLARE_COOKIE_VALUE if logged_in else '',
response.set_cookie("lo", CLOUDFLARE_COOKIE_VALUE if logged_in else '',
max_age=SESSION_LIFETIME, samesite="Lax",
domain=app.config["COOKIE_DOMAIN"])

View File

@ -371,7 +371,7 @@ def update_marsey(v):
return error("Image uploads are not allowed through TOR.")
if not file.content_type.startswith('image/'):
return error("You need to submit an image!")
for x in IMAGE_FORMATS:
if path.isfile(f'/asset_submissions/marseys/original/{name}.{x}'):
os.remove(f'/asset_submissions/marseys/original/{name}.{x}')
@ -387,7 +387,7 @@ def update_marsey(v):
copyfile(new_path, filename)
process_image(filename, v, resize=200, trim=True)
purge_files_in_cache([f"https://{SITE}/e/{name}.webp", f"https://{SITE}/assets/images/emojis/{name}.webp", f"https://{SITE}/asset_submissions/marseys/original/{name}.{format}"])
if tags and existing.tags != tags and tags != "none":
existing.tags = tags
g.db.add(existing)

View File

@ -103,7 +103,7 @@ def buy(v:User, award):
v.lootboxes_bought += 1
lootbox_msg = "You open your lootbox and receive: " + ', '.join(lootbox_items)
send_repeatable_notification(v.id, lootbox_msg)
if v.lootboxes_bought == 10:
badge_grant(badge_id=76, user=v)
elif v.lootboxes_bought == 50:
@ -131,16 +131,16 @@ def buy(v:User, award):
def award_thing(v, thing_type, id):
kind = request.values.get("kind", "").strip()
if thing_type == 'post':
if thing_type == 'post':
thing = get_post(id)
else:
else:
thing = get_comment(id)
if not thing.parent_submission and not thing.wall_user_id: abort(404) # don't let users award messages
if v.shadowbanned: abort(500)
author = thing.author
if author.shadowbanned: abort(404)
AWARDS = deepcopy(AWARDS_ENABLED)
if v.house:
AWARDS[v.house] = HOUSE_AWARDS[v.house]
@ -288,7 +288,7 @@ def award_thing(v, thing_type, id):
if author.agendaposter and time.time() < author.agendaposter: author.agendaposter += 86400
else: author.agendaposter = int(time.time()) + 86400
badge_grant(user=author, badge_id=28)
elif kind == "flairlock":
new_name = note[:100].replace("𒐪","").replace("","").strip()
@ -375,10 +375,10 @@ def award_thing(v, thing_type, id):
elif "Vampire" in kind and kind == v.house:
if author.bite: author.bite += 172800
else: author.bite = int(time.time()) + 172800
if not author.old_house:
author.old_house = author.house
if 'Vampire' not in author.house:
author.house = 'Vampire'

View File

@ -54,7 +54,7 @@ def casino_game_page(v:User, game):
@limiter.limit("100/minute;2000/hour;12000/day")
@auth_required
def casino_game_feed(v:User, game):
if v.rehab:
if v.rehab:
abort(403, "You are under Rehab award effect!")
elif game not in CASINO_GAME_KINDS:
abort(404)

View File

@ -83,7 +83,7 @@ def speak(data, v):
"text_censored": censor_slurs(text_html, 'chat'),
"time": int(time.time()),
}
if v.shadowbanned or not execute_blackjack(v, None, text, "chat"):
emit('speak', data)
elif recipient:

View File

@ -43,7 +43,7 @@ def post_pid_comment_cid(cid, pid=None, anything=None, v=None, sub=None):
g.db.commit()
post = comment.post
if post.over_18 and not (v and v.over_18) and not session.get('over_18', 0) >= int(time.time()):
if v and v.client: abort(403, "This content is not suitable for some users and situations.")
else: return render_template("errors/nsfw.html", v=v), 403
@ -70,9 +70,9 @@ def post_pid_comment_cid(cid, pid=None, anything=None, v=None, sub=None):
execute_shadowban_viewers_and_voters(v, post)
execute_shadowban_viewers_and_voters(v, comment)
if v and v.client: return top_comment.json(db=g.db)
else:
else:
if post.is_banned and not (v and (v.admin_level >= PERMS['POST_COMMENT_MODERATION'] or post.author_id == v.id)): template = "submission_banned.html"
else: template = "submission.html"
return render_template(template, v=v, p=post, sort=sort, comment_info=comment_info, render_replies=True, sub=post.subr)
@ -107,7 +107,7 @@ def comment(v:User):
post_target = get_post(parent.parent_submission, v=v, graceful=True) or get_account(parent.wall_user_id, v=v, include_blocks=True, include_shadowbanned=False)
parent_comment_id = parent.id
if parent.author_id == v.id: rts = True
if not v.can_post_in_ghost_threads and isinstance(post_target, Submission) and post_target.ghost:
if not v.can_post_in_ghost_threads and isinstance(post_target, Submission) and post_target.ghost:
abort(403, f"You need {TRUESCORE_GHOST_MINIMUM} truescore to post in ghost threads")
ghost = parent.ghost
else: abort(404)
@ -200,7 +200,7 @@ def comment(v:User):
abort(415)
body = body.strip()[:COMMENT_BODY_LENGTH_LIMIT]
if v.admin_level >= PERMS['SITE_SETTINGS_SNAPPY_QUOTES'] and posting_to_submission and post_target.id == SNAPPY_THREAD and level == 1:
with open(f"snappy_{SITE_NAME}.txt", "a", encoding="utf-8") as f:
f.write('\n{[para]}\n' + body)
@ -297,7 +297,7 @@ def comment(v:User):
for x in subscribers:
notify_users.add(x[0])
if parent_user.id != v.id:
notify_users.add(parent_user.id)
@ -422,9 +422,9 @@ def edit_comment(cid, v):
if int(time.time()) - c.created_utc > 60 * 3: c.edited_utc = int(time.time())
g.db.add(c)
notify_users = NOTIFY_USERS(body, v)
for x in notify_users-bots:
notif = g.db.query(Notification).filter_by(comment_id=c.id, user_id=x).one_or_none()
if not notif:
@ -481,12 +481,12 @@ def undelete_comment(cid, v):
@feature_required('PINS')
@auth_required
def pin_comment(cid, v):
comment = get_comment(cid, v=v)
if not comment.stickied:
if v.id != comment.post.author_id: abort(403)
if comment.post.ghost: comment.stickied = "(OP)"
else: comment.stickied = v.username + " (OP)"
@ -498,18 +498,18 @@ def pin_comment(cid, v):
send_repeatable_notification(comment.author_id, message)
return {"message": "Comment pinned!"}
@app.post("/unpin_comment/<int:cid>")
@auth_required
def unpin_comment(cid, v):
comment = get_comment(cid, v=v)
if comment.stickied:
if v.id != comment.post.author_id: abort(403)
if not comment.stickied.endswith(" (OP)"):
if not comment.stickied.endswith(" (OP)"):
abort(403, "You can only unpin comments you have pinned!")
comment.stickied = None
@ -602,7 +602,7 @@ def handle_wordle_action(cid, v):
comment.wordle_result = f'{guesses}_{status}_{answer}'
g.db.add(comment)
return {"response" : comment.wordle_html(v)}
@ -613,7 +613,7 @@ def toggle_comment_nsfw(cid, v):
if comment.author_id != v.id and not v.admin_level >= PERMS['POST_COMMENT_MODERATION'] and not (comment.post.sub and v.mods(comment.post.sub)):
abort(403)
if comment.over_18 and v.is_suspended_permanently:
abort(403)

View File

@ -22,7 +22,7 @@ def feeds_user(sort='hot', t='all'):
t=t,
v=None,
)
posts = get_posts(ids)
doc, tag, text = Doc().tagtext()
@ -54,7 +54,7 @@ def feeds_user(sort='hot', t='all'):
with tag("published"):
text(datetime.datetime.utcfromtimestamp(post.created_utc).isoformat()+"Z")
with tag("author"):
with tag("name"):
text(post.author_name)

View File

@ -35,7 +35,7 @@ def front_all(v, sub=None, subdomain=None):
sub = get_sub_by_name(sub, graceful=True)
if sub and not User.can_see(v, sub):
abort(403)
if (request.path.startswith('/h/') or request.path.startswith('/s/')) and not sub: abort(404)
try: page = max(int(request.values.get("page", 1)), 1)
@ -52,7 +52,7 @@ def front_all(v, sub=None, subdomain=None):
sort=request.values.get("sort", defaultsorting)
t=request.values.get('t', defaulttime)
try: gt=int(request.values.get("after", 0))
except: gt=0
@ -79,7 +79,7 @@ def front_all(v, sub=None, subdomain=None):
)
posts = get_posts(ids, v=v, eager=True)
if v:
if v.hidevotedon: posts = [x for x in posts if not hasattr(x, 'voted') or not x.voted]
award_timers(v)
@ -91,7 +91,7 @@ def front_all(v, sub=None, subdomain=None):
@cache.memoize(timeout=86400)
def frontlist(v=None, sort="hot", page=1, t="all", ids_only=True, filter_words='', gt=0, lt=0, sub=None, site=None, pins=True, holes=True):
posts = g.db.query(Submission)
if v and v.hidevotedon:
posts = posts.outerjoin(Vote,
and_(Vote.submission_id == Submission.id, Vote.user_id == v.id)
@ -148,7 +148,7 @@ def frontlist(v=None, sort="hot", page=1, t="all", ids_only=True, filter_words='
pins = g.db.query(Submission).filter(Submission.sub == sub.name, Submission.hole_pinned != None)
else:
pins = g.db.query(Submission).filter(Submission.stickied != None, Submission.is_banned == False)
if v:
pins = pins.filter(or_(Submission.sub == None, Submission.sub.notin_(v.all_blocks)))
for pin in pins:
@ -184,7 +184,7 @@ def random_post(v:User):
@auth_required
def random_user(v:User):
u = g.db.query(User.username).filter(User.song != None, User.shadowbanned == None).order_by(func.random()).first()
if u: u = u[0]
else: abort(404, "No users have set a profile anthem so far!")

View File

@ -63,14 +63,14 @@ def calc_users():
ua = str(user_agents.parse(g.agent))
if 'spider' not in ua.lower() and 'bot' not in ua.lower():
loggedout[session["session_id"]] = (timestamp, ua)
loggedin = {k: v for k, v in loggedin.items() if (timestamp - v) < LOGGEDIN_ACTIVE_TIME}
loggedout = {k: v for k, v in loggedout.items() if (timestamp - v[0]) < LOGGEDIN_ACTIVE_TIME}
cache.set(LOGGED_IN_CACHE_KEY, loggedin)
cache.set(LOGGED_OUT_CACHE_KEY, loggedout)
loggedin_counter = len(loggedin)
loggedout_counter = len(loggedout)
return {'loggedin_counter':loggedin_counter,
return {'loggedin_counter':loggedin_counter,
'loggedout_counter':loggedout_counter,
'loggedin_chat':loggedin_chat}
@ -82,7 +82,7 @@ def inject_constants():
return {"environ":environ, "SITE":SITE, "SITE_NAME":SITE_NAME, "SITE_FULL":SITE_FULL,
"AUTOJANNY_ID":AUTOJANNY_ID, "MODMAIL_ID":MODMAIL_ID, "VAPID_PUBLIC_KEY":VAPID_PUBLIC_KEY,
"listdir":listdir, "os_path":path, "AEVANN_ID":AEVANN_ID,
"PIZZASHILL_ID":PIZZASHILL_ID, "DEFAULT_COLOR":DEFAULT_COLOR,
"PIZZASHILL_ID":PIZZASHILL_ID, "DEFAULT_COLOR":DEFAULT_COLOR,
"COLORS":COLORS, "time":time, "PERMS":PERMS, "FEATURES":FEATURES,
"HOLE_NAME":HOLE_NAME, "HOLE_STYLE_FLAIR":HOLE_STYLE_FLAIR, "HOLE_REQUIRED":HOLE_REQUIRED,
"GUMROAD_LINK":GUMROAD_LINK, "DEFAULT_THEME":DEFAULT_THEME, "DESCRIPTION":DESCRIPTION,
@ -95,9 +95,9 @@ def inject_constants():
"site_settings":get_settings(), "EMAIL":EMAIL, "max": max, "min": min, "user_can_see":User.can_see,
"TELEGRAM_ID":TELEGRAM_ID, "EMAIL_REGEX_PATTERN":EMAIL_REGEX_PATTERN,
"TRUESCORE_DONATE_MINIMUM":TRUESCORE_DONATE_MINIMUM,
"DONATE_LINK":DONATE_LINK, "DONATE_SERVICE":DONATE_SERVICE, "BAN_EVASION_DOMAIN":BAN_EVASION_DOMAIN,
"DONATE_LINK":DONATE_LINK, "DONATE_SERVICE":DONATE_SERVICE, "BAN_EVASION_DOMAIN":BAN_EVASION_DOMAIN,
"HOUSE_JOIN_COST":HOUSE_JOIN_COST, "HOUSE_SWITCH_COST":HOUSE_SWITCH_COST, "IMAGE_FORMATS":','.join(IMAGE_FORMATS),
"PAGE_SIZES":PAGE_SIZES, "THEMES":THEMES, "COMMENT_SORTS":COMMENT_SORTS, "SORTS":SORTS,
"TIME_FILTERS":TIME_FILTERS, "HOUSES":HOUSES, "TIERS_ID_TO_NAME":TIERS_ID_TO_NAME,
"PAGE_SIZES":PAGE_SIZES, "THEMES":THEMES, "COMMENT_SORTS":COMMENT_SORTS, "SORTS":SORTS,
"TIME_FILTERS":TIME_FILTERS, "HOUSES":HOUSES, "TIERS_ID_TO_NAME":TIERS_ID_TO_NAME,
"DEFAULT_CONFIG_VALUE":DEFAULT_CONFIG_VALUE, "IS_LOCALHOST":IS_LOCALHOST, "BACKGROUND_CATEGORIES":BACKGROUND_CATEGORIES, "PAGE_SIZE":PAGE_SIZE, "TAGLINES":TAGLINES, "IS_FISTMAS":IS_FISTMAS, "get_alt_graph":get_alt_graph, "current_registered_users":current_registered_users
}

View File

@ -346,7 +346,7 @@ def sign_up_post(v:Optional[User]):
check_for_alts(new_user)
send_notification(new_user.id, WELCOME_MSG)
if SIGNUP_FOLLOW_ID:
signup_autofollow = get_account(SIGNUP_FOLLOW_ID)
new_follow = Follow(user_id=new_user.id, target_id=signup_autofollow.id)
@ -502,7 +502,7 @@ def request_2fa_disable():
token=generate_hash(f"{user.id}+{user.username}+disable2fa+{valid}+{user.mfa_secret}+{user.login_nonce}")
action_url=f"{SITE_FULL}/reset_2fa?id={user.id}&t={valid}&token={token}"
send_mail(to_address=user.email,
subject="2FA Removal Request",
html=render_template("email/2fa_remove.html",

View File

@ -329,7 +329,7 @@ def notifications(v:User):
total.extend(c.replies2)
if c not in listing: listing.append(c)
total.extend(listing)
total_cids = [x.id for x in total]

View File

@ -97,7 +97,7 @@ def delete_oauth_app(v, aid):
abort(404)
app = g.db.get(OauthApp, aid)
if not app: abort(404)
if app.author_id != v.id: abort(403)
for auth in g.db.query(ClientAuth).filter_by(oauth_client=app.id).all():

View File

@ -22,7 +22,7 @@ def vote_option(option_id, v):
if option.exclusive == 2:
if option.post.total_bet_voted(v):
abort(403, "You can't bet on a closed poll!")
if not v.charge_account('coins', POLL_BET_COINS):
if not v.charge_account('coins', POLL_BET_COINS):
abort(400, f"You don't have {POLL_BET_COINS} coins!")
g.db.add(v)
autojanny = get_account(AUTOJANNY_ID)

View File

@ -45,7 +45,7 @@ def publish(pid, v):
post.private = False
post.created_utc = int(time.time())
g.db.add(post)
if not post.ghost:
notify_users = NOTIFY_USERS(f'{post.title} {post.body}', v)
@ -189,7 +189,7 @@ def view_more(v, pid, sort, offset):
except: abort(400)
try: ids = set(int(x) for x in request.values.get("ids").split(','))
except: abort(400)
if v:
# shadowban check is done in sort_objects
# output is needed: see comments.py
@ -209,7 +209,7 @@ def view_more(v, pid, sort, offset):
comments = sort_objects(sort, comments, Comment,
include_shadowbanned=False)
comments = comments.offset(offset).all()
comments2 = []
@ -226,7 +226,7 @@ def view_more(v, pid, sort, offset):
ids.add(comment.id)
count += g.db.query(Comment).filter_by(parent_submission=post.id, parent_comment_id=comment.id).count() + 1
if count > 20: break
if len(comments) == len(comments2): offset = 0
else: offset += 1
comments = comments2
@ -255,7 +255,7 @@ def more_comments(v, cid):
if comments: p = comments[0].post
else: p = None
return render_template("comments.html", v=v, comments=comments, p=p, render_replies=True)
@app.post("/edit_post/<int:pid>")
@ -320,7 +320,7 @@ def edit_post(pid, v):
for text in [p.body, p.title, p.url]:
if not execute_blackjack(v, p, text, 'submission'): break
if len(body_html) > POST_BODY_HTML_LENGTH_LIMIT:
if len(body_html) > POST_BODY_HTML_LENGTH_LIMIT:
abort(400, f"Submission body_html too long!")
p.body_html = body_html
@ -367,13 +367,13 @@ def thumbnail_thread(pid:int, vid:int):
return f"{post_url}/{fragment_url}"
post = db.get(Submission, pid)
if not post or not post.url:
time.sleep(5)
post = db.get(Submission, pid)
if not post or not post.url: return
fetch_url = post.url
if fetch_url.startswith('/') and '\\' not in fetch_url:
@ -404,12 +404,12 @@ def thumbnail_thread(pid:int, vid:int):
]
for tag_name in meta_tags:
tag = soup.find(
'meta',
'meta',
attrs={
"name": tag_name,
"name": tag_name,
"content": True
}
)
@ -510,7 +510,7 @@ def is_repost():
params=parsed_url.params,
query=urlencode(filtered, doseq=True),
fragment=parsed_url.fragment)
url = urlunparse(new_url)
url = url.rstrip('/')
@ -539,7 +539,7 @@ def submit_post(v:User, sub=None):
def error(error):
if g.is_api_or_xhr: abort(400, error)
SUBS = [x[0] for x in g.db.query(Sub.name).order_by(Sub.name).all()]
return render_template("submit.html", SUBS=SUBS, v=v, error=error, title=title, url=url, body=body), 400
@ -555,7 +555,7 @@ def submit_post(v:User, sub=None):
title_html = filter_emojis_only(title, graceful=True, count_marseys=True, torture=torture)
if v.marseyawarded and not marseyaward_title_regex.fullmatch(title_html):
return error("You can only type marseys!")
if len(title_html) > POST_TITLE_HTML_LENGTH_LIMIT:
if len(title_html) > POST_TITLE_HTML_LENGTH_LIMIT:
return error("Rendered title is too big!")
if sub == 'changelog' and not v.admin_level >= PERMS['POST_TO_CHANGELOG']:
@ -610,7 +610,7 @@ def submit_post(v:User, sub=None):
params=parsed_url.params,
query=urlencode(filtered, doseq=True),
fragment=parsed_url.fragment)
url = urlunparse(new_url)
url = url.rstrip('/')
@ -660,7 +660,7 @@ def submit_post(v:User, sub=None):
if not url and not body and not request.files.get("file") and not request.files.get("file-url"):
return error("Please enter a url or some text.")
if not IS_LOCALHOST:
if not IS_LOCALHOST:
dup = g.db.query(Submission).filter(
Submission.author_id == v.id,
Submission.deleted_utc == 0,
@ -738,7 +738,7 @@ def submit_post(v:User, sub=None):
submission_id=post.id
)
g.db.add(vote)
if request.files.get('file-url') and not g.is_tor:
file = request.files['file-url']
@ -761,7 +761,7 @@ def submit_post(v:User, sub=None):
post.url = process_audio(file, v)
else:
abort(415)
if not post.thumburl and post.url:
gevent.spawn(thumbnail_thread, post.id, v.id)
@ -889,7 +889,7 @@ def mark_post_nsfw(pid, v):
if post.author_id != v.id and not v.admin_level >= PERMS['POST_COMMENT_MODERATION'] and not (post.sub and v.mods(post.sub)):
abort(403)
if post.over_18 and v.is_suspended_permanently:
abort(403)
@ -923,7 +923,7 @@ def unmark_post_nsfw(pid, v):
if post.author_id != v.id and not v.admin_level >= PERMS['POST_COMMENT_MODERATION'] and not (post.sub and v.mods(post.sub)):
abort(403)
if post.over_18 and v.is_suspended_permanently:
abort(403)
@ -1056,7 +1056,7 @@ def get_post_title(v):
try:
x = gevent.with_timeout(POST_TITLE_TIMEOUT, requests.get, url, headers=titleheaders, timeout=POST_TITLE_TIMEOUT, proxies=proxies)
except: abort(400)
content_type = x.headers.get("Content-Type")
if not content_type or "text/html" not in content_type: abort(400)

View File

@ -19,5 +19,5 @@ def push_subscribe(v):
subscription_json=subscription_json,
)
g.db.add(subscription)
return ''

View File

@ -58,7 +58,7 @@ def flag_post(pid, v):
moved = move_post(post, v, reason)
if moved: return {"message": moved}
existing = g.db.query(Flag.post_id).filter_by(user_id=v.id, post_id=post.id).one_or_none()
if existing: abort(409, "You already reported this post!")
flag = Flag(post_id=post.id, user_id=v.id, reason=reason)
@ -74,7 +74,7 @@ def flag_post(pid, v):
def flag_comment(cid, v):
comment = get_comment(cid)
existing = g.db.query(CommentFlag.comment_id).filter_by(user_id=v.id, comment_id=comment.id).one_or_none()
if existing: abort(409, "You already reported this comment!")
@ -125,7 +125,7 @@ def remove_report_comment(v, cid, uid):
uid = int(uid)
except: abort(404)
report = g.db.query(CommentFlag).filter_by(comment_id=cid, user_id=uid).one_or_none()
if report:
g.db.delete(report)
@ -143,7 +143,7 @@ def move_post(post:Submission, v:User, reason:str) -> Union[bool, str]:
sub_from = post.sub
sub_to = get_sub_by_name(reason, graceful=True)
sub_to = sub_to.name if sub_to else None
can_move_post = v.admin_level >= PERMS['POST_COMMENT_MODERATION'] or (post.sub and v.mods(sub_from))
if sub_from != 'chudrama': # posts can only be moved out of /h/chudrama by admins
can_move_post = can_move_post or post.author_id == v.id
@ -158,7 +158,7 @@ def move_post(post:Submission, v:User, reason:str) -> Union[bool, str]:
abort(403, f"You need to be a member of House {sub_to.capitalize()} to post in /h/{sub_to}")
else:
abort(403, f"@{post.author.username} needs to be a member of House {sub_to.capitalize()} for their post to be moved to /h/{sub_to}")
post.sub = sub_to
post.hole_pinned = None
g.db.add(post)

View File

@ -41,7 +41,7 @@ def get_alt_graph_ids(uid:int) -> List[int]:
).select_from(Alt, alt_graph_cte).filter(
or_(alt_graph_cte.c.user_id == Alt.user1, alt_graph_cte.c.user_id == Alt.user2)
)
alt_graph_cte = alt_graph_cte.union(alt_graph_cte_inner)
return set([x[0] for x in g.db.query(User.id).filter(User.id == alt_graph_cte.c.user_id, User.id != uid).all()])
@ -86,7 +86,7 @@ def check_for_alts(current:User, include_current_session=True):
if a.user1 != current_id: add_alt(a.user1, current_id)
if a.user2 != past_id: add_alt(a.user2, past_id)
if a.user2 != current_id: add_alt(a.user2, current_id)
past_accs.add(current_id)
if include_current_session:
session["history"] = list(past_accs)
@ -110,7 +110,7 @@ def execute_shadowban_viewers_and_voters(v:Optional[User], target:Union[Submissi
max_upvotes = min(ti, 13)
rand = randint(0, max_upvotes)
if target.upvotes >= rand: return
amount = randint(0, 3)
if amount != 1: return

View File

@ -59,13 +59,13 @@ def searchposts(v:User):
posts = g.db.query(Submission.id) \
.join(Submission.author) \
.filter(Submission.author_id.notin_(v.userblocks))
if v.admin_level < PERMS['POST_COMMENT_MODERATION']:
posts = posts.filter(
Submission.deleted_utc == 0,
Submission.is_banned == False,
Submission.private == False)
if 'author' in criteria:
posts = posts.filter(Submission.ghost == False)
author = get_user(criteria['author'], v=v, include_shadowbanned=False)
@ -95,7 +95,7 @@ def searchposts(v:User):
words = [or_(Submission.title.ilike('%'+x+'%'), Submission.body.ilike('%'+x+'%')) \
for x in criteria['q']]
posts = posts.filter(*words)
if 'over18' in criteria: posts = posts.filter(Submission.over_18==True)
if 'domain' in criteria:
@ -187,7 +187,7 @@ def searchcomments(v:User):
Comment.author_id.notin_(v.userblocks),
)
if 'post' in criteria:
try: post = int(criteria['post'])
except: abort(404)
@ -282,21 +282,21 @@ def searchusers(v:User):
t = request.values.get('t', 'all').lower()
term=query.lstrip('@')
term = term.replace('\\','').replace('_','\_').replace('%','')
users=g.db.query(User).filter(
or_(
User.username.ilike(f'%{term}%'),
User.original_username.ilike(f'%{term}%')
)
)
if v.admin_level < PERMS['USER_SHADOWBAN']:
users = users.filter(User.shadowbanned == None)
users=users.order_by(User.username.ilike(term).desc(), User.stored_subscriber_count.desc())
total=users.count()
users = users.offset(PAGE_SIZE * (page-1)).limit(PAGE_SIZE+1).all()
next_exists=(len(users)>PAGE_SIZE)
users=users[:PAGE_SIZE]

View File

@ -111,7 +111,7 @@ def settings_personal_post(v):
updated = False
# begin common selectors #
def update_flag(column_name:str, request_name:str):
if not request.values.get(request_name, ''): return False
request_flag = request.values.get(request_name, '') == 'true'
@ -119,7 +119,7 @@ def settings_personal_post(v):
setattr(v, column_name, request_flag)
return True
return False
def update_potentially_permanent_flag(column_name:str, request_name:str, friendly_name:str, badge_id:Optional[int]):
if not request.values.get(request_name): return False
current_value = getattr(v, column_name)
@ -161,14 +161,14 @@ def settings_personal_post(v):
updated = True
v.poor = request.values.get("poor", v.poor) == 'true'
session['poor'] = v.poor
slur_filter_updated = updated or update_potentially_permanent_flag("slurreplacer", "slurreplacer", "slur replacer", 192)
if isinstance(slur_filter_updated, bool):
updated = slur_filter_updated
else:
g.db.add(v)
return slur_filter_updated
profanity_filter_updated = updated or update_potentially_permanent_flag("profanityreplacer", "profanityreplacer", "profanity replacer", 190)
if isinstance(profanity_filter_updated, bool):
updated = profanity_filter_updated
@ -191,7 +191,7 @@ def settings_personal_post(v):
updated = True
v.spider = int(request.values.get("spider") == 'true')
if v.spider: badge_grant(user=v, badge_id=179)
else:
else:
badge = v.has_badge(179)
if badge: g.db.delete(badge)
@ -317,7 +317,7 @@ def settings_personal_post(v):
updated = True
cache.delete_memoized(frontlist)
else: abort(400)
updated = updated or set_selector_option("defaultsortingcomments", "defaultsortingcomments", COMMENT_SORTS, "comment sort")
updated = updated or set_selector_option("defaultsorting", "defaultsorting", SORTS, "post sort")
updated = updated or set_selector_option("defaulttime", "defaulttime", TIME_FILTERS, "time filter")
@ -337,7 +337,7 @@ def settings_personal_post(v):
if v.house:
if v.house.replace(' Founder', '') == house: abort(409, f"You're already in House {house}")
cost = HOUSE_SWITCH_COST
else:
else:
cost = HOUSE_JOIN_COST
success = v.charge_account('coins', cost)
@ -345,7 +345,7 @@ def settings_personal_post(v):
success = v.charge_account('marseybux', cost)
if not success: abort(403)
if house == "None": house = ''
if house == "None": house = ''
v.house = house
updated = True
@ -389,7 +389,7 @@ def set_color(v:User, attr:str, color:Optional[str]):
@auth_required
def namecolor(v):
return set_color(v, "namecolor", request.values.get("namecolor"))
@app.post("/settings/themecolor")
@limiter.limit(DEFAULT_RATELIMIT_SLOWER)
@limiter.limit(DEFAULT_RATELIMIT_SLOWER, key_func=lambda:f'{request.host}-{session.get("lo_user")}')
@ -430,7 +430,7 @@ def gumroad(v):
g.db.add(v)
badge_grant(badge_id=20+tier, user=v)
return {"message": f"{patron} rewards claimed!"}
@ -640,7 +640,7 @@ def settings_security(v:User):
def settings_block_user(v):
user = get_user(request.values.get("username"), graceful=True)
if not user: abort(404, "This user doesn't exist.")
if user.unblockable:
if not v.shadowbanned:
send_notification(user.id, f"@{v.username} has tried to block you and failed because of your unblockable status!")
@ -778,12 +778,12 @@ def settings_song_change(v):
if not yt_id_regex.fullmatch(id):
return render_template("settings/personal.html", v=v, error="Not a YouTube link"), 400
if path.isfile(f'/songs/{id}.mp3'):
if path.isfile(f'/songs/{id}.mp3'):
v.song = id
g.db.add(v)
return render_template("settings/personal.html", v=v, msg="Profile Anthem successfully updated!")
req = requests.get(f"https://www.googleapis.com/youtube/v3/videos?id={id}&key={YOUTUBE_KEY}&part=contentDetails", timeout=5).json()
duration = req['items'][0]['contentDetails']['duration']
if duration == 'P0D':
@ -794,7 +794,7 @@ def settings_song_change(v):
if "M" in duration:
duration = int(duration.split("PT")[1].split("M")[0])
if duration > 15:
if duration > 15:
return render_template("settings/personal.html", v=v, error="Duration of the video must not exceed 15 minutes."), 400
@ -835,7 +835,7 @@ def settings_song_change(v):
@auth_required
def settings_title_change(v):
if v.flairchanged: abort(403)
customtitleplain = sanitize_settings_text(request.values.get("title"), 100)
if len(customtitleplain) > 100:

View File

@ -142,7 +142,7 @@ def log(v:User):
actions = []
else:
actions = g.db.query(ModAction)
if not (v and v.admin_level >= PERMS['USER_SHADOWBAN']):
if not (v and v.admin_level >= PERMS['USER_SHADOWBAN']):
actions = actions.filter(ModAction.kind.notin_(MODACTION_PRIVILEGED_TYPES))
if admin_id:
@ -156,7 +156,7 @@ def log(v:User):
if kind: actions = actions.filter_by(kind=kind)
actions = actions.order_by(ModAction.id.desc()).offset(PAGE_SIZE*(page-1)).limit(PAGE_SIZE+1).all()
next_exists=len(actions) > PAGE_SIZE
actions=actions[:PAGE_SIZE]
admins = [x[0] for x in g.db.query(User.username).filter(User.admin_level >= PERMS['ADMIN_MOP_VISIBLE']).order_by(User.username).all()]
@ -228,7 +228,7 @@ def submit_contact(v):
execute_blackjack(v, new_comment, new_comment.body_html, 'modmail')
execute_under_siege(v, new_comment, new_comment.body_html, 'modmail')
new_comment.top_comment_id = new_comment.id
admins = g.db.query(User).filter(User.admin_level >= PERMS['NOTIFICATIONS_MODMAIL'], User.id != AEVANN_ID)
for admin in admins.all():
@ -254,7 +254,7 @@ def badge_list(site):
counts = {}
for c in counts_raw:
counts[c[0]] = (c[1], float(c[1]) * 100 / max(users, 1))
return badges, counts
@app.get("/badges")

View File

@ -37,7 +37,7 @@ def exile_post(v:User, pid):
_note=f'for <a href="{p.permalink}">{p.title_html}</a>'
)
g.db.add(ma)
return {"message": f"@{u.username} has been exiled from /h/{sub} successfully!"}
@app.post("/exile/comment/<int:cid>")
@ -92,11 +92,11 @@ def unexile(v:User, sub, uid):
target_user_id=u.id
)
g.db.add(ma)
if g.is_api_or_xhr:
return {"message": f"@{u.username} has been unexiled from /h/{sub} successfully!"}
return redirect(f'/h/{sub}/exilees')
@app.post("/h/<sub>/block")
@ -205,7 +205,7 @@ def sub_blockers(v:User, sub):
.filter_by(sub=sub.name) \
.order_by(nullslast(SubBlock.created_utc.desc()), User.username).all()
return render_template("sub/blockers.html",
return render_template("sub/blockers.html",
v=v, sub=sub, users=users, verb="blocking")
@ -219,7 +219,7 @@ def sub_followers(v:User, sub):
.filter_by(sub=sub.name) \
.order_by(nullslast(SubSubscription.created_utc.desc()), User.username).all()
return render_template("sub/blockers.html",
return render_template("sub/blockers.html",
v=v, sub=sub, users=users, verb="following")
@ -265,7 +265,7 @@ def add_mod(v:User, sub):
@is_not_permabanned
def remove_mod(v:User, sub):
sub = get_sub_by_name(sub).name
if not v.mods(sub): abort(403)
if v.shadowbanned: abort(500)
@ -510,7 +510,7 @@ def delete_sub_banner(v:User, sub:str, index:int):
@limiter.limit("1/10 second;30/day")
@limiter.limit("1/10 second;30/day", key_func=lambda:f'{request.host}-{session.get("lo_user")}')
@is_not_permabanned
def delete_all_sub_banners(v:User, sub:str):
def delete_all_sub_banners(v:User, sub:str):
sub = get_sub_by_name(sub)
if not v.mods(sub.name): abort(403)
if v.shadowbanned: return redirect(f'/h/{sub}/settings')
@ -542,7 +542,7 @@ def sub_sidebar(v:User, sub):
sub = get_sub_by_name(sub)
if not v.mods(sub.name): abort(403)
if v.shadowbanned: return redirect(f'/h/{sub}/settings')
file = request.files["sidebar"]
name = f'/images/{time.time()}'.replace('.','') + '.webp'
file.save(name)
@ -573,7 +573,7 @@ def sub_marsey(v:User, sub):
sub = get_sub_by_name(sub)
if not v.mods(sub.name): abort(403)
if v.shadowbanned: return redirect(f'/h/{sub}/settings')
file = request.files["marsey"]
name = f'/images/{time.time()}'.replace('.','') + '.webp'
file.save(name)
@ -692,12 +692,12 @@ def sub_stealth(v:User, sub):
@feature_required('PINS')
@is_not_permabanned
def mod_pin(cid, v):
comment = get_comment(cid, v=v)
if not comment.stickied:
if not (comment.post.sub and v.mods(comment.post.sub)): abort(403)
comment.stickied = v.username + " (Mod)"
g.db.add(comment)
@ -719,9 +719,9 @@ def mod_pin(cid, v):
@app.post("/unmod_pin/<int:cid>")
@is_not_permabanned
def mod_unpin(cid, v):
comment = get_comment(cid, v=v)
if comment.stickied:
if not (comment.post.sub and v.mods(comment.post.sub)): abort(403)
@ -776,7 +776,7 @@ def hole_log(v:User, sub):
if kind: actions = actions.filter_by(kind=kind)
actions = actions.order_by(SubAction.id.desc()).offset(PAGE_SIZE*(page-1)).limit(PAGE_SIZE+1).all()
next_exists=len(actions)>25
actions=actions[:25]
mods = [x[0] for x in g.db.query(Mod.user_id).filter_by(sub=sub.name).all()]

View File

@ -96,7 +96,7 @@ def upvoting_downvoting(v, username, uid, cls, vote_cls, vote_dir, template, sta
listing = [p.id for p in listing]
next_exists = len(listing) > PAGE_SIZE
listing = listing[:PAGE_SIZE]
if cls == Submission:
listing = get_posts(listing, v=v, eager=True)
elif cls == Comment:
@ -238,7 +238,7 @@ def all_upvoters_downvoters(v:User, username:str, vote_dir:int, is_who_simps_hat
users = g.db.query(User).filter(User.id.in_(votes.keys()))
if not v.can_see_shadowbanned:
users = users.filter(User.shadowbanned == None)
users2 = [(user, votes[user.id]) for user in users.all()]
users = sorted(users2, key=lambda x: x[1], reverse=True)
@ -255,7 +255,7 @@ def all_upvoters_downvoters(v:User, username:str, vote_dir:int, is_who_simps_hat
try: page = int(request.values.get("page", 1))
except: page = 1
users = users[PAGE_SIZE * (page-1):]
next_exists = (len(users) > PAGE_SIZE)
users = users[:PAGE_SIZE]
@ -340,7 +340,7 @@ def transfer_currency(v:User, username:str, currency_name:Literal['coins', 'mars
send_repeatable_notification(receiver.id, notif_text)
g.db.add(v)
return {"message": f"{amount - tax} {currency_name} have been transferred to @{receiver.username}"}
@app.post("/@<username>/transfer_coins")
@limiter.limit(DEFAULT_RATELIMIT_SLOWER)
@limiter.limit(DEFAULT_RATELIMIT_SLOWER, key_func=lambda:f'{request.host}-{session.get("lo_user")}')
@ -445,7 +445,7 @@ def subscribe(v, post_id):
new_sub = Subscription(user_id=v.id, submission_id=post_id)
g.db.add(new_sub)
return {"message": "Subscribed to post successfully!"}
@app.post("/unsubscribe/<int:post_id>")
@limiter.limit(DEFAULT_RATELIMIT_SLOWER)
@limiter.limit(DEFAULT_RATELIMIT_SLOWER, key_func=lambda:f'{request.host}-{session.get("lo_user")}')
@ -629,7 +629,7 @@ def is_available(name:str):
if len(name)<3 or len(name)>25:
return {name:False}
name2 = name.replace('\\', '').replace('_','\_').replace('%','')
x = g.db.query(User).filter(
@ -648,7 +648,7 @@ def is_available(name:str):
def user_id(id):
user = get_account(id)
return redirect(user.url)
@app.get("/u/<username>")
@auth_required
def redditor_moment_redirect(v:User, username:str):
@ -785,10 +785,10 @@ def u_username_wall(v:Optional[User], username:str):
next_exists = (len(comments) > PAGE_SIZE)
comments = comments[:PAGE_SIZE]
if (v and v.client) or request.path.endswith(".json"):
return {"data": [c.json(g.db) for c in comments]}
return render_template("userpage/wall.html", u=u, v=v, listing=comments, page=page, next_exists=next_exists, is_following=is_following, standalone=True, render_replies=True, wall=True)
@ -837,12 +837,12 @@ def u_username_wall_comment(v:User, username:str, cid):
c = c.parent_comment
context -= 1
top_comment = c
if v:
# this is required because otherwise the vote and block
# props won't save properly unless you put them in a list
output = get_comments_v_properties(v, False, None, Comment.top_comment_id == c.top_comment_id)[1]
if v and v.client: return top_comment.json(db=g.db)
return render_template("userpage/wall.html", u=u, v=v, listing=[top_comment], page=1, is_following=is_following, standalone=True, render_replies=True, wall=True, comment_info=comment_info)
@ -899,7 +899,7 @@ def u_username(v:Optional[User], username:str):
if u.unban_utc:
if (v and v.client) or request.path.endswith(".json"):
return {"data": [x.json(g.db) for x in listing]}
return render_template("userpage/submissions.html",
unban=u.unban_string,
u=u,
@ -913,7 +913,7 @@ def u_username(v:Optional[User], username:str):
if (v and v.client) or request.path.endswith(".json"):
return {"data": [x.json(g.db) for x in listing]}
return render_template("userpage/submissions.html",
u=u,
v=v,
@ -955,7 +955,7 @@ def u_username_comments(username, v=None):
try: page = max(int(request.values.get("page", "1")), 1)
except: page = 1
sort=request.values.get("sort","new")
t=request.values.get("t","all")
@ -990,7 +990,7 @@ def u_username_comments(username, v=None):
if (v and v.client) or request.path.endswith(".json"):
return {"data": [c.json(g.db) for c in listing]}
return render_template("userpage/comments.html", u=u, v=v, listing=listing, page=page, sort=sort, t=t,next_exists=next_exists, is_following=is_following, standalone=True)
@ -1064,7 +1064,7 @@ def unfollow_user(username, v):
if follow:
g.db.delete(follow)
g.db.flush()
target.stored_subscriber_count = g.db.query(Follow).filter_by(target_id=target.id).count()
g.db.add(target)
@ -1087,7 +1087,7 @@ def remove_follow(username, v):
if not follow: return {"message": f"@{target.username} has been removed as a follower!"}
g.db.delete(follow)
g.db.flush()
v.stored_subscriber_count = g.db.query(Follow).filter_by(target_id=v.id).count()
g.db.add(v)
@ -1129,7 +1129,7 @@ def get_saves_and_subscribes(v, template, relationship_cls, page:int, standalone
ids = ids[:PAGE_SIZE]
extra = None
if not v.admin_level >= PERMS['POST_COMMENT_MODERATION']:
if not v.admin_level >= PERMS['POST_COMMENT_MODERATION']:
extra = lambda q:q.filter(cls.is_banned == False, cls.deleted_utc == 0)
if cls is Submission:
@ -1138,7 +1138,7 @@ def get_saves_and_subscribes(v, template, relationship_cls, page:int, standalone
listing = get_comments(ids, v=v, extra=extra)
else:
raise TypeError("Only supports Submissions and Comments. This is probably the result of a bug with *this* function")
if v.client: return {"data": [x.json(g.db) for x in listing]}
return render_template(template, u=v, v=v, listing=listing, page=page, next_exists=next_exists, standalone=standalone)
@ -1183,7 +1183,7 @@ def fp(v:User, fp):
if existing: continue
add_alt(user1=v.id, user2=u.id)
print(v.username + ' + ' + u.username, flush=True)
check_for_alts(v)
g.db.add(v)
return '', 204
@ -1282,13 +1282,13 @@ def settings_kofi(v:User):
abort(400, f"You must have a verified email to verify {patron} status and claim your rewards!")
transactions = g.db.query(Transaction).filter_by(email=v.email, claimed=None).all()
if not transactions:
abort(400, f"{patron} rewards already claimed")
highest_tier = 0
marseybux = 0
for transaction in transactions:
tier = kofi_tiers[transaction.amount]
marseybux += marseybux_li[tier]

View File

@ -87,7 +87,7 @@ def vote_post_comment(target_id, new, v, cls, vote_cls):
else:
abort(400)
existing = existing.one_or_none()
if IS_FISTMAS():
coin_mult = 2
coin_value = coin_delta * coin_mult
@ -125,7 +125,7 @@ def vote_post_comment(target_id, new, v, cls, vote_cls):
real=real,
coins=coin_value
)
elif vote_cls == CommentVote:
elif vote_cls == CommentVote:
vote = CommentVote(user_id=v.id,
vote_type=new,
comment_id=target_id,

View File

@ -18,7 +18,7 @@ def get_logged_in_user():
token = request.headers.get("Authorization","").strip()
if token:
client = g.db.query(ClientAuth).filter(ClientAuth.access_token == token).one_or_none()
if client:
if client:
v = client.user
v.client = client
else:
@ -65,7 +65,7 @@ def get_logged_in_user():
if f'@{v.username}, ' not in f.read():
t = time.strftime("%d/%B/%Y %H:%M:%S UTC", time.gmtime(time.time()))
log_file(f'@{v.username}, {v.truescore}, {ip}, {t}\n', 'eg.log')
g.is_api_or_xhr = bool((v and v.client) or request.headers.get("xhr"))
return v

View File

@ -29,7 +29,7 @@
{% if not app.client_id%}
<button type="button" class="btn btn-primary ml-auto mr-2" data-nonce="{{g.nonce}}" data-onclick="postToastReload(this,'/admin/app/approve/{{app.id}}')">Approve</button>
<button type="button" class="btn btn-secondary mr-0" data-nonce="{{g.nonce}}" data-onclick="postToastReload(this,'/admin/app/reject/{{app.id}}')">Reject</button>
<button type="button" class="btn btn-secondary mr-0" data-nonce="{{g.nonce}}" data-onclick="postToastReload(this,'/admin/app/reject/{{app.id}}')">Reject</button>
{% else %}

View File

@ -35,7 +35,7 @@
{% if not app.client_id %}
<button type="button" class="btn btn-primary ml-auto mr-2" data-nonce="{{g.nonce}}" data-onclick="postToastReload(this,'/admin/app/approve/{{app.id}}')">Approve</button>
<button type="button" class="btn btn-secondary mr-0" data-nonce="{{g.nonce}}" data-onclick="postToastReload(this,'/admin/app/reject/{{app.id}}')">Reject</button>
<button type="button" class="btn btn-secondary mr-0" data-nonce="{{g.nonce}}" data-onclick="postToastReload(this,'/admin/app/reject/{{app.id}}')">Reject</button>
{% else %}

View File

@ -33,7 +33,7 @@
<div class="custom-control">
<input autocomplete="off" class="custom-control-input" type="radio" id="{{badge.id}}" name="badge_id" value="{{badge.id}}" required>
<label class="custom-control-label" for="{{badge.id}}"></label>
</div>
</div>
</td>
<td>
<label for="badge-{{badge.id}}">

View File

@ -6,12 +6,12 @@
{% include "comments.html" %}
{% endwith %}
{% if not listing %}
<div class="row no-gutters">
<div class="col">
<div class="row no-gutters">
<div class="col">
<div class="text-center py-6">
<h4 class="p-2">There are no comments here (yet).</h4>
</div>
</div>
</div>
</div>
</div>
{% endif %}
</div>

View File

@ -6,12 +6,12 @@
{% include "comments.html" %}
{% endwith %}
{% if not listing %}
<div class="row no-gutters">
<div class="col">
<div class="row no-gutters">
<div class="col">
<div class="text-center py-6">
<h4 class="p-2">There are no comments here (yet).</h4>
</div>
</div>
</div>
</div>
</div>
{% endif %}
</div>

View File

@ -1,5 +1,5 @@
{% extends "default.html" %}
{% block pagetitle %}{{game.capitalize()}}{% endblock %}
{% block pagetitle %}{{game.capitalize()}}{% endblock %}
{% block content %}
<link rel="stylesheet" href="{{('css/casino/game_screen.css') | asset}}">
<script defer src="{{'js/casino/game_screen.js' | asset}}"></script>

View File

@ -35,8 +35,8 @@
{% if c.is_banned %}removed by @{{c.ban_reason}} (Admin){% elif c.deleted_utc %}Deleted by author{% elif c.is_blocking %}You are blocking @{{c.author_name}}{% endif %}
</div>
</div>
{% if render_replies %}
{% if render_replies %}
<div id="replies-of-{{c.fullname}}">
{% if level<9 or request.path.startswith('/notifications') %}
{% for reply in replies %}
@ -197,7 +197,7 @@
{% elif c.created_utc %}
<span id="timestamp-{{c.id}}" data-nonce="{{g.nonce}}" data-onmouseover="timestamp(this, '{{c.created_utc}}')" data-bs-toggle="tooltip" data-bs-placement="bottom" class="time-stamp">&nbsp;{{c.age_string}}</span>
{% endif %}
{% if c.edited_utc %}
<span class="time-edited" id="time-edit-{{c.id}}" data-nonce="{{g.nonce}}" data-onmouseover="timestamp(this, '{{c.edited_utc}}')"><span>&#183;</span> <span class="font-italic">Edited {{c.edited_string}}</span></span>
{% endif %}
@ -251,26 +251,26 @@
{% if c.parent_submission or c.wall_user_id %}
{% if v and v.id==c.author_id %}
<div id="comment-edit-{{c.id}}" class="d-none comment-write collapsed child">
<input type="hidden" name="formkey" value="{{v|formkey}}">
<textarea autocomplete="off" {% if v.longpost %}minlength="280"{% endif %} maxlength="{% if v.bird %}140{% else %}10000{% endif %}" data-preview="preview-edit-{{c.id}}" data-nonce="{{g.nonce}}" data-oninput="markdown(this);charLimit('comment-edit-body-{{c.id}}','charcount-edit-{{c.id}}')" id="comment-edit-body-{{c.id}}" data-id="{{c.id}}" name="body" form="comment-edit-form-{{c.id}}" class="comment-box form-control rounded" placeholder="Add your comment..." rows="3">{{c.body}}</textarea>
<textarea autocomplete="off" {% if v.longpost %}minlength="280"{% endif %} maxlength="{% if v.bird %}140{% else %}10000{% endif %}" data-preview="preview-edit-{{c.id}}" data-nonce="{{g.nonce}}" data-oninput="markdown(this);charLimit('comment-edit-body-{{c.id}}','charcount-edit-{{c.id}}')" id="comment-edit-body-{{c.id}}" data-id="{{c.id}}" name="body" form="comment-edit-form-{{c.id}}" class="comment-box form-control rounded" placeholder="Add your comment..." rows="3">{{c.body}}</textarea>
<div class="text-small font-weight-bold mt-1" id="charcount-edit-{{c.id}}" style="right: 1rem; bottom: 0.5rem; z-index: 3;"></div>
<div class="comment-format">
<div class="comment-format">
<small class="btn btn-secondary format m-0" data-nonce="{{g.nonce}}" data-onclick="getGifs('comment-edit-body-{{c.id}}')" data-bs-toggle="modal" data-bs-target="#gifModal" data-bs-toggle="tooltip" data-bs-placement="bottom" title="Add GIF"><span class="font-weight-bolder text-uppercase">GIF</span></small>
&nbsp;
<small class="btn btn-secondary format m-0" data-nonce="{{g.nonce}}" data-onclick="loadEmojis('comment-edit-body-{{c.id}}')" data-bs-toggle="modal" data-bs-target="#emojiModal" data-bs-toggle="tooltip" data-bs-placement="bottom" title="Add Emoji"><i class="fas fa-smile-beam"></i></small>
&nbsp;
<label class="btn btn-secondary format m-0" for="file-edit-reply-{{c.id}}">
<div id="filename-edit-reply-{{c.id}}"><i class="fas fa-file"></i></div>
<input autocomplete="off" id="file-edit-reply-{{c.id}}" accept="image/*, video/*, audio/*" type="file" multiple="multiple" name="file" {% if g.is_tor %}disabled{% endif %} data-nonce="{{g.nonce}}" data-onchange="changename('filename-edit-reply-{{c.id}}','file-edit-reply-{{c.id}}')" hidden>
</label>
</div>
<button type="button" id="edit-btn-{{c.id}}" form="comment-edit-form-{{c.id}}" class="btn btn-primary ml-2 fl-r commentmob" data-nonce="{{g.nonce}}" data-onclick="comment_edit('{{c.id}}');remove_dialog()">Save Edit</button>
<button type="button" id="cancel-edit-{{c.id}}" data-nonce="{{g.nonce}}" data-onclick="toggleEdit('{{c.id}}');remove_dialog()" class="btn btn-link text-muted ml-auto fl-r commentmob">Cancel</button>
<button type="button" id="edit-btn-{{c.id}}" form="comment-edit-form-{{c.id}}" class="btn btn-primary ml-2 fl-r commentmob" data-nonce="{{g.nonce}}" data-onclick="comment_edit('{{c.id}}');remove_dialog()">Save Edit</button>
<button type="button" id="cancel-edit-{{c.id}}" data-nonce="{{g.nonce}}" data-onclick="toggleEdit('{{c.id}}');remove_dialog()" class="btn btn-link text-muted ml-auto fl-r commentmob">Cancel</button>
<div id="preview-edit-{{c.id}}" class="preview mb-3 mt-5"></div>
<div class="form-text text-small p-0 m-0"><a href="/formatting" {% if v and v.newtab %}data-target="t" target="_blank"{% endif %}>Formatting help</a></div>
</div>
@ -290,45 +290,45 @@
{% if v and not c.deleted_utc %}
<button type="button" class="list-inline-item mr-3 btn nobackground" data-nonce="{{g.nonce}}" data-onclick="toggleReplyBox('reply-to-{{c.fullname}}')"><i class="fas fa-reply" style="margin-top:0.35rem"></i></button>
{% endif %}
<li class="list-inline-item">
<button type="button" data-bs-toggle="modal" data-bs-target="#actionsModal-{{c.id}}">
<i class="fas fa-ellipsis-h"></i>
</button>
</li>
{% if v and (request.path.startswith('/@') and not wall) and v.admin_level < PERMS['VIEW_VOTE_BUTTONS_ON_USER_PAGE'] %}
<li id="voting-{{c.id}}-mobile" class="voting list-inline-item d-md-none">
{% if voted==1 %}
<span class="mr-2 arrow-up comment-{{c.id}}-up active"></span>
{% endif %}
<span class="comment-mobile-score-{{c.id}} score comment-score-{{c.id}} {% if voted==1 %}score-up{% elif voted==-1%}score-down{% endif %}{% if c.controversial %} controversial{% endif %}"{% if not c.is_banned %} data-bs-toggle="tooltip" data-bs-placement="top" title="+{{ups}} | -{{downs}}"{% endif %}style="cursor: default">{{score}}</span>
{% if voted==-1 %}
<span class="ml-2 my-0 arrow-down comment-{{c.id}}-down active"></span>
{% endif %}
</li>
{% elif v %}
<li id="voting-{{c.id}}-mobile" class="voting list-inline-item d-md-none">
<span tabindex="0" role="button" data-nonce="{{g.nonce}}" data-onclick="vote('comment-mobile', '{{c.id}}', '1')" class="comment-mobile-{{c.id}}-up mx-0 pr-1 arrow-up upvote-button comment-{{c.id}}-up {% if voted==1 %}active{% endif %}">
</span>
<span class="comment-mobile-score-{{c.id}} score comment-score-{{c.id}} {% if voted==1 %}score-up{% elif voted==-1%}score-down{% endif %}{% if c.controversial %} controversial{% endif %}"{% if not c.is_banned %} data-bs-toggle="tooltip" data-bs-placement="top" title="+{{ups}} | -{{downs}}"{% endif %}style="cursor: default">{{score}}</span>
<span {% if DISABLE_DOWNVOTES %}style="display:None!important"{% endif %} tabindex="0" role="button" data-nonce="{{g.nonce}}" data-onclick="vote('comment-mobile', '{{c.id}}', '-1')" class="comment-mobile-{{c.id}}-down mx-0 pl-1 my-0 arrow-down downvote-button comment-{{c.id}}-down {% if voted==-1 %}active{% endif %}">
</span>
</li>
{% else %}
<li id="voting-{{c.id}}-mobile" class="voting list-inline-item d-md-none">
<span tabindex="0" class="arrow-{{c.id}}-mobile-up mx-0 pr-1 arrow-mobile-up" data-href="/login?redirect={{request.full_path | urlencode}}">
<i class="fas fa-arrow-alt-up mx-0"></i>
</span>
<span class="comment-mobile-score-{{c.id}} score{% if c.controversial %} controversial{% endif %}"{% if not c.is_banned %} data-bs-toggle="tooltip" data-bs-placement="top" title="+{{ups}} | -{{downs}}"{% endif %}style="cursor: default">{{score}}</span>
<span tabindex="0" class="arrow-{{c.id}}-mobile-down arrow-mobile-down mx-0 pl-1 my-0" data-href="/login?redirect={{request.full_path | urlencode}}">
<i class="fas fa-arrow-alt-down mx-0"></i>
</span>
@ -344,35 +344,35 @@
<button type="button" class="btn caction py-0 m-0 px-3 nobackground arrow-up mx-0 comment-{{c.id}}-up active"></button>
{% endif %}
{% elif v %}
<button type="button" tabindex="0" data-nonce="{{g.nonce}}" data-onclick="vote('comment', '{{c.id}}', '1')" class="comment-{{c.id}}-up btn caction py-0 m-0 px-3 nobackground arrow-up upvote-button mx-0 comment-{{c.id}}-up {% if voted==1 %}active{% endif %}"></button>
{% else %}
<button type="button" tabindex="0" class="comment-{{c.id}}-up btn caction nobackground py-0 m-0 px-3 arrow-up" data-href="/login?redirect={{request.full_path | urlencode}}"></button>
{% endif %}
<span class="btn caction nobackground p-0 m-0" style="cursor: default">
<span data-bs-toggle="tooltip" data-bs-placement="top" title="+{{ups}} | -{{downs}}" class="comment-score-{{c.id}} score comment-score-{{c.id}} {% if voted==1 %}score-up{% elif voted==-1%}score-down{% endif %}{% if c.controversial %} controversial{% endif %}">{{score}}</span>
</span>
{% if v and (request.path.startswith('/@') and not wall) and v.admin_level < PERMS['VIEW_VOTE_BUTTONS_ON_USER_PAGE'] %}
{% if voted==-1 %}
<li class=" arrow-down py-0 m-0 px-3 comment-{{c.id}}-down active"></li>
{% endif %}
{% elif v %}
<button type="button" {% if DISABLE_DOWNVOTES %}style="display:None!important"{% endif %} tabindex="0" data-nonce="{{g.nonce}}" data-onclick="vote('comment', '{{c.id}}', '-1')" class="comment-{{c.id}}-down btn caction py-0 m-0 px-3 nobackground arrow-down downvote-button comment-{{c.id}}-down {% if voted==-1 %}active{% endif %}"></button>
{% else %}
<button type="button" {% if DISABLE_DOWNVOTES %}style="display:None!important"{% endif %} tabindex="0" class="comment-{{c.id}}-down btn caction py-0 m-0 px-3 nobackground arrow-down" data-href="/login?redirect={{request.full_path | urlencode}}"></button>
{% endif %}
{% if not c.ghost or (v and v.id == AEVANN_ID) %}
<a href="/votes/{{c.fullname}}" class="btn caction nobackground px-1 text-muted"><i class="fas fa-arrows-v"></i>Votes</a>
{% endif %}
<a class="btn caction nobackground px-1 text-muted" href="{{c.permalink}}"><i class="fas fa-book-open"></i>Context</a>
<button type="button" class="btn caction py-0 nobackground px-1 text-muted copy-link" data-clipboard-text="{% if SITE == 'rdrama.net' %}https://{{BAN_EVASION_DOMAIN}}{{c.shortlink}}{% else %}{{c.permalink}}{% endif %}"><i class="fas fa-copy"></i>Copy link</button>
@ -387,16 +387,16 @@
{% if FEATURES['AWARDS'] -%}
<button type="button" class="btn caction py-0 nobackground px-1 text-muted" data-bs-toggle="modal" data-bs-target="#awardModal" data-url="/award/comment/{{c.id}}" data-nonce="{{g.nonce}}"><i class="fas fa-gift"></i>Give Award</button>
{%- endif %}
<button type="button" id="unsave-{{c.id}}" class="btn caction py-0 nobackground px-1 {% if c.id in v.saved_comment_idlist %}d-md-inline-block{% endif %} text-muted d-none" data-nonce="{{g.nonce}}" data-onclick="postToastSwitch(this,'/unsave_comment/{{c.id}}','save-{{c.id}}','unsave-{{c.id}}','d-md-inline-block')"><i class="fas fa-save"></i>Unsave</button>
<button type="button" id="save-{{c.id}}" class="btn caction py-0 nobackground px-1 {% if c.id not in v.saved_comment_idlist %}d-md-inline-block{% endif %} text-muted d-none" data-nonce="{{g.nonce}}" data-onclick="postToastSwitch(this,'/save_comment/{{c.id}}','save-{{c.id}}','unsave-{{c.id}}','d-md-inline-block')"><i class="fas fa-save"></i>Save</button>
{% endif %}
{% if c.parent_submission or c.wall_user_id %}
{% if v and c.author_id == v.id %}
<button type="button" class="btn caction py-0 nobackground px-1 text-muted" data-nonce="{{g.nonce}}" data-onclick="toggleEdit('{{c.id}}')"><i class="fas fa-edit fa-fw"></i>Edit</button>
<button type="button" id="undelete-{{c.id}}" class="btn caction py-0 nobackground px-1 text-muted {% if not c.deleted_utc %}d-none{% endif %}" data-nonce="{{g.nonce}}" data-onclick="postToastSwitch(this,'/undelete/comment/{{c.id}}','delete-{{c.id}}','undelete-{{c.id}}','d-none')" data-toggleelement="comment-{{c.id}}-only" data-toggleattr="deleted"><i class="fas fa-trash-alt fa-fw"></i>Undelete</button>
<button type="button" id="delete-{{c.id}}" class="btn caction py-0 nobackground px-1 text-muted {% if c.deleted_utc %}d-none{% endif %}" data-bs-toggle="modal" data-bs-target="#deleteCommentModal" data-nonce="{{g.nonce}}" data-onclick="delete_commentModal(this, '{{c.id}}')"><i class="fas fa-trash-alt fa-fw"></i>Delete</button>
@ -437,7 +437,7 @@
{% if url != "" %}
<button type="button" id="unpin-{{c.id}}" class="dropdown-item list-inline-item {% if c.stickied %}d-md-block{% endif %} text-muted d-none text-info" data-bs-dismiss="modal" data-bs-target="#actionsModal-{{c.id}}" data-nonce="{{g.nonce}}" data-onclick="postToastSwitch(this,'/un{{url}}/{{c.id}}','pin-{{c.id}}','unpin-{{c.id}}','d-md-block')"><i class="fas fa-thumbtack fa-rotate--45 text-info fa-fw"></i>Unpin</button>
<button type="button" id="pin-{{c.id}}" class="dropdown-item list-inline-item {% if not c.stickied %}d-md-block{% endif %} text-muted d-none text-info" data-bs-dismiss="modal" data-bs-target="#actionsModal-{{c.id}}" data-nonce="{{g.nonce}}" data-onclick="postToastSwitch(this,'/{{url}}/{{c.id}}','pin-{{c.id}}','unpin-{{c.id}}','d-md-block')"><i class="fas fa-thumbtack fa-rotate--45 text-info fa-fw"></i>Pin</button>
{% endif %}
{% endif %}
@ -480,7 +480,7 @@
</div>
{% if v and v.id != c.author_id and c.body %}
<div autocomplete="off" class="markdown d-none card border my-2 p-3 comment-box form-control rounded" id="markdown-{{c.id}}" readonly>{{c.body.strip()}}</div>
<div autocomplete="off" class="markdown d-none card border my-2 p-3 comment-box form-control rounded" id="markdown-{{c.id}}" readonly>{{c.body.strip()}}</div>
{% endif %}
{{macros.comment_reply_box(c.fullname, "reply-to-" + c.fullname, "d-none", "collapsed child", 'reply-to-' + c.fullname, true)}}
@ -489,7 +489,7 @@
<button type="button" class="copy-link ml-3" data-clipboard-text="{{c.log_link}}"><i class="far fa-copy text-muted"></i></button>
{% endif %}
{% if render_replies %}
{% if render_replies %}
<div id="replies-of-{{c.fullname}}">
{% if request.path.startswith('/notifications/') and replies|length > 8 %}
{% for reply in replies %}
@ -506,7 +506,7 @@
</div>
{% if request.path.startswith('/notifications') and c.level == 1 and c.sentto and not c.parent_submission and c.author_id != AUTOJANNY_ID %}
{% if (v and v.admin_level >= PERMS['USER_BAN']) and (c.sentto == MODMAIL_ID) %}
{% if (v and v.admin_level >= PERMS['USER_BAN']) and (c.sentto == MODMAIL_ID) %}
<button type="button" class="btn btn-danger mr-3 {% if c.author.is_muted %}d-none{% endif %}" id="mute-user-{{c.id}}" data-nonce="{{g.nonce}}" data-onclick="postToastSwitch(this,'/mute_user/{{c.author.id}}','mute-user-{{c.id}}','unmute-user-{{c.id}}','d-none')">Mute</button>
<button type="button" class="btn btn-primary mr-3 {% if not c.author.is_muted %}d-none{% endif %}" id="unmute-user-{{c.id}}" data-nonce="{{g.nonce}}" data-onclick="postToastSwitch(this,'/unmute_user/{{c.author.id}}','mute-user-{{c.id}}','unmute-user-{{c.id}}','d-none')">Unmute</button>
{% endif %}
@ -517,9 +517,9 @@
<div id="reply-message-{{c.fullname}}" class="d-none">
<div id="comment-form-space-{{c.id}}" class="comment-write collapsed child">
<div class="input-group">
<input type="hidden" name="formkey" value="{{v|formkey}}">
<textarea required autocomplete="off" minlength="1" maxlength="10000" name="body" form="reply-to-c_{{c.id}}" data-id="{{c.id}}" class="comment-box form-control rounded" id="reply-form-body-{{c.id}}" rows="3" data-preview="message-reply-{{c.id}}" data-nonce="{{g.nonce}}" data-oninput="markdown(this)"></textarea>
<div class="comment-format" id="comment-format-bar-{{c.id}}">
<input type="hidden" name="formkey" value="{{v|formkey}}">
<textarea required autocomplete="off" minlength="1" maxlength="10000" name="body" form="reply-to-c_{{c.id}}" data-id="{{c.id}}" class="comment-box form-control rounded" id="reply-form-body-{{c.id}}" rows="3" data-preview="message-reply-{{c.id}}" data-nonce="{{g.nonce}}" data-oninput="markdown(this)"></textarea>
<div class="comment-format" id="comment-format-bar-{{c.id}}">
<button role="button" data-nonce="{{g.nonce}}" data-onclick="loadEmojis('reply-form-body-{{c.id}}')" class="btn btn-secondary m-0 mt-3 mr-1" data-bs-toggle="modal" data-bs-target="#emojiModal" data-bs-toggle="tooltip" data-bs-placement="bottom" title="Add Emoji"><i class="fas fa-smile-beam"></i></button>
{% if c.sentto == MODMAIL_ID %}
@ -530,7 +530,7 @@
{% endif %}
</div>
<button type="button" data-nonce="{{g.nonce}}" data-onclick="remove_dialog()" class="btn btn-link text-muted ml-auto" data-toggleelement="reply-message-{{c.fullname}}" data-toggleattr="d-none">Cancel</button>
<button type="button" data-nonce="{{g.nonce}}" data-onclick="remove_dialog()" class="btn btn-link text-muted ml-auto" data-toggleelement="reply-message-{{c.fullname}}" data-toggleattr="d-none">Cancel</button>
<button type="button" id="save-reply-to-{{c.id}}" class="btn btn-primary ml-2" data-nonce="{{g.nonce}}" data-onclick="post_reply('{{c.id}}');remove_dialog()">Reply</button>
</div>
<div id="message-reply-{{c.id}}" class="preview mt-2"></div>
@ -576,7 +576,7 @@
{% if c.author_id == v.id %}
<button type="button" data-bs-dismiss="modal" data-nonce="{{g.nonce}}" data-onclick="toggleEdit('{{c.id}}')" class="list-group-item"><i class="fas fa-edit mr-2"></i>Edit</button>
<button type="button" id="undelete2-{{c.id}}" class="{% if not c.deleted_utc %}d-none{% endif %} list-group-item text-success" data-nonce="{{g.nonce}}" data-onclick="postToastSwitch(this,'/undelete/comment/{{c.id}}', 'delete2-{{c.id}}', 'undelete2-{{c.id}}','d-none')" data-toggleelement="comment-{{c.id}}-only" data-toggleattr="deleted" data-bs-dismiss="modal"><i class="far fa-trash-alt text-success mr-2"></i>Undelete</button>
<button type="button" id="delete2-{{c.id}}" class="{% if c.deleted_utc %}d-none{% endif %} list-group-item text-danger" data-bs-toggle="modal" data-bs-dismiss="modal" data-bs-target="#deleteCommentModal" data-nonce="{{g.nonce}}" data-onclick="delete_commentModal(this, '{{c.id}}')"><i class="far fa-trash-alt text-danger mr-2"></i>Delete</button>
@ -711,7 +711,7 @@
<p class="d-mob-none">Your comment will be deleted everywhere on {{SITE_NAME}}.</p>
<p class="text-muted d-md-none">Your comment will be deleted everywhere on {{SITE_NAME}}.</p>
<button type="button" id="deleteCommentButton" class="btn btn-danger btn-block mt-5" data-bs-dismiss="modal">Delete comment</button>
<button type="button" class="btn btn-secondary btn-block" data-bs-dismiss="modal">Cancel</button>

View File

@ -38,7 +38,7 @@
opacity: 0;
overflow: hidden;
}
body,
td,
th {
@ -80,7 +80,7 @@
p.sub {
font-size: 13px;
}
.align-right {
text-align: right;
}
@ -90,7 +90,7 @@
.align-center {
text-align: center;
}
.button {
background-color: #FF66AC;
border-top: 10px solid #FF66AC;
@ -124,7 +124,7 @@
text-align: center !important;
}
}
.attributes {
margin: 0 0 21px;
}
@ -136,7 +136,7 @@
.attributes_item {
padding: 0;
}
.related {
width: 100%;
margin: 0;
@ -164,7 +164,7 @@
text-align: center;
padding: 25px 0 10px;
}
.discount {
width: 100%;
margin: 0;
@ -182,7 +182,7 @@
text-align: center;
font-size: 15px;
}
.social {
width: auto;
}
@ -195,7 +195,7 @@
margin: 0 8px 10px 8px;
padding: 0;
}
.purchase {
width: 100%;
margin: 0;
@ -267,7 +267,7 @@
-premailer-cellpadding: 0;
-premailer-cellspacing: 0;
}
.email-masthead {
display: none;
}
@ -280,7 +280,7 @@
color: #121213;
text-decoration: none;
}
.email-body {
width: 100%;
margin: 0;
@ -328,7 +328,7 @@
.content-cell {
padding: 35px;
}
@media only screen and (max-width: 600px) {
.email-body_inner,
.email-footer {

View File

@ -135,7 +135,7 @@ Text 2
Poll — Pick Multiple<br>
<span style="font-style: italic; font-weight: normal;">
* Polls always appear at end of post.
</span>
</span>
</td>
<td>$$bussy$$<br>$$gussy$$</td>
<td>

View File

@ -46,7 +46,7 @@
<th>Owners</th>
<th>Price</th>
<th>Actions</th>
<th>Added on</th>
<th>Added on</th>
</tr>
</thead>
@ -79,7 +79,7 @@
<div id="if-owned-{{hat.id}}" {% if hat.id not in owned_hat_ids %}class="d-none"{% endif %}>
<button type="button" id="unequip-{{hat.id}}" class="unequip {% if hat.id not in v.equipped_hat_ids %}d-none{% endif %} btn btn-success" data-nonce="{{g.nonce}}" data-onclick="postToastSwitch(this, '/unequip_hat/{{hat.id}}', 'equip-{{hat.id}}', 'unequip-{{hat.id}}', 'd-none')"><span class="m-auto">Unequip</span></button>
<button type="button" id="equip-{{hat.id}}" class="equip {% if hat.id in v.equipped_hat_ids %}d-none{% endif %} btn btn-success" data-nonce="{{g.nonce}}" data-onclick="equip_hat(this, '{{hat.id}}', '{{hat.name}}')"><span class="m-auto">Equip</span></button>
</div>
</td>
@ -89,5 +89,5 @@
{% endfor %}
</tbody>
</table>
{% endblock %}

View File

@ -63,7 +63,7 @@
{% endif %}
<img id="header--icon" alt="header icon" {% if sub %}src="{{sub.marsey_url}}"{% else %}src="{{icon_url}}"{% endif %}>
</a>
{% if sub %}
<a id="sub-name" href="/h/{{sub}}" class="font-weight-bold ml-2 flex-grow-1 mt-1" {% if sub.name|length >= 17 %}style="font-size:max(10px,1.2vw)"{% else %}style="font-size:max(14px,1.2vw)"{% endif %}>{% if not HOLE_STYLE_FLAIR %}/h/{% endif %}{{sub}}</a>
{% elif has_logo %}
@ -77,7 +77,7 @@
</a>
</div>
{% endif %}
{% if not request.path.startswith('/search/') %}
<div class="flex-grow-1 d-fl d-mob-none {% if not v %}pad{% endif %}">
<form class="form-inline search flex-nowrap mx-0 mx-lg-auto mb-0" {% if err %}style="margin-right:40rem!important"{% endif %} action="{% if request.path.startswith('/search') %}{{request.path}}{% else %}/search/posts/{% endif %}" method="get">
@ -102,7 +102,7 @@
<a class="mobile-nav-icon d-md-none" href="/notifications" data-bs-toggle="tooltip" data-bs-placement="bottom" title="Notifications"><i class="fas fa-bell align-middle text-gray-500 black"></i></a>
{% endif %}
{% endif %}
{% if not err %}
{% if v and v.admin_level >= PERMS['ADMIN_HOME_VISIBLE'] %}
<a class="mobile-nav-icon d-md-none" href="/admin"><i class="fas fa-crown align-middle text-gray-500 black"></i></a>
@ -154,7 +154,7 @@
{% if FEATURES['CHAT'] and v.admin_level >= PERMS['CHAT'] -%}
<li class="nav-item d-none d-lg-flex align-items-center justify-content-center text-center mx-1">
<a class="nav-link position-relative" href="/chat">
<i class="fas fa-messages" data-bs-toggle="tooltip" data-bs-placement="bottom" title="Chat"></i>
<i class="fas fa-messages" data-bs-toggle="tooltip" data-bs-placement="bottom" title="Chat"></i>
<b class="text-lg" data-bs-toggle="tooltip" data-bs-placement="bottom" title="Users in chat right now">
{{loggedin_chat}}
</b>
@ -165,7 +165,7 @@
<li class="nav-item d-flex align-items-center justify-content-center text-center mx-1">
<a class="nav-link" href="/random_user" data-bs-toggle="tooltip" data-bs-placement="bottom" title="Random User"><i class="fas fa-music"></i></a>
</li>
<li class="nav-item d-none d-lg-flex align-items-center justify-content-center text-center mx-1">
<a class="nav-link" href="/comments" data-bs-toggle="tooltip" data-bs-placement="bottom" title="All Comments"><i class="fas fa-comment-dots"></i></a>
</li>
@ -287,7 +287,7 @@
<li class="nav-item">
<button type="button" class="nav-link copy-link" data-clipboard-text="{{SITE_FULL}}/signup?ref={{v.username}}"><i class="fas fa-user-friends fa-fw mr-3"></i>Invite friends</button>
</li>
<a class="nav-item nav-link" href="https://rdrama.net/h/changelog"><i class="fas fa-clipboard fa-fw mr-3"></i>Changelog</a>
<a class="nav-item nav-link" rel="nofollow noopener" href="https://fsdfsd.net/rDrama/rDrama"><i class="fab fa-git-alt fa-fw mr-3"></i>Source code</a>
@ -301,7 +301,7 @@
{% if SITE_NAME == 'rDrama' %}
<a class="nav-item nav-link" href="/archives"><i class="fas fa-book fa-fw mr-3"></i>Archives</a>
{% endif %}
<a class="nav-item nav-link" href="/contact"><i class="fas fa-file-signature fa-fw mr-3"></i>Contact us</a>
<li class="nav-item border-top border-bottom mt-2 pt-2">

View File

@ -1,33 +1,33 @@
{%-
set JOURNOID_BANNERS = [
(
"Official site of /r/SubredditDrama 🍿",
"https://reddit.com/r/subredditdrama",
"Official site of /r/SubredditDrama 🍿",
"https://reddit.com/r/subredditdrama",
""
),
(
"As seen on The Independent 📰✨💞",
"https://www.independent.co.uk/news/world/americas/us-politics/reddit-conservatives-post-trans-child-fake-b2060803.html",
"As seen on The Independent 📰✨💞",
"https://www.independent.co.uk/news/world/americas/us-politics/reddit-conservatives-post-trans-child-fake-b2060803.html",
"https://rdrama.net//post/61530"
),
(
"As fact-checked by Reuters 📰✨💞",
"https://www.reuters.com/article/factcheck-socialmedia-gender/fact-check-post-about-parent-forcefully-medicating-transgender-child-is-fabricated-idUSL2N2WC1OK",
"As fact-checked by Reuters 📰✨💞",
"https://www.reuters.com/article/factcheck-socialmedia-gender/fact-check-post-about-parent-forcefully-medicating-transgender-child-is-fabricated-idUSL2N2WC1OK",
"https://rdrama.net//post/60443"
),
(
"As analyzed by Mashable 📰✨💞",
"https://mashable.com/article/libs-of-tiktok-furries-school-troll-fake",
"As analyzed by Mashable 📰✨💞",
"https://mashable.com/article/libs-of-tiktok-furries-school-troll-fake",
"https://rdrama.net//post/63155"
),
(
"As seen on Business Insider's retraction 📰✨💞",
"https://businessinsider.com/reddit-shuts-down-forum-for-texas-abortion-bounty-hunters-2021-9",
"As seen on Business Insider's retraction 📰✨💞",
"https://businessinsider.com/reddit-shuts-down-forum-for-texas-abortion-bounty-hunters-2021-9",
"https://rdrama.net//post/19236"
),
(
"As discussed on The Glenn Beck Program 📻✨💞",
"https://www.audacy.com/podcasts/the-glenn-beck-program-45436/elon-musk-vs-the-world-guests-rob-collins-riaz-patel-42722-1386209895",
"As discussed on The Glenn Beck Program 📻✨💞",
"https://www.audacy.com/podcasts/the-glenn-beck-program-45436/elon-musk-vs-the-world-guests-rob-collins-riaz-patel-42722-1386209895",
"https://rdrama.net//post/64305"
),
(

View File

@ -28,7 +28,7 @@
<div class="row" style="overflow: visible;padding-top:5px;">
<div class="col">
<div class="d-flex justify-content-between align-items-center">
{% block navbar %}
<div class="d-flex align-items-center mb-3 ml-auto">
<div class="dropdown dropdown-actions">
@ -44,7 +44,7 @@
{% endfor %}
</div>
</div>
<div class="dropdown dropdown-actions ml-3">
<button type="button" class="btn btn-secondary dropdown-toggle" id="dropdownMenuButton2" data-bs-toggle="dropdown">
{% if type %}<i class="fas {{types[type]['icon']}} mr-2"></i>{{type}}{% else %}<i class="fas fa-broom mr-2"></i>All{% endif %}

View File

@ -17,7 +17,7 @@
Already have an account? <a href="/login{{'?redirect='+redirect if redirect else ''}}" class="font-weight-bold toggle-login">Log in</a>
</div>
{% endblock %}
{% block scripts %}
{% block scripts %}
<div class="toast clipboard" id="toast-success" role="alert" data-bs-animation="true" data-bs-autohide="true" data-bs-delay="5000">
<div class="toast-body text-center">
<i class="fas fa-check-circle text-success mr-2"></i>Link copied to clipboard

View File

@ -1,7 +1,7 @@
{% extends "default.html" %}
{% block pagetitle %}Directory{% endblock %}
{% block pagetype %}directory{% endblock %}
{# Title (~25char max), Description (~80char max),
{# Title (~25char max), Description (~80char max),
Icon (fa-foo-bar), Color (#ff0000), URL (/post/12345/) #}
{%- set MEGATHREAD_INDEX = [] -%}

View File

@ -41,5 +41,5 @@
<div class="toast-body bg-danger text-center text-white">
<i class="fas fa-exclamation-circle mr-2"></i><span id="toast-post-error-text2">Error, please try again later.</span>
</div>
</div>
</div>
</div>

View File

@ -18,7 +18,7 @@
<p class="d-mob-none">Your post will be deleted everywhere on {{SITE_NAME}}.</p>
<p class="text-muted d-md-none">Your post will be deleted everywhere on {{SITE_NAME}}.</p>
<button type="button" id="deletePostButton" class="btn btn-danger btn-block mt-5" data-bs-dismiss="modal">Delete post</button>
<button type="button" class="btn btn-secondary btn-block" data-bs-dismiss="modal">Cancel</button>

View File

@ -81,7 +81,7 @@
<div>
{% if ma.sub %}
<a href="/h/{{ma.sub}}">/h/{{ma.sub}}</a>
-
-
{% endif %}
<a href="{{ma.user.url}}" class="font-weight-bold text-black" target="_self">@{{ma.user.username}}</a>
<span>{{ma.string | safe}}</span>
@ -106,7 +106,7 @@
<i class="fas fa-check-circle text-success mr-2"></i>Link copied to clipboard
</div>
</div>
<script defer src="{{'js/vendor/clipboard.js' | asset}}"></script>
{% else %}
{% with comments=notifications %}

View File

@ -22,7 +22,7 @@
<button type="button" id="save-{{p.id}}" class="{% if p.id in v.saved_idlist %}d-none{% endif %} list-inline-item" data-nonce="{{g.nonce}}" data-onclick="postToastSwitch(this,'/save_post/{{p.id}}','save-{{p.id}}','unsave-{{p.id}}','d-none')"><i class="fas fa-save"></i>Save</button>
<button type="button" id="unsave-{{p.id}}" class="{% if not p.id in v.saved_idlist %}d-none{% endif %} list-inline-item" data-nonce="{{g.nonce}}" data-onclick="postToastSwitch(this,'/unsave_post/{{p.id}}','save-{{p.id}}','unsave-{{p.id}}','d-none')"><i class="fas fa-save"></i>Unsave</button>
<button type="button" class="list-inline-item" data-bs-toggle="modal" data-bs-dismiss="modal" data-bs-target="#reportPostModal" data-nonce="{{g.nonce}}" data-onclick="report_postModal('{{p.id}}')"><i class="fas fa-flag"></i>Report</button>
{% endif %}
@ -42,7 +42,7 @@
<ul class="dropdown-menu">
{% if v.admin_level >= PERMS['POST_COMMENT_MODERATION'] and p.oauth_app %}
<a class="dropdown-item list-inline-item text-info" href="{{p.oauth_app.permalink}}/posts"><i class="fas fa-code"></i>API App</a>
{% endif %}
{% endif %}
{% if v.can_edit(p) %}
<button type="button" class="dropdown-item {% if p.new %} d-none{% endif %} list-inline-item text-info" id="{{p.id}}-sort-new" data-nonce="{{g.nonce}}" data-onclick="postToastSwitch(this, '/post/{{p.id}}/new', '{{p.id}}-sort-new', '{{p.id}}-unsort-new', 'd-none', null, 'PUT')"><i class="fas fa-sparkles text-center text-primary mr-2"></i>Set Default Sort New</button>
<button type="button" class="dropdown-item {% if not p.new %} d-none{% endif %} list-inline-item text-info" id="{{p.id}}-unsort-new" data-nonce="{{g.nonce}}" data-onclick="postToastSwitch(this, '/post/{{p.id}}/new', '{{p.id}}-unsort-new', '{{p.id}}-sort-new', 'd-none', null, 'DELETE')"><i class="fas fa-fire text-center text-primary mr-2"></i>Set Default Sort Hot</button>

View File

@ -66,7 +66,7 @@
{% if request.path.startswith('/search/posts') %}
<div>
<div style="display: inline-block; width: 150px; text-align: center;">Post Title Only:</div>
<button type="button" data-nonce="{{g.nonce}}" data-onclick="addParam()" class="searchparam mb-1">title:true</button>
<button type="button" data-nonce="{{g.nonce}}" data-onclick="addParam()" class="searchparam mb-1">title:true</button>
</div>
{% endif %}
</div>

View File

@ -6,10 +6,10 @@
</div>
{% if error %}
<div class="row no-gutters">
<div class="row no-gutters">
<div class="col">
{{macros.ghost_box(error, '', 1)}}
</div>
</div>
</div>
{% endif %}
{% endblock %}

View File

@ -91,7 +91,7 @@
<option value="{{entry}}"{{' selected' if v.defaulttime==entry}}>{{entry}}</option>
{% endfor %}
</select>
</div>
</div>
</div>
</div>
</div>

View File

@ -17,12 +17,12 @@
<input type="hidden" name="formkey" value="{{v|formkey}}">
<label for="edit-{{app.id}}-name" class="mb-0 w-lg-25">App Name</label>
<input autocomplete="off" id="edit-{{app.id}}-name" class="form-control" type="text" name="name" value="{{app.app_name}}">
{% if app.client_id %}
<label for="edit-{{app.id}}-client-id" class="mb-0 w-lg-25">Client ID</label>
<input autocomplete="off" id="edit-{{app.id}}-client-id" class="form-control copy-link" type="text" name="name" value="{{app.client_id}}" data-clipboard-text="{{app.client_id}}" readonly="readonly">
{% endif %}
<label for="edit-{{app.id}}-redirect" class="mb-0 w-lg-25">Redirect URI</label>
<input autocomplete="off" id="edit-{{app.id}}-redirect" class="form-control" type="text" name="redirect_uri" value="{{app.redirect_uri}}">
<label for="edit-{{app.id}}-desc" class="mb-0 w-lg-25">Description</label>

View File

@ -73,9 +73,9 @@
{% macro text_area_section(id, form_action, form_name, section_title, contents, below_text, placeholder_text, show_extras, show_file_upload, maxlength, show_if) %}
{% if show_if -%}
<div class="body d-lg-flex border-bottom">
<div class="body d-lg-flex border-bottom">
<label class="text-black w-lg-25">{{section_title}}</label>
<div class="w-lg-100">
<div class="w-lg-100">
<form id="{{id}}-form" action="{{form_action}}" method="post" enctype="multipart/form-data">
<input type="hidden" name="formkey" value="{{v|formkey}}">
<textarea autocomplete="off" id="{{id}}-text" class="form-control rounded" placeholder="{{placeholder_text}}" rows="3" name="{{form_name}}" form="{{id}}-form" maxlength="{{maxlength}}">{% if contents %}{{contents}}{% endif %}</textarea>

View File

@ -47,7 +47,7 @@
<div class="body w-lg-100">
<p>Change the background for the website.</p>
<div class="input-group mb2">
<select autocomplete="off" id='backgroundSelector' class="form-control" form="profile-settings" name="background" data-nonce="{{g.nonce}}" data-onchange="updatebgselection();">
<select autocomplete="off" id='backgroundSelector' class="form-control" form="profile-settings" name="background" data-nonce="{{g.nonce}}" data-onchange="updatebgselection();">
{% for entry in BACKGROUND_CATEGORIES %}
<option value="{{entry}}" {% if v.background and v.background.startswith(entry) %}selected{% endif %}>
{{entry}}
@ -55,10 +55,10 @@
{% endfor %}
</select>
</div>
<form class="d-flex mt-3 mb-2" id="upload-custom-background" action="/settings/custom_background" method="post" enctype="multipart/form-data">
<form class="d-flex mt-3 mb-2" id="upload-custom-background" action="/settings/custom_background" method="post" enctype="multipart/form-data">
<input type="hidden" name="formkey" value="{{v|formkey}}">
<label class="btn btn-primary" for="upload-custom-background-file">
<i class="fas fa-image mr-1"></i>
<i class="fas fa-image mr-1"></i>
{% if v.background and v.background.startswith('/images/') %}
{{v.background}}
{% else %}

View File

@ -51,7 +51,7 @@
{% if FEATURES['MARSEYBUX'] %}
<span class="text-small text-muted pl-1">Must be same email as the one you used to donate
{% if v.truescore >= TRUESCORE_DONATE_MINIMUM %}
on
on
{% if KOFI_TOKEN %}
<a rel="nofollow noopener" class="text-primary" href="{{KOFI_LINK}}">Kofi</a>
{% else %}
@ -61,14 +61,14 @@
</span>
{% endif %}
</div>
</form>
</form>
</div>
</section>
<section id="site-settings-password-section" class="settings-section-section">
<h5>Password</h5>
<div class="settings-section rounded">
<form action="/settings/security" method="post">
<div class="body">
<div class="body">
<div class="d-lg-flex">
<label for="old_password" class="mb-0 w-lg-25">Old Password</label>
<input autocomplete="off" class="form-control mb-2 w-lg-100" id="old_password" type="password" name="old_password" required>

View File

@ -78,5 +78,5 @@
{% endfor %}
</table>
</div>
{% endblock %}

View File

@ -22,7 +22,7 @@
<button type="submit" class="btn btn-primary ml-auto" id="create_button" {% if cost > v.coins %}disabled{% endif %}>Create {{HOLE_NAME|capitalize}}</button>
</div>
<p class="mt-2 mr-1" style="float: right"><b>Cost</b>: {{cost}} coins</p>
</div>
</div>
</div>
</div>
</div>

View File

@ -130,7 +130,7 @@
{% endif %}
{% endif %}
<div id="post-text" class="{% if p.author.agendaposter and p.sub != 'chudrama' %}agendaposter{% endif %} {% if p.author.rainbow %}rainbow-text{% endif %}">
{% if p.is_image %}
<div class="row no-gutters mb-4">
@ -175,23 +175,23 @@
<input type="hidden" name="formkey" value="{{v|formkey}}">
<input type="hidden" name="current_page" value="{{request.path}}">
<textarea id="post-edit-title" autocomplete="off" max-length="500" name="title" class="comment-box form-control rounded" required placeholder="title">{{p.title}}</textarea>
<textarea autocomplete="off" name="body" {% if v.longpost %}minlength="280"{% endif %} maxlength="{% if v.bird %}140{% else %}20000{% endif %}" data-preview="post-edit-{{p.id}}" data-nonce="{{g.nonce}}" data-oninput="markdown(this);charLimit('post-edit-box-{{p.id}}','charcount-post-edit')" id="post-edit-box-{{p.id}}" form="post-edit-form-{{p.id}}" class="comment-box form-control rounded" placeholder="Add text to your post..." rows="10" data-id="{{p.id}}">{{p.body}}</textarea>
<textarea autocomplete="off" name="body" {% if v.longpost %}minlength="280"{% endif %} maxlength="{% if v.bird %}140{% else %}20000{% endif %}" data-preview="post-edit-{{p.id}}" data-nonce="{{g.nonce}}" data-oninput="markdown(this);charLimit('post-edit-box-{{p.id}}','charcount-post-edit')" id="post-edit-box-{{p.id}}" form="post-edit-form-{{p.id}}" class="comment-box form-control rounded" placeholder="Add text to your post..." rows="10" data-id="{{p.id}}">{{p.body}}</textarea>
<div class="text-small font-weight-bold mt-1" id="charcount-post-edit" style="right: 1rem; bottom: 0.5rem; z-index: 3;"></div>
<div class="comment-format">
<button type="button" class="format btn btn-secondary"><span class="font-weight-bolder text-uppercase" data-nonce="{{g.nonce}}" data-onclick="getGifs('post-edit-box-{{p.id}}')" data-bs-toggle="modal" data-bs-target="#gifModal" data-bs-toggle="tooltip" data-bs-placement="bottom" title="Add GIF">GIF</span></button>
<button role="button" data-nonce="{{g.nonce}}" data-onclick="loadEmojis('post-edit-box-{{p.id}}')" class="format btn btn-secondary" role="button" data-bs-toggle="modal" data-bs-target="#emojiModal" data-bs-toggle="tooltip" data-bs-placement="bottom" title="Add Emoji"><i class="fas fa-smile-beam"></i></button>
<button role="button" data-nonce="{{g.nonce}}" data-onclick="loadEmojis('post-edit-box-{{p.id}}')" class="format btn btn-secondary" role="button" data-bs-toggle="modal" data-bs-target="#emojiModal" data-bs-toggle="tooltip" data-bs-placement="bottom" title="Add Emoji"><i class="fas fa-smile-beam"></i></button>
<label class="format btn btn-secondary m-0 {% if v %}d-inline-block{% else %}d-none{% endif %}" for="file-upload-edit-{{p.id}}">
<div id="filename-show-edit-{{p.id}}"><i class="fas fa-file"></i></div>
<input autocomplete="off" id="file-upload-edit-{{p.id}}" accept="image/*, video/*, audio/*" type="file" multiple="multiple" name="file" {% if g.is_tor %}disabled{% endif %} data-nonce="{{g.nonce}}" data-onchange="changename('filename-show-edit-{{p.id}}','file-upload-edit-{{p.id}}')" hidden>
</label>
<small class="format d-none"><i class="fas fa-link"></i></small>
<small class="format d-none"><i class="fas fa-link"></i></small>
</div>
<button type="submit" form="post-edit-form-{{p.id}}" class="btn btn-primary ml-2 fl-r" data-nonce="{{g.nonce}}" data-onclick="disable(this);remove_dialog()">Save Edit</button>
<button type="button" data-nonce="{{g.nonce}}" data-onclick="togglePostEdit('{{p.id}}');remove_dialog()" class="btn btn-link text-muted ml-auto fl-r">Cancel</button>
<button type="button" data-nonce="{{g.nonce}}" data-onclick="togglePostEdit('{{p.id}}');remove_dialog()" class="btn btn-link text-muted ml-auto fl-r">Cancel</button>
</form>
<div id="post-edit-{{p.id}}" class="preview mb-3 mt-5"></div>
<div class="form-text text-small p-0 m-0"><a href="/formatting" {% if v and v.newtab %}data-target="t" target="_blank"{% endif %}>Formatting help</a></div>
@ -301,7 +301,7 @@
</div>
{% if v and v.id != p.author_id and p.body and not v_forbid_deleted %}
<div autocomplete="off" class="markdown d-none card border my-2 p-3 comment-box form-control rounded" id="markdown-{{p.id}}" readonly>{{p.body.strip()}}</div>
<div autocomplete="off" class="markdown d-none card border my-2 p-3 comment-box form-control rounded" id="markdown-{{p.id}}" readonly>{{p.body.strip()}}</div>
{% endif %}
<div class="row border-md-0 comment-section pb-3">
@ -342,7 +342,7 @@
{% include "comments.html" %}
{% endwith %}
</div>
{% if offset %}
<script defer src="{{'js/view_more.js' | asset}}"></script>
{% endif %}

View File

@ -31,7 +31,7 @@
</div>
<div id="voting" class="d-md-block my-auto mr-3 text-center">
<div class="post-{{p.id}}-up arrow-up mx-auto">
</div>
@ -44,7 +44,7 @@
</div>
{% if v and v.admin_level >= PERMS['POST_COMMENT_MODERATION'] and p.body_html %}
<div class="post-body mt-4 mb-2">
<div class="post-body mt-4 mb-2">
{{p.body_html | safe}}
</div>
{% endif %}

View File

@ -144,7 +144,7 @@
{% endif %}
</li>
{% if p.realbody(v, listing=True) %}
<button type="button" class="list-inline-item ml-2" data-nonce="{{g.nonce}}" data-onclick="expandText('{{p.id}}')"><i class="fas fa-expand-alt mx-0 text-expand-icon-{{p.id}}"></i></button>
{% endif %}
@ -250,8 +250,8 @@
{% else %}
{% if u %}
{% if v and v.id == u.id %}
<div class="row no-gutters">
<div class="col">
<div class="row no-gutters">
<div class="col">
<div class="text-center px-3 my-3">
<span class="fa-stack fa-2x text-muted mb-4">
<i class="fas fa-square text-gray-500 opacity-25 fa-stack-2x"></i>
@ -260,12 +260,12 @@
<h5>You haven't {% if "/saved/" in request.path %}saved{% elif "/subscribed/" in request.path %}subscribed to{% else %}made{% endif %} a post yet</h5>
<p class="text-muted mb-md-5">Your {% if "/saved/" in request.path %}saved posts{% elif "/subscribed/" in request.path %}subscribed posts{% else %}posting history{% endif %} will show here.</p>
{% if "/saved/" not in request.path and "/subscribed/" not in request.path %}<a href="/submit" class="btn btn-primary">Create a post</a>{% endif %}
</div>
</div>
</div>
</div>
</div>
{% else %}
<div class="row no-gutters">
<div class="col">
<div class="row no-gutters">
<div class="col">
<div class="text-center px-3 my-3">
<span class="fa-stack fa-2x text-muted mb-4">
<i class="fas fa-square text-gray-500 opacity-25 fa-stack-2x"></i>
@ -273,16 +273,16 @@
</span>
<h5>@{{u.username}} hasn't made a post yet</h5>
<p class="text-muted mb-1">Their posting history will show here.</p>
</div>
</div>
</div>
</div>
</div>
{% endif %}
{% elif request.path != '/notifications/posts' %}
<div class="row no-gutters">
<div class="row no-gutters">
<div class="col">
{{macros.ghost_box(error if request.path.startswith('/search') else '', '', 1)}}
</div>
</div>
</div>
{% endif %}

View File

@ -31,7 +31,7 @@
</div>
<label class='mt-4' for="title">Post Title</label>
<input autocomplete="off" class="form-control allow-emojis" id="post-title" type="text" name="title" placeholder="Required" value="{{title}}" minlength="1" maxlength="500" required data-nonce="{{g.nonce}}" data-oninput="checkForRequired();savetext()">
<button role="button" data-nonce="{{g.nonce}}" data-onclick="loadEmojis('post-title')" class="btn btn-secondary format d-inline-block m-0" id="emoji-reply-btn-2" data-bs-toggle="modal" data-bs-target="#emojiModal" data-bs-toggle="tooltip" data-bs-placement="bottom" title="Add Emoji"><i class="fas fa-smile-beam"></i></button>
<button role="button" data-nonce="{{g.nonce}}" data-onclick="loadEmojis('post-title')" class="btn btn-secondary format d-inline-block m-0" id="emoji-reply-btn-2" data-bs-toggle="modal" data-bs-target="#emojiModal" data-bs-toggle="tooltip" data-bs-placement="bottom" title="Add Emoji"><i class="fas fa-smile-beam"></i></button>
<div id="urlblock">
<label for="URL" class="mt-3">URL</label>
<input autocomplete="off" class="form-control" id="post-url" name="url" type="url" placeholder="Optional if you have text." value="{{request.values.get('url','')}}" required data-nonce="{{g.nonce}}" data-oninput="checkForRequired();hide_image();savetext();checkRepost();autoSuggestTitle()">
@ -59,11 +59,11 @@
</div>
<small class="btn btn-secondary format d-inline-block m-0"><span class="font-weight-bolder text-uppercase" data-nonce="{{g.nonce}}" data-onclick="getGifs('post-text')" data-bs-toggle="modal" data-bs-target="#gifModal" data-bs-toggle="tooltip" data-bs-placement="bottom" title="Add GIF">GIF</span></small>
&nbsp;
<button role="button" data-nonce="{{g.nonce}}" data-onclick="loadEmojis('post-text')" class="btn btn-secondary format d-inline-block m-0" id="emoji-reply-btn" data-bs-toggle="modal" data-bs-target="#emojiModal" data-bs-toggle="tooltip" data-bs-placement="bottom" title="Add Emoji"><i class="fas fa-smile-beam"></i></button>
<button role="button" data-nonce="{{g.nonce}}" data-onclick="loadEmojis('post-text')" class="btn btn-secondary format d-inline-block m-0" id="emoji-reply-btn" data-bs-toggle="modal" data-bs-target="#emojiModal" data-bs-toggle="tooltip" data-bs-placement="bottom" title="Add Emoji"><i class="fas fa-smile-beam"></i></button>
<label class="format btn btn-secondary m-0 ml-2 {% if v %}d-inline-block{% else %}d-none{% endif %}" for="file-upload-submit">
<div id="filename-show-submit"><i class="fas fa-file"></i></div>
<input autocomplete="off" id="file-upload-submit" multiple="multiple" accept="image/*, video/*, audio/*" type="file" name="file" {% if g.is_tor %}disabled{% endif %} data-nonce="{{g.nonce}}" data-onchange="changename('filename-show-submit','file-upload-submit');checkForRequired()" hidden>
</label>
</label>
<div id="preview" class="preview my-3"></div>
<div class="form-text text-small my-1"><a href="/formatting" {% if v and v.newtab %}data-target="t" target="_blank"{% endif %}>Formatting help</a></div>
<div class="custom-control custom-checkbox">

View File

@ -41,7 +41,7 @@
<input id="submit-hat" disabled type="submit" data-nonce="{{g.nonce}}" data-onclick="disable(this)" class="btn btn-primary ml-auto" value="Submit Hat">
</div>
</div>
</form>
</form>
</div>
</div>
</div>
@ -60,7 +60,7 @@
<div class="d-lg-flex">
<div class="body w-lg-100">
<input type="hidden" name="formkey" value="{{v|formkey}}">
<div><label class="mt-3">Image</label></div>
<img loading="lazy" src="/asset_submissions/hats/{{hat.name}}.webp?s={{range(1, 10000000)|random}}" style="max-width:50%;border:5px white solid">
@ -78,7 +78,7 @@
<label class="mt-3" for="{{hat.name}}-name">Name</label>
<input autocomplete="off" type="text" id="{{hat.name}}-name" class="form-control" name="name" maxlength="30" value="{{hat.name}}" pattern='hat[a-zA-Z0-9]{1,24}' placeholder="Required" required {% if v.admin_level < PERMS['MODERATE_PENDING_SUBMITTED_HATS'] %}readonly{% endif %}>
>
<label class="mt-3" for="{{hat.name}}-description">Description</label>
<input autocomplete="off" type="text" id="{{hat.name}}-description" class="form-control" name="description" maxlength="300" value="{{hat.description}}" pattern='[^<>&\n\t]{1,300}' placeholder="Required" required {% if v.admin_level < PERMS['MODERATE_PENDING_SUBMITTED_HATS'] %}readonly{% endif %}>

View File

@ -36,7 +36,7 @@
<input id="submit-marsey" disabled type="submit" data-nonce="{{g.nonce}}" data-onclick="disable(this)" class="btn btn-primary ml-auto" value="Submit Marsey">
</div>
</div>
</form>
</form>
</div>
</div>
</div>
@ -55,10 +55,10 @@
<div class="d-lg-flex">
<div class="body w-lg-100">
<input type="hidden" name="formkey" value="{{v|formkey}}">
<div><label class="mt-3">Image</label></div>
<img loading="lazy" src="/asset_submissions/marseys/{{marsey.name}}.webp?s={{range(1, 10000000)|random}}" style="max-width:50%;border:5px white solid">
<div><label class="mt-3" for="{{marsey.name}}-submitter">Submitter</label></div>
<input autocomplete="off" type="text" id="{{marsey.name}}-submitter" class="form-control" maxlength="30" value="{{marsey.submitter}}" readonly>
@ -67,7 +67,7 @@
<label class="mt-3" for="{{marsey.name}}-name">Name</label>
<input autocomplete="off" type="text" id="{{marsey.name}}-name" class="form-control" name="name" maxlength="30" value="{{marsey.name}}" pattern='marsey[a-z0-9]{1,24}' placeholder="Required" required {% if v.admin_level < PERMS['MODERATE_PENDING_SUBMITTED_MARSEYS'] %}readonly{% endif %}>
<label class="mt-3" for="{{marsey.name}}-tags">Tags</label>
<input autocomplete="off" type="text" id="{{marsey.name}}-tags" class="form-control" name="tags" maxlength="200" value="{{marsey.tags}}" pattern='[a-z0-9: ]{1,200}' placeholder="Required" required {% if v.admin_level < PERMS['MODERATE_PENDING_SUBMITTED_MARSEYS'] %}readonly{% endif %}>
</div>

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