Fix Json transformation for nested objects

This commit is contained in:
octospacc 2023-04-19 18:06:08 +02:00
parent 42dc0771d2
commit afea1367db
11 changed files with 123 additions and 162 deletions

View File

@ -2,12 +2,13 @@
import os
from pathlib import Path
os.chdir(os.path.dirname(os.path.abspath(__file__)))
os.makedirs('./Dist', exist_ok=True)
with open('./Friendiiverse.html', 'r') as Base:
Base = Base.read()
def FragReplace(Find, Replace, Pattern='*.*', Folder='./'):
def FragReplace(Find, Replace, Pattern='*.*', Folder='./Source/'):
global Base
for File in Path('./').rglob(Pattern):
with open(File, 'r') as Frag:

26
Source/ApiTransform.js Normal file
View File

@ -0,0 +1,26 @@
var TransSchemas = {
Mastodon: {
Account: {
"__": "Author",
"url": "Url",
},
Status: {
"__": "Note",
"account": {"__": "Account"},
"content": "Content",
"created_at": "Time",
"url": "Url",
},
},
};
var TransParsers = {
Mastodon: {
Account(Data) {
return JsonTransform(Data, TransSchemas.Mastodon.Author, TransSchemas.Mastodon);
},
Status(Data) {
return JsonTransform(Data, TransSchemas.Mastodon.Status, TransSchemas.Mastodon);
},
},
};

6
Source/FakeApi.js Normal file
View File

@ -0,0 +1,6 @@
var FakeApi = {
//
Mastodon: {
//"timelines/public":
},
};

View File

@ -6,7 +6,7 @@
<link rel="stylesheet" href="./Style.css"/>
<script>
// Credentials hardcoding for now
var MastodonUrl = 'https://mastodon.uno';
var MastodonUrl = 'https://mastodon.social';
var FriendicaUrl = 'https://poliverso.org';
var FriendicaCredentials = 'redacted:redacted';
@ -34,10 +34,11 @@ var UseFakeApi = true;
<script>NoscriptView.remove();</script>
<script src="./Utils.js"></script>
<script src="./Strings.js"></script>
<script src="./Translations.js"></script>
<script src="./ApiTransform.js"></script>
<script src="./FakeApi.js"></script>
<script src="./Main.js"></script>
<script>(function(){
if (Debug) {
if (Debug && new URLSearchParams(window.location.hash).get('#Eruda')) {
var El = document.createElement('script');
El.src="https://cdn.jsdelivr.net/npm/eruda";
document.body.appendChild(El);

View File

@ -1,36 +1,34 @@
var CurrTasks = {};
var CurrentTimeline = [];
var CurrentTimelineExp = 0;
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 DoAsync(First, Then, Data) {
var Job = RndId();
CurrTasks[Job] = {
Remains: 0,
Return(Data) {
this.Remains -= 1;
this.Result = Data;
},
};
};
function WaitTasks(First, Then, Data) {
var Run = RndId();
CurrTasks[Run] = {Remains: 0};
// Call all First functs
ForceList(First).forEach(function(Fun, Data){
var Task = RndId();
var Proc = [Run, Task];
CurrTasks[Run].Remains += 1;
Data ? Fun(Proc, Data) : Fun(Proc);
var Proc = [Job, Task];
CurrTasks[Job][Task] = {};
CurrTasks[Job].Remains += 1;
//Fun(Proc, Data);
Data ? Fun(Data, Proc) : Fun(Proc);
});
CurrTasks[Run].Interval = setInterval(function(Run, Then){
if (CurrTasks[Run].Remains === 0) {
clearInterval(CurrTasks[Run].Interval);
// Continuosly check when First functs completed
CurrTasks[Job].Interval = setInterval(function(Job, Then){
if (CurrTasks[Job].Remains <= 0) {
clearInterval(CurrTasks[Job].Interval);
// Call all Then functs
ForceList(Then).forEach(function(Fun){
Fun(CurrTasks[Run].Result);
Fun(CurrTasks[Job].Result);
});
};
}, 50, Run, Then);
}, 50, Job, Then);
return Job;
};
function HttpCodeGood(Code) {
@ -74,32 +72,6 @@ function ApiCall(Data, Proc) {
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;
@ -116,27 +88,18 @@ function DisplayFriendicaTimeline(Timeline) {
};
function FetchMastodon(Proc) {
return ApiCall({Target: "Mastodon", Method: "timelines/public", CallFine: function(Res){
//console.log(JSON.parse(Res.responseText)[0])
var New = [ TransParsers.Mastodon.Status( JSON.parse(Res.responseText)[0] ) ];
console.log(New)
//return [
// TransParsers.Mastodon.Status(JSON.parse(Res.responseText)[0])
//];
//CurrentTimeline = CurrentTimeline.concat([TransParsers.Mastodon.Status(JSON.parse(Res.responseText)[0])]);
//CurrentTimelineExp -= 1;
CurrTasks[Res.Proc[0]].Remains -= 1;
// TODO: store data in global object
CurrTasks[Res.Proc[0]].Result = New;
ApiCall({Target: "Mastodon", Method: "timelines/public", CallFine: function(Res){
var Notes = [ TransParsers.Mastodon.Status( JSON.parse(Res.responseText)[0] ) ];
LogDebug(Notes, 'l');
CurrTasks[Proc[0]].Return(Notes);
}}, Proc);
};
function FillTimeline(Notes) {
console.log('notes', Notes)
Notes.forEach(function(Note){
TimelineView.innerHTML += `<div class=PostView>
TimelineView.innerHTML += `<div class="NoteView">
<a href="${Note.Url}">${Note.Time}</a>
${Note.Author}
${Note.Author.Url}
${Note.Content}
</div>`;
});
@ -148,7 +111,10 @@ PlazasView.innerHTML = `
<ul>
<li onclick="DisplayFriendicaTimeline('statuses/networkpublic_timeline');">Federation</li>
<li onclick="DisplayFriendicaTimeline('statuses/public_timeline');">${FriendicaUrl}</li>
<li onclick="WaitTasks(FetchMastodon, FillTimeline);">${MastodonUrl}</li>
<li onclick="DoAsync(FetchMastodon, FillTimeline);">
<img src=""/>
${MastodonUrl}
</li>
</ul>
</div>
<div>

View File

@ -20,7 +20,7 @@ footer {
white-space: break-spaces;
}
.PostView {
.NoteView {
border: 4px solid purple;
margin: 12px;
}

52
Source/Utils.js Normal file
View File

@ -0,0 +1,52 @@
function ForceList(Item) {
return (Array.isArray(Item) ? Item : [Item]);
};
function RndId() {
return `${Date.now()}${Math.random()}`;
};
function LogDebug(Data, Status) {
if (Debug) {
if (!Status) {
Status = 'l';
};
for (var i=0; i<Data.length; i++) {
try {
Data[i] = JSON.parse(Data[i]);
} catch(_){};
};
console[{l: "log", e: "error"}[Status.toLowerCase()]](Data);
};
};
// Transform JSON tree into a new using a template schema
function JsonTransform(TreeOld, SchemaCurr, SchemaRoot) {
var TreeNew = {};
Object.keys(TreeOld).forEach(function(KeyOld){
var Content = TreeOld[KeyOld];
var KeyNew = ((typeof(SchemaCurr) == 'object' && KeyOld in SchemaCurr) ? SchemaCurr[KeyOld] : KeyOld);
if (typeof(Content) == 'object' && Content !== null) {
if (Array.isArray(Content)) {
// Lists
var ListNew = [];
Content.forEach(function(Value){
ListNew.push(JsonTransform(Value, KeyNew));
});
TreeNew[KeyNew] = ListNew;
} else {
// Dicts
if (!KeyNew.__) {
KeyNew.__ = KeyOld;
};
TreeNew[KeyNew.__] = JsonTransform(Content, SchemaRoot[KeyNew.__], SchemaRoot);
TreeNew[SchemaRoot[KeyNew.__].__] = TreeNew[KeyNew.__];
delete TreeNew[KeyNew.__];
};
} else {
// Values
TreeNew[KeyNew] = Content;
};
});
return TreeNew;
};

View File

@ -1,33 +0,0 @@
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);
};

View File

@ -1,51 +0,0 @@
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(TreeOld, Schema) {
var TreeNew = {};
Object.keys(TreeOld).forEach(function(KeyOld){
var Content = TreeOld[KeyOld];
var KeyNew = ((typeof(Schema) == 'object' && KeyOld in Schema) ? Schema[KeyOld] : KeyOld);
if (typeof(Content) == 'object' && Content !== null) {
if (Array.isArray(Content)) {
// Lists
//New[NewKey] = Content;
//Content.forEach(function());
} else {
// Dicts
if (!KeyNew.__) {
KeyNew.__ = KeyOld;
};
TreeNew[KeyNew.__] = JsonTranslate(Content, KeyNew);
};
} else {
// Values
TreeNew[KeyNew] = Content;
};
});
return TreeNew;
};

View File

@ -1,7 +0,0 @@
function ForceList(Item) {
return (Array.isArray(Item) ? Item : [Item]);
};
function RndId() {
return `${Date.now()}${Math.random()}`;
};