Skip to content

Commit

Permalink
Settings pane plugged
Browse files Browse the repository at this point in the history
  • Loading branch information
Philaeux committed Aug 6, 2023
1 parent 70e2b22 commit c766687
Show file tree
Hide file tree
Showing 14 changed files with 343 additions and 186 deletions.
44 changes: 25 additions & 19 deletions src/dota_notes/app_dota.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,22 +2,28 @@
from dota2.client import Dota2Client
from dota2.msg import EDOTAGCMsg

import logging

from dota_notes.data.messages import Message, MessageType, MessageServerIdResponse, MessageConSatus, \
MessageServerIdRequest

logging.basicConfig(format='[%(asctime)s] %(levelname)s %(name)s: %(message)s', level=logging.DEBUG)
from dota_notes.data.messages import MessageServerIdResponse, MessageConnectionStatus, MessageServerIdRequest, \
MessageConnect


def dota_process(username, password, match_id_in_queue, server_id_out_queue):
"""Dota client spawner"""
app = DotaApp(username, password, match_id_in_queue, server_id_out_queue)
app.run()


class DotaApp:
def __init__(self, username, password, message_queue_dota, message_queue_qt):
self.username = username
"""Dota client processing jobs requested by the Qt process.
Args:
user: Steam username
password: Steam password
message_queue_dota: Queue to receive jobs
message_queue_qt: Queue to send job results
"""

def __init__(self, user, password, message_queue_dota, message_queue_qt):
self.user = user
self.password = password
self.message_queue_dota = message_queue_dota
self.message_queue_qt = message_queue_qt
Expand All @@ -35,37 +41,37 @@ def __init__(self, username, password, message_queue_dota, message_queue_qt):
self.dota.on(EDOTAGCMsg.EMsgGCSpectateFriendGameResponse, self.on_spectate_response)

def on_logged_on(self):
self.message_queue_qt.put(Message(MessageType.CLIENTS_STATUS, MessageConSatus("On", "Try")))
self.message_queue_qt.put(MessageConnectionStatus("On", "Try"))
self.dota.launch()

def do_dota_stuff(self):
self.message_queue_qt.put(Message(MessageType.CLIENTS_STATUS, MessageConSatus("On", "On")))
self.message_queue_qt.put(MessageConnectionStatus("On", "On"))
self.dota_ready = True

def on_disconnect(self):
self.message_queue_qt.put(Message(MessageType.CLIENTS_STATUS, MessageConSatus("Off", "Off")))
self.message_queue_qt.put(MessageConnectionStatus("Off", "Off"))

def on_spectate_response(self, response):
self.message_queue_qt.put(Message(MessageType.SERVER_ID_RESPONSE,
MessageServerIdResponse(response.server_steamid)))
self.message_queue_qt.put(MessageServerIdResponse(response.server_steamid))

def connect(self):
self.message_queue_qt.put(Message(MessageType.CLIENTS_STATUS, MessageConSatus("Try", "Off")))
self.steam.login(username=self.username, password=self.password)
self.message_queue_qt.put(MessageConnectionStatus("Try", "Off"))
self.steam.login(username=self.user, password=self.password)

def run(self):
while self.keep_running:
if not self.message_queue_dota.empty():
message = self.message_queue_dota.get(block=False)
if message.message_type == MessageType.CLIENTS_CONNECT:
if isinstance(message, MessageConnect):
self.user = message.user
self.password = message.password
self.connect()
else:
self.message_buffer_queue.append(message)
if self.dota_ready and len(self.message_buffer_queue) > 0:
message = self.message_buffer_queue.pop(0)
if message.message_type == MessageType.SERVER_ID_REQUEST:
message_request: MessageServerIdRequest = message.payload
self.dota.send(EDOTAGCMsg.EMsgGCSpectateFriendGame, {'steam_id': int(message_request.account_id)})
if isinstance(message, MessageServerIdRequest):
self.dota.send(EDOTAGCMsg.EMsgGCSpectateFriendGame, {'steam_id': int(message.account_id)})
self.steam.sleep(1)

def stop(self):
Expand Down
13 changes: 7 additions & 6 deletions src/dota_notes/app_flask.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,18 @@


def flask_process(port, match_info_queue):
"""Simple Flask application listening to GSI and sends match_ids detected to the Qt Application.
Args:
port: port to listen to
match_info_queue: Queue to transmit the match information
"""
"""Flask app spawner"""
flask_app = FlaskApp(port, match_info_queue)
flask_app.run()


class FlaskApp:
"""Simple Flask application listening to GSI and sends info detected to the Qt Application.
Args:
port: port to listen to
match_info_queue: Queue to transmit the match information
"""
def __init__(self, port, match_info_queue):
self.app = Flask(__name__)
self.port = port
Expand Down
23 changes: 0 additions & 23 deletions src/dota_notes/data/game_state.py

This file was deleted.

36 changes: 19 additions & 17 deletions src/dota_notes/data/messages.py
Original file line number Diff line number Diff line change
@@ -1,25 +1,25 @@
from typing import Optional
from enum import Enum
class MessageConnect:
"""Ask the client to connect with specific credentials
Attributes:
user: steam username
password: steam password
"""
user: str
password: str

class MessageType(Enum):
UNKNOWN = 0
CLIENTS_STATUS = 1
CLIENTS_CONNECT = 2
SERVER_ID_REQUEST = 3
SERVER_ID_RESPONSE = 4
def __init__(self, user: str, password: str):
self.user = user
self.password = password


class Message:
message_type: MessageType = MessageType.UNKNOWN
payload: Optional[object]
class MessageConnectionStatus:
"""Report the status of the connections of steam/dota clients
def __init__(self, message_type: MessageType, payload: Optional[object] = None):
self.message_type = message_type
self.payload = payload


class MessageConSatus:
Attributes:
steam: Steam connection status
dota: Dota connection status
"""
steam: str
dota: str

Expand All @@ -29,13 +29,15 @@ def __init__(self, steam: str, dota: str):


class MessageServerIdRequest:
"""Request the server ID a specific account is playing on"""
account_id: str

def __init__(self, account_id: str):
self.account_id = account_id


class MessageServerIdResponse:
"""Server ID where a specific player is playing on"""
server_id: int

def __init__(self, server_id: int):
Expand Down
71 changes: 60 additions & 11 deletions src/dota_notes/data/database.py → src/dota_notes/data/models.py
Original file line number Diff line number Diff line change
@@ -1,33 +1,56 @@
import os
import sys
from select import select
from typing import Optional

from sqlalchemy import create_engine, String
from sqlalchemy.orm import Session, DeclarativeBase, mapped_column, Mapped


class Database:
class Database(object):
"""Singleton defining database URI and unique ressources.
Attributes:
_instance: Singleton instance
uri: database location
engine: database connection used for session generation
"""

_instance = None

def __new__(cls, *args, **kwargs):
"""New overload to create a singleton."""
if not isinstance(cls._instance, cls):
cls._instance = object.__new__(cls)
return cls._instance

def __init__(self):
"""Defines all necessary ressources (URI & engine) and create database if necessary."""
if getattr(sys, 'frozen', False):
file_uri = os.path.dirname(sys.executable)
elif __file__:
file_uri = os.path.dirname(__file__)
self.uri = 'sqlite+pysqlite:///{0}/sqlite.db'.format(file_uri)
self.engine = create_engine(self.uri, echo=False)
Base.metadata.create_all(self.engine)
BaseEntity.metadata.create_all(self.engine)

with Session(self.engine) as session:
if session.get(Setting, "version") is None:
session.add(Setting("version", "1"))
if session.get(SettingEntity, "version") is None:
session.add(SettingEntity("version", "1"))
session.commit()


class Base(DeclarativeBase):
class BaseEntity(DeclarativeBase):
"""Database model base class"""
pass


class Setting(Base):
class SettingEntity(BaseEntity):
"""An application setting.
Attributes:
key: unique string defining a setting
value: value of the setting
"""
__tablename__ = 'settings'

key: Mapped[str] = mapped_column(primary_key=True)
Expand All @@ -41,7 +64,23 @@ def __repr__(self) -> str:
return f"Setting(key={self.key!r}, value={self.value!r})"


class Player(Base):
class PlayerEntity(BaseEntity):
"""Player information
Attributes:
steam_id: unique identifier
name: last seen name
pro_name: pro name (if fetched from the API)
custom_name: user set name
smurf: user defined smurf indicator
is_racist: flag
is_sexist: flag
is_toxic: flag
is_feeder: flag
gives_up: flag
destroys_items: flag
note: user set note
"""
__tablename__ = 'players'

steam_id: Mapped[str] = mapped_column(primary_key=True)
Expand Down Expand Up @@ -74,7 +113,12 @@ def __init__(self, steam_id, name, pro_name=None, custom_name="", smurf="", is_r

@staticmethod
def make_from_state(player_state):
return Player(
"""Create an entity from its state counterpart
Args:
player_state: state to import information from
"""
return PlayerEntity(
str(player_state.steam_id),
player_state.name,
player_state.pro_name if player_state.pro_name != "" else None,
Expand All @@ -89,6 +133,12 @@ def make_from_state(player_state):

@staticmethod
def import_export(from_object, to_object):
"""Copy the attributes from state to entity (or reverse)
Args:
from_object: Object to copy attributes from (can be entity or state)
to_object: Object to copy attributes to (can be entity or state)
"""
to_object.pro_name = from_object.pro_name
to_object.custom_name = from_object.custom_name
to_object.smurf = from_object.smurf
Expand All @@ -101,5 +151,4 @@ def import_export(from_object, to_object):
to_object.note = from_object.note

def __repr__(self) -> str:
return f"Player(steam_id{self.steam_id!r}, last_seen_name={self.name!r}, " \
f"pro_name={self.pro_name!r}, custom_name={self.custom_name!r}, smurf={self.smurf!r})"
return f"Player(steam_id{self.steam_id!r}, last_seen_name={self.name!r}, custom_name={self.custom_name!r})"
16 changes: 0 additions & 16 deletions src/dota_notes/data/player_state.py

This file was deleted.

Loading

0 comments on commit c766687

Please sign in to comment.