Beispiel #1
0
    async def send_message(self, to_id):
        message_text = self.aa_options['message']
        message = message_text.replace(
            '[username]', self.tg_bot_controller.tg_client.me_user_name)

        if message.find('[statistics]') >= 0:
            stats_str = await self.tg_bot_controller.tg_client.status_controller.get_user_aa_statistics_text(
                self.tg_bot_controller.tg_client.me_user_id)
            message = message.replace('[statistics]', '\n' + stats_str)

        if self.aa_options['show_bot']:
            message = self.tg_bot_controller.text_to_bot_text(
                message, to_id, "dialog")
        else:
            message = self.tg_bot_controller.text_to_bot_text(
                message, to_id, "bot")
        to_username = await self.tg_bot_controller.tg_client.get_entity_name(
            to_id, 'User')
        msg_log = StatusController.datetime_to_str(datetime.now(
        )) + ' Sending AA message to user "' + to_username + '"'
        msg_log = msg_log + '\n' + '<<< ' + message
        print(msg_log)
        await self.tg_bot_controller.tg_client.send_message(
            PeerUser(to_id), message)
        if self.aa_options['notify_entity_id']:
            msg_log = StatusController.datetime_to_str(datetime.now(
            )) + ' Отправляем сообщение пользователю {}'.format(
                await self.tg_bot_controller.user_link(to_id, to_username))
            msg_log = msg_log + '\n\n' + '``` ' + message + '```'
            await self.send_message_to_user(
                self.aa_options['notify_entity_id'],
                msg_log,
                do_set_next=False)
Beispiel #2
0
 async def on_user_message_to_me(self, from_id, message_text):
     if not self.aa_options['is_set']:
         return
     if from_id in self.aa_not_for_users:
         return
     if (from_id in self.aa_for_users) and self.aa_for_users[from_id]:
         return
     try:
         entity = await self.tg_bot_controller.tg_client.get_entity(
             PeerUser(int(from_id)))
     except:
         return
     if (not entity) or (type(entity) != User):
         return
     user_level = self.tg_bot_controller.get_entity_rights_level(
         entity, self.aa_options['from_user_ids'])
     if user_level < self.aa_options['from_mode']:
         if from_id not in self.aa_not_for_users:
             self.aa_not_for_users.append(from_id)
         return
     self.aa_for_users[from_id] = StatusController.now_local_datetime()
     check_user_name = await self.tg_bot_controller.tg_client.get_entity_name(
         from_id, 'User')
     print(
         StatusController.datetime_to_str(datetime.now()) +
         ' Adding AA schedule for user "' + check_user_name + '"')
     if self.aa_options['answer_after_minutes'] <= 0.05:
         await self.do_on_timer([from_id])
 async def cmd_plot_week(self, from_id, params):
     to_id = from_id
     from_id = await self.tg_bot_controller.get_from_id_param(
         from_id, params)
     date_str1 = StatusController.datetime_to_str(
         datetime.now() + timedelta(days=-6), '%Y-%m-%d')
     date_str2 = StatusController.datetime_to_str(
         datetime.now() + timedelta(days=1), '%Y-%m-%d')
     await self.send_activity_message(
         from_id,
         to_id, (date_str1, date_str2),
         img_caption="График активности [user] за неделю")
Beispiel #4
0
 async def show_current_branch_commands(self, from_id, pre_text=None):
     if self.aa_options['is_set']:
         msg = 'Автоответчик для ' + self.tg_bot_controller.tg_client.me_user_name + ' настроен и запущен!\n\nПараметры:\n'
         msg = msg + '```'
         for k, v in self.aa_options.items():
             if k not in ['is_set', 'notify_entity_id']:
                 msg = msg + k + ' = ' + str(v) + '\n'
         msg = msg + '```\n'
         msg = msg + 'Пользователи: '
         if len(self.aa_for_users) > 0:
             for user_id, user_date in self.aa_for_users.items():
                 msg = msg + '\n'
                 msg = msg + (await
                              self.tg_bot_controller.user_link(user_id))
                 msg = msg + ' **---** '
                 if user_date:
                     msg = msg + 'Ждёт с ' + StatusController.datetime_to_str(
                         user_date)
                 else:
                     msg = msg + 'Сообщение отправлено'
         else:
             msg = msg + 'Отсутствуют'
         msg = msg + '\n'
     else:
         msg = ''
     msg_text = msg + "\n".join(await self.get_commands_description_list(
         from_id, pre_text))
     buttons = await self.get_commands_buttons_list(from_id)
     await self.send_message_to_user(from_id,
                                     msg_text.strip(),
                                     buttons=buttons,
                                     set_active=True)
    def add_entity_db_name(self,
                           entity_id,
                           entity_type,
                           entity_name,
                           entity_phone=None,
                           entity_is_megagroup=False):
        row = self.db_conn.execute(
            """
            SELECT * FROM `entities` WHERE `entity_id` = ? ORDER BY `version` DESC LIMIT 1
        """, [str(entity_id)]).fetchone()
        if row:
            if (entity_name == row['entity_name']) and (entity_type
                                                        == row['entity_type']):
                return None
            version = int(row['version']) + 1
        else:
            version = 1

        if entity_is_megagroup:
            entity_type = 'Megagroup'

        c = self.db_conn.cursor()
        c.execute('INSERT INTO `entities` VALUES(?, ?, ?, ?, ?, ?, ?, ?)', [
            str(entity_id),
            str(entity_type), entity_name, entity_phone,
            StatusController.datetime_to_str(datetime.now()), None, None,
            str(version)
        ])
        self.db_conn.commit()
Beispiel #6
0
 def find_message_by_id_date(self, from_id, date):
     date = StatusController.tg_datetime_to_local_datetime(date)
     date = StatusController.datetime_to_str(date, '%Y-%m-%d %H:%M:%S')
     res = self.db_conn.execute(
         """
             SELECT m.*, 
             (SELECT version FROM `messages` m1 WHERE m1.`entity_id` = m.`entity_id` AND m1.message_id = m.message_id AND m1.from_id = m.from_id ORDER BY version DESC LIMIT 1) as 'max_version',
             (SELECT removed FROM `messages` m1 WHERE m1.`entity_id` = m.`entity_id` AND m1.message_id = m.message_id AND m1.from_id = m.from_id ORDER BY version DESC LIMIT 1) as 'is_removed'
             FROM `messages` m
             WHERE m.`from_id` = ? AND m.`taken_at` LIKE ?
             ORDER BY m.`taken_at` ASC
             LIMIT 1
         """,
         [str(from_id), date + '%']
     )
     row = res.fetchone()
     return row
 async def cmd_plot_today(self, from_id, params):
     to_id = from_id
     from_id = await self.tg_bot_controller.get_from_id_param(
         from_id, params)
     now_str = StatusController.datetime_to_str(datetime.now(), '%Y-%m-%d')
     await self.send_activity_message(
         from_id,
         to_id,
         now_str,
         img_caption="График активности [user] за сегодня")
 def get_story_file_name(taken_at, location):
     story_fname = StatusController.timestamp_to_utc_str(
         taken_at, '%Y-%m-%d--%H%M%S')
     if location:
         story_fname = story_fname + ' ' + location
     story_fname = re.sub(r'[^\w\s\d.,-]', '', story_fname)
     story_fname = story_fname.strip()
     story_fname = re.sub(r'\s+', ' ', story_fname)
     story_fname = re.sub(r'-+', '-', story_fname)
     return story_fname
Beispiel #9
0
 async def on_me_write_message_to_user(self, to_user_id):
     if not self.aa_options['is_set']:
         return
     if (to_user_id in self.aa_for_users) and self.aa_for_users[to_user_id]:
         del self.aa_for_users[to_user_id]
         check_user_name = await self.tg_bot_controller.tg_client.get_entity_name(
             to_user_id, 'User')
         print(
             StatusController.datetime_to_str(datetime.now()) +
             ' Removing AA schedule for user "' + check_user_name + '"')
    async def add_entity_dialog_messages_to_db(self,
                                               entity,
                                               limit,
                                               e_id=None,
                                               e_type=None):
        if (not e_id) or (not e_type):
            if type(entity) == User:
                e_type = 'User'
                e_id = entity.id
                if entity.bot:
                    e_type = 'Bot'
                self.add_entity_db_name(e_id, e_type,
                                        self.get_user_name_text(entity),
                                        entity.phone, False)
            elif type(entity) == Chat:
                e_type = 'Chat'
                e_id = entity.id
                self.chat_names[str(e_id)] = get_display_name(entity)
                self.add_entity_db_name(e_id, e_type, get_display_name(entity),
                                        None, False)
            elif type(entity) == Channel:
                e_type = 'Channel'
                if entity.megagroup:
                    e_type = 'Megagroup'
                e_id = entity.id
                self.channel_megagroups[str(e_id)] = entity.megagroup
                self.channel_names[str(e_id)] = get_display_name(entity)
                self.add_entity_db_name(e_id, e_type, get_display_name(entity),
                                        None, entity.megagroup)
            else:
                return

        messages = await self.tg_client.get_messages(entity, limit=limit)
        for message_i in messages:
            t_date = StatusController.tg_datetime_to_local_datetime(
                message_i.date)
            from_id = None
            to_id = None
            data_message = message_i.to_dict()
            if 'to_id' in data_message:
                if data_message['to_id']['_'] == 'PeerUser':
                    to_id = data_message['to_id']['user_id']
                elif data_message['to_id']['_'] == 'PeerChannel':
                    to_id = data_message['to_id']['channel_id']
                    from_id = to_id
                elif data_message['to_id']['_'] == 'PeerChat':
                    to_id = data_message['to_id']['chat_id']

            if ('from_id' in data_message) and data_message['from_id']:
                from_id = data_message['from_id']

            message_text = self.tg_client.get_dict_message_text(data_message)
            self.tg_client.add_message_to_db(e_id, e_type, from_id, to_id,
                                             message_i.id, message_text,
                                             t_date, 0)
Beispiel #11
0
    async def show_message_edits(self, from_id, entity_id, message_id):
        message_edits = self.dialog_stats.get_message_edits(
            entity_id, message_id)
        results = [
            'Кажется, ты переслал сообщение из отслеживаемого диалога',
            'Выведем доп. информацию по нему...',
            'Число правок: {}'.format(len(message_edits) - 1)
        ]
        if len(message_edits) > 0:
            last_version = None
            for message_edit in message_edits:
                results.append('')
                results.append('**Версия {} / {}**'.format(
                    message_edit['version'], message_edit['max_version']))
                date = StatusController.datetime_from_str(
                    message_edit['taken_at'], '%Y-%m-%d %H:%M:%S%z')
                results.append('Дата: {}'.format(
                    StatusController.datetime_to_str(date)))
                results.append('Сообщение: \n[{}]\n'.format(
                    self.dialog_stats.remove_message_tags(
                        message_edit['message'])))
                if last_version:
                    edit_ratio = self.dialog_stats.get_str_difference_ratio(
                        self.dialog_stats.remove_message_tags(
                            last_version['message']),
                        self.dialog_stats.remove_message_tags(
                            message_edit['message']))
                    results.append('Процент правок: {0:0.2f}%'.format(
                        100 * edit_ratio))
                    diff_counts = self.dialog_stats.get_str_difference_counts(
                        last_version['message'], message_edit['message'])
                    results.append('Число замен   : {}'.format(
                        diff_counts['replaces_count_edit']))
                    results.append('Число вставок : {}'.format(
                        diff_counts['inserts_count_edit']))
                    results.append('Число удалений: {}'.format(
                        diff_counts['deletes_count_edit']))

                last_version = message_edit
        results = "\n".join(results)
        await self.send_message_to_user(from_id, results)
 async def cmd_show_stories_log(self, from_id, params):
     story_records = self.tg_bot_controller.tg_client.entity_controller.get_entity_db_option(
         0, 'insta_story_entries', True, {})
     story_records = list(
         filter(
             lambda xs: xs[1]['filename'] != '',
             sorted(story_records.items(),
                    key=lambda x: x[1]['taken_at'],
                    reverse=True)))
     if not story_records or len(story_records) == 0:
         await self.send_message_to_user(from_id,
                                         'Истории ещё не скачивались!')
         return
     story_records = story_records[:10]
     story_records = [
         StatusController.timestamp_to_str(x[1]['taken_at']) + ': файл "' +
         x[1]['filename'] + '"' for x in story_records
     ]
     results = ['**Лог скачиваний**:\n```']
     results = results + story_records
     results = "\n\n".join(results) + '```'
     await self.send_message_to_user(from_id, results)
Beispiel #13
0
    async def do_on_timer(self, check_ids=None):
        try:
            if not self.aa_options['is_set']:
                return
            if ((datetime.now() - self.tg_bot_controller.tg_client.
                 me_last_activity).total_seconds() /
                    60.0) < self.aa_options['activate_after_minutes']:
                return
            if not check_ids:
                check_ids = list(self.aa_for_users.keys())
            dialogs = None
            for check_id in check_ids:
                if (check_id
                        in self.aa_for_users) and self.aa_for_users[check_id]:
                    if ((StatusController.now_local_datetime() -
                         self.aa_for_users[check_id]).total_seconds() /
                            60.0) >= self.aa_options['answer_after_minutes']:

                        if not dialogs:
                            input_peer = await self.tg_bot_controller.tg_client.get_input_entity(
                                PeerUser(check_id))
                            dialogs = await self.tg_bot_controller.tg_client(
                                GetDialogsRequest(limit=0,
                                                  offset_date=None,
                                                  offset_id=0,
                                                  offset_peer=input_peer,
                                                  hash=0,
                                                  folder_id=0))
                            if type(dialogs) == DialogsSlice:
                                dialogs = dialogs.dialogs

                        c_dialog = None
                        if dialogs:
                            for dialog in dialogs:
                                if (type(dialog.peer) == PeerUser) and (
                                        dialog.peer.user_id == check_id) and (
                                            dialog.read_inbox_max_id > 0):
                                    c_dialog = dialog
                                    break

                        do_remove_aa_user_record = False
                        if (not c_dialog) or (c_dialog.unread_count > 0):
                            unread_cnt_not_me = 0
                            t_messages = await self.tg_bot_controller.tg_client.get_messages(
                                PeerUser(check_id), limit=10)
                            for t_message in t_messages:
                                message_date = StatusController.tg_datetime_to_local_datetime(
                                    t_message.date)
                                user_date = self.aa_for_users[check_id]
                                if t_message.from_id == self.tg_bot_controller.tg_client.me_user_id:
                                    if (message_date > user_date) and (
                                        (message_date -
                                         user_date).total_seconds() > 1):
                                        do_remove_aa_user_record = True
                                        break
                                elif c_dialog and (t_message.id >
                                                   c_dialog.read_inbox_max_id):
                                    unread_cnt_not_me = unread_cnt_not_me + 1
                            if c_dialog and (unread_cnt_not_me == 0):
                                do_remove_aa_user_record = True
                        elif c_dialog and (c_dialog.unread_count == 0):
                            do_remove_aa_user_record = True

                        if do_remove_aa_user_record:
                            del self.aa_for_users[check_id]
                            check_user_name = await self.tg_bot_controller.tg_client.get_entity_name(
                                check_id, 'User')
                            print(
                                StatusController.datetime_to_str(
                                    datetime.now()) +
                                ' Removing AA schedule for user "' +
                                check_user_name + '"')
                            continue

                        self.aa_for_users[check_id] = None
                        self.aa_not_for_users.append(check_id)
                        await self.send_message(check_id)
                        if self.aa_options['allow_bot_chat']:
                            await self.tg_bot_controller.init_chat_for_user(
                                check_id, check_id, False,
                                self.aa_options['show_bot'])
        except:
            traceback.print_exc()
    def save_user_stories(self, user_id, username):

        try:
            response = self.branch_parent.api.user_reel_media(user_id)
        except:
            print(username + ': Stories read error!')
            traceback.print_exc()
            return

        story_records = self.tg_bot_controller.tg_client.entity_controller.get_entity_db_option(
            0, 'insta_story_entries', True, {})

        for st_id in list(story_records.keys()):
            try:
                n_time = StatusController.now_local_datetime()
                d_time = StatusController.timestamp_to_local_datetime(
                    int(story_records[st_id]['taken_at']))
                if (not d_time) or (n_time - d_time).total_seconds() > (
                        2 * 24 * 60 * 60):
                    del story_records[st_id]
            except:
                del story_records[st_id]

        dups = 0
        for item in response['items']:
            id = item['id']
            try:
                url = item['video_versions'][0]['url']
            except KeyError:
                url = item['image_versions2']['candidates'][0]['url']
            taken_at = item['taken_at']
            location = ''
            if 'story_locations' in item:
                location_items = item['story_locations']
                if location_items and len(location_items) > 0:
                    location_item = location_items[0]
                    if location_item and ('location' in location_item
                                          ) and location_item['location']:
                        location_item = location_item['location']
                        location = location_item['name']
                        if ('address'
                                in location_item) and location_item['address']:
                            location = location + ', ' + str(
                                location_item['address'])
                        if ('city' in location_item) and location_item['city']:
                            location = location + ', ' + str(
                                location_item['city'])
                        if ('lat' in location_item) and ('lng'
                                                         in location_item):
                            location = location + ', ' + str(
                                location_item['lat']) + ',' + str(
                                    location_item['lng'])
            story_fname = self.get_story_file_name(taken_at, location)
            viewers_info = {}
            viewers_ids = []
            if 'viewers' in item:
                viewers = item['viewers']
                for viewer in viewers:
                    viewers_info[str(viewer['pk'])] = {
                        'date': datetime.now(),
                        'username': viewer['username'],
                        'full_name': viewer['full_name'],
                        'pk': viewer['pk']
                    }
                    viewers_ids.append(viewer['pk'])
                viewers_ids.sort()
                viewers = json.dumps(viewers_ids)
            else:
                viewers = '[]'

            if id not in story_records:
                entry = {
                    "id": id,
                    "url": url,
                    "userid": user_id,
                    "username": username,
                    "taken_at": taken_at,
                    "filename": "",
                    "viewers": viewers,
                    "location": location
                }
                story_records[id] = entry
                old_viewers = '[]'
                print('New story for user ' + str(username) + ' was found: ' +
                      story_fname)
                MainHelper().play_notify_sound('notify_when_new_insta_story')
            else:
                dups = dups + 1
                old_viewers = story_records[id]['viewers']

            if old_viewers != viewers:
                if viewers != '[]':
                    MainHelper().play_notify_sound(
                        'notify_when_new_insta_view')
                old_viewers = json.loads(old_viewers)
                append_strs = []

                for new_viewer in viewers_ids:
                    if new_viewer not in old_viewers:
                        new_data = viewers_info[str(new_viewer)]
                        new_str = '"' + str(new_data['pk']) + '";"' + \
                                new_data['full_name'] + '";"' + str(new_data['date'].strftime('%Y-%m-%d %H:%M:%S')) + \
                                '";"https://www.instagram.com/' + new_data['username'] + '"'
                        append_strs.append(new_str)
                        print('!!! User ' + new_data['full_name'] +
                              ' watched your story ' + story_fname)

                if len(append_strs) > 0:
                    stories_folder = MainHelper().get_config_root_folder_value(
                        'instagram', 'stories_folder')
                    if not os.path.exists(stories_folder):
                        os.makedirs(stories_folder)
                    file_path = stories_folder + "/" + str(username)
                    if not os.path.exists(file_path):
                        os.makedirs(file_path)
                    file_name = story_fname + ".csv"
                    with open(file_path + "/" + file_name, 'a') as file:
                        if len(old_viewers) == 0:
                            file.write('"ID";"Full name";"Date";"User link"' +
                                       "\n")
                        for line in append_strs:
                            file.write(line + "\n")
                        file.close()

                if id in story_records:
                    story_records[id]['viewers'] = viewers

        if dups > 0:
            if dups > 1:
                stories_str = "stories"
            else:
                stories_str = "story"
            print(username + ": " + str(dups) + " old " + stories_str +
                  " was skipped.")
        if (not response['items']) or (len(response['items']) == 0):
            print(username + ": Stories was not found.")

        self.tg_bot_controller.tg_client.entity_controller.set_entity_db_option(
            0, 'insta_story_entries', story_records, True)
 async def cmd_activity_today(self, from_id, params):
     to_id = from_id
     from_id = await self.tg_bot_controller.get_from_id_param(
         from_id, params)
     now_str = StatusController.datetime_to_str(datetime.now(), '%Y-%m-%d')
     await self.send_activity_message(from_id, to_id, now_str, True, "diap")
Beispiel #16
0
    async def get_me_dialog_statistics(self, user_id, date_from=None, title='за всё время', only_last_dialog=False, skip_vocab=False):

        new_normal_form_cache = CacheHelper().get_from_cache('normal_forms', 'dialog_stats', False)
        if new_normal_form_cache:
            self.normal_form_cache = new_normal_form_cache

        new_word_type_form_cache = CacheHelper().get_from_cache('word_type_forms', 'dialog_stats', False)
        if new_word_type_form_cache:
            self.word_type_form_cache = new_word_type_form_cache

        days_a = '?'
        if (not date_from) and (not only_last_dialog):
            res = self.db_conn.execute(
                """
                    SELECT *
                    FROM `activity`
                    ORDER BY taken_at ASC
                """,
                [])
            rows = list(res.fetchall())
            days_a = 1
            if len(rows) > 1:
                date1 = StatusController.datetime_from_str(rows[0]['taken_at'])
                date2 = StatusController.datetime_from_str(rows[len(rows) - 1]['taken_at'])
                days_a = round((date2 - date1).total_seconds() / (24 * 60 * 60))
        results = []
        last_dialogue_date = None
        try:
            user_entity = await self.tg_client.get_entity(PeerUser(user_id))
        except:
            user_entity = None
        if user_entity and (type(user_entity) == User):
            if not date_from:
                res = self.db_conn.execute(
                    """
                        SELECT m.*, 
                        (SELECT version FROM `messages` m1 WHERE m1.`entity_id` = m.`entity_id` AND m1.message_id = m.message_id AND m1.from_id = m.from_id ORDER BY version DESC LIMIT 1) as 'max_version',
                        (SELECT removed FROM `messages` m1 WHERE m1.`entity_id` = m.`entity_id` AND m1.message_id = m.message_id AND m1.from_id = m.from_id ORDER BY version DESC LIMIT 1) as 'is_removed'
                        FROM `messages` m
                        WHERE m.`entity_id` = ? OR m.`entity_id` = ?
                        ORDER BY m.`taken_at` ASC, m.`message_id` ASC, m.`version` ASC
                    """,
                    [str(user_id), str(self.tg_client.me_user_id)]
                )
            else:
                date_from = StatusController.datetime_to_str(date_from, '%Y-%m-%d')
                res = self.db_conn.execute(
                    """
                        SELECT m.*, 
                        (SELECT version FROM `messages` m1 WHERE m1.`entity_id` = m.`entity_id` AND m1.message_id = m.message_id AND m1.from_id = m.from_id ORDER BY version DESC LIMIT 1) as 'max_version',
                        (SELECT removed FROM `messages` m1 WHERE m1.`entity_id` = m.`entity_id` AND m1.message_id = m.message_id AND m1.from_id = m.from_id ORDER BY version DESC LIMIT 1) as 'is_removed'
                        FROM `messages` m
                        WHERE (m.`entity_id` = ? OR m.`entity_id` = ?) AND (m.`taken_at` > ?)
                        ORDER BY m.`taken_at` ASC, m.`message_id` ASC, m.`version` ASC
                    """,
                    [str(user_id), str(self.tg_client.me_user_id), date_from]
                )
            rows = list(res.fetchall())

            me_name = self.tg_client.me_user_entity_name
            another_name = await self.tg_client.get_entity_name(user_id, 'User')
            dialog_name = me_name + ' <-> ' + another_name

            results.append('**Диалог '+dialog_name+' ('+title+')'+':**')
            results.append('')
            results.append('Сообщений диалога в БД: ' + str(len(rows)))
            if len(rows) > 0:
                date_start = StatusController.datetime_from_str(rows[0]['taken_at'], '%Y-%m-%d %H:%M:%S%z')
                if not only_last_dialog:
                    results.append('Самое раннее сообщение диалога в БД: ' + StatusController.datetime_to_str(date_start))
                if len(rows) > 1:
                    date_end = StatusController.datetime_from_str(rows[len(rows) - 1]['taken_at'], '%Y-%m-%d %H:%M:%S%z')
                    seconds_count = (date_end - date_start).total_seconds()
                    days_count = seconds_count / (24 * 60 * 60)
                    messages_count = len(rows)
                    if (not date_from) and (not only_last_dialog):
                        results.append('Длительность общения: {0:0.2f} суток'.format(days_count))
                    if not only_last_dialog:
                        results.append('Средняя частота сообщений: {0:0.2f} в сутки'.format(messages_count / days_count))

                    max_dialog_question_interval = round((24 * 60 * 60) * 1.25)
                    max_dialog_non_question_interval = round((24 * 60 * 60) * 0.75)
                    max_dialog_hello_as_second_message_offset = round((24 * 60 * 60) * 0.25)
                    dialog_hello_words = ['привет', 'приветствую', 'здравствуй', 'здравствуйте']
                    dialog_hello_phrases = ['доброе утро', 'доброго утра', 'добрый день', 'доброго дня', 'добрый вечер', 'доброго вечера']
                    dialog_hello_stop_context = ['-привет', 'всем привет', 'привет»', 'привет"']

                    msg_len_me = 0
                    msg_me_cnt = 0
                    msg_me_max_len = 0
                    msg_len_another = 0
                    msg_another_cnt = 0
                    msg_another_max_len = 0

                    me_deletes = 0
                    another_deletes = 0

                    me_hello = 0
                    another_hello = 0

                    me_words = []
                    another_words = []

                    dialogues = []
                    active_dialog = []
                    last_msg_from_id = None
                    last_date = date_start
                    last_msg_is_question = False

                    edited_messages_me = {}
                    edited_messages_another = {}
                    edited_sequence_interrupted = {}

                    last_message_row = None

                    for row in rows:
                        if not row['message']:
                            row['message'] = ''
                        if int(row['removed']) == 1 or int(row['is_removed']) == 1:
                            if int(row['version']) == int(row['max_version']):
                                if int(row['from_id']) == self.tg_client.me_user_id:
                                    me_deletes = me_deletes + 1
                                else:
                                    another_deletes = another_deletes + 1
                        else:
                            if row['message_id'] not in edited_sequence_interrupted:
                                for k_int in edited_sequence_interrupted.keys():
                                    if type(edited_sequence_interrupted[k_int]) == dict:
                                        if edited_sequence_interrupted[k_int]['from_id'] != row['from_id']:
                                            edited_sequence_interrupted[k_int]['interrupts'].append(row['message_id'])

                            if int(row['max_version']) > 1:
                                if int(row['version']) < int(row['max_version']):
                                    if row['message_id'] not in edited_sequence_interrupted:
                                        edited_sequence_interrupted[row['message_id']] = {
                                            'from_id': row['from_id'],
                                            'interrupts': []
                                        }
                                else:
                                    if row['message_id'] in edited_sequence_interrupted:
                                        edited_sequence_interrupted[row['message_id']] = len(edited_sequence_interrupted[row['message_id']]['interrupts']) > 0

                            if last_message_row and (int(last_message_row['version']) < int(last_message_row['max_version'])) and (row['from_id'] != last_message_row['from_id']):
                                edited_sequence_interrupted[row['message_id']] = True
                            if int(row['version']) == int(row['max_version']):
                                last_message_row = row

                            if int(row['max_version']) > 1:
                                if int(row['from_id']) == self.tg_client.me_user_id:
                                    if row['message_id'] not in edited_messages_me:
                                        edited_messages_me[row['message_id']] = []
                                    edited_messages_me[row['message_id']].append(row)
                                else:
                                    if row['message_id'] not in edited_messages_another:
                                        edited_messages_another[row['message_id']] = []
                                    edited_messages_another[row['message_id']].append(row)
                            if int(row['version']) == int(row['max_version']):
                                message_lower = str(row['message']).lower()
                                message_words = re.sub("[^\w]", " ", message_lower).split()
                                message_words = list(filter(lambda x: x and self.is_valid_word(x, []), message_words))

                                message_hello_words = list(filter(lambda x: x in dialog_hello_words, message_words))
                                message_stop_contexts = list(filter(lambda x: message_lower.find(x) >= 0, dialog_hello_stop_context))

                                msg_from_id = int(row['from_id'])
                                msg_is_question = str(row['message']).find('?') >= 0
                                msg_is_hello = (len(message_hello_words) > 0) and (len(message_stop_contexts) == 0)

                                if not msg_is_hello:
                                    for d_ph in dialog_hello_phrases:
                                        if message_lower.find(d_ph) >= 0:
                                            msg_is_hello = True
                                            break

                                if not skip_vocab:
                                    nform_list = [self.get_normal_form(x) for x in message_words]
                                    if msg_from_id == self.tg_client.me_user_id:
                                        me_words = me_words + nform_list
                                    else:
                                        another_words = another_words + nform_list

                                if msg_is_hello:
                                    if msg_from_id == self.tg_client.me_user_id:
                                        me_hello = me_hello + 1
                                    else:
                                        another_hello = another_hello + 1
                                msg_len = len(row['message'])
                                if msg_from_id == self.tg_client.me_user_id:
                                    msg_len_me = msg_len_me + msg_len
                                    msg_me_cnt = msg_me_cnt + 1
                                    if msg_len > msg_me_max_len:
                                        msg_me_max_len = msg_len
                                else:
                                    msg_len_another = msg_len_another + msg_len
                                    msg_another_cnt = msg_another_cnt + 1
                                    if msg_len > msg_another_max_len:
                                        msg_another_max_len = msg_len
                                msg_date = StatusController.datetime_from_str(row['taken_at'], '%Y-%m-%d %H:%M:%S%z')
                                if (
                                        (len(active_dialog) == 0) or (
                                            last_msg_is_question and
                                            ((msg_date - last_date).total_seconds() > max_dialog_question_interval)
                                        ) or (
                                            not last_msg_is_question and
                                            ((msg_date - last_date).total_seconds() > max_dialog_non_question_interval)
                                        )
                                ):
                                    if len(active_dialog) > 0:
                                        dialogues.append(active_dialog)
                                        active_dialog = []
                                active_dialog.append(row)
                                last_date = msg_date
                                if last_msg_from_id != msg_from_id:
                                    last_msg_is_question = msg_is_question
                                else:
                                    last_msg_is_question = last_msg_is_question or msg_is_question
                                last_msg_from_id = msg_from_id

                    for k_int in edited_sequence_interrupted.keys():
                        if type(edited_sequence_interrupted[k_int]) == dict:
                            edited_sequence_interrupted[k_int] = len(edited_sequence_interrupted[k_int]['interrupts']) > 0

                    me_edit_stats = self.get_edit_stats(edited_messages_me, edited_sequence_interrupted)
                    another_edit_stats = self.get_edit_stats(edited_messages_another, edited_sequence_interrupted)

                    if len(active_dialog) > 0:
                        dialogues.append(active_dialog)
                        active_dialog = []

                    if only_last_dialog:
                        dialogues = [dialogues[len(dialogues) - 1]]
                    else:
                        if len(dialogues) > 0:
                            last_dialogue_date = StatusController.datetime_from_str(dialogues[len(dialogues) - 1][0]['taken_at'], '%Y-%m-%d %H:%M:%S%z')
                        else:
                            last_dialogue_date = None

                    answers_me = 0
                    answers_wait_seconds_me = 0
                    answers_another = 0
                    answers_wait_seconds_another = 0

                    longest_len = 0
                    longest_dialog = None
                    shortest_len = 0

                    dia_me_start = 0
                    dia_another_start = 0

                    dia_me_finish = 0
                    dia_another_finish = 0

                    dia_between_seconds = 0
                    dia_between_max = 0
                    dia_between_max_from = None
                    dia_between_max_to = None
                    dia_between_cnt = 0

                    last_dia_end = None
                    for dial in dialogues:
                        dial_len = len(dial)

                        if (shortest_len == 0) or (dial_len < shortest_len):
                            shortest_len = dial_len
                        if (longest_len == 0) or (dial_len > longest_len):
                            longest_len = dial_len
                            longest_dialog = dial

                        if dial_len > 0:
                            first_dial = dial[0]
                            last_dial = dial[len(dial) - 1]
                            if int(first_dial['from_id']) == self.tg_client.me_user_id:
                                dia_me_start = dia_me_start + 1
                            else:
                                dia_another_start = dia_another_start + 1
                            if int(last_dial['from_id']) == self.tg_client.me_user_id:
                                dia_me_finish = dia_me_finish + 1
                            else:
                                dia_another_finish = dia_another_finish + 1
                            if last_dia_end:
                                curr_first_dia_begin = StatusController.datetime_from_str(first_dial['taken_at'], '%Y-%m-%d %H:%M:%S%z')
                                dia_between_seconds_curr = (curr_first_dia_begin - last_dia_end).total_seconds()
                                dia_between_seconds = dia_between_seconds + dia_between_seconds_curr
                                dia_between_cnt = dia_between_cnt + 1
                                if dia_between_seconds_curr > dia_between_max:
                                    dia_between_max = dia_between_seconds_curr
                                    dia_between_max_from = last_dia_end
                                    dia_between_max_to = curr_first_dia_begin
                            last_dia_end = StatusController.datetime_from_str(last_dial['taken_at'], '%Y-%m-%d %H:%M:%S%z')

                        last_msg_id = None
                        last_msg_date = None
                        for dia in dial:
                            msg_date = StatusController.datetime_from_str(dia['taken_at'], '%Y-%m-%d %H:%M:%S%z')
                            if last_msg_id and (last_msg_id != int(dia['from_id'])):
                                seconds_between = (msg_date - last_msg_date).total_seconds()
                                if seconds_between > (60 * 60 * 4) and ((last_msg_date.time().hour < 6) or (last_msg_date.time().hour >= 22)):
                                    # somebody just sleep
                                    last_msg_date = msg_date
                                    last_msg_id = int(dia['from_id'])
                                    continue
                                if last_msg_id == self.tg_client.me_user_id:
                                    answers_another = answers_another + 1
                                    answers_wait_seconds_another = answers_wait_seconds_another + seconds_between
                                else:
                                    answers_me = answers_me + 1
                                    answers_wait_seconds_me = answers_wait_seconds_me + seconds_between
                            last_msg_date = msg_date
                            last_msg_id = int(dia['from_id'])

                    if dia_between_cnt > 0:
                        dia_between_time = dia_between_seconds / dia_between_cnt
                        dia_between_time = "{0:0.2f} сут.".format(dia_between_time / (60 * 60 * 24))
                        dia_between_time_max = "{0:0.2f} сут.".format(dia_between_max / (60 * 60 * 24))
                        dia_between_time_max = StatusController.datetime_to_str(dia_between_max_from) + ' --- ' + StatusController.datetime_to_str(dia_between_max_to) + ' ('+dia_between_time_max+')'
                    else:
                        dia_between_time = '?'
                        dia_between_time_max = '?'

                    if answers_another > 0:
                        answers_wait_seconds_another = answers_wait_seconds_another / answers_another
                        another_answer_time = "{0:0.2f} мин.".format(answers_wait_seconds_another / 60)
                    else:
                        another_answer_time = '?'

                    if answers_me > 0:
                        answers_wait_seconds_me = answers_wait_seconds_me / answers_me
                        me_answer_time = "{0:0.2f} мин.".format(answers_wait_seconds_me / 60)
                    else:
                        me_answer_time = '?'

                    if not date_from:
                        self.tg_client.entity_controller.set_entity_answer_sec(user_id, answers_wait_seconds_me, answers_wait_seconds_another)

                    longest_dates = ''
                    longest_hours = 0
                    if longest_len > 1:
                        msg_date1 = StatusController.datetime_from_str(longest_dialog[0]['taken_at'], '%Y-%m-%d %H:%M:%S%z')
                        msg_date2 = StatusController.datetime_from_str(longest_dialog[longest_len - 1]['taken_at'], '%Y-%m-%d %H:%M:%S%z')
                        longest_hours = (msg_date2 - msg_date1).total_seconds() / (24 * 60 * 60)
                        longest_dates = StatusController.datetime_to_str(msg_date1) + ' --- ' + StatusController.datetime_to_str(msg_date2)

                    valid_word_types = ['СУЩ', 'МЕЖД']
                    valid_word_types_str = (",".join(valid_word_types)).lower()

                    me_top_10 = None
                    me_last_cnt = None
                    me_words_count = 0
                    all_words_me = {}
                    if (not skip_vocab) and (len(me_words) > 0):
                        for word in me_words:
                            if word and (word not in all_words_me):
                                all_words_me[word] = True
                        me_words_count = len(all_words_me)

                        me_words = list(filter(lambda x: x and self.is_valid_word(x, valid_word_types), me_words))
                        wordlist = sorted(me_words)
                        wordfreq = [wordlist.count(p) for p in wordlist]
                        dic = dict(zip(wordlist, wordfreq))
                        me_words = list(sorted(dic.items(), key=lambda x: x[1], reverse=True))
                        words = me_words
                        half_words = round(len(words) / 2)
                        if half_words < 3:
                            half_words = 3
                        elif half_words > 15:
                            half_words = 15
                        top_10 = list(filter(lambda x: x[1] > 1, words[0:half_words]))
                        top_10 = list(map(lambda x: '**' + str(x[0]) + '** (' + str(x[1]) + ')', top_10))
                        last_word, last_cnt = words[len(words) - 1]
                        last_cnt_words = map(lambda x: x[0], filter(lambda s: s[1] == last_cnt, words))
                        last_cnt_words = list(sorted(last_cnt_words, key=lambda x: len(x), reverse=True))
                        last_cnt_cnt = len(last_cnt_words) - half_words
                        if last_cnt_cnt < 3:
                            last_cnt_cnt = 3
                        elif last_cnt_cnt > 10:
                            last_cnt_cnt = 10
                        last_cnt_words = last_cnt_words[0:last_cnt_cnt]
                        me_top_10 = top_10
                        me_last_cnt = last_cnt_words

                    another_top_10 = None
                    another_last_cnt = None
                    another_words_count = 0
                    all_words_another = {}
                    if (not skip_vocab) and (len(another_words) > 0):
                        for word in another_words:
                            if word and (word not in all_words_another):
                                all_words_another[word] = True
                        another_words_count = len(all_words_another)

                        another_words = list(filter(lambda x: x and self.is_valid_word(x, valid_word_types), another_words))
                        wordlist = sorted(another_words)
                        wordfreq = [wordlist.count(p) for p in wordlist]
                        dic = dict(zip(wordlist, wordfreq))
                        another_words = list(sorted(dic.items(), key=lambda x: x[1], reverse=True))
                        words = another_words
                        half_words = round(len(words) / 2)
                        if half_words < 3:
                            half_words = 3
                        elif half_words > 15:
                            half_words = 15
                        top_10 = list(filter(lambda x: x[1] > 1, words[0:half_words]))
                        top_10 = list(map(lambda x: '**' + str(x[0]) + '** (' + str(x[1]) + ')', top_10))
                        last_word, last_cnt = words[len(words) - 1]
                        last_cnt_words = map(lambda x: x[0], filter(lambda s: s[1] == last_cnt, words))
                        last_cnt_words = list(sorted(last_cnt_words, key=lambda x: len(x), reverse=True))
                        last_cnt_cnt = len(last_cnt_words) - half_words
                        if last_cnt_cnt < 3:
                            last_cnt_cnt = 3
                        elif last_cnt_cnt > 10:
                            last_cnt_cnt = 10
                        last_cnt_words = last_cnt_words[0:last_cnt_cnt]
                        another_top_10 = top_10
                        another_last_cnt = last_cnt_words

                    me_not_another_words_count = 0
                    me_not_another_top = None

                    another_not_me_words_count = 0
                    another_not_me_top = None

                    if (not skip_vocab) and (len(me_words) > 0) and (len(another_words) > 0):
                        me_not_another_top = []
                        for word in me_words:
                            if word[0] not in all_words_another:
                                me_not_another_top.append(word)

                        me_not_another_words_count = len(me_not_another_top)
                        me_not_another_top = me_not_another_top[:15]
                        me_not_another_top = list(map(lambda x: '**' + str(x[0]) + '** (' + str(x[1]) + ')', me_not_another_top))

                        another_not_me_top = []
                        for word in another_words:
                            if word[0] not in all_words_me:
                                another_not_me_top.append(word)

                        another_not_me_words_count = len(another_not_me_top)
                        another_not_me_top = another_not_me_top[:15]
                        another_not_me_top = list(map(lambda x: '**' + str(x[0]) + '** (' + str(x[1]) + ')', another_not_me_top))

                    results.append('Сообщений '+another_name+': {0} ({1:0.3f} Kb.)'.format(msg_another_cnt, msg_len_another/1024))
                    results.append('Сообщений '+me_name+': {0} ({1:0.3f} Kb.)'.format(msg_me_cnt, msg_len_me/1024))
                    if msg_another_cnt > 0:
                        results.append('Средняя длина сообщения '+another_name+': {0:0.2f} сим.'.format(msg_len_another / msg_another_cnt))
                    if msg_me_cnt > 0:
                        results.append('Средняя длина сообщения '+me_name+': {0:0.2f} сим.'.format(msg_len_me / msg_me_cnt))
                    results.append('Самое длинное сообщение '+another_name+': ' + str(msg_another_max_len) + ' сим.')
                    results.append('Самое длинное сообщение '+me_name+': ' + str(msg_me_max_len) + ' сим.')
                    results.append('Число приветствий от '+another_name+': ' + str(another_hello))
                    results.append('Число приветствий от '+me_name+': ' + str(me_hello))

                    if not only_last_dialog:
                        results.append('')
                        results.append('Число диалогов: ' + str(len(dialogues)))
                        results.append('Сообщений в самом коротком диалоге: ' + str(shortest_len))
                        results.append('Сообщений в самом длинном диалоге: ' + str(longest_len))
                        results.append('Самый длинный диалог: ' + longest_dates + ' ({0:0.3f} сут)'.format(longest_hours))
                        if len(dialogues) > 0:
                            if dia_between_time != '?':
                                results.append('Среднее время между диалогами: ' + str(dia_between_time))
                            if dia_between_time_max != '?':
                                results.append('Самое большое время между диалогами: ' + str(dia_between_time_max))
                            results.append('Инициатор диалога ' + another_name + ': {0:0.2f} %'.format(100 * dia_another_start / len(dialogues)))
                            results.append('Инициатор диалога ' + me_name + ': {0:0.2f} %'.format(100 * dia_me_start / len(dialogues)))
                            results.append('Завершитель диалога ' + another_name + ': {0:0.2f} %'.format(100 * dia_another_finish / len(dialogues)))
                            results.append('Завершитель диалога ' + me_name + ': {0:0.2f} %'.format(100 * dia_me_finish / len(dialogues)))
                    else:
                        results.append('Сообщений в диалоге: ' + str(longest_len))
                        results.append('Продолжительность диалога: ' + longest_dates + ' ({0:0.3f} сут)'.format(longest_hours))
                        if dia_me_start > 0:
                            results.append('Инициатор: ' + me_name)
                        elif dia_another_start > 0:
                            results.append('Инициатор: ' + another_name)
                        if dia_me_finish > 0:
                            results.append('Завершитель: ' + me_name)
                        elif dia_another_finish > 0:
                            results.append('Завершитель: ' + another_name)

                    if another_answer_time != '?':
                        results.append('В среднем ' + another_name + ' отвечает за: ' + another_answer_time)
                    if me_answer_time != '?':
                        results.append('В среднем ' + me_name + ' отвечает за: ' + me_answer_time)
                    results.append('')
                    if me_edit_stats['edited_messages_count'] > 0 or another_edit_stats['edited_messages_count'] > 0:
                        if (not date_from) and (not only_last_dialog):
                            results.append('За время активности скрипта ('+str(days_a)+' сут.):')
                        results.append('Отредактировано сообщений {}: {}'.format(another_name, another_edit_stats['edited_messages_count']))
                        results.append('Отредактировано сообщений {}: {}'.format(me_name, me_edit_stats['edited_messages_count']))
                        results.append('Отредактировано сообщений {} после ответа на него: {}'.format(another_name, another_edit_stats['sequence_interrupted_cnt']))
                        results.append('Отредактировано сообщений {} после ответа на него: {}'.format(me_name, me_edit_stats['sequence_interrupted_cnt']))
                        results.append('Процент редактируемых сообщений {0}: {1:0.2f}%'.format(another_name, 100 * another_edit_stats['edited_messages_count'] / msg_another_cnt))
                        results.append('Процент редактируемых сообщений {0}: {1:0.2f}%'.format(me_name, 100 * me_edit_stats['edited_messages_count'] / msg_me_cnt))
                        if another_edit_stats['max_1_message_edits'] > 0:
                            results.append('Макс. число правок одного сообщения {}: {} ("{}")'.format(another_name, another_edit_stats['max_1_message_edits'], self.cut_text(another_edit_stats['max_edits_message'])))
                        if me_edit_stats['max_1_message_edits'] > 0:
                            results.append('Макс. число правок одного сообщения {}: {} ("{}")'.format(me_name, me_edit_stats['max_1_message_edits'], self.cut_text(me_edit_stats['max_edits_message'])))
                        if another_edit_stats['max_1_message_diff_percent'] > 0:
                            results.append('Макс. процент правок одного сообщения {0}: {1:0.2f}% ("{2}")'.format(another_name, another_edit_stats['max_1_message_diff_percent'], self.cut_text(another_edit_stats['max_changed_message'])))
                        if me_edit_stats['max_1_message_diff_percent'] > 0:
                            results.append('Макс. процент правок одного сообщения {0}: {1:0.2f}% ("{2}")'.format(me_name, me_edit_stats['max_1_message_diff_percent'], self.cut_text(me_edit_stats['max_changed_message'])))
                        results.append('')
                        results.append('В среднем правок на 1 сообщение {0}: {1:0.2f}'.format(another_name, another_edit_stats['mid_1_message_edits']))
                        results.append('В среднем правок на 1 сообщение {0}: {1:0.2f}'.format(me_name, me_edit_stats['mid_1_message_edits']))
                        results.append('Средний суммарный процент изменений редактируемых сообщений {0}: {1:0.3f}%'.format(another_name, another_edit_stats['message_edit_mid_summ_percent']))
                        results.append('Средний суммарный процент изменений редактируемых сообщений {0}: {1:0.3f}%'.format(me_name, me_edit_stats['message_edit_mid_summ_percent']))
                        results.append('Среднее время между правками одного сообщения {0}: {1:0.2f} мин.'.format(another_name, another_edit_stats['message_edit_mid_time_sec'] / 60))
                        results.append('Среднее время между правками одного сообщения {0}: {1:0.2f} мин.'.format(me_name, me_edit_stats['message_edit_mid_time_sec'] / 60))
                        results.append('')
                        results.append('Средняя правка (число замен / вставок / удалений) {0}: {1:0.2f} / {2:0.2f} / {3:0.2f}'.format(another_name, another_edit_stats['replaces_count_avg'], another_edit_stats['inserts_count_avg'], another_edit_stats['deletes_count_avg']))
                        results.append('Средняя правка (число замен / вставок / удалений) {0}: {1:0.2f} / {2:0.2f} / {3:0.2f}'.format(me_name, me_edit_stats['replaces_count_avg'], me_edit_stats['inserts_count_avg'], me_edit_stats['deletes_count_avg']))
                        results.append('')
                        results.append('Удалений сообщений ' + another_name + ': ' + str(another_deletes))
                        results.append('Удалений сообщений ' + me_name + ': ' + str(me_deletes))

                    if me_top_10 or another_top_10:
                        results.append('')
                        results.append('Различных слов ' + another_name + ' в диалогах: ' + str(another_words_count))
                        results.append('Различных слов ' + me_name + ' в диалогах: ' + str(me_words_count))
                        results.append('')
                        results.append('Самые частые слова ('+valid_word_types_str+') ' + another_name + ' в диалогах: ' + (", ".join(another_top_10)) + '')
                        results.append('')
                        results.append('Самые частые слова ('+valid_word_types_str+') ' + me_name + ' в диалогах: ' + (", ".join(me_top_10)) + '')
                        results.append('')
                        results.append('Самые редкие слова ('+valid_word_types_str+') ' + another_name + ' в диалогах: ' + (", ".join(another_last_cnt)) + '')
                        results.append('')
                        results.append('Самые редкие слова ('+valid_word_types_str+') ' + me_name + ' в диалогах: ' + (", ".join(me_last_cnt)) + '')
                        if me_not_another_words_count > 0:
                            results.append('')
                            results.append('Слова ' + me_name + ' ('+valid_word_types_str+'), которые ' + another_name + ' ни разу не использовал: **' + str(me_not_another_words_count) +'** шт. Самые частые: ' + (", ".join(me_not_another_top)) + '')
                        if another_not_me_words_count > 0:
                            results.append('')
                            results.append('Слова ' + another_name + ' ('+valid_word_types_str+'), которые ' + me_name + ' ни разу не использовал: **' + str(another_not_me_words_count) +'** шт. Самые частые: ' + (", ".join(another_not_me_top)) + '')

        CacheHelper().save_to_cache('normal_forms', 'dialog_stats', self.normal_form_cache)
        CacheHelper().save_to_cache('word_type_forms', 'dialog_stats', self.word_type_form_cache)

        return {
            'results': results,
            'last_dialogue_date': last_dialogue_date
        }
    async def cmd_user_info(self, to_id, params):
        from_id = to_id
        for_id = await self.tg_bot_controller.get_from_id_param(to_id, params)
        entity = await self.tg_bot_controller.tg_client.get_entity(for_id)
        res = []
        res.append('ID: ' + str(entity.id))
        if entity.username:
            res.append('Логин: ' + str(entity.username))
        if entity.phone:
            res.append('Телефон: ' + str(entity.phone))
        if entity.first_name:
            res.append('Имя: ' + str(entity.first_name))
        if entity.last_name:
            res.append('Фамилия: ' + str(entity.last_name))
        res.append('')
        if to_id != for_id:
            if entity.mutual_contact:
                res.append('У тебя в контактах, ты у него в контактах')
            elif entity.contact:
                res.append('У тебя в контактах')
        last_date = None
        if type(entity.status) == UserStatusOnline:
            status_name = 'Онлайн'
        elif type(entity.status) == UserStatusOffline:
            status_name = 'Оффлайн'
            last_date = StatusController.tg_datetime_to_local_datetime(
                entity.status.was_online)
            last_date = StatusController.datetime_to_str(last_date)
        elif entity.status:
            status_name = 'Не отслеживается (' + entity.status.to_dict(
            )['_'] + ')'
        elif entity.bot:
            status_name = 'Бот'
        else:
            status_name = 'Неизвестно'
        res.append('Статус: ' + status_name)
        if last_date:
            res.append('Был в сети: ' + last_date)
        res.append('')
        sessions_cnt = self.tg_bot_controller.tg_client.status_controller.get_user_activity_sessions_count(
            entity.id)
        if sessions_cnt > 0:
            res.append('Активность отслеживается (сохранено сессий: ' +
                       str(sessions_cnt) + ')')
        else:
            res.append('Активность не отслеживается')
        m_types = self.tg_bot_controller.tg_client.status_controller.get_user_messages_entity_types(
            entity.id)
        if m_types and len(m_types) > 0:
            res.append('Сообщения отслеживаются (' + (", ".join(m_types)) +
                       ')')
        else:
            res.append('Сообщения не отслеживается')

        stat_msg = await self.tg_bot_controller.tg_client.status_controller.get_user_aa_statistics_text(
            entity.id, False)
        if stat_msg:
            res.append('')
            res.append(stat_msg)

        stat_msg = await self.tg_bot_controller.tg_client.status_controller.get_stat_user_messages(
            entity.id, from_id)
        if stat_msg:
            res.append('')
            res.append(stat_msg)

        await self.send_message_to_user(to_id, "\n".join(res))
Beispiel #18
0
    def get_edit_stats(self, edited_messages: dict, edited_sequence_interrupted: dict):

        edits_count = 0
        max_1_message_edits = 0
        max_1_message_diff = 0
        mid_1_message_edits = 0.0
        message_edit_mid_full_percent = 0
        message_edit_mid_summ_percent = 0
        message_edit_mid_time_sec = 0
        edited_messages_count = len(edited_messages)
        max_edits_message = ''
        max_changed_message = ''

        replaces_count_avg = 0
        inserts_count_avg = 0
        deletes_count_avg = 0
        sequence_interrupted_cnt = 0

        if edited_messages_count > 0:
            for edit_rows in edited_messages.values():
                # print([(x['taken_at'] + ': "' + x['message'] + '"') for x in edit_rows])
                edit_ratio_summ = 0
                last_version = None
                summ_edits_time = 0
                message_edit_cnt = len(edit_rows) - 1
                mid_1_message_edits = mid_1_message_edits + message_edit_cnt
                if message_edit_cnt >= max_1_message_edits:
                    max_1_message_edits = message_edit_cnt
                    max_edits_message = self.remove_message_tags(edit_rows[len(edit_rows) - 1]['message'])

                replaces_count_edit = 0
                inserts_count_edit = 0
                deletes_count_edit = 0
                for edit_row in edit_rows:
                    if last_version:
                        curr_time = StatusController.datetime_from_str(edit_row['taken_at'], '%Y-%m-%d %H:%M:%S%z')
                        last_time = StatusController.datetime_from_str(last_version['taken_at'], '%Y-%m-%d %H:%M:%S%z')
                        summ_edits_time = summ_edits_time + abs((curr_time - last_time).total_seconds())
                        edits_count = edits_count + 1
                        edit_ratio = self.get_str_difference_ratio(self.remove_message_tags(last_version['message']), self.remove_message_tags(edit_row['message']))
                        edit_ratio_summ = edit_ratio_summ + edit_ratio

                        diff_counts = self.get_str_difference_counts(last_version['message'], edit_row['message'])
                        inserts_count_edit = inserts_count_edit + diff_counts['inserts_count_edit']
                        replaces_count_edit = replaces_count_edit + diff_counts['replaces_count_edit']
                        deletes_count_edit = deletes_count_edit + diff_counts['deletes_count_edit']

                    last_version = edit_row
                edit_ratio_full = self.get_str_difference_ratio(self.remove_message_tags(edit_rows[0]['message']), self.remove_message_tags(last_version['message']))
                if edit_ratio_full >= max_1_message_diff:
                    max_1_message_diff = edit_ratio_full
                    max_changed_message = self.remove_message_tags(edit_rows[len(edit_rows) - 1]['message'])
                message_edit_mid_full_percent = message_edit_mid_full_percent + edit_ratio_full
                message_edit_mid_summ_percent = message_edit_mid_summ_percent + edit_ratio_summ
                message_edit_mid_time_sec = message_edit_mid_time_sec + (summ_edits_time / message_edit_cnt)

                replaces_count_avg = replaces_count_avg + replaces_count_edit
                inserts_count_avg = inserts_count_avg + inserts_count_edit
                deletes_count_avg = deletes_count_avg + deletes_count_edit

                msg_id = edit_rows[0]['message_id']
                if (msg_id in edited_sequence_interrupted) and edited_sequence_interrupted[msg_id]:
                    sequence_interrupted_cnt = sequence_interrupted_cnt + 1

            mid_1_message_edits = mid_1_message_edits / edited_messages_count
            message_edit_mid_full_percent = 100 * message_edit_mid_full_percent / edited_messages_count
            message_edit_mid_summ_percent = 100 * message_edit_mid_summ_percent / edited_messages_count
            message_edit_mid_time_sec = message_edit_mid_time_sec / edited_messages_count
            replaces_count_avg = replaces_count_avg / edited_messages_count
            inserts_count_avg = inserts_count_avg / edited_messages_count
            deletes_count_avg = deletes_count_avg / edited_messages_count
            max_1_message_diff = 100 * max_1_message_diff

        return {
            "edits_count": edits_count,
            "sequence_interrupted_cnt": sequence_interrupted_cnt,
            "edited_messages_count": edited_messages_count,
            "max_1_message_edits": max_1_message_edits,
            "max_1_message_diff_percent": max_1_message_diff,
            "mid_1_message_edits": mid_1_message_edits,
            "message_edit_mid_full_percent": message_edit_mid_full_percent,
            "message_edit_mid_summ_percent": message_edit_mid_summ_percent,
            "message_edit_mid_time_sec": message_edit_mid_time_sec,
            "max_edits_message": max_edits_message,
            "max_changed_message": max_changed_message,
            "replaces_count_avg": replaces_count_avg,
            "inserts_count_avg": inserts_count_avg,
            "deletes_count_avg": deletes_count_avg,
        }
Beispiel #19
0
    async def message_handler(self, event):
        if type(event.original_update) != UpdateNewMessage:
            return
        try:
            await self.init_bot_entity()
            data = event.original_update
            if data.message.from_id == self.bot_entity_id:
                return
            MainHelper().play_notify_sound('notify_when_my_bot_message')
            if data.message.id and data.message.from_id and (
                    data.message.from_id != self.tg_client.me_user_id):
                msg_entity_name = await self.tg_client.get_entity_name(
                    data.message.from_id, 'User')
                if msg_entity_name:
                    print(
                        StatusController.datetime_to_str(datetime.now()) +
                        ' Message to my bot from "' + msg_entity_name + '"')
                    print('<<< ' + str(data.message.message))
                    t_date = StatusController.tg_datetime_to_local_datetime(
                        data.message.date)
                    self.tg_client.add_message_to_db(self.bot_entity_id, 'Bot',
                                                     data.message.from_id,
                                                     self.bot_entity_id,
                                                     data.message.id,
                                                     data.message.message,
                                                     t_date, 0)
            elif data.message.id and data.message.from_id and (
                    data.message.from_id == self.tg_client.me_user_id):
                t_date = StatusController.tg_datetime_to_local_datetime(
                    data.message.date)
                self.tg_client.add_message_to_db(self.bot_entity_id, 'Bot',
                                                 data.message.from_id,
                                                 self.bot_entity_id,
                                                 data.message.id,
                                                 data.message.message, t_date,
                                                 0)
            elif not data.message.id and data.message.from_id:
                t_date = StatusController.now_local_datetime()
                self.tg_client.add_message_to_db(self.bot_entity_id, 'Bot',
                                                 data.message.from_id,
                                                 self.bot_entity_id, None,
                                                 data.message.message, t_date,
                                                 0)
                msg_entity_name = await self.tg_client.get_entity_name(
                    data.message.from_id, 'User')
                if msg_entity_name:
                    print(
                        StatusController.datetime_to_str(datetime.now()) +
                        ' Command to my bot from "' + msg_entity_name + '"')
                    print('<<< ' + str(data.message.message))

            forward_data = None

            if data.message.id:
                bot_chat = await event.get_input_chat()
                if data.message.fwd_from:
                    forward_data = {
                        'from_id': data.message.fwd_from.from_id,
                        'date_from': data.message.fwd_from.date
                    }
            else:
                try:
                    bot_chat = await self.get_input_entity(
                        PeerUser(data.message.from_id))
                except:
                    traceback.print_exc()
                    bot_chat = None
                if not bot_chat:
                    bot_chat = self.tg_client.entity_controller.get_user_bot_chat(
                        data.message.from_id)
            if not bot_chat:
                print("Can't get chat!")
                return
            try:
                ee_name = await self.tg_client.get_entity_name(
                    bot_chat.user_id, 'User')
            except:
                ee_name = str(bot_chat.user_id)
            self.tg_client.entity_controller.add_entity_db_name(
                bot_chat.user_id, 'User', ee_name)
            self.tg_client.entity_controller.save_user_bot_chat(bot_chat)
            if data.message.message == '/start':
                self.tg_client.entity_controller.save_user_bot_last_version(
                    bot_chat.user_id,
                    MainHelper().get_config_float_value(
                        'main', 'actual_version'))
            if data.message.id:
                self.tg_client.bot_controller.set_message_for_user(
                    data.message.from_id, data.message.id, False)
            await self.tg_client.bot_controller.bot_command(
                data.message.message, data.message.from_id, self.bot_entity_id,
                'Bot', forward_data)
        except:
            traceback.print_exc()