(function () {
const supportedLanguages = ["en", "ar", "tr", "id"];
const languageLabels = {
en: "EN",
ar: "AR",
tr: "TR",
id: "ID"
};
const API_BASE_URL = "https://jvapi.haiyihy.com";
const fallbackMessages = {
en: {
document_title: "Host Center",
page_label: "Host Center",
back: "Back",
title: "Host Center",
language_button_aria: "Change language",
uid: "UID: 1234567890",
agency: "Agency: Bilibili(101013)",
streaming_duration: "Work Time (min)",
target: "Target",
daily_details: "Daily data",
gift_points: "Gift points",
online_minutes: "Online minutes",
no_daily_data: "No daily data",
close: "Close",
open_daily_data: "Open daily data",
my_income: "Salary",
join_agency_title: "Join Agency",
join_agency_text: "Search for an agency ID and submit your application.",
join_agency_action: "Join now",
agency_id: "Agency ID",
enter_agent_id: "Enter agency ID",
search: "Search",
searching: "Searching...",
agency_label: "Agency",
apply: "Apply",
applying: "Applying...",
found: "Agency found",
account_not_found: "Account not found or not an agency",
application_submitted: "Application submitted",
application_failed: "Application failed",
application_records: "Application Records",
pending: "Pending",
join_pending_note: "Application is pending. Please wait for agency approval.",
cancel: "Cancel",
cancelling: "Cancelling...",
cancellation_failed: "Cancellation failed",
application_cancelled: "Application cancelled",
missing_token: "Missing token",
network_error: "Network error. Please try again.",
withdraw_exchange: "Withdraw/Exchange",
open_withdraw_exchange: "Open withdraw and exchange page",
open_anchor_policy: "Open host policy",
anchor_policy: "Host Policy",
policy_loading: "Loading policy...",
policy_empty: "No policy data",
policy_missing_token: "Missing token",
policy_load_failed: "Failed to load policy",
policy_level: "Level",
policy_online: "Online (Hour)",
policy_effective_day: "Valid days",
policy_target: "Target",
policy_host_salary: "Host salary",
policy_agent_salary: "Agent salary",
policy_total_salary: "Total salary"
},
ar: {
document_title: "مركز المضيف",
page_label: "مركز المضيف",
back: "رجوع",
title: "مركز المضيف",
language_button_aria: "تغيير اللغة",
uid: "معرّف المستخدم: 1234567890",
agency: "الوكالة: Bilibili(101013)",
streaming_duration: "وقت العمل (دقيقة)",
target: "الهدف",
daily_details: "البيانات اليومية",
gift_points: "نقاط الهدايا",
online_minutes: "دقائق الاتصال",
no_daily_data: "لا توجد بيانات يومية",
close: "إغلاق",
open_daily_data: "فتح البيانات اليومية",
my_income: "الراتب",
join_agency_title: "الانضمام إلى وكالة",
join_agency_text: "ابحث عن معرّف وكالة وأرسل طلبك.",
join_agency_action: "انضم الآن",
agency_id: "معرّف الوكالة",
enter_agent_id: "أدخل معرّف الوكالة",
search: "بحث",
searching: "جار البحث...",
agency_label: "الوكالة",
apply: "تقديم",
applying: "جار التقديم...",
found: "تم العثور على الوكالة",
account_not_found: "لم يتم العثور على الحساب أو ليس وكالة",
application_submitted: "تم إرسال الطلب",
application_failed: "فشل إرسال الطلب",
application_records: "سجلات الطلب",
pending: "قيد الانتظار",
join_pending_note: "الطلب قيد الانتظار. يرجى انتظار موافقة الوكالة.",
cancel: "إلغاء",
cancelling: "جار الإلغاء...",
cancellation_failed: "فشل الإلغاء",
application_cancelled: "تم إلغاء الطلب",
missing_token: "رمز الدخول مفقود",
network_error: "خطأ في الشبكة. حاول مرة أخرى.",
withdraw_exchange: "سحب/استبدال",
open_withdraw_exchange: "فتح صفحة السحب والاستبدال",
open_anchor_policy: "فتح سياسة المضيف",
anchor_policy: "سياسة المضيف",
policy_loading: "جار تحميل السياسة...",
policy_empty: "لا توجد بيانات سياسة",
policy_missing_token: "رمز الدخول مفقود",
policy_load_failed: "فشل تحميل السياسة",
policy_level: "المستوى",
policy_online: "الاتصال (ساعة)",
policy_effective_day: "الأيام الصالحة",
policy_target: "الهدف",
policy_host_salary: "راتب المضيف",
policy_agent_salary: "راتب الوكيل",
policy_total_salary: "إجمالي الراتب"
},
tr: {
document_title: "Host Merkezi",
page_label: "Host Merkezi",
back: "Geri",
title: "Host Merkezi",
language_button_aria: "Dili değiştir",
uid: "UID: 1234567890",
agency: "Ajans: Bilibili(101013)",
streaming_duration: "Çalışma Süresi (dk)",
target: "Hedef",
daily_details: "Günlük veri",
gift_points: "Hediye puanı",
online_minutes: "Online dakika",
no_daily_data: "Günlük veri yok",
close: "Kapat",
open_daily_data: "Günlük veriyi aç",
my_income: "Maaş",
join_agency_title: "Ajansa Katıl",
join_agency_text: "Ajans ID ile arama yapıp başvurunu gönder.",
join_agency_action: "Şimdi katıl",
agency_id: "Ajans ID",
enter_agent_id: "Ajans ID gir",
search: "Ara",
searching: "Aranıyor...",
agency_label: "Ajans",
apply: "Başvur",
applying: "Başvuruluyor...",
found: "Ajans bulundu",
account_not_found: "Hesap bulunamadı veya ajans değil",
application_submitted: "Başvuru gönderildi",
application_failed: "Başvuru başarısız",
application_records: "Başvuru Kayıtları",
pending: "Beklemede",
join_pending_note: "Başvuru beklemede. Lütfen ajans onayını bekleyin.",
cancel: "İptal",
cancelling: "İptal ediliyor...",
cancellation_failed: "İptal başarısız",
application_cancelled: "Başvuru iptal edildi",
missing_token: "Token eksik",
network_error: "Ağ hatası. Lütfen tekrar deneyin.",
withdraw_exchange: "Çek/Değiştir",
open_withdraw_exchange: "Çekme ve değişim sayfasını aç",
open_anchor_policy: "Host politikasını aç",
anchor_policy: "Host Politikası",
policy_loading: "Politika yükleniyor...",
policy_empty: "Politika verisi yok",
policy_missing_token: "Token eksik",
policy_load_failed: "Politika yüklenemedi",
policy_level: "Seviye",
policy_online: "Online (Saat)",
policy_effective_day: "Geçerli gün",
policy_target: "Hedef",
policy_host_salary: "Host maaşı",
policy_agent_salary: "Ajans maaşı",
policy_total_salary: "Toplam maaş"
},
id: {
document_title: "Pusat Host",
page_label: "Pusat Host",
back: "Kembali",
title: "Pusat Host",
language_button_aria: "Ubah bahasa",
uid: "UID: 1234567890",
agency: "Agensi: Bilibili(101013)",
streaming_duration: "Waktu Kerja (mnt)",
target: "Target",
daily_details: "Data harian",
gift_points: "Poin hadiah",
online_minutes: "Menit online",
no_daily_data: "Tidak ada data harian",
close: "Tutup",
open_daily_data: "Buka data harian",
my_income: "Gaji",
join_agency_title: "Gabung Agensi",
join_agency_text: "Cari ID agensi dan kirim pengajuan Anda.",
join_agency_action: "Gabung sekarang",
agency_id: "ID Agensi",
enter_agent_id: "Masukkan ID agensi",
search: "Cari",
searching: "Mencari...",
agency_label: "Agensi",
apply: "Ajukan",
applying: "Mengajukan...",
found: "Agensi ditemukan",
account_not_found: "Akun tidak ditemukan atau bukan agensi",
application_submitted: "Pengajuan terkirim",
application_failed: "Pengajuan gagal",
application_records: "Catatan Pengajuan",
pending: "Menunggu",
join_pending_note: "Pengajuan sedang menunggu. Harap tunggu persetujuan agensi.",
cancel: "Batal",
cancelling: "Membatalkan...",
cancellation_failed: "Gagal membatalkan",
application_cancelled: "Pengajuan dibatalkan",
missing_token: "Token tidak ditemukan",
network_error: "Kesalahan jaringan. Silakan coba lagi.",
withdraw_exchange: "Tarik/Tukar",
open_withdraw_exchange: "Buka halaman tarik dan tukar",
open_anchor_policy: "Buka kebijakan host",
anchor_policy: "Kebijakan Host",
policy_loading: "Memuat kebijakan...",
policy_empty: "Tidak ada data kebijakan",
policy_missing_token: "Token tidak ditemukan",
policy_load_failed: "Gagal memuat kebijakan",
policy_level: "Level",
policy_online: "Online (Jam)",
policy_effective_day: "Hari valid",
policy_target: "Target",
policy_host_salary: "Gaji host",
policy_agent_salary: "Gaji agensi",
policy_total_salary: "Total gaji"
}
};
const params = readURLParams();
let currentLang = normalizeLanguage(params.get("lang"));
let currentMessages = fallbackMessages[currentLang] || fallbackMessages.en;
let currentProfile = null;
let currentAgencyProfile = null;
let currentTeamId = "";
let currentIdentity = null;
let currentSalary = "0.00";
let currentStreamingDuration = "0";
let currentGiftValue = "0";
let currentDailyTargets = [];
let foundJoinAgency = null;
let pendingJoinRecord = null;
function readURLParams() {
const result = new URLSearchParams(window.location.search);
const hashQuery = window.location.hash.includes("?") ? window.location.hash.split("?")[1] : "";
const hashParams = new URLSearchParams(hashQuery);
hashParams.forEach((value, key) => {
if (!result.has(key)) result.set(key, value);
});
return result;
}
function readRawParam(name) {
const queries = [window.location.search.replace(/^\?/, "")];
if (window.location.hash.includes("?")) queries.push(window.location.hash.split("?")[1]);
for (const query of queries) {
for (const part of query.split("&")) {
if (!part) continue;
const equalIndex = part.indexOf("=");
const rawKey = equalIndex >= 0 ? part.slice(0, equalIndex) : part;
const rawValue = equalIndex >= 0 ? part.slice(equalIndex + 1) : "";
let decodedKey = "";
try {
decodedKey = decodeURIComponent(rawKey);
} catch (error) {
continue;
}
if (decodedKey !== name) continue;
try {
return decodeURIComponent(rawValue.replace(/\+/g, "%2B"));
} catch (error) {
return rawValue;
}
}
}
return "";
}
function normalizeLanguage(lang) {
const value = String(lang || "en").toLowerCase();
return supportedLanguages.includes(value) ? value : "en";
}
async function loadMessages(lang) {
const normalizedLang = normalizeLanguage(lang);
if (window.location.protocol === "file:") return fallbackMessages[normalizedLang];
try {
const response = await fetch(`./locales/${normalizedLang}.json?v=20260428-2070`, { cache: "no-store" });
if (response.ok) return await response.json();
} catch (error) {
return fallbackMessages[normalizedLang];
}
return fallbackMessages[normalizedLang];
}
function localizedValue(messages, key) {
return messages?.[key] || fallbackMessages[currentLang]?.[key] || fallbackMessages.en[key] || "";
}
function message(key, fallback = "") {
return localizedValue(currentMessages, key) || fallback || key;
}
function renderMessages(messages) {
document.querySelectorAll("[data-i18n]").forEach((node) => {
const value = localizedValue(messages, node.dataset.i18n);
if (value) node.textContent = value;
});
document.querySelectorAll("[data-i18n-html]").forEach((node) => {
const value = localizedValue(messages, node.dataset.i18nHtml);
if (value) node.innerHTML = value;
});
document.querySelectorAll("[data-i18n-aria]").forEach((node) => {
const value = localizedValue(messages, node.dataset.i18nAria);
if (value) node.setAttribute("aria-label", value);
});
document.querySelectorAll("[data-i18n-placeholder]").forEach((node) => {
const value = localizedValue(messages, node.dataset.i18nPlaceholder);
if (value) node.setAttribute("placeholder", value);
});
}
function apiBaseURL() {
const override = window.HYAPP_API_BASE_URL || params.get("apiBase");
if (override) return String(override).replace(/\/+$/, "");
return API_BASE_URL.replace(/\/+$/, "");
}
function normalizeAuthorization(token) {
const value = String(token || "").trim();
if (!value) return "";
return /^bearer\s+/i.test(value) ? value : `Bearer ${value}`;
}
function authHeadersFromToken(token) {
return {
Authorization: normalizeAuthorization(token),
"req-lang": currentLang,
"req-client": "H5",
"req-version": "V2",
"req-zone": Intl.DateTimeFormat().resolvedOptions().timeZone || "Asia/Shanghai",
"req-app-intel": "version=1.0.0;build=1;model=H5;sysVersion=Web;channel=Web",
"req-sys-origin": "origin=ATYOU;originChild=ATYOU"
};
}
async function requestJSON(path, options = {}) {
const token = readRawParam("token");
if (!token) throw new Error(message("missing_token", "Missing token"));
const headers = authHeadersFromToken(token);
const request = {
method: options.method || "GET",
cache: "no-store",
headers
};
if (options.body !== undefined) {
headers["Content-Type"] = "application/json";
request.body = JSON.stringify(options.body);
}
const response = await fetch(new URL(path, `${apiBaseURL()}/`).toString(), request);
const data = await response.json().catch(() => ({}));
if (!response.ok || data.status === false) {
const error = new Error(data.errorMsg || data.message || `Request failed: ${response.status}`);
error.response = data;
throw error;
}
return data.body ?? data.data ?? null;
}
function profileUidPrefix(messages) {
const template = messages.uid || fallbackMessages.en.uid;
const marker = "1234567890";
return template.includes(marker) ? template.replace(marker, "").trim() : "UID:";
}
function pickProfileName(profile) {
return profile?.userNickname || profile?.name || "Oscar";
}
function pickProfileAccount(profile) {
return profile?.ownSpecialId?.account || profile?.account || profile?.id || "1234567890";
}
function agencyPrefix(messages) {
const template = messages.agency || fallbackMessages.en.agency;
const marker = "Bilibili(101013)";
return template.includes(marker) ? template.replace(marker, "").trim() : "Agency:";
}
function pickAgencyName(profile) {
return profile?.userNickname || profile?.name || profile?.teamName || "-";
}
function pickAgencyAccount(profile) {
return profile?.ownSpecialId?.account || profile?.account || profile?.id || "";
}
function formatAgencyText(profile, messages = currentMessages) {
const prefix = agencyPrefix(messages);
if (!profile) return `${prefix} -`;
const name = pickAgencyName(profile);
const account = pickAgencyAccount(profile);
return account ? `${prefix} ${name}(${account})` : `${prefix} ${name}`;
}
function renderAgencyProfile(profile, messages = currentMessages) {
const agencyButton = document.querySelector(".agency");
const agencyTextNode = document.querySelector(".agency span:first-child");
if (!agencyButton || !agencyTextNode) return;
agencyTextNode.textContent = formatAgencyText(profile, messages);
agencyButton.dataset.teamId = String(currentTeamId || pickAgencyTeamId(profile) || "");
agencyButton.dataset.account = String(profile?.account || "");
agencyButton.dataset.specialAccount = String(profile?.ownSpecialId?.account || "");
syncPolicyLink();
}
function pickSpecialAccount(profile) {
return profile?.ownSpecialId?.account ||
profile?.specialId?.account ||
profile?.specialAccount ||
profile?.shortAccount ||
profile?.shortId ||
"";
}
function pickJoinAgencyProfile(body) {
return body?.ownUserProfile || body?.userProfile || body?.teamProfile || body || null;
}
function pickSearchAgency(body) {
const teamProfile = body?.teamProfile || null;
const userProfile = body?.ownUserProfile || body?.userProfile || teamProfile?.ownUserProfile || teamProfile?.userProfile || null;
if (!teamProfile?.id) return null;
const specialAccount = pickSpecialAccount(userProfile) || pickSpecialAccount(teamProfile);
return {
...(teamProfile || {}),
...(userProfile || {}),
id: teamProfile.id,
teamId: teamProfile.id,
teamName: teamProfile.teamName || userProfile?.teamName || "",
userNickname: userProfile?.userNickname || teamProfile.userNickname || teamProfile.name || teamProfile.teamName || "",
name: userProfile?.name || teamProfile.name || teamProfile.teamName || "",
userAvatar: userProfile?.userAvatar || teamProfile.userAvatar || userProfile?.avatar || teamProfile.avatar || "",
avatar: userProfile?.avatar || teamProfile.avatar || userProfile?.userAvatar || teamProfile.userAvatar || "",
displayAccount: specialAccount || userProfile?.account || teamProfile.account || "",
account: userProfile?.account || teamProfile.account || "",
ownSpecialId: userProfile?.ownSpecialId || teamProfile.ownSpecialId || (specialAccount ? { account: specialAccount } : null),
specialId: userProfile?.specialId || teamProfile.specialId || null,
specialAccount,
shortAccount: userProfile?.shortAccount || teamProfile.shortAccount || "",
shortId: userProfile?.shortId || teamProfile.shortId || ""
};
}
function pickJoinAgencyName(profile) {
return profile?.userNickname || profile?.name || profile?.teamName || "-";
}
function pickJoinAgencyAccount(profile) {
return pickSpecialAccount(profile) || profile?.displayAccount || profile?.account || profile?.id || "-";
}
function pickAgencyTeamId(profile) {
return profile?.teamId || profile?.teamProfile?.id || profile?.id || "";
}
function pickTeamEntryId(entry) {
return entry?.teamProfile?.id || entry?.teamId || entry?.id || "";
}
function removeAvatarFallback() {
document.querySelector("#profileAvatarFallback")?.remove();
}
function ensureAvatarFallback(displayName) {
const avatarShell = document.querySelector(".avatar-shell");
if (!avatarShell) return null;
let avatarFallback = document.querySelector("#profileAvatarFallback");
if (avatarFallback) {
avatarFallback.hidden = false;
avatarFallback.setAttribute("aria-label", `${displayName} avatar`);
return avatarFallback;
}
const template = document.createElement("template");
template.innerHTML = `
`;
avatarFallback = template.content.firstElementChild;
avatarFallback.setAttribute("aria-label", `${displayName} avatar`);
avatarShell.appendChild(avatarFallback);
return avatarFallback;
}
function renderProfile(profile, messages = currentMessages) {
if (!profile) return;
const profileCard = document.querySelector(".profile-card");
const nameNode = document.querySelector("#profileName");
const uidNode = document.querySelector("#profileUid");
const avatarImage = document.querySelector("#profileAvatar");
const displayName = pickProfileName(profile);
const displayAccount = pickProfileAccount(profile);
if (profileCard) {
profileCard.dataset.userId = String(profile.id || "");
profileCard.dataset.account = String(profile.account || "");
profileCard.dataset.specialAccount = String(profile?.ownSpecialId?.account || "");
}
if (nameNode) nameNode.textContent = displayName;
if (uidNode) uidNode.textContent = `${profileUidPrefix(messages)} ${displayAccount}`.trim();
if (!avatarImage) return;
const avatar = profile.userAvatar ? String(profile.userAvatar) : "";
avatarImage.alt = displayName;
if (!avatar) {
avatarImage.hidden = true;
avatarImage.onerror = null;
avatarImage.removeAttribute("src");
ensureAvatarFallback(displayName);
return;
}
avatarImage.hidden = false;
removeAvatarFallback();
avatarImage.onerror = () => {
avatarImage.hidden = true;
avatarImage.removeAttribute("src");
ensureAvatarFallback(displayName);
};
avatarImage.src = avatar;
}
function hasOwn(object, key) {
return Boolean(object && Object.prototype.hasOwnProperty.call(object, key));
}
function isTruthyIdentityValue(value) {
if (typeof value === "boolean") return value;
if (typeof value === "number") return value === 1;
if (typeof value === "string") return ["true", "1", "yes"].includes(value.toLowerCase());
return false;
}
function shouldOpenJoinAgency(identity) {
if (!hasOwn(identity, "anchor")) return false;
return !isTruthyIdentityValue(identity.anchor);
}
function setLoading(isLoading) {
const root = document.querySelector(".host-center");
const loadingMask = document.querySelector("#loadingMask");
if (root) root.dataset.loading = isLoading ? "true" : "false";
if (loadingMask) {
loadingMask.hidden = !isLoading;
loadingMask.setAttribute("aria-busy", String(isLoading));
}
}
function setIdentityView(identity) {
const root = document.querySelector(".host-center");
const showJoinAgency = shouldOpenJoinAgency(identity);
if (root) root.dataset.view = showJoinAgency ? "join-agency" : "host";
document.querySelectorAll(".host-only").forEach((node) => {
node.hidden = showJoinAgency;
});
const joinAgencyCard = document.querySelector("#joinAgencyCard");
if (joinAgencyCard) joinAgencyCard.hidden = !showJoinAgency;
const agencyButton = document.querySelector(".agency");
if (agencyButton) agencyButton.hidden = showJoinAgency;
}
function closeHostCenterPage() {
try {
if (window.app && typeof window.app.closePage === "function") {
window.app.closePage();
return;
}
if (window.FlutterPageControl && typeof window.FlutterPageControl.postMessage === "function") {
window.FlutterPageControl.postMessage("close_page");
return;
}
if (window.history.length > 1) window.history.back();
} catch (error) {
console.error("close host center page failed:", error);
if (window.history.length > 1) window.history.back();
}
}
function formatCurrentSalary(value) {
const numericValue = Number(value);
if (Number.isFinite(numericValue)) return numericValue.toFixed(2);
return "0.00";
}
function pickCurrentSalary(body) {
if (typeof body === "number") return body;
if (body && typeof body === "object") {
return body.currentSalary ?? body.availableBalance ?? body.balance ?? 0;
}
return 0;
}
function renderCurrentSalary(value) {
currentSalary = formatCurrentSalary(value);
const salaryNode = document.querySelector("#currentSalary");
if (salaryNode) salaryNode.textContent = currentSalary;
}
function formatStreamingDuration(value) {
const numericValue = Number(value);
if (!Number.isFinite(numericValue)) return "0";
const safeValue = Math.max(0, numericValue);
return Number.isInteger(safeValue) ? String(safeValue) : String(Number(safeValue.toFixed(2)));
}
function pickStreamingDuration(body) {
const workTarget = pickFirstMemberWorkTarget(body);
return body?.onlineTime ?? body?.target?.onlineTime ?? workTarget?.target?.onlineTime ?? workTarget?.onlineTime ?? 0;
}
function renderStreamingDuration(value) {
currentStreamingDuration = formatStreamingDuration(value);
const durationNode = document.querySelector("#streamingDuration");
if (durationNode) durationNode.textContent = currentStreamingDuration;
}
function formatCountValue(value) {
if (value === null || value === undefined || value === "") return "-";
const number = Number(value);
if (Number.isFinite(number) && Number.isInteger(number)) return String(number);
if (Number.isFinite(number)) return String(Number(number.toFixed(2)));
return String(value);
}
function renderCurrentGiftValue(value) {
currentGiftValue = formatCountValue(value === null || value === undefined || value === "" ? 0 : value);
const giftNode = document.querySelector("#currentGiftValue");
const dailyGiftNode = document.querySelector("#dailyCurrentGift");
if (giftNode) giftNode.textContent = currentGiftValue;
if (dailyGiftNode) dailyGiftNode.textContent = currentGiftValue;
}
function pickFirstMemberWorkTarget(body) {
const targets = Array.isArray(body?.targets) ? body.targets : [];
return targets[0] || body?.target || null;
}
function pickGiftValue(workTarget) {
const target = workTarget?.target || workTarget || {};
return target.acceptGiftValue ?? target.giftValue ?? target.giftScore ?? target.currentGiftValue ?? null;
}
function pickDailyTargets(workTarget) {
const target = workTarget?.target || workTarget || {};
return Array.isArray(target.dailyTargets) ? target.dailyTargets : [];
}
function formatDateNumber(value) {
const text = String(value || "");
if (/^\d{8}$/.test(text)) {
return `${text.slice(0, 4)}.${text.slice(4, 6)}.${text.slice(6, 8)}`;
}
return text || "-";
}
function createDailyRow(item) {
const row = document.createElement("div");
row.className = "daily-row";
const date = document.createElement("div");
date.className = "daily-date";
date.textContent = formatDateNumber(item?.dateNumber);
const values = document.createElement("div");
values.className = "daily-values";
const gift = document.createElement("div");
gift.className = "daily-cell";
gift.innerHTML = `${currentMessages.gift_points || fallbackMessages.en.gift_points}${formatCountValue(item?.acceptGiftValue ?? 0)}`;
const online = document.createElement("div");
online.className = "daily-cell";
online.innerHTML = `${currentMessages.online_minutes || fallbackMessages.en.online_minutes}${formatCountValue(item?.onlineTime ?? 0)}`;
values.appendChild(gift);
values.appendChild(online);
row.appendChild(date);
row.appendChild(values);
return row;
}
function replaceNodeChildren(node, children) {
while (node.firstChild) node.removeChild(node.firstChild);
children.forEach((child) => node.appendChild(child));
}
function renderDailyTargets(targets = currentDailyTargets) {
currentDailyTargets = Array.isArray(targets) ? targets : [];
const list = document.querySelector("#dailyList");
if (!list) return;
if (!currentDailyTargets.length) {
const empty = document.createElement("div");
empty.className = "daily-empty";
empty.textContent = currentMessages.no_daily_data || fallbackMessages.en.no_daily_data;
replaceNodeChildren(list, [empty]);
return;
}
replaceNodeChildren(list, currentDailyTargets.map(createDailyRow));
}
function updateModalBodyLock() {
const hasOpenModal = Array.from(document.querySelectorAll(".daily-modal, .join-agency-modal")).some((modal) => !modal.hidden);
document.body.classList.toggle("daily-modal-open", hasOpenModal);
}
function renderMemberWorkSummary(memberWork) {
const workTarget = pickFirstMemberWorkTarget(memberWork);
renderStreamingDuration(pickStreamingDuration(memberWork));
renderCurrentGiftValue(pickGiftValue(workTarget) ?? 0);
renderDailyTargets(pickDailyTargets(workTarget));
}
function setDailyModalOpen(open) {
const modal = document.querySelector("#dailyModal");
if (!modal) return;
modal.hidden = !open;
updateModalBodyLock();
if (open) renderDailyTargets();
}
function showJoinAgencyStatus(text, type = "") {
const node = document.querySelector("#joinAgencyStatus");
if (!node) return;
node.textContent = text || "";
node.hidden = !text;
node.classList.toggle("is-error", type === "error");
node.classList.toggle("is-success", type === "success");
}
function renderJoinAgencyAvatar(profile, imageSelector, fallbackSelector) {
const image = document.querySelector(imageSelector);
const fallback = document.querySelector(fallbackSelector);
if (!image || !fallback) return;
const name = pickJoinAgencyName(profile);
const avatar = profile?.userAvatar || profile?.avatar || "";
fallback.textContent = String(name || "A").slice(0, 1).toUpperCase() || "A";
image.alt = name;
if (!avatar) {
image.hidden = true;
image.removeAttribute("src");
fallback.hidden = false;
return;
}
fallback.hidden = true;
image.hidden = false;
image.onerror = () => {
image.hidden = true;
image.removeAttribute("src");
fallback.hidden = false;
};
image.src = avatar;
}
function syncJoinAgencyApplyAvailability() {
const button = document.querySelector("#joinAgencyApplyButton");
if (button) button.hidden = Boolean(pendingJoinRecord) || !foundJoinAgency?.id;
const cancelButton = document.querySelector("#joinAgencyCancelButton");
if (cancelButton) cancelButton.hidden = !pendingJoinRecord || !pickPendingJoinRecordId(pendingJoinRecord);
}
function pickPendingJoinRecordId(record) {
return record?.messageId || record?.id || "";
}
function renderFoundJoinAgency(profile = foundJoinAgency) {
const card = document.querySelector("#joinAgencyResult");
if (!card) return;
if (!profile) {
card.hidden = true;
syncJoinAgencyApplyAvailability();
return;
}
card.hidden = false;
const nameNode = document.querySelector("#joinAgencyName");
const accountNode = document.querySelector("#joinAgencyAccountText");
if (nameNode) nameNode.textContent = pickJoinAgencyName(profile);
if (accountNode) accountNode.textContent = `${profileUidPrefix(currentMessages)} ${pickJoinAgencyAccount(profile)}`.trim();
renderJoinAgencyAvatar(profile, "#joinAgencyAvatar", "#joinAgencyAvatarFallback");
syncJoinAgencyApplyAvailability();
}
function renderPendingJoinRecord(record = pendingJoinRecord) {
const card = document.querySelector("#joinAgencyPending");
if (!card) return;
if (!record) {
card.hidden = true;
syncJoinAgencyApplyAvailability();
return;
}
const profile = pickJoinAgencyProfile(record);
card.hidden = false;
const nameNode = document.querySelector("#joinAgencyPendingName");
const accountNode = document.querySelector("#joinAgencyPendingAccount");
if (nameNode) nameNode.textContent = pickJoinAgencyName(profile);
if (accountNode) accountNode.textContent = `${profileUidPrefix(currentMessages)} ${pickJoinAgencyAccount(profile)}`.trim();
renderJoinAgencyAvatar(profile, "#joinAgencyPendingAvatar", "#joinAgencyPendingAvatarFallback");
syncJoinAgencyApplyAvailability();
}
function joinAgencyErrorMessage(error, fallbackKey) {
return error?.response?.errorMsg || error?.response?.message || error?.message || message(fallbackKey);
}
async function fetchPendingJoinRecord() {
try {
pendingJoinRecord = await requestJSON("/team/wait-apply/profile");
renderPendingJoinRecord(pendingJoinRecord);
return pendingJoinRecord;
} catch (error) {
pendingJoinRecord = null;
renderPendingJoinRecord(null);
if (error.message === message("missing_token")) showJoinAgencyStatus(error.message, "error");
return null;
}
}
async function searchJoinAgency(event) {
event?.preventDefault();
const input = document.querySelector("#joinAgencyAccount");
const button = document.querySelector("#joinAgencySearchButton");
const account = String(input?.value || "").trim();
if (!account) {
showJoinAgencyStatus(message("enter_agent_id"), "error");
return;
}
foundJoinAgency = null;
renderFoundJoinAgency(null);
if (button) {
button.disabled = true;
button.textContent = message("searching");
}
showJoinAgencyStatus("");
try {
const body = await requestJSON(`/team/search-account?account=${encodeURIComponent(account)}`);
const profile = pickSearchAgency(body);
if (!profile?.id) {
showJoinAgencyStatus(message("account_not_found"), "error");
return;
}
foundJoinAgency = profile;
renderFoundJoinAgency(foundJoinAgency);
showJoinAgencyStatus(message("found"), "success");
} catch (error) {
foundJoinAgency = null;
renderFoundJoinAgency(null);
showJoinAgencyStatus(joinAgencyErrorMessage(error, "network_error"), "error");
} finally {
if (button) {
button.disabled = false;
button.textContent = message("search");
}
}
}
async function applyToJoinAgency() {
if (pendingJoinRecord || !foundJoinAgency?.id) return;
const button = document.querySelector("#joinAgencyApplyButton");
if (button) {
button.disabled = true;
button.textContent = message("applying");
}
showJoinAgencyStatus("");
try {
const appliedAgency = foundJoinAgency;
await requestJSON("/team/user/apply", {
method: "POST",
body: {
teamId: appliedAgency.id,
reason: "JOIN"
}
});
foundJoinAgency = null;
renderFoundJoinAgency(null);
showJoinAgencyStatus(message("application_submitted"), "success");
const pending = await fetchPendingJoinRecord();
if (!pending) {
pendingJoinRecord = { ownUserProfile: appliedAgency };
renderPendingJoinRecord(pendingJoinRecord);
}
} catch (error) {
showJoinAgencyStatus(joinAgencyErrorMessage(error, "application_failed"), "error");
} finally {
if (button) {
button.disabled = false;
button.textContent = message("apply");
}
syncJoinAgencyApplyAvailability();
}
}
async function cancelJoinApplication() {
const id = pickPendingJoinRecordId(pendingJoinRecord);
if (!id) return;
const button = document.querySelector("#joinAgencyCancelButton");
if (button) {
button.disabled = true;
button.textContent = message("cancelling");
}
showJoinAgencyStatus("");
try {
await requestJSON("/team/user/join-apply-cancel", {
method: "POST",
body: { id }
});
pendingJoinRecord = null;
renderPendingJoinRecord(null);
showJoinAgencyStatus(message("application_cancelled"), "success");
} catch (error) {
showJoinAgencyStatus(joinAgencyErrorMessage(error, "cancellation_failed"), "error");
} finally {
if (button) {
button.disabled = false;
button.textContent = message("cancel");
}
syncJoinAgencyApplyAvailability();
}
}
function setJoinAgencyModalOpen(open) {
const modal = document.querySelector("#joinAgencyModal");
if (!modal) return;
modal.hidden = !open;
updateModalBodyLock();
if (!open) return;
showJoinAgencyStatus("");
fetchPendingJoinRecord();
window.setTimeout(() => {
document.querySelector("#joinAgencyAccount")?.focus();
}, 0);
}
async function fetchUserProfile() {
const token = readRawParam("token");
if (!token) {
console.warn("Missing token for /team/member/profile");
return null;
}
try {
const url = new URL("/team/member/profile", `${apiBaseURL()}/`);
const response = await fetch(url.toString(), {
cache: "no-store",
headers: authHeadersFromToken(token)
});
const data = await response.json().catch(() => ({}));
if (!response.ok || data.status === false) {
throw new Error(data.errorMsg || data.message || `Request failed: ${response.status}`);
}
currentProfile = data.body || data.data || {};
renderProfile(currentProfile);
return currentProfile;
} catch (error) {
console.error("Failed to load user profile:", error);
return null;
}
}
async function fetchIdentity() {
const token = readRawParam("token");
if (!token) {
console.warn("Missing token for /app/h5/identity");
return null;
}
try {
const url = new URL("/app/h5/identity", `${apiBaseURL()}/`);
const response = await fetch(url.toString(), {
cache: "no-store",
headers: authHeadersFromToken(token)
});
const data = await response.json().catch(() => ({}));
if (!response.ok || data.status === false) {
throw new Error(data.errorMsg || data.message || `Request failed: ${response.status}`);
}
currentIdentity = data.body || data.data || {};
return currentIdentity;
} catch (error) {
console.error("Failed to load H5 identity:", error);
return null;
}
}
async function fetchAgencyProfile() {
const token = readRawParam("token");
if (!token) {
console.warn("Missing token for /team/team-own/profile");
renderAgencyProfile(null);
return null;
}
try {
const url = new URL("/team/team-own/profile", `${apiBaseURL()}/`);
const response = await fetch(url.toString(), {
cache: "no-store",
headers: authHeadersFromToken(token)
});
const data = await response.json().catch(() => ({}));
if (!response.ok || data.status === false) {
throw new Error(data.errorMsg || data.message || `Request failed: ${response.status}`);
}
currentAgencyProfile = data.body || data.data || null;
renderAgencyProfile(currentAgencyProfile);
return currentAgencyProfile;
} catch (error) {
console.error("Failed to load agency profile:", error);
renderAgencyProfile(null);
return null;
}
}
async function fetchTeamEntry() {
const token = readRawParam("token");
if (!token) {
console.warn("Missing token for /team/entry");
return "";
}
try {
const url = new URL("/team/entry", `${apiBaseURL()}/`);
const response = await fetch(url.toString(), {
cache: "no-store",
headers: authHeadersFromToken(token)
});
const data = await response.json().catch(() => ({}));
if (!response.ok || data.status === false) {
throw new Error(data.errorMsg || data.message || `Request failed: ${response.status}`);
}
currentTeamId = pickTeamEntryId(data.body || data.data || {});
renderAgencyProfile(currentAgencyProfile);
syncPolicyLink();
return currentTeamId;
} catch (error) {
console.error("Failed to load team entry:", error);
return "";
}
}
async function fetchBankBalance() {
const token = readRawParam("token");
if (!token) {
console.warn("Missing token for /wallet/bank/balance");
return;
}
try {
const url = new URL("/wallet/bank/balance", `${apiBaseURL()}/`);
const response = await fetch(url.toString(), {
cache: "no-store",
headers: authHeadersFromToken(token)
});
const data = await response.json().catch(() => ({}));
if (!response.ok || data.status === false) {
throw new Error(data.errorMsg || data.message || `Request failed: ${response.status}`);
}
renderCurrentSalary(pickCurrentSalary(data.body ?? data.data));
} catch (error) {
console.error("Failed to load bank balance:", error);
renderCurrentSalary(0);
}
}
async function fetchStreamingDuration(memberId) {
const memberWork = await fetchMemberWork(memberId);
renderMemberWorkSummary(memberWork);
return memberWork;
}
async function fetchMemberWork(memberId) {
if (!memberId) {
console.warn("Missing memberId for /team/member-work");
return null;
}
try {
const url = new URL("/team/member-work", `${apiBaseURL()}/`);
url.searchParams.set("userId", String(memberId));
const token = readRawParam("token");
if (!token) {
console.warn("Missing token for /team/member-work");
return null;
}
const response = await fetch(url.toString(), {
cache: "no-store",
headers: authHeadersFromToken(token)
});
const data = await response.json().catch(() => ({}));
if (!response.ok || data.status === false) {
throw new Error(data.errorMsg || data.message || `Request failed: ${response.status}`);
}
return data.body || data.data || null;
} catch (error) {
console.error("Failed to load member work:", error);
return null;
}
}
function syncLocalizedLinks() {
const nextParams = new URLSearchParams(params);
const token = readRawParam("token");
if (token) nextParams.set("token", token);
if (currentLang) nextParams.set("lang", currentLang);
const query = nextParams.toString();
document.querySelectorAll('a[href^="../withdraw-exchange/index.html"]').forEach((link) => {
link.setAttribute("href", `../withdraw-exchange/index.html${query ? `?${query}` : ""}`);
});
}
function syncPolicyLink() {
const link = document.querySelector("#anchorPolicyLink");
if (!link) return;
const nextParams = new URLSearchParams(params);
const token = readRawParam("token");
const teamId = currentTeamId;
if (token) nextParams.set("token", token);
if (currentLang) nextParams.set("lang", currentLang);
if (teamId) nextParams.set("teamId", teamId);
const query = nextParams.toString();
link.setAttribute("href", `./policy.html${query ? `?${query}` : ""}`);
}
function setLanguageMenuOpen(open) {
const languageButton = document.querySelector(".language-button");
const languageMenu = document.querySelector(".language-menu");
if (!languageButton || !languageMenu) return;
languageMenu.hidden = !open;
languageButton.setAttribute("aria-expanded", String(open));
}
function renderLanguageControls(messages) {
const languageButton = document.querySelector(".language-button");
if (languageButton) {
languageButton.textContent = languageLabels[currentLang];
languageButton.setAttribute("aria-label", messages.language_button_aria || "Change language");
}
document.querySelectorAll(".language-menu [data-lang]").forEach((button) => {
const isActive = button.dataset.lang === currentLang;
button.classList.toggle("is-active", isActive);
button.setAttribute("aria-pressed", String(isActive));
});
}
async function applyLanguage(lang) {
currentLang = normalizeLanguage(lang);
const messages = await loadMessages(currentLang);
currentMessages = messages;
document.documentElement.lang = currentLang;
document.documentElement.dir = currentLang === "ar" ? "rtl" : "ltr";
document.title = messages.document_title || messages.title || "Host Center";
renderMessages(messages);
renderLanguageControls(messages);
syncLocalizedLinks();
syncPolicyLink();
renderProfile(currentProfile, messages);
renderAgencyProfile(currentAgencyProfile, messages);
renderDailyTargets();
renderFoundJoinAgency(foundJoinAgency);
renderPendingJoinRecord(pendingJoinRecord);
}
document.querySelector(".language-button")?.addEventListener("click", (event) => {
event.stopPropagation();
const languageMenu = document.querySelector(".language-menu");
setLanguageMenuOpen(Boolean(languageMenu?.hidden));
});
document.querySelectorAll(".language-menu [data-lang]").forEach((button) => {
button.addEventListener("click", (event) => {
event.stopPropagation();
setLanguageMenuOpen(false);
applyLanguage(button.dataset.lang);
});
});
document.addEventListener("click", () => {
setLanguageMenuOpen(false);
});
document.querySelector(".back-button")?.addEventListener("click", () => {
closeHostCenterPage();
});
document.querySelector(".agency")?.addEventListener("click", () => {
if (currentIdentity && shouldOpenJoinAgency(currentIdentity)) setJoinAgencyModalOpen(true);
});
document.querySelector("#joinAgencyButton")?.addEventListener("click", () => {
setJoinAgencyModalOpen(true);
});
document.querySelector("#joinAgencySearchForm")?.addEventListener("submit", searchJoinAgency);
document.querySelector("#joinAgencyApplyButton")?.addEventListener("click", () => {
applyToJoinAgency();
});
document.querySelector("#joinAgencyCancelButton")?.addEventListener("click", () => {
cancelJoinApplication();
});
document.querySelectorAll("[data-close-join-agency]").forEach((node) => {
node.addEventListener("click", () => {
setJoinAgencyModalOpen(false);
});
});
document.querySelector(".gift-value")?.addEventListener("click", () => {
setDailyModalOpen(true);
});
document.querySelectorAll("[data-close-daily]").forEach((node) => {
node.addEventListener("click", () => {
setDailyModalOpen(false);
});
});
document.addEventListener("keydown", (event) => {
if (event.key === "Escape") {
setDailyModalOpen(false);
setJoinAgencyModalOpen(false);
}
});
ensureAvatarFallback("Oscar");
async function initializePage() {
setLoading(true);
try {
await applyLanguage(currentLang);
const identity = await fetchIdentity();
setIdentityView(identity);
const profile = await fetchUserProfile();
const pendingRequests = [];
if (!shouldOpenJoinAgency(identity)) {
pendingRequests.push(fetchAgencyProfile());
pendingRequests.push(fetchTeamEntry());
pendingRequests.push(fetchBankBalance());
const memberId = profile?.id || profile?.account;
if (memberId) pendingRequests.push(fetchStreamingDuration(memberId));
}
await Promise.allSettled(pendingRequests);
} catch (error) {
console.error("Failed to initialize host center:", error);
setIdentityView(currentIdentity);
} finally {
setLoading(false);
}
}
initializePage();
})();