# AGPL 3 or any later version # (C) J.Y.Amihud ( Blender Dumbass ) import os import json from datetime import datetime from modules import Set from modules import markdown from modules.Common import * def guess_type(path): if "/json/" in path or ".json" in path: return "application/json" if "/css" in path or ".css" in path: return "text/css" if "/icon" in path or path.endswith(".png"): return "image/png" if path.endswith("jpg"): return "image/jpg" return "text/html" def headers(server, code): # Basic cookie for logins to work cookie = False if "Cookie" not in str(server.headers): cookie = True server.send_response(code) server.send_header("Content-type", guess_type(server.path)) if cookie: server.send_header("Set-Cookie", RandString()) server.end_headers() def head(title="", description="", image="", config={}): if image.startswith("/"): image = config.get("url","")+image favicon = config.get("favicon", "/icon/internet") html = """ """+title+""" """ return html def send(server, html, code): # Add headers headers(server, code) server.wfile.write(html.encode("utf-8")) def tabs(): folder = Set.Folder()+"/tabs" tabs = {} for tab in sorted(list(os.walk(folder))[0][1]): try: with open(folder+"/"+tab+"/config.json") as o: data = json.load(o) tabs[tab] = data except Exception as e: print(e) pass return tabs def articles(tab): folder = Set.Folder()+"/tabs/"+tab articles = {} for article in list(os.walk(folder))[0][1]: try: with open(folder+"/"+article+"/metadata.json") as o: data = json.load(o) articles[article] = data except Exception as e: print(e) pass # Sorting articles based on timestamp articles = {k:articles[k] for k in sorted(articles, key=lambda y: articles[y]["timestamp"], reverse=True)} return articles ### def MainPage(server): # Reading config config = Set.Load() # Generating html = head(title = config.get("title", "Website"), description = config.get("description", "Description"), config = config ) html = html + """

[LOGO]

"""+config.get("title", "My Website")+"""

"""+config.get("tagline", "")+"""

""" Tabs = tabs() for tab in Tabs: html = html + Button(Tabs[tab].get("title", tab), "/"+tab, Tabs[tab].get("icon", "folder")) html = html + "
" for i in range(50): html = html + "
" html = html + Footer() send(server, html, 200) def ListPage(server, tab): Tabs = tabs() Articles = articles(tab) config = Set.Load() try: page = int(server.parsed.get("page", ["0"])[0]) except Exception as e: print(e) page = 0 Buffer = 16 From = Buffer*page To = From+Buffer # Generating html = head(title = Tabs.get(tab, {}).get("title", tab), description = "", config = config ) html = html + Button(config.get("title", "My Website"), "/", image=config.get("favicon", "/icon/internet")) # Scroll thingie if len(Articles) > Buffer: if page > 0: html = html + Button(str(page-1), tab+"?page="+str(page-1), "left") html = html + '
'+str(page)+'
' if To < len(Articles)-1: html = html + Button(str(page+1), tab+"?page="+str(page+1), "right") html = html + """

""" print(page) rendered = 0 for n, article in enumerate(Articles): if n < From: continue if n >= To: break html = html + ArticlePreview(Articles[article], tab+"/"+article, tab, Tabs) rendered += 1 html = html + '

' # Bottom pannel for large dialogs if rendered >= Buffer/2: html = html + Button(config.get("title", "My Website"), "/", image=config.get("favicon", "/icon/internet")) # Scroll thingie if len(Articles) > Buffer: if page > 0: html = html + Button(str(page-1), tab+"?page="+str(page-1), "left") html = html + '
'+str(page)+'
' if To < len(Articles)-1: html = html + Button(str(page+1), tab+"?page="+str(page+1), "right") send(server, html, 200) def ArticlePage(server, url): if url.endswith(".md"): url = url.replace(".md", "") config = Set.Load() tab, article = url.split("/") Tabs = tabs() Articles = articles(tab) # Generating html = head(title = Tabs.get(tab, {}).get("title", tab), description = "", config = config ) html = html + Button(config.get("title", "My Website"), "/", image=config.get("favicon", "/icon/internet")) html = html + Button(Tabs.get(tab, {}).get("title", tab), "/"+tab, Tabs.get(tab, {}).get("icon", "folder")) # The article itself html = html + '
' html = html + '
' html = html +"

"+Articles.get(article, {}).get("title", article)+"

" # Page author author = Articles.get(article, {}).get("author", "") if author: html = html + '
'+User( author )+'
' # Page views # Views are calculated using an iframe which only loads when the page is # rendered in a browser. It is also looking at whether the same cookie renders # the same page, to avoid double counting from the same person. # The iframe itself shows a graph of views. views = str(Articles.get(article, {}).get("views", {}).get("amount", 0)) html = html + '
👁 '+views+'' html = html + """

""" html = html + '
' # Audio recording of the article recording = Articles.get(article, {}).get("recording", "") if recording: html = html + '' html = html + '
' html = html + markdown.convert(Set.Folder()+"/tabs/"+tab+"/"+article+"/text.md") html = html + '
' html = html + '
' # Thumbnail and suggestions send(server, html, 200) ### def Button(text, link, icon="", image=""): html = """ """ if icon: html = html + """ """ if image: html = html + """ """ html = html + """ """+text+""" """ return html def ArticlePreview(article, url, tab, Tabs): html = """
""" html = html + '

' html = html + '' html = html + article.get("title", "")+"

\n" if "thumbnail" in article: html = html + '
' author = article.get("author", "") if author: html = html + '
'+User( author )+'
' views = str(article.get("views", {}).get("amount", 0)) try: comments = str(len(article.get("comments", {}).get("comments"))) except: comments = "0" html = html +'
👁 '+views+' 💬 '+comments+'
' html = html + "
"+article.get("description", "")+"

" html = html + '
\n' return html def Footer(): html = """
""" html = html + Button("Powered with BDServer", "https://codeberg.org/blenderdumbass/BDServer/", "codeberg") html = html + """
""" return html def User(username, stretch=False): try: with open(Set.Folder()+"/accounts/"+username+".json") as o: account = json.load(o) except: account = {} # We are doing a lot of reductions in case somebody sneaks html code. avatar = account.get("avatar", "/pictures/monkey.png").replace("<", "<").replace(">", ">") username = username.replace("&", "&").replace("<", "<").replace(">", ">") title = account.get("title", username).replace("&", "&").replace("<", "<").replace(">", ">") html = '  '+title+'\n' return html def Graph(server, url): html = """ """ if url.endswith(".md"): url = url.replace(".md", "") try: with open(Set.Folder()+"/tabs"+url+"/metadata.json") as o: article = json.load(o) except: article = {} dates = article.get("views", {}).get("dates", {}) largest = max(dates.values()) dateformat = "%Y-%m-%d" startdate = datetime.strptime(sorted(list(dates.keys()), reverse=True)[0], dateformat) enddate = datetime.strptime(sorted(list(dates.keys()), reverse=True)[-1], dateformat) alldays = int((startdate - enddate).days) print(alldays) for n, date in enumerate(sorted(dates, reverse=True)): amount = dates[date] width = 100 / (alldays+1) height = 60 * (amount / largest) cd = datetime.strptime(date, dateformat) nd = int((startdate - cd).days) html = html + '
\n' send(server, html, 200)