mirror of
https://github.com/BetterSEQTA/BetterSEQTA-Plus.git
synced 2026-06-05 19:24:39 +00:00
fix: fix qr code to use safer methoed & bump ver
This commit is contained in:
+1
-1
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "betterseqtaplus",
|
||||
"version": "3.5.0",
|
||||
"version": "3.5.1",
|
||||
"type": "module",
|
||||
"description": "Enhance SEQTA Learn's usability and aesthetics! A fork of BetterSEQTA to continue development add add heaps more features!",
|
||||
"browserslist": "> 0.5%, last 2 versions, not dead",
|
||||
|
||||
@@ -11,6 +11,30 @@ import { main } from "@/seqta/main";
|
||||
import { delay } from "./seqta/utils/delay";
|
||||
import { initializeHideSensitiveToggle } from "@/seqta/utils/hideSensitiveToggle";
|
||||
|
||||
function registerFetchSeqtaAppLinkListener() {
|
||||
browser.runtime.onMessage.addListener((request, _sender, sendResponse) => {
|
||||
if (request?.type !== "fetchSeqtaAppLink") return false;
|
||||
void (async () => {
|
||||
try {
|
||||
const res = await fetch(`${location.origin}/seqta/student/load/profile`, {
|
||||
method: "POST",
|
||||
headers: { "Content-Type": "application/json" },
|
||||
credentials: "include",
|
||||
body: JSON.stringify({}),
|
||||
});
|
||||
const data = await res.json();
|
||||
const statusOk = data?.status === "200" || data?.status === 200;
|
||||
const raw = data?.payload?.app_link;
|
||||
const appLink = typeof raw === "string" && raw.length > 0 ? raw : null;
|
||||
sendResponse({ appLink: statusOk ? appLink : null });
|
||||
} catch {
|
||||
sendResponse({ appLink: null });
|
||||
}
|
||||
})();
|
||||
return true;
|
||||
});
|
||||
}
|
||||
|
||||
export let MenuOptionsOpen = false;
|
||||
|
||||
var IsSEQTAPage = false;
|
||||
@@ -30,6 +54,8 @@ async function init() {
|
||||
IsSEQTAPage = true;
|
||||
console.info("[BetterSEQTA+] Verified SEQTA Page");
|
||||
|
||||
registerFetchSeqtaAppLinkListener();
|
||||
|
||||
const documentLoadStyle = document.createElement("style");
|
||||
documentLoadStyle.textContent = documentLoadCSS;
|
||||
document.head.appendChild(documentLoadStyle);
|
||||
|
||||
+38
-18
@@ -167,8 +167,19 @@ function handleCloudFavorite(request: any, sendResponse: MessageSender): boolean
|
||||
return true;
|
||||
}
|
||||
|
||||
/** Handler for a message type; receives request and sendResponse callback */
|
||||
type MessageHandler = { (request: any, sendResponse: MessageSender): boolean | void };
|
||||
/** Handler for a message type; receives request, sendResponse, and optional sender (for tab routing) */
|
||||
type MessageHandler = {
|
||||
(request: any, sendResponse: MessageSender, sender?: browser.Runtime.MessageSender): boolean | void;
|
||||
};
|
||||
|
||||
function isSeqtaOrigin(origin: string): boolean {
|
||||
try {
|
||||
const u = new URL(origin);
|
||||
return u.hostname.includes("seqta") || u.hostname.endsWith(".edu.au");
|
||||
} catch {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
const MESSAGE_HANDLERS: Record<string, MessageHandler> = {
|
||||
reloadTabs: () => reloadSeqtaPages(),
|
||||
@@ -200,29 +211,38 @@ const MESSAGE_HANDLERS: Record<string, MessageHandler> = {
|
||||
cloudLogin: handleCloudLogin,
|
||||
cloudRefresh: handleCloudRefresh,
|
||||
cloudFavorite: handleCloudFavorite,
|
||||
getSeqtaSession: (req: { baseUrl?: string }, sendResponse: MessageSender) => {
|
||||
getSeqtaSession: (req: { baseUrl?: string }, sendResponse: MessageSender, sender?: browser.Runtime.MessageSender) => {
|
||||
(async () => {
|
||||
try {
|
||||
let baseUrl = req.baseUrl;
|
||||
if (!baseUrl) {
|
||||
const tabs = await browser.tabs.query({ active: true, currentWindow: true });
|
||||
let tabId = sender?.tab?.id;
|
||||
let originForCheck: string | undefined = req.baseUrl;
|
||||
|
||||
if (tabId == null) {
|
||||
const tabs = await browser.tabs.query({ active: true, lastFocusedWindow: true });
|
||||
const tab = tabs[0];
|
||||
if (!tab?.url) {
|
||||
sendResponse({ session: null });
|
||||
if (!tab?.id || !tab.url) {
|
||||
sendResponse({ appLink: null });
|
||||
return;
|
||||
}
|
||||
baseUrl = new URL(tab.url).origin;
|
||||
tabId = tab.id;
|
||||
if (!originForCheck) originForCheck = new URL(tab.url).origin;
|
||||
} else if (!originForCheck && sender?.tab?.url) {
|
||||
originForCheck = new URL(sender.tab.url).origin;
|
||||
}
|
||||
const cookies = await browser.cookies.getAll({ url: baseUrl });
|
||||
const jsession = cookies.find((c) => c.name === "JSESSIONID");
|
||||
if (jsession?.value) {
|
||||
sendResponse({ session: { baseUrl, jsessionId: jsession.value } });
|
||||
} else {
|
||||
sendResponse({ session: null });
|
||||
|
||||
if (!originForCheck || !isSeqtaOrigin(originForCheck)) {
|
||||
sendResponse({ appLink: null });
|
||||
return;
|
||||
}
|
||||
|
||||
const reply = (await browser.tabs.sendMessage(tabId, { type: "fetchSeqtaAppLink" })) as
|
||||
| { appLink?: string | null }
|
||||
| undefined;
|
||||
const appLink = typeof reply?.appLink === "string" && reply.appLink.length > 0 ? reply.appLink : null;
|
||||
sendResponse({ appLink });
|
||||
} catch (err) {
|
||||
console.error("[Background] getSeqtaSession error:", err);
|
||||
sendResponse({ session: null });
|
||||
sendResponse({ appLink: null });
|
||||
}
|
||||
})();
|
||||
return true;
|
||||
@@ -231,10 +251,10 @@ const MESSAGE_HANDLERS: Record<string, MessageHandler> = {
|
||||
|
||||
browser.runtime.onMessage.addListener(
|
||||
// @ts-ignore - OnMessageListener expects literal true for async, we return boolean
|
||||
(request: any, _: any, sendResponse: MessageSender) => {
|
||||
(request: any, sender: browser.Runtime.MessageSender, sendResponse: MessageSender) => {
|
||||
const handler = MESSAGE_HANDLERS[request.type];
|
||||
if (handler) {
|
||||
const result = handler(request, sendResponse);
|
||||
const result = handler(request, sendResponse, sender);
|
||||
return result === true;
|
||||
}
|
||||
console.log("Unknown request type");
|
||||
|
||||
@@ -4,11 +4,9 @@
|
||||
import QRCode from "qrcode";
|
||||
import { portal } from "../utils/portal";
|
||||
|
||||
const DEEPLINK_PREFIX = "desqta://connect/";
|
||||
|
||||
let showQrModal = $state(false);
|
||||
let qrDataUrl = $state<string | null>(null);
|
||||
let deeplink = $state<string | null>(null);
|
||||
let appLink = $state<string | null>(null);
|
||||
let errorMessage = $state<string | null>(null);
|
||||
let isLoading = $state(false);
|
||||
let isStandalone = $state(false);
|
||||
@@ -38,30 +36,21 @@
|
||||
}
|
||||
}
|
||||
|
||||
function buildDesqtaConnectPayload(baseUrl: string, jsessionId: string): string {
|
||||
const payload = JSON.stringify({ u: baseUrl, s: jsessionId });
|
||||
const base64 = btoa(unescape(encodeURIComponent(payload)));
|
||||
const encoded = encodeURIComponent(base64);
|
||||
return `${DEEPLINK_PREFIX}${encoded}`;
|
||||
}
|
||||
|
||||
async function getSession(): Promise<{ baseUrl: string; jsessionId: string } | null> {
|
||||
async function getAppLink(): Promise<string | null> {
|
||||
let baseUrl: string | undefined;
|
||||
|
||||
if (isExtensionPage()) {
|
||||
// Extension popup: background will get URL from active tab
|
||||
baseUrl = undefined;
|
||||
} else {
|
||||
// In-page (settings inside SEQTA): pass current page URL (cookies API not available in content scripts)
|
||||
baseUrl = normalizeBaseUrl(window.location.href);
|
||||
if (!isSeqtaUrl(baseUrl)) return null;
|
||||
}
|
||||
|
||||
const { session } = (await browser.runtime.sendMessage({
|
||||
const { appLink: link } = (await browser.runtime.sendMessage({
|
||||
type: "getSeqtaSession",
|
||||
baseUrl,
|
||||
})) as { session: { baseUrl: string; jsessionId: string } | null };
|
||||
return session ?? null;
|
||||
})) as { appLink: string | null };
|
||||
return link ?? null;
|
||||
}
|
||||
|
||||
async function generateQrCode() {
|
||||
@@ -71,9 +60,9 @@
|
||||
|
||||
try {
|
||||
isStandalone = isExtensionPage();
|
||||
const session = await getSession();
|
||||
const link = await getAppLink();
|
||||
|
||||
if (!session) {
|
||||
if (!link) {
|
||||
if (isStandalone) {
|
||||
errorMessage =
|
||||
"Open SEQTA Learn in a tab and log in, then open settings from that tab to generate a QR code.";
|
||||
@@ -83,9 +72,8 @@
|
||||
return;
|
||||
}
|
||||
|
||||
const link = buildDesqtaConnectPayload(session.baseUrl, session.jsessionId);
|
||||
const dataUrl = await QRCode.toDataURL(link, { width: 256, margin: 2 });
|
||||
deeplink = link;
|
||||
appLink = link;
|
||||
qrDataUrl = dataUrl;
|
||||
showQrModal = true;
|
||||
} catch (err) {
|
||||
@@ -99,12 +87,12 @@
|
||||
function closeModal() {
|
||||
showQrModal = false;
|
||||
qrDataUrl = null;
|
||||
deeplink = null;
|
||||
appLink = null;
|
||||
errorMessage = null;
|
||||
}
|
||||
|
||||
function openInDesqta() {
|
||||
if (deeplink) window.location.href = deeplink;
|
||||
function openAppLink() {
|
||||
if (appLink) window.location.href = appLink;
|
||||
}
|
||||
|
||||
function downloadQrImage() {
|
||||
@@ -160,12 +148,12 @@
|
||||
</button>
|
||||
</div>
|
||||
<div class="flex justify-center p-4 bg-white rounded-xl dark:bg-zinc-900">
|
||||
<img src={qrDataUrl} alt="DesQTA QR Code" class="w-64 h-64" />
|
||||
<img src={qrDataUrl} alt="SEQTA Learn app link QR code" class="w-64 h-64" />
|
||||
</div>
|
||||
<div class="flex flex-col gap-2 mt-4">
|
||||
<button
|
||||
type="button"
|
||||
onclick={openInDesqta}
|
||||
onclick={openAppLink}
|
||||
class="px-4 py-2.5 w-full text-sm font-medium text-white bg-indigo-600 rounded-lg transition-colors dark:bg-indigo-500 hover:bg-indigo-700 dark:hover:bg-indigo-600">
|
||||
Sign into DesQTA Desktop
|
||||
</button>
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
"64": "resources/icons/icon-64.png"
|
||||
}
|
||||
},
|
||||
"permissions": ["tabs", "notifications", "storage", "cookies"],
|
||||
"permissions": ["tabs", "notifications", "storage"],
|
||||
"host_permissions": ["https://newsapi.org/", "https://betterseqta.org/", "https://accounts.betterseqta.org/", "*://*/*"],
|
||||
"background": {
|
||||
"service_worker": "background.ts"
|
||||
|
||||
@@ -32,6 +32,9 @@ export function OpenWhatsNewPopup() {
|
||||
const text = stringToHTML(/* html */ `
|
||||
<div class="whatsnewTextContainer" style="height: 50%;overflow-y: auto;">
|
||||
|
||||
<h1>3.5.1 - QR & session link fix</h1>
|
||||
<li>Fixed DesQTA Connect Mobile App QR generation on Chrome</li>
|
||||
|
||||
<h1>3.5.0 - Adaptive Theme, Timetable Editor & More</h1>
|
||||
<li>Added adaptive theme colour</li>
|
||||
<li>Added optional soft gradient for adaptive theme when viewing a class</li>
|
||||
|
||||
Reference in New Issue
Block a user