Coder Social home page Coder Social logo

hekmon / transmissionrpc Goto Github PK

View Code? Open in Web Editor NEW
79.0 7.0 26.0 216 KB

Golang bindings for Transmission RPC API

License: MIT License

Go 100.00%
golang golang-library golang-bindings transmission transmission-api transmission-rpc torrents torrent-management

transmissionrpc's People

Contributors

bewie avatar davidnewhall avatar elboletaire avatar hekmon avatar hyperreal64 avatar primebit avatar rolinux avatar shric avatar tanelpuhu avatar veshij avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar

transmissionrpc's Issues

Adding torrents isn't starting them

Hey, I've been messing around with a tool using this package and I'm running into a little issue: Using the TorrentAdd call is resulting in a torrent that hasn't started properly and just hangs around with no download and 0 discovered peers until I pause it, wait a few seconds, and then resume it. Is this normal? How do I add a torrent that actually starts properly?

go get doesn't install v2

When running go get github.com/hekmon/transmissionrpc/v2, the follow message is returned.

go get: module github.com/hekmon/transmissionrpc@upgrade found (v1.1.0), but does not contain package github.com/hekmon/transmissionrpc/v2

Allow to request and edit torrent information via hashes

Based on the transmission-rpc documentation, ids arrays can be as follows:

   All torrents are used if the "ids" argument is omitted.
      "ids" should be one of the following:
      (1) an integer referring to a torrent id
      (2) a list of torrent id numbers, sha1 hash strings, or both
      (3) a string, "recently-active", for recently-active torrents

I've been trying out, and I may be missing something (or messing with something, I'm kinda newbie with golang), but I think your library does not support option 2, right?

It would be really nice to allow searching via hashes, many applications do not return the numeric id and, instead, use the string hash (like sonarr).

`seedIdleLimit` should be number not duration?

Hi!

I'm running into issues with TorrentSet and seedIdleLimit not being set. All limits are fine.

The struct takes a time.Duration but the spec for both v3 and v4+ needs a number.

Have I misunderstood something or should it be like that? I can see the TorrentSetPayload MarshalJSON function but running with a debugger it does not seem to run it.

Tiny inconsistency with field names - Peerlimit and PeerLimit

While the TorrentSetPayload is using Peerlimit, Torrent and TorrentAddPayload are using PeerLimit.

torrent_mutators.go
44:	Peerlimit *int64 `json:"peer-limit"` // maximum number of peers


$ ack -w PeerLimit
torrent_add.go
76:	PeerLimit *int64 `json:"peer-limit"` // maximum number of peers

torrent_accessors.go
157:	PeerLimit *int64 `json:"peer-limit"`

Just stumbled on it when trying to dynamically compare Torrent field values with configuration I have and dynamically (againπŸ˜„, basically like MarshalJSON does here also) generating TorrentSetPayload if there are differences.

I could make also PR if this change is ok but might break functionality for other using this?

TrackerReplace field of []string type does NOT work

Hi

The TrackerReplace field of []string type in type TorrentSetPayload struct does not work as intended. It's used by TorrentSet method (corresponding to transmission torrent-set rpc method) to edit the torrent tracker. TR will return an "invalid argument" rpc error. I have tested it in Transmission 3.0 for Linux.

It should be in []interface{} type and the <trackerId/new announce URLs> pairs should be passed as mixed types of int64 / string.

Why is MarshalJSON needed for torrent_mutators.go instead of using omitempty?

Hello,

I'm currently working on making this library compliant with Transmission RPC spec v17. I'm wondering what the reason is behind the MarshalJSON function for TorrentSetPayload instead of using omitempty. I'm sure there is a valid reason, I'm just trying to understand the code better.

Thanks for making this! Also: I noticed in the other issue, you mentioned you don't have time to maintain this. I would gladly take over maintainership if that is fine with you. I have forked this repo but I've had to change the Go modules to my repo in order to test my changes. This seems like it would conflict with making a pull request since both repos would be using different module URLs. I'm fairly new to this and I've never made PRs for Go projects before, so maybe there is a way to workaround this. Or else if you'd like to archive this repo and we can just use mine as the new one. I'm open to discussion about this.

Best regards

TorrentGetAll fails with Transmission 4

The error is 'torrent-get' rpc method failed: can't unmarshall request answer body: json: cannot unmarshal bool into Go struct field torrentGetResults.arguments.torrents of type int64

I call it as torrents, err := transmission.TorrentGetAll(context.TODO())

Everything was working fine until I updated to Transmission 4

FR: Expose http.Client.

If you're considering dropping a v3 tag after we figure out the RPC version changes...

I'd like to suggest a few things.

  1. Instead of taking in a bool for https and a string for uri, can we consider just providing a full url? Then the implementer can decide how their users input data, and split or join it themselves. This removes the need to join all the pieces in this library and run url.Parse.
  2. Instead of a time.Duration for HTTPTimeout, can we just take in an http.Client? This also removes the need for a dependency on hashicorp's cleanhttp module. You can let the implementer pass in their own client with a timeout pre-applied. The reason I want this is so I can log payloads and produce metrics with http.Transport middleware.
  • I may run into more suggestions as I add code to use this library, but these were the first problems I ran into. I have similar integrations for deluge, qbit, nzbget, rtorrent, and all 5 Starr apps; they all use a custom http.Client.

I'm happy to drop in a pull request if you're open to these changes.

Please provide TorrentAddFile with payload options.

Note: I'm happy to attempt the PR if you let me know which strategy you'd prefer, please let me know.

I'd like to either export file2base64 or provide another function which takes a filename and a TorrentAddPayload.

Let's say I want to add a torrent in a paused state. I can easily do this with a URL:

url := "http://..."
paused := true
payload := &transmissionrpc.TorrentAddPayload{
  Filename: &url,
  Paused: &paused,
}
torrent, err = client.TorrentAdd(payload)

If I want to add a file, there's the wrapper:

filename := "foo.torrent"
client.TorrentAddFile(filename)

But if I want to add that file paused, I need to reinvent TorrentAddFile, which is painful as file2base64 is not exported.

Support for RPC version 16 (Transmission 3.0)

Hi!

Transmission 3.0 was released with some changes in the RPC protocol. I could not find the exact list of changes, but it appears that some fields have changed types. For example trackerStats now uses bool for lastAnnounceTimedOut.

This breaks JSON unmarshal due to type mismatches:

'torrent-get' rpc method failed: can't unmarshall request answer body: json: cannot unmarshal bool into Go struct field torrentGetResults.arguments.torrents of type int64

Cheers,

Execute torrent actions over Torrent struct (i.e. torrent.RenamePath())

I've been trying this on my own with no luck*, let's see what do you think about it.

The idea is to be able to run some actions, like TorrentRenamePath or TorrentSetLocation, directly from the torrent object, so, instead of doing this:

ids := []string{"7C03A705D4BBF4F74A97401FD0165CC4D7E7DDD4"}
fields := []string{"id", "files", "hashString"}
torrents, err := client.TorrentGetHashes(fields, ids)

if err != nil {
  panic(err)
}

err = client.TorrentRenamePath(*torrents[0].ID, "FileName.mkv", "NewFileName.mkv")

if err != nil {
  panic(err)
}

Be able to do this:

ids := []string{"7C03A705D4BBF4F74A97401FD0165CC4D7E7DDD4"}
fields := []string{"id", "files", "hashString"}
torrents, err := client.TorrentGetHashes(fields, ids)

if err != nil {
  panic(err)
}

err = torrent[0].RenamePath("FileName.mkv", "NewFileName.mkv")

if err != nil {
  panic(err)
}

As said, I've tried this on my own.. but I started coding golang just three days ago and obviously my skills are still far from good.

Couldn't think in a way to use the Client inside a Torrent function, so I decided to try binding the Client to every Torrent to be able to access it later inside the function (again, I'm a newbie :)):

First I added the Client property to the Torrent struct:

type Torrent struct {
  // Original code below
  Client  *Client
}

Then I defined a new Torrents type for the [] *Torrent type with a BindClient to bind the client to every torrent:

type Torrents []*Torrent

func (t Torrents) BindClient(client *Client) {
  for _, torrent := range t {
    torrent.BindClient(client)
  }
}

// And a BindClient method for the Torrent:
func (t *Torrent) BindClient(client *Client) {
  t.Client = client
}

Obviously, after adding that Torrents type, I've searched-and-replaced all the []*Torrent matches in the code with Torrents.

Finally, in the torrentGet and torrentGetHash methods I bind the client to every torrent:

func (c *Client) torrentGet(fields []string, ids []int64) (torrents Torrents, err error) {
  // Original code below
  torrents = result.Torrents
  // Addition
  torrents.BindClient(c)
  return
}

func (c *Client) torrentGetHash(fields []string, ids []string) (torrents Torrents, err error) {
  // Original code below
  torrents = result.Torrents
  // Addition
  torrents.BindClient(c)
  return
}

And the RenamePath method looks like this:

// RenamePath directly from torrent
func (t *Torrent) RenamePath(path, name string) (err error) {
  return t.Client.TorrentRenamePath(*t.ID, path, name)
}

Doing this it works.... but I'm not really sure this is the best way. I think it would be better if can be done during the unmarshalling, but couldn't find a way to do it.

Edit: I neither like binding the client to every torrent, maybe there's a better way (?)

Please, let me know your thoughts πŸ˜ƒ

* Edit2: I started creating the issue saying "with no luck" because at the very start of writing it I had a syntax error on my code which was making it fail, but it works as said later.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    πŸ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. πŸ“ŠπŸ“ˆπŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❀️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.