Angelo Gladding

dlv5vbq7lzlthol5 4b942a3185b37d00

South Pasadena, California, United States currently feels like 68.15°F

Home CodecanopyFiles

Download raw file

BitTorrent support for the Canopy


# TODO async_add_torrent/add_torrent_alert

import pathlib
import signal
import sqlite3
import sys
import time

import libtorrent

save_path = pathlib.Path("./")
port = 6881
dht_bootstraps = [""]
max_download, max_upload = -1, -1  # -1 = no limit; 4000 = 4kb/s
statistics = ("state", "download_rate", "upload_rate",
              "total_download", "total_upload")

def main():

    dbconn = sqlite3.connect("torrents.db")
    db = dbconn.cursor()

    session = libtorrent.session()
        with (save_path / ".bt-session").open("rb") as fp:
    except FileNotFoundError:
    settings = libtorrent.session_settings()
    settings.user_agent = "bt/{}".format(libtorrent.version)
    session.listen_on(port, port + 10)
    for dht_server in dht_bootstraps:
        dht_host, dht_port = dht_server.split(":")
        session.add_dht_router(dht_host, int(dht_port))
    # XXX session.add_extension(lambda x: PythonExtension(alerts))

    def add_torrent(**details):
        storage_mode = libtorrent.storage_mode_t.storage_mode_sparse
        details.update(storage_mode=storage_mode, auto_managed=True,
                       duplicate_is_error=True, save_path=str(save_path))
        handle = session.add_torrent(details)
        return handle

    for torrent in db.execute("SELECT * FROM torrents"):
        add_torrent(url=torrent[1], resume_data=torrent[3])

    def handle_exit(*args):
        for handle in session.get_torrents():
            # if not handle.is_valid() or not handle.has_metadata():
            #     continue
            db.execute("""UPDATE torrents SET fast_resume = ?
                          WHERE info_hash = ?""",
        with (save_path / ".bt-session").open("wb") as fp:

    signal.signal(signal.SIGINT, handle_exit)
    signal.signal(signal.SIGTERM, handle_exit)
        while True:
            for handle in session.get_torrents():
                status = {k: str(getattr(handle.status(), k))
                          for k in statistics}
                db.execute("""UPDATE torrents
                              SET state = ?, download_rate = ?,
                                upload_rate = ?, total_download = ?,
                                total_upload = ?
                              WHERE info_hash = ?""",
                           (status["state"], status["download_rate"],
                            status["total_download"], status["total_upload"],
            while True:
                alert = session.pop_alert()
                if not alert:
                    alert_message = alert.message()
                except AttributeError:
                    alert_message = alert
                if alert_message.startswith(":"):
                print("!", alert_message)
            for magnet, in db.execute("SELECT magnet FROM incoming"):
                    handle = add_torrent(url=magnet)
                except RuntimeError:  # torrent already exists in session
                # TODO pause until torrent info has been fetched from DHT?
                # while not handle.has_metadata():
                #     time.sleep(.1)
                print("added torrent:",
                db.execute("""INSERT INTO torrents (info_hash, magnet, name)
                              VALUES (?, ?, ?)""",
                           (str(handle.info_hash()), magnet,
                db.execute("DELETE FROM incoming WHERE magnet = ?", (magnet,))
    except KeyboardInterrupt:

if __name__ == "__main__":