diff options
Diffstat (limited to 'edaweb')
213 files changed, 1736 insertions, 0 deletions
diff --git a/edaweb/app.py b/edaweb/app.py new file mode 100644 index 0000000..436df7a --- /dev/null +++ b/edaweb/app.py @@ -0,0 +1,256 @@ +from paste.translogger import TransLogger +from waitress import serve +from PIL import Image +import configparser +import transmission_rpc +import downloader +import datetime +import database +import services +import urllib +import random +import parser +import flask +import sys +import os +import io + +app = flask.Flask(__name__) +CONFIG = configparser.ConfigParser(interpolation = None) +CONFIG.read(os.path.join(os.path.dirname(__file__), "edaweb.conf")) +shown_images = set() +shown_sidebar_images = set() + +def get_pfp_img(db:database.Database): + global shown_images + dbimg = db.get_pfp_images() + if len(shown_images) == len(dbimg): + shown_images = set() + folder = set(dbimg).difference(shown_images) + choice = random.choice(list(folder)) + shown_images.add(choice) + return choice + +def get_sidebar_img(db:database.Database): + global shown_sidebar_images + dbimg = db.get_sidebar_images() + if len(shown_sidebar_images) == len(dbimg): + shown_sidebar_images = set() + folder = set(dbimg).difference(shown_sidebar_images) + choice = random.choice(list(folder)) + shown_sidebar_images.add(choice) + return choice + +def get_correct_article_headers(db:database.Database, title): + db_headers = list(db.get_header_articles()) + if title in [i[0] for i in db_headers]: + out = [] + for i in db_headers: + if i[0] != title: + out.append(i) + return out + [("index", "/~")] + else: + return db_headers + [("index", "/~")] + +def get_template_items(title, db): + return { + "links": db.get_header_links(), + "image": get_pfp_img(db), + "title": title, + "articles": get_correct_article_headers(db, title) + } + +@app.route("/") +@app.route("/~") +def index(): + with database.Database() as db: + with open(os.path.join(os.path.dirname(__file__), "static", "index.md"), "r") as f: + return flask.render_template( + "index.html.j2", + **get_template_items("eden's site :3", db), + days_till_ffs = datetime.datetime(2025, 11, 8) - datetime.datetime.now(), + markdown = parser.parse_text(f.read())[0], + featured_thoughts = db.get_featured_thoughts(), + commits = services.get_recent_commits(db)[:15], + sidebar_img = get_sidebar_img(db) + ) + +@app.route("/robots.txt") +def robots(): + return flask.send_from_directory("static", "robots.txt") + +@app.route("/services") +def serve_services(): + with database.Database() as db: + return flask.render_template( + "services.html.j2", + **get_template_items("services", db), + docker = services.get_all_docker_containers(), + trans = services.get_torrent_stats(), + pihole = services.get_pihole_stats() + ) + +@app.route("/discord") +def discord(): + with database.Database() as db: + return flask.render_template( + "discord.html.j2", + **get_template_items("discord", db), + discord = CONFIG["discord"]["username"] + ) + +@app.route("/thought") +def get_thought(): + thought_id = flask.request.args.get("id", type=int) + with database.Database() as db: + try: + category_name, title, dt, parsed, headers, redirect = parser.get_thought_from_id(db, thought_id) + # print(headers) + except TypeError: + flask.abort(404) + return + + if redirect is not None: + return flask.redirect(redirect, code = 301) + + return flask.render_template( + "thought.html.j2", + **get_template_items(title, db), + md_html = parsed, + contents_html = headers, + dt = "published: " + str(dt), + category = category_name, + othercategories = db.get_categories_not(category_name), + related = db.get_similar_thoughts(category_name, thought_id) + ) + +@app.route("/thoughts") +def get_thoughts(): + with database.Database() as db: + all_ = db.get_all_thoughts() + tree = {} + for id_, title, dt, category in all_: + if category not in tree.keys(): + tree[category] = [(id_, title, dt)] + else: + tree[category].append((id_, title, str(dt))) + + return flask.render_template( + "thoughts.html.j2", + **get_template_items("thoughts", db), + tree = tree + ) + +@app.route("/img/<filename>") +def serve_image(filename): + imdirpath = os.path.join(os.path.dirname(__file__), "static", "images") + if filename in os.listdir(imdirpath): + try: + w = int(flask.request.args['w']) + h = int(flask.request.args['h']) + except (KeyError, ValueError): + return flask.send_from_directory(imdirpath, filename) + + img = Image.open(os.path.join(imdirpath, filename)) + img.thumbnail((w, h), Image.LANCZOS) + io_ = io.BytesIO() + img.save(io_, format='JPEG') + return flask.Response(io_.getvalue(), mimetype='image/jpeg') + else: + flask.abort(404) + +@app.route("/nhdl") +def serve_nhdl(): + with database.Database() as db: + try: + nhentai_id = int(flask.request.args["id"]) + with downloader.CompressedImages(nhentai_id) as zippath: + # return app.send_static_file(os.path.split(zippath)[-1]) + return flask.redirect("/zip/%s" % os.path.split(zippath)[-1]) + + except (KeyError, ValueError): + return flask.render_template( + "nhdl.html.j2", + **get_template_items("Hentai Downloader", db) + ) + +@app.route("/isocd") +def serve_iso_form(): + with database.Database() as db: + return flask.render_template( + "isocd.html.j2", + **get_template_items("Get a GNU/Linux install CD", db), + iso_options = db.get_iso_cd_options() + ) + +@app.route("/zip/<zipfile>") +def serve_zip(zipfile): + return flask.send_from_directory(os.path.join(os.path.dirname(__file__), "static", "zips"), zipfile) + +@app.route("/pdf/<pdfname>") +def serve_pdf(pdfname): + return flask.send_from_directory(os.path.join(os.path.dirname(__file__), "static", "papers"), pdfname) + +@app.route("/nhdlredirect", methods = ["POST"]) +def redirect_nhdl(): + req = dict(flask.request.form) + try: + return flask.redirect("/nhdl?id=%i" % int(req["number_input"])) + except (TypeError, ValueError, KeyError): + flask.abort(400) + +@app.route("/getisocd", methods = ["POST"]) +def get_iso_cd(): + req = dict(flask.request.form) + print(req) + with database.Database() as db: + id_ = db.append_cd_orders(**req) + print(id_) + return flask.render_template( + "isocd_confirmation.html.j2", + **get_template_items("Get a GNU/Linux install CD", db), + email = req["email"], + req = req, + id_ = id_ + ) + +@app.route("/random") +def serve_random(): + try: + tags = flask.request.args['tags'].split(" ") + except KeyError: + flask.abort(400) + + sbi = services.get_random_image(tags) + req = urllib.request.Request(sbi.imurl) + mediaContent = urllib.request.urlopen(req).read() + with open(os.path.join(os.path.dirname(__file__), "static", "images", "random.jpg"), "wb") as f: + f.write(mediaContent) + + with database.Database() as db: + return flask.render_template( + "random.html.j2", + **get_template_items("random image", db), + sbi = sbi, + localimg = "/img/random.jpg?seed=%i" % random.randint(0, 9999) + ) + +@app.route("/questions") +def serve_questions(): + with database.Database() as db: + return flask.render_template( + "questions.html.j2", + **get_template_items("questions and answers", db), + qnas_link = CONFIG.get("qnas", "url"), + qnas = db.get_qnas() + ) + +if __name__ == "__main__": + try: + if sys.argv[1] == "--production": + #serve(TransLogger(app), host='127.0.0.1', port = 6969) + serve(TransLogger(app), host='0.0.0.0', port = 6969, threads = 32) + else: + app.run(host = "0.0.0.0", port = 5001, debug = True) + except IndexError: + app.run(host = "0.0.0.0", port = 5001, debug = True) diff --git a/edaweb/cache.py b/edaweb/cache.py new file mode 100644 index 0000000..5b66e43 --- /dev/null +++ b/edaweb/cache.py @@ -0,0 +1,18 @@ +import database +import services + +def update_cache(): + print("Updating cache...") + with database.Database() as db: + db.update_commit_cache(services.request_recent_commits(since = db.get_last_commit_time())) + print("Finished adding github commits...") + db.append_qnas(services.scrape_whispa(db.config.get("qnas", "url"), since = db.get_oldest_qna())) + print("Finished parsing Q&As...") + + print("Started getting docker information with SSH...") + print(services.cache_all_docker_containers(services.CONFIG.get("ssh", "docker_key_path"))) + print("Finished caching.") + + +if __name__ == "__main__": + update_cache()
\ No newline at end of file diff --git a/edaweb/database.py b/edaweb/database.py new file mode 100644 index 0000000..49ec33c --- /dev/null +++ b/edaweb/database.py @@ -0,0 +1,248 @@ +from urllib.parse import urlparse +from dataclasses import dataclass +from lxml import html +import configparser +import threading +import services +import operator +import datetime +import requests +import twython +import pymysql +import random +import os +import re + +@dataclass +class Database: + safeLogin:bool = True #automatically login with the user in the config file, who is read only + user:str = None #otherwise, login with the given username and passwd + passwd:str = None + + def __enter__(self): + self.config = configparser.ConfigParser(interpolation = None) + self.config.read(os.path.join(os.path.dirname(__file__), "edaweb.conf")) + + if self.safeLogin: + self.__connection = pymysql.connect( + **self.config["mysql"], + charset = "utf8mb4" + ) + else: + self.__connection = pymysql.connect( + user = self.user, + passwd = self.passwd, + host = self.config["mysql"]["host"], + db = self.config["mysql"]["db"], + charset = "utf8mb4" + ) + return self + + def __exit__(self, type, value, traceback): + self.__connection.commit() + self.__connection.close() + + def get_header_links(self): + with self.__connection.cursor() as cursor: + cursor.execute("SELECT name, link FROM headerLinks WHERE display = true ORDER BY name;") + return cursor.fetchall() + + def get_image(self, imageName): + with self.__connection.cursor() as cursor: + cursor.execute("SELECT alt, url FROM images WHERE imageName = %s;", (imageName, )) + return cursor.fetchone() + + def get_pfp_images(self): + with self.__connection.cursor() as cursor: + cursor.execute("SELECT alt, url FROM images WHERE pfp_img = 1;") + return cursor.fetchall() + + def get_sidebar_images(self): + with self.__connection.cursor() as cursor: + cursor.execute("SELECT alt, url FROM images WHERE sidebar_image = 1;") + return cursor.fetchall() + + def get_header_articles(self): + with self.__connection.cursor() as cursor: + cursor.execute("SELECT articleName, link FROM headerArticles WHERE display = true;") + return cursor.fetchall() + + def get_all_categories(self): + with self.__connection.cursor() as cursor: + cursor.execute("SELECT category_name FROM categories;") + return [i[0] for i in cursor.fetchall()] + + def add_category(self, category): + if not category in self.get_all_categories(): + with self.__connection.cursor() as cursor: + cursor.execute("INSERT INTO categories (category_name) VALUES (%s);", (category, )) + + self.__connection.commit() + return True + + return False + + def add_thought(self, category, title, markdown): + with self.__connection.cursor() as cursor: + cursor.execute(""" + INSERT INTO thoughts (category_id, title, markdown_text) + VALUES (( + SELECT category_id FROM categories WHERE category_name = %s + ), %s, %s);""", (category, title, markdown)) + self.__connection.commit() + + def get_thought(self, id_): + with self.__connection.cursor() as cursor: + cursor.execute(""" + SELECT categories.category_name, thoughts.title, thoughts.dt, thoughts.markdown_text, thoughts.redirect + FROM thoughts INNER JOIN categories + ON thoughts.category_id = categories.category_id + WHERE thought_id = %s;""", (id_, )) + return cursor.fetchone() + + def get_similar_thoughts(self, category, id_): + with self.__connection.cursor() as cursor: + cursor.execute(""" + SELECT thought_id, title, dt, category_name FROM thoughts + INNER JOIN categories ON thoughts.category_id = categories.category_id + WHERE category_name = %s AND thought_id != %s;""", + (category, id_)) + return cursor.fetchall() + + def get_featured_thoughts(self): + with self.__connection.cursor() as cursor: + cursor.execute("SELECT thought_id, title FROM thoughts WHERE featured = 1;") + return cursor.fetchall() + + def update_thought_markdown(self, id_, markdown): + with self.__connection.cursor() as cursor: + cursor.execute("UPDATE thoughts SET markdown_text = %s WHERE thought_id = %s;", (markdown, id_)) + self.__connection.commit() + + def get_categories_not(self, category_name): + with self.__connection.cursor() as cursor: + cursor.execute("SELECT category_name FROM categories WHERE category_name != %s;", (category_name, )) + return [i[0] for i in cursor.fetchall()] + + def get_all_thoughts(self): + with self.__connection.cursor() as cursor: + cursor.execute(""" + SELECT thought_id, title, dt, category_name FROM thoughts + INNER JOIN categories ON thoughts.category_id = categories.category_id; + """) + return cursor.fetchall() + + def get_cached_tweets(self, numToGet = None): + with self.__connection.cursor() as cursor: + sql = "SELECT tweet, tweet_id, account FROM diary WHERE account = %s ORDER BY tweeted_at DESC" + args = (self.config.get("twitter", "main_account"), ) + if numToGet is not None: + sql += " LIMIT %s;" + args = (self.config.get("twitter", "main_account"), numToGet) + else: + sql += ";" + cursor.execute(sql, args) + + return [(i[0], "https://%s/%s/status/%d" % (self.config.get("nitter", "outsideurl"), i[2], i[1])) for i in cursor.fetchall()] + + def get_cached_commits(self, since = None, recurse = True): + with self.__connection.cursor() as cursor: + if since is not None: + cursor.execute("SELECT DISTINCT message, url, commitTime, additions, deletions, total FROM commitCache WHERE commitTime > %s ORDER BY commitTime DESC;", (since, )) + else: + cursor.execute("SELECT DISTINCT message, url, commitTime, additions, deletions, total FROM commitCache ORDER BY commitTime DESC;") + # i think i might have spent too long doing functional programming + return [{ + "repo": urlparse(i[1]).path.split("/")[2], + "github_repo_url": "https://github.com" + "/".join(urlparse(i[1]).path.split("/")[:3]), + "git_repo_url": "https://%s/%s.git/about" % (self.config.get("github", "personal_domain"), urlparse(i[1]).path.split("/")[2]), + "message": i[0], + "github_commit_url": i[1], + "git_commit_url": "https://%s/%s.git/commit/?id=%s" % ( + self.config.get("github", "personal_domain"), + urlparse(i[1]).path.split("/")[2], + urlparse(i[1]).path.split("/")[-1] + ), + "datetime": i[2].timestamp(), + "stats": { + "additions": i[3], + "deletions": i[4], + "total": i[5] + } + } for i in cursor.fetchall()] + + def update_commit_cache(self, requested): + with self.__connection.cursor() as cursor: + for commit in requested: + cursor.execute("SELECT DISTINCT url FROM commitCache;") + urls = [i[0] for i in cursor.fetchall()] + + if commit["url"] not in urls: + cursor.execute(""" + INSERT INTO commitCache (message, url, commitTime, additions, deletions, total) + VALUES (%s, %s, %s, %s, %s, %s)""", + (commit["message"], commit["url"], commit["datetime"], commit["stats"]["additions"], commit["stats"]["deletions"], commit["stats"]["total"]) + ) + self.__connection.commit() + + def get_last_commit_time(self): + with self.__connection.cursor() as cursor: + cursor.execute("SELECT MAX(commitTime) FROM commitCache;") + return cursor.fetchone()[0] + + def get_my_twitter(self): + with self.__connection.cursor() as cursor: + cursor.execute("SELECT link FROM headerLinks WHERE name = 'twitter';") + return cursor.fetchone()[0] + + def get_my_diary_twitter(self): + return self.config.get("twitter", "diary_account") + + def get_iso_cd_options(self): + iso_dir = self.config.get("cds", "location") + return [ + i + for i in os.listdir(iso_dir) + if os.path.splitext(i)[-1].lower() in [".iso"] + and os.path.getsize(os.path.join(iso_dir, i)) < self.config.getint("cds", "maxsize") + ] + + def append_cd_orders(self, iso, email, house, street, city, county, postcode, name): + with self.__connection.cursor() as cursor: + cursor.execute(""" + INSERT INTO cd_orders_2 (iso, email, house, street, city, county, postcode, name) + VALUES (%s, %s, %s, %s, %s, %s, %s, %s); + """, (iso, email, house, street, city, county, postcode, name)) + id_ = cursor.lastrowid + self.__connection.commit() + return id_ + + def append_qnas(self, qnas): + with self.__connection.cursor() as cursor: + for qna in qnas: + cursor.execute("SELECT curiouscat_id FROM qnas WHERE curiouscat_id = %s;", (qna["id"], )) + if cursor.fetchone() is None: + + cursor.execute("INSERT INTO `qnas` VALUES (%s, %s, %s, %s, %s, %s);", ( + qna["id"], qna["link"], qna["datetime"], qna["question"], qna["answer"], qna["host"] + )) + print("Appended question with timestamp %s" % qna["datetime"].isoformat()) + + else: + print("Skipped question with timestamp %s" % qna["datetime"].isoformat()) + self.__connection.commit() + + def get_oldest_qna(self): + with self.__connection.cursor() as cursor: + cursor.execute("SELECT MAX(timestamp) FROM qnas;") + return cursor.fetchone()[0] + + def get_qnas(self): + with self.__connection.cursor() as cursor: + cursor.execute("SELECT * FROM qnas;") + return sorted(cursor.fetchall(), key = operator.itemgetter(2), reverse = True) + + + + + diff --git a/edaweb/downloader.py b/edaweb/downloader.py new file mode 100644 index 0000000..4b2af2f --- /dev/null +++ b/edaweb/downloader.py @@ -0,0 +1,54 @@ +from dataclasses import dataclass +from lxml import html +import requests +import shutil +import urllib +import os + +@dataclass +class CompressedImages: + nhentai_id: int + + def __enter__(self): + self.folderpath = os.path.join("static", str(self.nhentai_id)) + self.zippath = os.path.join("static", "zips", "%i.zip" % self.nhentai_id) + os.mkdir(self.folderpath) + + self.num_downloaded = self.download_images("https://nhentai.net/g/%i" % self.nhentai_id, self.folderpath, "nhentai.net") + + shutil.make_archive(self.zippath[:-4], "zip", self.folderpath) + + return self.zippath + + def __exit__(self, type, value, traceback): + # os.remove(self.zippath) + shutil.rmtree(self.folderpath) + + def download_images(self, url:str, out:str, domain:str) -> int: + tree = html.fromstring(requests.get(url).content) + for i, element in enumerate(tree.xpath("//a[@class='gallerythumb']"), 1): + imurl = self.get_img("https://%s%s" % (domain, element.get("href")), i) + print(imurl) + self.dl_img(imurl, out) + + return i + + def get_img(self, srcurl:str, num:int) -> str: + tree = html.fromstring(requests.get(srcurl).content) + for element in tree.xpath("//img"): + try: + if num == int(os.path.splitext(element.get("src").split("/")[-1])[0]): + return element.get("src") + except ValueError: + pass + + def dl_img(self, imurl, outpath:str): + req = urllib.request.Request(imurl, headers = {'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_5_8) AppleWebKit/534.50.2 (KHTML, like Gecko) Version/5.0.6 Safari/533.22.3'}) + mediaContent = urllib.request.urlopen(req).read() + with open(os.path.join(outpath, imurl.split("/")[-1]), "wb") as f: + f.write(mediaContent) + +if __name__ == "__main__": + with CompressedImages(306013) as zippath: + import subprocess + subprocess.run(["cp", zippath, "/home/eden/Downloads"])
\ No newline at end of file diff --git a/edaweb/parser.py b/edaweb/parser.py new file mode 100644 index 0000000..00daf3b --- /dev/null +++ b/edaweb/parser.py @@ -0,0 +1,209 @@ +#!/usr/bin/env python3 + +from urllib.parse import urlparse +from pygments import highlight +from pygments.formatters import HtmlFormatter, ClassNotFound +from pygments.lexers import get_lexer_by_name +import urllib.parse +import webbrowser +import lxml.etree +import lxml.html +import database +import argparse +import getpass +import houdini +import mistune +import jinja2 +import app +import sys +import re +import os + +class EdawebRenderer(mistune.HTMLRenderer): + def blockcode(self, text, lang): + try: + lexer = get_lexer_by_name(lang, stripall=True) + except ClassNotFound: + lexer = None + + if lexer: + formatter = HtmlFormatter() + return highlight(text, lexer, formatter) + # default + return '\n<pre><code>{}</code></pre>\n'.format(houdini.escape_html(text.strip())) + + def block_quote(self, content): + content = content[3:-5] # idk why this is required... + out = '\n<blockquote>' + for line in houdini.escape_html(content.strip()).split("\n"): + out += '\n<span class="quote">{}</span><br>'.format(line) + return out + '\n</blockquote>' + + def image(self, link, text, title): + return "<a href='%s' target='_blank'><img alt='%s' src='%s'></a>" % ( + urlparse(link)._replace(query='').geturl(), text, link + ) + + def heading(self, text, level): + hash_ = urllib.parse.quote_plus(text) + return "<h%d id='%s'>%s <a class='header_linker' href='#%s'>[#]</a></h%d>" % ( + level, hash_, text, hash_, level + ) + + # it would appear that the escape=False option does not work with custom renderers, + # so we set it to True and just have these silly function stubs to include them manually + def inline_html(self, html): + return html + + def block_html(self, html): + return html + +def get_thought_from_id(db, id_): + category_name, title, dt, markdown, redirect = db.get_thought(id_) + html, headers = parse_text(markdown) + return category_name, title, dt, html, headers, redirect + +def parse_file(path): + with open(path, "r") as f: + unformatted = f.read() + + return parse_text(unformatted)[0] + +def parse_text(unformatted): + md = mistune.create_markdown( + renderer = EdawebRenderer(), + plugins = ["strikethrough", "table", "url", "task_lists", "def_list"], + # escape = False + ) + html = md(unformatted) + if html == "": + return "", "" + + return html, get_headers(html) + +def get_headers(html): + root = lxml.html.fromstring(html) + + headers = [] + thesmallestlevel = 7 + for node in root.xpath('//h1|//h2|//h3|//h4|//h5//h6'): + level = int(node.tag[-1]) + if level < thesmallestlevel: + thesmallestlevel = level + headers.append(( + # lxml.etree.tostring(node), + # "<p>%s</p>" % urllib.parse.unquote_plus(node.attrib["id"]), # possibly insecure? + urllib.parse.unquote_plus(node.attrib["id"]), + level, # -horrible hack + "#%s" % node.attrib["id"]) + ) + + headers = [(i[0], i[1] - thesmallestlevel, i[2]) for i in headers] + # print(headers) + # there is a bug here- + # it must start with the largest header and only go up and down in increments of one + # TODO: fix it! + md_template = jinja2.Template(""" +{% for text, depth, link in contents %} +{{ " " * depth }} - [{{ text }}]({{ link }}) +{% endfor %} + """) + + return mistune.html(md_template.render(contents = headers)) + +def main(): + p = argparse.ArgumentParser() + subparse = p.add_subparsers(help = "sub-command help") + save_parser = subparse.add_parser("save", help = "Add a markdown file to the database") + echo_parser = subparse.add_parser("echo", help = "Print markdown render to stdout") + update_parser = subparse.add_parser("update", help = "Replace a markdown file") + export_parser = subparse.add_parser("export", help = "Export a database markdown file to disk") + list_parser = subparse.add_parser("list", help = "List all the markdowns in the database") + + for s in [save_parser, echo_parser, update_parser]: + s.add_argument( + "-m", "--markdown", + help = "Path to a markdown file", + type = str, + required = True + ) + + for s in [save_parser]: + s.add_argument( + "-t", "--title", + help = "Article title", + type = str, + required = True + ) + s.add_argument( + "-c", "--category", + help = "Article category", + type = str, + required = True + ) + + for s in [save_parser, update_parser, export_parser, list_parser]: + s.add_argument( + "-u", "--username", + help = "Username to use for the database", + type = str, + required = True + ) + + for s in [export_parser, update_parser]: + s.add_argument( + "-i", "--id", + help = "Article's id", + type = int, + required = True + ) + + export_parser.add_argument( + "-o", "--out", + help = "Path to write the markdown file to", + type = str, + required = True + ) + + args = vars(p.parse_args()) + + if "username" in args.keys(): + args["password"] = getpass.getpass("Enter password for %s@%s: " % (args["username"], app.CONFIG["mysql"]["host"])) + + try: + verb = sys.argv[1] + except IndexError: + print("No verb specified... Nothing to do... Exiting...") + exit() + + if verb in ["save", "export", "update", "list"]: + with database.Database( + safeLogin = False, + user = args["username"], + passwd = args["password"] + ) as db: + if verb == "save": + if db.add_category(args["category"]): + print("Added category...") + with open(args["markdown"], "r") as f: + db.add_thought(args["category"], args["title"], f.read()) + print("Added thought...") + + elif verb == "export": + with open(args["out"], "w") as f: + f.writelines(db.get_thought(args["id"])[-2]) + print("Written to %s" % args["out"]) + + elif verb == "update": + with open(args["markdown"], "r") as f: + db.update_thought_markdown(args["id"], f.read()) + + elif verb == "list": + for id_, title, dt, category_name in db.get_all_thoughts(): + print("%d\t%s\t%s\t%s" % (id_, title, dt, category_name)) + + elif verb == "echo": + print(parse_file(args["markdown"])) + +if __name__ == "__main__": + main() diff --git a/edaweb/services.py b/edaweb/services.py new file mode 100644 index 0000000..5506ef1 --- /dev/null +++ b/edaweb/services.py @@ -0,0 +1,369 @@ +from dataclasses import dataclass +from io import StringIO +from lxml import html, etree +from github import Github +import multiprocessing +import paramiko.client +from APiHole import PiHole +import transmission_rpc +import configparser +import math as maths +import requests +import datetime +import urllib +import docker +import random +import subprocess +import fabric +import pickle +import queue +import json +import time +import os + +theLastId = 0 +CONFIG = configparser.ConfigParser(interpolation = None) +CONFIG.read(os.path.join(os.path.dirname(__file__), "edaweb.conf")) + +def humanbytes(B): + 'Return the given bytes as a human friendly KB, MB, GB, or TB string' + B = float(B) + KB = float(1024) + MB = float(KB ** 2) # 1,048,576 + GB = float(KB ** 3) # 1,073,741,824 + TB = float(KB ** 4) # 1,099,511,627,776 + + if B < KB: + return '{0} {1}'.format(B,'Bytes' if 0 == B > 1 else 'Byte') + elif KB <= B < MB: + return '{0:.2f} KB'.format(B/KB) + elif MB <= B < GB: + return '{0:.2f} MB'.format(B/MB) + elif GB <= B < TB: + return '{0:.2f} GB'.format(B/GB) + elif TB <= B: + return '{0:.2f} TB'.format(B/TB) + +@dataclass +class SafebooruImage: + id_: int + url: str + searchTags: list + tags: list + source: str + imurl: str + + def remove_tag(self, tag): + return list(set(self.searchTags).difference(set([tag]))) + +@dataclass +class DownloadedImage: + imurl: str + + def __enter__(self): + self.filename = os.path.join("static", "images", "random.jpg") + + req = urllib.request.Request(self.imurl, headers = {'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_5_8) AppleWebKit/534.50.2 (KHTML, like Gecko) Version/5.0.6 Safari/533.22.3'}) + mediaContent = urllib.request.urlopen(req).read() + with open(self.filename, "wb") as f: + f.write(mediaContent) + return self.filename + + def __exit__(self, type, value, traceback): + os.remove(self.filename) + +def get_num_pages(tags): + pages_url = "https://safebooru.org/index.php?page=post&s=list&tags=%s" % "+".join(tags) + tree = html.fromstring(requests.get(pages_url).content) + try: + finalpage_element = tree.xpath("/html/body/div[6]/div/div[2]/div[2]/div/a[12]")[0] + except IndexError: + return 1 + else: + return int(int(urllib.parse.parse_qs(finalpage_element.get("href"))["pid"][0]) / (5*8)) + +def get_id_from_url(url): + return int(urllib.parse.parse_qs(url)["id"][0]) + +def get_random_image(tags): + global theLastId + searchPage = random.randint(1, get_num_pages(tags)) * 5 * 8 + url = "https://safebooru.org/index.php?page=post&s=list&tags=%s&pid=%i" % ("+".join(tags), searchPage) + tree = html.fromstring(requests.get(url).content) + + imageElements = [e for e in tree.xpath("/html/body/div[6]/div/div[2]/div[1]")[0].iter(tag = "a")] + try: + element = random.choice(imageElements) + except IndexError: + # raise ConnectionError("Couldn't find any images") + return get_random_image(tags) + + url = "https://safebooru.org/" + element.get("href") + if get_id_from_url(url) == theLastId: + return get_random_image(tags) + theLastId = get_id_from_url(url) + + try: + sbi = SafebooruImage( + id_ = get_id_from_url(url), + url = url, + tags = element.find("img").get("alt").split(), + searchTags = tags, + source = fix_source_url(get_source(url)), + imurl = get_imurl(url) + ) + except (ConnectionError, KeyError) as e: + print("[ERROR]", e) + return get_random_image(tags) + + if link_deleted(sbi.url): + print("Retried since the source was deleted...") + return get_random_image(tags) + + return sbi + +def get_source(url): + tree = html.fromstring(requests.get(url).content) + for element in tree.xpath('//*[@id="stats"]')[0].iter("li"): + if element.text.startswith("Source: h"): + return element.text[8:] + elif element.text.startswith("Source:"): + for child in element.iter(): + if child.get("href") is not None: + return child.get("href") + raise ConnectionError("Couldn't find source image for id %i" % get_id_from_url(url)) + +def fix_source_url(url): + parsed = urllib.parse.urlparse(url) + if parsed.netloc == "www.pixiv.net": + return "https://www.pixiv.net/en/artworks/" + urllib.parse.parse_qs(parsed.query)["illust_id"][0] + elif parsed.netloc in ["bishie.booru.org", "www.secchan.net"]: + return ConnectionError("Couldn't get source") + elif "pximg.net" in parsed.netloc or "pixiv.net" in parsed.netloc: + return "https://www.pixiv.net/en/artworks/" + parsed.path.split("/")[-1][:8] + elif parsed.netloc == "twitter.com": + return url.replace("twitter.com", "nitter.eda.gay") + return url + +def get_imurl(url): + tree = html.fromstring(requests.get(url).content) + return tree.xpath('//*[@id="image"]')[0].get("src") + +def link_deleted(url): + text = requests.get(url).text + return text[text.find("<title>") + 7 : text.find("</title>")] in ["Error | nitter", "イラストコミュニケーションサービス[pixiv]"] + +def request_recent_commits(since = datetime.datetime.now() - datetime.timedelta(days=7)): + g = Github(CONFIG.get("github", "access_code")) + out = [] + for repo in g.get_user().get_repos(): + # print(repo.name, list(repo.get_branches())) + try: + for commit in repo.get_commits(since = since): + out.append({ + "repo": repo.name, + "message": commit.commit.message, + "url": commit.html_url, + "datetime": commit.commit.author.date, + "stats": { + "additions": commit.stats.additions, + "deletions": commit.stats.deletions, + "total": commit.stats.total + } + }) + except Exception as e: + print(repo, e) + + return sorted(out, key = lambda a: a["datetime"], reverse = True) + +def scrape_nitter(username, get_until:int): + new_tweets = [] + nitter_url = CONFIG.get("nitter", "internalurl") + nitter_port = CONFIG.getint("nitter", "internalport") + scrape_new_pages = True + url = "http://%s:%d/%s" % (nitter_url, nitter_port, username) + + while scrape_new_pages: + tree = html.fromstring(requests.get(url).content) + for i, tweetUrlElement in enumerate(tree.xpath('//*[@class="tweet-link"]'), 0): + if i > 0 and tweetUrlElement.get("href").split("/")[1] == username: + id_ = int(urllib.parse.urlparse(tweetUrlElement.get("href")).path.split("/")[-1]) + tweet_link = "http://%s:%d%s" % (nitter_url, nitter_port, tweetUrlElement.get("href")) + + if id_ == get_until: + scrape_new_pages = False + break + + try: + dt, replying_to, text, images = parse_tweet(tweet_link) + new_tweets.append((id_, dt, replying_to, text, username, images)) + print(dt, "'%s'" % text) + except IndexError: + print("Couldn't get any more tweets") + scrape_new_pages = False + break + except ConnectionError: + print("Rate limited, try again later") + return [] + + + try: + cursor = tree.xpath('//*[@class="show-more"]/a')[0].get("href") + except IndexError: + # no more elements + break + url = "http://%s:%d/%s%s" % (nitter_url, nitter_port, username, cursor) + + return new_tweets + +def parse_tweet(tweet_url): + # print(tweet_url) + tree = html.fromstring(requests.get(tweet_url).content) + # with open("2images.html", "r") as f: + # tree = html.fromstring(f.read()) + + rate_limited_elem = tree.xpath("/html/body/div/div/div/span") + if rate_limited_elem != []: + if rate_limited_elem[0].text == "Instance has been rate limited.": + raise ConnectionError("Instance has been rate limited.") + + main_tweet_elem = tree.xpath('//*[@class="main-tweet"]')[0] + + dt_str = main_tweet_elem.xpath('//*[@class="tweet-published"]')[0].text + dt = datetime.datetime.strptime(dt_str.replace("Â", ""), "%b %d, %Y · %I:%M %p UTC") + text = tree.xpath('//*[@class="main-tweet"]/div/div/div[2]')[0].text_content() + if text == "": + text = "[Image only]" + replying_to_elems = tree.xpath('//*[@class="before-tweet thread-line"]/div/a') + if replying_to_elems != []: + replying_to = int(urllib.parse.urlparse(replying_to_elems[-1].get("href")).path.split("/")[-1]) + else: + replying_to = None + + images = [] + images_elems = tree.xpath('//*[@class="main-tweet"]/div/div/div[3]/div/div/a/img') + for image_elem in images_elems: + images.append("https://" + CONFIG.get("nitter", "outsideurl") + urllib.parse.urlparse(image_elem.get("src")).path) + + return dt, replying_to, text, images + +def scrape_whispa(whispa_url, since = None): + tree = html.fromstring(requests.get(whispa_url).content.decode()) + qnas = [] + # we're not doing proper HTML scraping here really... since the site uses client side rendering + # we rather parse the JS scripts to get the JSON payload of useful information... sadly this looks horrible + for i, script in enumerate(tree.xpath("/html/body/script"), 0): + js = str(script.text) + if "receivedFeedback" in js: + # my god this is horrible... + for j in json.loads(json.loads(js[19:-1])[1][2:])[0][3]["loadedUser"]["receivedFeedback"]: + if j["childFeedback"] == []: + continue + + dt = datetime.datetime.fromisoformat(j["childFeedback"][0]["createdAt"][:-1]) + + qnas.append({ + # "id": int(str(maths.modf(maths.log(int(j["id"], 16)))[0])[2:]), + "id": int(dt.timestamp()), + "link": None, + "datetime": dt, + "question": j["content"], + "answer": j["childFeedback"][0]["content"], + "host": "whispa.sh" + }) + return qnas + +def get_docker_containers(host, ssh_key_path): + result = fabric.Connection( + host = host, + user = "root", + connect_kwargs = { + "key_filename": ssh_key_path, + "look_for_keys": False + } + ).run('docker ps -a -s --format "table {{.Names}};{{.Status}};{{.Image}}"', hide = True) + return [line.split(";") for line in result.stdout.split("\n")[1:-1]] + +def cache_all_docker_containers(ssh_key_path): + containers = {} + containers["containers"] = {} + for host, name in CONFIG["docker_hosts"].items(): + print(host) + containers["containers"][(host, name)] = get_docker_containers(host, ssh_key_path) + + containers["cachetime"] = "Docker information last updated at %s" % str(datetime.datetime.now()) + with open("/tmp/docker-cache.json", "wb") as f: + pickle.dump(containers, f) + +def get_all_docker_containers(): + if not os.path.exists("/tmp/docker-cache.json"): + return {"containers": {}, "cachetime": "No cached docker information"} + + with open("/tmp/docker-cache.json", "rb") as f: + return pickle.load(f) + +def timeout(func): + # cant get this to work with queue.Queue() for some reason? + # this works but Manager() uses an extra thread than Queue() + manager = multiprocessing.Manager() + returnVan = manager.list() + # ti = time.time() + + def runFunc(q, func): + q.append(func()) + + def beginTimeout(): + t = multiprocessing.Process(target = runFunc, args = (returnVan, func)) + t.start() + + t.join(timeout = CONFIG["servicetimeout"].getint("seconds")) + + # print("Request took:", time.time() - ti) + try: + return returnVan[0] + except IndexError: + if t.is_alive(): + t.terminate() + + return beginTimeout + +@timeout +def get_torrent_stats(): + client = transmission_rpc.client.Client( + host = CONFIG.get("transmission", "host") + ) + s = vars(client.session_stats())["fields"] + return { + "Active torrents:": s["activeTorrentCount"], + "Downloaded:": humanbytes(s["cumulative-stats"]["downloadedBytes"]), + "Uploaded:": humanbytes(s["cumulative-stats"]["uploadedBytes"]), + "Active time:": str(datetime.timedelta(seconds = s["cumulative-stats"]["secondsActive"])), + "Files added:": s["cumulative-stats"]["filesAdded"], + "Current upload speed:": humanbytes(s["uploadSpeed"]) + "s/S", + "Current download speed:": humanbytes(s["downloadSpeed"]) + "s/S" + } + +@timeout +def get_pihole_stats(): + return PiHole.GetSummary(CONFIG.get("pihole", "url"), CONFIG.get("pihole", "key"), True) + +def get_recent_commits(db, max_per_repo = 3): + cache = db.get_cached_commits() + num_per_repo = {} + out = [] + for commit in cache: + if commit["repo"] not in num_per_repo.keys(): + num_per_repo[commit["repo"]] = 0 + + num_per_repo[commit["repo"]] += 1 + if num_per_repo[commit["repo"]] <= max_per_repo: + out.append(commit) + + return sorted(out, key = lambda a: a["datetime"], reverse = True) + +if __name__ == "__main__": + print(scrape_whispa(CONFIG.get("qnas", "url"))) + # import database + + # with database.Database() as db: + # print(json.dumps(get_recent_commits(db), indent=4)) diff --git a/edaweb/static/images/0don0t4ofuc41-3776935852.jpg b/edaweb/static/images/0don0t4ofuc41-3776935852.jpg Binary files differnew file mode 100644 index 0000000..f65e951 --- /dev/null +++ b/edaweb/static/images/0don0t4ofuc41-3776935852.jpg diff --git a/edaweb/static/images/1544552064683.jpg b/edaweb/static/images/1544552064683.jpg Binary files differnew file mode 100644 index 0000000..20a6527 --- /dev/null +++ b/edaweb/static/images/1544552064683.jpg diff --git a/edaweb/static/images/1549844950404.jpg b/edaweb/static/images/1549844950404.jpg Binary files differnew file mode 100644 index 0000000..5197c11 --- /dev/null +++ b/edaweb/static/images/1549844950404.jpg diff --git a/edaweb/static/images/1555824429083.png b/edaweb/static/images/1555824429083.png Binary files differnew file mode 100644 index 0000000..5b2fd0b --- /dev/null +++ b/edaweb/static/images/1555824429083.png diff --git a/edaweb/static/images/1555824491105.png b/edaweb/static/images/1555824491105.png Binary files differnew file mode 100644 index 0000000..2e20fca --- /dev/null +++ b/edaweb/static/images/1555824491105.png diff --git a/edaweb/static/images/1671540582317176.png b/edaweb/static/images/1671540582317176.png Binary files differnew file mode 100644 index 0000000..dd741d3 --- /dev/null +++ b/edaweb/static/images/1671540582317176.png diff --git a/edaweb/static/images/1urouter.jpg b/edaweb/static/images/1urouter.jpg Binary files differnew file mode 100644 index 0000000..b295e59 --- /dev/null +++ b/edaweb/static/images/1urouter.jpg diff --git a/edaweb/static/images/20220401_222149.jpg b/edaweb/static/images/20220401_222149.jpg Binary files differnew file mode 100644 index 0000000..d9fecae --- /dev/null +++ b/edaweb/static/images/20220401_222149.jpg diff --git a/edaweb/static/images/324162a23865a6a7e75761871d29935314cbc2b3.jpg b/edaweb/static/images/324162a23865a6a7e75761871d29935314cbc2b3.jpg Binary files differnew file mode 100644 index 0000000..cede48f --- /dev/null +++ b/edaweb/static/images/324162a23865a6a7e75761871d29935314cbc2b3.jpg diff --git a/edaweb/static/images/3502e26d0181c684bc17b56188bde6e80569d191_full.jpg b/edaweb/static/images/3502e26d0181c684bc17b56188bde6e80569d191_full.jpg Binary files differnew file mode 100644 index 0000000..1f75924 --- /dev/null +++ b/edaweb/static/images/3502e26d0181c684bc17b56188bde6e80569d191_full.jpg diff --git a/edaweb/static/images/5600x.jpg b/edaweb/static/images/5600x.jpg Binary files differnew file mode 100644 index 0000000..f3995b2 --- /dev/null +++ b/edaweb/static/images/5600x.jpg diff --git a/edaweb/static/images/9400t.jpg b/edaweb/static/images/9400t.jpg Binary files differnew file mode 100644 index 0000000..175e8f1 --- /dev/null +++ b/edaweb/static/images/9400t.jpg diff --git a/edaweb/static/images/9400t_cooler.jpg b/edaweb/static/images/9400t_cooler.jpg Binary files differnew file mode 100644 index 0000000..dcfaf27 --- /dev/null +++ b/edaweb/static/images/9400t_cooler.jpg diff --git a/edaweb/static/images/E1NlPc1X0AEkB-s.png b/edaweb/static/images/E1NlPc1X0AEkB-s.png Binary files differnew file mode 100644 index 0000000..b0be028 --- /dev/null +++ b/edaweb/static/images/E1NlPc1X0AEkB-s.png diff --git a/edaweb/static/images/E3xdm-hWYAEADNx.jpg b/edaweb/static/images/E3xdm-hWYAEADNx.jpg Binary files differnew file mode 100644 index 0000000..d14513d --- /dev/null +++ b/edaweb/static/images/E3xdm-hWYAEADNx.jpg diff --git a/edaweb/static/images/E4WhXAvWYAIFwEa.png b/edaweb/static/images/E4WhXAvWYAIFwEa.png Binary files differnew file mode 100644 index 0000000..144eb45 --- /dev/null +++ b/edaweb/static/images/E4WhXAvWYAIFwEa.png diff --git a/edaweb/static/images/E4cjVaPXEAU83U0.png b/edaweb/static/images/E4cjVaPXEAU83U0.png Binary files differnew file mode 100644 index 0000000..941a436 --- /dev/null +++ b/edaweb/static/images/E4cjVaPXEAU83U0.png diff --git a/edaweb/static/images/E7ODIBeX0AAivRV.jpg b/edaweb/static/images/E7ODIBeX0AAivRV.jpg Binary files differnew file mode 100644 index 0000000..dc52196 --- /dev/null +++ b/edaweb/static/images/E7ODIBeX0AAivRV.jpg diff --git a/edaweb/static/images/E7ODIZEWUAMQjty.jpg b/edaweb/static/images/E7ODIZEWUAMQjty.jpg Binary files differnew file mode 100644 index 0000000..2e90eda --- /dev/null +++ b/edaweb/static/images/E7ODIZEWUAMQjty.jpg diff --git a/edaweb/static/images/E7ODIv0WUAUp-ad.jpg b/edaweb/static/images/E7ODIv0WUAUp-ad.jpg Binary files differnew file mode 100644 index 0000000..97e704e --- /dev/null +++ b/edaweb/static/images/E7ODIv0WUAUp-ad.jpg diff --git a/edaweb/static/images/E7ODJELX0AAVqna.jpg b/edaweb/static/images/E7ODJELX0AAVqna.jpg Binary files differnew file mode 100644 index 0000000..eedfb14 --- /dev/null +++ b/edaweb/static/images/E7ODJELX0AAVqna.jpg diff --git a/edaweb/static/images/EbmVCYKWkAAwXKW.jpg b/edaweb/static/images/EbmVCYKWkAAwXKW.jpg Binary files differnew file mode 100644 index 0000000..20b3a19 --- /dev/null +++ b/edaweb/static/images/EbmVCYKWkAAwXKW.jpg diff --git a/edaweb/static/images/Ffi1ducXEAArXDg.jpg b/edaweb/static/images/Ffi1ducXEAArXDg.jpg Binary files differnew file mode 100644 index 0000000..5c31cc5 --- /dev/null +++ b/edaweb/static/images/Ffi1ducXEAArXDg.jpg diff --git a/edaweb/static/images/GGBDzuSXMAA1Ktk.jpg b/edaweb/static/images/GGBDzuSXMAA1Ktk.jpg Binary files differnew file mode 100644 index 0000000..35e04e1 --- /dev/null +++ b/edaweb/static/images/GGBDzuSXMAA1Ktk.jpg diff --git a/edaweb/static/images/GSxGe_rXQAAgEhj.jpg b/edaweb/static/images/GSxGe_rXQAAgEhj.jpg Binary files differnew file mode 100644 index 0000000..0351920 --- /dev/null +++ b/edaweb/static/images/GSxGe_rXQAAgEhj.jpg diff --git a/edaweb/static/images/GTq-GOgWQAErvCp.jpg b/edaweb/static/images/GTq-GOgWQAErvCp.jpg Binary files differnew file mode 100644 index 0000000..6a2f7b4 --- /dev/null +++ b/edaweb/static/images/GTq-GOgWQAErvCp.jpg diff --git a/edaweb/static/images/GZhgzaK.png b/edaweb/static/images/GZhgzaK.png Binary files differnew file mode 100755 index 0000000..c73e8b4 --- /dev/null +++ b/edaweb/static/images/GZhgzaK.png diff --git a/edaweb/static/images/GcyexeCW0AAYssz.jpg b/edaweb/static/images/GcyexeCW0AAYssz.jpg Binary files differnew file mode 100644 index 0000000..c0762a8 --- /dev/null +++ b/edaweb/static/images/GcyexeCW0AAYssz.jpg diff --git a/edaweb/static/images/GegzRla.png b/edaweb/static/images/GegzRla.png Binary files differnew file mode 100755 index 0000000..cf12555 --- /dev/null +++ b/edaweb/static/images/GegzRla.png diff --git a/edaweb/static/images/IMG_-g4wqat.jpg b/edaweb/static/images/IMG_-g4wqat.jpg Binary files differnew file mode 100644 index 0000000..9f05aaf --- /dev/null +++ b/edaweb/static/images/IMG_-g4wqat.jpg diff --git a/edaweb/static/images/IMG_1602.jpg b/edaweb/static/images/IMG_1602.jpg Binary files differnew file mode 100644 index 0000000..d1937fb --- /dev/null +++ b/edaweb/static/images/IMG_1602.jpg diff --git a/edaweb/static/images/IMG_1603.jpg b/edaweb/static/images/IMG_1603.jpg Binary files differnew file mode 100644 index 0000000..4d3e8c1 --- /dev/null +++ b/edaweb/static/images/IMG_1603.jpg diff --git a/edaweb/static/images/IMG_1604.jpg b/edaweb/static/images/IMG_1604.jpg Binary files differnew file mode 100644 index 0000000..4cc82c3 --- /dev/null +++ b/edaweb/static/images/IMG_1604.jpg diff --git a/edaweb/static/images/IMG_1605.jpg b/edaweb/static/images/IMG_1605.jpg Binary files differnew file mode 100644 index 0000000..38d6770 --- /dev/null +++ b/edaweb/static/images/IMG_1605.jpg diff --git a/edaweb/static/images/IMG_1606.jpg b/edaweb/static/images/IMG_1606.jpg Binary files differnew file mode 100644 index 0000000..fcbe2a4 --- /dev/null +++ b/edaweb/static/images/IMG_1606.jpg diff --git a/edaweb/static/images/IMG_1607.jpg b/edaweb/static/images/IMG_1607.jpg Binary files differnew file mode 100644 index 0000000..825e338 --- /dev/null +++ b/edaweb/static/images/IMG_1607.jpg diff --git a/edaweb/static/images/IMG_1609.jpg b/edaweb/static/images/IMG_1609.jpg Binary files differnew file mode 100644 index 0000000..6b7d834 --- /dev/null +++ b/edaweb/static/images/IMG_1609.jpg diff --git a/edaweb/static/images/IMG_1610.jpg b/edaweb/static/images/IMG_1610.jpg Binary files differnew file mode 100644 index 0000000..d201596 --- /dev/null +++ b/edaweb/static/images/IMG_1610.jpg diff --git a/edaweb/static/images/IMG_1611.jpg b/edaweb/static/images/IMG_1611.jpg Binary files differnew file mode 100644 index 0000000..9eb1af5 --- /dev/null +++ b/edaweb/static/images/IMG_1611.jpg diff --git a/edaweb/static/images/IMG_1612.jpg b/edaweb/static/images/IMG_1612.jpg Binary files differnew file mode 100644 index 0000000..f176c17 --- /dev/null +++ b/edaweb/static/images/IMG_1612.jpg diff --git a/edaweb/static/images/IMG_1613.png b/edaweb/static/images/IMG_1613.png Binary files differnew file mode 100644 index 0000000..63b743a --- /dev/null +++ b/edaweb/static/images/IMG_1613.png diff --git a/edaweb/static/images/IMG_1614.png b/edaweb/static/images/IMG_1614.png Binary files differnew file mode 100644 index 0000000..349afb7 --- /dev/null +++ b/edaweb/static/images/IMG_1614.png diff --git a/edaweb/static/images/IMG_1615.jpg b/edaweb/static/images/IMG_1615.jpg Binary files differnew file mode 100644 index 0000000..da42a2b --- /dev/null +++ b/edaweb/static/images/IMG_1615.jpg diff --git a/edaweb/static/images/IMG_1616.jpg b/edaweb/static/images/IMG_1616.jpg Binary files differnew file mode 100644 index 0000000..6f83c38 --- /dev/null +++ b/edaweb/static/images/IMG_1616.jpg diff --git a/edaweb/static/images/IMG_1617.jpg b/edaweb/static/images/IMG_1617.jpg Binary files differnew file mode 100644 index 0000000..7528c7d --- /dev/null +++ b/edaweb/static/images/IMG_1617.jpg diff --git a/edaweb/static/images/IMG_1618.jpg b/edaweb/static/images/IMG_1618.jpg Binary files differnew file mode 100644 index 0000000..9b82ea1 --- /dev/null +++ b/edaweb/static/images/IMG_1618.jpg diff --git a/edaweb/static/images/IMG_1619.jpg b/edaweb/static/images/IMG_1619.jpg Binary files differnew file mode 100644 index 0000000..ccae28a --- /dev/null +++ b/edaweb/static/images/IMG_1619.jpg diff --git a/edaweb/static/images/IMG_1620.jpg b/edaweb/static/images/IMG_1620.jpg Binary files differnew file mode 100644 index 0000000..54e92d6 --- /dev/null +++ b/edaweb/static/images/IMG_1620.jpg diff --git a/edaweb/static/images/IMG_1621.jpg b/edaweb/static/images/IMG_1621.jpg Binary files differnew file mode 100644 index 0000000..5aebae0 --- /dev/null +++ b/edaweb/static/images/IMG_1621.jpg diff --git a/edaweb/static/images/IMG_1622.jpg b/edaweb/static/images/IMG_1622.jpg Binary files differnew file mode 100644 index 0000000..56cc9c3 --- /dev/null +++ b/edaweb/static/images/IMG_1622.jpg diff --git a/edaweb/static/images/IMG_1623.jpg b/edaweb/static/images/IMG_1623.jpg Binary files differnew file mode 100644 index 0000000..43d0107 --- /dev/null +++ b/edaweb/static/images/IMG_1623.jpg diff --git a/edaweb/static/images/IMG_1624.png b/edaweb/static/images/IMG_1624.png Binary files differnew file mode 100644 index 0000000..4fd690f --- /dev/null +++ b/edaweb/static/images/IMG_1624.png diff --git a/edaweb/static/images/IMG_1625.jpg b/edaweb/static/images/IMG_1625.jpg Binary files differnew file mode 100644 index 0000000..496a7fa --- /dev/null +++ b/edaweb/static/images/IMG_1625.jpg diff --git a/edaweb/static/images/IMG_1626.jpg b/edaweb/static/images/IMG_1626.jpg Binary files differnew file mode 100644 index 0000000..90060fb --- /dev/null +++ b/edaweb/static/images/IMG_1626.jpg diff --git a/edaweb/static/images/IMG_1627.jpg b/edaweb/static/images/IMG_1627.jpg Binary files differnew file mode 100644 index 0000000..90c4f49 --- /dev/null +++ b/edaweb/static/images/IMG_1627.jpg diff --git a/edaweb/static/images/IMG_1628.jpg b/edaweb/static/images/IMG_1628.jpg Binary files differnew file mode 100644 index 0000000..f2cc8c6 --- /dev/null +++ b/edaweb/static/images/IMG_1628.jpg diff --git a/edaweb/static/images/IMG_1629.jpg b/edaweb/static/images/IMG_1629.jpg Binary files differnew file mode 100644 index 0000000..b19b03e --- /dev/null +++ b/edaweb/static/images/IMG_1629.jpg diff --git a/edaweb/static/images/IMG_1630.jpg b/edaweb/static/images/IMG_1630.jpg Binary files differnew file mode 100644 index 0000000..ddef77b --- /dev/null +++ b/edaweb/static/images/IMG_1630.jpg diff --git a/edaweb/static/images/IMG_1632.jpg b/edaweb/static/images/IMG_1632.jpg Binary files differnew file mode 100644 index 0000000..070615a --- /dev/null +++ b/edaweb/static/images/IMG_1632.jpg diff --git a/edaweb/static/images/IMG_1633.jpg b/edaweb/static/images/IMG_1633.jpg Binary files differnew file mode 100644 index 0000000..6fa7ae8 --- /dev/null +++ b/edaweb/static/images/IMG_1633.jpg diff --git a/edaweb/static/images/IMG_1636.jpg b/edaweb/static/images/IMG_1636.jpg Binary files differnew file mode 100644 index 0000000..a3de5ad --- /dev/null +++ b/edaweb/static/images/IMG_1636.jpg diff --git a/edaweb/static/images/IMG_1637.jpg b/edaweb/static/images/IMG_1637.jpg Binary files differnew file mode 100644 index 0000000..8e6b489 --- /dev/null +++ b/edaweb/static/images/IMG_1637.jpg diff --git a/edaweb/static/images/IMG_1638.jpg b/edaweb/static/images/IMG_1638.jpg Binary files differnew file mode 100644 index 0000000..b9ca9f3 --- /dev/null +++ b/edaweb/static/images/IMG_1638.jpg diff --git a/edaweb/static/images/IMG_1639.jpg b/edaweb/static/images/IMG_1639.jpg Binary files differnew file mode 100644 index 0000000..5695e58 --- /dev/null +++ b/edaweb/static/images/IMG_1639.jpg diff --git a/edaweb/static/images/IMG_1640.jpg b/edaweb/static/images/IMG_1640.jpg Binary files differnew file mode 100644 index 0000000..df3eaea --- /dev/null +++ b/edaweb/static/images/IMG_1640.jpg diff --git a/edaweb/static/images/IMG_1641.jpg b/edaweb/static/images/IMG_1641.jpg Binary files differnew file mode 100644 index 0000000..ce2eddb --- /dev/null +++ b/edaweb/static/images/IMG_1641.jpg diff --git a/edaweb/static/images/IMG_20210422_212009.jpg b/edaweb/static/images/IMG_20210422_212009.jpg Binary files differnew file mode 100644 index 0000000..a8337c4 --- /dev/null +++ b/edaweb/static/images/IMG_20210422_212009.jpg diff --git a/edaweb/static/images/IMG_20210824_175000.jpg b/edaweb/static/images/IMG_20210824_175000.jpg Binary files differnew file mode 100644 index 0000000..216c617 --- /dev/null +++ b/edaweb/static/images/IMG_20210824_175000.jpg diff --git a/edaweb/static/images/IMG_20220809_172130442_HDR.jpg b/edaweb/static/images/IMG_20220809_172130442_HDR.jpg Binary files differnew file mode 100644 index 0000000..e1987f8 --- /dev/null +++ b/edaweb/static/images/IMG_20220809_172130442_HDR.jpg diff --git a/edaweb/static/images/IMG_20220811_133224877_HDR.jpg b/edaweb/static/images/IMG_20220811_133224877_HDR.jpg Binary files differnew file mode 100644 index 0000000..eb05b1b --- /dev/null +++ b/edaweb/static/images/IMG_20220811_133224877_HDR.jpg diff --git a/edaweb/static/images/IMG_20220811_133224877_HDR_crop.jpg b/edaweb/static/images/IMG_20220811_133224877_HDR_crop.jpg Binary files differnew file mode 100644 index 0000000..7bc63ba --- /dev/null +++ b/edaweb/static/images/IMG_20220811_133224877_HDR_crop.jpg diff --git a/edaweb/static/images/IMG_20220812_112838125_HDR.jpg b/edaweb/static/images/IMG_20220812_112838125_HDR.jpg Binary files differnew file mode 100644 index 0000000..6e56a49 --- /dev/null +++ b/edaweb/static/images/IMG_20220812_112838125_HDR.jpg diff --git a/edaweb/static/images/IMG_20220823_154457137_HDR.jpg b/edaweb/static/images/IMG_20220823_154457137_HDR.jpg Binary files differnew file mode 100644 index 0000000..b46f0fe --- /dev/null +++ b/edaweb/static/images/IMG_20220823_154457137_HDR.jpg diff --git a/edaweb/static/images/IMG_20221023_163821542.jpg b/edaweb/static/images/IMG_20221023_163821542.jpg Binary files differnew file mode 100644 index 0000000..f2284df --- /dev/null +++ b/edaweb/static/images/IMG_20221023_163821542.jpg diff --git a/edaweb/static/images/IMG_20230812_132400733_HDR.jpg b/edaweb/static/images/IMG_20230812_132400733_HDR.jpg Binary files differnew file mode 100644 index 0000000..9f46bdc --- /dev/null +++ b/edaweb/static/images/IMG_20230812_132400733_HDR.jpg diff --git a/edaweb/static/images/IMG_20230812_132632784_HDR.jpg b/edaweb/static/images/IMG_20230812_132632784_HDR.jpg Binary files differnew file mode 100644 index 0000000..82060d1 --- /dev/null +++ b/edaweb/static/images/IMG_20230812_132632784_HDR.jpg diff --git a/edaweb/static/images/JwL2S2V.png b/edaweb/static/images/JwL2S2V.png Binary files differnew file mode 100755 index 0000000..9394c56 --- /dev/null +++ b/edaweb/static/images/JwL2S2V.png diff --git a/edaweb/static/images/PXL_20250314_150055804.jpg b/edaweb/static/images/PXL_20250314_150055804.jpg Binary files differnew file mode 100644 index 0000000..b660e18 --- /dev/null +++ b/edaweb/static/images/PXL_20250314_150055804.jpg diff --git a/edaweb/static/images/Screenshot_20210520-221830.png b/edaweb/static/images/Screenshot_20210520-221830.png Binary files differnew file mode 100644 index 0000000..33afee7 --- /dev/null +++ b/edaweb/static/images/Screenshot_20210520-221830.png diff --git a/edaweb/static/images/Screenshot_20210527_122432.png b/edaweb/static/images/Screenshot_20210527_122432.png Binary files differnew file mode 100644 index 0000000..33432ff --- /dev/null +++ b/edaweb/static/images/Screenshot_20210527_122432.png diff --git a/edaweb/static/images/Screenshot_20210620-144127.png b/edaweb/static/images/Screenshot_20210620-144127.png Binary files differnew file mode 100644 index 0000000..dd9b43a --- /dev/null +++ b/edaweb/static/images/Screenshot_20210620-144127.png diff --git a/edaweb/static/images/Screenshot_20210620-231652.png b/edaweb/static/images/Screenshot_20210620-231652.png Binary files differnew file mode 100644 index 0000000..5e2532d --- /dev/null +++ b/edaweb/static/images/Screenshot_20210620-231652.png diff --git a/edaweb/static/images/Screenshot_20210727-072303.png b/edaweb/static/images/Screenshot_20210727-072303.png Binary files differnew file mode 100644 index 0000000..7c03644 --- /dev/null +++ b/edaweb/static/images/Screenshot_20210727-072303.png diff --git a/edaweb/static/images/Screenshot_20210727-072344.png b/edaweb/static/images/Screenshot_20210727-072344.png Binary files differnew file mode 100644 index 0000000..248644a --- /dev/null +++ b/edaweb/static/images/Screenshot_20210727-072344.png diff --git a/edaweb/static/images/Screenshot_20210727-223004.png b/edaweb/static/images/Screenshot_20210727-223004.png Binary files differnew file mode 100644 index 0000000..dbe0630 --- /dev/null +++ b/edaweb/static/images/Screenshot_20210727-223004.png diff --git a/edaweb/static/images/Screenshot_20210731-181223.png b/edaweb/static/images/Screenshot_20210731-181223.png Binary files differnew file mode 100644 index 0000000..b1547be --- /dev/null +++ b/edaweb/static/images/Screenshot_20210731-181223.png diff --git a/edaweb/static/images/Screenshot_20210731-181229.png b/edaweb/static/images/Screenshot_20210731-181229.png Binary files differnew file mode 100644 index 0000000..363c17b --- /dev/null +++ b/edaweb/static/images/Screenshot_20210731-181229.png diff --git a/edaweb/static/images/Screenshot_20210811-125853.png b/edaweb/static/images/Screenshot_20210811-125853.png Binary files differnew file mode 100644 index 0000000..7d45240 --- /dev/null +++ b/edaweb/static/images/Screenshot_20210811-125853.png diff --git a/edaweb/static/images/Screenshot_20210818-203828.png b/edaweb/static/images/Screenshot_20210818-203828.png Binary files differnew file mode 100644 index 0000000..8026a0c --- /dev/null +++ b/edaweb/static/images/Screenshot_20210818-203828.png diff --git a/edaweb/static/images/Screenshot_20210825-131938.png b/edaweb/static/images/Screenshot_20210825-131938.png Binary files differnew file mode 100644 index 0000000..4b16443 --- /dev/null +++ b/edaweb/static/images/Screenshot_20210825-131938.png diff --git a/edaweb/static/images/Startech.jpg b/edaweb/static/images/Startech.jpg Binary files differnew file mode 100644 index 0000000..ba7f02f --- /dev/null +++ b/edaweb/static/images/Startech.jpg diff --git a/edaweb/static/images/a4-5000.jpg b/edaweb/static/images/a4-5000.jpg Binary files differnew file mode 100644 index 0000000..f26fd66 --- /dev/null +++ b/edaweb/static/images/a4-5000.jpg diff --git a/edaweb/static/images/aLvcFjj.png b/edaweb/static/images/aLvcFjj.png Binary files differnew file mode 100755 index 0000000..c928ba7 --- /dev/null +++ b/edaweb/static/images/aLvcFjj.png diff --git a/edaweb/static/images/aaaaahh.jpg b/edaweb/static/images/aaaaahh.jpg Binary files differnew file mode 100644 index 0000000..8dac9d4 --- /dev/null +++ b/edaweb/static/images/aaaaahh.jpg diff --git a/edaweb/static/images/anti_nft_b.png b/edaweb/static/images/anti_nft_b.png Binary files differnew file mode 100644 index 0000000..61dfb99 --- /dev/null +++ b/edaweb/static/images/anti_nft_b.png diff --git a/edaweb/static/images/arenas.jpg b/edaweb/static/images/arenas.jpg Binary files differnew file mode 100644 index 0000000..2b2cac6 --- /dev/null +++ b/edaweb/static/images/arenas.jpg diff --git a/edaweb/static/images/basil.jpg b/edaweb/static/images/basil.jpg Binary files differnew file mode 100644 index 0000000..c63ba48 --- /dev/null +++ b/edaweb/static/images/basil.jpg diff --git a/edaweb/static/images/bigshark.png b/edaweb/static/images/bigshark.png Binary files differnew file mode 100644 index 0000000..a499fb1 --- /dev/null +++ b/edaweb/static/images/bigshark.png diff --git a/edaweb/static/images/bob.gif b/edaweb/static/images/bob.gif Binary files differnew file mode 100644 index 0000000..90b6dd5 --- /dev/null +++ b/edaweb/static/images/bob.gif diff --git a/edaweb/static/images/braindamage.png b/edaweb/static/images/braindamage.png Binary files differnew file mode 100644 index 0000000..c26e75f --- /dev/null +++ b/edaweb/static/images/braindamage.png diff --git a/edaweb/static/images/catonlap.jpg b/edaweb/static/images/catonlap.jpg Binary files differnew file mode 100644 index 0000000..37e526b --- /dev/null +++ b/edaweb/static/images/catonlap.jpg diff --git a/edaweb/static/images/chuddy.jpg b/edaweb/static/images/chuddy.jpg Binary files differnew file mode 100644 index 0000000..7d732f7 --- /dev/null +++ b/edaweb/static/images/chuddy.jpg diff --git a/edaweb/static/images/cloudfree.png b/edaweb/static/images/cloudfree.png Binary files differnew file mode 100644 index 0000000..71c6ff2 --- /dev/null +++ b/edaweb/static/images/cloudfree.png diff --git a/edaweb/static/images/embedded_img2.png b/edaweb/static/images/embedded_img2.png Binary files differnew file mode 100644 index 0000000..3eeea56 --- /dev/null +++ b/edaweb/static/images/embedded_img2.png diff --git a/edaweb/static/images/embedded_img3.png b/edaweb/static/images/embedded_img3.png Binary files differnew file mode 100644 index 0000000..2a55742 --- /dev/null +++ b/edaweb/static/images/embedded_img3.png diff --git a/edaweb/static/images/embedded_img4.png b/edaweb/static/images/embedded_img4.png Binary files differnew file mode 100644 index 0000000..5e6ec6d --- /dev/null +++ b/edaweb/static/images/embedded_img4.png diff --git a/edaweb/static/images/embedded_img5.PNG b/edaweb/static/images/embedded_img5.PNG Binary files differnew file mode 100644 index 0000000..c96d284 --- /dev/null +++ b/edaweb/static/images/embedded_img5.PNG diff --git a/edaweb/static/images/face.jpg b/edaweb/static/images/face.jpg Binary files differnew file mode 100644 index 0000000..b123e53 --- /dev/null +++ b/edaweb/static/images/face.jpg diff --git a/edaweb/static/images/first_server.jpg b/edaweb/static/images/first_server.jpg Binary files differnew file mode 100644 index 0000000..8f537d7 --- /dev/null +++ b/edaweb/static/images/first_server.jpg diff --git a/edaweb/static/images/fstab.png b/edaweb/static/images/fstab.png Binary files differnew file mode 100644 index 0000000..6acaa83 --- /dev/null +++ b/edaweb/static/images/fstab.png diff --git a/edaweb/static/images/graduation.jpg b/edaweb/static/images/graduation.jpg Binary files differnew file mode 100644 index 0000000..89bafd7 --- /dev/null +++ b/edaweb/static/images/graduation.jpg diff --git a/edaweb/static/images/greenboi.jpg b/edaweb/static/images/greenboi.jpg Binary files differnew file mode 100644 index 0000000..7761c8a --- /dev/null +++ b/edaweb/static/images/greenboi.jpg diff --git a/edaweb/static/images/hpkvm_puttyconf.png b/edaweb/static/images/hpkvm_puttyconf.png Binary files differnew file mode 100644 index 0000000..5e9852f --- /dev/null +++ b/edaweb/static/images/hpkvm_puttyconf.png diff --git a/edaweb/static/images/hpkvm_serialconf.png b/edaweb/static/images/hpkvm_serialconf.png Binary files differnew file mode 100644 index 0000000..76122c1 --- /dev/null +++ b/edaweb/static/images/hpkvm_serialconf.png diff --git a/edaweb/static/images/i5-1145G7.png b/edaweb/static/images/i5-1145G7.png Binary files differnew file mode 100644 index 0000000..96b6fa3 --- /dev/null +++ b/edaweb/static/images/i5-1145G7.png diff --git a/edaweb/static/images/iKVCEoy.png b/edaweb/static/images/iKVCEoy.png Binary files differnew file mode 100755 index 0000000..05d6d70 --- /dev/null +++ b/edaweb/static/images/iKVCEoy.png diff --git a/edaweb/static/images/icons.png b/edaweb/static/images/icons.png Binary files differnew file mode 100644 index 0000000..4f19e72 --- /dev/null +++ b/edaweb/static/images/icons.png diff --git a/edaweb/static/images/ioporn.jpg b/edaweb/static/images/ioporn.jpg Binary files differnew file mode 100644 index 0000000..6608d31 --- /dev/null +++ b/edaweb/static/images/ioporn.jpg diff --git a/edaweb/static/images/its_true_1.jpg b/edaweb/static/images/its_true_1.jpg Binary files differnew file mode 100644 index 0000000..3dddfb3 --- /dev/null +++ b/edaweb/static/images/its_true_1.jpg diff --git a/edaweb/static/images/its_true_2.jpg b/edaweb/static/images/its_true_2.jpg Binary files differnew file mode 100644 index 0000000..b532a21 --- /dev/null +++ b/edaweb/static/images/its_true_2.jpg diff --git a/edaweb/static/images/j1800.jpg b/edaweb/static/images/j1800.jpg Binary files differnew file mode 100644 index 0000000..05db3a6 --- /dev/null +++ b/edaweb/static/images/j1800.jpg diff --git a/edaweb/static/images/j5040.jpg b/edaweb/static/images/j5040.jpg Binary files differnew file mode 100644 index 0000000..1a24299 --- /dev/null +++ b/edaweb/static/images/j5040.jpg diff --git a/edaweb/static/images/j5040_server.jpg b/edaweb/static/images/j5040_server.jpg Binary files differnew file mode 100644 index 0000000..9e2f3aa --- /dev/null +++ b/edaweb/static/images/j5040_server.jpg diff --git a/edaweb/static/images/kvm_1.png b/edaweb/static/images/kvm_1.png Binary files differnew file mode 100644 index 0000000..fa05b15 --- /dev/null +++ b/edaweb/static/images/kvm_1.png diff --git a/edaweb/static/images/kvm_2.png b/edaweb/static/images/kvm_2.png Binary files differnew file mode 100644 index 0000000..6fca0f8 --- /dev/null +++ b/edaweb/static/images/kvm_2.png diff --git a/edaweb/static/images/lackrack1.jpg b/edaweb/static/images/lackrack1.jpg Binary files differnew file mode 100644 index 0000000..31c4f9d --- /dev/null +++ b/edaweb/static/images/lackrack1.jpg diff --git a/edaweb/static/images/lackrack2.jpg b/edaweb/static/images/lackrack2.jpg Binary files differnew file mode 100644 index 0000000..9fda7d8 --- /dev/null +++ b/edaweb/static/images/lackrack2.jpg diff --git a/edaweb/static/images/libreboot.jpg b/edaweb/static/images/libreboot.jpg Binary files differnew file mode 100644 index 0000000..0bac72e --- /dev/null +++ b/edaweb/static/images/libreboot.jpg diff --git a/edaweb/static/images/liostore.png b/edaweb/static/images/liostore.png Binary files differnew file mode 100644 index 0000000..43003ee --- /dev/null +++ b/edaweb/static/images/liostore.png diff --git a/edaweb/static/images/media_E9lTIldWUAEeT63.jpg b/edaweb/static/images/media_E9lTIldWUAEeT63.jpg Binary files differnew file mode 100644 index 0000000..b30195a --- /dev/null +++ b/edaweb/static/images/media_E9lTIldWUAEeT63.jpg diff --git a/edaweb/static/images/media_FPus_2aXsAUhCu9.jpg b/edaweb/static/images/media_FPus_2aXsAUhCu9.jpg Binary files differnew file mode 100644 index 0000000..398fadd --- /dev/null +++ b/edaweb/static/images/media_FPus_2aXsAUhCu9.jpg diff --git a/edaweb/static/images/media_FRlRqYKXoAIw82O.jpg b/edaweb/static/images/media_FRlRqYKXoAIw82O.jpg Binary files differnew file mode 100644 index 0000000..b45a62b --- /dev/null +++ b/edaweb/static/images/media_FRlRqYKXoAIw82O.jpg diff --git a/edaweb/static/images/media_FeP_m8FXEAAqcJs.jpg b/edaweb/static/images/media_FeP_m8FXEAAqcJs.jpg Binary files differnew file mode 100644 index 0000000..f3afe10 --- /dev/null +++ b/edaweb/static/images/media_FeP_m8FXEAAqcJs.jpg diff --git a/edaweb/static/images/media_FfcNNZ2WYAAz97v.jpg b/edaweb/static/images/media_FfcNNZ2WYAAz97v.jpg Binary files differnew file mode 100644 index 0000000..8ae39ad --- /dev/null +++ b/edaweb/static/images/media_FfcNNZ2WYAAz97v.jpg diff --git a/edaweb/static/images/media_FlBsMq2XwAATJX5.jpg b/edaweb/static/images/media_FlBsMq2XwAATJX5.jpg Binary files differnew file mode 100644 index 0000000..7ba3ef1 --- /dev/null +++ b/edaweb/static/images/media_FlBsMq2XwAATJX5.jpg diff --git a/edaweb/static/images/media_FlBsfDcWQAQhJdP.jpg b/edaweb/static/images/media_FlBsfDcWQAQhJdP.jpg Binary files differnew file mode 100644 index 0000000..601dfbe --- /dev/null +++ b/edaweb/static/images/media_FlBsfDcWQAQhJdP.jpg diff --git a/edaweb/static/images/minecraft.png b/edaweb/static/images/minecraft.png Binary files differnew file mode 100644 index 0000000..19210d2 --- /dev/null +++ b/edaweb/static/images/minecraft.png diff --git a/edaweb/static/images/new_switch_opened.jpg b/edaweb/static/images/new_switch_opened.jpg Binary files differnew file mode 100644 index 0000000..df797ed --- /dev/null +++ b/edaweb/static/images/new_switch_opened.jpg diff --git a/edaweb/static/images/newdiscord.jpg b/edaweb/static/images/newdiscord.jpg Binary files differnew file mode 100644 index 0000000..d446602 --- /dev/null +++ b/edaweb/static/images/newdiscord.jpg diff --git a/edaweb/static/images/nicfan.jpg b/edaweb/static/images/nicfan.jpg Binary files differnew file mode 100644 index 0000000..6c2415e --- /dev/null +++ b/edaweb/static/images/nicfan.jpg diff --git a/edaweb/static/images/notstolenvalour4.png b/edaweb/static/images/notstolenvalour4.png Binary files differnew file mode 100644 index 0000000..f9e82e2 --- /dev/null +++ b/edaweb/static/images/notstolenvalour4.png diff --git a/edaweb/static/images/notstolenvalour5.png b/edaweb/static/images/notstolenvalour5.png Binary files differnew file mode 100644 index 0000000..87c09da --- /dev/null +++ b/edaweb/static/images/notstolenvalour5.png diff --git a/edaweb/static/images/notstolenvalour8.png b/edaweb/static/images/notstolenvalour8.png Binary files differnew file mode 100644 index 0000000..dcddf27 --- /dev/null +++ b/edaweb/static/images/notstolenvalour8.png diff --git a/edaweb/static/images/oldpic.png b/edaweb/static/images/oldpic.png Binary files differnew file mode 100644 index 0000000..20314e4 --- /dev/null +++ b/edaweb/static/images/oldpic.png diff --git a/edaweb/static/images/pfsenseswissvpnportforwards.png b/edaweb/static/images/pfsenseswissvpnportforwards.png Binary files differnew file mode 100644 index 0000000..34c05dc --- /dev/null +++ b/edaweb/static/images/pfsenseswissvpnportforwards.png diff --git a/edaweb/static/images/photo_2022-12-07_14-06-03.jpg b/edaweb/static/images/photo_2022-12-07_14-06-03.jpg Binary files differnew file mode 100644 index 0000000..224b748 --- /dev/null +++ b/edaweb/static/images/photo_2022-12-07_14-06-03.jpg diff --git a/edaweb/static/images/photo_5857106224099739202_y.jpg b/edaweb/static/images/photo_5857106224099739202_y.jpg Binary files differnew file mode 100644 index 0000000..c0a5820 --- /dev/null +++ b/edaweb/static/images/photo_5857106224099739202_y.jpg diff --git a/edaweb/static/images/powerani.gif b/edaweb/static/images/powerani.gif Binary files differnew file mode 100644 index 0000000..1eb1a18 --- /dev/null +++ b/edaweb/static/images/powerani.gif diff --git a/edaweb/static/images/profile_images_1598652418580963328_ENk7xKDw.jpg b/edaweb/static/images/profile_images_1598652418580963328_ENk7xKDw.jpg Binary files differnew file mode 100644 index 0000000..775d4e9 --- /dev/null +++ b/edaweb/static/images/profile_images_1598652418580963328_ENk7xKDw.jpg diff --git a/edaweb/static/images/rOJXmjG.png b/edaweb/static/images/rOJXmjG.png Binary files differnew file mode 100755 index 0000000..58a4ae4 --- /dev/null +++ b/edaweb/static/images/rOJXmjG.png diff --git a/edaweb/static/images/rack1.jpg b/edaweb/static/images/rack1.jpg Binary files differnew file mode 100644 index 0000000..b5049e9 --- /dev/null +++ b/edaweb/static/images/rack1.jpg diff --git a/edaweb/static/images/rack2.jpg b/edaweb/static/images/rack2.jpg Binary files differnew file mode 100644 index 0000000..1c9bc11 --- /dev/null +++ b/edaweb/static/images/rack2.jpg diff --git a/edaweb/static/images/router.jpg b/edaweb/static/images/router.jpg Binary files differnew file mode 100644 index 0000000..587f0e0 --- /dev/null +++ b/edaweb/static/images/router.jpg diff --git a/edaweb/static/images/russian_isp.png b/edaweb/static/images/russian_isp.png Binary files differnew file mode 100644 index 0000000..5b529c0 --- /dev/null +++ b/edaweb/static/images/russian_isp.png diff --git a/edaweb/static/images/russian_isp_abuse.png b/edaweb/static/images/russian_isp_abuse.png Binary files differnew file mode 100644 index 0000000..96da244 --- /dev/null +++ b/edaweb/static/images/russian_isp_abuse.png diff --git a/edaweb/static/images/russian_nginx_logs.jpg b/edaweb/static/images/russian_nginx_logs.jpg Binary files differnew file mode 100644 index 0000000..3fe22d3 --- /dev/null +++ b/edaweb/static/images/russian_nginx_logs.jpg diff --git a/edaweb/static/images/russian_yt.jpg b/edaweb/static/images/russian_yt.jpg Binary files differnew file mode 100644 index 0000000..16f3767 --- /dev/null +++ b/edaweb/static/images/russian_yt.jpg diff --git a/edaweb/static/images/s-l1600.jpg b/edaweb/static/images/s-l1600.jpg Binary files differnew file mode 100644 index 0000000..34a82cf --- /dev/null +++ b/edaweb/static/images/s-l1600.jpg diff --git a/edaweb/static/images/s-l16001.jpg b/edaweb/static/images/s-l16001.jpg Binary files differnew file mode 100644 index 0000000..0c34348 --- /dev/null +++ b/edaweb/static/images/s-l16001.jpg diff --git a/edaweb/static/images/s-l500.jpg b/edaweb/static/images/s-l500.jpg Binary files differnew file mode 100644 index 0000000..92307ff --- /dev/null +++ b/edaweb/static/images/s-l500.jpg diff --git a/edaweb/static/images/sample_ede336afca555579dd78f051e4a23feaa838716d.jpg b/edaweb/static/images/sample_ede336afca555579dd78f051e4a23feaa838716d.jpg Binary files differnew file mode 100644 index 0000000..b146bc4 --- /dev/null +++ b/edaweb/static/images/sample_ede336afca555579dd78f051e4a23feaa838716d.jpg diff --git a/edaweb/static/images/selfie.jpg b/edaweb/static/images/selfie.jpg Binary files differnew file mode 100644 index 0000000..17730e8 --- /dev/null +++ b/edaweb/static/images/selfie.jpg diff --git a/edaweb/static/images/server.jpg b/edaweb/static/images/server.jpg Binary files differnew file mode 100644 index 0000000..50bc1d7 --- /dev/null +++ b/edaweb/static/images/server.jpg diff --git a/edaweb/static/images/server2.jpg b/edaweb/static/images/server2.jpg Binary files differnew file mode 100644 index 0000000..dda70b1 --- /dev/null +++ b/edaweb/static/images/server2.jpg diff --git a/edaweb/static/images/shark1.jpg b/edaweb/static/images/shark1.jpg Binary files differnew file mode 100644 index 0000000..394846c --- /dev/null +++ b/edaweb/static/images/shark1.jpg diff --git a/edaweb/static/images/shark2.jpg b/edaweb/static/images/shark2.jpg Binary files differnew file mode 100644 index 0000000..2c432cd --- /dev/null +++ b/edaweb/static/images/shark2.jpg diff --git a/edaweb/static/images/shark3.jpg b/edaweb/static/images/shark3.jpg Binary files differnew file mode 100644 index 0000000..5343254 --- /dev/null +++ b/edaweb/static/images/shark3.jpg diff --git a/edaweb/static/images/shark3.png b/edaweb/static/images/shark3.png Binary files differnew file mode 100644 index 0000000..22e8ff9 --- /dev/null +++ b/edaweb/static/images/shark3.png diff --git a/edaweb/static/images/shun-hashimoto-mio-chibana.gif b/edaweb/static/images/shun-hashimoto-mio-chibana.gif Binary files differnew file mode 100644 index 0000000..869793f --- /dev/null +++ b/edaweb/static/images/shun-hashimoto-mio-chibana.gif diff --git a/edaweb/static/images/sicp.jpg b/edaweb/static/images/sicp.jpg Binary files differnew file mode 100644 index 0000000..575a456 --- /dev/null +++ b/edaweb/static/images/sicp.jpg diff --git a/edaweb/static/images/startech_rack_1.jpg b/edaweb/static/images/startech_rack_1.jpg Binary files differnew file mode 100644 index 0000000..1f66734 --- /dev/null +++ b/edaweb/static/images/startech_rack_1.jpg diff --git a/edaweb/static/images/startech_rack_2.jpg b/edaweb/static/images/startech_rack_2.jpg Binary files differnew file mode 100644 index 0000000..47f9aac --- /dev/null +++ b/edaweb/static/images/startech_rack_2.jpg diff --git a/edaweb/static/images/stolenvalour.jpg b/edaweb/static/images/stolenvalour.jpg Binary files differnew file mode 100644 index 0000000..d666623 --- /dev/null +++ b/edaweb/static/images/stolenvalour.jpg diff --git a/edaweb/static/images/sun.gif b/edaweb/static/images/sun.gif Binary files differnew file mode 100644 index 0000000..674e32a --- /dev/null +++ b/edaweb/static/images/sun.gif diff --git a/edaweb/static/images/switch.jpg b/edaweb/static/images/switch.jpg Binary files differnew file mode 100644 index 0000000..64ab20c --- /dev/null +++ b/edaweb/static/images/switch.jpg diff --git a/edaweb/static/images/switches.jpg b/edaweb/static/images/switches.jpg Binary files differnew file mode 100644 index 0000000..8b56651 --- /dev/null +++ b/edaweb/static/images/switches.jpg diff --git a/edaweb/static/images/t30.jpg b/edaweb/static/images/t30.jpg Binary files differnew file mode 100644 index 0000000..949d14b --- /dev/null +++ b/edaweb/static/images/t30.jpg diff --git a/edaweb/static/images/techdome.jpg b/edaweb/static/images/techdome.jpg Binary files differnew file mode 100644 index 0000000..74fe69c --- /dev/null +++ b/edaweb/static/images/techdome.jpg diff --git a/edaweb/static/images/telegrampic.jpg b/edaweb/static/images/telegrampic.jpg Binary files differnew file mode 100644 index 0000000..ddadb8b --- /dev/null +++ b/edaweb/static/images/telegrampic.jpg diff --git a/edaweb/static/images/telegrampic2.jpg b/edaweb/static/images/telegrampic2.jpg Binary files differnew file mode 100644 index 0000000..8b306ff --- /dev/null +++ b/edaweb/static/images/telegrampic2.jpg diff --git a/edaweb/static/images/testimonials.PNG b/edaweb/static/images/testimonials.PNG Binary files differnew file mode 100644 index 0000000..8584cdd --- /dev/null +++ b/edaweb/static/images/testimonials.PNG diff --git a/edaweb/static/images/theNVMEVault.png b/edaweb/static/images/theNVMEVault.png Binary files differnew file mode 100644 index 0000000..2cf31d7 --- /dev/null +++ b/edaweb/static/images/theNVMEVault.png diff --git a/edaweb/static/images/twitterpic.jpg b/edaweb/static/images/twitterpic.jpg Binary files differnew file mode 100644 index 0000000..57f16b4 --- /dev/null +++ b/edaweb/static/images/twitterpic.jpg diff --git a/edaweb/static/images/v2Yfoou.jpg b/edaweb/static/images/v2Yfoou.jpg Binary files differnew file mode 100755 index 0000000..f3a3249 --- /dev/null +++ b/edaweb/static/images/v2Yfoou.jpg diff --git a/edaweb/static/images/vcss-blue.gif b/edaweb/static/images/vcss-blue.gif Binary files differnew file mode 100644 index 0000000..c373b2a --- /dev/null +++ b/edaweb/static/images/vcss-blue.gif diff --git a/edaweb/static/images/www.gif b/edaweb/static/images/www.gif Binary files differnew file mode 100644 index 0000000..48fbd13 --- /dev/null +++ b/edaweb/static/images/www.gif diff --git a/edaweb/static/images/wxbKYVv.png b/edaweb/static/images/wxbKYVv.png Binary files differnew file mode 100755 index 0000000..75feb10 --- /dev/null +++ b/edaweb/static/images/wxbKYVv.png diff --git a/edaweb/static/images/x200.jpg b/edaweb/static/images/x200.jpg Binary files differnew file mode 100644 index 0000000..d7e48eb --- /dev/null +++ b/edaweb/static/images/x200.jpg diff --git a/edaweb/static/images/xeon.jpg b/edaweb/static/images/xeon.jpg Binary files differnew file mode 100644 index 0000000..4b1eef9 --- /dev/null +++ b/edaweb/static/images/xeon.jpg diff --git a/edaweb/static/images/xeon_motherboard.jpg b/edaweb/static/images/xeon_motherboard.jpg Binary files differnew file mode 100644 index 0000000..a17819f --- /dev/null +++ b/edaweb/static/images/xeon_motherboard.jpg diff --git a/edaweb/static/index.md b/edaweb/static/index.md new file mode 100644 index 0000000..e6bf91d --- /dev/null +++ b/edaweb/static/index.md @@ -0,0 +1,38 @@ +site now also avaliable under the domain [boymoder.blog](https://boymoder.blog)! + + + +## haiiiiiii +my name is eden and im a 23yo (boymoder/[fujoshi](https://www.urbandictionary.com/define.php?term=fujoshi)) computer science/robotics PhD student. i made my own website to encourage others to do so too. +i'll post my thoughts on here sometimes, and use this site to link to other stuff i host [more about me](/thought?id=2). + +[click here for a random image of lio fotia](/random?tags=lio_fotia) + +[click here for a random KawoShin image](/random?tags=nagisa_kaworu+ikari_shinji+yaoi) + +## FOSS alternative services + +- [nextcloud - dropbox (+ much more!) alternative](https://nc.eda.gay) +- [git server - github alternative](https://git.eda.gay/) +- [jellyfin - web player for ~~legally downloaded~~ TV and films](https://jellyfin.eda.gay) - RIP emby! + +[see the services im running right now](/services) (takes a couple seconds to load) + +these sites are hosted on my [homelab system](https://wiki.eda.gay) + + + + +## nice websites +- [wiby.me](http://wiby.me/) - search engine for old style websites with limited javascript (my site used to be on here but it got blacklisted for some reason?) +- [dysmorph.nekoweb.org](https://dysmorph.nekoweb.org/) - a site that is very based because it looks similar +- [transsexual.org](https://web.archive.org/web/20010802032136/http://transsexual.org/Toon.html) - awesome and relatable transsexual comics from a website that's slightly older than me +- [norfolkchurches.co.uk](http://www.norfolkchurches.co.uk/norwichintro.htm) - site about all the churches in norwich (and norfolk!), the city that has far too many medieval churches than it knows what to do with. this site is preciesly what the internet should be, the muted ramblings of someone with an expert knowledge on his preferred niche interest. without any javascript. nice if, like me, you have a middling interest in theology +- [boymoder.network](https://boymoder.network/) - website for boymoder awareness +- [4chan.org/lgbt/](https://boards.4channel.org/lgbt/) - but dont blame me if u catch brainworms +- [https://www.math.uni-bielefeld.de/~sillke/Twister/fun/elevator-fun90.html](https://www.math.uni-bielefeld.de/~sillke/Twister/fun/elevator-fun90.html) any website with a URL like this is gonna be good +- [boymoder.moe](https://nyaomidev.github.io/boymoder.moe/) +- [boymoders.com](https://boymoders.com) +- [john.citrons.xyz](https://john.citrons.xyz/) - for the nice 'ads' featured at the bottom of my page + + diff --git a/edaweb/static/papers/aai.pdf b/edaweb/static/papers/aai.pdf Binary files differnew file mode 100644 index 0000000..af2223b --- /dev/null +++ b/edaweb/static/papers/aai.pdf diff --git a/edaweb/static/papers/ar2.pdf b/edaweb/static/papers/ar2.pdf Binary files differnew file mode 100644 index 0000000..2b1693f --- /dev/null +++ b/edaweb/static/papers/ar2.pdf diff --git a/edaweb/static/robots.txt b/edaweb/static/robots.txt new file mode 100644 index 0000000..04154e9 --- /dev/null +++ b/edaweb/static/robots.txt @@ -0,0 +1,7 @@ +User-agent: *
+Allow: /
+User-agent: Googlebot-Image
+Disallow: *
+User-agent: *
+Disallow: /random*
+
diff --git a/edaweb/static/style.css b/edaweb/static/style.css new file mode 100644 index 0000000..6069ebf --- /dev/null +++ b/edaweb/static/style.css @@ -0,0 +1,211 @@ +html { + background-color: black; + font-family: 'Open Sans', sans-serif; + font-size: small; +} + +body { + /* background: linear-gradient(red,orange,yellow,green,blue,indigo,violet); */ + margin-left: 0px; + margin-right: 0px; + margin-bottom: 0px; + position: relative; + background: black; +} + +#wrapper { + background-color: #f1f3f3; + max-width: 974px; + min-width: 850px; + margin: auto; + margin-top: -10px; +} + +header { + background-color: #f1f3f3; +} + + +#headerflex { + display: flex; +} + +#headers { + flex-grow: 1; +} + +header nav { + flex-grow: 1; + display: inline; +} + +#externallinks { + background-color: black; + text-align: center; +} + +#externallinks nav ul li a { + color: #f1f3f3; + font-size: smaller; +} + +header div { + padding-left: 20px; + /* padding-bottom: 10px; */ +} + +nav ul { + margin: 0; + padding: 0; +} + +nav li { + display: inline-block; + list-style-type: none; +} + +nav a { + text-decoration: none; + display: block; + padding: 5px 6px 5px 6px; + color: black; +} + +#TheTitle { + text-decoration: none; + color: black; +} + +#TheTitle h1 { + padding-left: 6px; +} + +#articles { + text-align: left; + background-color: white; +} + +article section table { + font-family: monospace; +} + +article section table td { + text-align: right; +} + +#randomImage img { + max-width: 65%; +} + +#content img { + max-width: 65%; +} + +aside { + width: 30%; + padding-left: 15px; + margin-left: 15px; + float: right; +} + +#contents { + font-size: xx-small; +} + +#contents ul { + padding-left: 12px; + line-height: 3px; + } + +#contents ul li { + list-style: none; +} + +#tags { + font-size: xx-small; +} + +#sidebarImage { + transform: translateX(10px); +} + +.header_linker { + font-size: x-small; +} + +#diaryentry { + list-style-type: none; +} + +#diaryentry ul { + list-style-type: none; + display: inline-block; +} + +#diaryentry ul li img { + max-height: 150px; + margin-top: 10px; +} + +.qnaheader { + font-weight: bold; +} + +blockquote span { + color: #789922; +} + +blockquote span::before { + content: ">"; +} + +.running { + background-color: green; +} + +.notRunning { + background-color: red; +} + +header img { + max-height: 110px; +} + +form #number_input { + width: 50px; + margin-left: 10px; +} + +form #url_input { + margin-left: 10px; +} + +body div div { + padding-left: 10px; + padding-right: 10px; +} + +footer { + padding: 300px 10px 5px 20px; + margin-bottom: 300px; + font-size: xx-small; + align-content: center; +} + +#footer_banners { + display: flex; + align-items: center; + +} + +@media (max-width: 1023px) { + body { + margin: 0; + padding: 0; + } + + #wrapper { + min-width: 100%; + margin-top: 0; + } +} diff --git a/edaweb/templates/diary.html.j2 b/edaweb/templates/diary.html.j2 new file mode 100644 index 0000000..f6604f7 --- /dev/null +++ b/edaweb/templates/diary.html.j2 @@ -0,0 +1,26 @@ +{% extends "template.html.j2" %} +{% block content %} + <h4>this page might not be up-to-date if my diary account is search banned</h4> + <p>if in doubt check my <a href="https://twitter.com/{{ diary_account }}">diary account</a> <br> <a href="https://shadowban.yuzurisa.com/{{ diary_account }}">check if i'm currently search banned</a></p> + <dl> + {% for dt, entries in diary.items() %} + <dt><a href="{{ entries[0]['link'] }}">{{ dt }}</a></dt> + <dd> + <ol id="diaryentry"> + {% for entry in entries %} + {% if entry["images"] != [] %} + <ul> + {% for img in entry["images"] %} + <li><a href="{{ img }}" target='_blank'><img src="{{ img }}"></a></li> + {% endfor %} + </ul> + {% endif %} + <li> + <p>{{ entry["text"] }}</p> + </li> + {% endfor %} + </ol> + </dd> + {% endfor %} + </dl> +{% endblock %} diff --git a/edaweb/templates/discord.html.j2 b/edaweb/templates/discord.html.j2 new file mode 100644 index 0000000..597fb4b --- /dev/null +++ b/edaweb/templates/discord.html.j2 @@ -0,0 +1,5 @@ +{% extends "template.html.j2" %} +{% block content %} + <p>You can contact me on discord (telegram preferred):</p> + <h1>{{discord}}</h1> + {% endblock %}
\ No newline at end of file diff --git a/edaweb/templates/index.html.j2 b/edaweb/templates/index.html.j2 new file mode 100644 index 0000000..d6c08d8 --- /dev/null +++ b/edaweb/templates/index.html.j2 @@ -0,0 +1,24 @@ +{% extends "template.html.j2" %} +{% block content %} + <aside> + <a><i>{{ "%d days until FFS" % days_till_ffs.days }}</i></a> + <section id="recent_thoughts"> + <h4>recent thoughts:</h4> + <ul> + {% for id_, title in featured_thoughts %} + <li><a href="{{'/thought?id=%i' % id_}}">{{title}}</a></li> + {% endfor %} + </ul> + </section> + <img id="sidebar_img" alt="{{sidebar_img[0]}}" src="{{sidebar_img[1]}}"> + </aside> + {{markdown|safe}} + <section id="recent_commits"> + <h3>recent git commits:</h3> + <ul> + {% for commit in commits %} + <li>[<a href="{{commit['git_repo_url']}}">{{commit["repo"]}}</a>] {+{{commit["stats"]["additions"]}}; -{{commit["stats"]["deletions"]}}} <a href="{{commit['git_commit_url']}}">{{commit["message"]}}</a> - <a href="{{commit['github_commit_url']}}">github mirror</a></li> + {% endfor %} + </ul> + </section> +{% endblock %} diff --git a/edaweb/templates/isocd.html.j2 b/edaweb/templates/isocd.html.j2 new file mode 100644 index 0000000..3c532c0 --- /dev/null +++ b/edaweb/templates/isocd.html.j2 @@ -0,0 +1,32 @@ +{% extends "template.html.j2" %} +{% block content %} + <p>As discussed <a href="https://nitter.eda.gay/estrogenizedboy/status/1490322471215636480#m">here</a>, I will post a GNU/Linux install CD to you for free (provided you live in the United Kingdom). Just fill out the form below:</p> + <form action="/getisocd" method="POST"> + <label for="email">*Email:</label> + <input type="email" id="email" name="email" required><br><br> + <label for="iso">*ISO:</label> + <select name="iso" id="iso" required> + {% for iso in iso_options %} + <option value="{{ iso }}">{{ iso }}</option> + {% endfor %} + </select><br><br> + <p>Sadly there is an upper limit on ISOs of 700Mb coz thats what u can fit on a cd ;_; so big isos arent listed</p><br> + <label for="name">*Name:</label> + <input id="name" name="name" required><br><br> + <label for="house">*House Number/Name:</label> + <input id="house" name="house" required><br><br> + <label for="street">*Street:</label> + <input id="street" name="street" required><br><br> + <label for="city">City:</label> + <input id="city" name="city"><br><br> + <label for="county">County:</label> + <input id="county" name="county"><br><br> + <label for="postcode">*Postcode:</label> + <input id="postcode" name="postcode" required><br><br> + <input type="submit" value="Submit"> + </form> + <p>I make no promises how long this will actually take, but you might get a special present too uwu</p> + <p>btw if u abuse this service i'll just ignore u</p> + <h3>Testimonials</h3> + <a href="https://nitter.eda.gay/stellarnate_/status/1492468706412269569"><img src="/img/testimonials.PNG"></a> +{% endblock %}
\ No newline at end of file diff --git a/edaweb/templates/isocd_confirmation.html.j2 b/edaweb/templates/isocd_confirmation.html.j2 new file mode 100644 index 0000000..81045a8 --- /dev/null +++ b/edaweb/templates/isocd_confirmation.html.j2 @@ -0,0 +1,16 @@ +{% extends "template.html.j2" %} +{% block content %} + <p>Your order has been placed. Expect a confirmation email to {{ email }} when I can be bothered to sort it out.</p> + <br> + <p>Your order/reference id is {{ id_ }}</p> + <br> + <p>The details were as follows:</p> + <table> + {% for k, v in req.items() %} + <tr> + <td>{{ k.upper() }}</td> + <td>{{ v }}</td> + </tr> + {% endfor %} + </table> +{% endblock %}
\ No newline at end of file diff --git a/edaweb/templates/nhdl.html.j2 b/edaweb/templates/nhdl.html.j2 new file mode 100644 index 0000000..5ab62c2 --- /dev/null +++ b/edaweb/templates/nhdl.html.j2 @@ -0,0 +1,8 @@ +{% extends "template.html.j2" %} +{% block content %} + <form action="/nhdlredirect" method="POST"> + <label for="nhentai">nHentai.net number:</label> + <input type="text" id="number_input" name="number_input"><br><br> + <input type="submit" value="Download"> + </form> +{% endblock %}
\ No newline at end of file diff --git a/edaweb/templates/questions.html.j2 b/edaweb/templates/questions.html.j2 new file mode 100644 index 0000000..eb58380 --- /dev/null +++ b/edaweb/templates/questions.html.j2 @@ -0,0 +1,17 @@ +{% extends "template.html.j2" %} +{% block content %} + <h4><a href="{{ qnas_link }}">ask a question!</a></h4> + <dl> + {% for id_, link, dt, question, answer, host in qnas %} + {% if host == "curiouscat" %} + <dt class="qnaheader"><a href="{{ link }}">{{ dt.isoformat() }}</a> - {{ host }}</dt> + {% else %} + <dt class="qnaheader">{{ dt.isoformat() }} - {{ host }}</dt> + {% endif %} + <dd> + <dt class="question"><p>{{ question }}</p></dt> + <dd class="answer"><p>{{ answer }}</p></dd> + </dd> + {% endfor %} + </dl> +{% endblock %} diff --git a/edaweb/templates/random.html.j2 b/edaweb/templates/random.html.j2 new file mode 100644 index 0000000..76b433b --- /dev/null +++ b/edaweb/templates/random.html.j2 @@ -0,0 +1,22 @@ +{% extends "template.html.j2" %} +{% block content %} + <aside id="tags"> + <h1>current search tags: (click to remove)</h1> + <ul> + {% for tag in sbi.searchTags %} + <li><a href={{"/random?tags=" + "+".join(sbi.remove_tag(tag))}}>{{tag}}</a></li> + {% endfor %} + </ul> + <h1>this image's tags:</h1> + <ul> + {% for tag in sbi.tags %} + <li><a href={{"/random?tags=" + "+".join(sbi.searchTags + [tag])}}>{{tag}}</a></li> + {% endfor %} + </ul> + </aside> + <section id="randomImage"> + <a href={{sbi.source}}><img src={{localimg}}></a> + <h1><a href={{"/random?tags=" + "+".join(sbi.searchTags)}}>generate another</a></h1> + <h2><a href={{sbi.source}}>artist link</a></h2> + </section> +{% endblock %}
\ No newline at end of file diff --git a/edaweb/templates/services.html.j2 b/edaweb/templates/services.html.j2 new file mode 100644 index 0000000..9f42c7f --- /dev/null +++ b/edaweb/templates/services.html.j2 @@ -0,0 +1,59 @@ +{% extends "template.html.j2" %} +{% block content %} +<article id=statusTables> + <section id=docker> + <h2>docker</h2> + <ul> + {% for host, containers in docker["containers"].items() %} + <h4>{{ "%s - %s" % (host[0], host[1]) }}</h4> + <table> + {% for name, status, image in containers %} + <tr> + <td>{{ name }}</td> + {% if "Up" in status %} + <td class=running>{{ status }}</td> + {% else %} + <td class=notRunning>{{ status }}</td> + {% endif %} + <td>{{ image }}</td> + </tr> + {% endfor %} + </table> + {% endfor %} + </ul> + <p>{{ docker["cachetime"] }}</p> + </section> + + <section id="torrents"> + <h2>transmission</h2> + {% if trans == None %} + <p>Couldn't access the transmission API. Is docker container running?</p> + {% else %} + <table> + {% for k, v in trans.items() %} + <tr> + <td>{{ k }}</td> + <td>{{ v }}</td> + </tr> + {% endfor %} + </table> + {% endif %} + </section> + + <section id=pihole> + <h2>pihole</h2> + {% if pihole == None %} + <p>Couldn't access the pihole API. Is docker container running?</p> + {% else %} + <table> + {% for k, v in pihole.items() %} + <tr> + <td>{{ k }}</td> + <td>{{ v }}</td> + </tr> + {% endfor %} + </table> + {% endif %} + </section> +</article> +{% endblock %}
\ No newline at end of file diff --git a/edaweb/templates/template.html.j2 b/edaweb/templates/template.html.j2 new file mode 100644 index 0000000..86618bc --- /dev/null +++ b/edaweb/templates/template.html.j2 @@ -0,0 +1,76 @@ +<!doctype html> +<html lang="en"> + <head> + <meta name="abuseipdb-verification" content="3IuG6dik" /> + <link rel='stylesheet' href="{{url_for('static', filename='style.css')}}"> + <link rel="shortcut icon" href="/img/greenboi.jpg?h=16&w=16"> + <title>eda.gay :: {{title}}</title> + + <meta content="{{title}}" property="og:title" /> + <meta content="Formerly chuck's" property="og:description" /> + <meta content="https://boymoder.blog" property="og:url" /> + <meta content="/img/greenboi.jpg?h=512&w=512" property="og:image" /> + </head> + <body> + <div id=wrapper> + <header> + <div id="externallinks"> + <nav> + <ul> + {% for name, link in links %} + <li> + <a href="{{link}}">{{name}}</a> + </li> + {% endfor %} + </ul> + </nav> + </div> + <div id=headerflex> + <div id=headers> + <a href="/" id=TheTitle><h1>{{title}}</h1></a> + <nav id=articles> + <ul> + {% for name, link in articles %} + <li> + <a href="{{link}}">{{name}}</a> + </li> + {% endfor %} + </ul> + </nav> + </div> + <a id=sidebarImage href="/"> + <img alt="{{image[0]}}" src="{{image[1]}}"> + </a> + </div> + </header> + <div id="content"> + {% block content %} + {% endblock %} + </div> + <footer> + <p>this site is <a href="/thought?id=3">javascript free</a></p> + <a href="https://git.eda.gay/eda.gay.git/tree/LICENSE">sauce code released under gplv3</a> <a href="https://github.com/jwansek/eda.gay">alternate git link</a> + <div id="footer_banners"> + <p> + <a href="http://jigsaw.w3.org/css-validator/check/referer"> + <img style="border:0;width:88px;height:31px" + src="/img/vcss-blue.gif" + alt="Valid CSS!" /> + </a> + </p> + <a href="http://www.freebsd.org/"> + <img alt="Powered By FreeBSD" src="/img/powerani.gif"> + </a> + <a href="https://web3isgoinggreat.com/"> + <img src="/img/anti_nft_b.png" alt="anti-nft site "> + </a> + <img src="/img/www.gif"> + <img src="/img/bob.gif"> + <img src="/img/sun.gif"> + <img src="/img/cloudfree.png"> + </div> + <iframe src="https://john.citrons.xyz/embed?ref=eda.gay" style="padding-top:20px;margin-left:auto;display:block;margin-right:auto;max-width:732px;width:100%;height:94px;border:none;"></iframe> + </footer> + </div> + </body> +</html> diff --git a/edaweb/templates/thought.html.j2 b/edaweb/templates/thought.html.j2 new file mode 100644 index 0000000..2a5b519 --- /dev/null +++ b/edaweb/templates/thought.html.j2 @@ -0,0 +1,29 @@ +{% extends "template.html.j2" %} +{% block content %} + <aside> + <h4>{{ dt }}</h4> + {% if contents_html != "" %} + <h5>contents:</h5> + <div id="contents"> + {{ contents_html|safe }} + </div> + {% endif %} + <h5>this category:</h5> + <ul> + <li><b><a href="{{'/thoughts#'+category.replace(' ', '_')}}">{{category}}</a></b></li> + </ul> + <h5>related thoughts:</h5> + <ul> + {% for id_, title, dt, category in related %} + <li><a href="{{'/thought?id=%i' % id_}}">{{title}}</a></li> + {% endfor %} + </ul> + <h5>other categories:</h5> + {% for category_name in othercategories %} + <ul> + <li><a href="{{'/thoughts#'+category_name.replace(' ', '_')}}">{{category_name}}</a></li> + </ul> + {% endfor %} + </aside> + {{ md_html|safe }} +{% endblock %}
\ No newline at end of file diff --git a/edaweb/templates/thoughts.html.j2 b/edaweb/templates/thoughts.html.j2 new file mode 100644 index 0000000..bf06f57 --- /dev/null +++ b/edaweb/templates/thoughts.html.j2 @@ -0,0 +1,12 @@ +{% extends "template.html.j2" %} +{% block content %} + {% for category_name, thoughts in tree.items() %} + <h3 id="{{category_name.replace(' ', '_')}}">{{category_name}}</h3> + <dl> + {% for id_, title, dt in thoughts %} + <dt><a href="{{'/thought?id=%i' % id_}}">{{title}}</a></dt> + <dd>{{dt}}</dd> + {% endfor %} + </dl> + {% endfor %} +{% endblock %}
\ No newline at end of file |