Module: ExTwitter::NewApi
- Included in:
- Client
- Defined in:
- lib/ex_twitter/new_api.rb
Instance Method Summary collapse
- #_count_users_with_two_sided_threshold(users, options) ⇒ Object
- #_extract_favorite_users(favs, options = {}) ⇒ Object
- #_extract_inactive_users(users, options = {}) ⇒ Object
- #_extract_screen_names(tweets) ⇒ Object
- #_extract_uids(tweets) ⇒ Object
- #_extract_users(tweets, uids) ⇒ Object
-
#_fetch_parallelly(signatures) ⇒ Object
[:friends, args: [‘ts_3156’, …], {…].
- #close_friends(*args) ⇒ Object
- #clusters_assigned_to ⇒ Object
- #clusters_belong_to(text) ⇒ Object
- #common_followers(me, you) ⇒ Object
- #common_friends(me, you) ⇒ Object
- #favorited_by(*args) ⇒ Object
- #favoriting(*args) ⇒ Object
- #followers_parallelly(*args) ⇒ Object
- #friends_and_followers(*args) ⇒ Object
- #friends_followers_and_statuses(*args) ⇒ Object
- #friends_parallelly(*args) ⇒ Object
- #inactive_followers(user = nil) ⇒ Object
- #inactive_friends(user = nil) ⇒ Object
- #mutual_friends(me) ⇒ Object
- #one_sided_followers(me) ⇒ Object
- #one_sided_following(me) ⇒ Object
- #removed(pre_me, cur_me) ⇒ Object
- #removing(pre_me, cur_me) ⇒ Object
-
#replied(*args) ⇒ Object
users which specified user is replied when user is login you had better to call mentions_timeline.
-
#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.
Instance Method Details
#_count_users_with_two_sided_threshold(users, options) ⇒ Object
179 180 181 182 183 184 185 |
# File 'lib/ex_twitter/new_api.rb', line 179 def _count_users_with_two_sided_threshold(users, ) min = .has_key?(:min) ? [:min] : 0 max = .has_key?(:max) ? [:max] : 1000 users.each_with_object(Hash.new(0)) { |u, memo| memo[u.id] += 1 }. select { |_k, v| min <= v && v <= max }. sort_by { |_, v| -v }.to_h end |
#_extract_favorite_users(favs, options = {}) ⇒ Object
187 188 189 190 191 192 193 |
# File 'lib/ex_twitter/new_api.rb', line 187 def _extract_favorite_users(favs, = {}) counted_value = _count_users_with_two_sided_threshold(favs.map { |t| t.user }, ) counted_value.map do |uid, cnt| fav = favs.find { |f| f.user.id.to_i == uid.to_i } Array.new(cnt, fav.user) end.flatten end |
#_extract_inactive_users(users, options = {}) ⇒ Object
220 221 222 223 224 225 226 227 228 229 230 |
# File 'lib/ex_twitter/new_api.rb', line 220 def _extract_inactive_users(users, = {}) = .delete(:authorized) two_weeks_ago = 2.weeks.ago.to_i users.select do |u| if (Time.parse(u.status.created_at).to_i < two_weeks_ago) rescue false else false end end end |
#_extract_screen_names(tweets) ⇒ Object
113 114 115 116 117 |
# File 'lib/ex_twitter/new_api.rb', line 113 def _extract_screen_names(tweets) tweets.map do |t| $1 if t.text =~ /^(?:\.)?@(\w+)( |\W)/ # include statuses starts with . end.compact end |
#_extract_uids(tweets) ⇒ Object
148 149 150 151 152 |
# File 'lib/ex_twitter/new_api.rb', line 148 def _extract_uids(tweets) tweets.map do |t| t.user.id.to_i if t.text =~ /^(?:\.)?@(\w+)( |\W)/ # include statuses starts with . end.compact end |
#_extract_users(tweets, uids) ⇒ Object
154 155 156 |
# File 'lib/ex_twitter/new_api.rb', line 154 def _extract_users(tweets, uids) uids.map { |uid| tweets.find { |t| t.user.id.to_i == uid.to_i } }.map { |t| t.user }.compact 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 |
#close_friends(*args) ⇒ Object
235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 |
# File 'lib/ex_twitter/new_api.rb', line 235 def close_friends(*args) = {uniq: false}.merge(args.) min_max = { min: .has_key?(:min) ? .delete(:min) : 0, max: .has_key?(:max) ? .delete(:max) : 1000 } , _replied, _favoriting = if args.empty? [(), replied(), favoriting()] elsif uid_or_screen_name?(args[0]) [(args[0], ), replied(args[0], ), favoriting(args[0], )] elsif (m_names = %i(replying replied favoriting)).all? { |m_name| args[0].respond_to?(m_name) } m_names.map { |mn| args[0].send(mn) } else raise end _users = + _replied + _favoriting return [] if _users.empty? scores = _count_users_with_two_sided_threshold(_users, min_max) = _count_users_with_two_sided_threshold(, min_max) replied_scores = _count_users_with_two_sided_threshold(_replied, min_max) favoriting_scores = _count_users_with_two_sided_threshold(_favoriting, min_max) scores.keys.map { |uid| _users.find { |u| u.id.to_i == uid.to_i } }. map do |u| u[:score] = scores[u.id] u[:replying_score] = [u.id] u[:replied_score] = replied_scores[u.id] u[:favoriting_score] = favoriting_scores[u.id] u end end |
#clusters_assigned_to ⇒ Object
327 328 329 |
# File 'lib/ex_twitter/new_api.rb', line 327 def clusters_assigned_to raise NotImplementedError.new end |
#clusters_belong_to(text) ⇒ Object
299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 |
# File 'lib/ex_twitter/new_api.rb', line 299 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 |
#favorited_by(*args) ⇒ Object
232 233 |
# File 'lib/ex_twitter/new_api.rb', line 232 def favorited_by(*args) end |
#favoriting(*args) ⇒ Object
195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 |
# File 'lib/ex_twitter/new_api.rb', line 195 def favoriting(*args) = args. favs = if args.empty? favorites() elsif uid_or_screen_name?(args[0]) favorites(args[0], ) elsif args[0].kind_of?(Array) && args[0].all? { |t| t.respond_to?(:text) } args[0] else raise end result = _extract_favorite_users(favs, ) if .has_key?(:uniq) && ![:uniq] result else result.uniq { |r| r.id } end rescue => e logger.warn "#{__method__} #{user.inspect} #{e.class} #{e.}" raise e end |
#followers_parallelly(*args) ⇒ Object
9 10 11 12 13 |
# File 'lib/ex_twitter/new_api.rb', line 9 def followers_parallelly(*args) = {super_operation: __method__}.merge(args.) _follower_ids = follower_ids(*(args + [])) users(_follower_ids.map { |id| id.to_i }, ) 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) = {super_operation: __method__}.merge(args.) _friend_ids = friend_ids(*(args + [])) users(_friend_ids.map { |id| id.to_i }, ) end |
#inactive_followers(user = nil) ⇒ Object
285 286 287 288 289 290 291 292 293 294 295 296 297 |
# File 'lib/ex_twitter/new_api.rb', line 285 def inactive_followers(user = nil) if user.blank? _extract_inactive_users(followers_parallelly, authorized: true) elsif uid_or_screen_name?(user) = authenticating_user?(user) || (user) _extract_inactive_users(followers_parallelly(user), authorized: ) elsif user.respond_to?(:followers) = authenticating_user?(user.uid.to_i) || (user.uid.to_i) _extract_inactive_users(user.followers, authorized: ) else raise end end |
#inactive_friends(user = nil) ⇒ Object
271 272 273 274 275 276 277 278 279 280 281 282 283 |
# File 'lib/ex_twitter/new_api.rb', line 271 def inactive_friends(user = nil) if user.blank? _extract_inactive_users(friends_parallelly, authorized: true) elsif uid_or_screen_name?(user) = authenticating_user?(user) || (user) _extract_inactive_users(friends_parallelly(user), authorized: ) elsif user.respond_to?(:friends) = authenticating_user?(user.uid.to_i) || (user.uid.to_i) _extract_inactive_users(user.friends, 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
160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 |
# File 'lib/ex_twitter/new_api.rb', line 160 def replied(*args) = args. result = if args.empty? || (uid_or_screen_name?(args[0]) && authenticating_user?(args[0])) mentions_timeline.map { |m| m.user } else searched_result = search('@' + user(args[0]).screen_name, ) uids = _extract_uids(searched_result) _extract_users(searched_result, uids) end if .has_key?(:uniq) && ![:uniq] result else result.uniq { |r| r.id } 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
121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 |
# File 'lib/ex_twitter/new_api.rb', line 121 def (*args) = args. tweets = if args.empty? user_timeline() elsif uid_or_screen_name?(args[0]) user_timeline(args[0], ) 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) result = users(screen_names, {super_operation: __method__}.merge()) if .has_key?(:uniq) && ![:uniq] screen_names.map { |sn| result.find { |r| r.screen_name == sn } }.compact else result.uniq { |r| r.id } end rescue Twitter::Error::NotFound => e e. == 'No user matches for specified terms.' ? [] : (raise e) rescue => e logger.warn "#{__method__} #{args.inspect} #{e.class} #{e.}" raise e end |