Local Vk Downloader

Get Vk raw link without external service.

目前为 2020-04-25 提交的版本。查看 最新版本

// ==UserScript==
// @name         Local Vk Downloader
// @namespace    vkDownloadAuto
// @version      2.0.0
// @description  Get Vk raw link without external service.
// @match        https://m.vk.com/mail*
// ==/UserScript==
var peer = null;

function vkPlainGet(url, callback) {
    return ajax.plainpost(
        url,
        { _ajax: 1 },
        (function (e) {
            callback(e);
        }),
        (function () {
            callback(null)
        }),
        !0
    );
}

function vkGet(url, callback) {
    return vkPlainGet(url, function (e) {
        if (!e) {
            callback(null);
            return;
        }
        callback(parseResponse(e));
    });
}

function parseResponse(response) {
    if (typeof response == "string" && response.indexOf("<!DOCTYPE html>") != -1) {
        return parseDialogPage(response);
    }
    return parseJSON(response);
}

function parseDialogPage(htmlString) {
    var html = parseDocumentToHtml(htmlString);
    var itemsContainer = html.querySelector(".items");
    var items = itemsContainer.querySelector(".photos_page");
    var searchMore = itemsContainer.querySelector(".show_more_wrap");
    return {
        data: [items.outerHTML, searchMore ? searchMore.outerHTML : ""]
    }
}

function removeCounters(documentString) {
    var countersIdx = documentString.indexOf('_cntrs');
    var tail = documentString.substring(countersIdx);
    tail = tail.replace(/<img/g, "<div").replace(/<\/img/, "</div");
    return documentString.substring(0, countersIdx) + tail;
}

function removeImages(documentString) {
    return documentString.replace(/<img/g, "<div").replace(/<\/img/, "</div");
}

function parseDocumentToHtml(documentString) {
    var htmlElement = document.createElement('html');
    if (documentString.indexOf("<body") != -1) {
        documentString = documentString.substring(documentString.indexOf("<body"), documentString.indexOf("</body>") + 7);
    }
    htmlElement.innerHTML = removeCounters(documentString);
    return htmlElement;
}

function getMore(href) {
    vkGet(href, function (data) {
        receiveMore(data);
    });
}

function getSearchMoreHref(data) {
    if (!data || !data[1]) {
        return;
    }
    var htmlElement = parseDocumentToHtml(data[1]);
    if (!htmlElement) {
        return;
    }
    var showMore = htmlElement.querySelector(".show_more");
    if (!showMore) {
        return;
    }
    var href = showMore.href;
    if (!href) {
        return null;
    }
    return href;
}

function checkSearch() {
    var newPeer = getPeer();
    if (newPeer && newPeer != peer) {
        getAllMedia(newPeer);
    }
}

function listenSearch() {
    window.setInterval(checkSearch, 500);
}

function getPeer() {
    var hash = window.location.search;
    var idx = hash.indexOf("peer");
    if (idx == -1) {
        return null;
    }
    var end = hash.indexOf("&", idx);
    if (end == -1) {
        end = hash.length;
    }
    return hash.substring(idx + 5, end);
}

function getMediaUrl(newPeer, section) {
    var mediaUrlBase = "/mail?act=show_medias&peer=";
    var sectionUrl = "&section=";
    return mediaUrlBase + newPeer + sectionUrl + section;
}

function recursiveGetVideos(searchMoreLink, data, finishState) {
    if (!searchMoreLink) {
        finishState.videos = true;
        finishSegment(data, "videos", finishState);
        return;
    }
    vkGet(searchMoreLink, function (result) {
        if (!result || !result.data) {
            finishSegment(data, "videos", finishState);
            return;
        }
        getVideosLinks(result.data, function (items) {
            data.videos = data.videos.concat(items);
            var searchMoreLink = getSearchMoreHref(result.data);
            recursiveGetVideos(searchMoreLink, data, finishState);
        })
    });
}

function getVideosLinks(data, callback) {
    var htmlElement = parseDocumentToHtml(data[0]);
    var items = htmlElement.querySelectorAll(".video_item");
    if (!items || !items.length) {
        return;
    }
    var videos = [];
    var fetchLinksCount = items.length;
    var reduceFetched = function () {
        --fetchLinksCount;
        if (fetchLinksCount == 0) {
            callback(videos);
        }
    }
    for (var i = 0; i < items.length; ++i) {
        var item = items[i];
        var itemData = {};
        var previewImg = item.querySelector(".th_img");
        if (previewImg && previewImg.attributes.getNamedItem("src")) {
            itemData.preview = previewImg.attributes.getNamedItem("src").value;
        }
        var videoLength = item.querySelector(".thumb_label");
        if (videoLength) {
            itemData.length = videoLength.innerText;
        }
        var videoTitle = item.querySelector(".vi_title_text");
        if (videoTitle) {
            itemData.title = videoTitle.innerText;
            if(videoTitle.indexOf("Без названия") == -1){
                reduceFetched();
                continue;
            }
        }
        var videoHref = item.querySelector(".video_href");
        if (!videoHref) {
            reduceFetched();
            continue;
        }
        itemData.href = videoHref.href;
        var callbackFunction = (function (itemData, result) {
            var htmlElement = parseDocumentToHtml(result);
            var sources = htmlElement.querySelectorAll("source[type='video/mp4']");
            if (!sources || !sources.length) {
                reduceFetched();
                return;
            }
            itemData.sources = [];
            for (var i = 0; i < sources.length; ++i) {
                itemData.sources.push(sources[i].src);
            }
            videos.push(itemData);
            reduceFetched();
        }).bind(this, itemData);
        vkPlainGet(itemData.href, callbackFunction);
    }
}

function getVideos(newPeer, data, finishState) {
    vkGet(getMediaUrl(newPeer, "video"), function (result) {
        if (!result || !result.data) {
            finishSegment(data, "videos", finishState);
            return;
        }
        getVideosLinks(result.data, function (items) {
            data.videos = data.videos.concat(items);
            var searchMoreLink = getSearchMoreHref(result.data);
            recursiveGetVideos(searchMoreLink, data, finishState);
        });
    });
}

function getPhotosLinks(data, callback) {
    var htmlElement = parseDocumentToHtml(removeImages(data[0]));
    var items = htmlElement.querySelectorAll("div[data-src_big]");
    if (!items || !items.length) {
        return;
    }
    var photos = [];
    for (var i = 0; i < items.length; ++i) {
        var item = items[i];
        var src = item.attributes.getNamedItem("data-src_big");
        if (!src) {
            continue;
        }
        var breakIdx = src.indexOf("|");
        if (breakIdx != -1) {
            src = src.substring(0, breakIdx);
        }
        photos.push(src);
    }
    callback(photos);
}

function recursiveGetPhotos(searchMoreLink, data, finishState) {
    if (!searchMoreLink) {
        finishSegment(data, "photos", finishState);
        return;
    }
    vkGet(searchMoreLink, function (result) {
        if (!result || !result.data) {
            finishSegment(data, "photos", finishState);
            return;
        }
        getPhotosLinks(result.data, function (items) {
            data.photos = data.photos.concat(items);
            var searchMoreLink = getSearchMoreHref(result.data);
            recursiveGetPhotos(searchMoreLink, data, finishState);
        })
    });
}

function getPhotos(newPeer, data, finishState) {
    vkGet(getMediaUrl(newPeer, "photo"), function (result) {
        if (!result || !result.data) {
            finishSegment(data, "photos", finishState);
            return;
        }
        getPhotosLinks(result.data, function (items) {
            data.photos = data.photos.concat(items);
            var searchMoreLink = getSearchMoreHref(result.data);
            recursiveGetPhotos(searchMoreLink, data, finishState);
        });
    });
}

function getDocs(newPeer, data, finishState) {
    finishSegment(data, "docs", finishState)
}

function getAllMedia(newPeer) {
    console.log("***********************************ALL_MEDIA************************************")
    peer = newPeer;
    var data = {
        videos: [],
        photos: [],
        docs: []
    }
    var finishState = {
        videos: false,
        photos: false,
        docs: false
    }
    getVideos(newPeer, data, finishState);
    getPhotos(newPeer, data, finishState);
    getDocs(newPeer, data, finishState);
}

function start() {
    var newPeer = getPeer();
    if (newPeer != null) {
        getAllMedia(newPeer);
    }
}

function finishSegment(data, segment, finishState) {
    console.log(segment + ":", data[segment]);
    finishState[segment] = true;
    if (finishState.videos && finishState.photos && finishState.docs) {
        finish(data);
    }
}

function finish(data) {
    console.log(JSON.stringify(data));
    console.log("************************************FINISH**************************************")
}

listenSearch();
start();
长期地址
遇到问题?请前往 GitHub 提 Issues,或加Q群1031348184

赞助商

Fishcpy

广告

Rainyun

注册一下就行

Rainyun

一年攒够 12 元