Exemple #1
0
def send_autoupdate(collection_elements):
    """
    Helper function, that sends collection_elements through a channel to the
    autoupdate system.

    Does nothing if collection_elements is empty.
    """
    if collection_elements:
        try:
            Channel('autoupdate.send_data').send(
                collection_elements.as_channels_message())
        except ChannelLayer.ChannelFull:
            pass
Exemple #2
0
 def start_long_polling(self):
     if self.is_long_polling:
         raise Exception("is already running")
     session = self.get_session()
     # If you delete a long poll, you must wait 2 minutes. But that is
     # not very user-friendly. Long poll is deprecated anyway.
     #session.delete_long_poll()
     self.delete_webhook_callback()
     self.set_presubscriptions()
     self.request_initial_resource_values()
     self.is_long_polling = True
     self.should_stop_polling = False
     Channel('mbedcloudaccount.poll').send({'mbedcloudaccount_id': self.id})
 def test_request_abort(self):
     """
     Tests that the code aborts when a request-body close is sent.
     """
     Channel("test").send({
         "reply_channel": "test",
         "http_version": "1.1",
         "method": "POST",
         "path": "/test/",
         "body": b"there_a",
         "body_channel": "test-input",
         "headers": {
             "host": b"example.com",
             "content-type": b"application/x-www-form-urlencoded",
             "content-length": b"21",
         },
     }, immediately=True)
     Channel("test-input").send({
         "closed": True,
     }, immediately=True)
     with self.assertRaises(RequestAborted):
         AsgiRequest(self.get_next_message("test"))
 def test_post_files(self):
     """
     Tests POSTing files using multipart form data and multiple messages,
     with no body in the initial message.
     """
     body = (
         b'--BOUNDARY\r\n' +
         b'Content-Disposition: form-data; name="title"\r\n\r\n' +
         b'My First Book\r\n' +
         b'--BOUNDARY\r\n' +
         b'Content-Disposition: form-data; name="pdf"; filename="book.pdf"\r\n\r\n' +
         b'FAKEPDFBYTESGOHERE' +
         b'--BOUNDARY--'
     )
     Channel("test").send({
         "reply_channel": "test",
         "http_version": "1.1",
         "method": "POST",
         "path": "/test/",
         "body_channel": "test-input",
         "headers": {
             "content-type": b"multipart/form-data; boundary=BOUNDARY",
             "content-length": six.text_type(len(body)).encode("ascii"),
         },
     }, immediately=True)
     Channel("test-input").send({
         "content": body[:20],
         "more_content": True,
     }, immediately=True)
     Channel("test-input").send({
         "content": body[20:],
     }, immediately=True)
     request = AsgiRequest(self.get_next_message("test"))
     self.assertEqual(request.method, "POST")
     self.assertEqual(len(request.body), len(body))
     self.assertTrue(request.META["CONTENT_TYPE"].startswith("multipart/form-data"))
     self.assertFalse(request._post_parse_error)
     self.assertEqual(request.POST["title"], "My First Book")
     self.assertEqual(request.FILES["pdf"].read(), b"FAKEPDFBYTESGOHERE")
Exemple #5
0
 def on_failure(self, exc, task_id, args, kwargs, einfo):
     user_id, compendium_id, file_path, bio_feature_name, file_type, channel_name, view, operation = args
     channel = Channel(channel_name)
     message = Message(type='error', title='Error', message=str(exc))
     message.send_to(channel)
     compendium = CompendiumDatabase.objects.get(id=compendium_id)
     log = MessageLog()
     log.title = "Importing " + bio_feature_name + " (biological features) from " + file_type + " file"
     log.message = "Status: error, File: " + os.path.basename(file_path) + ", Type: " + file_type + \
                   ", Task: " + task_id + ", User: "******"Exception: " + str(exc) + ", Stacktrace: " + einfo.traceback
     log.source = log.SOURCE[1][0]
     log.save(using=compendium.compendium_nick_name)
 def dispatch(self, request, *args, **kwargs):
     if not gargoyle.is_active('import_from_google', request):
         return HttpResponseRedirect('/')
     app = SocialApp.objects.filter(provider='google')[0]
     url = "{}?process=connect&next={}".format(
         reverse("google_login"),
         reverse("import-google-contacts",
                 kwargs={'book': self.request.current_book.id}),
     )
     try:
         token = SocialToken.objects.get(account__user=self.request.user,
                                         app=app)
     except SocialToken.DoesNotExist:
         sentry.error("Social token missing in google import",
                      extra={
                          "user": self.request.user,
                      })
         return HttpResponseRedirect(url)
     try:
         creds = GoogleCredentials(
             access_token=token.token,
             token_expiry=None,
             token_uri=GOOGLE_TOKEN_URI,
             client_id=app.client_id,
             client_secret=app.secret,
             refresh_token=None,
             user_agent='Python',
             revoke_uri=None,
         )
         http = httplib2.Http()
         http = creds.authorize(http)
         people_service = build(serviceName='people',
                                version='v1',
                                http=http)
         connections = people_service.people().connections().list(
             resourceName='people/me', pageSize=50).execute()
     except HttpAccessTokenRefreshError:
         return HttpResponseRedirect(url)
     cache.set("{}::google-import".format(request.user.username),
               "processing", 86400)
     Channel('import-google-contacts').send({
         'user_id':
         self.request.user.id,
         'book_id':
         self.request.current_book.id
     })
     messages.success(
         request,
         "We're importing your Google contacts now! You'll receive an email when we're done."
     )
     return HttpResponseRedirect('/')
Exemple #7
0
def websocket_receive(message):
    try:
        data = json.loads(message.content['text'])
    except ValueError:
        message.reply_channel.send(
            reply_error('Invalid data', nonce='', type='receive'))
        return

    if not message.user.is_authenticated:
        message.reply_channel.send(
            reply_error('Not authenticated',
                        nonce=data.get('nonce', ''),
                        type='receive'))
        message.reply_channel.send(
            {'close': WEBSOCKET_DISCONNECT_UNAUTHORIZED})
        return

    cache_key = 'session:' + message.user.username
    current_session = cache.get(cache_key)

    if message.reply_channel.name != current_session:
        message.reply_channel.send(
            reply_error('Session duplication detected',
                        nonce=data.get('nonce', ''),
                        type='receive'))
        message.reply_channel.send({'close': WEBSOCKET_DISCONNECT_DUPLICATE})
        return

    if 'nonce' not in data:
        message.reply_channel.send(reply_error('No nonce', type='receive'))
        return
    if 'action' not in data:
        message.reply_channel.send(
            reply_error('No action', nonce=data['nonce'], type='receive'))
        return
    if 'data' not in data:
        message.reply_channel.send(
            reply_error('No data', nonce=data['nonce'], type='receive'))
        return

    channel = data['action']

    if channel not in available_channels:
        message.reply_channel.send(
            reply_error('Invalid action', nonce=data['nonce'], type='receive'))
        return

    data['data']['nonce'] = data['nonce']
    data['data']['username'] = message.user.username
    data['data']['reply'] = message.reply_channel.name
    Channel(channel).send(data['data'])
Exemple #8
0
def student(request, student_guid):
    # If we are submitting a repository url change (by pressing 'run tests').
    if request.method == "POST":
        form = RepoForm(request.POST)
        if form.is_valid():
            # Update the user with the submitted url, in case it has changed.
            userToUpdate = User.objects.get(email=form.cleaned_data['student_email'])
            userToUpdate.repository_url = form.cleaned_data['repository_url']
            userToUpdate.save()

            # Queue up a test run.
            run = TestRun(student=userToUpdate,
                          repository_url=userToUpdate.repository_url)
            run.save()
            Channel('run-tests').send({'id': run.id})
        return HttpResponseRedirect(reverse('student', kwargs={"student_guid": student_guid}))

    form = RepoForm()
    # Find the student for the current guid.
    student = User.objects.get(email=student_guid+"@student.gla.ac.uk")
    # Build a context dict with information required by the page.
    context_dict={
        'tests': [],
        'form': form,
        'student': {
            'guid': student_guid,
            'email': student.email,
            'name': student.get_full_name,
            'repository_url': student.repository_url
        }
    }

    # Find the test runs for the given user, sorted by most recent.
    test_runs = TestRun.objects.filter(student=student).order_by('-date_run')
    for test_run in test_runs:
        # Get the details for that test run.
        test_details = TestRunDetail.objects.filter(record=test_run)

        # Build up our context with the information required to show the details..
        context_dict['tests'].append({
            'date': test_run.date_run,
            'version': test_run.test_version,
            'time': test_run.time_taken,
            'url': test_run.repository_url,
            'status': test_run.status,
            'score': test_details.filter(passed=True).count(),
            'max_score': test_details.count(),
            'id': test_run.id
         })

    return render(request, 'nucleus/student.html', context=context_dict)
Exemple #9
0
    def read_compendia_channel(channel_name, view, request, user):
        channel = Channel(channel_name)

        start = 0
        end = None
        if request['page_size']:
            start = (request['page'] - 1) * request['page_size']
            end = start + request['page_size']
        order = ''
        if request['ordering'] == 'DESC':
            order = '-'
        query_response = CompendiumDatabase.objects.filter(Q(compendium_name__contains=request['filter']) |
                                                           Q(compendium_nick_name__contains=request['filter']) |
                                                           Q(description__contains=request['filter']) |
                                                           Q(html_description__contains=request['filter'])).order_by(
            order + request['ordering_value'])
        total = query_response.count()
        query_response = query_response[start:end]

        compendia = []
        importe_mapping_file_types = []
        ontology_file_types = BaseParser.get_parser_classes()

        permitted_db = command.consumers.GroupCompendiumPermission.get_permitted_db(user)
        for db in query_response:
            if not user.is_staff and not user.is_superuser and db.compendium_nick_name not in permitted_db:
                continue
            compendium = db.to_dict()
            try:
                compendium['bio_features_fields'] = [bff.to_dict() for bff in
                                                     BioFeatureFields.objects.using(db.compendium_nick_name).all()]
                importe_mapping_file_types = [{'file_type': cls.FILE_TYPE_NAME} for cls in importers.importer_mapping[db.compendium_type.bio_feature_name]]
                ontology_file_types = [{"file_type": cls.FILE_TYPE_NAME} for cls in ontology_file_types]
            except Exception as e:
                pass
            compendium['ontology_file_types'] = ontology_file_types
            compendium['bio_feature_file_types'] = importe_mapping_file_types
            compendia.append(compendium)

        channel.send({
            'text': json.dumps({
                'stream': view,
                'payload': {
                    'request': request,
                    'data': {
                        'compendia': compendia,
                        'total': total
                    }
                }
            })
        })
Exemple #10
0
def ws_receive(message):

    print("We got a message!")

    # Load the message['text'] array as our new payload
    payload = json.loads(message['text'])
    # Steal the payload type from the text, easier to move it than deal with it java side
    payload['type'] = payload['event']['type']
    # Remove it from the original location because it doesnt need to be there
    payload['event'].pop('Type', None)
    # Retain reply_channel
    payload['reply_channel'] = message.content['reply_channel']
    # Shoot off to channels
    Channel("trivia.receive").send(payload)
Exemple #11
0
 def handle(self, *args, **options):
     # Note the channel name is what is defined in
     # the routing.py file and I am explicitly getting
     # the "default" channel (defined in settings.py)
     c = Channel('websocket.receive',
                 channel_layer=channel_layers['default'])
     # I expect no data with this, but a dict is required
     c.send({
         "text": json.dumps({
             "action": "start_mytask",
             "job_name": "download",
         }),
         "reply_channel": "websocket.send!xxxxxxxxxxxx",
     })
Exemple #12
0
def deliver_task_completed_notification(task_id, reply_channel):
	task = Task.objects.get(pk=task_id)
	log.debug("Running Task Name=%s", task.title)
	if reply_channel is not None:
		Channel(reply_channel).send({
				"text": json.dumps({
					"action": "accepted",
					"task_id": task_id,
					"task_name": task.title,
					"task_status": task.status,
					"task_preiority": task.preiority,
					"task_store": task.store,
				})
		})	
Exemple #13
0
def store_manager_created_new_task(task_id, reply_channel):
	task = Task.objects.get(pk=task_id)
	log.debug("Running Task Name=%s", task.title)
	if reply_channel is not None:
		Channel(reply_channel).send({
				"text": json.dumps({
					"action": "task_created",
					"task_id": task_id,
					"task_title": task.title,
					"task_status": task.status,
					"task_preiority": task.preiority,
					"task_store": task.store
				})
			})
Exemple #14
0
 def func_wrapper(*args, **kwargs):
     channel_name, view, request, user = args
     channel = Channel(channel_name)
     try:
         func(*args, **kwargs)
     except ProgrammingError as e:
         error_msg = Message(type='error',
                             title='Error',
                             message=str(e) +
                             "<br><br> Is the compendium initialized?")
         error_msg.send_to(channel)
     except Exception as e:
         error_msg = Message(type='error', title='Error', message=str(e))
         error_msg.send_to(channel)
Exemple #15
0
    def read_sample_preview(channel_name, view, request, user):
        channel = Channel(channel_name)

        start = 0
        end = None
        if request['page_size']:
            start = (request['page'] - 1) * request['page_size']
            end = start + request['page_size']

        compendium = CompendiumDatabase.objects.get(id=request['compendium_id'])
        parsing_db = init_parsing(request['compendium_id'], request['values'])
        experiment = Experiment.objects.using(compendium.compendium_nick_name).get(id=request['values'])
        parsing_experiment = ParsingExperiment.objects.using(parsing_db).get(experiment_fk=experiment.id)
        order = ''
        if request['ordering'] == 'DESC':
            order = '-'
        query_response = ParsingSample.objects.using(parsing_db). \
            filter(experiment=parsing_experiment). \
            filter(Q(sample_name__contains=request['filter']) |
                   Q(description__contains=request['filter']) |
                   Q(platform__platform_access_id__contains=request['filter'])
                   ).order_by(order + request['ordering_value'])
        total = query_response.count()
        query_response = query_response[start:end]
        samples = []
        status = 'importing' if experiment.status.name == 'experiment_raw_data_importing' else None
        if not status:
            for smp in experiment.sample_set.all():
                if smp.platform.status and smp.platform.status.name == 'platform_importing':
                    status = 'importing'
        for sample in query_response:
            smp = sample.to_dict()
            smp['experiment_id'] = experiment.id
            smp['reporter_platform'] = Platform.objects.using(compendium.compendium_nick_name).\
                    get(id=sample.reporter_platform).to_dict()
            samples.append(smp)

        channel.send({
            'text': json.dumps({
                'stream': view,
                'payload': {
                    'request': request,
                    'data': {
                        'samples': samples,
                        'status': status,
                        'total': total
                    }
                }
            })
        })
Exemple #16
0
def channel():
    channel = request.form.get('channel')
    # If element already exist, NOT create another with the same name
    for elem in channels:
        if channel in elem.name:
            return jsonify({"success": False})
    # If no channel named the same, then create a new one
    newChannel = Channel(channel)
    channels.append(newChannel)
    # Create a dictionary for every object so then can be tranformed easily into JSON objects
    channelsFeed = []
    for object in channels:
        channelsFeed.append(object.__dict__)
    return jsonify({"success": True, "channel": channel, "channels": channelsFeed})
Exemple #17
0
    def test_normal_run(self):
        consumer = mock.Mock()
        Channel('test').send({'test': 'test'}, immediately=True)
        channel_layer = channel_layers[DEFAULT_CHANNEL_LAYER]
        channel_layer.router.add_route(route('test', consumer))
        old_send = channel_layer.send
        channel_layer.send = mock.Mock(side_effect=old_send)  # proxy 'send' for counting

        worker = PatchedWorker(channel_layer)
        worker.termed = 2

        worker.run()
        self.assertEqual(consumer.call_count, 1)
        self.assertEqual(channel_layer.send.call_count, 0)
Exemple #18
0
def upload(request):
    if request.method == 'POST':
        form = ImageUploadForm(request.POST, request.FILES)
        if form.is_valid():
            image_file = form.save()
            notification = {
                'id':image_file.id,
            }
            Channel('create_thumbnail').send(notification)            
            return redirect('uploadImage:image_list')
    else:
        form = ImageUploadForm()

    return render(request, 'uploadImage/upload.html', {'form': form})
Exemple #19
0
def main():
    name = 'cmdb:log'
    # all_cmdb_log_reply_channels = [x for x in redis_client.hgetall(name)]

    while True:
        duplicate_reply_channels_name = []
        to_do_map = {}
        with futures.ThreadPoolExecutor(max_workers=MAX_WORKER) as executor:
            looplog.logger.info('*** starting a new round thread ***')
            for reply_channel_name, reply_channel_info in redis_client.hgetall(
                    name).items():
                reply_channel_info = json.loads(reply_channel_info)
                uuid = reply_channel_info.get('uuid')
                row = reply_channel_info.get('row')
                heartbeat = reply_channel_info.get('heartbeat')
                current_time = int(time.time())
                if current_time - heartbeat > DEFAULT_INTERVAL:
                    duplicate_reply_channels_name.append(reply_channel_name)
                else:
                    looplog.logger.info('Scheduled thread %s' %
                                        (reply_channel_name))
                    future = executor.submit(yield_cmdb_log,
                                             reply_channel_name, uuid, row,
                                             heartbeat)
                    to_do_map[future] = reply_channel_name

            looplog.logger.info('Current to_do_map list is %s' % (to_do_map))

            done_iter = futures.as_completed(to_do_map)

            for future in done_iter:
                try:
                    future.result()
                except Exception as exc:
                    print('------ find Exception -------', to_do_map[future])
                    traceback.print_exc()

            # 删除过期的
            for rc in duplicate_reply_channels_name:
                # 主动断开ws连接,这样,正常的连接会通过
                # 浏览器重新自动连接
                # 如果是异常断开的无效的reply_channel
                # 还是需要从redis中删除
                # 调用send({"close": True})会调用disconnect
                # 也就会删除redis里面的reply_channel
                Channel(rc).send({"close": True})
                redis_client.hdel(name, rc)

        # 休眠一秒钟
        time.sleep(1)
Exemple #20
0
def scorm_set_score(sender, instance, created, **kwargs):
    if instance.key != 'cmi.score.scaled' or not created:
        return

    if not (instance.attempt.scaled_score_element is None
            or instance.newer_than(instance.attempt.scaled_score_element)):
        return

    instance.attempt.scaled_score = float(instance.value)
    instance.attempt.scaled_score_element = instance
    instance.attempt.save(
        update_fields=['scaled_score', 'scaled_score_element'])
    if instance.attempt.resource.report_mark_time == 'immediately':
        Channel('report.attempt').send({'pk': instance.attempt.pk})
Exemple #21
0
def ws_message(message):
    print 'terminal_input', message
    workspace_id, terminal_id = get_ids(message)
    if message['text'].startswith('@@RESIZE@@'):
        data = message['text'].split('@@RESIZE@@')[1].split(':')
        c = Channel('terminal.resize')
        c.send({
            'reply_channel': message.reply_channel.name,
            'user_id': message.user.id,
            'workspace_id': workspace_id,
            'terminal_id': terminal_id,
            'width': data[0],
            'height': data[1]
        })
    else:
        c = Channel('terminal.input')
        c.send({
            'reply_channel': message.reply_channel.name,
            'user_id': message.user.id,
            'workspace_id': workspace_id,
            'terminal_id': terminal_id,
            'input': message['text']
        })
Exemple #22
0
 def test_streaming_data(self):
     Channel("test").send({
         "reply_channel": "test",
         "http_version": "1.1",
         "method": "GET",
         "path": b"/test/",
     })
     response = StreamingHttpResponse('Line: %s' % i for i in range(10))
     handler = FakeAsgiHandler(response)
     reply_messages = list(
         handler(self.get_next_message("test", require=True)))
     self.assertEqual(len(reply_messages), 11)
     self.assertEqual(reply_messages[0]["content"], b"Line: 0")
     self.assertEqual(reply_messages[9]["content"], b"Line: 9")
Exemple #23
0
def remove_participant(sender, instance, **kwargs):
    """When a user is removed from a conversation we will notify them."""

    user = instance.user
    conversation = instance.conversation
    for item in ChannelSubscription.objects.filter(user=user):
        Channel(item.reply_channel).send({
            'text': json.dumps({
                'topic': 'conversations:leave',
                'payload': {
                    'id': conversation.id
                }
            })
        })
Exemple #24
0
def addHost(request,code):
    if request.method=='POST':
        form = forms.HostAddForm(request.POST)
        if form.is_valid():
            host = form.save()
            logger.log(request,'添加了主机%s(%s).'%(host.name,host.addr))
            site = get_current_site(request)
            ws_protocol = 'wss' if request.is_secure() else 'ws'
            Channel('HostAdd').send(dict(id = host.id,site=site,ws_protocol=ws_protocol))
            return JsonResponse(dict(ret=0))
        messages.error(request,form.errors)
    else:
        form = forms.HostAddForm()
    return render(request,'HostManage/addhost.html',locals())
Exemple #25
0
def ws_message(message):
    # Parse the query string

    msssg = json.loads(message["text"])

    id = msssg['id']
    toid = msssg['toid']
    msg = msssg['msg']

    if toid == 'first':
        people_exist = People.objects.filter(id=id)

        if not people_exist:
            people = People.objects.create(
                id=id, reply_channel=message.reply_channel.name)
        else:
            people = people_exist[0]
            people.reply_channel = message.reply_channel.name

        chatmsgs = ChatMessage.objects.filter(toid=id).filter(issent=0)

        message.channel_session["id"] = id
        for chatmsg in chatmsgs:
            message.reply_channel.send({
                'text':
                json.dumps({
                    'fromid': chatmsg.fromid,
                    'msg': chatmsg.text,
                })
            })
            chatmsg.issent = 1
            chatmsg.save()
        people.online = 1
        people.save()
    else:
        frompeople = People.objects.get(id=id)
        topeople = People.objects.get(id=toid)

        frompeople_online = frompeople.online
        topeople_online = topeople.online

        sendornot = frompeople_online * topeople_online

        Channel("chat-messages").send({
            "msg": msg,
            "fromid": id,
            "toid": toid,
            "sendornot": sendornot,
        })
Exemple #26
0
def ws_notify_clean_user(user_id):
    """根据用户id通知相应的客户端来
    刷新清除数据的结果展示
    """

    user = User.objects.get(id=user_id)
    ucs = UserClearStatus.objects.get(profile=user.profile)
    process_info = ucs.show_process_info()

    msg = {
        "message": "update_msg",
        "user_id": user_id,
        "process_info": process_info
    }
    Channel("update_clean_user").send(msg)
Exemple #27
0
 def test_redirect(self):
     for redirect_to in ['/', '..', 'https://example.com']:
         Channel("test").send({
             "reply_channel": "test",
             "http_version": "1.1",
             "method": "GET",
             "path": b"/test/",
         })
         response = HttpResponseRedirect(redirect_to)
         handler = FakeAsgiHandler(response)
         reply_messages = list(
             handler(self.get_next_message("test", require=True)))
         self.assertEqual(reply_messages[0]['status'], 302)
         header_dict = dict(reply_messages[0]['headers'])
         self.assertEqual(header_dict[b'Location'].decode(), redirect_to)
Exemple #28
0
    def test_non_streaming_file_response(self):
        Channel("test").send({
            "reply_channel": "test",
            "http_version": "1.1",
            "method": "GET",
            "path": b"/test/",
        })
        response = FileResponse(BytesIO(b'sadfdasfsdfsadf'))
        # This is to test the exception handling. This would only happening if
        # the StreamingHttpResponse was incorrectly subclassed.
        response.streaming = False

        handler = FakeAsgiHandler(response)
        with self.assertRaises(AttributeError):
            list(handler(self.get_next_message("test", require=True)))
Exemple #29
0
def addconfig(request,id,code):
    host = models.Host.objects.get(pk=id)
    if request.method=='POST':
        form = forms.LogCleanConfigAddForm(request.POST)
        if form.is_valid():
            cfg = form.save(commit=False)
            cfg.host_id=id
            cfg.sync=False
            cfg.save()
            logger.log(request,'添加了主机%s(%s)的日志清理设置(%s).'%(host.name,host.addr,cfg.configName))
            Channel('LogConfig').send({'host_id':id})
            return redirect('/HostManage/%s/LogCleanConfig/'%id)
    else:
        form = forms.LogCleanConfigAddForm()
    return render(request,'HostManage/addconfig.html',locals())
Exemple #30
0
def consulta_usuario_fecha(desde, hasta, usuario, reply_channel):
    historial = Perfil.objects.get(id=usuario)
    if desde == "":
        desde = str(historial.ultima_indemnizacion)
    if hasta == "":
        hasta = str(datetime.now().year) + '-' + str(
            datetime.now().month) + '-' + str(datetime.now().day)

    retorno = SALARIO_MENSUAL.objects.filter(usuario=historial).filter(
        fecha_de_pago__gte=desde).filter(fecha_de_pago__lte=hasta)

    if reply_channel is not None:
        Channel(reply_channel).send({
            "text":
            json.dumps({
                "tipo": "tabla",
                "fecha_de_pago": "<b>fecha de pago(yyyy-mm-dd)</b>",
                "salario": "<b>salario</b>",
                "comision": "<b>comisiones del mes</b>",
                "total": "<b>total del mes</b>",
                "facturas_del_mes": "<b>facturas del mes</b>",
            })
        })
    for r in retorno:
        if reply_channel is not None:
            Channel(reply_channel).send({
                "text":
                json.dumps({
                    "tipo": "tabla",
                    "fecha_de_pago": str(r.fecha_de_pago),
                    "salario": str(r.salario),
                    "comision": str(r.comision),
                    "total": str(r.total),
                    "facturas_del_mes": "",
                })
            })