Welcome to mirror list, hosted at ThFree Co, Russian Federation.

twitter.rb « services « models « app - github.com/diaspora/diaspora.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
blob: b14791736a90116491be96e8e1ac6316911e8721 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
# frozen_string_literal: true

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=''
    logger.debug "event=post_to_service type=twitter sender_id=#{user_id} post=#{post.guid}"
    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 post_opts(post)
    {tweet_id: post.tweet_id} if post.tweet_id.present?
  end

  def delete_from_service(opts)
    logger.debug "event=delete_from_service type=twitter sender_id=#{user_id} tweet_id=#{opts[:tweet_id]}"
    delete_from_twitter(opts[:tweet_id])
  end

  private

  def client
    @client ||= Twitter::REST::Client.new do |config|
      config.consumer_key = AppConfig.services.twitter.key
      config.consumer_secret = AppConfig.services.twitter.secret
      config.access_token = access_token
      config.access_token_secret = access_secret
    end
  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.destroy_status service_post_id
  end
end