Code structuring; Requests tests

This commit is contained in:
octospacc 2023-04-19 00:16:35 +02:00
parent a10f82c385
commit b96b82847a
7 changed files with 271 additions and 111 deletions

1
.gitignore vendored Normal file
View File

@ -0,0 +1 @@
Dist/*

23
Build.py Executable file
View File

@ -0,0 +1,23 @@
#!/usr/bin/env python3
import os
from pathlib import Path
os.makedirs('./Dist', exist_ok=True)
with open('./Friendiiverse.html', 'r') as Base:
Base = Base.read()
def FragReplace(Find, Replace, Pattern='*.*', Folder='./'):
global Base
for File in Path('./').rglob(Pattern):
with open(File, 'r') as Frag:
Frag = Replace[0] + Frag.read() + Replace[1]
for Prefix in ('', './'):
Base = Base.replace(Find[0] + Prefix + str(File) + Find[1], Frag)
FragReplace(('<link rel="stylesheet" href="', '"/>'), ('<style>', '</style>'), '*.css')
FragReplace(('<script src="', '"></script>'), ('<script>', '</script>'), '*.js')
with open('./Dist/Friendiiverse.html', 'w') as Build:
Build.write(Base)

View File

@ -3,12 +3,7 @@
<head>
<meta charset="utf-8"/>
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
<title></title>
<style>
img, video { max-width: 100%; }
#DataView { white-space: break-spaces; }
.PostView { border: 4px solid purple; margin: 12px; }
</style>
<link rel="stylesheet" href="./Style.css"/>
<script>
// Credentials hardcoding for now
var MastodonUrl = 'https://mastodon.uno';
@ -21,116 +16,25 @@ var UseFakeApi = true;
</script>
</head>
<body>
<div id=CoverView>
<div id="CoverView">
LOGO
Loading...
</div>
<div id=NoscriptView>
<div id="NoscriptView">
No Script!
</div>
<div id=PlazasView></div>
<div id=TimelineView></div>
<xmp id=DataView></xmp>
<script>
NoscriptView.remove();
var FakeApi = {};
FakeApi.F = {};
FakeApi.My = {};
function LogDebug(Data, Status) {
<div id="PlazasView"></div>
<div id="TimelineView"></div>
<xmp id="DataView"></xmp>
<script src="./Translations.js"></script>
<script src="./Main.js"></script>
<script>(function(){
if (Debug) {
for (var i=0; i<Data.length; i++) {
try {
Data[i] = JSON.parse(Data[i]);
} catch(_){};
var El = document.createElement('script');
El.src="https://cdn.jsdelivr.net/npm/eruda";
document.body.appendChild(El);
El.onload = function(){ eruda.init(); };
};
console[{l: "log", e: "error"}[Status]](Data);
};
};
function ApiCall(Data) {
// Data = {Target: "Friendica", Method: "...", Data: {}, Call: (), CallFine: (), CallFail: ()}
var Req = new XMLHttpRequest();
Req.onreadystatechange = function(){
if (this.readyState == 4) {
var Status = String(this.status);
if (Data.Call) Data.Call(this);
if (Status.startsWith(4) || Status.startsWith(5)) {
if (Data.CallFail) Data.CallFail(this);
LogDebug([Status, this.responseText], 'e');
} else {
if (Data.CallFine) Data.CallFine(this);
LogDebug([Status, this.responseText], 'l');
};
};
};
if (Data.Target == 'Mastodon') {
Req.open('GET', `${MastodonUrl}/api/v1/${Data.Method}`, true);
};
if (Data.Target == 'Friendica') {
Req.open('GET', `${FriendicaUrl}/api/${Data.Method}.json`, true);
Req.setRequestHeader('Authorization', `Basic ${btoa(FriendicaCredentials)}`);
};
Req.send();
};
function MastodonParse(Data, Type) {
{
Status: function(Data){
},
}[Type](Data);
};
/*
function DisplayMastodonTimeline(Timeline) {
ApiCall({Target: "Mastodon", Method: Timeline, CallFine: function(Res){
DataView.innerHTML = Res.responseText;
JSON.parse(DataView.innerHTML).forEach(function(Item){
TimelineView.innerHTML += `<div class=PostView>
<a href="${Item.external_url}">${Item.created_at}</a>
${Item.friendica_author.url}
${Item.friendica_html}
</div>`;
});
}});
};
*/
function DisplayFriendicaTimeline(Timeline) {
ApiCall({Target: "Friendica", Method: Timeline, CallFine: function(Res){
DataView.innerHTML = Res.responseText;
JSON.parse(DataView.innerHTML).forEach(function(Item){
var Title = Item.friendica_title ? `<h2>${Item.friendica_title}</h2>` : '';
TimelineView.innerHTML += `<div class=PostView>
<a href="${Item.external_url}">${Item.created_at}</a>
${Item.friendica_author.url}
${Title}
${Item.friendica_html}
</div>`;
});
}});
};
PlazasView.innerHTML = `
<div>
<h3>Featured</h3>
<ul>
<li onclick="DisplayFriendicaTimeline('statuses/networkpublic_timeline');">Federation</li>
<li onclick="DisplayFriendicaTimeline('statuses/public_timeline');">${FriendicaUrl}</li>
<li onclick="DisplayMastodonTimeline('timelines/public');">${MastodonUrl}</li>
</ul>
</div>
<div>
<h3>Categories</h3>
<ul>
<li>Testing</li>
<li>#fediverse</li>
</ul>
</div>
`;
</script>
<script src="https://cdn.jsdelivr.net/npm/eruda" onload="eruda.init();" defer async></script>
})();</script>
</body>
</html>

136
Main.js Normal file
View File

@ -0,0 +1,136 @@
NoscriptView.remove();
var CurrentTimeline = [];
var CurrentTimelineExp = 0;
var FakeApi = {};
FakeApi.F = {};
FakeApi.My = {};
function LogDebug(Data, Status) {
if (Debug) {
for (var i=0; i<Data.length; i++) {
try {
Data[i] = JSON.parse(Data[i]);
} catch(_){};
};
console[{l: "log", e: "error"}[Status]](Data);
};
};
function ApiCall(Data) {
// Data = {Target: "Friendica", Method: "...", Data: {}, Call: (), CallFine: (), CallFail: ()}
var Req = new XMLHttpRequest();
//Req.onreadystatechange = function(){
Req.onloadend = function(){
//if (this.readyState == 4) {
var Status = String(this.status);
if (Data.Call) {
return Data.Call(this);
}
if (['1', '2', '3'].includes(Status[0])) {
if (Data.CallFine) {
return Data.CallFine(this);
};
LogDebug([Status, this.responseText], 'l');
} else
if (['4', '5'].includes(Status[0])) {
if (Data.CallFail) {
return Data.CallFail(this);
};
LogDebug([Status, this.responseText], 'e');
};
//};
};
if (Data.Target == 'Mastodon') {
Req.open('GET', `${MastodonUrl}/api/v1/${Data.Method}`, true);
};
if (Data.Target == 'Friendica') {
Req.open('GET', `${FriendicaUrl}/api/${Data.Method}.json`, true);
Req.setRequestHeader('Authorization', `Basic ${btoa(FriendicaCredentials)}`);
};
Req.send();
};
/*
function MastodonParse(Data, Type) {
var Trans = {
Status(Data) {
return JsonTranslate(Data, TransSchemas.Mastodon.Status);
},
}
return Trans[Type](Data);
};
*/
/*
function DisplayMastodonTimeline(Timeline) {
ApiCall({Target: "Mastodon", Method: Timeline, CallFine: function(Res){
DataView.innerHTML = Res.responseText;
JSON.parse(DataView.innerHTML).forEach(function(Item){
TimelineView.innerHTML += `<div class=PostView>
<a href="${Item.external_url}">${Item.created_at}</a>
${Item.friendica_author.url}
${Item.friendica_html}
</div>`;
});
}});
};
*/
function DisplayFriendicaTimeline(Timeline) {
ApiCall({Target: "Friendica", Method: Timeline, CallFine: function(Res){
DataView.innerHTML = Res.responseText;
JSON.parse(DataView.innerHTML).forEach(function(Item){
var Title = Item.friendica_title ? `<h2>${Item.friendica_title}</h2>` : '';
TimelineView.innerHTML += `<div class=PostView>
<a href="${Item.external_url}">${Item.created_at}</a>
${Item.friendica_author.url}
${Title}
${Item.friendica_html}
</div>`;
});
}});
};
function FetchMastodon() {
return ApiCall({Target: "Mastodon", Method: "timelines/public", CallFine: function(Res){
//console.log(JSON.parse(Res.responseText)[0])
console.log([TransParsers.Mastodon.Status(JSON.parse(Res.responseText)[0])])
//return [
// TransParsers.Mastodon.Status(JSON.parse(Res.responseText)[0])
//];
CurrentTimeline = CurrentTimeline.concat([TransParsers.Mastodon.Status(JSON.parse(Res.responseText)[0])]);
CurrentTimelineExp -= 1;
}});
};
function FillTimeline(Notes) {
console.log('notes', Notes)
Notes.forEach(function(Note){
TimelineView.innerHTML += `<div class=PostView>
<a href="${Note.Url}">${Note.Time}</a>
${Note.Author}
${Note.Content}
</div>`;
});
};
PlazasView.innerHTML = `
<div>
<h3>Featured</h3>
<ul>
<li onclick="DisplayFriendicaTimeline('statuses/networkpublic_timeline');">Federation</li>
<li onclick="DisplayFriendicaTimeline('statuses/public_timeline');">${FriendicaUrl}</li>
<li onclick="var CurrentTimelineExp = 1; FetchMastodon(); /*FillTimeline();*//*DisplayMastodonTimeline('timelines/public');*/">${MastodonUrl}</li>
</ul>
</div>
<div>
<h3>Categories</h3>
<ul>
<li>Testing</li>
<li>#fediverse</li>
</ul>
</div>
`;

13
Style.css Normal file
View File

@ -0,0 +1,13 @@
img, video {
max-width: 100%;
}
#DataView {
white-space: break-spaces;
}
.PostView {
border: 4px solid purple;
margin: 12px;
}

33
Test.txt Normal file
View File

@ -0,0 +1,33 @@
function ApiCall(f) {
var Req = new XMLHttpRequest();
Req.onloadend = function(){ f(this) };
Req.open('GET', `https://mastodon.social/api/v1/timelines/public`, true);
Req.send();
};
function Retry(Text, f) {
console.log(f)
if (Text) {
return Text;
} else {
setTimeout(f, 50, Text, f);
};
};
function PrintRes(Res) {
var Text = Res.responseText;
setTimeout(Retry, 50, Text, Retry);
return Res.responseText;
};
/*
function PrintRes(Res) {
console.log(Res.responseText);
return Res.responseText;
};
*/
function FetchContent() {
return ApiCall(PrintRes);
};

50
Translations.js Normal file
View File

@ -0,0 +1,50 @@
var TransSchemas = {
Mastodon: {
Account: {
"__": "Author",
"url": "Url",
},
Status: {
"__": "Note",
"account": {"__": "Account"},
"content": "Content",
"created_at": "Time",
"url": "Url",
},
},
};
var TransParsers = {
Mastodon: {
Account(Data) {
return JsonTranslate(Data, TransSchemas.Mastodon.Author);
},
Status(Data) {
return JsonTranslate(Data, TransSchemas.Mastodon.Status);
},
},
};
function JsonTranslate(Old, Schema) {
var New = {};
Object.keys(Old).forEach(function(OldKey){
var Content = Old[OldKey];
var NewKey = (OldKey in Schema ? Schema[OldKey]: OldKey);
if (typeof(Content) == 'object' && Content !== null) {
if (Array.isArray(Content)) {
// Lists
//New[NewKey] = Content;
//Content.forEach(function());
} else {
// Dicts
NewKey.__ ||= OldKey;
New[NewKey.__] = JsonTranslate(Content, NewKey);
};
} else {
// Values
New[NewKey] = Content;
};
});
return New;
};