Compare commits

..

1 Commits

Author SHA1 Message Date
d806ecf947 some directinput tests 2023-05-07 09:01:23 +02:00
11 changed files with 190 additions and 238 deletions

View File

@ -1,3 +1,3 @@
[flake8] [flake8]
; ignore = E501 ; ignore = E501
max-line-length = 180 max-line-length = 160

View File

@ -4,6 +4,7 @@ General:
after_sendkeys_key_wait: 0.001 # Amount of seconds to wait after a keypress. Default is 0.01 after_sendkeys_key_wait: 0.001 # Amount of seconds to wait after a keypress. Default is 0.01
poe_window_title: 'Path of Exile' poe_window_title: 'Path of Exile'
poe_path: 'D:\\SteamLibrary\\steamapps\\common\\Path of Exile\\PathOfExileSteam.exe' poe_path: 'D:\\SteamLibrary\\steamapps\\common\\Path of Exile\\PathOfExileSteam.exe'
username: 'Rotzhase' # Used for leaving a group
Chat: Chat:
# Define chat messages with the following placeholders: # Define chat messages with the following placeholders:
# message, date, channel, user, guild, to_from, item, amount, currency, tab, row, col, league, # message, date, channel, user, guild, to_from, item, amount, currency, tab, row, col, league,
@ -12,10 +13,6 @@ Chat:
ty: 'Thank you and good luck.' ty: 'Thank you and good luck.'
sold: 'Sorry, {item} is already sold' sold: 'Sorry, {item} is already sold'
Parser: Parser:
re_log: '(?P<date>\d\d\d\d/\d\d/\d\d \d\d:\d\d:\d\d) (\d+) (\S+) \[(?P<level>\S+) (\S+) (\d+)\] (?P<message>.*)' re_log: '(?P<date>\d\d\d\d/\d\d/\d\d \d\d:\d\d:\d\d) (\d+) (\S+) \[(?P<level>\S+) (\S+) (\d+)\] (?P<channel>[#@%$&]?)(?P<ToFrom>To|From)?\s?(?P<guild><\S+>)? ?(?P<user>[^:]+): (?P<message>.*)'
re_comm: '(?P<channel>[#@%$&]?)(?P<ToFrom>To|From)?\s?(?P<guild><\S+>)? ?(?P<user>[^:]+): (?P<message>.*)'
re_joined: ': (?P<user>\S+) has joined the area.'
re_trade: 'Hi, I(( would)|(''d)) like to buy your ?(?P<nrItems>\d*) (?P<item>.+?) (listed )?for (my )?(?P<amount>\d+(\.\d+)?) (?P<currency>\D+) in (?P<league>\w+)\.?( \(stash tab \"(?P<tab>.+)\"; position: left (?P<col>\d+), top (?P<row>\d+)\))?' re_trade: 'Hi, I(( would)|(''d)) like to buy your ?(?P<nrItems>\d*) (?P<item>.+?) (listed )?for (my )?(?P<amount>\d+(\.\d+)?) (?P<currency>\D+) in (?P<league>\w+)\.?( \(stash tab \"(?P<tab>.+)\"; position: left (?P<col>\d+), top (?P<row>\d+)\))?'
re_clipboard_prefix: '^@(?P<user>\S+) ' # this regex is used as a prefix for re_trade re_clipboard_prefix: '^@(?P<user>\S+) ' # this regex is used as a prefix for re_trade

View File

@ -2,19 +2,16 @@ from enum import Enum
from typing import Union from typing import Union
import re import re
import datetime import datetime
import logging import logging, coloredlogs
import coloredlogs
re_trade = re.compile( 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'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+)\)' 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+)\] (?P<message>.*)') 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+)\] '
re_comm = re.compile(r'(?P<channel>[#@%$&]?)(?P<ToFrom>To|From)?\s?(?P<guild><\S+>)? ?(?P<user>[^:]+): (?P<message>.*)') r'(?P<channel>[#@%$&]?)(?P<ToFrom>To|From)?\s?(?P<guild><\S+>)? ?(?P<user>[^:]+): (?P<message>.*)'
)
re_joined = re.compile(r': (?P<user>\S+) has joined the area.')
re_clipboard = None re_clipboard = None
re_clipboard_prefix = None re_clipboard_prefix = None
@ -24,14 +21,10 @@ logging.basicConfig(level=logging.DEBUG, format='%(levelname)-8s:: %(message)s')
def compile_regex(conf: dict): def compile_regex(conf: dict):
global re_trade, re_log, re_clipboard, re_clipboard_prefix, re_comm, re_joined global re_trade, re_log, re_clipboard, re_clipboard_prefix
if 'General' in conf: if 'General' in conf:
if 're_log' in conf['Parser']: if 're_log' in conf['Parser']:
re_log = re.compile(conf['Parser']['re_log']) re_log = re.compile(conf['Parser']['re_log'])
if 're_comm' in conf['Parser']:
re_comm = re.compile(conf['Parser']['re_comm'])
if 're_joined' in conf['Parser']:
re_joined = re.compile(conf['Parser']['re_joined'])
if 're_trade' in conf['Parser']: if 're_trade' in conf['Parser']:
re_trade = re.compile(conf['Parser']['re_trade']) re_trade = re.compile(conf['Parser']['re_trade'])
if 're_clipboard_prefix' in conf['Parser']: if 're_clipboard_prefix' in conf['Parser']:
@ -104,29 +97,16 @@ class Trade():
and self.league == __o.league) and self.league == __o.league)
class Entered(): class Message():
def __init__(self, user: str) -> None:
self.user = user
@classmethod
def from_message(cls, message: str):
result = re_joined.search(message)
if not result:
log.debug(f'Joined regex doesn\'t fit for text "{message}"')
return None
user = result.group('user')
log.debug(f'User {user} entered')
return cls(user)
class Communcation():
def __init__(self, def __init__(self,
message: str, message: str,
date: datetime.datetime,
user: str, user: str,
channel: Channel, channel: Channel,
guild: Union[str, None] = None, guild: Union[str, None] = None,
to_from: Union[str, None] = None) -> None: to_from: Union[str, None] = None) -> None:
self.message = message self.message = message
self.date = date
self.channel = channel self.channel = channel
self.user = user self.user = user
self.guild = guild self.guild = guild
@ -137,21 +117,24 @@ class Communcation():
@classmethod @classmethod
def from_text(cls, text: str): def from_text(cls, text: str):
result = re_comm.search(text) result = re_log.search(text)
if not result: if not result:
log.debug(f'communication regex doesn\'t fit for text "{text}"') log.debug(f'Result is none for text "{text}"')
return None return None
date = datetime.datetime.strptime(
result.group('date'), '%Y/%m/%d %H:%M:%S')
guild = result.group('guild') guild = result.group('guild')
if guild: if guild:
guild = guild.strip('<>') guild = guild.strip('<>')
return cls(result.group('message'), return cls(result.group('message'),
date,
result.group('user'), result.group('user'),
channel_mapping[result.group('channel')], channel_mapping[result.group('channel')],
guild, guild,
result.group('ToFrom')) result.group('ToFrom'))
def __str__(self) -> str: def __str__(self) -> str:
text = f'Message: {self.channel.name}: ' text = f'Message: {self.date} - {self.channel.name}: '
if self.to_from: if self.to_from:
text = text + f'{self.to_from} ' text = text + f'{self.to_from} '
if self.guild: if self.guild:
@ -176,28 +159,3 @@ class Communcation():
else: else:
# Item in a stash from another char # Item in a stash from another char
return hash((self.trade.item, self.trade.league)) return hash((self.trade.item, self.trade.league))
class Message():
def __init__(self,
message: str,
date: datetime.datetime) -> None:
self.message = message
self.date = date
self.communication = Communcation.from_text(message)
self.entered = Entered.from_message(message)
@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')
return cls(result.group('message'),
date)
def __str__(self) -> str:
text = f'Message: {self.date} - {self.message}: '
return text

View File

@ -3,7 +3,7 @@ from tkinter import Tk
from tkinter import Button, Label from tkinter import Button, Label
from .data import Message from .data import Message
from src import sendkeys from src import sendkeys
from typing import Callable, Dict from typing import Callable
from src.data import log from src.data import log
import sv_ttk import sv_ttk
@ -14,7 +14,7 @@ class Gui(Tk):
sv_ttk.set_theme("dark") sv_ttk.set_theme("dark")
self.title("Uber Trader") self.title("Uber Trader")
# self.geometry("300x200+10+20") # self.geometry("300x200+10+20")
self.overrideredirect(True) # remove border self.overrideredirect(1) # remove border
self.wm_withdraw() # Hide window self.wm_withdraw() # Hide window
self.attributes('-topmost', True) # always on top self.attributes('-topmost', True) # always on top
# style = ttk.Style() # style = ttk.Style()
@ -24,27 +24,22 @@ class Gui(Tk):
self.tab_control.bind("<ButtonPress-1>", self.start_move) self.tab_control.bind("<ButtonPress-1>", self.start_move)
self.tab_control.bind("<ButtonRelease-1>", self.stop_move) self.tab_control.bind("<ButtonRelease-1>", self.stop_move)
self.tab_control.bind("<B1-Motion>", self.do_move) self.tab_control.bind("<B1-Motion>", self.do_move)
self.tabs: Dict = dict() self.tabs = dict()
def add_tab(self, number: int, message: Message) -> None: def add_tab(self, number: int, message: Message) -> None:
if not message.communication:
return
self.wm_deiconify() self.wm_deiconify()
user = message.communication.user if message.user not in self.tabs:
if user not in self.tabs: self.tabs[message.user] = {'frame': ttk.Frame(self.tab_control)}
self.tabs[user] = {'frame': ttk.Frame(self.tab_control)} self.tabs[message.user]['items'] = {}
self.tabs[user]['items'] = {} frame = self.tabs[message.user]['frame']
frame = self.tabs[user]['frame'] if message.trade is not None:
if message.communication.trade is not None: if message.trade.item not in self.tabs[message.user]['items']:
item = message.communication.trade.item row = len(self.tabs[message.user]['items'])
if item not in self.tabs[user]['items']: self.tabs[message.user]['items'][message.trade.item] = {}
row = len(self.tabs[user]['items']) self.tabs[message.user]['items'][message.trade.item]['row'] = row
self.tabs[user]['items'][item] = {} self.tabs[message.user]['items'][message.trade.item]['message'] = message
self.tabs[user]['items'][item]['row'] = row ttk.Label(frame, text=message.trade.item).grid(column=0, row=row)
self.tabs[user]['items'][item]['message'] = message Label(frame, text=f'{message.trade.amount} {message.trade.currency}').grid(column=1, row=row)
ttk.Label(frame, text=item).grid(column=0, row=row)
Label(frame, text=f'{message.communication.trade.amount}'
' {message.communication.trade.currency}').grid(column=1, row=row)
self.add_button(tab=frame, text='Inv', callback=self.inv_callback, self.add_button(tab=frame, text='Inv', callback=self.inv_callback,
message=message).grid(column=2, row=row) message=message).grid(column=2, row=row)
self.add_button(tab=frame, text='Trade', callback=self.trade_callback, self.add_button(tab=frame, text='Trade', callback=self.trade_callback,
@ -56,7 +51,7 @@ class Gui(Tk):
callback=self.wait_callback, callback=self.wait_callback,
message=message).grid(column=5, row=row) message=message).grid(column=5, row=row)
self.add_button(tab=frame, text='X', callback=self.destroy_tab, message=message).grid(column=6, row=row) self.add_button(tab=frame, text='X', callback=self.destroy_tab, message=message).grid(column=6, row=row)
self.tab_control.add(frame, text=user) self.tab_control.add(frame, text=message.user)
else: else:
log.warning(f'Trade in message "{str(message)}" is None') log.warning(f'Trade in message "{str(message)}" is None')
@ -94,24 +89,16 @@ class Gui(Tk):
sendkeys.send_to_format(type='wait', message=message) sendkeys.send_to_format(type='wait', message=message)
def destroy_tab(self, message: Message, tab: ttk.Frame) -> None: def destroy_tab(self, message: Message, tab: ttk.Frame) -> None:
if message.communication is None: if message.user in self.tabs:
log.error(f'Error destroying tab: no communication in message {message.message}') if message.trade.item in self.tabs[message.user]['items']:
return
if message.communication.trade is None:
log.error(f'Error destroying tab: no trade in message {message.message}')
return
user = message.communication.user
item = message.communication.trade.item
if message.communication.user in self.tabs:
if message.communication.trade.item in self.tabs[message.communication.user]['items']:
# Delete the item # Delete the item
row = self.tabs[message.communication.user]['items'][item]['row'] row = self.tabs[message.user]['items'][message.trade.item]['row']
for widget in self.tabs[user]['frame'].grid_slaves(row=row): for widget in self.tabs[message.user]['frame'].grid_slaves(row=row):
widget.destroy() widget.destroy()
del self.tabs[user]['items'][item] del self.tabs[message.user]['items'][message.trade.item]
if len(self.tabs[user]['items']) == 0: if len(self.tabs[message.user]['items']) == 0:
# If no item from this user is left, then also delete the tab # If no item from this user is left, then also delete the tab
del self.tabs[user] del self.tabs[message.user]
tab.destroy() tab.destroy()
if not self.tabs: if not self.tabs:
self.wm_withdraw() self.wm_withdraw()

View File

@ -6,7 +6,6 @@ from src.pyside6.trade_widget import TradeCollection
from PySide6 import QtCore from PySide6 import QtCore
from PySide6.QtWidgets import QApplication, QMainWindow, QTabWidget, QSizePolicy from PySide6.QtWidgets import QApplication, QMainWindow, QTabWidget, QSizePolicy
import qdarktheme import qdarktheme
from typing import Dict
class ResizingTabWidget(QTabWidget): class ResizingTabWidget(QTabWidget):
@ -18,8 +17,8 @@ class ResizingTabWidget(QTabWidget):
self.setSizePolicy(QSizePolicy.Policy.Minimum, QSizePolicy.Policy.Minimum) self.setSizePolicy(QSizePolicy.Policy.Minimum, QSizePolicy.Policy.Minimum)
self.setGeometry(0, 0, 20, 20) self.setGeometry(0, 0, 20, 20)
self.trade_in_collections: Dict[int, TradeCollection] = {} self.trade_in_collections = {}
self.trade_out_collections: Dict[int, TradeCollection] = {} self.trade_out_collections = {}
self.setTabsClosable(True) self.setTabsClosable(True)
self.tabCloseRequested.connect(self.del_tab) self.tabCloseRequested.connect(self.del_tab)
@ -41,14 +40,14 @@ class ResizingTabWidget(QTabWidget):
self.main_window.updateSizes() self.main_window.updateSizes()
def new_trade(self, message: Message): def new_trade(self, message: Message):
if message.communication.trade: if message.trade:
unique_item = message.communication.unique_user_item() unique_item = message.unique_user_item()
if unique_item in self.trade_in_collections: if unique_item in self.trade_in_collections:
self.trade_in_collections[unique_item].add_trade(message) self.trade_in_collections[unique_item].add_trade(message)
else: else:
collection = TradeCollection(self, unique_item) collection = TradeCollection(self, unique_item)
collection.add_trade(message) collection.add_trade(message)
self.addTab(collection, message.communication.trade.item) self.addTab(collection, message.trade.item)
self.trade_in_collections[unique_item] = collection self.trade_in_collections[unique_item] = collection
self.main_window.show() self.main_window.show()
@ -77,7 +76,7 @@ class MainWindow(QMainWindow):
self.setWindowFlag(QtCore.Qt.WindowStaysOnTopHint) self.setWindowFlag(QtCore.Qt.WindowStaysOnTopHint)
self.setAttribute(QtCore.Qt.WA_TranslucentBackground) self.setAttribute(QtCore.Qt.WA_TranslucentBackground)
self.setWindowTitle("PoeTrader") self.setWindowTitle("My App")
self.tab_widget = ResizingTabWidget(self) self.tab_widget = ResizingTabWidget(self)
self.tab_widget.currentChanged.connect(self.updateSizes) self.tab_widget.currentChanged.connect(self.updateSizes)
@ -95,16 +94,6 @@ class MainWindow(QMainWindow):
def new_trade(self, message: Message): def new_trade(self, message: Message):
self.tab_widget.new_trade(message) self.tab_widget.new_trade(message)
@QtCore.Slot()
def new_entered(self, message: Message):
for collection in self.tab_widget.trade_in_collections.values():
for tradeWidget in collection.trades.values():
if tradeWidget.message.communication.user == message.entered.user:
log.debug(f'Found trade with user {message.entered.user}')
tradeWidget.setHighlightStyle()
return
log.debug(f'User {message.entered.user} trade not found')
def start_app(): def start_app():
app = QApplication(sys.argv) app = QApplication(sys.argv)

View File

@ -4,7 +4,7 @@ from PySide6.QtGui import QIcon
from src.data import Message from src.data import Message
from src import sendkeys from src import sendkeys
from src.data import log from src.data import log
from typing import Callable, Dict from typing import Callable
class TradeWidget(QWidget): class TradeWidget(QWidget):
@ -22,8 +22,7 @@ class TradeWidget(QWidget):
self.setSizePolicy(QSizePolicy.Policy.Fixed, QSizePolicy.Policy.Fixed) self.setSizePolicy(QSizePolicy.Policy.Fixed, QSizePolicy.Policy.Fixed)
self.main_layout.setContentsMargins(0, 0, 0, 0) self.main_layout.setContentsMargins(0, 0, 0, 0)
self.setLayout(self.main_layout) self.setLayout(self.main_layout)
self.setNormalStyle() assert message.trade
assert message.communication.trade
def new_button(self, icon_filename: str, tooltip: str, callback: Callable[[], None]) -> QPushButton: def new_button(self, icon_filename: str, tooltip: str, callback: Callable[[], None]) -> QPushButton:
icon = QIcon(icon_filename) icon = QIcon(icon_filename)
@ -42,13 +41,6 @@ class TradeWidget(QWidget):
self.main_layout.addWidget(label) self.main_layout.addWidget(label)
return label return label
def setNormalStyle(self):
self.setStyleSheet("margin:5px; border:0px solid rgb(0, 255, 0); ")
def setHighlightStyle(self):
self.setStyleSheet("margin:5px; border:1px solid rgb(0, 255, 0); ")
class Trade_In_Widget(TradeWidget): class Trade_In_Widget(TradeWidget):
@ -64,12 +56,11 @@ class Trade_In_Widget(TradeWidget):
self.close_button = self.new_button('icons/material_close.svg', 'Dismiss', self.close_callback) self.close_button = self.new_button('icons/material_close.svg', 'Dismiss', self.close_callback)
# self.label_item = self.new_Label(message.trade.item) # self.label_item = self.new_Label(message.trade.item)
assert message.communication.trade self.label_price = self.new_Label(f'{message.trade.amount} {message.trade.currency}')
self.label_price = self.new_Label(f'{message.communication.trade.amount} {message.communication.trade.currency}') self.label_user = self.new_Label(message.user)
self.label_user = self.new_Label(message.communication.user) assert message.trade
assert message.communication.trade if message.trade.tab:
if message.communication.trade.tab: self.label_tab = self.new_Label(message.trade.tab)
self.label_tab = self.new_Label(message.communication.trade.tab)
def inv_callback(self): def inv_callback(self):
sendkeys.invite(message=self.message) sendkeys.invite(message=self.message)
@ -105,17 +96,16 @@ class Trade_Out_Widget(TradeWidget):
self.close_button = self.new_button('icons/material_close.svg', 'Dismiss', self.close_callback) self.close_button = self.new_button('icons/material_close.svg', 'Dismiss', self.close_callback)
# self.label_item = self.new_Label(message.trade.item) # self.label_item = self.new_Label(message.trade.item)
assert message.communication.trade assert message.trade
self.label_price = self.new_Label(f'{message.communication.trade.amount} {message.communication.trade.currency}') self.label_price = self.new_Label(f'{message.trade.amount} {message.trade.currency}')
self.label_user = self.new_Label(message.communication.user) self.label_user = self.new_Label(message.user)
def join_callback(self): def join_callback(self):
sendkeys.join(message=self.message) sendkeys.join(message=self.message)
def thank_callback(self): def thank_callback(self):
sendkeys.send_to_format(type='ty', message=self.message) sendkeys.send_to_format(type='ty', message=self.message)
sendkeys.leave() sendkeys.kick(message=self.message)
sendkeys.return_to_ho()
def trade_callback(self): def trade_callback(self):
sendkeys.trade(message=self.message) sendkeys.trade(message=self.message)
@ -148,7 +138,7 @@ class TradeCollection(QWidget):
self.main_layout.setContentsMargins(0, 0, 0, 0) self.main_layout.setContentsMargins(0, 0, 0, 0)
self.setContentsMargins(0, 0, 0, 0) self.setContentsMargins(0, 0, 0, 0)
self.setLayout(self.main_layout) self.setLayout(self.main_layout)
self.trades: Dict[int. TradeWidget] = {} self.trades = {}
def childEvent(self, event: QtCore.QChildEvent) -> None: def childEvent(self, event: QtCore.QChildEvent) -> None:
if event.removed() or event.added(): if event.removed() or event.added():
@ -157,20 +147,20 @@ class TradeCollection(QWidget):
return super().childEvent(event) return super().childEvent(event)
def add_trade(self, message: Message) -> None: def add_trade(self, message: Message) -> None:
assert message.communication.trade assert message.trade
if message.communication.unique_trade() in self.trades: if message.unique_trade() in self.trades:
return return
if message.communication.to_from == 'From': if message.to_from == 'From':
trade = Trade_In_Widget(message, self) trade = Trade_In_Widget(message, self)
else: else:
trade = Trade_Out_Widget(message, self) trade = Trade_Out_Widget(message, self)
self.main_layout.addWidget(trade) self.main_layout.addWidget(trade)
self.trades[message.communication.unique_trade()] = trade self.trades[message.unique_trade()] = trade
def del_trade(self, message: Message): def del_trade(self, message: Message):
assert message.communication.trade assert message.trade
del self.trades[message.communication.unique_trade()] del self.trades[message.unique_trade()]
if not self.trades: if not self.trades:
self.parent.del_collection(self.unique_user_item) self.parent.del_collection(self.unique_user_item)
self.deleteLater() self.deleteLater()

View File

@ -1,9 +1,12 @@
from pywinauto.application import Application, ProcessNotFoundError from pywinauto.application import Application, ProcessNotFoundError
from pywinauto.findwindows import ElementNotFoundError from pywinauto.findwindows import ElementNotFoundError
import pydirectinput
from src import data from src import data
from src import config from src import config
pydirectinput.PAUSE = 0.001
def send_text(text: str) -> None: def send_text(text: str) -> None:
app = Application() app = Application()
@ -23,6 +26,37 @@ def send_text(text: str) -> None:
win.type_keys('{ENTER}^A{DELETE}' + text + '{ENTER}', with_spaces=True, pause=config.conf['General']['after_sendkeys_key_wait']) win.type_keys('{ENTER}^A{DELETE}' + text + '{ENTER}', with_spaces=True, pause=config.conf['General']['after_sendkeys_key_wait'])
def send_directInput(text: str) -> None:
# with pydirectinput.KeyBdInput.__dictoffset__
app = Application()
try:
app.connect(path=config.conf['General']['poe_path'])
except ProcessNotFoundError:
data.log.warning(f'App "{config.conf["General"]["poe_window_title"]}": "{config.conf["General"]["poe_path"]}" not found')
return
try:
win = app.window(title_re=config.conf['General']['poe_window_title'])
except ElementNotFoundError:
data.log.warning(f'Window Title "{config.conf["General"]["poe_window_title"]}" not found')
return
win.SetFocus()
win.wait(wait_for='active')
pydirectinput.press('return')
write_directInput(text)
pydirectinput.press('return')
pass
def write_directInput(text: str):
for c in text:
if c.isupper():
pydirectinput.keyDown('shift')
pydirectinput.press(c.lower())
pydirectinput.keyUp('shift')
else:
pydirectinput.press(c)
def escape_mods(text: str) -> str: def escape_mods(text: str) -> str:
text = text.replace('%', '{%}') text = text.replace('%', '{%}')
text = text.replace('+', '{+}') text = text.replace('+', '{+}')
@ -45,36 +79,36 @@ def send_to_format(type: str, message: data.Message) -> None:
message (data.Message): Message data. Placeholders in the message type will be replaced with this data. message (data.Message): Message data. Placeholders in the message type will be replaced with this data.
conf (dict): Configution dictionary where the messages are stored. conf (dict): Configution dictionary where the messages are stored.
""" """
if message.communication.trade: if message.trade:
text = config.conf['Chat'][type].format(message=message.communication.message, text = config.conf['Chat'][type].format(message=message.message,
date=message.date, date=message.date,
channel=message.communication.channel.name, channel=message.channel.name,
user=message.communication.user, user=message.user,
guild=message.communication.guild, guild=message.guild,
to_from=message.communication.to_from, to_from=message.to_from,
item=message.communication.trade.item, item=message.trade.item,
amount=message.communication.trade.amount, amount=message.trade.amount,
currency=message.communication.trade.currency, currency=message.trade.currency,
tab=message.communication.trade.tab, tab=message.trade.tab,
row=message.communication.trade.row, row=message.trade.row,
col=message.communication.trade.col, col=message.trade.col,
league=message.communication.trade.league) league=message.trade.league)
else: else:
text = config.conf['Chat'][type].format(message=message.communication.message, text = config.conf['Chat'][type].format(message=message.message,
date=message.date, date=message.date,
channel=message.communication.channel.name, channel=message.channel.name,
user=message.communication.user, user=message.user,
guild=message.communication.guild, guild=message.guild,
to_from=message.communication.to_from) to_from=message.to_from)
send_to(message.communication.user, text) send_to(message.user, text)
def invite(message: data.Message) -> None: def invite(message: data.Message) -> None:
send_text(f'/invite {message.communication.user}') send_text(f'/invite {message.user}')
def join(message: data.Message) -> None: def join(message: data.Message) -> None:
send_text(f'/hideout {message.communication.user}') send_text(f'/hideout {message.user}')
def return_to_ho() -> None: def return_to_ho() -> None:
@ -82,7 +116,7 @@ def return_to_ho() -> None:
def kick(message: data.Message) -> None: def kick(message: data.Message) -> None:
send_text(f'/kick {message.communication.user}') send_text(f'/kick {message.user}')
def leave() -> None: def leave() -> None:
@ -90,4 +124,4 @@ def leave() -> None:
def trade(message: data.Message) -> None: def trade(message: data.Message) -> None:
send_text(f'/tradewith {message.communication.user}') send_text(f'/tradewith {message.user}')

View File

@ -10,12 +10,10 @@ from src.pyside6.gui_pyside6 import MainWindow
class Log_Reader(QtCore.QObject): class Log_Reader(QtCore.QObject):
new_trade_signal = QtCore.Signal(Message) new_trade_signal = QtCore.Signal(Message)
new_out_trade_signal = QtCore.Signal(Message) new_out_trade_signal = QtCore.Signal(Message)
new_entered = QtCore.Signal(Message)
def __init__(self, window: MainWindow): def __init__(self, window: MainWindow):
super().__init__() super().__init__()
self.new_trade_signal.connect(window.new_trade, QtCore.Qt.QueuedConnection) self.new_trade_signal.connect(window.new_trade, QtCore.Qt.QueuedConnection)
self.new_entered.connect(window.new_entered, QtCore.Qt.QueuedConnection)
def read_log(self, logfile: str) -> None: def read_log(self, logfile: str) -> None:
try: try:
@ -24,10 +22,8 @@ class Log_Reader(QtCore.QObject):
for line in loglines: for line in loglines:
message = Message.from_text(line) message = Message.from_text(line)
log.debug(message) log.debug(message)
if message and message.communication and message.communication.trade: if message and message.trade:
self.new_trade_signal.emit(message) self.new_trade_signal.emit(message)
if message and message.entered:
self.new_entered.emit(message)
except IOError: except IOError:
log.error(f'Error opening log file {logfile}.') log.error(f'Error opening log file {logfile}.')

View File

@ -1,6 +1,15 @@
from src import sendkeys from src import sendkeys
from src import config from src import config
from src import data from src import data
import win32api
import win32gui
import win32con
from time import sleep
def test_send_direct():
config.read_config(r'config.yaml')
sendkeys.send_directInput('Hello World')
def test_sendkeys(): def test_sendkeys():
@ -74,3 +83,20 @@ def test_ty_wo_trade():
text = '2021/03/08 23:24:52 17931875 bb3 [INFO Client 1492] @From Sinusal: Hi, how are you doing? ' text = '2021/03/08 23:24:52 17931875 bb3 [INFO Client 1492] @From Sinusal: Hi, how are you doing? '
message = data.Message.from_text(text) message = data.Message.from_text(text)
sendkeys.send_to_format('ty', message) sendkeys.send_to_format('ty', message)
def test_win31_api():
hwndMain = win32gui.FindWindow(None, "cmd")
hwndChild = win32gui.GetWindow(hwndMain, win32con.GW_CHILD)
while(True):
# [hwndChild] this is the Unique ID of the sub/child application/proccess
# [win32con.WM_CHAR] This sets what PostMessage Expects for input theres KeyDown and KeyUp as well
# [0x44] hex code for D
# [0]No clue, good luck!
# temp = win32api.PostMessage(hwndChild, win32con.WM_CHAR, 0x44, 0) returns key sent
temp = win32api.PostMessage(hwndChild, win32con.WM_CHAR, 0x44, 0)
# print(temp) prints the returned value of temp, into the console
print(temp)
# sleep(1) this waits 1 second before looping through again
sleep(1)

View File

@ -53,13 +53,4 @@ def test_write_to_log_42():
assert (log_file) assert (log_file)
text = "2021/05/11 23:34:41 13600796 bad [INFO Client 9008] @From <CHIP> HenryHase: Hi, I would like to buy your Cortex Relic Chambers Map (T15) listed for 3.4 exalted in Ultimatum (stash tab \"$\"; position: left 3, top 9)" text = "2021/05/11 23:34:41 13600796 bad [INFO Client 9008] @From <CHIP> HenryHase: Hi, I would like to buy your Cortex Relic Chambers Map (T15) listed for 3.4 exalted in Ultimatum (stash tab \"$\"; position: left 3, top 9)"
with open(log_file, 'a') as f: with open(log_file, 'a') as f:
f.write(text) f.write(text)
def test_write_entered():
config.read_config(r'config.yaml')
log_file = config.get_value('General.log_file')
assert (log_file)
text = r'2023/05/21 22:39:25 28761078 cffb0719 [INFO Client 13392] : Sinusal has joined the area.'
with open(log_file, 'a') as f:
f.write(text)

View File

@ -1,6 +1,6 @@
from src import config
from src import data
from datetime import datetime from datetime import datetime
from src import config, data
from src.data import Channel from src.data import Channel
@ -11,56 +11,42 @@ def test_message_from():
'listed for 18 chaos in Ritual (stash tab "$"; position: left 22, top 5)' 'listed for 18 chaos in Ritual (stash tab "$"; position: left 22, top 5)'
message = data.Message.from_text(text) message = data.Message.from_text(text)
assert message assert message
assert message.communication assert message.user == 'NyhaiPuki'
assert message.communication.user == 'NyhaiPuki' assert message.message == 'Hi, I would like to buy your level 21 23% Vaal Impurity of Lightning ' \
assert message.communication.message == 'Hi, I would like to buy your level 21 23% Vaal Impurity of Lightning ' \
'listed for 18 chaos in Ritual (stash tab "$"; position: left 22, top 5)' 'listed for 18 chaos in Ritual (stash tab "$"; position: left 22, top 5)'
assert message.date == datetime(2021, 3, 8, 23, 24, 52) assert message.date == datetime(2021, 3, 8, 23, 24, 52)
assert message.communication.channel == Channel.WHISPER assert message.channel == Channel.WHISPER
assert message.communication.guild is None assert message.guild is None
assert message.communication.to_from == 'From' assert message.to_from == 'From'
assert message.communication.trade assert message.trade
assert message.communication.trade.amount == 18 assert message.trade.amount == 18
assert message.communication.trade.col == 22 assert message.trade.col == 22
assert message.communication.trade.row == 5 assert message.trade.row == 5
assert message.communication.trade.currency == 'chaos' assert message.trade.currency == 'chaos'
assert message.communication.trade.item == 'level 21 23% Vaal Impurity of Lightning' assert message.trade.item == 'level 21 23% Vaal Impurity of Lightning'
assert message.communication.trade.league == 'Ritual' assert message.trade.league == 'Ritual'
def test_message_from_float(): def test_message_from_float():
conf = config.read_config(r'config.yaml') conf = config.read_config(r'config.yaml')
data.compile_regex(conf) data.compile_regex(conf)
text = '2023/01/02 23:57:26 15123437 cffb0734 [INFO Client 16668] @From <SETSU?> LASTTRYPOEenjoyer: ' \ text = '2023/01/02 23:57:26 15123437 cffb0734 [INFO Client 16668] @From <SETSU?> LASTTRYPOEenjoyer: Hi, I would like to buy your Watcher\'s Eye, Prismatic Jewel listed for 2.5 divine in Sanctum (stash tab "$2"; position: left 8, top 7)'
'Hi, I would like to buy your Watcher\'s Eye, Prismatic Jewel listed for 2.5 divine in Sanctum (stash tab "$2"; position: left 8, top 7)'
message = data.Message.from_text(text) message = data.Message.from_text(text)
assert message assert message
assert message.communication assert message.user == 'LASTTRYPOEenjoyer'
assert message.communication.user == 'LASTTRYPOEenjoyer' assert message.message == 'Hi, I would like to buy your Watcher\'s Eye, Prismatic Jewel listed for 2.5 divine in Sanctum (stash tab "$2"; position: left 8, top 7)'
assert message.communication.message == 'Hi, I would like to buy your Watcher\'s Eye, Prismatic Jewel listed for 2.5 divine' \ assert message.date == datetime(2021, 3, 8, 23, 24, 52)
' in Sanctum (stash tab "$2"; position: left 8, top 7)' assert message.channel == Channel.WHISPER
assert message.date == datetime(2023, 1, 2, 23, 57, 26) assert message.guild is None
assert message.communication.channel == Channel.WHISPER assert message.to_from == 'From'
assert message.communication.guild == 'SETSU?' assert message.trade
assert message.communication.to_from == 'From' assert message.trade.amount == 18
assert message.communication.trade assert message.trade.col == 22
assert message.communication.trade.amount == 2.5 assert message.trade.row == 5
assert message.communication.trade.col == 8 assert message.trade.currency == 'chaos'
assert message.communication.trade.row == 7 assert message.trade.item == 'level 21 23% Vaal Impurity of Lightning'
assert message.communication.trade.currency == 'divine' assert message.trade.league == 'Ritual'
assert message.communication.trade.item == 'Watcher\'s Eye, Prismatic Jewel'
assert message.communication.trade.league == 'Sanctum'
def test_entered():
conf = config.read_config(r'config.yaml')
data.compile_regex(conf)
text = r'2023/05/07 18:18:03 35114562 cffb0719 [INFO Client 6416] : Oathussy has joined the area.'
message = data.Message.from_text(text)
assert message
assert message.entered
assert message.entered.user == 'Oathussy'
def test_message_to(): def test_message_to():
@ -69,14 +55,13 @@ def test_message_to():
text_to = '2021/01/24 23:11:23 17039703 bb2 [INFO Client 10144] @To EraseAndDelete: Thank you & good luck!' text_to = '2021/01/24 23:11:23 17039703 bb2 [INFO Client 10144] @To EraseAndDelete: Thank you & good luck!'
message = data.Message.from_text(text_to) message = data.Message.from_text(text_to)
assert message assert message
assert message.communication assert message.user == 'EraseAndDelete'
assert message.communication.user == 'EraseAndDelete' assert message.message == 'Thank you & good luck!'
assert message.communication.message == 'Thank you & good luck!'
assert message.date == datetime(2021, 1, 24, 23, 11, 23) assert message.date == datetime(2021, 1, 24, 23, 11, 23)
assert message.communication.channel == Channel.WHISPER assert message.channel == Channel.WHISPER
assert message.communication.guild is None assert message.guild is None
assert message.communication.to_from == 'To' assert message.to_from == 'To'
assert message.communication.trade is None assert message.trade is None
def test_message_global(): def test_message_global():
@ -85,11 +70,10 @@ def test_message_global():
text_global = '2021/02/10 19:01:56 2720500 bb2 [INFO Client 3464] #HarvestScarab: so by the time it was finally juiced you couldnt do it' text_global = '2021/02/10 19:01:56 2720500 bb2 [INFO Client 3464] #HarvestScarab: so by the time it was finally juiced you couldnt do it'
message = data.Message.from_text(text_global) message = data.Message.from_text(text_global)
assert message assert message
assert message.communication assert message.user == 'HarvestScarab'
assert message.communication.user == 'HarvestScarab' assert message.message == 'so by the time it was finally juiced you couldnt do it'
assert message.communication.message == 'so by the time it was finally juiced you couldnt do it'
assert message.date == datetime(2021, 2, 10, 19, 1, 56) assert message.date == datetime(2021, 2, 10, 19, 1, 56)
assert message.communication.channel == Channel.GLOBAL assert message.channel == Channel.GLOBAL
assert message.communication.guild is None assert message.guild is None
assert message.communication.to_from is None assert message.to_from is None
assert message.communication.trade is None assert message.trade is None