Luxup

Outstream MoeVideo_new

Jun 26th, 2026 (edited)
40
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 9.11 KB | None | 0 0
  1. <div id="outstream_%SITE_AREA_ID%_%DIV_SUB_ID%" style="position: relative;"></div>
  2.  
  3. <script type="text/javascript">
  4. (() => {
  5. // 1. Уникальный идентификатор
  6. const BLOCK_UUID = '%SITE_AREA_ID%_%DIV_SUB_ID%';
  7. const VIDEO_CONTAINER_ID = 'outstream_' + BLOCK_UUID;
  8.  
  9. let isDebug = false;
  10. try {
  11. isDebug = /[?&]outstream_debug=1/.test(window.top.location.href);
  12. } catch (e) {
  13. isDebug = /[?&]outstream_debug=1/.test(document.referrer) || /[?&]outstream_debug=1/.test(window.location.href);
  14. }
  15.  
  16. const makeLogger = (tag = 'Waterfall_' + BLOCK_UUID) => {
  17. const prefix = "[" + tag + "] ->";
  18. return {
  19. log: (...args) => { if (isDebug) console.log(prefix, ...args); },
  20. error: (...args) => { if (isDebug) console.error(prefix, ...args); }
  21. };
  22. };
  23. const logger = makeLogger();
  24.  
  25. const RSYA_VIEW_TIME_MS = 3500;
  26. const VIDEO_MAX_WAIT_MS = 3100;
  27. const VIDEO_CLOSE_ON_COMPLETE_TIMEOUT = 2000;
  28.  
  29. const VIDEO_PLACEMENT_ID = 12946;
  30. const VIDEO_ADVERT_COUNT = 30;
  31.  
  32. // 2. Общий SITE_ID для всех слоев
  33. const SITE_ID = 225780;
  34. const STEP1_BLOCK_ID = 721726;
  35. const FALLBACK_BLOCK_ID = 721724;
  36.  
  37. const videoContainer = document.querySelector('#' + VIDEO_CONTAINER_ID);
  38. if (!videoContainer) {
  39. logger.error('КРИТИЧЕСКАЯ ОШИБКА: Контейнер не найден.');
  40. return;
  41. }
  42.  
  43. const bannerWrapper = document.createElement('div');
  44. bannerWrapper.id = VIDEO_CONTAINER_ID + '_banner_wrapper';
  45. bannerWrapper.style.cssText = 'position: relative; width: 100%; z-index: 10; background: #fff; min-height: 0;';
  46.  
  47. videoContainer.parentNode.insertBefore(bannerWrapper, videoContainer);
  48. videoContainer.style.cssText = 'position: absolute; top: 0; left: 0; width: 100%; height: 300px; z-index: -1; opacity: 0; pointer-events: none;';
  49.  
  50. let state = {
  51. bannerRendered: false, bannerEmpty: false, bannerViewed: false,
  52. videoLibLoaded: false, videoReady: false, videoShown: false,
  53. videoFinished: false, videoFailed: false, finalized: false, videoRequested: false
  54. };
  55.  
  56. const enqueueLuxupBlock = (divId, siteId, blockId) => {
  57. (window['__lxGc__'] = window['__lxGc__'] || {'s':{},'b':0})['cmd'] = window['__lxGc__']['cmd'] || [];
  58. window['__lxGc__']['cmd'].push(function(){
  59. window['__lxGc__']['display'](divId, "_"+siteId, "_"+blockId);
  60. });
  61. };
  62.  
  63. const showFallback = (reason) => {
  64. if (state.finalized) return;
  65. state.finalized = true;
  66. if (bannerWrapper.parentNode) bannerWrapper.parentNode.removeChild(bannerWrapper);
  67. videoContainer.style.display = 'none';
  68. logger.log("Шаг 3: Заглушка. Причина: " + reason);
  69. const fallbackDiv = document.createElement('div');
  70. fallbackDiv.id = "lx_" + FALLBACK_BLOCK_ID + "_wrapper_" + BLOCK_UUID;
  71. videoContainer.parentNode.insertBefore(fallbackDiv, videoContainer);
  72. enqueueLuxupBlock(fallbackDiv.id, SITE_ID, FALLBACK_BLOCK_ID);
  73. };
  74.  
  75. const showVideo = () => {
  76. if (state.finalized || state.videoShown || state.videoFailed) return;
  77. state.videoShown = true;
  78. logger.log('Успех! Снимаем слой баннера, показываем видео');
  79. if (bannerWrapper.parentNode) bannerWrapper.parentNode.removeChild(bannerWrapper);
  80. videoContainer.style.cssText = 'position: relative; z-index: 100; opacity: 1; height: auto; pointer-events: auto;';
  81. };
  82.  
  83. const checkStatus = () => {
  84. if (state.bannerEmpty) { showFallback('Баннер пуст'); return; }
  85. if (state.bannerViewed && state.videoReady) showVideo();
  86. };
  87.  
  88. const prepareVideo = () => {
  89. let closeOnCompleteTimeout = null;
  90.  
  91. window['addContentRoll']({
  92. element: '#' + VIDEO_CONTAINER_ID,
  93. width: '100%',
  94. placement: VIDEO_PLACEMENT_ID,
  95. promo: true,
  96. advertCount: VIDEO_ADVERT_COUNT,
  97. slot: 'page',
  98. sound: 'onclick',
  99. deviceMode: 'all',
  100. background: 'none',
  101. fly: {mode: 'off'},
  102.  
  103. adStart: () => {
  104. logger.log("Video: Ready (AdStarted)");
  105. state.videoReady = true;
  106. if (closeOnCompleteTimeout) { clearTimeout(closeOnCompleteTimeout); closeOnCompleteTimeout = null; }
  107. checkStatus();
  108. },
  109. adCompl: () => {
  110. logger.log("Video: Complete");
  111. closeOnCompleteTimeout = setTimeout(() => {
  112. state.videoFinished = true;
  113. if (state.videoShown) showFallback('Видео завершено (таймаут)');
  114. }, VIDEO_CLOSE_ON_COMPLETE_TIMEOUT);
  115. },
  116. adFinish: () => {
  117. logger.log("Video: Stopped");
  118. state.videoFinished = true;
  119. if (closeOnCompleteTimeout) { clearTimeout(closeOnCompleteTimeout); closeOnCompleteTimeout = null; }
  120. if (state.videoShown) showFallback('Видео завершено (AdStopped)');
  121. },
  122. adError: () => {
  123. logger.error("Video: Error");
  124. state.videoFailed = true;
  125. if (state.videoShown) showFallback('Ошибка видео');
  126. },
  127. adEmpty: () => {
  128. logger.log("Video: Empty");
  129. state.videoFailed = true;
  130. if (state.videoShown) showFallback('Видео пустое');
  131. }
  132. });
  133. };
  134.  
  135. const runVideoStep = () => {
  136. if (state.videoRequested || state.finalized) return;
  137. state.videoRequested = true;
  138. logger.log('Поток 2: Старт загрузки плеера moevideo');
  139.  
  140. setTimeout(() => {
  141. if (!state.finalized && !state.videoReady) {
  142. state.videoFailed = true;
  143. logger.log(`Глобальный таймаут видео (${VIDEO_MAX_WAIT_MS / 1000} сек истекли)`);
  144. }
  145. }, VIDEO_MAX_WAIT_MS);
  146.  
  147. const s = document.createElement("script");
  148. s.src = "https://cdn1.moe.video/p/cr.js";
  149. s.async = true;
  150. s.onload = () => { state.videoLibLoaded = true; prepareVideo(); };
  151. s.onerror = () => {
  152. logger.error("Ошибка загрузки скрипта moevideo");
  153. state.videoFailed = true;
  154. }
  155. document.head.appendChild(s);
  156. };
  157.  
  158. const runBannerStep = () => {
  159. logger.log('Поток 1: Старт баннера');
  160. const bannerDiv = document.createElement('div');
  161. bannerDiv.id = "lx_" + STEP1_BLOCK_ID + "_" + BLOCK_UUID;
  162. bannerWrapper.appendChild(bannerDiv);
  163. enqueueLuxupBlock(bannerDiv.id, SITE_ID, STEP1_BLOCK_ID);
  164.  
  165. // --- Умный трекинг видимости ---
  166. let timeInView = 0;
  167. let isVisible = false;
  168. const tickRate = 100;
  169. let timer = null;
  170.  
  171. const viewedObserver = new IntersectionObserver((entries) => {
  172. isVisible = entries[0].isIntersecting;
  173.  
  174. if (isVisible && !state.finalized) {
  175. if (!state.videoRequested) runVideoStep();
  176.  
  177. if (!timer) {
  178. logger.log("Баннер видим, запускаем счетчик...");
  179. timer = setInterval(() => {
  180. if (isVisible && !document.hidden && !state.finalized) {
  181. timeInView += tickRate;
  182. if (timeInView >= RSYA_VIEW_TIME_MS) {
  183. clearInterval(timer);
  184. viewedObserver.disconnect();
  185. logger.log(`Баннер честно просмотрен (${RSYA_VIEW_TIME_MS}мс)`);
  186. state.bannerViewed = true;
  187. checkStatus();
  188. }
  189. }
  190. }, tickRate);
  191. }
  192. }
  193. }, {threshold: 0.1});
  194.  
  195. const bannerReadyObserver = new MutationObserver(() => {
  196. if (bannerWrapper.querySelector('.__lxG__not_empty_block')) {
  197. bannerReadyObserver.disconnect();
  198. logger.log('Баннер загружен, ждем попадания во вьюпорт...');
  199. viewedObserver.observe(bannerWrapper);
  200. } else if (bannerWrapper.querySelector('.__lxG__rendered_none')) {
  201. state.bannerEmpty = true;
  202. bannerReadyObserver.disconnect();
  203. checkStatus();
  204. }
  205. });
  206.  
  207. bannerReadyObserver.observe(bannerWrapper, {
  208. childList: true,
  209. subtree: true,
  210. attributes: true,
  211. attributeFilter: ['class']
  212. });
  213. };
  214.  
  215. runBannerStep();
  216. })();
  217. </script>
Advertisement
Add Comment
Please, Sign In to add comment