九色-优化

91porny(九色)视频宽屏

// ==UserScript==
// @name         九色-优化
// @namespace    https://sleazyfork.org/zh-CN/users/1461640-%E6%98%9F%E5%AE%BF%E8%80%81%E9%AD%94
// @version      0.1.1
// @description  91porny(九色)视频宽屏
// @author       星宿老魔
// @match        https://91porny.com/*
// @match        https://*.jiuse.vip/*
// @icon         https://www.google.com/s2/favicons?sz=64&domain=91porny.com
// @license      MIT
// @grant        none
// ==/UserScript==

(function () {
  'use strict';

  const currentDomain = window.location.hostname;
  // 仅宽屏模式,无额外设置

  const config = {
    selectors: {
      videoContainer: '.videoPlayContainer',
      videoElement: '.video-js',
      videoRow: '.row',
      videoColumn:
        '.left.col-60.offset-md-10.col-md-40, .left.col-md-40.offset-md-10.col-60',
      controlBar: '.vjs-control-bar',
      sideContent: '.row .side.col-40.col-md-50',
      scaleElement: '.scale'
    },
    applyStyles: function () {
      const videoColumn = document.querySelector(this.selectors.videoColumn);
      if (videoColumn) {
        videoColumn.style.width = '100%';
        videoColumn.style.maxWidth = '100%';
        videoColumn.style.flexBasis = '100%';
        videoColumn.style.margin = '0';
        videoColumn.style.padding = '0 10px';
        videoColumn.style.marginTop = '0';
        videoColumn.style.paddingTop = '0';
        videoColumn.classList.remove('col-60', 'offset-md-10', 'col-md-40');
        videoColumn.classList.add('col-100');
      }

      const videoRow = document.querySelector(this.selectors.videoRow);
      if (videoRow) {
        videoRow.style.marginTop = '0';
        videoRow.style.paddingTop = '0';
      }

      const scaleElement = document.querySelector(this.selectors.scaleElement);
      if (scaleElement) {
        scaleElement.style.paddingBottom = '0';
        scaleElement.style.height = 'auto';
        scaleElement.style.minHeight = '0';
        scaleElement.style.aspectRatio = 'unset';
        scaleElement.style.marginTop = '0';
        scaleElement.style.paddingTop = '0';
      }

      const videoContainer = document.querySelector(this.selectors.videoContainer);
      if (videoContainer) {
        videoContainer.style.marginTop = '0';
        videoContainer.style.paddingTop = '0';
      }
    },
    cssRules: `
      .videoPlayContainer {
        width: 100% !important;
        max-width: 100% !important;
        margin: 0 auto !important;
        margin-top: 0 !important;
        padding-top: 0 !important;
      }
      .video-js {
        width: 100% !important;
        max-width: 100% !important;
      }
      .row .col-100 {
        width: 100% !important;
        max-width: 100% !important;
        flex-basis: 100% !important;
        margin: 0 !important;
        padding: 0 10px !important;
        margin-top: 0 !important;
        padding-top: 0 !important;
      }
      .row {
        margin-top: 0 !important;
        padding-top: 0 !important;
      }
      .row .side.col-40.col-md-50 {
        display: none;
      }
      .videoPlayContainer .scale {
        padding-bottom: 0 !important;
        height: auto !important;
        min-height: 0 !important;
        aspect-ratio: unset !important;
        margin-top: 0 !important;
        padding-top: 0 !important;
      }
      .videoPlayContainer .video-js {
        position: relative !important;
        top: 0 !important;
        left: 0 !important;
      }
      .videoPlayContainer,
      .videoPlayContainer > *,
      .col-100 {
        margin-top: 0 !important;
        padding-top: 0 !important;
      }
      body .container .row:first-child {
        margin-top: 0 !important;
        padding-top: 0 !important;
      }
      
      .rec-tabs-container {
          display: flex;
          gap: 10px;
          margin-bottom: 10px;
      }
      .rec-tab-button {
          background-color: #333;
          color: #fff;
          border: 1px solid #555;
          padding: 8px 15px;
          cursor: pointer;
          border-radius: 5px;
          font-size: 16px;
          font-weight: bold;
      }
      .rec-tab-button.active {
          background-color: #f0ad4e;
          color: #000;
          border-color: #f0ad4e;
      }
      .rec-tab-button:not(.active):hover {
          background-color: #444;
      }
      #recommended-videos-container, #author-videos-container {
          flex-wrap: wrap;
      }
      .d9867a703dd9335a77b9f88459aa7bff {
        display: none !important;
      }
    `
  };

  function debounce(func, wait) {
      let timeout;
      return function executedFunction(...args) {
          const later = () => {
              clearTimeout(timeout);
              func(...args);
          };
          clearTimeout(timeout);
          timeout = setTimeout(later, wait);
      };
  }

  function setWideScreenMode() {
    const videoContainer = document.querySelector(config.selectors.videoContainer);
    const videoElement =
      document.querySelector(config.selectors.videoElement) ||
      document.querySelector(config.selectors.videoIframe);

    if (!videoContainer && !videoElement) {
      console.log(`${currentDomain}宽屏模式: 未找到视频元素`);
      return;
    }

    if (config.applyStyles) {
      config.applyStyles();
    }

    if (videoContainer) {
      videoContainer.style.width = '100%';
      videoContainer.style.maxWidth = '100%';
      videoContainer.style.margin = '0 auto';
      videoContainer.style.position = 'relative';
    }

    if (videoElement) {
      const aspectRatio = 16 / 9;
      const containerWidth = videoContainer ? videoContainer.offsetWidth : window.innerWidth;
      const videoHeight = containerWidth / aspectRatio;

      videoElement.style.height = `${videoHeight}px`;
      videoElement.style.width = '100%';
      videoElement.style.maxWidth = '100%';
    }

    if (config.selectors.controlBar) {
      const controlBar = document.querySelector(config.selectors.controlBar);
      if (controlBar) {
        controlBar.style.width = '100%';
      }
    }

    console.log(`${currentDomain}宽屏模式: 已启用宽屏模式`);
  }

  function setupResizeListener() {
    window.addEventListener('resize', function () {
      setWideScreenMode();
    });
  }

  function addStyles() {
    const styleSheet = document.createElement('style');
    styleSheet.textContent = config.cssRules;
    document.head.appendChild(styleSheet);
  }

  function fetchAuthorInfoAndVideos(url) {
      const authorVideosContainer = document.getElementById('author-videos-container');
      const authorInfoContainer = document.getElementById('author-info-container');

      authorVideosContainer.innerHTML = '<p style="color: white; padding: 20px;">正在加载作者视频...</p>';
      authorInfoContainer.innerHTML = '';

      fetch(url)
          .then(response => response.text())
          .then(html => {
              const parser = new DOMParser();
              const doc = parser.parseFromString(html, 'text/html');

              // Find author info text
              const infoElement = Array.from(doc.querySelectorAll('p, h1, h2, h3, h4, h5')).find(el => el.textContent.includes('共计') && el.textContent.includes('视频'));
              if (infoElement) {
                  const infoLink = document.createElement('a');
                  infoLink.href = url;
                  infoLink.target = '_blank';
                  
                  let fullText = infoElement.textContent.trim();
                  let displayText = fullText.split(',')[0];
                   if (displayText === fullText) {
                      displayText = fullText.split(',')[0];
                  }
                  infoLink.textContent = displayText;
                  infoLink.title = '点击跳转作者主页';

                  infoLink.style.color = '#f0ad4e';
                  infoLink.style.display = 'block';
                  infoLink.style.marginBottom = '10px';
                  authorInfoContainer.appendChild(infoLink);
              }

              // Find videos
              const authorVideoElements = doc.querySelectorAll('.colVideoList');
              authorVideosContainer.innerHTML = ''; // Clear loading message

              if (authorVideoElements.length > 0) {
                  authorVideoElements.forEach(video => {
                      authorVideosContainer.appendChild(video);
                  });
              } else {
                  authorVideosContainer.innerHTML = '<p style="color: white; padding: 20px;">该作者没有其他视频。</p>';
              }
          })
          .catch(error => {
              console.error('获取作者视频失败:', error);
              authorVideosContainer.innerHTML = '<p style="color: white; padding: 20px;">加载作者视频失败。</p>';
          });
  }

  function modifyVideoRecommendations() {
      if (document.getElementById('rec-tabs-container')) {
          return; // Already modified
      }
      const recommendationTitle = Array.from(document.querySelectorAll('h5.container-title')).find(
          h5 => h5.textContent.trim() === '视频推荐'
      );

      if (!recommendationTitle) {
          return;
      }

      const titleContainer = recommendationTitle.parentElement;
      const recommendedVideosContainer = titleContainer.nextElementSibling;
      if (!recommendedVideosContainer || !recommendedVideosContainer.classList.contains('row')) {
          return;
      }
      recommendedVideosContainer.id = 'recommended-videos-container';
      recommendedVideosContainer.style.display = 'flex';

      const authorInfoContainer = document.createElement('div');
      authorInfoContainer.id = 'author-info-container';
      authorInfoContainer.style.display = 'none';
      recommendedVideosContainer.parentNode.insertBefore(authorInfoContainer, recommendedVideosContainer);

      const authorVideosContainer = document.createElement('div');
      authorVideosContainer.id = 'author-videos-container';
      authorVideosContainer.className = 'row';
      authorVideosContainer.style.display = 'none';
      authorInfoContainer.parentNode.insertBefore(authorVideosContainer, authorInfoContainer.nextSibling);

      const recommendedBtn = document.createElement('button');
      recommendedBtn.textContent = '视频推荐';
      recommendedBtn.className = 'rec-tab-button active';

      const authorBtn = document.createElement('button');
      authorBtn.textContent = '作者视频';
      authorBtn.className = 'rec-tab-button';

      const buttonContainer = document.createElement('div');
      buttonContainer.id = 'rec-tabs-container';
      buttonContainer.className = 'rec-tabs-container';
      buttonContainer.appendChild(recommendedBtn);
      buttonContainer.appendChild(authorBtn);

      titleContainer.innerHTML = '';
      titleContainer.appendChild(buttonContainer);

      recommendedBtn.addEventListener('click', () => {
          recommendedBtn.classList.add('active');
          authorBtn.classList.remove('active');
          recommendedVideosContainer.style.display = 'flex';
          authorVideosContainer.style.display = 'none';
          authorInfoContainer.style.display = 'none';
      });

      authorBtn.addEventListener('click', () => {
          authorBtn.classList.add('active');
          recommendedBtn.classList.remove('active');
          recommendedVideosContainer.style.display = 'none';
          authorVideosContainer.style.display = 'flex';
          authorInfoContainer.style.display = 'block';

          if (authorVideosContainer.children.length === 0) {
              const authorLinkElement = document.querySelector('.d-flex.justify-content-between a[href*="/author/"]');
              if (authorLinkElement) {
                  fetchAuthorInfoAndVideos(authorLinkElement.href);
              } else {
                  authorVideosContainer.innerHTML = '<p style="color: white; padding: 20px;">未找到当前视频的作者信息。</p>';
              }
          }
      });
  }

  function init() {
    addStyles();

    const delay = 500;

    const runUpdates = () => {
        setWideScreenMode();
        modifyVideoRecommendations();
    };

    if (document.readyState === 'loading') {
      document.addEventListener('DOMContentLoaded', () => setTimeout(runUpdates, delay));
    } else {
      setTimeout(runUpdates, delay);
    }

    document.addEventListener(
      'load',
      (e) => {
        if (e.target.tagName === 'VIDEO' || e.target.tagName === 'IFRAME') {
          setWideScreenMode();
        }
      },
      true
    );

    window.addEventListener('load', runUpdates);

    const debouncedRunUpdates = debounce(runUpdates, 250);

    const observer = new MutationObserver((mutations) => {
      let shouldUpdate = false;
      mutations.forEach((mutation) => {
        if (mutation.addedNodes.length > 0) {
          shouldUpdate = true;
        }
      });
      if (shouldUpdate) {
        debouncedRunUpdates();
      }
    });

    observer.observe(document.body, {
      childList: true,
      subtree: true
    });

    console.log(`${currentDomain}宽屏模式: 已启用`);
  }

  init();
})();