mirror of
https://git.wownero.com/lza_menace/suchwow.git
synced 2024-08-15 01:03:19 +00:00
updating funcs and queries
This commit is contained in:
parent
df33eaf258
commit
289995cd49
8 changed files with 66 additions and 169 deletions
|
@ -32,8 +32,13 @@ class User(Model):
|
|||
ban_timestamp = DateField(null=True)
|
||||
login_timestamp = DateTimeField(null=True)
|
||||
|
||||
def __repr__(self):
|
||||
return self.username
|
||||
def get_wow_received(self):
|
||||
tips = TipReceived.select().join(Post).where(Post.user == self)
|
||||
return sum(tip.amount for tip in tips)
|
||||
|
||||
def get_wow_sent(self):
|
||||
tips = TipSent.select().where(TipSent.from_user == self)
|
||||
return sum(tip.amount for tip in tips)
|
||||
|
||||
class Meta:
|
||||
database = db
|
||||
|
@ -74,17 +79,9 @@ class Post(Model):
|
|||
s = path.splitext(self.image_name)
|
||||
return s[0] + '.thumbnail' + s[1]
|
||||
|
||||
def get_received_wow(self):
|
||||
try:
|
||||
w = wownero.Wallet()
|
||||
it = w.incoming_transfers(self.account_index)
|
||||
if 'transfers' in it:
|
||||
amounts = [amt['amount'] for amt in it['transfers'] if 'transfers' in it]
|
||||
return wownero.as_wownero(wownero.from_atomic(sum(amounts)))
|
||||
else:
|
||||
return 0
|
||||
except:
|
||||
return '?'
|
||||
def get_wow_received(self):
|
||||
tips = TipReceived.select().where(TipReceived.post == self)
|
||||
return sum(tip.amount for tip in tips)
|
||||
|
||||
def hours_elapsed(self):
|
||||
now = datetime.utcnow()
|
||||
|
@ -107,7 +104,7 @@ class Post(Model):
|
|||
'timestamp': self.timestamp,
|
||||
'approved': self.approved,
|
||||
'approved_by': self.approved_by,
|
||||
'received_wow': self.get_received_wow(),
|
||||
'received_wow': self.get_wow_received(),
|
||||
'hours_elapsed': self.hours_elapsed()
|
||||
}
|
||||
|
||||
|
@ -149,7 +146,8 @@ class TipReceived(Model):
|
|||
|
||||
class TipSent(Model):
|
||||
id = AutoField()
|
||||
user = ForeignKeyField(User)
|
||||
from_user = ForeignKeyField(User)
|
||||
to_user = ForeignKeyField(User)
|
||||
txid = CharField(unique=True)
|
||||
timestamp = DateTimeField()
|
||||
amount = IntegerField()
|
||||
|
|
|
@ -1,12 +1,9 @@
|
|||
from os import makedirs
|
||||
|
||||
import click
|
||||
from flask import Blueprint, url_for, current_app
|
||||
from flask import Blueprint
|
||||
|
||||
from suchwow._models import db, User, Post, AuditEvent, TipSent, TipReceived, Vote
|
||||
from suchwow.utils.helpers import get_latest_tipped_posts
|
||||
from suchwow.utils.helpers import get_top_posters, get_top_posts
|
||||
from suchwow.reddit import make_post
|
||||
from suchwow.models import Post as OldPost
|
||||
from suchwow import wownero
|
||||
from suchwow import config
|
||||
|
||||
|
@ -23,6 +20,29 @@ def init():
|
|||
db.create_tables([User, Post, AuditEvent, TipSent, TipReceived, Vote])
|
||||
|
||||
|
||||
@bp.cli.command('rescan')
|
||||
def rescan():
|
||||
wallet = wownero.Wallet()
|
||||
wallet.make_wallet_rpc('rescan_blockchain')
|
||||
|
||||
|
||||
@bp.cli.command('save')
|
||||
def rescan():
|
||||
wallet = wownero.Wallet()
|
||||
wallet.make_wallet_rpc('store')
|
||||
print('Saved wallet.')
|
||||
|
||||
|
||||
@bp.cli.command("create_accounts")
|
||||
def create_accounts():
|
||||
wallet = wownero.Wallet()
|
||||
highest_account = OldPost.select().order_by(OldPost.timestamp.desc()).first().account_index
|
||||
print(f'Highest post account index is {highest_account} but highest wallet account is {wallet.accounts()[-1]}. Generating new accounts!')
|
||||
while wallet.accounts()[-1] < highest_account:
|
||||
account = wallet.new_account()
|
||||
print(f"Created account {account}")
|
||||
wallet.make_wallet_rpc('store')
|
||||
|
||||
# @bp.cli.command("post_reddit")
|
||||
# @click.argument('last_hours')
|
||||
# def post_reddit(last_hours):
|
||||
|
@ -40,15 +60,6 @@ def init():
|
|||
# return
|
||||
|
||||
|
||||
# @bp.cli.command("create_accounts")
|
||||
# def create_accounts():
|
||||
# wallet = wownero.Wallet()
|
||||
# for post in Post.select():
|
||||
# if post.account_index not in wallet.accounts():
|
||||
# account = wallet.new_account()
|
||||
# print(f"Created account {account}")
|
||||
|
||||
|
||||
# @bp.cli.command("payout_users")
|
||||
# def payout_users():
|
||||
# wallet = wownero.Wallet()
|
||||
|
|
|
@ -1,13 +1,27 @@
|
|||
import peewee
|
||||
from flask import render_template, Blueprint, request
|
||||
|
||||
from suchwow.utils.helpers import get_top_posters, get_top_posts
|
||||
from suchwow._models import Post, TipReceived, User
|
||||
|
||||
|
||||
bp = Blueprint("leaderboard", "leaderboard")
|
||||
|
||||
@bp.route("/leaderboards/top_posters")
|
||||
def top_posters():
|
||||
top_posters = get_top_posters()
|
||||
top_posters = TipReceived.select(
|
||||
TipReceived.post, peewee.fn.SUM(TipReceived.amount)
|
||||
).join(Post).order_by(
|
||||
peewee.fn.SUM(TipReceived.amount).desc()
|
||||
).group_by(TipReceived.post)
|
||||
# revenue = fn.SUM(Booking.slots * Case(None, (
|
||||
# (Booking.member == 0, Facility.guestcost),
|
||||
# ), Facility.membercost))
|
||||
#
|
||||
# query = (Facility
|
||||
# .select(Facility.name, revenue.alias('revenue'))
|
||||
# .join(Booking)
|
||||
# .group_by(Facility.name)
|
||||
# .order_by(SQL('revenue')))
|
||||
return render_template("leaderboard.html", posters=top_posters)
|
||||
|
||||
@bp.route("/leaderboards/top_posts")
|
||||
|
|
|
@ -2,8 +2,7 @@ from math import ceil
|
|||
|
||||
from flask import Blueprint, request, render_template, flash
|
||||
|
||||
from suchwow._models import Post, User
|
||||
from suchwow.utils.helpers import get_latest_tipped_posts
|
||||
from suchwow._models import Post, User, TipReceived
|
||||
|
||||
bp = Blueprint('main', 'main')
|
||||
|
||||
|
@ -16,10 +15,10 @@ def index():
|
|||
content = request.args.get("content", None)
|
||||
|
||||
if content == 'latest_tipped':
|
||||
posts = get_latest_tipped_posts()
|
||||
posts = Post.select().join(TipReceived).distinct().order_by(TipReceived.timestamp.desc()).limit(30)
|
||||
return render_template(
|
||||
"index.html",
|
||||
posts=posts[0:30],
|
||||
posts=posts,
|
||||
title="Latest Tipped Memes"
|
||||
)
|
||||
|
||||
|
@ -29,9 +28,9 @@ def index():
|
|||
flash("Wow, wtf hackerman. Cool it.", "is-danger")
|
||||
page = 1
|
||||
|
||||
posts = Post.select().where(Post.approved==True).order_by(Post.timestamp.desc())
|
||||
posts = Post.select().where(Post.approved == True).order_by(Post.timestamp.desc())
|
||||
if submitter:
|
||||
user = Post.select().where(Post.username == submitter).first()
|
||||
user = User.select().where(User.username == submitter)
|
||||
if not user:
|
||||
flash('That user does not exist!', 'is-warning')
|
||||
else:
|
||||
|
|
|
@ -11,7 +11,7 @@ from werkzeug.utils import secure_filename
|
|||
from suchwow import wownero, config
|
||||
from suchwow._models import User, Post, TipReceived
|
||||
from suchwow.utils.decorators import login_required, address_required, moderator_required
|
||||
from suchwow.utils.helpers import allowed_file, is_moderator, get_session_user
|
||||
from suchwow.utils.helpers import allowed_file, get_session_user
|
||||
from suchwow.utils.helpers import audit_event
|
||||
from suchwow.discord import post_discord_webhook
|
||||
|
||||
|
|
|
@ -16,19 +16,18 @@
|
|||
{% if posts %}
|
||||
{% for row in posts | batch(4) %}
|
||||
<div class="columns">
|
||||
{% for p in row %}
|
||||
{% set post = p.show() %}
|
||||
{% for post in row %}
|
||||
<div class="column">
|
||||
<div class="card">
|
||||
<div class="card-image">
|
||||
<a href="{{ url_for('post.read', id=post.id) }}">
|
||||
{% if p.get_image_path().endswith('mp4') %}
|
||||
{% if post.get_image_path().endswith('mp4') %}
|
||||
<video style="max-height: 100vh!important;" controls>
|
||||
<source src="{{ url_for('post.uploaded_file', filename=p.image_name) }}" type="video/mp4">
|
||||
<source src="{{ url_for('post.uploaded_file', filename=post.image_name) }}" type="video/mp4">
|
||||
Your browser does not support the video tag.
|
||||
</video>
|
||||
{% else %}
|
||||
<img alt="SuchWow #{{ post.id }} - {{ post.title }} by {{ post.user.username }}" src="{{ url_for('post.uploaded_file', filename=post.thumbnail_name) }}" />
|
||||
<img alt="SuchWow #{{ post.id }} - {{ post.title }} by {{ post.user.username }}" src="{{ url_for('post.uploaded_file', filename=post.get_thumbnail_name()) }}" />
|
||||
{% endif %}
|
||||
</a>
|
||||
</div>
|
||||
|
@ -38,13 +37,12 @@
|
|||
<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>
|
||||
<p class="subtitle is-6"><a href="/?submitter={{ post.user.username }}">{{ post.user.username }}</a></p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="content">
|
||||
{{ post.text | truncate(60) }}
|
||||
<p><strong>{{ post.received_wow }} WOW received</strong></p>
|
||||
<p><strong>{{ post.get_wow_received() | from_atomic }} 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>
|
||||
|
|
|
@ -5,8 +5,6 @@ from datetime import datetime, timedelta
|
|||
from flask import session
|
||||
|
||||
from suchwow._models import AuditEvent, User
|
||||
from suchwow.models import Moderator, Post, Profile
|
||||
from suchwow.wownero import Wallet, from_atomic
|
||||
from suchwow import config
|
||||
|
||||
|
||||
|
@ -14,13 +12,6 @@ def allowed_file(filename):
|
|||
return "." in filename and \
|
||||
filename.rsplit(".", 1)[1].lower() in config.ALLOWED_EXTENSIONS
|
||||
|
||||
def is_moderator(username):
|
||||
m = Moderator.filter(username=username)
|
||||
if m:
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
|
||||
def get_current_user():
|
||||
u = User.select().where(User.username == get_session_user()).first()
|
||||
return u
|
||||
|
@ -34,116 +25,3 @@ def get_session_user():
|
|||
return None
|
||||
return session["auth"]["preferred_username"].strip()
|
||||
|
||||
def get_latest_tipped_posts():
|
||||
key_name = 'latest_tips'
|
||||
posts = []
|
||||
tipped_posts = rw_cache(key_name)
|
||||
if not tipped_posts:
|
||||
w = Wallet()
|
||||
data = {}
|
||||
for acc in w.accounts():
|
||||
txes = w.transfers(acc)
|
||||
if 'in' in txes:
|
||||
for tx in txes['in']:
|
||||
p = Post.select().where(
|
||||
Post.account_index==acc
|
||||
).first()
|
||||
if p:
|
||||
data[tx['timestamp']] = p
|
||||
|
||||
dates = sorted(data, reverse=True)
|
||||
for d in dates:
|
||||
if not data[d] in posts:
|
||||
posts.append(data[d])
|
||||
|
||||
tipped_posts = rw_cache(key_name, posts)
|
||||
|
||||
return tipped_posts
|
||||
|
||||
def get_top_posters():
|
||||
top_posters = {}
|
||||
posts = rw_cache('top_posters')
|
||||
if not posts:
|
||||
posts = Post.select().where(Post.approved==True)
|
||||
for post in posts:
|
||||
transfers = []
|
||||
incoming = Wallet().incoming_transfers(post.account_index)
|
||||
if "transfers" in incoming:
|
||||
for xfer in incoming["transfers"]:
|
||||
transfers.append(from_atomic(xfer["amount"]))
|
||||
total = sum(transfers)
|
||||
if post.submitter not in top_posters:
|
||||
top_posters[post.submitter] = {"amount": 0, "posts": []}
|
||||
|
||||
top_posters[post.submitter]["amount"] += float(total)
|
||||
top_posters[post.submitter]["posts"].append(post)
|
||||
rw_cache('top_posters', top_posters)
|
||||
else:
|
||||
top_posters = posts
|
||||
return top_posters
|
||||
|
||||
def get_top_posts(days=1):
|
||||
top_posts = []
|
||||
try:
|
||||
days = int(days)
|
||||
except:
|
||||
days = 1
|
||||
|
||||
# stupid magic number bcuz fuck it
|
||||
if days not in [1, 3, 7, 30, 9999]:
|
||||
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 posts
|
||||
|
||||
# Use hacky filesystem cache since i dont feel like shipping redis
|
||||
def rw_cache(key_name, data=None, diff_seconds=3600):
|
||||
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 < diff_seconds:
|
||||
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
|
||||
|
|
|
@ -62,7 +62,6 @@ class Wallet(object):
|
|||
|
||||
def new_account(self, label=None):
|
||||
_account = self.make_wallet_rpc('create_account', {'label': label})
|
||||
self.store()
|
||||
return _account['account_index']
|
||||
|
||||
def addresses(self, account, addr_indices=None):
|
||||
|
|
Loading…
Reference in a new issue