CoolFace
Apppublic

Kfunga/mirror

sourceHugging Faceupdated 2y agoView on Hugging Face
0likes
wserver.py910 linesDownload Raw Back to web
1from aria2p import (2    API as ariaAPI,3    Client as ariaClient4)5from flask import (6    Flask,7    request8)9from logging import (10    getLogger,11    FileHandler,12    StreamHandler,13    INFO,14    basicConfig15)16from qbittorrentapi import (17    NotFound404Error,18    Client as QbClient19)20from time import sleep21from sabnzbdapi import SabnzbdClient22from asyncio import (23    get_running_loop,24    new_event_loop,25    set_event_loop26)27 28from web.nodes import make_tree29 30app = Flask(__name__)31 32try:33    web_loop = get_running_loop()34except RuntimeError:35    web_loop = new_event_loop()36    set_event_loop(web_loop)37 38qbittorrent_client = QbClient(39    host="localhost",40    port=8090,41    VERIFY_WEBUI_CERTIFICATE=False,42    REQUESTS_ARGS={"timeout": (43        30,44        6045    )},46    HTTPADAPTER_ARGS={47        "pool_maxsize": 200,48        "pool_block": True49    },50)51 52sabnzbd_client = SabnzbdClient(53    host="http://localhost",54    api_key="zee",55    port="8070",56)57 58aria2 = ariaAPI(59    ariaClient(60        host="http://localhost",61        port=6800,62        secret=""63    )64)65 66basicConfig(67    format="%(levelname)s | From %(name)s -> %(module)s line no: %(lineno)d | %(message)s",68    handlers=[69        FileHandler("Zee_Logs.txt"),70        StreamHandler()71    ],72    level=INFO,73)74 75LOGGER = getLogger(__name__)76 77page = """78<html lang="en">79  <head>80    <meta charset="UTF-8" />81    <meta http-equiv="X-UA-Compatible" content="IE=edge" />82    <meta name="viewport" content="width=device-width, initial-scale=1.0" />83    <title>Torrent File Selector</title>84    <link rel="icon" href="https://telegra.ph/file/43af672249c94053356c7.jpg" type="image/jpg">85    <script86      src="https://code.jquery.com/jquery-3.5.1.slim.min.js"87      integrity="sha256-4+XzXVhsDmqanXGHaHvgh1gMQKX40OUvDEBTu8JcmNs="88      crossorigin="anonymous"89    ></script>90    <link rel="preconnect" href="https://fonts.googleapis.com" />91    <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />92    <link93      href="https://fonts.googleapis.com/css2?family=Ubuntu:ital,wght@0,300;0,400;0,500;0,700;1,300;1,400;1,500;1,700&display=swap"94      rel="stylesheet"95    />96    <link97      rel="stylesheet"98      href="https://pro.fontawesome.com/releases/v5.10.0/css/all.css"99      integrity="sha384-AYmEC3Yw5cVb3ZcuHtOA93w35dYTsvhLPVnYs9eStHfGJvOvKxVfELGroGkvsg+p"100      crossorigin="anonymous"101    />102<style>103 104*{105    margin: 0;106    padding: 0;107    box-sizing: border-box;108    font-family: "Ubuntu", sans-serif;109    list-style: none;110    text-decoration: none;111    outline: none !important;112    color: white;113}114 115body{116    background-color: #0D1117;117}118 119header{120    margin: 3vh 1vw;121    padding: 0.5rem 1rem 0.5rem 1rem;122    display: flex;123    align-items: center;124    justify-content: space-between;125    border-bottom: #161B22;126    border-radius: 30px;127    background-color: #161B22;128    border: 2px solid rgba(255, 255, 255, 0.11);129}130 131header:hover, section:hover{132    box-shadow: 0px 0px 15px black;133}134 135.brand{136    display: flex;137    align-items: center;138}139 140img{141    width: 2.5rem;142    height: 2.5rem;143    border: 2px solid black;144    border-radius: 50%;145}146 147.name{148    margin-left: 1vw;149    font-size: 1.5rem;150}151 152.intro{153    text-align: center;154    margin-bottom: 2vh;155    margin-top: 1vh;156}157 158.social a{159    font-size: 1.5rem;160    padding-left: 1vw;161}162 163.social a:hover, .brand:hover{164    filter: invert(0.3);165}166 167section{168    margin: 0vh 1vw;169    margin-bottom: 10vh;170    padding: 1vh 3vw;171    display: flex;172    flex-direction: column;173    border: 2px solid rgba(255, 255, 255, 0.11);174    border-radius: 20px;175    background-color: #161B22 ;176}177 178li:nth-child(1){179    padding: 1rem 1rem 0.5rem 1rem;180}181 182li:nth-child(n+1){183    padding-left: 1rem;184}185 186li label{187    padding-left: 0.5rem;188}189 190li{191    padding-bottom: 0.5rem;192}193 194span{195    margin-right: 0.5rem;196    cursor: pointer;197    user-select: none;198    transition: transform 200ms ease-out;199}200 201span.active{202    transform: rotate(90deg);203    -ms-transform: rotate(90deg);	 /* for IE  */204    -webkit-transform: rotate(90deg);/* for browsers supporting webkit (such as chrome, firefox, safari etc.). */205    display: inline-block;206}207 208ul{209    margin: 1vh 1vw 1vh 1vw;210    padding: 0 0 0.5rem 0;211    border: 2px solid black;212    border-radius: 20px;213    background-color: #1c2129;214    overflow: hidden;215}216 217input[type="checkbox"]{218    cursor: pointer;219    user-select: none;220}221 222input[type="submit"] {223    border-radius: 20px;224    margin: 2vh auto 1vh auto;225    width: 50%;226    display: block;227    height: 5.5vh;228    border: 2px solid rgba(255, 255, 255, 0.11);229    background-color: #0D1117;230    font-size: 16px;231    font-weight: 500;232}233 234input[type="submit"]:hover, input[type="submit"]:focus{235    background-color: rgba(255, 255, 255, 0.068);236    cursor: pointer;237}238 239@media (max-width: 768px){240    input[type="submit"]{241        width: 100%;242    }243}244 245#treeview .parent {246    position: relative;247}248 249#treeview .parent > ul {250    display: none;251}252 253#sticks {254  margin: 0vh 1vw;255  margin-bottom: 1vh;256  padding: 1vh 3vw;257  display: flex;258  flex-direction: column;259  border: 2px solid rgba(255, 255, 255, 0.11);260  border-radius: 20px;261  background-color: #161b22;262  align-items: center;263}264 265#sticks.stick {266  position: sticky;267  top: 0;268  z-index: 10000;269}270</style>271<script>272function s_validate() {273    if ($("input[name^='filenode_']:checked").length == 0) {274        alert("Select one file at least!");275        return false;276        }277    }278</script>279</head>280<body>281  <!--© Designed and coded by @bipuldey19-Telegram-->282    <header>283      <div class="brand">284        <img285          src="https://telegra.ph/file/43af672249c94053356c7.jpg"286          alt="logo"287        />288        <a href="https://t.me/anas_tayyar">289          <h2 class="name">Bittorrent Selection</h2>290        </a>291      </div>292      <div class="social">293        <a href="https://www.github.com/anasty17/mirror-leech-telegram-bot"><i class="fab fa-github"></i></a>294        <a href="https://t.me/anas_tayyar"><i class="fab fa-telegram"></i></a>295      </div>296    </header>297    <div id="sticks">298        <h4>Selected files: <b id="checked_files">0</b> of <b id="total_files">0</b></h4>299        <h4>Selected files size: <b id="checked_size">0</b> of <b id="total_size">0</b></h4>300    </div>301      <section>302      <form action="{form_url}" onsubmit="return s_validate()" method="POST">303       {My_content}304       <input type="submit" name="Select these files ;)">305      </form>306    </section>307 308    <script>309      $(document).ready(function () {310        docready();311        var tags = $("li").filter(function () {312          return $(this).find("ul").length !== 0;313        });314 315        tags.each(function () {316          $(this).addClass("parent");317        });318 319        $("body").find("ul:first-child").attr("id", "treeview");320        $(".parent").prepend("<span>▶</span>");321 322        $("span").click(function (e) {323          e.stopPropagation();324          e.stopImmediatePropagation();325          $(this).parent( ".parent" ).find(">ul").toggle("slow");326          if ($(this).hasClass("active")) $(this).removeClass("active");327          else $(this).addClass("active");328        });329      });330 331      if(document.getElementsByTagName("ul").length >= 10){332        var labels = document.querySelectorAll("label");333        //Shorting the file/folder names334        labels.forEach(function (label) {335            if (label.innerText.toString().split(" ").length >= 9) {336                let FirstPart = label.innerText337                    .toString()338                    .split(" ")339                    .slice(0, 5)340                    .join(" ");341                let SecondPart = label.innerText342                    .toString()343                    .split(" ")344                    .splice(-5)345                    .join(" ");346                label.innerText = `${FirstPart}... ${SecondPart}`;347            }348            if (label.innerText.toString().split(".").length >= 9) {349                let first = label.innerText350                    .toString()351                    .split(".")352                    .slice(0, 5)353                    .join(" ");354                let second = label.innerText355                    .toString()356                    .split(".")357                    .splice(-5)358                    .join(".");359                label.innerText = `${first}... ${second}`;360            }361        });362    }363    </script>364 365<script>366$('input[type="checkbox"]').change(function(e) {367  var checked = $(this).prop("checked"),368      container = $(this).parent(),369      siblings = container.siblings();370/*371  $(this).attr('value', function(index, attr){372     return attr == 'yes' ? 'noo' : 'yes';373  });374*/375  container.find('input[type="checkbox"]').prop({376    indeterminate: false,377    checked: checked378  });379  function checkSiblings(el) {380    var parent = el.parent().parent(),381        all = true;382    el.siblings().each(function() {383      let returnValue = all = ($(this).children('input[type="checkbox"]').prop("checked") === checked);384      return returnValue;385    });386 387    if (all && checked) {388      parent.children('input[type="checkbox"]').prop({389        indeterminate: false,390        checked: checked391      });392      checkSiblings(parent);393    } else if (all && !checked) {394      parent.children('input[type="checkbox"]').prop("checked", checked);395      parent.children('input[type="checkbox"]').prop("indeterminate", (parent.find('input[type="checkbox"]:checked').length > 0));396      checkSiblings(parent);397    } else {398      el.parents("li").children('input[type="checkbox"]').prop({399        indeterminate: true,400        checked: false401      });402    }403  }404  checkSiblings(container);405});406</script>407<script>408    function docready () {409        $("label[for^='filenode_']").css("cursor", "pointer");410        $("label[for^='filenode_']").click(function () {411            $(this).prev().click();412        });413        checked_size();414        checkingfiles();415        var total_files = $("label[for^='filenode_']").length;416        $("#total_files").text(total_files);417        var total_size = 0;418        var ffilenode = $("label[for^='filenode_']");419        ffilenode.each(function () {420            var size = parseFloat($(this).data("size"));421            total_size += size;422            $(this).append(" - " + humanFileSize(size));423        });424        $("#total_size").text(humanFileSize(total_size));425    };426    function checked_size() {427        var checked_size = 0;428        var checkedboxes = $("input[name^='filenode_']:checked");429        checkedboxes.each(function () {430            var size = parseFloat($(this).data("size"));431            checked_size += size;432        });433        $("#checked_size").text(humanFileSize(checked_size));434    }435    function checkingfiles() {436        var checked_files = $("input[name^='filenode_']:checked").length;437        $("#checked_files").text(checked_files);438    }439    $("input[name^='foldernode_']").change(function () {440        checkingfiles();441        checked_size();442    });443    $("input[name^='filenode_']").change(function () {444        checkingfiles();445        checked_size();446    });447    function humanFileSize(size) {448        var i = -1;449        var byteUnits = [' kB', ' MB', ' GB', ' TB', 'PB', 'EB', 'ZB', 'YB'];450        do {451            size = size / 1024;452            i++;453        } while (size > 1024);454        return Math.max(size, 0).toFixed(1) + byteUnits[i];455    }456    function sticking() {457        var window_top = $(window).scrollTop();458        var div_top = $('.brand').offset().top;459        if (window_top > div_top) {460            $('#sticks').addClass('stick');461        } else {462            $('#sticks').removeClass('stick');463        }464    }465    $(function () {466        $(window).scroll(sticking);467        sticking();468    });469</script>470</body>471</html>472"""473 474code_page = """475<html lang="en">476  <head>477    <meta charset="UTF-8" />478    <meta http-equiv="X-UA-Compatible" content="IE=edge" />479    <meta name="viewport" content="width=device-width, initial-scale=1.0" />480    <title>Torrent Code Checker</title>481    <link rel="icon" href="https://telegra.ph/file/43af672249c94053356c7.jpg" type="image/jpg">482    <link rel="preconnect" href="https://fonts.googleapis.com" />483    <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />484    <link485      href="https://fonts.googleapis.com/css2?family=Ubuntu:ital,wght@0,300;0,400;0,500;0,700;1,300;1,400;1,500;1,700&display=swap"486      rel="stylesheet"487    />488    <link489      rel="stylesheet"490      href="https://pro.fontawesome.com/releases/v5.10.0/css/all.css"491      integrity="sha384-AYmEC3Yw5cVb3ZcuHtOA93w35dYTsvhLPVnYs9eStHfGJvOvKxVfELGroGkvsg+p"492      crossorigin="anonymous"493    />494    <style>495     *{496    margin: 0;497    padding: 0;498    box-sizing: border-box;499    font-family: "Ubuntu", sans-serif;500    list-style: none;501    text-decoration: none;502    color: white;503}504 505body{506    background-color: #0D1117;507}508 509header{510    margin: 3vh 1vw;511    padding: 0.5rem 1rem 0.5rem 1rem;512    display: flex;513    align-items: center;514    justify-content: space-between;515    border-bottom: #161B22;516    border-radius: 30px;517    background-color: #161B22;518    border: 2px solid rgba(255, 255, 255, 0.11);519}520 521header:hover, section:hover{522    box-shadow: 0px 0px 15px black;523}524 525.brand{526    display: flex;527    align-items: center;528}529 530img{531    width: 2.5rem;532    height: 2.5rem;533    border: 2px solid black;534    border-radius: 50%;535}536 537.name{538    color: white;539    margin-left: 1vw;540    font-size: 1.5rem;541}542 543.intro{544    text-align: center;545    margin-bottom: 2vh;546    margin-top: 1vh;547}548 549.social a{550    font-size: 1.5rem;551    color: white;552    padding-left: 1vw;553}554 555.social a:hover, .brand:hover{556    filter: invert(0.3);557}558 559section{560    margin: 0vh 1vw;561    margin-bottom: 10vh;562    padding: 1vh 3vw;563    display: flex;564    flex-direction: column;565    border: 2px solid rgba(255, 255, 255, 0.11);566    border-radius: 20px;567    background-color: #161B22 ;568    color: white;569}570 571section form{572    display: flex;573    margin-left: auto;574    margin-right: auto;575    flex-direction: column;576}577 578section div{579    background-color: #0D1117;580    border-radius: 20px;581    max-width: fit-content;582    padding: 0.7rem;583    margin-top: 2vh;584}585 586section label{587    font-size: larger;588    font-weight: 500;589    margin: 0 0 0.5vh 1.5vw;590    display: block;591}592 593section input[type="text"]{594    border-radius: 20px;595    outline: none;596    width: 50vw;597    height: 4vh;598    padding: 1rem;599    margin: 0.5vh;600    border: 2px solid rgba(255, 255, 255, 0.11);601    background-color: #3e475531;602    box-shadow: inset 0px 0px 10px black;603}604 605section input[type="text"]:focus{606    border-color: rgba(255, 255, 255, 0.404);607}608 609section button{610    border-radius: 20px;611    margin-top: 1vh;612    width: 100%;613    height: 5.5vh;614    border: 2px solid rgba(255, 255, 255, 0.11);615    background-color: #0D1117;616    color: white;617    font-size: 16px;618    font-weight: 500;619    cursor: pointer;620    transition: background-color 200ms ease;621}622 623section button:hover, section button:focus{624    background-color: rgba(255, 255, 255, 0.068);625}626 627section span{628    display: block;629    font-size: x-small;630    margin: 1vh;631    font-weight: 100;632    font-style: italic;633    margin-left: 23%;634    margin-right: auto;635    margin-bottom: 2vh;636}637 638@media (max-width: 768px) {639    section form{640        flex-direction: column;641        width: 90vw;642    }643 644    section div{645        max-width: 100%;646        margin-bottom: 1vh;647    }648 649    section label{650        margin-left: 3vw;651        margin-top: 1vh;652    }653 654    section input[type="text"]{655        width: calc(100% - 0.3rem);656    }657 658    section button{659        width: 100%;660        height: 5vh;661        display: block;662        margin-left: auto;663        margin-right: auto;664    }665 666    section span{667        margin-left: 5%;668    }669}670    </style>671  </head>672<body>673   <!--© Designed and coded by @bipuldey19-Telegram-->674    <header>675      <div class="brand">676        <img677          src="https://telegra.ph/file/43af672249c94053356c7.jpg"678          alt="logo"679        />680        <a href="https://t.me/anas_tayyar">681          <h2 class="name">Bittorrent Selection</h2>682        </a>683      </div>684      <div class="social">685        <a href="https://www.github.com/anasty17/mirror-leech-telegram-bot"><i class="fab fa-github"></i></a>686        <a href="https://t.me/anas_tayyar"><i class="fab fa-telegram"></i></a>687      </div>688    </header>689    <section>690      <form action="{form_url}">691        <div>692          <label for="pin_code">Pin Code :</label>693          <input694            type="text"695            name="pin_code"696            placeholder="Enter the code that you have got from Telegram to access the Torrent"697          />698        </div>699        <button type="submit" class="btn btn-primary">Submit</button>700      </form>701          <span702            >* Dont mess around. Your download will get messed up.</703          >704    </section>705</body>706</html>707"""708 709 710def re_verfiy(paused, resumed, hash_id):711    paused = paused.strip()712    resumed = resumed.strip()713    if paused:714        paused = paused.split("|")715    if resumed:716        resumed = resumed.split("|")717 718    k = 0719    while True:720        res = qbittorrent_client.torrents_files(torrent_hash=hash_id)721        verify = True722        for i in res:723            if (724                str(i.id) in paused725                and i.priority != 0726            ):727                verify = False728                break729            if (730                str(i.id) in resumed731                and i.priority == 0732            ):733                verify = False734                break735        if verify:736            break737        LOGGER.info("Reverification Failed! Correcting stuff...")738        sleep(1)739        try:740            qbittorrent_client.torrents_file_priority(741                torrent_hash=hash_id,742                file_ids=paused,743                priority=0744            )745        except NotFound404Error as e:746            raise NotFound404Error from e747        except Exception as e:748            LOGGER.error(f"{e} Errored in reverification paused!")749        try:750            qbittorrent_client.torrents_file_priority(751                torrent_hash=hash_id,752                file_ids=resumed,753                priority=1754            )755        except NotFound404Error as e:756            raise NotFound404Error from e757        except Exception as e:758            LOGGER.error(f"{e} Errored in reverification resumed!")759        k += 1760        if k > 5:761            return False762    LOGGER.info(f"Verified! Hash: {hash_id}")763    return True764 765 766@app.route("/app/files/<string:id_>", methods=["GET"])767def list_torrent_contents(id_):768    if "pin_code" not in request.args.keys():769        return code_page.replace("{form_url}", f"/app/files/{id_}")770 771    pincode = ""772    for nbr in id_:773        if nbr.isdigit():774            pincode += str(nbr)775        if len(pincode) == 4:776            break777    if request.args["pin_code"] != pincode:778        return "<h1>Incorrect pin code</h1>"779 780    if id_.startswith("SABnzbd_nzo"):781 782        async def get_files():783            res = await sabnzbd_client.get_files(id_)784            return res785 786        res = web_loop.run_until_complete(get_files())787        cont = make_tree(788            res,789            "nzb" # type: ignore790        )791    elif len(id_) > 20:792        res = qbittorrent_client.torrents_files(torrent_hash=id_)793        cont = make_tree(794            res,795            "qbit" # type: ignore796        )797    else:798        res = aria2.client.get_files(id_)799        cont = make_tree(800            res,801            "aria" # type: ignore802        )803    return page.replace(804        "{My_content}",805        cont[0]806    ).replace(807        "{form_url}",808        f"/app/files/{id_}?pin_code={pincode}"809    )810 811 812@app.route("/app/files/<string:id_>", methods=["POST"])813def set_priority(id_):814    data = dict(request.form)815 816    if id_.startswith("SABnzbd_nzo"):817 818        to_remove = []819        for i, value in data.items():820            if "filenode" in i and value != "on":821                node_no = i.split("_")[-1]822                to_remove.append(node_no)823 824        async def remove_files():825            await sabnzbd_client.remove_file(826                id_,827                to_remove828            )829 830        web_loop.run_until_complete(remove_files())831        LOGGER.info(f"Verified! nzo_id: {id_}")832 833    elif len(id_) > 20:834        resume = ""835        pause = ""836        for i, value in data.items():837            if "filenode" in i:838                node_no = i.split("_")[-1]839 840                if value == "on":841                    resume += f"{node_no}|"842                else:843                    pause += f"{node_no}|"844 845        pause = pause.strip("|")846        resume = resume.strip("|")847 848        try:849            qbittorrent_client.torrents_file_priority(850                torrent_hash=id_,851                file_ids=pause,852                priority=0853            )854        except NotFound404Error as e:855            raise NotFound404Error from e856        except Exception as e:857            LOGGER.error(f"{e} Errored in paused")858        try:859            qbittorrent_client.torrents_file_priority(860                torrent_hash=id_,861                file_ids=resume,862                priority=1863            )864        except NotFound404Error as e:865            raise NotFound404Error from e866        except Exception as e:867            LOGGER.error(f"{e} Errored in resumed")868        sleep(1)869        if not re_verfiy(870            pause,871            resume,872            id_873        ):874            LOGGER.error(f"Verification Failed! Hash: {id_}")875    else:876        resume = ""877        for i, value in data.items():878            if "filenode" in i and value == "on":879                node_no = i.split("_")[-1]880                resume += f"{node_no},"881 882        resume = resume.strip(",")883 884        res = aria2.client.change_option(885            id_,886            {"select-file": resume}887        )888        if res == "OK":889            LOGGER.info(f"Verified! Gid: {id_}")890        else:891            LOGGER.info(f"Verification Failed! Report! Gid: {id_}")892    return list_torrent_contents(id_)893 894 895@app.route("/")896def homepage():897    return "<h1>Visit my channel <a href='https://telegram.me/z_mirror'>@Z_Mirror</a>on Telegram By <a href='https://telegram.me/dawn_bharat'>@Dawn_Bharat</a></h1>"898 899 900@app.errorhandler(Exception)901def page_not_found(e):902    return (903        f"<h1>404: Task not found! Mostly wrong input. <br><br>Error: {e}</h2>",904        404,905    )906 907 908if __name__ == "__main__":909    app.run()910