Example #1
0
def main() -> None:
    if configuration.get('github_user') is None or configuration.get(
            'github_password') is None:
        print('Invalid Config')
        sys.exit(1)

    verification_numbers()

    issues = repo.get_repo().get_issues()
    for issue in issues:
        print(issue.title)
        if issue.state == 'open':
            process_issue(issue)

    txt = open('bannable.txt', mode='w')
    pd = open('pd_bannable.txt', mode='w')
    for bug in ALL_BUGS:
        if bug['bannable']:
            txt.write(bug['card'] + '\n')
            if bug['pd_legal']:
                pd.write(bug['card'] + '\n')
    txt.close()
    pd.close()

    bugsjson = open('bugs.json', mode='w')
    json.dump(ALL_BUGS, bugsjson, indent=2)
    bugsjson.close()
Example #2
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)
Example #3
0
def login(user=None, password=None):
    if user is None:
        user = configuration.get('to_username')
    if password is None:
        password = configuration.get('to_password')
    if user == '' or password == '':
        print('No TappedOut credentials provided')
        return
    url = "https://tappedout.net/accounts/login/"
    session = fetcher_internal.SESSION
    response = session.get(url)

    match = re.search(
        r"<input type='hidden' name='csrfmiddlewaretoken' value='(\w+)' />",
        response.text)
    if match is None:
        # Already logged in?
        return
    csrf = match.group(1)

    data = {
        'csrfmiddlewaretoken': csrf,
        'next': '/',
        'username': user,
        'password': password,
    }
    headers = {
        'referer': url,
    }
    print("Logging in to TappedOut as {0}".format(user))
    response = session.post(url, data=data, headers=headers)
    if response.status_code == 403:
        print("Failed to log in")
def decksite_url(path='/'):
    hostname = configuration.get('decksite_hostname')
    port = configuration.get('decksite_port')
    if port != 80:
        hostname = '{hostname}:{port}'.format(hostname=hostname, port=port)
    return parse.urlunparse((configuration.get('decksite_protocol'), hostname,
                             path, None, None, None))
 def __init__(self, db):
     warnings.filterwarnings('error', category=MySQLdb.Warning)
     try:
         self.name = db
         host = configuration.get('mysql_host')
         port = configuration.get('mysql_port')
         if str(port).startswith('0.0.0.0:'):
             # Thanks Docker :/
             port = int(port[8:])
         user = configuration.get('mysql_user')
         passwd = configuration.get('mysql_passwd')
         self.connection = MySQLdb.connect(host=host,
                                           port=port,
                                           user=user,
                                           passwd=passwd,
                                           use_unicode=True,
                                           charset='utf8',
                                           autocommit=True)
         self.cursor = self.connection.cursor(MySQLdb.cursors.DictCursor)
         self.execute('SET NAMES utf8mb4')
         try:
             self.execute("USE {db}".format(db=db))
         except DatabaseException:
             print('Creating database {db}'.format(db=db))
             self.execute(
                 'CREATE DATABASE {db} CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci'
                 .format(db=db))
             self.execute('USE {db}'.format(db=db))
     except MySQLdb.Error as e:
         raise DatabaseException(
             'Failed to initialize database in `{location}`'.format(
                 location=db)) from e
Example #6
0
    async def google(self, client: Client, channel: Channel, args: str,
                     author: Member, **_: Dict[str, Any]) -> None:
        """`!google {args}` Search google for `args`."""
        await client.send_typing(channel)

        api_key = configuration.get('cse_api_key')
        cse_id = configuration.get('cse_engine_id')
        if api_key is None or cse_id is None:
            return await client.send_message(
                channel, 'The google command has not been configured.')

        if len(args.strip()) == 0:
            return await client.send_message(
                channel,
                '{author}: No search term provided. Please type !google followed by what you would like to search'
                .format(author=author.mention))

        try:
            service = build('customsearch', 'v1', developerKey=api_key)
            res = service.cse().list(q=args, cx=cse_id, num=1).execute()  # pylint: disable=no-member
            if 'items' in res:
                r = res['items'][0]
                s = '{title} <{url}> {abstract}'.format(title=r['title'],
                                                        url=r['link'],
                                                        abstract=r['snippet'])
            else:
                s = '{author}: Nothing found on Google.'.format(
                    author=author.mention)
        except HttpError as e:
            if e.resp['status'] == '403':
                s = 'We have reached the allowed limits of Google API'
            else:
                raise e

        await client.send_message(channel, s)
Example #7
0
def run() -> None:
    wd = configuration.get_str('modo_bugs_dir')
    if not os.path.exists(wd):
        subprocess.run(['git', 'clone', 'https://github.com/PennyDreadfulMTG/modo-bugs.git', wd])
    os.chdir(wd)
    subprocess.run(['git', 'pull'])
    args = sys.argv[2:]
    if not args:
        args.extend(['scrape', 'update', 'verify', 'commit'])
    print('modo_bugs invoked with modes: ' + repr(args))

    changes: List[str] = []

    if 'scrape' in args:
        args.extend(['scrape_bb', 'scrape_an'])
    if 'scrape_bb' in args:
        scrape_bugblog.main(changes)
    if 'scrape_an' in args:
        scrape_announcements.main(changes)

    if 'update' in args:
        update.main()
    if 'verify' in args:
        verification.main()
    if 'commit' in args:
        subprocess.run(['git', 'add', '.'])
        subprocess.run(['git', 'commit', '-m', 'Updated'])
        user = configuration.get('github_user')
        pword = configuration.get('github_password')
        subprocess.run(['git', 'push', f'https://{user}:{pword}@github.com/PennyDreadfulMTG/modo-bugs.git'])
async def google(ctx: MtgContext, *, args: str) -> None:
    """Google search"""
    api_key = configuration.get('cse_api_key')
    cse_id = configuration.get('cse_engine_id')
    if api_key is None or cse_id is None:
        return await ctx.send('The google command has not been configured.')

    if len(args) == 0:
        return await ctx.send(
            '{author}: No search term provided. Please type !google followed by what you would like to search.'
            .format(author=ctx.author.mention))

    try:
        service = build('customsearch', 'v1', developerKey=api_key)
        res = service.cse().list(q=args, cx=cse_id, num=1).execute()  # pylint: disable=no-member
        if 'items' in res:
            r = res['items'][0]
            s = '{title} <{url}> {abstract}'.format(title=r['title'],
                                                    url=r['link'],
                                                    abstract=r['snippet'])
        else:
            s = '{author}: Nothing found on Google.'.format(
                author=ctx.author.mention)
    except HttpError as e:
        if e.resp['status'] == '403':
            s = 'We have reached the allowed limits of Google API'
        else:
            raise e

    await ctx.send(s)
def create_issue(content: str,
                 author: str,
                 location: str = 'Discord',
                 repo_name: str = 'PennyDreadfulMTG/Penny-Dreadful-Tools',
                 exception: Optional[Exception] = None) -> Issue:
    labels: List[str] = []
    if content is None or content == '':
        return None
    body = ''
    if '\n' in content:
        title, body = content.split('\n', 1)
        body += '\n\n'
    else:
        title = content
    body += 'Reported on {location} by {author}'.format(location=location,
                                                        author=author)
    if request:
        body += textwrap.dedent("""
            --------------------------------------------------------------------------------
            Request Method: {method}
            Path: {full_path}
            Cookies: {cookies}
            Endpoint: {endpoint}
            View Args: {view_args}
            Person: {id}
            Referrer: {referrer}
            Request Data: {safe_data}
        """.format(method=request.method,
                   full_path=request.full_path,
                   cookies=request.cookies,
                   endpoint=request.endpoint,
                   view_args=request.view_args,
                   id=session.get('id', 'logged_out'),
                   referrer=request.referrer,
                   safe_data=str(safe_data(request.form))))
        body += '\n'.join(
            ['{k}: {v}'.format(k=k, v=v) for k, v in request.headers])
    if exception:
        body += '--------------------------------------------------------------------------------\n'
        body += exception.__class__.__name__ + '\n'
        stack = traceback.extract_stack()[:-3] + traceback.extract_tb(
            exception.__traceback__)
        pretty = traceback.format_list(stack)
        body += 'Stack Trace:\n' + ''.join(pretty) + '\n'
    print(title + '\n' + body, file=sys.stderr)
    # Only check for github details at the last second to get log output even if github not configured.
    if not configuration.get('github_user') or not configuration.get(
            'github_password'):
        return None
    g = Github(configuration.get('github_user'),
               configuration.get('github_password'))
    git_repo = g.get_repo(repo_name)
    if repo_name == 'PennyDreadfulMTG/perf-reports':
        labels.append(location)
        if exception:
            labels.append(exception.__class__.__name__)
    issue = git_repo.create_issue(title=title, body=body, labels=labels)
    return issue
Example #10
0
def create_github_issue(title, author, repo='PennyDreadfulMTG/Penny-Dreadful-Tools'):
    if configuration.get('github_user') is None or configuration.get('github_password') is None:
        return None
    if title is None or title == '':
        return None
    g = Github(configuration.get('github_user'), configuration.get('github_password'))
    repo = g.get_repo(repo)
    issue = repo.create_issue(title=title, body='Reported on Discord by {author}'.format(author=author))
    return issue
Example #11
0
 async def get_server(self) -> discord.Guild:
     for guild in self.bot.guilds:
         if guild.name == self.bot.user.name:
             configuration.write('selfguild', guild.id)
             return guild
     if configuration.get('selfguild') is None:
         guild = await self.bot.create_guild(self.bot.user.name)
         configuration.write('selfguild', guild.id)
         return guild
     return self.bot.get_guild(configuration.get('selfguild'))
Example #12
0
 def __init__(self):
     lines = []
     files = glob.glob(
         os.path.join(configuration.get('legality_dir'), "Run_*.txt"))
     if len(files) == 0:
         files = glob.glob(
             os.path.join(configuration.get('legality_dir'), "*.jar"))
         if len(files) == 0:
             raise DoesNotExistException(
                 'Invalid configuration.  Could not find Legality Checker')
         self.runs = 0
         self.runs_percent = 0
         self.cards = []
         return
     for line in fileinput.input(files):
         lines.append(line.strip())
     scores = Counter(lines).most_common()
     self.runs = scores[0][1]
     self.runs_percent = round(round(self.runs / 168, 2) * 100)
     self.cards = []
     cs = oracle.cards_by_name()
     remaining_runs = (168 - self.runs)
     for name, hits in scores:
         name = html.unescape(name.encode('latin-1').decode('utf-8'))
         hits_needed = max(84 - hits, 0)
         card = cs.get(name)
         percent = round(round(hits / self.runs, 2) * 100)
         if remaining_runs == 0:
             percent_needed = 0
         else:
             percent_needed = round(
                 round(hits_needed / remaining_runs, 2) * 100)
         if card is None:
             raise DoesNotExistException(
                 "Legality list contains unknown card '{card}'".format(
                     card=name))
         if remaining_runs + hits < 84:
             status = 'Not Legal'
         elif hits >= 84:
             status = 'Legal'
         else:
             status = 'Undecided'
             hits = redact(hits)
             hits_needed = redact(hits_needed)
             percent = redact(percent)
             percent_needed = redact(percent_needed)
         card.update({
             'hits': hits,
             'hits_needed': hits_needed,
             'percent': percent,
             'percent_hits_needed': percent_needed,
             'status': status
         })
         self.cards.append(card)
 def __init__(self, db):
     warnings.filterwarnings('error', category=MySQLdb.Warning)
     self.name = db
     self.host = configuration.get('mysql_host')
     self.port = configuration.get('mysql_port')
     if str(self.port).startswith('0.0.0.0:'):
         # Thanks Docker :/
         self.port = int(self.port[8:])
     self.user = configuration.get('mysql_user')
     self.passwd = configuration.get('mysql_passwd')
     self.connect()
Example #14
0
def fetch():
    all_prices, timestamps = {}, []
    for i, url in enumerate(configuration.get('cardhoarder_urls')):
        s = fetcher_internal.fetch(url)
        s = ftfy.fix_encoding(s)
        timestamps.append(dtutil.parse_to_ts(s.split('\n', 1)[0].replace('UPDATED ', ''), '%Y-%m-%dT%H:%M:%S+00:00', dtutil.CARDHOARDER_TZ))
        all_prices[i] = parse_cardhoarder_prices(s)
    url = configuration.get('mtgotraders_url')
    if url:
        s = fetcher_internal.fetch(configuration.get('mtgotraders_url'))
        timestamps.append(dtutil.dt2ts(dtutil.now()))
        all_prices['mtgotraders'] = parse_mtgotraders_prices(s)
    if not timestamps:
        raise TooFewItemsException('Did not get any prices when fetching {urls} ({all_prices})'.format(urls=configuration.get('cardhoarder_urls') + [configuration.get('mtgotraders_url')], all_prices=all_prices))
    store(min(timestamps), all_prices)
Example #15
0
 async def spoiler(self, client: Client, channel: Channel, args: str,
                   author: Member, **_: Dict[str, Any]) -> None:
     """`!spoiler {cardname}`: Request a card from an upcoming set."""
     if len(args) == 0:
         return await client.send_message(
             channel, '{author}: Please specify a card name.'.format(
                 author=author.mention))
     sfcard = fetcher.internal.fetch_json(
         'https://api.scryfall.com/cards/named?fuzzy={name}'.format(
             name=args))
     if sfcard['object'] == 'error':
         return await client.send_message(
             channel,
             '{author}: {details}'.format(author=author.mention,
                                          details=sfcard['details']))
     imagename = '{set}_{number}'.format(set=sfcard['set'],
                                         number=sfcard['collector_number'])
     imagepath = '{image_dir}/{imagename}.jpg'.format(
         image_dir=configuration.get('image_dir'), imagename=imagename)
     if sfcard.get('card_faces'):
         c = sfcard['card_faces'][0]
     else:
         c = sfcard
     fetcher.internal.store(c['image_uris']['normal'], imagepath)
     text = emoji.replace_emoji(
         '{name} {mana}'.format(name=sfcard['name'], mana=c['mana_cost']),
         client)
     await client.send_file(channel, imagepath, content=text)
     oracle.scryfall_import(sfcard['name'])
Example #16
0
def if_todays_prices(out: bool = True) -> List[Card]:
    current_format = multiverse.get_format_id('Penny Dreadful')
    if out:
        not_clause = ''
        compare = '<'
    else:
        not_clause = 'NOT'
        compare = '>='

    where = """
        c.id {not_clause} IN
            (SELECT card_id FROM card_legality
                WHERE format_id = {format})
        AND c.name in (SELECT name FROM `{prices_database}`.cache WHERE week {compare} 0.5)
        AND c.layout IN ({layouts})
    """.format(not_clause=not_clause,
               format=current_format,
               prices_database=configuration.get('prices_database'),
               compare=compare,
               layouts=', '.join([
                   sqlescape(layout)
                   for layout in multiverse.playable_layouts()
               ]))

    rs = db().select(multiverse.cached_base_query(where=where))
    cards = [Card(r) for r in rs]
    return sorted(cards, key=lambda card: card['name'])
def determine_filepath(cards: List[Card]) -> str:
    imagename = basename(cards)
    # Hash the filename if it's otherwise going to be too large to use.
    if len(imagename) > 240:
        imagename = hashlib.md5(imagename.encode('utf-8')).hexdigest()
    filename = imagename + '.jpg'
    return '{dir}/{filename}'.format(dir=configuration.get('image_dir'), filename=filename)
Example #18
0
def league_api() -> Response:
    lg = league.active_league(should_load_decks=True)
    pdbot = request.form.get('api_token',
                             None) == configuration.get('pdbot_api_token')
    if not pdbot:
        lg.decks = [d for d in lg.decks if not d.is_in_current_run()]
    return return_json(lg)
Example #19
0
def times_from_location(q: str, twentyfour: bool) -> Dict[str, List[str]]:
    api_key = configuration.get('google_maps_api_key')
    if not api_key:
        raise NotConfiguredException('No value found for google_maps_api_key')
    url = 'https://maps.googleapis.com/maps/api/geocode/json?address={q}&key={api_key}&sensor=false'.format(
        q=fetch_tools.escape(q), api_key=api_key)
    info = fetch_tools.fetch_json(url)
    if 'error_message' in info:
        return info['error_message']
    try:
        location = info['results'][0]['geometry']['location']
    except IndexError as e:
        raise TooFewItemsException(e) from e
    url = 'https://maps.googleapis.com/maps/api/timezone/json?location={lat},{lng}&timestamp={timestamp}&key={api_key}&sensor=false'.format(
        lat=fetch_tools.escape(str(location['lat'])),
        lng=fetch_tools.escape(str(location['lng'])),
        timestamp=fetch_tools.escape(str(dtutil.dt2ts(dtutil.now()))),
        api_key=api_key)
    timezone_info = fetch_tools.fetch_json(url)
    if 'error_message' in timezone_info:
        return timezone_info['error_message']
    if timezone_info['status'] == 'ZERO_RESULTS':
        raise TooFewItemsException(timezone_info['status'])
    try:
        timezone = dtutil.timezone(timezone_info['timeZoneId'])
    except KeyError as e:
        raise TooFewItemsException(
            f'Unable to find a timezone in {timezone_info}') from e
    return {
        current_time(timezone, twentyfour):
        [info['results'][0]['formatted_address']]
    }
def ad_hoc() -> int:
    dist = Distribution(dict(
        name='Penny-Dreadful-Tools'
    ))
    dist.message_extractors = { # type: ignore
        'decksite': [
            ('**.py', 'python', {}),
            ('**.mustache', extract_mustache, {})
        ],
        'logsite': [
            ('**.py', 'python', {}),
            ('**.mustache', extract_mustache, {})
        ]
    }
    compiler = frontend.extract_messages(dist)
    compiler.initialize_options()
    compiler.output_file = './shared_web/translations/messages.pot'
    compiler.input_paths = ['decksite', 'logsite']
    compiler.finalize_options()
    compiler.run()

    api_key = configuration.get('poeditor_api_key')
    if api_key is None:
        return exitcode()
    client = POEditorAPI(api_token=api_key)
    client.update_terms('162959', './shared_web/translations/messages.pot')
    return exitcode()
def test_fallbackimagedownload() -> None:
    filepath = '{dir}/{filename}'.format(dir=configuration.get('image_dir'),
                                         filename='nalathni-dragon.jpg')
    if fetch_tools.acceptable_file(filepath):
        os.remove(filepath)
    c = [oracle.load_card('Nalathni Dragon')]
    assert image_fetcher.download_image(c) is not None
Example #22
0
def run():
    api_key = configuration.get("poeditor_api_key")
    if api_key is None:
        print("Missing poeditor.com API key")
        return
    client = POEditorAPI(api_token=api_key)
    languages = client.list_project_languages("162959")
    # pull down translations
    for locale in languages:
        print("Found translation for {code}: {percent}%".format(code=locale['code'], percent=locale['percentage']))
        if locale['percentage'] > 0:
            path = os.path.join('decksite', 'translations', locale['code'].replace('-', '_'), 'LC_MESSAGES')
            if not os.path.exists(path):
                os.makedirs(path)
            pofile = os.path.join(path, 'messages.po')
            print('Saving to {0}'.format(pofile))
            if os.path.exists(pofile):
                os.remove(pofile)
            client.export("162959", locale['code'], local_file=pofile)
    # Compile .po files into .mo files
    compiler = compile_catalog()
    compiler.directory = os.path.join('decksite', 'translations')
    compiler.domain = ['messages']
    compiler.run()
    # hack for English - We need an empty folder so that Enlish shows up in the 'Known Languages' list.
    path = os.path.join('decksite', 'translations', 'en', 'LC_MESSAGES')
    if not os.path.exists(path):
        os.makedirs(path)
def cache():
    db = database.get_database(configuration.get('prices_database'))

    now = int(time.time())
    week = now - 60 * 60 * 24 * 7
    month = now - 60 * 60 * 24 * 7 * 30
    last_rotation = int(rotation.last_rotation().timestamp())

    sql = 'SELECT MAX(`time`) FROM low_price'
    latest = db.value(sql)

    db.begin()
    db.execute('DELETE FROM cache')
    sql = """
        INSERT INTO cache (`time`, name, price, low, high, week, month, season)
            SELECT
                MAX(`time`) AS `time`,
                name,
                MIN(CASE WHEN `time` = %s THEN price END) AS price,
                MIN(CASE WHEN `time` > %s THEN price END) AS low,
                MAX(CASE WHEN `time` > %s THEN price END) AS high,
                AVG(CASE WHEN `time` > %s AND price = 1 THEN 1 WHEN `time` > %s THEN 0 END) AS week,
                AVG(CASE WHEN `time` > %s AND price = 1 THEN 1 WHEN `time` > %s THEN 0 END) AS month,
                AVG(CASE WHEN `time` > %s AND price = 1 THEN 1 WHEN `time` > %s THEN 0 END) AS season
            FROM low_price
            GROUP BY name;
    """
    db.execute(sql, [
        latest, last_rotation, last_rotation, week, week, month, month,
        last_rotation, last_rotation
    ])
    db.commit()
Example #24
0
async def handle_command(message, bot):
    parts = message.content.split(' ', 1)
    method = find_method(parts[0])

    if parts[0].lower() in configuration.get('otherbot_commands').split(','):
        return

    args = ""
    if len(parts) > 1:
        args = parts[1]

    if method is not None:
        try:
            if method.__code__.co_argcount == 5:
                await method(Commands, bot, message.channel, args, message.author)
            elif method.__code__.co_argcount == 4:
                await method(Commands, bot, message.channel, args)
            elif method.__code__.co_argcount == 3:
                await method(Commands, bot, message.channel)
            elif method.__code__.co_argcount == 2:
                await method(Commands, bot)
            elif method.__code__.co_argcount == 1:
                await method(Commands)
        except Exception as e: # pylint: disable=broad-except
            print('Caught exception processing command `{cmd}`'.format(cmd=message.content))
            print(traceback.format_exc())
            await bot.client.send_message(message.channel, 'I know the command `{cmd}` but I could not do that.'.format(cmd=parts[0]))
            await getattr(Commands, 'bug')(Commands, bot, message.channel, 'Command failed with {c}: {cmd}'.format(c=e.__class__.__name__, cmd=message.content), message.author)
    else:
        await bot.client.send_message(message.channel, 'Unknown command `{cmd}`. Try `!help`?'.format(cmd=parts[0]))
Example #25
0
def setup_session(url: str) -> None:
    discord = make_session(state=session.get('oauth2_state'))
    token = discord.fetch_token(TOKEN_URL,
                                client_secret=OAUTH2_CLIENT_SECRET,
                                authorization_response=url)
    session.permanent = True
    session['oauth2_token'] = token
    discord = make_session(token=session.get('oauth2_token'))
    user = discord.get(API_BASE_URL + '/users/@me').json()
    session['id'] = user['id']
    session['discord_id'] = user['id']
    session['discord_locale'] = user['locale']
    guilds = discord.get(API_BASE_URL + '/users/@me/guilds').json()
    wrong_guilds = False  # protect against an unexpected response from discord
    session['in_guild'] = False
    session['admin'] = False
    session['demimod'] = False
    for guild in guilds:
        if isinstance(guild, dict) and 'id' in guild:
            if guild['id'] == configuration.get('guild_id'):
                session['admin'] = (
                    guild['permissions'] & 0x10000000
                ) != 0  # Check for the MANAGE_ROLES permissions on Discord as a proxy for "is admin".
                session['demimod'] = (
                    guild['permissions'] & 0x20000
                ) != 0  # Check for the "Mention @everyone" permissions on Discord as a proxy for "is demimod".
                session['in_guild'] = True
        else:
            wrong_guilds = True
    if wrong_guilds:
        logger.warning(
            'auth.py: unexpected discord response. Guilds: {g}'.format(
                g=guilds))
Example #26
0
 def get(self) -> comp.Competition:
     lg = league.active_league(should_load_decks=True)
     pdbot = request.form.get('api_token',
                              None) == configuration.get('pdbot_api_token')
     if not pdbot:
         lg.decks = [d for d in lg.decks if not d.is_in_current_run()]
     return lg
def run() -> None:
    api_key = configuration.get('poeditor_api_key')
    if api_key is None:
        logger.warning('Missing poeditor.com API key')
        return
    client = POEditorAPI(api_token=api_key)
    languages = client.list_project_languages('162959')
    # pull down translations
    for locale in languages:
        logger.warning('Found translation for {code}: {percent}%'.format(code=locale['code'], percent=locale['percentage']))
        if locale['percentage'] > 0:
            path = os.path.join('shared_web', 'translations', locale['code'].replace('-', '_'), 'LC_MESSAGES')
            if not os.path.exists(path):
                os.makedirs(path)
            pofile = os.path.join(path, 'messages.po')
            logger.warning('Saving to {0}'.format(pofile))
            if os.path.exists(pofile):
                os.remove(pofile)
            client.export(project_id='162959', language_code=locale['code'],
                          local_file=pofile, filters=['translated', 'not_fuzzy'])

    # Compile .po files into .mo files
    validate_translations.ad_hoc()
    compiler = compile_catalog()
    compiler.directory = os.path.join('shared_web', 'translations')
    compiler.domain = ['messages']
    compiler.run()
    # hack for English - We need an empty folder so that Enlish shows up in the 'Known Languages' list.
    path = os.path.join('shared_web', 'translations', 'en', 'LC_MESSAGES')
    if not os.path.exists(path):
        os.makedirs(path)
Example #28
0
async def background_task_tournaments():
    await BOT.client.wait_until_ready()
    tournament_channel_id = configuration.get('tournament_channel_id')
    if not tournament_channel_id:
        return
    channel = discord.Object(id=tournament_channel_id)
    while not BOT.client.is_closed:
        info = tournaments.next_tournament_info()
        diff = info['next_tournament_time_precise']
        if diff <= 14400:
            embed = discord.Embed(title=info['next_tournament_name'], description='Starting in {0}.'.format(info['next_tournament_time']), colour=0xDEADBF)
            embed.set_image(url=fetcher.decksite_url('/favicon-152.png'))
            await BOT.client.send_message(channel, embed=embed)

        if diff <= 300:
            # Five minutes, final warning.  Sleep until the tournament has started.
            timer = 301
        elif diff <= 1800:
            # Half an hour. Sleep until 5 minute warning.
            timer = diff - 300
        elif diff <= 3600:
            # One hour.  Sleep until half-hour warning.
            timer = diff - 1800
        else:
            # Wait until four hours before tournament.
            timer = min(3600, diff - 14400)
        await asyncio.sleep(timer)
Example #29
0
 async def honk(self, channel):
     emojis = configuration.get('honk_emoji')
     if not emojis:
         return
     chosen = random.choice(emojis)
     emoji = await self.bot.get_cog('SelfGuild').get_emoji(chosen)
     await channel.send(str(emoji))
Example #30
0
def test_imagedownload() -> None:
    filepath = '{dir}/{filename}'.format(dir=configuration.get('image_dir'),
                                         filename='island.jpg')
    if fetcher_internal.acceptable_file(filepath):
        os.remove(filepath)
    c = [oracle.load_card('Island')]
    assert image_fetcher.download_image(c) is not None