Merge branch 'main' into comments

This commit is contained in:
0x01fe 2024-06-26 14:10:02 -05:00
commit ce9c995a50
22 changed files with 435 additions and 33 deletions

7
.gitignore vendored
View File

@ -6,6 +6,8 @@ __pycache__
docker-compose.yaml
*.sh
*.ini
# Ignore images in posts
*.jpg
*.png
@ -13,3 +15,8 @@ docker-compose.yaml
# Flask Data & Config
*.ini
data
*.gif
# Writing
writing

View File

@ -4,9 +4,7 @@ FROM python:3.12.2-slim-bookworm
RUN apt-get update && apt-get upgrade -y
RUN useradd -m app
USER app
RUN groupadd -r app && useradd -r -g app app
COPY . .
@ -15,4 +13,6 @@ RUN python3 -m pip install -r requirements.txt
WORKDIR ./app
USER app
CMD ["python3", "-u", "app.py"]

View File

@ -2,8 +2,5 @@
Code of the website hosted at https://www.0x01fe.net
Could I gitignore the config files?
Yes.
Do I?
no.
One might ask why my pretty simple website is written in Python. The answer is so that I can just drop markdown files in a folder and have them automatically formatted and uploaded. This is done using the fact that markdown translates to HTML perfectly and that Flask / Jinja2 templates are really easy to use!

View File

@ -1,8 +1,11 @@
import os
import glob
import configparser
import random
import base64
import datetime
import requests
import flask
import flask_wtf.csrf
import flask_session
@ -22,6 +25,7 @@ CONFIG_PATH = "./config.ini"
config = configparser.ConfigParser()
config.read(CONFIG_PATH)
WRITING_FOLDER = 'static/writing/'
POSTS_FOLDER = config['POSTS']['POSTS_FOLDER']
STATUS_FILE = config['STATUS']['STATUS_FILE']
PORT = int(config['NETWORK']['PORT'])
@ -38,6 +42,10 @@ app.config['SESSION_TYPE'] = 'filesystem'
app.config['SESSION_FILE_DIR'] = './data/.flask_session/'
flask_session.Session(app)
MUSIC_API_TOKEN = config['AUTH']['MUSIC_API_TOKEN']
MUSIC_API_URL = config['NETWORK']['MUSIC_API_URL']
statuses = {}
def get_posts(category_filter : str | None = None) -> list[Post]:
post_files = glob.glob(f'{POSTS_FOLDER}/*')
try:
@ -70,13 +78,36 @@ def get_posts(category_filter : str | None = None) -> list[Post]:
return reversed(ordered_posts)
def get_status() -> str:
def read_status_file() -> dict:
with open(STATUS_FILE, 'r', encoding='utf-8') as file:
statuses = file.readlines()
data = file.readlines()
status = random.randint(0, len(statuses) - 1)
result = {}
current_key = None
for line in data:
if line[0] == '#':
return markdown.markdown(statuses[status])
# Empty Key-Value pairs will cause errors
if current_key:
if not result[current_key]:
result.pop(current_key)
current_key = line.replace('#', '').strip()
result[current_key] = []
elif not (line == '\n'):
result[current_key].append(line)
return result
def get_status() -> str:
keys = list(statuses.keys())
selected_key = keys[random.randint(0, len(keys) - 1)]
section: list = statuses[selected_key]
selected_status = section[random.randint(0, len(section) - 1)]
return f'<div title="{selected_key}">{markdown.markdown(selected_status)}</div>'
# Main Page
@app.route('/')
@ -100,6 +131,26 @@ def index():
return flask.render_template('index.html', posts=posts_and_comments, status=status, form=form, user="yes")
# Posts
@app.route('/post/<string:post_name>')
def post(post_name: str):
for post in get_posts():
if post.title.replace(' ', '-') == post_name:
return flask.render_template('index.html', posts=[post.body], status=get_status())
flask.abort(404)
# Posts
@app.route('/post/<string:post_name>')
def post(post_name: str):
for post in get_posts():
if post.title.replace(' ', '-') == post_name:
return flask.render_template('index.html', posts=[post.body], status=get_status())
flask.abort(404)
# Games Page
@app.route('/games/')
def games():
@ -130,7 +181,25 @@ def music():
# Get status
status = get_status()
return flask.render_template('music.html', posts=post_bodies, status=status)
# Get top albums
r = requests.get(
MUSIC_API_URL +'/top/albums',
headers={
'token' : MUSIC_API_TOKEN,
'user' : '1',
'limit' : '9'
})
top_albums = r.json()['top']
for album_index in range(0, len(top_albums)):
album = top_albums[album_index]
time = int(album['listen_time'])
hours = round(time/1000/60/60, 1)
top_albums[album_index]['listen_time'] = hours
return flask.render_template('music.html', posts=post_bodies, status=status, top_albums=top_albums)
# Motion Pictures Page
@app.route('/motion-pictures/')
@ -164,6 +233,31 @@ def programming():
return flask.render_template('programming.html', posts=post_bodies, status=status)
@app.route('/writing/')
def writing():
works = []
# Get all works in writing folder
files = glob.glob(WRITING_FOLDER + '*')
for path in files:
date: str = datetime.datetime.fromtimestamp(os.path.getctime(path)).strftime("%B %d, %Y")
name: str = path.split('/')[-1]
works.append({
'date' : date,
'name' : name,
'path' : path
})
return flask.render_template('writing.html', works=works)
# About Page
@app.route('/about/')
def about():
@ -173,7 +267,42 @@ def about():
return flask.render_template('about.html', status=status)
# MISC
@app.route('/albumsquare/<user_id>/<int:rows>')
def album_square(user_id, rows : int):
limit = rows ** 2
res = (1080/(rows))-rows
# Get top albums
r = requests.get(
MUSIC_API_URL +'/top/albums',
headers={
'token' : MUSIC_API_TOKEN,
'user' : user_id,
'limit' : str(limit)
})
top_albums = r.json()['top']
for album_index in range(0, len(top_albums)):
album = top_albums[album_index]
time = int(album['listen_time'])
hours = round(time/1000/60/60, 1)
top_albums[album_index]['listen_time'] = hours
return flask.render_template('album_square.html', top_albums=top_albums, limit=rows, res=res)
if __name__ == "__main__":
statuses = read_status_file()
if DEV:
app.run(port=PORT)
else:

8
app/data/comments.json Normal file
View File

@ -0,0 +1,8 @@
{
"2" : [
{
"username" : "0x01FE",
"content" : "Hello, this is an example comment!"
}
]
}

5
app/data/users.json Normal file
View File

@ -0,0 +1,5 @@
{
"users" : {
"0x01FE" : "cGFzc3dvcmQ="
}
}

View File

@ -9,6 +9,8 @@ class Post:
body : str
file : str
id : int
title : str
url : str
def __init__(self, file_path):
self.file = file_path
@ -18,11 +20,13 @@ class Post:
self.category = lines[1].split(":")[1].strip()
self.author = lines[2].split(":")[1].strip()
self.title = lines[6][2:-1]
self.url = '/post/' + self.title.replace(' ', '-')
date = lines[3].split(":")[1].strip()
self.date = datetime.datetime.strptime(date, "%d-%m-%Y")
self.id = int(lines[4].split(":")[1].strip())
self.body = markdown.markdown(''.join(lines[7:]))
self.body = markdown.markdown(f'# [{self.title}]({self.url})\n' + ''.join(lines[7:]))

View File

@ -1,31 +1,112 @@
Catchy Right?
Everybody's lazy when they're tired
# Project Moon
Needles
Sally forth Rocinante!
The multitude tightens its hold.
# Misc
Check out [NEUPINK](https://neupink.bandcamp.com/album/swordflower-hills-killer-2)!
Solar Sect of Mystic Wisdom
~ Nuclear Fusion
His name really is Tim.
Just wait until you see the 1 in 1000 message.
I'm open to suggestions on how to improve the look of the website
As long as there is delusion, there is hope
It's 510.
Catchy Right?
## TV / Movie Quotes
# Monogatari
I don't know everything, I only know what I know.
## Song Lyrics
# Im in Your Mind by King Gizzard & The Lizard Wizard
Everybody's lazy when they're tired
# Straws In The Wind by King Gizzard & The Lizard Wizard
Mindful of the weary inkling that is lurking
Mortal traffic lights signaling when to stay or go
# Automation by King Gizzard & The Lizard Wizard
Cyber surgeon, Javascript person
# Gilgamesh by King Gizzard & The Lizard Wizard
Bone-dried swamplands swallow me
House of dust, land of bone
I ate dirt, I drank stone
Come on, snake, punish me
# The Dripping Tap by King Gizzard & The Lizard Wizard
Drip, drip from the tap, don't slip on the drip
His name really is Tim.
Just wait until you see the 1 in 1000 message.
I'm open to suggestions on how to improve the look of the website
Open the curtains
Don't miss a moment of this experiment
Needles
Sally forth Rocinante!
The multitude tightens its hold.
# Face to Face by Daft Punk
It's amazing what you'll find face to face
It's not hard to go the distance / When you finally get involved face to face
# Touch by Daft Punk
A tourist in a dream / A visitor, it seems / A half-forgotten song / Where do I belong?
# Magenta Mountian by King Gizzard & The Lizard Wizard
What do you mean ... You can't see it?
I don't believe you / your eyes deceive you / better check yourself in
You will say I'm crazy / I will go on my way 'cause it's what I need
I'd cross a thousand seas just to prove I'm not mad
I thought I saw a statue blink, and a bird with no head, Land on a golden thread, I rub my eyes, What am I saying? There's nothing there
Solar Sect of Mystic Wisdom
~ Nuclear Fusion
Check out [NEUPINK](https://neupink.bandcamp.com/album/swordflower-hills-killer-2)!
# Armor-clad Faith by NAOKI, Arc System Works
I'm a fool, I know nothing / I take the role of a silly clown
All I do is embrace the wounded soul
# Love the Subhuman Self by AISHA, Jamison Boaz, Arc System Works (Guilty Gear Strive)
So carry on, love the subhuman self
Break yourself inside out, she told me
# Symphony by NAOKI, Arc System Works (Guilty Gear Strive)
We're just a quirky note in the symphony
# White Whale by Shadow Academy
So, silent tide / Tell me which face do I show the world / And which one do I hide?
# Intrasport by King Gizzard & The Lizard Wizard
Dreams that sew me up like sleeping with a needle
Those feelings that I had are building up to something
I feel a schism in the rhythm, now I'm running
My hair is liquifying
My taste buds are igniting
# Set by King Gizzard & The Lizard Wizard
Cut the cord, kill the king and reset
Squeezing day into night with supernatural pressure
Right eye is the sun and left the moon's light
# Swan Song by King Gizzard & The Lizard Wizard
Score the music // Of your essence
Stars fall from their lofty places
Earth has been put through her paces
Cosmic surgeons cut the cable
Make a new world if you're able
# String Theocracy by Mili
Open the curtains
Don't miss a moment of this experiment
If you're going to replace me // At least have the audacity to kill me thoroughly
What's the color of the electric sheep you see?
Maybe we're all cold machines
# Change by King Gizzard & The Lizard Wizard
We're changing pace // Higher stakes
So called heroes wearing fake capes
Buildings that you know // People come and go // Are a certain way
And then you get the news that obliterates your view // Amputate your truths // The signifiance has changed
Hospital inane // Meaningless and grey // But lie within the walls and the signifiance will change
What would it take for us to change the game? // Maybe our existence is signifiance in vain
# Candles by King Gizzard & The Lizard Wizard
This little man is too hot to handle // Set the funeral on fire with the candles
Praying to the gods at the top of a mountian // Better throwing all your pennies in a fountian
My little heart, as cold as a morgue // Let the weight of it drop like an iceberg
# Presumptuous by King Gizzard & The Lizard Wizard
Eggshell, landmine, stepping stones // Kindred spirits at a crossroads
The world we built is on a tilt // Bottled up inside and filled with guilt

View File

@ -0,0 +1,19 @@
.albums {
height: 100%;
line-height: 0;
font-size: 0;
}
.albums img {
padding: 0 0;
margin: 0 0;
border: 0 0;
}
.body {
height: 100%;
padding: 0 0;
margin: 0 0;
}

View File

@ -0,0 +1,12 @@
EOF Mark,
Glassit-VSC,
JSON formatter,
Pylance,
Remote - SSH,
Synthwave '84 Blues,
Trailing Spaces,
Helm Intellisense,
background,
Helium Icon Theme,
SQLite Viewer,
Docker

View File

@ -107,6 +107,39 @@ a:hover {
text-decoration: none;
}
.rightbar {
height: fit-content;
align-self: flex-start;
top: 10px;
padding: 20pt;
margin: 5em 0;
margin-right: 2em;
border-style: var(--borders-style);
border-radius: var(--border-radius);
border-color: #1E2022;
background-color: var(--main-background);
opacity: 0.9;
/* box-shadow: -10px 10px var(--accent); */
/* Text Settings */
font-weight: bold;
line-height: 30pt;
}
.rightbar a {
text-decoration: none;
}
.rightbar h2 {
font-family: Georgia, 'Times New Roman', Times, serif;
line-height: normal;
}
.dlog {
flex: 3;
@ -158,7 +191,7 @@ a:hover {
text-decoration: underline;
text-decoration-style: solid;
text-decoration-thickness: 0.25em;
text-underline-offset: 6px;
text-underline-offset: 7px;
text-decoration-color: var(--primary);
}
@ -195,3 +228,49 @@ a:hover {
.comment-editor textarea:focus {
border: 3px solid var(--accent);
}
/* MUSIC */
.albums {
height: fit-content;
align-self: flex-start;
top: 10px;
padding: 20pt;
margin: 5em 0;
margin-right: 2em;
border-style: var(--borders-style);
border-radius: var(--border-radius);
border-color: #1E2022;
background-color: var(--main-background);
/* Text Settings
font-weight: bold;
line-height: 30pt; */
}
.real-albums img {
height: 100px;
width: 100px;
padding: 0 0;
margin: 0 0;
border: 0 0;
}
.real-albums {
line-height: 0;
font-size: 0;
padding: 0 0;
margin: 0 0;
}
.albums h1 {
font-size: 2em;
text-align: center;
padding: 0 0;
margin: 15pt 0;
margin-top: -5pt;
}

View File

@ -18,6 +18,7 @@
<a href="../music/">Music</a><br>
<a href="../motion-pictures/">Motion Picture</a><br>
<a href="../programming/">Programming</a><br>
<a href="/writing/">Writing</a><br>
<a href="."><u>About</u></a>
</div>

View File

@ -0,0 +1,20 @@
<!DOCTYPE html>
<html lang="en">
<header>
<link rel="shortcut icon" href="index_favicon.ico">
<link rel="stylesheet" href="{{ url_for('static', filename='albumsquare.css') }}">
<title>Album Square</title>
</header>
<body>
<div class="albums">
{% for album in top_albums %}
<a title="{{ album.album_name}} by {{ album.artist_name }} - {{ album.listen_time }} Hours">
<img src="{{ album.album_cover }}" style="width: {{ res }}px; height: {{ res }}px;">
</a>
{% if loop.index % limit == 0 %}
<br>
{% endif %}
{% endfor %}
</div>
</body>
</html>

View File

@ -18,6 +18,7 @@
<a href="../music/">Music</a><br>
<a href="../motion-pictures/">Motion Picture</a><br>
<a href="../programming/">Programming</a><br>
<a href="/writing/">Writing</a><br>
<a href="../about/">About</a>
</div>

View File

@ -14,11 +14,12 @@
<!-- Sidebar -->
<div class="sidebar">
<a href="."><u>Home</u></a><br>
<a href="./games/">Games</a><br>
<a href="./music/">Music</a><br>
<a href="./motion-pictures/">Motion Picture</a><br>
<a href="./programming/">Programming</a><br>
<a href="./about/">About</a>
<a href="/games/">Games</a><br>
<a href="/music/">Music</a><br>
<a href="/motion-pictures/">Motion Picture</a><br>
<a href="/programming/">Programming</a><br>
<a href="/writing/">Writing</a><br>
<a href="/about/">About</a>
</div>
<!-- Main Page -->

View File

@ -18,6 +18,7 @@
<a href="../music/">Music</a><br>
<a href="."><u>Motion Picture</u></a><br>
<a href="../programming/">Programming</a><br>
<a href="/writing/">Writing</a><br>
<a href="../about/">About</a>
</div>

View File

@ -18,6 +18,7 @@
<a href="."><u>Music</u></a><br>
<a href="../motion-pictures/">Motion Picture</a><br>
<a href="../programming/">Programming</a><br>
<a href="/writing/">Writing</a><br>
<a href="../about/">About</a>
</div>
@ -28,6 +29,20 @@
<div class="post">{{ post|safe }}</div>
{% endfor %}
</div>
<div class="albums">
<h1>Top Albums</h1>
<div class="real-albums">
{% for album in top_albums %}
<a title="{{ album.album_name}} by {{ album.artist_name }} - {{ album.listen_time }} Hours">
<img src="{{ album.album_cover }}">
</a>
{% if loop.index % 3 == 0 %}
<br>
{% endif %}
{% endfor %}
</div>
</div>
</div>
</body>
</html>

View File

@ -18,6 +18,7 @@
<a href="../music/">Music</a><br>
<a href="../motion-pictures/">Motion Picture</a><br>
<a href="."><u>Programming</u></a><br>
<a href="/writing/">Writing</a><br>
<a href="../about/">About</a>
</div>
@ -28,6 +29,12 @@
<div class="post">{{ post|safe }}</div>
{% endfor %}
</div>
<!-- Other Sidear -->
<div class="rightbar">
<h2>Other</h2>
<a href="">Technologies I Use</a>
</div>
</div>
</body>
</html>

View File

@ -0,0 +1,14 @@
<!DOCTYPE html>
<html lang="en">
<body>
<a href="/">home</a>
<p>
This is just a little page where I post stuff I write. I was kind of unsure if I wanted this stuff out here but I think to those who know me it could serve as an interesting view into some thoughts that I don't often express elsewhere.
</p>
<br>
<br>
{% for work in works %}
<a href="/{{ work.path }}">{{ work.name }}</a> {{ work.date }}
{% endfor %}
</body>
</html>

View File

@ -4,3 +4,4 @@ waitress==2.1.2
Werkzeug==2.2.3
Flask-Session==0.5.0
Flask-WTF==1.1.1
requests==2.31.0