Skip to content

Commit

Permalink
Application blank, architecture & utils
Browse files Browse the repository at this point in the history
Signed-off-by: selfkilla666 <[email protected]>
  • Loading branch information
selfkilla666 committed Jan 1, 2024
1 parent fbfee1d commit 91f3d9e
Show file tree
Hide file tree
Showing 17 changed files with 874 additions and 0 deletions.
Empty file added glyphify/__init__.py
Empty file.
Empty file added glyphify/classes/__init__.py
Empty file.
238 changes: 238 additions & 0 deletions glyphify/classes/application.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,238 @@
# Code by @selfkilla666
# https://github.com/witch-software/glyphify
# MIT License

from __future__ import annotations

from typing import Optional, TYPE_CHECKING
from pathlib import Path

from glyphify.classes.settings import TomlSettings
from glyphify.classes.discord_rpc import GlyphifyDiscordRPC
from glyphify.utils.thread import StoppableThread
from glyphify.utils.path import get_user_local_directory
from glyphify.utils.logs import generate_log_path
from glyphify.utils.debug import log_debug_info

import loguru
import eel

if TYPE_CHECKING:
import argparse


# Paths
LOG_FILE_PATH: str = str(generate_log_path(get_user_local_directory()))
SETTINGS_PATH: str = str(Path(get_user_local_directory() / "settings.toml"))
EEL_DIRECTORY: Path = Path("web")
EEL_JINJA_TEMPLATES_DIRECTORY: Path = Path("templates")


class GlyphifyApplication:
"""
Main class representing the Glyphify application.
Attributes:
APPLICATION_NAME (str): The name of the Glyphify application.
APPLICATION_VERSION (str): The version of the Glyphify application.
APPLICATION_ORG_NAME (str): The organization name associated with Glyphify.
APPLICATION_ORG_DOMAIN (str): The organization domain associated with Glyphify.
APPLICATION_TITLE_FORMAT (str): The formatted title of the Glyphify application.
logger (loguru.Logger): The logger instance for Glyphify.
argv (list[str]): Command-line arguments for Glyphify.
arguments (argparse.Namespace): Parsed command-line arguments.
settings (TomlSettings): The settings instance for Glyphify.
debug_mode (bool): Flag indicating whether Glyphify is running in debug mode.
windowless (bool): Flag indicating whether Glyphify is running in windowless mode.
discord_rpc (GlyphifyDiscordRPC): Discord RPC instance for Glyphify activity.
discord_rpc_thread (StoppableThread): Thread for running the Discord RPC.
eel_window_thread (StoppableThread): Thread for managing the Eel window.
Methods:
__init__(argv: list[str], arguments: argparse.Namespace, logger: Optional[loguru.Logger] = None, settings: Optional[TomlSettings] = None) -> None:
Initialize the GlyphifyApplication instance.
initialize_logger() -> None:
Initialize the logger for Glyphify.
initialize_settings() -> None:
Initialize the settings for Glyphify.
setup_eel_window() -> None:
Set up the Eel window for Glyphify.
run(argv: Optional[list[str]] = None) -> None:
Run the Glyphify application.
close() -> None:
Close the Glyphify application.
on_window_close() -> None:
Handle the event when the application window is closed.
"""

# TODO: Add application metadata
# TODO: Add documentation for this code
# TODO: Add CLI mode

# Application metadata
APPLICATION_NAME: str = "Glyphify"
APPLICATION_VERSION: str = "1.0.0"
APPLICATION_ORG_NAME: str = "Witch Software"
APPLICATION_ORG_DOMAIN: str = "witch-software.com"

APPLICATION_TITLE_FORMAT: str = f"{APPLICATION_NAME} v{APPLICATION_VERSION}"

# Variables
logger: loguru.Logger
argv: list[str]
arguments: argparse.Namespace
settings: TomlSettings
debug_mode: bool = False
windowless: bool = False

# Discord RPC for activity
discord_rpc: GlyphifyDiscordRPC = GlyphifyDiscordRPC()

# Threads
discord_rpc_thread: StoppableThread
eel_window_thread: StoppableThread

def __init__(
self,
argv: list[str],
arguments: argparse.Namespace,
*,
logger: Optional[loguru.Logger] = None,
settings: Optional[TomlSettings] = None,
) -> None:
"""
Initialize the GlyphifyApplication instance.
Parameters:
argv (list[str]): Command-line arguments for Glyphify.
arguments (argparse.Namespace): Parsed command-line arguments.
logger (Optional[loguru.Logger]): Optional logger instance for Glyphify.
settings (Optional[TomlSettings]): Optional settings instance for Glyphify.
"""

# Initialize logger
if logger:
self.logger = logger
else:
self.initialize_logger()

# Store variables
self.argv = argv
self.arguments = arguments
self.debug_mode = self.arguments.debug or False
self.windowless = self.arguments.windowless or False

# Log debug info about application
log_debug_info(self)

self.logger.info("Start application initialization...")

# Initialize settings
if settings:
self.settings = settings
else:
self.initialize_settings()

# Initialize eel and Discord RPC activity
eel.init(str(EEL_DIRECTORY))
self.discord_rpc.setup()

def initialize_logger(self):
"""
Initialize the logger for Glyphify.
"""

self.logger: loguru.Logger = loguru.logger
self.logger.add(
LOG_FILE_PATH,
format="{time:HH:mm:ss.SS} ({file}) [{level}] {message}",
colorize=True,
backtrace=True,
)

self.logger.success("Logger initialized!")
self.logger.debug(f'Logs stored into "{LOG_FILE_PATH}"')

def initialize_settings(self):
"""
Initialize the settings for Glyphify.
"""

self.logger.info("Initialize application settings...")

self.settings = TomlSettings(SETTINGS_PATH, logger=self.logger)
self.settings.load_settings()

self.logger.success("Settings initialized!")

def setup_eel_window(self) -> None:
"""
Set up the Eel window for Glyphify.
"""

@eel.expose
def onWindowClosed():
self.on_window_close()
return

eel.start("templates/index.html", mode="chrome", port=9876)

def run(self, *, argv: Optional[list[str]] = None) -> None:
"""
Run the Glyphify application.
Parameters:
argv (Optional[list[str]]): Optional command-line arguments.
"""

self.logger.info("Application start running...")

self.discord_rpc_thread = StoppableThread(target=self.discord_rpc.run)
self.discord_rpc_thread.start()

self.logger.info("Discord RPC activity is set up!")

self.eel_window_thread = StoppableThread(target=self.setup_eel_window)
self.eel_window_thread.start()

eel.setWindowTitle(self.APPLICATION_TITLE_FORMAT) # type: ignore[attr-defined]

self.logger.success("Application starts!")

self.eel_window_thread.join()

def close(self) -> None:
"""
Close the Glyphify application.
"""

self.logger.info("Terminate the application...")

self.discord_rpc_thread.stop()
self.eel_window_thread.stop()

self.logger.info("All threads are stopped.")

# FIXME: Make clearly exit

def on_window_close(self) -> None:
"""
Handle the event when the application window is closed.
"""

self.logger.info("Window is closed! Stopping the application...")

self.settings.save_settings()

self.close()
113 changes: 113 additions & 0 deletions glyphify/classes/discord_rpc.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
# Code by @selfkilla666
# https://github.com/witch-software/glyphify
# MIT License

from __future__ import annotations

from typing import Optional

from discordrpc import RPC as DiscordRPCActivity # type: ignore[import-untyped]
from discordrpc import button


class GlyphifyDiscordRPC:
"""
Class for managing Discord Rich Presence integration for Glyphify.
Attributes:
DISCORD_RPC_APPLICATION_ID (int): Default Discord RPC application ID for Glyphify.
rpc (DiscordRPCActivity): Discord RPC activity instance.
buttons (list[dict[str, str]]): List of buttons for the Discord Rich Presence.
Methods:
__init__(application_id: Optional[int] = None) -> None:
Initialize the GlyphifyDiscordRPC instance.
create_buttons() -> list[dict[str, str]]:
Create and return a list of buttons for the Discord Rich Presence.
setup() -> None:
Set up the Discord Rich Presence with default or user-specified buttons.
set_activity(**kwargs) -> None:
Set the Discord Rich Presence activity with the specified parameters.
run() -> None:
Run the Discord Rich Presence.
"""

DISCORD_RPC_APPLICATION_ID: int = 1191380153335566426

rpc: DiscordRPCActivity
buttons: list[dict[str, str]]

def __init__(self, *, application_id: Optional[int] = None) -> None:
"""
Initialize the GlyphifyDiscordRPC instance.
Parameters:
application_id (Optional[int]): Optional Discord RPC application ID.
Defaults to None.
Returns:
None
"""

if application_id:
self.DISCORD_RPC_APPLICATION_ID = application_id

self.rpc = DiscordRPCActivity.set_id(self.DISCORD_RPC_APPLICATION_ID)

def create_buttons(self) -> list[dict[str, str]]:
"""
Create and return a list of buttons for the Discord Rich Presence.
Returns:
list[dict[str, str]]: Formatted payload of buttons for RPC
"""

buttons: list[dict[str, str]]

buttons = button(
button_one_label="Repository",
button_one_url="https://github.com/witch-software/glyphify",
button_two_label="Download too!",
button_two_url="https://witchsoftware.itch.io/glyphify",
)

return buttons

def setup(self) -> None:
"""
Set up the Discord Rich Presence.
Returns:
None
"""

self.buttons = self.create_buttons()

self.rpc.set_activity(
state="pip install discord-rpc",
details="Discord RPC",
buttons=self.buttons,
timestamp=self.rpc.timestamp,
)

def set_activity(self, **kwargs) -> None:
"""
Set the Discord Rich Presence activity with the specified parameters.
Parameters:
**kwargs: Keyword arguments for setting the activity.
"""

self.rpc.set_activity(**kwargs)

def run(self) -> None:
"""
Run the Discord Rich Presence.
"""

self.rpc.run()
Loading

0 comments on commit 91f3d9e

Please sign in to comment.