discord-bot.py 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186
  1. import json
  2. import sys
  3. import logging
  4. import discord
  5. from datetime import datetime
  6. from config import Config
  7. from logger import logger
  8. from tinydb import Query
  9. import matplotlib.pyplot as plt
  10. import pandas as pd
  11. from db import MarketDB, PlayerDB, _hist, getDF
  12. TOKEN = Config["Tokens"]["BoobyLegendsEcon"]["Token"]
  13. def getPlayerCard(name):
  14. today=datetime.utcnow().strftime('%Y-%m-%d')
  15. thisCard=PlayerDB.search(Query().fragment({'date':today,'name':name}))[0]
  16. return thisCard
  17. def histGrid(name,columns=None):
  18. logger.debug(f"histGrid(name={name},columns={columns})")
  19. MAX_RECORD_COUNT=45
  20. df = getDF(name)
  21. footer=""
  22. dfSize=len(df)
  23. if dfSize > MAX_RECORD_COUNT:
  24. df.drop(df.head(dfSize-MAX_RECORD_COUNT).index,inplace=True)
  25. footer=f"\n{dfSize-MAX_RECORD_COUNT} more..."
  26. if columns is None:
  27. cols = ['date','cost','cost-min','cost-max']
  28. else:
  29. cols = columns
  30. return "```"+df[cols].to_string(index=False,col_space=6,na_rep="-")+footer+"```"
  31. def todayGrid(level=None,tier=None,columns=None):
  32. logger.debug(f"todayGrid(level={level},tier={tier},columns={columns})")
  33. MAX_RECORD_COUNT=41
  34. df = getDF(aDate=datetime.utcnow().strftime('%Y-%m-%d'))
  35. if level is not None:
  36. df=df[df['level']==level.lower()]
  37. if tier is not None:
  38. df=df[df['tier']==tier.upper()]
  39. footer=""
  40. dfSize=len(df)
  41. if dfSize > MAX_RECORD_COUNT:
  42. df.drop(df.tail(dfSize-MAX_RECORD_COUNT).index,inplace=True)
  43. footer=f"\n{dfSize-MAX_RECORD_COUNT} more..."
  44. if columns is None:
  45. cols = ['name','cost','cost-min','cost-max']
  46. else:
  47. cols = columns
  48. return "```"+df[cols].to_string(index=False,col_space=6,na_rep="-")+footer+"```"
  49. def postPlot(card=None,columns=['cost','cost-min','cost-max']):
  50. df=getDF(card).plot(x='date',y=columns)
  51. plt.title(str(card))
  52. plt.xticks(rotation=45)
  53. plt.xlabel("Date")
  54. plt.ylabel("Cost")
  55. plt.savefig(f"plots/{card}.png")
  56. with open(f"plots/{card}.png", 'rb') as f:
  57. picture = discord.File(f)
  58. return picture
  59. def getData():
  60. d=MarketDB.all()
  61. df=pd.DataFrame(d)
  62. df.sort_values(by=['card-num','date'], ascending=[True,True], inplace=True)
  63. df.to_csv('plots/BoobyLegendsMarket.csv',index=False)
  64. with open(f"plots/BoobyLegendsMarket.csv", 'rb') as f:
  65. data = discord.File(f)
  66. return data
  67. def parse(input,author):
  68. # parse the input string from the message so that we can see what we need to do
  69. parts = input.strip().split()
  70. logger.debug(input)
  71. logger.debug(parts)
  72. #global decoder
  73. AuthorName = author
  74. #drop out if this is not a Roll command
  75. if len(parts) == 0:
  76. return None
  77. if parts[0].upper() not in ['!','/','\\']:
  78. #Try to make a command if first character is !
  79. if parts[0][0]=="!":
  80. pt=["!",parts[0][1:]]
  81. pt.extend(parts[1:])
  82. parts=pt
  83. logger.debug(parts)
  84. else:
  85. logger.debug("Not a command")
  86. return None
  87. try:
  88. logger.debug("Command: "+parts[1].upper())
  89. if parts[1].upper() == "HISTORY":
  90. name = ' '.join(parts[2:])
  91. logger.info("History for: "+name)
  92. history=histGrid(name.strip())
  93. #give user message so he knows it's saved
  94. retstr = "{Author} requested history for **{name}**:\n{history}".format(
  95. Author=author,
  96. name=name,
  97. history=history
  98. )
  99. logger.debug(retstr)
  100. elif parts[1].upper() == "TODAY":
  101. level=None
  102. tier=None
  103. if len(parts) > 2: level=parts[2]
  104. if len(parts) > 3: tier=parts[3]
  105. logger.info(f"Today {level} {tier}")
  106. history=todayGrid(level,tier)
  107. retstr = "{Author} requested today's Costs for Today:\n{history}".format(
  108. Author=author,
  109. history=history
  110. )
  111. logger.debug(retstr)
  112. elif parts[1].upper() == "PLOT":
  113. name = ' '.join(parts[2:])
  114. logger.info("Plot for: "+name)
  115. retstr = postPlot(card=name.strip())
  116. elif parts[1].upper() == "GETDATA":
  117. logger.info("Getting Data Dump")
  118. retstr = getData()
  119. elif parts[1].upper() in ["LOGLEVEL"]:
  120. if parts[2].upper() == "DEBUG":
  121. logger.setLevel(logging.DEBUG)
  122. elif parts[2].upper() == "INFO":
  123. logger.setLevel(logging.INFO)
  124. retstr= "LogLevel set to "+parts[2].upper()
  125. elif parts[1].upper() in ["HELP"]:
  126. retstr = '''
  127. My Key words are "!", "/", or "\\"
  128. Show a Card's Historical cost with:```!History Eva Elfie```
  129. Show the current day's average prices with:```!Today```
  130. You can also filter this by Level or Level and tier:```!Today rare```or```!Today common S```
  131. You can get a graph plotted with the historical values for a star by:```!Plot Natasha Nice```
  132. Get a Data Dump of the current data set with```!GetData```
  133. '''
  134. else:
  135. retstr = '{Author}, your command was not understood.'.format(Author=author)
  136. except Exception as e:
  137. print(e)
  138. retstr = None
  139. return retstr
  140. #########################################################################
  141. # Main Program
  142. #########################################################################
  143. intents = discord.Intents.default()
  144. intents.message_content = True
  145. client = discord.Client(intents=intents)
  146. # This block is the work horse part
  147. @client.event
  148. async def on_message(message):
  149. # we do not want the bot to reply to itself
  150. if message.author == client.user:
  151. return
  152. # get the output for the given message
  153. output = parse(message.content,message.author.display_name)
  154. if output is not None:
  155. if isinstance(output,str):
  156. if len(output) > 2000:
  157. output=output[:1997]+"..."
  158. await message.channel.send(output)
  159. else:
  160. await message.channel.send(file=output)
  161. @client.event
  162. async def on_ready():
  163. print('Logged in as')
  164. print(client.user.name)
  165. print(client.user.id)
  166. print('------')
  167. client.run(TOKEN)