dailyshare 0.2.1 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
data/Gemfile CHANGED
@@ -1,3 +1,2 @@
1
1
  source 'https://rubygems.org'
2
-
3
- gemspec
2
+ gemspec
data/lib/dailyshare.rb CHANGED
@@ -20,17 +20,10 @@ Encoding.default_internal = Encoding::UTF_8
20
20
  require 'linguistics'
21
21
  Linguistics::use(:en)
22
22
 
23
- # load helpers
24
- require 'dailyshare/helpers/entry'
25
- require 'dailyshare/helpers/helpers'
26
-
27
- # load models
28
- require 'dailyshare/models/member'
29
- require 'dailyshare/models/photo'
30
-
31
- # load controllers
32
- require 'dailyshare/controllers/admin'
33
- require 'dailyshare/controllers/main'
23
+ require 'dailyshare/helpers'
24
+ require 'dailyshare/models'
25
+ require 'dailyshare/models'
26
+ require 'dailyshare/controllers'
34
27
 
35
28
  module DailyShare
36
29
  class App < Sinatra::Base
@@ -0,0 +1,111 @@
1
+ module DailyShare
2
+
3
+ class App < Sinatra::Base
4
+
5
+
6
+ get '/' do
7
+ context = context_from_date(Date.today)
8
+ @title = "#{CONFIG['seo']['title']} - day #{context[:count]}"
9
+ slim :index, :locals => context
10
+ end
11
+
12
+ get '/:y/:m/:d' do
13
+ begin
14
+ date = date_from_params(params)
15
+ context = context_from_date(date)
16
+ @title = "#{CONFIG['seo']['title']} - day #{context[:count]}"
17
+ rescue
18
+ pass
19
+ end
20
+
21
+ if valid_date?(date)
22
+ slim :index, :locals => context
23
+ else
24
+ redirect request.referrer
25
+ end
26
+ end
27
+
28
+ get '/:name' do
29
+ if (member = Member.byName(params[:name])).nil?
30
+ redirect request.referrer
31
+ end
32
+
33
+ slim :member, :locals => { :member => member }
34
+ end
35
+
36
+ get '/:name/missing' do
37
+ if (member = Member.byName(params[:name])).nil?
38
+ redirect request.referrer
39
+ end
40
+ slim :member_missing, :locals => { :photos => member.missingPhotos }
41
+ end
42
+
43
+ get '/admin' do
44
+ protected!
45
+ redirect '/'
46
+ end
47
+
48
+ get '/logout' do
49
+ session.delete(:member_id)
50
+ session.delete(:member_name)
51
+ status 401
52
+ slim :logout
53
+ end
54
+
55
+ post '/upload' do
56
+ protected!
57
+ if params[:file]
58
+ save_photo(params, params[:file][:tempfile])
59
+ end
60
+ redirect request.referrer
61
+ end
62
+
63
+ post '/edit' do
64
+ protected!
65
+ puts params
66
+
67
+ photo = Photo[:id=>params[:photo_id]]
68
+ if photo
69
+ photo.update_fields(params, [:title, :description])
70
+ end
71
+
72
+ redirect request.referrer
73
+ end
74
+
75
+ ##
76
+ # Receive emailed photos via Postmark.
77
+ #
78
+ post '/receiver' do
79
+ # parse post data
80
+ data = JSON.parse(request.body.read)
81
+
82
+ # grab image data
83
+ image = data['Attachments'][0]['Content']
84
+
85
+ # check which member this is based on sender
86
+ member = Member[:email=>data['From']]
87
+
88
+ # was there a member with that email?
89
+ if !member.nil?
90
+
91
+ # get most recent photo
92
+ recent = member.mostRecentPhoto
93
+
94
+ # only continue if a photo doesn't exist for today
95
+ if !recent.nil? && recent.date_added+1 <= Date.today
96
+
97
+ # prep params for submission
98
+ params = {
99
+ :member_id => member.id,
100
+ :title => data['Subject'],
101
+ :description => data['TextBody'],
102
+ :date_added => recent.date_added+1
103
+ }
104
+ save_photo(params,StringIO.new(Base64.decode64(image)))
105
+ end
106
+ end
107
+ end
108
+
109
+ end
110
+
111
+ end
@@ -142,5 +142,56 @@ module DailyShare
142
142
  end
143
143
  end
144
144
 
145
+ def date_from_params(params)
146
+ if params[:y] && params[:m] && params[:d]
147
+ Date.parse("#{params[:y]}-#{params[:m]}-#{params[:d]}")
148
+ else
149
+ Date.today
150
+ end
151
+ end
152
+
153
+ def valid_date?(date)
154
+ (date.year > 2011 || date <= Date.today)
155
+ end
156
+
157
+ def context_from_date(date)
158
+ edition = (date.strftime('%Y').to_i)-(CONFIG['dailyshare']['start'].strftime('%Y').to_i)
159
+ {
160
+ :ymd => date.strftime('%Y-%m-%d'),
161
+ :date => date,
162
+ :year => (edition+1).en.numwords,
163
+ :count => (((date-CONFIG['dailyshare']['start']).to_i)-((edition)*365).to_i).en.numwords,
164
+ :members => Member.order(:id).all
165
+ }
166
+ end
167
+
168
+ def prev_entry(date)
169
+ (date-1).strftime('/%Y/%m/%d/')
170
+ end
171
+
172
+ def next_entry(date)
173
+ (date+1).strftime('/%Y/%m/%d/')
174
+ end
175
+
176
+ def save_photo(params, file)
177
+ begin
178
+ photo = Photo.new
179
+ photo.set_fields(params, [:title, :description, :date_added, :member_id])
180
+ puts photo.inspect
181
+ photo.save_original(file)
182
+ photo.generate_sizes
183
+ photo.save_to_s3
184
+ rescue
185
+ false
186
+ else
187
+ photo.save
188
+ send_email(
189
+ CONFIG['email']['to'],
190
+ "new submisson",
191
+ slim(:'emails/uploaded', {:locals=>{:photo=>photo},:layout=>false})
192
+ )
193
+ end
194
+ end
195
+
145
196
  end
146
197
  end
@@ -0,0 +1,122 @@
1
+ require "stringio"
2
+
3
+ module DailyShare
4
+ class Photo < Sequel::Model
5
+ many_to_one :member
6
+
7
+ def before_save
8
+ description.strip!
9
+ end
10
+
11
+ def file(size)
12
+ case size
13
+ when :original
14
+ "#{date_added}-#{member.name}.jpg"
15
+ when :thumb
16
+ "#{date_added}-#{member.name}-thumb.jpg"
17
+ when :big
18
+ "#{date_added}-#{member.name}-big.jpg"
19
+ end
20
+ end
21
+
22
+ def url(size)
23
+ "#{CONFIG['url']['cdn']}/photos/#{file(size)}"
24
+ end
25
+
26
+ def save_original(tmpfile)
27
+ image = File.join(CONFIG['photo_dir'],file(:original))
28
+ File.open(image,'wb') {|f| f.write(tmpfile.read) }
29
+ image
30
+ end
31
+
32
+ def generate_sizes
33
+ img = Magick::Image::read(File.join(CONFIG['photo_dir'],file(:original))).first
34
+ if img
35
+ img.resize_to_fit(240,240).write(File.join(CONFIG['photo_dir'],file(:thumb)))
36
+ img.resize_to_fit(960,680).write(File.join(CONFIG['photo_dir'],file(:big)))
37
+ img.destroy!
38
+ true
39
+ else
40
+ false
41
+ end
42
+ end
43
+
44
+ def sizes
45
+ [File.join(CONFIG['photo_dir'],file(:original)),
46
+ File.join(CONFIG['photo_dir'],file(:thumb)),
47
+ File.join(CONFIG['photo_dir'],file(:big))]
48
+ end
49
+
50
+ def save_to_s3
51
+ sizes.each do |file|
52
+ AWS::S3::S3Object.store(
53
+ "/photos/#{File.basename(file)}",
54
+ open(file),
55
+ AUTH['aws']['bucket'],
56
+ {
57
+ :cache_control => 'max-age=315360000',
58
+ :access => 'public_read'
59
+ }
60
+ )
61
+ end
62
+ end
63
+
64
+ def parse_exif
65
+ img = EXIFR::JPEG.new(file)
66
+
67
+ # store fstop/focal length for comparison
68
+ fstop = img.exif[:f_number].to_f
69
+ flen = img.exif[:focal_length].to_f
70
+
71
+ {
72
+ # if no decimal is needed, leave it off
73
+ :fstop => (fstop == fstop.to_i ? fstop.to_i : fstop),
74
+ # convert exposure to string
75
+ :exposure => img.exif[:exposure_time].to_s,
76
+ # if no decimal is needed, leave it off
77
+ :focal_length => (flen == flen.to_i ? flen.to_i : flen).to_s+'mm'
78
+ }
79
+ end
80
+
81
+ end
82
+ end
83
+
84
+
85
+ module DailyShare
86
+ class Member < Sequel::Model
87
+ one_to_many :photos
88
+
89
+ def self.byName(name)
90
+ self[:name=>name]
91
+ end
92
+
93
+ def self.byEmail(email)
94
+ self[:email=>email.downcase]
95
+ end
96
+
97
+ def missingPhotos
98
+ DB["SELECT
99
+ date('2012-01-01'::date+(interval '1 day'*s.num)) AS date
100
+ FROM
101
+ (SELECT generate_series(0,now()::date-'2012-01-01'::date) AS num) AS s
102
+ WHERE
103
+ (SELECT
104
+ true
105
+ FROM
106
+ photos
107
+ WHERE
108
+ date_added=date('2012-01-01'::date+(interval '1 day'*s.num))
109
+ AND
110
+ member_id=?) IS null",id]
111
+ end
112
+
113
+ def mostRecentPhoto
114
+ photos_dataset.order(:date_added.desc).first
115
+ end
116
+
117
+ def submissionByDate(date)
118
+ photos_dataset.where(:date_added=>date).first
119
+ end
120
+
121
+ end
122
+ end
@@ -1,3 +1,3 @@
1
1
  module DailyShare
2
- VERSION = '0.2.1'
2
+ VERSION = '0.3.0'
3
3
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: dailyshare
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.1
4
+ version: 0.3.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2013-01-02 00:00:00.000000000 Z
12
+ date: 2013-01-03 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: linguistics
@@ -104,12 +104,9 @@ files:
104
104
  - Rakefile
105
105
  - dailyshare.gemspec
106
106
  - lib/dailyshare.rb
107
- - lib/dailyshare/controllers/admin.rb
108
- - lib/dailyshare/controllers/main.rb
109
- - lib/dailyshare/helpers/entry.rb
110
- - lib/dailyshare/helpers/helpers.rb
111
- - lib/dailyshare/models/member.rb
112
- - lib/dailyshare/models/photo.rb
107
+ - lib/dailyshare/controllers.rb
108
+ - lib/dailyshare/helpers.rb
109
+ - lib/dailyshare/models.rb
113
110
  - lib/dailyshare/version.rb
114
111
  homepage: https://github.com/tkellen/ruby-dailyshare
115
112
  licenses: []
@@ -1,65 +0,0 @@
1
- require 'base64'
2
-
3
- module DailyShare
4
-
5
- class App < Sinatra::Base
6
-
7
- get '/admin' do
8
- protected!
9
- redirect '/'
10
- end
11
-
12
- post '/upload/:date_added/:name' do
13
- protected!
14
- if params[:file]
15
- params[:member_id] = Member.byName(params[:name]).id
16
- save_photo(params,params[:file][:tempfile])
17
- end
18
- redirect request.referrer
19
- end
20
-
21
- post '/edit/:date/:name' do
22
- protected!
23
-
24
- member = Member.byName(params[:name])
25
- photo = Photo.by_date_and_member(params[:date],member)
26
- photo.update_fields(params,[:title,:description])
27
-
28
- redirect request.referrer
29
- end
30
-
31
- ##
32
- # Receive emailed photos via Postmark.
33
- #
34
- post '/receiver' do
35
- # parse post data
36
- data = JSON.parse(request.body.read)
37
-
38
- # grab image data
39
- image = data['Attachments'][0]['Content']
40
-
41
- # check which member this is based on sender
42
- member = Member[:email=>data['From']]
43
-
44
- # was there a member with that email?
45
- if !member.nil?
46
-
47
- # get most recent photo
48
- recent = Photo.most_recent_by_member(member)
49
-
50
- # only continue if a photo doesn't exist for today
51
- if !recent.nil? && recent.date_added+1 <= Date.today
52
-
53
- # prep params for submission
54
- params = {
55
- :member_id => member.id,
56
- :title => data['Subject'],
57
- :description => data['TextBody'],
58
- :date_added => recent.date_added+1
59
- }
60
- save_photo(params,StringIO.new(Base64.decode64(image)))
61
- end
62
- end
63
- end
64
- end
65
- end
@@ -1,51 +0,0 @@
1
- module DailyShare
2
-
3
- class App < Sinatra::Base
4
-
5
- get '/' do
6
- context = context_from_date(Date.today)
7
- @title = "#{CONFIG['seo']['title']} - day #{context[:count]}"
8
- slim :index, :locals => context
9
- end
10
-
11
- get '/logout' do
12
- session.delete(:member_id)
13
- session.delete(:member_name)
14
- status 401
15
- slim :logout
16
- end
17
-
18
- get '/:y/:m/:d' do
19
- begin
20
- date = date_from_params(params)
21
- context = context_from_date(date)
22
- @title = "#{CONFIG['seo']['title']} - day #{context[:count]}"
23
- rescue
24
- pass
25
- end
26
-
27
- if valid_date?(date)
28
- slim :index, :locals => context
29
- else
30
- redirect request.referrer
31
- end
32
- end
33
-
34
- get '/:name' do
35
- if (member = Member.byName(params[:name])).nil?
36
- redirect request.referrer
37
- end
38
-
39
- slim :member, :locals => { :photos => member.photos }
40
- end
41
-
42
- get '/:name/missing' do
43
- if (member = Member.byName(params[:name])).nil?
44
- redirect request.referrer
45
- end
46
- slim :member_missing, :locals => { :photos => member.missingPhotos }
47
- end
48
-
49
- end
50
-
51
- end
@@ -1,51 +0,0 @@
1
- module DailyShare
2
- module Helpers
3
-
4
- def date_from_params(params)
5
- Date.parse("#{params[:y]}-#{params[:m]}-#{params[:d]}")
6
- end
7
-
8
- def valid_date?(date)
9
- (date.year > 2011 || date <= Date.today)
10
- end
11
-
12
- def context_from_date(date)
13
- edition = (date.strftime('%Y').to_i)-(CONFIG['dailyshare']['start'].strftime('%Y').to_i)
14
- {
15
- :ymd => date.strftime('%Y-%m-%d'),
16
- :date => date,
17
- :year => (edition+1).en.numwords,
18
- :count => (((date-CONFIG['dailyshare']['start']).to_i)-((edition)*365).to_i).en.numwords,
19
- :photos => Member.all_with_photo_for(date)
20
- }
21
- end
22
-
23
- def prev_entry(date)
24
- (date-1).strftime('/%Y/%m/%d/')
25
- end
26
-
27
- def next_entry(date)
28
- (date+1).strftime('/%Y/%m/%d/')
29
- end
30
-
31
- def save_photo(params,file)
32
- begin
33
- photo = Photo.new
34
- photo.set_fields(params,[:title,:description,:date_added,:member_id])
35
- photo.save_original(file)
36
- photo.generate_sizes
37
- photo.save_to_s3
38
- rescue
39
- false
40
- else
41
- photo.save
42
- send_email(
43
- CONFIG['email']['to'],
44
- "new submisson",
45
- slim(:'emails/uploaded', {:locals=>{:photo=>photo},:layout=>false})
46
- )
47
- end
48
- end
49
-
50
- end
51
- end
@@ -1,36 +0,0 @@
1
- module DailyShare
2
- class Member < Sequel::Model
3
- one_to_many :photos
4
-
5
- def self.byName(name)
6
- self[:name=>name]
7
- end
8
-
9
- def self.byEmail(email)
10
- self[:email=>email.downcase]
11
- end
12
-
13
- def self.all_with_photo_for(date)
14
- select(:members__name,:p__title,:p__description,:p__date_added).
15
- left_join(:photos.as(:p),[:p__member_id=>:members__id,:date.sql_function(:p__date_added)=>date]).
16
- order(:members__id)
17
- end
18
-
19
- def missingPhotos
20
- DB["SELECT
21
- date('2012-01-01'::date+(interval '1 day'*s.num)) AS date
22
- FROM
23
- (SELECT generate_series(0,now()::date-'2012-01-01'::date) AS num) AS s
24
- WHERE
25
- (SELECT
26
- true
27
- FROM
28
- photos
29
- WHERE
30
- date_added=date('2012-01-01'::date+(interval '1 day'*s.num))
31
- AND
32
- member_id=?) IS null",id]
33
- end
34
-
35
- end
36
- end
@@ -1,87 +0,0 @@
1
- require "stringio"
2
-
3
- module DailyShare
4
- class Photo < Sequel::Model
5
- many_to_one :member
6
-
7
- def self.by_date_and_member(date,member)
8
- where(:date.sql_function(:date_added)=>date,:member_id=>member.id).first
9
- end
10
-
11
- def self.most_recent_by_member(member)
12
- where(:member_id=>member.id).order(:date_added.desc).first
13
- end
14
-
15
- def before_save
16
- description.strip!
17
- end
18
-
19
- def original
20
- "#{date_added}-#{self.member.name}.jpg"
21
- end
22
-
23
- def thumb
24
- "#{date_added}-#{self.member.name}-thumb.jpg"
25
- end
26
-
27
- def big
28
- "#{date_added}-#{self.member.name}-big.jpg"
29
- end
30
-
31
- def save_original(file)
32
- image = File.join(CONFIG['photo_dir'],original)
33
- File.open(image,'wb') {|f| f.write file.read }
34
- image
35
- end
36
-
37
- def generate_sizes
38
- img = Magick::Image::read(File.join(CONFIG['photo_dir'],original)).first
39
- if img
40
- img.resize_to_fit(240,240).write(File.join(CONFIG['photo_dir'],thumb))
41
- img.resize_to_fit(960,680).write(File.join(CONFIG['photo_dir'],big))
42
- img.destroy!
43
- true
44
- else
45
- false
46
- end
47
- end
48
-
49
- def sizes
50
- [File.join(CONFIG['photo_dir'],original),
51
- File.join(CONFIG['photo_dir'],thumb),
52
- File.join(CONFIG['photo_dir'],big)]
53
- end
54
-
55
- def save_to_s3
56
- sizes.each do |file|
57
- AWS::S3::S3Object.store(
58
- "/photos/#{File.basename(file)}",
59
- open(file),
60
- AUTH['aws']['bucket'],
61
- {
62
- :cache_control => 'max-age=315360000',
63
- :access => 'public_read'
64
- }
65
- )
66
- end
67
- end
68
-
69
- def parse_exif
70
- img = EXIFR::JPEG.new(file)
71
-
72
- # store fstop/focal length for comparison
73
- fstop = img.exif[:f_number].to_f
74
- flen = img.exif[:focal_length].to_f
75
-
76
- {
77
- # if no decimal is needed, leave it off
78
- :fstop => (fstop == fstop.to_i ? fstop.to_i : fstop),
79
- # convert exposure to string
80
- :exposure => img.exif[:exposure_time].to_s,
81
- # if no decimal is needed, leave it off
82
- :focal_length => (flen == flen.to_i ? flen.to_i : flen).to_s+'mm'
83
- }
84
- end
85
-
86
- end
87
- end