def render_for_groupchat(sender, reply_to, text):
    ttr = 0
    error = False
    try:
        t1 = time.time()
        png = conv.convertExpressionToPng(text, sender, str(uuid.uuid4()))
        ttr = time.time()-t1

        upload = vk_api.upload.VkUpload(vk_session)
        photo = upload.photo_messages(png)[0]
        photo_send_kwargs = {'peer_id':reply_to, 'attachment':f'photo{photo["owner_id"]}_{photo["id"]}', 'random_id':0}

        opt_man = data_managers.UserOptsManager(api)
        cic = opt_man.get_code_in_caption(sender)
        tic = opt_man.get_time_in_caption(sender)
        if cic and tic:
            photo_send_kwargs.update({'message': f'{utils.get_at_spec(sender)}: {text} (rendered in {ttr} seconds)'})
        elif tic:
            photo_send_kwargs.update({'message': f'{utils.get_at_spec(sender)}: rendered in {ttr} seconds'})
        elif cic:
            photo_send_kwargs.update({'message': f'{utils.get_at_spec(sender)}: {text}'})
        else:
            photo_send_kwargs.update({'message': f'{utils.get_at_spec(sender)}'})

        api.messages.send(**photo_send_kwargs)
        opt_man.set_last_render_time(sender, time.time())
    except ValueError as e:
        api.messages.send(peer_id=reply_to, message=f'{utils.get_at_spec(sender)}: LaTeX error:\n'+e.args[0], random_id=0)
        error = True
    except:
        api.messages.send(peer_id=reply_to, message='{utils.get_at_spec(sender)}: ERROR, see '+ERROR(traceback.format_exc(), sender, text),  random_id=0)
        error = True
    finally:
        stats.record_render(sender, ttr, error)
        stats.delete_older_than() 
Esempio n. 2
0
def set_caption_time(val, user_id=None):
    if val not in list('01'):
        return 'Please provide a (0 for no) or (1 for yes) as parameter.'
    opt_man = data_managers.UserOptsManager(vkapi)
    opt_man.set_time_in_caption(user_id, val == '1')
    return 'The next renders made for you will ' + (
        'not ' if val == '0' else
        "") + 'have the render time as part of the image caption.'
Esempio n. 3
0
def set_dpi(val, user_id=None):
    rlstore = data_managers.DisabledRateLimitStore(vkapi)
    max_dpi = 1200 if not rlstore[user_id] else 10000
    try:
        val = int(val)
        if val not in range(20, max_dpi): raise ValueError
    except ValueError:
        return f'Please provide an integer in the range (20, {max_dpi}). The default value is 300.'

    opt_man = data_managers.UserOptsManager(vkapi)
    opt_man.set_dpi(user_id, val)
    return f'Your DPI has been updated to {val}'
Esempio n. 4
0
def slash_help(*args, user_id=None):
    opt_man = data_managers.UserOptsManager(vkapi)
    cic = opt_man.get_code_in_caption(user_id)
    tic = opt_man.get_time_in_caption(user_id)
    dpi = opt_man.get_dpi(user_id)
    output = f'''Command list, values in <brackets> are required parameters, in [brackets] are optional:
/help -- this help

Preamble commands:
/reset-preamble -- restore your custom preamble to the default -- use this if you get render errors on valid code
/show-preamble -- show your custom preamble
/add-preamble <line> -- add a line to the end of your custom preamble
/delete-preamble <line-index> -- remove a line by its index from your custom preamble

Settings commands (current settings are in <brackets>):
/set-caption-code <{1 if cic else 0}> -- do you want to have LaTeX code in the message caption?
/set-render-time <{1 if tic else 0}> -- do you want render time in the message caption?
/set-dpi <{dpi}> -- set image resolution, higher is better
'''

    is_manager = data_managers.ManagerStore(vkapi)
    if is_manager[user_id]:
        output += f'''

As a manager, you also have these commands:

/ratelimit <@-user> -- enable rate-limiting for this user
/unratelimit <@-user> -- disable rate-limiting for this user
/getratelimit <@-user> -- check the state of rate-limiting for this user
/top-by-time [how-many]-- get top users by time taken to render
/top-by-renders [how-many] -- get top users by render requests
/top-by-errors [how-many] -- get top users by errors during rendering
/error-out -- intentionally cause an exception to test the error reporting feature
'''
    if user_id == OWNER_ID:
        output += f'''

As the bot owner, you also have these commands:
/promote <@-user> -- make user a manager
/demote <@-user> -- stop user being a manager
/get-promoted <@-user> -- check whether this user is a manager
/delete-error <uuid> -- delete an error report by its uuid
/delete-all-errors -- delete all error reports
/show-errors [how-many] -- show a list of error reports
'''
    return output
def render_for_user(sender, text):
    error = False
    ttr = 0
    try:
        t1 = time.time()
        png, pdf = conv.convertExpressionToPng(text, sender, str(uuid.uuid4()), returnPdf=True)
        ttr = time.time()-t1
        upload = vk_api.upload.VkUpload(vk_session)


        photo = upload.photo_messages(png)[0]
        photo_send_kwargs = {'peer_id':sender, 'attachment':f'photo{photo["owner_id"]}_{photo["id"]}', 'random_id':0, 'message':''}


        opt_man = data_managers.UserOptsManager(api)
        cic = opt_man.get_code_in_caption(sender)
        tic = opt_man.get_time_in_caption(sender)
        if cic:
            photo_send_kwargs.update({'message': text})
        if tic:
            if photo_send_kwargs['message']:
                photo_send_kwargs['message'] += f' (rendered in {ttr} seconds)'
            else:
                photo_send_kwargs['message'] = f'Rendered in {ttr} seconds'

        doc_send_kwargs = {'peer_id': sender, 'attachment': upload_doc(pdf, sender, upload), 'message': photo_send_kwargs['message'], 'random_id': 0}
        api.messages.send(**photo_send_kwargs)
        api.messages.send(**doc_send_kwargs)
        opt_man.set_last_render_time(sender, time.time())
    except ValueError as e:
        api.messages.send(peer_id=sender, message='LaTeX error:\n'+e.args[0], random_id=0)
        error = True
    except:
        api.messages.send(peer_id=sender, message='ERROR: see '+ERROR(traceback.format_exc(), sender, text),  random_id=0)
        error = True
    finally:
        stats.record_render(sender, ttr, error)
        stats.delete_older_than() 
Esempio n. 6
0
def recv_message(data):
    if data.get('secret') != VK_SECRET:
        ERROR('Request with improper secret field received!!\n\nData:\n' +
              str(data) + '\n\nRequest parameters:\n' + str(request))
        return 'plz no hack me :(', 403
    message = data['object']['message']
    sender = message['from_id']
    reply_to = message['peer_id']

    def reply(t):
        vkapi.messages.send(peer_id=reply_to,
                            message=(f'{utils.get_at_spec(sender)}: '
                                     if sender != reply_to else '') + t,
                            random_id=0)

    if 'payload' in message:
        payload = json.loads(bytes(message['payload'], 'utf-8'))
        if 'command' in payload:
            if payload['command'] == 'start':
                reply(
                    'Welcome to InLaTeX! To begin, type a LaTeX expression to render it, or type "/help" for a command list.'
                )
                return

    if 'action' in message:
        if 'type' in message['action']:
            if message['action']['type'] == 'chat_invite_user':
                reply(
                    'This is the InLaTeX bot. To use, please @-mention me and write an expression to render (like this: "@inlatexbot $E=mc^2$").\nFor more features, enter a private chat with me and type "/help".'
                )
                return

    try:
        text = message['text']
        if not text: raise KeyError
    except KeyError:
        reply('Your message did not contain text, but it is required.')
        return

    grp_ref = re.search('\\[.*\\|.*\\] ', text)
    if grp_ref != None:
        text = text[(grp_ref.span()[1]):]

    if text.startswith('/'):
        command = text[1:].split()
        if command[0] in slash_commands:
            fun = slash_commands[command[0]]
            try:
                answer = fun(*(command[1:]), user_id=sender)
                if answer:
                    reply(answer)
            except TypeError:
                reply(
                    'Wrong number of arguments for command, for command list type "/help".'
                    + traceback.format_exc())
            except:
                reply('ERROR: see ' +
                      ERROR(traceback.format_exc(), reply_to, text))
        else:
            reply(f'Unknown command "{command[0]}", for list type "/help".')
        return

    rlstore = data_managers.DisabledRateLimitStore(vkapi)
    if not rlstore[sender]:
        RATE_LIM_INTERVAL = 30
        opt_man = data_managers.UserOptsManager(vkapi)
        if time.time() - opt_man.get_last_render_time(
                sender) < RATE_LIM_INTERVAL:  # unregistered rate-limiting
            reply(
                f'It\'s been only {time.time() - opt_man.get_last_render_time(sender)}, please wait at least {RATE_LIM_INTERVAL} seconds before requesting next render'
            )
            return

    workers = cel.control.inspect(timeout=0.75).ping()
    if workers is None:
        reply('''ERROR: No Celery workers responded to ping!
This is a serious problem!

The bot is currently unable to render images.
A report has been sent to the bot's admin.''')
        ERROR('Celery ping failed', sender, text)
        return

    latex_celery_tasks.ERROR = ERROR
    if sender == reply_to:
        latex_celery_tasks.render_for_user.apply_async((sender, text))
    else:
        latex_celery_tasks.render_for_groupchat.apply_async(
            (sender, reply_to, text))