Skip to content

Latest commit

 

History

History
461 lines (335 loc) · 10 KB

API_REFERENCE.md

File metadata and controls

461 lines (335 loc) · 10 KB

API Reference

Complete documentation of all DisStore modules, classes, and functions.

Table of Contents:


Core Services

AppDis - Application Factory

File: src/app.py

Factory class that creates and manages all service instances using dependency injection.

from src.app import AppDis
from src.cfg import Cfg

# Initialize
cfg = Cfg()
app = AppDis(cfg)

# Get services
auth_svc = app.auth_svc()      # AuthSvc instance
stoc_svc = app.stoc_svc()      # StocSvc instance
disc_api = app.disc_api()      # DiscApi instance
cript = app.cript()            # Cript instance

Methods:

  • auth_svc() → AuthSvc - Get authentication service
  • stoc_svc() → StocSvc - Get storage service
  • disc_api() → DiscApi - Get Discord API wrapper
  • cfg() → Cfg - Get configuration

AuthSvc - Authentication Service

File: src/auth.py

Manages user signup, login, and password verification.

from src.auth import AuthSvc

auth = AuthSvc(disc_api, cfg, cript)

# Sign up new user
auth.signup(username="john_doe", password="SecurePass123!")
# Returns: Utilizator object

# Login existing user
user = auth.login(username="john_doe", password="SecurePass123!")
# Returns: Utilizator object with user ID and metadata

# Verify password (login only)
auth.verify_password(username="john_doe", password="SecurePass123!")
# Returns: True if correct, raises ParolaIncorecta if wrong

# Check if user exists
exists = auth.user_exists(username="john_doe")
# Returns: True/False

Raises:

  • UtilizatorExista - Username already exists
  • ParolaIncorecta - Wrong password
  • UtilizatorNegasit - User not found
  • ErrorDiscord - Discord API error

StocSvc - Storage Service

File: src/stoc.py

Manages file upload, download, listing, and deletion.

from src.stoc import StocSvc

stoc = StocSvc(disc_api, cfg, cript, part)

# Upload file
file_id = stoc.upload_fisier(
    username="john_doe",
    cale_fisier="path/to/file.txt",
    parola_criptare="FilePassword123!"
)
# Returns: "file_id_abc123def456"

# List files for user
files = stoc.lista_fisiere(username="john_doe")
# Returns: [DSM(id, name, size, hash, created), ...]

# Download file
data = stoc.download_fisier(
    username="john_doe",
    file_id="file_id_abc123",
    parola_criptare="FilePassword123!"
)
# Returns: binary file data (bytes)

# Delete file remotely
stoc.delete_fisier(file_id="file_id_abc123")
# Returns: True if successful

# Get file metadata
metadata = stoc.get_file_metadata(file_id="file_id_abc123")
# Returns: DSM object with file details

Raises:

  • FileNotFoundError - File doesn't exist locally
  • ParolaIncorecta - Wrong encryption password
  • ErrorDiscord - Discord API error
  • IntegrityError - Checksum verification failed

Infrastructure Modules

DiscApi - Discord REST API Wrapper

File: src/disc.py

Low-level Discord API interaction wrapper.

from src.disc import DiscApi

api = DiscApi(cfg, http_client=requests.Session())

# Fetch channels in category
channels = api.fetch_canale_categoria(guild_id, category_id)
# Returns: [Channel(id, name, type), ...]

# Send message to channel
message_id = api.send_mesaj_canal(
    channel_id,
    content="DSM:file_id:encrypted_data"
)
# Returns: "message_id_123456"

# Fetch all messages from channel
messages = api.fetch_mesaje_canal(channel_id)
# Returns: [Message(id, content, created_at), ...]

# Delete message
api.delete_mesaj(message_id)
# Returns: True if successful

# Create channel
channel_id = api.create_channel(guild_id, name="new-channel")
# Returns: "channel_id_123456"

# Create category
category_id = api.create_category(guild_id, name="ds-username")
# Returns: "category_id_123456"

# Move channel to category
api.move_channel_to_category(channel_id, category_id)
# Returns: True if successful

Features:

  • Automatic rate limit handling
  • Retry logic for transient failures
  • Message content length validation (2000 char limit)
  • TLS 1.2+ HTTPS for all requests

Cript - Cryptography Module

File: src/cript.py

Encryption, decryption, and password hashing.

from src.cript import Cript

cript = Cript()

# Encrypt data with password
encrypted = cript.cript_aes_gcm(
    plaintext="Secret message",
    parola="EncryptionPassword123!"
)
# Returns: "base64_encoded_iv_ciphertext_tag"

# Decrypt data with password
plaintext = cript.decript_aes_gcm(
    criptat=encrypted,
    parola="EncryptionPassword123!"
)
# Returns: "Secret message"

# Hash password for storage
hash_digest = cript.hash_parola(parola="UserPassword123!")
# Returns: {"hash": "hex_string", "salt": "hex_string"}

# Verify password against hash
verified = cript.verify_parola(
    parola="UserPassword123!",
    digest_salvat={"hash": "...", "salt": "..."}
)
# Returns: True if matches, False if wrong

Security Parameters:

  • Algorithm: AES-256-GCM
  • Key Derivation: PBKDF2-SHA256
  • Iterations: 200,000
  • IV Size: 16 bytes (random per operation)
  • Salt Size: 16 bytes (random per user)

Part - File Fragmentation

File: src/part.py

Split and reassemble files into fragments.

from src.part import Part

part = Part(chunk_size=1500)

# Fragment encrypted data
fragments = part.fragmenteaza_fisier(
    data=encrypted_bytes,
    chunk_size=1500
)
# Returns: [Fragment(index, data, id), ...]

# Reassemble fragments
reassembled = part.reasambleaza_fisier(fragments=fragments)
# Returns: complete encrypted bytes

# Verify fragment integrity
verified = part.verify_integritate(fragments=fragments)
# Returns: True if all fragments intact, False if corrupted

Fragment Structure:

class Fragment:
    index: int              # Fragment position (0, 1, 2, ...)
    data: bytes             # Fragment data
    fisier_id: str          # File ID
    id: str                 # Unique fragment ID

Codor - Encoding/Decoding

File: src/codor.py

Convert between binary, hexadecimal, and Base64.

from src.codor import Codor

codor = Codor()

# Binary to hexadecimal
hex_str = codor.hex_encode(b"Hello")
# Returns: "48656c6c6f"

# Hexadecimal to binary
data = codor.hex_decode("48656c6c6f")
# Returns: b"Hello"

# Binary to Base64
b64_str = codor.base64_encode(b"Secret")
# Returns: "U2VjcmV0"

# Base64 to binary
data = codor.base64_decode("U2VjcmV0")
# Returns: b"Secret"

Cfg - Configuration Manager

File: src/cfg.py

Load and validate environment configuration.

from src.cfg import Cfg

cfg = Cfg()

# Access configuration values
print(cfg.token_discord)        # Discord bot token
print(cfg.guild_id)              # Guild/server ID
print(cfg.master_key)            # Master encryption key
print(cfg.index_channel)         # Index channel name
print(cfg.max_users)             # Max users (1-50)
print(cfg.chunk_size)            # Fragment size (100-1800)

# Configuration is loaded from:
# 1. Environment variables
# 2. .env file
# 3. Defaults (if not specified)

# Directories auto-created
print(cfg.temp_dir)     # .temp/
print(cfg.downloaded_dir)  # downloaded/
print(cfg.state_dir)    # .state/

Environment Variables:

Variable Type Default Required
DISCORD_TOKEN str - ✅
DISCORD_GUILD_ID str - ✅
DISSTORE_MASTER_KEY str - ✅
DISSTORE_INDEX_CHANNEL str disstore-index
DISSTORE_MAX_USERS int 50
DISSTORE_CHUNK_SIZE int 1500

Data Models

Utilizator - User Model

File: src/modele.py

class Utilizator:
    username: str           # Username (unique)
    id_categorie: str       # Discord category ID
    sare: str              # Password salt (hex)
    verificare: str        # Password hash (hex)
    data_crearii: str      # Creation timestamp

DSM - File Metadata Model

class DSM:
    id: str                # File ID
    nume: str              # File name
    dimensiune: int        # File size in bytes
    hash: str              # SHA-256 checksum (hex)
    data_crearii: str      # Upload timestamp
    fragmente_count: int   # Number of fragments
    mesaj_ids: list        # Discord message IDs

Fragment Model

class Fragment:
    index: int             # Fragment order (0-based)
    data: bytes            # Fragment data
    fisier_id: str         # Parent file ID
    id: str                # Unique fragment ID

CLI & GUI

CLI Main

File: cli/main.py

Terminal user interface orchestration.

from cli.main import CliDis

cli = CliDis(app=AppDis(cfg))

# Main menu loop
cli.main_menu()  # Interactive CLI

# Sub-workflows
cli.signup_flow()       # New account
cli.login_flow()        # Existing account
cli.upload_flow()       # Upload file
cli.download_flow()     # Download file
cli.list_flow()         # List files
cli.delete_flow()       # Delete file

GUI Main

File: gui/main.py

Qt graphical interface.

from gui.main import FerPrincipal

gui = FerPrincipal(app=AppDis(cfg))
gui.show()  # Display window

Features:

  • Graphical file browser
  • Drag-and-drop upload
  • Progress indicators
  • Multiple account support

Exceptions

File: Various modules

All custom exceptions inherit from Exception.

# Authentication errors
from src.auth import ParolaIncorecta, UtilizatorExista, UtilizatorNegasit

try:
    auth.login("user", "wrong_password")
except ParolaIncorecta:
    print("Wrong password!")

# Storage errors
from src.stoc import IntegrityError

try:
    stoc.download_fisier("user", "file_id", "password")
except IntegrityError:
    print("File checksum failed!")

# Discord errors
from src.disc import ErrorDiscord

try:
    api.send_mesaj_canal(channel_id, "message")
except ErrorDiscord as e:
    print(f"Discord error: {e}")

Next Steps: