init: initial commit
This commit is contained in:
commit
d4496a2eda
8 changed files with 120 additions and 0 deletions
2
.dockerignore
Normal file
2
.dockerignore
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
.env
|
||||||
|
__pycache__/
|
7
.env.example
Normal file
7
.env.example
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
EXPORTER_PORT=8000
|
||||||
|
SCRAPE_INTERVAL=30
|
||||||
|
|
||||||
|
# twitch
|
||||||
|
TWITCH_CLIENT_ID=
|
||||||
|
TWITCH_CLIENT_SECRET=
|
||||||
|
TWITCH_CHANNELS=ikiznear
|
2
.gitignore
vendored
Normal file
2
.gitignore
vendored
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
__pycache__/
|
||||||
|
.env
|
9
Dockerfile
Normal file
9
Dockerfile
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
FROM python:3.11-slim
|
||||||
|
|
||||||
|
WORKDIR /app
|
||||||
|
COPY . /app
|
||||||
|
|
||||||
|
RUN pip install -r requirements.txt
|
||||||
|
|
||||||
|
EXPOSE 8000
|
||||||
|
CMD ["python", "main.py"]
|
37
main.py
Normal file
37
main.py
Normal file
|
@ -0,0 +1,37 @@
|
||||||
|
import os
|
||||||
|
import importlib.util
|
||||||
|
import time
|
||||||
|
from prometheus_client import start_http_server
|
||||||
|
from dotenv import load_dotenv
|
||||||
|
|
||||||
|
load_dotenv()
|
||||||
|
|
||||||
|
def load_stat_modules(path='stats'):
|
||||||
|
modules = []
|
||||||
|
for filename in os.listdir(path):
|
||||||
|
if filename.endswith(".py") and filename != "__init__.py":
|
||||||
|
module_name = filename[:-3]
|
||||||
|
filepath = os.path.join(path, filename)
|
||||||
|
|
||||||
|
spec = importlib.util.spec_from_file_location(module_name, filepath)
|
||||||
|
module = importlib.util.module_from_spec(spec)
|
||||||
|
spec.loader.exec_module(module)
|
||||||
|
|
||||||
|
if hasattr(module, 'update'):
|
||||||
|
modules.append(module)
|
||||||
|
return modules
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
port = int(os.getenv("EXPORTER_PORT", "8000"))
|
||||||
|
print(f"Starting exporter on port {port}...")
|
||||||
|
start_http_server(port)
|
||||||
|
|
||||||
|
modules = load_stat_modules()
|
||||||
|
|
||||||
|
while True:
|
||||||
|
for mod in modules:
|
||||||
|
try:
|
||||||
|
mod.update()
|
||||||
|
except Exception as e:
|
||||||
|
print(f"Error in {mod.__name__}: {e}")
|
||||||
|
time.sleep(int(os.getenv("SCRAPE_INTERVAL", "30")))
|
3
requirements.txt
Normal file
3
requirements.txt
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
prometheus_client
|
||||||
|
requests
|
||||||
|
python-dotenv
|
0
stats/__init__.py
Normal file
0
stats/__init__.py
Normal file
60
stats/twitch_stats.py
Normal file
60
stats/twitch_stats.py
Normal file
|
@ -0,0 +1,60 @@
|
||||||
|
from prometheus_client import Gauge
|
||||||
|
import requests
|
||||||
|
import os
|
||||||
|
import time
|
||||||
|
|
||||||
|
# Load env vars
|
||||||
|
TWITCH_CLIENT_ID = os.getenv("TWITCH_CLIENT_ID")
|
||||||
|
TWITCH_CLIENT_SECRET = os.getenv("TWITCH_CLIENT_SECRET")
|
||||||
|
CHANNELS = os.getenv("TWITCH_CHANNELS", "").split(",")
|
||||||
|
|
||||||
|
# Metric definition
|
||||||
|
live_status = Gauge('twitch_stream_live', 'Is the stream live?', ['channel'])
|
||||||
|
|
||||||
|
_token_cache = {
|
||||||
|
"access_token": None,
|
||||||
|
"expires_at": 0
|
||||||
|
}
|
||||||
|
|
||||||
|
print("[twitch] Client ID:", TWITCH_CLIENT_ID)
|
||||||
|
print("[twitch] Client Secret:", TWITCH_CLIENT_SECRET)
|
||||||
|
print("[twitch] Channels:", CHANNELS)
|
||||||
|
|
||||||
|
def get_token():
|
||||||
|
if time.time() < _token_cache["expires_at"] - 60:
|
||||||
|
return _token_cache["access_token"]
|
||||||
|
|
||||||
|
response = requests.post("https://id.twitch.tv/oauth2/token", data={
|
||||||
|
"client_id": TWITCH_CLIENT_ID,
|
||||||
|
"client_secret": TWITCH_CLIENT_SECRET,
|
||||||
|
"grant_type": "client_credentials"
|
||||||
|
})
|
||||||
|
|
||||||
|
# Print the response for debugging
|
||||||
|
print(f"[twitch] Response: {response.json()}")
|
||||||
|
|
||||||
|
data = response.json()
|
||||||
|
|
||||||
|
# Check for errors in the response
|
||||||
|
if "access_token" not in data:
|
||||||
|
raise ValueError(f"Error getting token: {data}")
|
||||||
|
|
||||||
|
_token_cache["access_token"] = data["access_token"]
|
||||||
|
_token_cache["expires_at"] = time.time() + data["expires_in"]
|
||||||
|
return _token_cache["access_token"]
|
||||||
|
|
||||||
|
headers = {
|
||||||
|
'Client-ID': TWITCH_CLIENT_ID,
|
||||||
|
'Authorization': f'Bearer {get_token()}'
|
||||||
|
}
|
||||||
|
|
||||||
|
def update():
|
||||||
|
for channel in CHANNELS:
|
||||||
|
url = f'https://api.twitch.tv/helix/streams?user_login={channel}'
|
||||||
|
try:
|
||||||
|
response = requests.get(url, headers=headers)
|
||||||
|
data = response.json()
|
||||||
|
is_live = int(bool(data.get('data')))
|
||||||
|
live_status.labels(channel=channel).set(is_live)
|
||||||
|
except Exception as e:
|
||||||
|
print(f"[twitch] Error checking {channel}: {e}")
|
Loading…
Add table
Add a link
Reference in a new issue