您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Displays bundle ID & full metadata on App Store pages with advanced features, copy/export buttons, and improved UI
- // ==UserScript==
- // @name App Store Metadata Viewer
- // @namespace http://tampermonkey.net/
- // @version 2.3
- // @description Displays bundle ID & full metadata on App Store pages with advanced features, copy/export buttons, and improved UI
- // @author sharmanhall
- // @match https://apps.apple.com/*/app/*/id*
- // @match https://apps.apple.com/app/id*
- // @grant GM_setClipboard
- // @grant GM_download
- // @grant GM_registerMenuCommand
- // @license MIT
- // @icon https://www.google.com/s2/favicons?sz=64&domain=apple.com
- // ==/UserScript==
- (function () {
- 'use strict';
- const settings = {
- displayMode: 'overlay',
- autoCopy: false
- };
- GM_registerMenuCommand('Toggle Display Mode', () => {
- settings.displayMode = settings.displayMode === 'overlay' ? 'inline' : 'overlay';
- alert(`Switched to: ${settings.displayMode}`);
- location.reload();
- });
- GM_registerMenuCommand('Toggle Auto-Copy', () => {
- settings.autoCopy = !settings.autoCopy;
- alert(`Auto-copy is now ${settings.autoCopy ? 'enabled' : 'disabled'}`);
- });
- function waitForAppId(attempt = 0) {
- const appIdMatch = window.location.href.match(/id(\d+)/);
- if (!appIdMatch && attempt < 10) {
- return setTimeout(() => waitForAppId(attempt + 1), 1000);
- } else if (!appIdMatch) {
- console.error('[Metadata Viewer] App ID not found.');
- return;
- }
- fetchAppData(appIdMatch[1]);
- }
- async function fetchAppData(appId) {
- const lookupUrl = `https://itunes.apple.com/lookup?id=${appId}`;
- try {
- const res = await fetch(lookupUrl);
- const data = await res.json();
- if (!data.results || !data.results.length) throw 'No results';
- showInfo(data.results[0]);
- } catch (err) {
- console.error('[Metadata Viewer] Failed to fetch metadata:', err);
- }
- }
- function formatBytes(bytes) {
- const kb = bytes / 1024;
- if (kb < 1024) return `${Math.round(kb)} KB`;
- return `${(kb / 1024).toFixed(1)} MB`;
- }
- function showInfo(app) {
- const {
- bundleId,
- version,
- minimumOsVersion,
- releaseDate,
- primaryGenreName,
- languageCodesISO2A,
- fileSizeBytes,
- sellerName,
- trackViewUrl
- } = app;
- const country = new URL(window.location.href).pathname.split('/')[1].toUpperCase();
- const lang = languageCodesISO2A?.join(', ') || 'N/A';
- const infoHTML = `
- <div id="bundle-id-widget" style="font-family: 'Segoe UI', Roboto, monospace; font-size: 13px; line-height: 1.8;">
- <div style="margin-bottom: 8px;"><strong>📦 Bundle ID:</strong> ${bundleId}</div>
- <div><strong>👨💻 Developer:</strong> ${sellerName}</div>
- <div><strong>📱 Version:</strong> ${version}</div>
- <div><strong>📅 Release Date:</strong> ${releaseDate?.split('T')[0]}</div>
- <div><strong>📂 Size:</strong> ${formatBytes(fileSizeBytes)}</div>
- <div><strong>🧭 Min OS:</strong> ${minimumOsVersion || 'N/A'}</div>
- <div><strong>🗂 Genre:</strong> ${primaryGenreName}</div>
- <div><strong>🌍 Country:</strong> ${country}</div>
- <div style="margin-bottom: 12px;"><strong>🗣️ Language(s):</strong> ${lang}</div>
- <div style="display: flex; gap: 10px; flex-wrap: wrap;">
- <button id="copyBtn" style="background:#1E88E5;color:white;border:none;padding:6px 10px;border-radius:5px;cursor:pointer;">📋 Copy Bundle ID</button>
- <button id="jsonBtn" style="background:#333;color:white;border:none;padding:6px 10px;border-radius:5px;cursor:pointer;">🗄 Export JSON</button>
- <a href="${trackViewUrl}" target="_blank" style="color:#42A5F5;text-decoration:none;padding:6px 10px;border-radius:5px;background:#222;display:inline-block;">🔗 View on App Store</a>
- </div>
- </div>
- `;
- const container = document.createElement('div');
- container.innerHTML = infoHTML;
- if (settings.displayMode === 'inline') {
- container.style.background = '#f9f9f9';
- container.style.padding = '14px';
- container.style.border = '1px solid #ccc';
- container.style.borderRadius = '8px';
- container.style.marginTop = '20px';
- const target = document.querySelector('h1') || document.body;
- target.parentElement.insertBefore(container, target.nextSibling);
- } else {
- Object.assign(container.style, {
- position: 'fixed',
- bottom: '20px',
- right: '20px',
- background: '#111',
- color: '#fff',
- padding: '16px',
- borderRadius: '10px',
- boxShadow: '0 0 16px rgba(0,0,0,0.6)',
- zIndex: 99999,
- maxWidth: '300px',
- opacity: '85%'
- });
- document.body.appendChild(container);
- }
- const copyBtn = document.getElementById('copyBtn');
- copyBtn.onclick = () => {
- (typeof GM_setClipboard === 'function' ? GM_setClipboard : navigator.clipboard.writeText)(bundleId);
- copyBtn.textContent = '✅ Copied!';
- setTimeout(() => (copyBtn.textContent = '📋 Copy Bundle ID'), 1500);
- };
- const jsonBtn = document.getElementById('jsonBtn');
- jsonBtn.onclick = () => {
- const blob = new Blob([JSON.stringify(app, null, 2)], { type: 'application/json' });
- const url = URL.createObjectURL(blob);
- GM_download({ url, name: `bundleinfo-${bundleId}.json` });
- };
- if (settings.autoCopy) {
- (typeof GM_setClipboard === 'function' ? GM_setClipboard : navigator.clipboard.writeText)(bundleId);
- }
- }
- window.addEventListener('load', waitForAppId);
- })();