dailyshare 0.2.1 → 0.3.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.
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