]> cat aescling's git repositories - mastodon.git/commitdiff
Use charlock_holmes instead of nkf at FetchLinkCardService (#4080)
authornullkal <nullkal@users.noreply.github.com>
Sat, 8 Jul 2017 20:44:31 +0000 (05:44 +0900)
committerEugen Rochko <eugen@zeonfederated.com>
Sat, 8 Jul 2017 20:44:31 +0000 (22:44 +0200)
* Specs for language detection

* Use CharlockHolmes instead of NKF

* Correct mistakes

* Correct style

* Set hint_enc instead of falling back and strip_tags

* Improve specs

* Add dependencies

.travis.yml
Aptfile
Dockerfile
Gemfile
Gemfile.lock
Vagrantfile
app/services/fetch_link_card_service.rb
spec/fixtures/requests/koi8-r.txt [new file with mode: 0644]
spec/fixtures/requests/sjis.txt
spec/fixtures/requests/sjis_with_wrong_charset.txt [new file with mode: 0644]
spec/services/fetch_link_card_service_spec.rb

index 4bb33266644c2418a0dccefc0abb61d0f8694fe5..4d4dc089306b5f54dc99d586a0d564ecc9597f3b 100644 (file)
@@ -32,6 +32,7 @@ addons:
     - g++-6
     - libprotobuf-dev
     - protobuf-compiler
+    - libicu-dev
 
 rvm:
   - 2.3.4
diff --git a/Aptfile b/Aptfile
index 0456343ef48ed3a98c94c19127e4c8056d42600f..3af0956e32bb6f974571e062340db9b8f763d223 100644 (file)
--- a/Aptfile
+++ b/Aptfile
@@ -3,3 +3,4 @@ libprotobuf-dev
 ffmpeg
 libxdamage1
 libxfixes3
+libicu-dev
index 7033cddd406f6d6fa8bd8afe98121609b46aaa69..97a69139303b5ae307d7cce2bd83b8d33952eba9 100644 (file)
@@ -25,6 +25,7 @@ RUN echo "@edge https://nl.alpinelinux.org/alpine/edge/main" >> /etc/apk/reposit
     ffmpeg \
     file \
     git \
+    icu-dev \
     imagemagick@edge \
     libpq \
     libxml2 \
diff --git a/Gemfile b/Gemfile
index 95c74eef90012b40395a1c7a6eea77263694079c..b52685cba98e1da761d782fbf86bd0c9deed0096 100644 (file)
--- a/Gemfile
+++ b/Gemfile
@@ -22,6 +22,7 @@ gem 'active_model_serializers', '~> 0.10'
 gem 'addressable', '~> 2.5'
 gem 'bootsnap'
 gem 'browser'
+gem 'charlock_holmes', '~> 0.7.3'
 gem 'cld3', '~> 3.1'
 gem 'devise', '~> 4.2'
 gem 'devise-two-factor', '~> 3.0'
index 71f83f736672cc11c186c260ac33e4953bd69e08..de0d6a1072374d2872694f98933c54b77c235cd6 100644 (file)
@@ -106,6 +106,7 @@ GEM
       rack (>= 1.0.0)
       rack-test (>= 0.5.4)
       xpath (~> 2.0)
+    charlock_holmes (0.7.3)
     case_transform (0.2)
       activesupport
     chunky_png (1.3.8)
@@ -501,6 +502,7 @@ DEPENDENCIES
   capistrano-rbenv (~> 2.1)
   capistrano-yarn (~> 2.0)
   capybara (~> 2.14)
+  charlock_holmes (~> 0.7.3)
   cld3 (~> 3.1)
   climate_control (~> 0.2)
   devise (~> 4.2)
index 1f56fcfb3fe1e186733a51d796e613564ea76286..cbe6623b316a96b1d9a11225df2c9483c91d13f4 100644 (file)
@@ -37,6 +37,7 @@ sudo apt-get install \
   yarn \
   libprotobuf-dev \
   libreadline-dev \
+  libicu-dev \
   -y
 
 # Install rvm
index 8ddaa2bf403137e2703a4669a265caf2f128a491..6ef3abb66714dcd58011a24c1f3f231b1743938e 100644 (file)
@@ -1,5 +1,4 @@
 # frozen_string_literal: true
-require 'nkf'
 
 class FetchLinkCardService < BaseService
   include HttpHelper
@@ -86,7 +85,12 @@ class FetchLinkCardService < BaseService
     return if response.code != 200 || response.mime_type != 'text/html'
 
     html = response.to_s
-    page = Nokogiri::HTML(html, nil, NKF.guess(html).to_s)
+
+    detector = CharlockHolmes::EncodingDetector.new
+    detector.strip_tags = true
+
+    guess = detector.detect(html, response.charset)
+    page = Nokogiri::HTML(html, nil, guess&.fetch(:encoding))
 
     card.type             = :link
     card.title            = meta_property(page, 'og:title') || page.at_xpath('//title')&.content
diff --git a/spec/fixtures/requests/koi8-r.txt b/spec/fixtures/requests/koi8-r.txt
new file mode 100644 (file)
index 0000000..d4242af
--- /dev/null
@@ -0,0 +1,20 @@
+HTTP/1.1 200 OK
+Server: nginx/1.11.10
+Date: Tue, 04 Jul 2017 16:43:39 GMT
+Content-Type: text/html
+Content-Length: 273
+Connection: keep-alive
+Last-Modified: Tue, 04 Jul 2017 16:41:34 GMT
+Accept-Ranges: bytes
+
+<HTML>
+<HEAD>
+  <META NAME="GENERATOR" CONTENT="Adobe PageMill 3.0J Mac">
+  <META HTTP-EQUIV="Content-Type" CONTENT="text/html;CHARSET=koi8-r">
+  <TITLE>������� ��������� ������ �� XVI ��. ���������� ������� ������������.</TITLE>
+</HEAD>
+<BODY>
+<P><CENTER><B><FONT SIZE="+2">������� ��������� ������ �� XVI ��. ���������� ������� ������������.</FONT></B><BR>
+<HR><BR>
+</BODY>
+</HTML>
index 9041aa25d6e57c137aa42c3da706f5946d18e245..faf18d35c5e6f22098572749d79e051fa30a3bc5 100644 (file)
@@ -11,10 +11,10 @@ Accept-Ranges: bytes
 <HEAD>
   <META NAME="GENERATOR" CONTENT="Adobe PageMill 3.0J Mac">
   <META HTTP-EQUIV="Content-Type" CONTENT="text/html;CHARSET=x-sjis">
-  <TITLE>JSIS�̃y�[�W</TITLE>
+  <TITLE>SJIS�̃y�[�W</TITLE>
 </HEAD>
 <BODY>
-<P><CENTER><B><FONT SIZE="+2">SJIS�̃y�[�W</FONT></B><BR>
+<P><CENTER><B><FONT SIZE="+2">�����N�܂��Ă�����L�O�l��Ă�̂̎��ł�����ł��B�����ԂɈӖ��҂͐������ǂ�Ȕ���܂����܂ł��\���グ����������邽�ɂ͎Q�l�A�邽��������A�����ɂ������܂��Ȃ��B���炢���Ȃ��̂͂ǂ���㌎��ł��邾�����������B������ĉ��c����ɔ��R�K�������ɉ]���ł����͂����������͂��Ȃ����w�}���Ƃ������o���Ȃ�����Ȃ���āA���͎̐̂�����͉A��{�炩��A�v������̂�̂���̂��\82�������ɂ���]�ƌ�΂���man�ɂ������֎Q��悤�ɓ����ɂ��������łȂ�̂ŁA�������\���ɕς���Ă���ł����ōl�������B������Ⴆ�΂��������Ƃǂ܂��̂��ۂނ�݂Ƃ���ł��āA���̎����ł͐\����ĂƂ��Đ��Ԃɕ�ׂ̂ɍs���Ȃ���ȁB</FONT></B><BR>
 <HR><BR>
 </BODY>
 </HTML>
diff --git a/spec/fixtures/requests/sjis_with_wrong_charset.txt b/spec/fixtures/requests/sjis_with_wrong_charset.txt
new file mode 100644 (file)
index 0000000..456750c
--- /dev/null
@@ -0,0 +1,20 @@
+HTTP/1.1 200 OK
+Server: nginx/1.11.10
+Date: Tue, 04 Jul 2017 16:43:39 GMT
+Content-Type: text/html; charset=utf-8
+Content-Length: 273
+Connection: keep-alive
+Last-Modified: Tue, 04 Jul 2017 16:41:34 GMT
+Accept-Ranges: bytes
+
+<HTML>
+<HEAD>
+  <META NAME="GENERATOR" CONTENT="Adobe PageMill 3.0J Mac">
+  <META HTTP-EQUIV="Content-Type" CONTENT="text/html;CHARSET=x-sjis">
+  <TITLE>SJIS�̃y�[�W</TITLE>
+</HEAD>
+<BODY>
+<P><CENTER><B><FONT SIZE="+2">�����N�܂��Ă�����L�O�l��Ă�̂̎��ł�����ł��B�����ԂɈӖ��҂͐������ǂ�Ȕ���܂����܂ł��\���グ����������邽�ɂ͎Q�l�A�邽��������A�����ɂ������܂��Ȃ��B���炢���Ȃ��̂͂ǂ���㌎��ł��邾�����������B������ĉ��c����ɔ��R�K�������ɉ]���ł����͂����������͂��Ȃ����w�}���Ƃ������o���Ȃ�����Ȃ���āA���͎̐̂�����͉A��{�炩��A�v������̂�̂���̂��\82�������ɂ���]�ƌ�΂���man�ɂ������֎Q��悤�ɓ����ɂ��������łȂ�̂ŁA�������\���ɕς���Ă���ł����ōl�������B������Ⴆ�΂��������Ƃǂ܂��̂��ۂނ�݂Ƃ���ł��āA���̎����ł͐\����ĂƂ��Đ��Ԃɕ�ׂ̂ɍs���Ȃ���ȁB</FONT></B><BR>
+<HR><BR>
+</BODY>
+</HTML>
index 7d7f8e74847bab20c6dbb9bc120d61643a2794e5..698eb032472deee3dead8b6eeb294ce42648010e 100644 (file)
@@ -8,6 +8,10 @@ RSpec.describe FetchLinkCardService do
     stub_request(:get, 'http://example.xn--fiqs8s/').to_return(request_fixture('idn.txt'))
     stub_request(:head, 'http://example.com/sjis').to_return(status: 200, headers: { 'Content-Type' => 'text/html' })
     stub_request(:get, 'http://example.com/sjis').to_return(request_fixture('sjis.txt'))
+    stub_request(:head, 'http://example.com/sjis_with_wrong_charset').to_return(status: 200, headers: { 'Content-Type' => 'text/html' })
+    stub_request(:get, 'http://example.com/sjis_with_wrong_charset').to_return(request_fixture('sjis_with_wrong_charset.txt'))
+    stub_request(:head, 'http://example.com/koi8-r').to_return(status: 200, headers: { 'Content-Type' => 'text/html' })
+    stub_request(:get, 'http://example.com/koi8-r').to_return(request_fixture('koi8-r.txt'))
     stub_request(:head, 'https://github.com/qbi/WannaCry').to_return(status: 404)
 
     subject.call(status)
@@ -27,6 +31,25 @@ RSpec.describe FetchLinkCardService do
 
       it 'works with SJIS' do
         expect(a_request(:get, 'http://example.com/sjis')).to have_been_made.at_least_once
+        expect(status.preview_card.title).to eq("SJISのページ")
+      end
+    end
+
+    context do
+      let(:status) { Fabricate(:status, text: 'Check out http://example.com/sjis_with_wrong_charset') }
+
+      it 'works with SJIS even with wrong charset header' do
+        expect(a_request(:get, 'http://example.com/sjis_with_wrong_charset')).to have_been_made.at_least_once
+        expect(status.preview_card.title).to eq("SJISのページ")
+      end
+    end
+
+    context do
+      let(:status) { Fabricate(:status, text: 'Check out http://example.com/koi8-r') }
+
+      it 'works with koi8-r' do
+        expect(a_request(:get, 'http://example.com/koi8-r')).to have_been_made.at_least_once
+        expect(status.preview_card.title).to eq("Московя начинаетъ только въ XVI ст. привлекать внимане иностранцевъ.")
       end
     end
   end