Merge branch 'frost' of https://github.com/Aevann1/Drama into frost
commit
2db414f12d
|
@ -47,4 +47,9 @@ class Sub(Base):
|
||||||
@property
|
@property
|
||||||
@lazy
|
@lazy
|
||||||
def block_num(self):
|
def block_num(self):
|
||||||
return len(self.blocks)
|
return len(self.blocks)
|
||||||
|
|
||||||
|
@property
|
||||||
|
@lazy
|
||||||
|
def follow_num(self):
|
||||||
|
return len(self.followers)
|
|
@ -90,6 +90,7 @@ class User(Base):
|
||||||
unmutable = Column(Boolean)
|
unmutable = Column(Boolean)
|
||||||
eye = Column(Boolean)
|
eye = Column(Boolean)
|
||||||
alt = Column(Boolean)
|
alt = Column(Boolean)
|
||||||
|
offsitementions = Column(Boolean, default=False, nullable=False)
|
||||||
frontsize = Column(Integer, default=25)
|
frontsize = Column(Integer, default=25)
|
||||||
controversial = Column(Boolean, default=False)
|
controversial = Column(Boolean, default=False)
|
||||||
bio = deferred(Column(String))
|
bio = deferred(Column(String))
|
||||||
|
@ -228,7 +229,11 @@ class User(Base):
|
||||||
if self.has_badge(badge): discount -= discounts[badge]
|
if self.has_badge(badge): discount -= discounts[badge]
|
||||||
|
|
||||||
return discount
|
return discount
|
||||||
|
|
||||||
|
@property
|
||||||
|
@lazy
|
||||||
|
def can_view_offsitementions(self):
|
||||||
|
return self.offsitementions or self.admin_level >= REDDIT_NOTIFS_JL_MIN
|
||||||
|
|
||||||
@property
|
@property
|
||||||
@lazy
|
@lazy
|
||||||
|
@ -446,22 +451,44 @@ class User(Base):
|
||||||
@property
|
@property
|
||||||
@lazy
|
@lazy
|
||||||
def post_notifications_count(self):
|
def post_notifications_count(self):
|
||||||
return g.db.query(Notification).join(Comment).filter(Notification.user_id == self.id, Notification.read == False, Comment.author_id == AUTOJANNY_ID).count()
|
return g.db.query(Notification).join(Comment).filter(
|
||||||
|
Notification.user_id == self.id, Notification.read == False,
|
||||||
|
Comment.author_id == AUTOJANNY_ID).count()
|
||||||
|
|
||||||
|
@property
|
||||||
|
@lazy
|
||||||
|
def modaction_notifications_count(self):
|
||||||
|
return g.db.query(Notification).join(Comment).filter(
|
||||||
|
Notification.user_id == self.id, Notification.read == False,
|
||||||
|
Comment.is_banned == False, Comment.deleted_utc == 0,
|
||||||
|
Comment.body_html.like(f'%<p>{NOTIF_MODACTION_PREFIX}%'),
|
||||||
|
Comment.parent_submission == None, Comment.author_id == NOTIFICATIONS_ID).count()
|
||||||
|
|
||||||
@property
|
@property
|
||||||
@lazy
|
@lazy
|
||||||
def reddit_notifications_count(self):
|
def reddit_notifications_count(self):
|
||||||
return g.db.query(Notification).join(Comment).filter(Notification.user_id == self.id, Notification.read == False, 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 == NOTIFICATIONS_ID).count()
|
return g.db.query(Notification).join(Comment).filter(
|
||||||
|
Notification.user_id == self.id, Notification.read == False,
|
||||||
|
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 == NOTIFICATIONS_ID).count()
|
||||||
|
|
||||||
@property
|
@property
|
||||||
@lazy
|
@lazy
|
||||||
def normal_count(self):
|
def normal_count(self):
|
||||||
return self.notifications_count - self.post_notifications_count - self.reddit_notifications_count
|
return self.notifications_count \
|
||||||
|
- self.post_notifications_count \
|
||||||
|
- self.modaction_notifications_count \
|
||||||
|
- self.reddit_notifications_count
|
||||||
|
|
||||||
@property
|
@property
|
||||||
@lazy
|
@lazy
|
||||||
def do_posts(self):
|
def do_posts(self):
|
||||||
return self.post_notifications_count and self.notifications_count-self.reddit_notifications_count == self.post_notifications_count
|
return self.post_notifications_count and \
|
||||||
|
self.post_notifications_count == (
|
||||||
|
self.notifications_count
|
||||||
|
- self.modaction_notifications_count
|
||||||
|
- self.reddit_notifications_count)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
@lazy
|
@lazy
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
from .__main__ import app, db_session
|
from .__main__ import app, db_session, cache
|
||||||
from flask import g
|
from flask import g
|
||||||
import files.helpers.cron
|
import files.helpers.cron
|
||||||
|
|
||||||
|
|
|
@ -5,12 +5,12 @@ from files.classes.badges import Badge, BadgeDef
|
||||||
# TODO: More sanity checks on passed parameters.
|
# TODO: More sanity checks on passed parameters.
|
||||||
# TODO: Add `replace=False` parameter which, when set true, removes any
|
# TODO: Add `replace=False` parameter which, when set true, removes any
|
||||||
# existing badge with identical id & user and replaces with new one.
|
# existing badge with identical id & user and replaces with new one.
|
||||||
def badge_grant(user_id, badge_id, desc='', url=''):
|
def badge_grant(user_id, badge_id, desc='', url='', commit=True):
|
||||||
user = g.db.query(User).filter(User.id == int(user_id)).one_or_none()
|
user = g.db.query(User).filter(User.id == int(user_id)).one_or_none()
|
||||||
if not user:
|
if not user:
|
||||||
return False
|
return None
|
||||||
elif user.has_badge(badge_id):
|
elif user.has_badge(badge_id):
|
||||||
return True
|
return None
|
||||||
|
|
||||||
badge = Badge(
|
badge = Badge(
|
||||||
badge_id=int(badge_id),
|
badge_id=int(badge_id),
|
||||||
|
@ -20,5 +20,8 @@ def badge_grant(user_id, badge_id, desc='', url=''):
|
||||||
)
|
)
|
||||||
|
|
||||||
g.db.add(badge)
|
g.db.add(badge)
|
||||||
g.db.commit()
|
if commit:
|
||||||
return True
|
g.db.commit()
|
||||||
|
else:
|
||||||
|
g.db.flush()
|
||||||
|
return badge
|
||||||
|
|
|
@ -114,4 +114,22 @@ def NOTIFY_USERS(text, v):
|
||||||
user = get_user(i.group(2), graceful=True)
|
user = get_user(i.group(2), graceful=True)
|
||||||
if user and v.id != user.id and not v.any_block_exists(user): notify_users.add(user.id)
|
if user and v.id != user.id and not v.any_block_exists(user): notify_users.add(user.id)
|
||||||
|
|
||||||
return notify_users - bots
|
return notify_users - bots
|
||||||
|
|
||||||
|
def notify_mod_action(by_id, msg):
|
||||||
|
body_html = sanitize(NOTIF_MODACTION_PREFIX + msg)
|
||||||
|
new_comment = Comment(
|
||||||
|
author_id=NOTIFICATIONS_ID,
|
||||||
|
parent_submission=None,
|
||||||
|
level=1,
|
||||||
|
body_html=body_html,
|
||||||
|
distinguish_level=6)
|
||||||
|
g.db.add(new_comment)
|
||||||
|
g.db.flush()
|
||||||
|
new_comment.top_comment_id = new_comment.id
|
||||||
|
|
||||||
|
send_to = g.db.query(User).filter(
|
||||||
|
User.admin_level >= NOTIF_MODACTION_JL_MIN, User.id != by_id).all()
|
||||||
|
for admin in send_to:
|
||||||
|
notif = Notification(comment_id=new_comment.id, user_id=admin.id)
|
||||||
|
g.db.add(notif)
|
||||||
|
|
|
@ -0,0 +1,83 @@
|
||||||
|
from flask import g
|
||||||
|
import time
|
||||||
|
from files.helpers.alerts import send_repeatable_notification
|
||||||
|
from files.helpers.const import bots
|
||||||
|
from files.helpers.discord import remove_role
|
||||||
|
from files.classes.badges import Badge
|
||||||
|
from files.classes.user import User
|
||||||
|
|
||||||
|
def award_timers(v, bot=False):
|
||||||
|
now = time.time()
|
||||||
|
dirty = False
|
||||||
|
|
||||||
|
def notify_if_not_bot(msg):
|
||||||
|
if not bot:
|
||||||
|
send_repeatable_notification(v.id,msg)
|
||||||
|
|
||||||
|
if v.patron_utc and v.patron_utc < now:
|
||||||
|
v.patron = 0
|
||||||
|
v.patron_utc = 0
|
||||||
|
notify_if_not_bot("Your paypig status has expired!")
|
||||||
|
if not bot and v.discord_id: remove_role(v, "1")
|
||||||
|
dirty = True
|
||||||
|
if v.unban_utc and v.unban_utc < now:
|
||||||
|
v.is_banned = 0
|
||||||
|
v.unban_utc = 0
|
||||||
|
v.ban_evade = 0
|
||||||
|
notify_if_not_bot("You have been unbanned!")
|
||||||
|
dirty = True
|
||||||
|
if v.agendaposter and v.agendaposter < now:
|
||||||
|
v.agendaposter = 0
|
||||||
|
notify_if_not_bot("Your chud theme has expired!")
|
||||||
|
badge = v.has_badge(28)
|
||||||
|
if badge: g.db.delete(badge)
|
||||||
|
dirty = True
|
||||||
|
if v.flairchanged and v.flairchanged < now:
|
||||||
|
v.flairchanged = None
|
||||||
|
notify_if_not_bot("Your flair lock has expired. You can now change your flair!")
|
||||||
|
badge = v.has_badge(96)
|
||||||
|
if badge: g.db.delete(badge)
|
||||||
|
dirty = True
|
||||||
|
if v.marseyawarded and v.marseyawarded < now:
|
||||||
|
v.marseyawarded = None
|
||||||
|
notify_if_not_bot("Your marsey award has expired!")
|
||||||
|
badge = v.has_badge(98)
|
||||||
|
if badge: g.db.delete(badge)
|
||||||
|
dirty = True
|
||||||
|
if v.longpost and v.longpost < now:
|
||||||
|
v.longpost = None
|
||||||
|
notify_if_not_bot("Your pizzashill award has expired!")
|
||||||
|
badge = v.has_badge(97)
|
||||||
|
if badge: g.db.delete(badge)
|
||||||
|
dirty = True
|
||||||
|
if v.bird and v.bird < now:
|
||||||
|
v.bird = None
|
||||||
|
notify_if_not_bot("Your bird site award has expired!")
|
||||||
|
badge = v.has_badge(95)
|
||||||
|
if badge: g.db.delete(badge)
|
||||||
|
dirty = True
|
||||||
|
if v.progressivestack and v.progressivestack < now:
|
||||||
|
v.progressivestack = None
|
||||||
|
notify_if_not_bot("Your progressive stack has expired!")
|
||||||
|
badge = v.has_badge(94)
|
||||||
|
if badge: g.db.delete(badge)
|
||||||
|
dirty = True
|
||||||
|
if v.rehab and v.rehab < now:
|
||||||
|
v.rehab = None
|
||||||
|
notify_if_not_bot("Your rehab has finished!")
|
||||||
|
badge = v.has_badge(109)
|
||||||
|
if badge: g.db.delete(badge)
|
||||||
|
dirty = True
|
||||||
|
if v.deflector and v.deflector < now:
|
||||||
|
v.deflector = None
|
||||||
|
notify_if_not_bot("Your deflector has expired!")
|
||||||
|
dirty = True
|
||||||
|
|
||||||
|
if dirty:
|
||||||
|
g.db.add(v)
|
||||||
|
g.db.commit()
|
||||||
|
|
||||||
|
def award_timers_bots_task():
|
||||||
|
accs = g.db.query(User).filter(User.id.in_(bots))
|
||||||
|
for u in accs:
|
||||||
|
award_timers(u, bot=True)
|
|
@ -132,9 +132,11 @@ PIN_LIMIT = 3
|
||||||
POST_RATE_LIMIT = "1/second;2/minute;10/hour;50/day"
|
POST_RATE_LIMIT = "1/second;2/minute;10/hour;50/day"
|
||||||
|
|
||||||
USER_TITLE_COST = 0
|
USER_TITLE_COST = 0
|
||||||
|
HOLE_INACTIVITY_DELETION = False
|
||||||
|
|
||||||
if SITE in {'rdrama.net','devrama.xyz'}:
|
if SITE in {'rdrama.net','devrama.xyz'}:
|
||||||
HOLE_COST = 50000
|
HOLE_COST = 50000
|
||||||
|
HOLE_INACTIVITY_DELETION = True
|
||||||
USER_TITLE_COST = 25
|
USER_TITLE_COST = 25
|
||||||
NOTIFICATIONS_ID = 1046
|
NOTIFICATIONS_ID = 1046
|
||||||
AUTOJANNY_ID = 2360
|
AUTOJANNY_ID = 2360
|
||||||
|
@ -660,6 +662,14 @@ AWARDS = {
|
||||||
"color": "text-silver",
|
"color": "text-silver",
|
||||||
"price": 10000
|
"price": 10000
|
||||||
},
|
},
|
||||||
|
"offsitementions": {
|
||||||
|
"kind": "offsitementions",
|
||||||
|
"title": "Y'all Seein' Eye",
|
||||||
|
"description": "Gives the recipient access to notifications when people off-site talk about us.",
|
||||||
|
"icon": "fas fa-eyes",
|
||||||
|
"color": "text-orange",
|
||||||
|
"price": 10000,
|
||||||
|
},
|
||||||
"unblockable": {
|
"unblockable": {
|
||||||
"kind": "unblockable",
|
"kind": "unblockable",
|
||||||
"title": "Unblockable",
|
"title": "Unblockable",
|
||||||
|
@ -799,8 +809,12 @@ FACTCHECK_REPLIES = ('<b style="color:#6023f8">Factcheck: This claim has been co
|
||||||
if SITE_NAME == 'rDrama': patron = 'Paypig'
|
if SITE_NAME == 'rDrama': patron = 'Paypig'
|
||||||
else: patron = 'Patron'
|
else: patron = 'Patron'
|
||||||
|
|
||||||
|
NOTIF_MODACTION_PREFIX = '[Modaction] '
|
||||||
|
NOTIF_MODACTION_JL_MIN = 2
|
||||||
|
|
||||||
REDDIT_NOTIFS_SITE = []
|
REDDIT_NOTIFS_SITE = []
|
||||||
REDDIT_NOTIFS_USERS = {}
|
REDDIT_NOTIFS_USERS = {}
|
||||||
|
REDDIT_NOTIFS_JL_MIN = 1
|
||||||
|
|
||||||
if SITE_NAME == 'rDrama':
|
if SITE_NAME == 'rDrama':
|
||||||
REDDIT_NOTIFS_SITE = ['rdrama', 'marsey',]
|
REDDIT_NOTIFS_SITE = ['rdrama', 'marsey',]
|
||||||
|
@ -814,6 +828,7 @@ if SITE_NAME == 'rDrama':
|
||||||
}
|
}
|
||||||
elif SITE_NAME == 'PCM':
|
elif SITE_NAME == 'PCM':
|
||||||
REDDIT_NOTIFS_SITE = ['pcmemes.net',]
|
REDDIT_NOTIFS_SITE = ['pcmemes.net',]
|
||||||
|
REDDIT_NOTIFS_JL_MIN = 3
|
||||||
|
|
||||||
discounts = {
|
discounts = {
|
||||||
# Big Spender badges, 2pp additive discount each
|
# Big Spender badges, 2pp additive discount each
|
||||||
|
@ -1035,17 +1050,16 @@ linefeeds_regex = re.compile("([^\n])\n([^\n])", flags=re.A)
|
||||||
def make_name(*args, **kwargs): return request.base_url
|
def make_name(*args, **kwargs): return request.base_url
|
||||||
|
|
||||||
# Lottery
|
# Lottery
|
||||||
|
LOTTERY_ENABLED = False
|
||||||
|
LOTTERY_TICKET_COST = 0
|
||||||
|
LOTTERY_SINK_RATE = 0
|
||||||
|
LOTTERY_ROYALTY_RATE = 0
|
||||||
|
LOTTERY_ROYALTY_ACCOUNT_ID = 0
|
||||||
|
LOTTERY_MANAGER_ACCOUNT_ID = 0
|
||||||
if SITE_NAME == 'rDrama':
|
if SITE_NAME == 'rDrama':
|
||||||
LOTTERY_ENABLED = True
|
LOTTERY_ENABLED = True
|
||||||
LOTTERY_TICKET_COST = 12
|
LOTTERY_TICKET_COST = 12
|
||||||
LOTTERY_SINK_RATE = 3
|
LOTTERY_SINK_RATE = 3
|
||||||
LOTTERY_ROYALTY_RATE = 1
|
LOTTERY_ROYALTY_RATE = 0
|
||||||
LOTTERY_ROYALTY_ACCOUNT_ID = 1387 # (Chapose)
|
LOTTERY_ROYALTY_ACCOUNT_ID = 1387 # (Chapose)
|
||||||
LOTTERY_MANAGER_ACCOUNT_ID = 11651 # (Lottershe)
|
LOTTERY_MANAGER_ACCOUNT_ID = 11651 # (Lottershe)
|
||||||
else:
|
|
||||||
LOTTERY_ENABLED = False
|
|
||||||
LOTTERY_TICKET_COST = 0
|
|
||||||
LOTTERY_SINK_RATE = 0
|
|
||||||
LOTTERY_ROYALTY_RATE = 0
|
|
||||||
LOTTERY_ROYALTY_ACCOUNT_ID = 0
|
|
||||||
LOTTERY_MANAGER_ACCOUNT_ID = 0
|
|
|
@ -5,6 +5,9 @@ import files.helpers.const as const
|
||||||
import files.helpers.lottery as lottery
|
import files.helpers.lottery as lottery
|
||||||
import files.helpers.offsitementions as offsitementions
|
import files.helpers.offsitementions as offsitementions
|
||||||
import files.helpers.stats as stats
|
import files.helpers.stats as stats
|
||||||
|
import files.helpers.awards as awards
|
||||||
|
import files.routes.static as route_static
|
||||||
|
from files.routes.subs import sub_inactive_purge_task
|
||||||
|
|
||||||
@app.cli.command('cron', help='Run scheduled tasks.')
|
@app.cli.command('cron', help='Run scheduled tasks.')
|
||||||
@click.option('--every-5m', is_flag=True, help='Call every 5 minutes.')
|
@click.option('--every-5m', is_flag=True, help='Call every 5 minutes.')
|
||||||
|
@ -22,4 +25,8 @@ def cron(every_5m, every_1h, every_1d):
|
||||||
|
|
||||||
if every_1d:
|
if every_1d:
|
||||||
stats.generate_charts_task(const.SITE)
|
stats.generate_charts_task(const.SITE)
|
||||||
|
route_static.stats_cached()
|
||||||
|
awards.award_timers_bots_task()
|
||||||
|
sub_inactive_purge_task()
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -92,6 +92,8 @@ def check_if_end_lottery_task():
|
||||||
start_new_lottery_session()
|
start_new_lottery_session()
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
def lottery_ticket_net_value():
|
||||||
|
return LOTTERY_TICKET_COST - LOTTERY_SINK_RATE - LOTTERY_ROYALTY_RATE
|
||||||
|
|
||||||
def purchase_lottery_tickets(v, quantity=1):
|
def purchase_lottery_tickets(v, quantity=1):
|
||||||
if quantity < 1:
|
if quantity < 1:
|
||||||
|
@ -107,7 +109,7 @@ def purchase_lottery_tickets(v, quantity=1):
|
||||||
v.currently_held_lottery_tickets += quantity
|
v.currently_held_lottery_tickets += quantity
|
||||||
v.total_held_lottery_tickets += quantity
|
v.total_held_lottery_tickets += quantity
|
||||||
|
|
||||||
net_ticket_value = (LOTTERY_TICKET_COST - LOTTERY_SINK_RATE - LOTTERY_ROYALTY_RATE) * quantity
|
net_ticket_value = lottery_ticket_net_value() * quantity
|
||||||
most_recent_lottery.prize += net_ticket_value
|
most_recent_lottery.prize += net_ticket_value
|
||||||
most_recent_lottery.tickets_sold += quantity
|
most_recent_lottery.tickets_sold += quantity
|
||||||
|
|
||||||
|
@ -115,7 +117,7 @@ def purchase_lottery_tickets(v, quantity=1):
|
||||||
|
|
||||||
beneficiary = g.db.query(User).get(LOTTERY_ROYALTY_ACCOUNT_ID)
|
beneficiary = g.db.query(User).get(LOTTERY_ROYALTY_ACCOUNT_ID)
|
||||||
|
|
||||||
if beneficiary:
|
if beneficiary and LOTTERY_ROYALTY_RATE:
|
||||||
beneficiary.coins += LOTTERY_ROYALTY_RATE * quantity
|
beneficiary.coins += LOTTERY_ROYALTY_RATE * quantity
|
||||||
|
|
||||||
g.db.commit()
|
g.db.commit()
|
||||||
|
@ -128,16 +130,16 @@ def grant_lottery_proceeds_to_manager(prize_value):
|
||||||
if manager:
|
if manager:
|
||||||
manager.coins += prize_value
|
manager.coins += prize_value
|
||||||
|
|
||||||
def grant_lottery_tickets_to_user(v, amount):
|
def grant_lottery_tickets_to_user(v, quantity):
|
||||||
active_lottery = get_active_lottery()
|
active_lottery = get_active_lottery()
|
||||||
prize_value = amount * LOTTERY_TICKET_COST
|
prize_value = lottery_ticket_net_value() * quantity
|
||||||
|
|
||||||
if active_lottery:
|
if active_lottery:
|
||||||
v.currently_held_lottery_tickets += amount
|
v.currently_held_lottery_tickets += quantity
|
||||||
v.total_held_lottery_tickets += amount
|
v.total_held_lottery_tickets += quantity
|
||||||
|
|
||||||
active_lottery.prize += prize_value
|
active_lottery.prize += prize_value
|
||||||
active_lottery.tickets_sold += amount
|
active_lottery.tickets_sold += quantity
|
||||||
|
|
||||||
grant_lottery_proceeds_to_manager(prize_value)
|
grant_lottery_proceeds_to_manager(prize_value)
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
from flask import g
|
from flask import g
|
||||||
import itertools
|
import itertools
|
||||||
import requests
|
import requests
|
||||||
|
from sqlalchemy import _or
|
||||||
import files.helpers.const as const
|
import files.helpers.const as const
|
||||||
from files.classes.user import User
|
from files.classes.user import User
|
||||||
from files.classes.comment import Comment
|
from files.classes.comment import Comment
|
||||||
|
@ -13,9 +14,9 @@ from files.classes.notifications import Notification
|
||||||
|
|
||||||
def offsite_mentions_task():
|
def offsite_mentions_task():
|
||||||
if const.REDDIT_NOTIFS_SITE:
|
if const.REDDIT_NOTIFS_SITE:
|
||||||
# Site-specific logic: send to JL1+, except on PCM JL3+
|
row_send_to = g.db.query(User.id)
|
||||||
jl_min = 3 if const.SITE_NAME == 'PCM' else 1
|
.filter(_or(User.admin_level >= const.REDDIT_NOTIFS_JL_MIN,
|
||||||
row_send_to = g.db.query(User.id).filter(User.admin_level >= jl_min).all()
|
User.offsitementions == True)).all()
|
||||||
send_to = [x[0] for x in row_send_to]
|
send_to = [x[0] for x in row_send_to]
|
||||||
|
|
||||||
site_mentions = get_mentions(const.REDDIT_NOTIFS_SITE)
|
site_mentions = get_mentions(const.REDDIT_NOTIFS_SITE)
|
||||||
|
|
|
@ -2,10 +2,14 @@ from flask import g
|
||||||
import time
|
import time
|
||||||
import calendar
|
import calendar
|
||||||
import matplotlib.pyplot as plt
|
import matplotlib.pyplot as plt
|
||||||
|
from sqlalchemy import *
|
||||||
|
|
||||||
from files.classes.user import User
|
from files.classes.user import User
|
||||||
from files.classes.submission import Submission
|
from files.classes.submission import Submission
|
||||||
from files.classes.comment import Comment
|
from files.classes.comment import Comment
|
||||||
|
from files.classes.votes import Vote, CommentVote
|
||||||
|
from files.classes.marsey import Marsey
|
||||||
|
from files.classes.award import AwardRelationship
|
||||||
from files.helpers.const import *
|
from files.helpers.const import *
|
||||||
|
|
||||||
def generate_charts_task(site):
|
def generate_charts_task(site):
|
||||||
|
@ -85,3 +89,58 @@ def chart(kind, site):
|
||||||
|
|
||||||
def chart_path(kind, site):
|
def chart_path(kind, site):
|
||||||
return f'/{site}_{kind}.png'
|
return f'/{site}_{kind}.png'
|
||||||
|
|
||||||
|
def stats(site=None):
|
||||||
|
day = int(time.time()) - 86400
|
||||||
|
week = int(time.time()) - 604800
|
||||||
|
posters = g.db.query(Submission.author_id).distinct(Submission.author_id).filter(Submission.created_utc > week).all()
|
||||||
|
commenters = g.db.query(Comment.author_id).distinct(Comment.author_id).filter(Comment.created_utc > week).all()
|
||||||
|
voters = g.db.query(Vote.user_id).distinct(Vote.user_id).filter(Vote.created_utc > week).all()
|
||||||
|
commentvoters = g.db.query(CommentVote.user_id).distinct(CommentVote.user_id).filter(CommentVote.created_utc > week).all()
|
||||||
|
active_users = set(posters) | set(commenters) | set(voters) | set(commentvoters)
|
||||||
|
|
||||||
|
stats = {
|
||||||
|
"marseys": g.db.query(Marsey).count(),
|
||||||
|
"users": g.db.query(User).count(),
|
||||||
|
"private users": g.db.query(User).filter_by(is_private=True).count(),
|
||||||
|
"banned users": g.db.query(User).filter(User.is_banned > 0).count(),
|
||||||
|
"verified email users": g.db.query(User).filter_by(is_activated=True).count(),
|
||||||
|
"coins in circulation": g.db.query(func.sum(User.coins)).scalar(),
|
||||||
|
"total shop sales": g.db.query(func.sum(User.coins_spent)).scalar(),
|
||||||
|
"signups last 24h": g.db.query(User).filter(User.created_utc > day).count(),
|
||||||
|
"total posts": g.db.query(Submission).count(),
|
||||||
|
"posting users": g.db.query(Submission.author_id).distinct().count(),
|
||||||
|
"listed posts": g.db.query(Submission).filter_by(is_banned=False).filter(Submission.deleted_utc == 0).count(),
|
||||||
|
"removed posts (by admins)": g.db.query(Submission).filter_by(is_banned=True).count(),
|
||||||
|
"deleted posts (by author)": g.db.query(Submission).filter(Submission.deleted_utc > 0).count(),
|
||||||
|
"posts last 24h": g.db.query(Submission).filter(Submission.created_utc > day).count(),
|
||||||
|
"total comments": g.db.query(Comment).filter(Comment.author_id.notin_((AUTOJANNY_ID,NOTIFICATIONS_ID))).count(),
|
||||||
|
"commenting users": g.db.query(Comment.author_id).distinct().count(),
|
||||||
|
"removed comments (by admins)": g.db.query(Comment).filter_by(is_banned=True).count(),
|
||||||
|
"deleted comments (by author)": g.db.query(Comment).filter(Comment.deleted_utc > 0).count(),
|
||||||
|
"comments last_24h": g.db.query(Comment).filter(Comment.created_utc > day, Comment.author_id.notin_((AUTOJANNY_ID,NOTIFICATIONS_ID))).count(),
|
||||||
|
"post votes": g.db.query(Vote).count(),
|
||||||
|
"post voting users": g.db.query(Vote.user_id).distinct().count(),
|
||||||
|
"comment votes": g.db.query(CommentVote).count(),
|
||||||
|
"comment voting users": g.db.query(CommentVote.user_id).distinct().count(),
|
||||||
|
"total upvotes": g.db.query(Vote).filter_by(vote_type=1).count() + g.db.query(CommentVote.comment_id).filter_by(vote_type=1).count(),
|
||||||
|
"total downvotes": g.db.query(Vote).filter_by(vote_type=-1).count() + g.db.query(CommentVote.comment_id).filter_by(vote_type=-1).count(),
|
||||||
|
"total awards": g.db.query(AwardRelationship).count(),
|
||||||
|
"awards given": g.db.query(AwardRelationship).filter(or_(AwardRelationship.submission_id != None, AwardRelationship.comment_id != None)).count(),
|
||||||
|
"users who posted, commented, or voted in the past 7 days": len(active_users),
|
||||||
|
}
|
||||||
|
|
||||||
|
if site == 'rDrama':
|
||||||
|
stats2 = {
|
||||||
|
"House furry members": g.db.query(User).filter(User.house.like('Furry%')).count(),
|
||||||
|
"House femboy members": g.db.query(User).filter(User.house.like('Femboy%')).count(),
|
||||||
|
"House vampire members": g.db.query(User).filter(User.house.like('Vampire%')).count(),
|
||||||
|
"House racist members": g.db.query(User).filter(User.house.like('Racist%')).count(),
|
||||||
|
"House furry total truescore": g.db.query(func.sum(User.truecoins)).filter(User.house.like('Furry%')).scalar(),
|
||||||
|
"House femboy total truescore": g.db.query(func.sum(User.truecoins)).filter(User.house.like('Femboy%')).scalar(),
|
||||||
|
"House vampire total truescore": g.db.query(func.sum(User.truecoins)).filter(User.house.like('Vampire%')).scalar(),
|
||||||
|
"House racist total truescore": g.db.query(func.sum(User.truecoins)).filter(User.house.like('Racist%')).scalar(),
|
||||||
|
}
|
||||||
|
stats.update(stats2)
|
||||||
|
|
||||||
|
return stats
|
||||||
|
|
|
@ -527,25 +527,7 @@ def change_settings(v, setting):
|
||||||
if site_settings[setting]: word = 'enable'
|
if site_settings[setting]: word = 'enable'
|
||||||
else: word = 'disable'
|
else: word = 'disable'
|
||||||
|
|
||||||
body = f"@{v.username} has {word}d `{setting}` in the [admin dashboard](/admin)!"
|
notify_mod_action(v.id, f"@{v.username} has {word}d `{setting}` in the [admin dashboard](/admin)!")
|
||||||
|
|
||||||
body_html = sanitize(body)
|
|
||||||
|
|
||||||
new_comment = Comment(author_id=NOTIFICATIONS_ID,
|
|
||||||
parent_submission=None,
|
|
||||||
level=1,
|
|
||||||
body_html=body_html,
|
|
||||||
sentto=2,
|
|
||||||
distinguish_level=6
|
|
||||||
)
|
|
||||||
g.db.add(new_comment)
|
|
||||||
g.db.flush()
|
|
||||||
|
|
||||||
new_comment.top_comment_id = new_comment.id
|
|
||||||
|
|
||||||
for admin in g.db.query(User).filter(User.admin_level > 2, User.id != v.id).all():
|
|
||||||
notif = Notification(comment_id=new_comment.id, user_id=admin.id)
|
|
||||||
g.db.add(notif)
|
|
||||||
|
|
||||||
ma = ModAction(
|
ma = ModAction(
|
||||||
kind=f"{word}_{setting}",
|
kind=f"{word}_{setting}",
|
||||||
|
@ -1018,29 +1000,7 @@ def shadowban(user_id, v):
|
||||||
g.db.add(ma)
|
g.db.add(ma)
|
||||||
|
|
||||||
cache.delete_memoized(frontlist)
|
cache.delete_memoized(frontlist)
|
||||||
|
notify_mod_action(v.id, f"@{v.username} has shadowbanned @{user.username}")
|
||||||
body = f"@{v.username} has shadowbanned @{user.username}"
|
|
||||||
|
|
||||||
body_html = sanitize(body)
|
|
||||||
|
|
||||||
|
|
||||||
new_comment = Comment(author_id=NOTIFICATIONS_ID,
|
|
||||||
parent_submission=None,
|
|
||||||
level=1,
|
|
||||||
body_html=body_html,
|
|
||||||
distinguish_level=6
|
|
||||||
)
|
|
||||||
g.db.add(new_comment)
|
|
||||||
g.db.flush()
|
|
||||||
|
|
||||||
new_comment.top_comment_id = new_comment.id
|
|
||||||
|
|
||||||
for admin in g.db.query(User).filter(User.admin_level > 2, User.id != v.id).all():
|
|
||||||
notif = Notification(comment_id=new_comment.id, user_id=admin.id)
|
|
||||||
g.db.add(notif)
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
g.db.commit()
|
g.db.commit()
|
||||||
return {"message": "User shadowbanned!"}
|
return {"message": "User shadowbanned!"}
|
||||||
|
|
||||||
|
@ -1176,28 +1136,7 @@ def ban_user(user_id, v):
|
||||||
g.db.add(comment)
|
g.db.add(comment)
|
||||||
except: pass
|
except: pass
|
||||||
|
|
||||||
|
notify_mod_action(v.id, f"@{v.username} has banned @{user.username} ({note})")
|
||||||
body = f"@{v.username} has banned @{user.username} ({note})"
|
|
||||||
|
|
||||||
body_html = sanitize(body)
|
|
||||||
|
|
||||||
|
|
||||||
new_comment = Comment(author_id=NOTIFICATIONS_ID,
|
|
||||||
parent_submission=None,
|
|
||||||
level=1,
|
|
||||||
body_html=body_html,
|
|
||||||
distinguish_level=6
|
|
||||||
)
|
|
||||||
g.db.add(new_comment)
|
|
||||||
g.db.flush()
|
|
||||||
|
|
||||||
new_comment.top_comment_id = new_comment.id
|
|
||||||
|
|
||||||
for admin in g.db.query(User).filter(User.admin_level > 2, User.id != v.id).all():
|
|
||||||
notif = Notification(comment_id=new_comment.id, user_id=admin.id)
|
|
||||||
g.db.add(notif)
|
|
||||||
|
|
||||||
|
|
||||||
g.db.commit()
|
g.db.commit()
|
||||||
|
|
||||||
if 'redir' in request.values: return redirect(user.url)
|
if 'redir' in request.values: return redirect(user.url)
|
||||||
|
@ -1273,23 +1212,10 @@ def ban_post(post_id, v):
|
||||||
g.db.add(v)
|
g.db.add(v)
|
||||||
|
|
||||||
if v.id != post.author_id:
|
if v.id != post.author_id:
|
||||||
body = f"@{v.username} has removed [{post.title}]({post.shortlink})"
|
notify_mod_action(v.id, f"@{v.username} has removed [{post.title}]({post.shortlink})")
|
||||||
body_html = sanitize(body)
|
|
||||||
new_comment = Comment(author_id=NOTIFICATIONS_ID,
|
|
||||||
parent_submission=None,
|
|
||||||
level=1,
|
|
||||||
body_html=body_html,
|
|
||||||
distinguish_level=6
|
|
||||||
)
|
|
||||||
g.db.add(new_comment)
|
|
||||||
g.db.flush()
|
|
||||||
new_comment.top_comment_id = new_comment.id
|
|
||||||
for admin in g.db.query(User).filter(User.admin_level > 2, User.id != v.id).all():
|
|
||||||
notif = Notification(comment_id=new_comment.id, user_id=admin.id)
|
|
||||||
g.db.add(notif)
|
|
||||||
|
|
||||||
requests.post(f'https://api.cloudflare.com/client/v4/zones/{CF_ZONE}/purge_cache', headers=CF_HEADERS, json={'files': [f"{SITE_FULL}/logged_out/"]}, timeout=5)
|
|
||||||
|
|
||||||
|
requests.post(f'https://api.cloudflare.com/client/v4/zones/{CF_ZONE}/purge_cache',
|
||||||
|
headers=CF_HEADERS, json={'files': [f"{SITE_FULL}/logged_out/"]}, timeout=5)
|
||||||
g.db.commit()
|
g.db.commit()
|
||||||
|
|
||||||
return {"message": "Post removed!"}
|
return {"message": "Post removed!"}
|
||||||
|
@ -1492,20 +1418,7 @@ def api_ban_comment(c_id, v):
|
||||||
g.db.add(ma)
|
g.db.add(ma)
|
||||||
|
|
||||||
if v.id != comment.author_id:
|
if v.id != comment.author_id:
|
||||||
body = f"@{v.username} has removed [comment]({comment.shortlink})"
|
notify_mod_action(v.id, f"@{v.username} has removed [comment]({comment.shortlink})")
|
||||||
body_html = sanitize(body)
|
|
||||||
new_comment = Comment(author_id=NOTIFICATIONS_ID,
|
|
||||||
parent_submission=None,
|
|
||||||
level=1,
|
|
||||||
body_html=body_html,
|
|
||||||
distinguish_level=6
|
|
||||||
)
|
|
||||||
g.db.add(new_comment)
|
|
||||||
g.db.flush()
|
|
||||||
new_comment.top_comment_id = new_comment.id
|
|
||||||
for admin in g.db.query(User).filter(User.admin_level > 2, User.id != v.id).all():
|
|
||||||
notif = Notification(comment_id=new_comment.id, user_id=admin.id)
|
|
||||||
g.db.add(notif)
|
|
||||||
|
|
||||||
g.db.commit()
|
g.db.commit()
|
||||||
return {"message": "Comment removed!"}
|
return {"message": "Comment removed!"}
|
||||||
|
|
|
@ -4,6 +4,7 @@ from files.helpers.alerts import *
|
||||||
from files.helpers.get import *
|
from files.helpers.get import *
|
||||||
from files.helpers.const import *
|
from files.helpers.const import *
|
||||||
from files.helpers.discord import *
|
from files.helpers.discord import *
|
||||||
|
from files.helpers.actions import badge_grant
|
||||||
from files.classes.award import *
|
from files.classes.award import *
|
||||||
from .front import frontlist
|
from .front import frontlist
|
||||||
from flask import g, request
|
from flask import g, request
|
||||||
|
@ -301,6 +302,10 @@ def award_thing(v, thing_type, id):
|
||||||
g.db.add(new_badge)
|
g.db.add(new_badge)
|
||||||
g.db.flush()
|
g.db.flush()
|
||||||
send_notification(author.id, f"@AutoJanny has given you the following profile badge:\n\n![]({new_badge.path})\n\n{new_badge.name}")
|
send_notification(author.id, f"@AutoJanny has given you the following profile badge:\n\n![]({new_badge.path})\n\n{new_badge.name}")
|
||||||
|
elif kind == "offsitementions":
|
||||||
|
author.offsitementions = True
|
||||||
|
new_badge = badge_grant(user_id=author.id, badge_id=140, commit=False)
|
||||||
|
send_notification(author.id, f"@AutoJanny has given you the following profile badge:\n\n![]({new_badge.path})\n\n{new_badge.name}")
|
||||||
elif kind == "alt":
|
elif kind == "alt":
|
||||||
author.alt = True
|
author.alt = True
|
||||||
if not author.has_badge(84):
|
if not author.has_badge(84):
|
||||||
|
@ -443,3 +448,4 @@ def admin_userawards_post(v):
|
||||||
|
|
||||||
if v.admin_level != 3: return render_template("admin/awards.html", awards=list(AWARDS3.values()), v=v)
|
if v.admin_level != 3: return render_template("admin/awards.html", awards=list(AWARDS3.values()), v=v)
|
||||||
return render_template("admin/awards.html", awards=list(AWARDS.values()), v=v)
|
return render_template("admin/awards.html", awards=list(AWARDS.values()), v=v)
|
||||||
|
|
||||||
|
|
|
@ -3,6 +3,7 @@ from files.helpers.get import *
|
||||||
from files.helpers.discord import *
|
from files.helpers.discord import *
|
||||||
from files.__main__ import app, cache, limiter
|
from files.__main__ import app, cache, limiter
|
||||||
from files.classes.submission import Submission
|
from files.classes.submission import Submission
|
||||||
|
from files.helpers.awards import award_timers
|
||||||
|
|
||||||
defaulttimefilter = environ.get("DEFAULT_TIME_FILTER", "all").strip()
|
defaulttimefilter = environ.get("DEFAULT_TIME_FILTER", "all").strip()
|
||||||
|
|
||||||
|
@ -43,9 +44,10 @@ def notifications(v):
|
||||||
|
|
||||||
messages = request.values.get('messages')
|
messages = request.values.get('messages')
|
||||||
modmail = request.values.get('modmail')
|
modmail = request.values.get('modmail')
|
||||||
|
modactions = request.values.get('modactions')
|
||||||
posts = request.values.get('posts')
|
posts = request.values.get('posts')
|
||||||
reddit = request.values.get('reddit')
|
reddit = request.values.get('reddit')
|
||||||
if modmail and v.admin_level > 1:
|
if modmail and v.admin_level >= 2:
|
||||||
comments = g.db.query(Comment).filter(Comment.sentto==2).order_by(Comment.id.desc()).offset(25*(page-1)).limit(26).all()
|
comments = g.db.query(Comment).filter(Comment.sentto==2).order_by(Comment.id.desc()).offset(25*(page-1)).limit(26).all()
|
||||||
next_exists = (len(comments) > 25)
|
next_exists = (len(comments) > 25)
|
||||||
listing = comments[:25]
|
listing = comments[:25]
|
||||||
|
@ -72,7 +74,25 @@ def notifications(v):
|
||||||
if n.created_utc > 1620391248: c.notif_utc = n.created_utc
|
if n.created_utc > 1620391248: c.notif_utc = n.created_utc
|
||||||
listing.append(c)
|
listing.append(c)
|
||||||
|
|
||||||
g.db.commit()
|
next_exists = (len(notifications) > len(listing))
|
||||||
|
elif modactions:
|
||||||
|
notifications = g.db.query(Notification, Comment) \
|
||||||
|
.join(Comment, Notification.comment_id == Comment.id) \
|
||||||
|
.filter(Notification.user_id == v.id,
|
||||||
|
Comment.body_html.like(f'%<p>{NOTIF_MODACTION_PREFIX}%'),
|
||||||
|
Comment.parent_submission == None, Comment.author_id == NOTIFICATIONS_ID) \
|
||||||
|
.order_by(Notification.created_utc.desc()).offset(25 * (page - 1)).limit(101).all()
|
||||||
|
listing = []
|
||||||
|
|
||||||
|
for index, x in enumerate(notifications[:100]):
|
||||||
|
n, c = x
|
||||||
|
if n.read and index > 24: break
|
||||||
|
elif not n.read:
|
||||||
|
n.read = True
|
||||||
|
c.unread = True
|
||||||
|
g.db.add(n)
|
||||||
|
if n.created_utc > 1620391248: c.notif_utc = n.created_utc
|
||||||
|
listing.append(c)
|
||||||
|
|
||||||
next_exists = (len(notifications) > len(listing))
|
next_exists = (len(notifications) > len(listing))
|
||||||
elif reddit:
|
elif reddit:
|
||||||
|
@ -90,8 +110,6 @@ def notifications(v):
|
||||||
if n.created_utc > 1620391248: c.notif_utc = n.created_utc
|
if n.created_utc > 1620391248: c.notif_utc = n.created_utc
|
||||||
listing.append(c)
|
listing.append(c)
|
||||||
|
|
||||||
g.db.commit()
|
|
||||||
|
|
||||||
next_exists = (len(notifications) > len(listing))
|
next_exists = (len(notifications) > len(listing))
|
||||||
else:
|
else:
|
||||||
comments = g.db.query(Comment, Notification).join(Notification, Notification.comment_id == Comment.id).filter(
|
comments = g.db.query(Comment, Notification).join(Notification, Notification.comment_id == Comment.id).filter(
|
||||||
|
@ -99,7 +117,8 @@ def notifications(v):
|
||||||
Comment.is_banned == False,
|
Comment.is_banned == False,
|
||||||
Comment.deleted_utc == 0,
|
Comment.deleted_utc == 0,
|
||||||
Comment.author_id != AUTOJANNY_ID,
|
Comment.author_id != AUTOJANNY_ID,
|
||||||
Comment.body_html.notlike('%<p>New site mention: <a href="https://old.reddit.com/r/%')
|
Comment.body_html.notlike('%<p>New site mention: <a href="https://old.reddit.com/r/%'),
|
||||||
|
Comment.body_html.notlike(f'%<p>{NOTIF_MODACTION_PREFIX}%')
|
||||||
).order_by(Notification.created_utc.desc())
|
).order_by(Notification.created_utc.desc())
|
||||||
|
|
||||||
if not (v and (v.shadowbanned or v.admin_level > 2)):
|
if not (v and (v.shadowbanned or v.admin_level > 2)):
|
||||||
|
@ -153,7 +172,8 @@ def notifications(v):
|
||||||
next_exists=next_exists,
|
next_exists=next_exists,
|
||||||
page=page,
|
page=page,
|
||||||
standalone=True,
|
standalone=True,
|
||||||
render_replies=True
|
render_replies=True,
|
||||||
|
NOTIF_MODACTION_JL_MIN=NOTIF_MODACTION_JL_MIN,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@ -219,85 +239,7 @@ def front_all(v, sub=None, subdomain=None):
|
||||||
|
|
||||||
if v:
|
if v:
|
||||||
if v.hidevotedon: posts = [x for x in posts if not hasattr(x, 'voted') or not x.voted]
|
if v.hidevotedon: posts = [x for x in posts if not hasattr(x, 'voted') or not x.voted]
|
||||||
|
award_timers(v)
|
||||||
|
|
||||||
if v.patron_utc and v.patron_utc < time.time():
|
|
||||||
v.patron = 0
|
|
||||||
v.patron_utc = 0
|
|
||||||
send_repeatable_notification(v.id, "Your paypig status has expired!")
|
|
||||||
if v.discord_id: remove_role(v, "1")
|
|
||||||
g.db.add(v)
|
|
||||||
g.db.commit()
|
|
||||||
|
|
||||||
if v.unban_utc and v.unban_utc < time.time():
|
|
||||||
v.is_banned = 0
|
|
||||||
v.unban_utc = 0
|
|
||||||
v.ban_evade = 0
|
|
||||||
send_repeatable_notification(v.id, "You have been unbanned!")
|
|
||||||
g.db.add(v)
|
|
||||||
g.db.commit()
|
|
||||||
|
|
||||||
if v.agendaposter and v.agendaposter < time.time():
|
|
||||||
v.agendaposter = 0
|
|
||||||
send_repeatable_notification(v.id, "Your chud theme has expired!")
|
|
||||||
g.db.add(v)
|
|
||||||
badge = v.has_badge(28)
|
|
||||||
if badge: g.db.delete(badge)
|
|
||||||
g.db.commit()
|
|
||||||
|
|
||||||
if v.flairchanged and v.flairchanged < time.time():
|
|
||||||
v.flairchanged = None
|
|
||||||
send_repeatable_notification(v.id, "Your flair lock has expired. You can now change your flair!")
|
|
||||||
g.db.add(v)
|
|
||||||
badge = v.has_badge(96)
|
|
||||||
if badge: g.db.delete(badge)
|
|
||||||
g.db.commit()
|
|
||||||
|
|
||||||
if v.marseyawarded and v.marseyawarded < time.time():
|
|
||||||
v.marseyawarded = None
|
|
||||||
send_repeatable_notification(v.id, "Your marsey award has expired!")
|
|
||||||
g.db.add(v)
|
|
||||||
badge = v.has_badge(98)
|
|
||||||
if badge: g.db.delete(badge)
|
|
||||||
g.db.commit()
|
|
||||||
|
|
||||||
if v.longpost and v.longpost < time.time():
|
|
||||||
v.longpost = None
|
|
||||||
send_repeatable_notification(v.id, "Your pizzashill award has expired!")
|
|
||||||
g.db.add(v)
|
|
||||||
badge = v.has_badge(97)
|
|
||||||
if badge: g.db.delete(badge)
|
|
||||||
g.db.commit()
|
|
||||||
|
|
||||||
if v.bird and v.bird < time.time():
|
|
||||||
v.bird = None
|
|
||||||
send_repeatable_notification(v.id, "Your bird site award has expired!")
|
|
||||||
g.db.add(v)
|
|
||||||
badge = v.has_badge(95)
|
|
||||||
if badge: g.db.delete(badge)
|
|
||||||
g.db.commit()
|
|
||||||
|
|
||||||
if v.progressivestack and v.progressivestack < time.time():
|
|
||||||
v.progressivestack = None
|
|
||||||
send_repeatable_notification(v.id, "Your progressive stack has expired!")
|
|
||||||
g.db.add(v)
|
|
||||||
badge = v.has_badge(94)
|
|
||||||
if badge: g.db.delete(badge)
|
|
||||||
g.db.commit()
|
|
||||||
|
|
||||||
if v.rehab and v.rehab < time.time():
|
|
||||||
v.rehab = None
|
|
||||||
send_repeatable_notification(v.id, "Your rehab has finished!")
|
|
||||||
g.db.add(v)
|
|
||||||
badge = v.has_badge(109)
|
|
||||||
if badge: g.db.delete(badge)
|
|
||||||
g.db.commit()
|
|
||||||
|
|
||||||
if v.deflector and v.deflector < time.time():
|
|
||||||
v.deflector = None
|
|
||||||
send_repeatable_notification(v.id, "Your deflector has expired!")
|
|
||||||
g.db.add(v)
|
|
||||||
g.db.commit()
|
|
||||||
|
|
||||||
if request.headers.get("Authorization"): return {"data": [x.json for x in posts], "next_exists": next_exists}
|
if request.headers.get("Authorization"): return {"data": [x.json for x in posts], "next_exists": next_exists}
|
||||||
return render_template("home.html", v=v, listing=posts, next_exists=next_exists, sort=sort, t=t, page=page, ccmode=ccmode, sub=sub, home=True)
|
return render_template("home.html", v=v, listing=posts, next_exists=next_exists, sort=sort, t=t, page=page, ccmode=ccmode, sub=sub, home=True)
|
||||||
|
|
|
@ -69,151 +69,12 @@ def sidebar(v):
|
||||||
@app.get("/stats")
|
@app.get("/stats")
|
||||||
@auth_required
|
@auth_required
|
||||||
def participation_stats(v):
|
def participation_stats(v):
|
||||||
|
return render_template("admin/content_stats.html",
|
||||||
return render_template("admin/content_stats.html", v=v, title="Content Statistics", data=stats(site=SITE))
|
v=v, title="Content Statistics", data=stats_cached())
|
||||||
|
|
||||||
|
|
||||||
@cache.memoize(timeout=86400)
|
@cache.memoize(timeout=86400)
|
||||||
def stats(site=None):
|
def stats_cached():
|
||||||
day = int(time.time()) - 86400
|
return statshelper.stats(SITE_NAME)
|
||||||
|
|
||||||
week = int(time.time()) - 604800
|
|
||||||
posters = g.db.query(Submission.author_id).distinct(Submission.author_id).filter(Submission.created_utc > week).all()
|
|
||||||
commenters = g.db.query(Comment.author_id).distinct(Comment.author_id).filter(Comment.created_utc > week).all()
|
|
||||||
voters = g.db.query(Vote.user_id).distinct(Vote.user_id).filter(Vote.created_utc > week).all()
|
|
||||||
commentvoters = g.db.query(CommentVote.user_id).distinct(CommentVote.user_id).filter(CommentVote.created_utc > week).all()
|
|
||||||
|
|
||||||
active_users = set(posters) | set(commenters) | set(voters) | set(commentvoters)
|
|
||||||
|
|
||||||
stats = {"marseys": g.db.query(Marsey).count(),
|
|
||||||
"users": g.db.query(User).count(),
|
|
||||||
"private users": g.db.query(User).filter_by(is_private=True).count(),
|
|
||||||
"banned users": g.db.query(User).filter(User.is_banned > 0).count(),
|
|
||||||
"verified email users": g.db.query(User).filter_by(is_activated=True).count(),
|
|
||||||
"coins in circulation": g.db.query(func.sum(User.coins)).scalar(),
|
|
||||||
"total shop sales": g.db.query(func.sum(User.coins_spent)).scalar(),
|
|
||||||
"signups last 24h": g.db.query(User).filter(User.created_utc > day).count(),
|
|
||||||
"total posts": g.db.query(Submission).count(),
|
|
||||||
"posting users": g.db.query(Submission.author_id).distinct().count(),
|
|
||||||
"listed posts": g.db.query(Submission).filter_by(is_banned=False).filter(Submission.deleted_utc == 0).count(),
|
|
||||||
"removed posts (by admins)": g.db.query(Submission).filter_by(is_banned=True).count(),
|
|
||||||
"deleted posts (by author)": g.db.query(Submission).filter(Submission.deleted_utc > 0).count(),
|
|
||||||
"posts last 24h": g.db.query(Submission).filter(Submission.created_utc > day).count(),
|
|
||||||
"total comments": g.db.query(Comment).filter(Comment.author_id.notin_((AUTOJANNY_ID,NOTIFICATIONS_ID))).count(),
|
|
||||||
"commenting users": g.db.query(Comment.author_id).distinct().count(),
|
|
||||||
"removed comments (by admins)": g.db.query(Comment).filter_by(is_banned=True).count(),
|
|
||||||
"deleted comments (by author)": g.db.query(Comment).filter(Comment.deleted_utc > 0).count(),
|
|
||||||
"comments last_24h": g.db.query(Comment).filter(Comment.created_utc > day, Comment.author_id.notin_((AUTOJANNY_ID,NOTIFICATIONS_ID))).count(),
|
|
||||||
"post votes": g.db.query(Vote).count(),
|
|
||||||
"post voting users": g.db.query(Vote.user_id).distinct().count(),
|
|
||||||
"comment votes": g.db.query(CommentVote).count(),
|
|
||||||
"comment voting users": g.db.query(CommentVote.user_id).distinct().count(),
|
|
||||||
"total upvotes": g.db.query(Vote).filter_by(vote_type=1).count() + g.db.query(CommentVote.comment_id).filter_by(vote_type=1).count(),
|
|
||||||
"total downvotes": g.db.query(Vote).filter_by(vote_type=-1).count() + g.db.query(CommentVote.comment_id).filter_by(vote_type=-1).count(),
|
|
||||||
"total awards": g.db.query(AwardRelationship).count(),
|
|
||||||
"awards given": g.db.query(AwardRelationship).filter(or_(AwardRelationship.submission_id != None, AwardRelationship.comment_id != None)).count(),
|
|
||||||
"users who posted, commented, or voted in the past 7 days": len(active_users),
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
if SITE_NAME == 'rDrama':
|
|
||||||
furries1 = g.db.query(User).filter(User.house.like('Furry%')).count()
|
|
||||||
femboys1 = g.db.query(User).filter(User.house.like('Femboy%')).count()
|
|
||||||
vampires1 = g.db.query(User).filter(User.house.like('Vampire%')).count()
|
|
||||||
racists1 = g.db.query(User).filter(User.house.like('Racist%')).count()
|
|
||||||
|
|
||||||
furries2 = g.db.query(func.sum(User.truecoins)).filter(User.house.like('Furry%')).scalar()
|
|
||||||
femboys2 = g.db.query(func.sum(User.truecoins)).filter(User.house.like('Femboy%')).scalar()
|
|
||||||
vampires2 = g.db.query(func.sum(User.truecoins)).filter(User.house.like('Vampire%')).scalar()
|
|
||||||
racists2 = g.db.query(func.sum(User.truecoins)).filter(User.house.like('Racist%')).scalar()
|
|
||||||
|
|
||||||
stats2 = {"House furry members": furries1,
|
|
||||||
"House femboy members": femboys1,
|
|
||||||
"House vampire members": vampires1,
|
|
||||||
"House racist members": racists1,
|
|
||||||
"House furry total truescore": furries2,
|
|
||||||
"House femboy total truescore": femboys2,
|
|
||||||
"House vampire total truescore": vampires2,
|
|
||||||
"House racist total truescore": racists2,
|
|
||||||
}
|
|
||||||
|
|
||||||
stats.update(stats2)
|
|
||||||
|
|
||||||
accs = g.db.query(User).filter(User.id.in_(bots))
|
|
||||||
|
|
||||||
for u in accs:
|
|
||||||
g.db.add(u)
|
|
||||||
|
|
||||||
if u.patron_utc and u.patron_utc < time.time():
|
|
||||||
u.patron = 0
|
|
||||||
u.patron_utc = 0
|
|
||||||
|
|
||||||
if u.unban_utc and u.unban_utc < time.time():
|
|
||||||
u.is_banned = 0
|
|
||||||
u.unban_utc = 0
|
|
||||||
u.ban_evade = 0
|
|
||||||
|
|
||||||
if u.agendaposter and u.agendaposter < time.time():
|
|
||||||
u.agendaposter = 0
|
|
||||||
badge = u.has_badge(28)
|
|
||||||
if badge: g.db.delete(badge)
|
|
||||||
|
|
||||||
if u.flairchanged and u.flairchanged < time.time():
|
|
||||||
u.flairchanged = None
|
|
||||||
badge = u.has_badge(96)
|
|
||||||
if badge: g.db.delete(badge)
|
|
||||||
|
|
||||||
if u.marseyawarded and u.marseyawarded < time.time():
|
|
||||||
u.marseyawarded = None
|
|
||||||
badge = u.has_badge(98)
|
|
||||||
if badge: g.db.delete(badge)
|
|
||||||
|
|
||||||
if u.longpost and u.longpost < time.time():
|
|
||||||
u.longpost = None
|
|
||||||
badge = u.has_badge(97)
|
|
||||||
if badge: g.db.delete(badge)
|
|
||||||
|
|
||||||
if u.bird and u.bird < time.time():
|
|
||||||
u.bird = None
|
|
||||||
badge = u.has_badge(95)
|
|
||||||
if badge: g.db.delete(badge)
|
|
||||||
|
|
||||||
if u.progressivestack and u.progressivestack < time.time():
|
|
||||||
u.progressivestack = None
|
|
||||||
badge = u.has_badge(94)
|
|
||||||
if badge: g.db.delete(badge)
|
|
||||||
|
|
||||||
if u.rehab and u.rehab < time.time():
|
|
||||||
u.rehab = None
|
|
||||||
badge = u.has_badge(109)
|
|
||||||
if badge: g.db.delete(badge)
|
|
||||||
|
|
||||||
if u.deflector and u.deflector < time.time():
|
|
||||||
u.deflector = None
|
|
||||||
|
|
||||||
one_week_ago = time.time() - 604800
|
|
||||||
active_holes = [x[0] for x in g.db.query(Submission.sub).distinct().filter(Submission.sub != None, Submission.created_utc > one_week_ago).all()]
|
|
||||||
|
|
||||||
dead_holes = g.db.query(Sub).filter(Sub.name.notin_(active_holes)).all()
|
|
||||||
names = [x.name for x in dead_holes]
|
|
||||||
|
|
||||||
posts = g.db.query(Submission).filter(Submission.sub.in_(names)).all()
|
|
||||||
for post in posts:
|
|
||||||
post.sub = None
|
|
||||||
g.db.add(post)
|
|
||||||
|
|
||||||
to_delete = g.db.query(Mod).filter(Mod.sub.in_(names)).all() + g.db.query(Exile).filter(Exile.sub.in_(names)).all() + g.db.query(SubBlock).filter(SubBlock.sub.in_(names)).all() + g.db.query(SubSubscription).filter(SubSubscription.sub.in_(names)).all()
|
|
||||||
for x in to_delete:
|
|
||||||
g.db.delete(x)
|
|
||||||
g.db.flush()
|
|
||||||
|
|
||||||
for x in dead_holes:
|
|
||||||
g.db.delete(x)
|
|
||||||
|
|
||||||
g.db.commit()
|
|
||||||
|
|
||||||
return stats
|
|
||||||
|
|
||||||
|
|
||||||
@app.get("/chart")
|
@app.get("/chart")
|
||||||
def chart():
|
def chart():
|
||||||
|
|
|
@ -448,4 +448,35 @@ def sub_sidebar(v, sub):
|
||||||
@auth_desired
|
@auth_desired
|
||||||
def subs(v):
|
def subs(v):
|
||||||
subs = g.db.query(Sub, func.count(Submission.sub)).outerjoin(Submission, Sub.name == Submission.sub).group_by(Sub.name).order_by(func.count(Submission.sub).desc()).all()
|
subs = g.db.query(Sub, func.count(Submission.sub)).outerjoin(Submission, Sub.name == Submission.sub).group_by(Sub.name).order_by(func.count(Submission.sub).desc()).all()
|
||||||
return render_template('sub/subs.html', v=v, subs=subs)
|
return render_template('sub/subs.html', v=v, subs=subs)
|
||||||
|
|
||||||
|
def sub_inactive_purge_task():
|
||||||
|
if not HOLE_INACTIVITY_DELETION:
|
||||||
|
return False
|
||||||
|
|
||||||
|
one_week_ago = time.time() - 604800
|
||||||
|
active_holes = [x[0] for x in g.db.query(Submission.sub).distinct() \
|
||||||
|
.filter(Submission.sub != None, Submission.created_utc > one_week_ago).all()]
|
||||||
|
|
||||||
|
dead_holes = g.db.query(Sub).filter(Sub.name.notin_(active_holes)).all()
|
||||||
|
names = [x.name for x in dead_holes]
|
||||||
|
|
||||||
|
posts = g.db.query(Submission).filter(Submission.sub.in_(names)).all()
|
||||||
|
for post in posts:
|
||||||
|
post.sub = None
|
||||||
|
g.db.add(post)
|
||||||
|
|
||||||
|
to_delete = g.db.query(Mod).filter(Mod.sub.in_(names)).all() \
|
||||||
|
+ g.db.query(Exile).filter(Exile.sub.in_(names)).all() \
|
||||||
|
+ g.db.query(SubBlock).filter(SubBlock.sub.in_(names)).all() \
|
||||||
|
+ g.db.query(SubSubscription).filter(SubSubscription.sub.in_(names)).all()
|
||||||
|
|
||||||
|
for x in to_delete:
|
||||||
|
g.db.delete(x)
|
||||||
|
g.db.flush()
|
||||||
|
|
||||||
|
for x in dead_holes:
|
||||||
|
g.db.delete(x)
|
||||||
|
|
||||||
|
g.db.commit()
|
||||||
|
return True
|
||||||
|
|
|
@ -14,7 +14,7 @@
|
||||||
|
|
||||||
<div class="row border-bottom bg-white w-200 pr-0" style="overflow: visible;">
|
<div class="row border-bottom bg-white w-200 pr-0" style="overflow: visible;">
|
||||||
<div class="col p-0 w-100">
|
<div class="col p-0 w-100">
|
||||||
<ul class="nav settings-nav" style="padding:0 0 0 20px">
|
<ul class="nav settings-nav" style="padding:0 0 0 20px" id="notifications--nav-list">
|
||||||
<li class="nav-item">
|
<li class="nav-item">
|
||||||
<a class="nav-link py-3{% if not '=true' in request.full_path %} active{% endif %}" href="/notifications">
|
<a class="nav-link py-3{% if not '=true' in request.full_path %} active{% endif %}" href="/notifications">
|
||||||
All {% if v.normal_count %} <span class="font-weight-bold" style="color:red">({{v.normal_count}})</span>{% endif %}
|
All {% if v.normal_count %} <span class="font-weight-bold" style="color:red">({{v.normal_count}})</span>{% endif %}
|
||||||
|
@ -30,14 +30,21 @@
|
||||||
Messages
|
Messages
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
{% if v.admin_level > 1 %}
|
{% if v.admin_level >= NOTIF_MODACTION_JL_MIN %}
|
||||||
|
<li class="nav-item">
|
||||||
|
<a class="nav-link py-3{% if '/notifications?modactions=true' in request.full_path %} active{% endif %}" href="/notifications?modactions=true">
|
||||||
|
Modactions {% if v.modaction_notifications_count %}<span class="font-weight-bold" style="color:#e5990d">({{v.modaction_notifications_count}})</span>{% endif %}
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
{% endif %}
|
||||||
|
{% if v.admin_level >= 2 %}
|
||||||
<li class="nav-item">
|
<li class="nav-item">
|
||||||
<a class="nav-link py-3{% if '/notifications?modmail=true' in request.full_path %} active{% endif %}" href="/notifications?modmail=true">
|
<a class="nav-link py-3{% if '/notifications?modmail=true' in request.full_path %} active{% endif %}" href="/notifications?modmail=true">
|
||||||
Modmail
|
Modmail
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% if v.admin_level %}
|
{% if v.can_view_offsitementions %}
|
||||||
<li class="nav-item">
|
<li class="nav-item">
|
||||||
<a class="nav-link py-3{% if '/notifications?reddit=true' in request.full_path %} active{% endif %}" href="/notifications?reddit=true">
|
<a class="nav-link py-3{% if '/notifications?reddit=true' in request.full_path %} active{% endif %}" href="/notifications?reddit=true">
|
||||||
Reddit {% if v.reddit_notifications_count %}<span class="font-weight-bold" style="color:#805ad5">({{v.reddit_notifications_count}})</span>{% endif %}
|
Reddit {% if v.reddit_notifications_count %}<span class="font-weight-bold" style="color:#805ad5">({{v.reddit_notifications_count}})</span>{% endif %}
|
||||||
|
|
|
@ -15,8 +15,8 @@
|
||||||
<th>#</th>
|
<th>#</th>
|
||||||
<th>Name</th>
|
<th>Name</th>
|
||||||
<th role="button" onclick="sort_table(2)">Posts</th>
|
<th role="button" onclick="sort_table(2)">Posts</th>
|
||||||
<th role="button" onclick="sort_table(3)">Blockers</th>
|
<th role="button" onclick="sort_table(3)">Followers</th>
|
||||||
|
<th role="button" onclick="sort_table(4)">Blockers</th>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
{% for sub, count in subs %}
|
{% for sub, count in subs %}
|
||||||
|
@ -24,6 +24,7 @@
|
||||||
<td>{{loop.index}}</td>
|
<td>{{loop.index}}</td>
|
||||||
<td><a href="/h/{{sub.name}}">{{sub.name}}</a></td>
|
<td><a href="/h/{{sub.name}}">{{sub.name}}</a></td>
|
||||||
<td><a href="/h/{{sub.name}}">{{count}}</a></td>
|
<td><a href="/h/{{sub.name}}">{{count}}</a></td>
|
||||||
|
<td><a href="/h/{{sub.name}}/followers">{{sub.follow_num}}</a></td>
|
||||||
<td><a href="/h/{{sub.name}}/blockers">{{sub.block_num}}</a></td>
|
<td><a href="/h/{{sub.name}}/blockers">{{sub.block_num}}</a></td>
|
||||||
</tr>
|
</tr>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
{%-
|
{%-
|
||||||
set CACHE_VER = {
|
set CACHE_VER = {
|
||||||
'css/main.css': 297,
|
'css/main.css': 299,
|
||||||
|
|
||||||
'css/4chan.css': 59,
|
'css/4chan.css': 59,
|
||||||
'css/classic.css': 59,
|
'css/classic.css': 59,
|
||||||
|
|
|
@ -1984,6 +1984,7 @@ COPY public.badge_defs (id, name, description) FROM stdin;
|
||||||
137 Lottershe Winner This user won the Lottershe grand prize.
|
137 Lottershe Winner This user won the Lottershe grand prize.
|
||||||
138 Dan This user is a Certified Dan Enthusiast.
|
138 Dan This user is a Certified Dan Enthusiast.
|
||||||
139 Kristallmopt This user was fired from a volunteer position
|
139 Kristallmopt This user was fired from a volunteer position
|
||||||
|
140 Y'all Seein' Eye Gets notified when other sites talk about us
|
||||||
4 White Hat Discreetly reported an exploit
|
4 White Hat Discreetly reported an exploit
|
||||||
1 Alpha User Joined during open alpha
|
1 Alpha User Joined during open alpha
|
||||||
2 Verified Email Verified Email
|
2 Verified Email Verified Email
|
||||||
|
@ -2087,7 +2088,7 @@ COPY public.badge_defs (id, name, description) FROM stdin;
|
||||||
-- Name: badge_defs_id_seq; Type: SEQUENCE SET; Schema: public; Owner: -
|
-- Name: badge_defs_id_seq; Type: SEQUENCE SET; Schema: public; Owner: -
|
||||||
--
|
--
|
||||||
|
|
||||||
SELECT pg_catalog.setval('public.badge_defs_id_seq', 139, true);
|
SELECT pg_catalog.setval('public.badge_defs_id_seq', 140, true);
|
||||||
|
|
||||||
|
|
||||||
--
|
--
|
||||||
|
|
Loading…
Reference in New Issue