Beispiel #1
0
    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')), ))
Beispiel #2
0
 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,
     ))
Beispiel #3
0
 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({})
Beispiel #4
0
 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({})
Beispiel #5
0
    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, ))
Beispiel #6
0
 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')),
     ))
Beispiel #7
0
    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({})
Beispiel #8
0
 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']
     )
Beispiel #9
0
 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")
Beispiel #10
0
 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,
     ))
Beispiel #11
0
 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,
     ))
Beispiel #12
0
 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({})
Beispiel #13
0
    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({})
Beispiel #14
0
 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,
     ))
     
Beispiel #15
0
 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({})
Beispiel #16
0
 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>',
     ))
Beispiel #17
0
    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({})
Beispiel #18
0
 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({})
Beispiel #19
0
 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')),
     ))
Beispiel #20
0
    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({})
Beispiel #21
0
 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,
     ))
Beispiel #22
0
 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,
     ))
Beispiel #23
0
 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)
Beispiel #24
0
 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=(',', ':')))
Beispiel #25
0
 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)
Beispiel #26
0
 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)
Beispiel #27
0
 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)
Beispiel #28
0
 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")
Beispiel #29
0
 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)
Beispiel #30
0
    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)
Beispiel #31
0
    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)
Beispiel #32
0
 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,
     ))
Beispiel #33
0
 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)
Beispiel #34
0
 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, ))
Beispiel #35
0
 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')),
     ))
Beispiel #36
0
 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>',
     ))
Beispiel #37
0
 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>',
     ))
Beispiel #38
0
 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,
     ))
Beispiel #39
0
    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')), ))
Beispiel #40
0
 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=(',',':')))
Beispiel #41
0
 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,
     ))
Beispiel #42
0
    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'])
Beispiel #43
0
 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))
Beispiel #44
0
    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')), ))
Beispiel #45
0
 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,
     ))
Beispiel #46
0
    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=(',', ':')))
Beispiel #47
0
 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")
Beispiel #48
0
 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)
Beispiel #49
0
 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)
Beispiel #50
0
 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})
Beispiel #51
0
    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, ))
Beispiel #52
0
    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,
        })
Beispiel #53
0
    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>',
            ))
Beispiel #54
0
    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>',
            ))
Beispiel #55
0
    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',