From 3c8205e0b9d44402b06c0033ad548e81fb8cf2d2 Mon Sep 17 00:00:00 2001 From: alyx Date: Thu, 14 Dec 2023 16:41:11 -0500 Subject: Basic onboarding flow --- background.js | 89 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ icons/128.png | Bin 0 -> 4867 bytes icons/16.png | Bin 0 -> 1117 bytes icons/32.png | Bin 0 -> 1310 bytes icons/44.png | Bin 0 -> 1732 bytes icons/64.png | Bin 0 -> 2279 bytes init.html | 7 +++++ init.js | 4 +++ manifest.json | 23 +++++++++++++++ schema.json | 28 ++++++++++++++++++ 10 files changed, 151 insertions(+) create mode 100644 background.js create mode 100644 icons/128.png create mode 100644 icons/16.png create mode 100644 icons/32.png create mode 100644 icons/44.png create mode 100644 icons/64.png create mode 100644 init.html create mode 100644 init.js create mode 100644 manifest.json create mode 100644 schema.json 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 Binary files /dev/null and b/icons/128.png differ diff --git a/icons/16.png b/icons/16.png new file mode 100644 index 0000000..b01f5fc Binary files /dev/null and b/icons/16.png differ diff --git a/icons/32.png b/icons/32.png new file mode 100644 index 0000000..ac585f4 Binary files /dev/null and b/icons/32.png differ diff --git a/icons/44.png b/icons/44.png new file mode 100644 index 0000000..ebe3fbe Binary files /dev/null and b/icons/44.png differ diff --git a/icons/64.png b/icons/64.png new file mode 100644 index 0000000..d37317d Binary files /dev/null and b/icons/64.png 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 @@ + + + + + + + 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": {} + } + } +} -- cgit v1.2.3-70-g09d2