Skip to content
Permalink
Browse files
Referencing fixed
  • Loading branch information
grantb3 committed Nov 27, 2018
2 parents 09adae3 + 6b30abd commit 95bf33a5182b4e0539dded15fb6f58dd0c0b406e
Show file tree
Hide file tree
Showing 13 changed files with 304 additions and 220 deletions.
@@ -6,6 +6,12 @@
/._pycache_
/kopia
/TextExtracts
/seq2seq
/py-googletrans
/BOT
/botsfloor
/nlp



names.json
@@ -9,6 +9,15 @@ Libraries being used:
- bs4 (https://www.crummy.com/software/BeautifulSoup/) by Leonard Richardson for parsing HTML pages
- discord.py (https://github.com/Rapptz/discord.py/) by Rapptz used to connect to Discord.
- selenium (https://docs.seleniumhq.org/) by (originally) Jason Huggins used to scrap pages that use javascript calls for data (translate module)
- googletrans(https://pypi.org/project/googletrans/) by SuHun Han used as Google Translate API


If you get an error (error 'NoneType' object has no attribute 'group') when using googletrans follow these instructions:
Step 1. pip uninstall googletrans
Step 2. clone https://github.com/BoseCorp/py-googletrans.git
Step 3. ./py-googletrans
Step 4. setup.py install


How to get god-forsaken Selenium to work:
(https://selenium-python.readthedocs.io/installation.html)
@@ -6,16 +6,18 @@ import discord
import asyncio
import wikipedia
import stackoverflow
import translate
import hangman
import conversate
import pickle
import os
import json
import translatesimple
import hangman

client = discord.Client()

#Returns help string
##################################################
# Benjamin Grant
# Returns help string
def commands():
commandList = "What can I do?\n"
commandList += "!q\n"
@@ -63,42 +65,55 @@ def initialise_files():
json.dump(names, open("names.json", "w"))

print("Initialisation complete.")

##################################################


@client.event
#Called on login
# Called on login
async def on_ready():

print('[*] ' + client.user.name + ' ('+client.user.id+') logged in')

initialise_files()

await client.change_presence(game=discord.Game(name="Chat to me!"))



@client.event
#Called whenever it receives a message
# Called whenever it receives a message
async def on_message(message):


await conversate.processMessage(client, message)

##################################################
# Benjamin Grant
if message.author.id == client.user.id:
return

await conversate.processMessage(client, message) # Commands and functionality by Benjamin Grant may be found here

if message.content.lower().startswith('!help'):
await client.send_message(message.channel, commands())
##################################################

##################################################
# Konrad Czarniecki

# command is !wiki search_word
elif message.content.lower().startswith('!wiki'):
await wikipedia.wikipedia(client, message)

# command is !flow search_phrase_here. Then '!f na' for next answer, '!f nq' for next question
elif message.content.lower().startswith('!flow'):
await stackoverflow.stackoverflow(client, message)

# command is !translate from_language to target_language your_query e.g !translate english to french i hate selenium
elif message.content.lower().startswith('!translate'):
await translate.translate(client, message)
await translatesimple.translate(client, message)

elif message.content.lower().startswith('!hangman'):
await hangman.hangman(client, message)

elif message.content.lower().startswith('!help'):
await client.send_message(message.channel, commands())
##################################################


#This token is linked to Ben's discord account/applications - sets bot account
@@ -1,3 +1,5 @@
##################################################
# Benjamin Grant
import random
import namestore
import datetime
@@ -7,47 +9,48 @@ import exchange

# Unlearns a word or category
async def unlearn(category=None, word=None):
if word == None:

if word == None: #Category being unlearned
with open("brain.pck", "rb") as f:
map = pickle.load(f)
brain = pickle.load(f) # Dictionary of category: [words]

if category in map:
del map[category]
if category in brain:
del brain[category]

with open("brain.pck", "wb") as f:
pickle.dump(map, f)
pickle.dump(brain, f)

elif category == None:
elif category == None: #Word being unlearned
with open("brain.pck", "rb") as f:
map = pickle.load(f)
brain = pickle.load(f)

if category in map:
if word in map[category]:
map[category].remove(word)
if category in brain:
if word in brain[category]:
brain[category].remove(word) #This maintains category while removing word

with open("brain.pck", "wb") as f:
pickle.dump(map, f)
pickle.dump(brain, f)


# Enables the bot to learn new words or categories and save them for later use
async def learn(category, word):
with open("brain.pck", "rb") as f:
map = pickle.load(f)
brain = pickle.load(f) # Dictionary of category: [words]

if category in map:
if word not in map[category]:
if category in brain:
if word not in brain[category]:
if type(word) is str:
map[category].append(word)
brain[category].append(word)
else:
map[category] = map[category] + word
brain[category] = brain[category] + word
else:
if type(word) is str:
map[category] = [word]
brain[category] = [word]
else:
map[category] = word
brain[category] = word

with open("brain.pck", "wb") as f:
pickle.dump(map, f)
pickle.dump(brain, f)

# Gets a random response for a given category
async def get_response(category):
@@ -57,9 +60,9 @@ async def get_response(category):
if category in map:
return random.choice(map[category])
else:
return None
return None #Check for None (invalid category, used for unit tests)

# Replaces string variables such as %name%
# Replaces in-string variables such as %name%
async def replacePlaceholders(msg, user):
name = await namestore.get_name(user.id)

@@ -70,9 +73,11 @@ async def replacePlaceholders(msg, user):

return ret

# Process commands or requests for modules
# Process commands or requests for modules. Return the message to be sent to the user
async def processCommands(message, id):
tokenised = message.split(" ")

tokenised = message.split(" ") #NLTK-less way to split by word (in basic cases)

quote_triggers = ("show me a quote",
"inspire me",
"motivate me",
@@ -84,6 +89,7 @@ async def processCommands(message, id):
currency_triggers =("what is", "how much is", "exchange", "convert")

if message.startswith('my name is'):

if len(tokenised) <= 3:
return 'Please provide a name.'
else:
@@ -104,12 +110,16 @@ async def processCommands(message, id):
else:
return 'Your name is ' + name.strip() + "."

#Usage: what is 100 GBP in USD
#Example usage: what is 100 GBP in USD
for trigger in currency_triggers[0]:

if message.startswith(trigger):

words = len(trigger.split(" "))

if tokenised[words+3] == "in":
try:

try: #Hacky, rushed way to parse text and split into arguments
amount = float(tokenised[words+1])
base_cur = tokenised[words+2].upper()
to_cur = tokenised[words+4].upper()
@@ -129,48 +139,48 @@ async def processCommands(message, id):
# Actual processing of message content and response
async def processMessage(client, message):

if client.user.id == message.author.id:
if client.user.id == message.author.id or message.content.startswith("!"):
return

text = message.content.lower()

response = await processCommands(text, message.author.id)

if response == None:
if response == None: #No command was detected in the text
response = "Sorry %name%, I don't know what you mean by '" + message.content + "'. Use !help for information about my functionality."

greeting = ("hi",
"hello",
"yo",
"sup",
"hey",
"suh")

states = ("how are you",
"how're you",
"are you okay",
"how do you feel",
"what's up",
"suh")

categories=(greeting, states)

matched=False

for greet in greeting:
if text.startswith(greet):
response = await get_response("GREETING")
matched=True
break
greeting = ("hi",
"hello",
"yo",
"sup",
"hey",
"suh")

states = ("how are you",
"how're you",
"are you okay",
"how do you feel",
"what's up",
"suh")

categories=(greeting, states)

if not matched:
for state in states:
if text.startswith(state):
response = await get_response("STATE")
matched=False

for greet in greeting:
if text.startswith(greet):
response = await get_response("GREETING")
matched=True
break

if not matched:
for state in states:
if text.startswith(state):
response = await get_response("STATE")
matched=True
break

response = await replacePlaceholders(response, message.author)

await client.send_message(message.channel, response)
##################################################
@@ -1,14 +1,18 @@
##################################################
# Benjamin Grant
"""
Libraries:
- requests (http://docs.python-requests.org/en/master/) by Kenneth Reitz for web requests
requests (http://docs.python-requests.org/en/master/) by Kenneth Reitz used for retrieving data from the web
The idea for this module is from Codio Week 1. The use of XML ElementTree also derived from there, however the logic was entirely created myself with help from https://docs.python.org/2/library/xml.etree.elementtree.html
"""
import requests
import xml.etree.ElementTree as ET

""" Returns a dictionary of currencies and rates. Coded with help from https://docs.python.org/2/library/xml.etree.elementtree.html """
# Returns a dictionary of currencies and rates
async def getCurrencyDictionary():
# Use of a context manager taken from http://docs.python-requests.org/en/master/api/#request-sessions
with requests.Session() as r:
response = r.get("http://www.ecb.europa.eu/stats/eurofxref/eurofxref-daily.xml").text

root = ET.fromstring(response)
curr={}
for child in root[2][0]:
@@ -24,4 +28,5 @@ async def convertCurrency(to, base, amount):
return amount

currencies = await getCurrencyDictionary()
return amount*currencies[to]/currencies[base]
return amount*currencies[to]/currencies[base]
##################################################

0 comments on commit 95bf33a

Please sign in to comment.