Basic account view, suggestion algorithm and other stuff

This commit is contained in:
Victorious Children Studios 2024-11-23 00:48:29 +02:00
parent a07a2bbaa1
commit 08e55ccdfe
3 changed files with 250 additions and 14 deletions

View file

@ -62,6 +62,9 @@ def Simplify(text):
return ntext
def Safe(text):
return text.replace("<", "&lt").replace(">", "&gt")
def RandString(n=50):
# this will make a random string
s = ""

View file

@ -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 + "</center>"
for i in range(50): html = html + "<br>"
# Trending articles
html = html + '<div class="flexity">'
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 + '</div>'
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 + '</div><br>'
@ -242,10 +355,11 @@ def ArticlePage(server, url):
tab, article = url.split("/")
Tabs = tabs()
Articles = articles(tab)
f = Set.Folder()
# Generating <head>
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 + '<div class="dark_box">'
html = html + markdown.convert(Set.Folder()+"/tabs/"+tab+"/"+article+"/text.md")
html = html + markdown.convert(f+"/tabs/"+tab+"/"+article+"/text.md")
html = html + '</div>'
html = html + '</div>'
# Thumbnail and suggestions
html = html + '<div class="checklist_section_article">'
thumbnail = Articles.get(article, {}).get("thumbnail")
if thumbnail:
html = html + '<div class="article_box"><br>'
html = html + '<img style="min-width:100%; width:100%" src="'+thumbnail+'">'
html = html + '<br><br></div>'
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 <head>
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 + '<div class="middle_section_article">'
html = html + '<div class="dark_box">'
html = html +"<center><h1>"+Accounts.get(account, {}).get("title", account)+"</h1></center>"
html = html + '</div>'
html = html + '<div class="dark_box">'
html = html +"<center>Invited by:<br>"+User(Accounts.get(account, {}).get("invited_by", account))+"</center>"
html = html + '</div>'
bio = Safe(Accounts.get(account, {}).get("bio" , ""))
if bio:
html = html + '<div class="dark_box">'
html = html + markdown.convert(bio, False)
html = html + '</div>'
# Posts by this account
html = html + '<div class="flexity">'
for article in Articles:
if Articles[article].get("author") != account:
continue
html = html + ArticlePreview(Articles[article], Tabs, server.cookie)
html = html + '</div>'
html = html + '</div>'
# Thumbnail and suggestions
html = html + '<div class="checklist_section_article">'
avatar = Safe(Accounts.get(account, {}).get("avatar" , ""))
if avatar:
html = html + '<div class="article_box"><br>'
html = html + '<img style="min-width:100%; width:100%" src="'+avatar+'">'
html = html + '<br><br></div>'
# Invited
invited = Accounts.get(account, {}).get("invited", [])
if invited:
html = html + '<center><div class="button">Invited:</div></center>'
for username in invited:
html = html + '<div class="dark_box">'
html = html + '<center>' + User(username) + '</center>\n'
html = html + '</div>'
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 = """
<div class="article_box">
"""
url, tab = article.get("url", ""), article.get("tab","")
sup = ""
if cookie not in article.get("views", {}).get("viewers", ""):
sup = '<center><sup><b> &nbsp; Unread &nbsp; </b></sup></center><br>'
html = html + '<a href="'+url+'"><h1>'
html = html + '<img src="/icon/'+Tabs.get(tab, {}).get("icon", "folder")+'" style="vertical-align: middle">'
html = html + article.get("title", "")+"</h1></a>\n"
html = html + article.get("title", "")+"</h1></a>"+sup+"\n"
if "thumbnail" in article:
html = html + '<center><a href="'+url+'"><img src="'+article["thumbnail"]+'"></a></center>'
@ -344,7 +557,7 @@ def ArticlePreview(article, url, tab, Tabs):
except: comments = "0"
html = html +'<br><center> 👁 '+views+' 💬 '+comments+' </center>'
html = html + "<br>"+article.get("description", "")+"<br><br>"
html = html + "<br>"+markdown.convert(article.get("description", ""), False)+"<br><br>"
html = html + '</div>\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("<", "&lt").replace(">", "&gt")
username = username.replace("&", "&amp").replace("<", "&lt").replace(">", "&gt")
title = account.get("title", username).replace("&", "&amp").replace("<", "&lt").replace(">", "&gt")
avatar = Safe(account.get("avatar", ""))
if not avatar: avatar = "/pictures/monkey.png"
username = Safe(username)
title = Safe(account.get("title", username))
html = '<img style="height:50px;vertical-align: middle" src="'+avatar+'">&nbsp;&nbsp;<a href="/account/'+username+'">'+title+'</a></center>\n'
return html
@ -430,4 +644,18 @@ def Graph(server, url):
html = html + '<div style="top:'+str(60-height)+'%;right:'+str((nd)*(width))+'%; width:'+str(max(width-0.5,0.5))+'%; height:'+str(height)+'%" title="'+str(date)+' - '+str(amount)+' views" class="graph_line"></div>\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)

View file

@ -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("?")]