diff --git a/Gemfile b/Gemfile index a5791940b..a87bad6e0 100644 --- a/Gemfile +++ b/Gemfile @@ -65,6 +65,10 @@ group :production do gem 'capistrano-deploytags', '~> 1.0.0', require: false end +group :development do + gem 'sinatra' +end + group :development, :test do gem 'awesome_print' gem 'pry-byebug' diff --git a/Gemfile.lock b/Gemfile.lock index 9d60a85e4..034fa2351 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -237,6 +237,7 @@ GEM multi_json (1.13.1) multi_xml (0.6.0) multipart-post (2.0.0) + mustermann (1.0.2) naught (1.1.0) net-http-digest_auth (1.4.1) net-http-persistent (2.9.4) @@ -274,6 +275,8 @@ GEM win32-file (>= 0.7.0) public_suffix (3.0.2) rack (2.0.5) + rack-protection (2.0.3) + rack rack-test (1.0.0) rack (>= 1.0, < 3) radix62 (1.0.1) @@ -354,6 +357,11 @@ GEM json (>= 1.8, < 3) simplecov-html (~> 0.10.0) simplecov-html (0.10.2) + sinatra (2.0.3) + mustermann (~> 1.0) + rack (~> 2.0) + rack-protection (= 2.0.3) + tilt (~> 2.0) sprockets (3.7.1) concurrent-ruby (~> 1.0) rack (> 1, < 3) @@ -485,6 +493,7 @@ DEPENDENCIES shoulda-matchers simple_form simplecov + sinatra sprockets-rails statistics2 streamio-ffmpeg diff --git a/Procfile b/Procfile index c8f3a7913..54767a5b0 100644 --- a/Procfile +++ b/Procfile @@ -1,2 +1,6 @@ -unicorn: bundle exec rails server -jobs: bundle exec rake jobs:work +unicorn: bin/rails server -p 3000 +jobs: bin/rake jobs:work +recommender: bundle exec ruby script/mock_services/recommender.rb +iqdbs: bundle exec ruby script/mock_services/iqdbs.rb +reportbooru: bundle exec ruby script/mock_services/reportbooru.rb +listbooru: bundle exec ruby script/mock_services/listbooru.rb \ No newline at end of file diff --git a/app/assets/javascripts/posts.js.erb b/app/assets/javascripts/posts.js.erb index 0941d4581..aa7a0f2ab 100644 --- a/app/assets/javascripts/posts.js.erb +++ b/app/assets/javascripts/posts.js.erb @@ -452,6 +452,9 @@ $("#edit").hide(); $("#share").hide(); $("#recommended").show(); + $.get("/recommended_posts", {context: "post", post_id: Danbooru.meta("post-id")}, function(data) { + $("#recommended").html(data); + }); } else { $("#edit").hide(); $("#comments").hide(); diff --git a/app/controllers/recommended_posts_controller.rb b/app/controllers/recommended_posts_controller.rb new file mode 100644 index 000000000..8695ab6aa --- /dev/null +++ b/app/controllers/recommended_posts_controller.rb @@ -0,0 +1,23 @@ +class RecommendedPostsController < ApplicationController + before_action :member_only + respond_to :html + + def show + @posts = load_posts() + + if request.xhr? + render partial: "show", layout: false + end + end + +private + + def load_posts + if params[:context] == "post" + @posts = RecommenderService.recommend(post_id: params[:post_id]) + + elsif params[:context] == "user" + @posts = RecommenderService.recommend(user_id: CurrentUser.id) + end + end +end diff --git a/app/logical/post_sets/recommended.rb b/app/logical/post_sets/recommended.rb index 01ffe92c1..87b17803c 100644 --- a/app/logical/post_sets/recommended.rb +++ b/app/logical/post_sets/recommended.rb @@ -1,16 +1,10 @@ module PostSets class Recommended < PostSets::Post - def initialize(post) + attr_reader :posts + + def initialize(posts) super("") - @post = post - end - - def posts - @posts ||= begin - response = RecommenderService.similar(@post) - post_ids = response.reject {|x| x[0] == @post.id}.slice(0, 6).map {|x| x[0]} - ::Post.find(post_ids) - end + @posts = posts end def presenter diff --git a/app/models/recommender_service.rb b/app/models/recommender_service.rb index c0cbd6d51..97fd28bc0 100644 --- a/app/models/recommender_service.rb +++ b/app/models/recommender_service.rb @@ -1,25 +1,26 @@ module RecommenderService extend self - SCORE_THRESHOLD = 10 + SCORE_THRESHOLD = 5 def enabled? Danbooru.config.recommender_server.present? end - def available?(post) + def available_for_post?(post) return true if Rails.env.development? + enabled? && CurrentUser.enable_recommended_posts? && post.created_at > Date.civil(2018, 1, 1) && post.score >= SCORE_THRESHOLD end - def similar(post) - if Danbooru.config.recommender_server == "development" - return Post.order("random()").limit(6).map {|x| [x.id, "1.000"]} - end + def available_for_user? + enabled? && CurrentUser.is_gold? + end - Cache.get("rss:#{post.id}", 1.day) do + def recommend_for_user(user_id) + ids = Cache.get("rsu:#{user_id}", 1.day) do resp = HTTParty.get( - "#{Danbooru.config.recommender_server}/similar/#{post.id}", + "#{Danbooru.config.recommender_server}/recommend/#{user_id}", Danbooru.config.httparty_options.merge( basic_auth: { username: "danbooru", @@ -29,5 +30,30 @@ module RecommenderService ) JSON.parse(resp.body) end + Post.find(ids.map(&:first)) + end + + def recommend_for_post(post_id) + ids = Cache.get("rss:#{post_id}", 1.day) do + resp = HTTParty.get( + "#{Danbooru.config.recommender_server}/similar/#{post_id}", + Danbooru.config.httparty_options.merge( + basic_auth: { + username: "danbooru", + password: Danbooru.config.recommender_key + } + ) + ) + JSON.parse(resp.body) + end + Post.find(ids.reject {|x| x[0] == post_id}.map(&:first)) + end + + def recommend(post_id: nil, user_id: nil) + if post_id + recommend_for_post(post_id) + elsif user_id + recommend_for_user(user_id) + end end end diff --git a/app/views/posts/partials/common/_secondary_links.html.erb b/app/views/posts/partials/common/_secondary_links.html.erb index 754dac440..e8fb0cac8 100644 --- a/app/views/posts/partials/common/_secondary_links.html.erb +++ b/app/views/posts/partials/common/_secondary_links.html.erb @@ -3,6 +3,9 @@
Not enough data available
- <% end %> -Loading...
+
Recommended Posts
+ +Based on your voting history, you may enjoy these posts. Vote more to get more accurate results. These recommendations update every hour.
+ + <%= render partial: "show" %> +