Module: ExTwitter::NewApi

Included in:
Client
Defined in:
lib/ex_twitter/new_api.rb

Instance Method Summary collapse

Instance Method Details

#_extract_inactive_users(users, options = {}) ⇒ Object



168
169
170
171
172
173
174
175
176
177
178
# File 'lib/ex_twitter/new_api.rb', line 168

def _extract_inactive_users(users, options = {})
  authorized = options.delete(:authorized)
  two_weeks_ago = 2.weeks.ago.to_i
  users.select do |u|
    if authorized
      (Time.parse(u.status.created_at).to_i < two_weeks_ago) rescue false
    else
      false
    end
  end
end

#_extract_screen_names(tweets, options = {}) ⇒ Object



113
114
115
116
117
118
# File 'lib/ex_twitter/new_api.rb', line 113

def _extract_screen_names(tweets, options = {})
  result = tweets.map do |t|
    $1 if t.text =~ /^(?:\.)?@(\w+)( |\W)/ # include statuses starts with .
  end.compact
  (options.has_key?(:uniq) && !options[:uniq]) ? result : result.uniq
end

#_extract_uids(tweets, options) ⇒ Object



143
144
145
146
147
148
# File 'lib/ex_twitter/new_api.rb', line 143

def _extract_uids(tweets, options)
  result = tweets.map do |t|
    t.user.id.to_i if t.text =~ /^(?:\.)?@(\w+)( |\W)/ # include statuses starts with .
  end.compact
  (options.has_key?(:uniq) && !options[:uniq]) ? result : result.uniq
end

#_extract_users(tweets, uids, options = {}) ⇒ Object



150
151
152
# File 'lib/ex_twitter/new_api.rb', line 150

def _extract_users(tweets, uids, options = {})
  uids.map { |u| tweets.find { |t| t.user.id.to_i == u.to_i } }.map { |t| t.user }
end

#_fetch_parallelly(signatures) ⇒ Object

:friends, args: [‘ts_3156’, …], {…


15
16
17
18
19
20
21
22
23
# File 'lib/ex_twitter/new_api.rb', line 15

def _fetch_parallelly(signatures) # [{method: :friends, args: ['ts_3156', ...], {...}]
  result = Array.new(signatures.size)

  Parallel.each_with_index(signatures, in_threads: result.size) do |signature, i|
    result[i] = send(signature[:method], *signature[:args])
  end

  result
end

#clusters_assigned_toObject

Raises:

  • (NotImplementedError)


236
237
238
# File 'lib/ex_twitter/new_api.rb', line 236

def clusters_assigned_to
  raise NotImplementedError.new
end

#clusters_belong_to(text) ⇒ Object



208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
# File 'lib/ex_twitter/new_api.rb', line 208

def clusters_belong_to(text)
  return [] if text.blank?

  exclude_words = JSON.parse(File.read(Rails.configuration.x.constants['cluster_bad_words_path']))
  special_words = JSON.parse(File.read(Rails.configuration.x.constants['cluster_good_words_path']))

  # クラスタ用の単語の出現回数を記録
  cluster_word_counter =
    special_words.map { |sw| [sw, text.scan(sw)] }
      .delete_if { |item| item[1].empty? }
      .each_with_object(Hash.new(1)) { |item, memo| memo[item[0]] = item[1].size }

  # 同一文字種の繰り返しを見付ける。漢字の繰り返し、ひらがなの繰り返し、カタカナの繰り返し、など
  text.scan(/[一-龠〆ヵヶ々]+|[ぁ-んー~]+|[ァ-ヴー~]+|[a-zA-Z0-9]+|[、。!!??]+/).

    # 複数回繰り返される文字を除去
    map { |w| w.remove /[?!?!。、w]|(ー{2,})/ }.

    # 文字数の少なすぎる単語、ひらがなだけの単語、除外単語を除去する
    delete_if { |w| w.length <= 1 || (w.length <= 2 && w =~ /^[ぁ-んー~]+$/) || exclude_words.include?(w) }.

    # 出現回数を記録
    each { |w| cluster_word_counter[w] += 1 }

  # 複数個以上見付かった単語のみを残し、出現頻度順にソート
  cluster_word_counter.select { |_, v| v > 3 }.sort_by { |_, v| -v }.to_h
end

#common_followers(me, you) ⇒ Object



83
84
85
86
87
88
89
90
91
# File 'lib/ex_twitter/new_api.rb', line 83

def common_followers(me, you)
  if uid_or_screen_name?(me) && uid_or_screen_name?(you)
    followers_parallelly(me).to_a & followers_parallelly(you).to_a
  elsif me.respond_to?(:followers) && you.respond_to?(:followers)
    me.followers.to_a & you.followers.to_a
  else
    raise
  end
end

#common_friends(me, you) ⇒ Object



73
74
75
76
77
78
79
80
81
# File 'lib/ex_twitter/new_api.rb', line 73

def common_friends(me, you)
  if uid_or_screen_name?(me) && uid_or_screen_name?(you)
    friends_parallelly(me).to_a & friends_parallelly(you).to_a
  elsif me.respond_to?(:friends) && you.respond_to?(:friends)
    me.friends.to_a & you.friends.to_a
  else
    raise
  end
end

#followers_parallelly(*args) ⇒ Object



9
10
11
12
13
# File 'lib/ex_twitter/new_api.rb', line 9

def followers_parallelly(*args)
  options = {super_operation: __method__}.merge(args.extract_options!)
  _follower_ids = follower_ids(*(args + [options]))
  users(_follower_ids.map { |id| id.to_i }, options)
end

#friends_and_followers(*args) ⇒ Object



25
26
27
28
29
30
# File 'lib/ex_twitter/new_api.rb', line 25

def friends_and_followers(*args)
  _fetch_parallelly(
    [
      {method: :friends_parallelly, args: args},
      {method: :followers_parallelly, args: args}])
end

#friends_followers_and_statuses(*args) ⇒ Object



32
33
34
35
36
37
38
# File 'lib/ex_twitter/new_api.rb', line 32

def friends_followers_and_statuses(*args)
  _fetch_parallelly(
    [
      {method: :friends_parallelly, args: args},
      {method: :followers_parallelly, args: args},
      {method: :user_timeline, args: args}])
end

#friends_parallelly(*args) ⇒ Object



3
4
5
6
7
# File 'lib/ex_twitter/new_api.rb', line 3

def friends_parallelly(*args)
  options = {super_operation: __method__}.merge(args.extract_options!)
  _friend_ids = friend_ids(*(args + [options]))
  users(_friend_ids.map { |id| id.to_i }, options)
end

#inactive_followers(user = nil) ⇒ Object



194
195
196
197
198
199
200
201
202
203
204
205
206
# File 'lib/ex_twitter/new_api.rb', line 194

def inactive_followers(user = nil)
  if user.blank?
    _extract_inactive_users(followers_parallelly, authorized: true)
  elsif uid_or_screen_name?(user)
    authorized = authenticating_user?(user) || authorized_user?(user)
    _extract_inactive_users(followers_parallelly(user), authorized: authorized)
  elsif user.respond_to?(:followers)
    authorized = authenticating_user?(user.uid.to_i) || authorized_user?(user.uid.to_i)
    _extract_inactive_users(user.followers, authorized: authorized)
  else
    raise
  end
end

#inactive_friends(user = nil) ⇒ Object



180
181
182
183
184
185
186
187
188
189
190
191
192
# File 'lib/ex_twitter/new_api.rb', line 180

def inactive_friends(user = nil)
  if user.blank?
    _extract_inactive_users(friends_parallelly, authorized: true)
  elsif uid_or_screen_name?(user)
    authorized = authenticating_user?(user) || authorized_user?(user)
    _extract_inactive_users(friends_parallelly(user), authorized: authorized)
  elsif user.respond_to?(:friends)
    authorized = authenticating_user?(user.uid.to_i) || authorized_user?(user.uid.to_i)
    _extract_inactive_users(user.friends, authorized: authorized)
  else
    raise
  end
end

#mutual_friends(me) ⇒ Object



62
63
64
65
66
67
68
69
70
71
# File 'lib/ex_twitter/new_api.rb', line 62

def mutual_friends(me)
  if uid_or_screen_name?(me)
    # TODO use friends_and_followers
    friends_parallelly(me).to_a & followers_parallelly(me).to_a
  elsif me.respond_to?(:friends) && me.respond_to?(:followers)
    me.friends.to_a & me.followers.to_a
  else
    raise
  end
end

#one_sided_followers(me) ⇒ Object



51
52
53
54
55
56
57
58
59
60
# File 'lib/ex_twitter/new_api.rb', line 51

def one_sided_followers(me)
  if uid_or_screen_name?(me)
    # TODO use friends_and_followers
    followers_parallelly(me).to_a - friends_parallelly(me).to_a
  elsif me.respond_to?(:friends) && me.respond_to?(:followers)
    me.followers.to_a - me.friends.to_a
  else
    raise
  end
end

#one_sided_following(me) ⇒ Object



40
41
42
43
44
45
46
47
48
49
# File 'lib/ex_twitter/new_api.rb', line 40

def one_sided_following(me)
  if uid_or_screen_name?(me)
    # TODO use friends_and_followers
    friends_parallelly(me).to_a - followers_parallelly(me).to_a
  elsif me.respond_to?(:friends) && me.respond_to?(:followers)
    me.friends.to_a - me.followers.to_a
  else
    raise
  end
end

#removed(pre_me, cur_me) ⇒ Object



103
104
105
106
107
108
109
110
111
# File 'lib/ex_twitter/new_api.rb', line 103

def removed(pre_me, cur_me)
  if uid_or_screen_name?(pre_me) && uid_or_screen_name?(cur_me)
    followers_parallelly(pre_me).to_a - followers_parallelly(cur_me).to_a
  elsif pre_me.respond_to?(:followers) && cur_me.respond_to?(:followers)
    pre_me.followers.to_a - cur_me.followers.to_a
  else
    raise
  end
end

#removing(pre_me, cur_me) ⇒ Object



93
94
95
96
97
98
99
100
101
# File 'lib/ex_twitter/new_api.rb', line 93

def removing(pre_me, cur_me)
  if uid_or_screen_name?(pre_me) && uid_or_screen_name?(cur_me)
    friends_parallelly(pre_me).to_a - friends_parallelly(cur_me).to_a
  elsif pre_me.respond_to?(:friends) && cur_me.respond_to?(:friends)
    pre_me.friends.to_a - cur_me.friends.to_a
  else
    raise
  end
end

#replied(*args) ⇒ Object

users which specified user is replied when user is login you had better to call mentions_timeline



156
157
158
159
160
161
162
163
164
165
166
# File 'lib/ex_twitter/new_api.rb', line 156

def replied(*args)
  options = args.extract_options!

  if args.empty? || (uid_or_screen_name?(args[0]) && authenticating_user?(args[0]))
    mentions_timeline.uniq { |m| m.user.id }.map { |m| m.user }
  else
    searched_result = search('@' + user(args[0]).screen_name, options)
    uids = _extract_uids(searched_result, options)
    _extract_users(searched_result, uids, options)
  end
end

#replying(*args) ⇒ Object

users which specified user is replying in_reply_to_user_id and in_reply_to_status_id is not used because of distinguishing mentions from replies



122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
# File 'lib/ex_twitter/new_api.rb', line 122

def replying(*args)
  options = args.extract_options!
  tweets =
    if args.empty?
      user_timeline(user.screen_name, options)
    elsif uid_or_screen_name?(args[0])
      user_timeline(args[0], options)
    elsif args[0].kind_of?(Array) && args[0].all? { |t| t.respond_to?(:text) }
      args[0]
    else
      raise
    end
  screen_names = _extract_screen_names(tweets, options)
  users(screen_names, {super_operation: __method__}.merge(options))
rescue Twitter::Error::NotFound => e
  e.message == 'No user matches for specified terms.' ? [] : (raise e)
rescue => e
  logger.warn "#{__method__} #{args.inspect} #{e.class} #{e.message}"
  raise e
end