Greasy Fork 还支持 简体中文。

InsCNM

Automatically fetch media information from Instagram URLs.

Versão de: 10/10/2024. Veja: a última versão.

Você precisará instalar uma extensão como Tampermonkey, Greasemonkey ou Violentmonkey para instalar este script.

Você precisará instalar uma extensão como Tampermonkey para instalar este script.

Você precisará instalar uma extensão como Tampermonkey ou Violentmonkey para instalar este script.

Você precisará instalar uma extensão como Tampermonkey ou Userscripts para instalar este script.

Você precisará instalar uma extensão como o Tampermonkey para instalar este script.

Você precisará instalar um gerenciador de scripts de usuário para instalar este script.

(Eu já tenho um gerenciador de scripts de usuário, me deixe instalá-lo!)

Você precisará instalar uma extensão como o Stylus para instalar este estilo.

Você precisará instalar uma extensão como o Stylus para instalar este estilo.

Você precisará instalar uma extensão como o Stylus para instalar este estilo.

Você precisará instalar um gerenciador de estilos de usuário para instalar este estilo.

Você precisará instalar um gerenciador de estilos de usuário para instalar este estilo.

Você precisará instalar um gerenciador de estilos de usuário para instalar este estilo.

(Eu já possuo um gerenciador de estilos de usuário, me deixar fazer a instalação!)

// ==UserScript==
// @name         InsCNM
// @namespace    http://tampermonkey.net/
// @version      5.2
// @description  Automatically fetch media information from Instagram URLs.
// @author       Belugu
// @match        https://www.instagram.com/p/*
// @match        https://www.instagram.com/reel/*
// @match        https://www.instagram.com/*
// @grant        GM_xmlhttpRequest
// @require      https://code.jquery.com/jquery-3.6.0.min.js
// @icon         https://iili.io/29TPCR1.jpg
// ==/UserScript==

(function() {
  // Main logic
  $(document).ready(async function() {
    if (window.location.href.match(/^https:\/\/www\.instagram\.com\/(p|reel)\/[a-zA-Z0-9_-]+\/$/)) {
      const shortcode = extractShortcodeFromURL(window.location.href);
      if (shortcode) {
        const mediaInfo = await fetchMediaInfoByShortcode(shortcode);
        if (mediaInfo) {
          const { taken_at, comment_count, like_count } = mediaInfo.items[0];
          showMediaInfoUI(`
            <p>发布时间: ${new Date(taken_at * 1000).toLocaleString()} <button class="copy-btn" data-copy="${new Date(taken_at * 1000).toLocaleString()}" style="background:none; border:none; cursor:pointer;">🗿</button></p>
            <p>评论数: ${comment_count} <button class="copy-btn" data-copy="${comment_count}" style="background:none; border:none; cursor:pointer;">🗿</button></p>
            <p>点赞数: ${like_count} <button class="copy-btn" data-copy="${like_count}" style="background:none; border:none; cursor:pointer;">🗿</button></p>
          `);
        } else {
          showMediaInfoUI('<p>获取媒体信息失败。</p>');
        }
      }
    }
  });

  function showMediaInfoUI(mediaInfoHtml) {
    const container = $(
      `<div id="instagram-fetcher-ui" style="position:fixed; top:20px; right:-350px; background:white; color:black; border:1px solid #ccc; padding:15px; z-index:10000; width:300px; border-radius:10px;">
        <div style="display: flex; justify-content: space-between; align-items: center;">
          <h3 style="color:black; margin:0;">输入网址后按 Enter 搜索</h3>
          <button id="close-ui-button" style="background:none; border:none; font-size:20px; cursor:pointer; color:black;">&times;</button>
        </div>
        <div id="input-area" style="display: flex; align-items: center; margin-top:10px;">
          <input type="text" id="instagram-url-input" placeholder="输入网址" style="width:80%; padding:5px; color:black; border:1px solid #ccc; border-radius:5px; box-shadow:none; outline:none;"/>
        </div>
        <div id="media-info-output" style="margin-top:15px; font-size:14px;">${mediaInfoHtml}</div>
      </div>`
    );

    $('body').append(container);
    $('#instagram-fetcher-ui').animate({ right: '20px' }, 400);

    $('#instagram-url-input').on('keyup', async function(e) {
      if (e.which === 13) { // Enter key pressed
        const url = $('#instagram-url-input').val();
        console.log("User entered URL:", url);
        if (url) {
          const shortcode = extractShortcodeFromURL(url);
          if (shortcode) {
            $('#media-info-output').text('正在获取媒体信息...');
            const mediaInfo = await fetchMediaInfoByShortcode(shortcode);
            if (mediaInfo) {
              const { taken_at, comment_count, like_count } = mediaInfo.items[0];
              $('#media-info-output').html(
                `<p>发布时间: ${new Date(taken_at * 1000).toLocaleString()} <button class="copy-btn" data-copy="${new Date(taken_at * 1000).toLocaleString()}" style="background:none; border:none; cursor:pointer;">🗿</button></p>
                 <p>评论数: ${comment_count} <button class="copy-btn" data-copy="${comment_count}" style="background:none; border:none; cursor:pointer;">🗿</button></p>
                 <p>点赞数: ${like_count} <button class="copy-btn" data-copy="${like_count}" style="background:none; border:none; cursor:pointer;">🗿</button></p>`
              );
            } else {
              $('#media-info-output').text('获取媒体信息失败。');
            }
          } else {
            $('#media-info-output').text('无效的 Instagram URL。');
          }
        }
      }
    });

    $('#close-ui-button').click(function() {
      $(this).css({ transform: 'scale(0.95)' });
      setTimeout(() => $(this).css({ transform: 'scale(1)' }), 100);
      $('#instagram-fetcher-ui').animate({ right: '-350px' }, 400, function() {
        $(this).remove();
      });
    });

    $(document).on('click', '.copy-btn', function() {
      const textToCopy = $(this).data('copy');
      navigator.clipboard.writeText(textToCopy).then(() => {
        showNotification("已复制到剪贴板");
      }).catch(err => {
        console.error('复制失败:', err);
      });
    });
  }

  // Function to get a random gradient color
  function getRandomGradient() {
    const gradients = [
      '#6a11cb, #2575fc',  // Blue gradient
      '#11998e, #38ef7d',  // Green gradient
      '#ff7e5f, #feb47b',  // Original orange gradient
      '#ff6a00, #ee0979',  // Red gradient
      '#43cea2, #185a9d'   // Aqua gradient
    ];
    return gradients[Math.floor(Math.random() * gradients.length)];
  }

  // Function to show a simple notification with animation
  function showNotification(message) {
    const gradient = getRandomGradient(); // Get the gradient before usage
    const notification = $(
      `<div class="notification" style="position:fixed; bottom:-60px; right:20px; background: linear-gradient(to right, ${gradient}); color:white; padding:10px; border-radius:5px; z-index:10001; opacity:0.9;">
        ${message}
      </div>`
    );

    // Adjust the position of existing notifications
    $('.notification').each(function() {
      const currentBottom = parseInt($(this).css('bottom'));
      $(this).css('bottom', currentBottom + 60 + 'px');
    });

    $('body').append(notification);
    notification.animate({ bottom: '40px', opacity: 1 }, 400).delay(3000).animate({ opacity: 0 }, 400, function() {
      $(this).remove();
    });
  }

  // Listen for Alt+N to toggle the input UI
  document.addEventListener('keydown', function (e) {
    if (e.altKey && e.key === 'n') {
      const container = $('#instagram-fetcher-ui');
      if (container.length) {
        container.find('#close-ui-button').click();
      } else {
        showMediaInfoUI('<p>输入网址后按 Enter 搜索。</p>');
      }
    }
  });

  // Function to extract the shortcode from a given URL
  function extractShortcodeFromURL(url) {
    try {
      const urlObj = new URL(url);
      const pathSegments = urlObj.pathname.split('/');
      console.log("URL Object:", urlObj);
      console.log("Path Segments:", pathSegments);
      if (pathSegments[1] === 'p' || pathSegments[1] === 'reel') {
        return pathSegments[2] ? pathSegments[2] : null;
      }
      return null;
    } catch (error) {
      console.error("Error extracting shortcode from URL:", error);
      return null;
    }
  }

  // Function to fetch media info by shortcode
  async function fetchMediaInfoByShortcode(shortcode) {
    const mediaId = await getMediaID(shortcode);
    if (!mediaId) {
      console.error("Failed to fetch media ID.");
      $('#media-info-output').text('获取媒体 ID 失败,请稍后重试。');
      return null;
    }

    try {
      const mediaInfo = await getMediaInfo(mediaId);
      console.log("Media Info:", mediaInfo);
      return mediaInfo;
    } catch (error) {
      console.error("Error retrieving media info:", error);
      return null;
    }
  }

  // Function to fetch media ID using shortcode
  async function getMediaID(shortcode) {
    try {
      const response = await fetch(`https://www.instagram.com/p/${shortcode}/`, {
        headers: {
          "User-Agent": window.navigator.userAgent,
          "Accept": "text/html"
        }
      });
      if (!response.ok) {
        throw new Error(`HTTP error! status: ${response.status}`);
      }
      const html = await response.text();
      const mediaIdMatch = html.match(/"media_id":"(\d+)"/);
      if (mediaIdMatch) {
        return mediaIdMatch[1];
      } else {
        console.error("Media ID not found in page HTML.");
      }
    } catch (error) {
      console.error("Error fetching media ID:", error);
    }
    return null;
  }

  // Function to get app ID
  function getAppID() {
    let result = null;
    $('script[type="application/json"]').each(function() {
      const regexp = /"APP_ID":"([0-9]+)"/ig;
      const matcher = $(this).text().match(regexp);
      if (matcher != null && result == null) {
        result = [...$(this).text().matchAll(regexp)];
      }
    });
    return (result) ? result.at(0).at(-1) : null;
  }

  // Function to get media info using media ID
  async function getMediaInfo(mediaId) {
    return new Promise((resolve, reject) => {
      let getURL = `https://i.instagram.com/api/v1/media/${mediaId}/info/`;

      if (mediaId == null) {
        console.error("Cannot call Media API because the media ID is invalid.");
        reject("Cannot call Media API because the media ID is invalid.");
        return;
      }

      GM_xmlhttpRequest({
        method: "GET",
        url: getURL,
        headers: {
          "User-Agent": window.navigator.userAgent,
          "Accept": "application/json",
          'X-IG-App-ID': getAppID()
        },
        onload: function (response) {
          try {
            if (response.finalUrl == getURL) {
              let obj = JSON.parse(response.responseText);
              resolve(obj);
            } else {
              let finalURL = new URL(response.finalUrl);
              if (finalURL.pathname.startsWith('/accounts/login')) {
                console.error("The account must be logged in to access Media API.");
              } else {
                console.error('Unable to retrieve content because the API was redirected to "' + response.finalUrl + '"');
              }
              reject(-1);
            }
          } catch (error) {
            console.error("Error parsing JSON response:", error);
            reject(error);
          }
        },
        onerror: function (err) {
          reject(err);
        }
      });
    });
  }
})();