Move hardcoded secrets to .env, add .env.example
Castopod password, DB password, BunnyCDN keys, Postiz JWT/IDs, and monitoring token all moved to environment variables. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
48
.env.example
Normal file
48
.env.example
Normal file
@@ -0,0 +1,48 @@
|
|||||||
|
# API Keys
|
||||||
|
OPENROUTER_API_KEY=
|
||||||
|
ELEVENLABS_API_KEY=
|
||||||
|
INWORLD_API_KEY=
|
||||||
|
OPENAI_API_KEY=
|
||||||
|
|
||||||
|
# SignalWire (real callers)
|
||||||
|
SIGNALWIRE_PROJECT_ID=
|
||||||
|
SIGNALWIRE_SPACE=
|
||||||
|
SIGNALWIRE_TOKEN=
|
||||||
|
SIGNALWIRE_PHONE=
|
||||||
|
SIGNALWIRE_STREAM_URL=
|
||||||
|
|
||||||
|
# Social media
|
||||||
|
TWITTER_API_KEY=
|
||||||
|
TWITTER_API_SECRET=
|
||||||
|
TWITTER_ACCESS_TOKEN=
|
||||||
|
TWITTER_ACCESS_TOKEN_SECRET=
|
||||||
|
CLIENT_SECRET_ID=
|
||||||
|
CLIENT_SECRET=
|
||||||
|
POSTIZ_URL=
|
||||||
|
POSTIZ_API_KEY=
|
||||||
|
BSKY_APP_PASSWORD=
|
||||||
|
|
||||||
|
# Castopod
|
||||||
|
CASTOPOD_USERNAME=admin
|
||||||
|
CASTOPOD_PASSWORD=
|
||||||
|
CASTOPOD_DB_PASS=
|
||||||
|
|
||||||
|
# Postiz publishing
|
||||||
|
POSTIZ_JWT_SECRET=
|
||||||
|
POSTIZ_USER_ID=
|
||||||
|
POSTIZ_INTEGRATIONS={}
|
||||||
|
|
||||||
|
# BunnyCDN
|
||||||
|
BUNNY_STORAGE_KEY=
|
||||||
|
BUNNY_ACCOUNT_KEY=
|
||||||
|
|
||||||
|
# Monitoring
|
||||||
|
HEARTBEAT_URL=
|
||||||
|
|
||||||
|
# Google AI
|
||||||
|
GOOGLE_API_KEY=
|
||||||
|
|
||||||
|
# Email (IMAP)
|
||||||
|
SUBMISSIONS_IMAP_HOST=
|
||||||
|
SUBMISSIONS_IMAP_USER=
|
||||||
|
SUBMISSIONS_IMAP_PASS=
|
||||||
@@ -18,7 +18,7 @@
|
|||||||
## Castopod (Podcast Publishing)
|
## Castopod (Podcast Publishing)
|
||||||
- **URL**: https://podcast.macneilmediagroup.com
|
- **URL**: https://podcast.macneilmediagroup.com
|
||||||
- **Podcast handle**: `@LukeAtTheRoost`
|
- **Podcast handle**: `@LukeAtTheRoost`
|
||||||
- **API Auth**: Basic auth (admin/podcast2026api)
|
- **API Auth**: Basic auth (credentials in .env: CASTOPOD_USERNAME, CASTOPOD_PASSWORD)
|
||||||
- **Container**: `castopod-castopod-1`
|
- **Container**: `castopod-castopod-1`
|
||||||
- **Database**: `castopod-mariadb-1` (user: castopod, db: castopod)
|
- **Database**: `castopod-mariadb-1` (user: castopod, db: castopod)
|
||||||
|
|
||||||
|
|||||||
@@ -4003,9 +4003,9 @@ def _restore_signalwire_webhook():
|
|||||||
|
|
||||||
# BunnyCDN config for public on-air status
|
# BunnyCDN config for public on-air status
|
||||||
_BUNNY_STORAGE_ZONE = "lukeattheroost"
|
_BUNNY_STORAGE_ZONE = "lukeattheroost"
|
||||||
_BUNNY_STORAGE_KEY = "92749cd3-85df-4cff-938fe35eb994-30f8-4cf2"
|
_BUNNY_STORAGE_KEY = os.getenv("BUNNY_STORAGE_KEY", "")
|
||||||
_BUNNY_STORAGE_REGION = "la"
|
_BUNNY_STORAGE_REGION = "la"
|
||||||
_BUNNY_ACCOUNT_KEY = "2865f279-297b-431a-ad18-0ccf1f8e4fa8cf636cea-3222-415a-84ed-56ee195c0530"
|
_BUNNY_ACCOUNT_KEY = os.getenv("BUNNY_ACCOUNT_KEY", "")
|
||||||
|
|
||||||
|
|
||||||
def _update_on_air_cdn(on_air: bool):
|
def _update_on_air_cdn(on_air: bool):
|
||||||
|
|||||||
@@ -42,7 +42,7 @@ echo "podcast-stats: starting hourly loop"
|
|||||||
while true; do
|
while true; do
|
||||||
echo "$(date -u '+%Y-%m-%dT%H:%M:%SZ') Running stats update..."
|
echo "$(date -u '+%Y-%m-%dT%H:%M:%SZ') Running stats update..."
|
||||||
if python podcast_stats.py --json --upload 2>&1; then
|
if python podcast_stats.py --json --upload 2>&1; then
|
||||||
curl -s "https://monitoring.macneilmediagroup.com/api/push/yk9tjJVUGVXhu4zjol2EvpepIlBTfFoD?status=up&msg=OK" > /dev/null
|
[ -n "$HEARTBEAT_URL" ] && curl -s "${HEARTBEAT_URL}?status=up&msg=OK" > /dev/null
|
||||||
echo " ...done, heartbeat sent"
|
echo " ...done, heartbeat sent"
|
||||||
else
|
else
|
||||||
echo " ...failed, will retry next hour"
|
echo " ...failed, will retry next hour"
|
||||||
|
|||||||
@@ -22,6 +22,8 @@ import sys
|
|||||||
from datetime import datetime, timezone
|
from datetime import datetime, timezone
|
||||||
|
|
||||||
import requests
|
import requests
|
||||||
|
from dotenv import load_dotenv
|
||||||
|
load_dotenv(os.path.join(os.path.dirname(os.path.abspath(__file__)), ".env"))
|
||||||
|
|
||||||
YOUTUBE_PLAYLIST = "PLGq4uZyNV1yYH_rcitTTPVysPbC6-7pe-"
|
YOUTUBE_PLAYLIST = "PLGq4uZyNV1yYH_rcitTTPVysPbC6-7pe-"
|
||||||
APPLE_PODCAST_ID = "1875205848"
|
APPLE_PODCAST_ID = "1875205848"
|
||||||
@@ -33,9 +35,9 @@ DOCKER_BIN = "/share/CACHEDEV1_DATA/.qpkg/container-station/bin/docker"
|
|||||||
CASTOPOD_DB_CONTAINER = "castopod-mariadb-1"
|
CASTOPOD_DB_CONTAINER = "castopod-mariadb-1"
|
||||||
|
|
||||||
BUNNY_STORAGE_ZONE = "lukeattheroost"
|
BUNNY_STORAGE_ZONE = "lukeattheroost"
|
||||||
BUNNY_STORAGE_KEY = "92749cd3-85df-4cff-938fe35eb994-30f8-4cf2"
|
BUNNY_STORAGE_KEY = os.getenv("BUNNY_STORAGE_KEY", "")
|
||||||
BUNNY_STORAGE_REGION = "la"
|
BUNNY_STORAGE_REGION = "la"
|
||||||
BUNNY_ACCOUNT_KEY = "2865f279-297b-431a-ad18-0ccf1f8e4fa8cf636cea-3222-415a-84ed-56ee195c0530"
|
BUNNY_ACCOUNT_KEY = os.getenv("BUNNY_ACCOUNT_KEY", "")
|
||||||
|
|
||||||
|
|
||||||
def _find_ytdlp():
|
def _find_ytdlp():
|
||||||
@@ -243,13 +245,14 @@ def _run_db_query(sql):
|
|||||||
docker_bin = path
|
docker_bin = path
|
||||||
break
|
break
|
||||||
|
|
||||||
|
db_pass = os.getenv("CASTOPOD_DB_PASS", "")
|
||||||
if docker_bin:
|
if docker_bin:
|
||||||
cmd = [docker_bin, "exec", "-i", CASTOPOD_DB_CONTAINER,
|
cmd = [docker_bin, "exec", "-i", CASTOPOD_DB_CONTAINER,
|
||||||
"mysql", "-u", "castopod", "-pBYtbFfk3ndeVabb26xb0UyKU", "castopod", "-N"]
|
"mysql", "-u", "castopod", f"-p{db_pass}", "castopod", "-N"]
|
||||||
else:
|
else:
|
||||||
cmd = [
|
cmd = [
|
||||||
"ssh", "-p", NAS_SSH_PORT, NAS_SSH,
|
"ssh", "-p", NAS_SSH_PORT, NAS_SSH,
|
||||||
f"{DOCKER_BIN} exec -i {CASTOPOD_DB_CONTAINER} mysql -u castopod -pBYtbFfk3ndeVabb26xb0UyKU castopod -N"
|
f"{DOCKER_BIN} exec -i {CASTOPOD_DB_CONTAINER} mysql -u castopod -p{db_pass} castopod -N"
|
||||||
]
|
]
|
||||||
try:
|
try:
|
||||||
proc = subprocess.run(cmd, input=sql, capture_output=True, text=True, timeout=30)
|
proc = subprocess.run(cmd, input=sql, capture_output=True, text=True, timeout=30)
|
||||||
|
|||||||
@@ -55,8 +55,8 @@ load_dotenv(Path(__file__).parent / ".env")
|
|||||||
|
|
||||||
# Configuration
|
# Configuration
|
||||||
CASTOPOD_URL = "https://podcast.macneilmediagroup.com"
|
CASTOPOD_URL = "https://podcast.macneilmediagroup.com"
|
||||||
CASTOPOD_USERNAME = "admin"
|
CASTOPOD_USERNAME = os.getenv("CASTOPOD_USERNAME", "admin")
|
||||||
CASTOPOD_PASSWORD = "podcast2026api"
|
CASTOPOD_PASSWORD = os.getenv("CASTOPOD_PASSWORD")
|
||||||
PODCAST_ID = 1
|
PODCAST_ID = 1
|
||||||
PODCAST_HANDLE = "LukeAtTheRoost"
|
PODCAST_HANDLE = "LukeAtTheRoost"
|
||||||
OPENROUTER_API_KEY = os.getenv("OPENROUTER_API_KEY")
|
OPENROUTER_API_KEY = os.getenv("OPENROUTER_API_KEY")
|
||||||
@@ -74,25 +74,14 @@ YT_PODCAST_PLAYLIST = "PLGq4uZyNV1yYH_rcitTTPVysPbC6-7pe-"
|
|||||||
|
|
||||||
# Postiz (social media posting)
|
# Postiz (social media posting)
|
||||||
POSTIZ_URL = "https://social.lukeattheroost.com"
|
POSTIZ_URL = "https://social.lukeattheroost.com"
|
||||||
POSTIZ_JWT_SECRET = "9d499bab97b303506af6ae18b29a60e6b5a0b1049177f533232ad14dd9729814"
|
POSTIZ_JWT_SECRET = os.getenv("POSTIZ_JWT_SECRET")
|
||||||
POSTIZ_USER_ID = "00c14319-9eac-42c3-a467-68d3c1634fe1"
|
POSTIZ_USER_ID = os.getenv("POSTIZ_USER_ID")
|
||||||
POSTIZ_INTEGRATIONS = {
|
POSTIZ_INTEGRATIONS = json.loads(os.getenv("POSTIZ_INTEGRATIONS", "{}"))
|
||||||
"facebook": {"id": "cmll9hwqj0001mt6xnas2f17w"},
|
|
||||||
"instagram": {"id": "cmlljn8920001pk6qqzutqwik"},
|
|
||||||
"discord": {"id": "cmllkprk90001uc6v6fwd5y9p", "channel": "1471386314447519754"},
|
|
||||||
"bluesky": {"id": "cmlk29h780001p76qa7sstp5h"},
|
|
||||||
"mastodon": {"id": "cmlk2r3mf0001le6vx9ey0k5a"},
|
|
||||||
"nostr": {"id": "cmlll3y78000cuc6vh8dcpl2w"},
|
|
||||||
"linkedin": {"id": "cmluar6cn0004o46x5a1u07vc"},
|
|
||||||
"threads": {"id": "cmm13sxhq001mo46x24com5p7"},
|
|
||||||
# TikTok excluded — requires video, not image posts. Use upload_clips.py instead.
|
|
||||||
# "tiktok": {"id": "cmm2ggsno0001md7134cam9t9"},
|
|
||||||
}
|
|
||||||
|
|
||||||
# NAS Configuration for chapters upload
|
# NAS Configuration for chapters upload
|
||||||
# BunnyCDN Storage
|
# BunnyCDN Storage
|
||||||
BUNNY_STORAGE_ZONE = "lukeattheroost"
|
BUNNY_STORAGE_ZONE = "lukeattheroost"
|
||||||
BUNNY_STORAGE_KEY = "92749cd3-85df-4cff-938fe35eb994-30f8-4cf2"
|
BUNNY_STORAGE_KEY = os.getenv("BUNNY_STORAGE_KEY")
|
||||||
BUNNY_STORAGE_REGION = "la" # Los Angeles
|
BUNNY_STORAGE_REGION = "la" # Los Angeles
|
||||||
|
|
||||||
NAS_HOST = "mmgnas"
|
NAS_HOST = "mmgnas"
|
||||||
@@ -102,7 +91,7 @@ DOCKER_PATH = "/share/CACHEDEV1_DATA/.qpkg/container-station/bin/docker"
|
|||||||
CASTOPOD_CONTAINER = "castopod-castopod-1"
|
CASTOPOD_CONTAINER = "castopod-castopod-1"
|
||||||
MARIADB_CONTAINER = "castopod-mariadb-1"
|
MARIADB_CONTAINER = "castopod-mariadb-1"
|
||||||
DB_USER = "castopod"
|
DB_USER = "castopod"
|
||||||
DB_PASS = "BYtbFfk3ndeVabb26xb0UyKU"
|
DB_PASS = os.getenv("CASTOPOD_DB_PASS")
|
||||||
DB_NAME = "castopod"
|
DB_NAME = "castopod"
|
||||||
|
|
||||||
LOCK_FILE = Path(__file__).parent / ".publish.lock"
|
LOCK_FILE = Path(__file__).parent / ".publish.lock"
|
||||||
|
|||||||
Reference in New Issue
Block a user