Skip to content

Commit

Permalink
search kinda working, torrents displaying - not downloading yet
Browse files Browse the repository at this point in the history
  • Loading branch information
jpillora committed Jun 16, 2015
1 parent 742a9ca commit de92fef
Show file tree
Hide file tree
Showing 42 changed files with 1,669 additions and 931 deletions.
26 changes: 0 additions & 26 deletions ct/embed/embed.go

This file was deleted.

311 changes: 0 additions & 311 deletions ct/embed/files.go

This file was deleted.

17 changes: 11 additions & 6 deletions ct/engine.go → ct/engines/engine.go
@@ -1,21 +1,26 @@
package ct
package engine

import "github.com/jpillora/cloud-torrent/ct/shared"
import "github.com/jpillora/cloud-torrent/ct/engines/native"

type engineID string
type ID string

//the common engine interface
type Engine interface {
Name() string //name (lower(name)->id)
NewConfig() interface{} //*Config object
SetConfig() error
SetConfig(interface{}) error
Magnet(uri string) error
List() ([]*shared.Torrent, error) //get a list of all Torrents
Fetch(*shared.Torrent) error //fetch the Files of a particular Torrent
Torrents() <-chan *shared.Torrent
}

//TODO engines which require polling
type EnginePoller interface {
Poll() error
PollTorrent(*shared.Torrent) error
}

//insert each of the cloud-torrent bundled engines
var bundledEngines = []Engine{
var Bundled = []Engine{
&native.Native{},
}
100 changes: 50 additions & 50 deletions ct/engines/native/native.go
@@ -1,41 +1,45 @@
package native

import (
"encoding/hex"
"fmt"
"time"

"github.com/anacrolix/torrent"
"github.com/jpillora/cloud-torrent/ct/shared"
)

//the native Cloud Torrent engine, backed by anacrolix/torrent
type Native struct {
config *config
client *torrent.Client
torrents []*torrent.Torrent
config *config
client *torrent.Client
queue chan *shared.Torrent
}

func (n *Native) Name() string {
return "Native"
}
func (n *Native) NewConfig() interface{} {
config := &config{
//default config
return &config{
Config: torrent.Config{
//apply defaults
DataDir: ".",
},
}
//store reference!
n.config = config
return config
}

func (n *Native) SetConfig() error {
c, err := torrent.NewClient(&n.config.Config)
func (n *Native) SetConfig(obj interface{}) error {
//recieve config
c, ok := obj.(*config)
if !ok {
return fmt.Errorf("Invalid config")
}

client, err := torrent.NewClient(&c.Config)
if err != nil {
return err
}
n.client = c
n.client = client
return nil
}

Expand All @@ -47,50 +51,46 @@ func (n *Native) Magnet(uri string) error {
return nil
}

func (n *Native) List() ([]*shared.Torrent, error) {
t1 := n.client.Torrents()
t2 := make([]*shared.Torrent, len(t1))
for i, t := range t1 {
t2[i] = &shared.Torrent{
Name: t.Name(),
Progress: t.BytesCompleted(),
Size: t.Length(),
}
}
return t2, nil
func (n *Native) Torrents() <-chan *shared.Torrent {
n.queue = make(chan *shared.Torrent)
go n.pollTorrents()
return n.queue
}

func (n *Native) Fetch(t2 *shared.Torrent) error {

var ih torrent.InfoHash
if _, err := hex.Decode(ih[:], []byte(t2.InfoHash)); err != nil {
return err
}

t1, ok := n.client.Torrent(ih)
if !ok {
return fmt.Errorf("Torrent not found: %s", t2.InfoHash)
}

t1fs := t1.Files()
t2.Files = make([]*shared.File, len(t1fs))
for i, f1 := range t1fs {
peices := f1.Progress()
f2 := &shared.File{
Path: f1.Path(),
Size: f1.Length(),
Chunks: len(peices),
Completed: 0,
}
for _, p := range peices {
if p.State == 'C' {
f2.Completed++
func (n *Native) pollTorrents() {
for {
for _, t := range n.client.Torrents() {
//copy torrent info
st := &shared.Torrent{
Name: t.Name(),
Loaded: t.Info() != nil,
InfoHash: t.InfoHash.HexString(),
Progress: t.BytesCompleted(),
Size: t.Length(),
}
//copy files info
files := t.Files()
st.Files = make([]*shared.File, len(files))
for i, f1 := range files {
peices := f1.Progress()
f2 := &shared.File{
Path: f1.Path(),
Size: f1.Length(),
Chunks: len(peices),
Completed: 0,
}
for _, p := range peices {
if p.State == 'C' {
f2.Completed++
}
}
st.Files[i] = f2
}
//enqueue update
n.queue <- st
}
t2.Files[i] = f2
time.Sleep(time.Second)
}

return nil
}

//mask over TorrentDataOpener to allow torrent.Config to be parsed
Expand Down
58 changes: 58 additions & 0 deletions ct/search-handlers.go
@@ -0,0 +1,58 @@
package ct

var defaultSearchConfig = []byte(`{
"google": {
"name": "Google Search",
"url": "https://www.google.com/search?q={{q}}",
"list": "#search ol > li",
"result": {
"title": "li > h3 a",
"url": ["li > h3 a", "@href", "/^\\/url\\?q=([^&]+)/"]
}
},
"kat": {
"name": "Kickass Torrents",
"url": "https://kat.cr/usearch/{{query}}/{{page:1}}/?field=seeders&sorder=desc",
"list": "#mainSearchTable table tr[id]",
"result": {
"name":".cellMainLink",
"url":[".cellMainLink", "@href"],
"magnet": ["a[title=Torrent\\ magnet\\ link]", "@href"],
"size": "td.nobr.center",
"seeds": ".green.center",
"peers": ".red.center"
}
},
"tpb": {
"name": "The Pirate Bay",
"url": "https://thepiratebay.se/search/{{query}}/{{page:0}}/7//",
"list": "#searchResult > tbody > tr",
"result": {
"name":"a.detLink",
"url":["a.detLink","@href"],
"magnet": ["a[title=Download\\ this\\ torrent\\ using\\ magnet]","@href"],
"size": "/Size (\\d+(\\.\\d+).[KMG]iB)/",
"seeds": "td:nth-child(3)",
"peers": "td:nth-child(4)"
}
},
"abb": {
"name": "The Audiobook Bay",
"url": "http://audiobookbay.co/page/{{page:1}}?s={{query}}",
"list": "#content > div",
"result": {
"name":["div.postTitle > h2 > a","@title"],
"path":["div.postTitle > h2 > a","@href"],
"seeds": "div.postContent > p:nth-child(3) > span:nth-child(1)",
"peers": "div.postContent > p:nth-child(3) > span:nth-child(3)"
}
},
"abb-item": {
"name": "The Audiobook Bay (Item)",
"url": "http://audiobookbay.co/{{path}}",
"result": {
"infohash": "/td>([a-f0-9]+)</",
"tracker": "table tr:nth-child(1) > td:nth-child(2)"
}
}
}`)
41 changes: 21 additions & 20 deletions ct/server-api.go
Expand Up @@ -9,6 +9,7 @@ import (

"github.com/anacrolix/torrent"
"github.com/anacrolix/torrent/metainfo"
"github.com/jpillora/cloud-torrent/ct/engines"
"github.com/jpillora/cloud-torrent/ct/shared"
)

Expand All @@ -34,7 +35,7 @@ func (s *Server) api(r *http.Request) error {
return fmt.Errorf("Invalid request URL")
}

eid := engineID(m[1])
eid := engine.ID(m[1])
e, ok := s.engines[eid]
if !ok {
return fmt.Errorf("Invalid engine ID: %s", eid)
Expand Down Expand Up @@ -96,25 +97,25 @@ func (s *Server) api(r *http.Request) error {
if err := e.Magnet(uri); err != nil {
return fmt.Errorf("Magnet error: %s", err)
}
case "list":
torrents, err := e.List()
if err != nil {
return fmt.Errorf("List error: %s", err)
}
etorrents := s.state.Torrents[eid]
for _, t := range torrents {
etorrents[t.InfoHash] = t
}
s.rt.Update() //state change
case "fetch":
ih := string(data)
t, ok := s.state.Torrents[eid][ih]
if !ok {
return fmt.Errorf("Invalid torrent: %s", ih)
}
if err := e.Fetch(t); err != nil {
return fmt.Errorf("Fetch error: %s", err)
}
// case "list":
// torrents, err := e.List()
// if err != nil {
// return fmt.Errorf("List error: %s", err)
// }
// for _, t := range torrents {
// s.state.Torrents[eid][t.InfoHash] = t
// }
// s.rt.Update() //state change
// case "fetch":
// ih := string(data)
// t, ok := s.state.Torrents[eid][ih]
// if !ok {
// return fmt.Errorf("Invalid torrent: %s", ih)
// }
// if err := e.Fetch(t); err != nil {
// return fmt.Errorf("Fetch error: %s", err)
// }
// s.rt.Update() //state change
default:
return fmt.Errorf("Invalid action: %s", action)
}
Expand Down

0 comments on commit de92fef

Please sign in to comment.