1;(function () { 2 // Gamesight gsid -> launcher download link. 3 // Injects the per-visitor Gamesight Session ID into download URLs as 4 // ?distr=<gsid> and mirrors it into a first-party cookie. 5 // 6 // Not gated on cookie consent: gsid generation is handled by analytics.js; 7 // here we just wait for gsid to become available and rewrite the buttons. 8 // Without a gsid the buttons keep their original href. 9 // 10 // Both cookies are also written back after a consent submit â see restoreCookies(). 11 // 12 // Target buttons: any link explicitly marked with data-gs-distr, plus any link 13 // pointing at the Gaijin launcher â so every Download button on every page is 14 // covered without per-button admin toggles or hardcoded distr values. 15 16 var BUTTON_SELECTOR = 'a[data-gs-distr], a[href*="gdn.gaijin.net/launcher"]' 17 var DISTR_PARAM = 'distr' 18 var COOKIE_NAME = 'gsid' 19 var COOKIE_MAX_AGE = 60 * 60 * 24 * 30 // 30 days 20 var SDK_COOKIE_NAME = '_gsid' 21 var SDK_COOKIE_MAX_AGE = 60 * 60 * 24 * 365 // the SDK's own lifetime 22 var POLL_INTERVAL = 200 23 var POLL_TIMEOUT = 8000 24 var RESTORE_INTERVAL = 100 25 var RESTORE_TIMEOUT = 2000 26 27 var applied = false 28 var polling = false 29 var restoring = false 30 var known = '' // last id seen, kept for restoreCookies() 31 32 function buttons() { 33 return document.querySelectorAll(BUTTON_SELECTOR) 34 } 35 36 function forEach(list, fn) { 37 Array.prototype.forEach.call(list, fn) 38 } 39 40 // Gamesight Web SDK: gsght('get', 'gsid') returns the Session ID once the SDK 41 // has loaded and been initialized (see docs.gamesight.io self-distribution). 42 function getGsid() { 43 if (!window.gsght) return '' 44 try { 45 var id = window.gsght('get', 'gsid') 46 return typeof id === 'string' ? id : '' 47 } catch (e) { 48 return '' 49 } 50 } 51 52 // Parsed with string operations on purpose: Autoptimize's JS minifier drops the 53 // line break after a regex literal that has no flags. 54 function cookieValue(name, raw) { 55 var parts = document.cookie ? document.cookie.split(';') : [] 56 57 for (var i = 0; i < parts.length; i++) { 58 var pair = parts[i].split('=') 59 if (pair.shift().trim() !== name) continue 60 61 var value = pair.join('=') 62 if (raw) return value 63 64 try { 65 return decodeURIComponent(value) 66 } catch (e) { 67 return value 68 } 69 } 70 71 return '' 72 } 73 74 function setDistr(href, gsid) { 75 try { 76 var url = new URL(href, window.location.href) 77 url.searchParams.set(DISTR_PARAM, gsid) 78 return url.toString() 79 } catch (e) { 80 return href // keep original href on malformed URL 81 } 82 } 83 84 function writeCookie(gsid) { 85 document.cookie = COOKIE_NAME + '=' + encodeURIComponent(gsid) + 86 '; path=/; max-age=' + COOKIE_MAX_AGE + '; SameSite=Lax' 87 } 88 89 // Mirrors where the SDK puts _gsid: it drops the first label of the host, and 90 // falls back to the full host when that leaves a bare TLD the browser rejects. 91 // Landing anywhere else would leave a second _gsid the SDK may read instead. 92 function sdkCookieDomain() { 93 var labels = window.location.hostname.split('.') 94 if (labels.length === 1) return '' // no domain attribute on a bare host 95 96 labels.shift() 97 if (labels.length === 1) return '; domain=.' + window.location.hostname 98 99 return '; domain=.' + labels.join('.') 100 } 101 102 // Written the way the SDK writes it â same name, domain and lifetime, and the 103 // bare uuid it stores, unencoded â so the SDK picks the id back up on the next 104 // page view instead of minting a new one. 105 function writeSdkCookie(gsid) { 106 document.cookie = SDK_COOKIE_NAME + '=' + gsid + 107 '; path=/; max-age=' + SDK_COOKIE_MAX_AGE + sdkCookieDomain() 108 } 109 110 function apply(gsid) { 111 if (applied) return 112 known = gsid 113 writeCookie(gsid) 114 writeSdkCookie(gsid) 115 forEach(buttons(), function (btn) { 116 var href = btn.getAttribute('href') 117 if (!href) return 118 btn.setAttribute('href', setDistr(href, gsid)) 119 }) 120 applied = true 121 } 122 123 function waitForGsid() { 124 if (polling || applied) return 125 var gsid = getGsid() 126 if (gsid) { apply(gsid); return } 127 128 polling = true
129 var elapsed = 0 130 var timer = setInterval(function () { 131 elapsed += POLL_INTERVAL 132 var id = getGsid() 133 if (id) { 134 clearInterval(timer) 135 polling = false 136 apply(id) 137 } else if (elapsed >= POLL_TIMEOUT) { 138 clearInterval(timer) 139 polling = false // give up; fallback href stays 140 } 141 }, POLL_INTERVAL) 142 } 143 144 // Mirrors analytics.js: with the rollback flag off, consent governs the id again 145 // and putting the cookies back would defeat it. 146 function preConsentEnabled() { 147 return !(window.UFL_GSID && window.UFL_GSID.preConsent === false) 148 } 149 150 function writeBoth() { 151 writeCookie(known) 152 writeSdkCookie(known) 153 } 154 155 // Cookiebot wipes its Unclassified category on every consent submit, accept and 156 // decline alike, and both ids are listed there. The value is still in memory, so 157 // it is written back. The wipe is not ordered against the events Cookiebot 158 // dispatches, so the window is watched rather than guessed at â a wipe arriving 159 // late would otherwise drop the id silently. 160 // Drop this once the ids are classified in the Cookiebot panel. 161 function restoreCookies() { 162 if (!known || restoring) return 163 164 writeBoth() 165 166 restoring = true 167 var elapsed = 0 168 var timer = setInterval(function () { 169 elapsed += RESTORE_INTERVAL 170 171 if (cookieValue(COOKIE_NAME) !== known || 172 cookieValue(SDK_COOKIE_NAME, true) !== known) writeBoth() 173 174 if (elapsed >= RESTORE_TIMEOUT) { 175 clearInterval(timer) 176 restoring = false 177 } 178 }, RESTORE_INTERVAL) 179 } 180 181 function init() { 182 known = known || cookieValue(COOKIE_NAME) || cookieValue(SDK_COOKIE_NAME, true) 183 184 if (preConsentEnabled()) { 185 window.addEventListener('CookiebotOnConsentReady', restoreCookies) 186 window.addEventListener('CookiebotOnAccept', restoreCookies) 187 window.addEventListener('CookiebotOnDecline', restoreCookies) 188 } 189 190 // Runs on every page, not only where there is a button to rewrite: a visitor 191 // who consents on a page without one has to carry the id onwards too. 192 waitForGsid() 193 } 194 195 document.addEventListener('DOMContentLoaded', init) 196})()
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.