diff --git a/Gemfile b/Gemfile index 3f23fef6..99544a19 100644 --- a/Gemfile +++ b/Gemfile @@ -8,7 +8,7 @@ gem 'bcrypt' gem 'sinatra-flash', require: 'sinatra/flash' gem 'sinatra-xsendfile', require: 'sinatra/xsendfile' gem 'puma', '5.6.5', require: nil -gem 'sidekiq', '~> 5.2.0' +gem 'sidekiq', '~> 7.0.8' gem 'mail' gem 'net-smtp' gem 'tilt' diff --git a/Gemfile.lock b/Gemfile.lock index 539127bf..9ef6a41b 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -49,7 +49,7 @@ GEM climate_control (0.2.0) coderay (1.1.3) concurrent-ruby (1.2.2) - connection_pool (2.3.0) + connection_pool (2.4.0) coveralls_reborn (0.25.0) simplecov (>= 0.18.1, < 0.22.0) term-ansicolor (~> 1.6) @@ -187,11 +187,11 @@ GEM net-protocol netrc (0.11.0) nio4r (2.5.8) - nokogiri (1.13.10-x86_64-linux) + nokogiri (1.14.3-x86_64-linux) racc (~> 1.4) ox (2.14.11) paypal-recurring (1.1.0) - pg (1.4.4) + pg (1.5.3) progress (3.6.0) pry (0.14.1) coderay (~> 1.1) @@ -199,7 +199,7 @@ GEM public_suffix (5.0.0) puma (5.6.5) nio4r (~> 2.0) - racc (1.6.2) + racc (1.7.1) rack (2.2.6.4) rack-cache (1.13.0) rack (>= 0.4) @@ -215,6 +215,8 @@ GEM rb-inotify (0.10.1) ffi (~> 1.0) redis (4.5.1) + redis-client (0.14.1) + connection_pool redis-namespace (1.9.0) redis (>= 4) regexp_parser (2.6.0) @@ -230,7 +232,7 @@ GEM rszr (1.3.0) ruby-progressbar (1.11.0) ruby2_keywords (0.0.5) - sanitize (6.0.1) + sanitize (6.0.2) crass (~> 1.0.2) nokogiri (>= 1.12.0) sass (3.7.4) @@ -239,17 +241,17 @@ GEM rb-fsevent (~> 0.9, >= 0.9.4) rb-inotify (~> 0.9, >= 0.9.7) sax-machine (1.3.2) - sequel (5.62.0) - sequel_pg (1.17.0) + sequel (5.68.0) + sequel_pg (1.17.1) pg (>= 0.18.0, != 1.2.0) sequel (>= 4.38.0) shotgun (0.9.2) rack (>= 1.0) - sidekiq (5.2.10) - connection_pool (~> 2.2, >= 2.2.2) - rack (~> 2.0) - rack-protection (>= 1.5.0) - redis (~> 4.5, < 4.6.0) + sidekiq (7.0.8) + concurrent-ruby (< 2) + connection_pool (>= 2.3.0) + rack (>= 2.2.4) + redis-client (>= 0.11.0) simplecov (0.21.2) docile (~> 1.1) simplecov-html (~> 0.11) @@ -370,7 +372,7 @@ DEPENDENCIES sequel sequel_pg shotgun - sidekiq (~> 5.2.0) + sidekiq (~> 7.0.8) simplecov simpleidn sinatra diff --git a/app/create.rb b/app/create.rb index 101633bd..3506d43c 100644 --- a/app/create.rb +++ b/app/create.rb @@ -1,7 +1,12 @@ CREATE_MATCH_REGEX = /^username$|^password$|^email$|^new_tags_string$|^is_education$/ +def education_whitelist_required? + return true if params[:is_education] == 'true' && $config['education_tag_whitelist'] + false +end + def education_whitelisted? - return true if params[:is_education] == 'true' && $config['education_tag_whitelist'] && !$config['education_tag_whitelist'].select {|t| params[:new_tags_string].match(t)}.empty? + return true if education_whitelist_required? && !$config['education_tag_whitelist'].select {|t| params[:new_tags_string].match(t)}.empty? false end @@ -63,8 +68,13 @@ post '/create' do ga_adgroupid: session[:ga_adgroupid] ) - if education_whitelisted? - @site.email_confirmed = true + if education_whitelist_required? + if education_whitelisted? + @site.email_confirmed = true + else + flash[:error] = 'The class tag is invalid.' + return {result: 'error'}.to_json + end else if !hcaptcha_valid? flash[:error] = 'The captcha was not valid, please try again.' diff --git a/app/settings.rb b/app/settings.rb index 27b8b6cd..e343582f 100644 --- a/app/settings.rb +++ b/app/settings.rb @@ -20,6 +20,9 @@ get '/settings/:username/?' do |username| pass if Site.select(:id).where(username: username).first.nil? require_login require_ownership_for_settings + + @bluesky_did = $redis_proxy.hget "dns-_atproto.#{@site.username}.neocities.org", 'TXT' + @title = "Site settings for #{username}" erb :'settings/site' end @@ -174,15 +177,33 @@ post '/settings/:username/custom_domain' do end end +post '/settings/:username/bluesky_set_did' do + require_login + require_ownership_for_settings + redirect '/settings' if !@site.domain.empty? + + # todo standards based validation + if params[:did].length > 50 + flash[:error] = 'DID provided was too long' + elsif !params[:did].match(/^did=did:plc:([a-z|0-9)]+)$/) + flash[:error] = 'DID was invalid' + else + $redis_proxy.hset "dns-_atproto.#{@site.username}.neocities.org", 'TXT', params[:did] + flash[:success] = 'DID set! You can now verify the domain on the Bluesky app.' + end + + redirect "/settings/#{@site.username}#bluesky" +end + post '/settings/:username/generate_api_key' do require_login require_ownership_for_settings - is_new = current_site.api_key.nil? - current_site.generate_api_key! + is_new = @site.api_key.nil? + @site.generate_api_key! msg = is_new ? "New API key has been generated." : "API key has been regenerated." flash[:success] = msg - redirect "/settings/#{current_site.username}#api_key" + redirect "/settings/#{@site.username}#api_key" end post '/settings/change_password' do diff --git a/models/event.rb b/models/event.rb index cdb25fd2..88122284 100644 --- a/models/event.rb +++ b/models/event.rb @@ -35,6 +35,7 @@ class Event < Sequel::Model ds = select_all(:events). order(:created_at.desc). join_table(:inner, :sites, id: :site_id). + where(follow_id: nil). exclude(Sequel.qualify(:sites, :is_deleted) => true). exclude(Sequel.qualify(:events, :is_deleted) => true). exclude(is_banned: true) diff --git a/models/site.rb b/models/site.rb index 9e3927c3..f45c2bea 100644 --- a/models/site.rb +++ b/models/site.rb @@ -35,6 +35,7 @@ class Site < Sequel::Model application/rss+xml application/x-elc image/webp + image/avif image/x-xcf application/epub application/epub+zip @@ -43,11 +44,11 @@ class Site < Sequel::Model } VALID_EXTENSIONS = %w{ - html htm txt text css js jpg jpeg png gif svg md markdown eot ttf woff woff2 json geojson csv tsv mf ico pdf asc key pgp xml mid midi manifest otf webapp less sass rss kml dae obj mtl scss webp xcf epub gltf bin webmanifest knowl atom opml rdf map gpg + html htm txt text css js jpg jpeg png gif svg md markdown eot ttf woff woff2 json geojson csv tsv mf ico pdf asc key pgp xml mid midi manifest otf webapp less sass rss kml dae obj mtl scss webp avif xcf epub gltf bin webmanifest knowl atom opml rdf map gpg resolveHandle } VALID_EDITABLE_EXTENSIONS = %w{ - html htm txt js css scss md manifest less webmanifest xml json opml rdf svg gpg pgp + html htm txt js css scss md manifest less webmanifest xml json opml rdf svg gpg pgp resolveHandle } MINIMUM_PASSWORD_LENGTH = 5 @@ -166,6 +167,7 @@ class Site < Sequel::Model MAX_COMMENTS_PER_DAY = 5 SANDBOX_TIME = 14.days BLACK_BOX_WAIT_TIME = 10.seconds + MAX_DISPLAY_FOLLOWS = 56*3 many_to_many :tags @@ -568,8 +570,8 @@ class Site < Sequel::Model follows_dataset.all end - def profile_follows_actioning_ids - follows_dataset.select(:actioning_site_id).exclude(:sites__site_changed => false).all + def profile_follows_actioning_ids(limit=nil) + follows_dataset.select(:actioning_site_id).exclude(:sites__site_changed => false).limit(limit).all end =begin @@ -1447,6 +1449,10 @@ class Site < Sequel::Model paginate(current_page, limit) end + def newest_follows + follows_dataset.where(:follows__created_at => (1.month.ago..Time.now)).order(:follows__created_at.desc).all + end + def host !domain.empty? ? domain : "#{username}.neocities.org" end diff --git a/tests/acceptance/settings/site_tests.rb b/tests/acceptance/settings/site_tests.rb index 5a9b4c27..387aad27 100644 --- a/tests/acceptance/settings/site_tests.rb +++ b/tests/acceptance/settings/site_tests.rb @@ -145,6 +145,35 @@ describe 'site/settings' do end end +describe 'api key' do + include Capybara::DSL + + before do + Capybara.reset_sessions! + @site = Fabricate :site + @child_site = Fabricate :site, parent_site_id: @site.id + page.set_rack_session id: @site.id + end + + it 'sets api key' do + visit "/settings/#{@child_site[:username]}#api_key" + _(@site.api_key).must_be_nil + _(@child_site.api_key).must_be_nil + click_button 'Generate API Key' + _(@site.reload.api_key).must_be_nil + _(@child_site.reload.api_key).wont_be_nil + _(page.body).must_match @child_site.api_key + end + + it 'regenerates api key for child site' do + visit "/settings/#{@child_site[:username]}#api_key" + @child_site.generate_api_key! + api_key = @child_site.api_key + click_button 'Generate API Key' + _(@child_site.reload.api_key).wont_equal api_key + end +end + describe 'delete' do include Capybara::DSL diff --git a/tests/acceptance/site_tests.rb b/tests/acceptance/site_tests.rb index 1656ddb4..5ab20e76 100644 --- a/tests/acceptance/site_tests.rb +++ b/tests/acceptance/site_tests.rb @@ -64,36 +64,45 @@ describe 'site page' do end - it 'allows site blocking and unblocking' do - tag = SecureRandom.hex 10 - blocked_site = Fabricate :site, new_tags_string: tag, created_at: 2.weeks.ago, site_changed: true, views: Site::BROWSE_MINIMUM_FOLLOWER_VIEWS+1 - site = Fabricate :site + describe 'blocking' do + before do + @tag = SecureRandom.hex 10 + @blocked_site = Fabricate :site, new_tags_string: @tag, created_at: 2.weeks.ago, site_changed: true, views: Site::BROWSE_MINIMUM_FOLLOWER_VIEWS+1 + end - page.set_rack_session id: site.id + after do + @blocked_site.destroy + end - visit "/browse?tag=#{tag}" + it 'allows site blocking and unblocking' do + site = Fabricate :site - _(page.find('.website-Gallery .username a')['href']).must_match /\/site\/#{blocked_site.username}/ + page.set_rack_session id: site.id - visit "/site/#{blocked_site.username}" + visit "/browse?tag=#{@tag}" - click_link 'Block' - click_button 'Block Site' + _(page.find('.website-Gallery .username a')['href']).must_match /\/site\/#{@blocked_site.username}/ - visit "/browse?tag=#{tag}" + visit "/site/#{@blocked_site.username}" - _(page).must_have_content /no active sites found/i + click_link 'Block' + click_button 'Block Site' - site.reload - _(site.blockings.length).must_equal 1 - _(site.blockings.first.site_id).must_equal blocked_site.id + visit "/browse?tag=#{@tag}" - visit "/site/#{blocked_site.username}" + _(page).must_have_content /no active sites found/i - click_link 'Unblock' + site.reload + _(site.blockings.length).must_equal 1 + _(site.blockings.first.site_id).must_equal @blocked_site.id - visit "/browse?tag=#{tag}" - _(page.find('.website-Gallery .username a')['href']).must_match /\/site\/#{blocked_site.username}/ + visit "/site/#{@blocked_site.username}" + + click_link 'Unblock' + + visit "/browse?tag=#{@tag}" + _(page.find('.website-Gallery .username a')['href']).must_match /\/site\/#{@blocked_site.username}/ + end end it '404s if site is banned' do diff --git a/vagrant/webapp.sh b/vagrant/webapp.sh index f0fb1228..fbddae89 100644 --- a/vagrant/webapp.sh +++ b/vagrant/webapp.sh @@ -4,7 +4,28 @@ DEBIAN_FRONTEND=noninteractive . /vagrant/vagrant/redis.sh -apt-get install -y git curl zlib1g-dev build-essential libssl-dev libreadline-dev libyaml-dev libsqlite3-dev sqlite3 libxml2-dev libxslt1-dev libcurl4-openssl-dev libffi-dev libpq-dev libmagickwand-dev imagemagick libmagickwand-dev libmagic-dev file clamav-daemon +apt-get install -y \ + build-essential \ + clamav-daemon \ + curl \ + file \ + git \ + imagemagick \ + libcurl4-openssl-dev \ + libffi-dev \ + libimlib2-dev \ + libmagic-dev \ + libmagickwand-dev \ + libpq-dev \ + libreadline-dev \ + libsqlite3-dev \ + libssl-dev \ + libwebp-dev \ + libxml2-dev \ + libxslt1-dev \ + libyaml-dev \ + sqlite3 \ + zlib1g-dev sed -i 's|[#]*DetectPUA false|DetectPUA true|g' /etc/clamav/clamd.conf diff --git a/views/_follows.erb b/views/_follows.erb index d9e1a6aa..851257e7 100644 --- a/views/_follows.erb +++ b/views/_follows.erb @@ -1,8 +1,8 @@ -<% site_followings = site.followings %> -<% if (!is_current_site && !site_followings.empty?) || is_current_site %> +<% site_followings = site.followings_dataset.count %> +<% if (!is_current_site && site_followings > 0) || is_current_site %>

<%= is_current_site ? 'Sites you follow' : 'This site follows' %>

- <% if site_followings.empty? %> + <% if site_followings == 0 %>

You are not following any sites yet. Add some by browsing sites or looking at your tags. <% else %> <% site.followings_dataset.select(:site_id).all.each do |following| %> @@ -12,17 +12,22 @@

<% end %> -<% site_follows = site.follows %> -<% if (!is_current_site && !site_follows.empty?) || is_current_site %> +<% site_follows = site.follows_dataset.count %> +<% if (!is_current_site && site_follows > 0) || is_current_site %>

Followers

- <% if site_follows.empty? %> + <% if site_follows == 0 %> No followers yet. <% else %> - <% site.profile_follows_actioning_ids.each do |follow| %> + <% site_profile_follows_actioning_ids = site.profile_follows_actioning_ids %> + <% site_profile_follows_actioning_ids[0...Site::MAX_DISPLAY_FOLLOWS].each do |follow| %> <% follow_actioning_site = follow.actioning_site_dataset.select(:username).first %> <% end %> + + <% if Site::MAX_DISPLAY_FOLLOWS < site_profile_follows_actioning_ids.count %> + see more + <% end %> <% end %>
<% end %> diff --git a/views/_news.erb b/views/_news.erb index 15631481..f6afdf28 100644 --- a/views/_news.erb +++ b/views/_news.erb @@ -10,51 +10,32 @@ +<% if defined?(site) && !params[:event_id] %> + <% follow_events = site.newest_follows %> + <% unless follow_events.empty? %> +
+
+ +
+ New Followers +
+ +
+ <% follow_events.first.site.newest_follows.each_with_index do |event,i| %> + <% if event.actioning_site.supporter? %><% end %><%= event.actioning_site.username %><% unless follow_events.length == i+1 %>, <% end %> + <% end %> +
+
+ <% end %> +<% end %> + <% events.each do |event| %> <% if event.profile_comment_id %>
<%== erb :'_news_profile_comment', layout: false, locals: {profile_comment: event.profile_comment, event: event} %> <% elsif event.tip_id %> - <% actioning_site = event.actioning_site_dataset.select(:id, :username, :title, :domain, :stripe_customer_id, :plan_type).first %> - <% event_site = event.site_dataset.select(:id, :username, :title, :domain, :stripe_customer_id, :plan_type).first %> - <% tip = event.tip %> -
-
-
- <% if actioning_site %> - - <% end %> -
- -
-
- <% if actioning_site %> - <% if current_site && current_site.id == actioning_site.id %> - You - <% else %> - <% if actioning_site.supporter? %><% end %><%= actioning_site.username %> - <% end %> - <% else %> - An anonymous donor - <% end %> - - sent a <%= tip.amount_string %> tip to - - <% if current_site && event_site.id == current_site.id %> - you! - <% else %> - <% if event_site.supporter? %><% end %><%= event_site.username %>! - <% end %> -
- - <%= tip.message %> -
- - - <%= event.created_at.ago %> - -
- +
+ <%== erb :'_news_tip', layout: false, locals: {tip: event.tip, event: event} %> <% elsif event.follow_id %> <% actioning_site = event.actioning_site_dataset.select(:id, :username, :title, :domain, :stripe_customer_id, :plan_type).first %> <% next if actioning_site.nil? %> diff --git a/views/_news_tip.erb b/views/_news_tip.erb new file mode 100644 index 00000000..6a717a9f --- /dev/null +++ b/views/_news_tip.erb @@ -0,0 +1,36 @@ +<% actioning_site = event.tip.actioning_site_dataset.select(:id, :username, :stripe_customer_id, :plan_type, :parent_site_id).first %> +<% event_site = event.site_dataset.select(:id, :username, :stripe_customer_id, :plan_type, :parent_site_id).first %> + +
+ +
+ <% if actioning_site %> + + <% end %> +
+ +
+ <% if actioning_site %> + <% if current_site && current_site.id == actioning_site.id %> + You + <% else %> + <% if actioning_site.supporter? %><% end %><%= actioning_site.username %> + <% end %> + <% else %> + An anonymous donor + <% end %> + + sent a <%= tip.amount_string %> tip to + <% if current_site && event_site.id == current_site.id %> + you + <% else %> + <% if event_site.supporter? %><% end %><%= event_site.username %> + <% end %> +
+ + + <%= event.created_at.ago %> + +
+ +
<%== sanitize_comment tip.message %>
diff --git a/views/_share.erb b/views/_share.erb index 7c869c43..c228c541 100644 --- a/views/_share.erb +++ b/views/_share.erb @@ -13,4 +13,4 @@
" target="_blank">Tumblr
-" target="_blank">Mastodon +" target="_blank">Mastodon diff --git a/views/settings/site.erb b/views/settings/site.erb index bf34f3ae..09b732d9 100644 --- a/views/settings/site.erb +++ b/views/settings/site.erb @@ -26,15 +26,19 @@
  • Profile
  • Custom Domain
  • -
  • Change Site Name
  • +
  • Rename
  • Tipping
  • -
  • API Key
  • +
  • API
  • <% if @site.admin_nsfw != true %>
  • 18+
  • <% end %> + <% if @site.domain.empty? %> +
  • Bluesky
  • + <% end %> +
  • Delete
  • @@ -64,6 +68,10 @@
    <% end %> +
    + <%== erb :'settings/site/bluesky' %> +
    +
    <%== erb :'settings/site/delete' %>
    diff --git a/views/settings/site/bluesky.erb b/views/settings/site/bluesky.erb new file mode 100644 index 00000000..f066b39b --- /dev/null +++ b/views/settings/site/bluesky.erb @@ -0,0 +1,24 @@ +

    Bluesky Integration (beta)

    + +

    + You can now verify control of your site on Neocities to create a handle on Bluesky. +

    + +

    + Bluesky App "Settings" "Change my handle" "I have my own domain" +

    + +

    + Domain: @<%= @site.username %>.neocities.org +

    + +

    +TXT value: +

    + +
    + <%== csrf_token_input_html %> + +
    + +
    \ No newline at end of file diff --git a/views/site.erb b/views/site.erb index b8df7627..bbbd2c35 100644 --- a/views/site.erb +++ b/views/site.erb @@ -74,9 +74,9 @@

    <% end %>
    - <%== erb :'_news', layout: false, locals: {site: @site, events: @latest_events} %> + <%== erb :'_news', layout: false, locals: {site: site, events: @latest_events} %> <% else %> -
    <%== erb :'_news', layout: false, locals: {site: @site, events: @latest_events} %>
    +
    <%== erb :'_news', layout: false, locals: {site: site, events: @latest_events} %>
    <% end %>
    diff --git a/views/site_files/text_editor.erb b/views/site_files/text_editor.erb index 9a5f7a79..f60a22af 100644 --- a/views/site_files/text_editor.erb +++ b/views/site_files/text_editor.erb @@ -163,42 +163,47 @@ var editor = {} + $(document).ready(function() { - $.get("/site_files/download/<%= Addressable::URI.parse(@filename).normalized_path.to_s %>", function(resp) { - editor = ace.edit("editor") - setTheme() - <% if @ace_mode %> - editor.getSession().setMode("ace/mode/<%= @ace_mode %>") - <% end %> - editor.getSession().setTabSize(2) - editor.getSession().setUseWrapMode(true) - editor.setFontSize(14) - editor.setShowPrintMargin(false) - editor.setOptions({ - maxLines: Infinity, - autoScrollEditorIntoView: true - }) + $.ajax({ + url: "/site_files/download/<%= Addressable::URI.parse(@filename).normalized_path.to_s %>", + cache: false, + success: function(resp) { + editor = ace.edit("editor") + setTheme() + <% if @ace_mode %> + editor.getSession().setMode("ace/mode/<%= @ace_mode %>") + <% end %> + editor.getSession().setTabSize(2) + editor.getSession().setUseWrapMode(true) + editor.setFontSize(14) + editor.setShowPrintMargin(false) + editor.setOptions({ + maxLines: Infinity, + autoScrollEditorIntoView: true + }) - // Disable autocomplete - editor.setBehavioursEnabled(false) + // Disable autocomplete + editor.setBehavioursEnabled(false) - editor.setValue(resp, -1) - editor.getSession().setUndoManager(new ace.UndoManager()) + editor.setValue(resp, -1) + editor.getSession().setUndoManager(new ace.UndoManager()) - editor.on('change', function(obj) { - $('a#saveButton,a#saveAndExitButton').css('opacity', 1) - unsavedChanges = true - }) + editor.on('change', function(obj) { + $('a#saveButton,a#saveAndExitButton').css('opacity', 1) + unsavedChanges = true + }) - editor.commands.addCommand({ - name: 'saveCommand', - bindKey: {win: 'Ctrl-S', mac: 'Command-S'}, - exec: function(editor) { - saveTextFile(false) - } - }) - }) - }) + editor.commands.addCommand({ + name: 'saveCommand', + bindKey: {win: 'Ctrl-S', mac: 'Command-S'}, + exec: function(editor) { + saveTextFile(false) + } + }) + } + }); + }); window.onbeforeunload = function() { if(unsavedChanges == true) diff --git a/workers/lets_encrypt_worker.rb b/workers/lets_encrypt_worker.rb index afdb090e..d151889d 100644 --- a/workers/lets_encrypt_worker.rb +++ b/workers/lets_encrypt_worker.rb @@ -64,7 +64,11 @@ class LetsEncryptWorker puts "testing #{challenge_url}" begin - res = HTTP.timeout(connect: 10, write: 10, read: 10).follow.get(challenge_url) + # Some dumb letsencrypt related cert expiration issue hotfix + ctx = OpenSSL::SSL::SSLContext.new + ctx.verify_mode = OpenSSL::SSL::VERIFY_NONE + + res = HTTP.timeout(connect: 10, write: 10, read: 10).follow.get(challenge_url, ssl_context: ctx) rescue => e puts e.inspect puts "error with #{challenge_url}" diff --git a/workers/screenshot_worker.rb b/workers/screenshot_worker.rb index 31cdc52e..53adc65a 100644 --- a/workers/screenshot_worker.rb +++ b/workers/screenshot_worker.rb @@ -6,7 +6,7 @@ class ScreenshotWorker HARD_TIMEOUT = 30.freeze PAGE_WAIT_TIME = 5.freeze # 3D/VR sites take a bit to render after loading usually. include Sidekiq::Worker - sidekiq_options queue: :screenshots, retry: 2, backtrace: true + sidekiq_options queue: :screenshots, retry: 10, backtrace: true def perform(username, path) site = Site[username: username] @@ -47,19 +47,21 @@ class ScreenshotWorker base_image_tmpfile_path = "/tmp/#{SecureRandom.uuid}.png" http_resp = HTTP.basic_auth(user: api_user, pass: api_password).get(uri) - BlackBox.new(site, path).check_uri(http_resp.headers['X-URL']) if defined?(BlackBox) + BlackBox.new(site, path).check_uri(http_resp.headers['X-URL']) if defined?(BlackBox) && http_resp.headers['X-URL'] File.write base_image_tmpfile_path, http_resp.to_s user_screenshots_path = File.join SCREENSHOTS_PATH, Site.sharding_dir(username), username screenshot_path = File.join user_screenshots_path, File.dirname(path_for_screenshot) FileUtils.mkdir_p screenshot_path unless Dir.exist?(screenshot_path) + FileUtils.cp base_image_tmpfile_path, File.join(user_screenshots_path, "#{path_for_screenshot}.png") + Site::SCREENSHOT_RESOLUTIONS.each do |res| width, height = res.split('x').collect {|r| r.to_i} full_screenshot_path = File.join(user_screenshots_path, "#{path_for_screenshot}.#{res}.webp") - opts = {quality: 90, resize_w: width, resize_h: height} + opts = {resize_w: width, resize_h: height, near_lossless: 0} if width == height opts.merge! crop_x: 160, crop_y: 0, crop_w: 960, crop_h: 960 @@ -69,6 +71,8 @@ class ScreenshotWorker end true + rescue WebP::EncoderError => e + puts "Failed: #{username} #{path} #{e.inspect}" rescue => e raise e ensure diff --git a/workers/thumbnail_worker.rb b/workers/thumbnail_worker.rb index 1436a4c9..6b4a02a5 100644 --- a/workers/thumbnail_worker.rb +++ b/workers/thumbnail_worker.rb @@ -24,11 +24,20 @@ class ThumbnailWorker format = File.extname(path).gsub('.', '') full_thumbnail_path = File.join(user_thumbnails_path, "#{path}.#{res}.webp") - image = Rszr::Image.load site_file_path - if image.width > image.height - image.resize! width, :auto - else - image.resize! :auto, height + begin + image = Rszr::Image.load site_file_path + rescue Rszr::LoadError + next + end + + begin + if image.width > image.height + image.resize! width, :auto + else + image.resize! :auto, height + end + rescue Rszr::TransformationError + next end begin