summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authoralyx <alyx@aleteoryx.me>2023-12-14 16:41:11 -0500
committeralyx <alyx@aleteoryx.me>2023-12-14 16:41:11 -0500
commit3c8205e0b9d44402b06c0033ad548e81fb8cf2d2 (patch)
treec5cd2e30d7982629f739ee2e393e80608f2cc276
parent95c2e6bf6700429e7bae9debff98b00315dfd838 (diff)
downloadtumblr_follower_mgr-master.tar.gz
tumblr_follower_mgr-master.tar.bz2
tumblr_follower_mgr-master.zip
Basic onboarding flowHEADmaster
-rw-r--r--background.js89
-rw-r--r--icons/128.pngbin0 -> 4867 bytes
-rw-r--r--icons/16.pngbin0 -> 1117 bytes
-rw-r--r--icons/32.pngbin0 -> 1310 bytes
-rw-r--r--icons/44.pngbin0 -> 1732 bytes
-rw-r--r--icons/64.pngbin0 -> 2279 bytes
-rw-r--r--init.html7
-rw-r--r--init.js4
-rw-r--r--manifest.json23
-rw-r--r--schema.json28
10 files changed, 151 insertions, 0 deletions
diff --git a/background.js b/background.js
new file mode 100644
index 0000000..ff88355
--- /dev/null
+++ b/background.js
@@ -0,0 +1,89 @@
+(async function() {
+
+/*
+
+"init" => what it sounds like, basic setup things
+"tumblr" => ok, we have oauth2 creds, now let's authorize with the user!
+"ready" => alright! main thing!!
+
+*/
+let {system_state, tumblr_expiry_date} = await chrome.storage.local.get({"system_state": "init", "tumblr_expiry_date": 0});
+
+let refreshTimeout = (system_state == "ready") ? setTimeout(refreshToken, Date.now() - tumblr_expiry_date) : null;
+
+async function refreshToken() {
+ const { tumblr_refresh_token, oauth_consumer_key, oauth_secret_key } = await chrome.storage.local.get(["tumblr_refresh_token", "oauth_consumer_key", "oauth_secret_key"]);
+
+ const form = new FormData();
+ form.append("grant_type", "refresh_token");
+ form.append("refresh_token", tumblr_refresh_token);
+ form.append("client_id", oauth_consumer_key);
+ form.append("client_secret", oauth_secret_key);
+ const {expires_in, access_token, refresh_token} = await fetch("https://api.tumblr.com/v2/oauth2/token", {body: form, method: "POST"}).then(a => a.json());
+ const tumblr_expiry_date = expires_in * 1000 + Date.now();
+
+ await chrome.storage.local.set({tumblr_expiry_date, tumblr_access_token: access_token, tumblr_refresh_token: refresh_token});
+
+ refreshTimeout = setTimeout(refreshToken, expires_in * 1000);
+
+}
+
+async function doNextThing(startup) {
+ switch (system_state) {
+ case "init":
+ await chrome.tabs.create({url: "chrome-extension://"+chrome.runtime.id+"/init.html"});
+ break;
+ case "tumblr":
+ let {oauth_consumer_key} = await chrome.storage.local.get(["oauth_consumer_key"]);
+ await chrome.tabs.create({url: "https://tumblr.com/oauth2/authorize?response_type=code&scope=basic%20offline_access%20write&state=NA&client_id="+oauth_consumer_key});
+ }
+}
+
+chrome.runtime.onMessage.addListener(async function({id, type, payload}, sender) {
+ console.debug(`Got message "${type}"@"${id}", payload ${JSON.stringify(payload)}`);
+ switch (type) {
+ case "set_creds":
+ const {oauth_consumer_key, oauth_secret_key} = payload;
+ clearTimeout(refreshTimeout);
+ system_state = "tumblr";
+ await chrome.storage.local.set({system_state, oauth_consumer_key, oauth_secret_key});
+
+ doNextThing();
+
+ if (sender.tab) {
+ await chrome.tabs.sendMessage(sender.tab.id, {id, status: "OK"});
+ }
+ return;
+ default:
+ if (sender.tab) {
+ chrome.tabs.sendMessage(sender.tab.id, {id, status: "ERRUNDEF", message: "No message type `"+type+"`!"});
+ }
+ return;
+ }
+});
+
+chrome.tabs.onUpdated.addListener(async function(tabId, {url}, tab) {
+ if (system_state == "tumblr" && url?.startsWith("https://example.com/tfm_redirect")) {
+ const { oauth_consumer_key, oauth_secret_key } = await chrome.storage.local.get(["oauth_consumer_key", "oauth_secret_key"]);
+
+ const code = /code=([a-fA-F0-9]+)/.exec(url)[1];
+
+ const form = new FormData();
+ form.append("grant_type", "authorization_code");
+ form.append("code", code);
+ form.append("client_id", oauth_consumer_key);
+ form.append("client_secret", oauth_secret_key);
+ const {expires_in, access_token, refresh_token} = await fetch("https://api.tumblr.com/v2/oauth2/token", {body: form, method: "POST"}).then(a => a.json());
+
+ const tumblr_expiry_date = expires_in * 1000 + Date.now();
+ await chrome.storage.local.set({system_state: "ready", tumblr_expiry_date, tumblr_access_token: access_token, tumblr_refresh_token: refresh_token});
+ clearTimeout(refreshTimeout);
+ refreshTimeout = setTimeout(refreshToken, expires_in * 1000);
+
+ await chrome.tabs.update(tabId, {url: "chrome-extension://"+chrome.runtime.id+"/ui.html"});
+ }
+});
+
+doNextThing(true);
+
+})();
diff --git a/icons/128.png b/icons/128.png
new file mode 100644
index 0000000..010663e
--- /dev/null
+++ b/icons/128.png
Binary files differ
diff --git a/icons/16.png b/icons/16.png
new file mode 100644
index 0000000..b01f5fc
--- /dev/null
+++ b/icons/16.png
Binary files differ
diff --git a/icons/32.png b/icons/32.png
new file mode 100644
index 0000000..ac585f4
--- /dev/null
+++ b/icons/32.png
Binary files differ
diff --git a/icons/44.png b/icons/44.png
new file mode 100644
index 0000000..ebe3fbe
--- /dev/null
+++ b/icons/44.png
Binary files differ
diff --git a/icons/64.png b/icons/64.png
new file mode 100644
index 0000000..d37317d
--- /dev/null
+++ b/icons/64.png
Binary files differ
diff --git a/init.html b/init.html
new file mode 100644
index 0000000..f075f8d
--- /dev/null
+++ b/init.html
@@ -0,0 +1,7 @@
+<!doctype html>
+<body>
+<input id=consumer placeholder="OAuth Consumer Key">
+<input id=secret placeholder="OAuth Secret Key">
+<button id=set>Set</button>
+<script src="init.js"></script>
+</body>
diff --git a/init.js b/init.js
new file mode 100644
index 0000000..fe3c30a
--- /dev/null
+++ b/init.js
@@ -0,0 +1,4 @@
+set.onclick = () => {
+ const msgid = Date.now();
+ chrome.runtime.sendMessage(null, {type: "set_creds", id: msgid, payload: { oauth_consumer_key: consumer.value, oauth_secret_key: secret.value } });
+}
diff --git a/manifest.json b/manifest.json
new file mode 100644
index 0000000..a2c31d4
--- /dev/null
+++ b/manifest.json
@@ -0,0 +1,23 @@
+{
+ "manifest_version": 3,
+ "name": "Tumblr Follower Manager",
+ "description": "Cause I follow too many fucks!",
+ "version": "1.0",
+ "action": {
+ "default_icon": "icons/32.png"
+ },
+ "background": {
+ "service_worker": "background.js",
+ "type": "module"
+ },
+ "storage": "schema.json",
+ "icons": {
+ "16": "icons/16.png",
+ "32": "icons/32.png",
+ "44": "icons/44.png",
+ "64": "icons/64.png",
+ "128": "icons/128.png"
+ },
+ "permissions": [ "tabs", "storage", "unlimitedStorage", "scripting" ],
+ "host_permissions": [ "https://example.com/tfm_*", "https://tumblr.com/" ]
+}
diff --git a/schema.json b/schema.json
new file mode 100644
index 0000000..296d086
--- /dev/null
+++ b/schema.json
@@ -0,0 +1,28 @@
+{
+ "type": "object",
+ "properties": {
+ "system_status": {
+ "type": "string",
+ "enum": ["init", "tumblr", "indexing", "ready"],
+ "default": "init"
+ },
+ "oauth_consumer_key": { "type": "string" },
+ "oauth_secret_key": { "type": "string" },
+
+ "tumblr_access_token": { "type": "string" },
+ "tumblr_refresh_token": { "type": "string" },
+ "tumblr_expiry_date": { "type": "number" },
+
+ "follow_index": {
+ "type": "object",
+ "additionalProperties": {
+ "type": "object",
+ "properties": {
+ "checked": { "type": "boolean", "default": false },
+ "tags": { "type": "array", "items": { "type": "string" }, "uniqueItems": true, "default": [] }
+ }
+ },
+ "default": {}
+ }
+ }
+}