market.py 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171
  1. from dataclasses import dataclass, field
  2. from typing import List, Dict
  3. from selenium import webdriver
  4. from selenium.webdriver.chrome.options import Options
  5. from selenium.webdriver.common.keys import Keys
  6. from selenium.webdriver.common.by import By
  7. from datetime import datetime
  8. import pandas as pd
  9. from tinydb import Query
  10. import json
  11. import sys
  12. from player import Player
  13. from config import Config
  14. from logger import logger
  15. from db import MarketDB
  16. from db import PlayerDB
  17. @dataclass
  18. class Market():
  19. url:str = 'https://play.boobylegends.com/market/'
  20. driver:webdriver = None
  21. Cards:List[dict] = field(default_factory=list)
  22. asOf:datetime = datetime.utcnow()
  23. df:pd.DataFrame = field(default_factory=pd.DataFrame)
  24. player:Player = None
  25. login:bool = True
  26. def fetchData(self):
  27. logger.debug("Market Fetching Data.")
  28. self.loadPage()
  29. self.Cards=[]
  30. cards=self.driver.find_elements(By.CLASS_NAME, 'wrapper-market-card')
  31. for card in cards:
  32. Card={}
  33. try:
  34. IDs=card.find_element(By.CLASS_NAME,'titre-card').text.split('\n')
  35. Card['card-num']=int(IDs[1])
  36. Card['name']=IDs[0]
  37. link=card.find_element(By.TAG_NAME,'a')
  38. Card['card-id'] = int(link.get_attribute('card-id'))
  39. Card['phid'] = link.get_attribute('phid')
  40. Card['level'] = link.get_attribute('level')
  41. Card['link'] = link.get_attribute('href')
  42. tierCard = card.find_element(By.CLASS_NAME,'tier-card')
  43. tierLink = tierCard.get_attribute('src')
  44. Card['tier'] = tierLink[:-4][-1].upper()
  45. Card['val']= int(card.find_element(By.CLASS_NAME,'score-card').text)
  46. Card['qty']= int(card.find_element(By.CLASS_NAME,'qty').text)
  47. Card['cost']= int(card.find_element(By.CLASS_NAME,'cost').text)
  48. self.Cards.append(Card)
  49. except Exception as e:
  50. logger.error(f"{e}\n{card.text}")
  51. self.loadDF()
  52. def initPage(self):
  53. logger.debug("Market Init Page.")
  54. options = webdriver.ChromeOptions()
  55. options.add_argument("--headless")
  56. options.add_argument("--disable-blink-features=AutomationControlled")
  57. options.add_argument("--log-level=3")
  58. self.driver = webdriver.Chrome(options=options)
  59. self.driver.get(self.url)
  60. if self.login: self.driver.add_cookie(Config["cookie"])
  61. def loadPage(self):
  62. logger.debug("Market Load Page.")
  63. if self.driver is None: self.initPage()
  64. self.driver.get(self.url)
  65. self.asOf=datetime.utcnow()
  66. def closePage(self):
  67. logger.debug("Market Close Page.")
  68. self.driver.close()
  69. def getPlayerInfo(self):
  70. logger.debug("Market Get Player Info")
  71. if self.player is None: self.player = Player()
  72. self.player.fetchData()
  73. self.player.closePage()
  74. def filterMarketCards(self,force=True):
  75. logger.debug("Market Filter Cards.")
  76. clist=[None]*152
  77. if force:
  78. self.getPlayerInfo()
  79. Cards = self.player.Cards
  80. else:
  81. today=datetime.utcnow().strftime('%Y-%m-%d')
  82. Cards=PlayerDB.search(Query().fragment({'date':today}))
  83. if len(Cards)==0:
  84. self.getPlayerInfo()
  85. Cards = self.player.Cards
  86. for card in Cards: clist[card['card-num']]=card['stock']
  87. js="clist={clist}\n".format(clist=json.dumps(clist))
  88. js+="""
  89. cards=document.getElementsByClassName('wrapper-market-card')
  90. for (var i = 0; i < cards.length; i++) {
  91. cardNum = cards.item(i).getElementsByClassName('pornstar-number')[0].outerText;
  92. innerCard = cards.item(i).getElementsByClassName('inner-market-card')[0]
  93. var stock = innerCard.getElementsByClassName('Stock')[0]
  94. if (stock){stock.innerText = "Stock: " + clist[cardNum]}
  95. else {
  96. let qty = document.createElement('div');
  97. qty.classList.add('Stock')
  98. qty.innerText = "Stock: " + clist[cardNum]
  99. innerCard.appendChild(qty)
  100. }
  101. if (clist[cardNum].includes('CRYSTAL')){
  102. cards.item(i).style.setProperty('Display','None');
  103. }
  104. }
  105. """
  106. print(js)
  107. self.driver.execute_script(js)
  108. def loadDF(self):
  109. logger.debug("Market Load DF.")
  110. self.df=pd.DataFrame(self.Cards)
  111. self.df.sort_values(by='card-num', ascending=True, inplace=True)
  112. def show(self,fields=['card-num','name','level','qty','cost'],filter=''):
  113. logger.debug("Market Show Data.")
  114. if filter != '':
  115. pdf=self.df.query(filter)
  116. else:
  117. pdf=self.df
  118. print(pdf[fields].to_string(index=False))
  119. def commit(self):
  120. def newCard(Card):
  121. thisCard={}
  122. thisCard['date'] = today
  123. thisCard['count'] = 1
  124. thisCard['card-num'] = Card['card-num']
  125. thisCard['name'] = Card['name']
  126. thisCard['qty'] = Card['qty']
  127. thisCard['cost'] = Card['cost']
  128. thisCard['cost-min'] = Card['cost']
  129. thisCard['cost-max'] = Card['cost']
  130. thisCard['level'] = Card['level']
  131. thisCard['tier'] = Card['tier']
  132. if Card['cost']!=0: MarketDB.insert(thisCard)
  133. def updateCard(Card):
  134. matchCard=MarketDB.search(Query().fragment({'date':today,'card-num':Card['card-num']}))
  135. if len(matchCard)==0:
  136. newCard(Card)
  137. else:
  138. thisCard=matchCard[0]
  139. newData={}
  140. newData['count']=thisCard['count']+1
  141. newData['qty']=(thisCard['count']*thisCard['qty']+Card['qty'])/(thisCard['count']+1)
  142. newData['cost']=(thisCard['count']*thisCard['cost']+Card['cost'])/(thisCard['count']+1)
  143. if 'cost-min' not in thisCard:
  144. newData['cost-min'] = Card['cost']
  145. elif thisCard['cost-min'] > Card['cost']:
  146. newData['cost-min'] = Card['cost']
  147. if 'cost-max' not in thisCard:
  148. newData['cost-max'] = Card['cost']
  149. elif thisCard['cost-max'] < Card['cost']:
  150. newData['cost-max'] = Card['cost']
  151. if Card['cost']!=0: MarketDB.update(newData,Query().fragment({'date':today,'card-num':Card['card-num']}))
  152. logger.debug("Market Commit.")
  153. today=self.asOf.strftime('%Y-%m-%d')
  154. current=MarketDB.search(Query()['date']==today)
  155. if len(current)==0:
  156. for Card in self.Cards:
  157. newCard(Card)
  158. else:
  159. for Card in self.Cards:
  160. updateCard(Card)