async def rate(ctx):
    '''
	Rate an artifact against an optimal 5* artifact. Put the command and image in the same message.

	-rate <image> [lvl=<level>] [<stat>=<weight> ...]

	If you have any issues or want to use the bot in your private server, contact shrubin#1866 on discord.
	Source code available at https://github.com/shrubin/Genshin-Artifact-Rater

	Default weights

	ATK%, DMG%, Crit - 1
	ATK, EM, Recharge - 0.5
	Everything else - 0

	Options

	lvl: Compare to specified artifact level (default: 20)
	-rate lvl=0

	<stat>: Set custom weights (valued between 0 and 1)
	-rate atk=1 er=0 atk%=0.5

	<stat> is any of HP, HP%, ATK, ATK%, ER (Recharge), EM, PHYS, CR (Crit Rate), CD (Crit Damage), ELEM (Elemental DMG%), Heal, DEF, DEF%
	'''
    if not ctx.message.attachments:
        return
    options = ctx.message.content.split()[1:]
    options = {
        opt_to_key[option.split('=')[0].lower()]: float(option.split('=')[1])
        for option in options
    }
    url = ctx.message.attachments[0].url
    suc, text = await ra.ocr(url)
    global calls
    calls += 1
    print(f'Calls: {calls}')
    if suc:
        results = ra.parse(text)
        score, main_score, sub_score = ra.rate(results, options)
        msg = f'Parsed Image: {results}\nGear Score: {score:.2f}% (main {main_score:.2f}%, sub {sub_score:.2f}%)'
    else:
        msg = f'OCR failed. Error: {text}'
        if 'Timed out' in text:
            msg += ', please try again in a few minutes'
    await ctx.send(msg)
async def rate(ctx):
    global calls, crashes

    if DEVELOPMENT and not (ctx.channel and ctx.channel.id == DEV_CHANNEL_ID):
        return

    lang = get_lang(ctx)
    presets = get_presets(ctx) or []
    presets = {preset.name: preset.command for preset in presets}

    url = None
    if ctx.message.attachments:
        url = ctx.message.attachments[0].url

    msg = ctx.message.content.split()[1:]
    options = []
    preset = None
    for word in msg:
        if not url and validators.url(word):
            url = word
            if '.' not in url.split('?')[0].split('/')[-1]:
                if '?' in url:
                    url = '.png?'.join(url.split('?'))
                else:
                    url += '.png'
        elif word in presets:
            preset = word
        elif '=' in word:
            options.append(word)
        else:
            print(f'Error: Could not parse "{ctx.message.content}"')
            await send(ctx, msg=lang.err_parse)
            return

    if not url:
        await send(ctx, msg=lang.err_not_found)
        return

    if preset:
        options = presets[preset].split() + options

    opt_to_key = create_opt_to_key(lang)
    try:
        options = {
            opt_to_key[option.split('=')[0].lower()]:
            float(option.split('=')[1])
            for option in options
        }
    except:
        print(f'Error: Could not parse "{ctx.message.content}"')
        await send(ctx, msg=lang.err_parse)
        return

    print(url)
    for i in range(RETRIES + 1):
        try:
            calls += 1
            suc, text = await ra.ocr(url, i + 1, lang)

            if not suc:
                if 'Timed out' in text:
                    text += f', {lang.err_try_again}'
                print(text)
                if i < RETRIES:
                    continue
                await send(ctx, msg=text)
                crashes += 1
                if crashes >= MAX_CRASHES and HEROKU_API_KEY and HEROKU_APP_ID:
                    print(f'Crashed {MAX_CRASHES} times, restarting')
                    app.restart()
                return

            level, results = ra.parse(text, lang)
            if lang.lvl in options:
                level = int(options[lang.lvl])
            elif level == None:
                level = 20
            score, main_score, main_weight, sub_score, sub_weight = ra.rate(
                level, results, options, lang)
            crashes = 0
            break

        except Exception:
            print(f'Uncaught exception\n{traceback.format_exc()}')
            if i < RETRIES:
                continue
            await send(ctx, msg=lang.err_unknown)
            if ERR_CHANNEL_ID:
                channel = bot.get_channel(ERR_CHANNEL_ID)
                await channel.send(
                    f'Uncaught exception in {ctx.guild} #{ctx.channel}\n{ctx.message.content}\n{url}\n{traceback.format_exc()}'
                )
            crashes += 1
            if crashes >= MAX_CRASHES and HEROKU_API_KEY and HEROKU_APP_ID:
                print(f'Crashed {MAX_CRASHES} times, restarting')
                app.restart()
            return

    if not results:
        await send(ctx, msg=lang.err_unknown)
        return

    if score <= 50:
        color = discord.Color.blue()
    elif score > 50 and score <= 75:
        color = discord.Color.purple()
    else:
        color = discord.Color.orange()

    msg = f'\n\n**{results[0][0]}: {results[0][1]}**'
    for result in results[1:]:
        msg += f'\n{result[0]}: {result[1]}'
    msg += f'\n\n**{lang.score}: {int(score * (main_weight + sub_weight))} ({score:.2f}%)**'
    msg += f'\n{lang.main_score}: {int(main_score * main_weight)} ({main_score:.2f}%)'
    msg += f'\n{lang.sub_score}: {int(sub_score * sub_weight)} ({sub_score:.2f}%)'
    msg += f'\n\n{lang.join}'

    embed = discord.Embed(color=color)
    embed.set_author(name=ctx.message.author.display_name,
                     icon_url=ctx.message.author.avatar_url)
    embed.add_field(name=f'{lang.art_level}: {level}', value=msg)

    await send(ctx, embed=embed)
Exemple #3
0
async def rate(ctx, lang):
    global calls, crashes

    options = ctx.message.content.split()[1:]
    if options and validators.url(options[0]):
        url = options[0]
        options = options[1:]
        if '.' not in url.split('?')[0].split('/')[-1]:
            if '?' in url:
                url = '.png?'.join(url.split('?'))
            else:
                url += '.png'
    elif ctx.message.attachments:
        url = ctx.message.attachments[0].url
    else:
        print(f'Error: Could not parse "{ctx.message.content}"')
        if not DEVELOPMENT:
            await ctx.send(lang.err_not_found)
        return

    opt_to_key = create_opt_to_key(lang)
    try:
        options = {
            opt_to_key[option.split('=')[0].lower()]:
            float(option.split('=')[1])
            for option in options
        }
    except:
        print(f'Error: Could not parse "{ctx.message.content}"')
        if not DEVELOPMENT:
            await ctx.send(lang.err_parse)
        return

    calls += 1
    print(url)
    for i in range(RETRIES + 1):
        try:
            suc, text = await ra.ocr(url, i + 1, lang)

            if not suc:
                if 'Timed out' in text:
                    text += f', {lang.err_try_again}'
                print(text)
                if i < RETRIES:
                    continue
                if not DEVELOPMENT:
                    await ctx.send(text)
                crashes += 1
                if crashes >= MAX_CRASHES and HEROKU_API_KEY and HEROKU_APP_ID:
                    print(f'Crashed {MAX_CRASHES} times, restarting')
                    app.restart()
                return

            if lang.uid == 'en':
                uid = detect(text)
                if uid != lang.uid and uid in tr.languages:
                    lang = tr.languages[uid]
                    print(f'Converting language to {lang.uid}')

            level, results = ra.parse(text, lang)
            if lang.lvl in options:
                level = int(options[lang.lvl])
            elif level == None:
                level = 20
            score, main_score, main_weight, sub_score, sub_weight = ra.rate(
                level, results, options, lang)
            crashes = 0
            break

        except Exception:
            print(f'Uncaught exception\n{traceback.format_exc()}')
            if i < RETRIES:
                continue
            if not DEVELOPMENT:
                await ctx.send(lang.err_unknown)
            if ERR_CHANNEL_ID:
                channel = bot.get_channel(ERR_CHANNEL_ID)
                await channel.send(
                    f'Uncaught exception in {ctx.guild} #{ctx.channel}\n{ctx.message.content}\n{url}\n{traceback.format_exc()}'
                )
            crashes += 1
            if crashes >= MAX_CRASHES and HEROKU_API_KEY and HEROKU_APP_ID:
                print(f'Crashed {MAX_CRASHES} times, restarting')
                app.restart()
            return

    if score <= 50:
        color = discord.Color.blue()
    elif score > 50 and score <= 75:
        color = discord.Color.purple()
    else:
        color = discord.Color.orange()

    msg = f'\n\n**{results[0][0]}: {results[0][1]}**'
    for result in results[1:]:
        msg += f'\n{result[0]}: {result[1]}'
    msg += f'\n\n**{lang.score}: {int(score * (main_weight + sub_weight))} ({score:.2f}%)**'
    msg += f'\n{lang.main_score}: {int(main_score * main_weight)} ({main_score:.2f}%)'
    msg += f'\n{lang.sub_score}: {int(sub_score * sub_weight)} ({sub_score:.2f}%)'
    msg += f'\n\n{lang.join % "(https://discord.gg/SyGmBxds3M)"}'

    embed = discord.Embed(color=color)
    embed.set_author(name=ctx.message.author.display_name,
                     icon_url=ctx.message.author.avatar_url)
    embed.add_field(name=f'{lang.art_level}: {level}', value=msg)

    if not DEVELOPMENT:
        await ctx.send(embed=embed)
    elif ERR_CHANNEL_ID:
        channel = bot.get_channel(ERR_CHANNEL_ID)
        await channel.send(embed=embed)
Exemple #4
0
async def rate(ctx):
    '''
    Rate an artifact against an optimal 5* artifact. Put the command and image in the same message.

    -rate <image> [lvl=<level>] [<stat>=<weight> ...]

    #1866 on discord.
    If you have any issues or want to use the bot in your private server, contact shrubin
    Source code available at https://github.com/shrubin/Genshin-Artifact-Rater

    Default weights

    ATK%, DMG%, Crit - 1
    ATK, EM, Recharge - 0.5
    Everything else - 0

    Options

    lvl: Compare to specified artifact level (default: <artifact_level>)
    -rate lvl=20

    <stat>: Set custom weights (valued between 0 and 1)
    -rate atk=1 er=0 atk%=0.5

    <stat> is any of HP, HP%, ATK, ATK%, ER (Recharge), EM, PHYS, CR (Crit Rate), CD (Crit Damage), ELEM (Elemental DMG%), Heal, DEF, DEF%
    '''
    if not ctx.message.attachments:
        return
    options = ctx.message.content.split()[1:]
    options = {
        opt_to_key[option.split('=')[0].lower()]: float(option.split('=')[1])
        for option in options
    }
    url = ctx.message.attachments[0].url
    suc, text = await ra.ocr(url)
    global calls
    calls += 1
    print(f'Calls: {calls}')
    embed = discord.Embed(color=discord.Color.green())

    if suc:
        try:
            level, results, results_str = ra.parse(text)
            if not ('Level' in options.keys()):
                options = {**options, 'Level': level}
            score, grade_score = ra.rate(results, options)
            score_msg = f'**Rating: {score:.2f}%**\n{grade_score}'
            embed.add_field(
                name=f'Artifact Level: +{level}',
                value=
                f'Traveler! I am done with your request. Here are the results:\n\n{results_str}\n{score_msg}'
            )
        except:
            error_msg = 'Traveler! There seems to be a problem with your artifact. Let\'s try another!'
            embed.add_field(name=f'Aaaaaaaa! Oh no!', value=f'{error_msg}')
    else:
        error_msg = f'Traveler... Paimon can\'t make any sense of this at all. It says \"{text}\". Maybe you can understand it better?'
        if 'Timed out' in text:
            error_msg += '. Let\'s try again later!'
        embed.add_field(name=f'Ehhhhh... Hehe...', value=f'{error_msg}')

    embed.set_footer(text=f'Requested by {ctx.message.author}',
                     icon_url=ctx.message.author.avatar_url)
    await ctx.send(embed=embed)