Рабочий пример описанного в статье кода, в числе других Rails Examples - всегда возможно найти в тестовом блоге автора на herokuapp.com, welcome.
Класс полностью работоспособен, вы можете попробовать самостоятельно, клонировав rails-app с GitHub автора; ну или же попросту примите на веру показанный выше скринкаст. Если идея вас заинтересовала - вы можете попробовать это форкнуть, заодно причесать и сделать логику несколько более аккуратной. Увы, после очередного закручивания гаек своего API зловредным Твиттером не вижу особого смысла в продолжении работы над данным проектом. По секрету скажу, что бдительные модераторы Twitter, испросив ссылки на демки (да, теперь вот так), моментально отказали мне в девелоперском доступе даже к одному-единственному тви-аккаунту, токены которого я запрашивал; что заведомо вселяет немалые сомнения в рентабельности дальнейшей разработки. Жаль, конечно, проект обещал быть интересным и востребованным... ну, что же; в свете текущих событий, политических и не очень... нелепо было бы обижаться на сотрудников Twitter, бегущих сегодня как огня не только ботов, но и вообще любых попыток автоматизации действий пользователя в своей соц. сети. Повторюсь, их право.
Когда приложение в режиме твиттер-бота начинает ретвитить найденные по заданным хештегам твиты, довольно быстро приходим к:
ActionDispatch::Cookies::CookieOverflow in TweetsController#index
, в качестве же решения проблемы использован - и, по-видимому, вполне успешно - gem 'activerecord-session_store'; не забывайте однако, при необходимости (или время от времени):
db:sessions:trim
подробнее - на страничке Active Record Session Store на гитхабе.
class Twi
def self.get_followers(client, user_id)
follower_ids = []
next_cursor = -1
while next_cursor != 0
cursor = client.follower_ids(user_id, :cursor => next_cursor)
follower_ids.concat cursor.attrs[:ids]
next_cursor = cursor.send(:next_cursor)
end
followers = []
follower_ids.each_slice(100) do |ids|
followers.concat client.users(ids)
end
followers
end
def self.get_followers_total followers
followers_total = []
followers.each_with_index do |user, _index|
followers_total << user.id
puts "adding follower to an array: #{user.screen_name}"
end
end
def self.get_friends(client, user_id)
friend_ids = []
next_cursor = -1
begin
while next_cursor != 0
cursor = client.friend_ids(user_id, :cursor => next_cursor)
friend_ids.concat cursor.attrs[:ids]
next_cursor = cursor.send(:next_cursor)
end
rescue Twitter::Error::Unauthorized
[]
end
friends = []
friend_ids.each_slice(100) do |ids|
friends.concat client.users(ids)
end
friends_total = []
friends.each_with_index do |user, _index|
friends_total << user.id
puts "adding friend to an array: #{user.screen_name}"
end
end
def self.follow(client, follow)
counter = 0
begin
follow.take(100).reverse_each do |user|
client.follow(user)
follow.delete(user)
counter += 1
puts "follow: #{user.screen_name} #{Time.now}"
sleep rand(30..60)
end
end
rescue Twitter::Error::TooManyRequests, Twitter::Error::Forbidden, OpenSSL::SSL::SSLError, Twitter::Error::ServiceUnavailable, HTTP::ConnectionError
[]
puts "rescue Twitter::Error #{Time.now}"
if counter > 0 #ending a long task if Twitter API doesn't allow work
sleep 905
counter = 0
retry
end
end
def self.unfollow(client, unfollow)
begin
unfollow.take(1000).reverse_each do |user|
client.unfollow(user)
unfollow.delete(user)
puts "unfollow: #{user.screen_name} #{Time.now}"
sleep rand(1..5)
end
rescue Twitter::Error::TooManyRequests, Twitter::Error::Forbidden, OpenSSL::SSL::SSLError, Twitter::Error::ServiceUnavailable, HTTP::ConnectionError
[]
puts "rescue Twitter::Error #{Time.now}"
sleep 905
retry
end
end
def self.retweet(client, sclient, topics)
counter = 0
while counter <= 30
begin
sclient.filter(track: topics.join(',')) do |tweet|
if tweet.is_a?(Twitter::Tweet)
puts tweet.text
client.retweet tweet
counter += 1
sleep rand(10..45)
end
end
rescue StandardError
puts 'error occurred, waiting for 5 seconds'
counter += 1
sleep 15
end
end
end
def self.post(client, array_posts)
array_posts.each do |i|
puts client.update(i)
sleep rand(10..45)
end
end
def self.parser(client, twi_acc)
array = Set.new
array1 = []
CSV.open("twitts.csv", "w") do |csv|
client.search(twi_acc, result_type: "recent", tweet_mode: "extended").take(30).collect do |tweet|
array << tweet
.attrs[:full_text]
.gsub(twi_acc, "")
.gsub("RT :", "")
.gsub("RT", "")
end
array.each do |item|
csv << [item]
array1 << item
puts item
end
end
array1
end
def self.print_followers followers
array = []
CSV.open("followers.csv", "w") do |csv|
total = followers.count
followers.each_with_index do |user, index|
print "\r#{index}/#{total} complete"
csv << [user.screen_name]
array << user.screen_name
end
end
array
end
end
Тем не менее, в качестве "домашнего" (open source и полностью бесплатно) "средства ухода" за своим тви-акком - приложение вполне имеет право на существование: как видите, в полностью автоматическом режиме вычисляются идентификаторы аккаунтов, которые далее фолловятся и анфолловятся, также приложение умеет искать твиты по заданным хеш-тегам - одному или нескольким - и ретвитить; также реализован постинг твитов (каждый твит с новой строчки) через рандомные промежутки времени. Разумеется, приложение способно не только хранить любое число аккаунтов для входа и токены доступа для любого количества твиттер-аккаунтов, но и легко переключаться между ними; что на данный момент представляется мне уже, к сожалению, избыточностью.