diff --git a/.gitignore b/.gitignore index 90ac1a7..4028b36 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,7 @@ -*.woff \ No newline at end of file +__pycache__ +*.md +!POST_TEMPLATE.md +!README.md + +docker-compose.yaml +*.sh \ No newline at end of file diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..67b613a --- /dev/null +++ b/Dockerfile @@ -0,0 +1,18 @@ +# syntax=docker/dockerfile:1 + +FROM python:3.12.2-slim-bookworm + +RUN apt-get update && apt-get upgrade -y + +RUN useradd -m app + +USER app + +COPY . . + +RUN python3 -m pip install --upgrade pip +RUN python3 -m pip install -r requirements.txt + +WORKDIR ./app + +CMD ["python3", "-u", "app.py"] diff --git a/README.md b/README.md new file mode 100644 index 0000000..d8282e3 --- /dev/null +++ b/README.md @@ -0,0 +1,9 @@ +# My-Website + +Code of the website hosted at https://www.0x01fe.net + +Could I gitignore the config files? +Yes. +Do I? +no. + diff --git a/app/app.py b/app/app.py new file mode 100644 index 0000000..3492a78 --- /dev/null +++ b/app/app.py @@ -0,0 +1,155 @@ +import glob +import configparser +import random + +import flask +import waitress +import markdown + +from post import Post + +app = flask.Flask(__name__, static_url_path='', static_folder='static') + +CONFIG_PATH = "./config.ini" +config = configparser.ConfigParser() +config.read(CONFIG_PATH) + +POSTS_FOLDER = config['POSTS']['POSTS_FOLDER'] +STATUS_FILE = config['STATUS']['STATUS_FILE'] +PORT = int(config['NETWORK']['PORT']) +DEV = int(config['NETWORK']['DEV']) + +def get_posts(category_filter : str | None = None) -> list[Post]: + post_files = glob.glob(f'{POSTS_FOLDER}/*') + try: + post_files.remove(f'{POSTS_FOLDER}/POST_TEMPLATE.md') + except ValueError as e: + print(e) + print(f'Couldn\'t remove the template file probably; {post_files}') + exit() + + posts: list[Post] = [] + for post_file in post_files: + post = Post(post_file) + + if not category_filter: + posts.append(post) + elif category_filter == post.category: + posts.append(post) + + # Order Posts by Date + ordered_posts = [] + for i in range(len(posts)): + + most_recent = posts[0] + for p in posts: + if p.date < most_recent.date: + most_recent = p + + ordered_posts.append(most_recent) + posts.remove(most_recent) + + return reversed(ordered_posts) + +def get_status() -> str: + with open(STATUS_FILE, 'r', encoding='utf-8') as file: + statuses = file.readlines() + + status = random.randint(0, len(statuses) - 1) + + return markdown.markdown(statuses[status]) + +# Main Page +@app.route('/') +def index(): + + # Get posts + posts = get_posts() + + post_bodies = [] + for post in posts: + post_bodies.append(post.body) + + # Get status + status = get_status() + + return flask.render_template('index.html', posts=post_bodies, status=status) + +# Games Page +@app.route('/games/') +def games(): + + # Get posts + posts = get_posts(category_filter="games") + + post_bodies = [] + for post in posts: + post_bodies.append(post.body) + + # Get status + status = get_status() + + return flask.render_template('games.html', posts=post_bodies, status=status) + +# Music Page +@app.route('/music/') +def music(): + + # Get posts + posts = get_posts(category_filter="music") + + post_bodies = [] + for post in posts: + post_bodies.append(post.body) + + # Get status + status = get_status() + + return flask.render_template('music.html', posts=post_bodies, status=status) + +# Motion Pictures Page +@app.route('/motion-pictures/') +def motion_pictures(): + + # Get posts + posts = get_posts(category_filter="motion-pictures") + + post_bodies = [] + for post in posts: + post_bodies.append(post.body) + + # Get status + status = get_status() + + return flask.render_template('motion-pictures.html', posts=post_bodies, status=status) + +# Programming Page +@app.route('/programming/') +def programming(): + + # Get posts + posts = get_posts(category_filter="programming") + + post_bodies = [] + for post in posts: + post_bodies.append(post.body) + + # Get status + status = get_status() + + return flask.render_template('programming.html', posts=post_bodies, status=status) + +# About Page +@app.route('/about/') +def about(): + + # Get status + status = get_status() + + return flask.render_template('about.html', status=status) + +if __name__ == "__main__": + if DEV: + app.run(port=PORT) + else: + waitress.serve(app, host='0.0.0.0', port=PORT) diff --git a/app/config.ini b/app/config.ini new file mode 100644 index 0000000..8d00b71 --- /dev/null +++ b/app/config.ini @@ -0,0 +1,9 @@ +[POSTS] +posts_folder=./posts + +[STATUS] +status_file=./resources/status.text + +[NETWORK] +PORT=1111 +DEV=0 diff --git a/app/post.py b/app/post.py new file mode 100644 index 0000000..1de822a --- /dev/null +++ b/app/post.py @@ -0,0 +1,25 @@ +import markdown +import datetime + +class Post: + + category : str + author : str + date : datetime.datetime + body : str + file : str + + def __init__(self, file_path): + self.file = file_path + + with open(file_path, 'r', encoding='utf-8') as file: + lines = file.readlines() + + self.category = lines[1].split(":")[1].strip() + self.author = lines[2].split(":")[1].strip() + + date = lines[3].split(":")[1].strip() + self.date = datetime.datetime.strptime(date, "%d-%m-%Y") + + self.body = markdown.markdown(''.join(lines[6:])) + diff --git a/app/posts/POST_TEMPLATE.md b/app/posts/POST_TEMPLATE.md new file mode 100644 index 0000000..7fd0fb8 --- /dev/null +++ b/app/posts/POST_TEMPLATE.md @@ -0,0 +1,9 @@ +# Metadata +category: category +author: author +date: date + +# POST +## TITLE +### DATE OR SUBTITLE +POST TEXT diff --git a/app/resources/status.text b/app/resources/status.text new file mode 100644 index 0000000..c258209 --- /dev/null +++ b/app/resources/status.text @@ -0,0 +1,31 @@ +Catchy Right? +Everybody's lazy when they're tired +As long as there is delusion, there is hope +It's 510. +Mindful of the weary inkling that is lurking +Mortal traffic lights signaling when to stay or go +Cyber surgeon, Javascript person +Bone-dried swamplands swallow me +House of dust, land of bone +I ate dirt, I drank stone +Come on, snake, punish me +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. +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 +A tourist in a dream / A visitor, it seems / A half-forgotten song / Where do I belong? +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)! \ No newline at end of file diff --git a/app/static/style.css b/app/static/style.css new file mode 100644 index 0000000..5a6e542 --- /dev/null +++ b/app/static/style.css @@ -0,0 +1,150 @@ +/* Global Stuff */ +@import url('https://fonts.googleapis.com/css?family=PT%20Mono:700|PT%20Mono:400'); + +body { + font-family: 'PT Mono'; + font-weight: 400; +} + +h1, h2, h3, h4, h5 { + font-family: 'PT Mono'; + font-weight: 700; +} + +html { + --text: hsl(224, 83%, 91%); + --background: hsl(224, 31%, 23%); + --primary: hsl(229, 81%, 73%); + --primary10: hsla(209, 61%, 71%, 10%); + --primary20: hsla(209, 61%, 71%, 20%); + --primary40: hsla(209, 61%, 71%, 40%); + --secondary: hsl(277, 81%, 33%); + --accent: hsl(291, 81%, 60%); + --accent75: hsla(291, 81%, 60%, 75%); + --accent50: hsla(291, 81%, 60%, 50%); + + --main-background: var(--primary10); + --borders-style: hidden; + --border-radius: 15px; +} + + +body { + color: var(--text); + background-color: var(--background); +} + +a { + color: var(--text); +} + +a:hover { + color: var(--accent); +} + + + + +/* Other */ + +.header { + text-align: center; + + margin: 0 30%; + padding: 2em; + + border-style: var(--borders-style); + border-color: #1E2022; + background-color: var(--background); + border-radius: var(--border-radius); +} + +.header a { + text-decoration: none; + color: var(--primary); +} + +.container { + + display: flex; + flex-direction: row; + + margin: 0px 10%; + + border-style: var(--borders-style); + border-color: #1E2022; + background-color: var(--main-background); + border-radius: var(--border-radius); +} + +.sidebar { + height: fit-content; + align-self: flex-start; + position: sticky; + top: 10px; + + padding: 20pt; + + margin: 5em 0; + margin-left: 2em; + + border-style: var(--borders-style); + border-radius: var(--border-radius); + border-color: #1E2022; + background-color: var(--main-background); + + opacity: 0.9; + + /* Text Settings */ + font-weight: bold; + line-height: 30pt; +} + +.sidebar a { + text-decoration: none; +} + +.dlog { + flex: 3; + + display: flex; + flex-direction: column; + + padding: 10pt; + margin: 0 5%; + margin-left: 0; + + border-style: var(--borders-style); + border-radius: var(--border-radius); + border-color: #1E2022; + /* background-color: var(--main-background); */ +} + +.post { + + border-style: var(--borders-style); + border-radius: var(--border-radius); + + padding: 1.5em 2em; + margin: 1em 2em; + + /* background-color: var(--main-background); */ +} + +.post h2 { + 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; +} + +.post p { + line-height: 2.25; + text-indent: 3em; +} diff --git a/app/templates/about.html b/app/templates/about.html new file mode 100644 index 0000000..a2663fc --- /dev/null +++ b/app/templates/about.html @@ -0,0 +1,41 @@ + + +
+ + + 0x01fe.net - About +
+ +
+

0x01fe.net

+ {{ status|safe }} +
+
+ + + + + +
+
+

About

+

+ Hi! I'm 0x01fe. This website is a personal project that allows me to express my thoughts online about things I like and also gives me something to program and tinker with on my spare time. If you want to contact me try hitting me up on discord at 0x01fe. +

+
+

Why 0x01fe?

+

+ This is a pretty common question I get regarding my username so I thought I'd put a little section here about it. The thought process behind the username was "I like computers so what's a computer related username I could have?" and the first thing that came to mind was the master boot record boot sector (100% related to that other Master Boot Record). So I opened up the Wikipedia Page on the master boot record and scrolled until something called out to me. When I saw the starting byte of the boot signature in hex was 0x01fe I thought "yeah that'd work", and I've stuck with it. +

+
+
+
+ + diff --git a/app/templates/games.html b/app/templates/games.html new file mode 100644 index 0000000..d023f8b --- /dev/null +++ b/app/templates/games.html @@ -0,0 +1,33 @@ + + +
+ + + 0x01fe.net - Games +
+ +
+

Games

+ {{ status|safe }} +
+
+ + + + + +
+ {% for post in posts %} +
{{ post|safe }}
+ {% endfor %} +
+
+ + diff --git a/app/templates/index.html b/app/templates/index.html new file mode 100644 index 0000000..a5bfb0c --- /dev/null +++ b/app/templates/index.html @@ -0,0 +1,33 @@ + + +
+ + + 0x01fe.net +
+ +
+

0x01fe.net

+ {{ status|safe }} +
+
+ + + + + +
+ {% for post in posts %} +
{{ post|safe }}
+ {% endfor %} +
+
+ + diff --git a/app/templates/motion-pictures.html b/app/templates/motion-pictures.html new file mode 100644 index 0000000..459f655 --- /dev/null +++ b/app/templates/motion-pictures.html @@ -0,0 +1,33 @@ + + +
+ + + 0x01fe.net - Motion Pictures +
+ +
+

Motion Pictures

+ {{ status|safe }} +
+
+ + + + + +
+ {% for post in posts %} +
{{ post|safe }}
+ {% endfor %} +
+
+ + diff --git a/app/templates/music.html b/app/templates/music.html new file mode 100644 index 0000000..9a00a11 --- /dev/null +++ b/app/templates/music.html @@ -0,0 +1,33 @@ + + +
+ + + 0x01fe.net - Music +
+ +
+

Music

+ {{ status|safe }} +
+
+ + + + + +
+ {% for post in posts %} +
{{ post|safe }}
+ {% endfor %} +
+
+ + diff --git a/app/templates/programming.html b/app/templates/programming.html new file mode 100644 index 0000000..91a5a31 --- /dev/null +++ b/app/templates/programming.html @@ -0,0 +1,33 @@ + + +
+ + + 0x01fe.net - Programming +
+ +
+

Programming

+ {{ status|safe }} +
+
+ + + + + +
+ {% for post in posts %} +
{{ post|safe }}
+ {% endfor %} +
+
+ + diff --git a/index.html b/index.html deleted file mode 100644 index f71eae4..0000000 --- a/index.html +++ /dev/null @@ -1,41 +0,0 @@ - - -
- - - 0x01fe.net -
- -
-

0x01fe.net

-

Catchy Right‽

-
-
- - - - - -
-
-

It's Peaks, Peaks of Yore

-

March 8th, 2024

-

Excuse the awful title please, but it truly is peak. Peaks of Yore has been a more enjoyable title than I could've ever expected. At first glance it seems like a "rage bait" game akin to the likes of Getting Over It With Bennett Foddy or Super Meatboy, but after the first few fundamental courses you realize the controls aren't fighting you, you just haven't mastered them yet.

-
-
-

Post Title

-

foobar

-
-
-

Post Title

-

foobar

-
-
-
- - diff --git a/index_style.css b/index_style.css deleted file mode 100644 index 89e3df0..0000000 --- a/index_style.css +++ /dev/null @@ -1,106 +0,0 @@ -/* Global Settings */ -@font-face { - font-family: ibmplexmono; - src: url(./IBMPlexMono-Regular.woff) format('woff'); -} - - -body { - /* font-family: 'Courier New', Courier, monospace; */ - font-family: ibmplexmono; -} - -a { - color: black; - text-decoration: none; -} - -a:hover { - color: hotpink; -} - - - - -/* Other */ - -.header { - text-align: center; - - margin: 10pt; - - border-style: solid; - border-color: #1E2022; - background-color: #F0F5F9; - border-radius: 5pt; -} - -.header h1 { - font-family: Arial, Helvetica, sans-serif; -} - -.container { - - display: flex; - flex-direction: row; - - border-style: solid; - border-color: #1E2022; - background-color: #F0F5F9; -} - -.sidebar { - order: 1; - float: left; - - padding: 20pt; - padding-bottom: 25%; - - margin: 15pt; - - border-style: solid; - border-radius: 10px; - border-color: #1E2022; - background-color: #C9D6DF; - - opacity: 0.9; - - /* Text Settings */ - font-weight: bold; - line-height: 30pt; -} - - -.dlog { - order: 2; - flex: 3; - text-align: center; - - display: flex; - flex-direction: column; - - padding: 10pt; - margin: 15pt; - margin-left: 15%; - margin-right: 15%; - - border-style: solid; - border-radius: 10px; - border-color: #1E2022; - background-color: #C9D6DF; -} - -.post { - /* opacity: 0.9; */ - - border: 2px solid #52616B; - border-radius: 10px; - - padding: 10pt; - - margin: 10pt; - margin-left: 20pt; - margin-right: 20pt; - - background-color: #C9D6DF; -} diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..bb91e2f --- /dev/null +++ b/requirements.txt @@ -0,0 +1,4 @@ +Markdown==3.5.2 +Flask==2.2.3 +waitress==2.1.2 +Werkzeug==2.2.3 \ No newline at end of file