def scrap_usernames(client, link, aggressive=True): q = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '`', '~', '!', '@', '#', '$', '%', '^', '&', '*', '(', ')', '-', '_', '+', '=', '[', '{', '}', ']', '|', ':', ';', '"', ',', '<', '.', '>', '/', '?'] channel = client.get_entity(link) all_usernames = set() if not isinstance(channel, Channel): raise Exception("Invalid Channel link/username provided") count = client.get_participants(channel, 0).total log.warning("\n\n********Preparing Group '{} ({})' with {} members for Scraping {}".format(channel.title, channel.id, count, ("Aggressively" if count > 10000 and aggressive else ""))) if count > 10000 and aggressive: for x in q: offset = 0 limit = 100 block = 1 while True: try: participants = client(GetParticipantsRequest(channel, ChannelParticipantsSearch(x), offset, limit, 0)) log.warning("{}: Block: {}, Capacity: {}, Count: {}, All: {}, Offset: {}".format(x, block, participants.count, len(participants.users), len(all_usernames), offset)) block += 1 if not participants.users: break for u in participants.users: all_usernames.add(u.username) offset += len(participants.users) except ChatAdminRequiredError as err: offset += 1 log.warning(err) log.warning(channel.stringify()) sleep(1) else: offset = 0 limit = 100 block = 1 while True: try: participants = client(GetParticipantsRequest(channel, ChannelParticipantsSearch(''), offset, limit, 0)) log.warning("Block: {}, Capacity: {}, Count: {}, All: {}, Offset: {}".format(block, count, len(participants.users), len(all_usernames), offset)) block += 1 if not participants.users: break for u in participants.users: all_usernames.add(u.username) offset += len(participants.users) except (TypeError, ChatAdminRequiredError) as err: offset += 1 log.error(err) log.error(channel.stringify()) sleep(1) return all_usernames
async def getMembers(members_file, channel,client): offset_user = 0 # номер участника, с которого начинается считывание limit_user = 100 # максимальное число записей, передаваемых за один раз all_participants = [] # список всех участников канала filter_user = ChannelParticipantsSearch('') while True: participants = await client(GetParticipantsRequest(channel, filter_user, offset_user, limit_user, hash=0)) if not participants.users: break all_participants.extend(participants.users) offset_user += len(participants.users) all_users = [] # список словарей с интересующими параметрами участников канала for participant in all_participants: if participant.bot == False: print(Fore.GREEN+f'[ ! ] Получен пользователь id{id}'+Style.RESET_ALL) all_users.append({"id": participant.id, "first_name": participant.first_name, "last_name": participant.last_name, "user": participant.username, "phone": participant.phone, "is_bot": participant.bot, 'access_hash': participant.access_hash}) with open(members_file,'w') as f: json.dump(all_users,f) print('Готово.') time.sleep(3)
def getMembers(client, dialog_name, type): offset = 0 limit = 1000 valid_members = [] entity = getEntity(client, dialog_name, type) if entity == None: return [], 0 if type == Channel: members = client( channels.GetParticipantsRequest( channel=entity, filter=ChannelParticipantsSearch(''), offset=offset, limit=limit, hash=0)) for user in members.users: if not user.bot: valid_members.append(user.username) elif type == Chat: members = client.get_participants(entity) for member in members: if not member.bot: valid_members.append(member.username) return valid_members, len(valid_members)
async def dump_all_participants(channel): offset_user = 0 limit_user = 100 all_participants = [] filter_user = ChannelParticipantsSearch('') while True: participants = await client( GetParticipantsRequest(channel, filter_user, offset_user, limit_user, hash=0)) if not participants.users: break all_participants.extend(participants.users) offset_user += len(participants.users) all_users_details = [] for participant in all_participants: all_users_details.append({ "id": participant.id, "first_name": participant.first_name, "last_name": participant.last_name, "user": participant.username, "phone": participant.phone, "is_bot": participant.bot }) with open('channel_users.json', 'w', encoding='utf8') as f: json.dump(all_users_details, f, ensure_ascii=False)
def parse_users(k): """ Search and filter users by letter of the alphabet For example k = "a" """ offset = 0 while True: participants = client(GetParticipantsRequest(channel=channel, filter=ChannelParticipantsSearch(k), offset=offset, limit=limit, hash=0)) if not participants.users: break for user in participants.users: user_string = f'{user.id};{user.first_name};{user.last_name};{user.username}' try: if user.deleted is True or user.first_name == "Deleted" and user.last_name == "Account": deleted_accounts.append(user_string.replace("None", "-")) continue elif user.username is None and config["default"]["with_username_only"] == 'true': print(f'Skip user without username --> {user.id} {user.first_name} {user.last_name}') continue elif user.first_name[0].lower() or user.last_name[0].lower() in queryKey: if user.bot is True: bots.append(user_string.replace("None", "-")) else: all_participants.append(user_string.replace("None", "-")) except Exception as e: pass offset += len(participants.users)
def isUserJoined(self, userID, channelName): try: LIMIT = 200 channel = self.client(ResolveUsernameRequest(channelName)).chats[0] offset = 0 output = [] while True: participants = self.client( GetParticipantsRequest(channel, ChannelParticipantsSearch(''), offset, LIMIT, hash=0)) if not participants.users: break offset += len(participants.users) for user in participants.users: if userID == user.id: return True return False except Exception as e: return 0
async def dump_all_participants(channel): # """Записывает json-файл с информацией о всех участниках канала/чата""" offset_user = 0 # номер участника, с которого начинается считывание limit_user = 100 # максимальное число записей, передаваемых за один раз all_participants = [] # список всех участников канала filter_user = ChannelParticipantsSearch('')
def getChanel(client): queryKey = [ 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z' ] all_participants = [] channel = 'olymp_trade_signals_free' for key in queryKey: offset = 0 limit = 100 while True: participants = client( GetParticipantsRequest(channel, ChannelParticipantsSearch(key), offset, limit, hash=0)) if not participants.users: break for user in participants.users: try: if re.findall(r"\b[a-zA-Z]", user.first_name)[0].lower() == key: all_participants.append(user) except: pass offset += len(participants.users) print(offset)
async def _get_channel_users(client: MautrixTelegramClient, entity: InputChannel, limit: int) -> list[TypeUser]: if 0 < limit <= 200: response = await client( GetParticipantsRequest(entity, ChannelParticipantsRecent(), offset=0, limit=limit, hash=0)) return list(_filter_participants(response.users, response.participants)) elif limit > 200 or limit == -1: users: list[TypeUser] = [] offset = 0 remaining_quota = limit if limit > 0 else 1000000 query = ChannelParticipantsSearch( "") if limit == -1 else ChannelParticipantsRecent() while True: if remaining_quota <= 0: break response = await client( GetParticipantsRequest(entity, query, offset=offset, limit=min(remaining_quota, 200), hash=0)) if not response.users: break users += _filter_participants(response.users, response.participants) offset += len(response.participants) remaining_quota -= len(response.participants) return users
async def dump_all_participants(channel): """Записывает json-файл с информацией о всех участниках канала/чата""" offset_user = 0 # номер участника, с которого начинается считывание limit_user = 100 # максимальное число записей, передаваемых за один раз all_participants = [] # список всех участников канала filter_user = ChannelParticipantsSearch('') while True: participants = await client(GetParticipantsRequest(channel, filter_user, offset_user, limit_user, hash=0)) if not participants.users: break all_participants.extend(participants.users) offset_user += len(participants.users) all_users_details = [] # список словарей с интересующими параметрами участников канала for participant in all_participants: if participant.phone != 'null': print('новий юзер') all_users_details.append({"id": participant.id, "first_name": participant.first_name, "last_name": participant.last_name, "user": participant.username, "phone": participant.phone, "is_bot": participant.bot}) with open('channel_users.json', 'w', encoding='utf8') as outfile: json.dump(all_users_details, outfile, ensure_ascii=False)
async def dump_all_participants(channel, client): """Записывает json-файл с информацией о всех участниках канала/чата""" offset_user = 0 # номер участника, с которого начинается считывание limit_user = 100 # максимальное число записей, передаваемых за один раз all_participants = [] # список всех участников канала filter_user = ChannelParticipantsSearch('') while True: participants = await client(GetParticipantsRequest(channel, filter_user, offset_user, limit_user, hash=0)) if not participants.users: break all_participants.extend(participants.users) offset_user += len(participants.users) channel_user_id = list() for participant in all_participants: print({"id": participant.id, "first_name": participant.first_name, "last_name": participant.last_name, "user": participant.username, "phone": participant.phone, "is_bot": participant.bot}) channel_user_id.append([participant.id, participant.first_name]) print(channel_user_id) return channel_user_id
async def dump_all_participants(chat): offset_user = 0 limit_user = 500 all_participants = [] filter_user = ChannelParticipantsSearch('') while True: participants = await client( GetParticipantsRequest(chat, filter_user, offset_user, limit_user, hash=0)) if not participants.users: break all_participants.extend(participants.users) offset_user += len(participants.users) all_users_details = [] for participant in all_participants: if not participant.bot: all_users_details.append({ "chat_id": chat.id, "user_id": participant.id, "current_username": participant.username, "current_first_name": participant.first_name, "current_last_name": participant.last_name }) with open('users.json', 'w', encoding='utf8') as outfile: json.dump(all_users_details, outfile, ensure_ascii=False)
async def handler(event): global lista1 if event.online: print("Evento") lista2 = [] participants2 = await client( GetParticipantsRequest(channel, ChannelParticipantsSearch(''), 0, 0, hash=0)) new_users = [] new_users.clear() for u in participants2.users: lista2.append([u.id, u.username]) for us in lista2: if us[0] in lista1: a = 1 else: new_users.append(us) for i in new_users: print('id:' + str(i[0]), 'user: '******'@pruebastienda',mensaje) await client.send_message(i[0], mensaje) #await client.send_message(i, mensaje) TOKEN = '1686414837:AAEinjhPgAMJD8ABV_hD6rCtJ2jsbXwVCm0' #bot = telebot.TeleBot(TOKEN) #bot.send_message(1496283722, 'mensaje de prueba') bot = telepot.Bot(TOKEN) bot.sendMessage(1496283722, 'mensaje de prueba') #print("Enviar msj " + str(i[1])) if i[0] != 1686414837: try: print("Enviado") #bot.send_message(1204307512, 'mensaje de prueba') except: print("An exception occurred") new_users.remove(i) lista1.append(i[0]) print('finalizo el evento')
def get_participants_ids(channel: Channel, raw_users: bool = False) -> list: channel = InputChannel(channel.id, channel.access_hash) result = client( GetParticipantsRequest(channel, ChannelParticipantsSearch(''), 0, 10000, 5)) if not raw_users: ids = [user.id for user in result.users if not user.bot] return ids else: return result.users
async def _get_users( self, user: '******', entity: Union[TypeInputPeer, InputUser, TypeChat, TypeUser, InputChannel] ) -> Tuple[List[TypeUser], List[TypeParticipant]]: # TODO replace with client.get_participants if self.peer_type == "chat": chat = await user.client(GetFullChatRequest(chat_id=self.tgid)) return chat.users, chat.full_chat.participants.participants elif self.peer_type == "channel": if not self.megagroup and not self.sync_channel_members: return [], [] limit = self.max_initial_member_sync if limit == 0: return [], [] try: if 0 < limit <= 200: response = await user.client( GetParticipantsRequest(entity, ChannelParticipantsRecent(), offset=0, limit=limit, hash=0)) return response.users, response.participants elif limit > 200 or limit == -1: users: List[TypeUser] = [] participants: List[TypeParticipant] = [] offset = 0 remaining_quota = limit if limit > 0 else 1000000 query = (ChannelParticipantsSearch("") if limit == -1 else ChannelParticipantsRecent()) while True: if remaining_quota <= 0: break response = await user.client( GetParticipantsRequest(entity, query, offset=offset, limit=min( remaining_quota, 100), hash=0)) if not response.users: break participants += response.participants users += response.users offset += len(response.participants) remaining_quota -= len(response.participants) return users, participants except ChatAdminRequiredError: return [], [] elif self.peer_type == "user": return [entity], [] return [], []
def tlg_get_basic_info(client, chat): '''Get basic information (id, title, name, num_users, num_messages) from a group/channel/chat''' # Get the corresponding chat entity chat_entity = client.get_entity(chat) # Get the number of users in the chat num_members_offset = client(GetParticipantsRequest(channel=chat_entity, \ filter=ChannelParticipantsSearch(''), offset=0, limit=0, hash=0)).count num_members = client(GetParticipantsRequest(channel=chat_entity, \ filter=ChannelParticipantsSearch(''), offset=num_members_offset, limit=0, hash=0)).count # Get messages data from the chat and extract the usefull data related to chat msgs = client.get_messages(chat_entity, limit=1) basic_info = OrderedDict \ ([ \ ("id", msgs[0].chat_id), \ ("title", msgs[0].chat.title), \ ("username", msgs[0].chat.username), \ ("num_members", num_members), \ ("num_messages", msgs.total), \ ("supergroup", msgs[0].chat.megagroup) \ ]) # Return basic info dict return basic_info
async def main(phone): await client.start() print("Client Created") # Ensure you're authorized if await client.is_user_authorized() == False: await client.send_code_request(phone) try: await client.sign_in(phone, input('Enter the code: ')) except SessionPasswordNeededError: await client.sign_in(password=input('Password: '******''), offset, limit, hash=0)) if not participants.users: break all_participants.extend(participants.users) offset += len(participants.users) all_user_details = [] for participant in all_participants: all_user_details.append({ "id": participant.id, "first_name": participant.first_name, "last_name": participant.last_name, "user": participant.username, "phone": participant.phone, "is_bot": participant.bot }) with open('user_data.json', 'w') as outfile: json.dump(all_user_details, outfile)
def tlg_get_all_members(client, chat): '''Get all members information from a group/channel/chat''' # Get the corresponding chat entity chat_entity = client.get_entity(chat) # Get and save all users data in a single list i = 0 members = [] users = [] num_members = client(GetParticipantsRequest(channel=chat_entity, \ filter=ChannelParticipantsSearch(''), offset=0, limit=0, hash=0)).count while True: participants_i = client(GetParticipantsRequest(channel=chat_entity, \ filter=ChannelParticipantsSearch(''), offset=i, limit=num_members, hash=0)) if not participants_i.users: break users.extend(participants_i.users) i = i + len(participants_i.users) # Build our messages data structures and add them to the list for usr in users: usr_last_connection = "" if hasattr(usr.status, "was_online"): usr_last_connection = "{}/{}/{} - {}:{}:{}".format(usr.status.was_online.day, \ usr.status.was_online.month, usr.status.was_online.year, \ usr.status.was_online.hour, usr.status.was_online.minute, \ usr.status.was_online.second) else: usr_last_connection = "The user does not share this information" usr_data = OrderedDict \ ([ \ ("id", usr.id), \ ("username", usr.username), \ ("first_name", usr.first_name), \ ("last_name", usr.last_name), \ ("last_connection", usr_last_connection) \ ]) members.append(usr_data) # Return members list return members
def get_telegram_usernames(write_results=True): print('Fetching telegram followers... This may take a few minutes') api_id = config['TELEGRAM']['ID'] # Your api_id api_hash = config['TELEGRAM']['HASH'] # Your api_hash phone_number = config['TELEGRAM']['PHONE'] # Your phone number client = TelegramClient(phone_number, api_id, api_hash) client.session.report_errors = False client.connect() # will need to enter code from message if session is not active if not client.is_user_authorized(): client.send_code_request(phone_number) client.sign_in(phone_number, input('Enter the code: ')) channel = client(ResolveUsernameRequest( config['TELEGRAM']['CHANNEL'])) # Your channel input_channel = InputChannel(channel.chats[0].id, channel.chats[0].access_hash) offset = 0 limit = 100 all_participants = [] # Can pull up to 10000 participants in one shot. Will need to filter if you have more users than that. while True: participants = client( GetParticipantsRequest(input_channel, ChannelParticipantsSearch(''), offset, limit, 0)) if not participants.users: break all_participants.extend(participants.users) offset += len(participants.users) print(offset) telegram_usernames = [] for participant in all_participants: if participant.username: telegram_usernames.append(participant.username.lower()) # telegram_usernames = [_user.username.lower() for _user in all_participants] if write_results: telegram_file = open('telegram_usernames.csv', 'w') telegram_writer = csv.writer(telegram_file, quoting=csv.QUOTE_ALL) for username in telegram_usernames: telegram_writer.writerow([username]) return telegram_usernames
def get_users(a_channel): offset = 0 limit = 100 all_participants = [] while True: participants = client.invoke(GetParticipantsRequest( a_channel, ChannelParticipantsSearch(''), offset, limit, hash=0 )) if not participants.users: break all_participants.extend(participants.users) offset += len(participants.users) sleep(1) return all_participants
def getId(client, chatName, limit, debug=False): #Checking for not existing try: resolve = client(ResolveUsernameRequest(chatName)) except UsernameInvalidError: print("Incorrect name of chat! Try again.") return False except UsernameNotOccupiedError: print("Incorrect name of chat! Try again.") return False #Checking for chat or no try: access_hash = resolve.chats[0].access_hash chat_id = resolve.chats[0].id except IndexError: print("It's not a chat!") return False input_channel = InputChannel(chat_id, access_hash) filter = ChannelParticipantsSearch('') offset = 0 hash = 0 allId = [] #Checking for channel/private chat try: client( GetParticipantsRequest(input_channel, filter, offset, limit, hash)) except ChatAdminRequiredError: print('It is channel/private chat!') return False count = 0 while True: if count == limit: break part = client( GetParticipantsRequest(input_channel, filter, offset, limit, hash), ) if not part.users: break allId.append(part.users[count].id) count += 1 offset += 1 print('{}/{}'.format(count, limit), end='\r') if debug: print(part.users[count].id) return allId
async def parse(): account = TelegramClient("parser.session", api_id, api_hash) await account.connect() url = input("Введите ссылку на канал или чат: ") channel = await account.get_entity(url) offset_user = 0 limit_user = 1 all_participants = [] filter_user = ChannelParticipantsSearch('') while True: participants = await account( GetParticipantsRequest(channel, filter_user, offset_user, limit_user, hash=0)) if not participants.users: break all_participants.extend(participants.users) offset_user += len(participants.users) print(f"Спаресено {len(all_participants)}") usernames = open("usernames.txt", "a", encoding="utf8") first_names = open("first_names.txt", "a", encoding="utf8") last_names = open("last_names.txt", "a", encoding="utf8") abouts = open("abouts.txt", "a", encoding="utf8") for i in range(len(all_participants)): try: full = await account(GetFullUserRequest(all_participants[i])) if full.user.username: usernames.write(f"{full.user.username}\n") if full.user.first_name: first_names.write(f"{full.user.first_name}\n") last_names.write( f"{full.user.last_name if full.user.last_name else ''}\n") if full.about: abouts.write(f"{full.about}\n") try: await account.download_media(full.profile_photo, "parsed_photos") except Exception as error: print(f"Ошибка при загрузке фото: {error}") print(f"Записаны данные с {i + 1} аккаунта") except Exception as error: print(error)
def get_users(loop): offset = 0 limit = 100 all_participants = [] #channel = Channel(1330505769, title='\u2066♥️\u2069Empathogens❄️קהילת🍄אמפתוגנים', photo=ChatPhoto(photo_small=FileLocation(dc_id=4, volume_id=449011102, local_id=3795, secret=5154166241589927286), photo_big=FileLocation(dc_id=4, volume_id=449011102, local_id=3797, secret=-3469345200309841222))) channel = get_entity(id=1330505769, title='\u2066♥️\u2069Empathogens❄️קהילת🍄אמפתוגנים', photo=ChatPhoto(photo_small=FileLocation(dc_id=4, volume_id=449011102, local_id=3795, secret=5154166241589927286), photo_big=FileLocation(dc_id=4, volume_id=449011102, local_id=3797, secret=-3469345200309841222)), date=datetime.datetime(2018, 9, 25, 13, 42, 14, tzinfo=datetime.timezone.utc), version=0) while True: participants = loop.run_until_complete(client(GetParticipantsRequest( channel, ChannelParticipantsSearch(''), offset, limit, hash=0 ))) if not participants.users: break all_participants.extend(participants.users) offset += len(participants.users) print('Magic Number: ', offset) return all_participants
def count_members(id, access_hash): offset = 0 limit = 10000 all_participants = [] while True: participants = client( GetParticipantsRequest(InputChannel(id, access_hash), ChannelParticipantsSearch(''), offset, limit, hash=0)) if not participants.users: break all_participants.extend(participants.users) offset += len(participants.users) return len(all_participants)
def getChannelUsers(self): my_filter = ChannelParticipantsSearch('') all_groups = self.groupJsonLoads() for grp in all_groups["groups"]: usr_name = all_groups["groups"][grp]["username"] title = all_groups["groups"][grp]["title"] limit = all_groups["groups"][grp]["count"] offset = 0 all_participants = {} if usr_name == None: continue print("==========> Group: ", title) self.client(GetFullChannelRequest(usr_name)) while True: part = self.client( GetParticipantsRequest(channel=usr_name, filter=my_filter, offset=offset, limit=limit, hash=0)) for usr in part.users: if usr.deleted == True: continue all_participants[usr.username] = { "id": usr.id, "first_name": usr.first_name, "last_name": usr.last_name, "username": usr.username, "phone": usr.phone } print("[+] Adding: ", usr.username, "...") offset += len(part.users) if len(part.users) < limit: break self.jsonUsersWrite(all_participants, title)
def get_members(group): offset = 0 limit = 500 all_participants = {} while True: participants = client( GetParticipantsRequest(group, ChannelParticipantsSearch(''), offset, limit, hash=0)) if not participants.users: break for user in participants.users: all_participants[user.id] = user offset += len(participants.users) return all_participants
async def update(db_conn): send_dev("initializing channel check") api_id = "<your api id>" # Your api_id api_hash = '<api hash>' # Your api_hash phone_number = 'admin phone number' # Your phone number channel_user_name = "<channel username>" client = TelegramClient(phone_number, api_id, api_hash) client.session.report_errors = False await client.connect() c = await client.is_user_authorized() if not c: await client.send_code_request(phone_number) await client.sign_in(phone_number, input('Enter the code: ')) offset = 0 limit = 200 my_filter = ChannelParticipantsSearch('') all_participants = [] while_condition = True ################################# users = set() while while_condition: participants = await client( GetParticipantsRequest(channel=channel_user_name, filter=my_filter, offset=offset, limit=limit, hash=0)) all_participants.extend(participants.users) for user in participants.users: users.add(str(user.id)) offset += len(participants.users) if len(participants.users) < limit: while_condition = False for id, username in db_conn.select_chat_ids(): send_dev("database users--> " + str(id) + " " + username) if str(id) not in users: send_dev("Removed students :" + str(id)) db_conn.delete_chat_id(id) await client.disconnect() send_dev("One update occurred and done.")
async def _fetch_users(self, query): max_batch_size = 200 participants = await self.telegram_client( GetParticipantsRequest( channel=self.channel_name, filter=ChannelParticipantsSearch(query), offset=0, limit=max_batch_size, hash=0, ) ) for user in participants.users: self.subscriptors.add(user.id) # There is a possibility that more users exist if we hit maximum count of users # So, we are making a recursion to reveal it if len(participants.users) == max_batch_size: for new_letter in string.ascii_lowercase + string.digits: await self._fetch_users(query + new_letter)
def get_channel_users(client, channel): from telethon.tl.functions.channels import GetParticipantsRequest from telethon.tl.types import ChannelParticipantsSearch offset = 0 limit = 100 all_participants = [] while True: participants = client( GetParticipantsRequest(channel, ChannelParticipantsSearch(''), offset, limit, hash=0)) if not participants.users: break all_participants.extend(participants.users) offset += len(participants.users) print(all_participants)
def dump_users(chat, client): counter = 0 offset = 0 chat_object = InputChannel(chat['chat_id'], chat['access_hash']) all_participants = [] print('Process...') while True: participants = client.invoke( GetParticipantsRequest(chat_object, ChannelParticipantsSearch(''), offset, limit)) if not participants.users: break all_participants.extend( ['{} {}'.format(x.id, x.username) for x in participants.users]) users_count = len(participants.users) offset += users_count counter += users_count print('{} users collected'.format(counter)) sleep(2) with open('users.txt', 'w') as file: file.write('\n'.join(map(str, all_participants)))