/*
 * 기본 작동방식 설명:
 * fetch로 디시 로스티 미디어 마이너 갤러리에 있는 글들 중 m번부터 n번까지의 글들을 반복문 돌려 내용을 긁어온다.
 * 너무 많은 페이지를 fetch하면 디시에선 자동적으로 몇십분동안 차단시키므로 이 코드에선 일단 m=38005, n=38008-1 &no=38005가 붙는것부터 38008까지 총 4개만 털 것이다.
 * fetch는 작동방식상 순서대로 전의 코드가 끝나면 다음줄이 작동되는게 아니라서, await을 쓸것이다. 당연히 내용물이 들어갈 함수도 async 함수가 될것이다.
 * 반복문에서 저 i(변수명으로 다른 문자 써도 되지만 보통 이런 변수명은 i를 많이 쓰지 않나?)를 갖고 각 로미갤 게시물 주소를 따는 함수가 기본적으로 loopfunc이라는 함수고, 매개변수로 loopfuncparam이란걸 받아와서 이게 함수면 이걸 대신 사용한다.
 * 주소를 땄으면 이제 fetch로 내용을 긁어올것이다.
 * 삭제된 게시물의 경우 정상적으로 페이지 내용이 안들어와서 오류가 일어나지만, 이걸 또 오류 발생을 막으려고 Promise.catch()나 try catch 등 별의 별 방법을 다 썼으나 내 실력의 한계로 별지랄을 해도 오류가 터져서 그냥 무시하고 지나가게 함.
 * 쨌든 이렇게 턴 각 게시물 내용을 doingfuncparam 매개변수로 받은 함수를 쓰거나, 그 매개변수가 없거나 함수가 아닐시 정의된 doingfunc로 그냥 써서 원하는 형태로 변형하고, 처리한뒤, rtv라는 변수명의 배열에 집어넣고 반환한다.
 * 여기서 털고자 하는것은 털고자 한 로미갤 게시물에 나온 모든 암호화된 url들(암호화 풀어서)이다. 말하자면 복잡한데...
 * 로스트 미디어 마이너 갤러리는 게시물 올릴때 발굴한 로스트 미디어를 올릴때 주소를 그대로 쓰면 봇이 지워버릴수 있으므로 규정상 반드시 url을 base64로 인코딩한뒤 올리게 되어있다.
 * 그래서 atob을 쓴다.
 * doingfuncparam 매개변수로 받을, 내용물을 처리할 함수는(searchAll을 실제로 호출할때 콜백함수와 같이 매개변수로 주는 함수로 썼다.)
 * 1. 콜백함수의 매개변수로 게시물 내용을 받는다.
 * 2. 거기에서 write_div라는 클래스명의 요소(모든 디시갤에서 게시물 본 내용이 든 태그이다.)를 통째로 가져온다.
 * 처음엔 전 html 문서를 통째로 iframe 안에 욱여넣고 프레임.contentDocument.body.querySelector('.write_div)로 쓰려고 했지만(참고로 write_div라는 클래스명을 가진 태그는 디시 시스템상 하나밖에 없어서 querySelectorAll()[n] 이따위짓거리를 할 필요가 없다),
 * 그렇게 하면 전 문서를 통째로 갖다쓰기 때문에 쓸데없는 다른것까지 로딩되어 엄청 느리고, 무겁게 된다.
 * 그래서 정규표현식으로 div.write_div 부분의 html코드를 그대로 match시켜 가져오게 했다.
 * 3. iframe을 하나 생성한다.
 * 4. srcdoc으로 html구조대로 문서를 넣고, 아까 구한 .write_div를 body 안에 넣는다.
 * 5. 만든 iframe을 실제로 html 문서 안에 넣는다. 그리고 드디어 만들어진 게시물이 있는 태그를 querySelector로 구한다.
 * 5. 이건 해보니까 작동이 안돼서 srcdoc에 .write_div를 다시 넣은 뒤 querySelector로 다시 구한다.
 * 6. 이것도 작동이 안돼서 이제 어차피 html내용이 있으니까 프레임.contentDocument.body.innerHTML을 바꿔서 .write_div를 넣고, 다시 querySelector로 구한다.
 * 7. 이제 얻은 .write_div 안에 있을 p태그를 전부 털어서 그들의 innerHTML을 공백문자단위로 분리한뒤(여기까지는 작동이 되었다), 각각 atob을 써서 base64로부터 변환한다. 이때 base64는 latin1 영역 안의 128 문자만 쓰므로 atob,btoa도 그 밖의 문자를 쓰면 오류가 난다.
 * 따라서 해당 128가지 문자가 아닌 모든 문자를 제거하는 함수를 즉석에서 하나 만들어 쓴다.
 * 8. 이걸로 base64 디코딩할수 있게 해놓으면, 이제 atob으로 전부 변환하고, 이 중 원래 정상적인 url 주소였던것은 디코딩되면서 다시 http,https로 시작하는것으로 바뀔테니 그러한것만 골라서(몇몇은 startsWith가 아닌 includes로 구분했는데, 이는 그냥 넘어가자.) 리턴할 배열에 넣는다.
 * 9. 이걸 다시 최종적으로 searchAll이 배열에 집어넣고, 이걸 다시 최종적으로 모든것이 저장될 myurlarray 배열에 집어넣는다.
 * -해당 부분 작동 설명 끝-
 * 이러면 배열이 들어간 배열이 들어간 배열...이 되므로 3차원배열일테니 flat을 써서 평탄화해준다.
 *
 * 디버깅하는 과정에서 보니 atob을 쓰기 위해 latin1에 속하지 않는 문자를 제거하는 함수 직전까지는 작동이 되는데 그 함수를 쓰니 처리할 문자열의 모든게 사라졌다.
 * 따라서 latin1의 128가지 문자가 아닌것을 제거할 함수에서 문제가 발생한듯하다.
*/
async function falseFunc() {
    return false;
}
async function fetchfunc(url, opts) {
    try {
        return await window.fetch(url, opts);
    } catch (error) {
        /* var rtv = await falseFunc();
        rtv.text=function(){
            return "";
        } */
        return await window.fetch("/", opts);
    }
    //return await window.fetch(url, opts).then((data) => { return data; }).catch((reason_of_err) => { if (reason_of_err) { return { text: function () { console.log(reason_of_err); return ''; } };} });
}
/**
 * @callback mycbfunc
 * @param {string} text
*/
/**
 * @param {string} urlparam
 * @param {number} fromparam
 * @param {number} toparam
 * @param {Function} loopfuncparam
 * @param {mycbfunc} doingfuncparam
 * @returns {Array}
 */
var searchAll = async (urlparam, fromparam, toparam, loopfuncparam, doingfuncparam) => {
    var rtv = [];
    var url = "";
    if (typeof urlparam !== 'string' && !(urlparam instanceof String)) {
        url = new String(urlparam);
    } else {
        url = urlparam;
    }
    var from = 0;
    if (!isNaN(Number(fromparam))) {
        from = Number(fromparam);
    }
    var to = 1000;
    if (!isNaN(Number(toparam))) {
        to = Number(toparam);
    }
    /**
     *
     * @param {string} urltoreplace
     * @param {number} curridx
     * @returns {string}
     */
    var loopfunc = (urltoreplace, curridx) => {
        var rtv0 = "";
        rtv0 = typeof urltoreplace === 'string' ? urltoreplace : new String(urltoreplace);
        if (isNaN(Number(curridx))) {
            return false;
        }
        if (typeof curridx !== 'number') {
            curridx = Number(curridx);
        }
        //dcinside
        rtv0 += rtv0.includes("?") ? `&no=${curridx}&page=1` : `?no=${curridx}&page=1`;
        return rtv0;
    };
    if (typeof loopfuncparam === 'function') {
        loopfunc = loopfuncparam;
    }
    var doingfunc = (textparam) => {
        return textparam;
    };
    if (typeof doingfuncparam === 'function') {
        doingfunc = doingfuncparam;
    }
    for (var i = from; i < to; i++) {
        var valtopush_pr = await window.fetch(loopfunc(url, i), { mode: 'no-cors', method: 'get' });
        var valtopush = await valtopush_pr.text();
        await (async () => { rtv.push(doingfunc(valtopush)); })();
    }
    await (async () => { console.log('end') })();
    return rtv;
}
var myurlarray = [];
(async () => {
    var myarr = await searchAll("/mgallery/board/view/?id=lostmedia", 38005, 38009, (urltoreplace, curridx) => {
        var rtv0 = "";
        rtv0 = typeof urltoreplace === 'string' ? urltoreplace : new String(urltoreplace);
        if (isNaN(Number(curridx))) {
            return false;
        }
        if (typeof curridx !== 'number') {
            curridx = Number(curridx);
        }
        //dcinside
        rtv0 += rtv0.includes("?") ? `&no=${curridx}&page=1` : `?no=${curridx}&page=1`;
        return rtv0;
    }, (textparam) => {
        var mynewframe = document.createElement("iframe");
        var matches = textparam.replaceAll(/\s+/gmi, ' ').replaceAll('\n', '').replaceAll('\r', '').replaceAll('\x3C', '<').match(/<div class="write_div"(.*?)>(.*?)<\/div>/mi);
        //matches!==null?console.log(matches[0]):{};
        mynewframe.srcdoc = `<!DOCTYPE html><html lang="en"><head><meta charset="UTF-8"><title>Document</title></head><body>${matches !== null ? new String(matches[0]) : ''}</body></html>`;
        var myframe = document.body.appendChild(mynewframe);
        var write_div = myframe.contentDocument.body.querySelector('.write_div');
        if (write_div === null) {
            myframe.srcdoc = `<!DOCTYPE html><html lang="en"><head><meta charset="UTF-8"><title>Document</title></head><body>${matches !== null ? new String(matches[0]) : ''}</body></html>`;
            write_div = myframe.contentDocument.body.querySelector('.write_div');
        }
        if (write_div === null) {
            myframe.contentDocument.body.innerHTML = matches !== null ? new String(matches[0]) : '';
            write_div = myframe.contentDocument.body.querySelector('.write_div');
        }
        //console.log(myframe.contentDocument.body.innerHTML);
        var paragraphs = write_div?.querySelectorAll('p');
        var rtarr = [];
        paragraphs?.forEach((el, idx, par) => {
            el.innerText.split(' ').forEach((val0, idx0, arr0) => {
                //console.log(atobval0);
                /**
                 *
                 * @param {string} str
                 */
                function latin1(str) {
                    //이 함수는 latin1 영역 밖의 문자는 싸그리 없애버린다. 그런데 딱 여기부터 작동이 안돼...
                    var rtv = '';
                    for (var i = 0; i < str.length; i++) {
                        if (str.charCodeAt(i) >= 0x80 && str.charCodeAt(i) <= 0xff) {
                            rtv += str[i];
                        } else {
                            rtv += '';
                        }
                    }
                }
                //latin1함수를 굳이 쓴 이유는 atob,btoa 함수가 latin1영역 안의 문자만 처리할수 있기 때문이다. base64인코딩이 원래 그러니까.
                var atobval0 = atob(latin1(val0));
                //atob는 base64를 디코딩하는, 기본적으로 Window.atob로 깔려있는 내장함수이다.
                //console.log(val0.split('').map((val1, idx1, arr1) => { if (val1.charCodeAt(0) > 0x00ff || val1.charCodeAt(0) < 0x0080) { return ''; }; return val1; }).join(''));
                console.log(latin1(val0));
                if ((atobval0.includes("https://") || atobval0.includes("http://") || atobval0.startsWith("www.") || atobval0.startsWith("//") || atobval0.startsWith("/") || atobval0.startsWith("./") || atobval0.startsWith("../"))) {
                    rtarr.push(atobval0);
                }
            });
        });
        myframe.remove();
        return rtarr;
    });
    await (async () => {
        myurlarray.push(myarr);
        myurlarray = myurlarray.flat(3);
        console.log(myurlarray);
    })();
})();