Public Timelines improvements and fixes (#14)

Here's the rundown:

The public timeline no longer exists. However: your private timelines now exist and can be scrolled back and forth. This is an addition to content warnings, boosts, and plenty of bug fixes.
A code cleanup has been put into place as well to cut down on some of the crap. Overall it's pretty good.

Reviewed-on: #14
This commit is contained in:
CatAClock 2025-05-08 22:04:23 +00:00
parent 9b52f641cb
commit 8b66616c4e
10 changed files with 447 additions and 168 deletions

0
CSS/expanded.css Normal file
View file

View file

@ -179,6 +179,8 @@ html {
} }
.Post { .Post {
overflow: hidden;
border-style: solid; border-style: solid;
border-width: 2px; border-width: 2px;
@ -186,6 +188,10 @@ html {
height: 25%; height: 25%;
} }
.Post:hover {
overflow: scroll;
}
.Username { .Username {
text-align: center; text-align: center;
font-weight: bold; font-weight: bold;

22
HTML/expanded.html Normal file
View file

@ -0,0 +1,22 @@
<!DOCTYPE html>
<html lang="en">
<head>
<title>The Fediverse</title>
<meta name="description" content="Change the fucking channel already!">
<link rel="icon" href="../Icons/favicon.ico" />
<link rel="stylesheet" href="../CSS/expanded.css">
<script type="module" src="../JS/expanded.js"></script>
<!-- Dependenci -->
<script language="JavaScript" type="text/javascript" src="https://kjur.github.io/jsrsasign/jsrsasign-latest-all-min.js"></script>
</head>
<body style="margin: 0px; text-align: center;">
<header>
<h1 class="Handle"></h1>
<h2 class="Origin">Bsky/Mastodon (TODO)</h2>
<p class="DetailedText"></p>
<p>Image here if it is a thing (TODO)</p>
<p onclick="history.back()"><b>Back</b></p>
</header>
</body>
</html>

View file

@ -1,6 +1,37 @@
import * as Variables from "./Variables.js"; import * as Variables from "./Variables.js";
export async function GetTimeline(Cursor) {
if (localStorage.getItem(Variables.BlueskyAccessToken) == null) {
console.log("No access token!");
return "";
}
let PDS = localStorage.getItem(Variables.BlueskyPDS);
let DPoP;
let request;
if (Cursor == "") {
DPoP = await ClientDPoPPDS("GET", PDS + "/xrpc/app.bsky.feed.getTimeline");
request = fetch(PDS + "/xrpc/app.bsky.feed.getTimeline", {method: "GET", headers: {"Authorization": "DPoP " + localStorage.getItem(Variables.BlueskyAccessToken), "DPoP": DPoP}});
} else {
DPoP = await ClientDPoPPDS("GET", PDS + "/xrpc/app.bsky.feed.getTimeline?cursor=" + Cursor);
request = fetch(PDS + "/xrpc/app.bsky.feed.getTimeline?cursor=" + Cursor, {method: "GET", headers: {"Authorization": "DPoP " + localStorage.getItem(Variables.BlueskyAccessToken), "DPoP": DPoP}});
}
let body = await request.then((response) => response.json());
let status = await request.then((response) => response.status);
let header = await request.then((response) => response.headers.get("dpop-nonce"));
if (status == 401) {
await HandleError(body, header);
body = await GetTimeline(Cursor);
}
return body;
}
export async function CreatePost(DID, Text) { export async function CreatePost(DID, Text) {
if (localStorage.getItem(Variables.BlueskyAccessToken) == null) {
console.log("No access token!");
return "";
}
let PDS = localStorage.getItem(Variables.BlueskyPDS); let PDS = localStorage.getItem(Variables.BlueskyPDS);
let Json = { let Json = {
"$type": "app.bsky.feed.post", "$type": "app.bsky.feed.post",
@ -18,18 +49,77 @@ export async function CreatePost(DID, Text) {
let status = await request.then((response) => response.status); let status = await request.then((response) => response.status);
let header = await request.then((response) => response.headers.get("dpop-nonce")); let header = await request.then((response) => response.headers.get("dpop-nonce"));
if (status == 401) { if (status == 401) {
if (body.message.includes("DPoP nonce mismatch")) { await HandleError(body, header);
await localStorage.setItem(Variables.BlueskyNonce, header);
}
if (body.message.includes("claim timestamp check failed")) {
await RefreshTokens();
}
body = await CreatePost(DID, Text); body = await CreatePost(DID, Text);
} }
if (status == 400) {
let matches = body.message.match(/(\d+)/);
Json.text = Text.slice(0, matches[0] - 1);
RequestBody.record = Json;
DPoP = await ClientDPoPPDS("POST", PDS + "/xrpc/com.atproto.repo.createRecord");
request = fetch(PDS + "/xrpc/com.atproto.repo.createRecord", { body: JSON.stringify(RequestBody), method: "POST", headers: {"Content-Type": "application/json", "Authorization": "DPoP " + localStorage.getItem(Variables.BlueskyAccessToken), "DPoP": DPoP}});
body = await request.then((response) => response.json());
status = await request.then((response) => response.status);
await CreateReplyPost(DID, Text.slice(matches[0] - 1, Text.length - 1), body, body);
}
return body;
}
export async function CreateReplyPost(DID, Text, ReplyID, RootID) {
if (localStorage.getItem(Variables.BlueskyAccessToken) == null) {
console.log("No access token!");
return "";
}
let PDS = localStorage.getItem(Variables.BlueskyPDS);
let Json = {
"$type": "app.bsky.feed.post",
"text": Text,
"createdAt": new Date(Date.now()).toISOString(),
"reply": {
"root": {
"uri": ReplyID.uri,
"cid": ReplyID.cid
},
"parent": {
"uri": RootID.uri,
"cid": RootID.cid
}
}
}
let RequestBody = {
"repo": DID,
"collection": "app.bsky.feed.post",
"record": Json
}
let DPoP = await ClientDPoPPDS("POST", PDS + "/xrpc/com.atproto.repo.createRecord");
let request = fetch(PDS + "/xrpc/com.atproto.repo.createRecord", { body: JSON.stringify(RequestBody), method: "POST", headers: {"Content-Type": "application/json", "Authorization": "DPoP " + localStorage.getItem(Variables.BlueskyAccessToken), "DPoP": DPoP}});
let body = await request.then((response) => response.json());
let status = await request.then((response) => response.status);
let header = await request.then((response) => response.headers.get("dpop-nonce"));
if (status == 401) {
await HandleError(body, header);
body = await CreatePost(DID, Text);
}
if (status == 400) {
let matches = body.message.match(/(\d+)/);
Json.text = Text.slice(0, matches[0] - 1);
RequestBody.record = Json;
let DPoP = await ClientDPoPPDS("POST", PDS + "/xrpc/com.atproto.repo.createRecord");
let request = fetch(PDS + "/xrpc/com.atproto.repo.createRecord", { body: JSON.stringify(RequestBody), method: "POST", headers: {"Content-Type": "application/json", "Authorization": "DPoP " + localStorage.getItem(Variables.BlueskyAccessToken), "DPoP": DPoP}});
let body = await request.then((response) => response.json());
let status = await request.then((response) => response.status);
await CreateReplyPost(DID, Text.slice(matches[0] - 1, Text.length - 1), body, RootID);
}
return body; return body;
} }
export async function SetThreadGate(DID, Post, VisibilitySettings) { export async function SetThreadGate(DID, Post, VisibilitySettings) {
if (localStorage.getItem(Variables.BlueskyAccessToken) == null) {
console.log("No access token!");
return "";
}
let PDS = localStorage.getItem(Variables.BlueskyPDS); let PDS = localStorage.getItem(Variables.BlueskyPDS);
let Json = { let Json = {
"$type": "app.bsky.feed.threadgate", "$type": "app.bsky.feed.threadgate",
@ -49,12 +139,7 @@ export async function SetThreadGate(DID, Post, VisibilitySettings) {
let status = await request.then((response) => response.status); let status = await request.then((response) => response.status);
let header = await request.then((response) => response.headers.get("dpop-nonce")); let header = await request.then((response) => response.headers.get("dpop-nonce"));
if (status == 401) { if (status == 401) {
if (body.message.includes("DPoP nonce mismatch")) { await HandleError(body, header);
await localStorage.setItem(Variables.BlueskyNonce, header);
}
if (body.message.includes("claim timestamp check failed")) {
await RefreshTokens();
}
body = await SetThreadGate(DID, Post, VisibilitySettings); body = await SetThreadGate(DID, Post, VisibilitySettings);
} }
return body; return body;
@ -251,6 +336,15 @@ export async function RefreshTokens() {
localStorage.setItem(Variables.BlueskyRefreshToken, body.refresh_token); localStorage.setItem(Variables.BlueskyRefreshToken, body.refresh_token);
} }
async function HandleError(body, header) {
if (body.message.includes("DPoP nonce mismatch")) {
await localStorage.setItem(Variables.BlueskyNonce, header);
}
if (body.message.includes("claim timestamp check failed")) {
await RefreshTokens();
}
}
// Stolen from elsewhere. // Stolen from elsewhere.
// Firefox snippet; Slightly edited. // Firefox snippet; Slightly edited.
async function sha256(message) { async function sha256(message) {

View file

@ -12,67 +12,115 @@ export async function GetPublicTimeline(Local = false, Remote = false, Website)
} }
if (Local == true) { if (Local == true) {
Timeline = await fetch(Website + "/api/v1/timelines/public?limit=12&local=true") Timeline = await fetch(Website + "/api/v1/timelines/public?local=true")
.then((response) => response.json()); .then((response) => response.json());
} else if (Remote == true) { } else if (Remote == true) {
Timeline = await fetch(Website + "/api/v1/timelines/public?limit=12&remote=true") Timeline = await fetch(Website + "/api/v1/timelines/public?remote=true")
.then((response) => response.json()); .then((response) => response.json());
} else { } else {
Timeline = await fetch(Website + "/api/v1/timelines/public?limit=12") Timeline = await fetch(Website + "/api/v1/timelines/public")
.then((response) => response.json()); .then((response) => response.json());
} }
return Timeline; return Timeline;
} }
// Gets the favorites of a user that you have access to. // Get the personal timeline.
export async function GetFavorites() { export async function GetTimeline(Cursor) {
let Favorites; if (localStorage.getItem(Variables.MastodonAccessToken) == null) {
// Check for a token. console.log("No access token!");
if (localStorage.getItem(Variables.MastodonAccessToken) != null) { return "";
let Website = Variables.MastodonWebsite; }
// Get the varaibles that are stored in localStorage. let Website = localStorage.getItem(Variables.MastodonWebsite);
Favorites = await fetch(Website + "/api/v1/favourites", {method: "GET", headers: {"Authorization": localStorage.getItem(Variables.MastodonTokenType) + " " + localStorage.getItem(Variables.MastodonAccessToken)}}) // Get the varaibles that are stored in localStorage.
if (Cursor == "") {
return await fetch(Website + "/api/v1/timelines/home", {method: "GET", headers: {"Authorization": localStorage.getItem(Variables.MastodonTokenType) + " " + localStorage.getItem(Variables.MastodonAccessToken)}})
.then((response) => response.json());
} else {
return await fetch(Website + "/api/v1/timelines/home?max_id=" + Cursor, {method: "GET", headers: {"Authorization": localStorage.getItem(Variables.MastodonTokenType) + " " + localStorage.getItem(Variables.MastodonAccessToken)}})
.then((response) => response.json()); .then((response) => response.json());
} }
return Favorites; }
// Gets the favorites of a user that you have access to.
export async function GetFavorites() {
if (localStorage.getItem(Variables.MastodonAccessToken) == null) {
console.log("No access token!");
return "";
}
let Website = localStorage.getItem(Variables.MastodonWebsite);
// Get the varaibles that are stored in localStorage.
return await fetch(Website + "/api/v1/favourites", {method: "GET", headers: {"Authorization": localStorage.getItem(Variables.MastodonTokenType) + " " + localStorage.getItem(Variables.MastodonAccessToken)}})
.then((response) => response.json());
} }
// Gets the bookmarks of a user that you have access to. // Gets the bookmarks of a user that you have access to.
export async function GetBookmarks() { export async function GetBookmarks() {
let Bookmarks; if (localStorage.getItem(Variables.MastodonAccessToken) == null) {
// Check for a token. console.log("No access token!");
if (localStorage.getItem(Variables.MastodonAccessToken) != null) { return "";
let Website = localStorage.getItem(Variables.MastodonWebsite);
// Get the varaibles that are stored in Variables.
Bookmarks = await fetch(Website + "/api/v1/bookmarks", {method: "GET", headers: {"Authorization": localStorage.getItem(Variables.MastodonTokenType) + " " + localStorage.getItem(Variables.MastodonAccessToken)}})
.then((response) => response.json());
} }
return Bookmarks; let Website = localStorage.getItem(Variables.MastodonWebsite);
// Get the varaibles that are stored in Variables.
return await fetch(Website + "/api/v1/bookmarks", {method: "GET", headers: {"Authorization": localStorage.getItem(Variables.MastodonTokenType) + " " + localStorage.getItem(Variables.MastodonAccessToken)}})
.then((response) => response.json());
} }
// Gets the notifications of a user that you have access to. // Gets the notifications of a user that you have access to.
export async function GetNotifications() { export async function GetNotifications() {
let Notifications; if (localStorage.getItem(Variables.MastodonAccessToken) == null) {
// Check for a token. console.log("No access token!");
if (localStorage.getItem(Variables.MastodonAccessToken) != null) { return "";
let Website = localStorage.getItem(Variables.MastodonWebsite);
// Get the varaibles that are stored in Variables and then input it.
Notifications = await fetch(Website + "/api/v1/notifications", {method: "GET", headers: {"Authorization": localStorage.getItem(Variables.MastodonTokenType) + " " + localStorage.getItem(Variables.MastodonAccessToken)}})
.then((response) => response.json());
} }
return Notifications; let Website = localStorage.getItem(Variables.MastodonWebsite);
// Get the varaibles that are stored in Variables and then input it.
return await fetch(Website + "/api/v1/notifications", {method: "GET", headers: {"Authorization": localStorage.getItem(Variables.MastodonTokenType) + " " + localStorage.getItem(Variables.MastodonAccessToken)}})
.then((response) => response.json());
} }
// Make a status // Make a status
export async function CreateStatus(Text, Visibility = "public") { export async function CreateStatus(Text, Visibility = "public") {
if (localStorage.getItem(Variables.MastodonAccessToken) == null) {
console.log("No access token!");
return "";
}
// Stolen from StackOverflow // Stolen from StackOverflow
Text = Text.replace(/(?:\r|\n|\r\n)/g, '<br>'); Text = Text.replace(/(?:\r|\n|\r\n)/g, '<br>');
// Check for a token // Check for a token
if (localStorage.getItem(Variables.MastodonAccessToken) != null) { let Website = localStorage.getItem(Variables.MastodonWebsite);
let Website = localStorage.getItem(Variables.MastodonWebsite); let request = fetch(Website + "/api/v1/statuses?status=" + Text + "&visibility=" + Visibility, {method: "POST", headers: {"Authorization": localStorage.getItem(Variables.MastodonTokenType) + " " + localStorage.getItem(Variables.MastodonAccessToken)}});
return await fetch(Website + "/api/v1/statuses?status=" + Text + "&visibility=" + Visibility, {method: "POST", headers: {"Authorization": localStorage.getItem(Variables.MastodonTokenType) + " " + localStorage.getItem(Variables.MastodonAccessToken)}}) let body = await request.then((response) => response.json());
.then((response) => response.json()); let status = await request.then((response) => response.status);
// This is in case you went over the characters.
if (status == 422) {
let matches = body.error.match(/(\d+)/);
console.log(matches);
request = fetch(Website + "/api/v1/statuses?status=" + Text.slice(0, matches[0] - 1) + "&visibility=" + Visibility, {method: "POST", headers: {"Authorization": localStorage.getItem(Variables.MastodonTokenType) + " " + localStorage.getItem(Variables.MastodonAccessToken)}});
body = await request.then((response) => response.json());
await CreateReplyStatus(Text.slice(matches[0] - 1, Text.length - 1), Visibility, body.id);
} }
return body;
}
export async function CreateReplyStatus(Text, Visibility = "public", ReplyID) {
if (localStorage.getItem(Variables.MastodonAccessToken) == null) {
console.log("No access token!");
return "";
}
// Stolen from StackOverflow
Text = Text.replace(/(?:\r|\n|\r\n)/g, '<br>');
// Check for a token
let Website = localStorage.getItem(Variables.MastodonWebsite);
let request = fetch(Website + "/api/v1/statuses?status=" + Text + "&visibility=" + Visibility + "&in_reply_to_id=" + ReplyID, {method: "POST", headers: {"Authorization": localStorage.getItem(Variables.MastodonTokenType) + " " + localStorage.getItem(Variables.MastodonAccessToken)}});
let body = await request.then((response) => response.json());
let status = await request.then((response) => response.status);
// This is in case you went over the characters.
if (status == 422) {
let matches = body.error.match(/(\d+)/);
request = fetch(Website + "/api/v1/statuses?status=" + Text.slice(0, matches[0] - 1) + "&visibility=" + Visibility + "&in_reply_to_id=" + ReplyID, {method: "POST", headers: {"Authorization": localStorage.getItem(Variables.MastodonTokenType) + " " + localStorage.getItem(Variables.MastodonAccessToken)}});
body = await request.then((response) => response.json());
await CreateReplyStatus(Text.slice(matches[0] - 1, Text.length - 1), Visibility, body.id);
}
return body;
} }
// The first step to using the app. // The first step to using the app.

View file

@ -1,4 +1,3 @@
// STRINGS TODO: make sure to seperate stuff that a user will want to input: BlueskyPDSName.
// Mastodon // Mastodon
export const MastodonWebsite = "mastodon_website"; export const MastodonWebsite = "mastodon_website";
export const MastodonClientID = "mastodon_client_id"; export const MastodonClientID = "mastodon_client_id";

5
JS/expanded.js Normal file
View file

@ -0,0 +1,5 @@
let content = decodeURI(document.location.href.split("content=")[1]);
let username = decodeURI(document.location.href.split("username=")[1].split("&content")[0]);
document.getElementsByClassName("Handle")[0].innerHTML = username;
document.getElementsByClassName("DetailedText")[0].innerHTML = content;

View file

@ -8,6 +8,7 @@ import * as Variables from "./Variables.js";
let Warning = document.getElementsByClassName("WarningMessage")[0]; let Warning = document.getElementsByClassName("WarningMessage")[0];
let Main = document.getElementsByClassName("MainBefore")[0]; let Main = document.getElementsByClassName("MainBefore")[0];
let ContainerContainer = document.getElementsByClassName("PostContainerContainer")[0]; let ContainerContainer = document.getElementsByClassName("PostContainerContainer")[0];
let ClickableContainers = ContainerContainer.getElementsByClassName("PostContainer")[2].children;
let BrowserWidth = window.innerWidth; let BrowserWidth = window.innerWidth;
let BrowserHeight = window.innerHeight; let BrowserHeight = window.innerHeight;
@ -81,12 +82,11 @@ ArrowsButton[1].onclick = (event) => {
if (!ContainerContainer.classList.contains("NextAnimation")) { if (!ContainerContainer.classList.contains("NextAnimation")) {
ContainerContainer.classList.add("NextAnimation"); ContainerContainer.classList.add("NextAnimation");
ButtonSound.play(); ButtonSound.play();
console.log("loading next posts...");
setTimeout(() => { setTimeout(() => {
ContainerContainer.classList.remove("NextAnimation"); ContainerContainer.classList.remove("NextAnimation");
}, 1000); }, 1000);
PosterContainerUpdate("Forward");
} }
PosterContainerUpdate();
} }
// Clicking the back button // Clicking the back button
@ -94,39 +94,140 @@ ArrowsButton[0].onclick = (event) => {
if (!ContainerContainer.classList.contains("BackAnimation")) { if (!ContainerContainer.classList.contains("BackAnimation")) {
ContainerContainer.classList.add("BackAnimation"); ContainerContainer.classList.add("BackAnimation");
ButtonSound.play(); ButtonSound.play();
console.log("getting previous posts...");
setTimeout(() => { setTimeout(() => {
ContainerContainer.classList.remove("BackAnimation"); ContainerContainer.classList.remove("BackAnimation");
}, 1000); }, 1000);
PosterContainerUpdate("Backward");
} }
PosterContainerUpdate();
} }
// MastodonAPI integration for (let i of ClickableContainers) {
async function PosterContainerUpdate() { i.onclick = (event) => {
// Variables for the public timelines let content = i.getElementsByClassName("PostContent")[0].innerHTML
let LocalVar = localStorage.getItem("Local"); let username = i.getElementsByClassName("Username")[0].innerHTML
var LocalTrue = (LocalVar === "true"); // Save some info
let RemoteVar = localStorage.getItem("Remote"); window.location.href = "./HTML/expanded.html?username=" + username + "&content=" + content;
var RemoteTrue = (RemoteVar === "true"); }
}
// These numbers are here so you don't go back.
let MastodonLoadedFeed = [];
let BlueskyLoadedFeed = [];
let CurrentThing = 0;
// Call this to update the things :)
async function PosterContainerUpdate(Direction) {
let Lim = 6;
let Website = localStorage.getItem(Variables.MastodonWebsite); let Website = localStorage.getItem(Variables.MastodonWebsite);
if (localStorage.getItem(Variables.MastodonWebsite) == null) { let Mastodon = true;
Website = "https://wetdry.world";
}
let Timeline = await MastodonAPI.GetPublicTimeline(LocalTrue, RemoteTrue, Website); // Mastodon gaining of timeline.
let Content = []; if (localStorage.getItem(Variables.MastodonWebsite) == null) {
let Users = []; // The default website is Wetdry :3
for (let i in Timeline) { console.log("No Mastodon instance. multiplying mastodon posts by 2...");
Content[i] = Timeline[i].content; Lim = Lim * 2;
Users[i] = Timeline[i].account.username; Mastodon = false;
} else if (MastodonLoadedFeed == 0) {
MastodonLoadedFeed = await MastodonAPI.GetTimeline("");
} }
let CenterContainer = document.getElementsByClassName("PostContainer")[2].children; // Bluesky gaining of timeline.
for (let i in CenterContainer) { if (localStorage.getItem(Variables.BlueskyPDS) == null) {
CenterContainer[i].getElementsByClassName("PostContent")[0].innerHTML = Content[i]; console.log("No Bluesky instance. multiplying mastodon posts by 2...");
CenterContainer[i].getElementsByClassName("Username")[0].innerHTML = Users[i]; Lim = Lim * 2;
} else if (BlueskyLoadedFeed.length == 0) {
BlueskyLoadedFeed = await BlueskyAPI.GetTimeline("").then((response) => response.feed);
} }
if (Direction == "Forward") {
CurrentThing = CurrentThing + Lim;
} else if (Direction == "Backward") {
if (CurrentThing - Lim >= 0) {
CurrentThing = CurrentThing - Lim;
}
}
// Debugging
console.log(MastodonLoadedFeed);
console.log(BlueskyLoadedFeed);
// The first one is for counting.
// The countergroup increments to another timeline once posts hit the "limit".
let counter = 0;
let countergroup = 0;
if (Mastodon == false) {
countergroup = countergroup + 1;
}
// This var is meant to stop "already seen" posts.
let BlueskyPostsDup = [];
for (let i of ClickableContainers) {
switch(countergroup) {
// Mastodon
case 0:
if (MastodonLoadedFeed[CurrentThing + counter] == undefined) {
let TempFeed = await MastodonAPI.GetTimeline(MastodonLoadedFeed[CurrentThing + counter - 1].id);
MastodonLoadedFeed = MastodonLoadedFeed.concat(TempFeed);
}
// Content warning. Don't show the content unless clicked!!!
if (MastodonLoadedFeed[CurrentThing + counter].spoiler_text != "") {
i.getElementsByClassName("PostContent")[0].innerHTML = "<b>WARNING: " + MastodonLoadedFeed[CurrentThing + counter].spoiler_text + "</b>";
i.getElementsByClassName("Username")[0].innerHTML = MastodonLoadedFeed[CurrentThing + counter].account.username;
break;
}
// Check for a reblog.
if (MastodonLoadedFeed[CurrentThing + counter].reblog != null) {
i.getElementsByClassName("PostContent")[0].innerHTML = MastodonLoadedFeed[CurrentThing + counter].reblog.content;
i.getElementsByClassName("Username")[0].innerHTML = MastodonLoadedFeed[CurrentThing + counter].reblog.account.username + " ( R: " + MastodonLoadedFeed[CurrentThing + counter].account.username + " )";
} else {
i.getElementsByClassName("PostContent")[0].innerHTML = MastodonLoadedFeed[CurrentThing + counter].content;
i.getElementsByClassName("Username")[0].innerHTML = MastodonLoadedFeed[CurrentThing + counter].account.username;
}
break;
// Bsky
case 1:
if (BlueskyLoadedFeed[CurrentThing + counter] == undefined) {
let TempFeed = await BlueskyAPI.GetTimeline(BlueskyLoadedFeed[CurrentThing + counter - 1].post.indexedAt).then((response) => response.feed)
BlueskyLoadedFeed = BlueskyLoadedFeed.concat(TempFeed);
}
// check for "already seen" posts, then put it as a seen post.
BlueskyLoadedFeed = CheckForDups(BlueskyLoadedFeed, BlueskyPostsDup, counter);
BlueskyPostsDup.push(BlueskyLoadedFeed[counter].post.uri);
// Labels
if (BlueskyLoadedFeed[CurrentThing + counter].post.labels.length != 0) {
i.getElementsByClassName("PostContent")[0].innerHTML = "<b>LABELS APPLIED: ";
i.getElementsByClassName("Username")[0].innerHTML = BlueskyLoadedFeed[CurrentThing + counter].post.author.handle;
for (let lab of BlueskyLoadedFeed[CurrentThing + counter].post.labels) {
i.getElementsByClassName("PostContent")[0].innerHTML = i.getElementsByClassName("PostContent")[0].innerHTML + lab.val + " ";
}
i.getElementsByClassName("PostContent")[0].innerHTML = i.getElementsByClassName("PostContent")[0].innerHTML + "</b>";
break;
}
// Check for a reblog
if (BlueskyLoadedFeed[CurrentThing + counter].hasOwnProperty("reason") && BlueskyLoadedFeed[CurrentThing + counter].reason.$type == "app.bsky.feed.defs#reasonRepost") {
i.getElementsByClassName("PostContent")[0].innerHTML = BlueskyLoadedFeed[CurrentThing + counter].post.record.text;
i.getElementsByClassName("Username")[0].innerHTML = BlueskyLoadedFeed[CurrentThing + counter].post.author.handle + " ( R: " + BlueskyLoadedFeed[CurrentThing + counter].reason.by.handle + " )";
} else {
i.getElementsByClassName("PostContent")[0].innerHTML = BlueskyLoadedFeed[CurrentThing + counter].post.record.text;
i.getElementsByClassName("Username")[0].innerHTML = BlueskyLoadedFeed[CurrentThing + counter].post.author.handle;
}
// Direction for where you go :3
break;
}
counter = counter + 1;
if (counter >= Lim) {
counter = 0;
countergroup = countergroup + 1;
}
}
}
// Assistant function to help with checking for duplicates.
function CheckForDups(Timeline, DupeArray, counter) {
for (let j of DupeArray) {
if (j == Timeline[counter].post.uri) {
Timeline.splice(counter, 1);
console.log("Culled a duplicate post.")
Timeline = CheckForDups(Timeline, DupeArray, counter);
}
}
return Timeline;
} }
// Open the settings // Open the settings

View file

@ -8,6 +8,9 @@ let PostButton = document.getElementsByClassName("Button")[0];
let VisibilityDropdown = document.getElementsByClassName("PostVisibility")[0]; let VisibilityDropdown = document.getElementsByClassName("PostVisibility")[0];
let InputArea = document.getElementsByClassName("Text")[0]; let InputArea = document.getElementsByClassName("Text")[0];
// Extra Variables
// Clicking the beeg POST button. // Clicking the beeg POST button.
PostButton.onclick = (event) => { PostButton.onclick = (event) => {
Post(); Post();
@ -57,9 +60,7 @@ async function Post() {
break; break;
} }
let Post = await BlueskyAPI.CreatePost(localStorage.getItem(Variables.BlueskyDID), Text); let Post = await BlueskyAPI.CreatePost(localStorage.getItem(Variables.BlueskyDID), Text);
console.log(Post);
let ThreadGate = await BlueskyAPI.SetThreadGate(localStorage.getItem(Variables.BlueskyDID), Post.uri, TempVisible); let ThreadGate = await BlueskyAPI.SetThreadGate(localStorage.getItem(Variables.BlueskyDID), Post.uri, TempVisible);
console.log(ThreadGate);
} }
InputArea.value = ""; InputArea.value = "";
} }

View file

@ -9,6 +9,8 @@
This is the only way I knew how to make a "non-module" inherit a module. This is the only way I knew how to make a "non-module" inherit a module.
I think this is why people use typescript or other frameworks. --> I think this is why people use typescript or other frameworks. -->
<script type="module" src="./JS/index.js"></script> <script type="module" src="./JS/index.js"></script>
<!-- Dependenci -->
<script language="JavaScript" type="text/javascript" src="https://kjur.github.io/jsrsasign/jsrsasign-latest-all-min.js"></script>
</head> </head>
<body style="margin: 0px;"> <body style="margin: 0px;">
@ -31,255 +33,256 @@
<div style="width: 100%" class="PostContainerContainer"> <div style="width: 100%" class="PostContainerContainer">
<div style="left: -170vw;" class="PostContainer Back"> <div style="left: -170vw;" class="PostContainer Back">
<article class="Post"> <article class="Post">
<p class="Username">No</p> <p class="Username"></p>
<p class="PostContent"></p> <p class="PostContent"></p>
</article> </article>
<article class="Post"> <article class="Post">
<p class="Username">No</p> <p class="Username"></p>
<p class="PostContent"></p> <p class="PostContent"></p>
</article> </article>
<article class="Post"> <article class="Post">
<p class="Username">No</p> <p class="Username"></p>
<p class="PostContent"></p> <p class="PostContent"></p>
</article> </article>
<article class="Post"> <article class="Post">
<p class="Username">No</p> <p class="Username"></p>
<p class="PostContent"></p> <p class="PostContent"></p>
</article> </article>
<article class="Post"> <article class="Post">
<p class="Username">No</p> <p class="Username"></p>
<p class="PostContent"></p> <p class="PostContent"></p>
</article> </article>
<article class="Post"> <article class="Post">
<p class="Username">No</p> <p class="Username"></p>
<p class="PostContent"></p> <p class="PostContent"></p>
</article> </article>
<article class="Post"> <article class="Post">
<p class="Username">No</p> <p class="Username"></p>
<p class="PostContent"></p> <p class="PostContent"></p>
</article> </article>
<article class="Post"> <article class="Post">
<p class="Username">No</p> <p class="Username"></p>
<p class="PostContent"></p> <p class="PostContent"></p>
</article> </article>
<article class="Post"> <article class="Post">
<p class="Username">No</p> <p class="Username"></p>
<p class="PostContent"></p> <p class="PostContent"></p>
</article> </article>
<article class="Post"> <article class="Post">
<p class="Username">No</p> <p class="Username"></p>
<p class="PostContent"></p> <p class="PostContent"></p>
</article> </article>
<article class="Post"> <article class="Post">
<p class="Username">No</p> <p class="Username"></p>
<p class="PostContent"></p> <p class="PostContent"></p>
</article> </article>
<article class="Post"> <article class="Post">
<p class="Username">No</p> <p class="Username"></p>
<p class="PostContent"></p> <p class="PostContent"></p>
</article> </article>
</div> </div>
<div style="left: -85vw;" class="PostContainer Back"> <div style="left: -85vw;" class="PostContainer Back">
<article class="Post"> <article class="Post">
<p class="Username">Testing</p> <p class="Username"></p>
<p class="PostContent">The things</p> <p class="PostContent"></p>
</article> </article>
<article class="Post"> <article class="Post">
<p class="Username">Testing</p> <p class="Username"></p>
<p class="PostContent">The things</p> <p class="PostContent"></p>
</article> </article>
<article class="Post"> <article class="Post">
<p class="Username">Testing</p> <p class="Username"></p>
<p class="PostContent">The things</p> <p class="PostContent"></p>
</article> </article>
<article class="Post"> <article class="Post">
<p class="Username">Testing</p> <p class="Username"></p>
<p class="PostContent">The things</p> <p class="PostContent"></p>
</article> </article>
<article class="Post"> <article class="Post">
<p class="Username">Testing</p> <p class="Username"></p>
<p class="PostContent">The things</p> <p class="PostContent"></p>
</article> </article>
<article class="Post"> <article class="Post">
<p class="Username">Testing</p> <p class="Username"></p>
<p class="PostContent">The things</p> <p class="PostContent"></p>
</article> </article>
<article class="Post"> <article class="Post">
<p class="Username">Testing</p> <p class="Username"></p>
<p class="PostContent">The things</p> <p class="PostContent"></p>
</article> </article>
<article class="Post"> <article class="Post">
<p class="Username">Testing</p> <p class="Username"></p>
<p class="PostContent">The things</p> <p class="PostContent"></p>
</article> </article>
<article class="Post"> <article class="Post">
<p class="Username">Testing</p> <p class="Username"></p>
<p class="PostContent">The things</p> <p class="PostContent"></p>
</article> </article>
<article class="Post"> <article class="Post">
<p class="Username">Testing</p> <p class="Username"></p>
<p class="PostContent">The things</p> <p class="PostContent"></p>
</article> </article>
<article class="Post"> <article class="Post">
<p class="Username">Testing</p> <p class="Username"></p>
<p class="PostContent">The things</p> <p class="PostContent"></p>
</article> </article>
<article class="Post"> <article class="Post">
<p class="Username">Testing</p> <p class="Username"></p>
<p class="PostContent">The things</p> <p class="PostContent"></p>
</article> </article>
</div> </div>
<!-- This is the container that houses the current viewing stuff -->
<div class="PostContainer"> <div class="PostContainer">
<article class="Post"> <article class="Post">
<p class="Username">Testing</p> <p class="Username"></p>
<p class="PostContent">The things</p> <p class="PostContent"></p>
</article> </article>
<article class="Post"> <article class="Post">
<p class="Username">Testing</p> <p class="Username"></p>
<p class="PostContent">The things</p> <p class="PostContent"></p>
</article> </article>
<article class="Post"> <article class="Post">
<p class="Username">Testing</p> <p class="Username"></p>
<p class="PostContent">The things</p> <p class="PostContent"></p>
</article> </article>
<article class="Post"> <article class="Post">
<p class="Username">Testing</p> <p class="Username"></p>
<p class="PostContent">The things</p> <p class="PostContent"></p>
</article> </article>
<article class="Post"> <article class="Post">
<p class="Username">Testing</p> <p class="Username"></p>
<p class="PostContent">The things</p> <p class="PostContent"></p>
</article> </article>
<article class="Post"> <article class="Post">
<p class="Username">Testing</p> <p class="Username"></p>
<p class="PostContent">The things</p> <p class="PostContent"></p>
</article> </article>
<article class="Post"> <article class="Post">
<p class="Username">Testing</p> <p class="Username"></p>
<p class="PostContent">The things</p> <p class="PostContent"></p>
</article> </article>
<article class="Post"> <article class="Post">
<p class="Username">Testing</p> <p class="Username"></p>
<p class="PostContent">The things</p> <p class="PostContent"></p>
</article> </article>
<article class="Post"> <article class="Post">
<p class="Username">Testing</p> <p class="Username"></p>
<p class="PostContent">The things</p> <p class="PostContent"></p>
</article> </article>
<article class="Post"> <article class="Post">
<p class="Username">Testing</p> <p class="Username"></p>
<p class="PostContent">The things</p> <p class="PostContent"></p>
</article> </article>
<article class="Post"> <article class="Post">
<p class="Username">Testing</p> <p class="Username"></p>
<p class="PostContent">The things</p> <p class="PostContent"></p>
</article> </article>
<article class="Post"> <article class="Post">
<p class="Username">Testing</p> <p class="Username"></p>
<p class="PostContent">The things</p> <p class="PostContent"></p>
</article> </article>
</div> </div>
<div style="left: 85vw;" class="PostContainer Next"> <div style="left: 85vw;" class="PostContainer Next">
<article class="Post"> <article class="Post">
<p class="Username">Testing</p> <p class="Username"></p>
<p class="PostContent">The things</p> <p class="PostContent"></p>
</article> </article>
<article class="Post"> <article class="Post">
<p class="Username">Testing</p> <p class="Username"></p>
<p class="PostContent">The things</p> <p class="PostContent"></p>
</article> </article>
<article class="Post"> <article class="Post">
<p class="Username">Testing</p> <p class="Username"></p>
<p class="PostContent">The things</p> <p class="PostContent"></p>
</article> </article>
<article class="Post"> <article class="Post">
<p class="Username">Testing</p> <p class="Username"></p>
<p class="PostContent">The things</p> <p class="PostContent"></p>
</article> </article>
<article class="Post"> <article class="Post">
<p class="Username">Testing</p> <p class="Username"></p>
<p class="PostContent">The things</p> <p class="PostContent"></p>
</article> </article>
<article class="Post"> <article class="Post">
<p class="Username">Testing</p> <p class="Username"></p>
<p class="PostContent">The things</p> <p class="PostContent"></p>
</article> </article>
<article class="Post"> <article class="Post">
<p class="Username">Testing</p> <p class="Username"></p>
<p class="PostContent">The things</p> <p class="PostContent"></p>
</article> </article>
<article class="Post"> <article class="Post">
<p class="Username">Testing</p> <p class="Username"></p>
<p class="PostContent">The things</p> <p class="PostContent"></p>
</article> </article>
<article class="Post"> <article class="Post">
<p class="Username">Testing</p> <p class="Username"></p>
<p class="PostContent">The things</p> <p class="PostContent"></p>
</article> </article>
<article class="Post"> <article class="Post">
<p class="Username">Testing</p> <p class="Username"></p>
<p class="PostContent">The things</p> <p class="PostContent"></p>
</article> </article>
<article class="Post"> <article class="Post">
<p class="Username">Testing</p> <p class="Username"></p>
<p class="PostContent">The things</p> <p class="PostContent"></p>
</article> </article>
<article class="Post"> <article class="Post">
<p class="Username">Testing</p> <p class="Username"></p>
<p class="PostContent">The things</p> <p class="PostContent"></p>
</article> </article>
</div> </div>
<div style="left: 170vw;" class="PostContainer Next"> <div style="left: 170vw;" class="PostContainer Next">
<article class="Post"> <article class="Post">
<p class="Username">No</p> <p class="Username"></p>
<p class="PostContent"></p> <p class="PostContent"></p>
</article> </article>
<article class="Post"> <article class="Post">
<p class="Username">No</p> <p class="Username"></p>
<p class="PostContent"></p> <p class="PostContent"></p>
</article> </article>
<article class="Post"> <article class="Post">
<p class="Username">No</p> <p class="Username"></p>
<p class="PostContent"></p> <p class="PostContent"></p>
</article> </article>
<article class="Post"> <article class="Post">
<p class="Username">No</p> <p class="Username"></p>
<p class="PostContent"></p> <p class="PostContent"></p>
</article> </article>
<article class="Post"> <article class="Post">
<p class="Username">No</p> <p class="Username"></p>
<p class="PostContent"></p> <p class="PostContent"></p>
</article> </article>
<article class="Post"> <article class="Post">
<p class="Username">No</p> <p class="Username"></p>
<p class="PostContent"></p> <p class="PostContent"></p>
</article> </article>
<article class="Post"> <article class="Post">
<p class="Username">No</p> <p class="Username"></p>
<p class="PostContent"></p> <p class="PostContent"></p>
</article> </article>
<article class="Post"> <article class="Post">
<p class="Username">No</p> <p class="Username"></p>
<p class="PostContent"></p> <p class="PostContent"></p>
</article> </article>
<article class="Post"> <article class="Post">
<p class="Username">No</p> <p class="Username"></p>
<p class="PostContent"></p> <p class="PostContent"></p>
</article> </article>
<article class="Post"> <article class="Post">
<p class="Username">No</p> <p class="Username"></p>
<p class="PostContent"></p> <p class="PostContent"></p>
</article> </article>
<article class="Post"> <article class="Post">
<p class="Username">No</p> <p class="Username"></p>
<p class="PostContent"></p> <p class="PostContent"></p>
</article> </article>
<article class="Post"> <article class="Post">
<p class="Username">No</p> <p class="Username"></p>
<p class="PostContent"></p> <p class="PostContent"></p>
</article> </article>
</div> </div>