Skip to content

Commit feaf04d

Browse files
committed
migrated from config.py to dot env
1 parent 08e913c commit feaf04d

9 files changed

Lines changed: 257 additions & 107 deletions

File tree

‎.dockerignore‎

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,14 @@
11
.venv
22
node_modules
3+
**/node_modules
34
.git
45
__pycache__
56
*.pyc
67
*.pyo
78
*.pyd
89
.env
910
dist
10-
build
11+
build
12+
StreamX
13+
log.txt
14+
*.log

‎.gitignore‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
__pycache__/
22
.venv/
33
venv/
4-
config.py
54
*.session*
65
*.txt
76
.env
@@ -11,6 +10,7 @@ export/
1110
GenCovers/
1211
!requirements.txt
1312
!test.py
13+
.env
1414

1515

1616
logs

‎Dockerfile‎

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,10 @@ COPY --from=frontend-builder /app/StreamXWeb/dist ./dist
4545
COPY start.sh /app/start.sh
4646
RUN chmod +x /app/start.sh
4747

48+
ENV PYTHONUNBUFFERED=1 \
49+
PYTHONDONTWRITEBYTECODE=1 \
50+
PORT=8000
51+
4852
EXPOSE 8000
4953

5054
CMD ["bash", "/app/start.sh"]

‎config.py‎

Lines changed: 171 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,171 @@
1+
import json
2+
import os
3+
import re
4+
from pathlib import Path
5+
6+
_env_path = Path(__file__).resolve().parent / ".env"
7+
try:
8+
from dotenv import load_dotenv
9+
10+
if _env_path.exists():
11+
load_dotenv(dotenv_path=_env_path, override=False)
12+
else:
13+
load_dotenv(override=False)
14+
except ImportError:
15+
if _env_path.exists():
16+
with open(_env_path, "r", encoding="utf-8") as _f:
17+
for _line in _f:
18+
_line = _line.strip()
19+
if not _line or _line.startswith("#") or "=" not in _line:
20+
continue
21+
_k, _, _v = _line.partition("=")
22+
_k = _k.strip()
23+
_v = _v.strip()
24+
if (_v.startswith('"') and _v.endswith('"')) or (_v.startswith("'") and _v.endswith("'")):
25+
_v = _v[1:-1]
26+
if _k and _k not in os.environ:
27+
os.environ[_k] = _v
28+
29+
30+
def _get_str(key: str, default: str = "") -> str:
31+
val = os.getenv(key)
32+
if val is None:
33+
return default
34+
return str(val).strip()
35+
36+
37+
def _get_int(key: str, default: int = 0) -> int:
38+
val = os.getenv(key)
39+
if val is None or not str(val).strip():
40+
return default
41+
try:
42+
return int(str(val).strip())
43+
except (TypeError, ValueError):
44+
return default
45+
46+
47+
def _get_bool(key: str, default: bool = False) -> bool:
48+
val = os.getenv(key)
49+
if val is None or not str(val).strip():
50+
return default
51+
return str(val).strip().lower() in ("true", "1", "yes", "y", "on")
52+
53+
54+
def _get_list_int(key: str, default: list | None = None) -> list[int]:
55+
if default is None:
56+
default = []
57+
val = os.getenv(key)
58+
if val is None or not str(val).strip():
59+
return default
60+
s = str(val).strip()
61+
if s.startswith("["):
62+
try:
63+
parsed = json.loads(s)
64+
if isinstance(parsed, list):
65+
return [int(x) for x in parsed if str(x).strip().lstrip("-").isdigit()]
66+
except Exception:
67+
pass
68+
parts = re.split(r"[\s,]+", s)
69+
out = [int(p) for p in parts if p.strip().lstrip("-").isdigit()]
70+
return out if out else default
71+
72+
73+
def _get_id_or_list(key: str, default: int | list = 0) -> int | list:
74+
val = os.getenv(key)
75+
if val is None or not str(val).strip():
76+
return default
77+
s = str(val).strip()
78+
if s.startswith("["):
79+
try:
80+
parsed = json.loads(s)
81+
if isinstance(parsed, list):
82+
return [int(x) for x in parsed if str(x).strip().lstrip("-").isdigit()]
83+
except Exception:
84+
pass
85+
try:
86+
return int(s)
87+
except (TypeError, ValueError):
88+
return default
89+
90+
91+
def _get_filter_mode(key: str, default: int = 1) -> int | str:
92+
val = os.getenv(key)
93+
if val is None or not str(val).strip():
94+
return default
95+
s = str(val).strip()
96+
if s.isdigit():
97+
return int(s)
98+
return s
99+
100+
101+
def _get_chat_topic(key: str, default: int = 0) -> int | str:
102+
val = os.getenv(key)
103+
if val is None or not str(val).strip():
104+
return default
105+
s = str(val).strip()
106+
if s.lower() == "all":
107+
return "all"
108+
try:
109+
return int(s)
110+
except (TypeError, ValueError):
111+
return s
112+
113+
114+
# Core
115+
BOT_TOKEN = _get_str("BOT_TOKEN")
116+
API_ID = _get_int("API_ID", 0)
117+
API_HASH = _get_str("API_HASH")
118+
MONGO_URI = _get_str("MONGO_URI")
119+
DATABASE_NAME = _get_str("DATABASE_NAME", "StreamX")
120+
OWNER_ID = _get_id_or_list("OWNER_ID", 0)
121+
SUDO_USERS = _get_list_int("SUDO_USERS", [])
122+
SECRET_KEY = _get_str("SECRET_KEY")
123+
GITHUB_TOKEN = _get_str("GITHUB_TOKEN")
124+
ONLY_API = _get_bool("ONLY_API", False)
125+
126+
# Firebase
127+
FIREBASE_CREDENTIALS = _get_str("FIREBASE_CREDENTIALS")
128+
129+
# Debug
130+
DEBUG = _get_bool("DEBUG", False)
131+
132+
# Thumbnail Generation
133+
COLLEGE = _get_bool("COLLEGE", True)
134+
TEXT_COLOR = _get_str("TEXT_COLOR", "#FFFFFF")
135+
136+
# API & Web
137+
CORS_ORIGIN = _get_str("CORS_ORIGIN", "https://streamxweb-chi.vercel.app")
138+
CORS_ORIGINS = _get_str("CORS_ORIGINS", CORS_ORIGIN)
139+
COOKIE_SECURE = _get_bool("COOKIE_SECURE", True)
140+
COOKIE_SAMESITE = _get_str("COOKIE_SAMESITE", "none")
141+
142+
# Userbot
143+
SESSION_STRING = _get_str("SESSION_STRING")
144+
SOURCE_CHANNEL_IDS = _get_list_int("SOURCE_CHANNEL_IDS", [])
145+
CHAT_TOPIC = _get_chat_topic("CHAT_TOPIC", 0)
146+
147+
# Misc
148+
CHANNEL_ID = _get_int("CHANNEL_ID", 0)
149+
DUMP_CHANNEL_ID = _get_int("DUMP_CHANNEL_ID", 0)
150+
FILTER_MODE = _get_filter_mode("FILTER_MODE", 1)
151+
COLLABORATOR_ID = _get_list_int("COLLABORATOR_ID", [])
152+
COLLABORATOR_IDS = _get_list_int("COLLABORATOR_IDS", COLLABORATOR_ID)
153+
154+
# Lyrics API
155+
LRCLIB = _get_bool("LRCLIB", False)
156+
MUSIXMATCH = _get_bool("MUSIXMATCH", True)
157+
158+
# Spotify
159+
SPOTIFY_CLIENT_ID = _get_str("SPOTIFY_CLIENT_ID")
160+
SPOTIFY_CLIENT_SECRET = _get_str("SPOTIFY_CLIENT_SECRET")
161+
162+
# Multi-Clients
163+
MULTI_CLIENTS = _get_bool("MULTI_CLIENTS", False)
164+
MULTI_CLIENTS_1 = _get_str("MULTI_CLIENTS_1")
165+
MULTI_CLIENTS_2 = _get_str("MULTI_CLIENTS_2")
166+
MULTI_CLIENTS_3 = _get_str("MULTI_CLIENTS_3")
167+
MULTI_CLIENTS_4 = _get_str("MULTI_CLIENTS_4")
168+
169+
for _env_k, _env_v in os.environ.items():
170+
if _env_k.startswith("MULTI_CLIENTS_") and _env_k not in globals():
171+
globals()[_env_k] = _env_v

‎docker-compose.yml‎

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,18 @@ services:
55
context: .
66
dockerfile: Dockerfile
77

8-
command: ["bash", "/app/start.sh"]
8+
env_file:
9+
- .env
910

1011
ports:
11-
- "8000:8000"
12-
12+
- "${PORT:-8000}:${PORT:-8000}"
13+
14+
volumes:
15+
- ./.env:/app/.env:ro
16+
- ./cookies:/app/cookies
17+
- ./Stream.session:/app/Stream.session
18+
- ./stream_media:/app/stream_media
19+
20+
command: ["bash", "/app/start.sh"]
21+
1322
restart: on-failure

‎requirements.txt‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ kurigram
22
requests
33
aiohttp
44
tgcrypto
5-
dotenv
5+
python-dotenv
66
pymongo
77
apscheduler
88
uvicorn[standard]
@@ -16,4 +16,4 @@ python-multipart
1616
pillow
1717
psutil
1818
firebase-admin
19-
yt-dlp[default]
19+
yt-dlp[default]

‎sample_config.py‎

Lines changed: 0 additions & 48 deletions
This file was deleted.

‎sample_env‎

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
BOT_TOKEN=
2+
API_ID=00000000
3+
API_HASH=
4+
MONGO_URI=
5+
DATABASE_NAME=StreamX
6+
OWNER_ID=100000000
7+
SUDO_USERS=[100000000]
8+
SECRET_KEY=
9+
FIREBASE_CREDENTIALS=
10+
GITHUB_TOKEN=
11+
ONLY_API=False
12+
13+
# DEBUG
14+
DEBUG=False
15+
16+
# THUMBNAIL GENERATION
17+
COLLEGE=False
18+
TEXT_COLOR=#FFFFFF
19+
20+
# API
21+
CORS_ORIGIN=*
22+
COOKIE_SECURE=False
23+
COOKIE_SAMESITE=none
24+
25+
# USERBOT
26+
SESSION_STRING=
27+
SOURCE_CHANNEL_IDS=[]
28+
CHAT_TOPIC=0
29+
30+
# MISC
31+
# 0 = accept media only from CHANNEL_ID; 1 = accept media from any chat/group/topic; 2 or "hybrid" = allowlist of trusted sources.
32+
FILTER_MODE=0
33+
CHANNEL_ID=-1000000000
34+
DUMP_CHANNEL_ID=0
35+
COLLABORATOR_ID=[]
36+
37+
# LYRICS API
38+
LRCLIB=False
39+
MUSIXMATCH=True
40+
41+
# SPOTIFY
42+
SPOTIFY_CLIENT_ID=
43+
SPOTIFY_CLIENT_SECRET=
44+
45+
# MULTI-CLIENTS
46+
MULTI_CLIENTS=False
47+
MULTI_CLIENTS_1=
48+
MULTI_CLIENTS_2=
49+
MULTI_CLIENTS_3=
50+
MULTI_CLIENTS_4=
51+
52+
53+
54+
"""####### REQUIRED ########
55+
BOT_TOKEN
56+
API_ID
57+
API_HASH
58+
MONGO_URI
59+
OWNER_ID
60+
CHANNEL_ID
61+
SECRET_KEY
62+
############ END #########"""

0 commit comments

Comments
 (0)