add effortpost marking

pull/222/head
Aevann 2024-02-07 00:04:43 +02:00
parent a3f59712e8
commit 7dfbb1541e
16 changed files with 141 additions and 24 deletions

View File

@ -219,6 +219,7 @@
.fa-coin:before{content:"\f85c"}
.fa-scarecrow:before{content:"\f70d"}
.fa-chart-simple:before{content:"\e473"}
.fa-memo:before{content:"\e1d8"}
/* do not remove - fixes hand, talking, marsey-love components
from breaking out of the comment box
@ -5194,6 +5195,9 @@ span.green {
padding: 2px 5px !important;
}
}
.effortpost-flair {
padding: 5px 5px 4px 5px !important;
}
.patron[style*="background-color:#ffffff"] {
color: black !important;
}
@ -7652,7 +7656,7 @@ blink {
animation: 60s linear 0s infinite move-colors;
}
:not(td) > a[href="/h/highrollerclub"].hole-flair {
:not(td) > a[href="/h/highrollerclub"].hole-flair, .effortpost-flair {
font-family: open sans,sans-serif !important;
background: repeating-linear-gradient(
45deg,

View File

@ -8,7 +8,7 @@ for (const id of save_value) {
autoExpand(document.getElementById('post-text'))
markdown(document.getElementById("post-text"));
const save_checked = ['post-notify', 'post-new', 'post-nsfw', 'post-private', 'post-ghost']
const save_checked = ['post-notify', 'post-new', 'post-nsfw', 'post-private', 'post-effortpost', 'post-ghost']
for (const key of save_checked) {
const value = localStorage.getItem(key)
if (value) {

View File

@ -34,6 +34,7 @@ class Post(Base):
bannedfor = Column(String)
chuddedfor = Column(String)
ghost = Column(Boolean, default=False)
effortpost = Column(Boolean, default=False)
views = Column(Integer, default=0)
deleted_utc = Column(Integer, default=0)
distinguish_level = Column(Integer, default=0)

View File

@ -297,3 +297,19 @@ def alert_everyone(cid):
select id, {cid}, false, {t} from users
on conflict do nothing;""")
g.db.execute(_everyone_query)
def alert_admins(body):
body_html = sanitize(body, blackjack="admin alert")
new_comment = Comment(author_id=AUTOJANNY_ID,
parent_post=None,
level=1,
body_html=body_html,
sentto=MODMAIL_ID,
distinguish_level=6,
is_bot=True
)
g.db.add(new_comment)
g.db.flush()
new_comment.top_comment_id = new_comment.id

View File

@ -206,6 +206,7 @@ PERMS = { # Minimum admin_level to perform action.
'UPDATE_ASSETS': 3,
'CHANGE_UNDER_SIEGE': 3,
'VIEW_IPS': 3,
'MARK_EFFORTPOST': 3,
'PROGSTACK': 4,
'UNDO_AWARD_PINS': 4,

View File

@ -206,6 +206,16 @@ MODACTION_TYPES = {
"icon": 'fa-file-signature',
"color": 'bg-success'
},
'mark_effortpost': {
"str": 'marked {self.target_link} as an effortpost',
"icon": 'fa-memo',
"color": 'bg-success'
},
'unmark_effortpost': {
"str": 'unmarked {self.target_link} as an effortpost',
"icon": 'fa-memo',
"color": 'bg-danger'
},
'move_hole': {
"str": 'changed hole of {self.target_link}',
"icon": 'fa-manhole',

View File

@ -2174,3 +2174,71 @@ if FEATURES['IP_LOGGING']:
def view_ip_users(v, ip):
ip_logs = g.db.query(IPLog).filter_by(ip=ip).order_by(IPLog.last_used.desc())
return render_template('admin/ip_users.html', v=v, ip=ip, ip_logs=ip_logs)
@app.post("/mark_effortpost/<int:pid>")
@limiter.limit('1/second', scope=rpath)
@limiter.limit('1/second', scope=rpath, key_func=get_ID)
@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400)
@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400, key_func=get_ID)
@admin_level_required(PERMS['MARK_EFFORTPOST'])
def mark_effortpost(pid, v):
p = get_post(pid)
if p.effortpost:
abort(400, "Post is already marked as an effortpost!")
p.effortpost = True
g.db.add(p)
ma = ModAction(
kind = "mark_effortpost",
user_id = v.id,
target_post_id = p.id,
)
g.db.add(ma)
if SITE_NAME == 'WPD':
mul = 8
else:
mul = 4
coins = (p.upvotes + p.downvotes) * mul
send_repeatable_notification(p.author_id, f":marseyclapping: @{v.username} (a site admin) has marked [{p.title}](/post/{p.id}) as an effortpost, it now gets x{mul} coins from votes. You have received {coins} coins retroactively, thanks! :!marseyclapping:")
return {"message": "Post has been marked as an effortpost!"}
@app.post("/unmark_effortpost/<int:pid>")
@limiter.limit('1/second', scope=rpath)
@limiter.limit('1/second', scope=rpath, key_func=get_ID)
@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400)
@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400, key_func=get_ID)
@admin_level_required(PERMS['MARK_EFFORTPOST'])
def unmark_effortpost(pid, v):
p = get_post(pid)
if not p.effortpost:
abort(400, "Post is already not marked as an effortpost!")
p.effortpost = False
g.db.add(p)
ma = ModAction(
kind = "unmark_effortpost",
user_id = v.id,
target_post_id = p.id,
)
g.db.add(ma)
if SITE_NAME == 'WPD':
mul = 8
else:
mul = 4
coins = (p.upvotes + p.downvotes) * mul
send_repeatable_notification(p.author_id, f":marseyitsover: @{v.username} (a site admin) has unmarked [{p.title}](/post/{p.id}) as an effortpost. {coins} coins have been deducted from you. :!marseyitsover:")
return {"message": "Post has been unmarked as an effortpost!"}

View File

@ -67,20 +67,7 @@ def request_api_keys(v):
g.db.add(new_app)
body = f"@{v.username} has requested API keys for `{request.values.get('name')}`. You can approve or deny the request [here](/admin/apps)."
body_html = sanitize(body, blackjack="app description")
new_comment = Comment(author_id=AUTOJANNY_ID,
parent_post=None,
level=1,
body_html=body_html,
sentto=MODMAIL_ID,
distinguish_level=6,
is_bot=True
)
g.db.add(new_comment)
g.db.flush()
new_comment.top_comment_id = new_comment.id
alert_admins(body)
return {"message": "API keys requested successfully!"}

View File

@ -540,6 +540,7 @@ def submit_post(v, hole=None):
flag_new = request.values.get("new", False, bool) or 'megathread' in title.lower()
flag_nsfw = FEATURES['NSFW_MARKING'] and request.values.get("nsfw", False, bool)
flag_private = request.values.get("private", False, bool)
flag_effortpost = request.values.get("effortpost", False, bool)
flag_ghost = request.values.get("ghost", False, bool) and v.can_post_in_ghost_threads
if flag_ghost: hole = None
@ -702,6 +703,10 @@ def submit_post(v, hole=None):
generate_thumb = (not p.thumburl and p.url and p.domain != SITE)
gevent.spawn(postprocess_post, p.url, p.body, p.body_html, p.id, generate_thumb, False)
if flag_effortpost:
body = f"@{v.username} has requested that [{p.title}](/post/{p.id}) be marked as an effortpost!"
alert_admins(body)
if v.client: return p.json
else:
p.voted = 1

View File

@ -44,8 +44,6 @@ def vote_post_comment(target_id, new, v, cls, vote_cls):
coin_delta = -1
alt = True
coin_mult = 1
g.db.flush()
existing = g.db.query(vote_cls).filter_by(user_id=v.id)
if vote_cls == Vote:
@ -56,14 +54,24 @@ def vote_post_comment(target_id, new, v, cls, vote_cls):
abort(400)
existing = existing.one_or_none()
if SITE_NAME == 'WPD':
coin_mult *= 4
if IS_EVENT():
coin_mult *= 2
if cls == Post and target.effortpost:
if SITE_NAME == 'WPD':
coin_mult = 8
else:
coin_mult = 4
else:
coin_mult = 1
if SITE_NAME == 'WPD':
coin_mult *= 4
if IS_EVENT():
coin_mult *= 2
if IS_HOMOWEEN() and target.author.zombie > 0:
coin_mult += 1
if IS_HOMOWEEN() and target.author.zombie > 0:
coin_mult += 1
coin_value = coin_delta * coin_mult

View File

@ -94,10 +94,12 @@
<h1 id="post-title" class="{{p.award_classes(v, True)}} card-title post-title text-left mb-md-3">
{% if p.realurl(v) and not v_forbid_deleted %}
<a class="no-visited" {% if not v or v.newtabexternal %}target="_blank"{% endif %} rel="noopener" href="{{p.realurl(v)}}">
{% if p.effortpost %}<span class="post-flair effortpost-flair font-weight-bolder mr-1">EFFORTPOST</span>{% endif %}
{% if p.flair %}<span class="post-flair font-weight-bolder mr-1">{{p.flair | safe}}</span>{% endif %}
{{p.realtitle(v) | safe}}
</a>
{% else %}
{% if p.effortpost %}<span class="post-flair effortpost-flair font-weight-bolder mr-1">EFFORTPOST</span>{% endif %}
{% if p.flair %}<span class="post-flair font-weight-bolder mr-1">{{p.flair | safe}}</span>{% endif %}
{{p.realtitle(v) | safe}}
{% endif %}

View File

@ -83,6 +83,10 @@
<button type="button" id="mark-{{p.id}}" class="dropdown-item {% if p.nsfw %}d-none{% endif %} list-inline-item text-danger" data-nonce="{{g.nonce}}" data-onclick="postToastSwitch(this,'/mark_post_nsfw/{{p.id}}','mark-{{p.id}}','unmark-{{p.id}}','d-none')"><i class="fas fa-eye-evil"></i>Mark NSFW</button>
<button type="button" id="unmark-{{p.id}}" class="dropdown-item {% if not p.nsfw %}d-none{% endif %} list-inline-item text-success" data-nonce="{{g.nonce}}" data-onclick="postToastSwitch(this,'/unmark_post_nsfw/{{p.id}}','mark-{{p.id}}','unmark-{{p.id}}','d-none')"><i class="fas fa-eye-evil"></i>Unmark NSFW</button>
{% endif %}
{% if v.admin_level >= PERMS['MARK_EFFORTPOST'] %}
<button type="button" id="mark-effortpost-{{p.id}}" class="dropdown-item {% if p.effortpost %}d-none{% endif %} list-inline-item text-danger" data-nonce="{{g.nonce}}" data-onclick="postToastSwitch(this,'/mark_effortpost/{{p.id}}','mark-effortpost-{{p.id}}','unmark-effortpost-{{p.id}}','d-none')"><i class="fas fa-memo"></i>Mark Effortpost</button>
<button type="button" id="unmark-effortpost-{{p.id}}" class="dropdown-item {% if not p.effortpost %}d-none{% endif %} list-inline-item text-success" data-nonce="{{g.nonce}}" data-onclick="postToastSwitch(this,'/unmark_effortpost/{{p.id}}','mark-effortpost-{{p.id}}','unmark-effortpost-{{p.id}}','d-none')"><i class="fas fa-memo"></i>Unmark Effortpost</button>
{% endif %}
{% if v.admin_level >= PERMS['PROGSTACK'] %}
<button type="button" id="progstack-{{p.id}}" class="dropdown-item {% if p.is_approved == PROGSTACK_ID %}d-none{% endif %} list-inline-item text-danger" data-nonce="{{g.nonce}}" data-onclick="postToastSwitch(this,'/admin/progstack/post/{{p.id}}','progstack-{{p.id}}','unprogstack-{{p.id}}','d-none')"><i class="fas fa-bullhorn"></i>Apply Progressive Stack</button>
<button type="button" id="unprogstack-{{p.id}}" class="dropdown-item {% if p.is_approved != PROGSTACK_ID %}d-none{% endif %} list-inline-item text-danger" data-nonce="{{g.nonce}}" data-onclick="postToastSwitch(this,'/admin/unprogstack/post/{{p.id}}','progstack-{{p.id}}','unprogstack-{{p.id}}','d-none')"><i class="fas fa-bullhorn"></i>Remove Progressive Stack</button>

View File

@ -37,6 +37,10 @@
<button type="button" id="mark2-{{p.id}}" class="{% if p.nsfw %}d-none{% endif %} nobackground btn btn-link btn-block btn-lg text-left text-danger" data-nonce="{{g.nonce}}" data-onclick="postToastSwitch(this,'/mark_post_nsfw/{{p.id}}','mark2-{{p.id}}','unmark2-{{p.id}}','d-none')" data-bs-dismiss="modal"><i class="fas fa-eye-evil text-center text-danger mr-2"></i>Mark NSFW</button>
<button type="button" id="unmark2-{{p.id}}" class="{% if not p.nsfw %}d-none{% endif %} nobackground btn btn-link btn-block btn-lg text-left text-success" data-nonce="{{g.nonce}}" data-onclick="postToastSwitch(this,'/unmark_post_nsfw/{{p.id}}','mark2-{{p.id}}','unmark2-{{p.id}}','d-none')" data-bs-dismiss="modal"><i class="fas fa-eye-evil text-center text-success mr-2"></i>Unmark NSFW</button>
{% endif %}
{% if v.admin_level >= PERMS['MARK_EFFORTPOST'] %}
<button type="button" id="mark-effortpost2-{{p.id}}" class="{% if p.effortpost %}d-none{% endif %} nobackground btn btn-link btn-block btn-lg text-left text-danger" data-nonce="{{g.nonce}}" data-onclick="postToastSwitch(this,'/mark_effortpost/{{p.id}}','mark-effortpost2-{{p.id}}','unmark-effortpost2-{{p.id}}','d-none')" data-bs-dismiss="modal"><i class="fas fa-memo text-center text-danger mr-2"></i>Mark Effortpost</button>
<button type="button" id="unmark-effortpost2-{{p.id}}" class="{% if not p.effortpost %}d-none{% endif %} nobackground btn btn-link btn-block btn-lg text-left text-success" data-nonce="{{g.nonce}}" data-onclick="postToastSwitch(this,'/unmark_effortpost/{{p.id}}','mark-effortpost2-{{p.id}}','unmark-effortpost2-{{p.id}}','d-none')" data-bs-dismiss="modal"><i class="fas fa-memo text-center text-success mr-2"></i>Unmark Effortpost</button>
{% endif %}
{% if v.admin_level >= PERMS['PROGSTACK'] %}
<button type="button" id="progstack2-{{p.id}}" class="{% if p.is_approved == PROGSTACK_ID %}d-none{% endif %} nobackground btn btn-link btn-block btn-lg text-left text-danger" data-nonce="{{g.nonce}}" data-onclick="postToastSwitch(this,'/admin/progstack/post/{{p.id}}','progstack2-{{p.id}}','unprogstack2-{{p.id}}','d-none')" data-bs-dismiss="modal"><i class="fas fa-bullhorn text-center text-danger mr-2"></i>Apply Progressive Stack</button>
<button type="button" id="unprogstack2-{{p.id}}" class="{% if p.is_approved != PROGSTACK_ID %}d-none{% endif %} nobackground btn btn-link btn-block btn-lg text-left text-danger" data-nonce="{{g.nonce}}" data-onclick="postToastSwitch(this,'/admin/unprogstack/post/{{p.id}}','progstack2-{{p.id}}','unprogstack2-{{p.id}}','d-none')" data-bs-dismiss="modal"><i class="fas fa-bullhorn text-center text-danger mr-2"></i>Remove Progressive Stack</button>

View File

@ -92,6 +92,7 @@
</div>
<h5 class="card-title post-title text-left w-lg-95 pb-0 pb-md-1">
<a id="{{p.id}}-title" {% if v and v.newtab %}data-target="t" target="_blank"{% endif %} href="{{p.permalink}}" class="{% if p.hole %}sub{% endif %} stretched-link {% if p.chudded %}text-uppercase{% endif %}">
{% if p.effortpost %}<span class="post-flair effortpost-flair font-weight-bolder mr-1">EFFORTPOST</span>{% endif %}
{% if p.flair %}<span class="post-flair font-weight-bolder mr-1">{{p.flair | safe}}</span>{% endif %}
{{p.realtitle(v) | safe}}
</a></h5>

View File

@ -82,6 +82,10 @@
<input autocomplete="off" type="checkbox" class="custom-control-input" id="post-private" name="private" data-nonce="{{g.nonce}}" data-onchange="savetext()">
<label class="custom-control-label" for="post-private">Draft</label>
</div>
<div class="custom-control custom-checkbox">
<input autocomplete="off" type="checkbox" class="custom-control-input" id="post-effortpost" name="effortpost" data-nonce="{{g.nonce}}" data-onchange="savetext()">
<label class="custom-control-label" for="post-effortpost">Notify admins to mark your post as an effortpost</label>
</div>
<div class="custom-control custom-checkbox {% if not v.can_post_in_ghost_threads %}d-none{% endif %}">
<input data-nonce="{{g.nonce}}" data-onchange='ghost_toggle(this)' autocomplete="off" type="checkbox" class="custom-control-input" id="post-ghost" name="ghost">
<label class="custom-control-label" for="post-ghost">Ghost thread</label>

View File

@ -0,0 +1,2 @@
alter table posts add column effortpost bool default false not null;
alter table posts alter column effortpost drop default;