Browse Source

🎉 Initial commit

master
KaKi87 8 months ago
commit
3330f9a725
12 changed files with 533 additions and 0 deletions
  1. +1
    -0
      .gitignore
  2. +13
    -0
      GoogleSearchCloudFlareDetector/README.md
  3. +104
    -0
      GoogleSearchCloudFlareDetector/index.js
  4. BIN
      GoogleSearchCloudFlareDetector/screenshot.jpg
  5. +12
    -0
      README.md
  6. +18
    -0
      RedditForceLocalSearch/README.md
  7. +58
    -0
      RedditForceLocalSearch/index.js
  8. BIN
      RedditForceLocalSearch/screenshot.png
  9. +15
    -0
      XDAForumsThreadsMeta/README.md
  10. +39
    -0
      XDAForumsThreadsMeta/index.js
  11. +86
    -0
      YGGTorrentInfiniteSession/README.md
  12. +187
    -0
      YGGTorrentInfiniteSession/index.js

+ 1
- 0
.gitignore View File

@ -0,0 +1 @@
.idea

+ 13
- 0
GoogleSearchCloudFlareDetector/README.md View File

@ -0,0 +1,13 @@
# Google Search CloudFlare detector
Tag Google Search results pointing to CloudFlare-protected websites.
![](./screenshot.jpg)
## Installation
[From GreasyFork](https://greasyfork.org/fr/scripts/396682-google-search-cloudflare-detector)
## Changelog
* `1.0.0` (2020-02-20) • [Initial release](https://greasyfork.org/fr/scripts/396682-google-search-cloudflare-detector?version=774106)

+ 104
- 0
GoogleSearchCloudFlareDetector/index.js View File

@ -0,0 +1,104 @@
// ==UserScript==
// @match https://www.google.*/search*
// @name Google Search CloudFlare detector
// @grant none
// @description Tag Google Search results pointing to CloudFlare-protected websites
// @version 1.0.0
// @author KaKi87
// @license GPL-3.0-or-later
// @namespace https://git.kaki87.net/KaKi87/userscripts/src/branch/master/GoogleSearchCloudFlareDetector
// ==/UserScript==
const getIp = host => new Promise(resolve => {
fetch(`https://api.kaki87.net/dns/${host}`)
.then(res => res.json())
.then(res => {
if(res.success)
resolve(res.data.find(entry => entry.type === 'A')['value']);
else
return '0.0.0.0';
})
});
const isIpInCidr = (ip, cidr) => {
// Source : https://gist.github.com/KaKi87/7c3907a1ec03ebc8ecb0294ab7176bce
const [range, bits = 32] = cidr.split('/');
const mask = ~(2 ** (32 - bits) - 1);
const ip4ToInt = ip => ip.split('.').reduce((int, oct) => (int << 8) + parseInt(oct, 10), 0) >>> 0;
return (ip4ToInt(ip) & mask) === (ip4ToInt(range) & mask);
};
const cloudFlareCidrList = [
// Source : https://www.cloudflare.com/ips-v4
'173.245.48.0/20',
'103.21.244.0/22',
'103.22.200.0/22',
'103.31.4.0/22',
'141.101.64.0/18',
'108.162.192.0/18',
'190.93.240.0/20',
'188.114.96.0/20',
'197.234.240.0/22',
'198.41.128.0/17',
'162.158.0.0/15',
'104.16.0.0/12',
'172.64.0.0/13',
'131.0.72.0/22',
];
const isCloudFlareIp = ip => !! cloudFlareCidrList.find(cidr => isIpInCidr(ip, cidr));
const links = [...document.querySelectorAll('#search a')]
.filter(el => !el.id && !el.className);
(async () => {
for(let i = 0; i < links.length; i++){
const element = links[i];
const title = element.querySelector('h3');
const host = element.href.split('/')[2];
const ip = await getIp(host);
if(isCloudFlareIp(ip))
title.innerHTML = `<span style="font-weight: bold; color: red;">(CloudFlare)</span> ${title.textContent}`;
}
})();

BIN
GoogleSearchCloudFlareDetector/screenshot.jpg View File

Before After
Width: 1102  |  Height: 2538  |  Size: 270 KiB

+ 12
- 0
README.md View File

@ -0,0 +1,12 @@
# Userscripts
A userscript ([Wikipedia](https://en.wikipedia.org/wiki/Userscript)) is a JavaScript file that can modify (usually improve) your browsing experience similarly to browser extensions ([Wikipedia](https://en.wikipedia.org/wiki/Browser_extension)) but with limited capabilities and less development effort.
Though many browser extensions exist for managing userscripts, Violentmonkey ([official website](https://violentmonkey.github.io/)) is recommended for all platforms.
My userscripts are published on my [GreasyFork profile](https://greasyfork.org/fr/users/430889-kaki87).
- [Google Search CloudFlare Detector](./GoogleSearchCloudFlareDetector)
- [Reddit Force Local Search](./RedditForceLocalSearch)
- [XDA Forums Threads Meta](./XDAForumsThreadsMeta) *(deprecated)*
- [YGGTorrent Infinite Session](./YGGTorrentInfiniteSession) *(FR)*

+ 18
- 0
RedditForceLocalSearch/README.md View File

@ -0,0 +1,18 @@
# Reddit Force Local Search
Force search in subreddit by default.
More info :
- https://www.reddit.com/r/help/comments/f42mn3/can_no_longer_search_within_subreddit_by_default/
- https://www.reddit.com/r/help/comments/f9rsvh/searching_should_default_to_within_current/
![](./screenshot.png)
## Installation
[From GreasyFork](https://greasyfork.org/fr/scripts/399193-reddit-force-local-search)
## Changelog
* `1.0.0` (2020-04-01) • [Initial release](https://greasyfork.org/fr/scripts/399193-reddit-force-local-search?version=786790)

+ 58
- 0
RedditForceLocalSearch/index.js View File

@ -0,0 +1,58 @@
// ==UserScript==
// @match https://www.reddit.com/*
// @name Reddit force local search
// @grant none
// @description Force search in subreddit by default
// @version 1.0.0
// @author r/KaKi_87
// @license GPL-3.0-or-later
// @namespace https://git.kaki87.net/KaKi87/userscripts/src/branch/master/RedditForceLocalSearch
// ==/UserScript==
const form = document.querySelector('#SearchDropdown form');
const getInput = () => document.querySelector('#header-search-bar');
const getSubreddit = () => {
const path = window.location.href.split('/');
return path[3] === 'r' ? path[4] : undefined;
};
const handler = event => {
const
query = getInput().value,
subreddit = getSubreddit();
if(!subreddit) return;
event.stopPropagation();
event.stopImmediatePropagation();
event.preventDefault();
window.location.href = `https://www.reddit.com/r/${subreddit}/search?q=${query}&restrict_sr=1`;
};
form.addEventListener('submit', handler, true);
const loop = () => {
const subreddit = getSubreddit();
const input = getInput();
input.setAttribute('placeholder', subreddit ? `Search in r/${subreddit}` : 'Search');
setTimeout(loop, 250);
};
loop();

BIN
RedditForceLocalSearch/screenshot.png View File

Before After
Width: 2691  |  Height: 309  |  Size: 8.2 KiB

+ 15
- 0
XDAForumsThreadsMeta/README.md View File

@ -0,0 +1,15 @@
# XDA Forums Threads Meta
Add created & updated metadata to XDA forum threads.
## DEPRECATION NOTICE
[I firstly created this script in order to get the updated date of threads *(i.e. custom ROMs)* in a topic *(i.e. a device)* directly from the topics list.](https://forum.xda-developers.com/general/about-xda/feature-request-sort-topics-time-edited-t3943066)
It seems, though, that edited date is no longer available on threads.
Therefore, this script has outlived its usefulness and will no longer receive updates unless the edited date information comes back.
## Changelog
* `1.0.0` (2019-06-26) • [Initial release](https://gist.github.com/KaKi87/9fadc869f11aebd8d3f71b01baf06f0f)

+ 39
- 0
XDAForumsThreadsMeta/index.js View File

@ -0,0 +1,39 @@
// ==UserScript==
// @match https://forum.xda-developers.com/*
// @name XDA Forums - Threads meta
// @grant none
// @description Add created & updated metadata to XDA forum threads
// @version 1.0.0
// @author KaKi87
// @license MIT
// @namespace https://git.kaki87.net/KaKi87/userscripts/src/branch/master/XDAForumsThreadsMeta
// ==/UserScript==
window.addEventListener('DOMContentLoaded', () => {
if(!document.querySelector('.thread-listing')) return;
const getThreadMeta = link => new Promise(resolve => $.get(link, data => {
const zip = (keys, values) => Object.assign(...keys.map((k, i) => ({ [k]: values[i] }))); // Source : https://stackoverflow.com/a/47517569
const thread = new DOMParser().parseFromString(data, 'text/html');
resolve({
created: zip(['date', 'time'],
thread.querySelector('#thread-header-meta')
.textContent.trim().split('\n')[0].split(' on ')[1].split(', ')),
...(thread.querySelector('.postbit-edited') ? {
edited: zip(['author', 'date', 'time'], thread.querySelector('.postbit-edited').textContent.match(/Last edited by (.+); (.+) at (.+)\./).slice(1))
} : {})
});
}));
(async() => {
const threads = [...document.querySelectorAll('.thread-row')].map(el => ({
link: el.querySelector('.threadTitle').href,
author: el.querySelector('div.smallfont a').textContent,
subtitle: el.querySelector('div.smallfont')
}));
for(let i = 0; i < threads.length; i++){
const
thread = threads[i],
meta = await getThreadMeta(thread.link);
thread.subtitle.innerHTML += `, created on ${meta.created.date} ${meta.created.time}${meta.edited ? `, edited on ${meta.edited.date} ${meta.edited.time} ${(thread.author !== meta.edited.author) ? `by ${meta.edited.author}` : ''}` : ''}`;
}
})();
});

+ 86
- 0
YGGTorrentInfiniteSession/README.md View File

@ -0,0 +1,86 @@
# YGGTorrent Infinite Session
*Stay signed in for real*
## Introduction
Le cookie de session du site Internet du tracker torrent YGG a une durée de vie de seulement *2 heures*.
Cette durée étant extrêmement *faible*, et aucune option d'augmentation de ce délai n'étant disponible, j'ai créé la mienne.
## Installation
[Depuis GreasyFork](https://greasyfork.org/fr/scripts/394508-yggtorrent-infinite-session)
## Fonctionnement
Ce script fonctionne de façon tout à fait **transparente** : il *mémorise* vos informations de connexion lorsque vous vous connectez, et les *oublie* lorsque vous vous déconnectez.
Entre temps, si le cookie de session expire, le script vous reconnectera automatiquement. *(sa raison d'être)*
Le code source est documenté et formaté du mieux possible pour assurer sa lisibilité et permettre son audit.
## Sécurité
### Identifiants
Vos identifiants ne sont accessibles que dans le cadre du script.
Cependant, vous devez considérer que la mémorisation par le script est équivalente à la **mémorisation par le navigateur** en termes de sécurité, c'est-à-dire qu'il est *facilement* possible de les récupérer par un accès physique à votre ordinateur ou par un virus.
### Navigation
Le script utilise une expression régulière afin de détecter intelligemment le site YGGTorrent.
Cette détection est positive si le protocole est HTTPS *(et non HTTP)* et que le nom de domaine correspond exactement à `ygg` ou `yggtorrent`.
Par exemple, ceux-ci fonctionneront :
- `https://ygg.is`
- `https://yggtorrent.is`
- `https://yggtorrent.pe`
- `https://yggtorrent.ws`
- `https://ww2.yggtorrent.ws`
Mais ceux-ci ne fonctionneront pas :
- `http://ygg.is`
- `http://yggtorrent.is`
- `https://yggfake.com`
- `https://fakeygg.com`
- `https://ygg.fake.com`
Bien que la plupart des fake ne font pas autant d'effort, certains pourraient, et il est de votre responsabilité *(et non de la mienne)* de ne pas les fréquenter, auquel cas la connexion automatique pourrait se déclencher et vos identifiants seraient alors transmis à des pirates.
Si cela devait toutefois arriver, pensez à vous rendre sur le vrai site, renouveler votre passkey et changer votre mot de passe.
Aussi, n'utilisez jamais un mot de passe sur plusieurs sites.
*Il est possiblement envisagé dans le futur de n'activer la connexion automatique que sur les domaines où l'utilisateur s'est déjà manuellement connecté.*
## Cas d'utilisation
Ce script est (presque) inutile si vous mémorisez vos mots de passe dans votre navigateur.
Néanmoins, votre navigateur ne saura pas automatiser la connexion, et c'est le rôle de ce script.
De plus, utilisant un gestionnaire de mots de passe au quotidien, et mes mots de passe étant donc générés, le copier/coller plusieurs fois par jour peut s'avérer ennuyant.
## Licence
Ce script est distribué sous la licence [GNU GPL v3](https://www.gnu.org/licenses/gpl-3.0.html).
## Maintenance
Ce script sera maintenu aussi longtemps qu'il aura une raison d'être, c'est-à-dire que le besoin d'automatiser la re-connexion au site en raison de l'expiration trop rapide de la session, sera un problème.
## Support
Ping *@KaKi87#2368* sur le serveur Discord [We Torrent](https://discord.gg/QkJzWSD).
## Notes de versions
* `1.0.0` (01/01/2020) • [Publication initiale](https://greasyfork.org/fr/scripts/394508-yggtorrent-infinite-session?version=762353)
---
[Remerciement spécial à Hiro sur Wareziens.net pour la petite pub.](https://www.wareziens.net/forum/topic-43322-topic-unique-yggtorrent-new-info-pubs-page-1-page-18.html#p537181)

+ 187
- 0
YGGTorrentInfiniteSession/index.js View File

@ -0,0 +1,187 @@
// ==UserScript==
// @name YGGTorrent infinite session
// @description Stay signed in for real
// @grant GM.getValue
// @grant GM.setValue
// @grant GM.deleteValue
// @version 1.0.0
// @author KaKi87
// @license GPL-3.0-or-later
// @namespace https://git.kaki87.net/KaKi87/userscripts/src/branch/master/YGGTorrentInfiniteSession
// ==/UserScript==
/*
Copyright (C) 2020 - KaKi87
This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with this program. If not, see https://www.gnu.org/licenses/.
*/
/*
* [ Function ] Get logout link
*
* NOTE : link not in DOM while logged out
*
*/
const getLogout = () => document.querySelector('[href$="/user/logout"]');
/*
* [ Event handler ] Delete credentials on logout
*
*/
const createLogoutHandler = () => {
const logout = getLogout();
if(!logout) return;
logout.addEventListener('click', async event => {
if(event.isTrusted)
{
event.preventDefault();
await GM.deleteValue('username');
await GM.deleteValue('password');
logout.click();
}
}, true);
}
/*
* [ Event listener ] Login callback
*
*/
const onceLoggedIn = callback => {
(function waitForLogin(){
if(getLogout()) callback();
else setTimeout(waitForLogin, 150);
})();
};
/*
* [ Main ]
*
*/
document.addEventListener('readystatechange', async () => {
if(document.readyState !== 'complete') return;
/*
* [ Step #1 ] Smartly detect YGGTorrent website
*
* despite frequent domain name changes
*
* using regular expression
*
* NOTE : although this expression is pretty strict,
*
* it will match any "*.ygg.tld" and "*.yggtorrent.tld"
*
*/
if(!window.location.href.match(new RegExp([
// EXPRESSION | DESIGNATION | COMMENT
'^' , // start
'https:\/\/' , // protocol | http_s_ only
'([^.]+\.)?' , // subdomain | optional
'ygg(torrent)?' , // domain | "ygg" or "yggtorrent"
'\.[^.]+' , // extension | aka. TLD
'(\/.+)?' , // path | optional
'$' // end
].join('')))) return;
/*
* [ Step #2 ] Get login form
*
* NOTE : form exists in DOM while logged in
*
*/
const form = document.querySelector('#user-login');
if(!form) return;
const
formUsername = form.querySelector('[type=text]'),
formPassword = form.querySelector('[type=password]');
/*
* [ Step #3 ] Handle login & logout
*
* Inherent features :
*
* - Save credentials on login
*
* - Delete credentials on logout
*
*/
if(getLogout()) createLogoutHandler();
else onceLoggedIn(() => {
GM.setValue('username', formUsername.value);
GM.setValue('password', formPassword.value);
createLogoutHandler();
});
/*
* [Step #4 ] Auto-login
*
*/
const
username = await GM.getValue('username'),
password = await GM.getValue('password');
if(username && password && !getLogout())
{
formUsername.value = username;
formPassword.value = password;
form.querySelector('[type=submit]').click();
}
});

Loading…
Cancel
Save