Skip to content
This repository was archived by the owner on Feb 24, 2026. It is now read-only.
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
167 commits
Select commit Hold shift + click to select a range
a83880d
Initial commit
iauu Aug 5, 2025
e75c2b2
Test webhook
iauu Aug 5, 2025
ec0bd8f
Update pyproject.toml
iauu Aug 5, 2025
fdcf733
Set author in pyproject.toml
iauu Aug 5, 2025
fc723fe
Update uv.lock and add pylock.toml
iauu Aug 7, 2025
6b5a8a9
Add cmd.md for common command used for development
iauu Aug 7, 2025
90f7b27
Remove samples folder for other package manager
iauu Aug 7, 2025
4901b85
Add new author for new code jam member
iauu Aug 7, 2025
1a22bd6
Add basic setup to include directory to seperate frontend and backend
iauu Aug 8, 2025
2ca59e6
Add pyscript as dependency
iauu Aug 8, 2025
f8d27fc
Add default groups for uv
iauu Aug 8, 2025
5d49a6e
Merge pull request #1 from i-am-unknown-81514525/setup
iauu Aug 8, 2025
6944cee
Update dependency and add crypto module
iauu Aug 8, 2025
20d0caa
Add Ed25519 key generation
iauu Aug 8, 2025
fa2a0ec
Add cryptography itself to also be required dependency
iauu Aug 8, 2025
6f4b885
Optimize the logic
iauu Aug 8, 2025
92bbd83
Fix linting
iauu Aug 8, 2025
f74587f
chore: update doc strings
Harshal6927 Aug 8, 2025
be7857a
Add JWT token generation base on private key
iauu Aug 9, 2025
0ec0509
Reformat and add docstring
iauu Aug 9, 2025
7f922f1
More ruff reformat
iauu Aug 9, 2025
b7c0b8a
Add listening for cookie change from website and redirect
iauu Aug 9, 2025
4c39080
Complete untested captcha_handler
iauu Aug 9, 2025
bb0cf6c
Set require auth cookie to false and delete it after auth
iauu Aug 9, 2025
1d220a5
feat: initial ui
Harshal6927 Aug 9, 2025
e951691
Add captcha script to get challenge
iauu Aug 10, 2025
3356aea
Add create_proxy for get_challenge
iauu Aug 11, 2025
ebc13a5
backend
Harshal6927 Aug 11, 2025
b83e8a4
get endpoint
Harshal6927 Aug 11, 2025
5d8e322
tayvona's error message ui changes
Harshal6927 Aug 11, 2025
4030e51
add submit-challeng endpoint
Harshal6927 Aug 11, 2025
27e495f
connect FE and BE
Harshal6927 Aug 12, 2025
3da4ca2
fix import bug
Harshal6927 Aug 12, 2025
2c280de
update jwt token generation
Harshal6927 Aug 12, 2025
153a407
Update README.md
Harshal6927 Aug 12, 2025
1dab1ae
Merge pull request #13 from i-am-unknown-81514525/harshal-main
Harshal6927 Aug 12, 2025
fa6ab6d
Change .venv script for mac/linux
DragonSenseiGuy Aug 12, 2025
0b5a9d8
Add linter
DragonSenseiGuy Aug 12, 2025
f4071fd
Add . and source to README
DragonSenseiGuy Aug 12, 2025
a7f37bf
Remove Linter
DragonSenseiGuy Aug 12, 2025
f6705c3
Make venv activate runnable by itself
DragonSenseiGuy Aug 12, 2025
0dfd771
Merge pull request #14 from i-am-unknown-81514525/dragon-edits
DragonSenseiGuy Aug 12, 2025
e76ff4a
Add function for js part to submit results
iauu Aug 11, 2025
bc3414a
Fix endpoint name on script
iauu Aug 11, 2025
8d79a9b
Add runner.js to run the user python code
iauu Aug 11, 2025
38ee9e1
Add code to handle the execution in python
iauu Aug 11, 2025
1ef5aaa
Add panel
iauu Aug 12, 2025
3599596
Attempt to add UI with panel
iauu Aug 12, 2025
d96ab48
Basic functional?
iauu Aug 12, 2025
5bb8e36
Add script integrity check
iauu Aug 13, 2025
03ea81d
Update redirect location
iauu Aug 13, 2025
f591ca5
Fix linting
iauu Aug 13, 2025
8222b65
Fix missing on_click handler for submit button
iauu Aug 13, 2025
273ed01
Add fix
iauu Aug 13, 2025
a4ef228
chore: fix captcha.py
Harshal6927 Aug 13, 2025
bf4b87d
Fox GetChallengeResponse schema
iauu Aug 13, 2025
c9cbe61
Folder restructure
iauu Aug 13, 2025
73c7f16
Revert server.backend -> server.demo change as requested
iauu Aug 13, 2025
ff06ed2
Merge pull request #18 from i-am-unknown-81514525/restructure
Harshal6927 Aug 13, 2025
768e7cb
Add
DragonSenseiGuy Aug 13, 2025
7abcdd0
Put it in static path
iauu Aug 13, 2025
93008f1
Update README.md
iauu Aug 13, 2025
c67408c
Fix worker using absolute path causing error
iauu Aug 13, 2025
ee13da6
Use consistent port between litestar and uvicorn
iauu Aug 13, 2025
873e4b3
Remove requirement of API base url
iauu Aug 13, 2025
2bc26d2
Merge pull request #19 from i-am-unknown-81514525/dragon
DragonSenseiGuy Aug 14, 2025
ad298df
Add captcha_handler alternative in js for fast loading
iauu Aug 13, 2025
cd8de15
Basic docker setup
iauu Aug 14, 2025
c3096ac
Fix docker building
iauu Aug 14, 2025
1e26642
Add file serving to demo frontend
iauu Aug 14, 2025
8132b69
Add captcha_handler.py to index.html with micropython
iauu Aug 14, 2025
907c386
fix static files
Harshal6927 Aug 14, 2025
9e211bd
Add build step for domain variation
iauu Aug 14, 2025
920f42f
Rewrite demo index.html, app.js and add API route on demo server to g…
iauu Aug 14, 2025
17291a9
Fix linting
iauu Aug 14, 2025
a075895
Fix typo in README.md
iauu Aug 15, 2025
88d065d
Add question set json
iauu Aug 15, 2025
fdfaffa
Add example question set
iauu Aug 15, 2025
e1084d7
Add more example questions
iauu Aug 15, 2025
2d1a7b1
Somemore idea
iauu Aug 15, 2025
060a954
Add more item for sentence constructor
iauu Aug 15, 2025
5d14cbb
Add more sentence structure
iauu Aug 15, 2025
115dd27
Use sympy for prime calculation instead
iauu Aug 15, 2025
cec0bc2
Add question for fib
iauu Aug 15, 2025
54aa1ec
Limit amount of fibonacci number calculate
iauu Aug 15, 2025
df86d8a
added more values to question set
Ununennium817 Aug 15, 2025
40a0169
Rename continue -> cont
iauu Aug 15, 2025
9f6af68
Add schema
iauu Aug 15, 2025
83de618
Minor update on small issue
iauu Aug 15, 2025
8e79fed
added even more values
Ununennium817 Aug 15, 2025
4ff1303
Update question set
iauu Aug 15, 2025
1b51a2f
Increase question range
iauu Aug 15, 2025
8897909
Update question set
iauu Aug 15, 2025
f407954
Add parser
iauu Aug 15, 2025
26b9959
Make sure base is at the start
iauu Aug 15, 2025
1077de3
Add docstring
iauu Aug 15, 2025
c4a3ac7
Rename to in python
iauu Aug 15, 2025
55702df
Update schema and add key and question state in captcha app state
iauu Aug 15, 2025
857d0db
Add question generation
iauu Aug 15, 2025
1116c47
Fix linting
iauu Aug 15, 2025
03f3c00
Add on_startup
iauu Aug 15, 2025
13ff599
small fixes
Harshal6927 Aug 15, 2025
c7e00aa
small fixes
Harshal6927 Aug 15, 2025
9657526
small fixes
Harshal6927 Aug 15, 2025
446dd2f
Add captcha reset js
iauu Aug 15, 2025
0d70829
Add public key endpoint that the server get on login
iauu Aug 15, 2025
b195f78
Add a validator
iauu Aug 16, 2025
36f8849
add login for website
Harshal6927 Aug 16, 2025
ce61e9b
update func names
Harshal6927 Aug 16, 2025
b9a9731
update readme
Harshal6927 Aug 16, 2025
f8b5c5f
update models
Harshal6927 Aug 16, 2025
7233c5b
website login (#23)
iauu Aug 17, 2025
9fd855f
Attempt to update UI
iauu Aug 16, 2025
aee936e
Fix import issue
iauu Aug 16, 2025
d195fe1
Idk why it need this commit but sure
iauu Aug 16, 2025
2c80e7b
Add logging for error
iauu Aug 16, 2025
58554ab
Add health checking
iauu Aug 16, 2025
f391274
Add timeout for question and strip problematic questions
iauu Aug 16, 2025
3a68114
Add back fib with smaller range and test for <4300 digit
iauu Aug 16, 2025
ee3ef68
Fix lintint
iauu Aug 16, 2025
22e0f27
Add curl in container
iauu Aug 16, 2025
70ef366
Fix mobile compatibility
iauu Aug 16, 2025
a0eb8c3
Fix type issue
iauu Aug 17, 2025
f33106d
Change JWT issuer to client-discoverable endpoint instead
iauu Aug 17, 2025
7530af2
Fix linter and typo
iauu Aug 17, 2025
ee7979f
Add gitignore to test.py
iauu Aug 17, 2025
31156e7
Update so challenge_id can only be used once, whether success on not
iauu Aug 17, 2025
58d94b5
Return apporiate status code for invalid JWT
iauu Aug 17, 2025
cb4caff
Add more error handling for runner.js
iauu Aug 17, 2025
b8c5a42
Update .gitignore
iauu Aug 17, 2025
f1885e6
Some fixes
iauu Aug 17, 2025
414fa2c
Apparently just this
iauu Aug 17, 2025
ec09b5c
Improve question phrasing
iauu Aug 17, 2025
980fb1e
Improve progress bar UI
iauu Aug 17, 2025
af5c677
Fix linting
iauu Aug 17, 2025
e79c2e2
Fix local var error
iauu Aug 17, 2025
1fc3405
Add better traceback for the user
iauu Aug 17, 2025
781ccf7
Revert ignore on 2 server data folder
iauu Aug 17, 2025
f65f4ed
Update captcha.py to accomodate images
fiwam Aug 16, 2025
384b0c1
Update challenge.py
fiwam Aug 16, 2025
9b8fd20
Update captcha.py
fiwam Aug 16, 2025
85442b1
Update challenge.py
fiwam Aug 16, 2025
cb29acd
Fix some part
iauu Aug 17, 2025
250750d
Change to use image
iauu Aug 17, 2025
506eb38
Update width and height settings
iauu Aug 17, 2025
59a8b87
Implement and link image together
iauu Aug 17, 2025
a22260f
Add /logout and /me endpoint
Harshal6927 Aug 17, 2025
59ffacf
Fix JWT prevent static resource load and JWT actually work now
iauu Aug 18, 2025
d5d9a75
use proper auth
Harshal6927 Aug 18, 2025
7cd3f1a
Remove timeout execution
iauu Aug 18, 2025
f408b07
Remove unused multiprocessing, os import
iauu Aug 18, 2025
ab21daa
Fix on http context and Host header missing protocol
iauu Aug 18, 2025
6b3007b
Use consistent local IP
iauu Aug 18, 2025
c8e57e1
Fix /api/auth/me endpoint
iauu Aug 18, 2025
39efae5
Fix inconsistent login button color
iauu Aug 18, 2025
e8f5cd9
Improve phrasing for some question
iauu Aug 18, 2025
876301f
Add font and remove the image write
iauu Aug 18, 2025
a1085de
Fix linting
iauu Aug 18, 2025
427d905
Remove debug file
iauu Aug 18, 2025
31416c1
Fix other pre-commit check
iauu Aug 18, 2025
ae0f53e
Fix inconsistent IP on .env.example
iauu Aug 18, 2025
bf26c13
Use consistent IP
iauu Aug 18, 2025
b2f806e
Change Size of iframe
DragonSenseiGuy Aug 18, 2025
e2a825b
Merge pull request #27 from i-am-unknown-81514525/dragon
DragonSenseiGuy Aug 18, 2025
7ae13b2
Add updated README.md with a video demo
iauu Aug 22, 2025
545d1ec
Remove Gemini Key and Change Spelling error
DragonSenseiGuy Aug 22, 2025
9cea873
Add 'peppy-poppies/' from commit '545d1ecbbe51f1df20adf1c1df159ef0e0e…
janine9vn Sep 13, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions peppy-poppies/.env.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# Secret key used for the demo server to generate JWT for login session. CAPTCHA server don't use this
SECRET_KEY=super-secret-key

# Change if needed (if you follow the instructions in the README, you don't need to change this)
KEY_PATH=./captcha_data # You can add your public/private key with `public.pem` and `private.pem` key. They must be pair of Ed25519 key
CODECAPTCHA_DOMAIN=http://127.0.0.1:8001

FONT_PATH=./captcha_data/JetBrainsMono-Regular.ttf # You can edit to a different font and edit this, the provide font use OFL license, included alongside the font
# OFL font is compatible with MIT

# ======================== Docker only ========================
# This is used for without domain as the service might not be discoverable in the same way. Use http://captcha:8001 in docker
CODECAPTCHA_DOMAIN_INTERNAL=
35 changes: 35 additions & 0 deletions peppy-poppies/.github/workflows/lint.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
# GitHub Action workflow enforcing our code style.

name: Lint

# Trigger the workflow on both push (to the main repository, on the main branch)
# and pull requests (against the main repository, but from any repo, from any branch).
on:
push:
branches:
- main
pull_request:

# Brand new concurrency setting! This ensures that not more than one run can be triggered for the same commit.
# It is useful for pull requests coming from the main repository since both triggers will match.
concurrency: lint-${{ github.sha }}

jobs:
lint:
runs-on: ubuntu-latest

env:
# The Python version your project uses. Feel free to change this if required.
PYTHON_VERSION: "3.12"

steps:
- name: Checkout repository
uses: actions/checkout@v4

- name: Set up Python ${{ env.PYTHON_VERSION }}
uses: actions/setup-python@v5
with:
python-version: ${{ env.PYTHON_VERSION }}

- name: Run pre-commit hooks
uses: pre-commit/action@v3.0.1
36 changes: 36 additions & 0 deletions peppy-poppies/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
# Files generated by the interpreter
__pycache__/
*.py[cod]

# Environment specific
.venv
venv
.env
env

# Unittest reports
.coverage*

# Logs
*.log

# PyEnv version selector
.python-version

# Built objects
*.so
dist/
build/

# IDEs
# PyCharm
.idea/
# VSCode
.vscode/
# MacOS
.DS_Store

*.pem
*.sqlite
!captcha_data/question_set.json
test.py
18 changes: 18 additions & 0 deletions peppy-poppies/.pre-commit-config.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# Pre-commit configuration.
# See https://github.com/python-discord/code-jam-template/tree/main#pre-commit-run-linting-before-committing

repos:
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v5.0.0
hooks:
- id: check-toml
- id: check-yaml
- id: end-of-file-fixer
- id: trailing-whitespace
args: [--markdown-linebreak-ext=md]

- repo: https://github.com/astral-sh/ruff-pre-commit
rev: v0.12.2
hooks:
- id: ruff-check
- id: ruff-format
7 changes: 7 additions & 0 deletions peppy-poppies/LICENSE.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
Copyright 2021 Python Discord

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
198 changes: 198 additions & 0 deletions peppy-poppies/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,198 @@
# CodeCaptcha
A CAPTCHA system where the user writes python code to solve a given question.

A normal example:

![Example question](docs-assets/16768e08d0bf01f942995f0077ef5e6718aba3298c7b609dd98cf3825fa0db0a.png)

<details>
<summary>Chaotic example (Note that it is very long):</summary>

This question has 100 steps and ~~AI has failed to solve this :)~~ (I used the wrong model in the original test with Google Gemini 2.5 Flash, and Gemini 2.5 Pro was able to solve this with 13,857 tokens)

![Example question](docs-assets/de19ebabd51028f36f7ee03dbe4365b54726181300998b3bf1fd3954a17966e1.png)

<details>
<summary>Spoiler: Test input</summary>

```py
[16386, 19874, 48296, 41718, 58488, 42810, 58044]
```

</details>

<details>
<summary>Spoiler: Test output</summary>

```py
[24, 24, 24, 24, 24, 24, 24]
```

Could you have possibly guessed the result looks like this? I certainly didn't

> Side note: The reason I figured out afterward is that each step in the question is deterministic (a given input would always give the same output for the same step), and many steps in the `question_set.json` have a many-to-one relationship, therefore, when there are a lot of steps (in this case: 100), it is very likely that all the inputs produce the exact same result.

</details>

</details>

## How to Run the project with the demo
<details>
<summary>Run with docker (recommended)</summary>

Prerequisites: Have [docker](https://docs.docker.com/engine/install/) installed with `docker compose`

### Step 1: Setup `.env`

In contrast to running without docker, `.env` setup is necessary for running in docker, It would fail if the following environment variables are not set.

- `CODECAPTCHA_DOMAIN` to `http://127.0.0.1:9201`
- It can be changed depending on the configuration in `docker-compose.yml`. This environment variable is the domain in which the **client** accesses the CAPTCHA server
- `CODECAPTCHA_DOMAIN_INTERNAL` to `http://captcha:8001`
- If the CAPTCHA endpoint is from `CODECAPTCHA_DOMAIN` it can be accessible inside the docker container (such as a publicly accessible domain), then this environment variable is not needed

Other configurations can be changed, according to the documentation in `.env.example`. The default values should work for them.

### Step 2: Run the project
```bash
docker compose up -d --build
```
The [demo site](http://127.0.0.1:9200) and the [captcha site](http://127.0.0.1:9201) can be accessed from http://127.0.0.1:9200 and http://127.0.0.1:9201 respectively
</details>
<details>
<summary>Run without docker</summary>

Prerequisites: Have [uv](https://docs.astral.sh/uv/getting-started/installation/) and `python3.12` installed

### Step 1: Setup `.venv`
```bash
uv sync
```

### Step 2: Setup `.env`
By default, the project can be run without creating or setting up `.env`, however, you might want to change some configurations. Check `.env.example` for information to configurate `.env`.

Note: If you changed the `.env` file, or any other files in `frontend/`, you must set the project up from the next step again.

### Step 3: Run the build script
```bash
uv run build.py
```
This configures the frontend code to create a set of files in `dist/` which link the demo assets to the CAPTCHA server endpoint defined in `CODECAPTCHA_DOMAIN`

### Step 4: Run the project
Run in 2 seperate terminals
```bash
# This must be run first
uv run litestar --app server.captcha.main:app run --port 8001 --reload
# Run the following about 5 to 10 seconds later in the other terminal
uv run litestar --app server.backend.main:app run --port 8000 --reload
```
`--host 0.0.0.0` can be added on either command if it need to be accessible from other IP

The [demo site](http://127.0.0.1:8000) and the [captcha site](http://127.0.0.1:8001) can be accessed from http://127.0.0.1:8000 and http://127.0.0.1:8001 respectively
</details>

## Short video demo
![Demo](docs-assets/Presentation.gif)

## Why is it wrong?

Have you ever seen a meme like this?

<img width="446" height="271" alt="image" src="https://github.com/user-attachments/assets/df3c995c-4ced-43de-82a0-16d0de28a628" />

> Mark Rushakoff Sep 19, 2009 from StackOverflow, Answer to "alternative captcha methods", https://stackoverflow.com/a/1448684 CC-BY-SA 2.5. The original source that the author mentioned is no longer available

One that is overcomplicated and no one can solve them? We done something similar, but for coding! You have to write the code to solve very specific problems that have no practical usage, and hopefully it's fun?

### Other reasons it is wrong
- It is written in python - which makes it really slow (This is why it takes 5-6 seconds to load) and in addition to the complex UI framework used on the CAPTCHA UI for features such as the code editor, it would freeze my tab for about 10s and about 30s to load (hopefully that doesn't happen on yours), and it downloads about 50MiB of packages before it can be run.
- Statistically LLMs have higher success rates to solve these problems than a human can, without help from LLMs or other people (considering most of the population in the world cannot write python code by themselves).
- LLMs are not trained to avoid solving these questions, unlike conventional CAPTCHAs, which makes them potentially have a higher chance of success than normal CAPTCHAs.
- The server also needed high computational effort to know and validate the answer, unlike normal CAPTCHA which the question is generated from answers.

## Project structure

- `server/captcha` - The CAPTCHA server, written with Litestar that is responsible for generating images and creating the questions.
- `server/backend` - A basic demo server written with Litestar that handles the theoretical login system that is gated with CAPTCHA.
- `frontend/captcha` - Contains the static assets for the CAPTCHA server.
<details>
<summary>Disclosure</summary>

`frontend/captcha/parse.py` is a patch for micropython as it didn't bundle the `urllib.parse` stdlib. The file contains `urllib.parse` and `ipaddress` standard libraries from [cpython](https://github.com/python/cpython) and a patch for some other feature that isn't available in micropython such as `str.isascii` and "too complex" regex which is used by the original code from the standard library, which replaces with equivialent behaviour.

</details>
- `frontend/demo` - A demo login page for testing
- `crypto` - A module that both CAPTCHA server and demo server use to generate/handle public private key pair, and to generate and validate the JWT(JSON Web Token) using the Ed25519 key.
- `captcha_data` - Contains a font file and the a question set
<details>
<summary>Disclosure</summary>

- `captcha_data/JetBrainsMono-Regular.ttf` is a font created by JetBrains, and licensed under SIL Open Font License, Version 1.1 (OFL). The license text is inclued in `captcha_data/OFL.txt` as required by the license. The font is included for the purpose to run the project with minimal setup, and any other font can be used. The OFL license is compatible with MIT license according to [FOSSA](https://fossa.com/blog/open-source-licenses-101-sil-open-font-license-ofl/)
- `captcha_data/question_set.json` is created with a combination of manual effort and AI generation. Approximately 2 million questions are generated during testing, with only 1 exceeding the execution timeout of 0.5s during testing when calculating a prime number, which likely originated from saturated resource usage from other tasks running on the test device. However, some question descriptions might not match the checking criteria (with 1 known case found after the deadline)

</details>
- `build.py` A build script which puts all the files from `frontend/` to `dist/` and replaces `[domain]` in specific files to the domain defined by the environment variable `CODECAPTCHA_DOMAIN` so the client can connect to the correct CAPTCHA servers specified in the static file. This is only needed for the demo server, but for consistency, the CAPTCHA server will also use it.

## Contribution list
<details>
<summary>harshal6927 (@Harshal6927)</summary>

- Demo server
- CAPTCHA server
- Demo page UI
- Demo login system on the backend
- Setup SQLite database for the servers
</details>
<details>
<summary>deleted.user0 (@i-am-unknown-81514525)</summary>

- CAPTCHA UI
- CAPTCHA frontend
- Adding login system on the demo frontend
- JWT generation and validation, Ed25519 key generation and handling
- Question generator parser
- Writing question set
- Update image generation
- Write the final `README.md`
</details>
<details>
<summary>ununenium817 (@Ununenium817)</summary>

- Help writing the CAPTCHA server that was replaced
- Writing question set
- Construct system prompt and code to generate part of question set
</details>
<details>
<summary>wrybyte (@tayvona)</summary>

- Minor UI improvement on demo page
</details>
<details>
<summary>fiwam (@fiwam)</summary>

- Update CAPTCHA frontend to handle image
- Convert the question generated to send image instead of text to client
</details>
<details>
<summary>dragonsenseiguy (@DragonSenseiGuy)</summary>

- Attempt to write the CAPTCHA server that was replaced
- Minor UI improvement for the CAPTCHA frame for usability
- Wrote JWT Validator but was scrapped(due to issues).
- Attempt to write the login system for demo server that didn't get merged.
- Update various part of `README.md`
</details>

## Framework choice

The project used a combination of Pyscript and Pyodide from the approved frameworks, with some HTML/js/css when necessary in the CAPTCHA files.
- Pyscript is used in `frontend/captcha/captcha.py` and `frontend/captcha/captcha_handler.py` to handle the communication between 2 sites to exchange the JWT token.
- Pyodide is used to run user code in isolation in `frontend/captcha/runner.js`

Other framework:
- [Panel](https://panel.holoviz.org/) is used as a frontend framework with pyscript as a CAPTCHA UI, defined in `frontend/captcha/captcha.py`.
- [Litestar](https://litestar.dev/) is used as backend framework for both the CAPTCHA server and DEMO server in `server/`.
- [pyjwt](https://pyjwt.readthedocs.io/) and [cryptography](https://cryptography.io/) is used for Ed25519 key handling, JWT creation and validation in `crypto/`.
- [Pillow](https://pillow.readthedocs.io/en/stable/) is used to generate image of question that is sent to the client.
35 changes: 35 additions & 0 deletions peppy-poppies/build.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
from os import getenv
from pathlib import Path
from shutil import copytree, rmtree

try:
from dotenv import load_dotenv

load_dotenv(override=True)
except ImportError:
pass
Comment on lines +5 to +10

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should this raise some sort of warning if the .env file isn't able to be loaded? If this is intended to be development only, should there be some sort of flag to read/set?


rmtree(Path("./dist"), ignore_errors=True) # remove the folder whether exist or not
copytree(Path("./frontend"), "./dist/frontend")

index_html_path: Path = Path("./dist") / "frontend" / "demo" / "index.html"

if index_html_path.exists():
with index_html_path.open("r", encoding="utf-8") as fp:
content = fp.read()

content = content.replace("[domain]", getenv("CODECAPTCHA_DOMAIN", "http://127.0.0.1:8001"))

with index_html_path.open("w", encoding="utf-8") as fp:
fp.write(content)

app_js_path: Path = Path("./dist") / "frontend" / "demo" / "app.js"

if app_js_path.exists():
with app_js_path.open("r", encoding="utf-8") as fp:
content = fp.read()

content = content.replace("[domain]", getenv("CODECAPTCHA_DOMAIN", "http://127.0.0.1:8001"))

with app_js_path.open("w", encoding="utf-8") as fp:
fp.write(content)
32 changes: 32 additions & 0 deletions peppy-poppies/captcha.Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
FROM python:3.12-slim-bookworm

COPY --from=ghcr.io/astral-sh/uv:latest /uv /uvx /bin/

RUN apt-get update && apt-get -y install curl

# Sync the project into a new environment, asserting the lockfile is up to date
WORKDIR /app
ENV UV_LINK_MODE=copy

RUN --mount=type=cache,target=/root/.cache/uv \
--mount=type=bind,source=uv.lock,target=uv.lock \
--mount=type=bind,source=pyproject.toml,target=pyproject.toml \
uv sync --locked --only-group backend --only-group math --compile-bytecode --no-install-project

ADD pyproject.toml /app
ADD uv.lock /app
ADD server/captcha /app/server/captcha
ADD frontend/captcha /app/frontend/captcha
ADD crypto /app/crypto

RUN --mount=type=cache,target=/root/.cache/uv \
uv sync --locked --only-group backend --only-group math --compile-bytecode

ADD build.py /app
ARG CODECAPTCHA_DOMAIN
ENV CODECAPTCHA_DOMAIN=$CODECAPTCHA_DOMAIN
RUN ["uv", "run", "--no-sync", "python3", "build.py"]

VOLUME ["/app/captcha_data"]

CMD ["uv", "run", "--no-sync", "litestar", "--app", "server.captcha.main:app", "run", "--port", "8001", "--host", "0.0.0.0"]
Empty file.
Binary file not shown.
Loading