diaspora/app/models/services/twitter.rb
Jonne Haß 8280556a47 Introduce message renderer
This new class replaces all existing server side message
rendering helpers and is the new global entry point for such
needs. All models with relevant fields now expose an instance
of MessageRenderer for those. MessageRenderer acts as
gateway between the existing processing solutions for markdown,
mentions and tags and provides a very flexible interface for
all output needs. This makes the API to obtain a message
in a certain format clear. As a result of centralizing the
processing a lot of duplication is eliminated. Centralizing
the message processing also makes it clear where to change
its behaviour, add new representations and what options
are already available.
2014-03-15 17:16:17 +01:00

107 lines
2.9 KiB
Ruby

class Services::Twitter < Service
include Rails.application.routes.url_helpers
MAX_CHARACTERS = 140
SHORTENED_URL_LENGTH = 21
LINK_PATTERN = %r{https?://\S+}
def provider
"twitter"
end
def post post, url=''
Rails.logger.debug "event=post_to_service type=twitter sender_id=#{self.user_id}"
tweet = attempt_post post
post.tweet_id = tweet.id
post.save
end
def profile_photo_url
client.user(nickname).profile_image_url_https "original"
end
def delete_post post
if post.present? && post.tweet_id.present?
Rails.logger.debug "event=delete_from_service type=twitter sender_id=#{self.user_id}"
delete_from_twitter post.tweet_id
end
end
private
def client
@client ||= Twitter::Client.new(
oauth_token: self.access_token,
oauth_token_secret: self.access_secret
)
end
def attempt_post post, retry_count=0
message = build_twitter_post post, retry_count
client.update message
rescue Twitter::Error::Forbidden => e
if ! e.message.include? 'is over 140' || retry_count == 20
raise e
else
attempt_post post, retry_count+1
end
end
def build_twitter_post post, retry_count=0
max_characters = MAX_CHARACTERS - retry_count
post_text = post.message.plain_text_without_markdown
truncate_and_add_post_link post, post_text, max_characters
end
def truncate_and_add_post_link post, post_text, max_characters
return post_text unless needs_link? post, post_text, max_characters
post_url = short_post_url(
post,
protocol: AppConfig.pod_uri.scheme,
host: AppConfig.pod_uri.authority
)
truncated_text = post_text.truncate max_characters - SHORTENED_URL_LENGTH + 1
truncated_text = restore_truncated_url truncated_text, post_text, max_characters
"#{truncated_text} #{post_url}"
end
def needs_link? post, post_text, max_characters
adjust_length_for_urls(post_text) > max_characters || post.photos.any?
end
def adjust_length_for_urls post_text
real_length = post_text.length
URI.extract(post_text, ['http','https']) do |url|
# add or subtract from real length - urls for tweets are always
# shortened to SHORTENED_URL_LENGTH
if url.length >= SHORTENED_URL_LENGTH
real_length -= url.length - SHORTENED_URL_LENGTH
else
real_length += SHORTENED_URL_LENGTH - url.length
end
end
real_length
end
def restore_truncated_url truncated_text, post_text, max_characters
return truncated_text if truncated_text !~ /#{LINK_PATTERN}\Z/
url = post_text.match(LINK_PATTERN, truncated_text.rindex('http'))[0]
truncated_text = post_text.truncate(
max_characters - SHORTENED_URL_LENGTH + 2,
separator: ' ', omission: ''
)
"#{truncated_text} #{url} ..."
end
def delete_from_twitter service_post_id
client.status_destroy service_post_id
end
end