170 lines
4.6 KiB
JavaScript
170 lines
4.6 KiB
JavaScript
export function readTelegramMiniAppInitDataFromLocation() {
|
|
if (typeof window === "undefined") return "";
|
|
const queryText = window.location.search.replace(/^\?/, "");
|
|
const hashText = window.location.hash.replace(/^#/, "");
|
|
for (const text of [queryText, hashText]) {
|
|
if (!text) continue;
|
|
const params = new URLSearchParams(text);
|
|
const initData = params.get("tgWebAppData");
|
|
if (initData) return initData;
|
|
}
|
|
return "";
|
|
}
|
|
|
|
export function createTelegramSdk({
|
|
scriptUrl,
|
|
bootTimeoutMs,
|
|
actionTimeoutMs,
|
|
miniAppAuthTimeoutMs,
|
|
onStatusChange = () => {},
|
|
onInitDataChange = () => {},
|
|
} = {}) {
|
|
let tg = resolve();
|
|
let sdkPromise = null;
|
|
let launchParamsDetected = false;
|
|
let initData = tg?.initData || readTelegramMiniAppInitDataFromLocation();
|
|
if (initData) launchParamsDetected = true;
|
|
|
|
function resolve() {
|
|
return window.Telegram?.WebApp || null;
|
|
}
|
|
|
|
function setStatus(status) {
|
|
onStatusChange(status);
|
|
}
|
|
|
|
function refresh() {
|
|
tg = resolve();
|
|
if (tg) setStatus("ready");
|
|
initData = tg?.initData || readTelegramMiniAppInitDataFromLocation();
|
|
onInitDataChange(initData);
|
|
if (initData) launchParamsDetected = true;
|
|
return tg;
|
|
}
|
|
|
|
function hasLaunchParams() {
|
|
refresh();
|
|
if (launchParamsDetected || initData) {
|
|
launchParamsDetected = true;
|
|
return true;
|
|
}
|
|
const queryText = window.location.search.replace(/^\?/, "");
|
|
const hashText = window.location.hash.replace(/^#/, "");
|
|
const detected = [queryText, hashText].some((text) => {
|
|
if (!text) return false;
|
|
const params = new URLSearchParams(text);
|
|
return ["tgWebAppData", "tgWebAppVersion", "tgWebAppPlatform", "tgWebAppThemeParams"].some(
|
|
(key) => params.has(key)
|
|
);
|
|
});
|
|
if (detected) launchParamsDetected = true;
|
|
return detected;
|
|
}
|
|
|
|
function load(timeoutMs = bootTimeoutMs) {
|
|
if (refresh()) return Promise.resolve(tg);
|
|
if (sdkPromise) return sdkPromise;
|
|
if (typeof document === "undefined") return Promise.resolve(null);
|
|
|
|
setStatus("loading");
|
|
sdkPromise = new Promise((resolvePromise) => {
|
|
const existingScript = document.querySelector("script[data-rw-telegram-web-app-sdk]");
|
|
const script = existingScript || document.createElement("script");
|
|
let resolved = false;
|
|
let timeoutId = null;
|
|
|
|
const resolveOnce = (value) => {
|
|
if (resolved) return;
|
|
resolved = true;
|
|
if (timeoutId) window.clearTimeout(timeoutId);
|
|
resolvePromise(value);
|
|
};
|
|
|
|
const refreshFromScript = () => {
|
|
tg = resolve();
|
|
setStatus(tg ? "ready" : "unavailable");
|
|
return tg;
|
|
};
|
|
|
|
script.addEventListener("load", () => resolveOnce(refreshFromScript()), { once: true });
|
|
script.addEventListener(
|
|
"error",
|
|
() => {
|
|
setStatus("unavailable");
|
|
resolveOnce(null);
|
|
},
|
|
{ once: true }
|
|
);
|
|
|
|
if (!existingScript) {
|
|
script.src = scriptUrl;
|
|
script.async = true;
|
|
script.defer = true;
|
|
script.dataset.rwTelegramWebAppSdk = "1";
|
|
document.head.appendChild(script);
|
|
}
|
|
|
|
timeoutId = window.setTimeout(() => {
|
|
if (!tg) setStatus("unavailable");
|
|
resolveOnce(tg);
|
|
}, timeoutMs);
|
|
}).finally(() => {
|
|
sdkPromise = null;
|
|
});
|
|
return sdkPromise;
|
|
}
|
|
|
|
async function ensureForAction() {
|
|
if (refresh()) return tg;
|
|
return await load(actionTimeoutMs);
|
|
}
|
|
|
|
function createMiniAppAuthTimeout() {
|
|
const controller = typeof AbortController === "undefined" ? null : new AbortController();
|
|
let timedOut = false;
|
|
let timeoutId = null;
|
|
let timeoutPromise = new Promise(() => {});
|
|
|
|
if (typeof window !== "undefined") {
|
|
timeoutPromise = new Promise((_, reject) => {
|
|
timeoutId = window.setTimeout(() => {
|
|
timedOut = true;
|
|
controller?.abort();
|
|
const error = new Error("telegram_mini_app_auth_timeout");
|
|
error.name = "AbortError";
|
|
reject(error);
|
|
}, miniAppAuthTimeoutMs);
|
|
});
|
|
}
|
|
|
|
return {
|
|
promise: timeoutPromise,
|
|
get signal() {
|
|
return controller?.signal;
|
|
},
|
|
get timedOut() {
|
|
return timedOut;
|
|
},
|
|
clear() {
|
|
if (timeoutId) window.clearTimeout(timeoutId);
|
|
timeoutId = null;
|
|
},
|
|
};
|
|
}
|
|
|
|
return {
|
|
get tg() {
|
|
return tg;
|
|
},
|
|
get initData() {
|
|
return initData;
|
|
},
|
|
refresh,
|
|
hasLaunchParams,
|
|
load,
|
|
ensureForAction,
|
|
createMiniAppAuthTimeout,
|
|
readInitDataFromLocation: readTelegramMiniAppInitDataFromLocation,
|
|
};
|
|
}
|