oso 1.0.0 → 1.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/.rvmrc +1 -0
- data/CHANGELOG.rdoc +5 -0
- data/Gemfile +19 -0
- data/Gemfile.lock +49 -0
- data/Manifest.txt +5 -1
- data/README.rdoc +13 -11
- data/lib/oso.rb +2 -2
- data/lib/oso/public/jquery.ago.js +31 -0
- data/lib/oso/server.rb +23 -3
- data/lib/oso/views/layout.rhtml +6 -0
- data/lib/oso/views/stat.rhtml +14 -0
- data/lib/oso/views/stats.rhtml +7 -8
- data/test/test_oso.rb +2 -2
- metadata +41 -7
- data/.gems +0 -4
- data/.gemtest +0 -0
data/.rvmrc
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
rvm use --create ree-1.8.7-2011.01@audiosocket-oso
|
data/CHANGELOG.rdoc
CHANGED
data/Gemfile
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
source :rubygems
|
2
|
+
|
3
|
+
gem "new_base_60", "1.0.3"
|
4
|
+
gem "rack", "1.2.1"
|
5
|
+
gem "redis-namespace", "0.10.0"
|
6
|
+
gem "sinatra", "1.1.2"
|
7
|
+
|
8
|
+
group :development do
|
9
|
+
gem "heroku"
|
10
|
+
gem "hoe"
|
11
|
+
gem "hoe-doofus"
|
12
|
+
gem "hoe-git"
|
13
|
+
end
|
14
|
+
|
15
|
+
group :test do
|
16
|
+
gem "fakeweb", "1.3.0"
|
17
|
+
gem "minitest", "2.0.2"
|
18
|
+
gem "mocha", "0.9.12"
|
19
|
+
end
|
data/Gemfile.lock
ADDED
@@ -0,0 +1,49 @@
|
|
1
|
+
GEM
|
2
|
+
remote: http://rubygems.org/
|
3
|
+
specs:
|
4
|
+
activesupport (3.0.5)
|
5
|
+
configuration (1.2.0)
|
6
|
+
fakeweb (1.3.0)
|
7
|
+
heroku (1.19.1)
|
8
|
+
activesupport (>= 2.1.0)
|
9
|
+
launchy (~> 0.3.2)
|
10
|
+
rest-client (>= 1.4.0, < 1.7.0)
|
11
|
+
hoe (2.8.0)
|
12
|
+
rake (>= 0.8.7)
|
13
|
+
hoe-doofus (1.0.0)
|
14
|
+
hoe-git (1.3.0)
|
15
|
+
hoe (>= 2.2.0)
|
16
|
+
launchy (0.3.7)
|
17
|
+
configuration (>= 0.0.5)
|
18
|
+
rake (>= 0.8.1)
|
19
|
+
mime-types (1.16)
|
20
|
+
minitest (2.0.2)
|
21
|
+
mocha (0.9.12)
|
22
|
+
new_base_60 (1.0.3)
|
23
|
+
rack (1.2.1)
|
24
|
+
rake (0.8.7)
|
25
|
+
redis (2.1.1)
|
26
|
+
redis-namespace (0.10.0)
|
27
|
+
redis (< 3.0.0)
|
28
|
+
rest-client (1.6.1)
|
29
|
+
mime-types (>= 1.16)
|
30
|
+
sinatra (1.1.2)
|
31
|
+
rack (~> 1.1)
|
32
|
+
tilt (~> 1.2)
|
33
|
+
tilt (1.2.2)
|
34
|
+
|
35
|
+
PLATFORMS
|
36
|
+
ruby
|
37
|
+
|
38
|
+
DEPENDENCIES
|
39
|
+
fakeweb (= 1.3.0)
|
40
|
+
heroku
|
41
|
+
hoe
|
42
|
+
hoe-doofus
|
43
|
+
hoe-git
|
44
|
+
minitest (= 2.0.2)
|
45
|
+
mocha (= 0.9.12)
|
46
|
+
new_base_60 (= 1.0.3)
|
47
|
+
rack (= 1.2.1)
|
48
|
+
redis-namespace (= 0.10.0)
|
49
|
+
sinatra (= 1.1.2)
|
data/Manifest.txt
CHANGED
@@ -1,5 +1,7 @@
|
|
1
|
-
.
|
1
|
+
.rvmrc
|
2
2
|
CHANGELOG.rdoc
|
3
|
+
Gemfile
|
4
|
+
Gemfile.lock
|
3
5
|
Manifest.txt
|
4
6
|
README.rdoc
|
5
7
|
Rakefile
|
@@ -9,9 +11,11 @@ lib/oso/public/audiosocket.png
|
|
9
11
|
lib/oso/public/favicon.ico
|
10
12
|
lib/oso/public/index.css
|
11
13
|
lib/oso/public/index.html
|
14
|
+
lib/oso/public/jquery.ago.js
|
12
15
|
lib/oso/public/robots.txt
|
13
16
|
lib/oso/public/style.css
|
14
17
|
lib/oso/server.rb
|
15
18
|
lib/oso/views/layout.rhtml
|
19
|
+
lib/oso/views/stat.rhtml
|
16
20
|
lib/oso/views/stats.rhtml
|
17
21
|
test/test_oso.rb
|
data/README.rdoc
CHANGED
@@ -9,11 +9,11 @@ three letters look a bit like our logo.
|
|
9
9
|
|
10
10
|
== Configuring
|
11
11
|
|
12
|
-
|
13
|
-
|
12
|
+
Oso has a <tt>.rvmrc</tt> because it's useful in our dev process. We
|
13
|
+
know it's annoying for you.
|
14
14
|
|
15
|
-
If you install
|
16
|
-
|
15
|
+
If you run <tt>bundle install</tt> you can launch <tt>rackup</tt> by
|
16
|
+
itself.
|
17
17
|
|
18
18
|
Oso needs Redis. Set the <tt>OSO_REDIS_URL</tt> environment variable,
|
19
19
|
which defaults to <tt>redis://localhost:6379</tt>. All keys are
|
@@ -29,8 +29,8 @@ to <tt>/</tt> with a <tt>url</tt> parameter. It'll return a
|
|
29
29
|
You can optionally pass a <tt>life</tt> parameter, which is the
|
30
30
|
lifetime of the shortened URL in seconds.
|
31
31
|
|
32
|
-
You can optionally pass a <tt>limit</tt> parameter, which is the
|
33
|
-
of times you want the shortened URL to work. After the limit is
|
32
|
+
You can optionally pass a <tt>limit</tt> parameter, which is the
|
33
|
+
number of times you want the shortened URL to work. After the limit is
|
34
34
|
reached <tt>404</tt>'s are returned.
|
35
35
|
|
36
36
|
You can optionally pass a <tt>name</tt> parameter, which will be used
|
@@ -43,8 +43,8 @@ If you install the <tt>oso</tt> RubyGem:
|
|
43
43
|
|
44
44
|
require "oso"
|
45
45
|
|
46
|
-
Oso.shorten "github.com"
|
47
|
-
Oso.shorten "github.com", life
|
46
|
+
Oso.shorten "github.com" # => "http://oso.local/Acf"
|
47
|
+
Oso.shorten "github.com", :life => 30 # => "http://oso.local/Ad0"
|
48
48
|
|
49
49
|
Set the <tt>OSO_URL</tt> environment variable to control where the
|
50
50
|
client looks for the server, or see the RDocs for information on
|
@@ -53,8 +53,10 @@ creating multiple instances.
|
|
53
53
|
== Deploying
|
54
54
|
|
55
55
|
If you fork it, Oso is already prepped for Heroku. It has an
|
56
|
-
up-to-date <tt
|
57
|
-
<tt>REDISTOGO_URL</tt> env var if it exists.
|
56
|
+
up-to-date <tt>Gemfile.lock</tt>, and it'll use the
|
57
|
+
<tt>REDISTOGO_URL</tt> env var if it exists. You'll probably want to
|
58
|
+
set the <tt>BUNDLE_WITHOUT</tt> env var to exclude the
|
59
|
+
<tt>development</tt> and <tt>test</tt> groups.
|
58
60
|
|
59
61
|
If you'd like to use it in your own <tt>config.ru</tt> file via the
|
60
62
|
gem, you'll need to provide the server's dependencies yourself. The
|
@@ -62,7 +64,7 @@ gem doesn't express any runtime dependencies since it's primarily used
|
|
62
64
|
as a client.
|
63
65
|
|
64
66
|
Assuming you've provided the server dependencies (see the
|
65
|
-
<tt
|
67
|
+
<tt>Gemfile</tt>), using the gem from Rack is simple:
|
66
68
|
|
67
69
|
require "oso/server"
|
68
70
|
run Sinatra::Application
|
data/lib/oso.rb
CHANGED
@@ -13,7 +13,7 @@ class Oso
|
|
13
13
|
|
14
14
|
# Duh.
|
15
15
|
|
16
|
-
VERSION = "1.0.
|
16
|
+
VERSION = "1.0.1"
|
17
17
|
|
18
18
|
# :nodoc:
|
19
19
|
|
@@ -58,7 +58,7 @@ class Oso
|
|
58
58
|
# conditions keep +url+ from being shortened in one second.
|
59
59
|
|
60
60
|
def shorten url, options = {}
|
61
|
-
params = options.merge url
|
61
|
+
params = options.merge :url => url
|
62
62
|
|
63
63
|
params[:life] &&= params[:life].to_i
|
64
64
|
params[:limit] &&= params[:limit].to_i
|
@@ -0,0 +1,31 @@
|
|
1
|
+
(function($) {
|
2
|
+
$.fn.ago = function() {
|
3
|
+
var now = parseInt((new Date()).getTime() / 1000)
|
4
|
+
|
5
|
+
return this.each(function() {
|
6
|
+
var then = parseInt($(this).attr("data-at"), 10)
|
7
|
+
var delta = now - then
|
8
|
+
var message = "" + delta + " seconds ago"
|
9
|
+
|
10
|
+
if (delta < 30)
|
11
|
+
message = "just now"
|
12
|
+
|
13
|
+
else if (delta >= 60 && delta < 120)
|
14
|
+
message = "a minute ago"
|
15
|
+
|
16
|
+
else if (delta >= 120 && delta < 3300)
|
17
|
+
message = "" + parseInt(delta / 60) + " minutes ago"
|
18
|
+
|
19
|
+
else if (delta >= 3300 && delta < 3600)
|
20
|
+
message = "almost an hour ago"
|
21
|
+
|
22
|
+
else if (delta >= 3600) {
|
23
|
+
var hours = parseInt(delta / 3600)
|
24
|
+
var unit = hours > 1 ? "hours" : "hour"
|
25
|
+
message = "" + hours + " " + unit + " ago"
|
26
|
+
}
|
27
|
+
|
28
|
+
$(this).html(message)
|
29
|
+
})
|
30
|
+
}
|
31
|
+
})(jQuery)
|
data/lib/oso/server.rb
CHANGED
@@ -6,8 +6,10 @@ require "uri"
|
|
6
6
|
url = ENV.values_at("OSO_REDIS_URL", "REDISTOGO_URL").compact.first
|
7
7
|
url = URI.parse url || "redis://localhost:6379"
|
8
8
|
|
9
|
-
$redis = Redis::Namespace.new
|
10
|
-
|
9
|
+
$redis = Redis::Namespace.new(:oso,
|
10
|
+
:redis => Redis.new(:host => url.host,
|
11
|
+
:password => url.password,
|
12
|
+
:port => url.port))
|
11
13
|
|
12
14
|
helpers do
|
13
15
|
def bad! message
|
@@ -36,6 +38,11 @@ helpers do
|
|
36
38
|
end
|
37
39
|
end
|
38
40
|
|
41
|
+
def shorten str
|
42
|
+
return str unless str.length > 40
|
43
|
+
str[0, 37] + "..."
|
44
|
+
end
|
45
|
+
|
39
46
|
def shorturl short
|
40
47
|
request.path_info = "/#{short}"
|
41
48
|
request.url
|
@@ -54,7 +61,8 @@ get "/stats" do
|
|
54
61
|
@bytimes = Hash[*$redis.zrevrange("by:time", 0, 10, :with_scores => true)]
|
55
62
|
|
56
63
|
[@byhits, @bytimes].each do |h|
|
57
|
-
h.
|
64
|
+
h.select! { |k, v| $redis.exists "short:#{k}" }
|
65
|
+
h.each { |k, v| h[k] = { :long => $redis.get("short:#{k}"), :score => v } }
|
58
66
|
end
|
59
67
|
|
60
68
|
@title = "Stats"
|
@@ -105,3 +113,15 @@ get "/:short" do |short|
|
|
105
113
|
|
106
114
|
redirect long
|
107
115
|
end
|
116
|
+
|
117
|
+
get "/:short/stats" do |short|
|
118
|
+
nope! unless @long = $redis.get("short:#{short}")
|
119
|
+
|
120
|
+
@short = short
|
121
|
+
@hits = $redis.zscore("by:hits", short).to_i
|
122
|
+
@limit = $redis.get("short:#{short}:limit").to_i
|
123
|
+
@time = $redis.zscore("by:time", short).to_i
|
124
|
+
|
125
|
+
@title = "Stats :: #@short"
|
126
|
+
erb :stat
|
127
|
+
end
|
data/lib/oso/views/layout.rhtml
CHANGED
@@ -18,5 +18,11 @@
|
|
18
18
|
|
19
19
|
<script type="text/javascript"
|
20
20
|
src="http://code.jquery.com/jquery-1.5.min.js"></script>
|
21
|
+
|
22
|
+
<script type="text/javascript" src="/jquery.ago.js"></script>
|
23
|
+
|
24
|
+
<script type="text/javascript">
|
25
|
+
$(function() { $("[data-at]").ago() })
|
26
|
+
</script>
|
21
27
|
</body>
|
22
28
|
</html>
|
@@ -0,0 +1,14 @@
|
|
1
|
+
<p>
|
2
|
+
<a href="<%= shorturl @short %>"><%= @short %></a> points at
|
3
|
+
<a href="<%= @long %>"><%= shorten @long %></a>.
|
4
|
+
|
5
|
+
<% if @hits > 0 %>
|
6
|
+
It's been hit <b><%= @hits %></b> time<%= "s" if @hits != 1 %>,
|
7
|
+
most recently <b data-at="<%= @time %>">timestamp</b>.
|
8
|
+
<% end %>
|
9
|
+
|
10
|
+
<% if @limit > 0 %>
|
11
|
+
It can be hit <b><%= @limit %> more time<%= "s" if @limit != 1 %></b>
|
12
|
+
before it disappears.
|
13
|
+
<% end %>
|
14
|
+
</p>
|
data/lib/oso/views/stats.rhtml
CHANGED
@@ -30,18 +30,17 @@
|
|
30
30
|
<tbody>
|
31
31
|
<% @bytimes.each do |short, data| %>
|
32
32
|
<tr>
|
33
|
-
<td
|
34
|
-
<td><a href="<%= data[:long] %>"><%= data[:long] %></a></td>
|
33
|
+
<td data-at="<%= data[:score] %>">time</td>
|
34
|
+
<td><a href="<%= data[:long] %>"><%= shorten data[:long] %></a></td>
|
35
35
|
<td><a href="<%= shorturl(short) %>"><%= shorturl(short) %></a></td>
|
36
36
|
</tr>
|
37
37
|
<% end %>
|
38
38
|
</tbody>
|
39
|
-
</table>
|
40
|
-
|
41
|
-
<h2>Most Hits</h2>
|
42
|
-
|
43
|
-
<table cellspacing="0">
|
44
39
|
<thead>
|
40
|
+
<tr colspan="3">
|
41
|
+
<td><h2>Most Hits</h2></td>
|
42
|
+
</tr>
|
43
|
+
|
45
44
|
<tr>
|
46
45
|
<th>Hits</th>
|
47
46
|
<th>URL</th>
|
@@ -53,7 +52,7 @@
|
|
53
52
|
<% @byhits.each do |short, data| %>
|
54
53
|
<tr>
|
55
54
|
<td><%= data[:score] %></td>
|
56
|
-
<td><a href="<%= data[:long] %>"><%= data[:long] %></a></td>
|
55
|
+
<td><a href="<%= data[:long] %>"><%= shorten data[:long] %></a></td>
|
57
56
|
<td><a href="<%= shorturl(short) %>"><%= shorturl(short) %></a></td>
|
58
57
|
</tr>
|
59
58
|
<% end %>
|
data/test/test_oso.rb
CHANGED
@@ -34,7 +34,7 @@ class TestOso < MiniTest::Unit::TestCase
|
|
34
34
|
|
35
35
|
def test_shorten
|
36
36
|
FakeWeb.register_uri :post, "http://example.org/",
|
37
|
-
body
|
37
|
+
:body => "http://example.org/1", :status => 201
|
38
38
|
|
39
39
|
oso = Oso.new "example.org"
|
40
40
|
|
@@ -43,7 +43,7 @@ class TestOso < MiniTest::Unit::TestCase
|
|
43
43
|
|
44
44
|
def test_shorten_bad
|
45
45
|
FakeWeb.register_uri :post, "http://example.org/",
|
46
|
-
body
|
46
|
+
:body => "No luck.", :status => 404
|
47
47
|
|
48
48
|
oso = Oso.new "example.org"
|
49
49
|
|
metadata
CHANGED
@@ -1,8 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: oso
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
|
5
|
-
|
4
|
+
hash: 21
|
5
|
+
prerelease: false
|
6
|
+
segments:
|
7
|
+
- 1
|
8
|
+
- 0
|
9
|
+
- 1
|
10
|
+
version: 1.0.1
|
6
11
|
platform: ruby
|
7
12
|
authors:
|
8
13
|
- Audiosocket
|
@@ -10,7 +15,7 @@ autorequire:
|
|
10
15
|
bindir: bin
|
11
16
|
cert_chain: []
|
12
17
|
|
13
|
-
date: 2011-
|
18
|
+
date: 2011-03-28 00:00:00 -05:00
|
14
19
|
default_executable:
|
15
20
|
dependencies:
|
16
21
|
- !ruby/object:Gem::Dependency
|
@@ -21,6 +26,11 @@ dependencies:
|
|
21
26
|
requirements:
|
22
27
|
- - "="
|
23
28
|
- !ruby/object:Gem::Version
|
29
|
+
hash: 27
|
30
|
+
segments:
|
31
|
+
- 1
|
32
|
+
- 3
|
33
|
+
- 0
|
24
34
|
version: 1.3.0
|
25
35
|
type: :development
|
26
36
|
version_requirements: *id001
|
@@ -32,6 +42,11 @@ dependencies:
|
|
32
42
|
requirements:
|
33
43
|
- - "="
|
34
44
|
- !ruby/object:Gem::Version
|
45
|
+
hash: 11
|
46
|
+
segments:
|
47
|
+
- 2
|
48
|
+
- 0
|
49
|
+
- 2
|
35
50
|
version: 2.0.2
|
36
51
|
type: :development
|
37
52
|
version_requirements: *id002
|
@@ -43,6 +58,11 @@ dependencies:
|
|
43
58
|
requirements:
|
44
59
|
- - "="
|
45
60
|
- !ruby/object:Gem::Version
|
61
|
+
hash: 35
|
62
|
+
segments:
|
63
|
+
- 0
|
64
|
+
- 9
|
65
|
+
- 12
|
46
66
|
version: 0.9.12
|
47
67
|
type: :development
|
48
68
|
version_requirements: *id003
|
@@ -54,7 +74,12 @@ dependencies:
|
|
54
74
|
requirements:
|
55
75
|
- - ">="
|
56
76
|
- !ruby/object:Gem::Version
|
57
|
-
|
77
|
+
hash: 47
|
78
|
+
segments:
|
79
|
+
- 2
|
80
|
+
- 8
|
81
|
+
- 0
|
82
|
+
version: 2.8.0
|
58
83
|
type: :development
|
59
84
|
version_requirements: *id004
|
60
85
|
description: |-
|
@@ -72,8 +97,10 @@ extra_rdoc_files:
|
|
72
97
|
- CHANGELOG.rdoc
|
73
98
|
- README.rdoc
|
74
99
|
files:
|
75
|
-
- .
|
100
|
+
- .rvmrc
|
76
101
|
- CHANGELOG.rdoc
|
102
|
+
- Gemfile
|
103
|
+
- Gemfile.lock
|
77
104
|
- Manifest.txt
|
78
105
|
- README.rdoc
|
79
106
|
- Rakefile
|
@@ -83,13 +110,14 @@ files:
|
|
83
110
|
- lib/oso/public/favicon.ico
|
84
111
|
- lib/oso/public/index.css
|
85
112
|
- lib/oso/public/index.html
|
113
|
+
- lib/oso/public/jquery.ago.js
|
86
114
|
- lib/oso/public/robots.txt
|
87
115
|
- lib/oso/public/style.css
|
88
116
|
- lib/oso/server.rb
|
89
117
|
- lib/oso/views/layout.rhtml
|
118
|
+
- lib/oso/views/stat.rhtml
|
90
119
|
- lib/oso/views/stats.rhtml
|
91
120
|
- test/test_oso.rb
|
92
|
-
- .gemtest
|
93
121
|
has_rdoc: true
|
94
122
|
homepage: http://github.com/audiosocket/oso
|
95
123
|
licenses: []
|
@@ -105,17 +133,23 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
105
133
|
requirements:
|
106
134
|
- - ">="
|
107
135
|
- !ruby/object:Gem::Version
|
136
|
+
hash: 3
|
137
|
+
segments:
|
138
|
+
- 0
|
108
139
|
version: "0"
|
109
140
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
110
141
|
none: false
|
111
142
|
requirements:
|
112
143
|
- - ">="
|
113
144
|
- !ruby/object:Gem::Version
|
145
|
+
hash: 3
|
146
|
+
segments:
|
147
|
+
- 0
|
114
148
|
version: "0"
|
115
149
|
requirements: []
|
116
150
|
|
117
151
|
rubyforge_project: oso
|
118
|
-
rubygems_version: 1.
|
152
|
+
rubygems_version: 1.3.7
|
119
153
|
signing_key:
|
120
154
|
specification_version: 3
|
121
155
|
summary: Audiosocket's minimal URL shortener
|
data/.gems
DELETED
data/.gemtest
DELETED
File without changes
|