PageSourceSearch

https://worldstar.com/signup-options

html worldstar.com collected 2026-09-25 14:34:00 UTC 43,157 bytes, 1,140 lines download raw bytes

1
2<!DOCTYPE html>
3<html lang="en">
4<head>
5  <meta charset="utf-8" />
6  <!-- Google Tag Manager -->
7<script>
vendor: 359 bytes, lines 7-11
7(function(w,d,s,l,i){w[l]=w[l]||[];w[l].push({'gtm.start':
8            new Date().getTime(),event:'gtm.js'});var f=d.getElementsByTagName(s)[0],
9        j=d.createElement(s),dl=l!='dataLayer'?'&l='+l:'';j.async=true;j.src=
10        'https://www.googletagmanager.com/gtm.js?id='+i+dl;f.parentNode.insertBefore(j,f);
11    })(window,document,'script','dataLayer','
11GTM-N8PRK68K
vendor: 3 bytes, line 11
11');
11</script>
11
12<!-- End Google Tag Manager -->  <meta http-equiv="content-language" content="en" />
13  <meta name="viewport" content="width=device-width, initial-scale=1.0">
14  <title>Worldstarhiphop: Breaking News | Music Videos | Entertainment News | Hip Hop News</title>
15  <link href="https://worldstar.com/signup-options" rel="canonical" />
16  <meta name="description" content="WorldstarHipHop is home to everything entertainment & hip hop. The #1 urban outlet responsible for breaking the latest urban news!">
17  <!-- Datadog initialization -->
18  
18<script type="text/javascript" src="https://www.datadoghq-browser-agent.com/datadog-logs-v4.js" crossorigin="anonymous"></script>
vendor: 1 bytes, line 18
18
19<script>
20  window.DD_LOGS &&
21    DD_LOGS.init({
22      clientToken: 'pub82afa1d2b2f8f61681f12acc743f0ad0',
23      
24      /* datadog's site used by our organization */
25      site: 'us5.datadoghq.com',
26
27      service: 'web-legacy',
28      
29      /* forward console.error logs, uncaught exceptions and network errors to Datadog. */
30      forwardErrorsToLogs: true,
31      
32      /* percentage of sessions to track: 100 for all, 0 for none. Only tracked sessions send logs. */
33      sampleRate: 1,
34    });
35  
36  // set minimum logging level, error for now
37  window.DD_LOGS && DD_LOGS.logger.setLevel('error');
38
39  // send logs to console and datadog (https://docs.datadoghq.com/logs/log_collection/javascript/)
40  window.DD_LOGS && DD_LOGS.logger.setHandler('http')
41</script>
41
42  <!-- JQuery script -->
43  
43<script src="https://code.jquery.com/jquery-3.5.1.min.js" integrity="sha256-9/aliU8dGd2tb6OSsuzixeV4y/faTqgFtohetphbbj0=" crossorigin="anonymous"></script>
43
44  <!-- For some reason jquery seems not to be loaded at times, this is the purpose of the hack below -->
45  
45<script type="text/javascript">
46    window.jQuery || document.write('
46<script src="/videos/js/jquery-3.5.1.min.js"><\/script>')
47  </script>
47
48  
48<script src="https://code.jquery.com/jquery-migrate-3.3.2.min.js" integrity="sha256-Ap4KLoCf1rXb52q+i3p0k2vjBsmownyBTE1EqlRiMwA=" crossorigin="anonymous"></script>
48
49
50  
50<script type="text/javascript" src="https://cdn.jsdelivr.net/gh/cure53/DOMPurify@main/dist/purify.min.js"></script>
50
51  
51<script type="text/javascript" src="https://cdn.jsdelivr.net/npm/uuid@latest/dist/umd/uuid.min.js"></script>
51
52  
52<script type="text/javascript" src="/videos/js/utils.js"></script>
52
53
54  <!-- Bootstrap css -->
55  <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css" integrity="sha384-Gn5384xqQ1aoWXA+058RXPxPg6fy4IWvTNh0E263XmFcJlSAwiGgFAW/dAiS6JXm" crossorigin="anonymous">
56
57  <!-- css -->
58  <link media="all" rel="stylesheet" href="/videos/assets/css/fonts.css">
59  <link media="all" rel="stylesheet" href="/videos/assets/css/all.css">
60  <link media="all" rel="stylesheet" href="/videos/assets/css/login-options.css">
61  <link href="/videos/assets/css/searchbar.css" rel="stylesheet">
62  <!-- /css -->
63
64  <!-- reCAPTCHA Enterprise -->
vendor: 70 bytes, lines 64-65
64
65  <script src="https://www.google.com/recaptcha/enterprise.js?render=
656Ld3YiAcAAAAAGVgqURL_hmxqsn8q0liHgBRqkt9
vendor: 15 bytes, lines 65-67
65"></script>
66
67  
67<!-- Begin GA SETUP -->
vendor: 66 bytes, lines 67-68
67
68  <script async src="https://www.googletagmanager.com/gtag/js?id=
68UA-31833046-2
vendor: 12 bytes, line 68
68"></script>
69<script id="google-analytics">
70  window.dataLayer = window.dataLayer || [];
71  function gtag() {
72    dataLayer.push(arguments);
73  };
74  gtag('js', new Date());
75
76  const assemblyUserId = getAssemblyUID();
77  
78  gtag('config', 'UA-31833046-2', {
79    'send_page_view': false,
80  });
81  if (!assemblyUserId) {
82    gtag('config', 'UA-31833046-2');
83  } else {
84    gtag('config', 'UA-31833046-2', {
85      'user_id': assemblyUserId
86    });
87  }
88</script>
88
89
90  <!-- Init Mixpanel & track page view -->
91	
92
93<script type="text/javascript">
94  // Mixpanel SDK
95  (function (f, b) {
96    if (!b.__SV) {
97      var e, g, i, h;
98      window.mixpanel = b;
99      b._i = [];
100      b.init = function (e, f, c) {
101        function g(a, d) {
102          var b = d.split(".");
103          2 == b.length && ((a = a[b[0]]), (d = b[1]));
104          a[d] = function () {
105            a.push([d].concat(Array.prototype.slice.call(arguments, 0)));
106          };
107        }
108        var a = b;
109        "undefined" !== typeof c ? (a = b[c] = []) : (c = "mixpanel");
110        a.people = a.people || [];
111        a.toString = function (a) {
112          var d = "mixpanel";
113          "mixpanel" !== c && (d += "." + c);
114          a || (d += " (stub)");
115          return d;
116        };
117        a.people.toString = function () {
118          return a.toString(1) + ".people (stub)";
119        };
120        i = "disable time_event track track_pageview track_links track_forms track_with_groups add_group set_group remove_group register register_once alias unregister identify name_tag set_config reset opt_in_tracking opt_out_tracking has_opted_in_tracking has_opted_out_tracking clear_opt_in_out_tracking start_batch_senders people.set people.set_once people.unset people.increment people.append people.union people.track_charge people.clear_charges people.delete_user people.remove".split( " ");
121        for (h = 0; h < i.length; h++) g(a, i[h]);
122        var j = "set set_once union unset remove delete".split(" ");
123        a.get_group = function () {
124          function b(c) {
125            d[c] = function () {
126              call2_args = arguments;
127              call2 = [c].concat(Array.prototype.slice.call(call2_args, 0));
128              a.push([e, call2]);
129            };
130          }
131          for ( var d = {}, e = ["get_group"].concat( Array.prototype.slice.call(arguments, 0)), c = 0; c < j.length; c++) b(j[c]);
132          return d;
133        };
134        b._i.push([e, f, c]);
135      };
136      b.__SV = 1.2;
137      e = f.createElement("script");
138      e.type = "text/javascript";
139      e.async = !0;
140      e.src = "undefined" !== typeof MIXPANEL_CUSTOM_LIB_URL ? MIXPANEL_CUSTOM_LIB_URL : "file:" === f.location.protocol && "//cdn.mxpnl.com/libs/mixpanel-2-latest.min.js".match(/^\/\//) ? "https://cdn.mxpnl.com/libs/mixpanel-2-latest.min.js" : "//cdn.mxpnl.com/libs/mixpanel-2-latest.min.js";
141      g = f.getElementsByTagName("script")[0];
142      g.parentNode.insertBefore(e, g);
143    }
144  })(document, window.mixpanel || []);
145
146  // Mixpanel initialization
147  mixpanel.init("794029538aa6613314df04b12f293456", { persistence: "localStorage" }); // debug: true, 
148
149  // Register mixpanel super properties
150  mixpanel.register({
151    assembly_uid: getAssemblyUID(),
152    user_agent: navigator.userAgent,
153    platform: "desktop",
154    // Set mixpanel's device_id to the wshh uid
155    // it will be set as distinct_id in Mixpanel as well since there is not user_id: https://docs.mixpanel.com/docs/tracking-methods/id-management/identifying-users-simplified
156    $device_id: getWSHHUID(),
157  });
158
159  // Track page view
160  mixpanel.track_pageview({
161    page: "singup_options",
162    counts_as_page_load: true,
163  });
164
165  const getPageFromPathname = (pathname) => {
166    if (!pathname) return '';
167    const pegaPath = pathname.split('/') || [];
168    let page = pegaPath.length > 1 ? pegaPath[1] : pathname;
169
170    if (page === 'videos') page = 'home';
171    else if (page === '') page = 'clean_home';
172
173    return page;
174  };
175
176  const trackMixpanelLinkEvent = function(elementId, eventName, extraProps = {}) {
177    extraProps.page = getPageFromPathname(document.location.pathname);
178    mixpanel.track_links(elementId, eventName, extraProps);
179  }
180
181  const trackMixpanelEvent = function(eventName, extraProps = {}) {
182    extraProps.page = getPageFromPathname(document.location.pathname);
183    try {
184      mixpanel.track(eventName, extraProps);
185    } catch (error) {
186      console.error("mixpanel-sdk Error logging mixpanel event:", error);
187    }
188  }
189
190  trackMixpanelLinkEvent('#deals', 'deals_btn_click');
191  // Source code
192  // https://cdn.mxpnl.com/libs/mixpanel-2-latest.min.js
193</script>
193
194</head>
195
196<body>
197  <!-- Bootstrap script -->
198  
198<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.12.9/umd/popper.min.js" integrity="sha384-ApNbgh9B+Y1QKtv3Rn7W3mgPxhU9K/ScQsAP7hUibX39j7fakFPskvXusvfa0b4Q" crossorigin="anonymous"></script>
198
199  
199<script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/js/bootstrap.min.js" integrity="sha384-JZR6Spejh4U02d8jOt6vLEHfe/JQGiRRSQQxSfFWpi1MquVdAyjUar5+76PVCmYl" crossorigin="anonymous"></script>
199
200  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/[email protected]/font/bootstrap-icons.css">
201  <!-- The core Firebase JS SDK is always required and must be listed first -->
202<script type="text/javascript" src="https://www.gstatic.com/firebasejs/8.10.1/firebase-app.js"></script>
202
203
204<!-- TODO: Add SDKs for Firebase products that you want to use https://firebase.google.com/docs/web/setup#available-libraries -->
205<script type="text/javascript" src="https://www.gstatic.com/firebasejs/8.10.1/firebase-auth.js"></script>
vendor: 1 bytes, line 205
205
206<script type="text/javascript" src="https://www.gstatic.com/firebasejs/8.10.1/firebase-analytics.js"></script>
vendor: 1 bytes, line 206
206
207<script type="text/javascript" src="https://www.gstatic.com/firebasejs/8.10.1/firebase-storage.js"></script>
vendor: 1 bytes, line 207
207
208<script type="text/javascript" src="https://www.gstatic.com/firebasejs/8.10.1/firebase-messaging.js"></script>
208
209
210<script type="text/javascript">
211  // Your web app's Firebase configuration
212  // For Firebase JS SDK v7.20.0 and later, measurementId is optional
213  const firebaseConfig = {
214    apiKey: "AIzaSyCHcbax-cz17PSX-2PsHgLcR4SI6RK9B1A",
215    authDomain: "auth.worldstar.com",
216    databaseURL: "https://wshh-b00d4.firebaseio.com",
217    projectId: "wshh-b00d4",
218    storageBucket: "wshh-b00d4.appspot.com",
219    messagingSenderId: "291183115057",
220    appId: "1:291183115057:web:9e4524f783be0c3d3f0e10",
221    measurementId: "G-HM4QS6BBEL"
222  };
223
224  const TEN_YEARS = 24 * 365 * 10;
225
226  // Initialize Firebase
227  firebase.initializeApp(firebaseConfig);
228  // Get the Analytics service for the app
229  const analyticsService = firebase.analytics();
230  // Get the Auth service for the app
231  const auth = firebase.auth();
232  // Set the app's storage location
233  const storageRef = firebase.app().storage('gs://wshh-user-uploads/').ref();
234
235  const fbPathname = window.location.pathname.split('/').pop();
236
237  // Helper functions
238  const getProfileImageURL = function(user) {
239    // Check if this is the photoURL generated by us using the timestamp
240    if (user.photoURL) {
241      return user.photoURL;
242    }
243    return '';
244  }
245
246  const getUserID = function() {
247    if (auth.currentUser) {
248      return auth.currentUser.uid;
249    }
250    return null;
251  }
252  // Helper functions end
253
254  const updateUserState = function(user, callback) {
255    if (!user) return;
256
257    // never delete this cookie
258    if (user.email) setCookie(LIVERAMP_EMAIL_COOKIE, user.email, TEN_YEARS);
259
260    const username = user.displayName || '';
261    const userImg = getProfileImageURL(user);
262    $('.username').text(username).show(600);
263
264    if (userImg) {
265      $('.profile-icon-txt').hide(500);
266      $('.profile-icon-img').attr('src', userImg).show(600);
267    } else {
268      $('.profile-icon-img').hide(0);
269      $('.profile-icon-txt').text(username[0]).show(0);
270    }
271
272    typeof callback === 'function' && callback();
273  }
274
275  const selectVideoEv = function(video_id, page, section, platform = '', cohort = '') {
276    logFirebaseEvent(
277      'select_video',
278      {
279        'extra': page,
280        'section': section,
281        'vid': video_id,
282        'platform': platform,
283      }
284    );
285    trackMixpanelEvent(
286      'select_video',
287      {
288        'section': section,
289        'video_id': video_id,
290        ...(cohort !== '' && { 'cohort': cohort }),
291      }
292    );
293  }
294
295  /**
296   * Logs a Firebase event. 
297   * 
298   * NOTE: event name character limit is 40 characters. (see https://firebase.google.com/docs/reference/cpp/group/event-names#:~:text=Event%20names%20can%20be%20up,start%20with%20an%20alphabetic%20character.)
299   * @param {string} event - The name of the event
300   * @param {object} data - The parameters to pass to the event
301   */
302  const logFirebaseEvent = function(event, data = {}) {
303    data.page = document.location.pathname.substring(1);
304    try {
305      firebase.analytics().logEvent(event, data);
306    } catch (error) {
307      console.error("firebase-sdk Error logging firebase event:", error);
308    }
309  }
310
311  const logoutUser = function() {
312    auth.signOut()
313      .then(function() {
314        logFirebaseEvent('logout_tapped');
315        trackMixpanelEvent('logout_tapped');
316        window.location = '/';
317      }).catch(function(err) {
318        setError(err);
319        console.error("firebase-sdk Error in logoutUser:", err);
320      });
321  }
322
323  const sendPasswordResetEmail = function(email, cb) {
324    const url = 'https://worldstar.com/login-options';
325    const actionCodeSettings = {
326      'url': url,
327      'android': {
328        'installApp': true,
329        'packageName': 'com.pt.wshhp',
330      },
331      'iOS': {
332        'bundleId': 'com.wshh.com',
333      },
334      'handleCodeInApp': true,
335    }
336    auth
337      .sendPasswordResetEmail(email, actionCodeSettings)
338      .then(function() {
339        logFirebaseEvent('reset_password_tapped');
340        trackMixpanelEvent('reset_password_tapped');
341        cb ? cb() : null;
342      })
343      .catch(function(err) {
344        setError(err);
345        console.error("firebase-sdk Error sendPasswordResetEmail:", err);
346      });
347  }
348
349  const resetPassword = function(code, newPassword) {
350    try {
351      auth.confirmPasswordReset(code, newPassword)
352        .then(function() {
353          window.location = '/reset-success';
354        }).catch(function(err) {
355          setError(err);
356          console.error("firebase-sdk Error in confirmPasswordReset:", err);
357        });
358    } catch (err) {
359      console.error("firebase-sdk Error exception caught in confirmPasswordReset:", err);
360    }
361  }
362
363  const signUpUser = function(details = {}) {
364    const email = details.email;
365    const password = details.password;
366    
367    // displayName
368    const extra = details.extra;
369
370    try {
371      auth
372        .createUserWithEmailAndPassword(email, password)
373        .then(function(cred) {
374          const user = cred.user;
375          // TODO bring back anonymous linking
376          // we have been doing anonymous linking wrong which is causing it to be wonky
377          // this link can help us do it right when we are ready to implement it, hopefully after single sign on
378          // https://stackoverflow.com/questions/39088876/firebase-convert-anonymous-user-account-to-permanent-account-error
379          // const credential = firebase.auth.EmailAuthProvider.credential(email, password);
380          // linkUserToProvider(credential)
381
382          // Update a temporary display name = email
383          user.updateProfile(extra);
384          // save the user in spanner via mobile-api, it will redirect the user to the profile page
385          saveUserToWS(user);
386        })
387        .catch(function(err) {
388          const eventData = {
389            'email': email,
390            // error codes available: https://firebase.google.com/docs/reference/js/v8/firebase.auth.Auth#createuserwithemailandpassword 
391            'errorCode': err.code,
392          };
393          logFirebaseEvent('account_creation_failed', eventData);
394          trackMixpanelEvent('account_creation_failed', eventData);
395          setError(err);
396          console.error("firebase-sdk Error in createUserWithEmailAndPassword:", err);
397        });
398    } catch (err) {
399      const eventData = {
400        'email': email,
401        'errorCode': err.code,
402      };
403      logFirebaseEvent('account_creation_failed', eventData);
404      trackMixpanelEvent('account_creation_failed', eventData);
405      setError(err);
406      console.error("firebase-sdk Error exception caught in signUpUser:", err);
407    }
408  }
409
410  const sendEmailVerification = function() {
411    const actionCodeSettings = {
412      'url': 'https://worldstar.com/profile',
413      'android': {
414        'installApp': true,
415        'packageName': 'com.pt.wshhp',
416      },
417      'iOS': {
418        'bundleId': 'com.wshh.com',
419      }
420    };
421    auth.currentUser
422      .sendEmailVerification(actionCodeSettings)
423      .then(function() {
424        logFirebaseEvent('verify_email_prompt_resend_confirmation');
425        trackMixpanelEvent('verify_email_prompt_resend_confirmation');
426      })
427      .catch(function(err) {
428        logFirebaseEvent('send_email_verification_failed');
429        trackMixpanelEvent('send_email_verification_failed');
430        console.error("firebase-sdk Error exception in sendEmailVerification:", err);
431      });
432  }
433
434  const loginUser = function(details = {}) {
435    const email = details.email;
436    const password = details.password;
437    try {
438      auth
439        .signInWithEmailAndPassword(email, password)
440        .then(function() {
441          // Get provider credential data from sessionStorage
442          const credential = sessionStorage.cred;
443          if (credential) {
444            const credentialFromJSON = firebase.auth.AuthCredential.fromJSON(credential);
445            linkUserToProvider(credentialFromJSON);
446            sessionStorage.removeItem('cred');
447          };
448          logFirebaseEvent('login_succeeded');
449          trackMixpanelEvent('login_succeeded');
450          window.location = '/profile';
451        })
452        .catch(function(err) {
453          const eventData = {
454            'email': email,
455          };
456          logFirebaseEvent('login_failed', eventData);
457          trackMixpanelEvent('login_failed', eventData);
458          setError(err);
459          console.error("firebase-sdk Error exception in signInWithEmailAndPassword:", err);
460        });
461    } catch (err) {
462      const eventData = {
463        'email': email,
464      };
465      logFirebaseEvent('login_failed', eventData);
466      trackMixpanelEvent('login_failed', eventData);
467      setError(err);
468      console.error("firebase-sdk Error exception in loginUser:", err);
469    }
470  }
471
472  const linkUserToProvider = function(credential, user = auth.currentUser) {
473    user.linkWithCredential(credential)
474      .catch(function(err) {
475          console.error("firebase-sdk Error in linkUserToProvider user.linkWithCredential:", err.message);
476      });
477  }
478
479  $(window).on('load', function() {
480    /*
481      Adding these events from here since I am certain I'll have access to the firebase sdk.
482    */
483    // Profile Icon
484    $('#login-icon').click(function() {
485      logFirebaseEvent('profile_icon_tapped');
486      trackMixpanelEvent('profile_icon_tapped');
487    });
488
489    // Home Button
490    $('.navbar-brand').click(function() {
491      logFirebaseEvent('home_button_tapped');
492      trackMixpanelEvent('home_button_tapped');
493    });
494
495    const media = ['facebook', 'twitter', 'reddit', 'all', 'whatsapp'];
496    media.forEach(function(currMedia) {
497      let selector = 'li[data-service="' + currMedia + '"] .shareaholic-share-button-sizing';
498      $(selector).click(function() {
499        const eventData = {
500          'extra': currMedia
501        };
502        logFirebaseEvent('share_video', eventData);
503        trackMixpanelEvent('share_video', eventData);
504      });
505    });
506    
507    // PROFILE PAGE: get the logged user or redirect to signup-options
508    // Other pages related to login or signup processes: redirect to profile if user is logged in
509    auth.onAuthStateChanged((user) => {
510      if (fbPathname === 'profile' || fbPathname === 'edit-profile') {
511        if (user) {
512          // log out anonymous users
513          if (user.isAnonymous) {
514            logoutUser();
515          }
516
517          // get the current user from spanner, if it does not exists getWSUser will redirect to signup-options
518          getWSUser(function (wsUser) {
519            user
520              .updateProfile({
521                displayName: wsUser.username,
522                photoURL: wsUser.profile_picture,
523              })
524              .then(() => updateUserState(user))
525          });
526
527          if (!user.emailVerified) {
528            const verificationModal = new bootstrap.Modal(document.getElementById('email-verification-modal'));
529            verificationModal.show();
530            logFirebaseEvent('verify_email_address_prompt_displayed');
531            trackMixpanelEvent('verify_email_address_prompt_displayed');
532          }
533        } else {
534          window.location.href = '/signup-options';
535        }
536      }
537      else if ((fbPathname === 'login' || fbPathname === 'login-options' || fbPathname === 'signup' || fbPathname === 'signup-options') && user) {
538        window.location.href = '/profile';
539      }
540
541      // Set the correct url for login icon in navbar
542      if ($('#login-icon')) {
543        if (user) $('#login-icon').attr('href', '/profile');
544        else $('#login-icon').attr('href', '/signup-options');
545      }
546    });
547  });
548</script>
548
549
550<script type="text/javascript">
551  if (firebase.messaging.isSupported()) {
552    const messaging = firebase.messaging();
553
554    // Get registration token. Initially this makes a network call, once retrieved
555    // subsequent calls to getToken will return from cache.
556    messaging.getToken({
557        vapidKey: 'BGGzqoXPgxKc_926Hixp4fu2uxa_wehF57lhWvu_KeiDKoj0-9i2Fjg5yUlEeB-f0ihbV6Vqumij36cyYd5EpkM'
558      })
559      .then((currentToken) => {
560        if (currentToken) {
561          // Send the token to your server and update the UI if necessary
562          // console.log('got token', currentToken)
563        } else {
564          // Show permission request UI
565          // console.log('No registration token available. Request permission to generate one.');
566        }
567      }).catch(function (err) {
568        console.error("Error in firebase-messaging messaging.getToken:", err);
569      });
570
571    // When a push message is received and the user is currently on a page for your origin,
572    // the message is passed to the page and an onMessage() event is dispatched with the payload of the push message.
573    messaging.onMessage((payload) => {
574      const payloadNotification = payload?.notification;
575      const notificationTitle = payloadNotification?.title;
576      const notificationIcon = payload?.notification?.icon || '/videos/assets/images/circle-crown.png';
577      const notificationBody = payloadNotification?.body;
578      const notificationClickAction = payloadNotification?.click_action || notificationBody;
579      const notificationOptions = {
580        body: notificationBody,
581        icon: notificationIcon,
582      };
583
584      const notification = new Notification(notificationTitle, notificationOptions);
585
586      notification.onclick = function (ev) {
587        ev.preventDefault();
588        window.open(notificationClickAction, '_blank');
589        notification.close();
590      }
591    });
592  }
593</script>
593
594 
595<!-- Include Spanner functions -->
596<script src="/utils/spanner.js"></script>
596
597<!-- Include Provider sign in functions -->
598<script src="/utils/provider-sso.js"></script>
598
599<!-- Google Tag Manager (noscript) -->
vendor: 68 bytes, lines 599-600
599
600<noscript><iframe src="https://www.googletagmanager.com/ns.html?id=
600GTM-N8PRK68K
vendor: 101 bytes, lines 600-601
600"
601                  height="0" width="0" style="display:none;visibility:hidden"></iframe></noscript>
602<!-- End Google Tag Manager (noscript) -->  <div id="wrapper" class="static-login">
603    <header id="header">
604      
605<div class="navbar-nav">
606  <nav class="navbar navbar-dark justify-content-between" style="background-color: #121212;">
607    <div class="justify-content-between" style="display: flex; align-items: center">
608      <div class="d-flex align-items-center">
609        <a onclick="onNavLinkClick(event, 'videos/', false)" class="navbar-brand" href="https://worldstarhiphop.com/videos/"><img src="https://worldstarhiphop.com/videos/images/logo_ws_horizontal.png" width="145px" height="30px"></a>
610        <!-- <div class="navbar-text"><a target="_blank" class="nav-link" href="https://worldstardistro.com">DISTRO</a></div> -->
611        <div class="navbar-text"><a class="nav-link" href="https://contact.worldstar.com">CONTACT</a></div>
612        <!-- TODO: restore/update once Flagr Advertise A/B test is complete -->
613        <!-- <div class="navbar-text"><a class="nav-link" href="https://worldstarhiphop.com/videos/vsubmit.php">SUBMIT VIDEO</a></div> -->
614        <div class="navbar-text"><a target="_blank" class="nav-link" href="https://advertise.worldstarhiphop.com">ADVERTISE</a></div>
615        <div class="navbar-text"><a id="deals" class="nav-link" href="https://deals.worldstarhiphop.com/">DEALS</a></div>
616        
617<div id="containerSearchBar" class="relative pt-2">
618  <div class="search-input-container"
619  >
620    <input
621      type="text"
622      id="searchInput"
623      class="search-input search-input-desktop"
624      placeholder="Search..."
625    />
626    <button id="searchButton" class="search-button">
627      <span class="search-button-icon-container bi bi-search h6"></span>
628    </button>
629  </div>
630  <div
631    class="suggestion-container"
632    style="width:20vw;"
633  ></div>
634  <div
635    class="search-overlay"
636    onclick="closeSuggestionList()"
637  ></div>
638</div>
639
640<script type="text/javascript">
641  const VIDEO_SEARCH_SUGGESTION_URL = 'https://api-staging.worldstar.com/search/suggestion';
642  const SEARCH_BAR_CLICK_EVENT = 'search_bar_click';
643  const SEARCH_BUTTON_CLICK_EVENT = 'search_btn_click'; // used when user clicks on search button or run the search by pressing enter on keyboardpass
644  const SEARCH_SUGGESTION_CLICK_EVENT = 'search_suggestion_clicked';
645  const SEARCH_SUGGESTION_SECTION = 'search_suggestion';
646  const SELECT_VIDEO_EVENT = 'select_video';
647  const TAG_BTN_CLICK_EVENT = 'tag_btn_click';
648  const SUGGESTION_VIDEOS = 'videos';
649  const SUGGESTION_TAGS = 'tags';
650  const pageSize = 40;
651  const isMobileView = false;
652  
653  let showSuggestionList = false;
654  let searchTerm = '';
655  let isLoading = false;
656  let searchResults = {
657    tags: [],
658    videos: []
659  };
660
661  const container = document.querySelector('#containerSearchBar');
662  const searchInput = container.querySelector('#searchInput');
663  const searchButton = container.querySelector('#searchButton');
664  const suggestionContainer = container.querySelector('.suggestion-container');
665  const searchOverlay = container.querySelector('.search-overlay');
666
667  const renderTags = () => {
668    return (
669      `<h3 class="result-section-title">TAGS</h3>
670        <ul class="tag-list">
671          ${searchResults?.tags?.slice(0, 5)?.map(tag => `
672            <li class="tag-item" data-tag-id="${tag.tagId}">
673              ${tag.tagName}
674            </li>
675          `).join('')}
676
677          <li
678            class="show-more"
679            style="display:${searchResults?.tags?.length > 5 ? 'block' : 'none'};"
680            id="showMoreTags"
681          >Show more tags</li>
682        </ul>
683      `
684    );
685  }
686
687  const renderFullTags = () => {
688    return (
689      `<div class="result-section-title-container">
690          <button class="back-button" id="backButtonTags">
691            BACK
692          </button>
693          <h3 class="result-section-title">ALL TAGS RESULTS</h3>
694        </div>
695        <ul class="tag-list">
696          ${searchResults?.tags?.map(tag => `
697            <li class="tag-item" data-tag-id="${tag.tagId}">
698              ${tag.tagName}
699            </li>
700          `).join('')}
701        </ul>
702      `
703    );
704  }
705
706  const renderVideos = () => {
707    return (
708      `<h3 class="result-section-title">VIDEOS</h3>
709        <ul class="video-list">
710          ${searchResults?.videos?.slice(0, 5)?.map(video => `
711            <li class="video-item" data-video-id="${video.encryptedVCode}">
712              <div class="video-thumbnail">
713                <img class="video-poster-img" src=${video.imageUrl} alt=${video.title}>
714              </div>
715              <div class="video-info">
716                <span class="video-title">${video.title}</span>
717              </div>
718            </li>
719          `).join('')}
720
721          <li
722            class="show-more"
723            style="display:${searchResults?.videos?.length > 5 ? 'block' : 'none'};"
724            id="showMoreVideos"
725          >Show more videos</li>
726        </ul>
727      `
728    );
729  };
730
731  const renderFullVideos = () => {
732    return (
733      `<div class="result-section-title-container">
734          <button class="back-button" id="backButtonVideos">
735            BACK
736          </button>
737          <h3 class="result-section-title">ALL VIDEOS RESULTS</h3>
738        </div>
739        <ul class="video-list">
740          ${searchResults?.videos?.map(video => `
741            <li class="video-item" data-video-id="${video.encryptedVCode}">
742              <div class="video-thumbnail">
743                <img class="video-poster-img" src=${video.imageUrl} alt=${video.title}>
744              </div>
745              <div class="video-info">
746                <span class="video-title">${video.title}</span>
747              </div>
748            </li>
749          `).join('')}
750        </ul>
751      `
752    );
753  };
754
755  const toggleSuggestionList = (showMoreResults, previousShowMoreResults = '') => {
756    const initialResult = document.getElementById('initialResult');
757    const moreVideosResult = document.getElementById('moreVideosResult');
758    const moreTagsResult = document.getElementById('moreTagsResult');
759
760    switch (showMoreResults) {
761      case SUGGESTION_VIDEOS:
762        initialResult?.classList.remove('slide-in-from-left');
763        initialResult?.classList.add('slide-out-left');
764        moreVideosResult?.classList.remove('slide-out-right');
765        moreVideosResult?.classList.add('slide-in-from-right');
766        break;
767      case SUGGESTION_TAGS:
768        initialResult?.classList.remove('slide-in-from-left');
769        initialResult?.classList.add('slide-out-left');
770        moreTagsResult?.classList.remove('slide-out-right');
771        moreTagsResult?.classList.add('slide-in-from-right');
772        break;
773      default:
774        initialResult?.classList.remove('slide-out-left');
775        initialResult?.classList.add('slide-in-from-left');
776        if (previousShowMoreResults === SUGGESTION_TAGS) {
777          moreTagsResult?.classList.remove('slide-in-from-right');
778          moreTagsResult?.classList.add('slide-out-right');
779        } else if (previousShowMoreResults === SUGGESTION_VIDEOS) {
780          moreVideosResult?.classList.remove('slide-in-from-right');
781          moreVideosResult?.classList.add('slide-out-right');
782        }
783        break;
784    };
785  };
786
787  const handleVideoClick = (videoId) => {
788    const video = searchResults.videos.find(v => v.encryptedVCode === videoId);
789    if (!video) return;
790
791    const { title, encryptedVCode, videoUrl } = video;
792    const data = {
793      title,
794      video_id: encryptedVCode,
795      section: SEARCH_SUGGESTION_SECTION,
796    };
797    trackMixpanelEvent(SELECT_VIDEO_EVENT, data);
798    trackMixpanelEvent(SEARCH_SUGGESTION_CLICK_EVENT, {
799      ...data,
800      type: SUGGESTION_VIDEOS,
801    });
802
803    closeSuggestionList();
804
805    // redirect to the video's URL
806    const isCurrentDomainClean = isCleanDomain(window.location.hostname);
807    const isCleanVideo = isCleanDomain(videoUrl);
808    // add extra parameters if cross domain
809    const onClickVideoUrl = isCurrentDomainClean === isCleanVideo ? videoUrl : getFullURL(videoUrl);
810    window.location.href = onClickVideoUrl;
811  };
812
813  const handleTagClick = (tagId) => {
814    const tag = searchResults.tags.find(v => v.tagId === (tagId ? parseInt(tagId) : -1));
815    if (!tag) return;
816
817    const { tagName, slug } = tag;
818    const data = {
819      tag: tagName,
820      tag_id: tagId?.toString(),
821      section: SEARCH_SUGGESTION_SECTION,
822    };
823    trackMixpanelEvent(TAG_BTN_CLICK_EVENT, data);
824    trackMixpanelEvent(SEARCH_SUGGESTION_CLICK_EVENT, {
825      ...data,
826      type: SUGGESTION_TAGS,
827    });
828
829    closeSuggestionList();
830    
831    // redirect to klp page (add extra parameters in cross domain)
832    const host = window.location.protocol + "//" + window.location.host;
833    const tagURL = host + '/watch/' + slug;
834    window.location.href = getUncleanClickURL(tagURL);
835  };
836
837  const attachSuggestionEventListeners = () => {
838    container.querySelectorAll('.tag-item').forEach(tag => {
839      tag.addEventListener('click', () => handleTagClick(tag.dataset.tagId));
840    });
841
842    container.querySelectorAll('.video-item').forEach(video => {
843      video.addEventListener('click', () => handleVideoClick(video.dataset.videoId));
844    });
845
846    const showMoreVideosButton = document.getElementById('showMoreVideos');
847    const showMoreTagsButton = document.getElementById('showMoreTags');
848    showMoreVideosButton?.addEventListener('click', () => toggleSuggestionList(SUGGESTION_VIDEOS));
849    showMoreTagsButton?.addEventListener('click', () => toggleSuggestionList(SUGGESTION_TAGS));
850
851    const backButtonTags = document.getElementById('backButtonTags');
852    backButtonTags?.addEventListener('click', () => toggleSuggestionList('', SUGGESTION_TAGS));
853    const backButtonVideos = document.getElementById('backButtonVideos');
854    backButtonVideos?.addEventListener('click', () => toggleSuggestionList('', SUGGESTION_VIDEOS));
855  };
856
857  const renderSuggestions = () => {
858    if (!showSuggestionList || searchTerm.length < 3) {
859      suggestionContainer.innerHTML = '';
860      suggestionContainer.style.display = 'none';
861      searchOverlay.style.display = 'none';
862      return;
863    }
864
865    suggestionContainer.style.display = 'block';
866    searchOverlay.style.display = 'block';
867    let content = '';
868
869    // Calculate the suggestion list height
870    calculateHeight();
871
872    if (isLoading) {
873      content = `
874        <div class="search-loading-container">
875          <div class="loading-spinner"></div>
876        </div>
877      `;
878    } else if (searchResults?.videos?.length > 0 || searchResults?.tags?.length > 0) {
879      content = `
880        <div
881          class="suggestion-result-container custom-scrollbar"
882        >
883          <h3 class="suggestion-result-container-header">
884            SEARCH <span class="suggestion-result-container-header-highlight">RESULTS</span>
885          </h3>
886          <div class="results-container" id="initialResult">
887            ${renderTags()}
888            ${renderVideos()}
889          </div>
890          <div class="results-container more-results hidden-section" id="moreTagsResult">
891            ${renderFullTags()}
892          </div>
893          <div class="results-container more-results hidden-section" id="moreVideosResult">
894            ${renderFullVideos()}
895          </div>
896        </div>
897      `;
898    } else {
899      content = `
900        <span class="no-results">
901          No results
902        </span>
903      `;
904    }
905
906    suggestionContainer.innerHTML = content;
907    attachSuggestionEventListeners();
908  }
909
910  const closeSuggestionList = () => {
911    showSuggestionList = false;
912    searchTerm = '';
913    toggleSuggestionList('');
914    searchInput.value = '';
915    renderSuggestions();
916  };
917
918  const handleSearchInputChange = async (e) => {
919    searchTerm = e.target.value;
920    if (searchTerm.length >= 3) {
921      isLoading = true;
922      renderSuggestions();
923      try {
924        const response = await fetch(
925          `${VIDEO_SEARCH_SUGGESTION_URL}?searchTerm=${searchTerm}&pageSize=${pageSize}`
926        );
927        const data = await response.json();
928
929        if (data) {
930          searchResults = {
931            videos: data.videos?.result || [],
932            tags: data.tags || []
933          };
934        }
935      } catch (error) {
936        console.error('Error fetching search results:', error);
937      } finally {
938        isLoading = false;
939        renderSuggestions();
940      }
941    } else {
942      searchResults = { tags: [], videos: [] };
943      renderSuggestions();
944    }
945  }
946
947  const handleSearchIconClick = (searchValue) => {
948    trackMixpanelEvent(SEARCH_BUTTON_CLICK_EVENT);
949  
950    var searchValue = searchInput?.value?.trim() || '';
951    if (searchValue) {
952      var newUrl = '/search/' + encodeURIComponent(searchValue);
953      window.location.href = getUncleanClickURL(newUrl);
954    }
955  };
956
957  const attachEventListeners = () => {
958    searchInput.addEventListener('input', (e) => handleSearchInputChange(e));
959    searchInput.addEventListener('focus', () => {
960      showSuggestionList = true;
961      trackMixpanelEvent(SEARCH_BAR_CLICK_EVENT);
962    });
963    searchInput.addEventListener('keydown', (e) => {
964      if (e.key === 'Enter') {
965        handleSearchIconClick();
966      }
967    });
968    searchButton.addEventListener('click', () => handleSearchIconClick());
969  }
970
971  const calculateHeight = () => {
972    if (!suggestionContainer) return;
973
974    let suggestionListHeight = -1;
975
976    if (searchResults?.videos?.length > 0 || searchResults?.tags?.length > 0) {
977      const searchBarRect = searchInput.getBoundingClientRect();
978      const distanceToBottom = window.innerHeight - searchBarRect.bottom;
979      const paddingBottom = 20;
980      suggestionListHeight = distanceToBottom ? 
981        Math.round(distanceToBottom - paddingBottom) : -1;
982    }
983    
984    const height = suggestionListHeight > 0
985      ? `${suggestionListHeight}px`
986      : 'fit-content';
987
988    suggestionContainer.style.height = height;
989  }
990
991  const handleMobileScroll = () => {
992    if (!searchInput) return;
993    searchInput.blur();
994  };
995
996  attachEventListeners();
997  
998  // Add window resize listener
999  if (isMobileView) {
1000    document.addEventListener('scroll', handleMobileScroll, {
1001      passive: true,
1002    });
1003    document.addEventListener('touchmove', handleMobileScroll, {
1004      passive: true,
1005    });
1006  } else {
1007    window.addEventListener('resize', () => calculateHeight());
1008  }
1009
1010</script>
1010
1011      </div>
1012
1013      <div style="display: flex; align-items: center">
1014        <!-- Will be used when we unify domains -->
1015        <!-- <div id="login-icon" class="navbar-text" data-toggle="modal" data-target="#loginModal">
1016          <a onclick="event.preventDefault()">
1017            LOG IN
1018          </a>
1019        </div>
1020        <div class="profile-icon">
1021          <a href="profile.php">
1022            <img class="profile-icon-img" width="32" height="32" src="">
1023            <div class="profile-icon-txt"></div>
1024          </a>
1025        </div> -->
1026        <div class="navbar-text">
1027          <a id="submit-videos-btn" onclick="onNavLinkClick(event, 'submit-video', true, 'submit_video_btn_click')" class="round-btn" class="nav-link" href="https://worldstar.com/submit-video">Submit Videos</a>
1028        </div>
1029        <div class="navbar-text">
1030          <a id="login-icon" onclick="onNavLinkClick(event, 'profile', true)" href="https://worldstar.com/profile">
1031            <img width="22px" height="22px" src="https://worldstarhiphop.com/videos/images/[email protected]">
1032          </a>
1033        </div>
1034      </div>
1035    </div>
1036  </nav>
1037</div>
1038
1039<script type="text/javascript">
1040  document.getElementById('search-form')?.addEventListener('submit', function(event) {
1041    // Prevent form submission
1042    event.preventDefault();
1043
1044    trackMixpanelEvent('search_btn_click');
1045    var searchValue = document.getElementById('searchInput')?.value?.trim() || '';
1046    if (searchValue) {
1047      var newUrl = '/search/' + encodeURIComponent(searchValue);
1048      window.location.href = getUncleanClickURL(newUrl);
1049    }
1050  });
1051</script>
1051
1052    </header>
1053
1054    <div class="container login-wrapper">
1055  <div class="page-header text-center">
1056    <h3>Sign Up for Worldstar</h3>
1057    <p>Create a profile to access Live streams,<br/> start streaming and more.</p>
1058    <p class="end-note">Already have an account? <a id="login-link" href="/login-options" class="red small font-weight-bold">LOG IN</a></p>
1059  </div>
1060  <div class="text-center" id="login-section">
1061    <div id="invalid-form-feedback" class="invalid-feedback"></div>
1062    <a id="signup-link" href="/signup">
1063      <button class="btn custom-btn">
1064        <span><img width="18px" height="18px" src="https://worldstarhiphop.com/videos/assets/images/icon_email.svg"></span>
1065        <span>SIGN UP WITH EMAIL</span>
1066      </button>
1067    </a>
1068    <div class="hr-sect">OR</div>
1069    <button class="btn custom-btn" onclick="providerSignIn('google')">
1070      <span><img width="18px" height="18px" src="https://worldstarhiphop.com/videos/assets/images/icon_google.svg"></span>
1071      <span>CONTINUE WITH GOOGLE</span>
1072    </button>
1073    <button class="btn custom-btn" onclick="providerSignIn('facebook')">
1074      <span><img width="18px" height="18px" src="https://worldstarhiphop.com/videos/assets/images/icon_facebook.svg"></span>
1075      <span>CONTINUE WITH FACEBOOK</span>
1076    </button>
1077    <button class="btn custom-btn" onclick="providerSignIn('apple')">
1078      <span><img width="18px" height="18px" src="https://worldstarhiphop.com/videos/assets/images/icon_apple.svg"></span>
1079      <span>CONTINUE WITH APPLE</span>
1080    </button>
1081    <p class="faint small terms-note">By creating an account, I agree to the <a href="https://worldstar.com/terms-of-service">Terms</a> and <a href="https://worldstar.com/privacy-policy">Privacy Policy</a>.</p>
1082  </div>
1083</div>
1084
1085<script type="text/javascript">
1086  const redirectURL = getRedirectURL();
1087  const errMessage = getURLParam('error');
1088
1089  if (errMessage) {
1090    setError({ message: errMessage });
1091  }
1092
1093  if (redirectURL) {
1094    $('#signup-link').attr('href', 'signup?redirect_url=' + redirectURL);
1095    $('#login-link').attr('href', 'login-options?redirect_url=' + redirectURL);
1096  }
1097</script>
1097
1098                                                                                                                              
1099    
1100		<center>
1101		<footer id="footer">
1102			<div class="f1">
1103				<div class="f2">
1104					<div class="f3">
1105						<strong class="footer-logo"><a onclick="onFooterLinkClick(event, 'videos', false)" href="https://worldstarhiphop.com/videos/">World Star Hip Hop</a></strong>
1106						<ul class="footer-nav">
1107							<li><a href="https://contact.worldstar.com/hc/en-us/articles/25632693260955-Digital-Services-Act-DSA-Contact-Information-for-WorldStarHipHop-Users-and-Authorities">EU DSA</a></li>
1108							<li><a onclick="onFooterLinkClick(event, 'privacy-policy', true)" href="https://worldstar.com/privacy-policy">PRIVACY</a></li>
1109							<li><a onclick="onFooterLinkClick(event, 'terms-of-service', true)" href="https://worldstar.com/terms-of-service">TERMS</a></li>
1110							<li><a onclick="onFooterLinkClick(event, 'dmca', true)" href="https://worldstar.com/dmca">DMCA</a></li>
1111							<li><a onclick="onFooterLinkClick(event, 'submit-video', true)" href="https://worldstar.com/submit-video">SUBMIT VIDEO</a></li>
1112						</ul>
1113					</div>
1114				</div>
1115			</div>
1116		</footer>
1117		
1117<script type="text/javascript">
1118			function onFooterLinkClick(e, page, isClean) {
1119				e.preventDefault();
1120				// redirect (add extra parameters in cross domain)
1121				const host = window.location.protocol + "//" + window.location.host;
1122				const tagURL = host + "/" + page;
1123				window.location.href = isClean ? getCleanClickURL(tagURL) : getUncleanClickURL(tagURL);
1124			};
1125		</script>
1125  </div>
1126
1127  
1127<script type="text/javascript">
1128    $(document).ready(function() {
1129      logFirebaseEvent('display_signup_options_ui');
1130      trackMixpanelEvent('display_signup_options_ui');
1131    });
1132  </script>
1132
1133
1134  
1134<script
1135    type="text/javascript"
1136    src="https://s.skimresources.com/js/265960X1751083.skimlinks.js"
1137  ></script>
1137
1138</body>
1139
1140</html>

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.