/
clumsyrobot.py
135 lines (116 loc) · 4.2 KB
/
clumsyrobot.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
# # # # #
# clumsyrobot.py
# v1.1.1 05/11/2019
# # # # #
from markov import Markov
from random import random
import pickle
try:
import discord
except ImportError:
print('ERROR: discord.py must be installed! (pip install -U discord.py)')
exit()
# # # # #
# Config values
# # # # #
# read the config file
CONFIG_FILE_NAME = 'clumsyrobot.cfg'
print('*** Loading config data from {}...'.format(CONFIG_FILE_NAME))
try:
config_file = open(CONFIG_FILE_NAME, 'r')
except IOError:
print('*** Could not load config file!')
exit()
# parse the config data
try:
config = {}
for line in config_file.readlines():
var, val = line.split('=')
config[var.strip()] = val.strip()
config_file.close()
except ValueError:
print('*** Malformed config file!')
exit()
# DISCORD_API_TOKEN: bot token used to authenticate with Discord API
try:
DISCORD_API_TOKEN = str(config['DISCORD_API_TOKEN'])
except KeyError:
print('*** No DISCORD_API_TOKEN value specified in config file! Cannot connect to Discord!')
exit()
except TypeError:
print('*** DISCORD_API_TOKEN value in config file is malformed! Cannot connect to Discord!')
exit()
# MESSAGES_PER_AUTOSAVE: messages received before backing up markov data
try:
MESSAGES_PER_AUTOSAVE = int(config['MESSAGES_PER_AUTOSAVE'])
except KeyError:
print('No MESSAGES_PER_AUTOSAVE value specified in config file. Using default.')
MESSAGES_PER_AUTOSAVE = 25
except TypeError:
print('*** MESSAGES_PER_AUTOSAVE value in config file is malformed!')
exit()
# RESPONSE_FREQUENCY: probability that clumsy will respond to any given message
try:
RESPONSE_FREQUENCY = float(config['RESPONSE_FREQUENCY'])
except KeyError:
print('No RESPONSE_FREQUENCY value specified in config file. Using default.')
RESPONSE_FREQUENCY = 0.05
except TypeError:
print('*** RESPONSE_FREQUENCY value in config file is malformed!')
exit()
# MARKOV_DATA_SAVE_LOCATION: path to the file where the serialized markov data is saved
try:
MARKOV_DATA_SAVE_LOCATION = str(config['MARKOV_DATA_SAVE_LOCATION'])
except KeyError:
print('No MARKOV_DATA_SAVE_LOCATION value specified in config file. Using default.')
MARKOV_DATA_SAVE_LOCATION = 'markov_data.pkl'
except TypeError:
print('*** MARKOV_DATA_SAVE_LOCATION value in config file is malformed!')
exit()
# # # # #
# Discord client implementation
# # # # #
class ClumsyRobot(discord.Client):
def __init__(self):
# load the markov chain data
print('*** Loading markov data from {}...'.format(MARKOV_DATA_SAVE_LOCATION))
try:
with open(MARKOV_DATA_SAVE_LOCATION, 'rb') as markov_file:
self._markov = Markov(pickle.load(markov_file))
markov_file.close()
except IOError:
print('*** Unable to load file!')
self._markov = Markov()
self._messages_since_last_autosave = 0
super().__init__()
# Connected as a discord client
async def on_ready(self):
print('*** Connected as {}.'.format(self.user))
# Message received
async def on_message(self, message):
# don't respond to or learn from our own messages
if message.author == self.user:
return
# learn and occasionally engage in discussion
content = message.content.lower()
self._markov.DigestInput(content)
if random() < RESPONSE_FREQUENCY:
response = self._markov.GenerateChain(content)
await message.channel.send(response)
# save the markov data sometimes
self._messages_since_last_autosave += 1
if self._messages_since_last_autosave == MESSAGES_PER_AUTOSAVE:
print('*** Saving markov data to {}...'.format(MARKOV_DATA_SAVE_LOCATION))
try:
with open(MARKOV_DATA_SAVE_LOCATION, 'wb') as markov_file:
pickle.dump(self._markov.GetData(), markov_file)
markov_file.close()
self._messages_since_last_autosave = 0
except IOError:
print('*** Unable to save file!')
# # # # #
# Startup/Initialization
# # # # #
print('*** Starting clumsyrobot...')
clumsy = ClumsyRobot()
clumsy.run(DISCORD_API_TOKEN)