initial commit
This commit is contained in:
commit
2e3553044c
7 changed files with 145 additions and 0 deletions
1
.env.example
Normal file
1
.env.example
Normal file
|
@ -0,0 +1 @@
|
||||||
|
SPACEAPI_TOKEN=your-secret-token-here
|
1
.gitignore
vendored
Normal file
1
.gitignore
vendored
Normal file
|
@ -0,0 +1 @@
|
||||||
|
.env
|
24
Dockerfile
Normal file
24
Dockerfile
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
# Use Python 3.11 slim image as base
|
||||||
|
FROM python:3.11-slim
|
||||||
|
|
||||||
|
# Set working directory
|
||||||
|
WORKDIR /app
|
||||||
|
|
||||||
|
# Copy requirements first to leverage Docker cache
|
||||||
|
COPY requirements.txt .
|
||||||
|
|
||||||
|
# Install dependencies
|
||||||
|
RUN pip install --no-cache-dir -r requirements.txt
|
||||||
|
|
||||||
|
# Copy the rest of the application
|
||||||
|
COPY . .
|
||||||
|
|
||||||
|
# Expose the port the app runs on
|
||||||
|
EXPOSE 5000
|
||||||
|
|
||||||
|
# Set environment variables
|
||||||
|
ENV FLASK_APP=app.py
|
||||||
|
ENV FLASK_ENV=production
|
||||||
|
|
||||||
|
# Command to run the application
|
||||||
|
CMD ["flask", "run", "--host=0.0.0.0"]
|
BIN
__pycache__/spaceapi.cpython-313.pyc
Normal file
BIN
__pycache__/spaceapi.cpython-313.pyc
Normal file
Binary file not shown.
77
app.py
Normal file
77
app.py
Normal file
|
@ -0,0 +1,77 @@
|
||||||
|
from flask import Flask, jsonify, request
|
||||||
|
from spaceapi import SpaceAPI, Location, Contact, State, LinkedSpace
|
||||||
|
import json
|
||||||
|
from dotenv import load_dotenv
|
||||||
|
import os
|
||||||
|
|
||||||
|
# Load environment variables from .env file
|
||||||
|
load_dotenv()
|
||||||
|
|
||||||
|
app = Flask(__name__)
|
||||||
|
|
||||||
|
# Global variable to store the current state
|
||||||
|
current_state = {}
|
||||||
|
|
||||||
|
def require_token(f):
|
||||||
|
def decorated(*args, **kwargs):
|
||||||
|
token = request.headers.get('X-SpaceAPI-Token')
|
||||||
|
if not token or token != os.getenv('SPACEAPI_TOKEN'):
|
||||||
|
return jsonify({"error": "Invalid or missing token"}), 401
|
||||||
|
return f(*args, **kwargs)
|
||||||
|
decorated.__name__ = f.__name__
|
||||||
|
return decorated
|
||||||
|
|
||||||
|
@app.route('/')
|
||||||
|
def hello_world():
|
||||||
|
space = SpaceAPI(
|
||||||
|
api_compatibility=["14", "15"],
|
||||||
|
space="Leitstelle511 - Chaos Computer Club Hannover",
|
||||||
|
logo="https://upload.wikimedia.org/wikipedia/commons/thumb/d/d1/Logo_CCC.svg/330px-Logo_CCC.svg.png",
|
||||||
|
url="http://hannover.ccc.de",
|
||||||
|
location=Location(
|
||||||
|
address="Klaus-Müller-Kilian-Weg 2, 30167 Hannover, Germany",
|
||||||
|
lat=52.3881,
|
||||||
|
lon=9.7181
|
||||||
|
),
|
||||||
|
contact=Contact(
|
||||||
|
email="kontakt@hannover.ccc.de",
|
||||||
|
irc="irc://hackint.eu/leitstelle511",
|
||||||
|
ml="511@hannover.ccc.de",
|
||||||
|
matrix="#leitstelle511-public:leitstelle511.net"
|
||||||
|
),
|
||||||
|
state=current_state,
|
||||||
|
projects=[
|
||||||
|
"https://hannover.ccc.de/projekte/schule/",
|
||||||
|
"https://hackover.de"
|
||||||
|
],
|
||||||
|
linked_spaces=[
|
||||||
|
LinkedSpace(
|
||||||
|
endpoint="https://leinelab.org/api/spaceapi.json",
|
||||||
|
website="https://leinelab.org"
|
||||||
|
)
|
||||||
|
]
|
||||||
|
)
|
||||||
|
return jsonify(space.__dict__)
|
||||||
|
|
||||||
|
@app.route('/state', methods=['POST'])
|
||||||
|
@require_token
|
||||||
|
def update_state():
|
||||||
|
global current_state
|
||||||
|
try:
|
||||||
|
data = request.get_json()
|
||||||
|
if not data or 'open' not in data:
|
||||||
|
return jsonify({"error": "Invalid state data. 'open' field is required"}), 400
|
||||||
|
|
||||||
|
# Create new state with provided open status
|
||||||
|
# lastchange will be automatically set to current timestamp
|
||||||
|
current_state = State(open=data['open'])
|
||||||
|
|
||||||
|
return jsonify({
|
||||||
|
"message": "State updated successfully",
|
||||||
|
"state": current_state.__dict__
|
||||||
|
})
|
||||||
|
except Exception as e:
|
||||||
|
return jsonify({"error": str(e)}), 400
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
app.run(host='0.0.0.0', port=5000, debug=True)
|
3
requirements.txt
Normal file
3
requirements.txt
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
flask==3.0.2
|
||||||
|
python-dotenv==1.0.1
|
||||||
|
spaceapi==0.1.0
|
39
spaceapi.py
Normal file
39
spaceapi.py
Normal file
|
@ -0,0 +1,39 @@
|
||||||
|
from dataclasses import dataclass, field
|
||||||
|
from typing import List, Optional
|
||||||
|
from datetime import datetime
|
||||||
|
import time
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class Location:
|
||||||
|
address: str
|
||||||
|
lat: float
|
||||||
|
lon: float
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class Contact:
|
||||||
|
email: str
|
||||||
|
irc: str
|
||||||
|
ml: str
|
||||||
|
matrix: str
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class State:
|
||||||
|
open: bool
|
||||||
|
lastchange: int = field(default_factory=lambda: int(time.time()))
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class LinkedSpace:
|
||||||
|
endpoint: str
|
||||||
|
website: str
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class SpaceAPI:
|
||||||
|
api_compatibility: List[str]
|
||||||
|
space: str
|
||||||
|
logo: str
|
||||||
|
url: str
|
||||||
|
location: Location
|
||||||
|
contact: Contact
|
||||||
|
state: State
|
||||||
|
projects: List[str]
|
||||||
|
linked_spaces: List[LinkedSpace]
|
Loading…
Add table
Add a link
Reference in a new issue