def get_callback_tail(event: Union[events.NewMessage.Event, Message, events.CallbackQuery.Event], chat_id: int) -> str: if 0 > chat_id != event.chat_id and event.is_private: chat_id_str, _ = resolve_id(chat_id) return f'%{chat_id_str}' return ''
async def _get_name(self, peer_id): if peer_id is None: return '' name = self._displays.get(peer_id) if name: return name # c = self.dumper.conn.cursor() _, kind = utils.resolve_id(peer_id) if kind == types.PeerUser: row = await db_user.find_one({'id': peer_id}) if row: return f'{row["first_name"] or ""} {row["last_name"] or ""}'.strip( ) elif kind == types.PeerChat: row = await db_user.find_one({'id': peer_id}) if row: return row['title'] elif kind == types.PeerChannel: row = await db_channel.find_one({'id': peer_id}) if row: return row['title'] row = await db_super_group.find_one({'id': peer_id}) if row: return row['title'] return ''
def _get_name(self, peer_id): if peer_id is None: return '' name = self._displays.get(peer_id) if name: return name c = self.dumper.conn.cursor() _, kind = utils.resolve_id(peer_id) if kind == types.PeerUser: row = c.execute( 'SELECT FirstName, LastName FROM User ' 'WHERE ID = ?', (peer_id, )).fetchone() if row: return '{} {}'.format(row[0] or '', row[1] or '').strip() elif kind == types.PeerChat: row = c.execute('SELECT Title FROM Chat ' 'WHERE ID ?', (peer_id, )).fetchone() if row: return row[0] elif kind == types.PeerChannel: row = c.execute('SELECT Title FROM Channel ' 'WHERE ID ?', (peer_id, )).fetchone() if row: return row[0] row = c.execute('SELECT Title FROM Supergroup ' 'WHERE ID ?', (peer_id, )).fetchone() if row: return row[0] return ''
async def get_portal_by_tgid(self, request: web.Request) -> web.Response: err = self.check_authorization(request) if err is not None: return err try: tgid, _ = resolve_id(int(request.match_info["tgid"])) except ValueError: return self.get_error_response(400, "tgid_invalid", "Given chat ID is not valid.") portal = Portal.get_by_tgid(tgid) if not portal: return self.get_error_response(404, "portal_not_found", "Portal to given Telegram chat not found.") user, _ = await self.get_user(request.query.get("user_id", None), expect_logged_in=None, require_puppeting=False) return web.json_response({ "mxid": portal.mxid, "chat_id": get_peer_id(portal.peer), "peer_type": portal.peer_type, "title": portal.title, "about": portal.about, "username": portal.username, "megagroup": portal.megagroup, "can_unbridge": (await portal.can_user_perform(user, "unbridge")) if user else False, })
def get_callback_tail(event: Union[events.NewMessage.Event, Message, events.CallbackQuery.Event], chat_id: int) -> str: if not event.is_private or event.chat.id == chat_id: return '' ori_chat_id, peer_type = resolve_id(chat_id) if peer_type is types.PeerChat: raise ValueError('Old-fashioned group chat is not supported') return f'%{ori_chat_id}' if ori_chat_id < 0 else f'%+{ori_chat_id}'
async def subscribe(event): """Send a message when the command /subscribe is issued.""" # insert chat_id chat_id = event.message.chat.id find = utils.db.user.get_or_none(chat_id=chat_id) user_id = find if not find: # 不存在用户信息 await event.respond('Failed. Please input /start') raise events.StopPropagation text = event.message.text text = text.replace(',', ',') # 替换掉中文逗号 text = regex.sub( '\s*,\s*', ',', text ) # 确保英文逗号间隔中间都没有空格 如 "https://t.me/xiaobaiup, https://t.me/com9ji" splitd = [i for i in regex.split('\s+', text) if i] # 删除空元素 if len(splitd) <= 1: await event.respond( '输入需要订阅的关键字,支持js正则语法:`/[\s\S]*/ig`\n\nInput the keyword that needs to subscribe, support JS regular syntax:`/[\s\S]*/ig`' ) cache.set('status_{}'.format(chat_id), { 'current_status': '/subscribe keywords', 'record_value': text }, expire=5 * 60) #设置5m后过期 elif len(splitd) == 3: command, keywords, channels = splitd result = await join_channel_insert_subscribe( user_id, parse_full_command(command, keywords, channels)) if isinstance(result, str): logger.error('join_channel_insert_subscribe 错误:' + result) await event.respond(result, parse_mode=None) # 提示错误消息 else: msg = '' for key, channel, _chat_id in result: if _chat_id: _chat_id, peer_type = telethon_utils.resolve_id( int(_chat_id)) if not channel: channel = f'<a href="t.me/c/{_chat_id}/-1">{_chat_id}</a>' msg += f'keyword:{key} channel:{channel}\n' if msg: msg = 'success subscribe:\n' + msg text, entities = html.parse(msg) # 解析超大文本 分批次发送 避免输出报错 for text, entities in telethon_utils.split_text( text, entities): await event.respond(text, formatting_entities=entities) #await event.respond('success subscribe:\n'+msg,parse_mode = None) raise events.StopPropagation
def delete_all_conversations(self): all_peers = [ utils.resolve_id(x[0]) for x in self.client.session.entities.get_input_list() ] for peer in all_peers: log.debug("Deleting conversation with {}...".format(peer)) try: input_entity = self.client.session.entities.get_input_entity( peer[0]) self.client( DeleteHistoryRequest(input_entity, max_id=9999999999999999)) except: log.error("Couldn't find {}".format(peer[0]))
async def get_portal_by_tgid(self, request: web.Request) -> web.Response: err = self.check_authorization(request) if err is not None: return err try: tgid, _ = resolve_id(int(request.match_info["tgid"])) except ValueError: return self.get_error_response(400, "tgid_invalid", "Given chat ID is not valid.") portal = Portal.get_by_tgid(tgid) if not portal: return self.get_error_response(404, "portal_not_found", "Portal to given Telegram chat not found.") return await self._get_portal_response(UserID(request.query.get("user_id", "")), portal)
async def get_input_entity(self, key): try: if key.SUBCLASS_OF_ID in (0xc91c90b6, 0xe669bf46, 0x40f202fd): # hex(crc32(b'InputPeer', b'InputUser' and b'InputChannel')) # We already have an Input version, so nothing else required return key # Try to early return if this key can be casted as input peer return utils.get_input_peer(key) except (AttributeError, TypeError): # Not a TLObject or can't be cast into InputPeer if isinstance(key, types.TLObject): key = utils.get_peer_id(key) exact = True else: exact = not isinstance(key, int) or key < 0 result = None if isinstance(key, str): phone = utils.parse_phone(key) if phone: result = await self.get_entity_rows_by_phone(phone) else: username, invite = utils.parse_username(key) if username and not invite: result = await self.get_entity_rows_by_username(username) else: tup = utils.resolve_invite_link(key)[1] if tup: result = await self.get_entity_rows_by_id(tup, exact=False) elif isinstance(key, int): result = await self.get_entity_rows_by_id(key, exact) if not result and isinstance(key, str): result = await self.get_entity_rows_by_name(key) if result: entity_id, entity_hash = result # unpack resulting tuple entity_id, kind = utils.resolve_id(entity_id) # removes the mark and returns type of entity if kind == types.PeerUser: return types.InputPeerUser(entity_id, entity_hash) elif kind == types.PeerChat: return types.InputPeerChat(entity_id) elif kind == types.PeerChannel: return types.InputPeerChannel(entity_id, entity_hash) else: raise ValueError('Could not find input entity with key ', key)
async def handler(update): #prints peer ids of channels result = await client.get_dialogs() print("\n List of channels:") for p in result: print(str(utils.resolve_id(p.id)[0]) + ": " + p.name) try: if str(update.message.to_id.channel_id) in channels: m = update.message media = m.media reply_msg = await m.get_reply_message() if reply_msg is None: text = "{}\n".format(m.message) else: text = "```REPLIED_TO:\n{}```{}\n".format( reply_msg.message, m.message) if media is not None and utils.get_extension(media) == '.jpg': logger.info("Will download image") download_res = await client.download_media( media, './downloads/') logger.info("Download done: {}".format(download_res)) url = img_cli.upload_from_path(download_res, anon=True)['link'] text += url + "\n" os.remove(download_res) logger.debug("File deleted") if not text == '': date = m.date.astimezone(timezone('Asia/Ulaanbaatar')) text += "`" + date.strftime("%Y-%m-%d %H:%M:%S GMT%Z") + "`\n" text += "==================================\n" msg = Webhook(channels[str(m.to_id.channel_id)], msg=text) msg.post() logger.info("Relaying Message from Channel ID: {}".format( update.message.to_id.channel_id)) else: logger.debug('Ignoring empty message: {}'.format( update.message)) else: logger.info("Ignoring Message from Channel: {}: {}".format( update.message.to_id.channel_id, update.message.to_id.channel_name)) except: logger.debug('Exception occurred while handling:\n') logger.debug(update)
async def set_not_afk(event): current_message = event.message.message if ".afk" not in current_message and "yes" in borg.storage.USER_AFK: # pylint:disable=E0602 borg.storage.USER_AFK = {} # pylint:disable=E0602 borg.storage.afk_time = None # pylint:disable=E0602 # pylint:disable=E0602 for chat_id in borg.storage.last_afk_message: await borg.storage.last_afk_message[chat_id].delete() borg.storage.last_afk_message = {} # pylint:disable=E0602 recvd_messages = "You received the following messages: \n" # pylint:disable=E0602 for chat_id in borg.storage.recvd_messages: # pylint:disable=E0602 current_message = borg.storage.recvd_messages[chat_id] user_id = current_message.from_id message_id = current_message.id # check_condition = str(chat_id).startswith("-") # chat_id, _ = resolve_id(chat_id) # https://t.me/DeepLink/21 # if not check_condition: # recvd_messages += "👉 tg://openmessage?chat_id={}&message_id={} \n".format(chat_id, message_id) # else: # recvd_messages += "👉 https://t.me/c/{}/{} \n\n".format(chat_id, message_id) chat_id, _ = resolve_id(chat_id) recvd_messages += "👉 tg://openmessage?chat_id={}&message_id={} \n".format(chat_id, message_id) try: if recvd_messages != "You received the following messages: \n": await borg.send_message( # pylint:disable=E0602 Config.PRIVATE_GROUP_BOT_API_ID, # pylint:disable=E0602 recvd_messages, link_preview=False ) await borg.send_message( # pylint:disable=E0602 Config.PRIVATE_GROUP_BOT_API_ID, # pylint:disable=E0602 "Set AFK mode to False" ) except Exception as e: # pylint:disable=C0103,W0703 await borg.send_message( # pylint:disable=E0602 event.chat_id, "Please set `PRIVATE_GROUP_BOT_API_ID` " + \ "for the proper functioning of afk functionality " + \ "in @UniBorg\n\n `{}`".format(str(e)), reply_to=event.message.id, silent=True ) borg.storage.recvd_messages = {}
def get_entity(self, context_id, at_date=None): """ Return the entity (user, chat or channel) corresponding to this context ID, at the given date (like all the specific methods). Context ID must be marked in the Bot API style, as with get_messages_from_context. """ peer_type = utils.resolve_id(context_id)[1] if peer_type == types.PeerUser: return self.get_user(context_id, at_date=at_date) elif peer_type == types.PeerChat: return self.get_chat(context_id, at_date=at_date) elif peer_type == types.PeerChannel: supergroup = self.get_supergroup(context_id, at_date=at_date) if not supergroup: return self.get_channel(context_id, at_date=at_date) return supergroup else: raise ValueError('Invalid ID {} given'.format(context_id))
async def set_not_afk(event): current_message = event.message.message await event.edit("**I'm no longer AFK**") if Config.COMMAND_HAND_LER + "afk" not in current_message and "yes" in borg.storage.USER_AFK: # pylint:disable=E0602 borg.storage.USER_AFK = {} # pylint:disable=E0602 borg.storage.afk_time = None # pylint:disable=E0602 # pylint:disable=E0602 for chat_id in borg.storage.last_afk_message: await borg.storage.last_afk_message[chat_id].delete() borg.storage.last_afk_message = {} # pylint:disable=E0602 recvd_messages = "You received the following messages: \n" # pylint:disable=E0602 for chat_id in borg.storage.recvd_messages: # pylint:disable=E0602 current_message = borg.storage.recvd_messages[chat_id] user_id = current_message.from_id message_id = current_message.id chat_id, _ = resolve_id(chat_id) if isinstance(_, types.PeerUser): recvd_messages += f"👉 [{chat_id}](tg://user?id={chat_id})" # sadly, there is no way to goto a particular message by a user, # after the 5.5 Android update else: recvd_messages += f"👉 https://t.me/c/{chat_id}/{message_id} \n" try: if recvd_messages != "You received the following messages: \n": await borg.send_message( # pylint:disable=E0602 Config.PRIVATE_GROUP_BOT_API_ID, # pylint:disable=E0602 recvd_messages, link_preview=False ) await borg.send_message( # pylint:disable=E0602 Config.PRIVATE_GROUP_BOT_API_ID, # pylint:disable=E0602 "Set AFK mode to False" ) except Exception as e: # pylint:disable=C0103,W0703 await borg.send_message( # pylint:disable=E0602 event.chat_id, "Please set `PRIVATE_GROUP_BOT_API_ID` " + \ "for the proper functioning of afk functionality " + \ "in @UniBorg\n\n `{}`".format(str(e)), reply_to=event.message.id, silent=True ) borg.storage.recvd_messages = {}
async def test_update_info_group_user(helper, client, bot_group, channel, slave, bot_id, chat_type, alias, avatar): chat = slave.get_chat_by_criteria(chat_type=chat_type, alias=alias, avatar=avatar) # Set bot as admin if needed if await is_bot_admin(client, bot_id, bot_group): await client.edit_admin(bot_group, bot_id, change_info=True, is_admin=True, delete_messages=False) with link_chats(channel, (chat, ), bot_group): await client.send_message(bot_group, "/update_info") title = (await helper.wait_for_event(in_chats(bot_group) & new_title)).new_title if alias: assert chat.alias in title else: assert chat.name in title if avatar: await helper.wait_for_event(in_chats(bot_group) & new_photo) if chat_type == "GroupChat": # Get group description bot_group_t, peer_type = resolve_id(bot_group) if peer_type == PeerChannel: group: ChatFull = await client( GetFullChannelRequest(bot_group_t)) else: group: ChatFull = await client(GetFullChatRequest(bot_group_t)) desc = group.full_chat.about chats_found = sum( int((i.name in desc) and # Original name is found, and (i.alias is None or i.alias in desc ) # alias is found too if available ) for i in chat.members) assert len(chat.members) >= 5 assert chats_found >= 5, f"At least 5 members shall be found in the description: {desc}"
def iter_resume_entities(self, context_id): """ Returns an iterator over the entities that need resuming for the given context_id. Note that the entities are *removed* once the iterator is consumed completely. """ c = self.conn.execute("SELECT ID, AccessHash FROM ResumeEntity " "WHERE ContextID = ?", (context_id,)) row = c.fetchone() while row: kind = resolve_id(row[0])[1] if kind == types.PeerUser: yield types.InputPeerUser(row[0], row[1]) elif kind == types.PeerChat: yield types.InputPeerChat(row[0]) elif kind == types.PeerChannel: yield types.InputPeerChannel(row[0], row[1]) row = c.fetchone() c.execute("DELETE FROM ResumeEntity WHERE ContextID = ?", (context_id,))
async def get_resume_entities(self, context_id): """ Returns an iterator over the entities that need resuming for the given context_id. Note that the entities are *removed* once the iterator is consumed completely. """ rows = db_resume_entity.find({'context_id': context_id}) count = await db_resume_entity.count_documents( {'context_id': context_id}) logger.info(f'加载了【{count}】条待恢复数据') result = [] async for row in rows: kind = resolve_id(row['id'])[1] if kind == types.PeerUser: result.append( types.InputPeerUser(row['id'], row['access_hash'])) elif kind == types.PeerChat: result.append(types.InputPeerChat(row['id'])) elif kind == types.PeerChannel: result.append( types.InputPeerChannel(row['id'], row['access_hash'])) await db_resume_entity.delete_many({'context_id': context_id}) return result
def get_channel_url(event_chat_username, event_chat__id): """ 获取频道/群组 url 优先返回chat_id的url https://docs.telethon.dev/en/latest/concepts/chats-vs-channels.html#converting-ids Args: event_chat_username (str): 频道名地址 e.g. tianfutong event_chat__id (str): 频道的非官方id。 e.g. -1001630956637 """ # event.is_private 无法判断 # 判断私有频道 # is_private = True if not event_chat_username else False host = 'https://t.me/' url = '' if event_chat__id: real_id, peer_type = telethon_utils.resolve_id( int(event_chat__id)) # 转换为官方真实id url = f'{host}c/{real_id}/' elif event_chat_username: url = f'{host}{event_chat_username}/' return url
async def join_channel_insert_subscribe(user_id, keyword_channel_list): """ 加入频道 且 写入订阅数据表 支持传入频道id Raises: events.StopPropagation: [description] """ res = [] # 加入频道 for k, c in keyword_channel_list: username = '' chat_id = '' try: if c.lstrip('-').isdigit(): # 整数 real_id, peer_type = telethon_utils.resolve_id(int(c)) channel_entity = await client.get_entity(real_id) chat_id = telethon_utils.get_peer_id( PeerChannel(real_id)) # 转换为marked_id # channel_entity.title else: # 传入普通名称 channel_entity = await client.get_entity( c ) # get_entity频繁请求会有报错 A wait of 19964 seconds is required (caused by ResolveUsernameRequest) chat_id = telethon_utils.get_peer_id( PeerChannel(channel_entity.id)) # 转换为marked_id if channel_entity.username: username = channel_entity.username if channel_entity and not channel_entity.left: # 已加入该频道 res.append((k, username, chat_id)) else: await client(JoinChannelRequest(channel_entity)) res.append((k, username, chat_id)) except Exception as _e: # 不存在的频道 logger.error(f'{c} JoinChannelRequest ERROR:{_e}') # 查询本地记录是否存在 channel_name_or_chat_id = regex.sub( r'^(?:http[s]?://)?t.me/(?:c/)?', '', c) # 清洗多余信息 find = utils.db.connect.execute_sql( 'select 1 from user_subscribe_list where status = 0 and (channel_name = ? or chat_id = ?)', (channel_name_or_chat_id, channel_name_or_chat_id)).fetchall() logger.warning( f'{c} JoinChannelRequest fail. cache join. cache find count: {len(find)}' ) if find: if len(find) > 1: # 存在1条以上的记录 则直接返回加入成功 if channel_name_or_chat_id.lstrip('-').isdigit(): # 整数 res.append((k, '', channel_name_or_chat_id)) else: res.append((k, channel_name_or_chat_id, '')) else: return '无法使用该频道:{}\n\nChannel error, unable to use: {}'.format( c, _e) else: return '无法使用该频道:{}\n\nChannel error, unable to use: {}'.format( c, _e) # 写入数据表 result = [] for keyword, channel_name, _chat_id in res: find = utils.db.user_subscribe_list.get_or_none( **{ 'user_id': user_id, 'keywords': keyword, 'channel_name': channel_name, 'chat_id': _chat_id, }) if find: re_update = utils.db.user_subscribe_list.update(status=0).where( utils.User_subscribe_list.id == find.id) #更新状态 re_update = re_update.execute() # 更新成功返回1,不管是否重复执行 if re_update: result.append((keyword, channel_name, _chat_id)) else: insert_res = utils.db.user_subscribe_list.create( **{ 'user_id': user_id, 'keywords': keyword, 'channel_name': channel_name.replace('@', ''), 'create_time': datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S'), 'chat_id': _chat_id }) if insert_res: result.append((keyword, channel_name, _chat_id)) return result
async def handler(update): global temp_completed_path global FOLDER_GROUP try: real_id = get_peer_id(update.message.peer_id) CID, peer_type = resolve_id(real_id) if update.message.from_id is not None: logger.info( "USER ON GROUP => U:[%s]G:[%s]M:[%s]" % (update.message.from_id.user_id, CID, update.message.message)) if update.message.media is not None and (not AUTHORIZED_USER or CID in usuarios): if FOLDER_GROUP != update.message.date: logger.info( "FOLDER_GROUP => [%s][%s][%s]" % (FOLDER_GROUP, update.message.date, temp_completed_path)) temp_completed_path = '' if update.message.media is not None and (not AUTHORIZED_USER or CID in usuarios): file_name = 'NONAME' if isinstance(update.message.media, types.MessageMediaPhoto): file_name = '{}{}'.format(update.message.media.photo.id, get_extension(update.message.media)) logger.info("MessageMediaPhoto [%s]" % file_name) elif any(x in update.message.message for x in youtube_list): file_name = 'YOUTUBE VIDEO' else: attributes = update.message.media.document.attributes for attr in attributes: if isinstance(attr, types.DocumentAttributeFilename): file_name = attr.file_name elif update.message.message: file_name = re.sub(r'[^A-Za-z0-9 -!\[\]\(\)]+', ' ', update.message.message) mensaje = 'DOWNLOAD IN QUEUE [%s] [%s] => [%s]' % (time.strftime( '%d/%m/%Y %H:%M:%S', time.localtime()), file_name, temp_completed_path) logger.info(mensaje) message = await update.reply('Download in queue...') await queue.put([update, message, temp_completed_path]) elif not AUTHORIZED_USER or CID in usuarios: if update.message.message == '/help': message = await update.reply(HELP) await queue.put([update, message]) elif update.message.message == '/version': message = await update.reply(VERSION) await queue.put([update, message, temp_completed_path]) elif update.message.message == '/alive': message = await update.reply('Keep-Alive') await queue.put([update, message, temp_completed_path]) elif update.message.message == '/me' or update.message.message == '/id': message = await update.reply('id: {}'.format(CID)) await queue.put([update, message, temp_completed_path]) logger.info('me :[%s]' % (CID)) else: time.sleep(2) if '/folder' in update.message.message: folder = update.message.message FOLDER_GROUP = update.message.date temp_completed_path = os.path.join( TG_DOWNLOAD_PATH, 'completed', folder.replace('/folder ', '') ) # SI VIENE EL TEXTO '/folder NAME_FOLDER' ESTE CREARÁ UNA CARPETA Y METERÁ ADENTRO TODOS LOS ARCHIVOS A CONTINUACION logger.info("DOWNLOAD FILE IN :[%s]", temp_completed_path) elif ((update.message.message).startswith('/sendfiles')): msg = await update.reply('Sending files...') create_directory(os.path.join(download_path, 'sendFiles')) ignored = {"*._process"} basepath = os.path.join(download_path, 'sendFiles') sending = 0 for root, subFolder, files in os.walk(basepath): subFolder.sort() files.sort() for item in files: if item.endswith('_process'): #skip directories continue sending += 1 fileNamePath = str(os.path.join(root, item)) logger.info("SEND FILE :[%s]", fileNamePath) await msg.edit('Sending {}...'.format(item)) loop = asyncio.get_event_loop() task = loop.create_task( tg_send_file(CID, fileNamePath, item)) download_result = await asyncio.wait_for( task, timeout=maximum_seconds_per_download) #message = await tg_send_file(fileNamePath) shutil.move(fileNamePath, fileNamePath + "_process") await msg.edit('{} files submitted'.format(sending)) logger.info("FILES SUBMITTED:[%s]", sending) elif ((update.message.message).startswith('#')): folder = update.message.message FOLDER_GROUP = update.message.date temp_completed_path = os.path.join( TG_DOWNLOAD_PATH, 'completed', folder.replace('#', '') ) # SI VIENE EL TEXTO '/folder NAME_FOLDER' ESTE CREARÁ UNA CARPETA Y METERÁ ADENTRO TODOS LOS ARCHIVOS A CONTINUACION logger.info("DOWNLOAD FILE IN :[%s]", temp_completed_path) elif update.message.message == '/me' or update.message.message == '/id': logger.info('UNAUTHORIZED USER: %s ', CID) message = await update.reply( 'UNAUTHORIZED USER: %s \n add this ID to TG_AUTHORIZED_USER_ID' % CID) except Exception as e: message = await update.reply('ERROR: ' + str(e)) logger.info('EXCEPTION USER: %s ', str(e))
def get_share_id(chat_id: int) -> int: return resolve_id(chat_id)[0]
async def join_channel_insert_subscribe(user_id, keyword_channel_list): """ 加入频道 且 写入订阅数据表 支持传入频道id Raises: events.StopPropagation: [description] """ res = [] # 加入频道 for k, c in keyword_channel_list: username = '' chat_id = '' try: is_chat_invite_link = False if c.lstrip('-').isdigit(): # 整数 real_id, peer_type = telethon_utils.resolve_id(int(c)) channel_entity = None # 不请求channel_entity # channel_entity = await client_get_entity(real_id, time.time() // 86400 ) chat_id = telethon_utils.get_peer_id( PeerChannel(real_id)) # 转换为marked_id else: # 传入普通名称 if regex.search('^\+', c): # 邀请链接 is_chat_invite_link = True c = c.lstrip('+') channel_entity = None chat_id = '' chatinvite = await resolve_invit_hash(c) if chatinvite: chat_id, chat_title, channel_entity = chatinvite else: channel_entity = await client_get_entity( c, time.time() // 86400) chat_id = telethon_utils.get_peer_id( PeerChannel(channel_entity.id)) # 转换为marked_id if channel_entity and hasattr(channel_entity, 'username'): username = channel_entity.username if channel_entity and not channel_entity.left: # 已加入该频道 logger.warning( f'user_id:{user_id}触发检查 已加入该私有频道:{chat_id} invite_hash:{c}' ) res.append((k, username, chat_id)) else: if is_chat_invite_link: # 通过邀请链接加入私有频道 logger.info(f'user_id:{user_id}通过邀请链接加入私有频道{c}') await client(ImportChatInviteRequest(c)) chatinvite = await resolve_invit_hash(c) if chatinvite: chat_id, chat_title, channel_entity = chatinvite res.append((k, username, chat_id)) else: await client(JoinChannelRequest(channel_entity or chat_id)) res.append((k, username, chat_id)) except errors.InviteHashExpiredError as _e: logger.error(f'{c} InviteHashExpiredError ERROR:{_e}') return f'无法使用该频道邀请链接:{c}\nLink has expired.' except errors.UserAlreadyParticipantError as _e: # 重复加入私有频道 logger.warning(f'{c} UserAlreadyParticipantError ERROR:{_e}') return f'无法使用该频道邀请链接:UserAlreadyParticipantError' except Exception as _e: # 不存在的频道 logger.error(f'{c} JoinChannelRequest ERROR:{_e}') # 查询本地记录是否存在 channel_name_or_chat_id = regex.sub( r'^(?:http[s]?://)?t.me/(?:c/)?', '', c) # 清洗多余信息 find = utils.db.connect.execute_sql( 'select 1 from user_subscribe_list where status = 0 and (channel_name = ? or chat_id = ?)', (channel_name_or_chat_id, channel_name_or_chat_id)).fetchall() logger.warning( f'{c} JoinChannelRequest fail. cache join. cache find count: {len(find)}' ) if find: if len(find) > 1: # 存在1条以上的记录 则直接返回加入成功 if channel_name_or_chat_id.lstrip('-').isdigit(): # 整数 res.append((k, '', channel_name_or_chat_id)) else: res.append((k, channel_name_or_chat_id, '')) else: return '无法使用该频道:{}\n\nChannel error, unable to use: {}'.format( c, _e) else: return '无法使用该频道:{}\n\nChannel error, unable to use: {}'.format( c, _e) # 写入数据表 result = [] for keyword, channel_name, _chat_id in res: if not channel_name: channel_name = '' find = utils.db.user_subscribe_list.get_or_none( **{ 'user_id': user_id, 'keywords': keyword, 'channel_name': channel_name, 'chat_id': _chat_id, }) if find: re_update = utils.db.user_subscribe_list.update(status=0).where( utils.User_subscribe_list.id == find.id) #更新状态 re_update = re_update.execute() # 更新成功返回1,不管是否重复执行 if re_update: result.append((keyword, channel_name, _chat_id)) else: insert_res = utils.db.user_subscribe_list.create( **{ 'user_id': user_id, 'keywords': keyword, 'channel_name': channel_name.replace('@', ''), 'create_time': datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S'), 'chat_id': _chat_id }) if insert_res: result.append((keyword, channel_name, _chat_id)) return result
from telethon import events from telethon.errors.rpcerrorlist import MessageDeleteForbiddenError from telethon.tl.types import PeerChannel from telethon.utils import resolve_id CHATS = [-1001109500936, -1001200633650] PEER_CHATS = [resolve_id(i)[0] for i in CHATS] async def init(bot): @bot.on(events.NewMessage(chats=CHATS)) async def handler(event): if isinstance(event.from_id, PeerChannel): if event.from_id.channel_id not in PEER_CHATS: try: await event.delete() except MessageDeleteForbiddenError: pass
async def common(event): """Echo the user message.""" chat_id = event.message.chat.id text = event.text text = text.replace(',', ',') # 替换掉中文逗号 text = regex.sub( '\s*,\s*', ',', text ) # 确保英文逗号间隔中间都没有空格 如 "https://t.me/xiaobaiup, https://t.me/com9ji" find = cache.get('status_{}'.format(chat_id)) if find: # 执行订阅 if find['current_status'] == '/subscribe keywords': # 当前输入关键字 await event.respond( '输入需要订阅的频道url或者name:\n\nEnter the url or name of the channel to subscribe to:' ) cache.set('status_{}'.format(chat_id), { 'current_status': '/subscribe channels', 'record_value': find['record_value'] + ' ' + text }, expire=5 * 60) # 记录输入的关键字 raise events.StopPropagation elif find['current_status'] == '/subscribe channels': # 当前输入频道 full_command = find['record_value'] + ' ' + text splitd = [i for i in regex.split('\s+', full_command) if i] # 删除空元素 if len(splitd) != 3: await event.respond( '关键字请不要包含空格 可使用正则表达式解决\n\nThe keyword must not contain Spaces.' ) raise events.StopPropagation command, keywords, channels = splitd user_id = utils.db.user.get_or_none(chat_id=chat_id) result = await join_channel_insert_subscribe( user_id, parse_full_command(command, keywords, channels)) if isinstance(result, str): await event.respond(result, parse_mode=None) # 提示错误消息 else: msg = '' for key, channel, _chat_id in result: if _chat_id: _chat_id, peer_type = telethon_utils.resolve_id( int(_chat_id)) msg += 'keyword:{} channel:{}\n'.format( key, (channel if channel else f't.me/c/{_chat_id}')) if msg: await event.respond('success subscribe:\n' + msg, parse_mode=None) cache.delete('status_{}'.format(chat_id)) raise events.StopPropagation #取消订阅 elif find['current_status'] == '/unsubscribe keywords': # 当前输入关键字 await event.respond( '输入需要**取消订阅**的频道url或者name:\n\nEnter the url or name of the channel where ** unsubscribe **is required:' ) cache.set('status_{}'.format(chat_id), { 'current_status': '/unsubscribe channels', 'record_value': find['record_value'] + ' ' + text }, expire=5 * 60) # 记录输入的关键字 raise events.StopPropagation elif find['current_status'] == '/unsubscribe channels': # 当前输入频道 full_command = find['record_value'] + ' ' + text splitd = [i for i in regex.split('\s+', full_command) if i] # 删除空元素 if len(splitd) != 3: await event.respond( '关键字请不要包含空格 可使用正则表达式解决\n\nThe keyword must not contain Spaces.' ) raise events.StopPropagation command, keywords, channels = splitd user_id = utils.db.user.get_or_none(chat_id=chat_id) result = update_subscribe( user_id, parse_full_command(command, keywords, channels)) # msg = '' # for key,channel in result: # msg += '{},{}\n'.format(key,channel) # if msg: # await event.respond('success:\n'+msg,parse_mode = None) await event.respond('success unsubscribe..') cache.delete('status_{}'.format(chat_id)) raise events.StopPropagation elif find['current_status'] == '/unsubscribe_id ids': # 当前输入订阅id splitd = text.strip().split(',') user_id = utils.db.user.get_or_none(chat_id=chat_id) result = [] for i in splitd: if not i.isdigit(): continue i = int(i) re_update = utils.db.user_subscribe_list.update( status=1).where( utils.User_subscribe_list.id == i, utils.User_subscribe_list.user_id == user_id) #更新状态 re_update = re_update.execute() # 更新成功返回1,不管是否重复执行 if re_update: result.append(i) await event.respond('success unsubscribe id:{}'.format( result if result else 'None')) raise events.StopPropagation
async def worker(name): while True: # Esperando una unidad de trabajo. queue_item = await queue.get() update = queue_item[0] message = queue_item[1] FOLDER_TO_GROUP = queue_item[2] if queue_item[2] else '' real_id = get_peer_id(update.message.peer_id) CID, peer_type = resolve_id(real_id) sender = await update.get_sender() username = sender.username # Comprobación de usuario if AUTHORIZED_USER and CID not in usuarios: logger.info('USUARIO: %s NO AUTORIZADO', CID) continue ### file_path = tmp_path file_name = 'FILENAME' if isinstance(update.message.media, types.MessageMediaPhoto): file_name = '{}{}'.format(update.message.media.photo.id, get_extension(update.message.media)) elif any(x in update.message.message for x in youtube_list): try: url = update.message.message logger.info(f'INIT DOWNLOADING VIDEO YOUTUBE [{url}] ') await youtube_download(url, update, message) logger.info(f'FINIT DOWNLOADING VIDEO YOUTUBE [{url}] ') queue.task_done() continue except Exception as e: logger.info('ERROR: %s DOWNLOADING YT: %s' % (e.__class__.__name__, str(e))) await message.edit('Error!') message = await message.edit('ERROR: %s DOWNLOADING YT: %s' % (e.__class__.__name__, str(e))) queue.task_done() continue else: attributes = update.message.media.document.attributes for attr in attributes: if isinstance(attr, types.DocumentAttributeFilename): file_name = attr.file_name elif update.message.message: file_name = re.sub(r'[^A-Za-z0-9 -!\[\]\(\)]+', ' ', update.message.message) else: file_name = time.strftime('%Y%m%d %H%M%S', time.localtime()) file_name = '{}{}'.format( update.message.media.document.id, get_extension(update.message.media)) file_path = os.path.join(file_path, file_name) _download_path, _complete_path = getDownloadPath(file_name, CID) logger.info( f"getDownloadPath FILE [{file_name}] to [{_download_path}]") await message.edit( f'Downloading {file_name} \ndownload in:\n{_download_path}') #time.sleep(1) logger.info('Downloading... ') mensaje = 'STARTING DOWNLOADING %s [%s] BY [%s]' % (time.strftime( '%d/%m/%Y %H:%M:%S', time.localtime()), file_path, (CID)) logger.info(mensaje) try: loop = asyncio.get_event_loop() if (TG_PROGRESS_DOWNLOAD == True or TG_PROGRESS_DOWNLOAD == 'True'): task = loop.create_task( client.download_media(update.message, file_path, progress_callback=lambda x, y: callback(x, y, file_path, file_name, message, _download_path))) else: task = loop.create_task( client.download_media(update.message, file_path)) download_result = await asyncio.wait_for( task, timeout=maximum_seconds_per_download) end_time = time.strftime('%d/%m/%Y %H:%M:%S', time.localtime()) end_time_short = time.strftime('%H:%M', time.localtime()) filename = os.path.split(download_result)[1] if FOLDER_TO_GROUP: final_path = os.path.join(FOLDER_TO_GROUP, filename) create_directory(FOLDER_TO_GROUP) os.chmod(FOLDER_TO_GROUP, 0o777) else: _path, final_path = getDownloadPath(filename, CID) create_directory(_path) ###### logger.info("RENAME/MOVE [%s] [%s]" % (download_result, final_path)) #create_directory(completed_path) shutil.move(download_result, final_path) os.chmod(final_path, 0o666) if TG_UNZIP_TORRENTS: if zipfile.is_zipfile(final_path): with zipfile.ZipFile(final_path, 'r') as zipObj: for fileName in zipObj.namelist(): if fileName.endswith('.torrent'): zipObj.extract(fileName, download_path_torrent) logger.info("UNZIP TORRENTS [%s] to [%s]" % (fileName, download_path_torrent)) ###### mensaje = 'DOWNLOAD FINISHED %s [%s] => [%s]' % ( end_time, file_name, final_path) logger.info(mensaje) await message.edit('Downloading finished:\n%s \nIN: %s\nat %s' % (file_name, _path, end_time_short)) except asyncio.TimeoutError: logger.info('[%s] Time exceeded %s' % (file_name, time.strftime('%d/%m/%Y %H:%M:%S', time.localtime()))) await message.edit('Error!') message = await update.reply( 'ERROR: Time exceeded downloading this file') except Exception as e: logger.critical(e) logger.info('[EXCEPCION]: %s' % (str(e))) logger.info('[%s] Excepcion %s' % (file_name, time.strftime('%d/%m/%Y %H:%M:%S', time.localtime()))) await message.edit('Error!') message = await update.reply('ERROR: %s downloading : %s' % (e.__class__.__name__, str(e))) # Unidad de trabajo terminada. queue.task_done()