From 08e55ccdfea629e9c34bbd742f0e340817847d65 Mon Sep 17 00:00:00 2001 From: Victorious Children Studios Date: Sat, 23 Nov 2024 00:48:29 +0200 Subject: [PATCH] Basic account view, suggestion algorithm and other stuff --- modules/Common.py | 3 + modules/Render.py | 256 +++++++++++++++++++++++++++++++++++++++++++--- modules/Run.py | 5 + 3 files changed, 250 insertions(+), 14 deletions(-) diff --git a/modules/Common.py b/modules/Common.py index 15cfee8..bbee73f 100644 --- a/modules/Common.py +++ b/modules/Common.py @@ -62,6 +62,9 @@ def Simplify(text): return ntext +def Safe(text): + return text.replace("<", "<").replace(">", ">") + def RandString(n=50): # this will make a random string s = "" diff --git a/modules/Render.py b/modules/Render.py index 947a32c..b45863b 100644 --- a/modules/Render.py +++ b/modules/Render.py @@ -3,6 +3,7 @@ import os import json +import random from datetime import datetime from modules import Set @@ -92,6 +93,24 @@ def tabs(): return tabs +def accounts(): + + folder = Set.Folder()+"/accounts" + accounts = {} + + for account in sorted(list(os.walk(folder))[0][2]): + + try: + with open(folder+"/"+account) as o: + data = json.load(o) + accounts[account.replace(".json","")] = data + except Exception as e: + print(e) + pass + + return accounts + + def articles(tab): folder = Set.Folder()+"/tabs/"+tab @@ -100,7 +119,10 @@ def articles(tab): try: with open(folder+"/"+article+"/metadata.json") as o: data = json.load(o) + data["tab"] = tab + data["url"] = "/"+tab+"/"+article articles[article] = data + except Exception as e: print(e) pass @@ -110,6 +132,85 @@ def articles(tab): return articles +def allArticles(): + + articles = {} + f = Set.Folder() + for tab in list(os.walk(f+"/tabs/"))[0][1]: + folder = f+"/tabs/"+tab + + for article in list(os.walk(folder))[0][1]: + try: + with open(folder+"/"+article+"/metadata.json") as o: + data = json.load(o) + data["tab"] = tab + data["url"] = "/"+tab+"/"+article + 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 randomArticles(): + + articles = {} + f = Set.Folder() + for tab in list(os.walk(f+"/tabs/"))[0][1]: + folder = f+"/tabs/"+tab + + for article in list(os.walk(folder))[0][1]: + try: + with open(folder+"/"+article+"/metadata.json") as o: + data = json.load(o) + data["tab"] = tab + data["url"] = "/"+tab+"/"+article + articles[article] = data + except Exception as e: + print(e) + pass + + # Randomizing Articles. + newarticles = {} + while articles: + article = random.choice(list(articles.keys())) + newarticles[article] = articles.pop(article) + + return newarticles + +def suggestedArticles(cookie, random=False): + + if not random: + articles = allArticles() + else: + articles = randomArticles() + + # Suggesting unread articles. + newarticles = {} + move = [] + for article in articles: + if cookie not in articles[article].get("views", {}).get("viewers", []): + move.append(article) + + for article in move: + newarticles[article] = articles[article] + + for article in articles: + if article not in move: + newarticles[article] = articles[article] + + return newarticles + +def previewsToSize(text): + + # Calculates roughly how many previews to fit any + # given article. + + # A thousand character article is about 4 articles. + return int(round(len(text)/2500)) + ### @@ -150,7 +251,21 @@ def MainPage(server): html = html + "" - for i in range(50): html = html + "
" + # Trending articles + + html = html + '
' + + trends = suggestedArticles(server.cookie) + Buffer = 20 + for n, article in enumerate(trends): + + if n >= Buffer: break + + article = trends[article] + html = html + ArticlePreview(article, Tabs, server.cookie) + + + html = html + '
' html = html + Footer() @@ -208,9 +323,7 @@ def ListPage(server, tab): if n < From: continue if n >= To: break - html = html + ArticlePreview(Articles[article], - tab+"/"+article, - tab, Tabs) + html = html + ArticlePreview(Articles[article], Tabs, server.cookie) rendered += 1 html = html + '
' @@ -242,10 +355,11 @@ def ArticlePage(server, url): tab, article = url.split("/") Tabs = tabs() Articles = articles(tab) + f = Set.Folder() # Generating - html = head(title = Tabs.get(tab, {}).get("title", tab), - description = "", + html = head(title = Articles.get(article, {}).get("title", article), + description = Articles.get(article, {}).get("description", ""), config = config ) @@ -288,18 +402,112 @@ def ArticlePage(server, url): html = html + '
' - html = html + markdown.convert(Set.Folder()+"/tabs/"+tab+"/"+article+"/text.md") + html = html + markdown.convert(f+"/tabs/"+tab+"/"+article+"/text.md") html = html + '
' html = html + '' # Thumbnail and suggestions + html = html + '
' + + thumbnail = Articles.get(article, {}).get("thumbnail") + if thumbnail: + + html = html + '

' + html = html + '' + html = html + '

' + + suggestions = suggestedArticles(server.cookie, random=True) + toomuch = previewsToSize(open(f+"/tabs/"+tab+"/"+article+"/text.md").read()) + + for n, title in enumerate(suggestions): + + if server.path in suggestions[title].get("url") : + continue + + if n > toomuch: + break + + article = suggestions[title] + html = html + ArticlePreview(article, Tabs, server.cookie) + html = html + "" send(server, html, 200) + +def AccountPage(server, account): + + config = Set.Load() + Accounts = accounts() + Tabs = tabs() + Articles = allArticles() + f = Set.Folder() + + # Generating + html = head(title = Safe(Accounts.get(account, {}).get("title", account)), + description = Safe(Accounts.get(account, {}).get("bio" , "")), + config = config + ) + + html = html + Button(config.get("title", "My Website"), "/", image=config.get("favicon", "/icon/internet")) + + # Name and bio + + html = html + '
' + html = html + '
' + html = html +"

"+Accounts.get(account, {}).get("title", account)+"

" + html = html + '
' + + html = html + '
' + html = html +"
Invited by:
"+User(Accounts.get(account, {}).get("invited_by", account))+"
" + html = html + '
' + + bio = Safe(Accounts.get(account, {}).get("bio" , "")) + if bio: + html = html + '
' + html = html + markdown.convert(bio, False) + html = html + '
' + + + # Posts by this account + + html = html + '
' + + for article in Articles: + + if Articles[article].get("author") != account: + continue + + html = html + ArticlePreview(Articles[article], Tabs, server.cookie) + + html = html + '
' + + html = html + '
' + + # Thumbnail and suggestions + + html = html + '
' + + avatar = Safe(Accounts.get(account, {}).get("avatar" , "")) + if avatar: + html = html + '

' + html = html + '' + html = html + '

' + + # Invited + + invited = Accounts.get(account, {}).get("invited", []) + if invited: + html = html + '
Invited:
' + for username in invited: + html = html + '
' + html = html + '
' + User(username) + '
\n' + html = html + '
' + + send(server, html, 200) ### @@ -320,17 +528,22 @@ def Button(text, link, icon="", image=""): """ return html -def ArticlePreview(article, url, tab, Tabs): +def ArticlePreview(article, Tabs, cookie=""): html = """
""" - + url, tab = article.get("url", ""), article.get("tab","") + + sup = "" + if cookie not in article.get("views", {}).get("viewers", ""): + sup = '
  Unread  

' + html = html + '

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

\n" + html = html + article.get("title", "")+""+sup+"\n" if "thumbnail" in article: html = html + '
' @@ -344,7 +557,7 @@ def ArticlePreview(article, url, tab, Tabs): except: comments = "0" html = html +'
👁 '+views+' 💬 '+comments+'
' - html = html + "
"+article.get("description", "")+"

" + html = html + "
"+markdown.convert(article.get("description", ""), False)+"

" html = html + '
\n' return html @@ -376,9 +589,10 @@ def User(username, stretch=False): 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(">", ">") + avatar = Safe(account.get("avatar", "")) + if not avatar: avatar = "/pictures/monkey.png" + username = Safe(username) + title = Safe(account.get("title", username)) html = '  '+title+'\n' return html @@ -429,5 +643,19 @@ def Graph(server, url): html = html + '
\n' + + # Saving the view + if server.cookie not in article.get("views", {}).get("viewers", []): + + try: + article["views"]["amount"] += 1 + article["views"]["viewers"].append(server.cookie) + + with open(Set.Folder()+"/tabs"+url+"/metadata.json", "w") as save: + json.dump(article, save, indent=4) + except Exception as e: + print(e) + pass + send(server, html, 200) diff --git a/modules/Run.py b/modules/Run.py index b85fbd4..e15551e 100644 --- a/modules/Run.py +++ b/modules/Run.py @@ -66,6 +66,11 @@ class handler(BaseHTTPRequestHandler): if "?" in url: url = url[:url.find("?")] Render.ArticlePage(self, url) + elif self.path[1:].startswith("account"): + url = self.path[9:] + if "?" in url: url = url[:url.find("?")] + Render.AccountPage(self, url) + elif self.path.startswith("/graph/"): url = self.path[6:] if "?" in url: url = url[:url.find("?")]