lentil 0.3.1 → 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: dd98f997f2495b12ae5d38bc8d23ac3b2de72109
4
- data.tar.gz: 0ad51644acda26f24c9673d168b29edb0d9486d9
3
+ metadata.gz: 942c1dd9c7d9d2eeffd3950d921c979fc969399a
4
+ data.tar.gz: 10b00660f681388bd87560f94bb4f594c643d072
5
5
  SHA512:
6
- metadata.gz: d39613263f4c4f043d64cb9264d0fb5eebfba32f50e8fa0115aa7907cf19cd9893bf80ab6162468457b6343e8b7d1b63e06cef1b1117a2591b2a4e30e539e969
7
- data.tar.gz: 5e5bc82f305c6058f6e51a73ca0d820b075e10e2bd7e968204acf1059782b5c9a8bbf7ebf519d833fca07beed7f1bdf73d4b2f262894891b24eafe9eee46b533
6
+ metadata.gz: d7536b168f00124322e37b23d9d6f93cbc048a3da9ae04375d639b3d3f27ad05ee254a2a398a653b48e24ca28a602b1353693407b1bef300aa30c0f392583076
7
+ data.tar.gz: 9ca11239e8fa46c2c0c96803b49578df3d01358da04d0b101fc9d48b786d4e9026b18ee047277194f093e2c588dc35cbb0c6dc812f0874a3954f864c9b84fb29
data/README.md CHANGED
@@ -72,6 +72,19 @@ You ought to see a message like: "15 new images added"
72
72
  - Go to <http://localhost:3000/admin/lentil_images> and click on "Moderate New." Approve or reject some images. Once you've approved some, go to <http://localhost:3000> to see your approved images.
73
73
  - Congratulations! You're now up and running!
74
74
 
75
+ ## Harvest Videos
76
+ Video harvesting is builtin to the image harvesting feature. Only once a single task has to be run to migrate the existing data to accomodate for schema.
77
+ After updating lentil to the latest release run
78
+ ```sh
79
+ bundle exec rails generate lentil:install
80
+ bundle exec rake lentil:image_services:restore_videos
81
+ ```
82
+
83
+ You ought to see a message like: "x record(s) updated"
84
+
85
+ Videos can be moderated like images.
86
+ In the home page and animate views videos will autoplay, muted and looped
87
+
75
88
  ## Scheduling tasks
76
89
 
77
90
  There are several rake tasks that you should schedule to run on a recurring basis:
@@ -80,9 +93,10 @@ There are several rake tasks that you should schedule to run on a recurring basi
80
93
  - `rake lentil:image_services:test_image_files[number_of_images,image_service]` checks that the image content for approved images is still available. After 3 failures, Lentil will stop displaying the images. After 10 failures, Lentil will stop checking. Defaults to checking 10 Instagram images. Images will not be checked more than once per day.
81
94
  - `rake lentil:popularity:update_score` recalculates the popularity score based on "likes" and "battles."
82
95
 
83
- Additionally, there are two optional rake tasks that support image file harvesting for longer-term retention:
96
+ Additionally, there are three optional rake tasks that support image file harvesting for longer-term retention:
84
97
 
85
98
  - `rake lentil:image_services:save_image_files[number_of_images,image_service,base_directory]` Lentil normally only stores image metadata, but this task will save the image file to a specified directory. This file will still not be used by Lentil, but the file retrieval will be noted in the Image model. Defaults to 50 Instagram images, saving to the path specified by the `base_image_file_dir` option from `config/lentil_config.yml`.
99
+ - `rake lentil:image_services:dump_metadata[image_service,base_directory]` Extracts all image metadata from the database and writes them as json files. Defaults to saving to the path specified by the `base_image_file_dir` option from `config/lentil_config.yml`.
86
100
  - `rake lentil:image_services:submit_donor_agreements[number_of_images,image_service]` will submit a donor agreement (using the `donor_agreement_text` option from `config/lentil_config.yml`) as a comment on approved Instagram images that have been in the system for at least a week. Currently defaults to one image.
87
101
 
88
102
  > In order to submit comments, you will need to generate an access token for the user that will submit the comments. See the [Instagram documentation](http://instagram.com/developer/authentication/) and a [discussion of access token expiration](https://groups.google.com/forum/?fromgroups=#!searchin/instagram-api-developers/access$20token%7Csort:date/instagram-api-developers/OBOTwIh3FSw/9hTccUX1Jq4J).
@@ -76,9 +76,10 @@ function addfancybox() {
76
76
  closeEffect : 'none',
77
77
  nextEffect : 'none',
78
78
  prevEffect : 'none',
79
+ live : true,
79
80
  loop : false,
80
81
  minWidth : '250px',
81
- type: 'image',
82
+ type: 'html',
82
83
  helpers : {
83
84
  title : { type : 'inside' },
84
85
  overlay : { locked : false }
@@ -90,6 +91,21 @@ function addfancybox() {
90
91
  window.history.pushState(null,null,FancyBoxCloseFunctionState.pathname);
91
92
  },
92
93
  beforeShow : function() {
94
+ var img = $(this.element).children(".instagram-img");
95
+ if($(img).attr("data-media-type") === "video") {
96
+ var video_url = $(img).attr("src");
97
+ //this.content = "<video src='" + video_url + "' height='320' width='320' controls='controls'></video>";
98
+ $(".fancybox-inner").html('<video controls="controls" height="100%" width="90%" src="' + video_url + '"></video>');
99
+ var vid = $(".fancybox-inner").children("video")[0];
100
+ vid.oncanplay = function() {
101
+ $.fancybox.reposition();
102
+ }
103
+ }
104
+ else {
105
+ var image_url = $(img).attr("src");
106
+ $(".fancybox-inner").html('<img class="fancybox-image" src="' + image_url + '" />');
107
+ }
108
+
93
109
  this.title = $(this.element).next(".text-overlay").html();
94
110
  imageId = $(this.element).parents("div").attr("id");
95
111
  $(".fancybox-wrap").attr('id', imageId);
@@ -33,7 +33,6 @@ function addinfinitescroll() {
33
33
  }
34
34
  },
35
35
  function () {
36
- addfancybox();
37
36
  addimageerrors();
38
37
  // on callback, if fancybox is open
39
38
  // then close it and reopen at the same spot
@@ -47,4 +46,4 @@ function addinfinitescroll() {
47
46
  }
48
47
  });
49
48
  }
50
- }
49
+ }
@@ -1,8 +1,8 @@
1
1
  function addimageerrors() {
2
- $("img.instagram-img, img.battle-img, img.fancybox-img").on("error", function () {
2
+ $(".instagram-img, .battle-img, .fancybox-img").off("error").on("error", function () {
3
3
  $(this).parents("div.image-tile, li.image-animate-tile").remove();
4
- if ($("body.images_animate") || $("body.images_staff_picks_animate")) {
4
+ /*if ($("body.images_animate") || $("body.images_staff_picks_animate")) {
5
5
  addanimatedimages();
6
- }
6
+ }*/
7
7
  });
8
- }
8
+ }
@@ -35,8 +35,10 @@
35
35
  class Lentil::Image < ActiveRecord::Base
36
36
  attr_accessible :description, :title, :user_id, :state, :staff_like, :url, :long_url, :external_identifier,
37
37
  :original_datetime, :popular_score, :taggings, :tag_id, :moderator, :moderated_at, :second_moderation,
38
- :do_not_request_donation, :donor_agreement_rejected
39
-
38
+ :do_not_request_donation, :donor_agreement_rejected, :media_type, :video_url
39
+
40
+ attr_protected :original_metadata
41
+
40
42
  has_many :won_battles, :class_name => "Battle"
41
43
  has_many :losers, :through => :battles
42
44
  has_many :lost_battles, :class_name => "Battle", :foreign_key => "loser_id"
@@ -54,8 +56,6 @@ class Lentil::Image < ActiveRecord::Base
54
56
  has_many :licensings
55
57
  has_many :licenses, :through=>:licensings
56
58
 
57
- serialize :original_metadata, Hash
58
-
59
59
  belongs_to :moderator, :class_name => Lentil::AdminUser
60
60
 
61
61
  default_scope where("failed_file_checks < 3")
@@ -199,4 +199,8 @@ class Lentil::Image < ActiveRecord::Base
199
199
  end
200
200
 
201
201
  end
202
+
203
+ def original_metadata=(meta)
204
+ write_attribute(:original_metadata, meta.to_hash)
205
+ end
202
206
  end
@@ -18,7 +18,13 @@
18
18
  <% @images.each do |image| %>
19
19
  <tr class="moderation">
20
20
  <%= semantic_fields_for "image[#{image.id}]", image do |f| %>
21
- <td><%= link_to_large_admin_image(image) %></td>
21
+ <td>
22
+ <% unless image.media_type == "video" %>
23
+ <%= link_to_large_admin_image(image) %>
24
+ <% else %>
25
+ <%= link_to(video_tag(image.video_url, controls: true, size: "250x250"), admin_lentil_image_path(image)) %>
26
+ <% end %>
27
+ </td>
22
28
  <td><%= image.description %></td>
23
29
  <td><%= image.user.user_name %></td>
24
30
  <td><%= image.service_tags.map{|tag| tag.name}.join(' | ') %>
@@ -1,8 +1,12 @@
1
1
  <div class="images">
2
2
  <% @images.each do |image| %>
3
3
  <div id="image_<%= image.id %>" class="grid__cell image-tile">
4
- <%= link_to url_for(image), 'data-fancybox-href' => image.jpeg, 'data-fancybox-group' => "image-tile-gallery", :class => :fancybox do %>
5
- <%= image_tag(image.jpeg, :class => "instagram-img " + image.id.to_s, :alt => image.description, :data => {:battles_count => image.battles_count, :win_pct => image.win_pct, :popularity => image.popular_score, :staff_like => image.staff_like, :like_votes_count => image.like_votes_count}) %>
4
+ <%= link_to url_for(image), 'data-fancybox-href' => image.video_url, 'data-fancybox-group' => "image-tile-gallery", :class => :fancybox do %>
5
+ <% unless image.media_type == "video" %>
6
+ <%= image_tag(image.jpeg, :class => "instagram-img " + image.id.to_s, :alt => image.description, :data => {:battles_count => image.battles_count, :win_pct => image.win_pct, :popularity => image.popular_score, :staff_like => image.staff_like, :like_votes_count => image.like_votes_count, :media_type => image.media_type}) %>
7
+ <% else %>
8
+ <%= video_tag(image.video_url, :autoplay => "true", :muted => "true", :loop => "true", :class => "instagram-img " + image.id.to_s, :height => "100%", :width => "100%", :poster => image.jpeg, :data => {:battles_count => image.battles_count, :win_pct => image.win_pct, :popularity => image.popular_score, :staff_like => image.staff_like, :like_votes_count => image.like_votes_count, :media_type => image.media_type}) %>
9
+ <% end %>
6
10
  <% end %>
7
11
 
8
12
  <%= render "/layouts/lentil/image_popup", :image => image %>
@@ -7,7 +7,15 @@
7
7
  <div id="ri-grid" class="ri-grid ri-grid-size-2 grid__cell animated-images staff-picks-animated" style="padding:0; margin:0;">
8
8
  <ul>
9
9
  <% @images.each do |image| %>
10
- <li class="image-animate-tile"><a href="#"><%= image_tag(image.jpeg, :class => "instagram-img") %></a></li>
10
+ <li class="image-animate-tile">
11
+ <a href="#">
12
+ <% unless image.media_type == "video" %>
13
+ <%= image_tag(image.jpeg, :class => "instagram-img") %>
14
+ <% else %>
15
+ <%= video_tag(image.video_url, :autoplay => "true", :muted => "true", :loop => "true", :poster => image.jpeg, :class => "instagram-img " + image.id.to_s, :height => "100%", :width => "100%", :data => {:media_type => image.media_type}) %>
16
+ <% end %>
17
+ </a>
18
+ </li>
11
19
  <% end -%>
12
20
  </ul>
13
21
  </div>
@@ -5,6 +5,25 @@
5
5
  <% end -%>
6
6
  <% title @title %>
7
7
  <%= render :partial => "/layouts/lentil/top_navigation" %>
8
+ <style>
9
+ .fancybox-prev {
10
+ width : 5%;
11
+ }
12
+ .fancybox-prev > span {
13
+ left : 0;
14
+ visibility: visible;
15
+ }
16
+ .fancybox-next {
17
+ width : 5%;
18
+ }
19
+ .fancybox-next > span {
20
+ right : 0;
21
+ visibility: visible;
22
+ }
23
+ .fancybox-inner {
24
+ text-align: center;
25
+ }
26
+ </style>
8
27
  <section class="wrapper">
9
28
  <div class="grid">
10
29
  <div class="grid__cell header">
@@ -17,7 +17,13 @@
17
17
  <div class="wrapper">
18
18
  <div class="grid__cell side-filler"></div>
19
19
  <div id="image_<%= @image.id %>" class="image-show grid__cell solo-image">
20
- <a href="<%= @image.url %>"><%= image_tag(@image.jpeg, :class => "instagram-img") %></a>
20
+ <a href="<%= @image.url %>">
21
+ <% unless @image.media_type == "video" %>
22
+ <%= image_tag(@image.jpeg, :class => "instagram-img") %>
23
+ <% else %>
24
+ <video src="<%= @image.video_url %>" poster="<%= @image.jpeg %>" controls='controls' class="instagram-img <%= @image.id.to_s %>" height="100%" width="100%" data-media-type="<%= @image.media_type %>" ></video>
25
+ <% end %>
26
+ </a>
21
27
  <%= render "/layouts/lentil/image_popup", :image => @image %>
22
28
  </div>
23
29
  <div class="grid__cell side-filler"></div>
@@ -4,7 +4,12 @@
4
4
  <div class="battle-image-wrap grid__cell">
5
5
  <%= semantic_fields_for "image[#{image.id}]", image do |f| %>
6
6
  <div id="image_<%= image.id %>" class="battle-image-tile">
7
- <a href="<%= url_for(image) %>" data-fancybox-href= "<%= image.jpeg %>" class="fancybox"><%= image_tag(image.jpeg, :class => "battle-img", :data => {:battles_count => image.battles_count, :win_pct => image.win_pct, :popularity => image.popular_score, :staff_like => image.staff_like, :like_votes_count => image.like_votes_count}) %>
7
+ <a href="<%= url_for(image) %>" data-fancybox-href= "<%= image.jpeg %>" class="fancybox">
8
+ <% unless image.media_type == "video" %>
9
+ <%= image_tag(image.jpeg, :class => "battle-img instagram-img", :data => {:battles_count => image.battles_count, :win_pct => image.win_pct, :popularity => image.popular_score, :staff_like => image.staff_like, :like_votes_count => image.like_votes_count, :media_type => image.media_type}) %>
10
+ <% else %>
11
+ <%= video_tag(image.video_url, :class => "instagram-img " + image.id.to_s, :height => "100%", :width => "100%", :poster => image.jpeg, :controls => "controls", :data => {:battles_count => image.battles_count, :win_pct => image.win_pct, :popularity => image.popular_score, :staff_like => image.staff_like, :like_votes_count => image.like_votes_count, :media_type => image.media_type}) %>
12
+ <% end %>
8
13
  <div class="battle-image-desc trunc-small"><div class="battle-image-inner-desc"><%= truncate(image.description, :length => 35) %></div></div>
9
14
  <div class="battle-image-desc trunc-medium"><div class="battle-image-inner-desc"><%= truncate(image.description, :length => 50) %></div></div>
10
15
  <div class="battle-image-desc trunc-large"><div class="battle-image-inner-desc"><%= truncate(image.description, :length => 70) %></div></div>
@@ -23,7 +28,12 @@
23
28
  <% @prev_images.each do |image| %>
24
29
  <div class="battle-image-wrap grid__cell" style="background:#e6e6e6">
25
30
  <div id="image_<%= image.id %>" class="battle-image-tile">
26
- <a href="<%= url_for(image) %>" data-fancybox-href= "<%= image.jpeg %>" class="fancybox"><%= image_tag(image.jpeg, :class => "battle-img", :data => {:battles_count => image.battles_count, :win_pct => image.win_pct, :popularity => image.popular_score, :staff_like => image.staff_like, :like_votes_count => image.like_votes_count}) %>
31
+ <a href="<%= url_for(image) %>" data-fancybox-href= "<%= image.jpeg %>" class="fancybox">
32
+ <% unless image.media_type == "video" %>
33
+ <%= image_tag(image.jpeg, :class => "battle-img instagram-img", :data => {:battles_count => image.battles_count, :win_pct => image.win_pct, :popularity => image.popular_score, :staff_like => image.staff_like, :like_votes_count => image.like_votes_count, :media_type => image.media_type}) %>
34
+ <% else %>
35
+ <%= video_tag(image.video_url, :class => "instagram-img " + image.id.to_s, :height => "100%", :width => "100%", :poster => image.jpeg, :controls => "controls", :data => {:battles_count => image.battles_count, :win_pct => image.win_pct, :popularity => image.popular_score, :staff_like => image.staff_like, :like_votes_count => image.like_votes_count, :media_type => image.media_type}) %>
36
+ <% end %>
27
37
  <div class="battle-image-desc trunc-small"><div class="battle-image-inner-desc"><%= truncate(image.description, :length => 35) %></div></div>
28
38
  <div class="battle-image-desc trunc-medium"><div class="battle-image-inner-desc"><%= truncate(image.description, :length => 50) %></div></div>
29
39
  <div class="battle-image-desc trunc-large"><div class="battle-image-inner-desc"><%= truncate(image.description, :length => 70) %></div></div>
@@ -0,0 +1,6 @@
1
+ class AddTypeToImages < ActiveRecord::Migration
2
+ def change
3
+ add_column :lentil_images, :media_type, :string
4
+ add_column :lentil_images, :video_url, :string
5
+ end
6
+ end
@@ -6,6 +6,7 @@ if defined?(ActiveAdmin)
6
6
  config.per_page = 10
7
7
 
8
8
  filter :state, :as => :select, :collection => proc { Lentil::Image::States }
9
+ filter :media_type, :as => :select
9
10
  filter :user_user_name, :as => :string, :label => "Username"
10
11
  filter :user_full_name, :as => :string, :label => "Full Name"
11
12
  filter :staff_like, :as => :select
@@ -31,7 +32,11 @@ if defined?(ActiveAdmin)
31
32
 
32
33
  index do
33
34
  column "Image" do |image|
34
- link_to(image_tag(image.image_url, :class => "moderation_thumbnail"), admin_lentil_image_path(image))
35
+ unless image.media_type == "video"
36
+ link_to(image_tag(image.image_url, :class => "moderation_thumbnail"), admin_lentil_image_path(image))
37
+ else
38
+ link_to(video_tag(image.video_url, controls: true, size: "250x250"), admin_lentil_image_path(image))
39
+ end
35
40
  end
36
41
  column :id
37
42
  column :description
@@ -91,7 +96,11 @@ if defined?(ActiveAdmin)
91
96
  image.state_name
92
97
  end
93
98
  row :image do
94
- link_to(image_tag(image.image_url), admin_lentil_image_path(image))
99
+ unless image.media_type == "video"
100
+ link_to(image_tag(image.image_url), admin_lentil_image_path(image))
101
+ else
102
+ video_tag(image.video_url, controls: true, size: "640x640")
103
+ end
95
104
  end
96
105
  end
97
106
  active_admin_comments
@@ -211,4 +220,4 @@ if defined?(ActiveAdmin)
211
220
  redirect_to :back, notice: "#{image_counter} #{'URL'.pluralize(image_counter)} added (out of #{total_urls})", alert: errors.join('<br>').html_safe
212
221
  end
213
222
  end
214
- end
223
+ end
@@ -124,7 +124,9 @@ module Lentil
124
124
  tags: instagram_metadata.tags,
125
125
  user: instagram_metadata.user,
126
126
  original_datetime: Time.at(instagram_metadata.created_time.to_i).to_datetime,
127
- original_metadata: instagram_metadata
127
+ original_metadata: instagram_metadata,
128
+ media_type: instagram_metadata.type,
129
+ video_url: instagram_metadata.videos && instagram_metadata.videos.standard_resolution.url
128
130
  }
129
131
  end
130
132
 
@@ -152,7 +154,9 @@ module Lentil
152
154
  :description => image_data[:name],
153
155
  :url => image_data[:url],
154
156
  :long_url => image_data[:large_url],
155
- :original_datetime => image_data[:original_datetime]
157
+ :video_url => image_data[:video_url],
158
+ :original_datetime => image_data[:original_datetime],
159
+ :media_type => image_data[:media_type]
156
160
  })
157
161
 
158
162
  # This is a temporary fix for a bug in the Hashie to_hash method.
@@ -240,6 +244,30 @@ module Lentil
240
244
 
241
245
  response.body
242
246
  end
247
+
248
+ #
249
+ # Retrieve the binary video data for a given Image object
250
+ #
251
+ # @param [Image] image An Image model object from the Instagram service
252
+ #
253
+ # @raise [Exception] If there are request problems
254
+ #
255
+ # @return [String] Binary video data
256
+ def harvest_video_data(image)
257
+ response = Typhoeus.get(image.video_url, followlocation: true)
258
+
259
+ if response.success?
260
+ raise "Invalid content type: " + response.headers['Content-Type'] unless (response.headers['Content-Type'] == 'video/mp4')
261
+ elsif response.timed_out?
262
+ raise "Request timed out"
263
+ elsif response.code == 0
264
+ raise "Could not get an HTTP response"
265
+ else
266
+ raise "HTTP request failed: " + response.code.to_s
267
+ end
268
+
269
+ response.body
270
+ end
243
271
 
244
272
  #
245
273
  # Test if an image is still avaiable
@@ -1,3 +1,3 @@
1
1
  module Lentil
2
- VERSION = "0.3.1"
2
+ VERSION = "0.4.0"
3
3
  end
@@ -55,15 +55,24 @@ namespace :lentil do
55
55
 
56
56
  begin
57
57
  # TODO: Currently expects JPEG
58
+ video_file_path = image_file_path + "/#{image.external_identifier}.mp4"
58
59
  image_file_path += "/#{image.external_identifier}.jpg"
59
60
  raise "Image file already exists, will not overwrite: #{image_file_path}" if File.exist?(image_file_path)
60
61
 
61
62
  image_data = harvester.harvest_image_data(image)
62
-
63
+
63
64
  File.open(image_file_path, "wb") do |f|
64
65
  f.write image_data
65
66
  end
66
67
 
68
+ if image.media_type == "video"
69
+ raise "Video file already exists, will not overwrite: #{video_file_path}" if File.exist?(video_file_path)
70
+ video_data = harvester.harvest_video_data(image)
71
+ File.open(video_file_path, "wb") do |f|
72
+ f.write video_data
73
+ end
74
+ end
75
+
67
76
  image.file_harvested_date = DateTime.now
68
77
  image.save
69
78
  puts "Harvested image #{image.id}, #{image_file_path}"
@@ -135,5 +144,83 @@ namespace :lentil do
135
144
  end
136
145
  end
137
146
  end
147
+
148
+ desc "Get video urls from videos previously harvested"
149
+ task :restore_videos, [:image_service] => :environment do |t, args|
150
+ args.with_defaults(:image_service => 'Instagram')
151
+
152
+ harvester = Lentil::InstagramHarvester.new
153
+
154
+ lentilService = Lentil::Service.unscoped.where(:name => args[:image_service]).first
155
+ numUpdated = 0;
156
+ lentilService.images.unscoped.each do |image|
157
+ #Skip if media type already known i.e. was properly harvested
158
+ next if !image.media_type.blank?
159
+
160
+ meta = image.original_metadata
161
+ obj = YAML.load(meta)
162
+ type = obj["type"]
163
+ video_url = image.video_url
164
+ if(type == "video")
165
+ video_url = obj["videos"]["standard_resolution"]["url"]
166
+ image.video_url = video_url
167
+ image.media_type = 'video'
168
+ image.save
169
+ numUpdated += 1
170
+ else
171
+ image.media_type = 'image'
172
+ image.save
173
+ numUpdated += 1
174
+ end
175
+ end
176
+ puts numUpdated.to_s + " record(s) updated"
177
+ end
178
+
179
+ desc "Dump image metadata for archiving"
180
+ task :dump_metadata, [:image_service, :base_directory] => :environment do |t, args|
181
+ args.with_defaults(:image_service => 'Instagram')
182
+ base_dir = args[:base_directory] || Lentil::Engine::APP_CONFIG["base_image_file_dir"] || nil
183
+ raise "Base directory is required" unless base_dir
184
+
185
+ lentilService = Lentil::Service.unscoped.where(:name => args[:image_service]).first
186
+ numArchived = 0;
187
+ lentilService.images.unscoped.each do |image|
188
+ begin
189
+ raise "Destination directory does not exist or is not a directory: #{base_dir}" unless File.directory?(base_dir)
190
+
191
+ image_file_path = "#{base_dir}/#{image.service.name}"
192
+
193
+ if !File.exist?(image_file_path)
194
+ Dir.mkdir(image_file_path)
195
+ else
196
+ raise "Service directory is not a directory: #{image_file_path}" unless File.directory?(image_file_path)
197
+ end
198
+ rescue => e
199
+ Rails.logger.error e.message
200
+ raise e
201
+ end
202
+
203
+ @jsonobj = JSON.parse(image.to_json)
204
+ @jsonobj.delete("id")
205
+ @jsonobj["tags"] = JSON.parse(image.tags.to_json)
206
+ @jsonobj["licenses"] = JSON.parse(image.licenses.to_json)
207
+ @jsonobj["licenses"].each do |lic|
208
+ lic.delete("id")
209
+ end
210
+
211
+ @jsonobj["like_votes"] = JSON.parse(image.like_votes.to_json)
212
+ @jsonobj["flags"] = JSON.parse(image.flags.to_json)
213
+
214
+ @jsonobj["service"] = JSON.parse(image.service.to_json).except("id")
215
+ @jsonobj["user"] = JSON.parse(image.user.to_json).except("id", "service_id")
216
+
217
+ image_file_path += "/#{image.external_identifier}.json"
218
+ File.open(image_file_path, "w") do |f|
219
+ f.write @jsonobj.to_json
220
+ numArchived += 1
221
+ end
222
+ end
223
+ puts "#{numArchived} image(s) metadata extracted"
224
+ end
138
225
  end
139
226
  end
@@ -11,7 +11,7 @@
11
11
  #
12
12
  # It's strongly recommended to check this file into your version control system.
13
13
 
14
- ActiveRecord::Schema.define(:version => 20131205181204) do
14
+ ActiveRecord::Schema.define(:version => 20141106172834) do
15
15
 
16
16
  create_table "active_admin_comments", :force => true do |t|
17
17
  t.string "resource_id", :null => false
@@ -90,6 +90,8 @@ ActiveRecord::Schema.define(:version => 20131205181204) do
90
90
  t.datetime "donor_agreement_rejected"
91
91
  t.boolean "do_not_request_donation", :default => false
92
92
  t.datetime "last_donor_agreement_failure_date"
93
+ t.string "media_type"
94
+ t.string "video_url"
93
95
  end
94
96
 
95
97
  add_index "lentil_images", ["external_identifier"], :name => "index_images_on_external_identifier"
@@ -282,3 +282,76 @@ three:
282
282
  donor_agreement_failed: 0
283
283
  failed_file_checks: 0
284
284
  file_last_checked:
285
+
286
+ video:
287
+ description: 'six #hunttesting'
288
+ created_at: 2013-04-16 16:16:16.273698000 Z
289
+ updated_at: 2013-04-16 16:16:16.481430000 Z
290
+ like_votes_count: 0
291
+ url: http://instagram.com/p/k5LhuktiSC/
292
+ user: bd
293
+ state: 1
294
+ external_identifier: '853651752801735775_3292244'
295
+ long_url: http://scontent-b.cdninstagram.com/hphotos-xfa1/t51.2885-15/915706_724481087621112_1586087020_n.jpg
296
+ original_datetime: 2013-04-16 15:58:34.000000000 Z
297
+ staff_like: true
298
+ moderator_id:
299
+ moderated_at:
300
+ second_moderation: false
301
+ wins_count: 5
302
+ losses_count: 5
303
+ win_pct: 50
304
+ popular_score: 0
305
+ file_harvested_date:
306
+ file_harvest_failed: 0
307
+ donor_agreement_submitted_date:
308
+ donor_agreement_failed: 0
309
+ failed_file_checks: 0
310
+ file_last_checked:
311
+ original_metadata:
312
+ attribution:
313
+ tags:
314
+ - hunttesting
315
+ location:
316
+ comments:
317
+ count: 0
318
+ data: []
319
+ filter: Amaro
320
+ created_time: '1393448079'
321
+ link: http://instagram.com/p/k5LhuktiSC/
322
+ likes:
323
+ count: 0
324
+ data: []
325
+ images:
326
+ low_resolution:
327
+ url: http://distilleryimage8.s3.amazonaws.com/28b09b209f2811e38e831293e346cce0_6.jpg
328
+ width: 306
329
+ height: 306
330
+ thumbnail:
331
+ url: http://distilleryimage8.s3.amazonaws.com/28b09b209f2811e38e831293e346cce0_5.jpg
332
+ width: 150
333
+ height: 150
334
+ standard_resolution:
335
+ url: http://distilleryimage8.s3.amazonaws.com/28b09b209f2811e38e831293e346cce0_8.jpg
336
+ width: 612
337
+ height: 612
338
+ caption:
339
+ created_time: '1393448079'
340
+ text: ! 'six #hunttesting'
341
+ from:
342
+ username: bddnc
343
+ profile_picture: http://images.ak.instagram.com/profiles/anonymousUser.jpg
344
+ id: '1128023464'
345
+ full_name: bddnc
346
+ id: '664613117098338265'
347
+ type: image
348
+ id: '853651752801735775_3292244'
349
+ user:
350
+ username: bddnc
351
+ website: ''
352
+ profile_picture: http://images.ak.instagram.com/profiles/anonymousUser.jpg
353
+ full_name: bddnc
354
+ bio: ''
355
+ id: '1128023464'
356
+ video_url: 'http://scontent-b.cdninstagram.com/hphotos-xaf1/t50.2886-16/10814479_740198139394848_641606265_n.mp4'
357
+ media_type: 'video'
@@ -2,13 +2,15 @@ require 'test_helper'
2
2
 
3
3
  class ImagesShowIndexTest < ActionDispatch::IntegrationTest
4
4
 
5
- setup do
6
- visit(lentil.image_path lentil_images(:one))
7
- end
8
-
9
5
  # This is important otherwise there is some strange reloading that goes on
10
6
  test "should have a class on the body" do
7
+ visit(lentil.image_path lentil_images(:one))
11
8
  assert page.has_selector?('body.lentil-images_show')
12
9
  end
10
+
11
+ test "video should have a video tag" do
12
+ visit(lentil.image_path lentil_images(:video))
13
+ assert page.has_selector?('video')
14
+ end
13
15
 
14
- end
16
+ end
@@ -44,7 +44,7 @@ class ActionDispatch::IntegrationTest
44
44
  visit admin_root_path
45
45
  fill_in 'Email', with: 'admin@example.com'
46
46
  fill_in 'Password', with: 'password'
47
- click_on 'Sign in'
47
+ click_on 'Log in'
48
48
  end
49
49
 
50
50
  def browser_start
@@ -233,33 +233,41 @@
233
233
  $img.parent().css( 'background-image', 'url(' + src + ')' );
234
234
 
235
235
  if( loaded === count ) {
236
+ self._loadingComplete($imgs);
237
+ }
236
238
 
237
- $imgs.remove();
238
- self.$el.removeClass( 'ri-grid-loading' );
239
- // the items
240
- self.$items = self.$list.children( 'li' );
241
- // make a copy of the items
242
- self.$itemsCache = self.$items.clone();
243
- // total number of items
244
- self.itemsTotal = self.$items.length;
245
- // the items that will be out of the grid
246
- // actually the item's child (anchor element)
247
- self.outItems= [];
248
- self._layout( function() {
249
- self._initEvents();
250
- } );
251
- // replace [options.step] items after [options.interval] time
252
- // the items that go out are randomly chosen, while the ones that get in
253
- // follow a "First In First Out" logic
254
- self._start();
239
+ } ).bind('error', function() {
240
+ count--;
255
241
 
242
+ if( loaded === count ) {
243
+ self._loadingComplete($imgs);
256
244
  }
245
+ }).attr( 'src', src );
257
246
 
258
- } ).attr( 'src', src )
259
-
260
247
  } );
261
248
 
262
249
  },
250
+ _loadingComplete : function($imgs) {
251
+ var self = this;
252
+ $imgs.remove();
253
+ self.$el.removeClass( 'ri-grid-loading' );
254
+ // the items
255
+ self.$items = self.$list.children( 'li' );
256
+ // make a copy of the items
257
+ self.$itemsCache = self.$items.clone();
258
+ // total number of items
259
+ self.itemsTotal = self.$items.length;
260
+ // the items that will be out of the grid
261
+ // actually the item's child (anchor element)
262
+ self.outItems= [];
263
+ self._layout( function() {
264
+ self._initEvents();
265
+ } );
266
+ // replace [options.step] items after [options.interval] time
267
+ // the items that go out are randomly chosen, while the ones that get in
268
+ // follow a "First In First Out" logic
269
+ self._start();
270
+ },
263
271
  _layout : function( callback ) {
264
272
 
265
273
  var self = this;
@@ -643,6 +651,11 @@
643
651
  }
644
652
 
645
653
  $el.next().remove();
654
+ var videos = $el.find("video");
655
+ if(videos.length !== 0) {
656
+ //Since it's a clone, have to start the event manually
657
+ videos[0].play();
658
+ }
646
659
  $el.parent().data( 'active', false );
647
660
 
648
661
  }, t );
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: lentil
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.1
4
+ version: 0.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jason Casden
@@ -11,7 +11,7 @@ authors:
11
11
  autorequire:
12
12
  bindir: bin
13
13
  cert_chain: []
14
- date: 2014-11-11 00:00:00.000000000 Z
14
+ date: 2015-03-03 00:00:00.000000000 Z
15
15
  dependencies:
16
16
  - !ruby/object:Gem::Dependency
17
17
  name: rails
@@ -19,14 +19,14 @@ dependencies:
19
19
  requirements:
20
20
  - - "~>"
21
21
  - !ruby/object:Gem::Version
22
- version: 3.2.20
22
+ version: 3.2.21
23
23
  type: :runtime
24
24
  prerelease: false
25
25
  version_requirements: !ruby/object:Gem::Requirement
26
26
  requirements:
27
27
  - - "~>"
28
28
  - !ruby/object:Gem::Version
29
- version: 3.2.20
29
+ version: 3.2.21
30
30
  - !ruby/object:Gem::Dependency
31
31
  name: jquery-rails
32
32
  requirement: !ruby/object:Gem::Requirement
@@ -61,14 +61,14 @@ dependencies:
61
61
  requirements:
62
62
  - - "~>"
63
63
  - !ruby/object:Gem::Version
64
- version: 3.2.0
64
+ version: 3.4.1
65
65
  type: :runtime
66
66
  prerelease: false
67
67
  version_requirements: !ruby/object:Gem::Requirement
68
68
  requirements:
69
69
  - - "~>"
70
70
  - !ruby/object:Gem::Version
71
- version: 3.2.0
71
+ version: 3.4.1
72
72
  - !ruby/object:Gem::Dependency
73
73
  name: meta_search
74
74
  requirement: !ruby/object:Gem::Requirement
@@ -646,6 +646,7 @@ files:
646
646
  - db/migrate/20130506204728_add_donor_agreement_rejected_to_images.rb
647
647
  - db/migrate/20130506205348_add_do_not_request_donation_to_lentil_images.rb
648
648
  - db/migrate/20131205181204_add_last_donor_agreement_failure_date_to_lentil_images.rb
649
+ - db/migrate/20141106172834_add_type_to_images.rb
649
650
  - db/seeds.rb
650
651
  - lib/generators/lentil/USAGE
651
652
  - lib/generators/lentil/install_generator.rb
@@ -856,7 +857,8 @@ homepage: https://github.com/NCSU-Libraries/lentil
856
857
  licenses:
857
858
  - MIT
858
859
  metadata: {}
859
- post_install_message:
860
+ post_install_message: You may need to run 'bundle exec rake lentil:install:migrations'
861
+ to incorporate any new database migration files.
860
862
  rdoc_options: []
861
863
  require_paths:
862
864
  - lib
@@ -872,7 +874,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
872
874
  version: '0'
873
875
  requirements: []
874
876
  rubyforge_project:
875
- rubygems_version: 2.4.2
877
+ rubygems_version: 2.4.6
876
878
  signing_key:
877
879
  specification_version: 4
878
880
  summary: lentil supports the harvesting of images from Instagram.