-
Notifications
You must be signed in to change notification settings - Fork 20
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Support auto-redirection by <link>
#106
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change | ||||
---|---|---|---|---|---|---|
@@ -0,0 +1,46 @@ | ||||||
import * as NetworkTools from "/common/modules/NetworkTools.js"; | ||||||
import * as AddonSettings from "/common/modules/AddonSettings/AddonSettings.js"; | ||||||
import { resolveActivityPubId } from "/common/modules/MastodonApi.js"; | ||||||
|
||||||
/** | ||||||
* Scrapes the ActivityPub <link> destination from the HTML page, if needed and exists. | ||||||
* | ||||||
* @param {number} tabId | ||||||
* @param {URL} url | ||||||
* @returns {Promise} | ||||||
*/ | ||||||
export async function redirectByActivityPubLink(tabId, url) { | ||||||
if (!tabId || !url) { | ||||||
throw new Error("Needs a tab id and a page URL"); | ||||||
} | ||||||
|
||||||
const [objectId] = await browser.tabs.executeScript(tabId, { | ||||||
code: `document.querySelector("link[rel=alternate][type='application/activity+json']")?.href`, | ||||||
runAt: "document_end", | ||||||
}); | ||||||
if (!objectId) { | ||||||
return; | ||||||
} | ||||||
|
||||||
const ownMastodon = await AddonSettings.get("ownMastodon"); | ||||||
if (ownMastodon.server === url.hostname) { | ||||||
return; | ||||||
} | ||||||
|
||||||
const body = await resolveActivityPubId(ownMastodon.server, objectId); | ||||||
|
||||||
const baseUrl = `https://${ownMastodon.server}`; | ||||||
let homeUrl; | ||||||
if (body.accounts[0]) { | ||||||
homeUrl = new URL(`@${body.accounts[0].acct}`, baseUrl); | ||||||
} else if (body.statuses[0]) { | ||||||
homeUrl = new URL( | ||||||
`@${body.statuses[0].account.acct}/${body.statuses[0].id}`, | ||||||
baseUrl | ||||||
); | ||||||
} else { | ||||||
return; | ||||||
} | ||||||
|
||||||
await NetworkTools.redirectToWebsite(homeUrl, tabId); | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
Any special reason you use await instead of just returning the Promise? That could be helpful for error handling or so, that's why I'd prefer return if there is no reason. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Hmm? I believe awaiting is more helpful, since an error will throw at await call site but not at return call site. And awaiting is anyway more consistent. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. hmm this goes deep into the way promises may be handled and I would have said before it makes no difference at all whether to await here, because likely where this is called it is also awaited. And await is just a cooler syntax for But what you say may be right too, the stacktrace may not lost thus last function then? But I am really unsure here, so a js snippet/proof or some source would help. I am always open to learn something new hehe. Otherwise I'd stand to what I said, I.e. remove the await, because that would be consistent to how it is done in the code base everywhere else. |
||||||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -15,6 +15,7 @@ import * as MisskeyDetect from "./Detect/Misskey.js"; | |
|
||
import * as NetworkTools from "/common/modules/NetworkTools.js"; | ||
import * as MastodonRedirect from "./MastodonRedirect.js"; | ||
import { redirectByActivityPubLink } from "./ActivityPubRedirect.js"; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. BTW I usually prefer a "module-like style", i.e. import |
||
|
||
import * as AddonSettings from "/common/modules/AddonSettings/AddonSettings.js"; | ||
import * as MastodonHandleCheck from "/common/modules/MastodonHandle/ConfigCheck.js"; | ||
|
@@ -149,12 +150,18 @@ function getInteractionType(url) { | |
|
||
/** | ||
* Handles changes to the URL of a tab. | ||
* | ||
* | ||
* @param {string} tabId | ||
* @param {Object} changeInfo | ||
* @returns {void} | ||
*/ | ||
async function onTabUpdate(tabId, changeInfo) { | ||
// clear cache of settings | ||
await AddonSettings.loadOptions(); | ||
if (await AddonSettings.get("redirectImmediately")) { | ||
redirectByActivityPubLink(tabId, changeInfo.url); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. not Maybe put a commend to make that clear… |
||
} | ||
|
||
const ownMastodon = await AddonSettings.get("ownMastodon"); | ||
const currentURL = new URL(changeInfo.url); | ||
if (ownMastodon.server !== currentURL.hostname){ | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -99,3 +99,22 @@ export function getTootStatus(mastodonServer, localTootId) { | |
return response.json(); | ||
}); | ||
} | ||
|
||
/** | ||
* Resolves the ActivityPub object ID on a given server | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. any link/ref to the ActivityPub spec to add to this doc to exlain what it is? I've found one before, but I don't know whether that is up-to-date. |
||
* | ||
* @param {string} mastodonServer | ||
* @param {string} objectId | ||
*/ | ||
export async function resolveActivityPubId(mastodonServer, objectId) { | ||
const apiUrl = new URL("api/v2/search", `https://${mastodonServer}`); | ||
apiUrl.searchParams.set("q", objectId); | ||
apiUrl.searchParams.set("resolve", "true"); | ||
|
||
const response = await NetworkTools.fetch(apiUrl); | ||
if (!response.ok) { | ||
throw new MastodonApiError(mastodonServer, response, `Failed to resolve ${objectId}.`); | ||
} | ||
|
||
return await response.json(); | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -6,5 +6,6 @@ | |
|
||
export const DEFAULT_SETTINGS = Object.freeze({ | ||
ownMastodon: null, | ||
redirectInMainWindow: false | ||
redirectInMainWindow: false, | ||
redirectImmediately: false, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why not enabled by default? |
||
}); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks a lot for introducing a setting!
IMHO, for a good UX we should then have two settings (both being enabled by default I guess):
This would enable one to disable the old redirect style (e.g. because of missing features/unwanted redirects like #28).