PoeTrade/src/data.py

161 lines
5.4 KiB
Python

from enum import Enum
from typing import Union
import re
import datetime
import logging
re_trade = re.compile(
r'Hi, I would like to buy your (?P<item>.+) listed for (?P<amount>\d+) (?P<currency>\S+) in (?P<league>\S+) '
r'\(stash tab "(?P<tab>.+)"; position: left (?P<col>\d+), top (?P<row>\d+)\)'
)
re_log = re.compile(
r'(?P<date>\d\d\d\d/\d\d/\d\d \d\d:\d\d:\d\d) (\d+) (\S+) \[(?P<level>\S+) (\S+) (\d+)\] '
r'(?P<channel>[#@%$&]?)(?P<ToFrom>To|From)?\s?(?P<guild><\S+>)? ?(?P<user>[^:]+): (?P<message>.*)'
)
re_clipboard = None
re_clipboard_prefix = None
log = logging.getLogger(__name__)
logging.basicConfig(level=logging.DEBUG, format='%(levelname)-8s:: %(message)s')
def compile_regex(conf: dict):
global re_trade, re_log, re_clipboard, re_clipboard_prefix
if 'General' in conf:
if 're_log' in conf['Parser']:
re_log = re.compile(conf['Parser']['re_log'])
if 're_trade' in conf['Parser']:
re_trade = re.compile(conf['Parser']['re_trade'])
if 're_clipboard_prefix' in conf['Parser']:
re_clipboard = re.compile(conf['Parser']['re_clipboard_prefix'] + conf['Parser']['re_trade'])
re_clipboard_prefix = re.compile(conf['Parser']['re_clipboard_prefix'] + '.*')
class Channel(Enum):
WHISPER = 0
GLOBAL = 1
PARTY = 2
LOCAL = 3
TRADE = 4
GUILD = 5
channel_mapping = {'#': Channel.GLOBAL,
'@': Channel.WHISPER,
'%': Channel.PARTY,
'': Channel.LOCAL,
'$': Channel.TRADE,
'&': Channel.GUILD}
class Trade():
def __init__(self,
nrItems: int,
item: str,
amount: float,
currency: str,
tab: str,
row: str,
col: str,
league: str) -> None:
self.nrItems = int(nrItems) if nrItems else None
self.item = item
self.amount = amount
self.currency = currency
self.tab = tab
self.row = int(row) if row else None
self.col = int(col) if col else None
self.league = league
@classmethod
def by_regex_result(cls, res):
return cls(nrItems=res['nrItems'],
item=res['item'],
amount=float(res['amount']),
currency=res['currency'],
tab=res['tab'],
row=res['row'],
col=res['col'],
league=res['league'])
def __str__(self) -> str:
return f'Trade: {self.nrItems} {self.item} for {self.amount} {self.currency} in {self.tab} ({self.row}/{self.col}) in {self.league} league'
def __hash__(self) -> int:
return hash((self.nrItems, self.item, self.amount, self.currency, self.tab, self.row, self.col, self.league))
def __eq__(self, __o: object) -> bool:
return (isinstance(__o, self.__class__)
and self.nrItems == __o.nrItems
and self.item == __o.item
and self.amount == __o.amount
and self.currency == __o.currency
and self.tab == __o.tab
and self.row == __o.row
and self.col == __o.col
and self.league == __o.league)
class Message():
def __init__(self,
message: str,
date: datetime.datetime,
user: str,
channel: Channel,
guild: Union[str, None] = None,
to_from: Union[str, None] = None) -> None:
self.message = message
self.date = date
self.channel = channel
self.user = user
self.guild = guild
self.to_from = to_from
self.trade: Union[Trade, None] = None
if self.channel is Channel.WHISPER:
self.parse_trade()
@classmethod
def from_text(cls, text: str):
result = re_log.search(text)
if not result:
log.debug(f'Result is none for text "{text}"')
return None
date = datetime.datetime.strptime(
result.group('date'), '%Y/%m/%d %H:%M:%S')
guild = result.group('guild')
if guild:
guild = guild.strip('<>')
return cls(result.group('message'),
date,
result.group('user'),
channel_mapping[result.group('channel')],
guild,
result.group('ToFrom'))
def __str__(self) -> str:
text = f'Message: {self.date} - {self.channel.name}: '
if self.to_from:
text = text + f'{self.to_from} '
if self.guild:
text = text + f'<{self.guild}> '
text = text + f'{self.user}: {self.message}'
return text
def parse_trade(self) -> None:
res = re_trade.search(self.message)
if res:
self.trade = Trade.by_regex_result(res)
def unique_trade(self) -> int:
assert self.trade
return hash((self.user, self.trade.__hash__()))
def unique_user_item(self) -> int:
assert self.trade
if self.to_from == 'From':
# Item in my stash.
return hash((self.trade.item, self.trade.tab, self.trade.row, self.trade.col, self.trade.league))
else:
# Item in a stash from another char
return hash((self.trade.item, self.trade.league))