Skip to content
Permalink
master
Switch branches/tags

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?
Go to file
 
 
Cannot retrieve contributors at this time
"""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