sinatra-s3 0.98
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.
- data/README +23 -0
- data/Rakefile +51 -0
- data/bin/sinatra-s3 +30 -0
- data/db/migrate/001_create_bits.rb +28 -0
- data/db/migrate/002_create_users.rb +24 -0
- data/db/migrate/003_create_bits_users.rb +16 -0
- data/db/migrate/004_create_torrents.rb +22 -0
- data/db/migrate/005_create_torrent_peers.rb +26 -0
- data/examples/README +9 -0
- data/examples/wiki.rb +199 -0
- data/examples/wiki.ru +5 -0
- data/examples/wikicloth/MIT-LICENSE +20 -0
- data/examples/wikicloth/README +81 -0
- data/examples/wikicloth/Rakefile +23 -0
- data/examples/wikicloth/init.rb +1 -0
- data/examples/wikicloth/install.rb +0 -0
- data/examples/wikicloth/lib/core_ext.rb +43 -0
- data/examples/wikicloth/lib/wiki_buffer/html_element.rb +237 -0
- data/examples/wikicloth/lib/wiki_buffer/link.rb +70 -0
- data/examples/wikicloth/lib/wiki_buffer/table.rb +159 -0
- data/examples/wikicloth/lib/wiki_buffer/var.rb +77 -0
- data/examples/wikicloth/lib/wiki_buffer.rb +279 -0
- data/examples/wikicloth/lib/wiki_cloth.rb +61 -0
- data/examples/wikicloth/lib/wiki_link_handler.rb +138 -0
- data/examples/wikicloth/lib/wikicloth.rb +5 -0
- data/examples/wikicloth/run_tests.rb +48 -0
- data/examples/wikicloth/sample_documents/air_force_one.wiki +170 -0
- data/examples/wikicloth/sample_documents/cheatsheet.wiki +205 -0
- data/examples/wikicloth/sample_documents/default.css +34 -0
- data/examples/wikicloth/sample_documents/elements.wiki +7 -0
- data/examples/wikicloth/sample_documents/george_washington.wiki +526 -0
- data/examples/wikicloth/sample_documents/images.wiki +15 -0
- data/examples/wikicloth/sample_documents/lists.wiki +421 -0
- data/examples/wikicloth/sample_documents/pipe_trick.wiki +68 -0
- data/examples/wikicloth/sample_documents/random.wiki +55 -0
- data/examples/wikicloth/sample_documents/tv.wiki +312 -0
- data/examples/wikicloth/sample_documents/wiki.png +0 -0
- data/examples/wikicloth/sample_documents/wiki_tables.wiki +410 -0
- data/examples/wikicloth/tasks/wikicloth_tasks.rake +0 -0
- data/examples/wikicloth/test/test_helper.rb +3 -0
- data/examples/wikicloth/test/wiki_cloth_test.rb +8 -0
- data/examples/wikicloth/uninstall.rb +0 -0
- data/examples/wikicloth/wikicloth-0.1.3.gem +0 -0
- data/examples/wikicloth/wikicloth.gemspec +69 -0
- data/lib/sinatra-s3/admin.rb +626 -0
- data/lib/sinatra-s3/base.rb +526 -0
- data/lib/sinatra-s3/errors.rb +51 -0
- data/lib/sinatra-s3/ext.rb +20 -0
- data/lib/sinatra-s3/helpers/acp.rb +100 -0
- data/lib/sinatra-s3/helpers/admin.rb +41 -0
- data/lib/sinatra-s3/helpers/tracker.rb +42 -0
- data/lib/sinatra-s3/helpers/versioning.rb +27 -0
- data/lib/sinatra-s3/helpers.rb +79 -0
- data/lib/sinatra-s3/models/bit.rb +180 -0
- data/lib/sinatra-s3/models/bucket.rb +81 -0
- data/lib/sinatra-s3/models/file_info.rb +3 -0
- data/lib/sinatra-s3/models/git_bucket.rb +3 -0
- data/lib/sinatra-s3/models/slot.rb +47 -0
- data/lib/sinatra-s3/models/torrent.rb +6 -0
- data/lib/sinatra-s3/models/torrent_peer.rb +5 -0
- data/lib/sinatra-s3/models/user.rb +35 -0
- data/lib/sinatra-s3/s3.rb +57 -0
- data/lib/sinatra-s3/tasks.rb +62 -0
- data/lib/sinatra-s3/tracker.rb +134 -0
- data/lib/sinatra-s3.rb +1 -0
- data/public/css/control.css +225 -0
- data/public/css/wiki.css +47 -0
- data/public/images/external-link.gif +0 -0
- data/public/js/prototype.js +2539 -0
- data/public/js/upload_status.js +117 -0
- data/public/test.html +8 -0
- data/s3.yml.example +17 -0
- data/test/s3api_test.rb +121 -0
- data/test/test_helper.rb +25 -0
- metadata +156 -0
@@ -0,0 +1,134 @@
|
|
1
|
+
module S3
|
2
|
+
|
3
|
+
TRACKER_INTERVAL = 10.minutes
|
4
|
+
EVENT_CODES = {
|
5
|
+
'started' => 200,
|
6
|
+
'completed' => 201,
|
7
|
+
'stopped' => 202
|
8
|
+
}
|
9
|
+
# All tracker errors are thrown as this class.
|
10
|
+
class TrackerError < Exception; end
|
11
|
+
|
12
|
+
class Tracker < Sinatra::Base
|
13
|
+
|
14
|
+
helpers do
|
15
|
+
include S3::AdminHelpers
|
16
|
+
include S3::TrackerHelper
|
17
|
+
end
|
18
|
+
|
19
|
+
configure do
|
20
|
+
ActiveRecord::Base.establish_connection(S3.config[:db])
|
21
|
+
end
|
22
|
+
|
23
|
+
before do
|
24
|
+
ActiveRecord::Base.verify_active_connections!
|
25
|
+
end
|
26
|
+
|
27
|
+
get '/tracker/announce/?' do
|
28
|
+
raise TrackerError, "No info_hash present." unless params[:info_hash]
|
29
|
+
raise TrackerError, "No peer_id present." unless params[:peer_id]
|
30
|
+
|
31
|
+
info_hash = params[:info_hash].to_hex_s
|
32
|
+
guid = params[:peer_id].to_hex_s
|
33
|
+
trnt = Torrent.find_by_info_hash(info_hash)
|
34
|
+
raise TrackerError, "No file found with hash of `#{params[:info_hash]}'." unless trnt
|
35
|
+
|
36
|
+
peer = TorrentPeer.find_by_guid_and_torrent_id(guid, trnt.id)
|
37
|
+
unless peer
|
38
|
+
peer = TorrentPeer.find_by_ipaddr_and_port_and_torrent_id(env['REMOTE_ADDR'], params[:port], trnt.id)
|
39
|
+
end
|
40
|
+
unless peer
|
41
|
+
peer = TorrentPeer.new(:torrent_id => trnt.id)
|
42
|
+
trnt.hits += 1
|
43
|
+
end
|
44
|
+
|
45
|
+
trnt.total += 1 if params[:event] == "completed"
|
46
|
+
params[:event] = 'completed' if params[:left] == 0
|
47
|
+
if params[:event]
|
48
|
+
peer.update_attributes(:uploaded => params[:uploaded], :downloaded => params[:downloaded],
|
49
|
+
:remaining => params[:left], :event => EVENT_CODES[params[:event]], :key => params[:key],
|
50
|
+
:port => params[:port], :ipaddr => env['REMOTE_ADDR'], :guid => guid)
|
51
|
+
end
|
52
|
+
complete, incomplete = 0, 0
|
53
|
+
peers = trnt.torrent_peers.map do |peer|
|
54
|
+
if peer.updated_at < Time.now - (TRACKER_INTERVAL * 2) or (params[:event] == 'stopped' and peer.guid == guid)
|
55
|
+
peer.destroy
|
56
|
+
next
|
57
|
+
end
|
58
|
+
if peer.event == EVENT_CODES['completed']
|
59
|
+
complete += 1
|
60
|
+
else
|
61
|
+
incomplete += 1
|
62
|
+
end
|
63
|
+
next if peer.guid == guid
|
64
|
+
{'peer id' => peer.guid.from_hex_s, 'ip' => peer.ipaddr, 'port' => peer.port}
|
65
|
+
end.compact
|
66
|
+
trnt.seeders = complete
|
67
|
+
trnt.leechers = incomplete
|
68
|
+
trnt.save
|
69
|
+
tracker_reply('peers' => peers, 'complete' => complete, 'incomplete' => incomplete)
|
70
|
+
end
|
71
|
+
|
72
|
+
get '/tracker/scrape/?' do
|
73
|
+
@torrents = torrent_list params[:info_hash]
|
74
|
+
tracker_reply('files' => @torrents.map { |t|
|
75
|
+
{'complete' => t.seeders, 'downloaded' => t.total, 'incomplete' => t.leechers, 'name' => t.bit.name} })
|
76
|
+
end
|
77
|
+
|
78
|
+
get '/tracker/?' do
|
79
|
+
@torrents = torrent_list params[:info_hash]
|
80
|
+
@transfer = TorrentPeer.sum :downloaded, :group => :torrent
|
81
|
+
torrent_view
|
82
|
+
end
|
83
|
+
|
84
|
+
protected
|
85
|
+
def torrent_view
|
86
|
+
builder do |html|
|
87
|
+
html.html do
|
88
|
+
html.head do
|
89
|
+
html.title "Sinatra-S3 Torrents"
|
90
|
+
html.style "@import '/control/s/css/control.css';", :type => 'text/css'
|
91
|
+
end
|
92
|
+
end
|
93
|
+
html.div :id => "page" do
|
94
|
+
html.div :id => "header" do
|
95
|
+
html.h1 "Sinatra-S3 Tracker"
|
96
|
+
html.h2 "Active Torrents"
|
97
|
+
end
|
98
|
+
|
99
|
+
html.div :id => "content" do
|
100
|
+
html.body do
|
101
|
+
html.table do
|
102
|
+
html.thead do
|
103
|
+
html.tr do
|
104
|
+
html.th "Name"
|
105
|
+
html.th "Size"
|
106
|
+
html.th "Seeders"
|
107
|
+
html.th "Leechers"
|
108
|
+
html.th "Downloads"
|
109
|
+
html.th "Transfered"
|
110
|
+
html.th "Since"
|
111
|
+
end
|
112
|
+
end
|
113
|
+
html.tbody do
|
114
|
+
@torrents.each do |t|
|
115
|
+
html.tr do
|
116
|
+
html.td t.bit.name
|
117
|
+
html.td number_to_human_size(t.bit.size)
|
118
|
+
html.td t.seeders
|
119
|
+
html.td t.leechers
|
120
|
+
html.td t.total
|
121
|
+
html.td number_to_human_size(@transfer[t])
|
122
|
+
html.td RubyTorrent::MetaInfo.from_stream(StringIO.new(t.metainfo)).creation_date #t.metainfo.creation_date
|
123
|
+
end
|
124
|
+
end
|
125
|
+
end
|
126
|
+
end
|
127
|
+
end
|
128
|
+
end
|
129
|
+
end
|
130
|
+
end
|
131
|
+
end
|
132
|
+
end
|
133
|
+
|
134
|
+
end
|
data/lib/sinatra-s3.rb
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), 'sinatra-s3', 's3')
|
@@ -0,0 +1,225 @@
|
|
1
|
+
#progress-bar {
|
2
|
+
width:500px;
|
3
|
+
height:25px;
|
4
|
+
margin:15px 0px;
|
5
|
+
border:solid 1px #000;
|
6
|
+
position:relative;
|
7
|
+
}
|
8
|
+
|
9
|
+
#progress-bar #status-bar {
|
10
|
+
display:block;
|
11
|
+
height:25px;
|
12
|
+
width:0;
|
13
|
+
background-color:#3F7C5F;
|
14
|
+
border-right:solid 1px #000;
|
15
|
+
position:absolute;
|
16
|
+
top:0; left:0;
|
17
|
+
}
|
18
|
+
|
19
|
+
#progress-bar #status-text {
|
20
|
+
display:block;
|
21
|
+
padding: 0 15px;
|
22
|
+
line-height:25px;
|
23
|
+
position:absolute;
|
24
|
+
top:0; left:0;
|
25
|
+
}
|
26
|
+
|
27
|
+
body {
|
28
|
+
font-family: arial, helvetica, sans-serif;
|
29
|
+
font-size: 16px;
|
30
|
+
margin: 20px;
|
31
|
+
background-color: #f5f8e1;
|
32
|
+
text-align: center;
|
33
|
+
}
|
34
|
+
|
35
|
+
h1, h2, h3, h4, h5 {
|
36
|
+
font-weight: normal;
|
37
|
+
margin: 0; padding: 0;
|
38
|
+
}
|
39
|
+
|
40
|
+
h1 { font-size: 15px; color: #797; }
|
41
|
+
h2 { font-size: 34px; }
|
42
|
+
h3 { font-size: 26px; margin-top: 12px; }
|
43
|
+
h4 { font-size: 21px; }
|
44
|
+
|
45
|
+
#page {
|
46
|
+
width: 700px;
|
47
|
+
margin: 0 auto;
|
48
|
+
padding: 3px 20px;
|
49
|
+
border: solid 1px #d5d8c1;
|
50
|
+
background-color: white;
|
51
|
+
text-align: left;
|
52
|
+
}
|
53
|
+
|
54
|
+
#header, #content {
|
55
|
+
margin: 12px 0px;
|
56
|
+
}
|
57
|
+
|
58
|
+
.menu {
|
59
|
+
float: right;
|
60
|
+
font-size: 11px;
|
61
|
+
}
|
62
|
+
|
63
|
+
.menu ul {
|
64
|
+
list-style: none;
|
65
|
+
margin: 0; padding: 0;
|
66
|
+
}
|
67
|
+
|
68
|
+
.menu ul li {
|
69
|
+
display: inline;
|
70
|
+
margin: 0; padding: 0;
|
71
|
+
}
|
72
|
+
|
73
|
+
.menu ul li a {
|
74
|
+
color: black;
|
75
|
+
text-decoration: none;
|
76
|
+
margin: 0px 2px; padding: 3px 6px;
|
77
|
+
font-weight: bold;
|
78
|
+
background-color: #f1f4d8;
|
79
|
+
-moz-opacity: 0.92;
|
80
|
+
}
|
81
|
+
|
82
|
+
.menu ul li a.active {
|
83
|
+
background-color: #f1e428;
|
84
|
+
}
|
85
|
+
|
86
|
+
.menu ul li a:hover {
|
87
|
+
color: white;
|
88
|
+
background-color: #C13438;
|
89
|
+
}
|
90
|
+
|
91
|
+
ul.errors {
|
92
|
+
color: black;
|
93
|
+
background-color: #f1e428;
|
94
|
+
padding: 4px;
|
95
|
+
margin: 0 0 10px 0;
|
96
|
+
-moz-opacity: 0.80;
|
97
|
+
width: 250px;
|
98
|
+
list-style: none;
|
99
|
+
}
|
100
|
+
|
101
|
+
form.create {
|
102
|
+
padding: 0 0 10px 0;
|
103
|
+
}
|
104
|
+
|
105
|
+
form.create .required,
|
106
|
+
form.create .optional {
|
107
|
+
padding: 5px 0;
|
108
|
+
}
|
109
|
+
|
110
|
+
form.create label {
|
111
|
+
display: block;
|
112
|
+
color: #575;
|
113
|
+
font-size: 10px;
|
114
|
+
}
|
115
|
+
|
116
|
+
form.create div.inline input,
|
117
|
+
form.create div.inline label,
|
118
|
+
form.create div.inline select
|
119
|
+
{
|
120
|
+
display: inline;
|
121
|
+
width: auto;
|
122
|
+
}
|
123
|
+
|
124
|
+
form.create div input,
|
125
|
+
form.create div select {
|
126
|
+
font-size: 16px;
|
127
|
+
width: 250px;
|
128
|
+
padding: 1px;
|
129
|
+
}
|
130
|
+
|
131
|
+
form.create div input.fixed {
|
132
|
+
font-family: "Lucida Console", monospace;
|
133
|
+
}
|
134
|
+
|
135
|
+
form.create div input.large {
|
136
|
+
font-size: 21px;
|
137
|
+
font-weight: bold;
|
138
|
+
}
|
139
|
+
|
140
|
+
form.create div input.long {
|
141
|
+
width: 450px;
|
142
|
+
}
|
143
|
+
|
144
|
+
table {
|
145
|
+
border-collapse: collapse;
|
146
|
+
border: 2px solid #3f3c5f;
|
147
|
+
color: #000;
|
148
|
+
background: #fff;
|
149
|
+
width: 100%;
|
150
|
+
}
|
151
|
+
caption {
|
152
|
+
margin: 0.3em 0;
|
153
|
+
font-size: .7em;
|
154
|
+
font-weight: normal;
|
155
|
+
text-align: left;
|
156
|
+
color: #000;
|
157
|
+
background: transparent;
|
158
|
+
}
|
159
|
+
td, th {
|
160
|
+
border: 1px solid #336;
|
161
|
+
padding: 0.3em;
|
162
|
+
}
|
163
|
+
thead th {
|
164
|
+
border: 1px solid #336;
|
165
|
+
text-align: left;
|
166
|
+
font-weight: bold;
|
167
|
+
background-color: #f1f478;
|
168
|
+
color: #333;
|
169
|
+
}
|
170
|
+
tfoot th, tfoot td {
|
171
|
+
border: 1px solid #396;
|
172
|
+
text-align: left;
|
173
|
+
background: #e8e8cf;
|
174
|
+
}
|
175
|
+
tfoot th {
|
176
|
+
font-weight: bold;
|
177
|
+
}
|
178
|
+
tbody td a {
|
179
|
+
background: transparent;
|
180
|
+
color: #00c;
|
181
|
+
text-decoration: underline;
|
182
|
+
}
|
183
|
+
tbody td a:hover {
|
184
|
+
background: transparent;
|
185
|
+
color: #00c;
|
186
|
+
text-decoration: underline;
|
187
|
+
}
|
188
|
+
tbody tr:hover th {
|
189
|
+
background-color: #c66;
|
190
|
+
}
|
191
|
+
tbody tr:hover th a {
|
192
|
+
color: white;
|
193
|
+
}
|
194
|
+
tbody th a {
|
195
|
+
background: transparent;
|
196
|
+
color: #3f7c5f;
|
197
|
+
text-decoration: underline;
|
198
|
+
font-weight: normal;
|
199
|
+
}
|
200
|
+
tbody th, tbody td {
|
201
|
+
vertical-align: top;
|
202
|
+
text-align: left;
|
203
|
+
font-size: 15px;
|
204
|
+
}
|
205
|
+
tfoot td {
|
206
|
+
border: 1px solid #996;
|
207
|
+
}
|
208
|
+
tbody tr:hover {
|
209
|
+
background: #efffd9;
|
210
|
+
}
|
211
|
+
tbody th:hover p {
|
212
|
+
color: #fec;
|
213
|
+
}
|
214
|
+
tbody th p {
|
215
|
+
font-size: 12px;
|
216
|
+
font-weight: normal;
|
217
|
+
margin: 4px 0;
|
218
|
+
}
|
219
|
+
.details {
|
220
|
+
padding-left: 12px;
|
221
|
+
}
|
222
|
+
.details p {
|
223
|
+
font-size: 10px;
|
224
|
+
line-height: 110%;
|
225
|
+
}
|
data/public/css/wiki.css
ADDED
@@ -0,0 +1,47 @@
|
|
1
|
+
.exlink { padding-right:15px;background:transparent url(/control/s/images/external-link.gif) no-repeat center right }
|
2
|
+
#title { text-decoration:none;font-weight:bold;color:#000 }
|
3
|
+
.thumb { background-color:#F8FCFF;border:1px solid #fff;margin-bottom:0.5em }
|
4
|
+
.tright { border-width:0.5em 0 0.8em 1.4em;margin:0.5em 0 0.8em 1.4em;clear:right;float:right }
|
5
|
+
.thumbinner {
|
6
|
+
background-color:#F9F9F9;
|
7
|
+
border:1px solid #CCCCCC;
|
8
|
+
font-size:94%;
|
9
|
+
overflow:hidden;
|
10
|
+
padding:3px !important;
|
11
|
+
text-align:center;
|
12
|
+
}
|
13
|
+
.thumbimage { border:1px solid #CCCCCC }
|
14
|
+
ins,del { display:block }
|
15
|
+
ins { text-decoration:none }
|
16
|
+
#page h1, #page h2, #page h3, #page h4, #page h5, #page h6 {
|
17
|
+
padding-bottom:0.17em;
|
18
|
+
padding-top:0.5em;
|
19
|
+
color:#000;
|
20
|
+
}
|
21
|
+
#page h1 { border-bottom:1px solid #AAAAAA; }
|
22
|
+
.editsection {
|
23
|
+
font-size:76%;
|
24
|
+
font-weight:normal;
|
25
|
+
}
|
26
|
+
.editsection {
|
27
|
+
display:none;
|
28
|
+
float:right;
|
29
|
+
margin-left:5px;
|
30
|
+
}
|
31
|
+
|
32
|
+
pre {
|
33
|
+
background-color:#F9F9F9;
|
34
|
+
border:1px dashed #2F6FAB;
|
35
|
+
color:black;
|
36
|
+
line-height:1.1em;
|
37
|
+
padding:1em;
|
38
|
+
white-space: pre-wrap; /* css-3 */
|
39
|
+
white-space: -moz-pre-wrap; /* Mozilla, since 1999 */
|
40
|
+
white-space: -pre-wrap; /* Opera 4-6 */
|
41
|
+
white-space: -o-pre-wrap; /* Opera 7 */
|
42
|
+
word-wrap: break-word; /* Internet Explorer 5.5+ */
|
43
|
+
}
|
44
|
+
#header { text-align:left;padding:10px 0;width:700px;margin:0 auto }
|
45
|
+
#page #revision_history { border:0px;margin:15px 0 }
|
46
|
+
#revision_history td, #revision_history th { border:0px }
|
47
|
+
#revision_history .check { width:1.5em;text-align:center }
|
Binary file
|