diff --git a/.gitignore b/.gitignore index f2ddd5e..a72ece6 100644 --- a/.gitignore +++ b/.gitignore @@ -26,5 +26,9 @@ build/ env/ venv -#Logs -app.log \ No newline at end of file +# Logs +app.log + +# Local Config +config.ini +*.ini \ No newline at end of file diff --git a/README.md b/README.md index 530da45..ab29b86 100644 --- a/README.md +++ b/README.md @@ -20,13 +20,35 @@ This Python script(**vfs-appointment-bot**) automates checking for appointments ## Installation - +For an alternative installation method, clone the source code from the project repository and install it manually. 1. **Clone the repository:** @@ -85,10 +107,24 @@ If you prefer a more traditional approach, you can clone the source code from th playwright install ``` -## Usage +## Configuration + +1. Download the [`config/config.ini`](https://raw.githubusercontent.com/ranjan-mohanty/vfs-appointment-bot/main/config/config.ini) template. -> **Pre-configuration:** -> Before running the script, ensure your update the vfs credentials and notification channel preferences in the config.ini file. See the [Notification Channels](#notification-channels) section for details on configuring email, Twilio, and Telegram notifications. + ```bash + curl -L https://raw.githubusercontent.com/ranjan-mohanty/vfs-appointment-bot/main/config/config.ini -o config.ini + ``` + +2. Update the vfs credentials and notification channel preferences. See the [Notification Channels](#notification-channels) section for details on configuring email, Twilio, and Telegram notifications. +3. Export the path of the config file to the environment variable `VFS_BOT_CONFIG_PATH` + + ```bash + export VFS_BOT_CONFIG_PATH=/config.ini + ``` + +**If you installed the script by cloning the repository (manual installation)**, you can directly edit the values in `config/config.ini`. + +## Usage 1. **Command-Line Argument:** diff --git a/vfs_appointment_bot/main.py b/vfs_appointment_bot/main.py index c3ca6d6..964c5c4 100644 --- a/vfs_appointment_bot/main.py +++ b/vfs_appointment_bot/main.py @@ -3,7 +3,7 @@ import sys from typing import Dict -from vfs_appointment_bot.utils.config_reader import get_config_value +from vfs_appointment_bot.utils.config_reader import get_config_value, initialize_config from vfs_appointment_bot.utils.timer import countdown from vfs_appointment_bot.vfs_bot.vfs_bot import LoginError from vfs_appointment_bot.vfs_bot.vfs_bot_factory import ( @@ -46,6 +46,7 @@ def main() -> None: Exception: For any other unexpected errors encountered during execution. """ initialize_logger() + initialize_config() parser = argparse.ArgumentParser( description="VFS Appointment Bot: Checks for appointments at VFS Global" diff --git a/vfs_appointment_bot/utils/config_reader.py b/vfs_appointment_bot/utils/config_reader.py index 3552394..6ce94cd 100644 --- a/vfs_appointment_bot/utils/config_reader.py +++ b/vfs_appointment_bot/utils/config_reader.py @@ -2,18 +2,16 @@ from configparser import ConfigParser from typing import Dict -_config = None +_config: ConfigParser = None -def get_config_parser(config_dir="config"): +def initialize_config(config_dir="config"): """ Reads all INI configuration files in a directory and caches the result. + Also reads user config from `VFS_BOT_CONFIG_PATH` env var (if set) Args: config_dir: The directory containing configuration files (default: "config"). - - Returns: - A ConfigParser object loaded with configuration data. """ global _config if not _config: @@ -22,7 +20,11 @@ def get_config_parser(config_dir="config"): if entry.is_file() and entry.name.endswith(".ini"): config_file_path = os.path.join(config_dir, entry.name) _config.read(config_file_path) - return _config + + # Read user defined config file + user_config_path = os.environ.get("VFS_BOT_CONFIG_PATH") + if user_config_path: + _config.read(user_config_path) def get_config_section(section: str, default: Dict = None) -> Dict: @@ -37,9 +39,8 @@ def get_config_section(section: str, default: Dict = None) -> Dict: A dictionary containing the configuration for the specified section, or the provided default dictionary if the section is not found. """ - config = get_config_parser() - if config.has_section(section): - return dict(config[section]) + if _config.has_section(section): + return dict(_config[section]) else: return default or {} @@ -57,8 +58,7 @@ def get_config_value(section: str, key: str, default: str = None) -> str: The value associated with the given key within the specified section, or the provided default value if the section or key does not exist. """ - config = get_config_parser() - if config.has_section(section) and config.has_option(section, key): - return config[section][key] + if _config.has_section(section) and _config.has_option(section, key): + return _config[section][key] else: return default