bencview 0.0.2 → 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/README.md +93 -0
- data/bencview +31 -0
- data/bencview.rb +152 -0
- data/json2bencode +13 -0
- data/package.gemspec +33 -0
- metadata +56 -87
- data/README.rdoc +0 -9
- data/Rakefile +0 -50
- data/bin/bencview +0 -107
- data/bin/bencview_clean +0 -58
- data/doc/LICENSE +0 -22
- data/doc/NEWS.rdoc +0 -11
- data/doc/README.rdoc +0 -9
- data/doc/bencview.rdoc +0 -59
- data/doc/bencview_clean.rdoc +0 -75
- data/etc/bencview.yaml +0 -2
- data/lib/bencview/meta.rb +0 -9
- data/lib/bencview/trestle.rb +0 -216
- data/test/helper.rb +0 -4
- data/test/helper_trestle.rb +0 -37
- data/test/rake_git.rb +0 -36
- data/test/test_bencview.rb +0 -43
- data/test/torrent/[rutracker.org].t3128973.torrent +0 -58
- data/test/torrent/[rutracker.org]2642547.torrent +0 -0
- data/test/torrent/[rutracker.org]314407.torrent +0 -0
- data/test/torrent/[rutracker.org]838460.torrent +0 -0
- data/test/torrent/stack overflow data dump - nov 2010.torrent +0 -0
- data/test/viewer_output_01.txt +0 -175
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 92a0139e1908590118e2d0bd7e0db48b3f8a94e7
|
4
|
+
data.tar.gz: a18f7b361bb9d4dcb5e83f45fd1d0773306db79f
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: b8221a19897cc70e617566f8379def9e18fbe1085a4867a0265cf77566c4244383fe60b2d01700bdc99dd3ecbb0fff2ff7d298f8520825384acf081c4c9989a9
|
7
|
+
data.tar.gz: ab6bc66c3b656aa476e673d352e23e8ec1bd1de14008d53799d54d7b7c0bbcdd23abe97bc414f82ac4b116ba48c85fabb5249d944ff04fd63440e374f9b1418a
|
data/README.md
ADDED
@@ -0,0 +1,93 @@
|
|
1
|
+
# bencview
|
2
|
+
|
3
|
+
`bencview` - a .torrent files viewer for terminal pagers.\
|
4
|
+
`json2bencode` - a converter from JSON to the torrent files format.
|
5
|
+
|
6
|
+
(Bencode is a data serialization format used by the BitTorrent network.)
|
7
|
+
|
8
|
+
## Installation
|
9
|
+
|
10
|
+
(Ruby 2.3.0+)
|
11
|
+
|
12
|
+
$ gem install bencview
|
13
|
+
|
14
|
+
Add to your `lesspipe.sh`:
|
15
|
+
|
16
|
+
<pre>
|
17
|
+
case "$1" in
|
18
|
+
...
|
19
|
+
<b> *.torrent) bencview "$1" ;;</b>
|
20
|
+
...
|
21
|
+
esac
|
22
|
+
</pre>
|
23
|
+
|
24
|
+
Optionally:
|
25
|
+
|
26
|
+
$ npm -g i json
|
27
|
+
|
28
|
+
## Usage
|
29
|
+
|
30
|
+
View a torrent file:
|
31
|
+
|
32
|
+
~~~
|
33
|
+
$ bencview gimp.torrent
|
34
|
+
infohash: a85b7e7f035c55f684238d0e252b273fe2a1ccf5
|
35
|
+
uri: magnet:?xt=urn:btih:a85b7e7f035c55f684238d0e252b273fe2a1ccf5&dn=gimp-2.8.14-setup-1.exe.torrent
|
36
|
+
announce: udp://tracker.publicbt.com:80
|
37
|
+
announce-list: 2
|
38
|
+
udp://tracker.publicbt.com:80
|
39
|
+
udp://tracker.openbittorrent.com:80
|
40
|
+
comment: GIMP 2.8.14 Installer for Microsoft Windows - updated
|
41
|
+
created by: mktorrent 1.0
|
42
|
+
creation date: Tue, 2 Sep 2014 22:05:50 +0000
|
43
|
+
url-list: 34
|
44
|
+
http://gimper.net/downloads/pub/gimp/v2.8/windows
|
45
|
+
http://gimp.afri.cc/pub/gimp/v2.8/windows
|
46
|
+
[...]
|
47
|
+
info/name: gimp-2.8.14-setup-1.exe
|
48
|
+
info/files: 1
|
49
|
+
91,931,728 gimp-2.8.14-setup-1.exe
|
50
|
+
info/files size: 91,931,728
|
51
|
+
~~~
|
52
|
+
|
53
|
+
Remove all trackers from it:
|
54
|
+
|
55
|
+
~~~
|
56
|
+
$ bencview -j gimp.torrent | json -e 'delete this.announce; delete this["announce-list"]' | json2bencode > file.torrent
|
57
|
+
|
58
|
+
$ file file.torrent
|
59
|
+
file.torrent: BitTorrent file
|
60
|
+
|
61
|
+
$ bencview file.torrent
|
62
|
+
infohash: a85b7e7f035c55f684238d0e252b273fe2a1ccf5
|
63
|
+
uri: magnet:?xt=urn:btih:a85b7e7f035c55f684238d0e252b273fe2a1ccf5&dn=gimp-2.8.14-setup-1.exe.torrent
|
64
|
+
comment: GIMP 2.8.14 Installer for Microsoft Windows - updated
|
65
|
+
created by: mktorrent 1.0
|
66
|
+
creation date: Tue, 2 Sep 2014 22:05:50 +0000
|
67
|
+
url-list: 34
|
68
|
+
http://gimper.net/downloads/pub/gimp/v2.8/windows
|
69
|
+
http://gimp.afri.cc/pub/gimp/v2.8/windows
|
70
|
+
[...]
|
71
|
+
info/name: gimp-2.8.14-setup-1.exe
|
72
|
+
info/files: 1
|
73
|
+
91,931,728 gimp-2.8.14-setup-1.exe
|
74
|
+
info/files size: 91,931,728
|
75
|
+
~~~
|
76
|
+
|
77
|
+
Note that the infohash hasn't changed.
|
78
|
+
|
79
|
+
## History
|
80
|
+
|
81
|
+
This is a complete rewrite of the original
|
82
|
+
bencview-0.0.x. `bencview_clean` util is gone, for `bencview` can
|
83
|
+
export torrent files into JSON.
|
84
|
+
|
85
|
+
1.0.0 version is also ~2 times smaller.
|
86
|
+
|
87
|
+
## Bugs
|
88
|
+
|
89
|
+
* Both utils assume the UTF8 locale.
|
90
|
+
|
91
|
+
## License
|
92
|
+
|
93
|
+
MIT.
|
data/bencview
ADDED
@@ -0,0 +1,31 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require 'optparse'
|
4
|
+
|
5
|
+
require_relative './bencview'
|
6
|
+
|
7
|
+
opt = {}
|
8
|
+
OptionParser.new do |o|
|
9
|
+
o.banner = "Usage: #{File.basename $0} [-jr] [input]"
|
10
|
+
o.on("-j", "Output as JSON") do
|
11
|
+
opt[:json] = true
|
12
|
+
end
|
13
|
+
o.on("-r", "Print as a Ruby hash (debug)") do
|
14
|
+
opt[:raw] = true
|
15
|
+
end
|
16
|
+
o.on('-v', '-V', 'Print the version number') do
|
17
|
+
puts (eval File.read File.join __dir__, 'package.gemspec').version
|
18
|
+
exit
|
19
|
+
end
|
20
|
+
end.parse!
|
21
|
+
|
22
|
+
io = ARGV.size > 0 ? File.open(ARGV[0]) : $stdin
|
23
|
+
torrent = Bencview::Torrent.new io
|
24
|
+
|
25
|
+
if opt[:raw]
|
26
|
+
require 'pp'
|
27
|
+
pp torrent.input
|
28
|
+
exit
|
29
|
+
end
|
30
|
+
|
31
|
+
puts opt[:json] ? torrent.to_json : torrent
|
data/bencview.rb
ADDED
@@ -0,0 +1,152 @@
|
|
1
|
+
require 'date'
|
2
|
+
require 'digest'
|
3
|
+
require 'uri'
|
4
|
+
require 'json'
|
5
|
+
require "base64"
|
6
|
+
|
7
|
+
require 'bencode'
|
8
|
+
|
9
|
+
module Bencview
|
10
|
+
# walk through object, firing `block` on each string leaf
|
11
|
+
def self.hash_walk obj, &block
|
12
|
+
if obj.respond_to? :to_hash
|
13
|
+
r = {}
|
14
|
+
obj.to_hash.each do |key, value|
|
15
|
+
r[key] = hash_walk value, &block # recursion
|
16
|
+
end
|
17
|
+
r
|
18
|
+
elsif obj.respond_to? :to_ary
|
19
|
+
obj.to_ary.map { |a| hash_walk a, &block } # recursion
|
20
|
+
elsif obj.kind_of? String
|
21
|
+
yield obj
|
22
|
+
else
|
23
|
+
obj
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
class Bencview::Torrent
|
29
|
+
attr_reader :input, :infohash
|
30
|
+
def initialize io
|
31
|
+
@input = (BEncode::Parser.new io).parse!
|
32
|
+
raise 'invalid input' unless @input
|
33
|
+
@infohash = sha1
|
34
|
+
end
|
35
|
+
|
36
|
+
def any_to_s obj
|
37
|
+
obj.kind_of?(Array) ? [obj.size, obj].join("\n ").strip : obj.to_s
|
38
|
+
end
|
39
|
+
|
40
|
+
def num n
|
41
|
+
n.to_s.reverse.gsub(/(\d{3})(?=\d)/, '\\1,').reverse
|
42
|
+
end
|
43
|
+
|
44
|
+
# BitTorrent specific
|
45
|
+
def sha1
|
46
|
+
return nil unless @input['info'].kind_of?(Hash)
|
47
|
+
Digest::SHA1.hexdigest @input['info'].bencode
|
48
|
+
end
|
49
|
+
|
50
|
+
# BitTorrent specific
|
51
|
+
def magnet name
|
52
|
+
return nil unless @infohash
|
53
|
+
"magnet:?xt=urn:btih:#{@infohash}" + (name ? "&dn=#{URI.escape name}.torrent" : "")
|
54
|
+
end
|
55
|
+
|
56
|
+
# BitTorrent specific
|
57
|
+
def bti obj, prefix
|
58
|
+
return nil unless obj.kind_of?(Hash)
|
59
|
+
|
60
|
+
rkey = -> key { "#{prefix}#{key}" }
|
61
|
+
|
62
|
+
r = []
|
63
|
+
obj.each do |key,val|
|
64
|
+
key = key.to_s.strip
|
65
|
+
if key =~ /^piece/
|
66
|
+
# TODO: calc the chunks
|
67
|
+
elsif key =~ /\.utf-8$/
|
68
|
+
# ignore
|
69
|
+
elsif key =~ /^(files|length)$/
|
70
|
+
# ignore, but see below `files_add`
|
71
|
+
elsif key == 'profiles' && val.kind_of?(Array)
|
72
|
+
val.each {|item| r.concat to_a item, "#{prefix}#{key}/" }
|
73
|
+
else
|
74
|
+
r.push "#{rkey.call key}: #{val}"
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
files = []
|
79
|
+
files_add = -> arr do
|
80
|
+
bytes = 0
|
81
|
+
max = 0
|
82
|
+
arr.each do |file|
|
83
|
+
bytes += file['length']
|
84
|
+
max = file['length'] if max < file['length']
|
85
|
+
end
|
86
|
+
max = (num max).size + 1
|
87
|
+
|
88
|
+
files.push "#{rkey.call 'files'}: #{arr.size}"
|
89
|
+
arr.each do |file|
|
90
|
+
files.push "%#{max}s %s" % [num(file['length']), file['path'].join('/')]
|
91
|
+
end
|
92
|
+
files.push "#{rkey.call 'files size'}: #{num bytes}"
|
93
|
+
end
|
94
|
+
|
95
|
+
if obj['files']
|
96
|
+
files_add.call obj['files']
|
97
|
+
elsif obj['length'] && obj['name']
|
98
|
+
files_add.call [{'length' => obj['length'], 'path' => [obj['name']]}]
|
99
|
+
end
|
100
|
+
|
101
|
+
r.concat files if files
|
102
|
+
end
|
103
|
+
|
104
|
+
def to_a obj=nil, prefix=''
|
105
|
+
obj = @input unless obj
|
106
|
+
|
107
|
+
r = []
|
108
|
+
info = nil
|
109
|
+
|
110
|
+
rkey = -> key { "#{prefix}#{key}" }
|
111
|
+
|
112
|
+
if @infohash && prefix == ''
|
113
|
+
r.push "infohash: #{@infohash}"
|
114
|
+
r.push "uri: #{magnet @input.dig 'info', 'name'}"
|
115
|
+
end
|
116
|
+
|
117
|
+
obj.each do |key,val|
|
118
|
+
key = key.to_s.strip
|
119
|
+
if key == 'info'
|
120
|
+
info = bti val, "#{prefix}info/"
|
121
|
+
elsif val.kind_of? Hash
|
122
|
+
r.concat to_a val, "#{prefix}#{key}/" # recursion
|
123
|
+
elsif key =~ /date/
|
124
|
+
r.push "#{rkey.call key}: #{DateTime.strptime(val.to_s, '%s').rfc2822}"
|
125
|
+
elsif key =~ /-list$/
|
126
|
+
r.push "#{rkey.call key}: #{any_to_s val}"
|
127
|
+
else
|
128
|
+
r.push "#{rkey.call key}: #{val}"
|
129
|
+
end
|
130
|
+
end
|
131
|
+
|
132
|
+
r.concat info if info
|
133
|
+
r
|
134
|
+
end
|
135
|
+
|
136
|
+
def to_s obj=nil, prefix=''
|
137
|
+
(to_a obj, prefix).join "\n"
|
138
|
+
end
|
139
|
+
|
140
|
+
# walk through object, return a hash suitable for JSON.stringify
|
141
|
+
def to_json
|
142
|
+
Bencview.hash_walk(@input) do |str|
|
143
|
+
begin
|
144
|
+
str.to_json
|
145
|
+
rescue
|
146
|
+
next Base64.strict_encode64 str
|
147
|
+
end
|
148
|
+
str
|
149
|
+
end.to_json
|
150
|
+
end
|
151
|
+
|
152
|
+
end
|
data/json2bencode
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require_relative './bencview'
|
4
|
+
|
5
|
+
io = ARGV.size > 0 ? File.open(ARGV[0]) : $stdin
|
6
|
+
print Bencview.hash_walk(JSON.parse io.read) do |str|
|
7
|
+
# check if the string is in base64
|
8
|
+
if str =~ /^([A-Za-z0-9+\/]{4})*([A-Za-z0-9+\/]{4}|[A-Za-z0-9+\/]{3}=|[A-Za-z0-9+\/]{2}==)$/
|
9
|
+
next Base64.decode64 str
|
10
|
+
else
|
11
|
+
str
|
12
|
+
end
|
13
|
+
end.bencode
|
data/package.gemspec
ADDED
@@ -0,0 +1,33 @@
|
|
1
|
+
Gem::Specification.new do |s|
|
2
|
+
s.version = '1.0.0'
|
3
|
+
|
4
|
+
s.name = 'bencview'
|
5
|
+
s.summary = "View .torrent files; JSON export/import"
|
6
|
+
s.author = 'Alexander Gromnitsky'
|
7
|
+
s.email = 'alexander.gromnitsky@gmail.com'
|
8
|
+
s.homepage = 'https://github.com/gromnitsky/bencview'
|
9
|
+
s.license = 'MIT'
|
10
|
+
s.files = [
|
11
|
+
'bencview',
|
12
|
+
'bencview.rb',
|
13
|
+
'json2bencode',
|
14
|
+
'package.gemspec',
|
15
|
+
'README.md',
|
16
|
+
]
|
17
|
+
|
18
|
+
s.require_paths = ['.']
|
19
|
+
s.bindir = '.'
|
20
|
+
s.executables = ['bencview', 'json2bencode']
|
21
|
+
|
22
|
+
s.add_runtime_dependency 'bencode', '~> 0.8.2'
|
23
|
+
|
24
|
+
s.required_ruby_version = '>= 2.3.0'
|
25
|
+
|
26
|
+
s.post_install_message = <<~END
|
27
|
+
*************************************************************************
|
28
|
+
If you were using bencview-0.0.x, please read
|
29
|
+
#{s.homepage},
|
30
|
+
for it's a different program now, totally incompatible w/ 0.0.x releases.
|
31
|
+
*************************************************************************
|
32
|
+
END
|
33
|
+
end
|
metadata
CHANGED
@@ -1,102 +1,71 @@
|
|
1
|
-
--- !ruby/object:Gem::Specification
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
2
|
name: bencview
|
3
|
-
version: !ruby/object:Gem::Version
|
4
|
-
|
5
|
-
version: 0.0.2
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 1.0.0
|
6
5
|
platform: ruby
|
7
|
-
authors:
|
6
|
+
authors:
|
8
7
|
- Alexander Gromnitsky
|
9
8
|
autorequire:
|
10
|
-
bindir:
|
9
|
+
bindir: "."
|
11
10
|
cert_chain: []
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
- !ruby/object:Gem::Dependency
|
16
|
-
name: open4
|
17
|
-
prerelease: false
|
18
|
-
requirement: &id001 !ruby/object:Gem::Requirement
|
19
|
-
none: false
|
20
|
-
requirements:
|
21
|
-
- - ">="
|
22
|
-
- !ruby/object:Gem::Version
|
23
|
-
version: 1.0.1
|
24
|
-
type: :runtime
|
25
|
-
version_requirements: *id001
|
26
|
-
- !ruby/object:Gem::Dependency
|
11
|
+
date: 2017-06-05 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
27
14
|
name: bencode
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
- !ruby/object:Gem::Version
|
34
|
-
version: 0.6.0
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: 0.8.2
|
35
20
|
type: :runtime
|
36
|
-
|
37
|
-
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: 0.8.2
|
27
|
+
description:
|
38
28
|
email: alexander.gromnitsky@gmail.com
|
39
|
-
executables:
|
40
|
-
- bencview_clean
|
29
|
+
executables:
|
41
30
|
- bencview
|
31
|
+
- json2bencode
|
42
32
|
extensions: []
|
43
|
-
|
44
|
-
|
45
|
-
-
|
46
|
-
-
|
47
|
-
-
|
48
|
-
-
|
49
|
-
-
|
50
|
-
|
51
|
-
-
|
52
|
-
|
53
|
-
|
54
|
-
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
-
|
65
|
-
|
66
|
-
|
67
|
-
- test/torrent/[rutracker.org].t3128973.torrent
|
68
|
-
- test/torrent/[rutracker.org]2642547.torrent
|
69
|
-
- test/torrent/[rutracker.org]314407.torrent
|
70
|
-
- test/torrent/[rutracker.org]838460.torrent
|
71
|
-
- test/torrent/stack overflow data dump - nov 2010.torrent
|
72
|
-
- test/viewer_output_01.txt
|
73
|
-
homepage: http://github.com/gromnitsky/bencview
|
74
|
-
licenses: []
|
75
|
-
|
76
|
-
post_install_message:
|
77
|
-
rdoc_options:
|
78
|
-
- -m
|
79
|
-
- doc/README.rdoc
|
80
|
-
require_paths:
|
81
|
-
- lib
|
82
|
-
required_ruby_version: !ruby/object:Gem::Requirement
|
83
|
-
none: false
|
84
|
-
requirements:
|
33
|
+
extra_rdoc_files: []
|
34
|
+
files:
|
35
|
+
- "./bencview"
|
36
|
+
- "./json2bencode"
|
37
|
+
- README.md
|
38
|
+
- bencview
|
39
|
+
- bencview.rb
|
40
|
+
- json2bencode
|
41
|
+
- package.gemspec
|
42
|
+
homepage: https://github.com/gromnitsky/bencview
|
43
|
+
licenses:
|
44
|
+
- MIT
|
45
|
+
metadata: {}
|
46
|
+
post_install_message: |
|
47
|
+
*************************************************************************
|
48
|
+
If you were using bencview-0.0.x, please read
|
49
|
+
https://github.com/gromnitsky/bencview,
|
50
|
+
for it's a different program now, totally incompatible w/ 0.0.x releases.
|
51
|
+
*************************************************************************
|
52
|
+
rdoc_options: []
|
53
|
+
require_paths:
|
54
|
+
- "."
|
55
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
56
|
+
requirements:
|
85
57
|
- - ">="
|
86
|
-
- !ruby/object:Gem::Version
|
87
|
-
version:
|
88
|
-
required_rubygems_version: !ruby/object:Gem::Requirement
|
89
|
-
|
90
|
-
requirements:
|
58
|
+
- !ruby/object:Gem::Version
|
59
|
+
version: 2.3.0
|
60
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
61
|
+
requirements:
|
91
62
|
- - ">="
|
92
|
-
- !ruby/object:Gem::Version
|
93
|
-
version:
|
63
|
+
- !ruby/object:Gem::Version
|
64
|
+
version: '0'
|
94
65
|
requirements: []
|
95
|
-
|
96
66
|
rubyforge_project:
|
97
|
-
rubygems_version:
|
67
|
+
rubygems_version: 2.5.2
|
98
68
|
signing_key:
|
99
|
-
specification_version:
|
100
|
-
summary:
|
101
|
-
test_files:
|
102
|
-
- test/test_bencview.rb
|
69
|
+
specification_version: 4
|
70
|
+
summary: View .torrent files; JSON export/import
|
71
|
+
test_files: []
|
data/README.rdoc
DELETED
@@ -1,9 +0,0 @@
|
|
1
|
-
bencview suite contains several utils to manage .torrent files.
|
2
|
-
|
3
|
-
bencview:: Torrent file viewer.
|
4
|
-
|
5
|
-
bencview_clean:: Cleans a list of announce trackers & replaces
|
6
|
-
main announce tracker (to be able to cheat,
|
7
|
-
for example, http://rutracker.org, ha-ha).
|
8
|
-
|
9
|
-
Read about them in corresponding <tt>*.rdoc</tt> files.
|
data/Rakefile
DELETED
@@ -1,50 +0,0 @@
|
|
1
|
-
# -*-ruby-*-
|
2
|
-
|
3
|
-
require 'rake'
|
4
|
-
require 'rake/gempackagetask'
|
5
|
-
require 'rake/clean'
|
6
|
-
require 'rake/rdoctask'
|
7
|
-
require 'rake/testtask'
|
8
|
-
|
9
|
-
require_relative 'lib/bencview/meta'
|
10
|
-
include Bencview
|
11
|
-
|
12
|
-
require_relative 'test/rake_git'
|
13
|
-
|
14
|
-
spec = Gem::Specification.new {|i|
|
15
|
-
i.name = Meta::NAME
|
16
|
-
i.version = `bin/#{i.name} -V`
|
17
|
-
i.summary = 'Torrent file viewer & metadata cleaner'
|
18
|
-
i.description = i.summary + '.' # eat this, freaking rubygems
|
19
|
-
i.author = Meta::AUTHOR
|
20
|
-
i.email = Meta::EMAIL
|
21
|
-
i.homepage = Meta::HOMEPAGE
|
22
|
-
|
23
|
-
i.platform = Gem::Platform::RUBY
|
24
|
-
i.required_ruby_version = '>= 1.9.2'
|
25
|
-
i.files = git_ls('.')
|
26
|
-
|
27
|
-
i.executables = FileList['bin/*'].gsub(/^bin\//, '')
|
28
|
-
|
29
|
-
i.test_files = FileList['test/test_*.rb']
|
30
|
-
|
31
|
-
i.rdoc_options << '-m' << 'doc/README.rdoc'
|
32
|
-
i.extra_rdoc_files = FileList['doc/*']
|
33
|
-
|
34
|
-
i.add_dependency('open4', '>= 1.0.1')
|
35
|
-
i.add_dependency('bencode', '>= 0.6.0')
|
36
|
-
}
|
37
|
-
|
38
|
-
Rake::GemPackageTask.new(spec).define
|
39
|
-
|
40
|
-
task default: [:repackage]
|
41
|
-
|
42
|
-
Rake::RDocTask.new('doc') {|i|
|
43
|
-
i.main = 'doc/README.rdoc'
|
44
|
-
i.rdoc_files = FileList['doc/*', 'lib/**/*.rb']
|
45
|
-
# i.rdoc_files.exclude("lib/**/some-nasty-staff")
|
46
|
-
}
|
47
|
-
|
48
|
-
Rake::TestTask.new {|i|
|
49
|
-
i.test_files = FileList['test/test_*.rb']
|
50
|
-
}
|
data/bin/bencview
DELETED
@@ -1,107 +0,0 @@
|
|
1
|
-
#!/usr/bin/env ruby
|
2
|
-
# -*-ruby-*-
|
3
|
-
|
4
|
-
require 'bencode'
|
5
|
-
require_relative '../lib/bencview/trestle.rb'
|
6
|
-
|
7
|
-
include Bencview
|
8
|
-
|
9
|
-
$conf = Hash.new
|
10
|
-
u = Trestle.new($conf)
|
11
|
-
|
12
|
-
$conf[:banner] = "Usage: #{File.basename($0)} [options] file [file ...]"
|
13
|
-
$conf[:dump] = false
|
14
|
-
|
15
|
-
# Return a string--human redable number, e.g. 123456 becomes '123,456'.
|
16
|
-
def dn(n)
|
17
|
-
return n.to_s if n.to_i/1000.0 < 1
|
18
|
-
n.to_s.gsub!(/(\d)(?=(\d\d\d)+(?!\d))/, "\\1,")
|
19
|
-
end
|
20
|
-
|
21
|
-
# Convert _s_ from _enc_ to the default external encoding.
|
22
|
-
def ds(s, enc)
|
23
|
-
s = s.to_s
|
24
|
-
return s if (enc == Encoding.default_external || enc == "" || !enc)
|
25
|
-
return dn(s) if s.match /^[0-9]+$/
|
26
|
-
s.encode(Encoding.default_external, enc,
|
27
|
-
:undef => :replace,
|
28
|
-
:invalid => :replace)
|
29
|
-
end
|
30
|
-
|
31
|
-
# Read _s_ as a number of seconds from the Epoch and return a human
|
32
|
-
# readable date string.
|
33
|
-
def ddate(s)
|
34
|
-
DateTime.strptime(s.to_s, '%s').rfc2822
|
35
|
-
end
|
36
|
-
|
37
|
-
# --[ main ]------------------------------------------------------------
|
38
|
-
|
39
|
-
u.config_parse(['foobar']) {|src|
|
40
|
-
o = u.cl_parse(src) # create an OptionParser object
|
41
|
-
o.on('-d', 'Dump all as raw hash') {|i| $conf[:dump] = true }
|
42
|
-
u.cl_parse(src, o) # run cl parser
|
43
|
-
}
|
44
|
-
|
45
|
-
# print our env
|
46
|
-
if $conf[:verbose] >= 2
|
47
|
-
puts 'Libs dir: ' + Trestle.gem_libdir
|
48
|
-
pp $conf
|
49
|
-
end
|
50
|
-
|
51
|
-
Trestle.errx(1, $conf[:banner]) if ARGV.size == 0
|
52
|
-
|
53
|
-
ec = 0
|
54
|
-
visfilesep = ARGV.size > 1 ? "\n" : "" # visual file separator
|
55
|
-
ARGV.each {|i|
|
56
|
-
begin
|
57
|
-
t = BEncode.load_file i
|
58
|
-
rescue
|
59
|
-
STDERR.puts "#{File.basename i}: #{$!}"
|
60
|
-
ec += 1
|
61
|
-
next
|
62
|
-
end
|
63
|
-
|
64
|
-
puts visfilesep + 'FILE: ' + File.basename(i)
|
65
|
-
if $conf[:dump]
|
66
|
-
pp t
|
67
|
-
next
|
68
|
-
end
|
69
|
-
enc = t['encoding'].to_s
|
70
|
-
|
71
|
-
t.each {|k,v|
|
72
|
-
case k
|
73
|
-
when "announce-list"
|
74
|
-
puts k + (v.size == 0 ? ':' : ":\n\t" + v.join("\n\t"))
|
75
|
-
when "info"
|
76
|
-
v.each {|info, infoval|
|
77
|
-
case info
|
78
|
-
when /piece/
|
79
|
-
next # a big unredable blob
|
80
|
-
when "files"
|
81
|
-
total = 0
|
82
|
-
puts "files (#{infoval.size}): "
|
83
|
-
|
84
|
-
biggest = 0
|
85
|
-
infoval.each {|i|
|
86
|
-
biggest = i['length'] if biggest < i['length']
|
87
|
-
total += i['length']
|
88
|
-
}
|
89
|
-
biggest = dn(biggest)
|
90
|
-
|
91
|
-
infoval.each {|i|
|
92
|
-
printf(" %#{biggest.size}s %s\n",
|
93
|
-
dn(i['length']), ds(i['path'].join('/'), enc))
|
94
|
-
}
|
95
|
-
puts 'length: ' + dn(total)
|
96
|
-
else
|
97
|
-
puts info + ': ' + ds(infoval, enc)
|
98
|
-
end
|
99
|
-
}
|
100
|
-
when /date/
|
101
|
-
puts k + ': ' + ddate(v)
|
102
|
-
else
|
103
|
-
puts k + ': ' + ds(v, enc)
|
104
|
-
end
|
105
|
-
}
|
106
|
-
}
|
107
|
-
exit ec
|