Skip to content
Permalink
Browse files
Merge remote-tracking branch 'origin/master'
  • Loading branch information
kubiliu2 committed Nov 6, 2018
2 parents 56f5cb8 + 4efb676 commit 5c09b1cfa3976d728560abdd7c0db11e72a09cab
Show file tree
Hide file tree
Showing 9 changed files with 376 additions and 67 deletions.
@@ -1,30 +1,67 @@
# chatbot
ChatBot for Discord
# Discord ChatBot

Download this, check README
https://github.com/Rapptz/discord.py


Get PyCharm, get pip and the rest of the libraries, PYTHON 3.6.6 (3.7 has problems with discord lib)

**main.py** will be the file you run in order to start the bot.

In order to make things easier to understand, we'll divide the features of the chatbot into more functions that are located in different modules (files).

For example: in order for the bot to respond to your "!hello", the main.py file imports the function named
*basicFunctions* from the basicFunctionsFile module.

This way, not only won't we have an endless main.py module but we will also be able to work individually on various
features within our own modules and once completed, simply import them in main.py with a single line of code.




**botClient.py** is required for the bot to run, it basically makes the variable *client* (which happens to be used
literally everywhere in our code) connect our code to Discord (or something like that I guess).

So for every new module/file you create, don't forget to add ``from botClient import client``.




https://www.digitaltrends.com/gaming/how-to-make-a-discord-bot/

https://www.devdungeon.com/content/make-discord-bot-python

https://www.devdungeon.com/content/make-discord-bot-python-part-2

# Requirements:

Get PyCharm, get pip and the rest of the libraries, **PYTHON 3.6.6** (3.7 has problems with discord lib)
https://github.com/Rapptz/discord.py (Download it, also check the README, it has instructions on how to install)

### Update to the new discord.py 1.0 lib (rewrite ver.)

Make sure you get the latest version of discord.py! Not 0.16, but 1.0 (REWRITE)
In order to do this, upgrade your pip from 10 to 18 using ``python -m pip install --upgrade pip`` in command prompt.

After that, use the command ``python -m pip install -U git+https://github.com/Rapptz/discord.py@rewrite#egg=discord.py[voice]`` in PyCharm Terminal.

Note that the latest version of discord.py (rewrite) has some changes, it's almost like an entirely different library.
Even so, it's better if we make the change now while we will learn than later.

Here is the documentation:
https://discordpy.readthedocs.io/en/rewrite/migrating.html

Basically you're gonna have this open in a tab at all times, it's pretty much a manual
Even the way you send messages has been changed:
https://discordpy.readthedocs.io/en/rewrite/migrating.html#migrating-1-0-sending-messages

Also, the discord.py 1.0 REWRITE library is new, it's been scheduled to fully release on 2018/11/01. This means that most video guides on YouTube will require most of the commands to be converted to discord.py 1.0 (from 0.16).

Important Links:
-----------------------------------------------------------------------
https://discordpy.readthedocs.io/en/rewrite/migrating.html
https://discordpy.readthedocs.io/en/latest/faq.html
https://discordpy.readthedocs.io/en/rewrite/ext/commands/commands.html
https://discordpy.readthedocs.io/en/rewrite/api.html
-----------------------------------------------------------------------
Tutorials:
-----------------------------------------------------------------------
https://www.digitaltrends.com/gaming/how-to-make-a-discord-bot \
https://www.devdungeon.com/content/make-discord-bot-python \
https://www.devdungeon.com/content/make-discord-bot-python-part-2 \
https://www.devdungeon.com/content/ai-chat-bot-python-aiml

https://www.devdungeon.com/content/ai-chat-bot-python-aiml
@@ -0,0 +1,34 @@
import asyncio
from discord.ext import commands
from botClient import client

class BasicFunctions:
def __init__(self, client):
self.client = client

@commands.command()
async def test(self, ctx):
counter = 0
tmp = await ctx.message.channel.send('Calcuating messages...')
async for log in ctx.message.channel.history(limit = int(100)):
if log.author == ctx.message.author:
counter += 1
await tmp.edit(content=f'You have {counter} messages.')

@commands.command()
async def sleep(self, ctx):
await ctx.message.channel.send('Going to sleep for 10 seconds.')
await asyncio.sleep(10)
await ctx.message.channel.send('Done sleeping, thanks.')

@commands.command()
async def hello(self, ctx):
await ctx.message.channel.send(f'Hello, {ctx.message.author.mention}!')

@commands.command()
async def uok(self, ctx):
await ctx.message.channel.send('Yes I am.')

def setup(client):
client.add_cog(BasicFunctions(client))

@@ -0,0 +1,5 @@
import discord
from discord.ext import commands

botToken = "NTA1ODE5NDgxNTY2NjA5NDE4.DraAUg.Zkf31aGXgR0kt6WRkj_XcSaPSF0"
client = commands.Bot(command_prefix='$')
Empty file.
@@ -0,0 +1,127 @@
import discord
from botClient import client
import random
from discord.ext import commands

guessAttemptsRight = 0
guessAttemptsTotal = 0
guessAttemptsTimeout = 0

class GuessGame:
def __init__(self, client):
self.client = client

@commands.command()
async def gstats(self, ctx):
if guessAttemptsTotal == 0:
await ctx.message.channel.send("You haven't attempted the guess game yet.")
return
if guessAttemptsRight == 0:
guessRate = str(0) + '%'
else:
guessRate = str(round((guessAttemptsRight * 100) / guessAttemptsTotal, 1)) + '%.'

embed = discord.Embed(title="Stats", description="Letter guess game statistics", color=0x17e6f0)
embed.add_field(name="Successful attempts: ", value=str(guessAttemptsRight), inline=True)
embed.add_field(name="Total attempts: ", value=str(guessAttemptsTotal), inline=True)
embed.add_field(name="Attempt success rate: ", value=str(guessRate), inline=True)
embed.add_field(name="Timeouts: ", value=str(guessAttemptsTimeout), inline=True)
await ctx.message.channel.send(embed=embed)

@commands.command()
async def greset(self, ctx):
global guessAttemptsRight
global guessAttemptsTotal
global guessAttemptsTimeout
guessAttemptsRight = 0
guessAttemptsTotal = 0
guessAttemptsTimeout = 0
await ctx.message.channel.send('Guess game results history has been cleared.')

@commands.command()
async def guess(self, ctx):
global guessAttemptsRight
global guessAttemptsTotal
global guessAttemptsTimeout
await ctx.message.channel.send('Guess a lowercase letter from the English alphabet.')

letterList = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's',
't',
'u', 'v', 'w', 'x', 'y', 'z']
letterPosition = random.randint(0, 25)
answer = letterList[letterPosition]

maxAttempts = 3
counter = 1
# answer = 'z' #testing purposes
# letterPosition = 25 #testing purposes
while counter <= maxAttempts:

def pred(m):
return m.author == ctx.message.author and m.channel == ctx.message.channel

guess = await client.wait_for('message', check=pred, timeout=7)

if guess is None:
await ctx.message.channel.send(f'Sorry, you took too long. It was "{answer}".')
guessAttemptsTimeout += 1
if counter != 1:
guessAttemptsTotal += 1
await ctx.message.channel.send(
'Player quit while game was in progress. Added as a loss.')
else:
await ctx.message.channel.send(
"Player didn't start the game. Not counted as a loss.")
return

if guess.content == '$guess':
if counter != 1:
guessAttemptsTotal += 1
await ctx.message.channel.send("**Started new game.** (Old game counted as loss.)")
else:
await ctx.message.channel.send("**Started new game.**")
return

try:
# print (answer) #for testing purposes
guessPosition = letterList.index(str(guess.content)) # saves the position of the guess letter
except ValueError:
await ctx.message.channel.send(
'That is not a valid input (single lowercase English letters only).')
if counter != 1:
guessAttemptsTotal += 1
await ctx.message.channel.send('Game reset.')
return

if str(guess.content) == answer:
if counter == 1:
await ctx.message.channel.send(f'LUCKY! The answer is indeed "{answer}".')
else:
await ctx.message.channel.send(f'You are right! The answer is indeed "{answer}".')
await ctx.message.channel.send('Guessed correctly after ' + str(counter) + ' attempt(s).')
guessAttemptsRight += 1
guessAttemptsTotal += 1
return

else:
if maxAttempts - counter == 0:
await ctx.message.channel.send(
f'Max attempts reached. Sorry. It was actually "{answer}".')
guessAttemptsTotal += 1
return
else:
await ctx.message.channel.send('Wrong. You have {} attempt(s) left.'
.format(maxAttempts - counter))

if abs(guessPosition - letterPosition) > 12: # these 4 lines took me 2 hours fml
answerDistance = 26 - abs(guessPosition - letterPosition)
else:
answerDistance = abs(letterPosition - guessPosition)

await ctx.message.channel.send(f'Hint: The letter you are looking for is {answerDistance} positions away.')

counter += 1


def setup(client):
client.add_cog(GuessGame(client))
@@ -0,0 +1,95 @@
import discord
from botClient import client
from discord.ext import commands

class BasicFunctionsHelp:
def __init__(self, client):
client.self = client

@commands.command()
async def comhelp(self, ctx):
embed = discord.Embed(title='Commands List', description=
"Use **$** in front of the command name \n"
"Example: $hello"
, color=0x17e6f0)

embed.add_field(name="Chat", value=
"``hello`` - Greet Simon \n "
"``uok`` - Check if Simon is okay \n"
"``test`` - Counts recent messages"
,inline=False)

embed.add_field(name="Games", value=
"``guess`` - Start playing a letter guessing game \n"
"``ghelp`` - Letter guessing game explanation \n"
"``gstats`` - See your guessing game statistics \n"
"``greset`` - Reset your guessing game statistics"
,inline=False)
embed.set_thumbnail(url=ctx.message.author.avatar_url)
embed.set_footer(text='Requested by ' + ctx.message.author.name + '.', icon_url=ctx.message.author.avatar_url)
await ctx.message.channel.send(embed=embed)

@commands.command()
async def comlist(self, ctx):
embed = discord.Embed(title='Commands List', description=
"Use **$** in front of the command name \n"
"Example: $hello"
, color=0x17e6f0)

embed.add_field(name="Chat", value=
"``hello`` - Greet Simon \n "
"``uok`` - Check if Simon is okay \n"
"``test`` - Counts recent messages"
,inline=False)

embed.add_field(name="Games", value=
"``guess`` - Start playing a letter guessing game \n"
"``guesshelp`` - Letter guessing game explanation \n"
"``gstats`` - See your guessing game statistics \n"
"``greset`` - Reset your guessing game statistics"
,inline=False)
embed.set_thumbnail(url=ctx.message.author.avatar_url)
embed.set_footer(text='Requested by ' + ctx.message.author.name + '.', icon_url=ctx.message.author.avatar_url)
await ctx.message.channel.send(embed=embed)

@commands.command()
async def guesshelp(self, ctx):
embed = discord.Embed(title = 'Guessing Game - How to Play', description =
"Letter Guessing Game Tutorial and Explanation", color=0x17e6f0)

embed.add_field(name="Objective", value=
"The objective is to find the correct letter from the alphabet. \n"
"You have 3 attempts. You win if you manage to guess the letter. \n"
"If you inputted 3 letters and none of them were the one chosen by the bot, you lose."
, inline=False)

embed.add_field(name="How do I play?", value=
"Start the game using the command ``$guess``. \n"
"The bot will ask you for a letter. You have 7 seconds to input a lowercase English alphabet letter"
" or the game will timeout and reset. \n"
"If you manage to score in the first try, you will get a ``LUCKY``. \n"
"If you don't, that's okay. You still have 2 attempts. Make sure you use the hints explained below. \n"
"After playing, you can check your stats using ``$gstats``. You can also reset them using ``$greset``"
, inline=False)

embed.add_field(name="How do I increase my chances?", value=
"The game will give hints in the form of distance to the correct letter "
"from your currently selected one. \n"
"**Example1:** If 'd' is the correct answer and you've chosen 'a', "
"you will get ``Hint: The letter you are looking for is 3 positions away.`` \n"
"Going 3 spots to the right will net you the correct answer. \n"
"The hints go in both directions: \n"
"**Example2** If 'z' is the correct answer and you've chosen 'b', you will get "
"``Hint: The letter you are looking for is 2 positions away.`` and not 24 positions. \n"
"Imagine the beginning and end of the alphabet connected, like this: `` ... w, x, y, z, a, b, c, d, e ...`` \n"
"So whether you go to the right or to the left is up to you. \nKeep in mind that it is possible to get every "
"answer right as long as you start with 3 attempts (including the initial guess)."
, inline=False)

embed.set_footer(text = "Requested by " + ctx.message.author.name + '.', icon_url= ctx.message.author.avatar_url)

await ctx.message.channel.send(embed=embed)


def setup(client):
client.add_cog(BasicFunctionsHelp(client))
48 main.py
@@ -0,0 +1,48 @@
import asyncio
import discord
from discord.ext import commands
import sys, traceback
from botClient import client
from botClient import botToken
import guessFile

extensions = ['test', 'basicFunctionsFile', 'helpFile', 'guessFile'] #Extensions list

@client.event
async def on_ready():
print('Logged in as')
print(client.user.name)
print('CID: ' + str(client.user.id))
print('-----------------------')

if __name__ == '__main__': #Load extensions from other modules
for extension in extensions:
try:
client.load_extension(extension)
except Exception as error:
print(f'{extension} cannot be loaded [{error}]')


@client.event
async def on_message(message):
if message.author == client.user:
return

if message.content == 'hai':
await message.channel.send('YES')

await client.process_commands(message) #So that events don't disable commands

@client.event
async def on_member_join(member):
# print(ctx.author.guild.name) testing
await message.channel.send(f'Welcome {member.mention} to {member.guild.name}!')
await client.process_commands(message) #So that events don't disable commands

@client.command()
async def ctest(ctx):
await ctx.send('I heard you! {}'.format(ctx.author.mention))


client.run(botToken)

0 comments on commit 5c09b1c

Please sign in to comment.