Merge pull request #227 from Retrospring/fix/tweet-length
Fixes to ensure answers shared to twitter post more reliably
This commit is contained in:
commit
c773d43447
|
@ -12,9 +12,10 @@ RUN curl -sL https://deb.nodesource.com/setup_12.x | bash -
|
||||||
|
|
||||||
RUN apt-get update -qq \
|
RUN apt-get update -qq \
|
||||||
&& apt-get install -y --no-install-recommends build-essential \
|
&& apt-get install -y --no-install-recommends build-essential \
|
||||||
libpq-dev postgresql-client \
|
libpq-dev postgresql-client \
|
||||||
libxml2-dev libxslt1-dev \
|
libxml2-dev libxslt1-dev \
|
||||||
libmagickwand-dev imagemagick \
|
libmagickwand-dev imagemagick \
|
||||||
|
libidn11-dev \
|
||||||
nodejs \
|
nodejs \
|
||||||
yarn \
|
yarn \
|
||||||
&& rm -rf /var/lib/apt/lists/*
|
&& rm -rf /var/lib/apt/lists/*
|
||||||
|
|
|
@ -52,7 +52,7 @@ jobs:
|
||||||
with:
|
with:
|
||||||
node-version: '12'
|
node-version: '12'
|
||||||
- name: Install dependencies
|
- name: Install dependencies
|
||||||
run: sudo apt update && sudo apt-get install -y libpq-dev libxml2-dev libxslt1-dev libmagickwand-dev imagemagick
|
run: sudo apt update && sudo apt-get install -y libpq-dev libxml2-dev libxslt1-dev libmagickwand-dev imagemagick libidn11-dev
|
||||||
- name: Copy default configuration
|
- name: Copy default configuration
|
||||||
run: |
|
run: |
|
||||||
cp config/database.yml.postgres config/database.yml
|
cp config/database.yml.postgres config/database.yml
|
||||||
|
|
1
Gemfile
1
Gemfile
|
@ -57,6 +57,7 @@ gem 'omniauth-tumblr'
|
||||||
|
|
||||||
# OAuth clients
|
# OAuth clients
|
||||||
gem 'twitter'
|
gem 'twitter'
|
||||||
|
gem 'twitter-text'
|
||||||
# To use a more recent Faraday version, a fork of this gem is required.
|
# To use a more recent Faraday version, a fork of this gem is required.
|
||||||
gem 'tumblr_client', git: 'https://github.com/amplifr/tumblr_client'
|
gem 'tumblr_client', git: 'https://github.com/amplifr/tumblr_client'
|
||||||
|
|
||||||
|
|
|
@ -251,6 +251,7 @@ GEM
|
||||||
concurrent-ruby (~> 1.0)
|
concurrent-ruby (~> 1.0)
|
||||||
i18n-js (3.6.0)
|
i18n-js (3.6.0)
|
||||||
i18n (>= 0.6.6)
|
i18n (>= 0.6.6)
|
||||||
|
idn-ruby (0.1.4)
|
||||||
image_processing (1.12.1)
|
image_processing (1.12.1)
|
||||||
mini_magick (>= 4.9.5, < 5)
|
mini_magick (>= 4.9.5, < 5)
|
||||||
ruby-vips (>= 2.0.17, < 3)
|
ruby-vips (>= 2.0.17, < 3)
|
||||||
|
@ -534,6 +535,9 @@ GEM
|
||||||
multipart-post (~> 2.0)
|
multipart-post (~> 2.0)
|
||||||
naught (~> 1.0)
|
naught (~> 1.0)
|
||||||
simple_oauth (~> 0.3.0)
|
simple_oauth (~> 0.3.0)
|
||||||
|
twitter-text (3.1.0)
|
||||||
|
idn-ruby
|
||||||
|
unf (~> 0.1.0)
|
||||||
tzinfo (1.2.9)
|
tzinfo (1.2.9)
|
||||||
thread_safe (~> 0.1)
|
thread_safe (~> 0.1)
|
||||||
uglifier (4.2.0)
|
uglifier (4.2.0)
|
||||||
|
@ -632,6 +636,7 @@ DEPENDENCIES
|
||||||
tumblr_client!
|
tumblr_client!
|
||||||
turbolinks (~> 2.5.3)
|
turbolinks (~> 2.5.3)
|
||||||
twitter
|
twitter
|
||||||
|
twitter-text
|
||||||
uglifier (>= 1.3.0)
|
uglifier (>= 1.3.0)
|
||||||
web-console (< 4.0.0)
|
web-console (< 4.0.0)
|
||||||
webpacker (~> 5.2)
|
webpacker (~> 5.2)
|
||||||
|
|
|
@ -48,7 +48,9 @@ class Ajax::AnswerController < AjaxController
|
||||||
end
|
end
|
||||||
|
|
||||||
services = JSON.parse params[:share]
|
services = JSON.parse params[:share]
|
||||||
ShareWorker.perform_async(current_user.id, answer.id, services)
|
services.each do |service|
|
||||||
|
ShareWorker.perform_async(current_user.id, answer.id, service)
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
@response[:status] = :okay
|
@response[:status] = :okay
|
||||||
|
|
|
@ -27,16 +27,30 @@ class Services::Twitter < Service
|
||||||
end
|
end
|
||||||
|
|
||||||
def prepare_tweet(answer)
|
def prepare_tweet(answer)
|
||||||
# TODO: improve this.
|
|
||||||
question_content = twitter_markdown answer.question.content.gsub(/\@(\w+)/, '\1')
|
question_content = twitter_markdown answer.question.content.gsub(/\@(\w+)/, '\1')
|
||||||
|
original_question_length = question_content.length
|
||||||
answer_content = twitter_markdown answer.content
|
answer_content = twitter_markdown answer.content
|
||||||
|
original_answer_length = answer_content.length
|
||||||
answer_url = show_user_answer_url(
|
answer_url = show_user_answer_url(
|
||||||
id: answer.id,
|
id: answer.id,
|
||||||
username: answer.user.screen_name,
|
username: answer.user.screen_name,
|
||||||
host: APP_CONFIG['hostname'],
|
host: APP_CONFIG['hostname'],
|
||||||
protocol: (APP_CONFIG['https'] ? :https : :http)
|
protocol: (APP_CONFIG['https'] ? :https : :http)
|
||||||
)
|
)
|
||||||
"#{question_content[0..122]}#{'…' if question_content.length > 123}" \
|
|
||||||
" — #{answer_content[0..123]}#{'…' if answer_content.length > 124} #{answer_url}"
|
parsed_tweet = { :valid => false }
|
||||||
|
tweet_text = ""
|
||||||
|
|
||||||
|
until parsed_tweet[:valid]
|
||||||
|
tweet_text = "#{question_content[0..122]}#{'…' if original_question_length > [123, question_content.length].min}" \
|
||||||
|
" — #{answer_content[0..123]}#{'…' if original_answer_length > [124, answer_content.length].min} #{answer_url}"
|
||||||
|
|
||||||
|
parsed_tweet = Twitter::TwitterText::Validation::parse_tweet(tweet_text)
|
||||||
|
|
||||||
|
question_content = question_content[0..-2]
|
||||||
|
answer_content = answer_content[0..-2]
|
||||||
|
end
|
||||||
|
|
||||||
|
tweet_text
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,19 +1,19 @@
|
||||||
class ShareWorker
|
class ShareWorker
|
||||||
include Sidekiq::Worker
|
include Sidekiq::Worker
|
||||||
|
|
||||||
sidekiq_options queue: :share, retry: false
|
sidekiq_options queue: :share, retry: 5
|
||||||
|
|
||||||
# @param user_id [Integer] the user id
|
# @param user_id [Integer] the user id
|
||||||
# @param answer_id [Integer] the user id
|
# @param answer_id [Integer] the user id
|
||||||
# @param services [Array] array containing strings
|
# @param service [String] the service to post to
|
||||||
def perform(user_id, answer_id, services)
|
def perform(user_id, answer_id, service)
|
||||||
User.find(user_id).services.each do |service|
|
service_type = "Services::#{service.camelize}"
|
||||||
begin
|
user_service = User.find(user_id).services.find_by(type: service_type)
|
||||||
service.post(Answer.find(answer_id)) if services.include? service.provider
|
|
||||||
rescue => e
|
user_service.post(Answer.find(answer_id))
|
||||||
logger.info "failed to post answer #{answer_id} to #{service.provider} for user #{user_id}: #{e.message}"
|
rescue => e
|
||||||
NewRelic::Agent.notice_error(e)
|
logger.info "failed to post answer #{answer_id} to #{service.provider} for user #{user_id}: #{e.message}"
|
||||||
end
|
NewRelic::Agent.notice_error(e)
|
||||||
end
|
raise
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -27,7 +27,9 @@ describe Ajax::AnswerController, :ajax_controller, type: :controller do
|
||||||
|
|
||||||
it "enqueues a job for sharing the answer to social networks" do
|
it "enqueues a job for sharing the answer to social networks" do
|
||||||
subject
|
subject
|
||||||
expect(ShareWorker).to have_enqueued_sidekiq_job(user.id, Answer.last.id, shared_services)
|
shared_services.each do |service|
|
||||||
|
expect(ShareWorker).to have_enqueued_sidekiq_job(user.id, Answer.last.id, service)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
include_examples "returns the expected response"
|
include_examples "returns the expected response"
|
||||||
|
|
|
@ -0,0 +1,46 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
require 'rails_helper'
|
||||||
|
|
||||||
|
describe Services::Twitter do
|
||||||
|
describe "#post" do
|
||||||
|
let(:user) { FactoryBot.create(:user) }
|
||||||
|
let(:service) { Services::Twitter.create(user: user) }
|
||||||
|
let(:answer) { FactoryBot.create(:answer, user: user,
|
||||||
|
content: 'a' * 255,
|
||||||
|
question_content: 'q' * 255) }
|
||||||
|
let(:twitter_client) { instance_double(Twitter::REST::Client) }
|
||||||
|
|
||||||
|
before do
|
||||||
|
allow(Twitter::REST::Client).to receive(:new).and_return(twitter_client)
|
||||||
|
allow(twitter_client).to receive(:update!)
|
||||||
|
stub_const("APP_CONFIG", {
|
||||||
|
'hostname' => 'example.com',
|
||||||
|
'https' => true,
|
||||||
|
'items_per_page' => 5,
|
||||||
|
'sharing' => {
|
||||||
|
'twitter' => {
|
||||||
|
'consumer_key' => 'AAA',
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
end
|
||||||
|
|
||||||
|
it "posts a shortened tweet" do
|
||||||
|
service.post(answer)
|
||||||
|
|
||||||
|
expect(twitter_client).to have_received(:update!).with("#{'q' * 123}… — #{'a' * 124}… https://example.com/#{user.screen_name}/a/#{answer.id}")
|
||||||
|
end
|
||||||
|
|
||||||
|
it "posts an un-shortened tweet" do
|
||||||
|
answer.question.content = 'Why are raccoons so good?'
|
||||||
|
answer.question.save!
|
||||||
|
answer.content = 'Because they are good cunes.'
|
||||||
|
answer.save!
|
||||||
|
|
||||||
|
service.post(answer)
|
||||||
|
|
||||||
|
expect(twitter_client).to have_received(:update!).with("#{answer.question.content} — #{answer.content} https://example.com/#{user.screen_name}/a/#{answer.id}")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
Loading…
Reference in New Issue