浏览代码

feat: initial version

Sean Blackburn 1 年之前
当前提交
4cb29591df
共有 65 个文件被更改,包括 2726 次插入0 次删除
  1. 13 0
      .copier-answers.yml
  2. 74 0
      .forgejo/workflows/push.yaml
  3. 4 0
      .forgejo/workflows/release.yaml
  4. 65 0
      .gitignore
  5. 49 0
      .pre-commit-config.yaml
  6. 27 0
      .releaserc.yaml
  7. 373 0
      LICENCE
  8. 14 0
      README.md
  9. 56 0
      cspell.config.yaml
  10. 20 0
      makefile
  11. 1172 0
      out/openapi.json
  12. 0 0
      src/components/callbacks/.gitkeep
  13. 12 0
      src/components/enums/grading-type.yaml
  14. 17 0
      src/components/enums/teaching-type.yaml
  15. 18 0
      src/components/enums/weekday.yaml
  16. 6 0
      src/components/examples/lecturers.yaml
  17. 45 0
      src/components/examples/module-history.yaml
  18. 37 0
      src/components/examples/modules.yaml
  19. 15 0
      src/components/examples/semester-versions.yaml
  20. 26 0
      src/components/examples/{semester}/blockclasses.yaml
  21. 34 0
      src/components/examples/{semester}/changes.yaml
  22. 1 0
      src/components/examples/{semester}/config.yaml
  23. 30 0
      src/components/examples/{semester}/{version}/classes.yaml
  24. 3 0
      src/components/examples/{semester}/{version}/config.yaml
  25. 0 0
      src/components/headers/.gitkeep
  26. 0 0
      src/components/links/.gitkeep
  27. 7 0
      src/components/parameters/semester.yaml
  28. 7 0
      src/components/parameters/version.yaml
  29. 0 0
      src/components/pathItems/.gitkeep
  30. 0 0
      src/components/requestBodies/.gitkeep
  31. 4 0
      src/components/responses/changelog-html-200.yaml
  32. 9 0
      src/components/responses/lecturers-200.yaml
  33. 7 0
      src/components/responses/module-history-200.yaml
  34. 9 0
      src/components/responses/modules-200.yaml
  35. 9 0
      src/components/responses/semester-versions-200.yaml
  36. 9 0
      src/components/responses/{semester}/blockclasses-200.yaml
  37. 9 0
      src/components/responses/{semester}/changes-200.yaml
  38. 7 0
      src/components/responses/{semester}/semester-config-200.yaml
  39. 9 0
      src/components/responses/{semester}/{version}/classes-200.yaml
  40. 4 0
      src/components/responses/{semester}/{version}/klassen-pdf-200.yaml
  41. 7 0
      src/components/responses/{semester}/{version}/semester-version-config-200.yaml
  42. 16 0
      src/components/schemas/lecturer.yaml
  43. 9 0
      src/components/schemas/module-dependency.yaml
  44. 62 0
      src/components/schemas/module-history.yaml
  45. 75 0
      src/components/schemas/module.yaml
  46. 16 0
      src/components/schemas/semester-version.yaml
  47. 63 0
      src/components/schemas/{semester}/blockclass.yaml
  48. 12 0
      src/components/schemas/{semester}/change.yaml
  49. 10 0
      src/components/schemas/{semester}/semester-config.yaml
  50. 62 0
      src/components/schemas/{semester}/{version}/class.yaml
  51. 21 0
      src/components/schemas/{semester}/{version}/semester-version-config.yaml
  52. 0 0
      src/components/securitySchemes/.gitkeep
  53. 39 0
      src/openapi.yaml
  54. 10 0
      src/paths/changelog-html.yaml
  55. 10 0
      src/paths/lecturers.yaml
  56. 10 0
      src/paths/module-history.yaml
  57. 10 0
      src/paths/modules.yaml
  58. 10 0
      src/paths/semester-versions.yaml
  59. 12 0
      src/paths/{semester}/blockclasses.yaml
  60. 12 0
      src/paths/{semester}/changes.yaml
  61. 12 0
      src/paths/{semester}/config.yaml
  62. 13 0
      src/paths/{semester}/{version}/classes.yaml
  63. 13 0
      src/paths/{semester}/{version}/config.yaml
  64. 13 0
      src/paths/{semester}/{version}/klassen-pdf.yaml
  65. 8 0
      src/redocly.yaml

+ 13 - 0
.copier-answers.yml

@@ -0,0 +1,13 @@
+# Changes here will be overwritten by Copier; NEVER EDIT MANUALLY
+_commit: 1.1.0
+_src_path: ssh://git@git.snas.black-burn.ch:43057/templates/copier-openapi.git
+author: Sean Blackburn
+ci: actions
+summary: OpenAPI documentation of the modulplaner API
+email: sean@black-burn.ch
+has_dockerfile: false
+license: mpl2_0
+project_name: Modulplaner OpenAPI
+repo_location: forgejo
+use_renovate: false
+use_semantic_release: true

+ 74 - 0
.forgejo/workflows/push.yaml

@@ -0,0 +1,74 @@
+name: Push action
+on: [push]
+
+jobs:
+  pre-commit:
+    runs-on: ubuntu-latest
+    steps:
+      - uses: actions/checkout@v4
+
+      - name: Add pipx to PATH
+        run: echo "/root/.local/bin" >> $GITHUB_PATH
+
+      - name: Setup cache
+        uses: actions/cache@v3
+        with:
+          path: |
+            /opt/hostedtoolcache
+            ~/.local/pipx
+            /root/.local/bin
+          key: ${{ runner.os }}-toolcache
+
+      - name: Install pre-commit
+        run: pipx install pre-commit --force
+
+      - uses: actions/cache@v3
+        with:
+          path: ~/.cache/pre-commit
+          key: pre-commit-3|${{ env.pythonLocation }}|${{ steps.get-hash-pre-commit.outputs.hash }}
+
+      - run: pre-commit run --all-files --show-diff-on-failure --color=always ${{ inputs.extra_args }}
+        shell: bash
+
+  semantic-release:
+    runs-on: ubuntu-latest
+    needs:
+      - pre-commit
+    if: github.ref == 'refs/heads/main'
+    steps:
+      - name: Checkout
+        uses: actions/checkout@v4
+
+      - name: Add pipx to PATH
+        run: echo "/root/.local/bin" >> $GITHUB_PATH
+
+      - uses: actions/setup-node@v4
+        with:
+          node-version: "22.9.0"
+
+      - name: Setup cache
+        uses: actions/cache@v3
+        with:
+          path: |
+            ~/.local/pipx
+            /root/.local/bin
+          key: ${{ runner.os }}-semantic-release-toolcache
+
+      - name: Install poetry
+        run: pipx install poetry --force
+
+      - name: Semantic Release
+        id: release
+        uses: https://github.com/cycjimmy/semantic-release-action@v4
+        with:
+          extra_plugins: |
+            @saithodev/semantic-release-gitea
+            @bjoluc/semantic-release-config-poetry
+            @semantic-release/git
+            @semantic-release/changelog
+            @semantic-release/exec
+            @google/semantic-release-replace-plugin
+            prettier
+        env:
+          GITEA_URL: ${{ github.server_url }}
+          GITEA_TOKEN: ${{ secrets.SEMANTIC_RELEASE_TOKEN }}

+ 4 - 0
.forgejo/workflows/release.yaml

@@ -0,0 +1,4 @@
+name: Release action
+on: [release]
+
+jobs:

+ 65 - 0
.gitignore

@@ -0,0 +1,65 @@
+# General
+.DS_Store
+.AppleDouble
+.LSOverride
+
+# Icon must end with two \r
+Icon
+
+# Thumbnails
+._*
+
+# Files that might appear in the root of a volume
+.DocumentRevisions-V100
+.fseventsd
+.Spotlight-V100
+.TemporaryItems
+.Trashes
+.VolumeIcon.icns
+.com.apple.timemachine.donotpresent
+
+# Directories potentially created on remote AFP share
+.AppleDB
+.AppleDesktop
+Network Trash Folder
+Temporary Items
+.apdisk
+
+*~
+
+# temporary files which can be created if a process still has a handle open of a deleted file
+.fuse_hidden*
+
+# KDE directory preferences
+.directory
+
+# Linux trash folder which might appear on any partition or disk
+.Trash-*
+
+# .nfs files are created when an open file is removed but is still being accessed
+.nfs*
+
+# Windows thumbnail cache files
+Thumbs.db
+Thumbs.db:encryptable
+ehthumbs.db
+ehthumbs_vista.db
+
+# Dump file
+*.stackdump
+
+# Folder config file
+[Dd]esktop.ini
+
+# Recycle Bin used on file shares
+$RECYCLE.BIN/
+
+# Windows Installer files
+*.cab
+*.msi
+*.msix
+*.msm
+*.msp
+
+# Windows shortcuts
+*.lnk

+ 49 - 0
.pre-commit-config.yaml

@@ -0,0 +1,49 @@
+exclude: ^(data/.*|.vscode/.*|node_modules/.*|)$
+
+repos:
+  - repo: https://github.com/commitizen-tools/commitizen
+    # Please run `pre-commit install --hook-type commit-msg` to check commit messages
+    rev: v3.29.1
+    hooks:
+      - id: commitizen
+
+  - repo: https://github.com/pre-commit/pre-commit-hooks
+    rev: v5.0.0
+    hooks:
+      - id: check-yaml
+      - id: check-json
+      - id: check-toml
+      - id: end-of-file-fixer
+      - id: trailing-whitespace
+      - id: detect-private-key
+      - id: check-case-conflict
+      - id: check-ast
+      - id: check-added-large-files
+        args: ["--maxkb=1000"]
+      - id: check-merge-conflict
+        args: [--assume-in-merge]
+
+  # Integrate filename spell checking https://github.com/streetsidesoftware/cspell/issues/3063
+  # currently using `make cspell-filenames` as a workaround.
+  - repo: https://github.com/streetsidesoftware/cspell-cli.git
+    rev: v8.13.3
+    hooks:
+      - id: cspell
+        name: cspell
+        additional_dependencies:
+          - "@cspell/dict-de-ch"
+          - "@cspell/dict-en-gb"
+        args:
+          - "lint"
+          - "--show-suggestions"
+          - "--no-must-find-files"
+          - "--locale"
+          - "en-GB,de-CH"
+
+
+  - repo: local
+    hooks:
+      - id: redocly-lint
+        name: redocly-lint
+        language: system
+        entry: make lint

+ 27 - 0
.releaserc.yaml

@@ -0,0 +1,27 @@
+plugins:
+  - "@semantic-release/commit-analyzer"
+  - "@semantic-release/release-notes-generator"
+  - "@bjoluc/semantic-release-config-poetry"
+  - "@semantic-release/changelog"
+  - - "@semantic-release/exec"
+    - prepareCmd: "npx prettier --write CHANGELOG.md; "
+
+  - - "@semantic-release/git"
+    - assets:
+      - "CHANGELOG.md"
+      message: "chore(release): ${nextRelease.version}\n\n${nextRelease.notes}"
+
+
+tagFormat: "${version}"
+branches:
+  - "+([0-9])?(.{+([0-9]),x}).x"
+  - "master"
+  - "main"
+  - "next"
+  - "next-major"
+
+  - "name": "beta"
+    "prerelease": true
+
+  - "name": "alpha"
+    "prerelease": true

+ 373 - 0
LICENCE

@@ -0,0 +1,373 @@
+Mozilla Public License Version 2.0
+==================================
+
+1. Definitions
+--------------
+
+1.1. "Contributor"
+    means each individual or legal entity that creates, contributes to
+    the creation of, or owns Covered Software.
+
+1.2. "Contributor Version"
+    means the combination of the Contributions of others (if any) used
+    by a Contributor and that particular Contributor's Contribution.
+
+1.3. "Contribution"
+    means Covered Software of a particular Contributor.
+
+1.4. "Covered Software"
+    means Source Code Form to which the initial Contributor has attached
+    the notice in Exhibit A, the Executable Form of such Source Code
+    Form, and Modifications of such Source Code Form, in each case
+    including portions thereof.
+
+1.5. "Incompatible With Secondary Licenses"
+    means
+
+    (a) that the initial Contributor has attached the notice described
+        in Exhibit B to the Covered Software; or
+
+    (b) that the Covered Software was made available under the terms of
+        version 1.1 or earlier of the License, but not also under the
+        terms of a Secondary License.
+
+1.6. "Executable Form"
+    means any form of the work other than Source Code Form.
+
+1.7. "Larger Work"
+    means a work that combines Covered Software with other material, in
+    a separate file or files, that is not Covered Software.
+
+1.8. "License"
+    means this document.
+
+1.9. "Licensable"
+    means having the right to grant, to the maximum extent possible,
+    whether at the time of the initial grant or subsequently, any and
+    all of the rights conveyed by this License.
+
+1.10. "Modifications"
+    means any of the following:
+
+    (a) any file in Source Code Form that results from an addition to,
+        deletion from, or modification of the contents of Covered
+        Software; or
+
+    (b) any new file in Source Code Form that contains any Covered
+        Software.
+
+1.11. "Patent Claims" of a Contributor
+    means any patent claim(s), including without limitation, method,
+    process, and apparatus claims, in any patent Licensable by such
+    Contributor that would be infringed, but for the grant of the
+    License, by the making, using, selling, offering for sale, having
+    made, import, or transfer of either its Contributions or its
+    Contributor Version.
+
+1.12. "Secondary License"
+    means either the GNU General Public License, Version 2.0, the GNU
+    Lesser General Public License, Version 2.1, the GNU Affero General
+    Public License, Version 3.0, or any later versions of those
+    licenses.
+
+1.13. "Source Code Form"
+    means the form of the work preferred for making modifications.
+
+1.14. "You" (or "Your")
+    means an individual or a legal entity exercising rights under this
+    License. For legal entities, "You" includes any entity that
+    controls, is controlled by, or is under common control with You. For
+    purposes of this definition, "control" means (a) the power, direct
+    or indirect, to cause the direction or management of such entity,
+    whether by contract or otherwise, or (b) ownership of more than
+    fifty percent (50%) of the outstanding shares or beneficial
+    ownership of such entity.
+
+2. License Grants and Conditions
+--------------------------------
+
+2.1. Grants
+
+Each Contributor hereby grants You a world-wide, royalty-free,
+non-exclusive license:
+
+(a) under intellectual property rights (other than patent or trademark)
+    Licensable by such Contributor to use, reproduce, make available,
+    modify, display, perform, distribute, and otherwise exploit its
+    Contributions, either on an unmodified basis, with Modifications, or
+    as part of a Larger Work; and
+
+(b) under Patent Claims of such Contributor to make, use, sell, offer
+    for sale, have made, import, and otherwise transfer either its
+    Contributions or its Contributor Version.
+
+2.2. Effective Date
+
+The licenses granted in Section 2.1 with respect to any Contribution
+become effective for each Contribution on the date the Contributor first
+distributes such Contribution.
+
+2.3. Limitations on Grant Scope
+
+The licenses granted in this Section 2 are the only rights granted under
+this License. No additional rights or licenses will be implied from the
+distribution or licensing of Covered Software under this License.
+Notwithstanding Section 2.1(b) above, no patent license is granted by a
+Contributor:
+
+(a) for any code that a Contributor has removed from Covered Software;
+    or
+
+(b) for infringements caused by: (i) Your and any other third party's
+    modifications of Covered Software, or (ii) the combination of its
+    Contributions with other software (except as part of its Contributor
+    Version); or
+
+(c) under Patent Claims infringed by Covered Software in the absence of
+    its Contributions.
+
+This License does not grant any rights in the trademarks, service marks,
+or logos of any Contributor (except as may be necessary to comply with
+the notice requirements in Section 3.4).
+
+2.4. Subsequent Licenses
+
+No Contributor makes additional grants as a result of Your choice to
+distribute the Covered Software under a subsequent version of this
+License (see Section 10.2) or under the terms of a Secondary License (if
+permitted under the terms of Section 3.3).
+
+2.5. Representation
+
+Each Contributor represents that the Contributor believes its
+Contributions are its original creation(s) or it has sufficient rights
+to grant the rights to its Contributions conveyed by this License.
+
+2.6. Fair Use
+
+This License is not intended to limit any rights You have under
+applicable copyright doctrines of fair use, fair dealing, or other
+equivalents.
+
+2.7. Conditions
+
+Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted
+in Section 2.1.
+
+3. Responsibilities
+-------------------
+
+3.1. Distribution of Source Form
+
+All distribution of Covered Software in Source Code Form, including any
+Modifications that You create or to which You contribute, must be under
+the terms of this License. You must inform recipients that the Source
+Code Form of the Covered Software is governed by the terms of this
+License, and how they can obtain a copy of this License. You may not
+attempt to alter or restrict the recipients' rights in the Source Code
+Form.
+
+3.2. Distribution of Executable Form
+
+If You distribute Covered Software in Executable Form then:
+
+(a) such Covered Software must also be made available in Source Code
+    Form, as described in Section 3.1, and You must inform recipients of
+    the Executable Form how they can obtain a copy of such Source Code
+    Form by reasonable means in a timely manner, at a charge no more
+    than the cost of distribution to the recipient; and
+
+(b) You may distribute such Executable Form under the terms of this
+    License, or sublicense it under different terms, provided that the
+    license for the Executable Form does not attempt to limit or alter
+    the recipients' rights in the Source Code Form under this License.
+
+3.3. Distribution of a Larger Work
+
+You may create and distribute a Larger Work under terms of Your choice,
+provided that You also comply with the requirements of this License for
+the Covered Software. If the Larger Work is a combination of Covered
+Software with a work governed by one or more Secondary Licenses, and the
+Covered Software is not Incompatible With Secondary Licenses, this
+License permits You to additionally distribute such Covered Software
+under the terms of such Secondary License(s), so that the recipient of
+the Larger Work may, at their option, further distribute the Covered
+Software under the terms of either this License or such Secondary
+License(s).
+
+3.4. Notices
+
+You may not remove or alter the substance of any license notices
+(including copyright notices, patent notices, disclaimers of warranty,
+or limitations of liability) contained within the Source Code Form of
+the Covered Software, except that You may alter any license notices to
+the extent required to remedy known factual inaccuracies.
+
+3.5. Application of Additional Terms
+
+You may choose to offer, and to charge a fee for, warranty, support,
+indemnity or liability obligations to one or more recipients of Covered
+Software. However, You may do so only on Your own behalf, and not on
+behalf of any Contributor. You must make it absolutely clear that any
+such warranty, support, indemnity, or liability obligation is offered by
+You alone, and You hereby agree to indemnify every Contributor for any
+liability incurred by such Contributor as a result of warranty, support,
+indemnity or liability terms You offer. You may include additional
+disclaimers of warranty and limitations of liability specific to any
+jurisdiction.
+
+4. Inability to Comply Due to Statute or Regulation
+---------------------------------------------------
+
+If it is impossible for You to comply with any of the terms of this
+License with respect to some or all of the Covered Software due to
+statute, judicial order, or regulation then You must: (a) comply with
+the terms of this License to the maximum extent possible; and (b)
+describe the limitations and the code they affect. Such description must
+be placed in a text file included with all distributions of the Covered
+Software under this License. Except to the extent prohibited by statute
+or regulation, such description must be sufficiently detailed for a
+recipient of ordinary skill to be able to understand it.
+
+5. Termination
+--------------
+
+5.1. The rights granted under this License will terminate automatically
+if You fail to comply with any of its terms. However, if You become
+compliant, then the rights granted under this License from a particular
+Contributor are reinstated (a) provisionally, unless and until such
+Contributor explicitly and finally terminates Your grants, and (b) on an
+ongoing basis, if such Contributor fails to notify You of the
+non-compliance by some reasonable means prior to 60 days after You have
+come back into compliance. Moreover, Your grants from a particular
+Contributor are reinstated on an ongoing basis if such Contributor
+notifies You of the non-compliance by some reasonable means, this is the
+first time You have received notice of non-compliance with this License
+from such Contributor, and You become compliant prior to 30 days after
+Your receipt of the notice.
+
+5.2. If You initiate litigation against any entity by asserting a patent
+infringement claim (excluding declaratory judgment actions,
+counter-claims, and cross-claims) alleging that a Contributor Version
+directly or indirectly infringes any patent, then the rights granted to
+You by any and all Contributors for the Covered Software under Section
+2.1 of this License shall terminate.
+
+5.3. In the event of termination under Sections 5.1 or 5.2 above, all
+end user license agreements (excluding distributors and resellers) which
+have been validly granted by You or Your distributors under this License
+prior to termination shall survive termination.
+
+************************************************************************
+*                                                                      *
+*  6. Disclaimer of Warranty                                           *
+*  -------------------------                                           *
+*                                                                      *
+*  Covered Software is provided under this License on an "as is"       *
+*  basis, without warranty of any kind, either expressed, implied, or  *
+*  statutory, including, without limitation, warranties that the       *
+*  Covered Software is free of defects, merchantable, fit for a        *
+*  particular purpose or non-infringing. The entire risk as to the     *
+*  quality and performance of the Covered Software is with You.        *
+*  Should any Covered Software prove defective in any respect, You     *
+*  (not any Contributor) assume the cost of any necessary servicing,   *
+*  repair, or correction. This disclaimer of warranty constitutes an   *
+*  essential part of this License. No use of any Covered Software is   *
+*  authorized under this License except under this disclaimer.         *
+*                                                                      *
+************************************************************************
+
+************************************************************************
+*                                                                      *
+*  7. Limitation of Liability                                          *
+*  --------------------------                                          *
+*                                                                      *
+*  Under no circumstances and under no legal theory, whether tort      *
+*  (including negligence), contract, or otherwise, shall any           *
+*  Contributor, or anyone who distributes Covered Software as          *
+*  permitted above, be liable to You for any direct, indirect,         *
+*  special, incidental, or consequential damages of any character      *
+*  including, without limitation, damages for lost profits, loss of    *
+*  goodwill, work stoppage, computer failure or malfunction, or any    *
+*  and all other commercial damages or losses, even if such party      *
+*  shall have been informed of the possibility of such damages. This   *
+*  limitation of liability shall not apply to liability for death or   *
+*  personal injury resulting from such party's negligence to the       *
+*  extent applicable law prohibits such limitation. Some               *
+*  jurisdictions do not allow the exclusion or limitation of           *
+*  incidental or consequential damages, so this exclusion and          *
+*  limitation may not apply to You.                                    *
+*                                                                      *
+************************************************************************
+
+8. Litigation
+-------------
+
+Any litigation relating to this License may be brought only in the
+courts of a jurisdiction where the defendant maintains its principal
+place of business and such litigation shall be governed by laws of that
+jurisdiction, without reference to its conflict-of-law provisions.
+Nothing in this Section shall prevent a party's ability to bring
+cross-claims or counter-claims.
+
+9. Miscellaneous
+----------------
+
+This License represents the complete agreement concerning the subject
+matter hereof. If any provision of this License is held to be
+unenforceable, such provision shall be reformed only to the extent
+necessary to make it enforceable. Any law or regulation which provides
+that the language of a contract shall be construed against the drafter
+shall not be used to construe this License against a Contributor.
+
+10. Versions of the License
+---------------------------
+
+10.1. New Versions
+
+Mozilla Foundation is the license steward. Except as provided in Section
+10.3, no one other than the license steward has the right to modify or
+publish new versions of this License. Each version will be given a
+distinguishing version number.
+
+10.2. Effect of New Versions
+
+You may distribute the Covered Software under the terms of the version
+of the License under which You originally received the Covered Software,
+or under the terms of any subsequent version published by the license
+steward.
+
+10.3. Modified Versions
+
+If you create software not governed by this License, and you want to
+create a new license for such software, you may create and use a
+modified version of this License if you rename the license and remove
+any references to the name of the license steward (except to note that
+such modified license differs from this License).
+
+10.4. Distributing Source Code Form that is Incompatible With Secondary
+Licenses
+
+If You choose to distribute Source Code Form that is Incompatible With
+Secondary Licenses under the terms of this version of the License, the
+notice described in Exhibit B of this License must be attached.
+
+Exhibit A - Source Code Form License Notice
+-------------------------------------------
+
+  This Source Code Form is subject to the terms of the Mozilla Public
+  License, v. 2.0. If a copy of the MPL was not distributed with this
+  file, You can obtain one at https://mozilla.org/MPL/2.0/.
+
+If it is not possible or desirable to put the notice in a particular
+file, then You may include the notice in a location (such as a LICENSE
+file in a relevant directory) where a recipient would be likely to look
+for such a notice.
+
+You may add additional accurate notices of copyright ownership.
+
+Exhibit B - "Incompatible With Secondary Licenses" Notice
+---------------------------------------------------------
+
+  This Source Code Form is "Incompatible With Secondary Licenses", as
+  defined by the Mozilla Public License, v. 2.0.

+ 14 - 0
README.md

@@ -0,0 +1,14 @@
+# Modulplaner OpenAPI
+
+OpenAPI documentation of the modulplaner API
+
+
+## Improvements
+
+- Rename `/data/` to `/api/`
+- Rename `teachers` to `lecturers`
+- Rename `id` fields to `pk` to avoid many naming collisions in programming languages
+- Move any binary files away from the API (xlsx, PDF, …)
+- The blockclasses should be part of the `{version}` api, not the `{semester}`
+- Change some German names to English (`klassen.pdf`, …)
+- Decide on `Blockclass` vs `Blockmodule`

+ 56 - 0
cspell.config.yaml

@@ -0,0 +1,56 @@
+version: "0.2"
+allowCompoundWords: false
+ignorePaths:
+  - "*.svg"
+  - .pre-commit-config.yaml
+  - .vscode/*
+  - .gitignore
+  - cspell.config.yaml
+  - .copier-answers.yml
+  - "*.svg"
+  - .forgejo/*
+  - .releaserc.yaml
+  - CHANGELOG.md
+dictionaryDefinitions: []
+ignoreWords: []
+dictionaries: []
+import:
+  - "@cspell/dict-de-ch/cspell-ext.json"
+  - "@cspell/dict-en-gb/cspell-ext.json"
+words:
+  - afana
+  - alges
+  - Bharath
+  - blockclass
+  - blockclasses
+  - Ceng
+  - Dunyasha
+  - ects
+  - edea
+  - einschr
+  - elmag
+  - firstname
+  - forgejo
+  - Gaus
+  - gitea
+  - hfta
+  - Initialversion
+  - klassen
+  - korr
+  - kryg
+  - lalg
+  - mgli
+  - Modulplaner OpenAPI
+  - modulplaner_openapi
+  - msee
+  - openapi
+  - prov
+  - rabh
+  - Racquel
+  - redocly
+  - rudu
+  - Ruuben
+  - Schaltungstechnik
+  - sean
+  - snas
+  - swaggerapi

+ 20 - 0
makefile

@@ -0,0 +1,20 @@
+pre-commit-install:
+	pre-commit install;
+	pre-commit install --hook-type commit-msg;
+
+update-template:
+	copier update --trust --defaults
+
+# https://copier.readthedocs.io/en/stable/updating/#recover-from-a-broken-update
+update-template-forced:
+	copier recopy $$project --trust
+
+cspell-filenames:
+	git ls-files | cspell stdin --show-context --locale en-GB,de-CH
+
+lint:
+	cd src; redocly lint openapi.yaml
+
+preview-docs:
+	cd src; redocly bundle openapi.yaml -o ../out/openapi.json
+	docker run -p 8080:8080 -e SWAGGER_JSON=/out/openapi.json -v $(PWD)/out:/out swaggerapi/swagger-ui

+ 1172 - 0
out/openapi.json

@@ -0,0 +1,1172 @@
+{
+  "openapi": "3.1.0",
+  "info": {
+    "title": "Modulplaner OpenAPI",
+    "version": "1.0.0",
+    "contact": {
+      "email": "sean@black-burn.ch"
+    },
+    "description": "OpenAPI documentation of the modulplaner API\n",
+    "license": {
+      "name": "MPL 2.0",
+      "url": "https://www.mozilla.org/en-US/MPL/2.0/"
+    }
+  },
+  "servers": [
+    {
+      "url": "http://localhost:8080",
+      "description": "localhost"
+    }
+  ],
+  "paths": {
+    "/data/semester-versions.json": {
+      "get": {
+        "operationId": "GetSemesterVersions",
+        "summary": "Overview of the available semesters and their respective versions of the timetable.",
+        "security": [],
+        "tags": [
+          "Semesters"
+        ],
+        "responses": {
+          "200": {
+            "$ref": "#/components/responses/semester-versions-200"
+          }
+        }
+      }
+    },
+    "/data/modules.json": {
+      "get": {
+        "operationId": "GetModules",
+        "summary": "All available modules and additional information.",
+        "security": [],
+        "tags": [
+          "Modules"
+        ],
+        "responses": {
+          "200": {
+            "$ref": "#/components/responses/modules-200"
+          }
+        }
+      }
+    },
+    "/data/lecturers.json": {
+      "get": {
+        "operationId": "GetLecturers",
+        "summary": "A list of all the lecturers.",
+        "security": [],
+        "tags": [
+          "Lecturers"
+        ],
+        "responses": {
+          "200": {
+            "$ref": "#/components/responses/lecturers-200"
+          }
+        }
+      }
+    },
+    "/data/module-history.json": {
+      "get": {
+        "operationId": "GetModuleHistory",
+        "summary": "A list of all the lecturers.",
+        "security": [],
+        "tags": [
+          "Modules"
+        ],
+        "responses": {
+          "200": {
+            "$ref": "#/components/responses/module-history-200"
+          }
+        }
+      }
+    },
+    "/data/changelog.html": {
+      "get": {
+        "operationId": "GetHTMLChangelog",
+        "summary": "HTML Changelog of the modulplaner frontend",
+        "security": [],
+        "tags": [
+          "Changelog"
+        ],
+        "responses": {
+          "200": {
+            "$ref": "#/components/responses/changelog-html-200"
+          }
+        }
+      }
+    },
+    "/data/{semester}/config.json": {
+      "get": {
+        "operationId": "GetSemesterConfig",
+        "summary": "Configuration / additional information for this semester.",
+        "security": [],
+        "tags": [
+          "Semester"
+        ],
+        "parameters": [
+          {
+            "$ref": "#/components/parameters/semester"
+          }
+        ],
+        "responses": {
+          "200": {
+            "$ref": "#/components/responses/semester-config-200"
+          }
+        }
+      }
+    },
+    "/data/{semester}/changes.json": {
+      "get": {
+        "operationId": "GetSemesterChanges",
+        "summary": "A list of all changes between the versions of this semester.",
+        "security": [],
+        "tags": [
+          "Semester"
+        ],
+        "parameters": [
+          {
+            "$ref": "#/components/parameters/semester"
+          }
+        ],
+        "responses": {
+          "200": {
+            "$ref": "#/components/responses/changes-200"
+          }
+        }
+      }
+    },
+    "/data/{semester}/blockclasses.json": {
+      "get": {
+        "operationId": "GetSemesterBlockclasses",
+        "summary": "A list of all blockclasses for this semester.",
+        "security": [],
+        "tags": [
+          "Semester"
+        ],
+        "parameters": [
+          {
+            "$ref": "#/components/parameters/semester"
+          }
+        ],
+        "responses": {
+          "200": {
+            "$ref": "#/components/responses/blockclasses-200"
+          }
+        }
+      }
+    },
+    "/data/{semester}/{version}/classes.json": {
+      "get": {
+        "operationId": "GetSemesterVersionClasses",
+        "summary": "A list of all classes for this semester/version.",
+        "security": [],
+        "tags": [
+          "Semester Version"
+        ],
+        "parameters": [
+          {
+            "$ref": "#/components/parameters/semester"
+          },
+          {
+            "$ref": "#/components/parameters/version"
+          }
+        ],
+        "responses": {
+          "200": {
+            "$ref": "#/components/responses/classes-200"
+          }
+        }
+      }
+    },
+    "/data/{semester}/{version}/config.json": {
+      "get": {
+        "operationId": "GetSemesterVersionConfig",
+        "summary": "Configuration/additional information for this semester/version.",
+        "security": [],
+        "tags": [
+          "Semester Version"
+        ],
+        "parameters": [
+          {
+            "$ref": "#/components/parameters/semester"
+          },
+          {
+            "$ref": "#/components/parameters/version"
+          }
+        ],
+        "responses": {
+          "200": {
+            "$ref": "#/components/responses/semester-version-config-200"
+          }
+        }
+      }
+    },
+    "/data/{semester}/{version}/klassen.pdf": {
+      "get": {
+        "operationId": "GetSemesterVersionKlassenPDF",
+        "summary": "PDF of the original timetable.",
+        "security": [],
+        "tags": [
+          "Semester Version"
+        ],
+        "parameters": [
+          {
+            "$ref": "#/components/parameters/semester"
+          },
+          {
+            "$ref": "#/components/parameters/version"
+          }
+        ],
+        "responses": {
+          "200": {
+            "$ref": "#/components/responses/klassen-pdf-200"
+          }
+        }
+      }
+    }
+  },
+  "components": {
+    "schemas": {
+      "semester-version": {
+        "type": "object",
+        "description": "Single semester and all of its versions",
+        "properties": {
+          "semester": {
+            "description": "Name of the semester",
+            "type": "string"
+          },
+          "versions": {
+            "description": "The different versions available for this semester",
+            "type": "array",
+            "items": {
+              "type": "string"
+            }
+          }
+        },
+        "required": [
+          "semester",
+          "versions"
+        ]
+      },
+      "grading-type": {
+        "description": "Types of grading",
+        "type": "string",
+        "oneOf": [
+          {
+            "title": "HN",
+            "const": "HN",
+            "description": "TODO"
+          },
+          {
+            "title": "MSP",
+            "const": "MSP",
+            "description": "Final Exam"
+          },
+          {
+            "title": "SE",
+            "const": "SE",
+            "description": "TODO"
+          }
+        ]
+      },
+      "module-dependency": {
+        "type": "object",
+        "description": "The dependencies of a single module, split by language.",
+        "additionalProperties": {
+          "description": "The language (as the key), in which the module has a dependency to (array values).\n",
+          "type": "array",
+          "items": {
+            "description": "The short module name",
+            "type": "string"
+          }
+        }
+      },
+      "module": {
+        "type": "object",
+        "description": "A single module definition",
+        "properties": {
+          "short": {
+            "description": "Short name of the module / its human readable ID.",
+            "type": "string"
+          },
+          "name": {
+            "description": "Full name of the module",
+            "type": "string"
+          },
+          "for_degrees": {
+            "description": "List of degrees, for which this module is meant.",
+            "type": [
+              "array",
+              "null"
+            ],
+            "items": {
+              "type": "string"
+            }
+          },
+          "module_id": {
+            "description": "The unique module ID number.",
+            "type": [
+              "number",
+              "null"
+            ]
+          },
+          "module_ids": {
+            "description": "TODO",
+            "type": [
+              "array",
+              "null"
+            ],
+            "items": {
+              "type": "integer",
+              "format": "int32"
+            }
+          },
+          "ects": {
+            "description": "The number of ECTS this module awards upon completion.",
+            "type": [
+              "number",
+              "null"
+            ]
+          },
+          "marks": {
+            "description": "The types of marks that this module involves (Final exam, continuous grading,\nproject, …).\n",
+            "type": [
+              "array",
+              "null"
+            ],
+            "items": {
+              "$ref": "#/components/schemas/grading-type"
+            }
+          },
+          "cat": {
+            "description": "Category of module (Context, Specialization, basic education, …).",
+            "type": [
+              "string",
+              "null"
+            ]
+          },
+          "sub_cat": {
+            "description": "Sub-category of the module (business administration, subject supplement,\nspecialization).\n",
+            "type": [
+              "string",
+              "null"
+            ]
+          },
+          "dependencies": {
+            "description": "What dependencies are required to be able to participate in this module.\n",
+            "$ref": "#/components/schemas/module-dependency"
+          },
+          "enablingModules": {
+            "description": "List of modules, that can be attended, after the completion of this module.\n",
+            "$ref": "#/components/schemas/module-dependency"
+          }
+        },
+        "required": [
+          "short",
+          "name",
+          "for_degrees",
+          "module_id",
+          "module_ids",
+          "ects",
+          "marks",
+          "cat",
+          "sub_cat",
+          "dependencies",
+          "enablingModules"
+        ]
+      },
+      "lecturer": {
+        "type": "object",
+        "description": "Single lecturer",
+        "properties": {
+          "short": {
+            "description": "A short name for the lecturer, that is unique",
+            "type": "string"
+          },
+          "surname": {
+            "description": "The surname of the lecturer",
+            "type": "string"
+          },
+          "firstname": {
+            "description": "The given name of a lecturer",
+            "type": "string"
+          }
+        },
+        "required": [
+          "short",
+          "surname",
+          "firstname"
+        ]
+      },
+      "weekday": {
+        "type": "integer",
+        "format": "int8",
+        "description": "The various weekdays",
+        "oneOf": [
+          {
+            "title": "Monday",
+            "const": 0
+          },
+          {
+            "title": "Tuesday",
+            "const": 1
+          },
+          {
+            "title": "Wednesday",
+            "const": 2
+          },
+          {
+            "title": "Thursday",
+            "const": 3
+          },
+          {
+            "title": "Friday",
+            "const": 4
+          },
+          {
+            "title": "Saturday",
+            "const": 5
+          },
+          {
+            "title": "Sunday",
+            "const": 6
+          }
+        ]
+      },
+      "teaching-type": {
+        "type": "string",
+        "description": "Various types of teaching types/locations",
+        "oneOf": [
+          {
+            "title": "On Site",
+            "const": "on_site",
+            "description": "Only taught on site"
+          },
+          {
+            "title": "Online",
+            "const": "online",
+            "description": "Exclusively taught online"
+          },
+          {
+            "title": "Blockmodule",
+            "const": "blockmodule",
+            "description": "A module that is taught in a single block over the span of a few weeks, not the\nentire semester.\n"
+          },
+          {
+            "title": "Hybrid",
+            "const": "hybrid",
+            "description": "Both on site and online"
+          }
+        ]
+      },
+      "module-history": {
+        "type": "object",
+        "description": "A complete history of all planned executions of each module",
+        "additionalProperties": {
+          "description": "The key is the modules short name with a mapping to an array",
+          "type": "array",
+          "items": {
+            "type": "object",
+            "properties": {
+              "semester": {
+                "description": "The semester this module took place in",
+                "type": "string"
+              },
+              "version": {
+                "description": "The version of the semester plan",
+                "type": "string"
+              },
+              "weekday": {
+                "description": "The weekday the module took place on",
+                "$ref": "#/components/schemas/weekday"
+              },
+              "class": {
+                "description": "Name of the class this module is part of",
+                "type": "string"
+              },
+              "from": {
+                "description": "Start time of the module, in seconds since midnight",
+                "type": "integer",
+                "format": "int32"
+              },
+              "to": {
+                "description": "End time of the module, in seconds since midnight",
+                "type": "integer",
+                "format": "int32"
+              },
+              "lecturers": {
+                "description": "List of lecturers teaching this module",
+                "type": "array",
+                "items": {
+                  "type": "string"
+                }
+              },
+              "teaching_type": {
+                "description": "The type of teaching",
+                "$ref": "#/components/schemas/teaching-type"
+              },
+              "rooms": {
+                "description": "List of rooms reserved for this module",
+                "type": "array",
+                "items": {
+                  "type": "string"
+                }
+              },
+              "pages": {
+                "description": "List of pages, on which the module can be found in the PDF",
+                "type": "array",
+                "items": {
+                  "type": "integer",
+                  "format": "int16"
+                }
+              },
+              "id": {
+                "description": "A unique ID for this module and the time it is taught",
+                "type": "string"
+              }
+            },
+            "required": [
+              "semester",
+              "version",
+              "weekday",
+              "class",
+              "from",
+              "to",
+              "lecturers",
+              "teaching_type",
+              "rooms",
+              "pages",
+              "id"
+            ]
+          }
+        }
+      },
+      "semester-config": {
+        "type": "object",
+        "description": "Semester configuration / additional information",
+        "properties": {
+          "blockclass_file": {
+            "description": "Relative path to the blockclass file",
+            "type": [
+              "string",
+              "null"
+            ]
+          }
+        },
+        "required": [
+          "blockclass_file"
+        ]
+      },
+      "change": {
+        "type": "object",
+        "description": "A single change in the semester plan version, outlining the changes",
+        "properties": {
+          "name": {
+            "description": "The name of the version",
+            "type": "string"
+          },
+          "changes": {
+            "description": "A HTML string of the changes",
+            "type": "string"
+          }
+        },
+        "required": [
+          "name",
+          "changes"
+        ]
+      },
+      "blockclass": {
+        "type": "object",
+        "description": "Single blockclass entry",
+        "properties": {
+          "weekday": {
+            "description": "Not used",
+            "type": "null"
+          },
+          "from": {
+            "description": "Time the module starts in seconds since midnight (not used, always 0)",
+            "type": "integer",
+            "format": "int32"
+          },
+          "to": {
+            "description": "Time the module starts in seconds since midnight (not used, always 0)",
+            "type": "integer",
+            "format": "int32"
+          },
+          "class": {
+            "description": "Class name this block module is part of",
+            "type": "string"
+          },
+          "name": {
+            "description": "Short name of the module",
+            "type": "string"
+          },
+          "rooms": {
+            "description": "The rooms which are reserved for this module",
+            "type": "array",
+            "items": {
+              "type": "string"
+            }
+          },
+          "teachers": {
+            "description": "The lecturers names that are teaching this module",
+            "type": "array",
+            "items": {
+              "type": "string"
+            }
+          },
+          "teaching_type": {
+            "description": "Type of teaching",
+            "$ref": "#/components/schemas/teaching-type"
+          },
+          "pages": {
+            "description": "The pages, on which the module can be found",
+            "type": "array",
+            "items": {
+              "type": "integer",
+              "format": "int16"
+            }
+          },
+          "degree_prg": {
+            "description": "Name of the degree program this module is part of",
+            "type": "string"
+          },
+          "part_of_other_classes": {
+            "description": "List of other classes, where this module is also taught",
+            "type": "array",
+            "items": {
+              "type": "string"
+            }
+          },
+          "id": {
+            "description": "Unique identifier for this blockmodule",
+            "type": "string"
+          }
+        },
+        "required": [
+          "weekday",
+          "from",
+          "to",
+          "class",
+          "name",
+          "rooms",
+          "teachers",
+          "teaching_type",
+          "pages",
+          "degree_prg",
+          "part_of_other_classes",
+          "id"
+        ]
+      },
+      "class": {
+        "type": "object",
+        "description": "Single class definition of a specific version",
+        "properties": {
+          "weekday": {
+            "description": "The weekday the module took place on",
+            "$ref": "#/components/schemas/weekday"
+          },
+          "from": {
+            "description": "Start time of the module, in seconds since midnight",
+            "type": "integer",
+            "format": "int32"
+          },
+          "to": {
+            "description": "End time of the module, in seconds since midnight",
+            "type": "integer",
+            "format": "int32"
+          },
+          "class": {
+            "description": "Name of the class this module is part of",
+            "type": "string"
+          },
+          "name": {
+            "description": "Short name of the module"
+          },
+          "rooms": {
+            "description": "List of rooms reserved for this module",
+            "type": "array",
+            "items": {
+              "type": "string"
+            }
+          },
+          "teachers": {
+            "description": "List of lecturers teaching this module",
+            "type": "array",
+            "items": {
+              "type": "string"
+            }
+          },
+          "teaching_type": {
+            "description": "The type of teaching",
+            "$ref": "#/components/schemas/teaching-type"
+          },
+          "pages": {
+            "description": "List of pages, on which the module can be found in the PDF",
+            "type": "array",
+            "items": {
+              "type": "integer",
+              "format": "int16"
+            }
+          },
+          "degree_prg": {
+            "description": "Name of the degree program this module is part of",
+            "type": "string"
+          },
+          "part_of_other_classes": {
+            "description": "List of other classes, where this module is also taught",
+            "type": "array",
+            "items": {
+              "type": "string"
+            }
+          },
+          "id": {
+            "description": "A unique ID for this module and the time it is taught",
+            "type": "string"
+          }
+        },
+        "required": [
+          "weekday",
+          "from",
+          "to",
+          "class",
+          "name",
+          "rooms",
+          "teachers",
+          "teaching_type",
+          "pages",
+          "degree_prg",
+          "part_of_other_classes",
+          "id"
+        ]
+      },
+      "semester-version-config": {
+        "type": "object",
+        "description": "Version specific configurations/additional information",
+        "properties": {
+          "pdf_version": {
+            "description": "Version name of the PDF",
+            "type": "string",
+            "example": "einschreiben / HS_24_einschr_3"
+          },
+          "export_date": {
+            "description": "The date, when the version of this plan was released.",
+            "format": "dd.mm.yyyy HH:MM:SS",
+            "type": "string",
+            "example": "17.06.2024 15:07:00"
+          },
+          "parse_date": {
+            "description": "The date, when the version of this plan was parsed.",
+            "format": "dd.mm.yyyy HH:MM:SS",
+            "type": "string",
+            "example": "04.10.2024 17:45:10"
+          }
+        },
+        "required": [
+          "pdf_version",
+          "export_date",
+          "parse_date"
+        ]
+      }
+    },
+    "responses": {
+      "semester-versions-200": {
+        "description": "OK",
+        "content": {
+          "application/json": {
+            "schema": {
+              "type": "array",
+              "items": {
+                "$ref": "#/components/schemas/semester-version"
+              }
+            },
+            "example": [
+              {
+                "semester": "24HS",
+                "versions": [
+                  "einschr_3",
+                  "einschr_2",
+                  "einschr_1"
+                ]
+              },
+              {
+                "semester": "24FS",
+                "versions": [
+                  "korr_2",
+                  "korr_2_1",
+                  "korr_1",
+                  "einschr_3_1",
+                  "einschr_3",
+                  "einschr_2",
+                  "einschr_1",
+                  "prov_4a"
+                ]
+              }
+            ]
+          }
+        }
+      },
+      "modules-200": {
+        "description": "OK",
+        "content": {
+          "application/json": {
+            "schema": {
+              "type": "array",
+              "items": {
+                "$ref": "#/components/schemas/module"
+              }
+            },
+            "example": [
+              {
+                "short": "aet1",
+                "name": "Allgemeine Elektrotechnik 1 ",
+                "for_degrees": [
+                  "Elektro- und Informationstechnik",
+                  "Systemtechnik"
+                ],
+                "module_id": 6007771,
+                "module_ids": [
+                  6007771
+                ],
+                "ects": 3,
+                "marks": [
+                  "HN",
+                  "MSP",
+                  "SE"
+                ],
+                "cat": "Fachausbildung",
+                "sub_cat": "Fachgrundlagen",
+                "dependencies": {
+                  "de": [
+                    "an1"
+                  ],
+                  "en": []
+                },
+                "enablingModules": {
+                  "de": [
+                    "aet2",
+                    "msee"
+                  ],
+                  "en": []
+                }
+              },
+              {
+                "short": "ast1",
+                "name": "Analoge Schaltungstechnik 1 ",
+                "for_degrees": null,
+                "module_id": null,
+                "module_ids": null,
+                "ects": null,
+                "marks": null,
+                "cat": null,
+                "sub_cat": null,
+                "dependencies": {},
+                "enablingModules": {
+                  "de": [],
+                  "en": []
+                }
+              }
+            ]
+          }
+        }
+      },
+      "lecturers-200": {
+        "description": "OK",
+        "content": {
+          "application/json": {
+            "schema": {
+              "type": "array",
+              "items": {
+                "$ref": "#/components/schemas/lecturer"
+              }
+            },
+            "example": [
+              {
+                "short": "rabh",
+                "surname": "Racquel",
+                "firstname": "Bharath"
+              },
+              {
+                "short": "rudu",
+                "surname": "Ruuben",
+                "firstname": "Dunyasha"
+              }
+            ]
+          }
+        }
+      },
+      "module-history-200": {
+        "description": "OK",
+        "content": {
+          "application/json": {
+            "schema": {
+              "$ref": "#/components/schemas/module-history"
+            },
+            "example": {
+              "aet1": [
+                {
+                  "semester": "24HS",
+                  "version": "einschr_3",
+                  "weekday": 0,
+                  "class": "1Ea",
+                  "from": 29700,
+                  "to": 39600,
+                  "lecturers": [
+                    "Gaus"
+                  ],
+                  "teaching_type": "on_site",
+                  "rooms": [
+                    "1.331"
+                  ],
+                  "pages": [
+                    3,
+                    5
+                  ],
+                  "id": "1Ea-aet1-0-29700-39600"
+                }
+              ],
+              "afana": [
+                {
+                  "semester": "12HS",
+                  "version": "korr_8",
+                  "weekday": 1,
+                  "class": "1Ia",
+                  "from": 45900,
+                  "to": 54600,
+                  "lecturers": [
+                    "Syn"
+                  ],
+                  "teaching_type": "on_site",
+                  "rooms": [
+                    "4.417"
+                  ],
+                  "pages": [
+                    3
+                  ],
+                  "id": "1Ia-afana-1-45900-54600"
+                },
+                {
+                  "semester": "12HS",
+                  "version": "korr_8",
+                  "weekday": 1,
+                  "class": "1Ib",
+                  "from": 33000,
+                  "to": 42300,
+                  "lecturers": [
+                    "Syn"
+                  ],
+                  "teaching_type": "on_site",
+                  "rooms": [
+                    "4.427"
+                  ],
+                  "pages": [
+                    4
+                  ],
+                  "id": "1Ib-afana-1-33000-42300"
+                }
+              ]
+            }
+          }
+        }
+      },
+      "changelog-html-200": {
+        "description": "OK",
+        "content": {
+          "text/html": {
+            "example": ""
+          }
+        }
+      },
+      "semester-config-200": {
+        "description": "OK",
+        "content": {
+          "application/json": {
+            "schema": {
+              "$ref": "#/components/schemas/semester-config"
+            },
+            "example": {
+              "blockclass_file": "Blockmodule.xlsx"
+            }
+          }
+        }
+      },
+      "changes-200": {
+        "description": "OK",
+        "content": {
+          "application/json": {
+            "schema": {
+              "type": "array",
+              "items": {
+                "$ref": "#/components/schemas/change"
+              }
+            },
+            "example": [
+              {
+                "name": "prov_5",
+                "changes": "<p>Initialversion</p>"
+              },
+              {
+                "name": "einschr_1",
+                "changes": "<p>Seit der letzten Version hat's neben diversen Raum- und Dozierenden-Änderungen folgende Anpassungen gegeben:</p>\n<p><strong>Verschiebung / Änderungen:</strong>\n  <ul>\n    <li>wus 1Ea</li>\n    <li>aet1 1Eb</li>\n    <li>glaL1 1Eb</li>\n    <li>oop1 1Eb</li>\n    <li>hfta 5Ea</li>\n    <li>kryg 5Ea</li>\n    <li>edea 5iCbb</li>\n    <li>an1 1Ma</li>\n    <li>lalg1 1Ma</li>\n    <li>an1 1Mb</li>\n    <li>lalg1 1Mb</li>\n    <li>pro4M 5Mbb</li>\n    <li>eltM 3Mb</li>\n    <li>elmag 3Mb</li>\n    <li>dglM 3Mb</li>\n  </ul>\n</p>\n<p><strong>Streichung von:</strong> <ul><li>mgli 1iCeng</li></ul> </p>"
+              },
+              {
+                "name": "korr_1",
+                "changes": "<p>Keine Angaben</p>"
+              },
+              {
+                "name": "korr_2",
+                "changes": "<p>Keine Angaben</p>"
+              }
+            ]
+          }
+        }
+      },
+      "blockclasses-200": {
+        "description": "OK",
+        "content": {
+          "application/json": {
+            "schema": {
+              "type": "array",
+              "items": {
+                "$ref": "#/components/schemas/blockclass"
+              }
+            },
+            "example": [
+              {
+                "weekday": null,
+                "from": 0,
+                "to": 0,
+                "class": "5Me",
+                "name": "aem",
+                "rooms": [],
+                "teachers": [],
+                "teaching_type": "blockmodule",
+                "pages": [
+                  1
+                ],
+                "degree_prg": "Maschinenbau",
+                "part_of_other_classes": [],
+                "id": "5Me-aem-b"
+              },
+              {
+                "weekday": null,
+                "from": 0,
+                "to": 0,
+                "class": "7KGb",
+                "name": "alges",
+                "rooms": [],
+                "teachers": [],
+                "teaching_type": "blockmodule",
+                "pages": [
+                  1
+                ],
+                "degree_prg": "Kontext GSW",
+                "part_of_other_classes": [],
+                "id": "7KGb-alges-b"
+              }
+            ]
+          }
+        }
+      },
+      "classes-200": {
+        "description": "OK",
+        "content": {
+          "application/json": {
+            "schema": {
+              "type": "array",
+              "items": {
+                "$ref": "#/components/schemas/class"
+              }
+            },
+            "example": [
+              {
+                "weekday": 0,
+                "from": 29700,
+                "to": 64800,
+                "class": "1Da",
+                "name": "dummy",
+                "rooms": [
+                  "5.3B51"
+                ],
+                "teachers": [
+                  "Cur"
+                ],
+                "teaching_type": "on_site",
+                "pages": [
+                  1
+                ],
+                "degree_prg": "Data Science",
+                "part_of_other_classes": [],
+                "id": "1Da-dummy-0-29700-64800"
+              },
+              {
+                "weekday": 1,
+                "from": 29700,
+                "to": 36000,
+                "class": "1Da",
+                "name": "eda",
+                "rooms": [
+                  "5.3B51"
+                ],
+                "teachers": [
+                  "Ped"
+                ],
+                "teaching_type": "on_site",
+                "pages": [
+                  1
+                ],
+                "degree_prg": "Data Science",
+                "part_of_other_classes": [],
+                "id": "1Da-eda-1-29700-36000"
+              }
+            ]
+          }
+        }
+      },
+      "semester-version-config-200": {
+        "description": "OK",
+        "content": {
+          "application/json": {
+            "schema": {
+              "$ref": "#/components/schemas/semester-version-config"
+            },
+            "example": {
+              "pdf_version": "einschreiben / HS_24_einschr_3",
+              "export_date": "17.06.2024 15:07:00",
+              "parse_date": "04.10.2024 17:45:10"
+            }
+          }
+        }
+      },
+      "klassen-pdf-200": {
+        "description": "OK",
+        "content": {
+          "application/vnd.ms-excel": {
+            "example": ""
+          }
+        }
+      }
+    },
+    "parameters": {
+      "semester": {
+        "name": "semester",
+        "in": "path",
+        "description": "Semester",
+        "required": true,
+        "schema": {
+          "type": "string",
+          "summary": "Name of the semester. To fetch the latest semester, use `latest`"
+        }
+      },
+      "version": {
+        "name": "version",
+        "in": "path",
+        "description": "Semester version",
+        "required": true,
+        "schema": {
+          "type": "string",
+          "summary": "Name of the version. To fetch the latest version, use `latest`"
+        }
+      }
+    }
+  }
+}

+ 0 - 0
src/components/callbacks/.gitkeep


+ 12 - 0
src/components/enums/grading-type.yaml

@@ -0,0 +1,12 @@
+description: Types of grading
+type: string
+oneOf:
+  - title: HN
+    const: HN
+    description: TODO
+  - title: MSP
+    const: MSP
+    description: Final Exam
+  - title: SE
+    const: SE
+    description: TODO

+ 17 - 0
src/components/enums/teaching-type.yaml

@@ -0,0 +1,17 @@
+type: string
+description: Various types of teaching types/locations
+oneOf:
+  - title: On Site
+    const: on_site
+    description: Only taught on site
+  - title: Online
+    const: online
+    description: Exclusively taught online
+  - title: Blockmodule
+    const: blockmodule
+    description: |
+      A module that is taught in a single block over the span of a few weeks, not the
+      entire semester.
+  - title: Hybrid
+    const: hybrid
+    description: Both on site and online

+ 18 - 0
src/components/enums/weekday.yaml

@@ -0,0 +1,18 @@
+type: integer
+format: int8
+description: The various weekdays
+oneOf:
+  - title: Monday
+    const: 0
+  - title: Tuesday
+    const: 1
+  - title: Wednesday
+    const: 2
+  - title: Thursday
+    const: 3
+  - title: Friday
+    const: 4
+  - title: Saturday
+    const: 5
+  - title: Sunday
+    const: 6

+ 6 - 0
src/components/examples/lecturers.yaml

@@ -0,0 +1,6 @@
+- short: rabh
+  surname: Racquel
+  firstname: Bharath
+- short: rudu
+  surname: Ruuben
+  firstname: Dunyasha

+ 45 - 0
src/components/examples/module-history.yaml

@@ -0,0 +1,45 @@
+aet1:
+  - semester: 24HS
+    version: einschr_3
+    weekday: 0
+    class: 1Ea
+    from: 29700
+    to: 39600
+    lecturers:
+      - Gaus
+    teaching_type: on_site
+    rooms:
+      - "1.331"
+    pages:
+      - 3
+      - 5
+    id: 1Ea-aet1-0-29700-39600
+afana:
+  - semester: 12HS
+    version: korr_8
+    weekday: 1
+    class: 1Ia
+    from: 45900
+    to: 54600
+    lecturers:
+      - Syn
+    teaching_type: on_site
+    rooms:
+      - "4.417"
+    pages:
+      - 3
+    id: 1Ia-afana-1-45900-54600
+  - semester: 12HS
+    version: korr_8
+    weekday: 1
+    class: 1Ib
+    from: 33000
+    to: 42300
+    lecturers:
+      - Syn
+    teaching_type: on_site
+    rooms:
+      - "4.427"
+    pages:
+      - 4
+    id: 1Ib-afana-1-33000-42300

+ 37 - 0
src/components/examples/modules.yaml

@@ -0,0 +1,37 @@
+- short: aet1
+  name: "Allgemeine Elektrotechnik 1 "
+  for_degrees:
+    - Elektro- und Informationstechnik
+    - Systemtechnik
+  module_id: 6007771
+  module_ids:
+    - 6007771
+  ects: 3
+  marks:
+    - HN
+    - MSP
+    - SE
+  cat: Fachausbildung
+  sub_cat: Fachgrundlagen
+  dependencies:
+    de:
+      - an1
+    en: []
+  enablingModules:
+    de:
+      - aet2
+      - msee
+    en: []
+- short: ast1
+  name: "Analoge Schaltungstechnik 1 "
+  for_degrees: null
+  module_id: null
+  module_ids: null
+  ects: null
+  marks: null
+  cat: null
+  sub_cat: null
+  dependencies: {}
+  enablingModules:
+    de: []
+    en: []

+ 15 - 0
src/components/examples/semester-versions.yaml

@@ -0,0 +1,15 @@
+- semester: 24HS
+  versions:
+    - einschr_3
+    - einschr_2
+    - einschr_1
+- semester: 24FS
+  versions:
+    - korr_2
+    - korr_2_1
+    - korr_1
+    - einschr_3_1
+    - einschr_3
+    - einschr_2
+    - einschr_1
+    - prov_4a

+ 26 - 0
src/components/examples/{semester}/blockclasses.yaml

@@ -0,0 +1,26 @@
+- weekday: null
+  from: 0
+  to: 0
+  class: 5Me
+  name: aem
+  rooms: []
+  teachers: []
+  teaching_type: blockmodule
+  pages:
+    - 1
+  degree_prg: Maschinenbau
+  part_of_other_classes: []
+  id: 5Me-aem-b
+- weekday: null
+  from: 0
+  to: 0
+  class: 7KGb
+  name: alges
+  rooms: []
+  teachers: []
+  teaching_type: blockmodule
+  pages:
+    - 1
+  degree_prg: Kontext GSW
+  part_of_other_classes: []
+  id: 7KGb-alges-b

+ 34 - 0
src/components/examples/{semester}/changes.yaml

@@ -0,0 +1,34 @@
+- name: prov_5
+  changes: <p>Initialversion</p>
+- name: einschr_1
+  changes: >-
+    <p>Seit der letzten Version hat's neben diversen Raum- und
+    Dozierenden-Änderungen folgende Anpassungen gegeben:</p>
+
+    <p><strong>Verschiebung / Änderungen:</strong>
+      <ul>
+        <li>wus 1Ea</li>
+        <li>aet1 1Eb</li>
+        <li>glaL1 1Eb</li>
+        <li>oop1 1Eb</li>
+        <li>hfta 5Ea</li>
+        <li>kryg 5Ea</li>
+        <li>edea 5iCbb</li>
+        <li>an1 1Ma</li>
+        <li>lalg1 1Ma</li>
+        <li>an1 1Mb</li>
+        <li>lalg1 1Mb</li>
+        <li>pro4M 5Mbb</li>
+        <li>eltM 3Mb</li>
+        <li>elmag 3Mb</li>
+        <li>dglM 3Mb</li>
+      </ul>
+    </p>
+
+    <p><strong>Streichung von:</strong>
+    <ul><li>mgli 1iCeng</li></ul>
+    </p>
+- name: korr_1
+  changes: <p>Keine Angaben</p>
+- name: korr_2
+  changes: <p>Keine Angaben</p>

+ 1 - 0
src/components/examples/{semester}/config.yaml

@@ -0,0 +1 @@
+blockclass_file: "Blockmodule.xlsx"

+ 30 - 0
src/components/examples/{semester}/{version}/classes.yaml

@@ -0,0 +1,30 @@
+- weekday: 0
+  from: 29700
+  to: 64800
+  class: 1Da
+  name: dummy
+  rooms:
+    - 5.3B51
+  teachers:
+    - Cur
+  teaching_type: on_site
+  pages:
+    - 1
+  degree_prg: Data Science
+  part_of_other_classes: []
+  id: 1Da-dummy-0-29700-64800
+- weekday: 1
+  from: 29700
+  to: 36000
+  class: 1Da
+  name: eda
+  rooms:
+    - 5.3B51
+  teachers:
+    - Ped
+  teaching_type: on_site
+  pages:
+    - 1
+  degree_prg: Data Science
+  part_of_other_classes: []
+  id: 1Da-eda-1-29700-36000

+ 3 - 0
src/components/examples/{semester}/{version}/config.yaml

@@ -0,0 +1,3 @@
+pdf_version: einschreiben / HS_24_einschr_3
+export_date: 17.06.2024 15:07:00
+parse_date: 04.10.2024 17:45:10

+ 0 - 0
src/components/headers/.gitkeep


+ 0 - 0
src/components/links/.gitkeep


+ 7 - 0
src/components/parameters/semester.yaml

@@ -0,0 +1,7 @@
+name: semester
+in: path
+description: Semester
+required: true
+schema:
+  type: string
+  summary: Name of the semester. To fetch the latest semester, use `latest`

+ 7 - 0
src/components/parameters/version.yaml

@@ -0,0 +1,7 @@
+name: version
+in: path
+description: Semester version
+required: true
+schema:
+  type: string
+  summary: Name of the version. To fetch the latest version, use `latest`

+ 0 - 0
src/components/pathItems/.gitkeep


+ 0 - 0
src/components/requestBodies/.gitkeep


+ 4 - 0
src/components/responses/changelog-html-200.yaml

@@ -0,0 +1,4 @@
+description: OK
+content:
+  text/html:
+    example: ""

+ 9 - 0
src/components/responses/lecturers-200.yaml

@@ -0,0 +1,9 @@
+description: OK
+content:
+  application/json:
+    schema:
+      type: array
+      items:
+        $ref: ../schemas/lecturer.yaml
+    example:
+      $ref: ../examples/lecturers.yaml

+ 7 - 0
src/components/responses/module-history-200.yaml

@@ -0,0 +1,7 @@
+description: OK
+content:
+  application/json:
+    schema:
+      $ref: ../schemas/module-history.yaml
+    example:
+      $ref: ../examples/module-history.yaml

+ 9 - 0
src/components/responses/modules-200.yaml

@@ -0,0 +1,9 @@
+description: OK
+content:
+  application/json:
+    schema:
+      type: array
+      items:
+        $ref: ../schemas/module.yaml
+    example:
+      $ref: ../examples/modules.yaml

+ 9 - 0
src/components/responses/semester-versions-200.yaml

@@ -0,0 +1,9 @@
+description: OK
+content:
+  application/json:
+    schema:
+      type: array
+      items:
+        $ref: ../schemas/semester-version.yaml
+    example:
+      $ref: ../examples/semester-versions.yaml

+ 9 - 0
src/components/responses/{semester}/blockclasses-200.yaml

@@ -0,0 +1,9 @@
+description: OK
+content:
+  application/json:
+    schema:
+      type: array
+      items:
+        $ref: ../../schemas/{semester}/blockclass.yaml
+    example:
+      $ref: ../../examples/{semester}/blockclasses.yaml

+ 9 - 0
src/components/responses/{semester}/changes-200.yaml

@@ -0,0 +1,9 @@
+description: OK
+content:
+  application/json:
+    schema:
+      type: array
+      items:
+        $ref: ../../schemas/{semester}/change.yaml
+    example:
+      $ref: ../../examples/{semester}/changes.yaml

+ 7 - 0
src/components/responses/{semester}/semester-config-200.yaml

@@ -0,0 +1,7 @@
+description: OK
+content:
+  application/json:
+    schema:
+      $ref: ../../schemas/{semester}/semester-config.yaml
+    example:
+      $ref: ../../examples/{semester}/config.yaml

+ 9 - 0
src/components/responses/{semester}/{version}/classes-200.yaml

@@ -0,0 +1,9 @@
+description: OK
+content:
+  application/json:
+    schema:
+      type: array
+      items:
+        $ref: ../../../schemas/{semester}/{version}/class.yaml
+    example:
+      $ref: ../../../examples/{semester}/{version}/classes.yaml

+ 4 - 0
src/components/responses/{semester}/{version}/klassen-pdf-200.yaml

@@ -0,0 +1,4 @@
+description: OK
+content:
+  application/vnd.ms-excel:
+    example: ""

+ 7 - 0
src/components/responses/{semester}/{version}/semester-version-config-200.yaml

@@ -0,0 +1,7 @@
+description: OK
+content:
+  application/json:
+    schema:
+      $ref: ../../../schemas/{semester}/{version}/semester-version-config.yaml
+    example:
+      $ref: ../../../examples/{semester}/{version}/config.yaml

+ 16 - 0
src/components/schemas/lecturer.yaml

@@ -0,0 +1,16 @@
+type: object
+description: Single lecturer
+properties:
+  short:
+    description: A short name for the lecturer, that is unique
+    type: string
+  surname:
+    description: The surname of the lecturer
+    type: string
+  firstname:
+    description: The given name of a lecturer
+    type: string
+required:
+  - short
+  - surname
+  - firstname

+ 9 - 0
src/components/schemas/module-dependency.yaml

@@ -0,0 +1,9 @@
+type: object
+description: The dependencies of a single module, split by language.
+additionalProperties:
+  description: |
+    The language (as the key), in which the module has a dependency to (array values).
+  type: array
+  items:
+    description: The short module name
+    type: string

+ 62 - 0
src/components/schemas/module-history.yaml

@@ -0,0 +1,62 @@
+type: object
+description: A complete history of all planned executions of each module
+additionalProperties:
+  description: The key is the modules short name with a mapping to an array
+  type: array
+  items:
+    type: object
+    properties:
+      semester:
+        description: The semester this module took place in
+        type: string
+      version:
+        description: The version of the semester plan
+        type: string
+      weekday:
+        description: The weekday the module took place on
+        $ref: ../enums/weekday.yaml
+      class:
+        description: Name of the class this module is part of
+        type: string
+      from:
+        description: Start time of the module, in seconds since midnight
+        type: integer
+        format: int32
+      to:
+        description: End time of the module, in seconds since midnight
+        type: integer
+        format: int32
+      lecturers:
+        description: List of lecturers teaching this module
+        type: array
+        items:
+          type: string
+      teaching_type:
+        description: The type of teaching
+        $ref: ../enums/teaching-type.yaml
+      rooms:
+        description: List of rooms reserved for this module
+        type: array
+        items:
+          type: string
+      pages:
+        description: List of pages, on which the module can be found in the PDF
+        type: array
+        items:
+          type: integer
+          format: int16
+      id:
+        description: A unique ID for this module and the time it is taught
+        type: string
+    required:
+      - semester
+      - version
+      - weekday
+      - class
+      - from
+      - to
+      - lecturers
+      - teaching_type
+      - rooms
+      - pages
+      - id

+ 75 - 0
src/components/schemas/module.yaml

@@ -0,0 +1,75 @@
+type: object
+description: A single module definition
+properties:
+  short:
+    description: Short name of the module / its human readable ID.
+    type: string
+  name:
+    description: Full name of the module
+    type: string
+  for_degrees:
+    description: List of degrees, for which this module is meant.
+    type:
+      - array
+      - "null"
+    items:
+      type: string
+  module_id:
+    description: The unique module ID number.
+    type:
+      - number
+      - "null"
+  module_ids:
+    description: TODO
+    type:
+      - array
+      - "null"
+    items:
+      type: integer
+      format: int32
+  ects:
+    description: The number of ECTS this module awards upon completion.
+    type:
+      - number
+      - "null"
+  marks:
+    description: |
+      The types of marks that this module involves (Final exam, continuous grading,
+      project, …).
+    type:
+      - array
+      - "null"
+    items:
+      $ref: ../enums/grading-type.yaml
+  cat:
+    description: Category of module (Context, Specialization, basic education, …).
+    type:
+      - string
+      - "null"
+  sub_cat:
+    description: |
+      Sub-category of the module (business administration, subject supplement,
+      specialization).
+    type:
+      - string
+      - "null"
+  dependencies:
+    description: |
+      What dependencies are required to be able to participate in this module.
+    $ref: ./module-dependency.yaml
+  enablingModules:
+    description: |
+      List of modules, that can be attended, after the completion of this module.
+    $ref: ./module-dependency.yaml
+required:
+  - short
+  - name
+  - for_degrees
+  - module_id
+  - module_ids
+  - ects
+  - marks
+  - cat
+  - sub_cat
+  - dependencies
+  - enablingModules

+ 16 - 0
src/components/schemas/semester-version.yaml

@@ -0,0 +1,16 @@
+type: object
+description: Single semester and all of its versions
+properties:
+  semester:
+    description: Name of the semester
+    type: string
+    example: "24HS"
+  versions:
+    description: The different versions available for this semester
+    type: array
+    items:
+      type: string
+      example: "einschr_1"
+required:
+  - semester
+  - versions

+ 63 - 0
src/components/schemas/{semester}/blockclass.yaml

@@ -0,0 +1,63 @@
+type: object
+description: Single blockclass entry
+properties:
+  weekday:
+    description: Not used
+    type: "null"
+  from:
+    description: Time the module starts in seconds since midnight (not used, always 0)
+    type: integer
+    format: int32
+  to:
+    description: Time the module starts in seconds since midnight (not used, always 0)
+    type: integer
+    format: int32
+  class:
+    description: Class name this block module is part of
+    type: string
+  name:
+    description: Short name of the module
+    type: string
+  rooms:
+    description: The rooms which are reserved for this module
+    type: array
+    items:
+      type: string
+  teachers:
+    description: The lecturers names that are teaching this module
+    type: array
+    items:
+      type: string
+  teaching_type:
+    description: Type of teaching
+    $ref: ../../enums/teaching-type.yaml
+  pages:
+    description: The pages, on which the module can be found
+    type: array
+    items:
+      type: integer
+      format: int16
+  degree_prg:
+    description: Name of the degree program this module is part of
+    type: string
+  part_of_other_classes:
+    description: List of other classes, where this module is also taught
+    type: array
+    items:
+      type: string
+  id:
+    description: Unique identifier for this blockmodule
+    type: string
+required:
+  - weekday
+  - from
+  - to
+  - class
+  - name
+  - rooms
+  - teachers
+  - teaching_type
+  - pages
+  - degree_prg
+  - part_of_other_classes
+  - id

+ 12 - 0
src/components/schemas/{semester}/change.yaml

@@ -0,0 +1,12 @@
+type: object
+description: A single change in the semester plan version, outlining the changes
+properties:
+  name:
+    description: The name of the version
+    type: string
+  changes:
+    description: A HTML string of the changes
+    type: string
+required:
+  - name
+  - changes

+ 10 - 0
src/components/schemas/{semester}/semester-config.yaml

@@ -0,0 +1,10 @@
+type: object
+description: Semester configuration / additional information
+properties:
+  blockclass_file:
+    description: Relative path to the blockclass file
+    type:
+      - string
+      - "null"
+required:
+  - blockclass_file

+ 62 - 0
src/components/schemas/{semester}/{version}/class.yaml

@@ -0,0 +1,62 @@
+type: object
+description: Single class definition of a specific version
+properties:
+  weekday:
+    description: The weekday the module took place on
+    $ref: ../../../enums/weekday.yaml
+  from:
+    description: Start time of the module, in seconds since midnight
+    type: integer
+    format: int32
+  to:
+    description: End time of the module, in seconds since midnight
+    type: integer
+    format: int32
+  class:
+    description: Name of the class this module is part of
+    type: string
+  name:
+    description: Short name of the module
+  rooms:
+    description: List of rooms reserved for this module
+    type: array
+    items:
+      type: string
+  teachers:
+    description: List of lecturers teaching this module
+    type: array
+    items:
+      type: string
+  teaching_type:
+    description: The type of teaching
+    $ref: ../../../enums/teaching-type.yaml
+  pages:
+    description: List of pages, on which the module can be found in the PDF
+    type: array
+    items:
+      type: integer
+      format: int16
+  degree_prg:
+    description: Name of the degree program this module is part of
+    type: string
+  part_of_other_classes:
+    description: List of other classes, where this module is also taught
+    type: array
+    items:
+      type: string
+  id:
+    description: A unique ID for this module and the time it is taught
+    type: string
+required:
+  - weekday
+  - from
+  - to
+  - class
+  - name
+  - rooms
+  - teachers
+  - teaching_type
+  - pages
+  - degree_prg
+  - part_of_other_classes
+  - id

+ 21 - 0
src/components/schemas/{semester}/{version}/semester-version-config.yaml

@@ -0,0 +1,21 @@
+type: object
+description: Version specific configurations/additional information
+properties:
+  pdf_version:
+    description: Version name of the PDF
+    type: string
+    example: "einschreiben / HS_24_einschr_3"
+  export_date:
+    description: The date, when the version of this plan was released.
+    format: dd.mm.yyyy HH:MM:SS
+    type: string
+    example: "17.06.2024 15:07:00"
+  parse_date:
+    description: The date, when the version of this plan was parsed.
+    format: dd.mm.yyyy HH:MM:SS
+    type: string
+    example: "04.10.2024 17:45:10"
+required:
+  - pdf_version
+  - export_date
+  - parse_date

+ 0 - 0
src/components/securitySchemes/.gitkeep


+ 39 - 0
src/openapi.yaml

@@ -0,0 +1,39 @@
+openapi: 3.1.0
+info:
+  title: Modulplaner OpenAPI
+  version: 1.0.0
+  contact:
+    email: sean@black-burn.ch
+  description: >
+    OpenAPI documentation of the modulplaner API
+  license:
+    name: MPL 2.0
+    url: https://www.mozilla.org/en-US/MPL/2.0/
+
+servers:
+  - url: http://localhost:8080
+    description: localhost
+
+paths:
+  /data/semester-versions.json:
+    $ref: ./paths/semester-versions.yaml
+  /data/modules.json:
+    $ref: ./paths/modules.yaml
+  /data/lecturers.json:
+    $ref: ./paths/lecturers.yaml
+  /data/module-history.json:
+    $ref: ./paths/module-history.yaml
+  /data/changelog.html:
+    $ref: ./paths/changelog-html.yaml
+  /data/{semester}/config.json:
+    $ref: ./paths/{semester}/config.yaml
+  /data/{semester}/changes.json:
+    $ref: ./paths/{semester}/changes.yaml
+  /data/{semester}/blockclasses.json:
+    $ref: ./paths/{semester}/blockclasses.yaml
+  /data/{semester}/{version}/classes.json:
+    $ref: ./paths/{semester}/{version}/classes.yaml
+  /data/{semester}/{version}/config.json:
+    $ref: ./paths/{semester}/{version}/config.yaml
+  /data/{semester}/{version}/klassen.pdf:
+    $ref: ./paths/{semester}/{version}/klassen-pdf.yaml

+ 10 - 0
src/paths/changelog-html.yaml

@@ -0,0 +1,10 @@
+get:
+  operationId: GetHTMLChangelog
+  summary: >-
+    HTML Changelog of the modulplaner frontend
+  security: []
+  tags:
+    - Changelog
+  responses:
+    "200":
+      $ref: ../components/responses/changelog-html-200.yaml

+ 10 - 0
src/paths/lecturers.yaml

@@ -0,0 +1,10 @@
+get:
+  operationId: GetLecturers
+  summary: >-
+    A list of all the lecturers.
+  security: []
+  tags:
+    - Lecturers
+  responses:
+    "200":
+      $ref: ../components/responses/lecturers-200.yaml

+ 10 - 0
src/paths/module-history.yaml

@@ -0,0 +1,10 @@
+get:
+  operationId: GetModuleHistory
+  summary: >-
+    A list of all the lecturers.
+  security: []
+  tags:
+    - Modules
+  responses:
+    "200":
+      $ref: ../components/responses/module-history-200.yaml

+ 10 - 0
src/paths/modules.yaml

@@ -0,0 +1,10 @@
+get:
+  operationId: GetModules
+  summary: >-
+    All available modules and additional information.
+  security: []
+  tags:
+    - Modules
+  responses:
+    "200":
+      $ref: ../components/responses/modules-200.yaml

+ 10 - 0
src/paths/semester-versions.yaml

@@ -0,0 +1,10 @@
+get:
+  operationId: GetSemesterVersions
+  summary: >-
+    Overview of the available semesters and their respective versions of the timetable.
+  security: []
+  tags:
+    - Semesters
+  responses:
+    "200":
+      $ref: ../components/responses/semester-versions-200.yaml

+ 12 - 0
src/paths/{semester}/blockclasses.yaml

@@ -0,0 +1,12 @@
+get:
+  operationId: GetSemesterBlockclasses
+  summary: >-
+    A list of all blockclasses for this semester.
+  security: []
+  tags:
+    - Semester
+  parameters:
+    - $ref: ../../components/parameters/semester.yaml
+  responses:
+    "200":
+      $ref: ../../components/responses/{semester}/blockclasses-200.yaml

+ 12 - 0
src/paths/{semester}/changes.yaml

@@ -0,0 +1,12 @@
+get:
+  operationId: GetSemesterChanges
+  summary: >-
+    A list of all changes between the versions of this semester.
+  security: []
+  tags:
+    - Semester
+  parameters:
+    - $ref: ../../components/parameters/semester.yaml
+  responses:
+    "200":
+      $ref: ../../components/responses/{semester}/changes-200.yaml

+ 12 - 0
src/paths/{semester}/config.yaml

@@ -0,0 +1,12 @@
+get:
+  operationId: GetSemesterConfig
+  summary: >-
+    Configuration / additional information for this semester.
+  security: []
+  tags:
+    - Semester
+  parameters:
+    - $ref: ../../components/parameters/semester.yaml
+  responses:
+    "200":
+      $ref: ../../components/responses/{semester}/semester-config-200.yaml

+ 13 - 0
src/paths/{semester}/{version}/classes.yaml

@@ -0,0 +1,13 @@
+get:
+  operationId: GetSemesterVersionClasses
+  summary: >-
+    A list of all classes for this semester/version.
+  security: []
+  tags:
+    - Semester Version
+  parameters:
+    - $ref: ../../../components/parameters/semester.yaml
+    - $ref: ../../../components/parameters/version.yaml
+  responses:
+    "200":
+      $ref: ../../../components/responses/{semester}/{version}/classes-200.yaml

+ 13 - 0
src/paths/{semester}/{version}/config.yaml

@@ -0,0 +1,13 @@
+get:
+  operationId: GetSemesterVersionConfig
+  summary: >-
+    Configuration/additional information for this semester/version.
+  security: []
+  tags:
+    - Semester Version
+  parameters:
+    - $ref: ../../../components/parameters/semester.yaml
+    - $ref: ../../../components/parameters/version.yaml
+  responses:
+    "200":
+      $ref: ../../../components/responses/{semester}/{version}/semester-version-config-200.yaml

+ 13 - 0
src/paths/{semester}/{version}/klassen-pdf.yaml

@@ -0,0 +1,13 @@
+get:
+  operationId: GetSemesterVersionKlassenPDF
+  summary: >-
+    PDF of the original timetable.
+  security: []
+  tags:
+    - Semester Version
+  parameters:
+    - $ref: ../../../components/parameters/semester.yaml
+    - $ref: ../../../components/parameters/version.yaml
+  responses:
+    "200":
+      $ref: ../../../components/responses/{semester}/{version}/klassen-pdf-200.yaml

+ 8 - 0
src/redocly.yaml

@@ -0,0 +1,8 @@
+# redocly config: https://redocly.com/docs/cli/commands/lint/#custom-configuration-file
+extends:
+  - recommended
+
+rules:
+  # operation-summary: off
+  operation-4xx-response: off
+  no-server-example.com: off