def sendSettings(message): markup = settingsMarkup(message.chat.id) chatID = message.chat.id currentChat = Chats.getChat(message.chat.id) lastMessage = currentChat.settings.lastMessageId # * Deleting previous "settings" message try: if lastMessage[0]: bot.delete_message(chatID, lastMessage[0]) except Exception: pass # * Sending new one settingsMessage = bot.send_message( chatID, message.replies.stg.msgTitle, reply_markup=markup ) # * Setting new messageID when the message was send to be able to delete this one, # * when new settings will be sent currentChat.settings.lastMessageId = [ settingsMessage.message_id, message.from_user.id ] currentChat.save()
def findWord(message): """Will look for the requested word in the database and send inforamation about it""" args = extractArgs(message.text) chatID = message.chat.id currentChat = Chats.getChat(chatID) # * Checking if the arguments where provided if not args: bot.send_message(chatID, message.replies.fw[2]) return # * Looking for words saving info about them and sending the result foundWords = [] theirNumbers = [] for word in currentChat.words: if word.text in args: foundWords.append(word.text) theirNumbers.append(word.sentTimes) if not foundWords: bot.send_message(chatID, message.replies.fw[1]) else: for part in stringForStats(chatID, foundWords, theirNumbers): bot.send_message(chatID, part)
def callbackAdditionalButtons(call): chatId = call.message.chat.id currentChat = Chats.getChat(chatId) settingsStrings = call.replies.stg.strings # ? All buttons # * Edit values buttons if call.data == 'stgEditValues': botReplies = call.replies.stg userDmId = currentChat.settings.lastMessageId[1] # * Creating a markup with all settings names, whose value can be edited markup = InlineKeyboardMarkup() for setting in settingsStrings: for button in setting: if button[2]: # * Converts in a strange way to get 'Test String' from 'testString' text = settingForUser(button[3]) tempButton = InlineKeyboardButton( text, callback_data=dumps([ button[1].replace('stg', 'edit'), button[3] ]) ) markup.row(tempButton) checkChat(userDmId) dmChat = Chats.getChat(userDmId) dmChat.settings.editMessageInfo['originalChatId'] = call.message.chat.id dmChat.save() originalChatUsername = call.message.chat.username if originalChatUsername: addUrlButton(markup, call.replies.goToChat[0], originalChatUsername) bot.send_message(userDmId, botReplies.editorMessage, reply_markup=markup) # * More info button if call.data == 'stgMoreInfo': allSettingsNames = [] for setting in settingsStrings: for button in setting: allSettingsNames.append(settingForUser(button[3])) text = '\n\n'.join(call.replies.stg.additionalInfo).format(*allSettingsNames) bot.send_message(chatId, text, parse_mode='html')
def callbackSettingsEditors(call): currentChat = Chats.getChat(call.message.chat.id) # * Sending a helping message and updating the DB newMessage = bot.send_message(call.message.chat.id, call.replies.stg.sendNewValue) addingInfoTo = currentChat.settings.editMessageInfo addingInfoTo['requestMessageId'] = newMessage.message_id addingInfoTo['requestChatId'] = newMessage.chat.id addingInfoTo['commandName'] = call.additionalInfo addingInfoTo['callbackId'] = call.id currentChat.save()
def __init__(self, objectWithID=None): if objectWithID: chatID = self.idFromObject(objectWithID) try: currentChat = Chats.getChat(chatID) self._language = currentChat.language except Chats.DoesNotExist: checkChat(chatID) self._language = 'eng' self._strings = replies[self._language]
def sendGlobalTopWord(message): topWordText = '' chatId = message.chat.id # * Checking if we has statistics atleast in one chat if not Chats.objects(words__not__size=0): bot.send_message(chatId, message.replies.nos) return # * Here will be saved the chat object which was most commonly used word, # * none of the words in other chats weren't sent as much times # * as particular word in this chat was. chatWithTop = Chats() # * Searches for the chat, which has the most used word in it # * (more ditailed description of this is written above the 'chatWithTop' variable defenition) sentTimes = 0 while Chats.objects(words__sentTimes__gt=sentTimes): allMatching = Chats.objects(words__sentTimes__gt=sentTimes) if len(allMatching) == 1 or len(allMatching) == sentTimes + 2: chatWithTop = allMatching[0] topWordText = chatWithTop.topWord.text break sentTimes += 1 # * Looks for this word in every chat and add its writtenTime to general sentEverywhere = 0 for chat in Chats.objects(words__text=topWordText): for word in chat.words: if word.text == topWordText: sentEverywhere += word.sentTimes resultString = Language(message).strs.gtw.format(topWordText, sentEverywhere) bot.send_message(chatId, resultString, reply_markup=getDeleteMarkup(commands.gtw, message))
def clearStats(message): """ Clears the Chat object for current chat, so there will be no information to use left, but it leaves the object in the database, so there will be no need to create a new one """ # * Cleaning the chat Document currentChat = Chats.getChat(message.chat.id) currentChat.words = [] currentChat.sentMessages = currentChat.sentWords = 0 currentChat.topWord = Word(text='', sentTimes=0) currentChat.save() # adder = IDAdder(currentChat,) bot.send_message(message.chat.id, message.replies.sclrd)
def sendTopWord(message): """Gets from the DB most commonly used word objects and sends it to the chat""" chatID = message.chat.id currentChat = Chats.getChat(chatID) topWord = currentChat.topWord if topWord.text: toSend = message.replies.tw.format(topWord.text, topWord.sentTimes) bot.send_message(chatID, toSend, reply_markup=getDeleteMarkup(commands.tw, message)) else: bot.send_message(chatID, message.replies.nos)
def modifyMessage(bot_instance, message): chatID = message.chat.id checkChat(chatID) currentChat = Chats.getChat(chatID) # * Setting bot replies message.replies = Language(message.chat.id).strs # ? Resposes # * Saving bot responses to the DB trough ReponsesManager class and deleting old messages if not message.text is None and '/' in message.text: deleteAfter = currentChat.settings['removeAfter']['value'] editor = ResponsesManager(currentChat) editor.addResponse(message.message_id) try: # * Deleting a reponse and all connected messages. Will delete everywhere if len(currentChat.responses) > deleteAfter: # * Spltting information about the oldest reponses into variables and deleting # * "main" nessage + other message, which were sent when the command was sent # * Splitting info to access it easier oldestResponse = list(currentChat.responses.items())[0] oldestResponseChatId = oldestResponse[0] oldestResponseIds = oldestResponse[1]['connectedIDs'] # * Deleting data from the DB and removing "main" message in the chat editor.deleteResponse(oldestResponseChatId) bot_instance.delete_message(chatID, oldestResponseChatId) # * Deleting other messages if oldestResponseIds: for chatId, addtionalIds in oldestResponseIds.items(): if not isinstance(addtionalIds, list): addtionalIds = [addtionalIds] for id in addtionalIds: bot_instance.delete_message(chatId, id) except apihelper.ApiException as error: print(error) currentChat.save()
def callbackInline(call): """Function to control inline buttonsm won't be used anywhere, just in the decorator""" if call.message: chatID = call.message.chat.id if call.data == 'toClearTrue': markup = types.InlineKeyboardMarkup(row_width = 1) keyboardItem1 = types.InlineKeyboardButton(call.replies.skeyboard[1], callback_data = 'deleteMessage') markup.add(keyboardItem1) bot.delete_message(chatID, call.message.message_id - 1) bot.edit_message_text(call.message.text, chatID, call.message.message_id, reply_markup = markup) # * Cleaning the chat Document currentChat = Chats.getChat(call.additionalInfo) currentChat.words = [] currentChat.sentMessages = currentChat.sentWords = 0 currentChat.topWord = Word(text='', sentTimes=0) currentChat.save() bot.send_message(chatID, call.replies.sclrd) if call.data == 'deleteMessage': bot.answer_callback_query(call.id, show_alert=False, text=call.replies.notf[0]) bot.delete_message(chatID, call.message.message_id) if call.data == 'deleteWithCommand': bot.answer_callback_query(call.id, show_alert=False, text=call.replies.notf[1]) bot.delete_message(chatID, call.message.message_id) bot.delete_message(chatID, call.additionalInfo) # * Handles changing language settings if call.data == 'setLangRu': Language(chatID).lang = (call, 'ru') if call.data == 'setLangEng': Language(chatID).lang = (call, 'eng') if call.data == 'setLangEng' or call.data == 'setLangRu': call.replies = Language(chatID).strs bot.answer_callback_query(call.id, show_alert = False, text = call.replies.sectl[1]) bot.delete_message(chatID, call.message.message_id)
def callbackSettings(call): chatId = call.message.chat.id currentChat = Chats.getChat(chatId) settingsStrings = call.replies.stg.strings # * Toggling setting, if a simple callback for i, callback in enumerate(allSettingsCallbacks): if call.data == callback: Settings.toggleSetting(currentChat, settingsStrings[i][0][3]) # * Upating the message markup = settingsMarkup(chatId) try: bot.edit_message_text( Language(chatId).strs.stg.msgTitle, chatId, call.message.message_id, reply_markup=markup, ) bot.answer_callback_query(call.id, Language(chatId).strs.stg.success) except ApiException as e: print(e)
def lang(self, values) -> None: objectWithID, newLanguage = values currentChat = Chats() # * Checking if provided language exists in the database if newLanguage in implamentedLanguages: for _ in range(2): chatID = self.idFromObject(objectWithID) try: currentChat = Chats.getChat(chatID) except Chats.DoesNotExist: checkChat(chatID) currentChat.language = newLanguage currentChat.save() self._strings = replies[newLanguage] self._language = newLanguage
def stringForStats(chatID, words, wordNumbers, additionalInfo=False, chatName=None): """ Returns a formated in a speial way string using all information bot has to use in /stats command and not only """ if not words: return None wordWrittenTimes = 1 result = [] # * Creating an array of ceratiain format. It will look somethig like this # & [['Word(s), which was/were written 1 time(s).', '"first"'], # & ['Word(s), which was/were written 2 time(s).', '"second"']] while wordWrittenTimes <= max(wordNumbers): # * Skipping an iterations if we don't have words which where written this much times if wordWrittenTimes not in wordNumbers: wordWrittenTimes += 1 continue # * Adds all info to the string, we get info from the DB oneLine = [Language(chatID).strs.s[1].format(wordWrittenTimes)] for i, word in enumerate(words): if wordWrittenTimes == wordNumbers[i]: oneLine.append (f'"{word}"') # * Adding one like of words which where written same number of times # * and incrementing the variable responcible for everything result.append(oneLine) wordWrittenTimes += 1 messages = [[]] for item in result: messages[-1].append(item) if len(reduce(lambda a, b : ''.join(a) + ''.join(b), messages[-1])) >= 3000: messages.append([]) # * Adding each to make a strings which will look something like this # & 'Word(s), which was/were written 1 time(s).\n"first"' allMessages = [] for index, message in enumerate(messages): singleMessage = [] if not chatName is None and not index: singleMessage.append(Language(chatID).strs.s[4].format( chatName )) for item in message: messageText = f'{item[0]}\n{", ".join(item[1:])}' singleMessage.append(messageText) allMessages.append(singleMessage) # * Making a string out of our array and adding more info to the string if we want to result = [] currentChat = Chats.getChat(chatID) for message in allMessages: # * Checking if we need additional info and add it if message == allMessages[-1] and additionalInfo: message.append(Language(chatID).strs.s[0].format( currentChat.sentMessages, currentChat.sentWords )) # * Adding all together, to get a final result result.append('\n\n'.join(message)) for i, item in enumerate(result): if len(item) >= 3000: del result[i] chuncks = [] j = 0 for j in range(0, len(item), item.index(',', j+2950) + 1): try: chuncks.append(item[0+j:item.index(',', j+2950) + 1]) except Exception: chuncks.append(item[j - 1:]) # string[0+i:length+string.index(',', i - 50)] for i in range(0, len(string), length) for j, chunk in enumerate(chuncks): result.insert(i + j, chunk) return result
def settingsMarkup(chatID): markup = InlineKeyboardMarkup() currentSettings = Chats.objects(ID=chatID).get().settings settingsStrings = Language(chatID).strs.stg.strings for index, setting in enumerate(currentSettings): # * Will stop the foop if we have already iterated through all settings. # * Has to be stopped because "settings" object contains not only settings values, # * but some additional info connected to /settings command if index >= len(settingsStrings): break isOnString = '❌' settingObject = currentSettings[setting] if isinstance(settingObject, bool) and settingObject: isOnString = '✅' elif isinstance(settingObject, dict) and settingObject['haveTo']: isOnString = '✅' # * Creaing and adding all buttons to the markup. Will create using 2D array in config newButtons = [] for index, buttonInfo in enumerate(settingsStrings[index]): buttonText = buttonInfo[0] # * Formating button text if can be formated if canFormat(buttonText): buttonText = buttonText.format(settingObject['value']) tempButton = InlineKeyboardButton( f'{buttonText}', callback_data=buttonInfo[1], ) if not index: tempButton = InlineKeyboardButton( f'{buttonText} {isOnString}', callback_data=buttonInfo[1] ) newButtons.append(tempButton) markup.row(*newButtons) # ? Additional buttons buttonText = Language(chatID).strs.stg # * Editing button markup.row(InlineKeyboardButton( buttonText.editButtonValue, callback_data=additionalButtonCallbacks[0], )) # * Button to get more info markup.row(InlineKeyboardButton( buttonText.moreInfoButtonValue, callback_data=additionalButtonCallbacks[1] )) # * Button to move to Bot's chat addUrlButton(markup, Language(chatID).strs.goToBot[0], bot.get_me().username) # tempButton = InlineKeyboardButton( # f'{settingsStrings[index][0]} {isOnString}', # callback_data=settingsStrings[index][1] # ) # markup.add(tempButton) return markup
def modifyMessage(bot_instance, message): # * Checking if a message id an a chat id match a those which are in the DB. # * Then we assume, that the message it's a new value for a setting, so we # * change it. currentChat = Chats.getChat(message.chat.id) if currentChat is None: return editMessageInfo = currentChat.settings.editMessageInfo if (editMessageInfo and editMessageInfo['requestMessageId'] + 1 == message.message_id and editMessageInfo['requestChatId'] == message.chat.id): try: editArgument = int(message.text.split()[0]) # * Changing setting value and sending user a reponse originalChatId = editMessageInfo['originalChatId'] chatWeToChange = Chats.getChat(originalChatId) strings = Language(originalChatId).strs originalChat = Chats.getChat(originalChatId) # * Checking if new value is not the same as it was before oldValue = Settings.getSettingsValue(originalChat, editMessageInfo['commandName']) print(editArgument, oldValue) if editArgument == oldValue: raise ValueError() except ValueError as e: print(e) bot.send_message(message.chat.id, strings.stg.valueIsWrong) editMessageInfo['requestMessageId'] = message.message_id + 1 currentChat.save() # * Changes setting Settings.setSettingValue( chatWeToChange, editMessageInfo['commandName'], editArgument ) # * Deleting the spare replies, when the number of saved replies # * is higher then the new value of removeAfter idsToRemove = [] if editMessageInfo['commandName'] == 'removeAfter' and oldValue > editArgument: for i, response in enumerate(originalChat.responses.items()): if i >= oldValue - editArgument: break try: bot_instance.delete_message(originalChatId, int(response[0])) if response[1]['connectedIDs']: for chatId, ids in response[1]['connectedIDs'].items(): for id in ids: # pass bot_instance.delete_message(int(chatId), id) except ApiException as e: print(e) idsToRemove.append(response[0]) for toRemove in idsToRemove: del originalChat.responses[toRemove] originalChat.save() # * Updates settings message in the originalChat bot.edit_message_text( strings.stg.msgTitle, originalChatId, originalChat.settings.lastMessageId[0], reply_markup=settingsMarkup(originalChatId) ) # * Answering bot.answer_callback_query( editMessageInfo['callbackId'], strings.stg.changeSuccess )
def countWords(message): """ Handles text messages. Upates and save new information to the database, so it will be up-to-date to the real chat history. It's a main part of this bot """ global savedMessageID # * If a message contains a slash and it wasn't handled yet, command doesn' exist if message.text.strip()[0] == '/': bot.send_message(message.chat.id, message.replies.cnf) elif not 'http' in message.text: splitedMessage = splitSentence(message.text) if '' not in splitedMessage: # * Checking if current chat exists in the database an getting its object to use currentChat = Chats.getChat(message.chat.id) # * Update "counters" in database currentChat.sentWords += len(splitedMessage) currentChat.sentMessages += 1 wordsList = [] for part in splitedMessage: wordLower = part.lower() # * Adds a word in the list, if it's not fond in it wordsList = [word.text for word in currentChat.words] if not wordLower in wordsList or not currentChat.words: # * Adds new Word object object to the DB if there is't any tempWord = Word( text = wordLower, sentTimes = 1 ) currentChat.words.append(tempWord) # * Incriments the number of the word if it's found in the list else: # * Doing the same stuff, but in mongoDB for word in currentChat.words: if word.text == wordLower: word.sentTimes += 1 break # * Updating the topWord object in the DB wordNumbers = [word.sentTimes for word in currentChat.words] topSentTimes = currentChat.topWord.sentTimes if topSentTimes < max(wordNumbers) or not currentChat.topWord.text: wordsList = [word.text for word in currentChat.words] topIndex = wordNumbers.index(max(wordNumbers)) currentChat.topWord = Word( text = wordsList[topIndex], sentTimes = max(wordNumbers) ) print('savingTheDB') currentChat.save()
def sendStats(message): """ Sends a message with all words information in a special formated string, which is provide by 'stringsForStats' functionm. Gets informations from the database and splits the result of the funcion unsing built-in 'untils' methods. """ chatID = message.chat.id clearButton = types.InlineKeyboardButton( message.replies.skeyboard[0], callback_data=dumps(['toClearTrue', chatID]) ) # * Getting info from the DB to pass into the function currentChat = Chats.getChat(chatID) wordObjects = currentChat.words wordNumbers = [word.sentTimes for word in wordObjects] words = [word.text for word in wordObjects] sendToPrivate = Chats.getSettings(chatID)['sendPrivate'] chatName = None if sendToPrivate: chatName = message.chat.username formatedStrings = stringForStats(chatID, words, wordNumbers, True, chatName) markup = None # * Allowes to save message ids. More info in the class doc string editor = ResponsesManager(currentChat) if not formatedStrings: tempMessage = bot.send_message(message.chat.id, message.replies.nos) editor.addIDs(message.message_id, tempMessage) return # * If specified in settings will set chatID variable to users chat id, # * so the statistics will be sent not to the chat but to user pesonaly. if sendToPrivate: chatID = message.from_user.id if formatedStrings: # * Sending a splited message and adding an inline keyboard to the last element, # * so the user will be able to everything faster and more comftable. try: for index, part in enumerate(formatedStrings): if index + 1 == len(formatedStrings): markup = getDeleteMarkup(commands.s, message, clearButton) if message.chat.username and Chats.getSettings(message.chat.id)['sendPrivate']: addUrlButton(markup, message.replies.goToChat[0], message.chat.username) tempMessage = bot.send_message( chatID, part, reply_markup=markup, disable_notification=True, parse_mode='html' ) editor.addIDs(message.message_id, tempMessage, chatID) if Chats.getSettings(message.chat.id)['sendPrivate'] and message.chat.type != 'private': markup = types.InlineKeyboardMarkup() addUrlButton(markup, message.replies.goToBot[1], bot.get_me().username) editor.addIDs( message.message_id, bot.send_message( message.chat.id, message.replies.s[2].format( bot.get_me().username ), reply_markup=markup )) except apihelper.ApiException as e: print(e) editor.addIDs( message.message_id, bot.send_message( message.chat.id, message.replies.s[3].format( bot.get_me().username )))