updating funcs and queries

This commit is contained in:
lza_menace 2022-09-04 10:13:17 -07:00
parent df33eaf258
commit 289995cd49
8 changed files with 66 additions and 169 deletions

View File

@ -32,8 +32,13 @@ class User(Model):
ban_timestamp = DateField(null=True) ban_timestamp = DateField(null=True)
login_timestamp = DateTimeField(null=True) login_timestamp = DateTimeField(null=True)
def __repr__(self): def get_wow_received(self):
return self.username 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: class Meta:
database = db database = db
@ -74,17 +79,9 @@ class Post(Model):
s = path.splitext(self.image_name) s = path.splitext(self.image_name)
return s[0] + '.thumbnail' + s[1] return s[0] + '.thumbnail' + s[1]
def get_received_wow(self): def get_wow_received(self):
try: tips = TipReceived.select().where(TipReceived.post == self)
w = wownero.Wallet() return sum(tip.amount for tip in tips)
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 hours_elapsed(self): def hours_elapsed(self):
now = datetime.utcnow() now = datetime.utcnow()
@ -107,7 +104,7 @@ class Post(Model):
'timestamp': self.timestamp, 'timestamp': self.timestamp,
'approved': self.approved, 'approved': self.approved,
'approved_by': self.approved_by, 'approved_by': self.approved_by,
'received_wow': self.get_received_wow(), 'received_wow': self.get_wow_received(),
'hours_elapsed': self.hours_elapsed() 'hours_elapsed': self.hours_elapsed()
} }
@ -149,7 +146,8 @@ class TipReceived(Model):
class TipSent(Model): class TipSent(Model):
id = AutoField() id = AutoField()
user = ForeignKeyField(User) from_user = ForeignKeyField(User)
to_user = ForeignKeyField(User)
txid = CharField(unique=True) txid = CharField(unique=True)
timestamp = DateTimeField() timestamp = DateTimeField()
amount = IntegerField() amount = IntegerField()

View File

@ -1,12 +1,9 @@
from os import makedirs from os import makedirs
import click from flask import Blueprint
from flask import Blueprint, url_for, current_app
from suchwow._models import db, User, Post, AuditEvent, TipSent, TipReceived, Vote from suchwow._models import db, User, Post, AuditEvent, TipSent, TipReceived, Vote
from suchwow.utils.helpers import get_latest_tipped_posts from suchwow.models import Post as OldPost
from suchwow.utils.helpers import get_top_posters, get_top_posts
from suchwow.reddit import make_post
from suchwow import wownero from suchwow import wownero
from suchwow import config from suchwow import config
@ -23,6 +20,29 @@ def init():
db.create_tables([User, Post, AuditEvent, TipSent, TipReceived, Vote]) 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") # @bp.cli.command("post_reddit")
# @click.argument('last_hours') # @click.argument('last_hours')
# def post_reddit(last_hours): # def post_reddit(last_hours):
@ -40,15 +60,6 @@ def init():
# return # 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") # @bp.cli.command("payout_users")
# def payout_users(): # def payout_users():
# wallet = wownero.Wallet() # wallet = wownero.Wallet()

View File

@ -1,13 +1,27 @@
import peewee
from flask import render_template, Blueprint, request 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 = Blueprint("leaderboard", "leaderboard")
@bp.route("/leaderboards/top_posters") @bp.route("/leaderboards/top_posters")
def 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) return render_template("leaderboard.html", posters=top_posters)
@bp.route("/leaderboards/top_posts") @bp.route("/leaderboards/top_posts")

View File

@ -2,8 +2,7 @@ from math import ceil
from flask import Blueprint, request, render_template, flash from flask import Blueprint, request, render_template, flash
from suchwow._models import Post, User from suchwow._models import Post, User, TipReceived
from suchwow.utils.helpers import get_latest_tipped_posts
bp = Blueprint('main', 'main') bp = Blueprint('main', 'main')
@ -16,10 +15,10 @@ def index():
content = request.args.get("content", None) content = request.args.get("content", None)
if content == 'latest_tipped': 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( return render_template(
"index.html", "index.html",
posts=posts[0:30], posts=posts,
title="Latest Tipped Memes" title="Latest Tipped Memes"
) )
@ -29,9 +28,9 @@ def index():
flash("Wow, wtf hackerman. Cool it.", "is-danger") flash("Wow, wtf hackerman. Cool it.", "is-danger")
page = 1 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: if submitter:
user = Post.select().where(Post.username == submitter).first() user = User.select().where(User.username == submitter)
if not user: if not user:
flash('That user does not exist!', 'is-warning') flash('That user does not exist!', 'is-warning')
else: else:

View File

@ -11,7 +11,7 @@ from werkzeug.utils import secure_filename
from suchwow import wownero, config from suchwow import wownero, config
from suchwow._models import User, Post, TipReceived from suchwow._models import User, Post, TipReceived
from suchwow.utils.decorators import login_required, address_required, moderator_required 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.utils.helpers import audit_event
from suchwow.discord import post_discord_webhook from suchwow.discord import post_discord_webhook

View File

@ -16,19 +16,18 @@
{% if posts %} {% if posts %}
{% for row in posts | batch(4) %} {% for row in posts | batch(4) %}
<div class="columns"> <div class="columns">
{% for p in row %} {% for post in row %}
{% set post = p.show() %}
<div class="column"> <div class="column">
<div class="card"> <div class="card">
<div class="card-image"> <div class="card-image">
<a href="{{ url_for('post.read', id=post.id) }}"> <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> <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. Your browser does not support the video tag.
</video> </video>
{% else %} {% 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 %} {% endif %}
</a> </a>
</div> </div>
@ -38,13 +37,12 @@
<p class="title is-4"> <p class="title is-4">
<a href="{{ url_for('post.read', id=post.id) }}">{{ post.title }}</a> <a href="{{ url_for('post.read', id=post.id) }}">{{ post.title }}</a>
</p> </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> </div>
<div class="content"> <div class="content">
{{ post.text | truncate(60) }} {{ 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> <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> <p>({{ post.timestamp | humanize }})</p>
</div> </div>

View File

@ -5,8 +5,6 @@ from datetime import datetime, timedelta
from flask import session from flask import session
from suchwow._models import AuditEvent, User from suchwow._models import AuditEvent, User
from suchwow.models import Moderator, Post, Profile
from suchwow.wownero import Wallet, from_atomic
from suchwow import config from suchwow import config
@ -14,13 +12,6 @@ def allowed_file(filename):
return "." in filename and \ return "." in filename and \
filename.rsplit(".", 1)[1].lower() in config.ALLOWED_EXTENSIONS 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(): def get_current_user():
u = User.select().where(User.username == get_session_user()).first() u = User.select().where(User.username == get_session_user()).first()
return u return u
@ -34,116 +25,3 @@ def get_session_user():
return None return None
return session["auth"]["preferred_username"].strip() 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

View File

@ -62,7 +62,6 @@ class Wallet(object):
def new_account(self, label=None): def new_account(self, label=None):
_account = self.make_wallet_rpc('create_account', {'label': label}) _account = self.make_wallet_rpc('create_account', {'label': label})
self.store()
return _account['account_index'] return _account['account_index']
def addresses(self, account, addr_indices=None): def addresses(self, account, addr_indices=None):