diff --git a/HTML/post.html b/HTML/post.html index 3ab1a55..44a3b83 100644 --- a/HTML/post.html +++ b/HTML/post.html @@ -13,9 +13,17 @@

Post

- -

POST!

+ +
+ +
+

POST!

Back

diff --git a/HTML/setting.html b/HTML/setting.html index e3ff4a9..4e71edd 100644 --- a/HTML/setting.html +++ b/HTML/setting.html @@ -17,10 +17,10 @@

Toggle Local

Toggle Remote

Login to Mastodon

- +

Login to Bluesky

- +

Back

diff --git a/JS/BlueskyAPI.js b/JS/BlueskyAPI.js index 1265857..c5ce038 100644 --- a/JS/BlueskyAPI.js +++ b/JS/BlueskyAPI.js @@ -1,24 +1,7 @@ -import * as Cookie from "./Cookies.js"; +import * as Variables from "./Variables.js"; -export async function GetBlueskyDID(PDS, Handle) { - let DPoP = await ClientDPoPPDS("GET", PDS + "/xrpc/com.atproto.identity.resolveHandle?handle=" + Handle); - let request = fetch(PDS + "/xrpc/com.atproto.identity.resolveHandle?handle=" + Handle, { method: "GET", headers: {"Authorization": "DPoP " + Cookie.GetCookie(Cookie.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) { - if (body.message.includes("DPoP nonce mismatch")) { - await Cookie.InputCookie(Cookie.BlueskyNonce, header); - } - if (body.message.includes("claim timestamp check failed")) { - await RefreshTokens(); - } - body = await GetBlueskyDID(PDS, Handle); - } - return body; -} - -export async function CreatePost(PDS, DID, Text) { +export async function CreatePost(DID, Text) { + let PDS = localStorage.getItem(Variables.BlueskyPDS); let Json = { "$type": "app.bsky.feed.post", "text": Text, @@ -30,18 +13,49 @@ export async function CreatePost(PDS, DID, Text) { "record": Json } let DPoP = await ClientDPoPPDS("POST", PDS + "/xrpc/com.atproto.repo.createRecord"); - let request = fetch(PDS + "/xrpc/com.atproto.repo.createRecord", { body: JSON.stringify(RequestBody), method: "POST", headers: {"Content-Type": "application/json", "Authorization": "DPoP " + Cookie.GetCookie(Cookie.BlueskyAccessToken), "DPoP": DPoP}}); + let request = fetch(PDS + "/xrpc/com.atproto.repo.createRecord", { body: JSON.stringify(RequestBody), method: "POST", headers: {"Content-Type": "application/json", "Authorization": "DPoP " + localStorage.getItem(Variables.BlueskyAccessToken), "DPoP": DPoP}}); let body = await request.then((response) => response.json()); let status = await request.then((response) => response.status); let header = await request.then((response) => response.headers.get("dpop-nonce")); if (status == 401) { if (body.message.includes("DPoP nonce mismatch")) { - await Cookie.InputCookie(Cookie.BlueskyNonce, header); + await localStorage.setItem(Variables.BlueskyNonce, header); } if (body.message.includes("claim timestamp check failed")) { await RefreshTokens(); } - body = await CreatePost(PDS, DID, Text); + body = await CreatePost(DID, Text); + } + return body; +} + +export async function SetThreadGate(DID, Post, VisibilitySettings) { + let PDS = localStorage.getItem(Variables.BlueskyPDS); + let Json = { + "$type": "app.bsky.feed.threadgate", + "post": Post, + "allow": VisibilitySettings, + "createdAt": new Date(Date.now()).toISOString() + } + let RequestBody = { + "repo": DID, + "collection": "app.bsky.feed.threadgate", + "record": Json, + "rkey": Post.split("/")[Post.split("/").length - 1] + } + let DPoP = await ClientDPoPPDS("POST", PDS + "/xrpc/com.atproto.repo.createRecord"); + let request = fetch(PDS + "/xrpc/com.atproto.repo.createRecord", { body: JSON.stringify(RequestBody), method: "POST", headers: {"Content-Type": "application/json", "Authorization": "DPoP " + localStorage.getItem(Variables.BlueskyAccessToken), "DPoP": DPoP}}); + let body = await request.then((response) => response.json()); + let status = await request.then((response) => response.status); + let header = await request.then((response) => response.headers.get("dpop-nonce")); + if (status == 401) { + if (body.message.includes("DPoP nonce mismatch")) { + await localStorage.setItem(Variables.BlueskyNonce, header); + } + if (body.message.includes("claim timestamp check failed")) { + await RefreshTokens(); + } + body = await SetThreadGate(DID, Post, VisibilitySettings); } return body; } @@ -91,8 +105,8 @@ async function ReauthRequest(TokenEndpoint, Token, DPoP) { // Component 4/4 export async function ClientDPoPToken(POSTorGET, RequestURL) { - let PublicKey = await crypto.subtle.importKey("jwk", JSON.parse(Cookie.GetCookie(Cookie.BlueskyPublicKey)), {name: "ECDSA", namedCurve: "P-256"}, true, ["verify"]); - let PrivateKey = await crypto.subtle.importKey("jwk", JSON.parse(Cookie.GetCookie(Cookie.BlueskyPrivateKey)), {name: "ECDSA", namedCurve: "P-256"}, true, ["sign"]); + let PublicKey = await crypto.subtle.importKey("jwk", JSON.parse(localStorage.getItem(Variables.BlueskyPublicKey)), {name: "ECDSA", namedCurve: "P-256"}, true, ["verify"]); + 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: @@ -110,7 +124,7 @@ export async function ClientDPoPToken(POSTorGET, RequestURL) { Payload.htm = POSTorGET; Payload.htu = RequestURL; Payload.iat = Math.floor(new Date(Date.now()).getTime() / 1000); - Payload.nonce = Cookie.GetCookie(Cookie.BlueskyNonce); + Payload.nonce = localStorage.getItem(Variables.BlueskyNonce); var sHeader = JSON.stringify(Header); var sPayload = JSON.stringify(Payload); @@ -126,8 +140,8 @@ export async function ClientDPoPToken(POSTorGET, RequestURL) { } export async function ClientDPoPPDS(POSTorGET, RequestURL) { - let PublicKey = await crypto.subtle.importKey("jwk", JSON.parse(Cookie.GetCookie(Cookie.BlueskyPublicKey)), {name: "ECDSA", namedCurve: "P-256"}, true, ["verify"]); - let PrivateKey = await crypto.subtle.importKey("jwk", JSON.parse(Cookie.GetCookie(Cookie.BlueskyPrivateKey)), {name: "ECDSA", namedCurve: "P-256"}, true, ["sign"]); + let PublicKey = await crypto.subtle.importKey("jwk", JSON.parse(localStorage.getItem(Variables.BlueskyPublicKey)), {name: "ECDSA", namedCurve: "P-256"}, true, ["verify"]); + 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: @@ -145,8 +159,8 @@ export async function ClientDPoPPDS(POSTorGET, RequestURL) { Payload.htm = POSTorGET; Payload.htu = RequestURL; Payload.iat = Math.floor(new Date(Date.now()).getTime() / 1000); - Payload.nonce = Cookie.GetCookie(Cookie.BlueskyNonce); - Payload.ath = await CreatePKCECodeChallenge(Cookie.GetCookie(Cookie.BlueskyAccessToken)); + Payload.nonce = localStorage.getItem(Variables.BlueskyNonce); + Payload.ath = await CreatePKCECodeChallenge(localStorage.getItem(Variables.BlueskyAccessToken)); var sHeader = JSON.stringify(Header); var sPayload = JSON.stringify(Payload); @@ -161,7 +175,13 @@ export async function ClientDPoPPDS(POSTorGET, RequestURL) { return JWT; } -export async function HandleAuthorization() { +export async function HandleAuthorization(Website) { + // Quickly check to see if it has something before :// so it doesn't screw the link. + if (Website.toLowerCase().split("://").length > 1) { + Website = "https://" + Website.split("://")[1]; + } else { + Website = "https://" + Website; + } // Declare Variables let KeyPair = await crypto.subtle.generateKey({name: "ECDSA", namedCurve: "P-256"}, true, ["sign", "verify"]); @@ -172,38 +192,42 @@ export async function HandleAuthorization() { let PKCEverifier = await CreatePKCECodeVerifier(); let PKCEchallenge = await CreatePKCECodeChallenge(PKCEverifier); // Save these - Cookie.InputCookie(Cookie.BlueskyPKCEVerifier, PKCEverifier); - Cookie.InputCookie(Cookie.BlueskyPKCEChallenge, PKCEchallenge); + localStorage.setItem(Variables.BlueskyPKCEVerifier, PKCEverifier); + localStorage.setItem(Variables.BlueskyPKCEChallenge, PKCEchallenge); // PAR request (beginning) let PAR = PARrequest(WellKnown.pushed_authorization_request_endpoint, State, PKCEchallenge); let body = await PAR.then((response) => response.json()); let nonce = await PAR.then((response) => response.headers.get("dpop-nonce")); // Save nonce - Cookie.InputCookie(Cookie.BlueskyNonce, nonce); + localStorage.setItem(Variables.BlueskyNonce, nonce); // Export keys let ExportedKey1 = await crypto.subtle.exportKey("jwk", KeyPair.publicKey); let ExportedKey2 = await crypto.subtle.exportKey("jwk", KeyPair.privateKey); // Convert them into a good format. - Cookie.InputCookie(Cookie.BlueskyPublicKey, JSON.stringify(ExportedKey1)); - Cookie.InputCookie(Cookie.BlueskyPrivateKey, JSON.stringify(ExportedKey2)); + localStorage.setItem(Variables.BlueskyPublicKey, JSON.stringify(ExportedKey1)); + localStorage.setItem(Variables.BlueskyPrivateKey, JSON.stringify(ExportedKey2)); // Now we need to authenticate. Make sure the State stays the same throughout this whole process :] - document.location.href = "https://bsky.social/oauth/authorize?client_id=https://fedi.crowdedgames.group/oauth/client-metadata.json&request_uri=" + body.request_uri; + document.location.href = Website + "/oauth/authorize?client_id=https://fedi.crowdedgames.group/oauth/client-metadata.json&request_uri=" + body.request_uri; } export async function GainTokens() { let WellKnown = await GetPDSWellKnown(); // 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) && Cookie.IsCookieReal(Cookie.BlueskyPKCEVerifier) && !(Cookie.IsCookieReal(Cookie.BlueskyAccessToken))) { + 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) { // Create varaibles, be aware of waits because of internet. let DPoP = await ClientDPoPToken("POST", WellKnown.token_endpoint); let code = document.location.href.split("code=")[1]; // Authentication - let cookie = await Cookie.GetCookie(Cookie.BlueskyPKCEVerifier); - let Auth = await AuthRequest(WellKnown.token_endpoint, code, DPoP, cookie); + let Var = await localStorage.getItem(Variables.BlueskyPKCEVerifier); + let Auth = await AuthRequest(WellKnown.token_endpoint, code, DPoP, Var); // Save the tokens and be done - Cookie.InputCookie(Cookie.BlueskyAccessToken, Auth.access_token); - Cookie.InputCookie(Cookie.BlueskyRefreshToken, Auth.refresh_token); + localStorage.setItem(Variables.BlueskyAccessToken, Auth.access_token); + 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); } } @@ -213,18 +237,18 @@ export async function RefreshTokens() { // Create varaibles, be aware of waits because of internet. let DPoP = await ClientDPoPToken("POST", WellKnown.token_endpoint); // Token refresh - let cookie = await Cookie.GetCookie(Cookie.BlueskyRefreshToken); - let Auth = ReauthRequest(WellKnown.token_endpoint, cookie, DPoP); + 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")) { - await Cookie.InputCookie(Cookie.BlueskyNonce, header); + localStorage.setItem(Variables.BlueskyNonce, header); DPoP = await ClientDPoPToken("POST", WellKnown.token_endpoint); - let body = await ReauthRequest(WellKnown.token_endpoint, cookie, DPoP).then((response) => response.json()); + body = await ReauthRequest(WellKnown.token_endpoint, Var, DPoP).then((response) => response.json()); } // Save the tokens and be done - Cookie.InputCookie(Cookie.BlueskyAccessToken, body.access_token); - Cookie.InputCookie(Cookie.BlueskyRefreshToken, body.refresh_token); + localStorage.setItem(Variables.BlueskyAccessToken, body.access_token); + localStorage.setItem(Variables.BlueskyRefreshToken, body.refresh_token); } // Stolen from elsewhere. diff --git a/JS/Cookies.js b/JS/Cookies.js deleted file mode 100644 index 467c5f0..0000000 --- a/JS/Cookies.js +++ /dev/null @@ -1,65 +0,0 @@ -// STRINGS TODO: make sure to seperate stuff that a user will want to input: BlueskyAppName, BlueskyPDSName. -// Mastodon -export const MastodonWebsite = "mastodon_website"; -export const MastodonClientID = "mastodon_client_id"; -export const MastodonClientSecret = "mastodon_client_secret"; -export const MastodonAccessToken = "mastodon_access_token"; -export const MastodonTokenType = "mastodon_token_type"; - -// Bluesky -export const BlueskyApp = "https://bsky.app"; -export const BlueskyPDS = "https://bsky.social"; -export const BlueskyPKCEVerifier = "bluesky_pkce_verifier"; -export const BlueskyPKCEChallenge = "bluesky_pkce_challenge"; -export const BlueskyPublicKey = "bluesky_public_key"; -export const BlueskyPrivateKey = "bluesky_private_key"; -export const BlueskyNonce = "bluesky_nonce"; -export const BlueskyAccessToken = "bluesky_access_token"; -export const BlueskyRefreshToken = "bluesky_refresh_token"; - -// Tumblr -export const TumblrWebsiteName = "https://www.tumblr.com"; - -// FUNCTIONS -// Get the cookie from cookie storage. -export function GetCookie(CookieName = "") { - // Check if you put in nothing. - if (CookieName == 0) { - console.error("Where is the cookie name? Returning nothing..."); - return ""; - } - // Get the cookie. - let Cookie = document.cookie.split("; ").find((row) => row.startsWith(CookieName + "="))?.split("="); - // If the cookie doesn't exist... - if (Cookie == undefined || Cookie.length == 1) { - console.log("Cookie not found. Returning nothing..."); - return ""; - } else { - return Cookie[1]; - } -} - -// Check if a cookie is real (as in the value isn't nonexistant). -export function IsCookieReal(CookieName = "") { - let Cookie = GetCookie(CookieName); - if (Cookie.length == 0) { - return false; - } - return true; -} - -// Remove the cookie. -export function ExpireCookie(CookieName = "") { - document.cookie = CookieName + "=nothing;samesite=strict;path=/;expires=Thu, 01 Jan 1970 00:00:00 GMT;"; - return; -} - -// Add a new cookie (or change it's value). -export function InputCookie(CookieName = "", Value = "") { - if (Value == 0 || CookieName == 0) { - console.error("You forgot to put in a value. Stopping..."); - return; - } - document.cookie = CookieName + "=" + Value + ";samesite=strict;path=/;expires=Fri, 31 Dec 9999 23:59:59 GMT;" - return; -} diff --git a/JS/MastodonAPI.js b/JS/MastodonAPI.js index 91ea634..d5701fa 100644 --- a/JS/MastodonAPI.js +++ b/JS/MastodonAPI.js @@ -1,10 +1,10 @@ -import * as Cookie from "./Cookies.js"; +import * as Variables from "./Variables.js"; export const Scopes = "read write follow push"; // Gets the public timeline. export async function GetPublicTimeline(Local = false, Remote = false, Website) { - // Cookies can be found in `setting.js` + // 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."); @@ -28,10 +28,10 @@ export async function GetPublicTimeline(Local = false, Remote = false, Website) export async function GetFavorites() { let Favorites; // Check for a token. - if (Cookie.IsCookieReal(Cookie.MastodonAccessToken)) { - let Website = Cookie.MastodonWebsite; - // Get the varaibles that are stored in cookies. - Favorites = await fetch(Website + "/api/v1/favourites", {method: "GET", headers: {"Authorization": Cookie.GetCookie(Cookie.MastodonTokenType) + " " + Cookie.GetCookie(Cookie.MastodonAccessToken)}}) + if (localStorage.getItem(Variables.MastodonAccessToken) != null) { + let Website = Variables.MastodonWebsite; + // Get the varaibles that are stored in localStorage. + Favorites = await fetch(Website + "/api/v1/favourites", {method: "GET", headers: {"Authorization": localStorage.getItem(Variables.MastodonTokenType) + " " + localStorage.getItem(Variables.MastodonAccessToken)}}) .then((response) => response.json()); } return Favorites; @@ -41,10 +41,10 @@ export async function GetFavorites() { export async function GetBookmarks() { let Bookmarks; // Check for a token. - if (Cookie.IsCookieReal(Cookie.MastodonAccessToken)) { - let Website = Cookie.GetCookie(Cookie.MastodonWebsite); - // Get the varaibles that are stored in cookies. - Bookmarks = await fetch(Website + "/api/v1/bookmarks", {method: "GET", headers: {"Authorization": Cookie.GetCookie(Cookie.MastodonTokenType) + " " + Cookie.GetCookie(Cookie.MastodonAccessToken)}}) + if (localStorage.getItem(Variables.MastodonAccessToken) != null) { + let Website = localStorage.getItem(Variables.MastodonWebsite); + // Get the varaibles that are stored in Variables. + Bookmarks = await fetch(Website + "/api/v1/bookmarks", {method: "GET", headers: {"Authorization": localStorage.getItem(Variables.MastodonTokenType) + " " + localStorage.getItem(Variables.MastodonAccessToken)}}) .then((response) => response.json()); } return Bookmarks; @@ -54,21 +54,23 @@ export async function GetBookmarks() { export async function GetNotifications() { let Notifications; // Check for a token. - if (Cookie.IsCookieReal(Cookie.MastodonAccessToken)) { - let Website = Cookie.GetCookie(Cookie.MastodonWebsite); - // Get the varaibles that are stored in cookies and then input it. - Notifications = await fetch(Website + "/api/v1/notifications", {method: "GET", headers: {"Authorization": Cookie.GetCookie(Cookie.MastodonTokenType) + " " + Cookie.GetCookie(Cookie.MastodonAccessToken)}}) + if (localStorage.getItem(Variables.MastodonAccessToken) != null) { + let Website = localStorage.getItem(Variables.MastodonWebsite); + // Get the varaibles that are stored in Variables and then input it. + Notifications = await fetch(Website + "/api/v1/notifications", {method: "GET", headers: {"Authorization": localStorage.getItem(Variables.MastodonTokenType) + " " + localStorage.getItem(Variables.MastodonAccessToken)}}) .then((response) => response.json()); } return Notifications; } // Make a status -export async function CreateStatus(Text) { +export async function CreateStatus(Text, Visibility = "public") { + // Stolen from StackOverflow + Text = Text.replace(/(?:\r|\n|\r\n)/g, '
'); // Check for a token - if (Cookie.IsCookieReal(Cookie.MastodonAccessToken)) { - let Website = Cookie.MastodonWebsiteCookie; - return await fetch(Website + "/api/v1/statuses?status=" + Text , {method: "POST", headers: {"Authorization": Cookie.GetCookie(Cookie.MastodonTokenType) + " " + Cookie.GetCookie(Cookie.MastodonAccessToken)}}) + if (localStorage.getItem(Variables.MastodonAccessToken) != null) { + let Website = localStorage.getItem(Variables.MastodonWebsite); + return await fetch(Website + "/api/v1/statuses?status=" + Text + "&visibility=" + Visibility, {method: "POST", headers: {"Authorization": localStorage.getItem(Variables.MastodonTokenType) + " " + localStorage.getItem(Variables.MastodonAccessToken)}}) .then((response) => response.json()); } } @@ -84,13 +86,13 @@ export async function HandleAuthentication(Website) { Website = "https://" + Website; } // Save the website - Cookie.InputCookie(Cookie.MastodonWebsite, Website); + localStorage.setItem(Variables.MastodonWebsite, Website); // Registering the app. InstanceData = await fetch(Website + "/api/v1/apps?client_name=Channel Viewer&redirect_uris=" + document.location.href + "&scopes=" + Scopes, {method: "POST"}) .then((response) => response.json()); - // Save the client stuff as cookies. - Cookie.InputCookie(Cookie.MastodonClientID, InstanceData.client_id); - Cookie.InputCookie(Cookie.MastodonClientSecret, InstanceData.client_secret); + // Save the client stuff as Variables. + localStorage.setItem(Variables.MastodonClientID, InstanceData.client_id); + localStorage.setItem(Variables.MastodonClientSecret, InstanceData.client_secret); // Now authenticate the app. document.location.href = Website + "/oauth/authorize?client_id=" + InstanceData.client_id + "&redirect_uri=" + document.location.href + "&response_type=code&scope=" + Scopes; } @@ -98,15 +100,15 @@ export async function HandleAuthentication(Website) { // This specific functino goes after HandleAuthentication for when login happens. export async function GainToken() { // check if you both have a code and have a current authentication. - if (document.location.href.split("code=").length > 1 && Cookie.IsCookieReal(Cookie.MastodonClientID) && !(Cookie.IsCookieReal(Cookie.MastodonAccessToken))) { + if (document.location.href.split("code=").length > 1 && localStorage.getItem(Variables.MastodonClientID) != null && localStorage.getItem(Variables.MastodonAccessToken) == null) { // Get some vars. let code = document.location.href.split("code=")[1]; - let Website = Cookie.GetCookie(Cookie.MastodonWebsite); + let Website = localStorage.getItem(Variables.MastodonWebsite); // Authenticate. - let AuthenticationToken = await fetch(Website + "/oauth/token?client_id=" + Cookie.GetCookie(Cookie.MastodonClientID) + "&client_secret=" + Cookie.GetCookie(Cookie.MastodonClientSecret) + "&redirect_uri=" + document.location.href + "&grant_type=authorization_code&code=" + code, {method: "POST"}) + let AuthenticationToken = await fetch(Website + "/oauth/token?client_id=" + localStorage.getItem(Variables.MastodonClientID) + "&client_secret=" + localStorage.getItem(Variables.MastodonClientSecret) + "&redirect_uri=" + document.location.href + "&grant_type=authorization_code&code=" + code, {method: "POST"}) .then((response) => response.json()); // Cookify These. - Cookie.InputCookie(Cookie.MastodonAccessToken, AuthenticationToken.access_token); - Cookie.InputCookie(Cookie.MastodonTokenType, AuthenticationToken.token_type); + localStorage.setItem(Variables.MastodonAccessToken, AuthenticationToken.access_token); + localStorage.setItem(Variables.MastodonTokenType, AuthenticationToken.token_type); } } diff --git a/JS/TumblrAPI.js b/JS/TumblrAPI.js index 79a00a1..54134b8 100644 --- a/JS/TumblrAPI.js +++ b/JS/TumblrAPI.js @@ -1 +1 @@ -import * as Cookie from "./Cookies.js"; +import * as Variables from "./Variables.js"; diff --git a/JS/Variables.js b/JS/Variables.js new file mode 100644 index 0000000..8fa8ad0 --- /dev/null +++ b/JS/Variables.js @@ -0,0 +1,24 @@ +// STRINGS TODO: make sure to seperate stuff that a user will want to input: BlueskyPDSName. +// Mastodon +export const MastodonWebsite = "mastodon_website"; +export const MastodonClientID = "mastodon_client_id"; +export const MastodonClientSecret = "mastodon_client_secret"; +export const MastodonAccessToken = "mastodon_access_token"; +export const MastodonTokenType = "mastodon_token_type"; + +// Bluesky +export const BlueskyPDS = "bluesky_pds"; +export const BlueskyDID = "bluesky_did"; +export const BlueskyPKCEVerifier = "bluesky_pkce_verifier"; +export const BlueskyPKCEChallenge = "bluesky_pkce_challenge"; +export const BlueskyPublicKey = "bluesky_public_key"; +export const BlueskyPrivateKey = "bluesky_private_key"; +export const BlueskyNonce = "bluesky_nonce"; +export const BlueskyAccessToken = "bluesky_access_token"; +export const BlueskyRefreshToken = "bluesky_refresh_token"; + +// Tumblr +export const TumblrWebsiteName = "https://www.tumblr.com"; + +// WARNING: Research suggests that cookies are very unsecue. +// Every Fetch request (http or https) sends these cookies. That's bad! diff --git a/JS/index.js b/JS/index.js index b0047ba..79c8cfb 100644 --- a/JS/index.js +++ b/JS/index.js @@ -1,7 +1,7 @@ import * as MastodonAPI from "./MastodonAPI.js"; import * as BlueskyAPI from "./BlueskyAPI.js"; import * as TumblrAPI from "./TumblrAPI.js"; -import * as Cookie from "./Cookies.js"; +import * as Variables from "./Variables.js"; // GLOBAL VARS // fuck you. I see why website developers use divs so fucking often. @@ -104,14 +104,14 @@ ArrowsButton[0].onclick = (event) => { // MastodonAPI integration async function PosterContainerUpdate() { - // Cookies for the public timelines - let LocalCookie = Cookie.GetCookie("Local"); - var LocalTrue = (LocalCookie === "true"); - let RemoteCookie = Cookie.GetCookie("Remote"); - var RemoteTrue = (RemoteCookie === "true"); - let Website = Cookie.GetCookie(Cookie.MastodonWebsite); + // Variables for the public timelines + let LocalVar = localStorage.getItem("Local"); + var LocalTrue = (LocalVar === "true"); + let RemoteVar = localStorage.getItem("Remote"); + var RemoteTrue = (RemoteVar === "true"); + let Website = localStorage.getItem(Variables.MastodonWebsite); - if (!(Cookie.IsCookieReal(Cookie.MastodonWebsite))) { + if (localStorage.getItem(Variables.MastodonWebsite) == null) { Website = "https://wetdry.world"; } diff --git a/JS/mail.js b/JS/mail.js index 2ba773f..8dac64e 100644 --- a/JS/mail.js +++ b/JS/mail.js @@ -1,7 +1,7 @@ import * as MastodonAPI from "./MastodonAPI.js"; import * as BlueskyAPI from "./BlueskyAPI.js"; import * as TumblrAPI from "./TumblrAPI.js"; -import * as Cookie from "./Cookies.js"; +import * as Variables from "./Variables.js"; // Below is the thing it populates if you login. async function PopulateFavorites() { diff --git a/JS/post.js b/JS/post.js index 00878f3..ac0de1d 100644 --- a/JS/post.js +++ b/JS/post.js @@ -1,11 +1,12 @@ import * as MastodonAPI from "./MastodonAPI.js"; import * as BlueskyAPI from "./BlueskyAPI.js"; import * as TumblrAPI from "./TumblrAPI.js"; -import * as Cookie from "./Cookies.js"; +import * as Variables from "./Variables.js"; // Elements. -let PostButton = document.getElementsByClassName("button")[0]; -let InputArea = document.getElementsByClassName("text")[0]; +let PostButton = document.getElementsByClassName("Button")[0]; +let VisibilityDropdown = document.getElementsByClassName("PostVisibility")[0]; +let InputArea = document.getElementsByClassName("Text")[0]; // Clicking the beeg POST button. PostButton.onclick = (event) => { @@ -14,14 +15,56 @@ PostButton.onclick = (event) => { async function Post() { let Text = InputArea.value; + let Visible = VisibilityDropdown.value; + // don't do anything if there is no value + if (Text == "") { + return; + } // Mastodon posting. - if (Cookie.IsCookieReal(Cookie.MastodonAccessToken)) { - MastodonAPI.CreateStatus(Text); + if (localStorage.getItem(Variables.MastodonAccessToken) != null) { + let TempVisible; + switch(Visible) { + case "Public": + TempVisible = "public"; + break; + case "Quiet": + TempVisible = "unlisted"; + break; + case "Friend": + TempVisible = "private"; + break; + case "Private": + TempVisible = "direct"; + break; + } + MastodonAPI.CreateStatus(Text, TempVisible); } // Bluesky posting. - if (Cookie.IsCookieReal(Cookie.BlueskyAccessToken)) { - let DID = await BlueskyAPI.GetBlueskyDID("https://woodear.us-west.host.bsky.network", "crowdedgames.group"); - BlueskyAPI.CreatePost("https://woodear.us-west.host.bsky.network", DID.did, Text); + if (localStorage.getItem(Variables.BlueskyAccessToken) != null) { + let TempVisible; + switch(Visible) { + case "Public": + TempVisible = undefined; + break; + case "Quiet": + TempVisible = undefined; + break; + case "Friend": + TempVisible = [{"$type": "app.bsky.feed.threadgate#followingRule"}, {"$type": "app.bsky.feed.threadgate#followerRule"}]; + break; + case "Private": + TempVisible = []; + break; + } + let Post = await BlueskyAPI.CreatePost(localStorage.getItem(Variables.BlueskyDID), Text); + console.log(Post); + let ThreadGate = await BlueskyAPI.SetThreadGate(localStorage.getItem(Variables.BlueskyDID), Post.uri, TempVisible); + console.log(ThreadGate); } InputArea.value = ""; } + +// Check if you can interact with the textbox +if (localStorage.getItem(Variables.MastodonAccessToken) == null && localStorage.getItem(Variables.BlueskyAccessToken) == null) { + InputArea.disabled = true; +} diff --git a/JS/setting.js b/JS/setting.js index 581b546..779975d 100644 --- a/JS/setting.js +++ b/JS/setting.js @@ -1,7 +1,7 @@ import * as MastodonAPI from "./MastodonAPI.js"; import * as BlueskyAPI from "./BlueskyAPI.js"; import * as TumblrAPI from "./TumblrAPI.js"; -import * as Cookie from "./Cookies.js"; +import * as Variables from "./Variables.js"; // Settings buttons let LocalButton = document.getElementsByClassName("Local")[0]; @@ -19,20 +19,20 @@ let Origin = location.origin + "/HTML/setting.html" // Change weather the timelines are public or remote LocalButton.onclick = (event) => { - // Toggle the cookie - if (Cookie.IsCookieReal("Local")) { - Cookie.ExpireCookie("Local"); + // Toggle the Variable + if (localStorage.getItem("Local") != null) { + localStorage.removeItem("Local"); } else { - Cookie.InputCookie("Local", "true"); + localStorage.setItem("Local", "true"); } } RemoteButton.onclick = (event) => { - // Toggle the cookie - if (Cookie.IsCookieReal("Romote")) { - Cookie.ExpireCookie("Remote"); + // Toggle the Variable + if (localStorage.getItem("Remote") != null) { + localStorage.removeItem("Remote"); } else { - Cookie.InputCookie("Remote", "true"); + localStorage.setItem("Remote", "true"); } } @@ -47,10 +47,11 @@ MastodonLoginButton.onclick = (event) => { // Logout MastodonLogoutButton.onclick = (event) => { - Cookie.ExpireCookie(Cookie.MastodonClientID); - Cookie.ExpireCookie(Cookie.MastodonClientSecret); - Cookie.ExpireCookie(Cookie.MastodonAccessToken); - Cookie.ExpireCookie(Cookie.MastodonTokenType); + localStorage.removeItem(Variables.MastodonClientID); + localStorage.removeItem(Variables.MastodonClientSecret); + localStorage.removeItem(Variables.MastodonAccessToken); + localStorage.removeItem(Variables.MastodonTokenType); + localStorage.removeItem(Variables.MastodonWebsite); document.location.href = Origin; } @@ -58,36 +59,39 @@ MastodonLogoutButton.onclick = (event) => { // Login BlueskyLoginButton.onclick = (event) => { if (BlueskyWebInput.value != "") { - BlueskyAPI.HandleAuthorization(); + let text = BlueskyWebInput.value + BlueskyAPI.HandleAuthorization(text); } } // Logout BlueskyLogoutButton.onclick = (event) => { - Cookie.ExpireCookie(Cookie.BlueskyPKCEVerifier); - Cookie.ExpireCookie(Cookie.BlueskyPKCEChallenge); - Cookie.ExpireCookie(Cookie.BlueskyNonce); - Cookie.ExpireCookie(Cookie.BlueskyAccessToken); - Cookie.ExpireCookie(Cookie.BlueskyRefreshToken); - Cookie.ExpireCookie(Cookie.BlueskyPublicKey); - Cookie.ExpireCookie(Cookie.BlueskyPrivateKey); + localStorage.removeItem(Variables.BlueskyPDS); + localStorage.removeItem(Variables.BlueskyDID); + localStorage.removeItem(Variables.BlueskyPKCEVerifier); + localStorage.removeItem(Variables.BlueskyPKCEChallenge); + localStorage.removeItem(Variables.BlueskyNonce); + localStorage.removeItem(Variables.BlueskyAccessToken); + localStorage.removeItem(Variables.BlueskyRefreshToken); + localStorage.removeItem(Variables.BlueskyPublicKey); + localStorage.removeItem(Variables.BlueskyPrivateKey); document.location.href = Origin; } // if an access token is found, login. async function CheckLogin() { // Check for a mastodon token. - if (Cookie.IsCookieReal(Cookie.MastodonAccessToken)) { + if (localStorage.getItem(Variables.MastodonAccessToken) != null) { // Swap the buttons MastodonLoginButton.remove(); MastodonWebInput.remove(); MastodonLogoutButton.setAttribute("style", ""); } else { // Auto log in - await MastodonAPI.GainToken(Cookie.MastodonWebsite); + await MastodonAPI.GainToken(Variables.MastodonWebsite); } // Check for a bluesky token. - if (Cookie.IsCookieReal(Cookie.BlueskyAccessToken)) { + if (localStorage.getItem(Variables.BlueskyAccessToken) != null) { // Swap the buttons BlueskyLoginButton.remove(); BlueskyWebInput.remove();