// ==UserScript==
// @name Local Movie Search
// @namespace http://tampermonkey.net/
// @version 1.2
// @description 在网页上添加输入框和按钮,搜索本地电影是否存在(需要配合Everything的HTTP服务器使用)。注:拖选要搜索的电影名再使用ALT+C快捷键可直接搜索。
// @author huangmmd
// @match *://*/*
// @grant GM_xmlhttpRequest
// @grant GM_registerMenuCommand
// @downloadURL none
// ==/UserScript==
(function() {
'use strict';
// 创建输入框和按钮
const input = document.createElement('input');
input.placeholder = '输入电影名字';
input.style.padding = '7.744px 11.616px'; // 7.04px * 1.1 = 7.744px, 10.56px * 1.1 = 11.616px
input.style.border = '2.2px solid #ccc'; // 2px * 1.1 = 2.2px
input.style.borderRadius = '3.872px'; // 3.52px * 1.1 = 3.872px
input.style.marginRight = '4.84px'; // 4.4px * 1.1 = 4.84px
input.style.fontSize = '13.552px'; // 12.32px * 1.1 = 13.552px
const button = document.createElement('button');
button.textContent = '搜索本地电影';
button.style.padding = '7.744px 11.616px'; // 7.04px * 1.1 = 7.744px, 10.56px * 1.1 = 11.616px
button.style.backgroundColor = '#007BFF';
button.style.color = 'white';
button.style.border = 'none';
button.style.borderRadius = '3.872px'; // 3.52px * 1.1 = 3.872px
button.style.cursor = 'pointer';
button.style.fontSize = '13.552px'; // 12.32px * 1.1 = 13.552px
button.addEventListener('mouseover', function() {
this.style.backgroundColor = '#0056b3';
});
button.addEventListener('mouseout', function() {
this.style.backgroundColor = '#007BFF';
});
// 创建用于显示结果的元素
const resultDiv = document.createElement('div');
resultDiv.style.color = '#333';
resultDiv.style.marginBottom = '5px';
resultDiv.style.fontSize = '13.552px'; // 修改字体大小为与输入框一致
// 将输入框、按钮和结果显示元素添加到页面左下角
const container = document.createElement('div');
container.style.position = 'fixed';
container.style.bottom = '19.36px'; // 17.6px * 1.1 = 19.36px
container.style.left = '19.36px'; // 17.6px * 1.1 = 19.36px
container.style.zIndex = 9999;
container.style.backgroundColor = 'white';
container.style.padding = '14.52px'; // 13.2px * 1.1 = 14.52px
container.style.borderRadius = '7.744px'; // 7.04px * 1.1 = 7.744px
container.style.boxShadow = '0 0 10px rgba(0, 0, 0, 0.1)';
container.appendChild(resultDiv);
container.appendChild(input);
container.appendChild(button);
document.body.appendChild(container);
// 创建设置面板
const settingsContainer = document.createElement('div');
settingsContainer.style.position = 'fixed';
settingsContainer.style.top = '50%';
settingsContainer.style.left = '50%';
settingsContainer.style.transform = 'translate(-50%, -50%)'; // 居中显示
settingsContainer.style.zIndex = 9999;
settingsContainer.style.backgroundColor = 'white';
settingsContainer.style.padding = '15px';
settingsContainer.style.borderRadius = '8px';
settingsContainer.style.boxShadow = '0 0 10px rgba(0, 0, 0, 0.1)';
settingsContainer.style.display = 'none'; // 默认隐藏设置面板
// 添加关闭按钮
const closeButton = document.createElement('button');
closeButton.textContent = '关闭';
closeButton.style.position = 'absolute';
closeButton.style.top = '9.68px'; // 8.8px * 1.1 = 9.68px
closeButton.style.right = '9.68px'; // 8.8px * 1.1 = 9.68px
closeButton.style.padding = '4.84px 9.68px'; // 4.4px * 1.1 = 4.84px, 8.8px * 1.1 = 9.68px
closeButton.style.backgroundColor = '#dc3545';
closeButton.style.color = 'white';
closeButton.style.border = 'none';
closeButton.style.borderRadius = '3.872px'; // 3.52px * 1.1 = 3.872px
closeButton.style.cursor = 'pointer';
closeButton.style.fontSize = '11.616px'; // 10.56px * 1.1 = 11.616px
closeButton.addEventListener('click', function() {
settingsContainer.style.display = 'none';
});
settingsContainer.appendChild(closeButton);
const settingsLabel = document.createElement('label');
settingsLabel.textContent = '检索服务器地址: ';
settingsLabel.style.display = 'block';
settingsLabel.style.marginBottom = '4.84px'; // 4.4px * 1.1 = 4.84px
const settingsInput = document.createElement('input');
settingsInput.type = 'text';
settingsInput.value = 'http://localhost:8080'; // 默认值
settingsInput.style.width = '193.6px'; // 176px * 1.1 = 193.6px
settingsInput.style.padding = '7.744px 11.616px'; // 7.04px * 1.1 = 7.744px, 10.56px * 1.1 = 11.616px
settingsInput.style.border = '2px solid #ccc';
settingsInput.style.borderRadius = '3.872px'; // 3.52px * 1.1 = 3.872px
settingsInput.style.marginRight = '4.84px'; // 4.4px * 1.1 = 4.84px
settingsInput.style.fontSize = '13.552px'; // 12.32px * 1.1 = 13.552px
const settingsSaveButton = document.createElement('button');
settingsSaveButton.textContent = '保存';
settingsSaveButton.style.padding = '7.744px 11.616px'; // 7.04px * 1.1 = 7.744px, 10.56px * 1.1 = 11.616px
settingsSaveButton.style.backgroundColor = '#007BFF';
settingsSaveButton.style.color = 'white';
settingsSaveButton.style.border = 'none';
settingsSaveButton.style.borderRadius = '3.872px'; // 3.52px * 1.1 = 3.872px
settingsSaveButton.style.cursor = 'pointer';
settingsSaveButton.style.fontSize = '13.552px'; // 12.32px * 1.1 = 13.552px
settingsSaveButton.addEventListener('click', function() {
localStorage.setItem('searchServerUrl', settingsInput.value);
settingsContainer.style.display = 'none';
});
settingsContainer.appendChild(settingsLabel);
settingsContainer.appendChild(settingsInput);
settingsContainer.appendChild(settingsSaveButton);
document.body.appendChild(settingsContainer);
// 加载保存的服务器地址
const savedUrl = localStorage.getItem('searchServerUrl');
if (savedUrl) {
settingsInput.value = savedUrl;
}
// 使用 GM_registerMenuCommand 创建设置菜单
GM_registerMenuCommand('设置检索服务器地址', function() {
settingsContainer.style.display = settingsContainer.style.display === 'none' ? 'block' : 'none';
});
// 按钮点击事件处理函数
function performSearch() {
const movieName = input.value.trim();
if (movieName) {
// 将电影名字按空格拆分成多个部分
const movieParts = movieName.split(' ');
// 存储所有找到的电影和未找到的电影
let allFoundMovies = [];
let notFoundMovies = [];
// 遍历每个部分进行搜索
movieParts.forEach(part => {
if (part) {
const searchUrl = `${settingsInput.value}/?s=${encodeURIComponent(part)}`;
GM_xmlhttpRequest({
method: 'GET',
url: searchUrl,
onload: function(response) {
const commonFormats = ['.mp4', '.mkv', '.avi', '.mov', '.flv', '.wmv'];
let foundMovies = [];
commonFormats.forEach(format => {
const regex = new RegExp(`[^\\s"']+${format}`, 'g');
let matches = response.responseText.match(regex);
if (matches) {
foundMovies = foundMovies.concat(matches);
}
});
// 过滤掉包含 /favi 的结果
foundMovies = foundMovies.filter(movie => !movie.includes('/favi'));
// 将找到的电影添加到所有找到的电影数组中
if (foundMovies.length > 0) {
allFoundMovies = allFoundMovies.concat(foundMovies);
} else {
notFoundMovies.push(part);
}
// 显示所有找到的电影和未找到的电影
let resultText = '';
if (allFoundMovies.length > 0) {
resultText += '本地存在以下电影:
';
allFoundMovies.forEach(movie => {
let decodedMovie = decodeURIComponent(movie);
// 提取文件路径和文件名
let filePath = decodedMovie.substring(0, decodedMovie.lastIndexOf('/'));
let fileName = decodedMovie.substring(decodedMovie.lastIndexOf('/') + 1);
// 设置 title 属性为文件名
resultText += `${filePath}
`;
});
}
if (notFoundMovies.length > 0) {
if (allFoundMovies.length > 0) {
resultText += '
';
}
resultText += '本地不存在以下电影:
';
notFoundMovies.forEach(movie => {
resultText += `${movie}
`;
});
}
resultDiv.innerHTML = resultText;
// 添加点击事件监听器,点击结果显示页的其他位置时清除结果显示
document.addEventListener('click', function clearResult(event) {
if (!resultDiv.contains(event.target)) {
resultDiv.textContent = '';
document.removeEventListener('click', clearResult);
}
});
// 根据结果显示情况设置自动消失
if (notFoundMovies.length > 0 && allFoundMovies.length === 0) {
// 3 秒后自动消失结果
setTimeout(() => {
resultDiv.textContent = '';
}, 3000);
}
},
onerror: function() {
resultDiv.textContent = '请求失败,请检查 Everything 服务器是否正常运行';
// 3 秒后自动消失结果
setTimeout(() => {
resultDiv.textContent = '';
}, 3000);
}
});
}
});
} else {
resultDiv.textContent = '请输入电影名字';
// 3 秒后自动消失结果
setTimeout(() => {
resultDiv.textContent = '';
}, 3000);
}
}
button.addEventListener('click', performSearch);
// 绑定快捷键 ALT + C
document.addEventListener('keydown', function(event) {
if (event.altKey && event.key === 'c') {
const selectedText = window.getSelection().toString().trim();
if (selectedText) {
input.value = selectedText;
// 模拟按钮点击事件进行搜索
performSearch();
}
}
});
})();