discord-bot.py 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185
  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.xlabel("Date")
  53. plt.ylabel("Cost")
  54. plt.savefig(f"plots/{card}.png")
  55. with open(f"plots/{card}.png", 'rb') as f:
  56. picture = discord.File(f)
  57. return picture
  58. def getData():
  59. d=MarketDB.all()
  60. df=pd.DataFrame(d)
  61. df.sort_values(by=['card-num','date'], ascending=[True,True], inplace=True)
  62. df.to_csv('plots/BoobyLegendsMarket.csv',index=False)
  63. with open(f"plots/BoobyLegendsMarket.csv", 'rb') as f:
  64. data = discord.File(f)
  65. return data
  66. def parse(input,author):
  67. # parse the input string from the message so that we can see what we need to do
  68. parts = input.strip().split()
  69. logger.debug(input)
  70. logger.debug(parts)
  71. #global decoder
  72. AuthorName = author
  73. #drop out if this is not a Roll command
  74. if len(parts) == 0:
  75. return None
  76. if parts[0].upper() not in ['!','/','\\']:
  77. #Try to make a command if first character is !
  78. if parts[0][0]=="!":
  79. pt=["!",parts[0][1:]]
  80. pt.extend(parts[1:])
  81. parts=pt
  82. logger.debug(parts)
  83. else:
  84. logger.debug("Not a command")
  85. return None
  86. try:
  87. logger.debug("Command: "+parts[1].upper())
  88. if parts[1].upper() == "HISTORY":
  89. name = ' '.join(parts[2:])
  90. logger.info("History for: "+name)
  91. history=histGrid(name.strip())
  92. #give user message so he knows it's saved
  93. retstr = "{Author} requested history for **{name}**:\n{history}".format(
  94. Author=author,
  95. name=name,
  96. history=history
  97. )
  98. logger.debug(retstr)
  99. elif parts[1].upper() == "TODAY":
  100. level=None
  101. tier=None
  102. if len(parts) > 2: level=parts[2]
  103. if len(parts) > 3: tier=parts[3]
  104. logger.info(f"Today {level} {tier}")
  105. history=todayGrid(level,tier)
  106. retstr = "{Author} requested today's Costs for Today:\n{history}".format(
  107. Author=author,
  108. history=history
  109. )
  110. logger.debug(retstr)
  111. elif parts[1].upper() == "PLOT":
  112. name = ' '.join(parts[2:])
  113. logger.info("Plot for: "+name)
  114. retstr = postPlot(card=name.strip())
  115. elif parts[1].upper() == "GETDATA":
  116. logger.info("Getting Data Dump")
  117. retstr = getData()
  118. elif parts[1].upper() in ["LOGLEVEL"]:
  119. if parts[2].upper() == "DEBUG":
  120. logger.setLevel(logging.DEBUG)
  121. elif parts[2].upper() == "INFO":
  122. logger.setLevel(logging.INFO)
  123. retstr= "LogLevel set to "+parts[2].upper()
  124. elif parts[1].upper() in ["HELP"]:
  125. retstr = '''
  126. My Key words are "!", "/", or "\\"
  127. Show a Card's Historical cost with:```!History Eva Elfie```
  128. Show the current day's average prices with:```!Today```
  129. You can also filter this by Level or Level and tier:```!Today rare```or```!Today common S```
  130. You can get a graph plotted with the historical values for a star by:```!Plot Natasha Nice```
  131. Get a Data Dump of the current data set with```!GetData```
  132. '''
  133. else:
  134. retstr = '{Author}, your command was not understood.'.format(Author=author)
  135. except Exception as e:
  136. print(e)
  137. retstr = None
  138. return retstr
  139. #########################################################################
  140. # Main Program
  141. #########################################################################
  142. intents = discord.Intents.default()
  143. intents.message_content = True
  144. client = discord.Client(intents=intents)
  145. # This block is the work horse part
  146. @client.event
  147. async def on_message(message):
  148. # we do not want the bot to reply to itself
  149. if message.author == client.user:
  150. return
  151. # get the output for the given message
  152. output = parse(message.content,message.author.display_name)
  153. if output is not None:
  154. if isinstance(output,str):
  155. if len(output) > 2000:
  156. output=output[:1997]+"..."
  157. await message.channel.send(output)
  158. else:
  159. await message.channel.send(file=output)
  160. @client.event
  161. async def on_ready():
  162. print('Logged in as')
  163. print(client.user.name)
  164. print(client.user.id)
  165. print('------')
  166. client.run(TOKEN)