def report(form: ReportForm) -> bool:
    try:
        db().get_lock('deck_id:{id}'.format(id=form.entry))
        db().get_lock('deck_id:{id}'.format(id=form.opponent))

        for m in match.get_matches(form):
            if int(form.opponent) == m.opponent_deck_id:
                form.errors[
                    'result'] = 'This match was reported as You {game_wins}–{game_losses} {opponent} {date}'.format(
                        game_wins=m.game_wins,
                        game_losses=m.game_losses,
                        opponent=m.opponent,
                        date=dtutil.display_date(m.date))
                return False

        counts = deck.count_matches(form.entry, form.opponent)
        if counts[int(form.entry)] >= 5:
            form.errors['entry'] = 'You already have 5 matches reported'
            return False
        if counts[int(form.opponent)] >= 5:
            form.errors[
                'opponent'] = 'Your opponent already has 5 matches reported'
            return False
        pdbot = form.get('api_token',
                         None) == configuration.get('pdbot_api_token')
        if pdbot:
            mtgo_match_id = form.get('matchID', None)
        else:
            mtgo_match_id = None
            entry_name = deck.load_deck(int(form.entry)).person
            opp_name = deck.load_deck(int(form.opponent)).person
            fetcher.post_discord_webhook(
                configuration.get_str('league_webhook_id'),
                configuration.get_str('league_webhook_token'),
                '{entry} reported {f.entry_games}-{f.opponent_games} vs {opponent}'
                .format(f=form, entry=entry_name, opponent=opp_name))

        db().begin()
        match.insert_match(dtutil.now(), form.entry, form.entry_games,
                           form.opponent, form.opponent_games, None, None,
                           mtgo_match_id)
        db().commit()
        return True
    except LockNotAcquiredException:
        form.errors[
            'entry'] = 'Cannot report right now, somebody else is reporting a match for you or your opponent. Try again a bit later'
        return False
    finally:
        db().release_lock('deck_id:{id}'.format(id=form.opponent))
        db().release_lock('deck_id:{id}'.format(id=form.entry))
def tournament_deck(cells: ResultSet, competition_id: int,
                    date: datetime.datetime,
                    final: Dict[str, int]) -> Optional[deck.Deck]:
    d: deck.RawDeckDescription = {
        'source': 'Gatherling',
        'competition_id': competition_id,
        'created_date': dtutil.dt2ts(date)
    }
    player = cells[2]
    username = aliased(player.a.contents[0].string)
    d['mtgo_username'] = username
    d['finish'] = final.get(username)
    link = cells[4].a
    d['url'] = gatherling_url(link['href'])
    d['name'] = link.string
    if cells[5].find('a'):
        d['archetype'] = cells[5].a.string
    else:
        d['archetype'] = cells[5].string
    gatherling_id = urllib.parse.parse_qs(
        urllib.parse.urlparse(str(d['url'])).query)['id'][0]
    d['identifier'] = gatherling_id
    existing = deck.get_deck_id(d['source'], d['identifier'])
    if existing is not None:
        return deck.load_deck(existing)
    dlist = decklist.parse(
        fetcher.internal.post(gatherling_url('deckdl.php'),
                              {'id': gatherling_id}))
    d['cards'] = dlist
    if len(dlist['maindeck']) + len(dlist['sideboard']) == 0:
        logger.warning(
            'Rejecting deck with id {id} because it has no cards.'.format(
                id=gatherling_id))
        return None
    return deck.add_deck(d)
Exemple #3
0
def export(deck_id):
    d = ds.load_deck(deck_id)
    if d.is_in_current_run():
        if not auth.person_id() or auth.person_id() != d.person_id:
            abort(403)
    safe_name = deck_name.file_name(d)
    return (mc.to_mtgo_format(str(d)), 200, {'Content-type': 'text/plain; charset=utf-8', 'Content-Disposition': 'attachment; filename={name}.txt'.format(name=safe_name)})
Exemple #4
0
def cmc(deck_id):
    name = str(deck_id) + '-cmc.png'
    if not os.path.exists(configuration.get('charts_dir')):
        raise DoesNotExistException(
            'Cannot store graph images because {dir} does not exist.'.format(
                dir=configuration.get('charts_dir')))
    path = os.path.join(configuration.get('charts_dir'), name)
    if os.path.exists(path):
        return path
    d = deck.load_deck(deck_id)
    costs = {}
    for ci in d.maindeck:
        c = ci.get('card')
        if c.is_land():
            continue
        if c.mana_cost is None:
            cost = '0'
        elif next((s for s in c.mana_cost if '{X}' in s), None) is not None:
            cost = 'X'
        else:
            cost = int(float(c.cmc))
            if cost >= 7:
                cost = '7+'
            cost = str(cost)
        costs[cost] = ci.get('n') + costs.get(cost, 0)
    return image(path, costs)
Exemple #5
0
def do_admin_retire_deck() -> wrappers.Response:
    form = RetireForm(request.form)
    if form.validate():
        d = ds.load_deck(form.entry)
        lg.retire_deck(d)
        return redirect(url_for('admin_retire_deck'))
    return make_response(admin_retire_deck(form))
Exemple #6
0
def cmc(deck_id: int, attempts: int = 0) -> str:
    if attempts > 3:
        msg = 'Unable to generate cmc chart for {id} in 3 attempts.'.format(
            id=deck_id)
        logger.error(msg)
        raise OperationalException(msg)
    path = determine_path(str(deck_id) + '-cmc.png')
    if acceptable_file(path):
        return path
    d = deck.load_deck(deck_id)
    costs: Dict[str, int] = {}
    for ci in d.maindeck:
        c = ci.card
        if c.is_land():
            continue
        if c.mana_cost is None:
            cost = '0'
        elif next((s for s in c.mana_cost if '{X}' in s), None) is not None:
            cost = 'X'
        else:
            converted = int(float(c.cmc))
            cost = '7+' if converted >= 7 else str(converted)
        costs[cost] = ci.get('n') + costs.get(cost, 0)
    path = image(path, costs)
    if acceptable_file(path):
        return path
    return cmc(deck_id, attempts + 1)
Exemple #7
0
def retire_deck() -> Union[str, Response]:
    form = RetireForm(request.form, discord_user=session.get('id'))
    if form.validate():
        d = ds.load_deck(form.entry)
        ps.associate(d, session['id'])
        lg.retire_deck(d)
        return redirect(url_for('signup'))
    return retire(form)
Exemple #8
0
def export(deck_id):
    d = deck.load_deck(deck_id)
    safe_name = deck_name.file_name(d)
    return (str(d), 200, {
        'Content-type':
        'text/plain; charset=utf-8',
        'Content-Disposition':
        'attachment; filename={name}.txt'.format(name=safe_name)
    })
Exemple #9
0
def store_deck(d: deck.Deck) -> deck.Deck:
    d['source'] = d['source_name']
    d['url'] = d['source_url']
    existing = deck.get_deck_id(d['source'], d['identifier'])
    if existing is not None:
        return deck.load_deck(existing)
    d['mtgo_username'] = d['person']
    d['cards'] = decklist.unvivify(d)
    return deck.add_deck(d)
def deck(deck_id):
    d = ds.load_deck(deck_id)
    if auth.discord_id() and auth.logged_person() is None and not d.is_person_associated():
        ps.associate(d, auth.discord_id())
        p = ps.load_person_by_discord_id(auth.discord_id())
        auth.log_person(p)

    view = Deck(d, auth.logged_person())
    return view.page()
def deck_embed(deck_id: int) -> Response:
    # Discord doesn't actually show this yet.  I've reached out to them for better documentation about what they do/don't accept.
    d = deck.load_deck(deck_id)
    view = DeckEmbed(d, None, None)
    width = 1200
    height = 500
    embed = {
        'type': 'rich',
        'version': '1.0',
        'title': view.page_title(),
        'width': width,
        'height': height,
        'html': template.render(view)
    }
    return return_json(embed)
Exemple #12
0
def deck_api(deck_id):
    blob = deck.load_deck(deck_id)
    return return_json(blob)
Exemple #13
0
def deck(deck_id: int) -> str:
    d = ds.load_deck(deck_id)
    view = Deck(d, auth.person_id(), auth.discord_id())
    return view.page()
def deck_api(deck_id: int) -> Response:
    blob = deck.load_deck(deck_id)
    return return_json(blob)
Exemple #15
0
def decks(deck_id):
    view = Deck(deck.load_deck(deck_id))
    return view.page()
Exemple #16
0
 def get(self, deck_id: int) -> Deck:
     return deck.load_deck(deck_id)