The old one worked just fine until qidian updated whatever it was that broke it, so it's 100% possible, but as i don't hav any knowledge of how to code i can't really explore what it was they did and how to fix it X_x
Throws an error at line 103 every tick for chapters that are paywalled. yueimg loads most of the scripts and css for the site. webnovel.com also pulls jQuery from there. In short, you'd need to do a lot of work to get webnovel.com to work properly without accessing yueimg. Same goes for first-party scripts. I'm surprised you can even browse the site with those scripts disabled. I just tried disabling them in uMatrix, and the site completely broke.
Well i have gotten used to allowing webnovel and yeimg just when im going to open links for any new chapters and then remove the temporary permission right after i have done that, and that always worked before as the script just reloaded itself and then skipped the ad, but now it doesn't do anything when i remove permission from webnovel and yueimg Not a huge deal, just a routine i have gotten used to and i like the smaller font when webnovel and yueimg isn't allowed X_x but if it's not possible ill just allow those scripts ofc. Not sure if it matters but i use firefox 56 and greasemonkey 3.9
Maybe related to this: https://forum.novelupdates.com/posts/4017278/ OP doesn't have these changes because they're something I haven't tested myself.
Thanks for your update to this script, @ekojsalim! If you are able to, it would be amazing if you could fix the mobile version of this script as well. I tried adding the changes you made in your update, but it didn't seem to work.
Code: // ==UserScript== // @name webnovel.com skip video ads // @namespace http://forum.novelupdates.com/ // @version 5 // @run-at document-end // @match http://webnovel.com/book/* // @match https://webnovel.com/book/* // @match http://www.webnovel.com/book/* // @match https://www.webnovel.com/book/* // ==/UserScript== //------------------------------------------------------------------------------ // This script is released to the public domain. No attribution is required. //------------------------------------------------------------------------------ // How frequently this script should check for new chapters. // // The amount is in milliseconds. const INTERVAL_CHAPTER_CHECK = 1000; // When a token is not ready yet, this is how much time we should wait // before trying again. // // The amount is in milliseconds. const INTERVAL_TOKEN_CHECK = 1000; function getCookie(name) { var value = "; " + document.cookie; var parts = value.split("; " + name + "="); if (parts.length == 2) return parts.pop().split(";").shift(); } /** * Check for new chapters and try to remove the adwall from them. */ function main() { Array.from( // Locked chapters. document.querySelectorAll('.cha-content._lock') ).forEach((lock) => { // Check whether the chapter is inside or outside the `<div data-vtype="2">` element. if (lock.closest('[data-vtype="2"]') || lock.querySelector('[data-vtype="2"]')) { return; } // Remove this class so this chapter won't be processed the next time // `main` is called. lock.classList.remove('_lock'); // Remove the video. const v = lock.closest('.chapter_content').querySelector('.lock-video'); if (v) { v.remove(); } // Element with the chapter content. const contentElement = lock.querySelector('.cha-words'); contentElement.style.opacity = '0.1'; // Get the ID for the series ("book"). // // Some chapters have the `data-bid` property, but not all of them. // That's why it's better to just get this from the URL. const bid = window.location.href.split('/book/')[1].split('/')[0]; // Get the ID for the chapter. const { cid } = lock.querySelector('[data-cid]').dataset; // Both ID are required. if (!bid || !cid) { return; } return fetch( `https://www.webnovel.com/apiajax/chapter/GetChapterContentToken?bookId=${bid}&chapterId=${cid}&_csrfToken=${getCookie("_csrfToken")}` , {credentials: "include"}) .then(resp => resp.json()) .then(data => { return data.data.token }) .then(token => encodeURIComponent(token)) .then(token => new Promise((resolve) => { // The raw body of the chapter. // // It will be plain text, so we must manually build the HTML for it. let content = ''; // Try to get the content of the chapter, and fulfill the promise once // we have it. // // This function will retry until it succeeds. function tick() { if (token != '') { const url = `https://www.webnovel.com/apiajax/chapter/GetChapterContentByToken?token=${token}&_csrfToken=${getCookie("_csrfToken")}`; fetch(url, {credentials: "include"}) .then(resp => resp.json()) .then((data) => { content = data.data.content.trim(); if (content) { resolve(content); } else { setTimeout(tick, INTERVAL_TOKEN_CHECK); } }) .catch((err) => { console.error(err.stack); tick(); }); } } tick(); })) .then((content) => { // Build the HTML for the chapter content. // // For now we only split on line breaks and wrap each piece // with "<p></p>" tags. const chapterHtml = content .split('\n') .map(p => p.trim()) .filter(p => !!p) .map(p => `<p>${p}</p>`) .join(''); // Update the chapter content and turn opacity back to 100%. contentElement.innerHTML = chapterHtml; contentElement.style.opacity = '1'; }) .catch((err) => { console.error(err); }) }); } // Since Qidian may load new chapters without refreshing the page, we must // continuously check for new chapters in the page. setInterval(main, INTERVAL_CHAPTER_CHECK); Fixed the error that @ekojsalim had in his code. Premium chapters return a null token. Just needed to add an if statement in the loop to spot that. Make sure to drop a like on his post since he did like 99% of the work fixing the script.
Works on both GreaseMonkey and TamperMonkey on Firefox on two different machines. Thank you. Both @ekojsalim and @Jeebus scripts worked for me. Currently using the later.
Is it possible to make one that works on mobile? I use greasemonkey on the firefox browser. The old one worked just by adding m.webnovel to it but this one doesn't.
Preface: I don't know JS but I mixed available scripts to get a working mobile version. I used shadofx's script https://openuserjs.org/scripts/shadofx/webnovel.com_skip_video_ads_mobile/source but took the tick() function from @Jeebus with the mobile URLs (though desktop ones also seem to work). And thanks to @ekojsalim for working out we need to pass the _csrfToken as both a parameter and cookie to get this working again. Code: // ==UserScript== // @name webnovel.com skip video ads mobile // @namespace http://forum.novelupdates.com/ // @version 5 // @run-at document-end // @match http://m.webnovel.com/book/* // @match https://m.webnovel.com/book/* // @license MIT // ==/UserScript== //------------------------------------------------------------------------------------------------------------------- // Thanks go to shadofx for modifying the desktop version (v4) of this script // to work on mobile. This can be found at // https://openuserjs.org/scripts/shadofx/webnovel.com_skip_video_ads_mobile/source //------------------------------------------------------------------------------------------------------------------- // How frequently this script should check for new chapters. // // The amount is in milliseconds. const INTERVAL_CHAPTER_CHECK = 1000; // When a token is not ready yet, this is how much time we should wait // before trying again. // // The amount is in milliseconds. const INTERVAL_TOKEN_CHECK = 1000; function getCookie(name) { var value = "; " + document.cookie; var parts = value.split("; " + name + "="); if (parts.length == 2) return parts.pop().split(";").shift(); } /** * Check for new chapters and try to remove the adwall from them. */ function main() { Array.from( // Locked chapters. document.querySelectorAll('.j_chapterWrapper') ).filter((item)=>item.querySelector('.cha-txt').classList.contains('cha-txt-hide')) .forEach((lock) => { // Element with the chapter content. const contentElement = lock.querySelector('.cha-txt'); // Remove this class so this chapter won't be processed the next time // `main` is called. contentElement.classList.remove('cha-txt-hide'); // Remove the video. const v = lock.querySelector('.cha-watch-ad'); if(v) v.remove(); contentElement.style.opacity = '0.1'; // Get the ID for the series ("book"). // // Some chapters have the `data-bid` property, but not all of themw. // That's why it's better to just get this from the URL. const bid = window.location.href.split('/book/')[1].split('/')[0]; // Get the ID for the chapter. const cid = lock.dataset.chapterid; //Get the csrf token const csrf = getCookie("_csrfToken"); // alert(`https://m.webnovel.com/ajax/chapter/getChapterContentToken?bookId=${bid}&chapterId=${cid}&_csrfToken=${csrf}`); // Both ID are required. if (!bid || !cid || !csrf) { return; } return fetch( `https://m.webnovel.com/ajax/chapter/getChapterContentToken?bookId=${bid}&chapterId=${cid}&_csrfToken=${csrf}` , {credentials: "same-origin"}) .then(resp => resp.json()) .then(data => { return data.data.token }) .then(token => encodeURIComponent(token)) .then(token => new Promise((resolve) => { // The raw body of the chapter. // // It will be plain text, so we must manually build the HTML for it. let content = ''; // Try to get the content of the chapter, and fulfill the promise once // we have it. // // This function will retry until it succeeds. function tick() { if (token != '') { const url = `https://m.webnovel.com/ajax/chapter/getChapterContentByToken?token=${token}&_csrfToken=${csrf}`; fetch(url, {credentials: "same-origin"}) .then(resp => resp.json()) .then((data) => { content = data.data.content.trim(); if (content) { resolve(content); } else { setTimeout(tick, INTERVAL_TOKEN_CHECK); } }) .catch((err) => { console.error(err.stack); tick(); }); } } tick(); })) .then((content) => { // Build the HTML for the chapter content. // // For now we only split on line breaks and wrap each piece // with "<p></p>" tags. const chapterHtml = content .split('\n') .map(p => p.trim()) .filter(p => !!p) .map(p => `<p>${p}</p>`) .join(''); // Update the chapter content and turn opacity back to 100%. contentElement.innerHTML = chapterHtml; contentElement.style.opacity = '1'; }) .catch((err) => { console.error(err.stack); }); }); } // Since Qidian may load new chapters without refreshing the page, we must // continuously check for new chapters in the page. setInterval(main, INTERVAL_CHAPTER_CHECK);
If you're going to slap a MIT license on this, at least remove the public domain notice and the "no attribution" sentence. They're both literally contradicting the only clause the MIT license.
Thanks for telling me. I checked and it looks like shadofx added the MIT license, but didn't remove the public domain notice, and since that was the base of what I posted the contradiction remained. Should I remove the notice for shadofx?