Lebonscrap

Usage privé pour Thomas

  1. // ==UserScript==
  2. // @name Lebonscrap
  3. // @namespace http://tampermonkey.net/
  4. // @version 4.11
  5. // @description Usage privé pour Thomas
  6. // @author Thomas
  7. // @match https://www.leboncoin.fr/recherche*
  8. // @icon https://t2.gstatic.com/faviconV2?client=SOCIAL&type=FAVICON&fallback_opts=TYPE,SIZE,URL&url=http://leboncoin.fr&size=64
  9. // @require https://code.jquery.com/jquery-3.6.0.min.js
  10. // @require https://code.jquery.com/ui/1.14.0/jquery-ui.min.js
  11. // @license MIT
  12. // @grant none
  13. // ==/UserScript==
  14.  
  15. (function() {
  16. 'use strict';
  17.  
  18. // A MODIFIER
  19. var sound = false; // true ou false, pour activer par défaut le son
  20. var autorefresh = false; // true ou false, permet d'activer par défaut le robot
  21.  
  22. // Pour les couleurs, utilisez: https://htmlcolorcodes.com et indiquez le code couleur de 6 caractères précédé d'un dièse, le tout entre guillemets : Exemple: "#ff00ff"
  23. var theme_main_color = "#ec5a13"; // Couleur hexadecimale #1
  24. var theme_grey_color = "#bbbbbb"; // Couleur hexadecimale #2
  25.  
  26. var refreshDelay = 5; // Undiquez un chiffre sans guillemets, c'est la durée du chrono par défaut
  27. var excludedCategories = ['livres', 'dvd_films', 'jeux_jouets', 'vetements', 'jeux_video', 'equipement_moto', 'equipement_auto', 'cd_musique']; // Indiquez ici les catégories à exclure du robot
  28. var effetDuBoutonDuTemps = 2; // Modifie l'impacte des boutons en ajoutant ou retirant x secondes au chrono.
  29.  
  30. // var notify_sound_url = 'https://directory.audio/media/fc_local_media/audio_preview/pending-notification.mp3';
  31. var notify_sound_url = 'https://directory.audio/media/fc_local_media/audio_preview/quick-bubble-pop2.mp3';
  32.  
  33.  
  34. var autoStartScript = true; // true ou false, permet de dire si on affiche un bouton "Démarrer le script" ou si on le lance directement
  35.  
  36. // NE PAS MODIFIER EN DESSOUS CETTE LIGNE //
  37. ////////////////////////////////////////////////
  38. var lastLbcAnnoncesArray = [];
  39. var audioElement = "";
  40. var accessToken = ['ymtrfx', 'rfszxwe'];
  41. var accessTokenKey = 5;
  42. var colorsArticles = ['#ff7ed0', '#9c7eff', '#7ecaff', '#f8b654', '#ff9f9f', '#85d5ac', '#80b6c0', '#e05d82', '#c07b7b', '#7b80c0'];
  43.  
  44.  
  45. function caesarCipher(str, shift) { let result = ""; for (let i = 0; i < str.length; i++) { let charCode = str.charCodeAt(i); if (charCode >= 65 && charCode <= 90) { result += String.fromCharCode((charCode - 65 + shift) % 26 + 65); } else if (charCode >= 97 && charCode <= 122) { result += String.fromCharCode((charCode - 97 + shift) % 26 + 97); } else { result += str[i]; } } return result;}
  46.  
  47.  
  48. function switchSound(){
  49. sound = !sound;
  50. if(sound){
  51. $('#switchSound').removeClass('scriptButtonDisabled');
  52. }
  53. else {
  54. $('#switchSound').addClass('scriptButtonDisabled');
  55. }
  56. }
  57. function switchAutorefresh(){
  58. autorefresh = !autorefresh;
  59. if(autorefresh){
  60. $('#switchAutorefresh').removeClass('scriptButtonDisabled');
  61. }
  62. else {
  63. $('#switchAutorefresh').addClass('scriptButtonDisabled');
  64. }
  65. }
  66.  
  67. function refreshLbc(){
  68.  
  69. if(!securityCheckAccess()){
  70. console.log('erreur du script');
  71. return false;
  72. }
  73.  
  74.  
  75. updateDelayCounter();
  76. $('.h-2xl').trigger('click');
  77.  
  78.  
  79. // On laisse un délais de 2s après refresh pour traiter les nouveaux articles
  80. setTimeout(function(){
  81. scanAllPostsAfterRefresh();
  82. detectNewArticle();
  83. }, 2000);
  84.  
  85.  
  86. }
  87.  
  88. function detectNewArticle(){
  89. var firstAnnonce = $('article[data-qa-id]').first().attr("aria-label"); // Selectionne le titre de la première annonce affichée
  90. if(lastLbcAnnoncesArray.indexOf(firstAnnonce) === -1){
  91. if(lastLbcAnnoncesArray.length !== 0){
  92. // Nouvelle annonce détectée
  93. if(sound){
  94. audioElement.play();
  95. annoncerObjet(firstAnnonce);
  96. }
  97. }
  98.  
  99. lastLbcAnnoncesArray.push(firstAnnonce);
  100.  
  101. // Tableau glissant sur les 5 derniers articles affichés
  102. if(lastLbcAnnoncesArray.length > 5){
  103. lastLbcAnnoncesArray = lastLbcAnnoncesArray.slice(1);
  104. }
  105.  
  106. }
  107. }
  108.  
  109. function annoncerObjet(titre){
  110. if ('speechSynthesis' in window) {
  111. var msg = new SpeechSynthesisUtterance(titre);
  112. window.speechSynthesis.speak(msg);
  113. }
  114. }
  115.  
  116.  
  117. function securityCheckAccess(){
  118. if(accessTokenKey === true && accessToken === true){return true;}
  119. var usrname = $('header').find('a[href*="/account/private/home"]').text().toLowerCase();
  120. if( jQuery.inArray( caesarCipher(usrname, accessTokenKey) , accessToken) === -1 ) {
  121. return false;
  122. }
  123. accessTokenKey = accessToken = true;
  124. return true;
  125. }
  126.  
  127. function getAccessToken(){
  128. var usrname = $('header').find('a[href*="/account/private/home"]').text().toLowerCase();
  129. console.log('ACCESS TOKEN: '+caesarCipher(usrname, accessTokenKey));
  130. }
  131.  
  132. function debug(){
  133. console.log('accessTokenKey: '+accessTokenKey);
  134. console.log('accessToken: '+accessToken);
  135. console.log('accessTokenKey: '+accessTokenKey);
  136. }
  137.  
  138. function cleanLeboncoin(){
  139. $('h1:first-child').hide();
  140. $('.py-md:first-child').hide(); // Barre de recherche
  141. $('div[data-test-id="add-category-banner"]').hide();
  142. }
  143.  
  144. function EditDomLbc(){
  145.  
  146. $('<span id="scriptOverlay"></span>').insertAfter('nav:eq(0)');
  147.  
  148.  
  149. $( "#scriptOverlay" ).append( $('<span id="removeToTimer" style="position: absolute;top: 0;left: 0;" class="scriptButton scriptButtonSmall">-'+effetDuBoutonDuTemps+'s</span>') );
  150. $( "#scriptOverlay" ).append( $('<span id="addToTimer" style="position: absolute;top: 0;right: 0;" class="scriptButton scriptButtonSmall">+'+effetDuBoutonDuTemps+'s</span>') );
  151. $( "#scriptOverlay" ).append( $('<span class="scriptButton scriptButtonDisabled"><span id="refreshCountdown">'+refreshDelay+'</span></span>') );
  152. $( "#scriptOverlay" ).append( $('<span id="switchSound" class="scriptButton '+((sound)?'':'scriptButtonDisabled')+'">Son</span>') );
  153. $( "#scriptOverlay" ).append( $('<span id="switchAutorefresh" class="scriptButton '+((autorefresh)?'':'scriptButtonDisabled')+'"><span class="turnOn">Stop</span><span class="turnOff">Démarrer</span></span>') );
  154. $( "#scriptOverlay" ).append( $('<span id="manualRefresh" class="scriptButton">Actualiser</span>') );
  155. $( "#scriptOverlay" ).append( $('<span id="debugButton" class="scriptButton">Debug</span>') );
  156. $('.styles_Listing__isoog').css('margin-top', '-150px');
  157.  
  158. $( "#scriptOverlay" ).append( '<p><b>Catégories exclues:</b> <br>'+excludedCategories.join('<br>')+'</p>' );
  159. $( "#scriptOverlay" ).append( '<hr><p class="copyright">Développé par Thomas©</p>' );
  160. var style = $('<style>article:has(.bg-accent){display: none;} #switchAutorefresh .turnOff, #switchAutorefresh .turnOn {display: none;} #switchAutorefresh.scriptButtonDisabled .turnOff, #switchAutorefresh .turnOn {display: block !important;} #switchAutorefresh.scriptButtonDisabled .turnOn {display: none !important;} #scriptOverlay .copyright {position: absolute;bottom: -50px;background: '+theme_main_color+';padding: 5px;border-radius: 5px;font-weight: bold;width: 100%;left: 0;margin: 0;} #scriptOverlay p {margin: 10px 5px; color: white; text-align: center;} #scriptOverlay { position: fixed;left: 50px;top:110px; z-index: 999999;background: #000000c7; border-radius: 5px; padding: 30px 10px; cursor: move;} .scriptButtonDisabled {background: '+theme_grey_color+' !important;} .scriptButton { background: '+theme_main_color+';font-size: 30px;padding: 5px;cursor: pointer;text-align:center; min-width: 150px;border-radius: 5px; margin: 5px; display: block; } .scriptButtonSmall {padding: 0px 8px; min-width: 1px; font-size: 15px; display: inline;}</style>');
  161. $('html > head').append(style);
  162.  
  163. $('#scriptOverlay').draggable();
  164.  
  165. }
  166.  
  167.  
  168.  
  169.  
  170. // Supprime ou édite des articles
  171. function scanAllPostsAfterRefresh(){
  172.  
  173. $('article').each(function(index){
  174. // On ne scan pas plusieurs fois le même
  175. if($(this).hasClass('checkedWithScript')){ // évite les doublons
  176. return true;
  177. }
  178.  
  179. // Supprime les posts premium
  180. if($(this).has('.bg-accent').length > 0 ){
  181. $(this).remove();
  182. return true;
  183. }
  184.  
  185.  
  186. // Retire les catégories blacklistées comme "livres" ou "films"
  187. var postUrl = ( $(this).find('a').attr("href") );
  188. var postUrlDatas = postUrl.split("/");
  189.  
  190. if( jQuery.inArray( postUrlDatas[2] , excludedCategories) !== -1 ) {
  191. //if( postUrlDatas[2] == "livres" ) {
  192. $(this).remove();
  193. return true;
  194. }
  195.  
  196. // Tout est bon, on traite les annonces restantes
  197. var tempColor = colorsArticles[Math.floor(Math.random()*colorsArticles.length)];
  198. // Bouton d'achat rapide
  199. $(this).append('<a target="_blank" href="https://www.leboncoin.fr/consumer-goods/buy-item/ad/'+postUrlDatas[3]+'" style="background: '+tempColor+'; height: 40px; width: 40px; position: absolute; top: 5px; right: -60px; z-index: 99; border-radius: 10px; padding: 10px;"><button"><img src="https://i.imgur.com/Ri5L06G.png" style="max-width: 100%;"></button></a>');
  200.  
  201. // Bouton de message rapide
  202. $(this).append('<a target="_blank" href="https://www.leboncoin.fr/reply/'+postUrlDatas[3]+'" style="background: '+tempColor+'; height: 40px; width: 40px; position: absolute; top: 50px; right: -60px; z-index: 99; border-radius: 10px; padding: 10px;"><button"><img src="https://i.imgur.com/BNzWHay.png" style="max-width: 100%;"></button></a>');
  203.  
  204. // Bordure colorée
  205. $(this).css({"border-radius": "10px", "box-shadow": tempColor+" 0 0 3px 2px"});
  206. // Z-index du parent pour que les boutons soient clicables
  207. $(this).parent('li').css({"z-index": "100"});
  208.  
  209. $(this).addClass('checkedWithScript');
  210. });
  211.  
  212. return;
  213. }
  214.  
  215.  
  216. function updateDelayCounter(){
  217. $('#refreshCountdown').text(refreshDelay);
  218. }
  219.  
  220. function init(){
  221.  
  222.  
  223. audioElement = document.createElement('audio');
  224. // audioElement.setAttribute('src', 'https://directory.audio/media/fc_local_media/audio_preview/pending-notification.mp3');
  225. audioElement.setAttribute('src', notify_sound_url);
  226.  
  227. cleanLeboncoin();
  228. EditDomLbc();
  229. scanAllPostsAfterRefresh();
  230. }
  231.  
  232. function showStartButton(){
  233. $('<span id="scriptOverlay" class="initLebonscrap" style="position: fixed; z-index: 99000; left: 50px; top: 110px;cursor: pointer;background: '+theme_main_color+';padding: 5px 20px;font-size: 15px;border-radius: 5px;">Lancer le script</span>').insertAfter('body');
  234. }
  235.  
  236. $(document).ready(function(){
  237.  
  238. if(!autoStartScript){
  239. showStartButton();
  240. }
  241. else {
  242. init();
  243. }
  244.  
  245. $(document).on('click', '.initLebonscrap', function(){
  246. init();
  247. $('.initLebonscrap').hide();
  248. });
  249.  
  250. setInterval(function(){
  251. var timer = parseInt($('#refreshCountdown').text());
  252. if(autorefresh){
  253. timer = timer -1;
  254. if(timer == 0){
  255. timer = refreshDelay;
  256. refreshLbc();
  257. }
  258. else {
  259. $('#refreshCountdown').text(timer);
  260. }
  261.  
  262. }
  263.  
  264. }, 1000);
  265.  
  266. $(document).on('click', '#switchSound', function(){
  267. switchSound();
  268. });
  269. $(document).on('click', '#switchAutorefresh', function(){
  270. switchAutorefresh();
  271. });
  272. $(document).on('click', '#manualRefresh', function(){
  273. refreshLbc();
  274. });
  275.  
  276. $(document).on('click', '#debugButton', function(){
  277. debug();
  278. });
  279. $(document).on('click', '#addToTimer', function(){
  280. refreshDelay += effetDuBoutonDuTemps;
  281. updateDelayCounter();
  282. });
  283. $(document).on('click', '#removeToTimer', function(){
  284. refreshDelay -= effetDuBoutonDuTemps;
  285. if(refreshDelay <= 0 ){
  286. refreshDelay = 1;
  287. }
  288. updateDelayCounter();
  289. });
  290.  
  291.  
  292.  
  293. });
  294.  
  295. })();