FinalReleaseChanges (#49)
- Loads of bug fixes. - CSS improvements. - Tags added. - Optimized some things. - Some other oddities? I don't know :3 - Happiness increased by 2%.
This commit is contained in:
parent
f03e73132a
commit
8c69eaa88a
16 changed files with 393 additions and 183 deletions
|
@ -1,3 +1,7 @@
|
|||
html {
|
||||
background: linear-gradient(to right, #00FFFF, #dcdcdc, #dcdcdc, #dcdcdc, #dcdcdc, #dcdcdc, #00FFFF);
|
||||
}
|
||||
|
||||
.Button {
|
||||
margin-top: 30px;
|
||||
|
||||
|
@ -13,14 +17,46 @@ body {
|
|||
text-align: center;
|
||||
}
|
||||
|
||||
section {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
div:not(.Posts) {
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
margin-bottom: auto;
|
||||
|
||||
border-style: solid;
|
||||
border-width: 2px 0;
|
||||
|
||||
width: 49%;
|
||||
}
|
||||
|
||||
#stick {
|
||||
position: sticky;
|
||||
top: 0;
|
||||
}
|
||||
|
||||
img {
|
||||
width: 20vh;
|
||||
height: 20vh;
|
||||
}
|
||||
|
||||
footer {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
|
||||
height: 5vh;
|
||||
height: 20vh;
|
||||
}
|
||||
|
||||
/* Mastodon things */
|
||||
.Trees {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
.Entry {
|
||||
border-left: 2px solid;
|
||||
border-right: 1px dashed;
|
||||
|
|
|
@ -15,7 +15,7 @@ body {
|
|||
|
||||
.Embed {
|
||||
border-style: solid;
|
||||
border-radius: 1%;
|
||||
border-radius: 2%;
|
||||
|
||||
background-color: yellow;
|
||||
}
|
||||
|
@ -40,6 +40,10 @@ body {
|
|||
background-color: #050505;
|
||||
}
|
||||
|
||||
.Favorite, .Boost, .Reply {
|
||||
margin: auto;
|
||||
}
|
||||
|
||||
.Button {
|
||||
margin-top: 30px;
|
||||
|
||||
|
|
|
@ -221,9 +221,9 @@ html {
|
|||
.Username {
|
||||
text-align: center;
|
||||
font-weight: bold;
|
||||
font-size: 2ch;
|
||||
font-size: min(2vw, 2ch);
|
||||
|
||||
margin-top: -5px;
|
||||
margin-top: max(-5px, -0.5vw);
|
||||
}
|
||||
|
||||
.PostContent {
|
||||
|
@ -247,6 +247,11 @@ html {
|
|||
|
||||
.Time {
|
||||
font-size: 4ch;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.Time:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
.MainFooter, .MainBlackedFooter {
|
||||
|
@ -260,6 +265,8 @@ html {
|
|||
border-width: 2px;
|
||||
border-color: #00FFFF;
|
||||
|
||||
padding: auto;
|
||||
|
||||
height: 20vh;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/* Combination */
|
||||
header, footer {
|
||||
style="position: relative;
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
|
|
40
CSS/post.css
40
CSS/post.css
|
@ -1,4 +1,5 @@
|
|||
html {
|
||||
background: linear-gradient(#FFFFFF, #dcdcdc, #2eff51);
|
||||
overflow-x: hidden;
|
||||
overflow-y: hidden;
|
||||
}
|
||||
|
@ -14,6 +15,43 @@ body {
|
|||
|
||||
section {
|
||||
height: 75vh;
|
||||
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
justify-content: center;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
textarea, select, input, label {
|
||||
resize: none;
|
||||
|
||||
border-style: solid;
|
||||
border-width: 2px;
|
||||
border-color: #00FFFF;
|
||||
border-radius: 2% / 50%;
|
||||
}
|
||||
|
||||
.Divide {
|
||||
margin-top: auto;
|
||||
margin-bottom: auto;
|
||||
margin-left: 1%;
|
||||
margin-right: 1%;
|
||||
|
||||
border-style: solid;
|
||||
border-width: 4px;
|
||||
border-radius: 10%;
|
||||
|
||||
padding: 1%;
|
||||
|
||||
background-color: white;
|
||||
filter: drop-shadow(0px 20px 10px #00cf23);
|
||||
|
||||
transition: background-color 0.5s, filter 0.5s;
|
||||
}
|
||||
|
||||
.Button:hover {
|
||||
background-color: #dcdcdc;
|
||||
filter: drop-shadow(0px -20px 10px #2eff51);
|
||||
}
|
||||
|
||||
.SmallButton {
|
||||
|
@ -30,5 +68,5 @@ footer {
|
|||
display: flex;
|
||||
justify-content: center;
|
||||
|
||||
height: 5vh;
|
||||
height: 20vh;
|
||||
}
|
||||
|
|
|
@ -28,9 +28,8 @@ body {
|
|||
border-width: 6px;
|
||||
border-color: #00FFFF;
|
||||
|
||||
padding: 8%;
|
||||
padding: 8vh 6vw;
|
||||
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
background: linear-gradient(#dcdcdc, #b4b4b4);
|
||||
color: black;
|
||||
|
|
|
@ -15,18 +15,25 @@
|
|||
<header>
|
||||
<h1>Account</h1>
|
||||
</header>
|
||||
<div>
|
||||
<h2 class="Account"></h2>
|
||||
<img class="AccountImage" />
|
||||
<p class="AccountDescription"></p>
|
||||
<div style="display: flex; justify-content: center;">
|
||||
<p class="Button Follow">Follow!</p>
|
||||
<p class="Button Block">Block!</p>
|
||||
<section>
|
||||
<!-- Account information goes into this div. -->
|
||||
<div id="stick">
|
||||
<h2 class="Account"></h2>
|
||||
<img class="AccountImage"/>
|
||||
<p class="AccountDescription"></p>
|
||||
<aside style="display: flex; justify-content: center;">
|
||||
<p class="Button Follow">Follow!</p>
|
||||
<p class="Button Block">Block!</p>
|
||||
</aside>
|
||||
</div>
|
||||
<div class="Posts">
|
||||
<p>Not implemented. Posts should populate here.</p>
|
||||
<!-- Either other account info goes here, or posts go here. -->
|
||||
<div>
|
||||
<h2 class="Account"></h2>
|
||||
<img class="AccountImage" hidden=true/>
|
||||
<p class="AccountDescription"></p>
|
||||
<div class="Posts"></div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
<footer>
|
||||
<p class="Button" onclick="history.back();"><b>Back</b></p>
|
||||
</footer>
|
||||
|
|
|
@ -35,7 +35,8 @@
|
|||
</header>
|
||||
<p class="PostText Regular"></p>
|
||||
<div class="Images Regular"></div>
|
||||
<div "display: flex;">
|
||||
<!-- Interactables. -->
|
||||
<div style="display: flex;">
|
||||
<p class="Favorite">Favorite!</p>
|
||||
<p class="Boost">Boost!</p>
|
||||
<p class="Reply">Reply!</p>
|
||||
|
|
|
@ -16,19 +16,28 @@
|
|||
<h1>Post</h1>
|
||||
</header>
|
||||
<section>
|
||||
<textarea cols="50" rows="25" class="Text" placeholder="status here..."></textarea>
|
||||
<div>
|
||||
<!-- This the typing div :3 -->
|
||||
<div class="Divide">
|
||||
<textarea cols="50" rows="25" class="Text" placeholder="status here..."></textarea>
|
||||
<div><textarea cols="50" rows="2" class="Warning" maxlength="100" placeholder="Content Warnings"></textarea></div>
|
||||
<div><textarea cols="50" rows="1" class="Tags" maxlength="50" placeholder="Tags (seperate with ;)"></textarea></div>
|
||||
</div>
|
||||
<!-- This the "settings" div :3 -->
|
||||
<div class="Divide">
|
||||
<select class="PostVisibility">
|
||||
<option value="Public">Public Post</option>
|
||||
<option value="Quiet">Quiet Public Post</option>
|
||||
<option value="Friend">Friends Only Post</option>
|
||||
<option value="Private">Private Post</option>
|
||||
</select>
|
||||
<input type="checkbox" class="PostYoutube" />
|
||||
<label>Post to Youtube</label>
|
||||
<div></div>
|
||||
<input type="checkbox" class="PostYoutube" />
|
||||
<label>Post to Youtube</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="Divide Button">
|
||||
<p>POST!</p>
|
||||
</div>
|
||||
<textarea cols="50" rows="1" class="Warning" placeholder="Content Warnings"></textarea>
|
||||
<p class="Button">POST!</p>
|
||||
</section>
|
||||
<footer>
|
||||
<p class="SmallButton" onclick="history.back();"><b>Back</b></p>
|
||||
|
|
|
@ -15,31 +15,29 @@
|
|||
<header>
|
||||
<h1>Setting</h1>
|
||||
</header>
|
||||
<div style="display: flex; justify-content: center; height: 75vh;">
|
||||
<div style="display: flex; flex-wrap: wrap; justify-content: center; height: 75vh;">
|
||||
<!-- Toggling things. -->
|
||||
<div class="Button">
|
||||
<p class="Remote">Toggle Remote</p>
|
||||
</div>
|
||||
<!-- Mastodon things. -->
|
||||
<div class="Button">
|
||||
<!-- Sorry people! -->
|
||||
<!-- Mastodon things. -->
|
||||
<div>
|
||||
<input type="text" class="WebInput Mastodon" placeholder="Website (mastodon.social)"/>
|
||||
<p class="Login Mastodon"><em>Login to Mastodon</em></p>
|
||||
<p class="Logout Mastodon Hidden"><em>Logout of Mastodon</em></p>
|
||||
</div>
|
||||
<!-- Bluesky things. -->
|
||||
<div>
|
||||
<input type="text" class="WebInput Bluesky" placeholder="Website (bsky.social)"/>
|
||||
<p class="Login Bluesky"><em>Login to Bluesky</em></p>
|
||||
<p class="Logout Bluesky Hidden"><em>Logout of Bluesky</em></p>
|
||||
</div>
|
||||
<!-- Youtube things. -->
|
||||
<div>
|
||||
<input type="text" class="WebInput Youtube" placeholder="Youtube API Key"/>
|
||||
<input type="text" class="WebInput Youtube" placeholder="Youtube Channel Handle"/>
|
||||
<p class="Login Youtube"><em>Login to Youtube</em></p>
|
||||
<p class="Logout Youtube Hidden"><em>Logout of Youtube</em></p>
|
||||
</div>
|
||||
<input type="text" class="WebInput Mastodon" placeholder="Website (mastodon.social)"/>
|
||||
<p class="Login Mastodon"><em>Login to Mastodon</em></p>
|
||||
<p class="Logout Mastodon Hidden"><em>Logout of Mastodon</em></p>
|
||||
</div>
|
||||
<!-- Bluesky things. -->
|
||||
<div class="Button">
|
||||
<input type="text" class="WebInput Bluesky" placeholder="Website (bsky.social)"/>
|
||||
<p class="Login Bluesky"><em>Login to Bluesky</em></p>
|
||||
<p class="Logout Bluesky Hidden"><em>Logout of Bluesky</em></p>
|
||||
</div>
|
||||
<!-- Youtube things. -->
|
||||
<div class="Button">
|
||||
<input type="text" class="WebInput Youtube" placeholder="Youtube API Key"/>
|
||||
<input type="text" class="WebInput Youtube" placeholder="Youtube Channel Handle"/>
|
||||
<p class="Login Youtube"><em>Login to Youtube</em></p>
|
||||
<p class="Logout Youtube Hidden"><em>Logout of Youtube</em></p>
|
||||
</div>
|
||||
</div>
|
||||
<footer>
|
||||
|
|
110
JS/BlueskyAPI.js
110
JS/BlueskyAPI.js
|
@ -65,6 +65,23 @@ export async function GetProfile(DID) {
|
|||
return body;
|
||||
}
|
||||
|
||||
export async function GetProfileFeed(DID) {
|
||||
if (Token == null) {
|
||||
return "";
|
||||
}
|
||||
let FetchThing = localStorage.getItem(Variables.BlueskyPDS) + "/xrpc/app.bsky.feed.getAuthorFeed?actor=" + DID;
|
||||
let DPoP = await ClientDPoPPDS("GET", FetchThing);
|
||||
let request = fetch(FetchThing, { method: "GET", headers: {"Authorization": "DPoP " + Token, "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 GetProfileFeed(DID);
|
||||
}
|
||||
return body;
|
||||
}
|
||||
|
||||
// This gets the post. If there are multiple URIs, they must be within an array.
|
||||
export async function GetPosts(URIs) {
|
||||
if (Token == null) {
|
||||
|
@ -115,7 +132,7 @@ export async function GetRecord(Repo, Collection, RKey) {
|
|||
|
||||
// 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) {
|
||||
export async function CreatePost(DID, Text, ContentWarning = undefined, Tags = [], ReplyID = undefined, RootID = undefined) {
|
||||
if (Token == null) {
|
||||
return "";
|
||||
}
|
||||
|
@ -124,34 +141,18 @@ export async function CreatePost(DID, Text, ContentWarning = undefined) {
|
|||
"text": Text,
|
||||
"createdAt": new Date(Date.now()).toISOString()
|
||||
};
|
||||
// Content warning stuff.
|
||||
if (ContentWarning != undefined) {
|
||||
Record.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") {
|
||||
let matches = body.message.match(/(\d+)/);
|
||||
Record.text = Text.slice(0, matches[0] - 1);
|
||||
body = await CreateRecord(DID, "app.bsky.feed.post", Record, undefined);
|
||||
await CreateReplyPost(DID, Text.slice(matches[0] - 1, Text.length - 1), body, body);
|
||||
}
|
||||
return body;
|
||||
}
|
||||
|
||||
// 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 (Token == null) {
|
||||
return "";
|
||||
}
|
||||
let Record = {
|
||||
"$type": "app.bsky.feed.post",
|
||||
"text": Text,
|
||||
"createdAt": new Date(Date.now()).toISOString(),
|
||||
"reply": {
|
||||
// ReplyID and RootID simultaniously.
|
||||
if (ReplyID != undefined && RootID != undefined) {
|
||||
Record.reply = {
|
||||
"parent": {
|
||||
"uri": ReplyID.uri,
|
||||
"cid": ReplyID.cid
|
||||
|
@ -160,22 +161,22 @@ export async function CreateReplyPost(DID, Text, ReplyID, RootID, ContentWarning
|
|||
"uri": RootID.uri,
|
||||
"cid": RootID.cid
|
||||
}
|
||||
}
|
||||
};
|
||||
if (ContentWarning != undefined) {
|
||||
Record.labels = {
|
||||
"$type": "com.atproto.label.defs#selfLabels",
|
||||
"values": [{
|
||||
"val": ContentWarning
|
||||
}]
|
||||
}
|
||||
};
|
||||
}
|
||||
// Tags
|
||||
if (Tags.length != 0) {
|
||||
Record.tags = Tags;
|
||||
}
|
||||
let body = await CreateRecord(DID, "app.bsky.feed.post", Record, undefined);
|
||||
if (body.hasOwnProperty("error") && body.error == "InvalidRequest") {
|
||||
let matches = body.message.match(/(\d+)/);
|
||||
Record.text = Text.slice(0, matches[0] - 1);
|
||||
body = await CreateRecord(DID, "app.bsky.feed.post", Record, undefined);
|
||||
await CreateReplyPost(DID, Text.slice(matches[0] - 1, Text.length - 1), body, RootID);
|
||||
if (ReplyID == undefined && RootID == undefined) {
|
||||
await CreatePost(DID, Text.slice(matches[0] - 1, Text.length), ContentWarning, Tags, body, body);
|
||||
} else {
|
||||
await CreatePost(DID, Text.slice(matches[0] - 1, Text.length), ContentWarning, Tags, body, RootID);
|
||||
}
|
||||
}
|
||||
return body;
|
||||
}
|
||||
|
@ -402,8 +403,7 @@ export async function DeleteRecord(Repo, Collection, RKey) {
|
|||
// 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"})
|
||||
.then((response) => response.json());
|
||||
return fetch("https://bsky.social/.well-known/oauth-authorization-server", {method: "GET"});
|
||||
}
|
||||
|
||||
// Component 2/4
|
||||
|
@ -525,7 +525,7 @@ export async function HandleAuthorization(Website) {
|
|||
// Declare Variables
|
||||
let KeyPair = await crypto.subtle.generateKey({name: "ECDSA", namedCurve: "P-256"}, true, ["sign", "verify"]);
|
||||
|
||||
let WellKnown = await GetPDSWellKnown();
|
||||
let WellKnown = await GetPDSWellKnown().then((response) => response.json());
|
||||
|
||||
let State = crypto.randomUUID();
|
||||
|
||||
|
@ -551,7 +551,7 @@ export async function HandleAuthorization(Website) {
|
|||
}
|
||||
|
||||
export async function GainTokens() {
|
||||
let WellKnown = await GetPDSWellKnown();
|
||||
let WellKnown = await GetPDSWellKnown().then((response) => response.json());
|
||||
|
||||
// Check to see if something's a miss...
|
||||
if ((document.location.href.split("state=").length > 1 && document.location.href.split("iss=").length > 1 && document.location.href.split("code=").length > 1) && localStorage.getItem(Variables.BlueskyPKCEVerifier) != null && localStorage.getItem(Variables.BlueskyAccessToken) == null) {
|
||||
|
@ -562,41 +562,41 @@ export async function GainTokens() {
|
|||
let Var = await localStorage.getItem(Variables.BlueskyPKCEVerifier);
|
||||
let Auth = await AuthRequest(WellKnown.token_endpoint, code, DPoP, Var);
|
||||
// Save the tokens and be done
|
||||
localStorage.setItem(Variables.BlueskyAccessToken, Auth.access_token);
|
||||
localStorage.setItem(Variables.BlueskyRefreshToken, Auth.refresh_token);
|
||||
await localStorage.setItem(Variables.BlueskyAccessToken, Auth.access_token);
|
||||
await localStorage.setItem(Variables.BlueskyRefreshToken, Auth.refresh_token);
|
||||
// That long string just gets the payload
|
||||
// aud = PDS server we are communicating with; sub = user DID
|
||||
localStorage.setItem(Variables.BlueskyPDS, "https://" + KJUR.jws.JWS.readSafeJSONString(b64utoutf8(localStorage.getItem(Variables.BlueskyAccessToken).split(".")[1])).aud.split(":")[2]);
|
||||
localStorage.setItem(Variables.BlueskyDID, KJUR.jws.JWS.readSafeJSONString(b64utoutf8(localStorage.getItem(Variables.BlueskyAccessToken).split(".")[1])).sub);
|
||||
await localStorage.setItem(Variables.BlueskyPDS, "https://" + KJUR.jws.JWS.readSafeJSONString(b64utoutf8(localStorage.getItem(Variables.BlueskyAccessToken).split(".")[1])).aud.split(":")[2]);
|
||||
await localStorage.setItem(Variables.BlueskyDID, KJUR.jws.JWS.readSafeJSONString(b64utoutf8(localStorage.getItem(Variables.BlueskyAccessToken).split(".")[1])).sub);
|
||||
}
|
||||
}
|
||||
|
||||
// Refreshing tokens is an integral part of auth.
|
||||
export async function RefreshTokens() {
|
||||
let WellKnown = await GetPDSWellKnown();
|
||||
let WellKnown = await GetPDSWellKnown().then((response) => response.json());
|
||||
// Fake PAR request to get the nonce.
|
||||
let State = crypto.randomUUID();
|
||||
let PKCEverifier = await CreatePKCECodeVerifier();
|
||||
let PKCEchallenge = await CreatePKCECodeChallenge(PKCEverifier);
|
||||
let PAR = PARrequest(WellKnown.pushed_authorization_request_endpoint, State, PKCEchallenge);
|
||||
let nonce = await PAR.then((response) => response.headers.get("dpop-nonce"));
|
||||
// Save nonce
|
||||
await localStorage.setItem(Variables.BlueskyNonce, nonce);
|
||||
// Create varaibles, be aware of waits because of internet.
|
||||
let DPoP = await ClientDPoPToken("POST", WellKnown.token_endpoint);
|
||||
// Token refresh
|
||||
let Var = await localStorage.getItem(Variables.BlueskyRefreshToken);
|
||||
let Auth = ReauthRequest(WellKnown.token_endpoint, Var, DPoP);
|
||||
let body = await Auth.then((response) => response.json());
|
||||
let header = await Auth.then((response) => response.headers.get("dpop-nonce"));
|
||||
if (body.hasOwnProperty("error_description") && body.error_description.includes("DPoP nonce mismatch")) {
|
||||
localStorage.setItem(Variables.BlueskyNonce, header);
|
||||
DPoP = await ClientDPoPToken("POST", WellKnown.token_endpoint);
|
||||
body = await ReauthRequest(WellKnown.token_endpoint, Var, DPoP).then((response) => response.json());
|
||||
}
|
||||
let Auth = await ReauthRequest(WellKnown.token_endpoint, Var, DPoP).then((response) => response.json());
|
||||
// Save the tokens and be done
|
||||
localStorage.setItem(Variables.BlueskyAccessToken, body.access_token);
|
||||
localStorage.setItem(Variables.BlueskyRefreshToken, body.refresh_token);
|
||||
await localStorage.setItem(Variables.BlueskyAccessToken, Auth.access_token);
|
||||
await localStorage.setItem(Variables.BlueskyRefreshToken, Auth.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 localStorage.setItem(Variables.BlueskyNonce, header);
|
||||
if (body.message != undefined && body.message.includes("claim timestamp check failed")) {
|
||||
await RefreshTokens();
|
||||
Token = localStorage.getItem(Variables.BlueskyAccessToken);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -93,19 +93,59 @@ export async function GetStatus(ID) {
|
|||
.then((response) => response.json());
|
||||
}
|
||||
|
||||
// Get your own account by verifying your credentials.
|
||||
export async function GetOwnAccount() {
|
||||
if (Token == null || TokenType == null) {
|
||||
return "";
|
||||
}
|
||||
return await fetch(localStorage.getItem(Variables.MastodonWebsite) + "/api/v1/accounts/verify_credentials", {method: "GET", headers: {"Authorization": TokenType + " " + Token}})
|
||||
.then((response) => response.json());
|
||||
}
|
||||
|
||||
// Get your own account blocks.
|
||||
export async function GetOwnAccountBlocks() {
|
||||
if (Token == null || TokenType == null) {
|
||||
return "";
|
||||
}
|
||||
return await fetch(localStorage.getItem(Variables.MastodonWebsite) + "/api/v1/blocks/", {method: "GET", headers: {"Authorization": TokenType + " " + Token}})
|
||||
.then((response) => response.json());
|
||||
}
|
||||
|
||||
// Get another account's statuses.
|
||||
export async function GetAccountStatuses(ID) {
|
||||
if (Token == null || TokenType == null) {
|
||||
return "";
|
||||
}
|
||||
return await fetch(localStorage.getItem(Variables.MastodonWebsite) + "/api/v1/accounts/" + ID + "/statuses", {method: "GET", headers: {"Authorization": TokenType + " " + Token}})
|
||||
.then((response) => response.json());
|
||||
}
|
||||
|
||||
// Get another account.
|
||||
export async function GetAccount(ID) {
|
||||
if (Token == null || TokenType == null) {
|
||||
return "";
|
||||
}
|
||||
return await fetch(localStorage.getItem(Variables.MastodonWebsite) + "/api/v1/accounts/" + ID, {method: "GET", headers: {"Authorization": TokenType + " " + Token}})
|
||||
.then((response) => response.json());
|
||||
}
|
||||
|
||||
// Creators
|
||||
// Make a status
|
||||
export async function CreateStatus(Text, SpoilerText = undefined, Visibility = "public") {
|
||||
export async function CreateStatus(Text, Visibility = "public", SpoilerText = undefined, ReplyID = undefined) {
|
||||
if (Token == null || TokenType == null) {
|
||||
return "";
|
||||
}
|
||||
// Stolen from StackOverflow.
|
||||
Text = Text.replace(/(?:\r|\n|\r\n)/g, '<br>');
|
||||
// Get the correct fetch body.
|
||||
let FetchThing = localStorage.getItem(Variables.MastodonWebsite) + "/api/v1/statuses?status=" + Text + "&visibility=" + Visibility;
|
||||
let FetchThing = localStorage.getItem(Variables.MastodonWebsite) + "/api/v1/statuses?status=" + encodeURIComponent(Text) + "&visibility=" + Visibility;
|
||||
// Content warning stuff.
|
||||
if (SpoilerText != undefined) {
|
||||
FetchThing += "&spoiler_text=" + SpoilerText;
|
||||
}
|
||||
if (ReplyID != undefined) {
|
||||
FetchThing += "&in_reply_to_id=" + ReplyID;
|
||||
}
|
||||
// Send the request.
|
||||
let request = fetch(FetchThing, {method: "POST", headers: {"Authorization": TokenType + " " + Token}});
|
||||
let body = await request.then((response) => response.json());
|
||||
|
@ -114,45 +154,16 @@ export async function CreateStatus(Text, SpoilerText = undefined, Visibility = "
|
|||
if (status == 422) {
|
||||
let matches = body.error.match(/(\d+)/);
|
||||
// Get the correct fetch body.
|
||||
FetchThing = localStorage.getItem(Variables.MastodonWebsite) + "/api/v1/statuses?status=" + Text.slice(0, matches[0] - 1) + "&visibility=" + Visibility
|
||||
FetchThing = localStorage.getItem(Variables.MastodonWebsite) + "/api/v1/statuses?status=" + encodeURIComponent(Text.slice(0, matches[0] - 1)) + "&visibility=" + Visibility
|
||||
if (SpoilerText != undefined) {
|
||||
FetchThing += "&spoiler_text=" + SpoilerText;
|
||||
}
|
||||
// Send the request.
|
||||
request = fetch(FetchThing, {method: "POST", headers: {"Authorization": TokenType + " " + Token}});
|
||||
request = fetch(enFetchThing, {method: "POST", headers: {"Authorization": TokenType + " " + Token}});
|
||||
body = await request.then((response) => response.json());
|
||||
await CreateReplyStatus(Text.slice(matches[0] - 1, SpoilerText, Text.length - 1), Visibility, body.id);
|
||||
}
|
||||
return body;
|
||||
}
|
||||
|
||||
export async function CreateReplyStatus(Text, SpoilerText = undefined, Visibility = "public", ReplyID) {
|
||||
if (Token == null || TokenType == null) {
|
||||
return "";
|
||||
}
|
||||
// Stolen from StackOverflow
|
||||
Text = Text.replace(/(?:\r|\n|\r\n)/g, '<br>');
|
||||
// Get the correct fetch body.
|
||||
let FetchThing = localStorage.getItem(Variables.MastodonWebsite) + "/api/v1/statuses?status=" + Text + "&visibility=" + Visibility + "&in_reply_to_id=" + ReplyID;
|
||||
if (SpoilerText != undefined) {
|
||||
FetchThing += "&spoiler_text=" + SpoilerText;
|
||||
}
|
||||
// Send the request.
|
||||
let request = fetch(FetchThing, {method: "POST", headers: {"Authorization": TokenType + " " + Token}});
|
||||
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+)/);
|
||||
// Get the correct fetch body.
|
||||
FetchThing = localStorage.getItem(Variables.MastodonWebsite) + "/api/v1/statuses?status=" + Text.slice(0, matches[0] - 1) + "&visibility=" + Visibility + "&in_reply_to_id=" + ReplyID;
|
||||
if (SpoilerText != undefined) {
|
||||
FetchThing += "&spoiler_text=" + SpoilerText;
|
||||
if (ReplyID != undefined) {
|
||||
await CreateReplyStatus(Text.slice(matches[0] - 1, Text.length), Visibility, SpoilerText, body.id);
|
||||
}
|
||||
// Send the request.
|
||||
request = fetch(FetchThing, {method: "POST", headers: {"Authorization": TokenType + " " + Token}});
|
||||
body = await request.then((response) => response.json());
|
||||
await CreateReplyStatus(Text.slice(matches[0] - 1, Text.length - 1), SpoilerText, Visibility, body.id);
|
||||
}
|
||||
return body;
|
||||
}
|
||||
|
@ -205,7 +216,7 @@ export async function CreateBlock(ID, IsBlocked) {
|
|||
return "";
|
||||
}
|
||||
let request = localStorage.getItem(Variables.MastodonWebsite) + "/api/v1/accounts/" + ID;
|
||||
if (IsReblogged == false) {
|
||||
if (IsBlocked == false) {
|
||||
request += "/block";
|
||||
} else {
|
||||
request += "/unblock";
|
||||
|
|
|
@ -10,15 +10,24 @@ let post = JSON.parse(localStorage.getItem("post"));
|
|||
let AccountName = document.getElementsByClassName("Account")[0];
|
||||
let AccountImage = document.getElementsByClassName("AccountImage")[0];
|
||||
let AccountDescription = document.getElementsByClassName("AccountDescription")[0];
|
||||
|
||||
let AlternateAccountName = document.getElementsByClassName("Account")[1];
|
||||
let AlternateAccountImage = document.getElementsByClassName("AccountImage")[1];
|
||||
let AlternateAccountDescription = document.getElementsByClassName("AccountDescription")[1];
|
||||
|
||||
let FollowButton = document.getElementsByClassName("Follow")[0];
|
||||
let BlockButton = document.getElementsByClassName("Block")[0];
|
||||
|
||||
let AccountPosts = document.getElementsByClassName("Posts")[0];
|
||||
|
||||
// Other vars.
|
||||
let Following = false;
|
||||
let Blocking = false;
|
||||
|
||||
// SPAWN
|
||||
GetAccount();
|
||||
|
||||
// The interaction is given to another function for async.
|
||||
FollowButton.onclick = (event) => {
|
||||
FollowBoop();
|
||||
}
|
||||
|
@ -33,6 +42,7 @@ async function FollowBoop() {
|
|||
SetFollow();
|
||||
}
|
||||
|
||||
// Extra thing for the frontend to say "hey I am the follow meister".
|
||||
function SetFollow() {
|
||||
Following = !(Following);
|
||||
if (Following == true) {
|
||||
|
@ -42,6 +52,7 @@ function SetFollow() {
|
|||
}
|
||||
}
|
||||
|
||||
// The interaction is given to another function for async.
|
||||
BlockButton.onclick = (event) => {
|
||||
BlockBoop();
|
||||
}
|
||||
|
@ -56,6 +67,7 @@ async function BlockBoop() {
|
|||
SetBlock();
|
||||
}
|
||||
|
||||
// Extra thing for the frontend to say "hey I am the block meister".
|
||||
function SetBlock() {
|
||||
Blocking = !(Blocking);
|
||||
if (Blocking == true) {
|
||||
|
@ -74,20 +86,24 @@ async function GetAccount() {
|
|||
Blocking = !(Relations[0].blocking);
|
||||
SetFollow();
|
||||
SetBlock();
|
||||
// Check for a reblog.
|
||||
if (post.reblog != null) {
|
||||
post = post.reblog;
|
||||
}
|
||||
AccountName.innerHTML = post.account.username;
|
||||
AccountDescription.innerHTML = post.account.note;
|
||||
AccountImage.setAttribute("src", post.account.avatar);
|
||||
// Build the fields
|
||||
let Field = "<div style=\"display: flex; justify-content: center;\">";
|
||||
let Field = "<aside class=\"Trees\">";
|
||||
for (let i of post.account.fields) {
|
||||
Field += "<b class=\"Entry\">" + i.name + "</b><em class=\"Exitry\">" + i.value + "</em>";
|
||||
}
|
||||
Field += "</div>";
|
||||
Field += "</aside>";
|
||||
AccountDescription.innerHTML += Field;
|
||||
// Get their recent posts. Determine if they are cewl or not.
|
||||
let Posts = await MastodonAPI.GetAccountStatuses(post.account.id);
|
||||
for (let i of Posts) {
|
||||
if (i.reblog != null) {
|
||||
i = i.reblog;
|
||||
}
|
||||
AccountPosts.innerHTML += i.content + "<br/><br/>";
|
||||
}
|
||||
} else if (website == "Bluesky") {
|
||||
// Set the relationship follows
|
||||
let thing = await BlueskyAPI.GetRecord(localStorage.getItem(Variables.BlueskyDID), "app.bsky.graph.follow", post.post.author.did);
|
||||
|
@ -108,5 +124,40 @@ async function GetAccount() {
|
|||
AccountName.innerHTML = account.handle;
|
||||
AccountDescription.innerHTML = account.description;
|
||||
AccountImage.setAttribute("src", account.avatar);
|
||||
// Get their recent posts. Determine if they are cewl or not.
|
||||
let Posts = await BlueskyAPI.GetProfileFeed(account.did);
|
||||
console.log(Posts);
|
||||
for (let i of Posts.feed) {
|
||||
AccountPosts.innerHTML += i.post.record.text + "<br/><br/>";
|
||||
}
|
||||
} else {
|
||||
FollowButton.setAttribute("hidden", "");
|
||||
BlockButton.setAttribute("hidden", "");
|
||||
AlternateAccountImage.setAttribute("hidden", false);
|
||||
// This is meant for the regular account. A big ol' you :3
|
||||
let Token = localStorage.getItem(Variables.MastodonAccessToken);
|
||||
if (Token != null) {
|
||||
let MastoProfile = await MastodonAPI.GetOwnAccount();
|
||||
AccountName.innerHTML = MastoProfile.username;
|
||||
AccountDescription.innerHTML = MastoProfile.note;
|
||||
AccountImage.setAttribute("src", MastoProfile.avatar);
|
||||
// Build the fields
|
||||
let Field = "<div style=\"display: flex; justify-content: center;\">";
|
||||
for (let i of MastoProfile.fields) {
|
||||
Field += "<b class=\"Entry\">" + i.name + "</b><em class=\"Exitry\">" + i.value + "</em>";
|
||||
}
|
||||
Field += "</div>";
|
||||
AccountDescription.innerHTML += Field;
|
||||
}
|
||||
Token = localStorage.getItem(Variables.BlueskyAccessToken);
|
||||
if (Token != null) {
|
||||
let BlueProfile = await BlueskyAPI.GetProfile(localStorage.getItem(Variables.BlueskyDID));
|
||||
AlternateAccountImage.setAttribute("width", "20%");
|
||||
AlternateAccountImage.setAttribute("height", "20%");
|
||||
AlternateAccountName.innerHTML = BlueProfile.handle;
|
||||
AlternateAccountDescription.innerHTML = BlueProfile.description;
|
||||
AlternateAccountImage.setAttribute("src", BlueProfile.avatar);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -20,6 +20,9 @@ let GrandParentpost;
|
|||
document.getElementsByClassName("Origin Regular")[0].innerHTML = website;
|
||||
GetPost();
|
||||
|
||||
// Fixes a bug where the interpreter sucks ass.
|
||||
let EmbedCounter = 0;
|
||||
|
||||
// Button stuff
|
||||
Favorite.onclick = (event) => {
|
||||
if (website == "Mastodon") {
|
||||
|
@ -83,20 +86,19 @@ async function SetThreadPost(element, i) {
|
|||
// Functions and things.
|
||||
async function GetPost() {
|
||||
if (website == "Mastodon") {
|
||||
// Check for a reblog.
|
||||
if (post.reblog != null) {
|
||||
document.getElementsByClassName("Handle Regular")[0].innerHTML = post.account.username + " ( R: " + post.reblog + " )";
|
||||
} else {
|
||||
document.getElementsByClassName("Handle Regular")[0].innerHTML = post.account.username;
|
||||
}
|
||||
document.getElementsByClassName("PostText Regular")[0].innerHTML = post.content;
|
||||
// Set the texts. It's opposite because "setting" causes it to switch.
|
||||
post = await MastodonAPI.GetStatus(post.id);
|
||||
FavoriteFlipper = !(post.favourited);
|
||||
BoostFlipper = !(post.reblogged);
|
||||
SetFavorite();
|
||||
SetBoost();
|
||||
// Check for a reblog.
|
||||
if (post.reblog != null) {
|
||||
document.getElementsByClassName("Handle Regular")[0].innerHTML = post.reblog.account.username + " ( R: " + post.account.username + " )";
|
||||
post = post.reblog;
|
||||
} else {
|
||||
document.getElementsByClassName("Handle Regular")[0].innerHTML = post.account.username;
|
||||
}
|
||||
document.getElementsByClassName("PostText Regular")[0].innerHTML = post.content;
|
||||
// Show the image if it exists.
|
||||
if (post.media_attachments.length != 0) {
|
||||
for (let i of post.media_attachments) {
|
||||
|
@ -105,10 +107,10 @@ async function GetPost() {
|
|||
}
|
||||
// Now time to see if there are any parents
|
||||
if (post.in_reply_to_id != null) {
|
||||
let ParentPost = await MastodonReplylFunction("Parent", post.in_reply_to_id);
|
||||
Parentpost = await MastodonReplylFunction("Parent", post.in_reply_to_id);
|
||||
// Now time to see if there are any grandparents
|
||||
if (ParentPost == undefined && ParentPost.in_reply_to_id != null) {
|
||||
MastodonReplylFunction("GrandParent", ParentPost.in_reply_to_id);
|
||||
if (Parentpost != undefined && Parentpost.in_reply_to_id != null) {
|
||||
GrandParentpost = await MastodonReplylFunction("GrandParent", Parentpost.in_reply_to_id);
|
||||
}
|
||||
}
|
||||
} else if (website == "Bluesky") {
|
||||
|
@ -144,7 +146,7 @@ async function GetPost() {
|
|||
Parentpost = await BlueskyReplyFunction("Parent", post.reply.parent, post.reply.parent.author);
|
||||
// Now time to see if there are any grandparents.
|
||||
if (Parentpost.value.hasOwnProperty("reply")) {
|
||||
GrandParentpost = await BlueskyReplyFunction("Parent", Parentpost.value.reply.parent, post.reply.grandparentAuthor);
|
||||
GrandParentpost = await BlueskyReplyFunction("GrandParent", Parentpost.value.reply.parent, post.reply.grandparentAuthor);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
@ -213,8 +215,8 @@ async function ApplyMedia(Media, Element, Author = undefined) {
|
|||
// 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);
|
||||
let Texty = await BlueskyAPI.GetPosts([Media.record.record.uri]);
|
||||
let 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.
|
||||
|
@ -223,8 +225,8 @@ async function ApplyMedia(Media, Element, Author = undefined) {
|
|||
}
|
||||
// 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);
|
||||
let Texty = await BlueskyAPI.GetPosts([Media.record.uri]);
|
||||
let 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") {
|
||||
|
@ -234,6 +236,7 @@ async function ApplyMedia(Media, Element, Author = undefined) {
|
|||
} else if (Media.$type == "app.bsky.embed.images" || Media.$type == "app.bsky.embed.video") {
|
||||
await BlueskyBlobEmbed(Media, Element, Author);
|
||||
}
|
||||
EmbedCounter = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -241,15 +244,22 @@ async function ApplyMedia(Media, Element, Author = undefined) {
|
|||
async function BlueskyBlobEmbed(Blob, Element, Author) {
|
||||
if (Blob.$type == "app.bsky.embed.images") {
|
||||
for (let i of Blob.images) {
|
||||
Element.innerHTML += "<img src=\"\" alt=\"\"/>";
|
||||
var Blobby = await BlueskyAPI.GetBlob(Author, i.image.ref.$link);
|
||||
var ObjectURL = URL.createObjectURL(Blobby);
|
||||
Element.innerHTML += "<img src=" + ObjectURL + " alt=\"" + EscapeRegExp(i.alt) + "\"/>";
|
||||
let TempElement = Element.getElementsByTagName("img")[EmbedCounter];
|
||||
EmbedCounter += 1;
|
||||
TempElement.setAttribute("src", ObjectURL);
|
||||
TempElement.setAttribute("alt", EscapeRegExp(i.alt));
|
||||
}
|
||||
// Video embed.
|
||||
} else if (Blob.$type == "app.bsky.embed.video") {
|
||||
Element.innerHTML += "<video controls src=\"\">Loading...</video>";
|
||||
Element = Element.getElementsByTagName("video")[0];
|
||||
var Blobby = await BlueskyAPI.GetBlob(Author, Blob.video.ref.$link);
|
||||
var ObjectURL = URL.createObjectURL(Blobby);
|
||||
Element.innerHTML += "<video controls src=" + ObjectURL + "></video>";
|
||||
Element.setAttribute("src", ObjectURL);
|
||||
Element.innerHTML = "";
|
||||
}
|
||||
}
|
||||
|
||||
|
|
31
JS/index.js
31
JS/index.js
|
@ -19,6 +19,7 @@ let SettingButton = document.getElementsByClassName("Setting")[0];
|
|||
let MailButton = document.getElementsByClassName("Mail")[0];
|
||||
let PostingButton = document.getElementsByClassName("Posting")[0];
|
||||
let FeedButton = document.getElementsByClassName("Feed")[0];
|
||||
let TimeAccountButton = document.getElementsByClassName("Time")[0];
|
||||
|
||||
// Sounds
|
||||
const ButtonSound = new Audio("Audio/button-305770.mp3");
|
||||
|
@ -205,9 +206,6 @@ async function PosterContainerUpdate(Direction) {
|
|||
if (Mastodon == false) {
|
||||
countergroup = countergroup + 1;
|
||||
}
|
||||
if (Bluesky == false) {
|
||||
countergroup = countergroup + 1;
|
||||
}
|
||||
// This var is meant to stop "already seen" posts.
|
||||
let BlueskyPostsDup = [];
|
||||
WebsiteAPIType = [];
|
||||
|
@ -218,23 +216,26 @@ async function PosterContainerUpdate(Direction) {
|
|||
// Begin by having the website we are using get pushed to the expanded view array and clean out the HTML.
|
||||
WebsiteAPIType.push("Mastodon");
|
||||
i.getElementsByClassName("PostContent")[0].innerHTML = "";
|
||||
if (MastodonLoadedFeed[CurrentThing + counter] == undefined) {
|
||||
if (MastodonLoadedFeed[CurrentThing + counter + 1] == undefined) {
|
||||
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);
|
||||
TempFeed = await MastodonAPI.GetPublicTimeline(true, true, localStorage.getItem(Variables.MastodonWebsite), MastodonLoadedFeed[CurrentThing + counter].id);
|
||||
} else {
|
||||
TempFeed = await MastodonAPI.GetPublicTimeline(true, false, localStorage.getItem(Variables.MastodonWebsite), MastodonLoadedFeed[CurrentThing + counter - 1].id);
|
||||
TempFeed = await MastodonAPI.GetPublicTimeline(true, false, localStorage.getItem(Variables.MastodonWebsite), MastodonLoadedFeed[CurrentThing + counter].id);
|
||||
}
|
||||
} else {
|
||||
TempFeed = await MastodonAPI.GetTimeline(MastodonLoadedFeed[CurrentThing + counter - 1].id);
|
||||
TempFeed = await MastodonAPI.GetTimeline(MastodonLoadedFeed[CurrentThing + counter].id);
|
||||
}
|
||||
MastodonLoadedFeed = MastodonLoadedFeed.concat(TempFeed);
|
||||
MastodonLoadedFeed = await MastodonLoadedFeed.concat(TempFeed);
|
||||
}
|
||||
// put the reblog into the regular post; Make changes as necessary.
|
||||
if (MastodonLoadedFeed[CurrentThing + counter].reblog != null) {
|
||||
i.getElementsByClassName("Username")[0].innerHTML = MastodonLoadedFeed[CurrentThing + counter].reblog.account.username + " ( R: " + MastodonLoadedFeed[CurrentThing + counter].account.username + " )";
|
||||
// Fix a reblog issue.
|
||||
let ReblogFix = MastodonLoadedFeed[CurrentThing + counter].account.username;
|
||||
MastodonLoadedFeed[CurrentThing + counter] = MastodonLoadedFeed[CurrentThing + counter].reblog;
|
||||
MastodonLoadedFeed[CurrentThing + counter].reblog = ReblogFix;
|
||||
} else {
|
||||
i.getElementsByClassName("Username")[0].innerHTML = MastodonLoadedFeed[CurrentThing + counter].account.username
|
||||
}
|
||||
|
@ -263,14 +264,14 @@ async function PosterContainerUpdate(Direction) {
|
|||
// Begin by having the website we are using get pushed to the expanded view array and clean out the HTML.
|
||||
WebsiteAPIType.push("Bluesky");
|
||||
i.getElementsByClassName("PostContent")[0].innerHTML = "";
|
||||
if (BlueskyLoadedFeed[CurrentThing + counter] == undefined) {
|
||||
if (BlueskyLoadedFeed[CurrentThing + counter + 1] == undefined) {
|
||||
let TempFeed;
|
||||
if (Discover == true) {
|
||||
BlueskyLoadedFeed = await BlueskyAPI.GetPublicTimeline(BlueskyLoadedFeed[CurrentThing + counter - 1].post.indexedAt).then((response) => response.feed);
|
||||
BlueskyLoadedFeed = await BlueskyAPI.GetPublicTimeline(BlueskyLoadedFeed[CurrentThing + counter].post.indexedAt).then((response) => response.feed);
|
||||
} else {
|
||||
TempFeed = await BlueskyAPI.GetTimeline(BlueskyLoadedFeed[CurrentThing + counter - 1].post.indexedAt).then((response) => response.feed);
|
||||
TempFeed = await BlueskyAPI.GetTimeline(BlueskyLoadedFeed[CurrentThing + counter].post.indexedAt).then((response) => response.feed);
|
||||
}
|
||||
BlueskyLoadedFeed = BlueskyLoadedFeed.concat(TempFeed);
|
||||
BlueskyLoadedFeed = await BlueskyLoadedFeed.concat(TempFeed);
|
||||
}
|
||||
// check for "already seen" posts, then put it as a seen post.
|
||||
BlueskyLoadedFeed = CheckForDups(BlueskyLoadedFeed, BlueskyPostsDup, counter);
|
||||
|
@ -343,6 +344,12 @@ MailButton.onclick = (event) => {
|
|||
window.location.href = "./HTML/mail.html";
|
||||
}
|
||||
|
||||
// A quick way of opening the account.
|
||||
// In theory, this should be in another "channel" or the mail area, but those areas are crowded.
|
||||
TimeAccountButton.onclick = (event) => {
|
||||
window.location.href = "./HTML/account.html";
|
||||
}
|
||||
|
||||
// Open the posting area.
|
||||
PostingButton.onclick = (event) => {
|
||||
window.location.href = "./HTML/post.html";
|
||||
|
|
52
JS/post.js
52
JS/post.js
|
@ -9,6 +9,7 @@ let VisibilityDropdown = document.getElementsByClassName("PostVisibility")[0];
|
|||
let InputArea = document.getElementsByClassName("Text")[0];
|
||||
let YoutubePoser = document.getElementsByClassName("PostYoutube")[0];
|
||||
let WarningInputArea = document.getElementsByClassName("Warning")[0];
|
||||
let TagsInputArea = document.getElementsByClassName("Tags")[0];
|
||||
|
||||
// Clicking the beeg POST button.
|
||||
PostButton.onclick = (event) => {
|
||||
|
@ -32,6 +33,21 @@ async function Post() {
|
|||
// Mastodon posting.
|
||||
if (localStorage.getItem(Variables.MastodonAccessToken) != null) {
|
||||
let TempVisible;
|
||||
// Adding tags
|
||||
let TempText = Text;
|
||||
let Tags = TagsInputArea.value.split(";");
|
||||
if (Tags.length > 1) {
|
||||
TempText += "<br/><br/>";
|
||||
}
|
||||
for (let i of Tags) {
|
||||
while (i[0] == " ") {
|
||||
i = i.substring(1, i.length);
|
||||
}
|
||||
if (i[0] != "#" && i.length != 0) {
|
||||
i = "#" + i;
|
||||
}
|
||||
TempText += i + " ";
|
||||
}
|
||||
switch(Visible) {
|
||||
case "Public":
|
||||
TempVisible = "public";
|
||||
|
@ -48,24 +64,38 @@ async function Post() {
|
|||
}
|
||||
if (website == "Mastodon") {
|
||||
if (WarningInputArea.value == "") {
|
||||
await MastodonAPI.CreateReplyStatus(Text, undefined, TempVisible, JSON.parse(localStorage.getItem("post")).id);
|
||||
await MastodonAPI.CreateStatus(TempText, TempVisible, undefined, JSON.parse(localStorage.getItem("post")).id);
|
||||
} else {
|
||||
await MastodonAPI.CreateReplyStatus(Text, WarningInputArea.value, TempVisible, JSON.parse(localStorage.getItem("post")).id);
|
||||
await MastodonAPI.CreateStatus(TempText, TempVisible, WarningInputArea.value, JSON.parse(localStorage.getItem("post")).id);
|
||||
}
|
||||
InputArea.value = "";
|
||||
WarningInputArea.value = "";
|
||||
TagsInputArea.value = "";
|
||||
return;
|
||||
} else if (website == "All") {
|
||||
if (WarningInputArea.value == "") {
|
||||
await MastodonAPI.CreateStatus(Text, undefined, TempVisible);
|
||||
await MastodonAPI.CreateStatus(TempText, TempVisible, undefined);
|
||||
} else {
|
||||
await MastodonAPI.CreateStatus(Text, WarningInputArea.value, TempVisible);
|
||||
await MastodonAPI.CreateStatus(TempText, TempVisible, WarningInputArea.value);
|
||||
}
|
||||
}
|
||||
}
|
||||
// Bluesky posting.
|
||||
if (localStorage.getItem(Variables.BlueskyAccessToken) != null) {
|
||||
let TempVisible;
|
||||
// Adding tags
|
||||
let Tags = TagsInputArea.value.split(";");
|
||||
let TagsTemp = [];
|
||||
for (let i of Tags) {
|
||||
while (i[0] == " ") {
|
||||
i = i.substring(1, i.length);
|
||||
}
|
||||
if (i[0] != "#" && i.length != 0) {
|
||||
i = "#" + i;
|
||||
}
|
||||
TagsTemp.push(i);
|
||||
}
|
||||
Tags = TagsTemp;
|
||||
switch(Visible) {
|
||||
case "Public":
|
||||
TempVisible = undefined;
|
||||
|
@ -84,28 +114,29 @@ async function Post() {
|
|||
let Post;
|
||||
if (JSON.parse(localStorage.getItem("post")).hasOwnProperty("reply")) {
|
||||
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);
|
||||
Post = await BlueskyAPI.CreatePost(localStorage.getItem(Variables.BlueskyDID), Text, undefined, Tags, 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);
|
||||
Post = await BlueskyAPI.CreatePost(localStorage.getItem(Variables.BlueskyDID), Text, WarningInputArea.value, Tags, JSON.parse(localStorage.getItem("post")).post, JSON.parse(localStorage.getItem("post")).reply.root);
|
||||
}
|
||||
await BlueskyAPI.CreateThreadGate(localStorage.getItem(Variables.BlueskyDID), Post.uri, TempVisible);
|
||||
} else {
|
||||
if (WarningInputArea.value == "") {
|
||||
Post = await BlueskyAPI.CreateReplyPost(localStorage.getItem(Variables.BlueskyDID), Text, JSON.parse(localStorage.getItem("post")).post, JSON.parse(localStorage.getItem("post")).post);
|
||||
Post = await BlueskyAPI.CreatePost(localStorage.getItem(Variables.BlueskyDID), Text, undefined, Tags, 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);
|
||||
Post = await BlueskyAPI.CreatePost(localStorage.getItem(Variables.BlueskyDID), Text, WarningInputArea.value, Tags, JSON.parse(localStorage.getItem("post")).post, JSON.parse(localStorage.getItem("post")).post);
|
||||
}
|
||||
await BlueskyAPI.CreateThreadGate(localStorage.getItem(Variables.BlueskyDID), Post.uri, TempVisible);
|
||||
}
|
||||
InputArea.value = "";
|
||||
WarningInputArea.value = "";
|
||||
TagsInputArea.value = "";
|
||||
return;
|
||||
} else if (website == "All") {
|
||||
let Post;
|
||||
if (WarningInputArea.value == "") {
|
||||
Post = await BlueskyAPI.CreatePost(localStorage.getItem(Variables.BlueskyDID), Text);
|
||||
Post = await BlueskyAPI.CreatePost(localStorage.getItem(Variables.BlueskyDID), Text, undefined, Tags);
|
||||
} else {
|
||||
Post = await BlueskyAPI.CreatePost(localStorage.getItem(Variables.BlueskyDID), Text, WarningInputArea.value);
|
||||
Post = await BlueskyAPI.CreatePost(localStorage.getItem(Variables.BlueskyDID), Text, WarningInputArea.value, Tags);
|
||||
}
|
||||
await BlueskyAPI.CreateThreadGate(localStorage.getItem(Variables.BlueskyDID), Post.uri, TempVisible);
|
||||
}
|
||||
|
@ -118,6 +149,7 @@ async function Post() {
|
|||
// The input being cleared means that the posting happened.
|
||||
InputArea.value = "";
|
||||
WarningInputArea.value = "";
|
||||
TagsInputArea.value = "";
|
||||
}
|
||||
|
||||
// Check if you can interact with the textbox
|
||||
|
|
Loading…
Add table
Reference in a new issue