departr 0.4 → 0.6

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 ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 40696450d3edaf3459d98c4b571d36420337fc50
4
+ data.tar.gz: ea3887c825338d06d7213b2ff8aefdcbaec8d5d7
5
+ SHA512:
6
+ metadata.gz: 63a264efb01f7aa9e446433f47a04385a4f434dc6d94e04228bc655970d3cd68adfdd2d1fa8ead0fbc454924a9c3e4bb0c45af852d18d355e0483854803bb30d
7
+ data.tar.gz: e8b0bb98b8aceaaff2e52747391d37d6560249f8cb32c46bf4fec59d03478748649e3cfb1a37a2ba78edb899d93479bad258a2fe3e3bc825476eb09c4f2fb147
data/.gitignore ADDED
@@ -0,0 +1,7 @@
1
+ config.ru
2
+ Gemfile.lock
3
+ .bundle
4
+ public/images
5
+ lib/images.msh
6
+ log
7
+ .DS_Store
data/README.md CHANGED
@@ -7,12 +7,18 @@ Departr is a smart and fast startpage to help you reach other web sites.
7
7
  It's up and running here http://departr.solt.biz/
8
8
 
9
9
  Anyway, it's look like that :
10
- ![Screenshot](https://github.com/florentsolt/departr/raw/master/screenshot.png)
10
+ ![Screenshot](https://github.com/florentsolt/departr/raw/master/screenshot.jpg)
11
11
 
12
12
  # How to install
13
13
 
14
14
  gem install departr
15
15
 
16
+ Then, run the departr-images to fetch backgrounds (you can run this task every day):
17
+
18
+ departr-images 500PX_CONSUMER_KEY 500PX_CONSUMER_SECRET 500PX_USERNAME 500PX_PASSWORD
19
+
20
+ You need to go there to regirster an application http://500px.com/settings/applications.
21
+
16
22
  All you need now it to open your favorite code editor and create a file `config.ru` that looks like https://github.com/florentsolt/departr/blob/master/config.ru.example
17
23
  Do not forget to create a RPX account on http://www.janrain.com/ and fill the config under the `rpx` section with your account infos.
18
24
 
@@ -22,4 +28,4 @@ Then run it :
22
28
 
23
29
  Or :
24
30
 
25
- rackup
31
+ rackup
@@ -0,0 +1,78 @@
1
+ #!/usr/bin/env ruby
2
+ require 'oauth'
3
+ require 'json'
4
+
5
+ if ARGV.size != 4
6
+ puts "Usage: #{$0} CONSUMER_KEY CONSUMER_SECRET USERNAME PASSWORD"
7
+ exit
8
+ end
9
+
10
+ CONSUMER_KEY = ARGV.shift
11
+ CONSUMER_SECRET = ARGV.shift
12
+ BASE_URL = 'https://api.500px.com'
13
+ USERNAME = ARGV.shift
14
+ PASSWORD = ARGV.shift
15
+
16
+
17
+ consumer = OAuth::Consumer.new(CONSUMER_KEY, CONSUMER_SECRET, {
18
+ :site => BASE_URL,
19
+ :request_token_path => "/v1/oauth/request_token",
20
+ :access_token_path => "/v1/oauth/access_token",
21
+ :authorize_path => "/v1/oauth/authorize"})
22
+
23
+ request_token = consumer.get_request_token()
24
+ access_token = consumer.get_access_token(request_token, {}, {
25
+ :x_auth_mode => 'client_auth',
26
+ :x_auth_username => USERNAME,
27
+ :x_auth_password => PASSWORD})
28
+
29
+ photos = []
30
+ 1.upto(4) do |page|
31
+ data = JSON.parse(access_token.get("/v1/photos?rpp=100&feature=editors&image_size=2048&only=Landscapes&page=#{page}").body)
32
+ photos += data['photos']
33
+ end
34
+
35
+ dir = File.join(__dir__, '..', 'public', 'images')
36
+ Dir.mkdir(dir) if not File.exists? dir
37
+
38
+ photos.delete_if do |photo|
39
+ photo['width'].to_i < 1200
40
+ end
41
+
42
+ photos.each do |photo|
43
+ file = File.join(dir, "#{photo['id']}.jpg")
44
+ if not File.exists? file
45
+ puts "Download #{file}"
46
+ system("curl -s '#{photo['image_url']}' -o #{file}")
47
+ system("jpegtran -optimize -copy none -progressive -outfile #{file} #{file}")
48
+ end
49
+ end
50
+
51
+ photos.delete_if do |photo|
52
+ file = File.join(dir, "#{photo['id']}.jpg")
53
+ md5 = `md5sum #{file}`.strip.split(' ').first
54
+ if md5 == '92ec602c88283582b9e322ba7dffccde'
55
+ # If the file is "Your image is loading..."
56
+ puts "Skipping #{file}"
57
+ File.unlink file
58
+ true
59
+ else
60
+ false
61
+ end
62
+ end
63
+
64
+ File.open(File.join(__dir__, '..', 'lib', 'images.msh'), 'w') do |fd|
65
+ fd.puts Marshal.dump(photos)
66
+ end
67
+
68
+ ids = photos.map do |photo|
69
+ photo['id'].to_i
70
+ end
71
+
72
+ Dir[File.join(dir, "*.jpg")].each do |file|
73
+ id = File.basename(file, '.jpg').to_i
74
+ if not ids.include? id
75
+ puts "Remove #{file}"
76
+ File.unlink(file)
77
+ end
78
+ end
data/chrome/logo.png ADDED
Binary file
@@ -0,0 +1,17 @@
1
+ {
2
+ "manifest_version": 2,
3
+
4
+ "name": "Departr",
5
+ "description": "Departr is a smart and fast startpage to help you reach other web sites..",
6
+ "version": "1.3",
7
+
8
+ "permissions": [ "cookies", "tabs", "http://departr.solt.biz/*" ],
9
+
10
+ "chrome_url_overrides": {
11
+ "newtab": "newtab.html"
12
+ },
13
+
14
+ "icons": {
15
+ "128": "logo.png"
16
+ }
17
+ }
@@ -0,0 +1,85 @@
1
+ <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
2
+ <html>
3
+ <head>
4
+ <title>Departr</title>
5
+ <link href='/favicon.ico' rel='icon' type='image/png' />
6
+ <meta content='text/html; charset=utf-8' http-equiv='content-type' />
7
+ <script src='/newtab.js' type='text/javascript'></script>
8
+ <style>
9
+ * {
10
+ font-family: "trebuchet MS", verdana, sans-serif;
11
+ }
12
+
13
+ body {
14
+ padding: 0px;
15
+ margin: 0px;
16
+ height: 100%;
17
+ overflow: hidden;
18
+ background-color: rgba(238, 238, 238, 0.8);
19
+ }
20
+
21
+ html {
22
+ height: 100%;
23
+ overflow: hidden;
24
+ }
25
+
26
+ a, a:hover, a:link, a:visited {
27
+ color: inherit;
28
+ }
29
+
30
+ #background {
31
+ width: 100%;
32
+ height: 100%;
33
+ position: absolute;
34
+ top: 0px;
35
+ left: 0px;
36
+ color: transparent;
37
+ background-size: cover;
38
+ background-position: 50% 50%;
39
+ background-repeat: none;
40
+ background-image: url(http://departr.solt.biz/background.jpg);
41
+ z-index: -1;
42
+ }
43
+
44
+ #background:after {
45
+ width: 100%;
46
+ position: absolute;
47
+ font-size: 14px;
48
+ top: 0px;
49
+ bottom: 2em;
50
+ left: 0px;
51
+ content: "";
52
+ background-image: url("data:image/jpeg;base64,iVBORw0KGgoAAAANSUhEUgAAAAIAAAACCAYAAABytg0kAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAABhJREFUeNpiYGBgePz//38GRhABAgABBgBFTAbfCBNE2AAAAABJRU5ErkJggg==");
53
+ }
54
+
55
+ #credits {
56
+ background-color: rgba(255, 255, 255, 0.4);
57
+ color: black;
58
+ opacity: 0.8;
59
+ filter: alpha(opacity=80);
60
+ font-size: 14px;
61
+ height: 2em;
62
+ line-height: 2em;
63
+ position: absolute;
64
+ left: 0px;
65
+ bottom: 0px;
66
+ z-index: 0;
67
+ width: 100%;
68
+ text-align: right;
69
+ }
70
+
71
+ #credits a {
72
+ text-decoration: none;
73
+ padding-right: 1em;
74
+ }
75
+
76
+ </style>
77
+ </head>
78
+ <body>
79
+ <div id='background'></div>
80
+ <div id='credits'>
81
+ <a id='credits_link' href=""></a>
82
+ </div>
83
+ </body>
84
+ </html>
85
+
data/chrome/newtab.js ADDED
@@ -0,0 +1,19 @@
1
+ window.onload = function() {
2
+
3
+ chrome.cookies.get({ url: 'http://departr.solt.biz', name: 'bg_id'},
4
+ function (cookie) {
5
+ if (cookie) {
6
+ var a = document.getElementById('credits_link')
7
+ a.href = "http://500px.com/photo/" + cookie.value;
8
+ }
9
+ });
10
+
11
+ chrome.cookies.get({ url: 'http://departr.solt.biz', name: 'bg_user'},
12
+ function (cookie) {
13
+ if (cookie) {
14
+ var a = document.getElementById('credits_link')
15
+ a.innerText = decodeURIComponent(cookie.value).replace(/\+/g," ");
16
+ }
17
+ });
18
+
19
+ }
data/departr.gemspec CHANGED
@@ -2,22 +2,23 @@
2
2
 
3
3
  Gem::Specification.new do |s|
4
4
  s.name = "departr"
5
- s.version = 0.4
6
- s.date = '2012-02-15'
5
+ s.version = "0.6"
6
+ s.date = '2014-02-20'
7
7
  s.platform = Gem::Platform::RUBY
8
8
  s.author = "Florent Solt"
9
9
  s.email = "florent@solt.biz"
10
10
  s.homepage = "https://github.com/florentsolt/departr"
11
- s.summary = "Departr is a smart and fast startpage to help you reach other web sites."
11
+ s.summary = "Departr!"
12
+ s.description = "Departr is a smart and fast startpage to help you reach other web sites."
13
+ s.license = "MIT"
12
14
 
13
15
  s.files = `git ls-files`.split("\n")
14
16
  s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
15
17
  s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
16
18
  s.require_paths = ["lib"]
17
19
 
18
- s.add_runtime_dependency("json", ["~> 1.6"])
19
- s.add_runtime_dependency("tzinfo", ["~> 0.3"])
20
- s.add_runtime_dependency("haml", ["~> 3.1"])
21
- s.add_runtime_dependency("sass", ["~> 3.1"])
22
- s.add_runtime_dependency("sinatra", ["~> 1.3"])
20
+ s.add_runtime_dependency("haml", ["~> 4.0"])
21
+ s.add_runtime_dependency("sass", ["~> 3.2"])
22
+ s.add_runtime_dependency("sinatra", ["~> 1.4"])
23
+ s.add_runtime_dependency("oauth", ["~> 0.4"])
23
24
  end
@@ -14,15 +14,7 @@ module Departr
14
14
  if File.exists? filename(provider, user)
15
15
  File.mtime(filename(provider, user))
16
16
  else
17
- nil
18
- end
19
- end
20
-
21
- def etag(provider, user)
22
- begin
23
- Digest::MD5.hexdigest(time(provider, user).to_s)
24
- rescue
25
- '-no-command-file-'
17
+ Time.at(0)
26
18
  end
27
19
  end
28
20
 
@@ -10,19 +10,13 @@ module Departr
10
10
  :open_in_new_page => false,
11
11
  :default_search => "http://www.google.com/search?ie=UTF-8&oe=UTF-8&q=",
12
12
 
13
- :github => true,
14
- :calendar => true,
15
- :clock1 => "Europe/Paris",
16
- :clock2 => "America/New_York",
17
- :clock3 => "America/Los_Angeles",
18
-
19
13
  # Default commands
20
14
 
21
15
  :commands => [
22
16
  {'name' => "google search for {words}", 'url' => "http://www.google.com/search?rls=en&q={words}&ie=UTF-8&oe=UTF-8"},
23
17
  {'name' => "google search for {words} in {lang}", 'url' => "http://www.google.com/search?rls={lang}&q={words}&ie=UTF-8&oe=UTF-8"},
24
18
  {'name' => "wikipedia search for {words}", 'url' => "http://en.wikipedia.org/wiki/{words}"},
25
- {'name' => "twitter search for {words}", 'url' => "http://search.twitter.com/search?q={words}"},
19
+ {'name' => "twitter search for {words}", 'url' => "https://twitter.com/search?q={words}&src=typd"},
26
20
  {'name' => "youtube search for {words}", 'url' => "http://www.youtube.com/results?search_query={words}"},
27
21
  {'name' => "dailymotion search for {words}", 'url' => "http://www.dailymotion.com/relevance/search/{words}"},
28
22
  {'name' => "facebook search for {words}", 'url' => "http://www.facebook.com/search/?q={words}"},
@@ -11,23 +11,7 @@ module Departr
11
11
  super
12
12
  Departr::Config.instance_eval(&blk) if block_given?
13
13
  @config = Config
14
-
15
- # when called in the constructor, it remains persistant
16
- # if not, it's rebuild every time
17
- javascripts! if production?
18
- end
19
-
20
- def javascripts!
21
- return @javascripts if not @javascripts.nil?
22
- @javascripts = ''
23
- Dir[File.join(settings.root, 'public', 'javascripts', '*.js')].sort.delete_if do |file|
24
- not File.basename(file).match(/^\d+_/)
25
- end.each do |file|
26
- @javascripts << "\n/* #{File.basename(file)} */\n"
27
- @javascripts << File.read(file)
28
- end
29
- @javascripts_checksum = Digest::SHA1.hexdigest(@javascripts)
30
- @javascripts = JSMin.minify(@javascripts) if production?
14
+ @images = Marshal.load(File.read(File.join(__dir__, '..', 'images.msh')))
31
15
  end
32
16
 
33
17
  #-----------------------------------------------------------------------------
@@ -38,12 +22,12 @@ module Departr
38
22
 
39
23
  set :sass, {
40
24
  :cache_store => Sass::CacheStores::Memory.new,
41
- :style => production? ? :compressed : :expanded
25
+ :style => Server.production? && :compressed || :expanded
42
26
  }
43
27
 
44
28
  set :haml, {
45
29
  :format => :xhtml,
46
- :ugly => production?
30
+ :ugly => Server.production?
47
31
  }
48
32
 
49
33
  set :reload_templates, true if development?
@@ -74,16 +58,6 @@ module Departr
74
58
  end
75
59
  check
76
60
  end
77
-
78
- def clock_label(tz)
79
- return ''.to_json if not tz
80
- tz.split('/').last.gsub('_', ' ').to_json
81
- end
82
-
83
- def clock_offset(tz)
84
- return 0 if not tz
85
- TZInfo::Timezone.get(tz).current_period.utc_total_offset / 3600
86
- end
87
61
  end
88
62
 
89
63
  #-----------------------------------------------------------------------------
@@ -92,16 +66,29 @@ module Departr
92
66
 
93
67
  get '/javascripts/all.js' do
94
68
  content_type :js
95
- javascripts!
96
- etag "js-#{@javascripts_checksum}" if production?
97
- @javascripts
69
+
70
+ if not defined? @@javascripts or not Server.production?
71
+ @@javascripts = ''
72
+ @@javascripts_time = Time.at(0)
73
+ Dir[File.join(settings.root, 'public', 'javascripts', '*.js')].sort.delete_if do |file|
74
+ not File.basename(file).match(/^\d+_/)
75
+ end.each do |file|
76
+ @@javascripts << "\n/* #{File.basename(file)} */\n"
77
+ @@javascripts << File.read(file)
78
+ @@javascripts_time = File.mtime(file) if File.mtime(file) > @@javascripts_time
79
+ end
80
+ @@javascripts = JSMin.minify(@@javascripts) if Server.production?
81
+ end
82
+
83
+ last_modified @@javascripts_time
84
+ @@javascripts
98
85
  end
99
86
 
100
87
  get '/stylesheets/all.css' do
101
88
  content_type :css
102
- if production?
89
+ if Server.production?
103
90
  time = File.mtime(File.join(settings.root, 'views', 'style.sass'))
104
- etag "css-#{time.to_i}"
91
+ last_modified time
105
92
  end
106
93
  sass :style
107
94
  end
@@ -169,7 +156,7 @@ module Departr
169
156
  get '/command/all' do
170
157
  auth!
171
158
  content_type :json
172
- etag "command-" + Command.etag(@provider, @user) if production?
159
+ etag "command-" + Command.etag(@provider, @user) if Server.production?
173
160
  Command.get(@provider, @user).to_json
174
161
  end
175
162
 
@@ -181,18 +168,37 @@ module Departr
181
168
  haml :help
182
169
  end
183
170
 
184
- get '/' do
171
+ get '/background.jpg' do
172
+ background = @images.sample
173
+ response.set_cookie("bg_user", :value => background['user']['fullname'], :path => '/', :expires => Time.now + 60*60*24*365)
174
+ response.set_cookie("bg_id", :value => background['id'], :path => '/', :expires => Time.now + 60*60*24*365)
175
+ headers 'Cache-Control' => "no-cache, no-store, must-revalidate",
176
+ 'Pragma' => 'no-cache',
177
+ 'Expires' => '0'
178
+ redirect "/images/#{background['id']}.jpg"
179
+ end
180
+
181
+ get '/javascripts/context.js' do
182
+ content_type :js
185
183
  if auth?
186
- etag "index-#{Command.etag(@provider, @user)}-#{Settings.etag(@provider, @user)}" if production?
187
- @commands = Command.get(@provider, @user)
188
- @settings = Settings.get(@provider, @user)
184
+ last_modified [Command.time(@provider, @user), Settings.time(@provider, @user)].max if Server.production?
185
+ commands = Command.get(@provider, @user)
186
+ settings = Settings.get(@provider, @user)
189
187
  else
190
- etag "default-#{Digest::SHA1.hexdigest(Command.default.inspect)}" if production?
191
188
  response.delete_cookie("user")
192
189
  response.delete_cookie("session")
193
- @commands = Command.default
194
- @settings = Settings.default
190
+ commands = Command.default
191
+ settings = Settings.default
195
192
  end
193
+ "Command.data = #{commands.to_json};\n" +
194
+ "Settings = #{settings.to_json};"
195
+ end
196
+
197
+ get '/' do
198
+ dir = File.join(__dir__, '..', '..', 'views')
199
+ index = File.mtime(File.join(dir, 'index.haml')).to_i
200
+ layout = File.mtime(File.join(dir, 'layout.haml')).to_i
201
+ etag "#{layout}-#{index}" if Server.production?
196
202
  haml :index
197
203
  end
198
204
  end