Qidian AdBlock

Discussion in 'Tech Discussion' started by noisypixy, Aug 1, 2017.

  1. shuiko

    shuiko Well-Known Member

    Joined:
    Nov 8, 2015
    Messages:
    397
    Likes Received:
    265
    Reading List:
    Link
    hot
     
    Tembulon likes this.
  2. Auranyte

    Auranyte Well-Known Member

    Joined:
    Oct 22, 2015
    Messages:
    87
    Likes Received:
    96
    Reading List:
    Link
    Highly doubtful any ad-skip script will work without allowing those 2 domains.
     
  3. Miothan

    Miothan New Member

    Joined:
    Jun 5, 2018
    Messages:
    3
    Likes Received:
    0
    Reading List:
    Link
    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
     
  4. noisypixy

    noisypixy Sacatunn que pen, que summum que tun.

    Joined:
    Jun 25, 2016
    Messages:
    716
    Likes Received:
    950
    Reading List:
    Link
    Hey, thanks for fixing it.

    Feel free to take ownership of the code if you want.
     
    Tembulon likes this.
  5. Jeebus

    Jeebus Well-Known Member

    Joined:
    Jun 20, 2017
    Messages:
    904
    Likes Received:
    780
    Reading List:
    Link
    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.
     
    Last edited: Jun 5, 2018
  6. Miothan

    Miothan New Member

    Joined:
    Jun 5, 2018
    Messages:
    3
    Likes Received:
    0
    Reading List:
    Link
    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
     
  7. noisypixy

    noisypixy Sacatunn que pen, que summum que tun.

    Joined:
    Jun 25, 2016
    Messages:
    716
    Likes Received:
    950
    Reading List:
    Link
    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.
     
  8. starfyre7

    starfyre7 Active Member

    Joined:
    Dec 26, 2015
    Messages:
    26
    Likes Received:
    12
    Reading List:
    Link
    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.
     
  9. jace1884

    jace1884 Active Member

    Joined:
    Jun 25, 2017
    Messages:
    4
    Likes Received:
    1
    Reading List:
    Link
    Thanks for updating!
     
  10. Atros

    Atros Well-Known Member

    Joined:
    Dec 9, 2015
    Messages:
    757
    Likes Received:
    1,073
    Reading List:
    Link
    Thanks a bunch for this! Much better now.
     
  11. Jeebus

    Jeebus Well-Known Member

    Joined:
    Jun 20, 2017
    Messages:
    904
    Likes Received:
    780
    Reading List:
    Link
    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.
     
    Last edited: Jun 6, 2018
  12. Pertiest

    Pertiest Active Member

    Joined:
    Dec 7, 2016
    Messages:
    11
    Likes Received:
    5
    Reading List:
    Link
    Tx for the effort, but it still doesn't work for me :S
     
    Boon likes this.
  13. rdawv

    rdawv The Ancient of Lore

    Joined:
    Jan 18, 2016
    Messages:
    2,137
    Likes Received:
    7,349
    Reading List:
    Link
    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.
     
  14. Pertiest

    Pertiest Active Member

    Joined:
    Dec 7, 2016
    Messages:
    11
    Likes Received:
    5
    Reading List:
    Link
    Ok, with tampermonkey and without one of my adblockers (ultimate BTW) it works :)
     
    Pandamonic likes this.
  15. Boon

    Boon Well-Known Member

    Joined:
    Jun 3, 2016
    Messages:
    74
    Likes Received:
    22
    Reading List:
    Link
    Doesn't seem to work on waterfox 56.2.0 (most recent version).
     
  16. EcoJakk

    EcoJakk Well-Known Member

    Joined:
    Jan 1, 2016
    Messages:
    38
    Likes Received:
    22
    Reading List:
    Link
    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.
     
  17. Wishez

    Wishez Active Member

    Joined:
    Sep 1, 2017
    Messages:
    2
    Likes Received:
    0
    Reading List:
    Link
    Thanks for updating it.
     
  18. Rheklr

    Rheklr Active Member

    Joined:
    Dec 18, 2016
    Messages:
    10
    Likes Received:
    3
    Reading List:
    Link
    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);
    
    
    
    
     
    Last edited: Jun 9, 2018
    EcoJakk, Wishez and starfyre7 like this.
  19. noisypixy

    noisypixy Sacatunn que pen, que summum que tun.

    Joined:
    Jun 25, 2016
    Messages:
    716
    Likes Received:
    950
    Reading List:
    Link
    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.
     
    Rheklr and mrttao like this.
  20. Rheklr

    Rheklr Active Member

    Joined:
    Dec 18, 2016
    Messages:
    10
    Likes Received:
    3
    Reading List:
    Link
    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?