sinatra-torrent 0.0.5 → 0.0.6
Sign up to get free protection for your applications and to get access to all the features.
- data/Rakefile +12 -21
- data/Readme.md +8 -4
- data/VERSION +1 -1
- data/lib/sinatra/torrent.rb +65 -39
- data/lib/sinatra/torrent/activerecord.rb +3 -1
- data/sinatra-torrent.gemspec +21 -18
- data/spec/spec_helper.rb +9 -0
- data/spec/torrent_spec.rb +18 -0
- metadata +52 -54
data/Rakefile
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
require 'rake'
|
2
|
+
require 'rspec/core/rake_task'
|
2
3
|
|
3
4
|
begin
|
4
5
|
require 'jeweler'
|
@@ -11,32 +12,22 @@ begin
|
|
11
12
|
gem.authors = ["JP Hastings-Spital"]
|
12
13
|
|
13
14
|
gem.add_dependency('sinatra','>=1.1.2') # Required for send_file modifications
|
15
|
+
gem.add_dependency('bencode')
|
14
16
|
end
|
15
17
|
Jeweler::GemcutterTasks.new
|
16
18
|
rescue LoadError
|
17
19
|
puts "Jeweler (or a dependency) not available. Install it with: sudo gem install jeweler"
|
18
20
|
end
|
19
21
|
|
20
|
-
|
21
|
-
|
22
|
-
test.libs << 'lib' << 'test'
|
23
|
-
test.pattern = 'test/**/test_*.rb'
|
24
|
-
test.verbose = true
|
25
|
-
end
|
22
|
+
task :default => :test
|
23
|
+
task :test => :spec
|
26
24
|
|
27
|
-
|
28
|
-
require
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
rescue LoadError
|
35
|
-
task :rcov do
|
36
|
-
abort "RCov is not available. In order to run rcov, you must: sudo gem install spicycode-rcov"
|
25
|
+
if !defined?(RSpec)
|
26
|
+
puts "spec targets require RSpec"
|
27
|
+
else
|
28
|
+
desc "Run all examples"
|
29
|
+
RSpec::Core::RakeTask.new(:spec) do |t|
|
30
|
+
t.pattern = 'spec/**/*_spec.rb'
|
31
|
+
t.rspec_opts = ['-cfs']
|
37
32
|
end
|
38
|
-
end
|
39
|
-
|
40
|
-
task :test => :check_dependencies
|
41
|
-
|
42
|
-
task :default => :test
|
33
|
+
end
|
data/Readme.md
CHANGED
@@ -13,20 +13,24 @@ Usage
|
|
13
13
|
|
14
14
|
"Woah, that's pretty simple!" I hear you say. Why yes, I think it is.
|
15
15
|
|
16
|
-
All files you put in the `downloads` directory at the root of your sinatra app will be downloadable at `/downloads/your_file.ext` and it's torrent will be dynamically generated (and cached) at `/torrents/your_file.ext.torrent`.
|
16
|
+
All files you put in the `downloads` directory at the root of your sinatra app will be downloadable at `/downloads/your_file.ext` and it's torrent will be dynamically generated (and cached) at `/torrents/your_file.ext.torrent`. If a torrent file takes over 1 second to be generated, it'll be put in a queue for creation in a background job. You can run these background jobs using the Rake helper (see below).
|
17
|
+
|
18
|
+
If you have set the `:torrent_timeout` sinatra setting to a `Proc`, it will be run (synchronously!) after the delayed job has been queued and before the user is sent the error message. eg. `set :torrent_timeout, Proc.new { start_process_forked_running_rake_hash_queue }`
|
17
19
|
|
18
20
|
### I want options!
|
19
21
|
|
20
|
-
There needs to be a database of torrents and
|
22
|
+
There needs to be a database of torrents, peers and background hashing jobs, this is taken care of by a database adapter. Currently I've written (a really basic) one for active record, so many databases are supported as is, but you can write your own for others (eg. mongo). I'm still finding my way around the Sinatra extensions api, so this is how you specify your own ActiveRecord settings:
|
21
23
|
|
22
24
|
require 'sinatra'
|
23
25
|
require 'sinatra/torrent/activerecord'
|
24
|
-
|
26
|
+
Sinatra::Torrent::Database.settings = {
|
25
27
|
'adapater' => 'sqlite3',
|
26
28
|
'database' => 'torrents.db'
|
27
29
|
}
|
28
30
|
require 'sinatra/torrent'
|
29
31
|
|
32
|
+
The active record adapter is loaded by default if no others are specified and an SQLite database will be maintained in memory unless settings (like those above) are specified. This means that, unless you set options like this, when your app shuts down your hashes will be lost!
|
33
|
+
|
30
34
|
Rake
|
31
35
|
----
|
32
36
|
|
@@ -55,7 +59,7 @@ If a torrent takes longer than 1 second to generate on-the-fly, it'll be added t
|
|
55
59
|
To Do
|
56
60
|
-----
|
57
61
|
|
58
|
-
*
|
62
|
+
* Get the BitTornado webseed style to work.
|
59
63
|
|
60
64
|
Ummmm
|
61
65
|
-----
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.0.
|
1
|
+
0.0.6
|
data/lib/sinatra/torrent.rb
CHANGED
@@ -8,17 +8,25 @@ require 'sinatra/torrent/helpers'
|
|
8
8
|
|
9
9
|
module Sinatra
|
10
10
|
module Torrent
|
11
|
-
|
12
|
-
|
11
|
+
# Sets the settings for the app
|
12
|
+
def self.settings=(settings = {})
|
13
|
+
@@settings = {
|
14
|
+
# Directory which holds all the files which will be provided as torrents
|
15
|
+
:downloads_directory => File.join(File.dirname(__FILE__),Sinatra::Torrent.downloads_directory),
|
16
|
+
# Mount point for the downloads directory
|
17
|
+
:downloads_mount => 'downloads',
|
18
|
+
# Mount point for the torrents directory
|
19
|
+
:torrents_mount => 'torrents'
|
20
|
+
}
|
21
|
+
settings.each { |key,value| @@settings[key] = value unless @@settings[value].nil? }
|
22
|
+
end
|
23
|
+
|
24
|
+
# settings etc
|
13
25
|
def self.registered(app)
|
26
|
+
# Set default settings
|
27
|
+
begin @@settings rescue self.settings=({}) end
|
14
28
|
# Putting the annouce URL of a tracker in here will use that tracker rather than the inbuilt one
|
15
29
|
app.set :external_tracker, nil
|
16
|
-
# Directory which holds all the files which will be provided as torrents
|
17
|
-
app.set :downloads_directory, File.join(File.dirname(__FILE__),Sinatra::Torrent.downloads_directory)
|
18
|
-
# Mount point for the downloads directory
|
19
|
-
app.set :downloads_mount, 'downloads'
|
20
|
-
# Mount point for the torrents directory
|
21
|
-
app.set :torrents_mount, 'torrents'
|
22
30
|
# Load up a database adapter if one isn't already loaded
|
23
31
|
require 'sinatra/torrent/activerecord' unless (Sinatra::Torrent.const_defined?('Database') rescue false)
|
24
32
|
# Stores the instance of the database used to store tracker info.
|
@@ -28,25 +36,26 @@ module Sinatra
|
|
28
36
|
# Do we wish to track external torrents too? (untested)
|
29
37
|
app.set :allow_external_torrents, false
|
30
38
|
# The frequency with which we ask trackers to announce themselves. Once every x seconds
|
31
|
-
app.set :announce_frequency,
|
39
|
+
app.set :announce_frequency, 900
|
40
|
+
# Method to call when torrent creation timesout
|
41
|
+
app.set :torrent_timeout, nil
|
32
42
|
|
33
43
|
# TORRENTS
|
34
44
|
|
35
45
|
app.mime_type :torrent, 'application/x-bittorrent'
|
36
46
|
|
37
47
|
# Serves up the torrents with appropriate announce URL
|
38
|
-
app.get Regexp.new("^/#{
|
39
|
-
filename = File.join(
|
48
|
+
app.get Regexp.new("^/#{@@settings[:torrents_mount]}/(.+)\.torrent$") do |rel_location|
|
49
|
+
filename = File.join(@@settings[:downloads_directory], rel_location)
|
40
50
|
halt(404, "That file doesn't exist! #{filename}") unless File.exists?(filename)
|
41
51
|
|
42
|
-
if !(d =
|
43
|
-
p d
|
52
|
+
if !(d = settings.database_adapter.torrent_by_path_and_timestamp(rel_location,File.mtime(filename)))
|
44
53
|
begin
|
45
54
|
Timeout::timeout(1) do
|
46
55
|
d = Sinatra::Torrent.create(filename)
|
47
56
|
end
|
48
57
|
rescue Timeout::Error
|
49
|
-
eta =
|
58
|
+
eta = settings.database_adapter.add_hashjob(rel_location)
|
50
59
|
|
51
60
|
begin
|
52
61
|
wait = case (eta/60).floor
|
@@ -61,18 +70,21 @@ module Sinatra
|
|
61
70
|
wait = "a short while"
|
62
71
|
end
|
63
72
|
|
73
|
+
settings.torrent_timeout.call if settings.torrent_timeout.is_a?(Proc)
|
74
|
+
|
64
75
|
halt(503,"This torrent is taking too long to build, we're running it in the background. Please try again in #{wait}.")
|
65
76
|
end
|
66
77
|
|
67
|
-
|
78
|
+
settings.database_adapter.store_torrent(rel_location,File.mtime(filename),d['metadata'],d['infohash'])
|
68
79
|
end
|
69
80
|
|
70
|
-
# These are
|
81
|
+
# These are settings which could change between database retrievals
|
71
82
|
d['metadata'].merge!({
|
72
|
-
|
73
|
-
'
|
74
|
-
'
|
75
|
-
'
|
83
|
+
# Webseeds not currently supported
|
84
|
+
# 'httpseeds' => [File.join('http://'+env['HTTP_HOST'],URI.encode(settings.torrents_mount),'webseed')],
|
85
|
+
'url-list' => [File.join('http://'+env['HTTP_HOST'],URI.encode(@@settings[:downloads_mount]),URI.encode(rel_location)+'?'+d['infohash'])],
|
86
|
+
'announce' => settings.external_tracker || File.join('http://'+env['HTTP_HOST'],URI.encode(@@settings[:torrents_mount]),'announce'),
|
87
|
+
'comment' => settings.torrent_comment,
|
76
88
|
})
|
77
89
|
|
78
90
|
content_type :torrent, :charset => 'utf-8'
|
@@ -82,13 +94,13 @@ module Sinatra
|
|
82
94
|
# TRACKER
|
83
95
|
|
84
96
|
# Tracker announce mount point
|
85
|
-
app.get "/#{
|
97
|
+
app.get "/#{@@settings[:torrents_mount]}/announce" do
|
86
98
|
# Convert to a hex info_hash if required TODO: Is it required?
|
87
99
|
params['info_hash'] = Digest.hexencode(params['info_hash'] || '')
|
88
100
|
halt(400,"A valid info-hash was not given") if params['info_hash'].match(/^[0-9a-f]{40}$/).nil?
|
89
|
-
info =
|
101
|
+
info = settings.database_adapter.torrent_info(params['info_hash'])
|
90
102
|
|
91
|
-
if (!
|
103
|
+
if (!settings.allow_external_torrents and !settings.database_adapter.torrent_by_infohash(params['info_hash']))
|
92
104
|
return {
|
93
105
|
'failure reason' => 'This tracker does not track that torrent'
|
94
106
|
}.bencode
|
@@ -102,54 +114,68 @@ module Sinatra
|
|
102
114
|
params['peer_id'] = params['peer_id'].force_encoding("ISO-8859-1")
|
103
115
|
|
104
116
|
# Registers this peer's announcement
|
105
|
-
|
117
|
+
settings.database_adapter.announce(params)
|
106
118
|
|
107
119
|
{
|
108
|
-
'interval' =>
|
120
|
+
'interval' => settings.announce_frequency,
|
109
121
|
#'tracker id' => 'bleugh', # TODO: Keep this?
|
110
122
|
'complete' => info['complete'],
|
111
123
|
'incomplete' => info['incomplete'],
|
112
|
-
'peers' =>
|
124
|
+
'peers' => settings.database_adapter.peers_by_infohash(params['info_hash'],[params['peer_id']],(params['numwant'] || 50).to_i),
|
113
125
|
}.bencode
|
114
126
|
end
|
115
127
|
|
116
128
|
# TODO: Scrape
|
117
129
|
app.get '/torrents/scrape' do
|
118
|
-
|
130
|
+
{
|
131
|
+
'files' => Hash[*request.env['QUERY_STRING'].scan(/info_hash=([0-9a-f]{20})/).collect do |infohash|
|
132
|
+
torrent = settings.database_adapter.torrent_by_infohash(infohash[0])
|
133
|
+
next if !torrent
|
134
|
+
stats = settings.database_adapter.torrent_info(infohash[0])
|
135
|
+
[
|
136
|
+
torrent['infohash'],
|
137
|
+
{
|
138
|
+
'complete' => stats['complete'],
|
139
|
+
'downloaded' => 0,
|
140
|
+
'incomplete' => stats['incomplete'],
|
141
|
+
'name' => File.basename(torrent['path'])
|
142
|
+
}
|
143
|
+
]
|
144
|
+
end.compact.flatten]
|
145
|
+
}.bencode
|
119
146
|
end
|
120
147
|
|
121
148
|
# INDEX PAGE
|
122
149
|
|
123
|
-
|
124
|
-
|
125
|
-
locals = {:torrents => (Dir.glob("#{options.downloads_directory}/**").collect {|f| f[options.downloads_directory.length+1..-1] } rescue [])}
|
150
|
+
app.get "/#{@@settings[:torrents_mount]}/" do
|
151
|
+
locals = {:torrents => (Dir.glob("#{@@settings[:downloads_directory]}/**").collect {|f| {:file => f[@@settings[:downloads_directory].length+1..-1],:hashed? => settings.database_adapter.torrent_by_path_and_timestamp(f[@@settings[:downloads_directory].length+1..-1],File.mtime(f)) != false} } rescue [])}
|
126
152
|
begin
|
127
153
|
haml :torrents_index,:locals => locals
|
128
154
|
rescue Errno::ENOENT
|
129
|
-
"<ul>"<<locals[:torrents].collect{|t| "<li><a href=\"/#{
|
155
|
+
"<ul>"<<locals[:torrents].collect{|t| "<li><a href=\"/#{@@settings[:torrents_mount]}/#{t[:file]}.torrent\" class=\"#{(t[:hashed?] ? 'ready' : 'unhashed')}\">#{t[:file]}</a></li>" }.join<<"</ul>"
|
130
156
|
end
|
131
157
|
end
|
132
158
|
|
133
159
|
# DATA
|
134
160
|
|
161
|
+
=begin : Not currently supported
|
135
162
|
# BitTornado WebSeeding manager
|
136
|
-
|
163
|
+
# http://bittornado.com/docs/webseed-spec.txt
|
164
|
+
app.get "/#{settings.torrents_mount}/webseed" do
|
137
165
|
# Which file is the client looking for?
|
138
|
-
halt(404, "Torrent not tracked") unless (
|
166
|
+
halt(404, "Torrent not tracked") unless (d = settings.database_adapter.torrent_by_infohash(params[:infohash]))
|
139
167
|
|
140
|
-
# http://bittornado.com/docs/webseed-spec.txt
|
141
168
|
|
142
|
-
# TODO: intelligent wait period
|
143
|
-
halt(503,"15") if false # ask clients to wait 15 seconds before requesting again
|
144
169
|
end
|
170
|
+
=end
|
145
171
|
|
146
172
|
# Provides the files for web download. Any query parameters are treated as a checksum for the file (via the torrent infohash)
|
147
|
-
app.get "/#{
|
148
|
-
filename = File.join(
|
173
|
+
app.get "/#{@@settings[:downloads_mount]}/:filename" do
|
174
|
+
filename = File.join(@@settings[:downloads_directory],File.expand_path('/'+params[:filename]))
|
149
175
|
halt(404) unless File.exists?(filename)
|
150
176
|
|
151
177
|
# If there are query params then we assume it's specifying a specific version of the file by info_hash
|
152
|
-
halt(409,"The file is no longer the same as the one specified in your torrent") if !env['QUERY_STRING'].empty? and (
|
178
|
+
halt(409,"The file is no longer the same as the one specified in your torrent") if !env['QUERY_STRING'].empty? and (settings.database_adapter.torrent_by_path_and_timestamp(filename,File.mtime(filename))['infohash'] rescue nil) != env['QUERY_STRING']
|
153
179
|
send_file(filename)
|
154
180
|
end
|
155
181
|
end
|
@@ -1,6 +1,8 @@
|
|
1
1
|
# The active record adapter works with SQLite3 in memory by default
|
2
2
|
require 'active_record'
|
3
3
|
|
4
|
+
ActiveRecord::Base.logger = nil
|
5
|
+
|
4
6
|
module Sinatra
|
5
7
|
module Torrent
|
6
8
|
# This is the wrapper class used by sinatra-torrent to communicate with
|
@@ -21,7 +23,7 @@ module Sinatra
|
|
21
23
|
# Makes sure the table is present & ready, log in using the settings
|
22
24
|
def initialize
|
23
25
|
@db = ActiveRecord::Base.establish_connection(@@settings)
|
24
|
-
|
26
|
+
|
25
27
|
unless Torrent.table_exists?
|
26
28
|
ActiveRecord::Schema.define do
|
27
29
|
create_table :torrents do |table|
|
data/sinatra-torrent.gemspec
CHANGED
@@ -1,44 +1,47 @@
|
|
1
1
|
# Generated by jeweler
|
2
2
|
# DO NOT EDIT THIS FILE DIRECTLY
|
3
|
-
# Instead, edit Jeweler::Tasks in Rakefile, and run
|
3
|
+
# Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
|
4
4
|
# -*- encoding: utf-8 -*-
|
5
5
|
|
6
6
|
Gem::Specification.new do |s|
|
7
|
-
s.name =
|
8
|
-
s.version = "0.0.
|
7
|
+
s.name = "sinatra-torrent"
|
8
|
+
s.version = "0.0.6"
|
9
9
|
|
10
10
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
11
|
s.authors = ["JP Hastings-Spital"]
|
12
|
-
s.date =
|
13
|
-
s.description =
|
14
|
-
s.email =
|
12
|
+
s.date = "2012-07-01"
|
13
|
+
s.description = "An extension to Sinatra which will allow you to run a webseeded torrent tracker of files in the folder you specify."
|
14
|
+
s.email = "jphastings@gmail.com"
|
15
15
|
s.files = [
|
16
16
|
"Rakefile",
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
17
|
+
"Readme.md",
|
18
|
+
"VERSION",
|
19
|
+
"lib/sinatra/torrent.rb",
|
20
|
+
"lib/sinatra/torrent/activerecord.rb",
|
21
|
+
"lib/sinatra/torrent/hashing.rb",
|
22
|
+
"lib/sinatra/torrent/helpers.rb",
|
23
|
+
"sinatra-torrent.gemspec",
|
24
|
+
"spec/spec_helper.rb",
|
25
|
+
"spec/torrent_spec.rb"
|
24
26
|
]
|
25
|
-
s.homepage =
|
26
|
-
s.rdoc_options = ["--charset=UTF-8"]
|
27
|
+
s.homepage = "http://github.com/jphastings/sinatra-torrent"
|
27
28
|
s.require_paths = ["lib"]
|
28
|
-
s.rubygems_version =
|
29
|
-
s.summary =
|
29
|
+
s.rubygems_version = "1.8.24"
|
30
|
+
s.summary = "A sinatra extension to run webseeded torrent tracker"
|
30
31
|
|
31
32
|
if s.respond_to? :specification_version then
|
32
|
-
current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
|
33
33
|
s.specification_version = 3
|
34
34
|
|
35
35
|
if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
|
36
36
|
s.add_runtime_dependency(%q<sinatra>, [">= 1.1.2"])
|
37
|
+
s.add_runtime_dependency(%q<bencode>, [">= 0"])
|
37
38
|
else
|
38
39
|
s.add_dependency(%q<sinatra>, [">= 1.1.2"])
|
40
|
+
s.add_dependency(%q<bencode>, [">= 0"])
|
39
41
|
end
|
40
42
|
else
|
41
43
|
s.add_dependency(%q<sinatra>, [">= 1.1.2"])
|
44
|
+
s.add_dependency(%q<bencode>, [">= 0"])
|
42
45
|
end
|
43
46
|
end
|
44
47
|
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__),'spec_helper')
|
2
|
+
require File.join(File.dirname(__FILE__),'..','lib','sinatra','torrent')
|
3
|
+
|
4
|
+
describe 'The Torrent extension' do
|
5
|
+
it 'should load correctly in sinatra'
|
6
|
+
|
7
|
+
describe 'the scrape url' do
|
8
|
+
it 'should provide scrape information' do
|
9
|
+
|
10
|
+
end
|
11
|
+
|
12
|
+
it 'should provide scrape information for multiple infohashes' do
|
13
|
+
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
it 'should have more test cases'
|
18
|
+
end
|
metadata
CHANGED
@@ -1,48 +1,55 @@
|
|
1
|
-
--- !ruby/object:Gem::Specification
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
2
|
name: sinatra-torrent
|
3
|
-
version: !ruby/object:Gem::Version
|
4
|
-
|
5
|
-
prerelease:
|
6
|
-
segments:
|
7
|
-
- 0
|
8
|
-
- 0
|
9
|
-
- 5
|
10
|
-
version: 0.0.5
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.6
|
5
|
+
prerelease:
|
11
6
|
platform: ruby
|
12
|
-
authors:
|
7
|
+
authors:
|
13
8
|
- JP Hastings-Spital
|
14
9
|
autorequire:
|
15
10
|
bindir: bin
|
16
11
|
cert_chain: []
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
dependencies:
|
21
|
-
- !ruby/object:Gem::Dependency
|
12
|
+
date: 2012-07-01 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
22
15
|
name: sinatra
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ! '>='
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: 1.1.2
|
22
|
+
type: :runtime
|
23
23
|
prerelease: false
|
24
|
-
|
24
|
+
version_requirements: !ruby/object:Gem::Requirement
|
25
25
|
none: false
|
26
|
-
requirements:
|
27
|
-
- -
|
28
|
-
- !ruby/object:Gem::Version
|
29
|
-
hash: 23
|
30
|
-
segments:
|
31
|
-
- 1
|
32
|
-
- 1
|
33
|
-
- 2
|
26
|
+
requirements:
|
27
|
+
- - ! '>='
|
28
|
+
- !ruby/object:Gem::Version
|
34
29
|
version: 1.1.2
|
30
|
+
- !ruby/object:Gem::Dependency
|
31
|
+
name: bencode
|
32
|
+
requirement: !ruby/object:Gem::Requirement
|
33
|
+
none: false
|
34
|
+
requirements:
|
35
|
+
- - ! '>='
|
36
|
+
- !ruby/object:Gem::Version
|
37
|
+
version: '0'
|
35
38
|
type: :runtime
|
36
|
-
|
37
|
-
|
39
|
+
prerelease: false
|
40
|
+
version_requirements: !ruby/object:Gem::Requirement
|
41
|
+
none: false
|
42
|
+
requirements:
|
43
|
+
- - ! '>='
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
version: '0'
|
46
|
+
description: An extension to Sinatra which will allow you to run a webseeded torrent
|
47
|
+
tracker of files in the folder you specify.
|
38
48
|
email: jphastings@gmail.com
|
39
49
|
executables: []
|
40
|
-
|
41
50
|
extensions: []
|
42
|
-
|
43
51
|
extra_rdoc_files: []
|
44
|
-
|
45
|
-
files:
|
52
|
+
files:
|
46
53
|
- Rakefile
|
47
54
|
- Readme.md
|
48
55
|
- VERSION
|
@@ -51,39 +58,30 @@ files:
|
|
51
58
|
- lib/sinatra/torrent/hashing.rb
|
52
59
|
- lib/sinatra/torrent/helpers.rb
|
53
60
|
- sinatra-torrent.gemspec
|
54
|
-
|
61
|
+
- spec/spec_helper.rb
|
62
|
+
- spec/torrent_spec.rb
|
55
63
|
homepage: http://github.com/jphastings/sinatra-torrent
|
56
64
|
licenses: []
|
57
|
-
|
58
65
|
post_install_message:
|
59
|
-
rdoc_options:
|
60
|
-
|
61
|
-
require_paths:
|
66
|
+
rdoc_options: []
|
67
|
+
require_paths:
|
62
68
|
- lib
|
63
|
-
required_ruby_version: !ruby/object:Gem::Requirement
|
69
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
64
70
|
none: false
|
65
|
-
requirements:
|
66
|
-
- -
|
67
|
-
- !ruby/object:Gem::Version
|
68
|
-
|
69
|
-
|
70
|
-
- 0
|
71
|
-
version: "0"
|
72
|
-
required_rubygems_version: !ruby/object:Gem::Requirement
|
71
|
+
requirements:
|
72
|
+
- - ! '>='
|
73
|
+
- !ruby/object:Gem::Version
|
74
|
+
version: '0'
|
75
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
73
76
|
none: false
|
74
|
-
requirements:
|
75
|
-
- -
|
76
|
-
- !ruby/object:Gem::Version
|
77
|
-
|
78
|
-
segments:
|
79
|
-
- 0
|
80
|
-
version: "0"
|
77
|
+
requirements:
|
78
|
+
- - ! '>='
|
79
|
+
- !ruby/object:Gem::Version
|
80
|
+
version: '0'
|
81
81
|
requirements: []
|
82
|
-
|
83
82
|
rubyforge_project:
|
84
|
-
rubygems_version: 1.
|
83
|
+
rubygems_version: 1.8.24
|
85
84
|
signing_key:
|
86
85
|
specification_version: 3
|
87
86
|
summary: A sinatra extension to run webseeded torrent tracker
|
88
87
|
test_files: []
|
89
|
-
|