PageSourceSearch

https://applytop.com/js/role-page/index-1.6.19.js

js applytop.com collected 2026-10-01 16:15:45 UTC 21,972 bytes, 672 lines download raw bytes

1// applytop/app-1.6.19/src/helpers/native-bridge.js
2function nativePlugins() {
3  try {
4    const cap = window.Capacitor;
5    if (!cap || typeof cap.isNativePlatform !== "function" || !cap.isNativePlatform()) return null;
6    return cap.Plugins || {};
7  } catch (_) {
8    return null;
9  }
10}
11function install(P) {
12  const App = P.App;
13  const Share = P.Share;
14  const Camera = P.Camera;
15  const PushNotifications = P.PushNotifications;
16  const Network = P.Network;
17  const Browser = P.Browser;
18  const SecureStorage = P.SecureStoragePlugin;
19  const BiometricAuth = P.BiometricAuthNative;
20  function getStore() {
21    return typeof window.CdvPurchase !== "undefined" ? window.CdvPurchase.store : null;
22  }
23  const GPB_PRODUCTS = [
24    { id: "credits_small", type: "consumable" },
25    { id: "credits_medium", type: "consumable" },
26    { id: "credits_large", type: "consumable" },
27    { id: "pro_lifetime", type: "non consumable" },
28    { id: "pro_weekly", type: "paid subscription" },
29    { id: "pro_monthly", type: "paid subscription" },
30    { id: "pro_yearly", type: "paid subscription" },
31    { id: "career_growth_weekly", type: "paid subscription" }
32  ];
33  const _pendingPurchases = /* @__PURE__ */ new Map();
34  let _storeInitialized = false;
35  function initStore() {
36    const store = getStore();
37    if (!store || _storeInitialized) return;
38    _storeInitialized = true;
39    try {
40      const CdvPurchase = window.CdvPurchase;
41      const Platform = CdvPurchase.Platform;
42      const ProductType = CdvPurchase.ProductType;
43      const typeMap = {
44        "consumable": ProductType.CONSUMABLE,
45        "non consumable": ProductType.NON_CONSUMABLE,
46        "paid subscription": ProductType.PAID_SUBSCRIPTION
47      };
48      store.register(GPB_PRODUCTS.map((p) => ({
49        id: p.id,
50        type: typeMap[p.type] || ProductType.CONSUMABLE,
51        platform: Platform.GOOGLE_PLAY
52      })));
53      store.when().approved((transaction) => {
54        for (const productId of (transaction.products || []).map((p) => p.id)) {
55          const waiter = _pendingPurchases.get(productId);
56          if (waiter) {
57            waiter.resolve({
58              purchaseToken: transaction.purchaseId || transaction.transactionId,
59              productId,
60              orderId: transaction.transactionId || null
61            });
62            _pendingPurchases.delete(productId);
63          }
64        }
65        transaction.finish();
66      }).cancelled((transaction) => {
67        for (const productId of (transaction.products || []).map((p) => p.id)) {
68          const waiter = _pendingPurchases.get(productId);
69          if (waiter) {
70            waiter.resolve(null);
71            _pendingPurchases.delete(productId);
72          }
73        }
74      });
75      store.error((err) => {
76        console.warn("[AT bridge] Store error:", err);
77      });
78      store.initialize([Platform.GOOGLE_PLAY]).catch((err) => {
79        console.warn("[AT bridge] Store initialize failed:", err);
80      });
81    } catch (err) {
82      console.warn("[AT bridge] initStore failed:", err);
83    }
84  }
85  async function startPurchase(productId) {
86    const store = getStore();
87    if (!store) {
88      console.warn("[AT bridge] cordova-plugin-purchase not loaded");
89      return null;
90    }
91    initStore();
92    const offer = store.get(productId)?.getOffer();
93    if (!offer) {
94      console.warn("[AT bridge] No Play offer for product:", productId);
95      return { error: true, message: "This purchase is not available on this build" };
96    }
97    return new Promise((resolve, reject) => {
98      _pendingPurchases.set(productId, { resolve, reject });
99      offer.order().catch((err) => {
100        console.warn("[AT bridge] order() failed:", err);
101        const waiter = _pendingPurchases.get(productId);
102        if (waiter) {
103          waiter.resolve(null);
104          _pendingPurchases.delete(productId);
105        }
106      });
107    });
108  }
109  const TOKEN_KEY = "at.token";
110  const USER_ID_KEY = "at.userId";
111  const USER_EMAIL_KEY = "at.email";
112  async function saveToken({ token, userId, email }) {
113    if (!SecureStorage) return false;
114    try {
115      await SecureStorage.set({ key: TOKEN_KEY, value: token });
116      if (userId) await SecureStorage.set({ key: USER_ID_KEY, value: userId });
117      if (email) await SecureStorage.set({ key: USER_EMAIL_KEY, value: email });
118      return true;
119    } catch (err) {
120      console.warn("[AT bridge] saveToken failed:", err);
121      return false;
122    }
123  }
124  async function getToken() {
125    if (!SecureStorage) return null;
126    try {
127      const tokenRes = await SecureStorage.get({ key: TOKEN_KEY }).catch(() => null);
128      const userIdRes = await SecureStorage.get({ key: USER_ID_KEY }).catch(() => null);
129      const emailRes = await SecureStorage.get({ key: USER_EMAIL_KEY }).catch(() => null);
130      if (!tokenRes?.value || !userIdRes?.value) return null;
131      return { token: tokenRes.value, userId: userIdRes.value, email: emailRes?.value || null };
132    } catch (err) {
133      console.warn("[AT bridge] getToken failed:", err);
134      return null;
135    }
136  }
137  async function clearToken() {
138    if (!SecureStorage) return;
139    try {
140      await SecureStorage.remove({ key: TOKEN_KEY }).catch(() => {
141      });
142      await SecureStorage.remove({ key: USER_ID_KEY }).catch(() => {
143      });
144      await SecureStorage.remove({ key: USER_EMAIL_KEY }).catch(() => {
145      });
146    } catch (_) {
147    }
148  }
149  let _cachedFcmToken = null;
150  let _fcmTokenWaiters = [];
151  function setFcmToken(token) {
152    _cachedFcmToken = token;
153    _fcmTokenWaiters.forEach((fn) => fn(token));
154    _fcmTokenWaiters = [];
155  }
156  async function pushIsSafe() {
157    try {
158      const ATPush = P.ATPush;
159      if (!ATPush || typeof ATPush.isAvailable !== "function") return false;
160      const res = await ATPush.isAvailable();
161      return !!(res && res.available);
162    } catch (_) {
163      return false;
164    }
165  }
166  async function getFcmToken() {
167    if (_cachedFcmToken) return _cachedFcmToken;
168    if (!PushNotifications) return null;
169    if (!await pushIsSafe()) {
170      console.warn("[AT bridge] Push unavailable (Firebase not initialised in this build); skipping registration");
171      return null;
172    }
173    try {
174      const perm = await PushNotifications.requestPermissions();
175      if (perm.receive !== "granted") return null;
176      await PushNotifications.register();
177      return await new Promise((resolve) => {
178        const timeout = setTimeout(() => resolve(null), 1e4);
179        _fcmTokenWaiters.push((token) => {
180          clearTimeout(timeout);
181          resolve(token);
182        });
183      });
184    } catch (err) {
185      console.warn("[AT bridge] getFcmToken failed:", err);
186      return null;
187    }
188  }
189  async function share({ title, text, url }) {
190    if (!Share) return false;
191    try {
192      await Share.share({ title, text, url, dialogTitle: title });
193      return true;
194    } catch (_) {
195      return false;
196    }
197  }
198  async function cameraCapture() {
199    if (!Camera) return null;
200    try {
201      const photo = await Camera.getPhoto({
202        quality: 80,
203        allowEditing: false,
204        resultType: "base64",
205        source: "CAMERA"
206      });
207      return { base64: photo.base64String, mimeType: "image/" + (photo.format || "jpeg") };
208    } catch (_) {
209      return null;
210    }
211  }
212  async function enableBiometric() {
213    if (!BiometricAuth) return false;
214    try {
215      const info = await BiometricAuth.checkBiometry();
216      return !!info?.isAvailable;
217    } catch (_) {
218      return false;
219    }
220  }
221  async function promptBiometric() {
222    if (!BiometricAuth) return true;
223    try {
224      const info = await BiometricAuth.checkBiometry();
225      if (!info?.isAvailable) return true;
226      await BiometricAuth.authenticate({
227        reason: "Unlock ApplyTop",
228        cancelTitle: "Use password",
229        allowDeviceCredential: true
230      });
231      return true;
232    } catch (_) {
233      return false;
234    }
235  }
236  async function logout() {
237    await clearToken();
238    return true;
239  }
240  async function openExternal({ url }) {
241    if (!Browser) {
242      window.open(url, "_blank");
243      return true;
244    }
245    try {
246      await Browser.open({ url });
247      return true;
248    } catch (err) {
249      console.warn("[AT bridge] openExternal failed:", err);
250      return false;
251    }
252  }
253  function wireLifecycleEvents() {
254    if (App) {
255      try {
256        App.addListener("appStateChange", ({ isActive }) => {
257          window.dispatchEvent(new CustomEvent(isActive ? "at:resume" : "at:pause"));
258        });
259        App.addListener("backButton", ({ canGoBack }) => {
260          if (window.history.length > 1 || canGoBack) window.history.back();
261          else App.exitApp();
262        });
263        App.addListener("appUrlOpen", ({ url }) => {
264          try {
265            const parsed = new URL(url);
266            if (parsed.protocol === "applytop:") {
267              window.location.href = "/" + parsed.host + parsed.pathname + (parsed.search || "");
268            } else if (parsed.host && parsed.host.endsWith("applytop.com")) {
269              window.location.href = parsed.pathname + parsed.search + parsed.hash;
270            }
271          } catch (err) {
272            console.warn("[AT bridge] appUrlOpen parse failed:", err);
273          }
274        });
275      } catch (err) {
276        console.warn("[AT bridge] App listener wiring failed:", err);
277      }
278    }
279    if (Network) {
280      try {
281        Network.addListener("networkStatusChange", (status) => {
282          window.dispatchEvent(new CustomEvent("at:networkchange", {
283            detail: { connected: status.connected, type: status.connectionType }
284          }));
285        });
286        Network.getStatus().then((status) => {
287          window.dispatchEvent(new CustomEvent("at:networkchange", {
288            detail: { connected: status.connected, type: status.connectionType }
289          }));
290        }).catch(() => {
291        });
292      } catch (err) {
293        console.warn("[AT bridge] Network listener wiring failed:", err);
294      }
295    }
296    if (PushNotifications) {
297      try {
298        PushNotifications.addListener("registration", ({ value }) => setFcmToken(value));
299        PushNotifications.addListener("registrationError", (err) => {
300          console.warn("[AT bridge] FCM registration error:", err);
301        });
302        PushNotifications.addListener("pushNotificationActionPerformed", ({ notification }) => {
303          const data = notification?.data || {};
304          if (data.url) window.location.href = data.url;
305          else if (data.alertId) window.location.href = "/dashboard/matches?alert=" + encodeURIComponent(data.alertId);
306          else window.location.href = "/dashboard/matches";
307        });
308      } catch (err) {
309        console.warn("[AT bridge] Push listener wiring failed:", err);
310      }
311    }
312  }
313  window.AT = {
314    saveToken,
315    getToken,
316    clearToken,
317    purchase: ({ productId }) => startPurchase(productId),
318    purchaseSubscription: ({ productId }) => startPurchase(productId),
319    share,
320    cameraCapture,
321    getFcmToken,
322    enableBiometric,
323    promptBiometric,
324    logout,
325    openExternal
326  };
327  wireLifecycleEvents();
328  if (typeof window.CdvPurchase !== "undefined") initStore();
329  else document.addEventListener("deviceready", initStore, { once: true });
330}
331try {
332  const P = nativePlugins();
333  if (P) install(P);
334} catch (err) {
335  console.warn("[AT bridge] install failed:", err);
336}
337
338// applytop/app-1.6.19/src/helpers/net.js
339function nativeHeaders() {
340  try {
341    if (window.Capacitor && window.Capacitor.isNativePlatform && window.Capacitor.isNativePlatform()) {
342      return {
343        "X-AT-Client": "android",
344        "X-AT-App-Version": window.constant && window.constant.appVersion || ""
345      };
346    }
347  } catch (_) {
348  }
349  return {};
350}
351function clearSession() {
352  localStorage.removeItem("token");
353  localStorage.removeItem("user");
354  try {
355    if (window.AT && window.AT.logout) window.AT.logout();
356  } catch (_) {
357  }
358}
359async function call(path, method, data) {
360  const cleanPath = path.replace(/^\/+/, "").replace(/\/+$/, "");
361  const apiUrl = (window.constant && window.constant.apiUrl || `https://${window.location.hostname}/api`).replace(/\/+$/, "");
362  let fullUrl = `${apiUrl}/${cleanPath}`;
363  if (method === "POST") {
364    let response = await fetch(fullUrl, {
365      method: "POST",
366      headers: {
367        "Content-Type": "application/json;charset=utf-8",
368        ...nativeHeaders()
369      },
370      body: JSON.stringify(data)
371    });
372    let result = await response.json();
373    if (result.error && result.errorMessage === "Auth Error") {
374      clearSession();
375      window.location.href = "/login";
376      return result;
377    }
378    return result;
379  } else if (method === "FORMDATA") {
380    let response = await fetch(fullUrl, {
381      method: "POST",
382      headers: { ...nativeHeaders() },
383      body: data
384    });
385    let result = await response.json();
386    if (result.error && result.errorMessage === "Auth Error") {
387      clearSession();
388      window.location.href = "/login";
389      return result;
390    }
391    return result;
392  } else if (method === "GET") {
393    const authHeaders = {};
394    if (data) {
395      const separator = fullUrl.includes("?") ? "&" : "?";
396      const queryParams = [];
397      if (data.token) {
398        authHeaders["Authorization"] = `Bearer ${data.token}`;
399        delete data.token;
400      }
401      if (data.userId) {
402        queryParams.push(`userId=${encodeURIComponent(data.userId)}`);
403        delete data.userId;
404      }
405      for (const key in data) {
406        if (data[key] !== void 0 && data[key] !== null) {
407          queryParams.push(`${encodeURIComponent(key)}=${encodeURIComponent(data[key])}`);
408        }
409      }
410      if (queryParams.length > 0) {
411        fullUrl += separator + queryParams.join("&");
412      }
413    }
414    let response = await fetch(fullUrl, {
415      method: "GET",
416      headers: authHeaders
417    });
418    if (response.ok) {
419      let result = await response.json();
420      if (result.error && result.errorMessage === "Auth Error") {
421        clearSession();
422        window.location.href = "/login";
423        return result;
424      }
425      return result;
426    } else {
427      console.error("GET request failed:", response.status, response.statusText);
428      let result = await response.json();
429      if (result.error && result.errorMessage === "Auth Error") {
430        clearSession();
431        window.location.href = "/login";
432        return result;
433      }
434      return {
435        success: false,
436        error: `Request failed with status ${response.status}`
437      };
438    }
439  }
440}
441
442// applytop/app-1.6.19/src/helpers/attribution.js
443var STORAGE_KEY = "applytop.attribution";
444var FIRST_TOUCH_KEYS = ["utm_source", "utm_medium", "utm_campaign", "utm_term", "utm_content", "gclid", "fbclid", "ttclid", "ref"];
445var LAST_TOUCH_KEYS = ["click_id", "sub_id"];
446function readStoredRaw() {
447  try {
448    return localStorage.getItem(STORAGE_KEY);
449  } catch (e) {
450    return null;
451  }
452}
453function isInternalReferrer(referrer) {
454  if (!referrer) return false;
455  try {
456    const ref = new URL(referrer);
457    const here = window.location.hostname || "";
458    if (ref.hostname === here) return true;
459    const refApex = ref.hostname.replace(/^.*?([^.]+\.[^.]+)$/, "$1");
460    const hereApex = here.replace(/^.*?([^.]+\.[^.]+)$/, "$1");
461    return !!hereApex && refApex === hereApex;
462  } catch (e) {
463    return false;
464  }
465}
466function captureAttribution() {
467  if (typeof window === "undefined" || typeof localStorage === "undefined") return;
468  let params;
469  try {
470    params = new URLSearchParams(window.location.search || "");
471  } catch (e) {
472    return;
473  }
474  let existing = {};
475  const raw = readStoredRaw();
476  if (raw) {
477    try {
478      const parsed = JSON.parse(raw);
479      if (parsed && typeof parsed === "object") existing = parsed;
480    } catch (e) {
481    }
482  }
483  let changed = false;
484  for (const key of LAST_TOUCH_KEYS) {
485    const v = params.get(key);
486    if (v !== null && v !== "" && existing[key] !== v) {
487      existing[key] = v.slice(0, 512);
488      changed = true;
489    }
490  }
491  for (const key of FIRST_TOUCH_KEYS) {
492    if (existing[key]) continue;
493    const v = params.get(key);
494    if (v !== null && v !== "") {
495      existing[key] = v.slice(0, 512);
496      changed = true;
497    }
498  }
499  if (!existing.referrer_url) {
500    const rawReferrer = (document.referrer || "").slice(0, 2048);
501    if (rawReferrer && !isInternalReferrer(rawReferrer)) {
502      existing.referrer_url = rawReferrer;
503      changed = true;
504    }
505  }
506  if (!existing.landing_page) {
507    existing.landing_page = (window.location.pathname || "/") + (window.location.search || "");
508    existing.landing_page_at = (/* @__PURE__ */ new Date()).toISOString();
509    changed = true;
510  }
511  if (!changed) return;
512  try {
513    localStorage.setItem(STORAGE_KEY, JSON.stringify(existing));
514  } catch (e) {
515  }
516}
517function readAttribution() {
518  const raw = readStoredRaw();
519  if (!raw) return {};
520  try {
521    const obj = JSON.parse(raw);
522    return obj && typeof obj === "object" ? obj : {};
523  } catch (e) {
524    return {};
525  }
526}
527captureAttribution();
528
529// applytop/app-1.6.19/src/helpers/track.js
530var SESSION_KEY = "applytop.anon_session";
531function getOrCreateSessionId() {
532  try {
533    let id = localStorage.getItem(SESSION_KEY);
534    if (id) return id;
535    const rand = typeof crypto !== "undefined" && crypto.randomUUID ? crypto.randomUUID() : Date.now().toString(36) + Math.random().toString(36).slice(2);
536    id = `anon_${rand}`.slice(0, 64);
537    localStorage.setItem(SESSION_KEY, id);
538    return id;
539  } catch (_) {
540    return null;
541  }
542}
543function abVariant() {
544  const key = getOrCreateSessionId();
545  if (!key) return "A";
546  let h = 5381;
547  const s = String(key);
548  for (let i = 0; i < s.length; i++) h = (h << 5) + h + s.charCodeAt(i) | 0;
549  return (h & 1) === 0 ? "A" : "B";
550}
551function isLandingPath(pathname) {
552  const p = (pathname || "/").replace(/\/+$/, "") || "/";
553  return p === "/" || p === "/index" || p === "/pl" || p === "/es" || p === "/hi";
554}
555function track(eventType, opts = {}) {
556  if (!eventType) return;
557  try {
558    let user = null;
559    try {
560      user = JSON.parse(localStorage.getItem("user") || "null");
561    } catch (_) {
562    }
563    const body = {
564      eventType,
565      metadata: {
566        ...readAttribution(),
567        ...opts.metadata || {}
568      }
569    };
570    if (user && user.id && user.token) {
571      body.userId = user.id;
572      body.token = user.token;
573    } else {
574      body.sessionId = getOrCreateSessionId();
575    }
576    if (opts.cvId) body.cvId = opts.cvId;
577    if (opts.jobId) body.jobId = opts.jobId;
578    if (opts.variant) body.variant = opts.variant;
579    if (opts.trigger) body.trigger = opts.trigger;
580    if (opts.path) body.path = opts.path;
581    if (opts.referrer) body.referrer = opts.referrer;
582    call("events/track", "POST", body).catch(() => {
583    });
584  } catch (_) {
585  }
586}
587var bootstrapped = false;
588function bootstrapAutoTracking() {
589  if (typeof window === "undefined" || typeof document === "undefined") return;
590  if (bootstrapped) return;
591  bootstrapped = true;
592  if (typeof location !== "undefined" && location.pathname && location.pathname.startsWith("/roppongi")) {
593    return;
594  }
595  const firePageView = () => {
596    try {
597      const path = (location.pathname || "/") + (location.search || "");
598      const referrer = document.referrer || null;
599      const screenStr = typeof screen !== "undefined" && screen.width && screen.height ? `${screen.width}x${screen.height}` : null;
600      track("page_view", {
601        path,
602        referrer,
603        metadata: screenStr ? { screen: screenStr } : {},
604        // Stamp the hero A/B bucket on landing views so page_view is the
605        // denominator of the variant funnel.
606        variant: isLandingPath(location.pathname) ? abVariant() : void 0
607      });
608    } catch (_) {
609    }
610  };
611  if (document.readyState === "loading") {
612    document.addEventListener("DOMContentLoaded", firePageView, { once: true });
613  } else {
614    firePageView();
615  }
616  document.addEventListener("click", (e) => {
617    try {
618      const el = e.target && e.target.closest && e.target.closest("[data-track-cta]");
619      if (!el) return;
620      const cta = el.getAttribute("data-track-cta");
621      if (!cta) return;
622      const body = {
623        eventType: "landing_cta_clicked",
624        metadata: { ...readAttribution(), cta },
625        path: (location.pathname || "/") + (location.search || "")
626      };
627      if (isLandingPath(location.pathname)) body.variant = abVariant();
628      let user = null;
629      try {
630        user = JSON.parse(localStorage.getItem("user") || "null");
631      } catch (_) {
632      }
633      if (user && user.id && user.token) {
634        body.userId = user.id;
635        body.token = user.token;
636      } else {
637        body.sessionId = getOrCreateSessionId();
638      }
639      const apiUrl = typeof window !== "undefined" && window.constant && window.constant.apiUrl ? window.constant.apiUrl.replace(/\/+$/, "") : `https://${location.hostname}/api`;
640      if (apiUrl && navigator.sendBeacon) {
641        navigator.sendBeacon(`${apiUrl}/events/track`, new Blob([JSON.stringify(body)], { type: "application/json" }));
642      } else {
643        track("landing_cta_clicked", { metadata: { cta }, variant: body.variant, path: body.path });
644      }
645    } catch (_) {
646    }
647  }, true);
648  document.addEventListener("click", (e) => {
649    try {
650      const a = e.target && e.target.closest && e.target.closest("a[href]");
651      if (!a) return;
652      const href = a.getAttribute("href") || "";
653      if (!href || href.startsWith("#") || /^(mailto:|tel:|javascript:)/i.test(href)) return;
654      let url;
655      try {
656        url = new URL(href, location.href);
657      } catch (_) {
658        return;
659      }
660      if (!/^https?:$/i.test(url.protocol)) return;
661      if (url.hostname === location.hostname) return;
662      track("outbound_click", {
663        metadata: {
664          url: url.href.slice(0, 512),
665          text: (a.textContent || "").trim().slice(0, 80) || null
666        }
667      });
668    } catch (_) {
669    }
670  }, true);
671}
672bootstrapAutoTracking();

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.