diff --git a/.gitignore b/.gitignore index 64ae7f3..6e00996 100644 --- a/.gitignore +++ b/.gitignore @@ -1,25 +1,163 @@ -# If you prefer the allow list template instead of the deny list, see community template: -# https://github.com/github/gitignore/blob/main/community/Golang/Go.AllowList.gitignore -# -# Binaries for programs and plugins -*.exe -*.exe~ -*.dll +# Byte-compiled / optimized / DLL files +__pycache__/ +*.py[cod] +*$py.class + +# C extensions *.so -*.dylib -# Test binary, built with `go test -c` -*.test +# Distribution / packaging +.Python +build/ +develop-eggs/ +dist/ +downloads/ +eggs/ +.eggs/ +lib/ +lib64/ +parts/ +sdist/ +var/ +wheels/ +share/python-wheels/ +*.egg-info/ +.installed.cfg +*.egg +MANIFEST -# Output of the go coverage tool, specifically when used with LiteIDE -*.out +# PyInstaller +# Usually these files are written by a python script from a template +# before PyInstaller builds the exe, so as to inject date/other infos into it. +*.manifest +*.spec -# Dependency directories (remove the comment below to include it) -# vendor/ +# Installer logs +pip-log.txt +pip-delete-this-directory.txt -# Go workspace file -go.work -go.work.sum +# Unit test / coverage reports +htmlcov/ +.tox/ +.nox/ +.coverage +.coverage.* +.cache +nosetests.xml +coverage.xml +*.cover +*.py,cover +.hypothesis/ +.pytest_cache/ +cover/ -# env file -.env \ No newline at end of file +# Translations +*.mo +*.pot + +# Django stuff: +*.log +local_settings.py +db.sqlite3 +db.sqlite3-journal + +# Flask stuff: +instance/ +.webassets-cache + +# Scrapy stuff: +.scrapy + +# Sphinx documentation +docs/_build/ + +# PyBuilder +.pybuilder/ +target/ + +# Jupyter Notebook +.ipynb_checkpoints + +# IPython +profile_default/ +ipython_config.py + +# pyenv +# For a library or package, you might want to ignore these files since the code is +# intended to run in multiple environments; otherwise, check them in: +# .python-version + +# pipenv +# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. +# However, in case of collaboration, if having platform-specific dependencies or dependencies +# having no cross-platform support, pipenv may install dependencies that don't work, or not +# install all needed dependencies. +#Pipfile.lock + +# poetry +# Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control. +# This is especially recommended for binary packages to ensure reproducibility, and is more +# commonly ignored for libraries. +# https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control +#poetry.lock + +# pdm +# Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control. +#pdm.lock +# pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it +# in version control. +# https://pdm.fming.dev/latest/usage/project/#working-with-version-control +.pdm.toml +.pdm-python +.pdm-build/ + +# PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm +__pypackages__/ + +# Celery stuff +celerybeat-schedule +celerybeat.pid + +# SageMath parsed files +*.sage.py + +# Environments +.env +.venv +env/ +venv/ +ENV/ +env.bak/ +venv.bak/ + +# Spyder project settings +.spyderproject +.spyproject + +# Rope project settings +.ropeproject + +# mkdocs documentation +/site + +# mypy +.mypy_cache/ +.dmypy.json +dmypy.json + +# Pyre type checker +.pyre/ + +# pytype static type analyzer +.pytype/ + +# Cython debug symbols +cython_debug/ + +# PyCharm +# JetBrains specific template is maintained in a separate JetBrains.gitignore that can +# be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore +# and can be added to the global gitignore or merged into this file. For a more nuclear +# option (not recommended) you can uncomment the following to ignore the entire idea folder. +#.idea/ +guestbook.db \ No newline at end of file diff --git a/README.md b/README.md index e8dae65..def8150 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,2 @@ # guestbook - +A guestbook made in Python. \ No newline at end of file diff --git a/app.py b/app.py new file mode 100644 index 0000000..8588257 --- /dev/null +++ b/app.py @@ -0,0 +1,49 @@ +import hashlib, os +import time +from flask import Flask, redirect, render_template, request +import sqlite3 +import re + +app = Flask(__name__) +db = sqlite3.connect('guestbook.db', check_same_thread=False) +cs = db.cursor() +app.secret_key = hashlib.md5(os.urandom(32)).hexdigest() + +@app.template_filter('parsetime') +def parsetime(value): + return time.strftime('%Y-%m-%d %H:%M', time.localtime(value)) + +@app.route('/') +def index(): + statement = 'SELECT "id", "name", "website", "comment", "date", "ip" FROM "entries" ORDER BY id DESC' + cs.execute(statement) + return render_template("index.html", comments=cs.fetchall()) + +@app.route('/submit', methods=["POST"]) +def submit(): + errors = [] + name = request.form.get("name") + website = request.form.get("website") + comment = request.form.get("comment") + if name != "": + if name.isalnum() != True: + errors.append("Your name must not contain any non-alphanumeric characters") + else: + name = "Anonymous" + if website !="": + if not re.fullmatch(r"^[a-zA-Z0-9]+(\.[a-zA-Z0-9]+)*\.[a-zA-Z]{2,3}(\.[a-zA-Z]{2,3})?$", website): + errors.append("Your site doesn't look valid.") + if comment == "": + errors.append("You must write something.") + elif len(comment) > 512: + errors.append("You wrote more than 512 characters") + if errors != []: + response = "" + for error in errors: + response += f"{error}
" + return response + statement = 'INSERT INTO "entries" ("name", "website", "comment", "date", "ip") VALUES (?, ?, ?, ?, ?);' + values = (name, website, comment, int(time.time()), str(request.remote_addr)) + cs.execute(statement, values) + db.commit() + return redirect("/") \ No newline at end of file diff --git a/static/style.css b/static/style.css new file mode 100644 index 0000000..072e489 --- /dev/null +++ b/static/style.css @@ -0,0 +1,46 @@ +body { + background-color: #110e0e; + max-width: 400px; + color: white; + font-family: Verdana,sans-serif; +} + +form { + max-width: 250px; + margin-bottom: 12px; +} + +form input{ + width: 100%; + background-color: #201b1b; + color: white; + border: 2px solid #b41d1d; +} +form textarea { + width: 100%; + height: 100px; + background-color: #201b1b; + color: white; + border: 2px solid #b41d1d; + resize: none; +} +form button { + background-color: #ff4949; + color: white; + border: 2px solid #b41d1d; +} +form button:hover { + background-color: rgb(184, 68, 68); +} +.comment { + background-color: #201b1b; + color: white; + border: 2px solid #b41d1d; + padding: 8px; + margin-bottom: 4px; +} + +a { + color: #ff4949; +} + \ No newline at end of file diff --git a/templates/index.html b/templates/index.html new file mode 100644 index 0000000..ea0431f --- /dev/null +++ b/templates/index.html @@ -0,0 +1,26 @@ + + + + + + guestbook + + + +
+ + + + +
+
+ Sites indexed: {% for comment in comments %}{{comment[2]}} {% endfor %} +
+ {% for comment in comments %} +
+ {{comment[1]}} {{comment[4]|parsetime}}
+ {{comment[3]}} +
+ {% endfor %} + + \ No newline at end of file