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 from suchwow.models import Moderator, Post from suchwow.wownero import Wallet, from_atomic from suchwow import config 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_session_user(): if "auth" not in session or not session["auth"]: return None return session["auth"]["preferred_username"].strip() def post_webhook(msg): try: if current_app.config["DEBUG"]: msg = "[DEBUG] " + msg data = { "text": msg, "channel": config.MM_CHANNEL, "username": config.MM_USERNAME, "icon_url": config.MM_ICON } res = r_post(config.MM_ENDPOINT, data=dumps(data)) res.raise_for_status() return True except: return False 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 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 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