1(function () { 2 const urlParams = new URLSearchParams(window.location.search); 3 const domain = urlParams.get('domain-r'); 4 const click_id = urlParams.get('sub1') || urlParams.get('uuid'); 5 const baseUrl = domain ? `https://${domain}` : null; 6 7 if (!click_id || !baseUrl) return; 8 9 const config = { 10 baseUrl, 11 click_id, 12 retryCount: 15, 13 retryDelay: 10000 14 }; 15 16 // Storage for timers and listeners 17 const cleanup = { 18 intervals: [], 19 timeouts: [], 20 eventListeners: [], 21 abortControllers: [] 22 }; 23 24 document.addEventListener("DOMContentLoaded", () => { 25 if (!domain) return; 26 27 checkTime(); 28 resolution(); 29 initializeMouseTracking(); 30 detectSocialLogin(); 31 }); 32 33 // --- 1. Tracking Activity/Inactivity Time --- 34 function checkTime() { 35 let tabActive = !document.hidden; 36 let activeTime = 0; 37 let hiddenTime = 0; 38 const intervalSec = 3; 39 40 const timerId = setInterval(() => { 41 if (tabActive) { 42 activeTime += intervalSec; 43 console.log('activeTime =', activeTime); 44 sendEvent('mainEvent', 'time', intervalSec); 45 } else { 46 hiddenTime += intervalSec; 47 console.log('hiddenTime =', hiddenTime); 48 } 49 }, intervalSec * 1000); 50 51 cleanup.intervals.push(timerId); 52 53 document.addEventListener("visibilitychange", () => { 54 tabActive = !document.hidden; 55 }); 56 } 57 58 // --- 2. Screen resolution --- 59 function resolution() { 60 const size = `${window.screen.width}x${window.screen.height}`; 61 sendEvent('mainEvent', 'resolution', size); 62 } 63 64 // --- 3. Sending events --- 65 function sendEvent(action, event, value) { 66 const payload = { action, event, value, uuid: config.click_id }; 67 sendWithRetry(`${config.baseUrl}/events/main`, payload, config.retryCount); 68 } 69 70 function sendCustomEvent(id, value) { 71 const payload = { 72 action: 'customEvent', 73 event: 'event', 74 event_id: id, 75 value, 76 click_id: config.click_id 77 }; 78 const tid = setTimeout(() => sendWithRetry(`${config.baseUrl}/events`, payload, config.retryCount), 3000); 79 cleanup.timeouts.push(tid); 80 } 81 82 function sendWithRetry(url, data, retriesLeft) { 83 const controller = new AbortController(); 84 cleanup.abortControllers.push(controller); 85 86 fetch(url, { 87 method: 'POST', 88 headers: { 'Content-Type': 'application/x-www-form-urlencoded' }, 89 body: new URLSearchParams(data), 90 signal: controller.signal 91 }) 92 .then(res => res.json()) 93 .then(res => { 94 if (res.status !== 'success' && retriesLeft > 0) { 95 const tid = setTimeout(() => sendWithRetry(url, data, retriesLeft - 1), config.retryDelay); 96 cleanup.timeouts.push(tid); 97 } 98 }) 99 .catch(() => { 100 if (retriesLeft > 0) { 101 const tid = setTimeout(() => sendWithRetry(url, data, retriesLeft - 1), config.retryDelay); 102 cleanup.timeouts.push(tid); 103 } 104 }); 105 } 106 107 // --- 4. Tracking mouse/touch movements --- 108 function initializeMouseTracking() { 109 window.isMove = 0; 110 const events = ["touchmove", "touchstart", "touchend", "mouseover", "mouseenter", "wheel", "mousemove"]; 111 112 function mouseMove(e) { 113 if (!window.isMove) { 114 window.isMove = 1; 115 sendCustomEvent('4ab66022-4d47-4764-9a6d-738953e6fc06', 1); 116 console.log('Mouse/touch movement detected'); 117 118 // After the first trigger, remove all listeners 119 events.forEach(evt => document.body.removeEventListener(evt, mouseMove)); 120 } 121 } 122 123 events.forEach(evt => { 124 document.body.addEventListener(evt, mouseMove, { passive: true }); 125 cleanup.eventListeners.push({ target: document.body, type: evt, handler: mouseMove }); 126 }); 127 } 128 129 // --- 5. Reload page --- 130 const pageReloaded = 131 (window.performance.navigation && window.performance.navigation.type === 1) || 132 window.performance 133 .getEntriesByType('navigation') 134 .some(nav => nav.type === 'reload'); 135 136 if (pageReloaded) { 137 sendCustomEvent('a521accd-3af3-444e-baac-5eab1b67bec5', 1); 138 } 139 140 // --- 6. Determining authorization in social networks --- 141 async function detectSocialLogin() { 142 const services = [ 143 { 144 domain: "accounts.google.com", 145 redirect: "/ServiceLogin?passive=true&continue=https%3A%2F%2Fwww.google.com%2Ffavicon.ico&uilel=3&hl=en&service=mail", 146 name: "Gmail",
147 icon: "ssl.gstatic.com/ui/v1/icons/mail/images/favicon5.ico" 148 }, 149 { 150 domain: "accounts.google.com", 151 redirect: "/ServiceLogin?passive=true&continue=https%3A%2F%2Fwww.youtube.com%2Ffavicon.ico&uilel=3&hl=en&service=youtube", 152 name: "Youtube", 153 icon: "s.ytimg.com/yts/img/favicon_32-vflOogEID.png" 154 }, 155 { 156 domain: "login.skype.com", 157 redirect: "/login?message=signin_continue&redirect_uri=https%3A%2F%2Fsecure.skype.com%2Ffavicon.ico", 158 name: "Skype" 159 }, 160 { 161 domain: "www.spotify.com", 162 redirect: "/en/login/?forward_url=https%3A%2F%2Fwww.spotify.com%2Ffavicon.ico", 163 name: "Spotify" 164 }, 165 { 166 domain: "www.reddit.com", 167 redirect: "/login/?dest=https%3A%2F%2Fwww.reddit.com%2Ffavicon.ico", 168 name: "Reddit" 169 }, 170 { 171 domain: "www.tumblr.com", 172 redirect: "/login?redirect_to=%2Ffavicon.ico", 173 name: "Tumblr" 174 }, 175 { 176 domain: "www.dropbox.com", 177 redirect: "/login?cont=https%3A%2F%2Fwww.dropbox.com%2Fstatic%2Fimages%2Fabout%2Fdropbox_logo_glyph_2015.svg", 178 name: "Dropbox", 179 icon: "www.dropbox.com/static/images/favicon.ico" 180 }, 181 { 182 domain: "www.amazon.com", 183 redirect: "/ap/signin/178-4417027-1316064?_encoding=UTF8&openid.assoc_handle=usflex&openid.claimed_id=http%3A%2F%2Fspecs.openid.net%2Fauth%2F2.0%2Fidentifier_select&openid.identity=http%3A%2F%2Fspecs.openid.net%2Fauth%2F2.0%2Fidentifier_select&openid.mode=checkid_setup&openid.ns=http%3A%2F%2Fspecs.openid.net%2Fauth%2F2.0&openid.ns.pape=http%3A%2F%2Fspecs.openid.net%2Fextensions%2Fpape%2F1.0&openid.pape.max_auth_age=10000000&openid.return_to=https%3A%2F%2Fwww.amazon.com%2Ffavicon.ico", 184 name: "Amazon.com" 185 }, 186 { 187 domain: "www.pinterest.com", 188 redirect: "/login/?next=https%3A%2F%2Fwww.pinterest.com%2Ffavicon.ico", 189 name: "Pinterest" 190 }, 191 { 192 domain: "us.battle.net", 193 redirect: "/login/en/index?ref=/forums/static/images/icons/bnet-favicon.ico", 194 name: "Battle.net", 195 icon: "us.battle.net/forums/static/images/icons/bnet-favicon.ico" 196 }, 197 { 198 domain: "store.steampowered.com", 199 redirect: "/login/?redir=favicon.ico", 200 name: "Steam" 201 }, 202 { 203 domain: "accounts.google.com", 204 redirect: "/ServiceLogin?service=blogger&hl=de&passive=1209600&continue=https://www.blogger.com/favicon.ico", 205 name: "Blogger" 206 }, 207 { 208 domain: "github.com", 209 redirect: "/login?return_to=https%3A%2F%2Fgithub.com%2Ffavicon.ico%3Fid%3D1", 210 name: "Github" 211 }, 212 { 213 domain: "news.ycombinator.com", 214 redirect: "/login?goto=y18.gif%23", 215 name: "Hackernews" 216 }, 217 { 218 domain: "courses.edx.org", 219 redirect: "/login?next=/favicon.ico", 220 name: "EdX" 221 }, 222 { 223 domain: "slack.com", 224 redirect: "/checkcookie?redir=https%3A%2F%2Fslack.com%2Ffavicon.ico%23", 225 name: "Slack" 226 }, 227 { 228 domain: "www.airbnb.com", 229 redirect: "/login?redirect_params[action]=favicon.ico&redirect_params[controller]=home", 230 name: "Airbnb" 231 }, 232 { 233 domain: "disqus.com", 234 redirect: "/profile/login/?next=https%3A%2F%2Fdisqus.com%2Ffavicon.ico", 235 name: "Disqus" 236 }, 237 { 238 domain: "vk.com", 239 redirect: "/login?u=2&to=ZmF2aWNvbi5pY28-", 240 name: "VK" 241 }, 242 { 243 domain: "www.twitch.tv", 244 redirect: "/login?redirect_on_login=/favicon.ico", 245 name: "Twitch" 246 } 247]; 248 249 250 const results = await Promise.all(services.map(service => 251 tryImg(service).catch(() => false) 252 )); 253 254 if (results.some(r => r)) { 255 sendCustomEvent('4dc871b0-6b51-43ff-b1b1-8dd1af5fa1b0', 1); 256 } 257 } 258 259 function tryImg(service) { 260 return new Promise((resolve, reject) => { 261 const img = new Image(); 262 const controller = new AbortController(); 263 cleanup.abortControllers.push(controller); 264 265 img.onload = () => { 266 resolve(true); 267 img.onload = img.onerror = null; 268 }; 269 img.onerror = () => { 270 reject(false); 271 img.onload = img.onerror = null; 272 }; 273 274 img.src = `https://${service.domain}${service.redirect}`; 275 }); 276 } 277 278 // --- 7. Defining bots --- 279 let botdLoaded = null; 280 const botdPromise = botdLoaded 281 ? Promise.resolve(botdLoaded) 282 : import('https://openfpcdn.io/botd/v1').then((Botd) => { 283 botdLoaded = Botd; 284 return Botd.load(); 285 }); 286 287 botdPromise 288 .then((botd) => botd.detect()) 289 .then((result) => { 290 if (result.bot) { 291 sendCustomEvent('7e71e560-b6b1-44de-8ae9-ea9452053c3c', 1); 292 } 293 }) 294 .catch(() => { 295 // Error - we are not sending anything 296 }); 297 298 // --- Clearing resources when closing the page --- 299 window.addEventListener("beforeunload", () => {
300 cleanup.intervals.forEach(clearInterval); 301 cleanup.timeouts.forEach(clearTimeout); 302 cleanup.eventListeners.forEach(({ target, type, handler }) => { 303 target.removeEventListener(type, handler); 304 }); 305 cleanup.abortControllers.forEach(ctrl => ctrl.abort()); 306 }); 307 308})();
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.