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

@ -178,7 +178,9 @@ html {
height: 70vh;
}
.Post {
.Post {
overflow: hidden;
border-style: solid;
border-width: 2px;
@ -186,6 +188,10 @@ html {
height: 25%;
}
.Post:hover {
overflow: scroll;
}
.Username {
text-align: center;
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";
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) {
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",
@ -18,18 +49,77 @@ export async function CreatePost(DID, Text) {
let status = await request.then((response) => response.status);
let header = await request.then((response) => response.headers.get("dpop-nonce"));
if (status == 401) {
if (body.message.includes("DPoP nonce mismatch")) {
await localStorage.setItem(Variables.BlueskyNonce, header);
}
if (body.message.includes("claim timestamp check failed")) {
await RefreshTokens();
}
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;
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;
}
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 Json = {
"$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 header = await request.then((response) => response.headers.get("dpop-nonce"));
if (status == 401) {
if (body.message.includes("DPoP nonce mismatch")) {
await localStorage.setItem(Variables.BlueskyNonce, header);
}
if (body.message.includes("claim timestamp check failed")) {
await RefreshTokens();
}
await HandleError(body, header);
body = await SetThreadGate(DID, Post, VisibilitySettings);
}
return body;
@ -251,6 +336,15 @@ export async function RefreshTokens() {
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.
// Firefox snippet; Slightly edited.
async function sha256(message) {

View file

@ -12,67 +12,115 @@ export async function GetPublicTimeline(Local = false, Remote = false, Website)
}
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());
} 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());
} else {
Timeline = await fetch(Website + "/api/v1/timelines/public?limit=12")
Timeline = await fetch(Website + "/api/v1/timelines/public")
.then((response) => response.json());
}
return Timeline;
}
// Gets the favorites of a user that you have access to.
export async function GetFavorites() {
let Favorites;
// Check for a token.
if (localStorage.getItem(Variables.MastodonAccessToken) != null) {
let Website = Variables.MastodonWebsite;
// Get the varaibles that are stored in localStorage.
Favorites = await fetch(Website + "/api/v1/favourites", {method: "GET", headers: {"Authorization": localStorage.getItem(Variables.MastodonTokenType) + " " + localStorage.getItem(Variables.MastodonAccessToken)}})
// Get the personal timeline.
export async function GetTimeline(Cursor) {
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.
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());
}
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.
export async function GetBookmarks() {
let Bookmarks;
// Check for a token.
if (localStorage.getItem(Variables.MastodonAccessToken) != null) {
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());
if (localStorage.getItem(Variables.MastodonAccessToken) == null) {
console.log("No access token!");
return "";
}
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.
export async function GetNotifications() {
let Notifications;
// Check for a token.
if (localStorage.getItem(Variables.MastodonAccessToken) != null) {
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());
if (localStorage.getItem(Variables.MastodonAccessToken) == null) {
console.log("No access token!");
return "";
}
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
export async function CreateStatus(Text, Visibility = "public") {
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
if (localStorage.getItem(Variables.MastodonAccessToken) != null) {
let Website = localStorage.getItem(Variables.MastodonWebsite);
return await fetch(Website + "/api/v1/statuses?status=" + Text + "&visibility=" + Visibility, {method: "POST", headers: {"Authorization": localStorage.getItem(Variables.MastodonTokenType) + " " + localStorage.getItem(Variables.MastodonAccessToken)}})
.then((response) => response.json());
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)}});
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+)/);
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.

View file

@ -1,4 +1,3 @@
// STRINGS TODO: make sure to seperate stuff that a user will want to input: BlueskyPDSName.
// Mastodon
export const MastodonWebsite = "mastodon_website";
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 Main = document.getElementsByClassName("MainBefore")[0];
let ContainerContainer = document.getElementsByClassName("PostContainerContainer")[0];
let ClickableContainers = ContainerContainer.getElementsByClassName("PostContainer")[2].children;
let BrowserWidth = window.innerWidth;
let BrowserHeight = window.innerHeight;
@ -81,12 +82,11 @@ ArrowsButton[1].onclick = (event) => {
if (!ContainerContainer.classList.contains("NextAnimation")) {
ContainerContainer.classList.add("NextAnimation");
ButtonSound.play();
console.log("loading next posts...");
setTimeout(() => {
ContainerContainer.classList.remove("NextAnimation");
}, 1000);
PosterContainerUpdate("Forward");
}
PosterContainerUpdate();
}
// Clicking the back button
@ -94,39 +94,140 @@ ArrowsButton[0].onclick = (event) => {
if (!ContainerContainer.classList.contains("BackAnimation")) {
ContainerContainer.classList.add("BackAnimation");
ButtonSound.play();
console.log("getting previous posts...");
setTimeout(() => {
ContainerContainer.classList.remove("BackAnimation");
}, 1000);
PosterContainerUpdate("Backward");
}
PosterContainerUpdate();
}
// MastodonAPI integration
async function PosterContainerUpdate() {
// Variables for the public timelines
let LocalVar = localStorage.getItem("Local");
var LocalTrue = (LocalVar === "true");
let RemoteVar = localStorage.getItem("Remote");
var RemoteTrue = (RemoteVar === "true");
for (let i of ClickableContainers) {
i.onclick = (event) => {
let content = i.getElementsByClassName("PostContent")[0].innerHTML
let username = i.getElementsByClassName("Username")[0].innerHTML
// Save some info
window.location.href = "./HTML/expanded.html?username=" + username + "&content=" + content;
}
}
// 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);
if (localStorage.getItem(Variables.MastodonWebsite) == null) {
Website = "https://wetdry.world";
}
let Mastodon = true;
let Timeline = await MastodonAPI.GetPublicTimeline(LocalTrue, RemoteTrue, Website);
let Content = [];
let Users = [];
for (let i in Timeline) {
Content[i] = Timeline[i].content;
Users[i] = Timeline[i].account.username;
// Mastodon gaining of timeline.
if (localStorage.getItem(Variables.MastodonWebsite) == null) {
// The default website is Wetdry :3
console.log("No Mastodon instance. multiplying mastodon posts by 2...");
Lim = Lim * 2;
Mastodon = false;
} else if (MastodonLoadedFeed == 0) {
MastodonLoadedFeed = await MastodonAPI.GetTimeline("");
}
let CenterContainer = document.getElementsByClassName("PostContainer")[2].children;
for (let i in CenterContainer) {
CenterContainer[i].getElementsByClassName("PostContent")[0].innerHTML = Content[i];
CenterContainer[i].getElementsByClassName("Username")[0].innerHTML = Users[i];
// Bluesky gaining of timeline.
if (localStorage.getItem(Variables.BlueskyPDS) == null) {
console.log("No Bluesky instance. multiplying mastodon posts by 2...");
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

View file

@ -8,6 +8,9 @@ let PostButton = document.getElementsByClassName("Button")[0];
let VisibilityDropdown = document.getElementsByClassName("PostVisibility")[0];
let InputArea = document.getElementsByClassName("Text")[0];
// Extra Variables
// Clicking the beeg POST button.
PostButton.onclick = (event) => {
Post();
@ -57,9 +60,7 @@ async function Post() {
break;
}
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);
console.log(ThreadGate);
}
InputArea.value = "";
}

View file

@ -9,6 +9,8 @@
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. -->
<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>
<body style="margin: 0px;">
@ -31,255 +33,256 @@
<div style="width: 100%" class="PostContainerContainer">
<div style="left: -170vw;" class="PostContainer Back">
<article class="Post">
<p class="Username">No</p>
<p class="Username"></p>
<p class="PostContent"></p>
</article>
<article class="Post">
<p class="Username">No</p>
<p class="Username"></p>
<p class="PostContent"></p>
</article>
<article class="Post">
<p class="Username">No</p>
<p class="Username"></p>
<p class="PostContent"></p>
</article>
<article class="Post">
<p class="Username">No</p>
<p class="Username"></p>
<p class="PostContent"></p>
</article>
<article class="Post">
<p class="Username">No</p>
<p class="Username"></p>
<p class="PostContent"></p>
</article>
<article class="Post">
<p class="Username">No</p>
<p class="Username"></p>
<p class="PostContent"></p>
</article>
<article class="Post">
<p class="Username">No</p>
<p class="Username"></p>
<p class="PostContent"></p>
</article>
<article class="Post">
<p class="Username">No</p>
<p class="Username"></p>
<p class="PostContent"></p>
</article>
<article class="Post">
<p class="Username">No</p>
<p class="Username"></p>
<p class="PostContent"></p>
</article>
<article class="Post">
<p class="Username">No</p>
<p class="Username"></p>
<p class="PostContent"></p>
</article>
<article class="Post">
<p class="Username">No</p>
<p class="Username"></p>
<p class="PostContent"></p>
</article>
<article class="Post">
<p class="Username">No</p>
<p class="Username"></p>
<p class="PostContent"></p>
</article>
</div>
<div style="left: -85vw;" class="PostContainer Back">
<article class="Post">
<p class="Username">Testing</p>
<p class="PostContent">The things</p>
<p class="Username"></p>
<p class="PostContent"></p>
</article>
<article class="Post">
<p class="Username">Testing</p>
<p class="PostContent">The things</p>
<p class="Username"></p>
<p class="PostContent"></p>
</article>
<article class="Post">
<p class="Username">Testing</p>
<p class="PostContent">The things</p>
<p class="Username"></p>
<p class="PostContent"></p>
</article>
<article class="Post">
<p class="Username">Testing</p>
<p class="PostContent">The things</p>
<p class="Username"></p>
<p class="PostContent"></p>
</article>
<article class="Post">
<p class="Username">Testing</p>
<p class="PostContent">The things</p>
<p class="Username"></p>
<p class="PostContent"></p>
</article>
<article class="Post">
<p class="Username">Testing</p>
<p class="PostContent">The things</p>
<p class="Username"></p>
<p class="PostContent"></p>
</article>
<article class="Post">
<p class="Username">Testing</p>
<p class="PostContent">The things</p>
<p class="Username"></p>
<p class="PostContent"></p>
</article>
<article class="Post">
<p class="Username">Testing</p>
<p class="PostContent">The things</p>
<p class="Username"></p>
<p class="PostContent"></p>
</article>
<article class="Post">
<p class="Username">Testing</p>
<p class="PostContent">The things</p>
<p class="Username"></p>
<p class="PostContent"></p>
</article>
<article class="Post">
<p class="Username">Testing</p>
<p class="PostContent">The things</p>
<p class="Username"></p>
<p class="PostContent"></p>
</article>
<article class="Post">
<p class="Username">Testing</p>
<p class="PostContent">The things</p>
<p class="Username"></p>
<p class="PostContent"></p>
</article>
<article class="Post">
<p class="Username">Testing</p>
<p class="PostContent">The things</p>
<p class="Username"></p>
<p class="PostContent"></p>
</article>
</div>
<!-- This is the container that houses the current viewing stuff -->
<div class="PostContainer">
<article class="Post">
<p class="Username">Testing</p>
<p class="PostContent">The things</p>
<p class="Username"></p>
<p class="PostContent"></p>
</article>
<article class="Post">
<p class="Username">Testing</p>
<p class="PostContent">The things</p>
<p class="Username"></p>
<p class="PostContent"></p>
</article>
<article class="Post">
<p class="Username">Testing</p>
<p class="PostContent">The things</p>
<p class="Username"></p>
<p class="PostContent"></p>
</article>
<article class="Post">
<p class="Username">Testing</p>
<p class="PostContent">The things</p>
<p class="Username"></p>
<p class="PostContent"></p>
</article>
<article class="Post">
<p class="Username">Testing</p>
<p class="PostContent">The things</p>
<p class="Username"></p>
<p class="PostContent"></p>
</article>
<article class="Post">
<p class="Username">Testing</p>
<p class="PostContent">The things</p>
<p class="Username"></p>
<p class="PostContent"></p>
</article>
<article class="Post">
<p class="Username">Testing</p>
<p class="PostContent">The things</p>
<p class="Username"></p>
<p class="PostContent"></p>
</article>
<article class="Post">
<p class="Username">Testing</p>
<p class="PostContent">The things</p>
<p class="Username"></p>
<p class="PostContent"></p>
</article>
<article class="Post">
<p class="Username">Testing</p>
<p class="PostContent">The things</p>
<p class="Username"></p>
<p class="PostContent"></p>
</article>
<article class="Post">
<p class="Username">Testing</p>
<p class="PostContent">The things</p>
<p class="Username"></p>
<p class="PostContent"></p>
</article>
<article class="Post">
<p class="Username">Testing</p>
<p class="PostContent">The things</p>
<p class="Username"></p>
<p class="PostContent"></p>
</article>
<article class="Post">
<p class="Username">Testing</p>
<p class="PostContent">The things</p>
<p class="Username"></p>
<p class="PostContent"></p>
</article>
</div>
<div style="left: 85vw;" class="PostContainer Next">
<article class="Post">
<p class="Username">Testing</p>
<p class="PostContent">The things</p>
<p class="Username"></p>
<p class="PostContent"></p>
</article>
<article class="Post">
<p class="Username">Testing</p>
<p class="PostContent">The things</p>
<p class="Username"></p>
<p class="PostContent"></p>
</article>
<article class="Post">
<p class="Username">Testing</p>
<p class="PostContent">The things</p>
<p class="Username"></p>
<p class="PostContent"></p>
</article>
<article class="Post">
<p class="Username">Testing</p>
<p class="PostContent">The things</p>
<p class="Username"></p>
<p class="PostContent"></p>
</article>
<article class="Post">
<p class="Username">Testing</p>
<p class="PostContent">The things</p>
<p class="Username"></p>
<p class="PostContent"></p>
</article>
<article class="Post">
<p class="Username">Testing</p>
<p class="PostContent">The things</p>
<p class="Username"></p>
<p class="PostContent"></p>
</article>
<article class="Post">
<p class="Username">Testing</p>
<p class="PostContent">The things</p>
<p class="Username"></p>
<p class="PostContent"></p>
</article>
<article class="Post">
<p class="Username">Testing</p>
<p class="PostContent">The things</p>
<p class="Username"></p>
<p class="PostContent"></p>
</article>
<article class="Post">
<p class="Username">Testing</p>
<p class="PostContent">The things</p>
<p class="Username"></p>
<p class="PostContent"></p>
</article>
<article class="Post">
<p class="Username">Testing</p>
<p class="PostContent">The things</p>
<p class="Username"></p>
<p class="PostContent"></p>
</article>
<article class="Post">
<p class="Username">Testing</p>
<p class="PostContent">The things</p>
<p class="Username"></p>
<p class="PostContent"></p>
</article>
<article class="Post">
<p class="Username">Testing</p>
<p class="PostContent">The things</p>
<p class="Username"></p>
<p class="PostContent"></p>
</article>
</div>
<div style="left: 170vw;" class="PostContainer Next">
<article class="Post">
<p class="Username">No</p>
<p class="Username"></p>
<p class="PostContent"></p>
</article>
<article class="Post">
<p class="Username">No</p>
<p class="Username"></p>
<p class="PostContent"></p>
</article>
<article class="Post">
<p class="Username">No</p>
<p class="Username"></p>
<p class="PostContent"></p>
</article>
<article class="Post">
<p class="Username">No</p>
<p class="Username"></p>
<p class="PostContent"></p>
</article>
<article class="Post">
<p class="Username">No</p>
<p class="Username"></p>
<p class="PostContent"></p>
</article>
<article class="Post">
<p class="Username">No</p>
<p class="Username"></p>
<p class="PostContent"></p>
</article>
<article class="Post">
<p class="Username">No</p>
<p class="Username"></p>
<p class="PostContent"></p>
</article>
<article class="Post">
<p class="Username">No</p>
<p class="Username"></p>
<p class="PostContent"></p>
</article>
<article class="Post">
<p class="Username">No</p>
<p class="Username"></p>
<p class="PostContent"></p>
</article>
<article class="Post">
<p class="Username">No</p>
<p class="Username"></p>
<p class="PostContent"></p>
</article>
<article class="Post">
<p class="Username">No</p>
<p class="Username"></p>
<p class="PostContent"></p>
</article>
<article class="Post">
<p class="Username">No</p>
<p class="Username"></p>
<p class="PostContent"></p>
</article>
</div>