This repository has been archived by the owner on Dec 26, 2021. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 0
/
turnipsPredictor.py
358 lines (342 loc) · 21.2 KB
/
turnipsPredictor.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
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
"""
Contains the cog for the turnip commands.
"""
from discord.ext import commands
import turnipCalculator
import datetime
import turnipSummaryImage
import discord
import errors
import timezoner
getDateAcquirer = timezoner.Timezoner("userData")
def getDate(date: str, discordID: str) -> datetime:
try:
if date == "Today":
date = getDateAcquirer.getCurrentDatetime(discordID)
else:
date = datetime.datetime.strptime(date, '%d/%m/%Y')
except ValueError:
raise errors.InvalidDateFormat
return date
class Turnips(commands.Cog):
def __init__(self, bot):
self.bot = bot
@commands.command(name='ap', help="Adds price to the turnip price storage"
"\n<Time> : Either PM or AM "
"\n<bells> : The bells you get for selling turnips"
"\n[date]: OPTIONAL the date you want to enter price for in DD/MM/YYYY",
aliases=['AddPrice', 'addprice'])
async def addTurnipPrice(self, ctx, time, bells, date="Today"):
response = "An Error Has Occurred!"
time = time.upper() # Turns the time given into Uppercase
if not bells.isdigit():
response = "Bells must be given as a number! E.g 1-9"
elif time == 'AM' or time == 'PM':
try:
date = getDate(date, ctx.message.author.id)
if turnipCalculator.addData(ctx.message.author.id, date, time, bells):
response = "Added price of {} bells for {} at {}".format(bells,
date.strftime('%d/%m/%Y'),
time)
except errors.InvalidDateTime:
response = "Time given to internal system was Invalid\n" \
"Has to be either `AM` or `PM`"
except errors.InvalidPeriod:
response = "You can't give me a time and price for Sunday!"
except errors.InvalidDateFormat:
await ctx.send("Error: Invalid Date format given")
except errors.AWSError as error:
response = "Unable to store data!\nError been reported to operator"
print("ERROR:\nDiscordID: {}\nTime:{}\nError:{}\n-----".format(ctx.message.author.id,
datetime.datetime.now(),
error))
except Exception as e:
response = "Internal Error, sorry >.<\nIssue has been reported to operator.\n(ap.catch.rest)"
print("ERROR:\nDiscordID: {}\nTime:{}\nError:{}\n-----".format(ctx.message.author.id,
datetime.datetime.now(),
e))
else:
response = "Time isn't correct, has to be either `AM` or `PM`"
await ctx.send(response)
@commands.command(name='ts', help="Get your Turnip Summary"
"\n[date]: OPTIONAL Get your summary for a specific week in DD/MM/YYYY",
aliases=['TurnipSummary', 'turnipsummary'])
async def currentTurnipSummary(self, ctx, date="Today"):
try:
date = getDate(date, ctx.message.author.id)
date = date + datetime.timedelta(days=1)
report = turnipCalculator.createTurnipModel(ctx.message.author.id, date).summary()
if bool(report) is False:
await ctx.send("Failed to create a report with data provided\n"
"You've given some invalid bell amount somewhere\n"
"You can run `<removeInvalidData` to try and fix this issue\n"
"There's a guide to help fix this at https://bit.ly/turnipBot")
print("REPORT ERROR:\nDiscordID: {}\nTime:{}\n-----".format(ctx.message.author.id,
datetime.datetime.now(), ))
return
newImage = turnipSummaryImage.SummaryImage(report, ctx.message.author.id)
newImage.createImage()
img_URL = newImage.uploadImage()
embedded = discord.Embed(title="Turnip Prediction", description="Your current turnip prediction",
color=0xCF70D3)
embedded.set_author(name="Turnip Bot",
url="https://github.com/vlee489/Turnip-Bot/",
icon_url="https://cdn.vlee.me.uk/TurnipBot/icon.png")
embedded.set_image(url=img_URL)
embedded.set_footer(text="Turnip Bot", icon_url="https://cdn.vlee.me.uk/TurnipBot/icon.png")
embedded.timestamp = datetime.datetime.now()
await ctx.send(embed=embedded)
except errors.FileNotCreated as e:
await ctx.send("Failed to create image of summary >.<\n "
"Issue has been reported to operator.\n")
print("ERROR:\nDiscordID: {}\nTime:{}\nError:{}\n-----".format(ctx.message.author.id,
datetime.datetime.now(),
e))
return
except errors.AWSError as e:
await ctx.send("Failed to upload image >.<\n "
"Issue has been reported to operator.\n")
print("ERROR:\nDiscordID: {}\nTime:{}\nError:{}\n-----".format(ctx.message.author.id,
datetime.datetime.now(),
e))
except errors.NoData:
await ctx.send("No Data to create model with\n "
"So your prices will be somewhere between 0 to 700.\n"
"Use `<ap` and/or `<setBuyPrice` to get started!")
except errors.InvalidDateFormat:
await ctx.send("Error: Invalid Date format given")
except Exception as e:
await ctx.send("Internal Error, sorry >.<\n "
"Issue has been reported to operator.\n"
"(ts.catch.rest)")
print("ERROR:\nDiscordID: {}\nTime:{}\nError:{}\n-----".format(ctx.message.author.id,
datetime.datetime.now(),
e))
return
@commands.command(name='tst', help="Get your Turnip Summary as text\n"
"This is built for people using screen readers, use <ts if you can"
"\n[date]: OPTIONAL Get your summary for a specific week in DD/MM/YYYY",
aliases=['TurnipSummaryText', 'turnipsummarytext'])
async def currentTurnipSummaryText(self, ctx, date="Today"):
try:
date = getDate(date, ctx.message.author.id)
date = date + datetime.timedelta(days=1)
report = turnipCalculator.createTurnipModel(ctx.message.author.id, date).summary()
if bool(report) is False:
await ctx.send("Failed to create a report with data provided\n"
"You've given some invalid bell amount somewhere\n"
"You can run `<removeInvalidData` to try and fix this issue\n"
"There's a guide to help fix this at https://bit.ly/turnipBot")
print("REPORT ERROR:\nDiscordID: {}\nTime:{}\n-----".format(ctx.message.author.id,
datetime.datetime.now(), ))
return
reply = "Turnip Summary\n```"
reply = reply + " {:15} {:13} {:13} {:6}\n".format('Time', 'Price(Bells)', 'Likely(bells)', 'Odds(%)')
for periods in report:
reply = reply + " {:15} {:13} {:13} {:6}\n".format(periods,
report[periods]['price'],
report[periods]['likely'],
report[periods]['chance'])
reply = reply + '```'
await ctx.send(reply)
except errors.NoData:
await ctx.send("No Data to create model with\n "
"So your prices will be somewhere between 0 to 700.\n"
"Use `<ap` and/or `<setBuyPrice` to get started!")
except errors.AWSError as e:
await ctx.send("Internal Error, sorry >.<\n "
"Issue has been reported to operator.\n"
"(ts.AWS)")
print("ERROR:\nDiscordID: {}\nTime:{}\nError:{}\n-----".format(ctx.message.author.id,
datetime.datetime.now(),
e))
except errors.InvalidDateFormat:
await ctx.send("Error: Invalid Date format given")
except Exception as e:
print("ERROR:\nDiscordID: {}\nTime:{}\nError:{}\n-----".format(ctx.message.author.id,
datetime.datetime.now(),
e))
await ctx.send("Internal Error, sorry >.<\n "
"Issue has been reported to operator.\n"
"(ts.catch.rest)")
return
@commands.command(name='tsgraph',
help="Get your Turnip Summary Graph"
"\n[date]: OPTIONAL Get your summary for a specific week in DD/MM/YYYY",
aliases=['tsg', 'turnipsummarygraph', 'turnipSummaryGraph'])
async def tsgraph(self, ctx, date="Today"):
try:
date = getDate(date, ctx.message.author.id)
date = date + datetime.timedelta(days=1)
report = turnipCalculator.createTurnipModel(ctx.message.author.id, date).summary()
if bool(report) is False:
await ctx.send("Failed to create a report with data provided\n"
"You've given some invalid bell amount somewhere\n"
"You can run `<removeInvalidData` to try and fix this issue\n"
"There's a guide to help fix this at https://bit.ly/turnipBot")
print("REPORT ERROR:\nDiscordID: {}\nTime:{}\n-----".format(ctx.message.author.id,
datetime.datetime.now(), ))
return
newImage = turnipSummaryImage.SummaryImage(report, ctx.message.author.id)
newImage.createGraph()
img_URL = newImage.uploadGraphImage()
embedded = discord.Embed(title="Turnip Prediction Graph", description="Your current turnip prediction",
color=0xCF70D3)
embedded.set_author(name="Turnip Bot",
url="https://github.com/vlee489/Turnip-Bot/",
icon_url="https://cdn.vlee.me.uk/TurnipBot/icon.png")
embedded.set_image(url=img_URL)
embedded.set_footer(text="Turnip Bot", icon_url="https://cdn.vlee.me.uk/TurnipBot/icon.png")
embedded.timestamp = datetime.datetime.now()
await ctx.send(embed=embedded)
except errors.FileNotCreated as e:
await ctx.send("Failed to create image of summary >.<\n "
"Issue has been reported to operator.\n")
print("ERROR:\nDiscordID: {}\nTime:{}\nError:{}\n-----".format(ctx.message.author.id,
datetime.datetime.now(),
e))
except errors.AWSError as e:
await ctx.send("Failed to upload image >.<\n "
"Issue has been reported to operator.\n")
print("ERROR:\nDiscordID: {}\nTime:{}\nError:{}\n-----".format(ctx.message.author.id,
datetime.datetime.now(),
e))
except errors.NoData:
await ctx.send("No Data to create model with\n "
"So your prices will be somewhere between 0 to 700.\n"
"Use `<ap` and/or `<setBuyPrice` to get started!")
except errors.InvalidDateFormat:
await ctx.send("Error: Invalid Date format given")
except Exception as e:
await ctx.send("Internal Error, sorry >.<\n "
"Issue has been reported to operator.\n"
"(tsg.catch.rest)")
print("ERROR:\nDiscordID: {}\nTime:{}\nError:{}\n-----".format(ctx.message.author.id,
datetime.datetime.now(),
e))
return
@commands.command(name='setBuyPrice',
help="Set the Price you bought the turnips for from Daisy Mae this week.\n"
"This should be the price from YOUR OWN ISLAND!!!"
"\n<bells>: The amount of bells each turnip cost."
"\n[date]: OPTIONAL Set a price for a specific week in DD/MM/YYYY",
aliases=['setbuyprice', 'sbp'])
async def setBuyPrice(self, ctx, bells, date="Today"):
if not bells.isdigit():
await ctx.send("Bells must be given as a number! E.g 1-9")
return
try:
date = getDate(date, ctx.message.author.id)
turnipCalculator.addBuyPrice(ctx.message.author.id, date, bells)
await ctx.send("Added purchase price of {} bells from Daisy Mae on {}".format(bells,
date.strftime("%d/%m/%Y")))
except errors.BellsOutOfRange as e:
await ctx.send("Purchase price must be between 90-110 bells")
return
except errors.InvalidDateFormat:
await ctx.send("Error: Invalid Date format given")
except Exception as error:
await ctx.send("Internal Error, sorry >.<\n "
"Issue has been reported to operator.\n"
"(sbp.catch.rest)")
print("ERROR:\nDiscordID: {}\nTime:{}\nError:{}\n-----".format(ctx.message.author.id,
datetime.datetime.now(),
error))
return
@commands.command(name='removeInvalidData',
help="Attempts to find and remove invalid data to make your turnip summary generate.\n",
aliases=["correctErrors", "removeinvaliddata", 'rid'])
async def correctErrors(self, ctx, date="Today"):
try:
date = getDate(date, ctx.message.author.id)
removedDate = turnipCalculator.clearErrors(ctx.message.author.id, date)
await ctx.send("I've removed all the data that was causing an error now!\n"
"You should be able to run summary commands again now.\n"
"The following days have been removed.\n"
"{}".format(removedDate))
except errors.AWSError as e:
await ctx.send("Failed to access dataStore >.<\n "
"Issue has been reported to operator.\n")
print("ERROR:\nDiscordID: {}\nTime:{}\nError:{}\n-----".format(ctx.message.author.id,
datetime.datetime.now(),
e))
except errors.DataCorrect:
await ctx.send("Data is already correct and can create a summary\n")
except errors.NoData:
await ctx.send("No Data to create model with\n")
except errors.InternalError as error:
await ctx.send("Internal Error, sorry >.<\n "
"Issue has been reported to operator.\n"
"(rid.tooManyResponses)")
print("ERROR:\nDiscordID: {}\nTime:{}\nError:{}\n-----".format(ctx.message.author.id,
datetime.datetime.now(),
error))
except Exception as error:
await ctx.send("Internal Error, sorry >.<\n "
"Issue has been reported to operator.\n"
"(rid.catch.rest)")
print("ERROR:\nDiscordID: {}\nTime:{}\nError:{}\n-----".format(ctx.message.author.id,
datetime.datetime.now(),
error))
@commands.command(name='removePrice', help="Remove a price from turnip price storage"
"\n<Time> : Either PM or AM "
"\n<date> : The date you want to enter price for in DD/MM/YYYY",
aliases=['RemovePrice', 'rp', 'removeprice'])
async def removePrice(self, ctx, time, date):
time = time.upper() # Turns the time given into Uppercase
try:
date = getDate(date, ctx.message.author.id)
responseBool = turnipCalculator.removePrice(str(ctx.message.author.id), date, time)
if responseBool:
await ctx.send("We have removed the the entry for {} on {}".format(time, date.strftime("%d/%m/%Y")))
return
else:
await ctx.send("We where **Unable** to remove the entry for {} on {} "
"\nLikely doesn't exist".format(time, date.strftime("%d/%m/%Y")))
return
except errors.InvalidDateTime:
await ctx.send("Error: Invalid date given!")
except errors.InvalidDateFormat:
await ctx.send("Error: Invalid Date format given")
except errors.AWSError:
await ctx.send("There was an error getting to the database")
@commands.command(name='getPrice', help="View the prices you have given to Turnip Bot"
"\n[date]: OPTIONAL Set a price for a specific week in DD/MM/YYYY",
aliases=['gp', 'GetPrice', 'getprice'])
async def viewPrice(self, ctx, date="Today"):
try:
date = getDate(date, ctx.message.author.id)
printOut = "```\n"
prices = turnipCalculator.getPrices(str(ctx.message.author.id), date)
for items in prices:
printOut = printOut + "{:16}: {:4}\n".format(items, prices[items])
printOut = printOut + "```"
embedded = discord.Embed(title="Turnip Price List", description="The Turnip Prices you've given",
color=0xCF70D3)
embedded.set_author(name="Turnip Bot",
url="https://github.com/vlee489/Turnip-Bot/",
icon_url="https://cdn.vlee.me.uk/TurnipBot/icon.png")
embedded.add_field(name="Price on file:", value=printOut, inline=False)
embedded.set_footer(text="Turnip Bot", icon_url="https://cdn.vlee.me.uk/TurnipBot/icon.png")
embedded.timestamp = datetime.datetime.now()
await ctx.send(embed=embedded)
except errors.InvalidDateFormat:
await ctx.send("Error: Invalid Date Format")
@commands.command(name='setTimezone', help="Set your default timezone"
"\n<timezone>: The TZ database name of your timezone"
"\nA list of valid TZ dataabse names are at "
"https://bit.vlee.me.uk/TZ",
aliases=['SetTimezone', 'settimezone'])
async def setTimezone(self, ctx, timezone):
try:
response = getDateAcquirer.addTimezone(ctx.message.author.id, timezone)
if response:
await ctx.send("Set your timezone to {}".format(timezone.title()))
else:
await ctx.send("Timezone your provided was invalid, please choose a valid timezone,\n"
"from https://bit.vlee.me.uk/TZ")
return
except errors.AWSError:
await ctx.send("Couldn't add your timezone, try again later.")
def setup(bot):
bot.add_cog(Turnips(bot))