-
Notifications
You must be signed in to change notification settings - Fork 1
/
Twitter Image to SauceNAO.user.js
142 lines (116 loc) · 5.41 KB
/
Twitter Image to SauceNAO.user.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
// ==UserScript==
// @name Twitter Image to SauceNAO
// @namespace http://yourwebsite.com
// @version 3.2
// @description Adds a button to convert Twitter image URLs to SauceNAO search URLs. Instantly searches for single image tweets, and shows a dropdown for multiple images.
// @author FunkyJustin
// @match https://twitter.com/*
// @match https://x.com/*
// @grant none
// @license MIT
// ==/UserScript==
(function() {
'use strict';
function convertToSauceNAOUrl(imageUrl) {
const encodedUrl = encodeURIComponent(imageUrl);
return `https://saucenao.com/search.php?url=${encodedUrl}`;
}
function createSauceNAODropdown(imageUrls, button) {
const dropdown = document.createElement('div');
dropdown.className = 'saucenao-dropdown';
dropdown.style.position = 'absolute';
dropdown.style.backgroundColor = 'white';
dropdown.style.border = '1px solid #ccc';
dropdown.style.zIndex = '10000';
dropdown.style.boxShadow = '0px 4px 6px rgba(0, 0, 0, 0.1)';
dropdown.style.maxHeight = '200px';
dropdown.style.overflowY = 'auto';
dropdown.style.padding = '4px';
dropdown.style.fontSize = '14px';
imageUrls.forEach((imageUrl, index) => {
const menuItem = document.createElement('div');
menuItem.style.padding = '8px';
menuItem.style.cursor = 'pointer';
menuItem.style.color = '#000';
menuItem.innerText = `Search Image ${index + 1}`;
menuItem.addEventListener('click', () => {
const saucenaoUrl = convertToSauceNAOUrl(imageUrl);
window.open(saucenaoUrl, '_blank');
dropdown.remove();
});
dropdown.appendChild(menuItem);
});
const searchAllItem = document.createElement('div');
searchAllItem.style.padding = '8px';
searchAllItem.style.cursor = 'pointer';
searchAllItem.style.color = '#000';
searchAllItem.innerText = 'Search All Images';
searchAllItem.addEventListener('click', () => {
imageUrls.forEach(imageUrl => {
const saucenaoUrl = convertToSauceNAOUrl(imageUrl);
window.open(saucenaoUrl, '_blank');
});
dropdown.remove();
});
dropdown.appendChild(searchAllItem);
button.parentNode.style.position = 'relative';
button.parentNode.appendChild(dropdown);
const buttonRect = button.getBoundingClientRect();
dropdown.style.bottom = `${button.offsetTop}px`;
dropdown.style.left = `${button.offsetLeft}px`;
document.addEventListener('click', (event) => {
if (!dropdown.contains(event.target) && event.target !== button) {
dropdown.remove();
}
}, { once: true });
return dropdown;
}
function addSauceNAOBtn() {
const articles = document.querySelectorAll('article');
articles.forEach(article => {
const images = article.querySelectorAll('img[src*="pbs.twimg.com/media"]');
const imageUrls = Array.from(images).map(img => img.src);
if (imageUrls.length > 0) {
const container = article.querySelector('div[role="group"]');
if (container) {
const existingButton = container.querySelector('.saucenao-button');
if (!existingButton) {
const button = document.createElement('div');
button.className = 'saucenao-button';
button.style.display = 'inline-block';
button.style.marginLeft = '8px';
button.style.cursor = 'pointer';
button.style.color = 'rgb(29, 155, 240)';
button.innerText = 'SauceNAO';
const dropdownIcon = document.createElement('span');
dropdownIcon.innerText = ' ▼'; // Dropdown icon
dropdownIcon.style.display = imageUrls.length > 1 ? 'inline' : 'none'; // Show only if multiple images
button.appendChild(dropdownIcon); // Add the icon to the button
button.addEventListener('click', (event) => {
event.stopPropagation();
event.preventDefault();
if (imageUrls.length === 1) {
const saucenaoUrl = convertToSauceNAOUrl(imageUrls[0]);
window.open(saucenaoUrl, '_blank');
} else {
document.querySelectorAll('.saucenao-dropdown').forEach(el => el.remove());
createSauceNAODropdown(imageUrls, button);
}
});
container.appendChild(button);
}
}
}
});
}
const observer = new MutationObserver((mutations) => {
mutations.forEach(() => {
addSauceNAOBtn();
});
});
observer.observe(document.body, {
childList: true,
subtree: true
});
addSauceNAOBtn();
})();