bridge for container info (case-insensitive)
This script should not be not be installed directly. It is a library for other scripts to include with the meta directive // @require https://update.greasyfork.org/scripts/566662/1756942/Container_Info_Bridge.js
// ==UserScript==
// @name Container_Info_Bridge
// @description Bridge for container info from extension
// @version 0.4
// ==/UserScript==
// ── Normalize key ─────────────────────────────────────────────────────────────
function normalizeContainerKey(str) {
if (!str || typeof str !== 'string') return null;
return str.trim().toLowerCase().replace(/\s+/g, '_');
}
// ── Parse identity name into parts ───────────────────────────────────────────
// "giosmithhhhhh_Netherlands8" → { username: "giosmithhhhhh", country: "Netherlands", number: "8" }
function parseIdentityName(name) {
if (!name) return { raw: null, username: null, country: null, number: null };
const underscoreIdx = name.lastIndexOf('_');
if (underscoreIdx === -1) return { raw: name, username: name, country: null, number: null };
const username = name.slice(0, underscoreIdx);
const countryRaw = name.slice(underscoreIdx + 1);
const match = countryRaw.match(/^([a-zA-Z]+)(\d*)$/);
const country = match ? match[1] : countryRaw;
const number = match && match[2] ? match[2] : null;
return { raw: name, username, country, number };
}
// ── Request raw container info from extension ─────────────────────────────────
function requestContainerInfo(timeout = 5 * 1000) {
return new Promise((resolve) => {
let settled = false;
function cleanup() {
settled = true;
window.removeEventListener('message', onMessage);
}
function onMessage(event) {
try {
const msg = event.data;
if (!msg || msg.action !== 'containerInfo') return;
let parsed = null;
if (typeof msg.containerInfo === 'string') {
try { parsed = JSON.parse(msg.containerInfo); }
catch (e) { console.warn('[Bridge] failed to JSON.parse containerInfo', e); }
} else if (typeof msg.containerInfo === 'object' && msg.containerInfo !== null) {
parsed = msg.containerInfo;
}
cleanup();
resolve(parsed ?? null);
} catch (e) {
console.error('[Bridge] error in onMessage', e);
}
}
window.addEventListener('message', onMessage);
try {
window.postMessage({ action: 'getContainerInfo' }, '*');
} catch (e) {
console.error('[Bridge] postMessage failed', e);
cleanup();
resolve(null);
}
setTimeout(() => {
if (!settled) {
cleanup();
console.warn('[Bridge] container info request timed out');
resolve(null);
}
}, timeout);
});
}
// ── Main exported function ────────────────────────────────────────────────────
const getContainerProfile = async () => {
const info = await requestContainerInfo();
if (!info) {
console.warn('[Bridge] no info received from extension');
return null;
}
const identity = info.identity ?? {};
const cookieStoreId = info.cookieStoreId ?? identity.cookieStoreId ?? null;
const parsed = parseIdentityName(identity.name ?? null);
return {
// directly parsed from identity.name
username: parsed.username,
country: parsed.country,
number: parsed.number,
// container
cookieStoreId,
ts: info.ts ?? null,
// full identity block
identity: {
name: identity.name ?? null,
icon: identity.icon ?? null,
iconUrl: identity.iconUrl ?? null,
color: identity.color ?? null,
colorCode: identity.colorCode ?? null,
},
// normalized lookup keys
keys: {
byName: normalizeContainerKey(identity.name),
byUsername: normalizeContainerKey(parsed.username),
byCookieStoreId: normalizeContainerKey(cookieStoreId),
},
};
};
// // ── self-test ─────────────────────────────────────────────────────────────────
// (async function testContainerBridge() {
// console.warn('[Bridge] requesting container profile...');
// const profile = await getContainerProfile();
// if (!profile) {
// console.warn('[Bridge] ❌ returned null — extension did not reply');
// return;
// }
// console.warn('[Bridge] ✅ username: ', profile.username);
// console.warn('[Bridge] ✅ country: ', profile.country);
// console.warn('[Bridge] ✅ number: ', profile.number);
// console.warn('[Bridge] ✅ cookieStoreId: ', profile.cookieStoreId);
// console.warn('[Bridge] ✅ identity.name: ', profile.identity.name);
// console.warn('[Bridge] ✅ full object: ', profile);
// })();