merge branch Testing
This commit is contained in:
parent
495c1886f0
commit
c022194589
11 changed files with 473 additions and 206 deletions
|
@ -1,5 +1,5 @@
|
|||
/* HTML items */
|
||||
.Embed, img, video {
|
||||
img, video {
|
||||
border-style: solid;
|
||||
border-radius: 1%;
|
||||
|
||||
|
@ -8,6 +8,13 @@
|
|||
width: 45%;
|
||||
}
|
||||
|
||||
.Embed {
|
||||
border-style: solid;
|
||||
border-radius: 1%;
|
||||
|
||||
background-color: yellow;
|
||||
}
|
||||
|
||||
/* Classes */
|
||||
.Handle {
|
||||
background-color: white;
|
||||
|
|
|
@ -216,7 +216,7 @@ html {
|
|||
}
|
||||
|
||||
/* Footer things */
|
||||
.Setting, .Posting, .Mail {
|
||||
.Setting, .Posting, .Mail, .Feed {
|
||||
margin-top: 30px;
|
||||
|
||||
border-style: solid;
|
||||
|
@ -226,12 +226,12 @@ html {
|
|||
height: 100px;
|
||||
}
|
||||
|
||||
.Time {
|
||||
font-size: 4ch;
|
||||
.Mail, .Setting {
|
||||
margin-right: 5%;
|
||||
}
|
||||
|
||||
.Posting {
|
||||
margin-right: 5%;
|
||||
.Time {
|
||||
font-size: 4ch;
|
||||
}
|
||||
|
||||
.MainFooter {
|
||||
|
|
|
@ -27,6 +27,7 @@
|
|||
<input type="checkbox" class="PostYoutube" />
|
||||
<label>Post to Youtube</label>
|
||||
</div>
|
||||
<textarea cols="50" rows="1" class="Warning" placeholder="Content Warnings"></textarea>
|
||||
<p class="Button">POST!</p>
|
||||
</section>
|
||||
<footer>
|
||||
|
|
|
@ -17,7 +17,6 @@
|
|||
</header>
|
||||
<div style="display: flex; justify-content: center; height: 75vh;">
|
||||
<div class="Button" style="margin: auto;">
|
||||
<p class="Local">Toggle Local</p>
|
||||
<p class="Remote">Toggle Remote</p>
|
||||
</div>
|
||||
<div class="Button" style="display: flex; justify-content: center; margin: auto;">
|
||||
|
|
216
JS/BlueskyAPI.js
216
JS/BlueskyAPI.js
|
@ -1,20 +1,22 @@
|
|||
import * as Variables from "./Variables.js";
|
||||
|
||||
|
||||
// Getters
|
||||
// This gets the timeline. The cursor is a time in Z form.
|
||||
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}});
|
||||
DPoP = await ClientDPoPPDS("GET", localStorage.getItem(Variables.BlueskyPDS) + "/xrpc/app.bsky.feed.getTimeline");
|
||||
request = fetch(localStorage.getItem(Variables.BlueskyPDS) + "/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}});
|
||||
DPoP = await ClientDPoPPDS("GET", localStorage.getItem(Variables.BlueskyPDS) + "/xrpc/app.bsky.feed.getTimeline?cursor=" + Cursor);
|
||||
request = fetch(localStorage.getItem(Variables.BlueskyPDS) + "/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);
|
||||
|
@ -26,15 +28,41 @@ export async function GetTimeline(Cursor) {
|
|||
return body;
|
||||
}
|
||||
|
||||
// Gets a "public" timeline (essentially a feed by bsky.app where you can discover posts).
|
||||
export async function GetPublicTimeline(Cursor) {
|
||||
if (localStorage.getItem(Variables.BlueskyAccessToken) == null) {
|
||||
console.log("No access token!");
|
||||
return "";
|
||||
}
|
||||
|
||||
let DPoP;
|
||||
let request;
|
||||
if (Cursor == "") {
|
||||
DPoP = await ClientDPoPPDS("GET", localStorage.getItem(Variables.BlueskyPDS) + "/xrpc/app.bsky.feed.getFeed?feed=at://did:plc:z72i7hdynmk6r22z27h6tvur/app.bsky.feed.generator/whats-hot");
|
||||
request = fetch(localStorage.getItem(Variables.BlueskyPDS) + "/xrpc/app.bsky.feed.getFeed?feed=at://did:plc:z72i7hdynmk6r22z27h6tvur/app.bsky.feed.generator/whats-hot", {method: "GET", headers: {"Authorization": "DPoP " + localStorage.getItem(Variables.BlueskyAccessToken), "DPoP": DPoP}});
|
||||
} else {
|
||||
DPoP = await ClientDPoPPDS("GET", localStorage.getItem(Variables.BlueskyPDS) + "/xrpc/app.bsky.feed.getTimeline?feed=at://did:plc:z72i7hdynmk6r22z27h6tvur/app.bsky.feed.generator/whats-hot&cursor=" + Cursor);
|
||||
request = fetch(localStorage.getItem(Variables.BlueskyPDS) + "/xrpc/app.bsky.feed.getTimeline?feed=at://did:plc:z72i7hdynmk6r22z27h6tvur/app.bsky.feed.generator/whats-hot&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 GetPublicTimeline(Cursor);
|
||||
}
|
||||
return body;
|
||||
}
|
||||
|
||||
// This gets the post. If there are multiple URIs, they must be within an array.
|
||||
export async function GetPosts(URIs) {
|
||||
if (localStorage.getItem(Variables.BlueskyAccessToken) == null) {
|
||||
console.log("No access token!");
|
||||
return "";
|
||||
}
|
||||
|
||||
let PDS = localStorage.getItem(Variables.BlueskyPDS);
|
||||
let DPoP = await ClientDPoPPDS("GET", PDS + "/xrpc/app.bsky.feed.getPosts?uris=" + URIs);
|
||||
let request = fetch(PDS + "/xrpc/app.bsky.feed.getPosts?uris=" + URIs, { method: "GET", headers: {"Authorization": "DPoP " + localStorage.getItem(Variables.BlueskyAccessToken), "DPoP": DPoP}});
|
||||
let DPoP = await ClientDPoPPDS("GET", localStorage.getItem(Variables.BlueskyPDS) + "/xrpc/app.bsky.feed.getPosts?uris=" + URIs);
|
||||
let request = fetch(localStorage.getItem(Variables.BlueskyPDS) + "/xrpc/app.bsky.feed.getPosts?uris=" + URIs, { 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"));
|
||||
|
@ -52,15 +80,51 @@ export async function GetBlob(DID, CID) {
|
|||
return body;
|
||||
}
|
||||
|
||||
export async function CreatePost(DID, Text) {
|
||||
// Gets a record. The repo is the account DID, the collection is the type of record, and the key is the little bit at the end.
|
||||
export async function GetRecord(Repo, Collection, RKey) {
|
||||
let RequestBody = {
|
||||
"repo": Repo,
|
||||
"collection": Collection,
|
||||
"rkey": RKey
|
||||
}
|
||||
let DPoP = await ClientDPoPPDS("GET", localStorage.getItem(Variables.BlueskyPDS) + "/xrpc/com.atproto.repo.getRecord?repo=" + Repo + "&collection=" + Collection + "&rkey=" + RKey);
|
||||
let request = fetch(localStorage.getItem(Variables.BlueskyPDS) + "/xrpc/com.atproto.repo.getRecord?repo=" + Repo + "&collection=" + Collection + "&rkey=" + RKey, { method: "GET", 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 GetRecord(Repo, Collection, RKey);
|
||||
}
|
||||
return body;
|
||||
}
|
||||
|
||||
// Creators
|
||||
// This creates a post. Requires the DID of the account and the Text for the record.
|
||||
export async function CreatePost(DID, Text, ContentWarning = undefined) {
|
||||
if (localStorage.getItem(Variables.BlueskyAccessToken) == null) {
|
||||
console.log("No access token!");
|
||||
return "";
|
||||
}
|
||||
let Record = {
|
||||
let Record;
|
||||
if (ContentWarning == undefined) {
|
||||
Record = {
|
||||
"$type": "app.bsky.feed.post",
|
||||
"text": Text,
|
||||
"createdAt": new Date(Date.now()).toISOString()
|
||||
}
|
||||
} else {
|
||||
Record = {
|
||||
"$type": "app.bsky.feed.post",
|
||||
"text": Text,
|
||||
"createdAt": new Date(Date.now()).toISOString(),
|
||||
"labels": {
|
||||
"$type": "com.atproto.label.defs#selfLabels",
|
||||
"values": [{
|
||||
"val": ContentWarning
|
||||
}]
|
||||
}
|
||||
}
|
||||
}
|
||||
let body = await CreateRecord(DID, "app.bsky.feed.post", Record, undefined);
|
||||
if (body.hasOwnProperty("error") && body.error == "InvalidRequest") {
|
||||
|
@ -72,23 +136,49 @@ export async function CreatePost(DID, Text) {
|
|||
return body;
|
||||
}
|
||||
|
||||
export async function CreateReplyPost(DID, Text, ReplyID, RootID) {
|
||||
// Creates a reply post. The RootID is always the first post, the ReplyID is the post you are replying to.
|
||||
export async function CreateReplyPost(DID, Text, ReplyID, RootID, ContentWarning = undefined) {
|
||||
if (localStorage.getItem(Variables.BlueskyAccessToken) == null) {
|
||||
console.log("No access token!");
|
||||
return "";
|
||||
}
|
||||
let Record = {
|
||||
"$type": "app.bsky.feed.post",
|
||||
"text": Text,
|
||||
"createdAt": new Date(Date.now()).toISOString(),
|
||||
"reply": {
|
||||
"parent": {
|
||||
"uri": ReplyID.uri,
|
||||
"cid": ReplyID.cid
|
||||
let Record;
|
||||
if (ContentWarning == undefined) {
|
||||
Record = {
|
||||
"$type": "app.bsky.feed.post",
|
||||
"text": Text,
|
||||
"createdAt": new Date(Date.now()).toISOString(),
|
||||
"reply": {
|
||||
"parent": {
|
||||
"uri": ReplyID.uri,
|
||||
"cid": ReplyID.cid
|
||||
},
|
||||
"root": {
|
||||
"uri": RootID.uri,
|
||||
"cid": RootID.cid
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
Record = {
|
||||
"$type": "app.bsky.feed.post",
|
||||
"text": Text,
|
||||
"createdAt": new Date(Date.now()).toISOString(),
|
||||
"reply": {
|
||||
"parent": {
|
||||
"uri": ReplyID.uri,
|
||||
"cid": ReplyID.cid
|
||||
},
|
||||
"root": {
|
||||
"uri": RootID.uri,
|
||||
"cid": RootID.cid
|
||||
},
|
||||
},
|
||||
"root": {
|
||||
"uri": RootID.uri,
|
||||
"cid": RootID.cid
|
||||
"labels": {
|
||||
"$type": "com.atproto.label.defs#selfLabels",
|
||||
"values": [{
|
||||
"val": ContentWarning
|
||||
}]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -102,7 +192,8 @@ export async function CreateReplyPost(DID, Text, ReplyID, RootID) {
|
|||
return body;
|
||||
}
|
||||
|
||||
export async function SetThreadGate(DID, Post, VisibilitySettings) {
|
||||
// Creates a Thread Gate for who can reply. Requires the account DID, a post, and a list of who is allowed.
|
||||
export async function CreateThreadGate(DID, Post, VisibilitySettings) {
|
||||
if (localStorage.getItem(Variables.BlueskyAccessToken) == null) {
|
||||
console.log("No access token!");
|
||||
return "";
|
||||
|
@ -117,7 +208,8 @@ export async function SetThreadGate(DID, Post, VisibilitySettings) {
|
|||
return body;
|
||||
}
|
||||
|
||||
export async function SendLike(DID, RefURI, RefCID) {
|
||||
// Create a like and send it to the server.
|
||||
export async function CreateLike(DID, RefURI, RefCID) {
|
||||
if (localStorage.getItem(Variables.BlueskyAccessToken) == null) {
|
||||
console.log("No access token!");
|
||||
return "";
|
||||
|
@ -142,7 +234,8 @@ export async function SendLike(DID, RefURI, RefCID) {
|
|||
return body;
|
||||
}
|
||||
|
||||
export async function SendRepost(DID, RefURI, RefCID) {
|
||||
// Create a repost and send it to the server.
|
||||
export async function CreateRepost(DID, RefURI, RefCID) {
|
||||
if (localStorage.getItem(Variables.BlueskyAccessToken) == null) {
|
||||
console.log("No access token!");
|
||||
return "";
|
||||
|
@ -167,24 +260,27 @@ export async function SendRepost(DID, RefURI, RefCID) {
|
|||
return body;
|
||||
}
|
||||
|
||||
export async function GetRecord(Repo, Collection, RKey) {
|
||||
// Put record updates a record.
|
||||
export async function PutRecord(Repo, Collection, Record, RKey) {
|
||||
let RequestBody = {
|
||||
"repo": Repo,
|
||||
"collection": Collection,
|
||||
"record": Record,
|
||||
"rkey": RKey
|
||||
}
|
||||
let DPoP = await ClientDPoPPDS("GET", localStorage.getItem(Variables.BlueskyPDS) + "/xrpc/com.atproto.repo.getRecord?repo=" + Repo + "&collection=" + Collection + "&rkey=" + RKey);
|
||||
let request = fetch(localStorage.getItem(Variables.BlueskyPDS) + "/xrpc/com.atproto.repo.getRecord?repo=" + Repo + "&collection=" + Collection + "&rkey=" + RKey, { method: "GET", headers: {"Content-Type": "application/json", "Authorization": "DPoP " + localStorage.getItem(Variables.BlueskyAccessToken), "DPoP": DPoP}});
|
||||
let DPoP = await ClientDPoPPDS("POST", localStorage.getItem(Variables.BlueskyPDS) + "/xrpc/com.atproto.repo.putRecord");
|
||||
let request = fetch(localStorage.getItem(Variables.BlueskyPDS) + "/xrpc/com.atproto.repo.putRecord", { 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 DeleteRecord(Repo, Collection, RKey);
|
||||
body = await PutRecord(Repo, Collection, Record, RKey);
|
||||
}
|
||||
return body;
|
||||
}
|
||||
|
||||
// Creates a record. Universal way of making things.
|
||||
export async function CreateRecord(Repo, Collection, Record, RKey) {
|
||||
let RequestBody = {
|
||||
"repo": Repo,
|
||||
|
@ -206,6 +302,47 @@ export async function CreateRecord(Repo, Collection, Record, RKey) {
|
|||
return body;
|
||||
}
|
||||
|
||||
// Applyers
|
||||
export function ApplyFacets(record, text) {
|
||||
let StringArray = [];
|
||||
let SplitAreas = [0];
|
||||
let Hrefs = [];
|
||||
let TempText = "";
|
||||
if (record.hasOwnProperty("facets")) {
|
||||
// First, append split areas.
|
||||
for (let i of record.facets) {
|
||||
if (i.features[0].$type == "app.bsky.richtext.facet#link") {
|
||||
SplitAreas.push(i.index.byteStart);
|
||||
SplitAreas.push(i.index.byteEnd);
|
||||
Hrefs.push(i.features[0].uri);
|
||||
Hrefs.push("");
|
||||
}
|
||||
}
|
||||
// Last minute append.
|
||||
SplitAreas.push(text.length);
|
||||
// Remove emoji regex
|
||||
let EmojiRegex = /\p{Emoji_Modifier_Base}\p{Emoji_Modifier}?|\p{Emoji_Presentation}|\p{Emoji}\uFE0F/gu;
|
||||
let EmojiObjects = text.match(EmojiRegex);
|
||||
let SubtractNumber = 0;
|
||||
if (EmojiObjects != null) {
|
||||
SubtractNumber = EmojiObjects.length * 2;
|
||||
}
|
||||
// Now we split the string
|
||||
for (let i = 1; i < SplitAreas.length; i++) {
|
||||
StringArray.push(text.slice(SplitAreas[i - 1] - SubtractNumber, SplitAreas[i] - SubtractNumber));
|
||||
}
|
||||
// Finally, we append the string with <a>
|
||||
for (let i = 1; i < StringArray.length; i += 2) {
|
||||
TempText += StringArray[i - 1] + "<a href='" + Hrefs[i - 1] + "'>" + StringArray[i] + "</a>";
|
||||
}
|
||||
}
|
||||
if (TempText == "") {
|
||||
return text;
|
||||
}return TempText;
|
||||
}
|
||||
|
||||
// Deleters
|
||||
// Removes a record. Can be a like, a repost, a post, etc.
|
||||
export async function DeleteRecord(Repo, Collection, RKey) {
|
||||
let RequestBody = {
|
||||
"repo": Repo,
|
||||
|
@ -224,6 +361,7 @@ export async function DeleteRecord(Repo, Collection, RKey) {
|
|||
return body;
|
||||
}
|
||||
|
||||
// Things to get this to work.
|
||||
// Component 1/4
|
||||
export async function GetPDSWellKnown() {
|
||||
return await fetch("https://bsky.social/.well-known/oauth-authorization-server", {method: "GET"})
|
||||
|
@ -273,7 +411,7 @@ export async function ClientDPoPToken(POSTorGET, RequestURL) {
|
|||
let PrivateKey = await crypto.subtle.importKey("jwk", JSON.parse(localStorage.getItem(Variables.BlueskyPrivateKey)), {name: "ECDSA", namedCurve: "P-256"}, true, ["sign"]);
|
||||
|
||||
// Header
|
||||
var Header = {typ: "dpop+jwt", alg: "ES256", jwk:
|
||||
let Header = {typ: "dpop+jwt", alg: "ES256", jwk:
|
||||
await crypto.subtle.exportKey("jwk", PublicKey)
|
||||
.then(function(response) {
|
||||
delete response["key_ops"];
|
||||
|
@ -282,7 +420,7 @@ export async function ClientDPoPToken(POSTorGET, RequestURL) {
|
|||
return response})
|
||||
};
|
||||
// Payload
|
||||
var Payload = {};
|
||||
let Payload = {};
|
||||
Payload.iss = "https://fedi.crowdedgames.group/oauth/client-metadata.json";
|
||||
Payload.jti = crypto.randomUUID();
|
||||
Payload.htm = POSTorGET;
|
||||
|
@ -290,9 +428,9 @@ export async function ClientDPoPToken(POSTorGET, RequestURL) {
|
|||
Payload.iat = Math.floor(new Date(Date.now()).getTime() / 1000);
|
||||
Payload.nonce = localStorage.getItem(Variables.BlueskyNonce);
|
||||
|
||||
var sHeader = JSON.stringify(Header);
|
||||
var sPayload = JSON.stringify(Payload);
|
||||
var JWT = KJUR.jws.JWS.sign("ES256", sHeader, sPayload,
|
||||
let sHeader = JSON.stringify(Header);
|
||||
let sPayload = JSON.stringify(Payload);
|
||||
let JWT = KJUR.jws.JWS.sign("ES256", sHeader, sPayload,
|
||||
await crypto.subtle.exportKey("jwk", PrivateKey)
|
||||
.then(function(response) {
|
||||
delete response["key_ops"];
|
||||
|
@ -308,7 +446,7 @@ export async function ClientDPoPPDS(POSTorGET, RequestURL) {
|
|||
let PrivateKey = await crypto.subtle.importKey("jwk", JSON.parse(localStorage.getItem(Variables.BlueskyPrivateKey)), {name: "ECDSA", namedCurve: "P-256"}, true, ["sign"]);
|
||||
|
||||
// Header
|
||||
var Header = {typ: "dpop+jwt", alg: "ES256", jwk:
|
||||
let Header = {typ: "dpop+jwt", alg: "ES256", jwk:
|
||||
await crypto.subtle.exportKey("jwk", PublicKey)
|
||||
.then(function(response) {
|
||||
delete response["key_ops"];
|
||||
|
@ -317,7 +455,7 @@ export async function ClientDPoPPDS(POSTorGET, RequestURL) {
|
|||
return response})
|
||||
};
|
||||
// Payload
|
||||
var Payload = {};
|
||||
let Payload = {};
|
||||
Payload.iss = "https://fedi.crowdedgames.group/oauth/client-metadata.json";
|
||||
Payload.jti = crypto.randomUUID();
|
||||
Payload.htm = POSTorGET;
|
||||
|
@ -326,9 +464,9 @@ export async function ClientDPoPPDS(POSTorGET, RequestURL) {
|
|||
Payload.nonce = localStorage.getItem(Variables.BlueskyNonce);
|
||||
Payload.ath = await CreatePKCECodeChallenge(localStorage.getItem(Variables.BlueskyAccessToken));
|
||||
|
||||
var sHeader = JSON.stringify(Header);
|
||||
var sPayload = JSON.stringify(Payload);
|
||||
var JWT = KJUR.jws.JWS.sign("ES256", sHeader, sPayload,
|
||||
let sHeader = JSON.stringify(Header);
|
||||
let sPayload = JSON.stringify(Payload);
|
||||
let JWT = KJUR.jws.JWS.sign("ES256", sHeader, sPayload,
|
||||
await crypto.subtle.exportKey("jwk", PrivateKey)
|
||||
.then(function(response) {
|
||||
delete response["key_ops"];
|
||||
|
|
|
@ -2,24 +2,34 @@ import * as Variables from "./Variables.js";
|
|||
|
||||
export const Scopes = "read write follow push";
|
||||
|
||||
// Getters
|
||||
// Gets the public timeline.
|
||||
export async function GetPublicTimeline(Local = false, Remote = false, Website) {
|
||||
export async function GetPublicTimeline(Local = false, Remote = false, Website, Cursor) {
|
||||
// Variables can be found in `setting.js`
|
||||
let Timeline;
|
||||
if (Local == true && Remote == true) {
|
||||
console.error("Don't set both Local and Remote timelines to true.");
|
||||
return Timeline;
|
||||
}
|
||||
|
||||
if (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?remote=true")
|
||||
.then((response) => response.json());
|
||||
if (Cursor == "") {
|
||||
if (Remote == true && Local == false) {
|
||||
Timeline = await fetch(Website + "/api/v1/timelines/public?remote=true")
|
||||
.then((response) => response.json());
|
||||
} else if (Local == true && Remote == false) {
|
||||
Timeline = await fetch(Website + "/api/v1/timelines/public?local=true")
|
||||
.then((response) => response.json());
|
||||
} else {
|
||||
Timeline = await fetch(Website + "/api/v1/timelines/public")
|
||||
.then((response) => response.json());
|
||||
}
|
||||
} else {
|
||||
Timeline = await fetch(Website + "/api/v1/timelines/public")
|
||||
.then((response) => response.json());
|
||||
if (Remote == true && Local == false) {
|
||||
Timeline = await fetch(Website + "/api/v1/timelines/public?remote=true&max_id=" + Cursor)
|
||||
.then((response) => response.json());
|
||||
} else if (Local == true && Remote == false) {
|
||||
Timeline = await fetch(Website + "/api/v1/timelines/public?local=true&max_id=" + Cursor)
|
||||
.then((response) => response.json());
|
||||
} else {
|
||||
Timeline = await fetch(Website + "/api/v1/timelines/public?max_id=" + Cursor)
|
||||
.then((response) => response.json());
|
||||
}
|
||||
}
|
||||
return Timeline;
|
||||
}
|
||||
|
@ -77,6 +87,7 @@ export async function GetNotifications() {
|
|||
.then((response) => response.json());
|
||||
}
|
||||
|
||||
// A status is just a post. It gets it.
|
||||
export async function GetStatus(ID) {
|
||||
if (localStorage.getItem(Variables.MastodonAccessToken) == null) {
|
||||
console.log("No access token!");
|
||||
|
@ -88,8 +99,9 @@ export async function GetStatus(ID) {
|
|||
.then((response) => response.json());
|
||||
}
|
||||
|
||||
// Creators
|
||||
// Make a status
|
||||
export async function CreateStatus(Text, Visibility = "public") {
|
||||
export async function CreateStatus(Text, SpoilerText = undefined, Visibility = "public") {
|
||||
if (localStorage.getItem(Variables.MastodonAccessToken) == null) {
|
||||
console.log("No access token!");
|
||||
return "";
|
||||
|
@ -98,20 +110,29 @@ export async function CreateStatus(Text, Visibility = "public") {
|
|||
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, {method: "POST", headers: {"Authorization": localStorage.getItem(Variables.MastodonTokenType) + " " + localStorage.getItem(Variables.MastodonAccessToken)}});
|
||||
let request;
|
||||
if (SpoilerText == undefined) {
|
||||
request = fetch(Website + "/api/v1/statuses?status=" + Text + "&visibility=" + Visibility, {method: "POST", headers: {"Authorization": localStorage.getItem(Variables.MastodonTokenType) + " " + localStorage.getItem(Variables.MastodonAccessToken)}});
|
||||
} else {
|
||||
request = fetch(Website + "/api/v1/statuses?status=" + Text + "&visibility=" + Visibility + "&spoiler_text=" + SpoilerText, {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, {method: "POST", headers: {"Authorization": localStorage.getItem(Variables.MastodonTokenType) + " " + localStorage.getItem(Variables.MastodonAccessToken)}});
|
||||
if (SpoilerText == undefined) {
|
||||
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)}});
|
||||
} else {
|
||||
request = fetch(Website + "/api/v1/statuses?status=" + Text + "&visibility=" + Visibility + "&spoiler_text=" + SpoilerText, {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);
|
||||
await CreateReplyStatus(Text.slice(matches[0] - 1, SpoilerText, Text.length - 1), Visibility, body.id);
|
||||
}
|
||||
return body;
|
||||
}
|
||||
|
||||
export async function CreateReplyStatus(Text, Visibility = "public", ReplyID) {
|
||||
export async function CreateReplyStatus(Text, SpoilerText = undefined, Visibility = "public", ReplyID) {
|
||||
if (localStorage.getItem(Variables.MastodonAccessToken) == null) {
|
||||
console.log("No access token!");
|
||||
return "";
|
||||
|
@ -120,20 +141,29 @@ export async function CreateReplyStatus(Text, Visibility = "public", ReplyID) {
|
|||
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 request;
|
||||
if (SpoilerText == undefined) {
|
||||
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)}});
|
||||
} else {
|
||||
request = fetch(Website + "/api/v1/statuses?status=" + Text + "&visibility=" + Visibility + "&in_reply_to_id=" + ReplyID + "&spoiler_text=" + SpoilerText, {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)}});
|
||||
if (SpoilerText == undefined) {
|
||||
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)}});
|
||||
} else {
|
||||
request = fetch(Website + "/api/v1/statuses?status=" + Text + "&visibility=" + Visibility + "&in_reply_to_id=" + ReplyID + "&spoiler_text=" + SpoilerText, {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);
|
||||
await CreateReplyStatus(Text.slice(matches[0] - 1, Text.length - 1), SpoilerText, Visibility, body.id);
|
||||
}
|
||||
return body;
|
||||
}
|
||||
|
||||
export async function SendFavorite(ID, IsFavorited) {
|
||||
export async function CreateFavorite(ID, IsFavorited) {
|
||||
if (localStorage.getItem(Variables.MastodonAccessToken) == null) {
|
||||
console.log("No access token!");
|
||||
return "";
|
||||
|
@ -148,7 +178,7 @@ export async function SendFavorite(ID, IsFavorited) {
|
|||
}
|
||||
}
|
||||
|
||||
export async function SendReblog(ID, IsReblogged) {
|
||||
export async function CreateReblog(ID, IsReblogged) {
|
||||
if (localStorage.getItem(Variables.MastodonAccessToken) == null) {
|
||||
console.log("No access token!");
|
||||
return "";
|
||||
|
@ -163,6 +193,7 @@ export async function SendReblog(ID, IsReblogged) {
|
|||
}
|
||||
}
|
||||
|
||||
// Things to make this work
|
||||
// The first step to using the app.
|
||||
export async function HandleAuthentication(Website) {
|
||||
// See if the user is smart enough to put https.
|
||||
|
|
232
JS/expanded.js
232
JS/expanded.js
|
@ -14,6 +14,8 @@ let BoostFlipper = false;
|
|||
// Variables
|
||||
let website = document.location.href.split("website=")[1];
|
||||
let post = JSON.parse(localStorage.getItem("post"));
|
||||
let Parentpost;
|
||||
let GrandParentpost;
|
||||
|
||||
document.getElementsByClassName("Origin Regular")[0].innerHTML = website;
|
||||
GetPost();
|
||||
|
@ -21,18 +23,18 @@ GetPost();
|
|||
// Button stuff
|
||||
Favorite.onclick = (event) => {
|
||||
if (website == "Mastodon") {
|
||||
MastodonAPI.SendFavorite(post.id, post.favourited);
|
||||
MastodonAPI.CreateFavorite(post.id, post.favourited);
|
||||
} else if (website == "Bluesky") {
|
||||
BlueskyAPI.SendLike(localStorage.getItem(Variables.BlueskyDID), post.post.uri, post.post.cid);
|
||||
BlueskyAPI.CreateLike(localStorage.getItem(Variables.BlueskyDID), post.post.uri, post.post.cid);
|
||||
}
|
||||
SetFavorite();
|
||||
}
|
||||
|
||||
Boost.onclick = (event) => {
|
||||
if (website == "Mastodon") {
|
||||
MastodonAPI.SendReblog(post.id, post.reblogged);
|
||||
MastodonAPI.CreateReblog(post.id, post.reblogged);
|
||||
} else if (website == "Bluesky") {
|
||||
BlueskyAPI.SendRepost(localStorage.getItem(Variables.BlueskyDID), post.post.uri, post.post.cid);
|
||||
BlueskyAPI.CreateRepost(localStorage.getItem(Variables.BlueskyDID), post.post.uri, post.post.cid);
|
||||
}
|
||||
SetBoost();
|
||||
}
|
||||
|
@ -41,6 +43,30 @@ Reply.onclick = (event) => {
|
|||
window.location.href = "../../HTML/post.html?website=" + website;
|
||||
}
|
||||
|
||||
// Seleecting other posts
|
||||
for (let i of document.getElementsByClassName("Parent")) {
|
||||
i.onclick = (event) => {
|
||||
SetThreadPost(Parentpost);
|
||||
}
|
||||
}
|
||||
|
||||
for (let i of document.getElementsByClassName("GrandParent")) {
|
||||
i.onclick = (event) => {
|
||||
SetThreadPost(GrandParentpost);
|
||||
}
|
||||
}
|
||||
|
||||
async function SetThreadPost(element) {
|
||||
if (website == "Mastodon") {
|
||||
localStorage.setItem("post", JSON.stringify(element));
|
||||
} else if (website == "Bluesky") {
|
||||
let Temp = await BlueskyAPI.GetPosts(element.uri);
|
||||
element.post = Temp.posts[0];
|
||||
localStorage.setItem("post", JSON.stringify(element));
|
||||
}
|
||||
document.location.href = "./expanded.html?website=" + website;
|
||||
}
|
||||
|
||||
// Functions and things.
|
||||
async function GetPost() {
|
||||
if (website == "Mastodon") {
|
||||
|
@ -50,7 +76,7 @@ async function GetPost() {
|
|||
document.getElementsByClassName("Handle Regular")[0].innerHTML = post.reblog.account.username + " ( R: " + post.account.username + " )";
|
||||
if (post.reblog.media_attachments.length != 0) {
|
||||
for (let i of post.reblog.media_attachments) {
|
||||
await CreateMedia(i, document.getElementsByClassName("Images Regular")[0]);
|
||||
ApplyMedia(i, document.getElementsByClassName("Images Regular")[0]);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
@ -59,51 +85,44 @@ async function GetPost() {
|
|||
// Show the image if it exists.
|
||||
if (post.media_attachments.length != 0) {
|
||||
for (let i of post.media_attachments) {
|
||||
await CreateMedia(i, document.getElementsByClassName("Images Regular")[0]);
|
||||
ApplyMedia(i, document.getElementsByClassName("Images Regular")[0]);
|
||||
}
|
||||
}
|
||||
}
|
||||
// Set the texts. It's opposite because "setting" causes it to switch.
|
||||
FavoriteFlipper = !(post.favourite);
|
||||
post = await MastodonAPI.GetStatus(post.id);
|
||||
FavoriteFlipper = !(post.favourited);
|
||||
BoostFlipper = !(post.reblogged);
|
||||
SetFavorite();
|
||||
SetBoost();
|
||||
// Now time to see if there are any parents
|
||||
if (post.in_reply_to_id != null) {
|
||||
var AnotherPost = await MastodonAPI.GetStatus(post.in_reply_to_id);
|
||||
Parentpost = await MastodonAPI.GetStatus(post.in_reply_to_id);
|
||||
document.getElementsByClassName("Origin Parent")[0].innerHTML = website;
|
||||
if (AnotherPost.reblog != null) {
|
||||
document.getElementsByClassName("PostText Parent")[0].innerHTML = AnotherPost.reblog.content;
|
||||
if (AnotherPost.reblog.media_attachments.length != 0) {
|
||||
for (let i of AnotherPost.reblog.media_attachments) {
|
||||
await CreateMedia(i, document.getElementsByClassName("Images Parent")[0]);
|
||||
}
|
||||
}
|
||||
document.getElementsByClassName("Handle Parent")[0].innerHTML = Parentpost.account.username;
|
||||
if (Parentpost.spoiler_text != "") {
|
||||
document.getElementsByClassName("PostText Parent")[0].innerHTML = "WARNING: " + Parentpost.spoiler_text;
|
||||
} else {
|
||||
document.getElementsByClassName("PostText Parent")[0].innerHTML = AnotherPost.content;
|
||||
if (AnotherPost.media_attachments.length != 0) {
|
||||
for (let i of AnotherPost.media_attachments) {
|
||||
await CreateMedia(i, document.getElementsByClassName("Images Parent")[0]);
|
||||
}
|
||||
document.getElementsByClassName("PostText Parent")[0].innerHTML = Parentpost.content;
|
||||
}
|
||||
if (Parentpost.media_attachments.length != 0) {
|
||||
for (let i of Parentpost.media_attachments) {
|
||||
ApplyMedia(i, document.getElementsByClassName("Images Parent")[0]);
|
||||
}
|
||||
}
|
||||
// Now time to see if there are any grandparents
|
||||
if (AnotherPost.in_reply_to_id != null) {
|
||||
var AnotherAnotherPost = await MastodonAPI.GetStatus(AnotherPost.in_reply_to_id);
|
||||
if (Parentpost.in_reply_to_id != null) {
|
||||
GrandParentpost = await MastodonAPI.GetStatus(Parentpost.in_reply_to_id);
|
||||
document.getElementsByClassName("Origin GrandParent")[0].innerHTML = website;
|
||||
if (AnotherAnotherPost.reblog != null) {
|
||||
document.getElementsByClassName("PostText GrandParent")[0].innerHTML = AnotherAnotherPost.reblog.content;
|
||||
if (AnotherAnotherPost.reblog.media_attachments.length != 0) {
|
||||
for (let i of AnotherAnotherPost.reblog.media_attachments) {
|
||||
await CreateMedia(i, document.getElementsByClassName("Images GrandParent")[0]);
|
||||
}
|
||||
}
|
||||
document.getElementsByClassName("Handle GrandParent")[0].innerHTML = GrandParentpost.account.username;
|
||||
if (GrandParentpost.spoiler_text != "") {
|
||||
document.getElementsByClassName("PostText GrandParent")[0].innerHTML = "WARNING: " + GrandParentpost.spoiler_text;
|
||||
} else {
|
||||
document.getElementsByClassName("PostText GrandParent")[0].innerHTML = AnotherAnotherPost.content;
|
||||
if (AnotherAnotherPost.media_attachments.length != 0) {
|
||||
for (let i of AnotherAnotherPost.media_attachments) {
|
||||
await CreateMedia(i, document.getElementsByClassName("Images GrandParent")[0]);
|
||||
}
|
||||
document.getElementsByClassName("PostText GrandParent")[0].innerHTML = GrandParentpost.content;
|
||||
}
|
||||
if (GrandParentpost.media_attachments.length != 0) {
|
||||
for (let i of GrandParentpost.media_attachments) {
|
||||
ApplyMedia(i, document.getElementsByClassName("Images GrandParent")[0]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -116,30 +135,13 @@ async function GetPost() {
|
|||
document.getElementsByClassName("Handle Regular")[0].innerHTML = post.post.author.handle;
|
||||
}
|
||||
// Text. This will be modified later.
|
||||
var Text = post.post.record.text;
|
||||
console.log(Text);
|
||||
var TestText = Text.replace(/\r?\n|\r/g, "");
|
||||
console.log(TestText);
|
||||
// Check for facets. Facets are things that change what the text does or looks like.
|
||||
if (post.post.record.hasOwnProperty("facets")) {
|
||||
for (let i of post.post.record.facets) {
|
||||
if (i.features[0].$type == "app.bsky.richtext.facet#link") {
|
||||
var EmojiRegex = /\p{Emoji_Modifier_Base}\p{Emoji_Modifier}?|\p{Emoji_Presentation}|\p{Emoji}\uFE0F/gu;
|
||||
var EmojiObjects = Text.match(EmojiRegex);
|
||||
var SubtractNumber = 0;
|
||||
if (EmojiObjects != null) {
|
||||
SubtractNumber = EmojiObjects.length * 2;
|
||||
}
|
||||
Text = Text.substring(0, i.index.byteStart - SubtractNumber) + "<a href='" + i.features[0].uri + "'>" + Text.substring(i.index.byteStart - SubtractNumber, i.index.byteEnd - SubtractNumber) + "</a>" + Text.substring(i.index.byteEnd - SubtractNumber, Text.length - 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
var Text = await BlueskyAPI.ApplyFacets(post.post.record, post.post.record.text);
|
||||
// Place the text.
|
||||
Text = Text.replace(/\r?\n|\r/g, "<br/>");
|
||||
document.getElementsByClassName("PostText Regular")[0].innerHTML = Text;
|
||||
// Show the image if it exists.
|
||||
if (post.post.record.hasOwnProperty("embed")) {
|
||||
await CreateMedia(post.post.record, document.getElementsByClassName("Images Regular")[0], post.post.author.did);
|
||||
ApplyMedia(post.post.record.embed, document.getElementsByClassName("Images Regular")[0], post.post.author.did);
|
||||
}
|
||||
// We don't need to update the post with new information. The repos are seperate.
|
||||
// Set the texts. It's opposite because "setting" causes it to switch.
|
||||
|
@ -155,22 +157,42 @@ async function GetPost() {
|
|||
SetBoost();
|
||||
// Now time to see if there are any parents.
|
||||
if (post.hasOwnProperty("reply")) {
|
||||
var AnotherPost = await BlueskyAPI.GetRecord(post.reply.parent.uri.split("/")[2], post.reply.parent.uri.split("/")[3], post.reply.parent.uri.split("/")[4]);
|
||||
Parentpost = await BlueskyAPI.GetRecord(post.reply.parent.uri.split("/")[2], post.reply.parent.uri.split("/")[3], post.reply.parent.uri.split("/")[4]);
|
||||
document.getElementsByClassName("Origin Parent")[0].innerHTML = website;
|
||||
document.getElementsByClassName("Handle Parent")[0].innerHTML = post.reply.parent.author.handle;
|
||||
document.getElementsByClassName("PostText Parent")[0].innerHTML = AnotherPost.value.text;
|
||||
if (AnotherPost.value.hasOwnProperty("embed")) {
|
||||
await CreateMedia(AnotherPost.value, document.getElementsByClassName("Images Parent")[0], post.reply.parent.author.did);
|
||||
Text = BlueskyAPI.ApplyFacets(Parentpost.value, Parentpost.value.text);
|
||||
Text = Text.replace(/\r?\n|\r/g, "<br/>");
|
||||
// Sensitive topic :3
|
||||
if (Parentpost.value.hasOwnProperty("labels") && Parentpost.value.labels.length != 0) {
|
||||
document.getElementsByClassName("PostText Parent")[0].innerHTML = "LABELS APPLIED: ";
|
||||
console.log(Parentpost.value.labels);
|
||||
for (let lab of Parentpost.value.labels.values) {
|
||||
document.getElementsByClassName("PostText Parent")[0].innerHTML += lab.val + " ";
|
||||
}
|
||||
} else {
|
||||
document.getElementsByClassName("PostText Parent")[0].innerHTML = Text;
|
||||
if (Parentpost.value.hasOwnProperty("embed")) {
|
||||
ApplyMedia(Parentpost.value.embed, document.getElementsByClassName("Images Parent")[0], post.reply.parent.author.did);
|
||||
}
|
||||
}
|
||||
|
||||
// Now time to see if there are any grandparents.
|
||||
if (AnotherPost.value.hasOwnProperty("reply")) {
|
||||
var AnotherAnotherPost = await BlueskyAPI.GetRecord(AnotherPost.value.reply.parent.uri.split("/")[2], AnotherPost.value.reply.parent.uri.split("/")[3], AnotherPost.value.reply.parent.uri.split("/")[4]);
|
||||
if (Parentpost.value.hasOwnProperty("reply")) {
|
||||
GrandParentpost = await BlueskyAPI.GetRecord(Parentpost.value.reply.parent.uri.split("/")[2], Parentpost.value.reply.parent.uri.split("/")[3], Parentpost.value.reply.parent.uri.split("/")[4]);
|
||||
document.getElementsByClassName("Origin GrandParent")[0].innerHTML = website;
|
||||
document.getElementsByClassName("Handle Parent")[0].innerHTML = post.reply.grandparentAuthor.handle;
|
||||
document.getElementsByClassName("PostText GrandParent")[0].innerHTML = AnotherAnotherPost.value.text;
|
||||
if (AnotherAnotherPost.value.hasOwnProperty("embed")) {
|
||||
await CreateMedia(AnotherAnotherPost.value, document.getElementsByClassName("Images GrandParent")[0], post.reply.grandparentAuthor.did);
|
||||
document.getElementsByClassName("Handle GrandParent")[0].innerHTML = post.reply.grandparentAuthor.handle;
|
||||
Text = BlueskyAPI.ApplyFacets(GrandParentpost.value, GrandParentpost.value.text);
|
||||
Text = Text.replace(/\r?\n|\r/g, "<br/>");
|
||||
// Sensitive topic :3
|
||||
if (GrandParentpost.value.hasOwnProperty("labels") && GrandParentpost.value.labels.length != 0) {
|
||||
document.getElementsByClassName("PostText GrandParent")[0].innerHTML = "LABELS APPLIED: ";
|
||||
for (let lab of GrandParentpost.value.labels.values) {
|
||||
document.getElementsByClassName("PostText GrandParent")[0].innerHTML += lab.val + " ";
|
||||
}
|
||||
} else {
|
||||
document.getElementsByClassName("PostText GrandParent")[0].innerHTML = Text;
|
||||
if (GrandParentpost.value.hasOwnProperty("embed")) {
|
||||
ApplyMedia(GrandParentpost.value.embed, document.getElementsByClassName("Images GrandParent")[0], post.reply.grandparentAuthor.did);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -179,53 +201,69 @@ async function GetPost() {
|
|||
}
|
||||
}
|
||||
|
||||
async function CreateMedia(Media, Element, Author = undefined) {
|
||||
// Applyers. Essentially applies a thing to an operation.
|
||||
// Finds any associated media and applies it to the post.
|
||||
async function ApplyMedia(Media, Element, Author = undefined) {
|
||||
// Check to see if the image is on the same server.
|
||||
if (website == "Mastodon") {
|
||||
if (Media.type == "image") {
|
||||
if (Media.remote_url == null) {
|
||||
Element.innerHTML += "<img src=" + Media.url + " alt='" + Media.description + "'/>";
|
||||
Element.innerHTML += "<img src=" + Media.url + " alt='" + EscapeRegExp(Media.description) + "'/>";
|
||||
} else {
|
||||
Element.innerHTML += "<img src=" + Media.remote_url + " alt='" + Media.description + "'/>";
|
||||
Element.innerHTML += "<img src=" + Media.remote_url + " alt='" + EscapeRegExp(Media.description) + "'/>";
|
||||
}
|
||||
} else if (Media.type == "video") {
|
||||
if (Media.remote_url == null) {
|
||||
Element.innerHTML += "<video controls src=" + Media.url + " alt='" + Media.description + "'></video>";
|
||||
Element.innerHTML += "<video controls src=" + Media.url + " alt='" + EscapeRegExp(Media.description) + "'></video>";
|
||||
} else {
|
||||
Element.innerHTML += "<video controls src=" + Media.remote_url + " alt='" + Media.description + "'></video>";
|
||||
Element.innerHTML += "<video controls src=" + Media.remote_url + " alt='" + EscapeRegExp(Media.description) + "'></video>";
|
||||
}
|
||||
}
|
||||
} else if (website == "Bluesky") {
|
||||
if (Media.embed.$type == "app.bsky.embed.record") {
|
||||
var Texty = await BlueskyAPI.GetPosts([Media.embed.record.uri]);
|
||||
console.log(Texty);
|
||||
Element.innerHTML += "<p class='Embed'>" + Texty.posts[0].record.text + "</p><br/>";
|
||||
if (Texty.posts[0].embed.$type == "app.bsky.embed.images") {
|
||||
for (let i of Texty.posts[0].embed.images) {
|
||||
var Blobby = await BlueskyAPI.GetBlob(Author, i.image.ref.$link);
|
||||
var ObjectURL = URL.createObjectURL(Blobby);
|
||||
Element.innerHTML += "<img src=" + ObjectURL + " alt='" + i.alt + "'/>";
|
||||
}
|
||||
} else if (Media.embed.$type == "app.bsky.embed.video") {
|
||||
var Blobby = await BlueskyAPI.GetBlob(Author, Texty.posts[0].embed.video.ref.$link);
|
||||
var ObjectURL = URL.createObjectURL(Blobby);
|
||||
Element.innerHTML += "<video controls src=" + ObjectURL + "></video>";
|
||||
// Record and media embed; They are from seperate posts.
|
||||
if (Media.$type == "app.bsky.embed.recordWithMedia") {
|
||||
await BlueskyBlobEmbed(Media.media, Element, Author);
|
||||
var Texty = await BlueskyAPI.GetPosts([Media.record.record.uri]);
|
||||
var Text = BlueskyAPI.ApplyFacets(Texty.posts[0].record, Texty.posts[0].record.text);
|
||||
Text = Text.replace(/\r?\n|\r/g, "<br/>");
|
||||
Element.innerHTML += "<p class='Embed'>" + Text + "</p><br/>";
|
||||
// To stop confusion: this is for the RECORD EMBED! It gets an image from the record embed and puts it there.
|
||||
if (Texty.posts[0].record.embed.$type == "app.bsky.embed.images" || Texty.posts[0].record.embed.$type == "app.bsky.embed.video") {
|
||||
await BlueskyBlobEmbed(Texty.posts[0].record.embed, Element, Author);
|
||||
}
|
||||
// It's not an embed, continue...
|
||||
} else if (Media.embed.$type == "app.bsky.embed.images") {
|
||||
for (let i of Media.embed.images) {
|
||||
var Blobby = await BlueskyAPI.GetBlob(Author, i.image.ref.$link);
|
||||
var ObjectURL = URL.createObjectURL(Blobby);
|
||||
Element.innerHTML += "<img src=" + ObjectURL + " alt='" + i.alt + "'/>";
|
||||
// Just a record on it's own.
|
||||
} else if (Media.$type == "app.bsky.embed.record") {
|
||||
var Texty = await BlueskyAPI.GetPosts([Media.record.uri]);
|
||||
var Text = BlueskyAPI.ApplyFacets(Texty.posts[0].record, Texty.posts[0].record.text);
|
||||
Text = Text.replace(/\r?\n|\r/g, "<br/>");
|
||||
Element.innerHTML += "<p class='Embed'>" + Text + "</p><br/>";
|
||||
if (Texty.posts[0].record.embed.$type == "app.bsky.embed.images" || Texty.posts[0].record.embed.$type == "app.bsky.embed.video") {
|
||||
await BlueskyBlobEmbed(Texty.posts[0].record.embed, Element, Author);
|
||||
}
|
||||
} else if (Media.embed.$type == "app.bsky.embed.video") {
|
||||
var Blobby = await BlueskyAPI.GetBlob(Author, Media.embed.video.ref.$link);
|
||||
var ObjectURL = URL.createObjectURL(Blobby);
|
||||
Element.innerHTML += "<video controls src=" + ObjectURL + "></video>";
|
||||
// Image on it's own
|
||||
} else if (Media.$type == "app.bsky.embed.images" || Media.$type == "app.bsky.embed.video") {
|
||||
await BlueskyBlobEmbed(Media, Element, Author);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Fucking hell.
|
||||
async function BlueskyBlobEmbed(Blob, Element, Author) {
|
||||
if (Blob.$type == "app.bsky.embed.images") {
|
||||
for (let i of Blob.images) {
|
||||
var Blobby = await BlueskyAPI.GetBlob(Author, i.image.ref.$link);
|
||||
var ObjectURL = URL.createObjectURL(Blobby);
|
||||
Element.innerHTML += "<img src=" + ObjectURL + " alt='" + EscapeRegExp(i.alt) + "'/>";
|
||||
}
|
||||
// Video embed.
|
||||
} else if (Blob.$type == "app.bsky.embed.video") {
|
||||
var Blobby = await BlueskyAPI.GetBlob(Author, Blob.video.ref.$link);
|
||||
var ObjectURL = URL.createObjectURL(Blobby);
|
||||
Element.innerHTML += "<video controls src=" + ObjectURL + "></video>";
|
||||
}
|
||||
}
|
||||
|
||||
// Setters
|
||||
function SetFavorite() {
|
||||
FavoriteFlipper = !(FavoriteFlipper);
|
||||
if (FavoriteFlipper == false) {
|
||||
|
@ -243,3 +281,11 @@ function SetBoost() {
|
|||
Boost.innerHTML = "Unboost...";
|
||||
}
|
||||
}
|
||||
|
||||
// Functions stolen form elsewhere
|
||||
function EscapeRegExp(text) {
|
||||
if (text == null) {
|
||||
return null;
|
||||
}
|
||||
return text.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, '\$&');
|
||||
}
|
||||
|
|
72
JS/index.js
72
JS/index.js
|
@ -14,22 +14,27 @@ let BrowserWidth = window.innerWidth;
|
|||
let BrowserHeight = window.innerHeight;
|
||||
|
||||
let ArrowsButton = document.getElementsByClassName("Arrow");
|
||||
|
||||
let SettingButton = document.getElementsByClassName("Setting")[0];
|
||||
let MailButton = document.getElementsByClassName("Mail")[0];
|
||||
let PostingButton = document.getElementsByClassName("Posting")[0];
|
||||
let FeedButton = document.getElementsByClassName("Feed")[0];
|
||||
|
||||
// Sounds
|
||||
const ButtonSound = new Audio("Audio/button-305770.mp3");
|
||||
const WarningClick = new Audio("Audio/button-pressed-38129.mp3");
|
||||
const BackgroundMusic = new Audio("Audio/soft-piano-music-312509.mp3");
|
||||
|
||||
// Discoverability
|
||||
let Discover = false;
|
||||
|
||||
// Update a timer
|
||||
function UpdateTime() {
|
||||
let TimeNow = new Date();
|
||||
let Hour = TimeNow.getHours();
|
||||
let Minute = TimeNow.getMinutes();
|
||||
|
||||
var WebsiteTime = document.getElementsByClassName("Time")[0]
|
||||
let WebsiteTime = document.getElementsByClassName("Time")[0]
|
||||
WebsiteTime.innerHTML = "";
|
||||
if (Hour < 10) {
|
||||
WebsiteTime.innerHTML = WebsiteTime.innerHTML + "0" + Hour;
|
||||
|
@ -149,12 +154,20 @@ async function PosterContainerUpdate(Direction) {
|
|||
|
||||
// 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("");
|
||||
// If discover is turned on...
|
||||
if (Discover == true) {
|
||||
if (localStorage.getItem("Remote") != null) {
|
||||
MastodonLoadedFeed = await MastodonAPI.GetPublicTimeline(true, true, localStorage.getItem(Variables.MastodonWebsite), "");
|
||||
} else {
|
||||
MastodonLoadedFeed = await MastodonAPI.GetPublicTimeline(true, false, localStorage.getItem(Variables.MastodonWebsite), "");
|
||||
}
|
||||
} else {
|
||||
MastodonLoadedFeed = await MastodonAPI.GetTimeline("");
|
||||
}
|
||||
}
|
||||
// Bluesky gaining of timeline.
|
||||
if (localStorage.getItem(Variables.BlueskyPDS) == null) {
|
||||
|
@ -162,7 +175,11 @@ async function PosterContainerUpdate(Direction) {
|
|||
Lim = Lim * 2;
|
||||
Bluesky = false;
|
||||
} else if (BlueskyLoadedFeed.length == 0) {
|
||||
BlueskyLoadedFeed = await BlueskyAPI.GetTimeline("").then((response) => response.feed);
|
||||
if (Discover == true) {
|
||||
BlueskyLoadedFeed = await BlueskyAPI.GetPublicTimeline("").then((response) => response.feed);
|
||||
} else {
|
||||
BlueskyLoadedFeed = await BlueskyAPI.GetTimeline("").then((response) => response.feed);
|
||||
}
|
||||
}
|
||||
if (Direction == "Forward") {
|
||||
CurrentThing = CurrentThing + Lim;
|
||||
|
@ -192,7 +209,16 @@ async function PosterContainerUpdate(Direction) {
|
|||
WebsiteAPIType.push("Mastodon");
|
||||
i.getElementsByClassName("PostContent")[0].innerHTML = "";
|
||||
if (MastodonLoadedFeed[CurrentThing + counter] == undefined) {
|
||||
let TempFeed = await MastodonAPI.GetTimeline(MastodonLoadedFeed[CurrentThing + counter - 1].id);
|
||||
let TempFeed;
|
||||
if (Discover == true) {
|
||||
if (localStorage.getItem("Remote") != null) {
|
||||
TempFeed = await MastodonAPI.GetPublicTimeline(true, true, localStorage.getItem(Variables.MastodonWebsite), MastodonLoadedFeed[CurrentThing + counter - 1].id);
|
||||
} else {
|
||||
TempFeed = await MastodonAPI.GetPublicTimeline(true, false, localStorage.getItem(Variables.MastodonWebsite), MastodonLoadedFeed[CurrentThing + counter - 1].id);
|
||||
}
|
||||
} else {
|
||||
TempFeed = await MastodonAPI.GetTimeline(MastodonLoadedFeed[CurrentThing + counter - 1].id);
|
||||
}
|
||||
MastodonLoadedFeed = MastodonLoadedFeed.concat(TempFeed);
|
||||
}
|
||||
// Check for images. Reblog roundabout fix included.
|
||||
|
@ -238,13 +264,18 @@ async function PosterContainerUpdate(Direction) {
|
|||
WebsiteAPIType.push("Bluesky");
|
||||
i.getElementsByClassName("PostContent")[0].innerHTML = "";
|
||||
if (BlueskyLoadedFeed[CurrentThing + counter] == undefined) {
|
||||
let TempFeed = await BlueskyAPI.GetTimeline(BlueskyLoadedFeed[CurrentThing + counter - 1].post.indexedAt).then((response) => response.feed)
|
||||
let TempFeed;
|
||||
if (Discover == true) {
|
||||
BlueskyLoadedFeed = await BlueskyAPI.GetPublicTimeline(BlueskyLoadedFeed[CurrentThing + counter - 1].post.indexedAt).then((response) => response.feed);
|
||||
} else {
|
||||
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);
|
||||
// Check for an image
|
||||
// Check for an image.
|
||||
if (BlueskyLoadedFeed[CurrentThing + counter].post.record.hasOwnProperty("embed")) {
|
||||
if (BlueskyLoadedFeed[CurrentThing + counter].post.record.embed.$type == "app.bsky.embed.images") {
|
||||
i.getElementsByClassName("PostContent")[0].innerHTML += "This post has an image!<br/>";
|
||||
|
@ -266,26 +297,14 @@ async function PosterContainerUpdate(Direction) {
|
|||
i.getElementsByClassName("PostContent")[0].innerHTML += "</b>";
|
||||
break;
|
||||
}
|
||||
// Check for a reblog
|
||||
// Check for a reblog.
|
||||
if (BlueskyLoadedFeed[CurrentThing + counter].hasOwnProperty("reason") && BlueskyLoadedFeed[CurrentThing + counter].reason.$type == "app.bsky.feed.defs#reasonRepost") {
|
||||
i.getElementsByClassName("Username")[0].innerHTML = BlueskyLoadedFeed[CurrentThing + counter].post.author.handle + " ( R: " + BlueskyLoadedFeed[CurrentThing + counter].reason.by.handle + " )";
|
||||
} else {
|
||||
i.getElementsByClassName("Username")[0].innerHTML = BlueskyLoadedFeed[CurrentThing + counter].post.author.handle;
|
||||
}
|
||||
var TempText = BlueskyLoadedFeed[CurrentThing + counter].post.record.text;
|
||||
if (BlueskyLoadedFeed[CurrentThing + counter].post.record.hasOwnProperty("facets")) {
|
||||
for (let i of BlueskyLoadedFeed[CurrentThing + counter].post.record.facets) {
|
||||
if (i.features[0].$type == "app.bsky.richtext.facet#link") {
|
||||
var EmojiRegex = /\p{Emoji_Modifier_Base}\p{Emoji_Modifier}?|\p{Emoji_Presentation}|\p{Emoji}\uFE0F/gu;
|
||||
var EmojiObjects = TempText.match(EmojiRegex);
|
||||
var SubtractNumber = 0;
|
||||
if (EmojiObjects != null) {
|
||||
SubtractNumber = EmojiObjects.length * 2;
|
||||
}
|
||||
TempText = TempText.substring(0, i.index.byteStart - SubtractNumber) + "<a href='" + i.features[0].uri + "'>" + TempText.substring(i.index.byteStart - SubtractNumber, i.index.byteEnd - SubtractNumber) + "</a>" + TempText.substring(i.index.byteEnd - SubtractNumber, TempText.length - 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
// Apply correct facets.
|
||||
let TempText = await BlueskyAPI.ApplyFacets(BlueskyLoadedFeed[CurrentThing + counter].post.record, BlueskyLoadedFeed[CurrentThing + counter].post.record.text);
|
||||
TempText = TempText.replace(/\r?\n|\r/g, "<br/>");
|
||||
i.getElementsByClassName("PostContent")[0].innerHTML += TempText;
|
||||
break;
|
||||
|
@ -328,3 +347,12 @@ MailButton.onclick = (event) => {
|
|||
PostingButton.onclick = (event) => {
|
||||
window.location.href = "./HTML/post.html";
|
||||
}
|
||||
|
||||
FeedButton.onclick = (event) => {
|
||||
Discover = !(Discover);
|
||||
MastodonLoadedFeed = [];
|
||||
BlueskyLoadedFeed = [];
|
||||
CurrentThing = 0;
|
||||
PosterContainerUpdate();
|
||||
|
||||
}
|
||||
|
|
46
JS/post.js
46
JS/post.js
|
@ -8,6 +8,7 @@ let PostButton = document.getElementsByClassName("Button")[0];
|
|||
let VisibilityDropdown = document.getElementsByClassName("PostVisibility")[0];
|
||||
let InputArea = document.getElementsByClassName("Text")[0];
|
||||
let YoutubePoser = document.getElementsByClassName("PostYoutube")[0];
|
||||
let WarningInputArea = document.getElementsByClassName("Warning")[0];
|
||||
|
||||
// Clicking the beeg POST button.
|
||||
PostButton.onclick = (event) => {
|
||||
|
@ -46,10 +47,20 @@ async function Post() {
|
|||
break;
|
||||
}
|
||||
if (website == "Mastodon") {
|
||||
await MastodonAPI.CreateReplyStatus(Text, TempVisible, JSON.parse(localStorage.getItem("post")).id);
|
||||
if (WarningInputArea.value == "") {
|
||||
await MastodonAPI.CreateReplyStatus(Text, undefined, TempVisible, JSON.parse(localStorage.getItem("post")).id);
|
||||
} else {
|
||||
await MastodonAPI.CreateReplyStatus(Text, WarningInputArea.value, TempVisible, JSON.parse(localStorage.getItem("post")).id);
|
||||
}
|
||||
return;
|
||||
InputArea.value = "";
|
||||
WarningInputArea.value = "";
|
||||
} else if (website == "All") {
|
||||
await MastodonAPI.CreateStatus(Text, TempVisible);
|
||||
if (WarningInputArea.value == "") {
|
||||
await MastodonAPI.CreateStatus(Text, undefined, TempVisible);
|
||||
} else {
|
||||
await MastodonAPI.CreateStatus(Text, WarningInputArea.value, TempVisible);
|
||||
}
|
||||
}
|
||||
}
|
||||
// Bluesky posting.
|
||||
|
@ -70,18 +81,32 @@ async function Post() {
|
|||
break;
|
||||
}
|
||||
if (website == "Bluesky") {
|
||||
let Post;
|
||||
if (JSON.parse(localStorage.getItem("post")).hasOwnProperty("reply")) {
|
||||
let Post = await BlueskyAPI.CreateReplyPost(localStorage.getItem(Variables.BlueskyDID), Text, JSON.parse(localStorage.getItem("post")).post, JSON.parse(localStorage.getItem("post")).reply.root);
|
||||
await BlueskyAPI.SetThreadGate(localStorage.getItem(Variables.BlueskyDID), Post.uri, TempVisible);
|
||||
return;
|
||||
if (WarningInputArea.value == "") {
|
||||
Post = await BlueskyAPI.CreateReplyPost(localStorage.getItem(Variables.BlueskyDID), Text, JSON.parse(localStorage.getItem("post")).post, JSON.parse(localStorage.getItem("post")).reply.root);
|
||||
} else {
|
||||
Post = await BlueskyAPI.CreateReplyPost(localStorage.getItem(Variables.BlueskyDID), Text, JSON.parse(localStorage.getItem("post")).post, JSON.parse(localStorage.getItem("post")).reply.root, WarningInputArea.value);
|
||||
}
|
||||
await BlueskyAPI.CreateThreadGate(localStorage.getItem(Variables.BlueskyDID), Post.uri, TempVisible);
|
||||
} else {
|
||||
let Post = await BlueskyAPI.CreateReplyPost(localStorage.getItem(Variables.BlueskyDID), Text, JSON.parse(localStorage.getItem("post")).post, JSON.parse(localStorage.getItem("post")).post);
|
||||
await BlueskyAPI.SetThreadGate(localStorage.getItem(Variables.BlueskyDID), Post.uri, TempVisible);
|
||||
return;
|
||||
if (WarningInputArea.value == "") {
|
||||
Post = await BlueskyAPI.CreateReplyPost(localStorage.getItem(Variables.BlueskyDID), Text, JSON.parse(localStorage.getItem("post")).post, JSON.parse(localStorage.getItem("post")).post);
|
||||
} else {
|
||||
Post = await BlueskyAPI.CreateReplyPost(localStorage.getItem(Variables.BlueskyDID), Text, JSON.parse(localStorage.getItem("post")).post, JSON.parse(localStorage.getItem("post")).post, WarningInputArea.value);
|
||||
}
|
||||
await BlueskyAPI.CreateThreadGate(localStorage.getItem(Variables.BlueskyDID), Post.uri, TempVisible);
|
||||
}
|
||||
InputArea.value = "";
|
||||
WarningInputArea.value = "";
|
||||
} else if (website == "All") {
|
||||
let Post = await BlueskyAPI.CreatePost(localStorage.getItem(Variables.BlueskyDID), Text);
|
||||
await BlueskyAPI.SetThreadGate(localStorage.getItem(Variables.BlueskyDID), Post.uri, TempVisible);
|
||||
let Post;
|
||||
if (WarningInputArea.value == "") {
|
||||
Post = await BlueskyAPI.CreatePost(localStorage.getItem(Variables.BlueskyDID), Text);
|
||||
} else {
|
||||
Post = await BlueskyAPI.CreatePost(localStorage.getItem(Variables.BlueskyDID), Text, WarningInputArea.value);
|
||||
}
|
||||
await BlueskyAPI.CreateThreadGate(localStorage.getItem(Variables.BlueskyDID), Post.uri, TempVisible);
|
||||
}
|
||||
}
|
||||
// Youtube posting.
|
||||
|
@ -91,6 +116,7 @@ async function Post() {
|
|||
}
|
||||
// The input being cleared means that the posting happened.
|
||||
InputArea.value = "";
|
||||
WarningInputArea.value = "";
|
||||
}
|
||||
|
||||
// Check if you can interact with the textbox
|
||||
|
|
|
@ -5,7 +5,6 @@ import * as YoutubeAPI from "./YoutubeAPI.js";
|
|||
import * as Variables from "./Variables.js";
|
||||
|
||||
// Settings buttons
|
||||
let LocalButton = document.getElementsByClassName("Local")[0];
|
||||
let RemoteButton = document.getElementsByClassName("Remote")[0];
|
||||
|
||||
// Website Stuff
|
||||
|
@ -25,16 +24,7 @@ let YoutubeLogoutButton = document.getElementsByClassName("Logout Youtube")[0];
|
|||
// original link
|
||||
let Origin = location.origin + "/HTML/setting.html"
|
||||
|
||||
// Change weather the timelines are public or remote
|
||||
LocalButton.onclick = (event) => {
|
||||
// Toggle the Variable
|
||||
if (localStorage.getItem("Local") != null) {
|
||||
localStorage.removeItem("Local");
|
||||
} else {
|
||||
localStorage.setItem("Local", "true");
|
||||
}
|
||||
}
|
||||
|
||||
// Allow the user to change if Remote is a thing or not.
|
||||
RemoteButton.onclick = (event) => {
|
||||
// Toggle the Variable
|
||||
if (localStorage.getItem("Remote") != null) {
|
||||
|
|
|
@ -301,9 +301,10 @@
|
|||
|
||||
<footer class="MainFooter">
|
||||
<p class="Setting">Setting</p>
|
||||
<p class="Feed">Feed</p>
|
||||
<p class="Time" style="width: 50%">Time</p>
|
||||
<p class="Posting">Post</p>
|
||||
<p class="Mail">Mail</p>
|
||||
<p class="Posting">Posting</p>
|
||||
</footer>
|
||||
</section>
|
||||
</body>
|
||||
|
|
Loading…
Add table
Reference in a new issue