async def zip(event, session): """Create 1.5GB zips with all files collectd in this chat.""" to_id, to_type = get_peer_information(event.message.to_id) subscriber = Subscriber.get_or_create(session, to_id, to_type, event.message) chat_path = get_chat_path(subscriber.chat_name) if not os.path.exists(chat_path): return "No files for this chat yet." zip_dir = init_zip_dir(subscriber.chat_name) text = f"Zipping started, this might take some time. Please don't issue this command again until I'm finished." await event.respond(text) create_zips(subscriber.chat_name, zip_dir, chat_path) text = "Zipping is completed. I'll now start uploading." await event.respond(text) for zip_file in os.listdir(zip_dir): zip_file_path = os.path.join(zip_dir, zip_file) await archive.send_file(event.message.to_id, zip_file_path) shutil.rmtree(zip_dir) return "All files are uploaded :)"
async def stop(event, session): """Stop the bot.""" to_id, to_type = get_peer_information(event.message.to_id) subscriber = Subscriber.get_or_create(session, to_id, to_type, event.message) subscriber.active = False session.add(subscriber) return "Files won't be archived any longer."
async def start(event, session): """Start the bot.""" to_id, to_type = get_peer_information(event.message.to_id) subscriber = Subscriber.get_or_create(session, to_id, to_type, event.message) subscriber.active = True session.add(subscriber) return 'Files posted in this chat will now be archived.'
async def process(event, session): """Check if we received any files.""" to_id, to_type = get_peer_information(event.message.to_id) subscriber = Subscriber.get_or_create(session, to_id, to_type, event.message) try: await process_message(session, subscriber, event.message, event) except BadMessageError: # Ignore bad message errors return
async def process(event, session): """Main entry for processing messages and downloading files.""" to_id, to_type = get_peer_information(event.message.to_id) subscriber = Subscriber.get_or_create(session, to_id, to_type, event.message) try: await process_message(session, subscriber, event.message, event) except BadMessageError: # Ignore bad message errors return
async def scan_chat(event, session): """Check if we received any files.""" to_id, to_type = get_peer_information(event.message.to_id) subscriber = Subscriber.get_or_create(session, to_id, to_type, event.message) await event.respond('Starting full chat scan.') async for message in archive.iter_messages(event.message.to_id): try: await process_message(session, subscriber, message, event, full_scan=True) except BadMessageError: # Ignore bad message errors return return "Full chat scan successful."
async def set_name(event, session): """Set the name of the current chat (also affects the saving directory.""" to_id, to_type = get_peer_information(event.message.to_id) new_chat_name = event.message.message.split(" ", maxsplit=1)[1].strip() # We already save to zips, prevent that if new_chat_name == "zips": return "Invalid chat name. Pick another." subscriber = Subscriber.get_or_create( session, to_id, to_type, event.message, chat_name=new_chat_name ) old_chat_path = get_chat_path(subscriber.chat_name) new_chat_path = get_chat_path(new_chat_name) # Handle any command that tries to escape the download directory new_real_path = os.path.realpath(new_chat_path) target_real_path = os.path.realpath(config["download"]["target_dir"]) if ( not new_real_path.startswith(target_real_path) or new_real_path == target_real_path ): user = await archive.get_entity(types.PeerUser(event.message.from_id)) sentry.captureMessage( "User tried to escape directory.", extra={ "new_chat_name": new_chat_name, "chat": subscriber.chat_name, "user": get_username(user), }, tags={"level": "info"}, ) return "Please stop fooling around and don't try to escape the directory. I have been notified about this." # Check whether we already have a chat with this name if ( session.query(Subscriber) .filter(Subscriber.chat_name == new_chat_name) .one_or_none() ): return "Chat name already exists. Please choose another one." # Move the old directory to the new location elif old_chat_path != new_chat_path: subscriber.chat_name = new_chat_name if os.path.exists(old_chat_path): os.rename(old_chat_path, new_chat_path) return "Chat name changed."
async def get_option_for_subscriber(event, session): """Return the resolved option value and the subscriber for a command.""" chat_id, chat_type = get_peer_information(event.message.to_id) subscriber = Subscriber.get_or_create(session, chat_id, chat_type, event.message) # Convert the incoming text into an boolean try: value = get_bool_from_text(event.message.message.split(' ', maxsplit=1)[1]) except Exception: text = "Got an invalid value. Please use one of [true, false, on, off, 0, 1]" await event.respond(text) return None, None return subscriber, value
async def clear_history(event, session): """Stop the bot.""" to_id, to_type = get_peer_information(event.message.to_id) subscriber = Subscriber.get_or_create(session, to_id, to_type, event.message) chat_path = get_chat_path(subscriber.chat_name) for known_file in subscriber.files: session.delete(known_file) if os.path.exists(chat_path): shutil.rmtree(chat_path) session.commit() return "All files from this chat have been deleted."
async def accepted_media_types(event, session): """Set query attributes.""" to_id, to_type = get_peer_information(event.message.to_id) subscriber = Subscriber.get_or_create(session, to_id, to_type, event.message) # Convert the incoming text into an boolean arguments = event.message.message.lower().split(' ')[1:] accepted_media = set() for argument in arguments: if argument in possible_media: accepted_media.add(argument) accepted_media = list(accepted_media) accepted_media.sort() subscriber.accepted_media = ' '.join(accepted_media) return f"Now accepting following media types: {accepted_media}."
async def set_name(event, session): """Set query attributes.""" to_id, to_type = get_peer_information(event.message.to_id) new_chat_name = event.message.message.split(' ', maxsplit=1)[1].strip() if new_chat_name == 'zips': return "Invalid chat name. Pick another." subscriber = Subscriber.get_or_create(session, to_id, to_type, event.message, chat_name=new_chat_name) old_chat_path = get_chat_path(subscriber.chat_name) new_chat_path = get_chat_path(new_chat_name) new_real_path = os.path.realpath(new_chat_path) target_real_path = os.path.realpath(config.TARGET_DIR) if not new_real_path.startswith(target_real_path) or \ new_real_path == target_real_path: user = await archive.get_entity(types.PeerUser(event.message.from_id)) sentry.captureMessage("User tried to escape directory.", extra={ 'new_chat_name': new_chat_name, 'chat': subscriber.chat_name, 'user': get_username(user) }, tags={'level': 'info'}) return "Please stop fooling around and don't try to escape the directory. I have been notified about this." if session.query(Subscriber) \ .filter(Subscriber.chat_name == new_chat_name) \ .one_or_none(): return "Chat name already exists. Please choose another one." elif old_chat_path != new_chat_path: subscriber.chat_name = new_chat_name if os.path.exists(old_chat_path): os.rename(old_chat_path, new_chat_path) return "Chat name changed."
async def process(event, session): """Main entry for processing messages and downloading files.""" to_id, to_type = get_peer_information(event.message.to_id) subscriber = Subscriber.get_or_create(session, to_id, to_type, event.message) tries = 3 current_try = 0 while tries < current_try: try: await process_message(session, subscriber, event.message, event) return except BadMessageError: # Ignore bad message errors return except FloodWaitError as e: # We got a flood wait error. Wait for the specified time and recursively retry time.sleep(e.seconds + 1) except TimeoutError: # Timeout error. Just wait for 10 secs. time.sleep(10) current_try += 1
async def info(event, session): """Send a the information about the current user settings.""" to_id, to_type = get_peer_information(event.message.to_id) subscriber = Subscriber.get_or_create(session, to_id, to_type, event.message) return get_info_text(subscriber)
async def info(event, session): """Send a help text.""" to_id, to_type = get_peer_information(event.message.to_id) subscriber = Subscriber.get_or_create(session, to_id, to_type, event.message) return get_info_text(subscriber)