From 5875a5ebd561c38302f06c38eef8648fc085087f Mon Sep 17 00:00:00 2001 From: Maximilian Giller Date: Mon, 11 Mar 2024 01:34:50 +0100 Subject: [PATCH] Initial FastApi, Peewee setup --- src/__init__.py | 0 src/activity.php | 58 --------------- src/config.php | 6 -- src/config.py | 1 + src/endpoints/__init__.py | 0 src/endpoints/activity_api.py | 0 src/endpoints/streak_api.py | 12 +++ src/http.php | 14 ---- src/index.php | 88 ---------------------- src/main.py | 21 ++++++ src/storage.php | 76 ------------------- src/storage/__init__.py | 3 + src/storage/activity.py | 15 ++++ src/storage/database.py | 12 +++ src/storage/streak.py | 17 +++++ src/streaks.php | 22 ------ src/templates.php | 133 ---------------------------------- 17 files changed, 81 insertions(+), 397 deletions(-) create mode 100644 src/__init__.py delete mode 100644 src/activity.php delete mode 100644 src/config.php create mode 100644 src/config.py create mode 100644 src/endpoints/__init__.py create mode 100644 src/endpoints/activity_api.py create mode 100644 src/endpoints/streak_api.py delete mode 100644 src/http.php delete mode 100755 src/index.php create mode 100644 src/main.py delete mode 100644 src/storage.php create mode 100644 src/storage/__init__.py create mode 100644 src/storage/activity.py create mode 100644 src/storage/database.py create mode 100644 src/storage/streak.py delete mode 100644 src/streaks.php delete mode 100644 src/templates.php diff --git a/src/__init__.py b/src/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/src/activity.php b/src/activity.php deleted file mode 100644 index d40bbbb..0000000 --- a/src/activity.php +++ /dev/null @@ -1,58 +0,0 @@ -startTime = time(); - $this->expectedDuration = 0; - $this->title = ""; - $this->description = ""; - $this->available = false; - $this->working = false; - $this->template = ""; - $this->streak = array(); - } - - public function initialLoad(): void - { - } - - public function getCurrentDuration(): int - { - return time() - $this->startTime; - } - - public function getRemainingDuration(): int - { - return $this->expectedDuration - $this->getCurrentDuration(); - } - - public function getPublicData(): array - { - return array( - "startTime" => $this->startTime, - "expectedDuration" => $this->expectedDuration, - "title" => $this->title, - "description" => $this->description, - "available" => $this->available, - "working" => $this->working, - "currentDuration" => $this->getCurrentDuration(), - "remainingDuration" => $this->getRemainingDuration(), - "streak" => $this->streak, - ); - } -} \ No newline at end of file diff --git a/src/config.php b/src/config.php deleted file mode 100644 index d0b5406..0000000 --- a/src/config.php +++ /dev/null @@ -1,6 +0,0 @@ - str: + return "Hellow" diff --git a/src/http.php b/src/http.php deleted file mode 100644 index e7dd73e..0000000 --- a/src/http.php +++ /dev/null @@ -1,14 +0,0 @@ -title = $_GET["title"]; - } - if (isset($_GET["description"])) { - $activity->description = $_GET["description"]; - } - if (isset($_GET["duration"])) { - $activity->expectedDuration = (int)$_GET["duration"]; - } - if (isset($_GET["available"])) { - $activity->available = filter_var($_GET["available"], FILTER_VALIDATE_BOOLEAN); - } - if (isset($_GET["working"])) { - $activity->working = filter_var($_GET["working"], FILTER_VALIDATE_BOOLEAN); - } - if (isset($_GET["template"])) { - $activity->template = $_GET["template"]; - } -} - -function handleTemplate(Activity $activity) -{ - // Load and find template - try { - $templates = loadTemplates(); - } catch (Exception $e) { - respondAndDie($e->getMessage()); - } - - $template = $templates->findValidTemplate($activity); - if ($template == null) { - // No applicable template found - return; - } - - // Apply template - $template->applyTo($activity); - - // Overwrite parameters if template was specified on activity - if ($activity->template != "") { - loadGivenParameters($activity); - } -} - -// If no secret key is provided, respond with the current activity -global $SECRET_KEY; -if (!isset($_GET["secret"]) || $_GET["secret"] != $SECRET_KEY) { - // Respond with the current activity - try { - $activity = loadActivity(); - } catch (Exception $e) { - respondAndDie($e->getMessage()); - } - handleTemplate($activity); - $activity->streak = getStreakEntries("sleep"); - respondWithJson($activity->getPublicData()); -} - -// Update activity -$activity = new Activity(); -loadGivenParameters($activity); -storeActivity($activity); - -// Handle sleep streak -$tz = 'Europe/Berlin'; -$timestamp = $activity->startTime; -$dt = new DateTime("now", new DateTimeZone($tz)); //first argument "must" be a string -$dt->setTimestamp($timestamp); //adjust the object to correct timestamp - -$startingHour = (int) $dt->format('H'); -if ($activity->template == "sleeping" && $startingHour > 18) { - markTodayAsSuccess("sleep"); -} - -respondAndDie("Activity updated"); \ No newline at end of file diff --git a/src/main.py b/src/main.py new file mode 100644 index 0000000..7a0a6b6 --- /dev/null +++ b/src/main.py @@ -0,0 +1,21 @@ +from fastapi import FastAPI + +from .config import DATABASE +from .storage import * +from .endpoints.streak_api import router as streak_router + +import os + + +# Setup database +def create_database(): + with database: + database.create_tables([Activity, ActivityRecord, Streak, StreakRecord]) + + +if not os.path.exists(DATABASE): + create_database() + +app = FastAPI() + +app.include_router(streak_router, prefix="/streak", tags=["streak"]) diff --git a/src/storage.php b/src/storage.php deleted file mode 100644 index 0f5eb94..0000000 --- a/src/storage.php +++ /dev/null @@ -1,76 +0,0 @@ -loadDefaultTemplates(); - storeTemplates($templates); - return $templates; - } - - return loadObject($TEMPLATES_FILE, Templates::class); -} - -function storeObject(object $object, string $file): void -{ - $file = fopen($file, "w"); - fwrite($file, json_encode($object, JSON_PRETTY_PRINT)); - fclose($file); -} - -/** - * @throws ReflectionException - * @throws JsonException - */ -function loadObject(string $file, string $class): object -{ - $json = file_get_contents($file); - $data = json_decode($json, true, 512, JSON_THROW_ON_ERROR); - return parseObject($data, $class); -} - -/** - * @throws ReflectionException - */ -function parseObject(array $data, string $class): object -{ - $reflection = new ReflectionClass($class); - $instance = $reflection->newInstanceWithoutConstructor(); - foreach ($data as $property => $value) { - $propertyReflection = $reflection->getProperty($property); - $propertyReflection->setAccessible(true); - $propertyReflection->setValue($instance, $value); - } - - try { - $instance->initialLoad(); - } catch (Exception $e) { - // Ignore - } - - return $instance; -} \ No newline at end of file diff --git a/src/storage/__init__.py b/src/storage/__init__.py new file mode 100644 index 0000000..23bd2f3 --- /dev/null +++ b/src/storage/__init__.py @@ -0,0 +1,3 @@ +from .activity import Activity, ActivityRecord +from .streak import Streak, StreakRecord +from .database import database diff --git a/src/storage/activity.py b/src/storage/activity.py new file mode 100644 index 0000000..87cb541 --- /dev/null +++ b/src/storage/activity.py @@ -0,0 +1,15 @@ +from .database import BaseModel +from peewee import BooleanField, TextField, DateTimeField, ForeignKeyField + + +class Activity(BaseModel): + name = TextField() + description = TextField() + is_available = BooleanField() + is_working = BooleanField() + + +class ActivityRecord(BaseModel): + started_at = DateTimeField() + + activity = ForeignKeyField(Activity, backref='records') diff --git a/src/storage/database.py b/src/storage/database.py new file mode 100644 index 0000000..527ffc9 --- /dev/null +++ b/src/storage/database.py @@ -0,0 +1,12 @@ +from peewee import Model, SqliteDatabase, UUIDField + +from ..config import DATABASE + +database = SqliteDatabase(DATABASE) + + +class BaseModel(Model): + id = UUIDField(primary_key=True) + + class Meta: + database = database diff --git a/src/storage/streak.py b/src/storage/streak.py new file mode 100644 index 0000000..e597cd9 --- /dev/null +++ b/src/storage/streak.py @@ -0,0 +1,17 @@ +from datetime import date + +from .database import BaseModel +from peewee import TextField, ForeignKeyField, FloatField, BooleanField, DateField + + +class Streak(BaseModel): + name = TextField() + description = TextField + + +class StreakRecord(BaseModel): + reference_date = DateField(default=date.today) + is_achieved = BooleanField() + value = FloatField() + + streak = ForeignKeyField(Streak, backref='records') diff --git a/src/streaks.php b/src/streaks.php deleted file mode 100644 index 76eb54e..0000000 --- a/src/streaks.php +++ /dev/null @@ -1,22 +0,0 @@ -templates as $templateId => $template) { - $this->templates[$templateId] = parseObject($template, Template::class); - } - } - - public function existsTemplate(string $templateId): bool - { - // Does key in array exist? - if (array_key_exists($templateId, $this->templates)) { - return true; - } - - return false; - } - - public function findValidTemplate(Activity $activity): ?Template - { - if ($activity->template != "") { - if ($this->existsTemplate($activity->template)) { - return $this->templates[$activity->template]; - } else { - return null; - } - } - - // Check for other validity conditions - $validTemplate = null; - foreach ($this->templates as $templateId => $template) { - if ($template->isValidFor($activity) && ($validTemplate == null || $template->priority > $validTemplate->priority)) { - $validTemplate = $template; - } - } - - return $validTemplate; - } - - public function loadDefaultTemplates(): void - { - $awakeTemplate = new Template(); - $awakeTemplate->title = "Awake"; - $awakeTemplate->description = ""; - $awakeTemplate->expectedDuration = 0; - $awakeTemplate->available = false; - $awakeTemplate->working = false; - $awakeTemplate->priority = 0; - $awakeTemplate->triggerOnlyOnEmptyTitle = true; - - $this->templates["awake"] = $awakeTemplate; - - $sleepingTemplate = new Template(); - $sleepingTemplate->title = "Sleeping"; - $sleepingTemplate->description = ""; - $sleepingTemplate->expectedDuration = 60 * 60 * 8; // 8 hours - $sleepingTemplate->available = false; - $sleepingTemplate->working = false; - $sleepingTemplate->priority = 10; - $sleepingTemplate->triggerOnlyOnEmptyTitle = true; - $sleepingTemplate->triggerAfterTimeout = true; - $sleepingTemplate->timeout = 60 * 60 * 4; // 4 hours - - $this->templates["sleeping"] = $sleepingTemplate; - } -} - -class Template -{ - public string $title; - public string $description; - public int $expectedDuration; - public bool $available; - public bool $working; - - // Meta template information - public int $priority; // Higher priority templates are applied first - - public bool $triggerOnlyOnEmptyTitle; // If true, the template will be only applied if the activity title is empty - - public bool $triggerAfterTimeout; // If true, the template will be applied after the timeout - public int $timeout; // Timeout for trigger in seconds - - public function __construct() - { - $this->title = ""; - $this->description = ""; - $this->expectedDuration = 0; - $this->available = false; - $this->working = false; - $this->priority = 0; - $this->triggerOnlyOnEmptyTitle = false; - $this->triggerAfterTimeout = false; - $this->timeout = 0; - } - - public function applyTo(Activity $activity): void - { - $activity->title = $this->title; - $activity->description = $this->description; - $activity->expectedDuration = $this->expectedDuration; - $activity->available = $this->available; - $activity->working = $this->working; - } - - public function isValidFor(Activity $activity): bool - { - // Is any trigger active? - if (!$this->triggerOnlyOnEmptyTitle && !$this->triggerAfterTimeout) { - return false; - } - - if ($this->triggerOnlyOnEmptyTitle && $activity->title != "") { - return false; - } - - if ($this->triggerAfterTimeout && $activity->getCurrentDuration() < $this->timeout) { - return false; - } - - return true; - } - - public function initialLoad(): void - { - } -}