mirror of
https://git.ari.lt/ari.lt/ari.lt.git
synced 2025-02-04 17:49:24 +01:00
Improve index, add badges
Signed-off-by: Ari Archer <ari@ari.lt>
This commit is contained in:
parent
eb044272e0
commit
c515f24ab5
14 changed files with 426 additions and 65 deletions
BIN
captcha.key
Normal file
BIN
captcha.key
Normal file
Binary file not shown.
|
@ -1,3 +1,5 @@
|
||||||
flask
|
flask
|
||||||
types-flask
|
types-flask
|
||||||
flask-sqlalchemy
|
flask-sqlalchemy
|
||||||
|
flask-ishuman
|
||||||
|
crc4
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
"""ari.lt"""
|
"""ari.lt"""
|
||||||
|
|
||||||
import datetime
|
import datetime
|
||||||
|
import hashlib
|
||||||
import os
|
import os
|
||||||
import sys
|
import sys
|
||||||
from typing import Any
|
from typing import Any
|
||||||
|
@ -23,6 +24,8 @@ def create_app(name: str) -> flask.Flask:
|
||||||
app.config["PREFERRED_URL_SCHEME"] = "http" if app.debug else "https"
|
app.config["PREFERRED_URL_SCHEME"] = "http" if app.debug else "https"
|
||||||
app.config["DOMAIN"] = "ari.lt"
|
app.config["DOMAIN"] = "ari.lt"
|
||||||
|
|
||||||
|
app.config["SECRET_KEY"] = os.urandom(4096)
|
||||||
|
|
||||||
app.config["SESSION_COOKIE_SAMESITE"] = "strict"
|
app.config["SESSION_COOKIE_SAMESITE"] = "strict"
|
||||||
app.config["SESSION_COOKIE_SECURE"] = True
|
app.config["SESSION_COOKIE_SECURE"] = True
|
||||||
app.config["SESSION_COOKIE_HTTPONLY"] = True
|
app.config["SESSION_COOKIE_HTTPONLY"] = True
|
||||||
|
@ -31,12 +34,35 @@ def create_app(name: str) -> flask.Flask:
|
||||||
app.config["SQLALCHEMY_ENGINE_OPTIONS"] = {"pool_pre_ping": True}
|
app.config["SQLALCHEMY_ENGINE_OPTIONS"] = {"pool_pre_ping": True}
|
||||||
app.config["SQLALCHEMY_TRACK_MODIFICATIONS"] = False
|
app.config["SQLALCHEMY_TRACK_MODIFICATIONS"] = False
|
||||||
|
|
||||||
|
app.config["CAPTCHA_PEPPER_FILE"] = "captcha.key"
|
||||||
|
app.config["CAPTCHA_EXPIRY"] = 60 * 10 # 10 minutes
|
||||||
|
app.config["CAPTCHA_CHARSET"] = "abdefghmnqrtyABDEFGHLMNRTY2345689#@%?!"
|
||||||
|
app.config["CAPTCHA_RANGE"] = (4, 6)
|
||||||
|
|
||||||
app.config["USE_SESSION_FOR_NEXT"] = True
|
app.config["USE_SESSION_FOR_NEXT"] = True
|
||||||
|
|
||||||
|
from .models import Admin, db
|
||||||
|
|
||||||
|
with app.app_context():
|
||||||
|
db.init_app(app)
|
||||||
|
db.create_all()
|
||||||
|
|
||||||
|
# if db.session.query(Admin).count() < 1:
|
||||||
|
# print("Creating an admin account...")
|
||||||
|
|
||||||
|
# full_name: str = input("Full name: ")
|
||||||
|
# email: str = input("Email: ")
|
||||||
|
# salt: bytes = os.urandom(64)
|
||||||
|
# pwhash: bytes = hashlib.sha3_512(salt + input("Password: ")).digest()
|
||||||
|
|
||||||
from .views import views
|
from .views import views
|
||||||
|
|
||||||
app.register_blueprint(views, url_prefix="/")
|
app.register_blueprint(views, url_prefix="/")
|
||||||
|
|
||||||
|
from .c import c
|
||||||
|
|
||||||
|
c.init_app(app)
|
||||||
|
|
||||||
@app.context_processor # type: ignore
|
@app.context_processor # type: ignore
|
||||||
def _() -> Any:
|
def _() -> Any:
|
||||||
"""Context processor"""
|
"""Context processor"""
|
||||||
|
|
7
src/aw/c.py
Normal file
7
src/aw/c.py
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
#!/usr/bin/env python3
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
"""Captcha"""
|
||||||
|
|
||||||
|
import flask_ishuman
|
||||||
|
|
||||||
|
c: flask_ishuman.IsHuman = flask_ishuman.IsHuman()
|
|
@ -5,3 +5,10 @@
|
||||||
from typing import Final
|
from typing import Final
|
||||||
|
|
||||||
HUGEINT_MAX: Final[int] = (10**65) - 1
|
HUGEINT_MAX: Final[int] = (10**65) - 1
|
||||||
|
|
||||||
|
USERNAME_SIZE: Final[int] = 64
|
||||||
|
|
||||||
|
NAME_SIZE: Final[int] = 256
|
||||||
|
WEBSITE_SIZE: Final[int] = 256
|
||||||
|
EMAIL_CT_SIZE: Final[int] = 256
|
||||||
|
COMMENT_SIZE: Final[int] = 1024
|
||||||
|
|
|
@ -2,15 +2,20 @@
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
"""DB Models"""
|
"""DB Models"""
|
||||||
|
|
||||||
|
import datetime
|
||||||
|
import string
|
||||||
import typing as t
|
import typing as t
|
||||||
from decimal import Decimal
|
from decimal import Decimal
|
||||||
|
from secrets import SystemRandom
|
||||||
|
|
||||||
|
import crc4
|
||||||
from flask_sqlalchemy import SQLAlchemy
|
from flask_sqlalchemy import SQLAlchemy
|
||||||
from sqlalchemy import DECIMAL, Dialect, TypeDecorator
|
from sqlalchemy import DECIMAL, DateTime, Dialect, TypeDecorator, Unicode
|
||||||
|
|
||||||
from . import const
|
from . import const
|
||||||
|
|
||||||
db: SQLAlchemy = SQLAlchemy()
|
db: SQLAlchemy = SQLAlchemy()
|
||||||
|
rand: SystemRandom = SystemRandom()
|
||||||
|
|
||||||
|
|
||||||
class HugeUInt(TypeDecorator): # type: ignore
|
class HugeUInt(TypeDecorator): # type: ignore
|
||||||
|
@ -54,7 +59,55 @@ class Counter(db.Model):
|
||||||
|
|
||||||
id: int = db.Column(
|
id: int = db.Column(
|
||||||
db.Integer,
|
db.Integer,
|
||||||
primary_key=True,
|
|
||||||
unique=True,
|
unique=True,
|
||||||
|
primary_key=True,
|
||||||
)
|
)
|
||||||
count: int = db.Column(HugeUInt())
|
count: int = db.Column(HugeUInt())
|
||||||
|
|
||||||
|
def __init__(self, count: int = 0) -> None:
|
||||||
|
assert count >= 0 and count <= const.HUGEINT_MAX, "count out of range"
|
||||||
|
self.count: int = count
|
||||||
|
|
||||||
|
|
||||||
|
class Comment(db.Model):
|
||||||
|
"""Comment"""
|
||||||
|
|
||||||
|
id: int = db.Column(
|
||||||
|
db.Integer,
|
||||||
|
unique=True,
|
||||||
|
primary_key=True,
|
||||||
|
)
|
||||||
|
|
||||||
|
name: str = db.Column(Unicode(const.NAME_SIZE))
|
||||||
|
website: t.Optional[str] = db.Column(db.String(const.WEBSITE_SIZE), nullable=True)
|
||||||
|
|
||||||
|
email_ct: bytes = db.Column(db.LargeBinary(length=const.EMAIL_CT_SIZE))
|
||||||
|
key: bytes = db.Column(db.LargeBinary(length=32))
|
||||||
|
|
||||||
|
comment: str = db.Column(Unicode(const.COMMENT_SIZE))
|
||||||
|
confirmed: bool = db.Column(db.Boolean, default=False)
|
||||||
|
posted: datetime.datetime = db.Column(DateTime, nullable=False)
|
||||||
|
|
||||||
|
token: str = db.Column(db.String(32))
|
||||||
|
|
||||||
|
def __init__(
|
||||||
|
self, name: str, website: t.Optional[str], email: str, comment: str
|
||||||
|
) -> None:
|
||||||
|
assert len(name) <= const.NAME_SIZE, "Name too long"
|
||||||
|
assert len(website or "") <= const.WEBSITE_SIZE, "Website too long"
|
||||||
|
assert len(email) <= const.EMAIL_CT_SIZE, "Email too long"
|
||||||
|
assert len(comment) <= const.COMMENT_SIZE, "Comment too long"
|
||||||
|
|
||||||
|
self.name: str = name
|
||||||
|
self.website: t.Optional[str] = website
|
||||||
|
|
||||||
|
self.key: bytes = rand.randbytes(32)
|
||||||
|
self.email_ct: bytes = crc4.rc4(self.email.encode(), self.key) # type: ignore
|
||||||
|
|
||||||
|
self.comment: str = comment
|
||||||
|
self.confirmed: bool = False
|
||||||
|
self.posted: datetime.datetime = datetime.datetime.now(datetime.timezone.utc)
|
||||||
|
|
||||||
|
self.token: str = "".join(
|
||||||
|
rand.choices(string.ascii_letters + string.digits, k=32)
|
||||||
|
)
|
||||||
|
|
|
@ -8,6 +8,7 @@ import flask
|
||||||
from werkzeug.wrappers import Response
|
from werkzeug.wrappers import Response
|
||||||
|
|
||||||
from .routing import Bp
|
from .routing import Bp
|
||||||
|
from .c import c
|
||||||
|
|
||||||
views: Bp = Bp("views", __name__)
|
views: Bp = Bp("views", __name__)
|
||||||
|
|
||||||
|
@ -55,6 +56,14 @@ def license() -> flask.Response:
|
||||||
with open("LICENSE", "r") as fp:
|
with open("LICENSE", "r") as fp:
|
||||||
return flask.Response(fp.read(), mimetype="text/plain")
|
return flask.Response(fp.read(), mimetype="text/plain")
|
||||||
|
|
||||||
|
@views.post("/")
|
||||||
|
def comment() -> flask.Response:
|
||||||
|
"""publish a comment"""
|
||||||
|
return flask.Response(
|
||||||
|
c.new().rawpng(),
|
||||||
|
mimetype="image/png"
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
@views.get("/git", defaults={"_": ""})
|
@views.get("/git", defaults={"_": ""})
|
||||||
@views.get("/git/", defaults={"_": ""})
|
@views.get("/git/", defaults={"_": ""})
|
||||||
|
@ -77,3 +86,33 @@ def favicon() -> Response:
|
||||||
mimetype="image/vnd.microsoft.icon",
|
mimetype="image/vnd.microsoft.icon",
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@views.get("/captcha.png")
|
||||||
|
def captcha() -> flask.Response:
|
||||||
|
"""CAPTCHA"""
|
||||||
|
return flask.Response(
|
||||||
|
c.new().rawpng(),
|
||||||
|
mimetype="image/png"
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@views.get("/badge.png")
|
||||||
|
def badge() -> Response:
|
||||||
|
"""Website badge"""
|
||||||
|
return flask.redirect(
|
||||||
|
flask.url_for(
|
||||||
|
"static",
|
||||||
|
filename="badges/badge.png",
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@views.get("/badge-yellow.png")
|
||||||
|
def badge_yellow() -> Response:
|
||||||
|
"""Website badge (yellow)"""
|
||||||
|
return flask.redirect(
|
||||||
|
flask.url_for(
|
||||||
|
"static",
|
||||||
|
filename="badges/badge-yellow.png",
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
BIN
src/static/badges/badge-yellow.png
Normal file
BIN
src/static/badges/badge-yellow.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 883 B |
BIN
src/static/badges/badge.png
Normal file
BIN
src/static/badges/badge.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 2.7 KiB |
|
@ -48,7 +48,7 @@ body {
|
||||||
|
|
||||||
margin: auto;
|
margin: auto;
|
||||||
padding: 0;
|
padding: 0;
|
||||||
max-width: 1400px;
|
max-width: 1600px;
|
||||||
|
|
||||||
text-rendering: optimizeSpeed;
|
text-rendering: optimizeSpeed;
|
||||||
line-height: 1.5;
|
line-height: 1.5;
|
||||||
|
@ -94,7 +94,7 @@ li {
|
||||||
margin: 0.5em 0;
|
margin: 0.5em 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
p, table {
|
p, table, table * {
|
||||||
text-align: justify;
|
text-align: justify;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -112,6 +112,10 @@ a:hover {
|
||||||
text-decoration: underline;
|
text-decoration: underline;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.mob {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
@media (prefers-reduced-motion: reduce) {
|
@media (prefers-reduced-motion: reduce) {
|
||||||
*,
|
*,
|
||||||
*::before,
|
*::before,
|
||||||
|
@ -129,3 +133,9 @@ a:hover {
|
||||||
scroll-behavior: auto !important;
|
scroll-behavior: auto !important;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@media only screen and (max-width: 1250px) {
|
||||||
|
.mob {
|
||||||
|
display: initial;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -4,14 +4,24 @@
|
||||||
font-family: Hack, hack, sans-serif;
|
font-family: Hack, hack, sans-serif;
|
||||||
}
|
}
|
||||||
|
|
||||||
.split > * {
|
.split {
|
||||||
padding: 2em;
|
display: grid;
|
||||||
|
grid-template-columns: 3fr 1fr;
|
||||||
|
grid-gap: 0.5em;
|
||||||
|
align-items: stretch;
|
||||||
|
height: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
.split {
|
.split > * {
|
||||||
display: grid;
|
display: flex;
|
||||||
grid-gap: 0.5em;
|
flex-direction: column;
|
||||||
grid-template-columns: 3fr 1fr;
|
justify-content: center;
|
||||||
|
padding: 2em;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.esplit {
|
||||||
|
grid-template-columns: 1fr 1fr;
|
||||||
}
|
}
|
||||||
|
|
||||||
.split > :first-child {
|
.split > :first-child {
|
||||||
|
@ -24,25 +34,13 @@
|
||||||
position: absolute;
|
position: absolute;
|
||||||
left: 0;
|
left: 0;
|
||||||
right: 0;
|
right: 0;
|
||||||
top: 50%;
|
top: 0;
|
||||||
bottom: 50%;
|
bottom: 0;
|
||||||
border-right: 2px solid var(--red);
|
border-right: 2px solid var(--red);
|
||||||
animation: grow 0.5s forwards;
|
animation: grow 0.5s forwards;
|
||||||
pointer-events: none;
|
pointer-events: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
@keyframes grow {
|
|
||||||
from {
|
|
||||||
top: 50%;
|
|
||||||
bottom: 50%;
|
|
||||||
}
|
|
||||||
|
|
||||||
to {
|
|
||||||
top: 0;
|
|
||||||
bottom: 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
canvas#particles {
|
canvas#particles {
|
||||||
position: fixed;
|
position: fixed;
|
||||||
top: 0;
|
top: 0;
|
||||||
|
@ -53,28 +51,78 @@ canvas#particles {
|
||||||
pointer-events: none;
|
pointer-events: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
@media (prefers-reduced-motion: reduce) {
|
form {
|
||||||
*,
|
background-color: #030303;
|
||||||
*::before,
|
width: 100%;
|
||||||
*::after {
|
padding: 1em;
|
||||||
-webkit-animation-duration: 0.01ms !important;
|
margin: 1em;
|
||||||
animation-duration: 0.01ms !important;
|
border-bottom: 1px solid var(--red);
|
||||||
|
}
|
||||||
|
|
||||||
-webkit-animation-iteration-count: 1 !important;
|
form > button {
|
||||||
animation-iteration-count: 1 !important;
|
background-color: #111;
|
||||||
|
border: none;
|
||||||
|
padding: 0.5em;
|
||||||
|
width: 100%;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
-webkit-transition-duration: 0.01ms !important;
|
.form-group {
|
||||||
-o-transition-duration: 0.01ms !important;
|
display: grid;
|
||||||
transition-duration: 0.01ms !important;
|
grid-template-columns: 8em auto;
|
||||||
|
grid-gap: 1em;
|
||||||
|
margin: 0.4em;
|
||||||
|
}
|
||||||
|
|
||||||
scroll-behavior: auto !important;
|
.form-group * {
|
||||||
|
border: none;
|
||||||
|
padding: 0.3em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-group > :last-child {
|
||||||
|
background-color: #111;
|
||||||
|
resize: vertical;
|
||||||
|
min-height: 3em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.captcha {
|
||||||
|
display: grid;
|
||||||
|
place-items: center;
|
||||||
|
margin: 0.5em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.captcha > img {
|
||||||
|
display: block;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
#comments > div {
|
||||||
|
background-color: #111;
|
||||||
|
padding: 0.5em;
|
||||||
|
margin: 0.5em;
|
||||||
|
}
|
||||||
|
|
||||||
|
#comments > div button {
|
||||||
|
border: none;
|
||||||
|
background-color: #000;
|
||||||
|
cursor: pointer;
|
||||||
|
border-bottom: 1px solid var(--red);
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes grow {
|
||||||
|
from {
|
||||||
|
transform: scaleY(0);
|
||||||
|
}
|
||||||
|
to {
|
||||||
|
transform: scaleY(1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@media only screen and (max-width: 1000px) {
|
@media only screen and (max-width: 1250px) {
|
||||||
.split {
|
.split {
|
||||||
grid-template-columns: 1fr;
|
grid-template-columns: 1fr;
|
||||||
grid-template-rows: auto auto;
|
grid-template-rows: auto auto;
|
||||||
|
align-items: unset;
|
||||||
}
|
}
|
||||||
|
|
||||||
.split > :first-child {
|
.split > :first-child {
|
||||||
|
@ -90,11 +138,6 @@ canvas#particles {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
.split {
|
|
||||||
grid-template-columns: 1fr;
|
|
||||||
border-bottom: 2px dashed gray;
|
|
||||||
}
|
|
||||||
|
|
||||||
.split > :last-child {
|
.split > :last-child {
|
||||||
word-break: break-all;
|
word-break: break-all;
|
||||||
}
|
}
|
||||||
|
|
|
@ -33,8 +33,9 @@ document.addEventListener("DOMContentLoaded", function () {
|
||||||
canvas.height = window.innerHeight;
|
canvas.height = window.innerHeight;
|
||||||
|
|
||||||
let particles = [];
|
let particles = [];
|
||||||
|
const particle_density = 1.5e-5;
|
||||||
|
let num_particles;
|
||||||
|
|
||||||
const num_particles = 512;
|
|
||||||
const particle_size = 2;
|
const particle_size = 2;
|
||||||
const avoidance_radius = 48;
|
const avoidance_radius = 48;
|
||||||
|
|
||||||
|
@ -87,6 +88,10 @@ document.addEventListener("DOMContentLoaded", function () {
|
||||||
|
|
||||||
class Particle {
|
class Particle {
|
||||||
constructor() {
|
constructor() {
|
||||||
|
this.reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
reset() {
|
||||||
this.x = Math.random() * canvas.width;
|
this.x = Math.random() * canvas.width;
|
||||||
this.y = Math.random() * canvas.height;
|
this.y = Math.random() * canvas.height;
|
||||||
this.velocity = {
|
this.velocity = {
|
||||||
|
@ -96,19 +101,21 @@ document.addEventListener("DOMContentLoaded", function () {
|
||||||
}
|
}
|
||||||
|
|
||||||
update(particles) {
|
update(particles) {
|
||||||
if (this.x < 0 || this.x > canvas.width) {
|
if (this.x <= 0 || this.x >= canvas.width) {
|
||||||
this.velocity.x *= -1;
|
this.velocity.x *= -1;
|
||||||
|
this.x = Math.max(Math.min(this.x, canvas.width), 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.y < 0 || this.y > canvas.height) {
|
if (this.y <= 0 || this.y >= canvas.height) {
|
||||||
this.velocity.y *= -1;
|
this.velocity.y *= -1;
|
||||||
|
this.y = Math.max(Math.min(this.y, canvas.height), 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
let dx = mouse.x - this.x;
|
let dx = mouse.x - this.x;
|
||||||
let dy = mouse.y - this.y;
|
let dy = mouse.y - this.y;
|
||||||
let distance = Math.sqrt(dx * dx + dy * dy);
|
let distance = Math.sqrt(dx * dx + dy * dy);
|
||||||
|
|
||||||
if (distance < avoidance_radius) {
|
if (distance < avoidance_radius && distance > 0) {
|
||||||
this.velocity.x += (dx / distance) * 0.5;
|
this.velocity.x += (dx / distance) * 0.5;
|
||||||
this.velocity.y += (dy / distance) * 0.5;
|
this.velocity.y += (dy / distance) * 0.5;
|
||||||
}
|
}
|
||||||
|
@ -149,13 +156,17 @@ document.addEventListener("DOMContentLoaded", function () {
|
||||||
draw() {
|
draw() {
|
||||||
ctx.beginPath();
|
ctx.beginPath();
|
||||||
ctx.arc(this.x, this.y, particle_size, 0, Math.PI * 2);
|
ctx.arc(this.x, this.y, particle_size, 0, Math.PI * 2);
|
||||||
ctx.fillStyle = "rgba(255, 81, 71, 0.2)";
|
ctx.fillStyle = "rgba(255, 81, 71, 0.5)";
|
||||||
ctx.fill();
|
ctx.fill();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function init() {
|
function init() {
|
||||||
particles = [];
|
particles = [];
|
||||||
|
num_particles = Math.floor(
|
||||||
|
particle_density * canvas.width * canvas.height,
|
||||||
|
);
|
||||||
|
num_particles = Math.min(num_particles, 1024);
|
||||||
for (let i = 0; i < num_particles; i++) {
|
for (let i = 0; i < num_particles; i++) {
|
||||||
particles.push(new Particle());
|
particles.push(new Particle());
|
||||||
}
|
}
|
||||||
|
|
|
@ -38,7 +38,7 @@
|
||||||
<header>{% block header %}{% endblock %}</header>
|
<header>{% block header %}{% endblock %}</header>
|
||||||
<main>{% block main %}{% endblock %}</main>
|
<main>{% block main %}{% endblock %}</main>
|
||||||
<footer>
|
<footer>
|
||||||
<i>The <a target="_blank" href="{{ url_for('views.git') }}">source code</a> and all content, except the Nerd Hack font (see <a target="_blank" href="{{ url_for("static", filename="fonts/LICENSE") }}">Nerd Hack font license</a>), are licensed under the <a target="_blank" href="https://www.gnu.org/licenses/agpl-3.0.en.html">AGPL-3.0-or-later</a> by Ari Archer <<a target="_blank" href="mailto:ari@ari.lt">ari@ari.lt</a>>. Copyright 2020-{{ current_year }}.</i>
|
<i>The <a target="_blank" href="{{ url_for('views.git') }}">source code</a> and all content, except the Nerd Hack font (see <a target="_blank" href="{{ url_for("static", filename="fonts/LICENSE") }}">Nerd Hack font license</a>), are licensed under the <a target="_blank" href="https://www.gnu.org/licenses/agpl-3.0.en.html">AGPL-3.0-or-later</a> by Ari Archer <<a target="_blank" href="mailto:ari@ari.lt">ari@ari.lt</a>> as a part of the <a href="{{ url_for("views.badge") }}" target="_blank">ari-web</a> project. Copyright 2019-{{ current_year }}.</i>
|
||||||
</footer>
|
</footer>
|
||||||
</article>
|
</article>
|
||||||
</body>
|
</body>
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
|
|
||||||
{% block description %}Ari-web: A personal website of a Lithuanian open source developer Ari Archer (Arija A.) who provides different free, private, and open source services for others.{% endblock %}
|
{% block description %}Ari-web: A personal website of a Lithuanian open source developer Ari Archer (Arija A.) who provides different free, private, and open source services for others.{% endblock %}
|
||||||
|
|
||||||
{% block keywords %}ari::web, services, foss services, homepage, portfolio{% endblock %}
|
{% block keywords %}ari::web, services, foss services, homepage, portfolio, resume{% endblock %}
|
||||||
|
|
||||||
{% block head %}
|
{% block head %}
|
||||||
<link rel="stylesheet" href="{{ url_for("static", filename="fonts/Hack.css") }}" type="text/css" referrerpolicy="no-referrer" />
|
<link rel="stylesheet" href="{{ url_for("static", filename="fonts/Hack.css") }}" type="text/css" referrerpolicy="no-referrer" />
|
||||||
|
@ -47,22 +47,44 @@
|
||||||
|
|
||||||
{% block header %}
|
{% block header %}
|
||||||
<h1>Ari.lt: Free and open source world of Ari Archer.</h1>
|
<h1>Ari.lt: Free and open source world of Ari Archer.</h1>
|
||||||
|
|
||||||
|
<nav class="mob">
|
||||||
|
<div align="center">
|
||||||
|
<details>
|
||||||
|
<summary>Navigation</summary>
|
||||||
|
|
||||||
|
<ul>
|
||||||
|
<li>Links: <a href="#links">#links</a></li>
|
||||||
|
<li>Staff list: <a href="#staff">#staff</a></li>
|
||||||
|
<li>Self-hosted services list: <a href="#services">#services</a></li>
|
||||||
|
<li>Guestbook: <a href="#gb">#gb</a></li>
|
||||||
|
</ul>
|
||||||
|
</details>
|
||||||
|
</div>
|
||||||
|
</nav>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
{% block main %}
|
{% block main %}
|
||||||
<div class="split">
|
<div class="split">
|
||||||
<div>
|
<div>
|
||||||
<p>Welcome to my website, visitor {{ visitor }}!</p>
|
<p>Welcome to my website, visitor <b>{{ visitor }}</b>!</p>
|
||||||
|
|
||||||
|
<blockquote>
|
||||||
|
Before I start explaining who I am, if you're here on this page because of one of the users
|
||||||
|
using ari-web services and you want to report abuse, please contact me using one of the
|
||||||
|
contacts listed on this page (such as the <a href="mailto:ari@ari.lt" target="_blank">ari@ari.lt</a> email)
|
||||||
|
or see <a href="#staff">the list of staff</a>. You may also leave a comment on <a href="#gb">the guestbook</a>.
|
||||||
|
</blockquote>
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
My name is <b>Ari Archer</b> also known as <b>Arija A.</b>, but most commonly referred to as
|
My name is <b>Ari Archer</b> also known as <b>Arija A.</b>, but most commonly referred to as
|
||||||
<b>Ari</b>. I am a {{ ari_age }} year old, neurodivergent, transgender, open source developer from Lithuania who does
|
<b>Ari</b>. I am a <b>{{ ari_age }} year old</b>, neurodivergent, transgender, open source developer from Lithuania who does
|
||||||
fun stuff in primarily <a target="_blank" href="https://en.wikipedia.org/wiki/Python_(programming_language)">Python</a> (~{{ python_exp }} years)
|
fun stuff in primarily <a target="_blank" href="https://en.wikipedia.org/wiki/Python_(programming_language)">Python</a> (~<b>{{ python_exp }}</b> years)
|
||||||
and <a target="_blank" href="https://en.wikipedia.org/wiki/C_(programming_language)">C (89, 99)</a> (~{{ c_exp }} years).
|
and <a target="_blank" href="https://en.wikipedia.org/wiki/C_(programming_language)">C (89, 99)</a> (~<b>{{ c_exp }}</b> years).
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
I've picked up programming at first in Python, writing various programs on my phone, and later on discovering a communty
|
I've picked up programming at first in Python, writing various programs on my phone, and later on discovering a community
|
||||||
where I could share my code. At the time I didn't have access to a computer, so I used to play around with
|
where I could share my code. At the time I didn't have access to a computer, so I used to play around with
|
||||||
basic <a target="_blank" href="https://en.wikipedia.org/wiki/JavaScript">JavaScript</a> on my local library computers.
|
basic <a target="_blank" href="https://en.wikipedia.org/wiki/JavaScript">JavaScript</a> on my local library computers.
|
||||||
At around 2019 I got access to a personal computer, which is where my main <a target="_blank" href="https://en.wikipedia.org/wiki/Free_and_open-source_software">FOSS</a> journey started -
|
At around 2019 I got access to a personal computer, which is where my main <a target="_blank" href="https://en.wikipedia.org/wiki/Free_and_open-source_software">FOSS</a> journey started -
|
||||||
|
@ -72,12 +94,12 @@
|
||||||
<p>
|
<p>
|
||||||
I hated the limiting feeling of being on <a target="_blank" href="https://en.wikipedia.org/wiki/Microsoft_Windows">Microsoft Windows</a> 10
|
I hated the limiting feeling of being on <a target="_blank" href="https://en.wikipedia.org/wiki/Microsoft_Windows">Microsoft Windows</a> 10
|
||||||
very limiting, so soon after getting a personal computer I installed a free and open source <a target="_blank" href="https://en.wikipedia.org/wiki/Linux">Linux</a>
|
very limiting, so soon after getting a personal computer I installed a free and open source <a target="_blank" href="https://en.wikipedia.org/wiki/Linux">Linux</a>
|
||||||
kernel distribution - and I've never went back to Windows ever since then. Democracy, freedom, shareability
|
kernel distribution - and I've never went back to Windows ever since then. <i>Democracy, freedom, shareability</i>
|
||||||
and customization ("hackability") are huge values for me.
|
and <i>customization</i> ("hackability") are huge values for me.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
Technology is a big part of my life, and I am way past the stage where I find <i>just</i> technology facinating -
|
Technology is a big part of my life, and I am way past the stage where I find <i>just</i> technology fascinating -
|
||||||
I find various problems and their optimal solutions very interesting and I like to come up with my own - even if
|
I find various problems and their optimal solutions very interesting and I like to come up with my own - even if
|
||||||
it's "<a target="_blank" href="https://en.wikipedia.org/wiki/Reinventing_the_wheel">reinventing the wheel</a>" or "impractical" -
|
it's "<a target="_blank" href="https://en.wikipedia.org/wiki/Reinventing_the_wheel">reinventing the wheel</a>" or "impractical" -
|
||||||
I like to dig deep into it and understand how it works at its core, rather than relying on high-level features of an
|
I like to dig deep into it and understand how it works at its core, rather than relying on high-level features of an
|
||||||
|
@ -95,6 +117,18 @@
|
||||||
<li>Cooking - I really enjoy putting together a healthy, vegan dish, which's recipe I can share with others.</li>
|
<li>Cooking - I really enjoy putting together a healthy, vegan dish, which's recipe I can share with others.</li>
|
||||||
<li>And also <a href="https://blog.ari.lt/">blogging</a>, as archiving things and <i>thoughts</i> has been a huge part of my life since forever.</li>
|
<li>And also <a href="https://blog.ari.lt/">blogging</a>, as archiving things and <i>thoughts</i> has been a huge part of my life since forever.</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
But generally, I am pretty much open to try <i>everything at least once</i> if I have the time and energy to do so.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
People often describe my personality as kind, accepting, open-minded, and nonjudgmental due to the way I interact
|
||||||
|
with the world and people - I am always accepting of people no matter what they've gone through or are
|
||||||
|
going through. They also see my logical side and describe me as <i>intelligent, analytical</i>, and <i>creative</i>
|
||||||
|
because of how I tend to approach various logical problems. Though, this side of me can sometimes be
|
||||||
|
overpowered by my emotional side if I lose control of my emotions.
|
||||||
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
|
@ -106,10 +140,13 @@
|
||||||
<li>Name: Arija A. (Ari Archer)</li>
|
<li>Name: Arija A. (Ari Archer)</li>
|
||||||
<li>Pronouns: She/Her</li>
|
<li>Pronouns: She/Her</li>
|
||||||
<li>Age: {{ ari_age }} years old.</li>
|
<li>Age: {{ ari_age }} years old.</li>
|
||||||
|
<li>Education: Primary school, middle school, high school (ongoing).</li>
|
||||||
<li>Country: Lithuania (Lietuva).</li>
|
<li>Country: Lithuania (Lietuva).</li>
|
||||||
<li>Languages: Lithuanian (native), English (B2), German (basic).</li>
|
<li>Languages: Lithuanian (native, {{ ari_age }}y), English (B2, {{ ari_age - 8 }}y), German (basic, {{ ari_age - 12 }}y).</li>
|
||||||
<li>Programming Experience: {{ programming_exp }} years ({{python_exp }}y in Python, {{ c_exp }}y in C).</li>
|
<li>Programming Experience: {{ programming_exp }} years ({{python_exp }}y in Python, {{ c_exp }}y in C).</li>
|
||||||
<li>Skills: Backend web development in Python using Flask, basic front-end development (HTML, JS, CSS, SCSS) and SEO (search engine optimization), software and library development in C and Python, Linux and intermediate Linux systems administration, technical documentation and specifications, application of different mathematical methods.</li>
|
<li>Skills: Backend web development in Python using Flask, basic front-end development (HTML, JS, CSS, SCSS) and SEO (search engine optimization), software and library development in C and Python, Linux and intermediate Linux systems administration, technical documentation and specifications, application of different mathematical methods.</li>
|
||||||
|
<li>Learning: Better communication skills, self-improvement, cryptography (post-quantum cryptography), working on mental health and emotional grounding.</li>
|
||||||
|
<li>Personality: Recognised as kind, open-minded, intelligent, analytical, non-Judgmental, chill, anxious, generous, introverted, independent, caring, helpful, and supportive by people in my life.</li>
|
||||||
<li>
|
<li>
|
||||||
Contacts
|
Contacts
|
||||||
|
|
||||||
|
@ -125,14 +162,65 @@
|
||||||
<blockquote>
|
<blockquote>
|
||||||
"Talk is cheap. Show me the code."
|
"Talk is cheap. Show me the code."
|
||||||
</blockquote>
|
</blockquote>
|
||||||
<pre>
|
<pre> - Linus Torvalds, creator of Linux</pre>
|
||||||
- Linus Torvalds, creator of Linux
|
|
||||||
</pre>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
That was a short introduction of who I am and what I do.
|
This is a brief description of me as a person, I probably cannot fit all of it in a single page. I do hope that
|
||||||
|
this is a good introduction to what I do, what skills I posses.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
Current status:
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<div align="center">
|
||||||
|
<blockquote><pre>This is a status
|
||||||
|
Hello world</pre>
|
||||||
|
Last updated: 2024-06-06 00:17:11 UTC</blockquote>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h2 id="links"><a href="#links">#</a> Links</h2>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
Many of my links, social media, etc. can be found at:
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<div class="mob">
|
||||||
|
<h3>Contacts</h3>
|
||||||
|
<ul>
|
||||||
|
<li>GitHub: <a target="_blank" href="https://github.com/TruncatedDinoSour">TruncatedDinoSour</a></li>
|
||||||
|
<li>GitHub organization: <a target="_blank" href="https://github.com/ari-lt">ari-lt</a> (<a href="mailto:org@ari.lt">org@ari.lt</a>)</li>
|
||||||
|
<li>Matrix: <a target="_blank" href="https://matrix.to/#/@ari:ari.lt">@ari:ari.lt</a></li>
|
||||||
|
<li>Fediverse: <a target="_blank" href="https://ak.ari.lt/ari">@ari@ak.ari.lt</a></li>
|
||||||
|
<li>E-Mail: <a target="_blank" href="mailto:ari@ari.lt">ari@ari.lt</a> (GPG: <a target="_blank" href="https://keys.openpgp.org/vks/v1/by-fingerprint/4FAD63E936B305906A6C4894A50D5B4B599AF8A2">4FAD63E936B305906A6C4894A50D5B4B599AF8A2</a>)</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h3>Activity</h3>
|
||||||
|
|
||||||
|
<ul>
|
||||||
|
<li>Source code of the website: <a target="_blank" href="{{ url_for("views.git") }}">{{ url_for("views.git") }}</a></li>
|
||||||
|
<li>Blog: <a target="_blank" href="https://blog.ari.lt/">blog.ari.lt</a></li>
|
||||||
|
<li>Matrix room: <a target="_blank" href="https://matrix.to/#/#root:ari.lt">#root:ari.lt</a></li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<h3>Projects</h3>
|
||||||
|
|
||||||
|
<ul>
|
||||||
|
<li>Ari.lt - an open source website by ari archer: <a target="_blank" href="https://github.com/ari-lt">ari-lt GitHub organization</a></a>
|
||||||
|
<li>Baz - a fast, easy, simple and lightweight plugin manager for GNU bash: <a target="_blank" href="https://github.com/TruncatedDinoSour/baz">TruncatedDinoSour/baz</a></a>
|
||||||
|
<li>Kos - A simple SUID tool written in C++: <a target="_blank" href="https://github.com/TruncatedDinoSour/kos">TruncatedDinoSour/kos</a></a>
|
||||||
|
<li>Armour - password securing, management and generation library with a custom database format: <a target="_blank" href="https://github.com/TruncatedDinoSour/armour">TruncatedDinoSour/armour</a></a>
|
||||||
|
<li>Fa - stack based, reverse polish notation low-level programming language that transpiles down to assembly: <a target="_blank" href="https://github.com/TruncatedDinoSour/fa">TruncatedDinoSour/fa</a></a>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
Note that these are not the only projects I've ever worked on. These are a few
|
||||||
|
highlights that I find neat personally for differnt reasons. There don't showcase all
|
||||||
|
of my abilities, although these are practical examples of things I work on
|
||||||
|
sometimes.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<h2 id="staff"><a href="#staff">#</a> Staff</h2>
|
<h2 id="staff"><a href="#staff">#</a> Staff</h2>
|
||||||
|
@ -142,7 +230,8 @@
|
||||||
Feel free to visit their websites and show appriciation :).
|
Feel free to visit their websites and show appriciation :).
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<div align="center">
|
<div class="split esplit">
|
||||||
|
<div align="center">
|
||||||
<table>
|
<table>
|
||||||
<tr>
|
<tr>
|
||||||
<th>Name</th>
|
<th>Name</th>
|
||||||
|
@ -170,6 +259,16 @@
|
||||||
<td><a href="https://sulian.eu/" target="_blank">sulian.eu</a></td>
|
<td><a href="https://sulian.eu/" target="_blank">sulian.eu</a></td>
|
||||||
</tr>
|
</tr>
|
||||||
</table>
|
</table>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<p>
|
||||||
|
Ari.lt is mainly a personal site, although it is not limited to being <i>just</i> a personal website.
|
||||||
|
I, together with a couple of <a href="#staff">staff members</a>, host some <a href="#services">services</a> on
|
||||||
|
a shared <a href="https://s.ari.lt/">server</a>. Some of these services are a bit locked down or have aggressive policies to prevent spam
|
||||||
|
as our team is small.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<h2 id="services"><a href="#services">#</a> Services</h2>
|
<h2 id="services"><a href="#services">#</a> Services</h2>
|
||||||
|
@ -236,7 +335,7 @@
|
||||||
<td><a href="https://pb.ari.lt/" target="_blank">pb.ari.lt</a></td>
|
<td><a href="https://pb.ari.lt/" target="_blank">pb.ari.lt</a></td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td>db.cubiq.dev</td>
|
<td>Private PocketBase instance</td>
|
||||||
<td>Private database storage for <a href="https://github.com/TheCubiq/" target="_blank">Github: TheCubiq</a></td>
|
<td>Private database storage for <a href="https://github.com/TheCubiq/" target="_blank">Github: TheCubiq</a></td>
|
||||||
<td><a href="https://db.cubiq.dev/" target="_blank">db.cubiq.dev</a></td>
|
<td><a href="https://db.cubiq.dev/" target="_blank">db.cubiq.dev</a></td>
|
||||||
</tr>
|
</tr>
|
||||||
|
@ -246,10 +345,74 @@
|
||||||
<td><a href="https://t1nklas.lt/" target="_blank">t1nklas.lt</a></td>
|
<td><a href="https://t1nklas.lt/" target="_blank">t1nklas.lt</a></td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td>git.kappach.at</td>
|
<td>Forgejo instance for <a href="https://kappach.at/" target="_blank">kappach.at</a></td>
|
||||||
<td>Git forge instance of KappaChat - An extensible Matrix client written in C.</td>
|
<td>Git forge instance of KappaChat - An extensible Matrix client written in C.</td>
|
||||||
<td><a href="https://git.kappach.at/" target="_blank">git.kappach.at</a></td>
|
<td><a href="https://git.kappach.at/" target="_blank">git.kappach.at</a></td>
|
||||||
</tr>
|
</tr>
|
||||||
</table>
|
</table>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<h2 id="gb"><a href="#gb">#</a> Guestbook</h2>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
If you want to interact with the community feel free to leave your comments here! You will require an
|
||||||
|
email address to prevent spam and impersonation, it will be listed, although not as text as it will
|
||||||
|
be encrypted server-side using <a target="_blank" href="https://en.wikipedia.org/wiki/RC4">RC4</a> (a fast, but insecure cipher)
|
||||||
|
with a 32-byte (256 bit) key. Check your mailbox when you comment as you will need to verify the comment.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<form method="post">
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="name">Name:</label>
|
||||||
|
<input required type="text" id="name" name="name" placeholder="Cool Person" />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="website">Website (optional):</label>
|
||||||
|
<input type="url" id="website" name="website" placeholder="https://example.com/" />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="email">Email:</label>
|
||||||
|
<input required type="email" id="email" name="email" placeholder="me@example.com" />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="comment">Comment:</label>
|
||||||
|
<textarea required type="text" id="comment" name="comment" placeholder="Hello!"></textarea>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="captcha">
|
||||||
|
<img loading="lazy" width="240px" height="90" src="{{ url_for("views.captcha") }}?new" onclick="this.src=this.src+Math.floor(1000*Math.random())" alt="An image CAPTCHA" />
|
||||||
|
<i>Click the image above to reload and get a new CAPTCHA</i>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="captcha">CAPTCHA:</label>
|
||||||
|
<input required type="text" id="comment" name="comment" placeholder="Enter the CAPTCHA code above." />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<button type="submit">Comment</button>
|
||||||
|
</form>
|
||||||
|
|
||||||
|
<hr />
|
||||||
|
|
||||||
|
<div align="center">
|
||||||
|
<i>Report any impersonation to the owner of this website: Ari Archer.</i>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div id="comments">
|
||||||
|
<div id="guestbook-1">
|
||||||
|
<p><a href="#guestbook-1">#1:</a> Cool Person (<a target="_blank" href="#!">https://example.com/</a>) <<i><button onclick="rc4('data','key')">show email</button></i>> at 2024-06-05 11:11:11 UTC says...</p>
|
||||||
|
<pre>Cool website, but you should kill yourself!
|
||||||
|
Meow!</pre>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div id="guestbook-1">
|
||||||
|
<p><a href="#guestbook-1">#1:</a> Cool Person (<a target="_blank" href="#!">https://example.com/</a>) <<i><button onclick="rc4('data','key')">show email</button></i>> at 2024-06-05 11:11:11 UTC says...</p>
|
||||||
|
<pre>Cool website, but you should kill yourself!
|
||||||
|
Meow!</pre>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
Loading…
Add table
Reference in a new issue