mirror of
https://git.wownero.com/wownero/wownero-funding-system.git
synced 2024-08-15 00:53:45 +00:00
folder rename; future commits make sense after this
This commit is contained in:
parent
09d0f09d8e
commit
f473a4234e
71 changed files with 0 additions and 0 deletions
0
funding/bin/__init__.py
Normal file
0
funding/bin/__init__.py
Normal file
210
funding/bin/anti_xss.py
Normal file
210
funding/bin/anti_xss.py
Normal file
|
@ -0,0 +1,210 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
Python 富文本XSS过滤类
|
||||
@package XssHtml
|
||||
@version 0.1
|
||||
@link http://phith0n.github.io/python-xss-filter
|
||||
@since 20150407
|
||||
@copyright (c) Phithon All Rights Reserved
|
||||
Based on native Python module HTMLParser purifier of HTML, To Clear all javascript in html
|
||||
You can use it in all python web framework
|
||||
Written by Phithon <root@leavesongs.com> in 2015 and placed in the public domain.
|
||||
phithon <root@leavesongs.com> 编写于20150407
|
||||
From: XDSEC <www.xdsec.org> & 离别歌 <www.leavesongs.com>
|
||||
GitHub Pages: https://github.com/phith0n/python-xss-filter
|
||||
Usage:
|
||||
parser = XssHtml()
|
||||
parser.feed('<html code>')
|
||||
parser.close()
|
||||
html = parser.getHtml()
|
||||
print html
|
||||
Requirements
|
||||
Python 2.6+ or 3.2+
|
||||
Cannot defense xss in browser which is belowed IE7
|
||||
浏览器版本:IE7+ 或其他浏览器,无法防御IE6及以下版本浏览器中的XSS
|
||||
"""
|
||||
import re
|
||||
try:
|
||||
from html.parser import HTMLParser
|
||||
except:
|
||||
from HTMLParser import HTMLParser
|
||||
|
||||
class XssHtml(HTMLParser):
|
||||
allow_tags = ['a', 'img', 'br', 'strong', 'b', 'code', 'pre',
|
||||
'p', 'div', 'em', 'span', 'h1', 'h2', 'h3', 'h4',
|
||||
'h5', 'h6', 'blockquote', 'ul', 'ol', 'tr', 'th', 'td',
|
||||
'hr', 'li', 'u', 'embed', 's', 'table', 'thead', 'tbody',
|
||||
'caption', 'small', 'q', 'sup', 'sub']
|
||||
common_attrs = ["style", "class", "name"]
|
||||
nonend_tags = ["img", "hr", "br", "embed"]
|
||||
tags_own_attrs = {
|
||||
"img": ["src", "width", "height", "alt", "align"],
|
||||
"a": ["href", "target", "rel", "title"],
|
||||
"embed": ["src", "width", "height", "type", "allowfullscreen", "loop", "play", "wmode", "menu"],
|
||||
"table": ["border", "cellpadding", "cellspacing"],
|
||||
}
|
||||
|
||||
_regex_url = re.compile(r'^(http|https|ftp)://.*', re.I | re.S)
|
||||
_regex_style_1 = re.compile(r'(\\|&#|/\*|\*/)', re.I)
|
||||
_regex_style_2 = re.compile(r'e.*x.*p.*r.*e.*s.*s.*i.*o.*n', re.I | re.S)
|
||||
|
||||
|
||||
def __init__(self, allows=[]):
|
||||
HTMLParser.__init__(self)
|
||||
self.allow_tags = allows if allows else self.allow_tags
|
||||
self.result = []
|
||||
self.start = []
|
||||
self.data = []
|
||||
|
||||
def getHtml(self):
|
||||
"""
|
||||
Get the safe html code
|
||||
"""
|
||||
for i in range(0, len(self.result)):
|
||||
self.data.append(self.result[i])
|
||||
return ''.join(self.data)
|
||||
|
||||
def handle_startendtag(self, tag, attrs):
|
||||
self.handle_starttag(tag, attrs)
|
||||
|
||||
def handle_starttag(self, tag, attrs):
|
||||
if tag not in self.allow_tags:
|
||||
return
|
||||
end_diagonal = ' /' if tag in self.nonend_tags else ''
|
||||
if not end_diagonal:
|
||||
self.start.append(tag)
|
||||
attdict = {}
|
||||
for attr in attrs:
|
||||
attdict[attr[0]] = attr[1]
|
||||
|
||||
attdict = self._wash_attr(attdict, tag)
|
||||
if hasattr(self, "node_%s" % tag):
|
||||
attdict = getattr(self, "node_%s" % tag)(attdict)
|
||||
else:
|
||||
attdict = self.node_default(attdict)
|
||||
|
||||
attrs = []
|
||||
for (key, value) in attdict.items():
|
||||
attrs.append('%s="%s"' % (key, self._htmlspecialchars(value)))
|
||||
attrs = (' ' + ' '.join(attrs)) if attrs else ''
|
||||
self.result.append('<' + tag + attrs + end_diagonal + '>')
|
||||
|
||||
def handle_endtag(self, tag):
|
||||
if self.start and tag == self.start[len(self.start) - 1]:
|
||||
self.result.append('</' + tag + '>')
|
||||
self.start.pop()
|
||||
|
||||
def handle_data(self, data):
|
||||
self.result.append(self._htmlspecialchars(data))
|
||||
|
||||
def handle_entityref(self, name):
|
||||
if name.isalpha():
|
||||
self.result.append("&%s;" % name)
|
||||
|
||||
def handle_charref(self, name):
|
||||
if name.isdigit():
|
||||
self.result.append("&#%s;" % name)
|
||||
|
||||
def node_default(self, attrs):
|
||||
attrs = self._common_attr(attrs)
|
||||
return attrs
|
||||
|
||||
def node_a(self, attrs):
|
||||
attrs = self._common_attr(attrs)
|
||||
attrs = self._get_link(attrs, "href")
|
||||
attrs = self._set_attr_default(attrs, "target", "_blank")
|
||||
attrs = self._limit_attr(attrs, {
|
||||
"target": ["_blank", "_self"]
|
||||
})
|
||||
return attrs
|
||||
|
||||
def node_embed(self, attrs):
|
||||
attrs = self._common_attr(attrs)
|
||||
attrs = self._get_link(attrs, "src")
|
||||
attrs = self._limit_attr(attrs, {
|
||||
"type": ["application/x-shockwave-flash"],
|
||||
"wmode": ["transparent", "window", "opaque"],
|
||||
"play": ["true", "false"],
|
||||
"loop": ["true", "false"],
|
||||
"menu": ["true", "false"],
|
||||
"allowfullscreen": ["true", "false"]
|
||||
})
|
||||
attrs["allowscriptaccess"] = "never"
|
||||
attrs["allownetworking"] = "none"
|
||||
return attrs
|
||||
|
||||
def _true_url(self, url):
|
||||
if self._regex_url.match(url):
|
||||
return url
|
||||
else:
|
||||
return "http://%s" % url
|
||||
|
||||
def _true_style(self, style):
|
||||
if style:
|
||||
style = self._regex_style_1.sub('_', style)
|
||||
style = self._regex_style_2.sub('_', style)
|
||||
return style
|
||||
|
||||
def _get_style(self, attrs):
|
||||
if "style" in attrs:
|
||||
attrs["style"] = self._true_style(attrs.get("style"))
|
||||
return attrs
|
||||
|
||||
def _get_link(self, attrs, name):
|
||||
if name in attrs:
|
||||
attrs[name] = self._true_url(attrs[name])
|
||||
return attrs
|
||||
|
||||
def _wash_attr(self, attrs, tag):
|
||||
if tag in self.tags_own_attrs:
|
||||
other = self.tags_own_attrs.get(tag)
|
||||
else:
|
||||
other = []
|
||||
|
||||
_attrs = {}
|
||||
if attrs:
|
||||
for (key, value) in attrs.items():
|
||||
if key in self.common_attrs + other:
|
||||
_attrs[key] = value
|
||||
return _attrs
|
||||
|
||||
def _common_attr(self, attrs):
|
||||
attrs = self._get_style(attrs)
|
||||
return attrs
|
||||
|
||||
def _set_attr_default(self, attrs, name, default=''):
|
||||
if name not in attrs:
|
||||
attrs[name] = default
|
||||
return attrs
|
||||
|
||||
def _limit_attr(self, attrs, limit={}):
|
||||
for (key, value) in limit.items():
|
||||
if key in attrs and attrs[key] not in value:
|
||||
del attrs[key]
|
||||
return attrs
|
||||
|
||||
def _htmlspecialchars(self, html):
|
||||
return html.replace("<", "<")\
|
||||
.replace(">", ">")\
|
||||
.replace('"', """)\
|
||||
.replace("'", "'")
|
||||
|
||||
|
||||
def such_xss(inp):
|
||||
"""Very ghetto anti-xss countermeasures. Possibly unsafe! :D
|
||||
Needs testing, or a proper solution. wow."""
|
||||
parser = XssHtml()
|
||||
parser.feed(inp)
|
||||
parser.close()
|
||||
result = parser.getHtml()
|
||||
|
||||
# oh noes teh markdown blockquotes
|
||||
lines = result.split('\n')
|
||||
_lines = []
|
||||
for line in lines:
|
||||
if line.startswith('>'):
|
||||
line = line[4:]
|
||||
line = '>%s' % line
|
||||
_lines.append(line)
|
||||
|
||||
return "\n".join(_lines)
|
52
funding/bin/daemon.py
Normal file
52
funding/bin/daemon.py
Normal file
|
@ -0,0 +1,52 @@
|
|||
import settings
|
||||
import requests
|
||||
|
||||
|
||||
class WowneroDaemon:
|
||||
def __init__(self):
|
||||
self.url = settings.RPC_LOCATION
|
||||
self.headers = {"User-Agent": "Mozilla"}
|
||||
|
||||
def create_address(self, label_name):
|
||||
data = {
|
||||
'method': 'create_address',
|
||||
'params': {'account_index': 0, 'label': label_name},
|
||||
'jsonrpc': '2.0',
|
||||
'id': '0'
|
||||
}
|
||||
return self._make_request(data)
|
||||
|
||||
def get_address(self, index):
|
||||
data = {
|
||||
'method': 'get_address',
|
||||
'params': {'address_index': [index], 'account_index': 0},
|
||||
'jsonrpc': '2.0',
|
||||
'id': '0'
|
||||
}
|
||||
try:
|
||||
result = self._make_request(data)
|
||||
return next(z for z in result['result']['addresses'] if z['address_index'] == index)
|
||||
except:
|
||||
return
|
||||
|
||||
def get_transfers_in(self, index):
|
||||
data = {
|
||||
"method":"get_transfers",
|
||||
"params": {"pool": True, "in": True, "account_index": 0, "subaddr_indices": [index]},
|
||||
"jsonrpc": "2.0",
|
||||
"id": "0",
|
||||
}
|
||||
data = self._make_request(data)
|
||||
data = data['result'].get('in', [])
|
||||
for d in data:
|
||||
d['amount_human'] = float(d['amount'])/1e11
|
||||
|
||||
return {
|
||||
'sum': sum([float(z['amount'])/1e11 for z in data]),
|
||||
'txs': data
|
||||
}
|
||||
|
||||
def _make_request(self, data):
|
||||
r = requests.post(self.url, json=data, headers=self.headers)
|
||||
r.raise_for_status()
|
||||
return r.json()
|
93
funding/bin/utils.py
Normal file
93
funding/bin/utils.py
Normal file
|
@ -0,0 +1,93 @@
|
|||
from datetime import datetime, date
|
||||
|
||||
import requests
|
||||
from flask import g
|
||||
from flask.json import JSONEncoder
|
||||
|
||||
import settings
|
||||
|
||||
|
||||
def json_encoder(obj):
|
||||
if isinstance(obj, (datetime, date)):
|
||||
return obj.isoformat()
|
||||
raise TypeError ("Type %s not serializable" % type(obj))
|
||||
|
||||
|
||||
class Summary:
|
||||
@staticmethod
|
||||
def fetch_prices():
|
||||
if hasattr(g, 'wowfunding_prices') and g.wow_prices:
|
||||
return g.wow_prices
|
||||
|
||||
from wowfunding.factory import cache
|
||||
cache_key = 'wowfunding_prices'
|
||||
data = cache.get(cache_key)
|
||||
if data:
|
||||
return data
|
||||
data = {
|
||||
'wow-btc': price_tradeogre_wow_btc(),
|
||||
'btc-usd': price_cmc_btc_usd()
|
||||
}
|
||||
|
||||
cache.set(cache_key, data=data, expiry=7200)
|
||||
g.wow_prices = data
|
||||
return data
|
||||
|
||||
@staticmethod
|
||||
def fetch_stats(purge=False):
|
||||
from wowfunding.factory import db_session
|
||||
from wowfunding.orm.orm import Proposal, User, Comment
|
||||
from wowfunding.factory import cache
|
||||
cache_key = 'wowfunding_stats'
|
||||
data = cache.get(cache_key)
|
||||
if data and not purge:
|
||||
return data
|
||||
|
||||
categories = settings.FUNDING_CATEGORIES
|
||||
statuses = settings.FUNDING_STATUSES.keys()
|
||||
|
||||
for cat in categories:
|
||||
q = db_session.query(Proposal)
|
||||
q = q.filter(Proposal.category == cat)
|
||||
res = q.count()
|
||||
data.setdefault('cats', {})
|
||||
data['cats'][cat] = res
|
||||
|
||||
for status in statuses:
|
||||
q = db_session.query(Proposal)
|
||||
q = q.filter(Proposal.status == status)
|
||||
res = q.count()
|
||||
data.setdefault('statuses', {})
|
||||
data['statuses'][status] = res
|
||||
|
||||
data.setdefault('users', {})
|
||||
data['users']['count'] = db_session.query(User.id).count()
|
||||
cache.set(cache_key, data=data, expiry=300)
|
||||
return data
|
||||
|
||||
|
||||
def price_cmc_btc_usd():
|
||||
headers = {'User-Agent': 'Mozilla/5.0 (Android 4.4; Mobile; rv:41.0) Gecko/41.0 Firefox/41.0'}
|
||||
try:
|
||||
r = requests.get('https://api.coinmarketcap.com/v2/ticker/1/?convert=USD', headers=headers)
|
||||
r.raise_for_status()
|
||||
return r.json().get('data', {}).get('quotes', {}).get('USD', {}).get('price')
|
||||
except:
|
||||
return
|
||||
|
||||
|
||||
def price_tradeogre_wow_btc():
|
||||
headers = {'User-Agent': 'Mozilla/5.0 (Android 4.4; Mobile; rv:41.0) Gecko/41.0 Firefox/41.0'}
|
||||
try:
|
||||
r = requests.get('https://tradeogre.com/api/v1/ticker/BTC-WOW', headers=headers)
|
||||
r.raise_for_status()
|
||||
return float(r.json().get('high'))
|
||||
except:
|
||||
return
|
||||
|
||||
|
||||
def wow_to_usd(wows: float, usd_per_btc: float, btc_per_wow: float):
|
||||
try:
|
||||
return round(usd_per_btc / (1.0 / (wows * btc_per_wow)), 2)
|
||||
except:
|
||||
pass
|
48
funding/bin/utils_request.py
Normal file
48
funding/bin/utils_request.py
Normal file
|
@ -0,0 +1,48 @@
|
|||
from datetime import datetime
|
||||
from flask import session, g
|
||||
|
||||
import settings
|
||||
from wowfunding.bin.utils import Summary
|
||||
from wowfunding.factory import app, db_session
|
||||
from wowfunding.orm.orm import Proposal, User, Comment
|
||||
|
||||
|
||||
@app.context_processor
|
||||
def templating():
|
||||
from flask.ext.login import current_user
|
||||
recent_comments = db_session.query(Comment).filter(Comment.automated == False).order_by(Comment.date_added.desc()).limit(10).all()
|
||||
summary_data = Summary.fetch_stats()
|
||||
return dict(logged_in=current_user.is_authenticated,
|
||||
current_user=current_user,
|
||||
funding_categories=settings.FUNDING_CATEGORIES,
|
||||
funding_statuses=settings.FUNDING_STATUSES,
|
||||
summary_data=summary_data,
|
||||
recent_comments=recent_comments)
|
||||
|
||||
|
||||
@app.before_request
|
||||
def before_request():
|
||||
pass
|
||||
|
||||
|
||||
@app.after_request
|
||||
def after_request(res):
|
||||
if hasattr(g, 'wowfunding_prices'):
|
||||
delattr(g, 'wowfunding_prices')
|
||||
res.headers.add('Accept-Ranges', 'bytes')
|
||||
if settings.DEBUG:
|
||||
res.headers['Cache-Control'] = 'no-cache, no-store, must-revalidate'
|
||||
res.headers['Pragma'] = 'no-cache'
|
||||
res.headers['Expires'] = '0'
|
||||
res.headers['Cache-Control'] = 'public, max-age=0'
|
||||
return res
|
||||
|
||||
|
||||
@app.teardown_appcontext
|
||||
def shutdown_session(**kwargs):
|
||||
db_session.remove()
|
||||
|
||||
|
||||
@app.errorhandler(404)
|
||||
def error(err):
|
||||
return 'Error', 404
|
163
funding/bin/utils_time.py
Normal file
163
funding/bin/utils_time.py
Normal file
|
@ -0,0 +1,163 @@
|
|||
from datetime import datetime, date
|
||||
from dateutil import parser
|
||||
import math
|
||||
import calendar
|
||||
|
||||
|
||||
class TimeMagic():
|
||||
def __init__(self):
|
||||
self.now = datetime.now()
|
||||
self.weekdays_en = {
|
||||
0: 'monday',
|
||||
1: 'tuesday',
|
||||
2: 'wednesday',
|
||||
3: 'thursday',
|
||||
4: 'friday',
|
||||
5: 'saturday',
|
||||
6: 'sunday'
|
||||
}
|
||||
self.months_en = {
|
||||
0: 'january',
|
||||
1: 'february',
|
||||
2: 'march',
|
||||
3: 'april',
|
||||
4: 'may',
|
||||
5: 'june',
|
||||
6: 'july',
|
||||
7: 'august',
|
||||
8: 'september',
|
||||
9: 'october',
|
||||
10: 'november',
|
||||
11: 'december'
|
||||
}
|
||||
|
||||
def get_weekday_from_datetime(self, dt):
|
||||
n = dt.today().weekday()
|
||||
return n
|
||||
|
||||
def week_number_get(self):
|
||||
now = datetime.now()
|
||||
return int(now.strftime("%V"))
|
||||
|
||||
def week_number_verify(self, week_nr):
|
||||
if week_nr > 0 or week_nr <= 53:
|
||||
return True
|
||||
|
||||
def get_weeknr_from_date(self, date):
|
||||
return date.strftime("%V")
|
||||
|
||||
def year_verify(self, year):
|
||||
if isinstance(year, str):
|
||||
try:
|
||||
year = int(year)
|
||||
except Exception as ex:
|
||||
return False
|
||||
|
||||
if 2000 <= year <= 2030:
|
||||
return True
|
||||
|
||||
def get_day_number(self):
|
||||
dt = datetime.now()
|
||||
return dt.today().weekday()
|
||||
|
||||
def get_month_nr(self):
|
||||
return datetime.now().strftime("%m")
|
||||
|
||||
def get_daynr_from_weekday(self, weekday):
|
||||
for k, v in self.weekdays_en.items():
|
||||
if v == weekday:
|
||||
return k
|
||||
|
||||
def get_day_from_daynr(self, nr):
|
||||
return self.weekdays_en[nr]
|
||||
|
||||
def get_month_from_weeknr(self, nr):
|
||||
nr = float(nr) / float(4)
|
||||
if nr.is_integer():
|
||||
nr -= 1
|
||||
else:
|
||||
nr = math.floor(nr)
|
||||
if nr < 0:
|
||||
nr = 0
|
||||
|
||||
return self.months_en[nr]
|
||||
|
||||
def get_month_nr_from_month(self, month):
|
||||
for k, v in self.months_en.items():
|
||||
if v == month:
|
||||
return k
|
||||
|
||||
def get_year(self):
|
||||
return date.today().year
|
||||
|
||||
def get_month(self):
|
||||
return date.today().month
|
||||
|
||||
def get_amount_of_days_from_month_nr(self, month_nr):
|
||||
try:
|
||||
max_days = calendar.monthrange(self.get_year(), int(month_nr))[1]
|
||||
return max_days
|
||||
except Exception as e:
|
||||
pass
|
||||
|
||||
def from_till(self):
|
||||
m = self.get_month()
|
||||
d = self.get_amount_of_days_from_month_nr(m)
|
||||
y = self.get_year()
|
||||
|
||||
if len(str(d)) == 1:
|
||||
d = '0' + str(d)
|
||||
else:
|
||||
d = str(d)
|
||||
|
||||
if len(str(m)) == 1:
|
||||
m = '0' + str(m)
|
||||
else:
|
||||
m = str(m)
|
||||
|
||||
f = '%s/01/%s' % (m, y)
|
||||
t = '%s/%s/%s' % (m, d, y)
|
||||
|
||||
return {'date_from': f, 'date_till': t}
|
||||
|
||||
def ago_dt(self, datetime):
|
||||
return self.ago(datetime)
|
||||
|
||||
def ago_str(self, date_str):
|
||||
date = parser.parse(date_str)
|
||||
return self.ago(date)
|
||||
|
||||
def ago(self, datetime=None, epoch=None):
|
||||
import math
|
||||
|
||||
if epoch:
|
||||
td = int(epoch)
|
||||
else:
|
||||
if datetime:
|
||||
td = (self.now - datetime).total_seconds()
|
||||
else:
|
||||
return None
|
||||
|
||||
if td < 60:
|
||||
if td == 1:
|
||||
return '%s second ago'
|
||||
else:
|
||||
return 'Just now'
|
||||
elif 60 <= td < 3600:
|
||||
if 60 <= td < 120:
|
||||
return '1 minute ago'
|
||||
else:
|
||||
return '%s minutes ago' % str(int(math.floor(td / 60)))
|
||||
elif 3600 <= td < 86400:
|
||||
if 3600 <= td < 7200:
|
||||
return '1 hour ago'
|
||||
else:
|
||||
return '%s hours ago' % str(int(math.floor(td / 60 / 60)))
|
||||
elif td >= 86400:
|
||||
if td <= 86400 < 172800:
|
||||
return '1 day ago'
|
||||
else:
|
||||
x = int(math.floor(td / 24 / 60 / 60))
|
||||
if x == 1:
|
||||
return '1 day ago'
|
||||
return '%s days ago' % str(x)
|
Loading…
Add table
Add a link
Reference in a new issue