mirror of
https://git.wownero.com/lza_menace/suchwow.git
synced 2024-08-15 01:03:19 +00:00
finish most of my hacky bullshit
This commit is contained in:
parent
133057b4e9
commit
309abaac83
9 changed files with 160 additions and 98 deletions
|
@ -37,9 +37,6 @@ def index():
|
|||
page = request.args.get("page", 1)
|
||||
submitter = request.args.get("submitter", None)
|
||||
content = request.args.get("content", None)
|
||||
if content == "trending":
|
||||
posts = get_activity()
|
||||
return render_template("index.html", posts=posts)
|
||||
|
||||
try:
|
||||
page = int(page)
|
||||
|
|
|
@ -54,10 +54,15 @@ class Post(Model):
|
|||
amounts = [amt['amount'] for amt in it['transfers'] if 'transfers' in it]
|
||||
return wownero.as_wownero(wownero.from_atomic(sum(amounts)))
|
||||
else:
|
||||
return '0'
|
||||
return 0
|
||||
except:
|
||||
return '?'
|
||||
|
||||
def hours_elapsed(self):
|
||||
now = datetime.utcnow()
|
||||
diff = now - self.timestamp
|
||||
return diff.total_seconds() / 60 / 60
|
||||
|
||||
def show(self):
|
||||
return {
|
||||
'id': self.id,
|
||||
|
@ -77,6 +82,8 @@ class Post(Model):
|
|||
'to_reddit': self.to_reddit,
|
||||
'to_discord': self.to_discord,
|
||||
'approved': self.approved,
|
||||
'received_wow': self.get_received_wow(),
|
||||
'hours_elapsed': self.hours_elapsed()
|
||||
}
|
||||
|
||||
class Meta:
|
||||
|
|
|
@ -1,15 +1,17 @@
|
|||
from datetime import datetime, timedelta
|
||||
from os import path
|
||||
from flask import render_template, Blueprint, request, session, flash
|
||||
from flask import send_from_directory, redirect, url_for, current_app
|
||||
from werkzeug.utils import secure_filename
|
||||
from suchwow import wownero
|
||||
from suchwow.models import Post
|
||||
from suchwow.utils.helpers import rw_cache
|
||||
|
||||
|
||||
bp = Blueprint("leaderboard", "leaderboard")
|
||||
|
||||
@bp.route("/leaderboard")
|
||||
def leaderboard():
|
||||
@bp.route("/leaderboards/top_posters")
|
||||
def top_posters():
|
||||
top_posters = {}
|
||||
posts = Post.select().where(Post.approved==True)
|
||||
for post in posts:
|
||||
|
@ -26,3 +28,36 @@ def leaderboard():
|
|||
top_posters[post.submitter]["posts"].append(post)
|
||||
|
||||
return render_template("leaderboard.html", posters=top_posters)
|
||||
|
||||
@bp.route("/leaderboards/top_posts")
|
||||
def top_posts():
|
||||
top_posts = []
|
||||
days = request.args.get('days', 1)
|
||||
try:
|
||||
days = int(days)
|
||||
except:
|
||||
days = 1
|
||||
|
||||
if days not in [1, 3, 7, 30]:
|
||||
days = 7
|
||||
|
||||
hours = 24 * days
|
||||
diff = datetime.now() - timedelta(hours=hours)
|
||||
key_name = f'top_posts_{str(hours)}'
|
||||
|
||||
posts = rw_cache(key_name)
|
||||
if not posts:
|
||||
posts = Post.select().where(
|
||||
Post.approved==True,
|
||||
Post.timestamp > diff
|
||||
).order_by(
|
||||
Post.timestamp.desc()
|
||||
)
|
||||
for post in posts:
|
||||
p = post.show()
|
||||
if isinstance(p['received_wow'], float):
|
||||
top_posts.append(p)
|
||||
|
||||
posts = rw_cache(key_name, top_posts)
|
||||
|
||||
return render_template("post/top.html", posts=posts, days=days)
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
import pickle
|
||||
from datetime import datetime
|
||||
from datetime import datetime, timedelta
|
||||
from os import path, remove
|
||||
from io import BytesIO
|
||||
from base64 import b64encode
|
||||
|
@ -12,53 +11,14 @@ from suchwow import wownero
|
|||
from suchwow import config
|
||||
from suchwow.models import Post, Comment
|
||||
from suchwow.utils.decorators import login_required, profile_required, moderator_required
|
||||
from suchwow.utils.helpers import allowed_file, is_moderator, get_session_user, post_webhook
|
||||
from suchwow.utils.helpers import allowed_file, is_moderator, get_session_user
|
||||
from suchwow.utils.helpers import rw_cache, post_webhook
|
||||
from suchwow.reddit import make_post
|
||||
from suchwow.discord import post_discord_webhook
|
||||
|
||||
|
||||
bp = Blueprint("post", "post")
|
||||
|
||||
@bp.route("/posts/top")
|
||||
def top():
|
||||
top_posts = {}
|
||||
pickle_file = path.join(config.DATA_FOLDER, 'top_posts.pkl')
|
||||
|
||||
try:
|
||||
mtime_ts = path.getmtime(pickle_file)
|
||||
mtime = datetime.fromtimestamp(mtime_ts)
|
||||
now = datetime.now()
|
||||
diff = now - mtime
|
||||
|
||||
# If pickled data file is less than an hour old, load it and render page
|
||||
# Otherwise, determine balances, build json, store pickled data, and render page
|
||||
if diff.seconds < 3600:
|
||||
with open(pickle_file, 'rb') as f:
|
||||
print('Loading pickled data for /posts/top')
|
||||
pickled_data = pickle.load(f)
|
||||
return render_template("post/top.html", posts=pickled_data)
|
||||
except:
|
||||
pass
|
||||
|
||||
print('Generating and pickling new data for /posts/top')
|
||||
posts = Post.select().where(Post.approved==True)
|
||||
for post in posts:
|
||||
transfers = []
|
||||
incoming = wownero.Wallet().incoming_transfers(post.account_index)
|
||||
if "transfers" in incoming:
|
||||
for xfer in incoming["transfers"]:
|
||||
transfers.append(xfer["amount"])
|
||||
total = wownero.from_atomic(sum(transfers))
|
||||
if total > 0:
|
||||
top_posts[float(total)] = post
|
||||
|
||||
_t = sorted(top_posts.items(), reverse=True)[0:10]
|
||||
|
||||
with open(pickle_file, 'wb') as f:
|
||||
f.write(pickle.dumps(_t))
|
||||
|
||||
return render_template("post/top.html", posts=_t)
|
||||
|
||||
@bp.route("/post/<id>")
|
||||
def read(id):
|
||||
_address_qr = BytesIO()
|
||||
|
|
|
@ -7,6 +7,11 @@
|
|||
<h1>About</h1>
|
||||
<p>Post memes! Have fun! Comment and talk shit! Earn WOW!</p>
|
||||
<p>Quit your day job and become a full-time shitposter and memer!</p>
|
||||
<p>Commiserate with the gang in IRC, get high, and let your responsibilities fall to the wayside.</p>
|
||||
<p>Join the revolution!</p>
|
||||
<br />
|
||||
<br />
|
||||
<br />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
|
|
@ -4,26 +4,20 @@
|
|||
|
||||
<div class="container" style="text-align:center;">
|
||||
|
||||
<!-- <h3>Leaderboards</h3>
|
||||
<a href="{{ url_for('post.top') }}"><button class="btn btn-warning">Top Posts</button></a>
|
||||
<a href="{{ url_for('leaderboard.leaderboard') }}"><button class="btn btn-warning">Top Posters</button></a>
|
||||
<hr> -->
|
||||
|
||||
<h1 class="title">Latest Posts</h1>
|
||||
<h1 class="title">Latest Memes</h1>
|
||||
|
||||
<section class="section">
|
||||
{% if posts %}
|
||||
{% for row in posts | batch(4) %}
|
||||
<div class="columns">
|
||||
{% for post in row %}
|
||||
{% set post = post.show() %}
|
||||
<div class="column">
|
||||
<div class="card">
|
||||
<div class="card-image">
|
||||
<figure class="image is-192x192">
|
||||
<a href="{{ url_for('post.read', id=post.id) }}">
|
||||
<img src="{{ url_for('post.uploaded_file', filename=post.get_thumbnail_name()) }}" alt="Placeholder image">
|
||||
<img src="{{ url_for('post.uploaded_file', filename=post.thumbnail_name) }}" alt="Placeholder image">
|
||||
</a>
|
||||
</figure>
|
||||
</div>
|
||||
<div class="card-content">
|
||||
<div class="media">
|
||||
|
@ -37,9 +31,9 @@
|
|||
|
||||
<div class="content">
|
||||
{{ post.text | truncate(60) }}
|
||||
<!-- <br> -->
|
||||
<p><strong>{{ post.get_received_wow() }} WOW received</strong></p>
|
||||
<p><strong>{{ post.received_wow }} WOW received</strong></p>
|
||||
<time datetime="2016-1-1">{{ post.timestamp.year }}-{{ post.timestamp.month }}-{{ post.timestamp.day }} {{ post.timestamp.hour }}:{{ post.timestamp.minute }} UTC</time>
|
||||
<p>({{ post.timestamp | humanize }})</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -52,16 +46,15 @@
|
|||
{% endif %}
|
||||
</section>
|
||||
|
||||
{% if total_pages %}
|
||||
<nav class="pagination is-centered pb-4" role="navigation" aria-label="pagination">
|
||||
<ul class="pagination-list">
|
||||
{% for p in range(1, total_pages + 1) %}
|
||||
<a href="{% if request.args.submitter %}/?submitter={{ request.args.submitter }}&{% else %}/?{% endif %}page={{ p }}" class="pagination-link {% if p == page %}current-page-btn{% endif %}">{{ p }}</a>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
</nav>
|
||||
{% endif %}
|
||||
|
||||
{% if total_pages %}
|
||||
<nav class="pagination is-centered pb-4" role="navigation" aria-label="pagination">
|
||||
<ul class="pagination-list">
|
||||
{% for p in range(1, total_pages + 1) %}
|
||||
<a href="{% if request.args.submitter %}/?submitter={{ request.args.submitter }}&{% else %}/?{% endif %}page={{ p }}" class="pagination-link {% if p == page %}current-page-btn{% endif %}">{{ p }}</a>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
</nav>
|
||||
{% endif %}
|
||||
|
||||
|
||||
</div>
|
||||
|
|
|
@ -14,6 +14,17 @@
|
|||
<div id="navbarBasicExample" class="navbar-menu">
|
||||
<div class="navbar-start">
|
||||
<a class="navbar-item" href="{{ url_for('index') }}">Home</a>
|
||||
<div class="navbar-item has-dropdown is-hoverable">
|
||||
<a class="navbar-link">Leaderboards</a>
|
||||
|
||||
<div class="navbar-dropdown">
|
||||
<a class="navbar-item" href="{{ url_for('leaderboard.top_posters') }}">Top Posters</a>
|
||||
<a class="navbar-item" href="{{ url_for('leaderboard.top_posts') }}?days=1">Top Memes Last 1 Day</a>
|
||||
<a class="navbar-item" href="{{ url_for('leaderboard.top_posts') }}?days=3">Top Memes Last 3 Days</a>
|
||||
<a class="navbar-item" href="{{ url_for('leaderboard.top_posts') }}?days=7">Top Memes Last Week</a>
|
||||
<a class="navbar-item" href="{{ url_for('leaderboard.top_posts') }}?days=30">Top Memes Last Month</a>
|
||||
</div>
|
||||
</div>
|
||||
<a class="navbar-item" href="{{ url_for('about') }}">About</a>
|
||||
<a class="navbar-item" href="{{ url_for('post.create') }}">Submit</a>
|
||||
{% if session.auth %}
|
||||
|
|
|
@ -4,41 +4,56 @@
|
|||
|
||||
<div class="container" style="text-align:center;">
|
||||
|
||||
<div class="title">
|
||||
<h3>{% block title %}Top 10 Posts{% endblock %}</h3>
|
||||
</div>
|
||||
<h1 class="title">Top Memes Last {{ days }} Days</h1>
|
||||
|
||||
<section class="section">
|
||||
{% if posts %}
|
||||
<table class="table table-striped">
|
||||
<tr>
|
||||
<th>Date</th>
|
||||
<th>ID</th>
|
||||
<th>Title</th>
|
||||
<th>Submitter</th>
|
||||
<th>Thumbnail</th>
|
||||
<th>Amount</th>
|
||||
</tr>
|
||||
{% for post in posts %}
|
||||
<tr>
|
||||
<td>{{ post[1].timestamp.strftime('%Y-%m-%d %H:%M') }}</td>
|
||||
<td>{{ post[1].id }}</td>
|
||||
<td><a href="{{ url_for('post.read', id=post[1].id) }}">{{ post[1].title }}</a></td>
|
||||
<td><a href="/?submitter={{ post[1].submitter }}">{{ post[1].submitter }}</a></td>
|
||||
<td>
|
||||
<a href="{{ url_for('post.read', id=post[1].id) }}">
|
||||
<img src="{{ url_for('post.uploaded_file', filename=post[1].get_thumbnail_name()) }}" width=200 style="max-height:200px;">
|
||||
</a>
|
||||
</td>
|
||||
<td>{{ post[0] }} WOW</td>
|
||||
</tr>
|
||||
{% for row in posts | sort(attribute='received_wow', reverse=True) | batch(4) %}
|
||||
<div class="columns">
|
||||
{% for post in row %}
|
||||
<div class="column">
|
||||
<div class="card">
|
||||
<div class="card-image">
|
||||
<a href="{{ url_for('post.read', id=post.id) }}">
|
||||
<img src="{{ url_for('post.uploaded_file', filename=post.thumbnail_name) }}" alt="Placeholder image">
|
||||
</a>
|
||||
</div>
|
||||
<div class="card-content">
|
||||
<div class="media">
|
||||
<div class="media-content">
|
||||
<p class="title is-4">
|
||||
<a href="{{ url_for('post.read', id=post.id) }}">{{ post.title }}</a>
|
||||
</p>
|
||||
<p class="subtitle is-6"><a href="/?submitter={{ post.submitter }}">{{ post.submitter }}</a></p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="content">
|
||||
{{ post.text | truncate(60) }}
|
||||
<p><strong>{{ post.received_wow }} WOW received</strong></p>
|
||||
<time datetime="2016-1-1">{{ post.timestamp.year }}-{{ post.timestamp.month }}-{{ post.timestamp.day }} {{ post.timestamp.hour }}:{{ post.timestamp.minute }} UTC</time>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
{% endfor %}
|
||||
</table>
|
||||
{% else %}
|
||||
<p>No posts yet!</p>
|
||||
{% endif %}
|
||||
</section>
|
||||
|
||||
{% if total_pages %}
|
||||
<nav class="pagination is-centered pb-4" role="navigation" aria-label="pagination">
|
||||
<ul class="pagination-list">
|
||||
{% for p in range(1, total_pages + 1) %}
|
||||
<a href="{% if request.args.submitter %}/?submitter={{ request.args.submitter }}&{% else %}/?{% endif %}page={{ p }}" class="pagination-link {% if p == page %}current-page-btn{% endif %}">{{ p }}</a>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
</nav>
|
||||
{% endif %}
|
||||
|
||||
<hr>
|
||||
<a href="{{ url_for('index') }}"><button class="btn btn-warning">Go Home</button></a>
|
||||
|
||||
</div>
|
||||
|
||||
|
|
|
@ -1,3 +1,6 @@
|
|||
import pickle
|
||||
from os import path, remove
|
||||
from datetime import datetime, timedelta
|
||||
from requests import post as r_post
|
||||
from json import dumps
|
||||
from flask import session, current_app
|
||||
|
@ -54,3 +57,39 @@ def get_activity():
|
|||
new_data.append(data[d]['post'])
|
||||
|
||||
return new_data[0:20]
|
||||
|
||||
|
||||
# Use hacky filesystem cache since i dont feel like shipping redis
|
||||
def rw_cache(key_name, data=None):
|
||||
pickle_file = path.join(config.DATA_FOLDER, f'{key_name}.pkl')
|
||||
try:
|
||||
if path.isfile(pickle_file):
|
||||
mtime_ts = path.getmtime(pickle_file)
|
||||
mtime = datetime.fromtimestamp(mtime_ts)
|
||||
now = datetime.now()
|
||||
diff = now - mtime
|
||||
# If pickled data file is less than an hour old, load it and render page
|
||||
# Otherwise, determine balances, build json, store pickled data, and render page
|
||||
if diff.seconds < 3600:
|
||||
print(f'unpickling {key_name}')
|
||||
with open(pickle_file, 'rb') as f:
|
||||
pickled_data = pickle.load(f)
|
||||
return pickled_data
|
||||
else:
|
||||
if data:
|
||||
print(f'pickling {key_name}')
|
||||
with open(pickle_file, 'wb') as f:
|
||||
f.write(pickle.dumps(data))
|
||||
return data
|
||||
else:
|
||||
return None
|
||||
else:
|
||||
if data:
|
||||
print(f'pickling {key_name}')
|
||||
with open(pickle_file, 'wb') as f:
|
||||
f.write(pickle.dumps(data))
|
||||
return data
|
||||
else:
|
||||
return None
|
||||
except:
|
||||
return None
|
||||
|
|
Loading…
Reference in a new issue