From d9a1eeacc9ebbbae2dbae1465553e81bced20828 Mon Sep 17 00:00:00 2001 From: Albert Yi Date: Wed, 18 Jul 2018 10:54:03 -0700 Subject: [PATCH 1/4] Recommend posts on /posts/show based on voting patterns --- .env | 6 ++--- app/logical/post_sets/similar.rb | 19 ++++++++++++++ app/models/recommender_service.rb | 26 +++++++++++++++++++ .../posts/partials/index/_similar.html.erb | 7 +++++ app/views/posts/show.html.erb | 4 +++ 5 files changed, 59 insertions(+), 3 deletions(-) create mode 100644 app/logical/post_sets/similar.rb create mode 100644 app/models/recommender_service.rb create mode 100644 app/views/posts/partials/index/_similar.html.erb diff --git a/.env b/.env index 5a7e0f1ab..08f7601dc 100644 --- a/.env +++ b/.env @@ -80,8 +80,8 @@ # export DANBOORU_AWS_SQS_REGION= # export DANBOORU_IQDBS_AUTH_KEY= # export DANBOORU_IQDBS_SERVER= -# export DANBOORU_CCS_SERVER= -# export DANBOORU_CCS_KEY= # export DANBOORU_CLOUDFLARE_KEY= # export DANBOORU_CLOUDFLARE_EMAIL= -# export DANBOORU_CLOUDFLARE_ZONE= \ No newline at end of file +# export DANBOORU_CLOUDFLARE_ZONE= +# export DANBOORU_RECOMMENDER_KEY= +# export DANBOORU_RECOMMENDER_SERVER= diff --git a/app/logical/post_sets/similar.rb b/app/logical/post_sets/similar.rb new file mode 100644 index 000000000..65ab49c85 --- /dev/null +++ b/app/logical/post_sets/similar.rb @@ -0,0 +1,19 @@ +module PostSets + class Similar < PostSets::Post + def initialize(post) + super(tags) + end + + def posts + @posts ||= begin + post_ids, scores = RecommenderService.similar(post) + post_ids = post_ids.reject {|x| x == post.id}.slice(0, 5) + Post.find(post_ids) + end + end + + def presenter + ::Presenters::PostSetPresenters::Post.new(self) + end + end +end diff --git a/app/models/recommender_service.rb b/app/models/recommender_service.rb new file mode 100644 index 000000000..999da429b --- /dev/null +++ b/app/models/recommender_service.rb @@ -0,0 +1,26 @@ +module RecommenderService + extend self + + def enabled? + Danbooru.config.recommender_server.present? + end + + def available?(post) + enabled? && CurrentUser.id == 1 && post.created_at > 6.months.ago && post.score >= 10 + end + + def similar(post) + 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 + end +end diff --git a/app/views/posts/partials/index/_similar.html.erb b/app/views/posts/partials/index/_similar.html.erb new file mode 100644 index 000000000..ab2b750df --- /dev/null +++ b/app/views/posts/partials/index/_similar.html.erb @@ -0,0 +1,7 @@ +
+

You might also like:

+ +
+ <%= PostSets::Similar.new(post).presenter.post_previews_html(self) %> +
+
diff --git a/app/views/posts/show.html.erb b/app/views/posts/show.html.erb index a26557f35..260421775 100644 --- a/app/views/posts/show.html.erb +++ b/app/views/posts/show.html.erb @@ -82,6 +82,10 @@ <% end %> + <% if RecommenderService.available?(@post) %> + <%= render "posts/partials/index/similar", post: @post %> + <% end %> + <% if @post.presenter.has_nav_links?(self) %> <%= render "posts/partials/show/nav_links", :post => @post, :position => "bottom" %> <% end %> From 75162d3d8be406fd09ebcb8f09497e48534e0aa2 Mon Sep 17 00:00:00 2001 From: Albert Yi Date: Fri, 20 Jul 2018 12:30:29 -0700 Subject: [PATCH 2/4] bug fixes + tests --- app/assets/stylesheets/specific/posts.scss | 4 ++++ app/logical/post_sets/similar.rb | 11 ++++++----- app/views/posts/partials/index/_similar.html.erb | 8 ++++---- test/functional/posts_controller_test.rb | 16 ++++++++++++++++ 4 files changed, 30 insertions(+), 9 deletions(-) diff --git a/app/assets/stylesheets/specific/posts.scss b/app/assets/stylesheets/specific/posts.scss index ec0d180e5..97e3ff1ad 100644 --- a/app/assets/stylesheets/specific/posts.scss +++ b/app/assets/stylesheets/specific/posts.scss @@ -324,6 +324,10 @@ div#c-posts { font-weight: bold; } + .similar-posts { + margin-top: 1em; + } + #add-fav-button, #remove-fav-button { margin-top: 1em; } diff --git a/app/logical/post_sets/similar.rb b/app/logical/post_sets/similar.rb index 65ab49c85..b41166f94 100644 --- a/app/logical/post_sets/similar.rb +++ b/app/logical/post_sets/similar.rb @@ -1,19 +1,20 @@ module PostSets class Similar < PostSets::Post def initialize(post) - super(tags) + super("") + @post = post end def posts @posts ||= begin - post_ids, scores = RecommenderService.similar(post) - post_ids = post_ids.reject {|x| x == post.id}.slice(0, 5) - Post.find(post_ids) + response = RecommenderService.similar(@post) + post_ids = response.reject {|x| x[0] == @post.id}.slice(0, 5).map {|x| x[0]} + ::Post.find(post_ids) end end def presenter - ::Presenters::PostSetPresenters::Post.new(self) + ::PostSetPresenters::Post.new(self) end end end diff --git a/app/views/posts/partials/index/_similar.html.erb b/app/views/posts/partials/index/_similar.html.erb index ab2b750df..5f068dfd3 100644 --- a/app/views/posts/partials/index/_similar.html.erb +++ b/app/views/posts/partials/index/_similar.html.erb @@ -1,7 +1,7 @@ -
-

You might also like:

+
+

You might also like:

-
+
<%= PostSets::Similar.new(post).presenter.post_previews_html(self) %> -
+
diff --git a/test/functional/posts_controller_test.rb b/test/functional/posts_controller_test.rb index a1298709e..19e76597e 100644 --- a/test/functional/posts_controller_test.rb +++ b/test/functional/posts_controller_test.rb @@ -115,6 +115,22 @@ class PostsControllerTest < ActionDispatch::IntegrationTest get post_path(@post), params: {:id => @post.id} assert_response :success end + + context "when the recommend service is enabled" do + setup do + @post2 = create(:post) + RecommenderService.stubs(:enabled?).returns(true) + RecommenderService.stubs(:available?).returns(true) + RecommenderService.stubs(:similar).returns([[@post.id, "1.0"], [@post2.id, "0.01"]]) + end + + should "render a section for similar posts" do + get_auth post_path(@post), @user + assert_response :success + assert_select ".similar-posts" + assert_select ".similar-posts #post_#{@post2.id}" + end + end end context "update action" do From f75e0903e8c457854c877f927252ee596d1f5348 Mon Sep 17 00:00:00 2001 From: Albert Yi Date: Fri, 20 Jul 2018 13:18:24 -0700 Subject: [PATCH 3/4] add default values for recommender --- config/danbooru_default_config.rb | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/config/danbooru_default_config.rb b/config/danbooru_default_config.rb index 25c629298..e1110ca6f 100644 --- a/config/danbooru_default_config.rb +++ b/config/danbooru_default_config.rb @@ -783,6 +783,12 @@ module Danbooru def cloudflare_key end + + def recommender_server + end + + def recommender_key + end end class EnvironmentConfiguration From abcef9115be1de1d5f26d1bba0c52cf7ef547523 Mon Sep 17 00:00:00 2001 From: Albert Yi Date: Fri, 20 Jul 2018 13:52:56 -0700 Subject: [PATCH 4/4] fix tests --- app/controllers/wiki_pages_controller.rb | 2 +- test/functional/wiki_pages_controller_test.rb | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/app/controllers/wiki_pages_controller.rb b/app/controllers/wiki_pages_controller.rb index aedfffc30..5c3eab980 100644 --- a/app/controllers/wiki_pages_controller.rb +++ b/app/controllers/wiki_pages_controller.rb @@ -5,7 +5,7 @@ class WikiPagesController < ApplicationController before_action :normalize_search_params, :only => [:index] def new - @wiki_page = WikiPage.new(wiki_page_params) + @wiki_page = WikiPage.new(wiki_page_create_params) respond_with(@wiki_page) end diff --git a/test/functional/wiki_pages_controller_test.rb b/test/functional/wiki_pages_controller_test.rb index d5f046d9e..45e950d03 100644 --- a/test/functional/wiki_pages_controller_test.rb +++ b/test/functional/wiki_pages_controller_test.rb @@ -126,7 +126,7 @@ class WikiPagesControllerTest < ActionDispatch::IntegrationTest end should "rename a wiki page with a non-empty tag if secondary validations are skipped" do - put_auth wiki_page_path(@wiki_page), @user, params: {:wiki_page => {:title => "bar", :skip_secondary_validations => "1"}} + put_auth wiki_page_path(@wiki_page), @mod, params: {:wiki_page => {:title => "bar", :skip_secondary_validations => "1"}} assert_equal("bar", @wiki_page.reload.title) end