Compare commits

..

No commits in common. "main" and "python+markdown" have entirely different histories.

23 changed files with 53 additions and 464 deletions

13
.gitignore vendored
View File

@ -4,15 +4,4 @@ __pycache__
!README.md
docker-compose.yaml
*.sh
*.ini
# Ignore images in posts
*.jpg
*.png
*.gif
# Writing
writing
*.sh

View File

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

View File

@ -2,5 +2,8 @@
Code of the website hosted at https://www.0x01fe.net
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!
Could I gitignore the config files?
Yes.
Do I?
no.

View File

@ -1,10 +1,7 @@
import os
import glob
import configparser
import random
import datetime
import requests
import flask
import waitress
import markdown
@ -17,16 +14,11 @@ 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'])
DEV = int(config['NETWORK']['DEV'])
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:
@ -59,36 +51,13 @@ def get_posts(category_filter : str | None = None) -> list[Post]:
return reversed(ordered_posts)
def read_status_file() -> dict:
with open(STATUS_FILE, 'r', encoding='utf-8') as file:
data = file.readlines()
result = {}
current_key = None
for line in data:
if line[0] == '#':
# 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())
with open(STATUS_FILE, 'r', encoding='utf-8') as file:
statuses = file.readlines()
selected_key = keys[random.randint(0, len(keys) - 1)]
section: list = statuses[selected_key]
status = random.randint(0, len(statuses) - 1)
selected_status = section[random.randint(0, len(section) - 1)]
return f'<div title="{selected_key}">{markdown.markdown(selected_status)}</div>'
return markdown.markdown(statuses[status])
# Main Page
@app.route('/')
@ -106,16 +75,6 @@ def index():
return flask.render_template('index.html', posts=post_bodies, status=status)
# 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():
@ -146,25 +105,7 @@ def music():
# Get status
status = get_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)
return flask.render_template('music.html', posts=post_bodies, status=status)
# Motion Pictures Page
@app.route('/motion-pictures/')
@ -198,31 +139,6 @@ 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():
@ -232,42 +148,7 @@ 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:

9
app/config.ini Normal file
View File

@ -0,0 +1,9 @@
[POSTS]
posts_folder=./posts
[STATUS]
status_file=./resources/status.text
[NETWORK]
PORT=1111
DEV=0

View File

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

View File

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

View File

@ -8,8 +8,6 @@ class Post:
date : datetime.datetime
body : str
file : str
title : str
url : str
def __init__(self, file_path):
self.file = file_path
@ -19,11 +17,9 @@ 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.body = markdown.markdown(f'# [{self.title}]({self.url})\n' + ''.join(lines[7:]))
self.body = markdown.markdown(''.join(lines[6:]))

View File

@ -1,112 +1,31 @@
# 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
Catchy Right?
Everybody's lazy when they're tired
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
# Face to Face by Daft Punk
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.
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
# 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
Solar Sect of Mystic Wisdom
~ Nuclear Fusion
Check out [NEUPINK](https://neupink.bandcamp.com/album/swordflower-hills-killer-2)!

View File

@ -1,19 +0,0 @@
.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

@ -1,12 +0,0 @@
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

@ -19,7 +19,6 @@ html {
--primary20: hsla(209, 61%, 71%, 20%);
--primary40: hsla(209, 61%, 71%, 40%);
--secondary: hsl(277, 81%, 33%);
--secondary50: hsla(277, 81%, 33%, 50%);
--accent: hsl(291, 81%, 60%);
--accent75: hsla(291, 81%, 60%, 75%);
--accent50: hsla(291, 81%, 60%, 50%);
@ -70,7 +69,7 @@ a:hover {
display: flex;
flex-direction: row;
margin: 0px 5%;
margin: 0px 10%;
border-style: var(--borders-style);
border-color: #1E2022;
@ -96,8 +95,6 @@ a:hover {
opacity: 0.9;
/* box-shadow: -10px 10px var(--accent); */
/* Text Settings */
font-weight: bold;
line-height: 30pt;
@ -107,39 +104,6 @@ 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;
@ -153,6 +117,7 @@ a:hover {
border-style: var(--borders-style);
border-radius: var(--border-radius);
border-color: #1E2022;
/* background-color: var(--main-background); */
}
.post {
@ -163,40 +128,18 @@ a:hover {
padding: 1.5em 2em;
margin: 1em 2em;
background-color: var(--main-background);
/* box-shadow: 10px 10px var(--accent); */
}
.post img {
border-style: var(--borders-style);
border-radius: var(--border-radius);
width: 90%;
padding: 0.5em;
margin: 0.5em 1em;
display: block;
margin-left: auto;
margin-right: auto;
background-color: var(--background);
}
.post h1 {
font-family: Georgia, 'Times New Roman', Times, serif;
font-weight: 100;
font-size: 26px;
text-decoration: underline;
text-decoration-style: solid;
text-decoration-thickness: 0.25em;
text-underline-offset: 7px;
text-decoration-color: var(--primary);
/* background-color: var(--main-background); */
}
.post h2 {
font-family: Georgia, 'Times New Roman', Times, serif;
text-decoration: underline;
text-decoration-style: solid;
text-decoration-thickness: 0.25em;
text-underline-offset: 6px;
text-decoration-color: var(--accent75);
}
.post h3 {
font-weight: 300;
font-size: 18px;
}
@ -205,49 +148,3 @@ a:hover {
line-height: 2.25;
text-indent: 3em;
}
/* 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,7 +18,6 @@
<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

@ -1,20 +0,0 @@
<!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,7 +18,6 @@
<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,12 +14,11 @@
<!-- 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="/writing/">Writing</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="./about/">About</a>
</div>
<!-- Main Page -->

View File

@ -18,7 +18,6 @@
<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,7 +18,6 @@
<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>
@ -29,20 +28,6 @@
<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,7 +18,6 @@
<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>
@ -29,12 +28,6 @@
<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

@ -1,14 +0,0 @@
<!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

@ -1,5 +1,4 @@
Markdown==3.5.2
Flask==2.2.3
waitress==2.1.2
Werkzeug==2.2.3
requests==2.31.0
Werkzeug==2.2.3