def process_callback_query(self, user_id, chat_id, message_id, data): next_state = self command_array = data.split(" ") # only accept "/publish <draft/published>" callback queries if len(command_array) == 2 and command_array[0] == "/publish" and command_array[1] in [state.value for state in PostState]: publish_type = command_array[1] # check if previously selected post still exists post = self.bot.persistence.get_post(self.post_id) if post is not None: is_published = self.bot.publish(post.id, PostState(publish_type)) # publishing successful if is_published: self.bot.edit_message_text(chat_id, message_id , "<b>" + post.title + "</b> has been <b>published</b> as <b>" + ("draft" if publish_type == PostState.DRAFT.value else "final post") + "</b>." , parse_mode=ParseMode.HTML.value) # if published as post -> go back to main menu if publish_type == PostState.PUBLISHED.value: from packages.states.navigation.idlestate import IdleState next_state = IdleState(self.bot, user_id, chat_id=chat_id) else: next_state = SelectDraftUpdateState(self.bot, user_id, post.id, chat_id=chat_id) # publishing not successful else: self.bot.edit_message_text(chat_id, self.message_id , "It seems publishing is not possible..." , parse_mode=ParseMode.HTML.value) next_state = PublishDraftState(self.bot, user_id, post.id, chat_id=chat_id) # previously selected post no longer exists else: self.bot.send_message(chat_id , "It seems the draft you selected no longer exists..." , parse_mode=ParseMode.HTML.value) # show remaining drafts for updating user_drafts = self.bot.persistence.get_posts(user_id=user_id, status=PostState.DRAFT) if len(user_drafts) > 0: from packages.states.draft.updatedraftstate import UpdateDraftState next_state = UpdateDraftState(self.bot, user_id, chat_id=chat_id) # no remaining drafts -> automatically go back to main menu else: from packages.states.navigation.idlestate import IdleState next_state = IdleState(self.bot, user_id, chat_id=chat_id) else: next_state = super().process_callback_query(user_id, chat_id, message_id, data) return next_state
def process_callback_query(self, user_id, chat_id, message_id, data): next_state = self command_array = data.split(" ") # only accept "/deleteposttag <tag_id>" callback queries if len(command_array) == 2 and command_array[0] == "/deleteposttag": tag_id = command_array[1] # check if previously selected post still exists post = self.bot.persistence.get_post(self.post_id) if post is not None: deleted_tag = self.bot.persistence.delete_post_tag(post.id, tag_id) # tag removal successful if deleted_tag is not None: self.bot.edit_message_text(chat_id, message_id , "Tag <b>" + deleted_tag.name + "</b> has been <b>deleted</b> from draft <b>" + post.title + "</b>." , parse_mode=ParseMode.HTML.value) # tag removal not successful else: self.bot.edit_message_text(chat_id, self.message_id , "It seems the tag you selected no longer exists..." , parse_mode=ParseMode.HTML.value) # show remaining tags for deletion if len(post.tags) - (1 if deleted_tag is not None else 0) > 0: next_state = DeleteTagState(self.bot, user_id, post.id, chat_id=chat_id) # no remaining tags -> automatically go back to update option menu else: next_state = SelectDraftUpdateState(self.bot, user_id, post.id, chat_id=chat_id) # previously selected post no longer exists else: self.bot.send_message(chat_id , "It seems the draft you selected no longer exists..." , parse_mode=ParseMode.HTML.value) # show remaining drafts for updating user_drafts = self.bot.persistence.get_posts(user_id=user_id, status=PostState.DRAFT) if len(user_drafts) > 0: from packages.states.draft.updatedraftstate import DeleteDraftState next_state = DeleteDraftState(self.bot, user_id, chat_id=chat_id) # no remaining drafts -> automatically go back to main menu else: from packages.states.navigation.idlestate import IdleState next_state = IdleState(self.bot, user_id, chat_id=chat_id) else: next_state = super().process_callback_query(user_id, chat_id, message_id, data) return next_state
def test_user(self): user_id = 1 user_state = IdleState(None, user_id) user_name = "user1" user = self.db.add_user(user_id, user_state, name=user_name) users = self.db.get_users() updated_user = self.db.update_user(user_id, user_state, name="updated_user") self.assertTrue(len(users) == 1) self.assertTrue(user in users) self.assertTrue(self.db.get_user(user_id) == updated_user) self.assertEqual(self.db.delete_user(user_id), updated_user)
def process_callback_query(self, user_id, chat_id, message_id, data): next_state = self command_array = data.split(" ") # only accept "/confirmdraftdeletion <confirm/back>" callback queries if len(command_array ) == 2 and command_array[0] == "/confirmdraftdeletion": # confirmed draft deletion if command_array[1] == "/confirm": deleted_post = self.bot.persistence.delete_post( self.post_id) if self.bot.unpublish(self.post_id) else None # post removal successful if deleted_post is not None: self.bot.edit_message_text(chat_id, message_id, "Draft <b>" + deleted_post.title + "</b> has been <b>deleted</b>.", parse_mode=ParseMode.HTML.value) # post removal not successful else: self.bot.edit_message_text( chat_id, self.message_id, "It seems the draft you selected no longer exists...", parse_mode=ParseMode.HTML.value) # show remaining drafts for deletion user_drafts = self.bot.persistence.get_posts( user_id=user_id, status=PostState.DRAFT) if len(user_drafts) > 0: from packages.states.draft.deletedraftstate import DeleteDraftState next_state = DeleteDraftState(self.bot, user_id, chat_id=chat_id) # no remaining drafts -> automatically go back to main menu else: from packages.states.navigation.idlestate import IdleState next_state = IdleState(self.bot, user_id, chat_id=chat_id) else: next_state = super().process_callback_query( user_id, chat_id, message_id, data) return next_state
def process_message(self, user_id, chat_id, text, entities): next_state = self text = text.strip(' \t\n\r') # let super() handle any bot commands if text.startswith("/") or "bot_command" in [ entity["type"] for entity in entities ]: next_state = super().process_message(user_id, chat_id, text, entities) # accept simple text as post title else: # remove inline keyboard from latest bot message (by leaving out reply_options parameter) self.build_state_message(chat_id, self.welcome_message, message_id=self.message_id) # try to create new draft post = self.bot.persistence.add_post(user_id, text, PostState.DRAFT, "Bildergalerie", "") # post creation was successful -> show post update options if post is not None: self.bot.send_message(chat_id, "Draft <b>" + text + "</b> has been <b>created</b>.", parse_mode=ParseMode.HTML.value) from packages.states.navigation.selectdraftupdatestate import SelectDraftUpdateState next_state = SelectDraftUpdateState(self.bot, user_id, post.id, chat_id=chat_id) # post creation failed -> back to main menu else: self.bot.send_message( chat_id, "New draft could not be created. Returning to main menu.", parse_mode=ParseMode.HTML.value) next_state = IdleState(self.bot, user_id, chat_id=chat_id) return next_state
def process_callback_query(self, user_id, chat_id, message_id, data): next_state = self command_array = data.split(" ") # only accept "/confirmpostdeletion <confirm/back>" callback queries if len(command_array) == 2 and command_array[0] == "/confirmpostdeletion": # confirmed post deletion if command_array[1] == "/confirm": deleted_post = self.bot.persistence.delete_post(self.post_id) if self.bot.unpublish(self.post_id) else None original_post_id = None if deleted_post.original_post is None else deleted_post.original_post.id # delete all predecessor posts while original_post_id: original_post = self.bot.persistence.delete_post(original_post_id) original_post_id = None if not (original_post and original_post.original_post) else original_post.original_post.id # post removal successful if deleted_post is not None: self.bot.edit_message_text(chat_id, message_id , "Post <b>" + deleted_post.title + "</b> has been <b>deleted</b>." , parse_mode=ParseMode.HTML.value) # post removal not successful else: self.bot.edit_message_text(chat_id, self.message_id , "It seems the post you selected no longer exists..." , parse_mode=ParseMode.HTML.value) # show remaining posts for deletion user_posts = self.bot.persistence.get_posts(user_id=user_id, status=PostState.PUBLISHED) if len([post for post in user_posts if post.status == PostState.PUBLISHED]) \ > len([draft for draft in user_posts if draft.status == PostState.DRAFT and draft.original_post is not None]): from packages.states.post.deletepoststate import DeletePostState next_state = DeletePostState(self.bot, user_id, chat_id=chat_id) # no remaining posts -> automatically go back to main menu else: from packages.states.navigation.idlestate import IdleState next_state = IdleState(self.bot, user_id, chat_id=chat_id) else: next_state = super().process_callback_query(user_id, chat_id, message_id, data) return next_state
def process_message(self, user_id, chat_id, text, entities): next_state = self text = text.strip(' \t\n\r') # let super() handle any bot commands if text.startswith("/") or "bot_command" in [ entity["type"] for entity in entities ]: next_state = super().process_message(user_id, chat_id, text, entities) # accept simple text as tag list else: # remove inline keyboard from latest bot message (by leaving out reply_options parameter) self.build_state_message(chat_id, self.welcome_message, message_id=self.message_id) # check if previously selected post still exists post = self.bot.persistence.get_post(self.post_id) if post is not None: new_tags = [] for new_tag_name in [ x.strip(' \t\n\r') for x in re.split("[,\t\n\r]", text) ]: # ignore "empty" tags if len(new_tag_name) == 0: continue tag = self.bot.persistence.add_post_tag( post.id, new_tag_name) if tag is not None: new_tags.append(tag.name) if len(new_tags) > 0: self.bot.send_message(chat_id, "Tag(s) <b>" + ", ".join(new_tags) + "</b> have been added to draft <b>" + post.title + "</b>.", parse_mode=ParseMode.HTML.value) else: self.bot.send_message( chat_id, "<b>No tags(s) added</b>. All specified tag(s) were already assigned to draft <b>" + post.title + "</b>.", parse_mode=ParseMode.HTML.value) next_state = AddTagState(self.bot, user_id, self.post_id, chat_id=chat_id) # previously selected post no longer exists else: self.bot.send_message( chat_id, "It seems the draft you selected no longer exists...", parse_mode=ParseMode.HTML.value) # show remaining drafts for updating user_drafts = self.bot.persistence.get_posts( user_id=user_id, status=PostState.DRAFT) if len(user_drafts) > 0: from packages.states.draft.updatedraftstate import UpdateDraftState next_state = UpdateDraftState(self.bot, user_id, chat_id=chat_id) # no remaining drafts -> automatically go back to main menu else: from packages.states.navigation.idlestate import IdleState next_state = IdleState(self.bot, user_id, chat_id=chat_id) return next_state
def process_callback_query(self, user_id, chat_id, message_id, data): next_state = self command_array = data.split(" ") # only accept "/deletepostimage <image_id>" callback queries if len(command_array) == 2 and command_array[0] == "/deletepostimage": image_id = command_array[1] # check if previously selected post still exists post = self.bot.persistence.get_post(self.post_id) if post is not None: deleted_image = self.bot.persistence.delete_post_image( post.id, image_id) # image removal successful if deleted_image is not None: self.bot.edit_message_text( chat_id, message_id, "Image <b>" + deleted_image.name + "</b> has been <b>deleted</b> from draft <b>" + post.title + "</b>.", parse_mode=ParseMode.HTML.value) # image removal not successful else: self.bot.edit_message_text( chat_id, self.message_id, "It seems the image you selected no longer exists...", parse_mode=ParseMode.HTML.value) # show remaining images for deletion post_images = post.gallery.images + ( [post.title_image] if post.title_image is not None else []) if len(post_images) - (1 if deleted_image is not None else 0) > 0: next_state = DeleteImageState(self.bot, user_id, post.id, chat_id=chat_id) # no remaining images -> automatically go back to update option menu else: next_state = SelectDraftUpdateState(self.bot, user_id, self.post_id, chat_id=chat_id) # previously selected post no longer exists else: self.bot.send_message( chat_id, "It seems the draft you selected no longer exists...", parse_mode=ParseMode.HTML.value) # show remaining drafts for updating user_drafts = self.bot.persistence.get_posts( user_id=user_id, status=PostState.DRAFT) if len(user_drafts) > 0: from packages.states.draft.updatedraftstate import DeleteDraftState next_state = DeleteDraftState(self.bot, user_id, chat_id=chat_id) # no remaining drafts -> automatically go back to main menu else: from packages.states.navigation.idlestate import IdleState next_state = IdleState(self.bot, user_id, chat_id=chat_id) # only accept "/previewpostimage <image_id>" callback queries elif len(command_array ) == 2 and command_array[0] == "/previewpostimage": image_id = command_array[1] # remove inline keyboard from latest bot message (by leaving out reply_options parameter) self.build_state_message(chat_id, self.welcome_message, message_id=self.message_id) # check if previously selected post still exists post = self.bot.persistence.get_post(self.post_id) if post is not None: preview_image = None for image in post.gallery.images + ([ post.title_image ] if post.title_image is not None else []): # ignore "wrong" images if str(image.id) != str(image_id): continue else: preview_image = image # image found -> preview if image is not None: self.bot.send_photo( chat_id, image.thumb_id if image.thumb_id else image.file_id, caption=image.caption) # image not found else: self.bot.edit_message_text( chat_id, self.message_id, "It seems the image you selected no longer exists...", parse_mode=ParseMode.HTML.value) next_state = DeleteImageState(self.bot, user_id, self.post_id, chat_id=chat_id) # previously selected post no longer exists else: self.bot.send_message( chat_id, "It seems the draft you selected no longer exists...", parse_mode=ParseMode.HTML.value) # show remaining drafts for updating user_drafts = self.bot.persistence.get_posts( user_id=user_id, status=PostState.DRAFT) if len(user_drafts) > 0: from packages.states.draft.updatedraftstate import DeleteDraftState next_state = DeleteDraftState(self.bot, user_id, chat_id=chat_id) # no remaining drafts -> automatically go back to main menu else: from packages.states.navigation.idlestate import IdleState next_state = IdleState(self.bot, user_id, chat_id=chat_id) else: next_state = super().process_callback_query( user_id, chat_id, message_id, data) return next_state
def process_message(self, user_id, chat_id, text, entities): next_state = self text = text.strip(' \t\n\r') # let super() handle any bot commands if text.startswith("/") or "bot_command" in [ entity["type"] for entity in entities ]: next_state = super().process_message(user_id, chat_id, text, entities) # accept simple text as new post title else: # remove inline keyboard from latest bot message (by leaving out reply_options parameter) self.build_state_message(chat_id, self.welcome_message, message_id=self.message_id) # check if previously selected post still exists post = self.bot.persistence.get_post(self.post_id) if post is not None: new_title = text updated_post = self.bot.persistence.update_post( post.id, post.user.id, new_title, post.status, post.gallery.title, post.content, None if post.title_image is None else post.title_image.id, post.tmsp_publish, None if post.original_post is None else post.original_post.id) # post update successful if updated_post is not None: self.bot.send_message( chat_id, "Draft title has been updated to <b>" + updated_post.title + "</b>.", parse_mode=ParseMode.HTML.value) # post update not successful else: self.bot.send_message(chat_id, "Draft title could not be updated.", parse_mode=ParseMode.HTML.value) next_state = SelectDraftUpdateState(self.bot, user_id, self.post_id, chat_id=chat_id) # previously selected post no longer exists else: self.bot.send_message( chat_id, "It seems the draft you selected no longer exists...", parse_mode=ParseMode.HTML.value) # show remaining drafts for updating user_drafts = self.bot.persistence.get_posts( user_id=user_id, status=PostState.DRAFT) if len(user_drafts) > 0: from packages.states.draft.updatedraftstate import UpdateDraftState next_state = UpdateDraftState(self.bot, user_id, chat_id=chat_id) # no remaining drafts -> automatically go back to main menu else: from packages.states.navigation.idlestate import IdleState next_state = IdleState(self.bot, user_id, chat_id=chat_id) return next_state
def process_callback_query(self, user_id, chat_id, message_id, data): next_state = self command_array = data.split(" ") # only accept "/previewcontent" callback queries if len(command_array) == 1 and command_array[0] == "/previewcontent": # check if previously selected post still exists post = self.bot.persistence.get_post(self.post_id) if post is not None: # replace edit instructions with current draft content self.bot.edit_message_text(chat_id, self.message_id, post.content) next_state = EditDraftContentState(self.bot, user_id, post.id, chat_id=chat_id) # previously selected post no longer exists else: self.bot.send_message(chat_id , "It seems the draft you selected no longer exists..." , parse_mode=ParseMode.HTML.value) # show remaining drafts for updating user_drafts = self.bot.persistence.get_posts(user_id=user_id, status=PostState.DRAFT) if len(user_drafts) > 0: from packages.states.draft.updatedraftstate import UpdateDraftState next_state = UpdateDraftState(self.bot, user_id, chat_id=chat_id) # no remaining drafts -> automatically go back to main menu else: from packages.states.navigation.idlestate import IdleState next_state = IdleState(self.bot, user_id, chat_id=chat_id) # only accept "/formatting" callback queries elif len(command_array) == 1 and command_array[0] == "/formatting": # check if previously selected post still exists post = self.bot.persistence.get_post(self.post_id) if post is not None: message = "Following <b>Markdown</b> options are supported:\r\n\r\n" \ + "Heading 1-6: #..# text\r\n" \ + "Bold text: <b>**text**</b>\r\n" \ + "Italic text: <i>*text*</i>\r\n" \ + "Web link: [text](http://www.example.com/)\r\n" \ + "Inline code: <code>`some code`</code>\r\n" \ + "Pre-formatted code block <pre>```some code```</pre>" # replace edit instructions with Markdown formatting options self.bot.edit_message_text(chat_id, self.message_id, message, parse_mode=ParseMode.HTML.value) next_state = EditDraftContentState(self.bot, user_id, post.id, chat_id=chat_id) # previously selected post no longer exists else: self.bot.send_message(chat_id , "It seems the draft you selected no longer exists..." , parse_mode=ParseMode.HTML.value) # show remaining drafts for updating user_drafts = self.bot.persistence.get_posts(user_id=user_id, status=PostState.DRAFT) if len(user_drafts) > 0: from packages.states.draft.updatedraftstate import UpdateDraftState next_state = UpdateDraftState(self.bot, user_id, chat_id=chat_id) # no remaining drafts -> automatically go back to main menu else: from packages.states.navigation.idlestate import IdleState next_state = IdleState(self.bot, user_id, chat_id=chat_id) else: next_state = super().process_callback_query(user_id, chat_id, message_id, data) return next_state
def process_photo_message(self, user_id, chat_id, file_id, thumb_id=None, caption=None): next_state = self # remove inline keyboard from latest bot message (by leaving out reply_options parameter) self.build_state_message(chat_id, self.welcome_message, message_id=self.message_id) # check if previously selected post still exists post = self.bot.persistence.get_post(self.post_id) if post is not None: image = None # TODO move this code to bot? -> file = self.context.download_file(file_id) telegram_file = self.bot.get_file(file_id) if "result" in telegram_file and "file_path" in telegram_file[ "result"]: file_url = telegram_file["result"]["file_path"] file = self.bot.download_file(file_url) if file is not None: file_name = str(self.message_id) + "." + file_url.rsplit( ".", 1)[1] image = self.bot.persistence.add_post_image( post.id, file_id, file_name, file, thumb_id=thumb_id, caption=caption) if image is not None: self.bot.send_message( chat_id, "Image <b>" + image.name + "</b> has been <b>added</b> to draft <b>" + post.title + "</b>.", parse_mode=ParseMode.HTML.value) else: self.bot.send_message(chat_id, "<b>Image not added</b> to draft <b>" + post.title + "</b>.", parse_mode=ParseMode.HTML.value) next_state = AddImageState(self.bot, user_id, post.id, chat_id=chat_id) # previously selected post no longer exists else: self.bot.send_message( chat_id, "It seems the draft you selected no longer exists...", parse_mode=ParseMode.HTML.value) # show remaining drafts for updating user_drafts = self.bot.get_user_posts(user_id=user_id, status=PostState.DRAFT) if len(user_drafts) > 0: from packages.states.draft.updatedraftstate import UpdateDraftState next_state = UpdateDraftState(self.bot, user_id, chat_id=chat_id) # no remaining drafts -> automatically go back to main menu else: from packages.states.navigation.idlestate import IdleState next_state = IdleState(self.bot, user_id, chat_id=chat_id) return next_state
def process_callback_query(self, user_id, chat_id, message_id, data): next_state = self command_array = data.split(" ") # only accept "/confirmpostupdate <confirm/back>" callback queries if len(command_array ) == 2 and command_array[0] == "/confirmpostupdate": # confirmed post update if command_array[1] == "/confirm": # check if previously selected post still exists post = self.bot.persistence.get_post(self.post_id) if post is not None: new_draft = self.bot.persistence.copy_post(self.post_id) # draft creation successful if new_draft is not None: self.bot.edit_message_text( chat_id, message_id, "New draft for modification of post <b>" + new_draft.title + "</b> has been <b>created</b>.", parse_mode=ParseMode.HTML.value) # show update options for newly created draft from packages.states.navigation.selectdraftupdatestate import SelectDraftUpdateState next_state = SelectDraftUpdateState(self.bot, user_id, new_draft.id, chat_id=chat_id) # draft creation not successful else: self.bot.edit_message_text( chat_id, self.message_id, "It seems the post you selected cannot be updated...", parse_mode=ParseMode.HTML.value) # show remaining posts for updating user_posts = self.bot.persistence.get_posts( user_id=user_id, status=PostState.PUBLISHED) if len([post for post in user_posts if post.status == PostState.PUBLISHED]) \ > len([draft for draft in user_posts if draft.status == PostState.DRAFT and draft.original_post is not None]): from packages.states.post.updatepoststate import UpdatePostState next_state = UpdatePostState(self.bot, user_id, chat_id=chat_id) # no remaining posts -> automatically go back to main menu else: from packages.states.navigation.idlestate import IdleState next_state = IdleState(self.bot, user_id, chat_id=chat_id) else: next_state = super().process_callback_query( user_id, chat_id, message_id, data) return next_state