transmission-card icon indicating copy to clipboard operation
transmission-card copied to clipboard

Add an option to add torrent through a file

Open jondycz opened this issue 2 years ago • 6 comments

Here is some prototype code. Though it doesn't work since the second function is asynchronous and the Hass object is out of its scope. Currently lacking braincells to come up with a solution. The first function is called using an onclick event from a button, that could be positioned on the right side of the input field.

  _addTorrentViaFileButton(event) {
    var x = document.createElement("INPUT");
    x.setAttribute("type", "file");
    x.addEventListener("change", this._addTorrentViaFile);
    x.click();
  };
  
  async _addTorrentViaFile(event) {
    let base64string = await new Promise((resolve) => {
      let file = event.currentTarget.files[0];
      const fileReader = new FileReader();
      fileReader.readAsDataURL(file);
        fileReader.onload = () => {
            resolve(fileReader.result);
        };
    });
    this.hass.callService('transmission', 'add_torrent', { entry_id: `${this._getConfigEntry()}`, torrent: base64string });
  };

Perhaps one way of doing it would be changing the value of the input field to the calculated base64 value and then using this to emulate the Enter keyboard event https://stackoverflow.com/questions/3276794/jquery-or-pure-js-simulate-enter-key-pressed-for-testing

jondycz avatar Jan 15 '23 20:01 jondycz

Got it working by emulating the keyboard event. Waiting for the previous PR to be merged to avoid conflicts.

jondycz avatar Jan 16 '23 18:01 jondycz

According to the transmission integration, it should support base64 encoded torrent files. Though I have tried 2 and for both I had gotten a service call error claiming the file name is too long. Perhaps it would have been better to convert the torrent file into a magnet link. Any other ideas?

jondycz avatar Jan 16 '23 18:01 jondycz

According to the transmission integration documentationpage:

It can either be a URL (HTTP, HTTPS or FTP), magnet link or a local file (make sure that the path is white listed).

Not sure encoded file in base64 is supported

royto avatar Jan 16 '23 19:01 royto

What the Developer Tools -> services in HA show: Add a new torrent to download (URL, magnet link or Base64 encoded).

jondycz avatar Jan 16 '23 19:01 jondycz

async function convertToMagnet(torrentFile) {
    const reader = new FileReader();
    reader.readAsArrayBuffer(torrentFile);
    return new Promise((resolve, reject) => {
        reader.onloadend = () => {
            const buf = new Uint8Array(reader.result);
            const infoHash = sha1(buf);
            resolve(`magnet:?xt=urn:btih:${infoHash}`);
        }
    });
}

function sha1(buf) {
    const crypto = window.crypto || window.msCrypto;
    const hash = crypto.subtle.digest('SHA-1', buf);
    const digest = new Uint8Array(hash);
    const hex = Array.prototype.map.call(digest, x => (x < 16 ? "0" : "") + x.toString(16)).join("");
    return hex;
}

Only issue is, this only works when accessing the page through https. In the end, we could make the file upload option disappear when accessing through http unless we find a workaround. Issue is with the window.crypto.subtle - when accessing through http, it's undefined

jondycz avatar Jan 16 '23 20:01 jondycz

Only issue is, this only works when accessing the page through https. In the end, we could make the file upload option disappear when accessing through http unless we find a workaround. Issue is with the window.crypto.subtle - when accessing through http, it's undefined

When on http put a disabled Upload icon and on its tooltip explain that file upload only works over https.

maorcc avatar Aug 10 '24 22:08 maorcc