def get(self): search_term = self.get_argument("term") search_hq = False if search_term.lower().endswith(' hq'): search_term = search_term[:-3] search_hq = True matches = [ DATABASE.items_get_latest_by_id(id) for (name, id, hq) in DATABASE.items_search( language=self._get_language(), filter=search_term, ) ] if len(matches) == 1 or (search_hq and len(matches) == 2): m = matches[0] if search_hq: #Lexical sorting will always put this lower m = matches[1] self.redirect('/items/{id}'.format(id=m.item_state.id, )) return if search_hq: matches = [m for m in matches if m.item_state.hq] search_term += ' HQ' context = self._common_setup(page_title="Matches for '{term}'".format( term=search_term)) context.update({ 'search_term': search_term, 'search_matches': matches, }) self._render('search.html', context, html_headers=('<script src="{ajax_js}"></script>'.format( ajax_js=self.static_url('ajax.js')), ))
def post(self): item_id = self.get_argument("item_id", default=None) if not item_id: self.redirect("/items/search?term={term}".format( term=tornado.escape.url_escape(self.get_argument('term')), )) return item_id = int(item_id) value = self.get_argument("value", default=None) if value: try: value = int(value.strip()) except ValueError: raise tornado.web.HTTPError(422, reason="Invalid value: {value}".format( value=value, )) else: value = None context = self._build_common_context() if value is not None: DATABASE.items_add_price( item_id=item_id, value_average=value, value_average_low=value, value_average_high=value, quantity=None, user_id=context['identity']['user_id'], ) self.redirect("/items/{item_id}".format( item_id=item_id, ))
def post(self): item_id = int(self.get_argument("item_id")) value = int(self.get_argument("value")) context = self._build_common_context() DATABASE.items_add_price(item_id, value, context['identity']['user_id']) self.write({})
def post(self): item_id = int(self.get_argument("item_id")) context = self._build_common_context() DATABASE.watchlist_remove(context['identity']['user_id'], item_id) self.write({})
def post(self): item_id = self.get_argument("item_id", default=None) if not item_id: self.redirect("/items/search?term={term}".format( term=tornado.escape.url_escape(self.get_argument('term')), )) return item_id = int(item_id) value = self.get_argument("value", default=None) if value: try: value = int(value.strip()) except ValueError: raise tornado.web.HTTPError( 422, reason="Invalid value: {value}".format(value=value, )) else: value = None context = self._build_common_context() if value is not None: DATABASE.items_add_price( item_id=item_id, value_average=value, value_average_low=value, value_average_high=value, quantity=None, user_id=context['identity']['user_id'], ) self.redirect("/items/{item_id}".format(item_id=item_id, ))
def get(self): search_term = self.get_argument("term") search_hq = False if search_term.lower().endswith(' hq'): search_term = search_term[:-3] search_hq = True matches = [DATABASE.items_get_latest_by_id(id) for (name, id, hq) in DATABASE.items_search( language=self._get_language(), filter=search_term, )] if len(matches) == 1 or (search_hq and len(matches) == 2): m = matches[0] if search_hq: #Lexical sorting will always put this lower m = matches[1] self.redirect('/items/{id}'.format( id=m.item_state.id, )) return if search_hq: matches = [m for m in matches if m.item_state.hq] search_term += ' HQ' context = self._common_setup(page_title="Matches for '{term}'".format(term=search_term)) context.update({ 'search_term': search_term, 'search_matches': matches, }) self._render('search.html', context, html_headers=( '<script src="{ajax_js}"></script>'.format(ajax_js=self.static_url('ajax.js')), ))
def post(self): user_id = self.get_current_user() or DATABASE.users_login(*validate_credentials( self.get_argument('username'), self.get_argument('password'), )) if user_id is None or user_id < 0: raise tornado.web.HTTPError(403, reason='Unable to validate access') item_id = DATABASE.items_get_id_by_base_item_id( int(self.get_argument('item_id')), bool(self.get_argument('hq', default=False)), ) if item_id is None: raise tornado.web.HTTPError(404, reason='Unknown item') cached_item = DATABASE.items_get_latest_by_id(item_id) if not cached_item.item_state.price or cached_item.item_state.price.timestamp < (time.time() - (TIME_HOUR * CONFIG['data']['prices']['api_submission_cooldown_hours'])): DATABASE.items_add_price( item_id=item_id, value_average=int(self.get_argument('value_average')), value_average_low=int(self.get_argument('value_average_low')), value_average_high=int(self.get_argument('value_average_high')), quantity=int(self.get_argument('quantity')), user_id=user_id, ) self.set_secure_cookie( CONFIG['cookies']['authentication']['identifier'], str(user_id), expires_days=CONFIG['cookies']['authentication']['longevity_days'] )
def post(self): (username, password) = validate_credentials(self) try: DATABASE.users_create(username, password) except Exception, e: _logger.error(str(e)) raise tornado.web.HTTPError(409, reason="Character-name already exists")
def post(self): language = self.get_argument("language") context = self._build_common_context() user_id = context['identity']['user_id'] DATABASE.users_set_language(user_id, language) self.redirect('/users/{user_id}'.format( user_id=user_id, ))
def post(self): anonymous = self.get_argument("anonymity") == 'hide' context = self._build_common_context() user_id = context['identity']['user_id'] DATABASE.users_set_anonymous(user_id, anonymous) self.redirect('/users/{user_id}'.format( user_id=user_id, ))
def post(self): item_id = int(self.get_argument("item_id")) timestamp = int(self.get_argument("timestamp")) remove = self.get_argument("remove") == 'true' context = self._build_common_context() restrict_moderator(context) DATABASE.flags_resolve(item_id, timestamp, remove) self.write({})
def post(self): item_id = int(self.get_argument("item_id")) context = self._build_common_context() user_id = context['identity']['user_id'] if DATABASE.watchlist_count(user_id) >= CONFIG['lists']['item_watch']['limit']: raise tornado.web.HTTPError(409, reason='You cannot watch any more items') DATABASE.watchlist_add(user_id, item_id) self.write({})
def get(self, item_id): item_id = int(item_id) item_properties = DATABASE.items_get_properties(language=self._get_language(), item_id=item_id) if item_properties is None: raise tornado.web.HTTPError(404, reason='"{item_id}" is not a known item'.format( item_id=item_id, )) (item_name, xivdb_id, lodestone_id, hq) = item_properties context = self._build_common_context() quality_counterpart = None quality_counterpart_id = DATABASE.items_get_hq_variant_id(xivdb_id, not hq) if quality_counterpart_id is not None: quality_counterpart = DATABASE.items_get_latest_by_id(quality_counterpart_id) sites = dict((site[0], { 'server': site[1], 'url': site[3], 'colour': site[5], }) for site in DATABASE.aggregate_list_sites()) prices = collections.defaultdict(list) #Data-interpolation happens in the renderer, to avoid wasting memory unnecessarily for (site_id, timestamp, value, quantity) in DATABASE.aggregate_get_prices(xivdb_id, hq): prices[site_id].append((timestamp, value, quantity)) for site_id in prices: prices[site_id] = normalise_price_data( prices[site_id], interval=(CONFIG['aggregation']['graphing']['interval_hours'] * TIME_HOUR), align=True, start_time=(context['rendering']['time_current'] - (CONFIG['aggregation']['graphing']['days'] * TIME_DAY)), end_time=context['rendering']['time_current'], ) context['rendering']['title'] = item_name context.update({ 'language': self._get_language(), 'item_name': item_name, 'item_hq': hq, 'item_id': item_id, 'xivdb_id': xivdb_id, 'lodestone_id': lodestone_id, 'quality_counterpart': quality_counterpart, 'sites': sites, 'prices': prices, }) self._render('agg_item.html', context, html_headers=( #TODO: make this local static content once it's been validated '<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.1.6/Chart.bundle.min.js"></script>', ))
def post(self): item_id = int(self.get_argument("item_id")) context = self._build_common_context() user_id = context['identity']['user_id'] if DATABASE.watchlist_count( user_id) >= CONFIG['lists']['item_watch']['limit']: raise tornado.web.HTTPError( 409, reason='You cannot watch any more items') DATABASE.watchlist_add(user_id, item_id) self.write({})
def post(self): item_id = int(self.get_argument("item_id")) value = int(self.get_argument("value")) context = self._build_common_context() DATABASE.items_add_price( item_id=item_id, value_average=value, value_average_low=value, value_average_high=value, quantity=None, user_id=context['identity']['user_id'], ) self.write({})
def get(self): context = self._common_setup(page_title="Items") context.update({ 'get_crystal_list': (lambda : (DATABASE.items_get_latest_by_id(id) for id in _CRYSTAL_LIST)), 'get_most_valuable_list': (lambda : DATABASE.items_get_most_valuable( limit=CONFIG['lists']['most_valuable']['limit'], max_age=(context['rendering']['time_current'] - (CONFIG['lists']['most_valuable']['max_days'] * TIME_DAY)), min_value=CONFIG['lists']['most_valuable']['min_value'], max_value=CONFIG['lists']['most_valuable']['max_value'], )), 'get_most_watched_list': (lambda : DATABASE.watchlist_get_most_watched( limit=CONFIG['lists']['item_watch']['limit'], )), 'get_no_supply_list': (lambda : DATABASE.items_get_no_supply( limit=CONFIG['lists']['no_supply']['limit'], max_age=(context['rendering']['time_current'] - (CONFIG['lists']['no_supply']['max_days'] * TIME_DAY)), )), 'get_recently_updated_list': (lambda : DATABASE.items_get_recently_updated( limit=CONFIG['lists']['recently_updated']['limit'], max_age=(context['rendering']['time_current'] - (CONFIG['lists']['recently_updated']['max_days'] * TIME_DAY)), )), 'get_stale_list': (lambda : DATABASE.items_get_stale( limit=CONFIG['lists']['stale']['limit'], min_age=(context['rendering']['time_current'] - (CONFIG['lists']['stale']['min_days'] * TIME_DAY)), max_age=(context['rendering']['time_current'] - (CONFIG['lists']['stale']['max_days'] * TIME_DAY)), )), 'get_watched_list': (lambda : DATABASE.watchlist_list(user_id=context['identity']['user_id'])), 'watch_count': DATABASE.watchlist_count(context['identity']['user_id']), 'watch_limit': CONFIG['lists']['item_watch']['limit'], }) self._render('items.html', context, html_headers=( '<script src="{ajax_js}"></script>'.format(ajax_js=self.static_url('ajax.js')), ))
def post(self): reason = self.get_argument("reason").strip() user_id = int(self.get_argument("user_id")) if not reason: raise tornado.web.HTTPError(422, reason="No explanation provided for this action".format( offset=offset, )) context = self._build_common_context() restrict_moderator(context) DATABASE.users_accept_recovery_password(user_id) DATABASE.interactions_record(user_id, context['identity']['user_id'], 'recovered', reason) self.redirect('/users/{user_id}'.format( user_id=user_id, ))
def get(self): context = self._common_setup(page_title="Moderators") moderators = [ (user_id, user_name) for (user_id, user_name, _) in DATABASE.users_list(status=USER_STATUS_MODERATOR, order_most_recent=True) ] moderators.extend( (user_id, user_name) for (user_id, user_name, _) in DATABASE.users_list(status=USER_STATUS_ADMINISTRATOR, order_most_recent=True) ) context['moderators'] = moderators self._render('moderators.html', context)
def _render_snapshot(self): snapshot = DATABASE.items_get_price_snapshot( include_null=(self.get_argument('include_null', default='0') == '1'), max_age=int(self.get_argument('max_age', 0)), ) self.write(json.dumps(snapshot, separators=(',', ':')))
def get(self): context = self._common_setup( page_title="Users", restrict=restrict_moderator, ) pending = [] active = [] moderators = [] administrators = [] banned = [] for (user_id, user_name, user_status) in DATABASE.users_list(): if user_status == USER_STATUS_PENDING: pending.append((user_id, user_name)) elif user_status == USER_STATUS_ACTIVE: active.append((user_id, user_name)) elif user_status == USER_STATUS_MODERATOR: moderators.append((user_id, user_name)) elif user_status == USER_STATUS_ADMINISTRATOR: administrators.append((user_id, user_name)) elif user_status == USER_STATUS_BANNED: banned.append((user_id, user_name)) context.update({ 'users_pending': pending, 'users_active': active, 'users_moderator': moderators, 'users_administrator': administrators, 'users_banned': banned, }) self._render('users.html', context)
def post(self): (username, password) = validate_credentials(self) if not DATABASE.users_set_recovery_password(username, password): raise tornado.web.HTTPError(403, reason="Unable to set recovery password: character is not registered") self.redirect("/login/recover")
def get(self): search_term = self.get_argument("term") search_hq = False if search_term.lower().endswith(' hq'): search_term = search_term[:-3] search_hq = True matches = DATABASE.items_search( language=self._get_language(), filter=search_term, ) if len(matches) == 1 or (search_hq and len(matches) == 2): m = matches[0] if search_hq: #Lexical sorting will always put this lower m = matches[1] self.redirect('/items/{id}'.format( id=m.item_state.id, )) return if search_hq: matches = [m for m in matches if m[2]] search_term += ' HQ' context = self._common_setup(page_title="Matches for '{term}'".format(term=search_term)) context.update({ 'search_term': search_term, 'search_matches': matches, }) self._render('agg_search.html', context)
def get(self): search_term = self.get_argument("term") search_hq = False if search_term.lower().endswith(' hq'): search_term = search_term[:-3] search_hq = True matches = DATABASE.items_search( language=self._get_language(), filter=search_term, ) if len(matches) == 1 or (search_hq and len(matches) == 2): m = matches[0] if search_hq: #Lexical sorting will always put this lower m = matches[1] self.redirect('/items/{id}'.format(id=m.item_state.id, )) return if search_hq: matches = [m for m in matches if m[2]] search_term += ' HQ' context = self._common_setup(page_title="Matches for '{term}'".format( term=search_term)) context.update({ 'search_term': search_term, 'search_matches': matches, }) self._render('agg_search.html', context)
def get(self): context = self._build_common_context() context['sites'] = [{ 'server': site[1], 'name': site[2], 'url': site[3], } for site in DATABASE.aggregate_list_sites()] self._render('agg_index.html', context)
def get(self, base_item_id): item_id = DATABASE.items_get_id_by_base_item_id(int(base_item_id), bool(self.get_argument('hq', default=False))) if item_id is None: raise tornado.web.HTTPError(404, reason='"{item_id}" is not a known base-item'.format( item_id=base_item_id, )) self.redirect("/items/{item_id}".format( item_id=item_id, ))
def get(self, base_item_id): item_id = DATABASE.items_get_id_by_base_item_id( int(base_item_id), bool(self.get_argument('hq', default=False))) if item_id is None: raise tornado.web.HTTPError( 404, reason='"{item_id}" is not a known base-item'.format( item_id=base_item_id, )) self.redirect("/items/{item_id}".format(item_id=item_id, ))
def get(self): context = self._common_setup( page_title="Flags", restrict=restrict_moderator, ) context['flags'] = DATABASE.flags_list() self._render('flags.html', context, html_headers=( '<script src="{ajax_js}"></script>'.format(ajax_js=self.static_url('ajax.js')), ))
def get(self): context = self._common_setup( page_title="Flags", restrict=restrict_moderator, ) context['flags'] = DATABASE.flags_list() self._render('flags.html', context, html_headers=( '<script src="/static/ajax.js"></script>', ))
def get(self): context = self._common_setup(page_title="Items") context.update({ 'crystal_list': _CRYSTAL_LIST, 'watch_count': DATABASE.watchlist_count(context['identity']['user_id']), 'watch_limit': CONFIG['lists']['item_watch']['limit'], }) self._render('items.html', context, html_headers=( '<script src="/static/ajax.js"></script>', ))
def post(self): item_id = int(self.get_argument("item_id")) value = self.get_argument("value", default=None) if value: try: value = int(value.strip()) except ValueError: raise tornado.web.HTTPError(422, reason="Invalid value: {value}".format( value=value, )) else: value = None context = self._build_common_context() if value is not None: DATABASE.items_add_price(item_id, value, context['identity']['user_id']) self.redirect("/items/{item_id}".format( item_id=item_id, ))
def get(self): context = self._common_setup( page_title="Flags", restrict=restrict_moderator, ) context['flags'] = DATABASE.flags_list() self._render('flags.html', context, html_headers=('<script src="{ajax_js}"></script>'.format( ajax_js=self.static_url('ajax.js')), ))
def get(self): search_term = self.get_argument("term") limit = CONFIG['lists']['search']['limit'] options = [] for (name, id, hq) in DATABASE.items_search(language=self._get_language(), filter=search_term, limit=limit): if hq: name = '{name} HQ'.format(name=name) options.append({ 'label': name, 'value': id, }) self.write(json.dumps(options, separators=(',',':')))
def post(self): action = self.get_argument("action") reason = self.get_argument("reason").strip() user_id = int(self.get_argument("user_id")) if not reason: raise tornado.web.HTTPError(422, reason="No explanation provided for this action".format( offset=offset, )) context = self._build_common_context() subject_identity = DATABASE.users_get_identity(user_id) if subject_identity is None: raise tornado.web.HTTPError(404, reason="No user exists with id {id}".format( id=user_id, )) if action =='activated' and _can_set_active(user_id, subject_identity[1], context['identity']['user_id'], context['role']): status = USER_STATUS_ACTIVE CLEAR_BAN(user_id) elif action == 'promoted' and _can_set_moderator(user_id, subject_identity[1], context['identity']['user_id'], context['role']): status = USER_STATUS_MODERATOR CLEAR_BAN(user_id) elif action == 'banned' and _can_set_banned(user_id, subject_identity[1], context['identity']['user_id'], context['role']): status = USER_STATUS_BANNED ADD_BAN(user_id) else: raise tornado.web.HTTPError(422, reason="Unsupported action: {action}".format( action=action, )) DATABASE.users_set_status(user_id, status) DATABASE.interactions_record(user_id, context['identity']['user_id'], action, reason) self.redirect('/users/{user_id}'.format( user_id=user_id, ))
def post(self): user_id = self.get_current_user() or DATABASE.users_login( *validate_credentials( self.get_argument('username'), self.get_argument('password'), )) if user_id is None or user_id < 0: raise tornado.web.HTTPError(403, reason='Unable to validate access') item_id = DATABASE.items_get_id_by_base_item_id( int(self.get_argument('item_id')), bool(self.get_argument('hq', default=False)), ) if item_id is None: raise tornado.web.HTTPError(404, reason='Unknown item') cached_item = DATABASE.items_get_latest_by_id(item_id) if not cached_item.item_state.price or cached_item.item_state.price.timestamp < ( time.time() - (TIME_HOUR * CONFIG['data']['prices']['api_submission_cooldown_hours'])): DATABASE.items_add_price( item_id=item_id, value_average=int(self.get_argument('value_average')), value_average_low=int(self.get_argument('value_average_low')), value_average_high=int( self.get_argument('value_average_high')), quantity=int(self.get_argument('quantity')), user_id=user_id, ) self.set_secure_cookie( CONFIG['cookies']['authentication']['identifier'], str(user_id), expires_days=CONFIG['cookies']['authentication']['longevity_days'])
def get(self): search_term = self.get_argument("term") limit = CONFIG['lists']['search']['limit'] context = self._build_common_context() options = [] for (name, id, hq) in DATABASE.items_search(language=context['identity']['language'], filter=search_term, limit=limit): if hq: name = '{name} HQ'.format(name=name) options.append({ 'label': name, 'value': id, }) self.write(json.dumps(options))
def get(self): context = self._common_setup(page_title="Items") context.update({ 'get_crystal_list': (lambda: (DATABASE.items_get_latest_by_id(id) for id in _CRYSTAL_LIST)), 'get_most_valuable_list': (lambda: DATABASE.items_get_most_valuable( limit=CONFIG['lists']['most_valuable']['limit'], max_age=(context['rendering']['time_current'] - (CONFIG[ 'lists']['most_valuable']['max_days'] * TIME_DAY)), min_value=CONFIG['lists']['most_valuable']['min_value'], max_value=CONFIG['lists']['most_valuable']['max_value'], )), 'get_most_watched_list': (lambda: DATABASE.watchlist_get_most_watched(limit=CONFIG['lists'][ 'item_watch']['limit'], )), 'get_no_supply_list': (lambda: DATABASE.items_get_no_supply( limit=CONFIG['lists']['no_supply']['limit'], max_age=(context['rendering']['time_current'] - (CONFIG[ 'lists']['no_supply']['max_days'] * TIME_DAY)), )), 'get_recently_updated_list': (lambda: DATABASE.items_get_recently_updated( limit=CONFIG['lists']['recently_updated']['limit'], max_age=(context['rendering']['time_current'] - (CONFIG[ 'lists']['recently_updated']['max_days'] * TIME_DAY)), )), 'get_stale_list': (lambda: DATABASE.items_get_stale( limit=CONFIG['lists']['stale']['limit'], min_age=(context['rendering']['time_current'] - (CONFIG['lists']['stale']['min_days'] * TIME_DAY)), max_age=(context['rendering']['time_current'] - (CONFIG['lists']['stale']['max_days'] * TIME_DAY)), )), 'get_watched_list': (lambda: DATABASE.watchlist_list( user_id=context['identity']['user_id'])), 'watch_count': DATABASE.watchlist_count(context['identity']['user_id']), 'watch_limit': CONFIG['lists']['item_watch']['limit'], }) self._render('items.html', context, html_headers=('<script src="{ajax_js}"></script>'.format( ajax_js=self.static_url('ajax.js')), ))
def get(self): search_term = self.get_argument("term") limit = CONFIG['lists']['search']['limit'] options = [] for (name, id, hq) in DATABASE.items_search(language=self._get_language(), filter=search_term, limit=limit): if hq: name = '{name} HQ'.format(name=name) options.append({ 'label': name, 'value': id, }) self.write(json.dumps(options, separators=(',', ':')))
def post(self): (username, password) = validate_credentials(self) user_id = DATABASE.users_login(username, password) if user_id is not None: if user_id == -1: raise tornado.web.HTTPError(403, reason="Account is banned") self.set_secure_cookie( CONFIG['cookies']['authentication']['identifier'], str(user_id), expires_days=CONFIG['cookies']['authentication']['longevity_days'], ) self.redirect(self.get_argument("next", default="/")) return time.sleep(1) raise tornado.web.HTTPError(403, reason="Unrecognised character-name/password")
def get(self, user_id): user_id = int(user_id) context = self._common_setup() moderator = context['role']['moderator'] if not moderator and context['identity']['user_id'] != user_id: raise tornado.web.HTTPError(403, reason="You do not have access to user profiles") profile = DATABASE.users_get_profile(user_id) if profile is None: raise tornado.web.HTTPError(404, reason="No user exists with id {id}".format( id=user_id, )) (profile, actions_received, actions_performed, prices_submitted, invalid_prices_submitted, unresolved_flags, valid_flags_reported, invalid_flags_reported, ) = profile context['rendering']['title'] = profile[0] context.update({ 'user_id': user_id, 'user_name': profile[0], 'user_language': profile[1], 'user_language_options': USER_LANGUAGE_NAMES, 'user_anonymous': profile[2], 'user_status': USER_STATUS_NAMES[profile[3]], 'user_last_seen': profile[4], 'user_prices_submitted': prices_submitted, }) if moderator: context.update({ 'user_actions_received': actions_received, 'user_actions_performed': actions_performed, 'user_invalid_prices_submitted': invalid_prices_submitted, 'user_unresolved_flags': unresolved_flags, 'user_valid_flags_reported': valid_flags_reported, 'user_invalid_flags_reported': invalid_flags_reported, 'user_set_active': _can_set_active(user_id, profile[3], context['identity']['user_id'], context['role']), 'user_set_moderator': _can_set_moderator(user_id, profile[3], context['identity']['user_id'], context['role']), 'user_set_banned': _can_set_banned(user_id, profile[3], context['identity']['user_id'], context['role']), 'user_candidate_password_timestamp': profile[5], }) self._render('user.html', context)
def get(self, user_id): user_id = int(user_id) context = self._common_setup() moderator = context['role']['moderator'] if not moderator and context['identity']['user_id'] != user_id: raise tornado.web.HTTPError(403, reason="You do not have access to user profiles") profile = DATABASE.users_get_profile(user_id) if profile is None: raise tornado.web.HTTPError(404, reason="No user exists with id {id}".format( id=user_id, )) (profile, actions_received, actions_performed, prices_submitted, invalid_prices_submitted, unresolved_flags, valid_flags_reported, invalid_flags_reported, ) = profile context['rendering']['title'] = profile[0] context.update({ 'user_id': user_id, 'user_name': profile[0], 'user_anonymous': profile[1], 'user_status': USER_STATUS_NAMES[profile[2]], 'user_last_seen': profile[3], 'user_prices_submitted': prices_submitted, }) if moderator: context.update({ 'user_actions_received': actions_received, 'user_actions_performed': actions_performed, 'user_invalid_prices_submitted': invalid_prices_submitted, 'user_unresolved_flags': unresolved_flags, 'user_valid_flags_reported': valid_flags_reported, 'user_invalid_flags_reported': invalid_flags_reported, 'user_set_active': _can_set_active(user_id, profile[2], context['identity']['user_id'], context['role']), 'user_set_moderator': _can_set_moderator(user_id, profile[2], context['identity']['user_id'], context['role']), 'user_set_banned': _can_set_banned(user_id, profile[2], context['identity']['user_id'], context['role']), 'user_candidate_password_timestamp': profile[4], }) self._render('user.html', context)
def post(self): item_id = int(self.get_argument("item_id")) timestamp = int(self.get_argument("timestamp")) context = self._build_common_context() deleted = True if context['role']['moderator']: DATABASE.items_delete_price(item_id, timestamp) else: if context['rendering']['time_current'] - timestamp > CONFIG['data']['prices']['delete_window']: DATABASE.flags_create(item_id, timestamp, context['identity']['user_id']) deleted = False else: DATABASE.items_delete_price(item_id, timestamp, context['identity']['user_id']) self.write({'deleted': deleted})
def post(self): item_id = int(self.get_argument("item_id")) timestamp = int(self.get_argument("timestamp")) context = self._build_common_context() if context['role']['moderator']: DATABASE.items_delete_price(item_id, timestamp) else: if context['rendering']['time_current'] - timestamp > ( CONFIG['data']['prices']['delete_days'] * TIME_DAY): DATABASE.flags_create(item_id, timestamp, context['identity']['user_id']) else: DATABASE.items_delete_price(item_id, timestamp, context['identity']['user_id']) self.redirect("/items/{item_id}".format(item_id=item_id, ))
def post(self): item_id = int(self.get_argument("item_id")) timestamp = int(self.get_argument("timestamp")) context = self._build_common_context() deleted = True if context['role']['moderator']: DATABASE.items_delete_price(item_id, timestamp) else: if context['rendering']['time_current'] - timestamp > ( CONFIG['data']['prices']['delete_days'] * TIME_DAY): DATABASE.flags_create(item_id, timestamp, context['identity']['user_id']) deleted = False else: DATABASE.items_delete_price(item_id, timestamp, context['identity']['user_id']) self.write({ 'deleted': deleted, })
def get(self, item_id): item_id = int(item_id) context = self._common_setup() item_properties = DATABASE.items_get_properties( language=context['identity']['language'], item_id=item_id) if item_properties is None: raise tornado.web.HTTPError( 404, reason='"{item_id}" is not a known item'.format( item_id=item_id, )) (item_name, xivdb_id, lodestone_id, hq) = item_properties quality_counterpart = None quality_counterpart_id = DATABASE.items_get_hq_variant_id( xivdb_id, not hq) if quality_counterpart_id is not None: quality_counterpart = DATABASE.items_get_latest_by_id( quality_counterpart_id) (crafted_from, crafts_into) = DATABASE.related_get(xivdb_id) price_data = DATABASE.items_get_prices( item_id, max_age=(context['rendering']['time_current'] - (CONFIG['graphing']['days'] * TIME_DAY))) #Defaults low_month = low_week = low_24h = None high_month = high_week = high_24h = None average_month = average_week = average_24h = None trend_weekly = trend_daily = trend_current = None normalised_data = normalise_price_data( ((price.timestamp, price.value, price.quantity) for price in price_data), interval=(CONFIG['graphing']['interval_hours'] * TIME_HOUR), align=True, start_time=(context['rendering']['time_current'] - (CONFIG['graphing']['days'] * TIME_DAY)), end_time=context['rendering']['time_current'], ) if normalised_data: ( low_24h, low_week, low_month, high_24h, high_week, high_month, ) = self._compute_maxmin(price_data, context['rendering']['time_current']) (timeblock_days, timeblock_weeks) = self._compute_timeblock_averages( normalised_data, context['rendering']['time_current']) (average_24h, average_week, average_month) = self._compute_averages(timeblock_days, timeblock_weeks) (trend_current, trend_daily, trend_weekly) = self._compute_trends( normalised_data, context['rendering']['time_current'], timeblock_days, timeblock_weeks) context['rendering']['title'] = item_name context.update({ 'item_name': item_name, 'item_hq': hq, 'item_id': item_id, 'xivdb_id': xivdb_id, 'lodestone_id': lodestone_id, 'quality_counterpart': quality_counterpart, 'crafted_from': sorted((i for i in crafted_from if i), key=(lambda i: getattr(i.item_state.name, context[ 'identity']['language']))), 'crafts_into': sorted((i for i in crafts_into if i), key=(lambda i: getattr(i.item_state.name, context[ 'identity']['language']))), 'price_data': price_data, 'normalised_data': normalised_data, 'average_month': average_month, 'average_week': average_week, 'average_24h': average_24h, 'low_month': low_month, 'low_week': low_week, 'low_24h': low_24h, 'high_month': high_month, 'high_week': high_week, 'high_24h': high_24h, 'trend_weekly': trend_weekly, 'trend_daily': trend_daily, 'trend_current': trend_current, 'delete_lockout_time': 0, #Assume it's a moderator by default, to avoid resizing the table 'watch_count': DATABASE.watchlist_count(context['identity']['user_id']), 'watch_limit': CONFIG['lists']['item_watch']['limit'], 'watching': DATABASE.watchlist_is_watching(context['identity']['user_id'], item_id), }) if not context['role']['moderator']: context['delete_lockout_time'] = context['rendering'][ 'time_current'] - (CONFIG['data']['prices']['delete_days'] * TIME_DAY) self._render( 'item.html', context, html_headers=( '<script src="{ajax_js}"></script>'.format( ajax_js=self.static_url('ajax.js')), #TODO: make this static '<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.1.6/Chart.min.js"></script>', ))
def get(self, item_id): item_id = int(item_id) item_properties = DATABASE.items_get_properties( language=self._get_language(), item_id=item_id) if item_properties is None: raise tornado.web.HTTPError( 404, reason='"{item_id}" is not a known item'.format( item_id=item_id, )) (item_name, xivdb_id, lodestone_id, hq) = item_properties context = self._build_common_context() quality_counterpart = None quality_counterpart_id = DATABASE.items_get_hq_variant_id( xivdb_id, not hq) if quality_counterpart_id is not None: quality_counterpart = DATABASE.items_get_latest_by_id( quality_counterpart_id) sites = dict((site[0], { 'server': site[1], 'url': site[3], 'colour': site[5], }) for site in DATABASE.aggregate_list_sites()) prices = collections.defaultdict(list) #Data-interpolation happens in the renderer, to avoid wasting memory unnecessarily for (site_id, timestamp, value, quantity) in DATABASE.aggregate_get_prices(xivdb_id, hq): prices[site_id].append((timestamp, value, quantity)) for site_id in prices: prices[site_id] = normalise_price_data( prices[site_id], interval=(CONFIG['aggregation']['graphing']['interval_hours'] * TIME_HOUR), align=True, start_time=( context['rendering']['time_current'] - (CONFIG['aggregation']['graphing']['days'] * TIME_DAY)), end_time=context['rendering']['time_current'], ) context['rendering']['title'] = item_name context.update({ 'language': self._get_language(), 'item_name': item_name, 'item_hq': hq, 'item_id': item_id, 'xivdb_id': xivdb_id, 'lodestone_id': lodestone_id, 'quality_counterpart': quality_counterpart, 'sites': sites, 'prices': prices, }) self._render( 'agg_item.html', context, html_headers=( #TODO: make this local static content once it's been validated '<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.1.6/Chart.bundle.min.js"></script>', ))
TIME_WEEK, TIME_MONTH, VALUE_MAX, VALUE_MIN, VALUE_NOSTOCK, ) from ..data import ( normalise_price_data, ) from login import ( validate_credentials, ) _crystal_list = dict((item.item_state.name.en, item.item_state.id) for item in DATABASE.items_query(lambda items: [ i for i in items if i.item_state.name.en.endswith(( ' Shard', ' Crystal', ' Cluster', )) ])) _CRYSTAL_LIST = tuple( map(_crystal_list.get, ( 'Fire Shard', 'Ice Shard', 'Wind Shard', 'Earth Shard', 'Lightning Shard', 'Water Shard', 'Fire Crystal', 'Ice Crystal', 'Wind Crystal', 'Earth Crystal',