(function () { const isPostbag = window.location.pathname.indexOf("/opinion/postbag") !== -1; function getCookie(name) { const match = document.cookie.match(new RegExp('(^| )' + name + '=([^;]+)')); if (match) return match[2]; try { const rawLocal = localStorage.getItem(name); if (rawLocal) { // 1. Check if item has JSON expiration wrapper if (rawLocal.charAt(0) === '{' && rawLocal.charAt(rawLocal.length - 1) === '}') { try { const parsed = JSON.parse(rawLocal); if (parsed && typeof parsed.expires === 'number') { if (Date.now() > parsed.expires) { localStorage.removeItem(name); return null; } return parsed.value; } } catch (jsonErr) { } } // 2. Check if item is a JWT token with an internal exp claim const parts = rawLocal.split('.'); if (parts.length === 3) { try { let b64 = parts[1].replace(/-/g, '+').replace(/_/g, '/'); while (b64.length % 4) b64 += '='; const payload = JSON.parse(atob(b64)); if (payload && payload.exp && (payload.exp * 1000) < Date.now()) { localStorage.removeItem(name); return null; } } catch (jwtErr) { } } return rawLocal; } const rawSession = sessionStorage.getItem(name); if (rawSession) return rawSession; } catch (e) { return null; } return null; } function setCookie(name, value, ms) { const d = new Date(); const ttl = ms || (1 * 60 * 60 * 1000); const expiresTime = d.getTime() + ttl; d.setTime(expiresTime); document.cookie = name + "=" + value + ";path=/;SameSite=Lax;expires=" + d.toUTCString(); try { const itemObj = { value: value, expires: expiresTime }; localStorage.setItem(name, JSON.stringify(itemObj)); sessionStorage.setItem(name, value); } catch (e) { } } function isLoggedIn() { const hasCookie = !!getCookie(window._m_c || "__bwp"); const dgsMetaUser = document.querySelector('meta[name="dgs-user"]'); const hasActiveSub = dgsMetaUser && dgsMetaUser.content === 'enable'; return hasCookie || hasActiveSub; } function logPaywallView(type, action, variant, variantName, customParams) { if (!action) { action = 'paywall_impression'; } customParams = customParams || {}; const isPostbag = window.location.pathname.indexOf("/opinion/postbag") !== -1; const current_section = (typeof customParams.section_name !== 'undefined' && customParams.section_name !== null) ? customParams.section_name : ((typeof g_section_name !== 'undefined' && g_section_name) ? g_section_name : ""); const isSubLanding = current_section === 'subscription' || current_section === 'digital-subscription' || current_section === 'subscriptions' || current_section === 'digital-subscriptions'; let log_variant = variant; if (isSubLanding) { log_variant = ""; } else if (typeof log_variant === 'undefined' || log_variant === null || log_variant === '') { log_variant = window.DGS_PAYWALL_VARIANT || ''; } let log_variant_name = variantName; if (isSubLanding) { log_variant_name = ""; } else if (typeof log_variant_name === 'undefined' || log_variant_name === null || log_variant_name === '') { log_variant_name = window.DGS_PAYWALL_VARIANT_NAME || ''; } if (!isSubLanding && log_variant && !log_variant_name && window.DGS_PAYWALL_WORDINGS_ALL && window.DGS_PAYWALL_WORDINGS_ALL[log_variant]) { const vObj = window.DGS_PAYWALL_WORDINGS_ALL[log_variant]; log_variant_name = vObj['variant_name'] || ''; } let dgsBase = "/v3/"; let log_type = isPostbag ? 'postbag' : type; let log_content_id = isPostbag ? "" : ((typeof customParams.content_id !== 'undefined' && customParams.content_id !== null) ? customParams.content_id : ((typeof g_content_id !== 'undefined' && g_content_id) ? g_content_id : "")); if (current_section === 'topic_main') { log_type = 'topic_main'; } else if (current_section === 'topic_content') { log_type = 'topic_content'; } let log_topic_id = (typeof customParams.topic_id !== 'undefined' && customParams.topic_id !== null) ? customParams.topic_id : ((typeof g_topic_id !== 'undefined' && g_topic_id) ? g_topic_id : ""); if (current_section === 'topic_content' && log_topic_id) { log_content_id = log_topic_id; } let log_category_id = (typeof customParams.category_id !== 'undefined' && customParams.category_id !== null) ? customParams.category_id : ((typeof g_category_id !== 'undefined' && g_category_id) ? g_category_id : ""); const logUrl = dgsBase + "api/log-action-paywall"; const data = { type: log_type, action: action, content_id: log_content_id, section_name: current_section, category_id: log_category_id, variant: log_variant || "", variant_name: log_variant_name || "" }; const params = new URLSearchParams(data); // 1. ลองใช้ navigator.sendBeacon สำหรับการกด CTA หรือเปลี่ยนหน้า เพื่อป้องกัน Request โดน Abort เมื่อเบราว์เซอร์ Unload/Redirect if (typeof navigator !== 'undefined' && typeof navigator.sendBeacon === 'function') { try { const blob = new Blob([params.toString()], { type: 'application/x-www-form-urlencoded' }); const sent = navigator.sendBeacon(logUrl, blob); if (sent) { console.log("Paywall action logged via sendBeacon:", action, data); return; } } catch (beaconErr) { console.warn("sendBeacon error, falling back to fetch/ajax:", beaconErr); } } // 2. ใช้ fetch พร้อม keepalive: true (ทำงานได้ต่อเนื่องแม้เพจกำลังถูก Unload/Redirect) if (typeof fetch === 'function') { fetch(logUrl, { method: "POST", headers: { "Content-Type": "application/x-www-form-urlencoded" }, body: params, keepalive: true }) .then(function (res) { return res.json(); }) .then(function (res) { console.log("Paywall action logged successfully via fetch:", res); }) .catch(function (err) { console.error("Failed to log paywall view via fetch:", err); }); return; } // 3. Fallback สำหรับเบราว์เซอร์เก่ามากที่ไม่มี fetch/sendBeacon if (typeof $ !== 'undefined' && $.ajax) { $.ajax({ url: logUrl, method: "POST", data: data, dataType: "json", success: function (res) { console.log("Paywall view logged successfully via jQuery:", res); }, error: function (err) { console.error("Failed to log paywall view via jQuery:", err); } }); } } window.logPaywallView = logPaywallView; function logPaywallLockDiagnostic(triggerSource) { try { const pageKey = 'dgs_diag_logged_' + window.location.pathname; if (sessionStorage.getItem(pageKey)) { return; } sessionStorage.setItem(pageKey, '1'); const cookieName = window._p_c || "__bwp_pw"; const loginCookieName = window._m_c || "__bwp"; // 1. ตรวจสอบคุกกี้ Login (__bwp) const matchLogin = document.cookie.match(new RegExp('(^| )' + loginCookieName + '=([^;]+)')); const hasLoginCookie = !!matchLogin; let loggedInUserId = null; if (hasLoginCookie) { try { const loginRaw = decodeURIComponent(matchLogin[2]); const uidMatch = loginRaw.match(/userID["\s:;]+([0-9]+)/i) || loginRaw.match(/"id"[:\s]+([0-9]+)/i); if (uidMatch) loggedInUserId = uidMatch[1]; } catch (e) { } } // 2. ตรวจสอบคุกกี้สถานะสมาชิก (_bp_pdgs หรือ __bwp_pw) const subCookie = getCookie(window._s_c || "_bp_pdgs"); const hasSubCookie = (subCookie === "1"); const matchPw = document.cookie.match(new RegExp('(^| )' + cookieName + '=([^;]+)')); const hasPwCookie = !!matchPw; let pwPayload = null; let isPwExpired = false; if (hasPwCookie) { try { const parts = matchPw[2].split('.'); if (parts.length === 3) { let b64 = parts[1].replace(/-/g, '+').replace(/_/g, '/'); while (b64.length % 4) b64 += '='; pwPayload = JSON.parse(atob(b64)); if (pwPayload && pwPayload.exp) { isPwExpired = (pwPayload.exp * 1000) < Date.now(); } } } catch (e) { } } // 3. ตรวจสอบ LocalStorage Backup (ถ้ามีค้างอยู่) let lsPayload = null; let hasLs = false; let isLsExpired = false; try { const lsToken = localStorage.getItem(cookieName); if (lsToken) { hasLs = true; const parts = lsToken.split('.'); if (parts.length === 3) { let b64 = parts[1].replace(/-/g, '+').replace(/_/g, '/'); while (b64.length % 4) b64 += '='; lsPayload = JSON.parse(atob(b64)); if (lsPayload && lsPayload.exp) { isLsExpired = (lsPayload.exp * 1000) < Date.now(); } } } } catch (e) { } // ต้อง (1) Login อยู่ และ (2) มี Cookie สิทธิ์ (__bwp_sub หรือ __bwp_pw) if (!hasLoginCookie || (!hasSubCookie && !hasPwCookie)) { return; } // 4. ตรวจสอบ Meta Tags จาก Server / CDN const dgsMetaContent = document.querySelector('meta[name="dgs-content"]'); const dgsMetaUser = document.querySelector('meta[name="dgs-user"]'); const metaContent = dgsMetaContent ? dgsMetaContent.content : null; const metaUser = dgsMetaUser ? dgsMetaUser.content : null; // 5. วิเคราะห์เหตุผลว่าทำไมมีสิทธิ์แล้วยังติดล็อก let lockReason = 'UNKNOWN_LOCK'; if (isPwExpired || isLsExpired) { lockReason = 'EXPIRED_TOKEN (Token ใน Cookie หรือ LocalStorage หมดอายุแล้ว)'; } else if (pwPayload && pwPayload.pw === 0 && pwPayload.sub === 0) { lockReason = 'TOKEN_PW_ZERO (มี Token แต่สถานะ pw=0 และ sub=0 ไม่ใช่ Subscriber)'; } else if (loggedInUserId && pwPayload && pwPayload.uid && String(loggedInUserId) !== String(pwPayload.uid)) { lockReason = 'UID_MISMATCH (User ID ที่ Login ไม่ตรงกับ UID ใน Token)'; } else if (metaUser === 'disable') { lockReason = 'CDN_CACHE_MISMATCH (มี Login, มี Cookie สมาชิกครบ แต่ CDN ส่งหน้าแคช disable มา)'; } else { lockReason = 'ALL_TOKENS_VALID_BUT_PAYWALL_TRIGGERED (ข้อมูลครบถ้วนแต่ติดล็อก)'; } const diagPayload = { trigger_source: triggerSource || 'unknown', lock_reason: lockReason, user_id: loggedInUserId || (pwPayload ? pwPayload.uid : null) || (lsPayload ? lsPayload.uid : null) || 'GUEST', has_login_cookie: hasLoginCookie, has_pw_cookie: hasPwCookie, has_sub_cookie: hasSubCookie, cookie_pw: pwPayload, is_pw_cookie_expired: isPwExpired, has_localstorage_pw: hasLs, localstorage_pw: lsPayload, is_ls_expired: isLsExpired, meta_dgs_content: metaContent, meta_dgs_user: metaUser, page_url: window.location.href, referrer: document.referrer || '', timestamp: new Date().toISOString() }; const logEndpoint = "/v3/api/log-paywall-diagnostic"; const bodyStr = JSON.stringify(diagPayload); if (typeof navigator !== 'undefined' && typeof navigator.sendBeacon === 'function') { const blob = new Blob([bodyStr], { type: 'application/json' }); navigator.sendBeacon(logEndpoint, blob); } else if (typeof fetch === 'function') { fetch(logEndpoint, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: bodyStr, keepalive: true }).catch(function () { }); } } catch (err) { console.warn("[Paywall] logPaywallLockDiagnostic error:", err); } } function initPaywallScrollObserver() { // ค้นหา Element ของแถบ Paywall หรือพื้นที่ที่โดนเบลอ (.sticky-blurred-paywall สำหรับ Life, .force_login--popup สำหรับ News) const paywallEl = document.querySelector('.sticky-blurred-paywall, .force_login--popup, .paywall-locked-body'); if (!paywallEl) { return; } // ใช้ Intersection Observer API สำหรับจับความเคลื่อนไหวเมื่อเลื่อนจอมาเจอ Element if (typeof IntersectionObserver !== 'undefined') { const observer = new IntersectionObserver((entries, obs) => { entries.forEach(entry => { if (entry.isIntersecting) { console.log("Paywall popup encountered: User scrolled down and saw the paywall."); logPaywallView("article"); logPaywallLockDiagnostic("scroll_blurred_article"); obs.disconnect(); // สั่งหยุดจับความเคลื่อนไหวหลังจากบันทึก Log สำเร็จครั้งแรก } }); }, { threshold: 0.1 // ทำงานเมื่อ Element โผล่ขึ้นมาในจออย่างน้อย 10% }); observer.observe(paywallEl); } else { // ระบบสำรองสำหรับบราวเซอร์รุ่นเก่า (ผูก Event Scroll) const onScroll = function () { const rect = paywallEl.getBoundingClientRect(); const viewHeight = Math.max(document.documentElement.clientHeight, window.innerHeight); if (rect.top >= 0 && rect.top <= viewHeight) { console.log("Paywall popup encountered (fallback): User scrolled down and saw the paywall."); logPaywallView("article"); logPaywallLockDiagnostic("scroll_blurred_article_fallback"); window.removeEventListener('scroll', onScroll); } }; window.addEventListener('scroll', onScroll); } } function initPopupTrigger() { // Do not run paywall popup trigger on digital subscription pages if (window.location.pathname.indexOf("/digital-subscription") !== -1) { return; } if (window.location.pathname.indexOf("/subscriptions") !== -1) { return; } // Do not run paywall popup trigger on premium publications (ebook) pages if (window.location.pathname.indexOf("/premium-publications") !== -1) { return; } // หน้า Postbag: ใช้เฉพาะ Lock Bar Paywall ในหน้าเนื้อหา (ไม่แสดง Popup Modal) if (isPostbag) { initPaywallScrollObserver(); return; } // อ่านค่าสถานะ Paywall และสิทธิ์การใช้งานตรงจาก Meta Tags ที่ส่งมาจาก Server const dgsMetaArticle = document.querySelector('meta[name="dgs-content"]'); const dgsMetaUser = document.querySelector('meta[name="dgs-user"]'); const isContentLocked = dgsMetaArticle && dgsMetaArticle.content === 'enable'; const isUserDisabled = dgsMetaUser && dgsMetaUser.content === 'disable'; // จัดการแสดงผลตามเงื่อนไขของประเภทหน้าจอ (ยกเลิก Section Popup และ Popup ข่าว < 3 เดือน) if (isUserDisabled) { logPaywallLockDiagnostic("page_load_user_disabled"); if (isContentLocked) { if (typeof g_content_id !== 'undefined' && g_content_id) { // หน้าข่าวเดี่ยวที่โดนล็อก (Print / Online > 3 เดือน): รันตัวตรวจจับการเลื่อนหน้าจอ (Scroll Observer) initPaywallScrollObserver(); } } } } // ปิดการบันทึก Log Action และการ Save ลง Cache (sessionStorage / localStorage) เมื่อกดปุ่ม Subscribe document.addEventListener("click", function (e) { const btnDefault = e.target.closest('.btn--default'); const btnBuy = e.target.closest('.btn-buynow, #subscribe_btn, .welcome-btn a, a[href*="/digital-subscription/payment/"], a[href*="Digital_subscription_c/payment/"]'); const btnModalLogin = e.target.closest('#signinModal .btnsignin, #signinModal .planlogin-desc a'); const path = window.location.pathname; const isDigitalSubPage = path.indexOf("/digital-subscription") !== -1; const isSubPage = path.indexOf("/subscriptions") !== -1 || path.indexOf("/subscription") !== -1; if (btnDefault || (btnBuy && (isDigitalSubPage || isSubPage)) || (btnModalLogin && (isDigitalSubPage || isSubPage)) || btnBuy) { const isArticlePopup = btnDefault && btnDefault.closest('.force_login--popup'); const isPopupLogin = btnDefault && btnDefault.closest('#popup-login'); const isEbookPopup = (btnDefault && btnDefault.closest('#popupdgs')) || path.indexOf("/premium-publications") !== -1; const isPostbagPage = isPostbag || path.indexOf("/opinion/postbag") !== -1; let pageType = 'section'; let clickContentId = (typeof g_content_id !== 'undefined' && g_content_id) ? g_content_id : ""; let currentSection = (typeof g_section_name !== 'undefined' && g_section_name) ? g_section_name : ""; let clickVariant = window.DGS_PAYWALL_VARIANT || ''; if (isEbookPopup) { pageType = 'ebook'; currentSection = 'ebook'; clickVariant = window.DGS_PAYWALL_VARIANT || ''; logPaywallView("ebook", "paywall_cta_click", clickVariant); } else if (isPostbagPage) { pageType = 'postbag'; currentSection = 'opinion'; clickVariant = window.DGS_PAYWALL_VARIANT || ''; logPaywallView("postbag", "paywall_cta_click", clickVariant); } else if (isArticlePopup) { pageType = 'article'; clickVariant = window.DGS_PAYWALL_VARIANT || ''; logPaywallView("article", "paywall_cta_click", clickVariant); } else if (isPopupLogin) { pageType = 'article'; clickVariant = window.DGS_PAYWALL_VARIANT || ''; logPaywallView("article", "paywall_cta_click", clickVariant); } else if (isDigitalSubPage || isSubPage) { pageType = 'section'; currentSection = isDigitalSubPage ? 'digital-subscription' : 'subscription'; clickVariant = ''; logPaywallView("section", "paywall_cta_click", "", "", { section_name: currentSection }); } else { // Fallback check based on globally available variables pageType = (typeof g_content_id !== 'undefined' && g_content_id) ? 'article' : 'section'; clickVariant = window.DGS_PAYWALL_VARIANT || ''; if (!currentSection) { currentSection = (pageType === 'section') ? 'digital-subscription' : ''; } logPaywallView(pageType, "paywall_cta_click", clickVariant); } if (currentSection === 'topic_main') { pageType = 'topic_main'; } else if (currentSection === 'topic_content') { pageType = 'topic_content'; if (typeof g_topic_id !== 'undefined' && g_topic_id) { clickContentId = g_topic_id; } } if (pageType) { const isSubLandingSection = currentSection === 'subscription' || currentSection === 'digital-subscription' || currentSection === 'subscriptions' || currentSection === 'digital-subscriptions'; const finalVariant = isSubLandingSection ? '' : clickVariant; let clickVariantName = ''; if (!isSubLandingSection) { clickVariantName = window.DGS_PAYWALL_VARIANT_NAME || ''; if (!clickVariantName && window.DGS_PAYWALL_WORDINGS_ALL && window.DGS_PAYWALL_WORDINGS_ALL[clickVariant]) { const vObj = window.DGS_PAYWALL_WORDINGS_ALL[clickVariant]; clickVariantName = vObj['variant_name'] || ''; } } sessionStorage.setItem('clicked_subscribe_paywall', 'true'); sessionStorage.setItem('subscribe_9_9_type', pageType); sessionStorage.setItem('subscribe_9_9_content_id', clickContentId); sessionStorage.setItem('subscribe_9_9_section_name', currentSection); sessionStorage.setItem('subscribe_9_9_category_id', (typeof g_category_id !== 'undefined' && g_category_id) ? g_category_id : ""); sessionStorage.setItem('subscribe_9_9_variant', finalVariant); sessionStorage.setItem('subscribe_9_9_variant_name', clickVariantName); // Backup to localStorage in case of bank redirect opening in a new tab/session localStorage.setItem('subscribe_9_9_type_backup', pageType); localStorage.setItem('subscribe_9_9_content_id_backup', clickContentId); localStorage.setItem('subscribe_9_9_section_name_backup', currentSection); localStorage.setItem('subscribe_9_9_category_id_backup', (typeof g_category_id !== 'undefined' && g_category_id) ? g_category_id : ""); localStorage.setItem('subscribe_9_9_variant_backup', finalVariant); localStorage.setItem('subscribe_9_9_variant_name_backup', clickVariantName); } } }); function checkCheckoutStart() { if (window.location.pathname.indexOf("/digital-subscription/payment/") !== -1) { if (sessionStorage.getItem('clicked_subscribe_paywall') === 'true') { sessionStorage.removeItem('clicked_subscribe_paywall'); const pageType = sessionStorage.getItem('subscribe_9_9_type') || localStorage.getItem('subscribe_9_9_type_backup') || 'section'; const contentId = sessionStorage.getItem('subscribe_9_9_content_id') || localStorage.getItem('subscribe_9_9_content_id_backup'); const sectionName = sessionStorage.getItem('subscribe_9_9_section_name') || localStorage.getItem('subscribe_9_9_section_name_backup') || 'digital-subscription'; const categoryId = sessionStorage.getItem('subscribe_9_9_category_id') || localStorage.getItem('subscribe_9_9_category_id_backup'); const isSubLandingSection = sectionName === 'subscription' || sectionName === 'digital-subscription' || sectionName === 'subscriptions' || sectionName === 'digital-subscriptions'; const variant = isSubLandingSection ? '' : (sessionStorage.getItem('subscribe_9_9_variant') || localStorage.getItem('subscribe_9_9_variant_backup') || ''); const variantName = isSubLandingSection ? '' : (sessionStorage.getItem('subscribe_9_9_variant_name') || localStorage.getItem('subscribe_9_9_variant_name_backup') || ''); logPaywallView(pageType, 'checkout_start', variant, variantName, { content_id: contentId, section_name: sectionName, category_id: categoryId, topic_id: pageType === 'topic_content' ? contentId : null }); console.log("Logged checkout_start action for section: " + sectionName); } } } function checkPurchaseComplete() { if (window.location.pathname.indexOf("/digital-subscription/payment/success/") !== -1) { const urlParams = new URLSearchParams(window.location.search); const ref = urlParams.get('Ref'); if (ref) { const sessionKey = 'purchase_complete_logged_' + ref; if (sessionStorage.getItem(sessionKey) !== 'true' && localStorage.getItem(sessionKey) !== 'true') { // Set immediately to prevent duplicate async trigger sessionStorage.setItem(sessionKey, 'true'); localStorage.setItem(sessionKey, 'true'); const pageType = sessionStorage.getItem('subscribe_9_9_type') || localStorage.getItem('subscribe_9_9_type_backup') || 'section'; const contentId = sessionStorage.getItem('subscribe_9_9_content_id') || localStorage.getItem('subscribe_9_9_content_id_backup'); const sectionName = sessionStorage.getItem('subscribe_9_9_section_name') || localStorage.getItem('subscribe_9_9_section_name_backup') || 'digital-subscription'; const categoryId = sessionStorage.getItem('subscribe_9_9_category_id') || localStorage.getItem('subscribe_9_9_category_id_backup'); const isSubLandingSection = sectionName === 'subscription' || sectionName === 'digital-subscription' || sectionName === 'subscriptions' || sectionName === 'digital-subscriptions'; const variant = isSubLandingSection ? '' : (sessionStorage.getItem('subscribe_9_9_variant') || localStorage.getItem('subscribe_9_9_variant_backup') || ''); const variantName = isSubLandingSection ? '' : (sessionStorage.getItem('subscribe_9_9_variant_name') || localStorage.getItem('subscribe_9_9_variant_name_backup') || ''); logPaywallView(pageType, 'purchase_complete', variant, variantName, { content_id: contentId, section_name: sectionName, category_id: categoryId, topic_id: pageType === 'topic_content' ? contentId : null }); console.log("Logged purchase_complete action with Ref: " + ref + " for section: " + sectionName); // Clear subscription flow context from sessionStorage sessionStorage.removeItem('subscribe_9_9_type'); sessionStorage.removeItem('subscribe_9_9_content_id'); sessionStorage.removeItem('subscribe_9_9_section_name'); sessionStorage.removeItem('subscribe_9_9_category_id'); sessionStorage.removeItem('pw_free_checked'); sessionStorage.removeItem('subscribe_9_9_variant'); sessionStorage.removeItem('subscribe_9_9_variant_name'); // Clear backup from localStorage localStorage.removeItem('subscribe_9_9_type_backup'); localStorage.removeItem('subscribe_9_9_content_id_backup'); localStorage.removeItem('subscribe_9_9_section_name_backup'); localStorage.removeItem('subscribe_9_9_category_id_backup'); localStorage.removeItem('subscribe_9_9_variant_backup'); localStorage.removeItem('subscribe_9_9_variant_name_backup'); } } } } function initSubscriptionModalLog() { const isDigitalSub = window.location.pathname.indexOf("/digital-subscription") !== -1; const isSub = window.location.pathname.indexOf("/subscriptions") !== -1 || window.location.pathname.indexOf("/subscription") !== -1; if (!isDigitalSub && !isSub) { return; } const sectionName = isDigitalSub ? "digital-subscription" : "subscription"; const actionShow = isDigitalSub ? "digital-subscriptions_popup_signin" : "subscriptions_popup_signin"; const actionLogin = isDigitalSub ? "digital-subscriptions_login" : "subscriptions_login_click"; const actionClose = isDigitalSub ? "digital-subscriptions_popup_close" : "subscriptions_popup_close"; let logged = false; const handleModalShow = function () { if (logged) return; logged = true; setTimeout(function () { logged = false; }, 1000); logPaywallView("section", actionShow, null, null, { content_id: "", section_name: sectionName, category_id: "null" }); }; if (typeof $ !== 'undefined') { $('#signinModal').on('show.bs.modal', handleModalShow); } else { const modalEl = document.getElementById('signinModal'); if (modalEl) { modalEl.addEventListener('show.bs.modal', handleModalShow); } } const modalEl = document.getElementById('signinModal'); if (modalEl) { modalEl.addEventListener('click', function (e) { const isSignIn = e.target.closest('.btnsignin'); const isRegister = e.target.closest('.planlogin-desc a'); const isClose = e.target.closest('.closex'); if (isSignIn || isRegister) { logPaywallView("section", actionLogin, null, null, { content_id: "", section_name: sectionName, category_id: "null" }); } else if (isClose) { logPaywallView("section", actionClose, null, null, { content_id: "", section_name: sectionName, category_id: "null" }); } }); } } function initPaywallCopyProtection() { // If developer cookie bpdgs_dev = 1 is set, bypass copy protection for testing if (getCookie('bpdgs_dev') === '1') { console.log("Paywall Copy Protection bypassed (bpdgs_dev = 1)"); return; } const dgsMetaArticle = document.querySelector('meta[name="dgs-content"]'); const isContentLocked = dgsMetaArticle && dgsMetaArticle.getAttribute('content') === 'enable'; if (!isContentLocked) { return; } // 1. Inject CSS to disable text selection on article content elements const style = document.createElement('style'); style.innerHTML = ` .article-content, #article-content, .box-postbag--user { -webkit-user-select: none !important; -moz-user-select: none !important; -ms-user-select: none !important; user-select: none !important; } `; document.head.appendChild(style); // 2. Attach event listeners to prevent copy, cut, right-click context menu, and dragging const targetElements = document.querySelectorAll('#article-content, .article-content, .box-postbag--user'); targetElements.forEach(function (el) { el.addEventListener('copy', function (e) { e.preventDefault(); return false; }); el.addEventListener('cut', function (e) { e.preventDefault(); return false; }); el.addEventListener('contextmenu', function (e) { e.preventDefault(); return false; }); el.addEventListener('dragstart', function (e) { e.preventDefault(); return false; }); }); // 3. Prevent keyboard copy/select shortcuts (Ctrl+C, Cmd+C, Ctrl+A, Cmd+A) when focused/selected inside article document.addEventListener('keydown', function (e) { if ((e.ctrlKey || e.metaKey) && (e.key === 'c' || e.key === 'C' || e.key === 'a' || e.key === 'A')) { const selection = window.getSelection(); if (selection && selection.rangeCount > 0) { let container = selection.getRangeAt(0).commonAncestorContainer; if (container.nodeType === 3) container = container.parentNode; if (container && container.closest && container.closest('#article-content, .article-content, .box-postbag--user')) { e.preventDefault(); return false; } } } }); } function hasActiveSubscriptionFromPaywallCookie() { try { // 1. ตรวจสอบจากคุกกี้สถานะหน้าบ้าน _bp_pdgs (ปลอดภัย 100% ตามมาตรฐาน Dual-Cookie) const subCookie = getCookie(window._s_c || "_bp_pdgs"); if (subCookie === "1") { return true; } // Fallback เผื่อสภาพแวดล้อม dev ที่คุกกี้ __bwp_pw ยังอ่านได้จาก JS const rawCookie = getCookie(window._p_c || "__bwp_pw"); if (rawCookie) { const parts = rawCookie.split('.'); if (parts.length === 3) { let b64 = parts[1].replace(/-/g, '+').replace(/_/g, '/'); while (b64.length % 4) b64 += '='; const payload = JSON.parse(atob(b64)); if (payload && (payload.pw === 1 || payload.sub === 1)) { if (!payload.exp || (payload.exp * 1000) > Date.now()) { return true; } } } } // 2. ตรวจสอบจาก meta tag dgs-user const dgsMetaUser = document.querySelector('meta[name="dgs-user"]'); if (dgsMetaUser && dgsMetaUser.content === 'enable') { return true; } return false; } catch (e) { return false; } } function checkCdnSubscriberCacheMismatch() { const isSubscriber = hasActiveSubscriptionFromPaywallCookie(); const dgsMetaArticle = document.querySelector('meta[name="dgs-content"]'); const isContentLocked = dgsMetaArticle && dgsMetaArticle.content === 'enable'; const dgsMetaUser = document.querySelector('meta[name="dgs-user"]'); const isUserDisabled = dgsMetaUser && dgsMetaUser.content === 'disable'; const pageKey = 'cdn_bypass_' + window.location.pathname; // ถ้าผู้ใช้เป็นสมาชิกจาก cookie _bp_pdgs หรือ __bwp_pw แต่หน้าเว็บที่ได้จาก CDN เป็นหน้าติดล็อกของผู้ใช้ทั่วไป if (isSubscriber && isContentLocked && isUserDisabled) { if (!sessionStorage.getItem(pageKey)) { sessionStorage.setItem(pageKey, '1'); console.warn("CDN Subscriber Cache Mismatch detected Reloading to fetch live content from origin..."); window.location.reload(); return true; } } else if (dgsMetaUser && dgsMetaUser.content === 'enable') { sessionStorage.removeItem(pageKey); } return false; } /** * กู้คืนสิทธิ์สมาชิกผ่าน Single Source of Truth (/member/get_member_login) * ไม่ยิง /api/refresh-paywall-cookie ซ้ำซ้อน แต่ดักฟังผลจาก g_member ใน Header * หากพบว่าเป็นสมาชิก (is_subscriber: true) แต่หน้าเว็บปัจจุบันติดแคช Inox CDN หน้าล็อก -> สั่ง Reload เพื่อ Bypass CDN */ function checkAndRecoverPaywallCookie() { const loginCookieName = window.BKP_COOKIE_MEMBER || "__bwp"; const hasLoginCookie = document.cookie.indexOf(loginCookieName + '=') !== -1; const subCookie = getCookie(window._s_c || "_bp_pdgs"); const hasSubCookie = (subCookie === "1"); const pwCookieName = window._p_c || "__bwp_pw"; const hasPwCookie = document.cookie.indexOf(pwCookieName + '=') !== -1; // ถ้ามีคุกกี้สิทธิ์อยู่แล้ว ไม่ต้องทำอะไร if (hasSubCookie || hasPwCookie) { return false; } // ตรวจสอบเฉพาะเมื่อผู้ใช้เข้าสู่ระบบอยู่ (มีคุกกี้ Login) และหน้านี้ติดล็อก const dgsMetaArticle = document.querySelector('meta[name="dgs-content"]'); const isContentLocked = dgsMetaArticle && dgsMetaArticle.content === 'enable'; const dgsMetaUser = document.querySelector('meta[name="dgs-user"]'); const isUserDisabled = !dgsMetaUser || dgsMetaUser.content === 'disable'; if (hasLoginCookie && (isContentLocked || isUserDisabled)) { const pageRecoveryKey = 'pw_recovery_' + window.location.pathname; if (sessionStorage.getItem(pageRecoveryKey)) { return false; } const triggerReloadIfSubscriber = function () { const isSub = (window.g_member && window.g_member.is_subscriber) || hasActiveSubscriptionFromPaywallCookie(); if (isSub) { console.log("Paywall subscriber confirmed via get_member_login. Reloading to bypass CDN cache..."); sessionStorage.setItem(pageRecoveryKey, '1'); window.location.reload(); } }; // ผูกกับ g_member.get_member_login ใน Header (Single Source of Truth) เพื่อไม่ให้ยิงซ้ำ if (window.g_member && typeof window.g_member.get_member_login === 'function') { window.g_member.get_member_login(function () { triggerReloadIfSubscriber(); }); return true; } } return false; } /** * ล้าง Token ออกจาก localStorage เพื่อความปลอดภัยตามมาตรฐานสากล (Token ต้องอยู่ใน HttpOnly Cookie เท่านั้น) */ function cleanupPaywallLocalStorage() { try { const cookieName = window._p_c || "__bwp_pw"; if (localStorage.getItem(cookieName)) { localStorage.removeItem(cookieName); } } catch (e) { // silent fail } } // Initialize trigger immediately on DOM ready without delay to prevent Flash of Content function initDgsPaywall() { // Clean up legacy _t parameter from URL bar if present to keep URL clean if (window.location.search && window.location.search.indexOf('_t=') !== -1 && window.history && window.history.replaceState) { const cleanSearch = window.location.search.replace(/([?&])_t=\d+(&|$)/, '$1').replace(/[?&]$/, ''); const cleanUrl = window.location.pathname + cleanSearch + window.location.hash; window.history.replaceState(null, document.title, cleanUrl); } cleanupPaywallLocalStorage(); if (checkCdnSubscriberCacheMismatch()) { return; } checkAndRecoverPaywallCookie(); initPopupTrigger(); initSubscriptionModalLog(); checkCheckoutStart(); checkPurchaseComplete(); initPaywallCopyProtection(); } if (document.readyState === "complete" || document.readyState === "interactive") { initDgsPaywall(); } else { document.addEventListener("DOMContentLoaded", initDgsPaywall); } })();