Complete documentation of all DisStore modules, classes, and functions.
Table of Contents:
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 instanceMethods:
auth_svc() → AuthSvc- Get authentication servicestoc_svc() → StocSvc- Get storage servicedisc_api() → DiscApi- Get Discord API wrappercfg() → Cfg- Get configuration
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/FalseRaises:
UtilizatorExista- Username already existsParolaIncorecta- Wrong passwordUtilizatorNegasit- User not foundErrorDiscord- Discord API error
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 detailsRaises:
FileNotFoundError- File doesn't exist locallyParolaIncorecta- Wrong encryption passwordErrorDiscord- Discord API errorIntegrityError- Checksum verification failed
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 successfulFeatures:
- Automatic rate limit handling
- Retry logic for transient failures
- Message content length validation (2000 char limit)
- TLS 1.2+ HTTPS for all requests
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 wrongSecurity 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)
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 corruptedFragment Structure:
class Fragment:
index: int # Fragment position (0, 1, 2, ...)
data: bytes # Fragment data
fisier_id: str # File ID
id: str # Unique fragment IDFile: 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"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 |
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 timestampclass 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 IDsclass Fragment:
index: int # Fragment order (0-based)
data: bytes # Fragment data
fisier_id: str # Parent file ID
id: str # Unique fragment IDFile: 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 fileFile: gui/main.py
Qt graphical interface.
from gui.main import FerPrincipal
gui = FerPrincipal(app=AppDis(cfg))
gui.show() # Display windowFeatures:
- Graphical file browser
- Drag-and-drop upload
- Progress indicators
- Multiple account support
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: