123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170 |
- from dataclasses import dataclass, field
- from typing import List
- from datetime import datetime
- import requests
- from bs4 import BeautifulSoup
- import pandas as pd
- from tinydb import Query
- import json
- from player import Player
- from config import Config
- from logger import logger
- from db import MarketDB
- from db import PlayerDB
- @dataclass
- class Market():
- url: str = 'https://play.boobylegends.com/market/'
- Cards: List[dict] = field(default_factory=list)
- asOf: datetime = datetime.utcnow()
- df: pd.DataFrame = field(default_factory=pd.DataFrame)
- player: Player = None
- login: bool = True
- def fetchData(self):
- logger.debug("Market Fetching Data.")
- try:
- self.loadPage()
- self.Cards = []
-
- page_content = requests.get(self.url).content
- soup = BeautifulSoup(page_content, 'html.parser')
- cards = soup.find_all(class_='wrapper-market-card')
-
- for card in cards:
- try:
- Card = {}
- Card['card-num'] = int(card.find(class_='pornstar-number').text)
- Card['name'] = card.select_one('div.titre-card h2').text.strip()
- link = card.find('a')
- Card['card-id'] = int(link.get('card-id'))
- Card['phid'] = link.get('phid')
- Card['level'] = link.get('level')
- Card['link'] = link.get('href')
-
- tierCard = card.find(class_='tier-card')
- tierLink = tierCard.get('src')
- # Extracting tier from URL
- extracted_tier = tierLink.split('/')[-1].split('.')[0].upper()
- # Check if extracted tier starts with "TIER-" and adjust accordingly
- if extracted_tier.startswith("TIER-"):
- Card['tier'] = extracted_tier.split("TIER-")[-1]
- else:
- Card['tier'] = extracted_tier
-
- Card['val'] = int(card.find(class_='score-card').find('span').text)
- Card['qty'] = int(card.find(class_='qty').text.strip())
- Card['cost'] = int(card.find(class_='cost').find('span').text)
-
- self.Cards.append(Card)
- except Exception as e:
- logger.error(f"Error processing card: {e}\nCard HTML:\n{card}")
-
- self.loadDF()
- except Exception as e:
- logger.error(f"Exception during data fetch: {e}")
- def loadPage(self):
- logger.debug("Market Load Page.")
- self.asOf = datetime.utcnow()
- def getPlayerInfo(self):
- logger.debug("Market Get Player Info")
- if self.player is None: self.player = Player()
- self.player.fetchData()
- def filterMarketCards(self, force=True):
- logger.debug("Market Filter Cards.")
- clist = [None] * 152
- if force:
- self.getPlayerInfo()
- Cards = self.player.Cards
- else:
- today = datetime.utcnow().strftime('%Y-%m-%d')
- Cards = PlayerDB.search(Query().fragment({'date': today}))
- if len(Cards) == 0:
- self.getPlayerInfo()
- Cards = self.player.Cards
- for card in Cards:
- clist[card['card-num']] = card['stock']
-
- # Removed Selenium-specific functionality.
- # Uncomment and modify the code if needed for different implementation.
- # js = f"clist={json.dumps(clist)}\n"
- # js += """
- # cards=document.getElementsByClassName('wrapper-market-card')
- # for (var i = 0; i < cards.length; i++) {
- # cardNum = cards.item(i).getElementsByClassName('pornstar-number')[0].outerText;
- # innerCard = cards.item(i).getElementsByClassName('inner-market-card')[0]
- # var stock = innerCard.getElementsByClassName('Stock')[0]
- # if (stock){stock.innerText = "Stock: " + clist[cardNum]}
- # else {
- # let qty = document.createElement('div');
- # qty.classList.add('Stock')
- # qty.innerText = "Stock: " + clist[cardNum]
- # innerCard.appendChild(qty)
- # }
- # if (clist[cardNum].includes('CRYSTAL')){
- # cards.item(i).style.setProperty('Display','None');
- # }
- # }
- # """
- # print(js)
- # self.driver.execute_script(js)
- def loadDF(self):
- logger.debug("Market Load DF.")
- self.df = pd.DataFrame(self.Cards)
- self.df.sort_values(by='card-num', ascending=True, inplace=True)
- def show(self, fields=['card-num', 'name', 'level', 'qty', 'cost'], filter=''):
- logger.debug("Market Show Data.")
- if filter != '':
- pdf = self.df.query(filter)
- else:
- pdf = self.df
- print(pdf[fields].to_string(index=False))
- def commit(self):
- def newCard(Card):
- thisCard = {}
- thisCard['date'] = today
- thisCard['count'] = 1
- thisCard['card-num'] = Card['card-num']
- thisCard['name'] = Card['name']
- thisCard['qty'] = Card['qty']
- thisCard['cost'] = Card['cost']
- thisCard['cost-min'] = Card['cost']
- thisCard['cost-max'] = Card['cost']
- thisCard['level'] = Card['level']
- thisCard['tier'] = Card['tier']
- if Card['cost'] != 0:
- MarketDB.insert(thisCard)
- def updateCard(Card):
- matchCard = MarketDB.search(Query().fragment({'date': today, 'card-num': Card['card-num']}))
- if len(matchCard) == 0:
- newCard(Card)
- else:
- thisCard = matchCard[0]
- newData = {}
- newData['count'] = thisCard['count'] + 1
- newData['qty'] = round((thisCard['count'] * thisCard['qty'] + Card['qty']) / (thisCard['count'] + 1), 1)
- newData['cost'] = round((thisCard['count'] * thisCard['cost'] + Card['cost']) / (thisCard['count'] + 1), 1)
- if 'cost-min' not in thisCard or thisCard['cost-min'] > Card['cost']:
- newData['cost-min'] = Card['cost']
- if 'cost-max' not in thisCard or thisCard['cost-max'] < Card['cost']:
- newData['cost-max'] = Card['cost']
- if Card['cost'] != 0:
- MarketDB.update(newData, Query().fragment({'date': today, 'card-num': Card['card-num']}))
- logger.debug("Market Commit.")
- today = self.asOf.strftime('%Y-%m-%d')
- current = MarketDB.search(Query()['date'] == today)
- if len(current) == 0:
- for Card in self.Cards:
- newCard(Card)
- else:
- for Card in self.Cards:
- updateCard(Card)
|