market.py 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170
  1. from dataclasses import dataclass, field
  2. from typing import List
  3. from datetime import datetime
  4. import requests
  5. from bs4 import BeautifulSoup
  6. import pandas as pd
  7. from tinydb import Query
  8. import json
  9. from player import Player
  10. from config import Config
  11. from logger import logger
  12. from db import MarketDB
  13. from db import PlayerDB
  14. @dataclass
  15. class Market():
  16. url: str = 'https://play.boobylegends.com/market/'
  17. Cards: List[dict] = field(default_factory=list)
  18. asOf: datetime = datetime.utcnow()
  19. df: pd.DataFrame = field(default_factory=pd.DataFrame)
  20. player: Player = None
  21. login: bool = True
  22. def fetchData(self):
  23. logger.debug("Market Fetching Data.")
  24. try:
  25. self.loadPage()
  26. self.Cards = []
  27. page_content = requests.get(self.url).content
  28. soup = BeautifulSoup(page_content, 'html.parser')
  29. cards = soup.find_all(class_='wrapper-market-card')
  30. for card in cards:
  31. try:
  32. Card = {}
  33. Card['card-num'] = int(card.find(class_='pornstar-number').text)
  34. Card['name'] = card.select_one('div.titre-card h2').text.strip()
  35. link = card.find('a')
  36. Card['card-id'] = int(link.get('card-id'))
  37. Card['phid'] = link.get('phid')
  38. Card['level'] = link.get('level')
  39. Card['link'] = link.get('href')
  40. tierCard = card.find(class_='tier-card')
  41. tierLink = tierCard.get('src')
  42. # Extracting tier from URL
  43. extracted_tier = tierLink.split('/')[-1].split('.')[0].upper()
  44. # Check if extracted tier starts with "TIER-" and adjust accordingly
  45. if extracted_tier.startswith("TIER-"):
  46. Card['tier'] = extracted_tier.split("TIER-")[-1]
  47. else:
  48. Card['tier'] = extracted_tier
  49. Card['val'] = int(card.find(class_='score-card').find('span').text)
  50. Card['qty'] = int(card.find(class_='qty').text.strip())
  51. Card['cost'] = int(card.find(class_='cost').find('span').text)
  52. self.Cards.append(Card)
  53. except Exception as e:
  54. logger.error(f"Error processing card: {e}\nCard HTML:\n{card}")
  55. self.loadDF()
  56. except Exception as e:
  57. logger.error(f"Exception during data fetch: {e}")
  58. def loadPage(self):
  59. logger.debug("Market Load Page.")
  60. self.asOf = datetime.utcnow()
  61. def getPlayerInfo(self):
  62. logger.debug("Market Get Player Info")
  63. if self.player is None: self.player = Player()
  64. self.player.fetchData()
  65. def filterMarketCards(self, force=True):
  66. logger.debug("Market Filter Cards.")
  67. clist = [None] * 152
  68. if force:
  69. self.getPlayerInfo()
  70. Cards = self.player.Cards
  71. else:
  72. today = datetime.utcnow().strftime('%Y-%m-%d')
  73. Cards = PlayerDB.search(Query().fragment({'date': today}))
  74. if len(Cards) == 0:
  75. self.getPlayerInfo()
  76. Cards = self.player.Cards
  77. for card in Cards:
  78. clist[card['card-num']] = card['stock']
  79. # Removed Selenium-specific functionality.
  80. # Uncomment and modify the code if needed for different implementation.
  81. # js = f"clist={json.dumps(clist)}\n"
  82. # js += """
  83. # cards=document.getElementsByClassName('wrapper-market-card')
  84. # for (var i = 0; i < cards.length; i++) {
  85. # cardNum = cards.item(i).getElementsByClassName('pornstar-number')[0].outerText;
  86. # innerCard = cards.item(i).getElementsByClassName('inner-market-card')[0]
  87. # var stock = innerCard.getElementsByClassName('Stock')[0]
  88. # if (stock){stock.innerText = "Stock: " + clist[cardNum]}
  89. # else {
  90. # let qty = document.createElement('div');
  91. # qty.classList.add('Stock')
  92. # qty.innerText = "Stock: " + clist[cardNum]
  93. # innerCard.appendChild(qty)
  94. # }
  95. # if (clist[cardNum].includes('CRYSTAL')){
  96. # cards.item(i).style.setProperty('Display','None');
  97. # }
  98. # }
  99. # """
  100. # print(js)
  101. # self.driver.execute_script(js)
  102. def loadDF(self):
  103. logger.debug("Market Load DF.")
  104. self.df = pd.DataFrame(self.Cards)
  105. self.df.sort_values(by='card-num', ascending=True, inplace=True)
  106. def show(self, fields=['card-num', 'name', 'level', 'qty', 'cost'], filter=''):
  107. logger.debug("Market Show Data.")
  108. if filter != '':
  109. pdf = self.df.query(filter)
  110. else:
  111. pdf = self.df
  112. print(pdf[fields].to_string(index=False))
  113. def commit(self):
  114. def newCard(Card):
  115. thisCard = {}
  116. thisCard['date'] = today
  117. thisCard['count'] = 1
  118. thisCard['card-num'] = Card['card-num']
  119. thisCard['name'] = Card['name']
  120. thisCard['qty'] = Card['qty']
  121. thisCard['cost'] = Card['cost']
  122. thisCard['cost-min'] = Card['cost']
  123. thisCard['cost-max'] = Card['cost']
  124. thisCard['level'] = Card['level']
  125. thisCard['tier'] = Card['tier']
  126. if Card['cost'] != 0:
  127. MarketDB.insert(thisCard)
  128. def updateCard(Card):
  129. matchCard = MarketDB.search(Query().fragment({'date': today, 'card-num': Card['card-num']}))
  130. if len(matchCard) == 0:
  131. newCard(Card)
  132. else:
  133. thisCard = matchCard[0]
  134. newData = {}
  135. newData['count'] = thisCard['count'] + 1
  136. newData['qty'] = round((thisCard['count'] * thisCard['qty'] + Card['qty']) / (thisCard['count'] + 1), 1)
  137. newData['cost'] = round((thisCard['count'] * thisCard['cost'] + Card['cost']) / (thisCard['count'] + 1), 1)
  138. if 'cost-min' not in thisCard or thisCard['cost-min'] > Card['cost']:
  139. newData['cost-min'] = Card['cost']
  140. if 'cost-max' not in thisCard or thisCard['cost-max'] < Card['cost']:
  141. newData['cost-max'] = Card['cost']
  142. if Card['cost'] != 0:
  143. MarketDB.update(newData, Query().fragment({'date': today, 'card-num': Card['card-num']}))
  144. logger.debug("Market Commit.")
  145. today = self.asOf.strftime('%Y-%m-%d')
  146. current = MarketDB.search(Query()['date'] == today)
  147. if len(current) == 0:
  148. for Card in self.Cards:
  149. newCard(Card)
  150. else:
  151. for Card in self.Cards:
  152. updateCard(Card)