Permalink
Cannot retrieve contributors at this time
Name already in use
A tag already exists with the provided branch name. Many Git commands accept both tag and branch names, so creating this branch may cause unexpected behavior. Are you sure you want to create this branch?
Python_Telegram_Chat_bot/chat_bot_main.py
Go to fileThis commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
157 lines (116 sloc)
7.93 KB
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
"""this is a chat bot built in python for use with the telegram API""" | |
"""requests can be installed using pip with the "pip install requests" command | |
requests documentation can be found at : http://docs.python-requests.org/en/master/ | |
requests can be used to make http requests to a website and is used in my project to retrieve JSON objects from a url""" | |
import requests | |
"""chatterbot can be installed using pip with the "pip install chatterbot" command | |
chatterbot documentation can be found at : https://chatterbot.readthedocs.io/en/stable/ | |
chatterbot is used in my project to generate responses based on training data provided both by custom corpuses and those prepackaged with the library | |
NOTE : the file created by "create_movie_corpus.py" must be moved to the "custom" library in the the chatterbot_corpus library folder, a conventional installation location for this would be : "C:\Program Files\Python36\Lib\site-packages\chatterbot_corpus\data\custom" """ | |
from chatterbot import ChatBot | |
from chatterbot.trainers import ChatterBotCorpusTrainer | |
import json #standard library | |
import webbrowser #standard library | |
import time #standard library | |
import logging #standard library | |
#this allows for log files to be created and appended to | |
logging.basicConfig(filename='chat_bot_logs.txt', level = logging.INFO, format='%(levelname)s : %(asctime)s : %(message)s') | |
my_bot_token = "755874438:AAFh2b2XebMD4p-cSGEdav59Ibwj-LBZhrI" | |
#this is the url where all pending messages will be viewable from | |
receive_messages_url = "https://api.telegram.org/bot755874438:AAFh2b2XebMD4p-cSGEdav59Ibwj-LBZhrI/getUpdates" | |
#all messages up to message id given have been processed and can be discarded | |
acknowledge_messages = "https://api.telegram.org/bot755874438:AAFh2b2XebMD4p-cSGEdav59Ibwj-LBZhrI/getUpdates?offset={}" | |
# anything added onto the end of the "send_messages_url" is the message that is sent to the user | |
# chat_id = the user that the message is sent to | |
# chat_id must be formatted using "send_messages_url.format(chat_id,message)" (because of the square braces) | |
send_messages_url = "https://api.telegram.org/bot755874438:AAFh2b2XebMD4p-cSGEdav59Ibwj-LBZhrI/sendMessage?chat_id={}&text={}" | |
"""checks for new messages from the get_url function and places them into an array for individual processing""" | |
def new_messages_array(): | |
message_array = [] | |
JSON = get_url(receive_messages_url) | |
for i in range(0, (len(JSON['result']))): | |
message_array.append(JSON['result'][i]) | |
return message_array | |
"""reads the logs from the "receive_messages_url" and gets the json information, converts it into a py dictionary""" | |
"""this function was taken from the tutorial at 'https://www.codementor.io/garethdwyer/building-a-telegram-bot-using-python-part-1-goi5fncay'""" | |
def get_url(url): | |
out = requests.get(url) | |
out = out.content.decode("utf8") | |
out = json.loads(out) | |
return out | |
"""the below functions get get essential information about messages from the message given to them from the new_messages_array""" | |
def get_user_id(message): | |
out = message['message']['from']['id'] | |
return out | |
def get_first_name(message): | |
out = message['message']['from']['first_name'] | |
return out | |
def get_last_name(message): | |
out = message['message']['from']['last_name'] | |
return out | |
def get_update_id(message): | |
out = message['update_id'] | |
return out | |
def get_message_id(message): | |
out = message['message']['message_id'] | |
return out | |
def get_text(message): | |
out = message['message']['text'] | |
return out | |
"""end of codementor tutorial""" | |
"""this is the function that will generate the responses and give them to the user""" | |
def local_chat_bot(message): # always takes in only a single message from message_array | |
user_id = get_user_id(message) | |
first_name = get_first_name(message) | |
last_name = get_last_name(message) | |
update_id = get_update_id(message) | |
message_id = get_message_id(message) | |
text = get_text(message) | |
if text == "/start": #the first message that must be sent to the bot must be /start, this is a rule set by the telegram API, this if statement will check to see if this is that /start command and if it is, it will reply with the pre determined message which introduces the user to the chatbot | |
# can put in more emails but need to check if its okay with others first | |
send = "Hi there {} {}, I'm py_chat_bot! I was built by a small group of students at unviersity over a six week period. I can make use of the Google API, provide games to play, and make general conversation. We would love for you to provide any feedback to us to the contacts below :) Fred Cook - fredcook789@gmail.com Thankyou".format(first_name,last_name) | |
# manage to get this to output in multiple lines then format it to do so | |
logging.info(('message_id = {} \n text = {}\n reply = {} \n').format(message_id, text, send)) #these can be removed, used for debugging and development | |
webbrowser.open(send_messages_url.format(user_id, send)) | |
webbrowser.open(acknowledge_messages.format(update_id + 1)) | |
else: #if the user does not send /start then get a response from the chatbot and reply with it | |
send = reply(text) | |
# send = send.capitalize() this seemed like a good idea, however, it always resulted in the program crashing, could be fixed at a later date | |
print("message {} replied to. text = {}. Reply = {}".format(message_id, text, send)) | |
webbrowser.open(send_messages_url.format(user_id, send)) | |
webbrowser.open(acknowledge_messages.format(update_id + 1)) | |
logging.info(('message_id = {} \n text = {}\n reply = {} \n').format(message_id, text, send)) | |
"""this is the function that starts the program, it could be made into a separate 'main' file, it calls the other functions and at the end it 'acknowledges messages' as to allow for more than 100 messages to be on the receive_messages_url at any given time""" | |
def start(): | |
logging.info('New program run \n') #separates multiple runs of the program in the log files | |
while True: | |
try: | |
new_message_array = new_messages_array() | |
while len(new_message_array) > 0: | |
local_chat_bot(new_message_array[0]) | |
new_message_array.pop(0) | |
logging.info('message popped') | |
print("No new messages") | |
# THIS CAN BE REMOVED, THIS IS SUPPOSED TO SIMULATE THE CHAT_BOT FUNCTION TAKING TIME | |
time.sleep(5) #may need to keep this as telegram api rules state a maximum polling rate, if we don't receive enough messages we will have to keep this, potentially increase the time | |
# need to be able toclear the receive_message_url and marks them all as replied to | |
logging.info('successful start loop run') | |
except: | |
print("no new messages") | |
"""this function is called with text given by the user and returns the text that the chatbot generates""" | |
def reply(message): | |
response = chatterbot.get_response(message) | |
#print(chatterbot.utils.get_response_time(chatbot)) this prints the amount of time taken for the bot to respond, good for testing | |
return response | |
if __name__ == "__main__": | |
"""the following code takes inspiration from the examples found on the chatterbot documentation website mentioned above""" | |
chatterbot = ChatBot("Training Example") | |
chatterbot.set_trainer(ChatterBotCorpusTrainer) | |
filters=("chatterbot.filters.RepetitiveResponseFilter") | |
chatterbot.train("chatterbot.corpus.english") | |
chatterbot.train("chatterbot.corpus.custom.movie_lines_corpus") | |
"""end of chatterbot examples""" | |
print("training finished") | |
start() | |
#TODO: set up long polling ideally | |
#TODO: design a way to have the program decide if the input from the user is soemthing that the google APIs should be queried for e.g. "where is the nearest restaurant?", or if it is soemthing that should be sent to the chat bot function so maybe something like if 'nearest in message ... go to google APIs else... go to chat_bot |