instabot 0.1.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/lib/instabot.rb +10 -0
- data/lib/instabot/actions.rb +51 -0
- data/lib/instabot/banner.rb +9 -0
- data/lib/instabot/config.rb +38 -0
- data/lib/instabot/core.rb +129 -0
- data/lib/instabot/create_protocol.rb +42 -0
- data/lib/instabot/grabber.rb +131 -0
- data/lib/instabot/logger.rb +43 -0
- data/lib/instabot/login.rb +49 -0
- data/lib/instabot/modes.rb +242 -0
- data/lib/instabot/version.rb +4 -0
- metadata +158 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: c2b6c889968c1400b06a21a066935e41a259348d
|
4
|
+
data.tar.gz: 087a315b538c61565e2ec96babe37ef35136dc05
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 337aa9ba1be94a28eb9194dc503ed639ae663d54935e2aac005673412e106c0582f6b35b366fb3e1ce6ebf1d85c1b5392cd27257d6ad352d1c9519792b578275
|
7
|
+
data.tar.gz: aaa701d0675812fd495e7d7ab3513578eaca7daf35e70035f63d9ab2fd91744702144d95b756f420443da330045240108a61004bc4b8fe9a6c535938e98d31ae
|
data/lib/instabot.rb
ADDED
@@ -0,0 +1,10 @@
|
|
1
|
+
require "instabot/create_protocol"
|
2
|
+
require "instabot/version"
|
3
|
+
require "instabot/actions"
|
4
|
+
require "instabot/grabber"
|
5
|
+
require "instabot/banner"
|
6
|
+
require "instabot/logger"
|
7
|
+
require "instabot/config"
|
8
|
+
require "instabot/login"
|
9
|
+
require "instabot/modes"
|
10
|
+
require "instabot/core"
|
@@ -0,0 +1,51 @@
|
|
1
|
+
module Actions
|
2
|
+
|
3
|
+
def follow(user_id)
|
4
|
+
log("trying to follow a user [#{user_id}]")
|
5
|
+
check_login_status(:auto_retry)
|
6
|
+
follow_url = "https://www.instagram.com/web/friendships/#{user_id}/follow/"
|
7
|
+
set_mechanic_data
|
8
|
+
response = @agent.post(follow_url, @params, @headers)
|
9
|
+
# custom_puts "User followed!".bold.cyan
|
10
|
+
save_action_data user_id, :follow
|
11
|
+
@local_stroage[:followed_users] << user_id
|
12
|
+
return({user_id: user_id, response_code: response.code})
|
13
|
+
end
|
14
|
+
|
15
|
+
def unfollow(user_id)
|
16
|
+
log("trying to unfollow a user [#{user_id}]")
|
17
|
+
check_login_status(:auto_retry)
|
18
|
+
unfollow_url = "https://www.instagram.com/web/friendships/#{user_id}/unfollow/"
|
19
|
+
set_mechanic_data
|
20
|
+
response = @agent.post(unfollow_url, @params, @headers)
|
21
|
+
# custom_puts "[+] ".cyan + "User unfollowed!".bold.cyan
|
22
|
+
save_action_data user_id, :unfollow
|
23
|
+
@local_stroage[:unfollowed_users] << user_id
|
24
|
+
return({user_id: user_id, response_code: response.code})
|
25
|
+
end
|
26
|
+
|
27
|
+
def like(media_id)
|
28
|
+
log("trying to like a media[#{media_id}]")
|
29
|
+
check_login_status(:auto_retry)
|
30
|
+
comment_url = "https://www.instagram.com/web/likes/#{media_id}/like/"
|
31
|
+
set_mechanic_data
|
32
|
+
response = @agent.post(comment_url, @params, @headers)
|
33
|
+
# custom_puts "[+] ".cyan + "Media liked".bold.cyan
|
34
|
+
save_action_data media_id, :like
|
35
|
+
@local_stroage[:liked_medias] << media_id
|
36
|
+
return({media_id: media_id, response_code: response.code})
|
37
|
+
end
|
38
|
+
|
39
|
+
def comment(media_id=0, text="")
|
40
|
+
log("trying to send a comment to media[#{media_id}]")
|
41
|
+
check_login_status(:auto_retry)
|
42
|
+
comment_url = "https://www.instagram.com/web/comments/#{media_id}/add/"
|
43
|
+
set_mechanic_data({ comment_text: text.to_s })
|
44
|
+
response = @agent.post(comment_url, @params, @headers)
|
45
|
+
# custom_puts "[+] ".cyan + "comment successfully has been sent".bold.cyan
|
46
|
+
save_action_data media_id, :comment
|
47
|
+
@local_stroage[:commented_medias] << media_id
|
48
|
+
return({media_id: media_id, response_code: response.code})
|
49
|
+
end
|
50
|
+
|
51
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
module Config
|
2
|
+
|
3
|
+
class << self
|
4
|
+
attr_accessor :options
|
5
|
+
end
|
6
|
+
|
7
|
+
def self.setup
|
8
|
+
self.options ||= Configuration.new
|
9
|
+
yield(options)
|
10
|
+
end
|
11
|
+
|
12
|
+
class Configuration
|
13
|
+
attr_accessor :username, :password, :tags, :comments, :pretty_print, :pre_load, :wait_per_action, :infinite_tags, :max_like_per_day, :max_follow_per_day, :max_unfollow_per_day, :max_comment_per_day, :unwanted_list, :white_list_users
|
14
|
+
def initialize
|
15
|
+
@username = nil
|
16
|
+
@password = nil
|
17
|
+
@white_list_users = nil
|
18
|
+
@unwanted_list = nil
|
19
|
+
@wait_per_action = 1 * 60
|
20
|
+
@tags = ["test","hello","hello_world","birthday","food"]
|
21
|
+
@max_like_per_day = 50
|
22
|
+
@max_follow_per_day = 50
|
23
|
+
@max_unfollow_per_day = 50
|
24
|
+
@max_comment_per_day = 50
|
25
|
+
@comments = [
|
26
|
+
["this", "the", "your"],
|
27
|
+
["photo", "picture", "pic", "shot", "snapshot"],
|
28
|
+
["is", "looks", "feels", "is really"],
|
29
|
+
["great", "super", "good", "very good", "good","wow", "WOW", "cool", "GREAT","magnificent","magical", "very cool", "stylish", "beautiful","so beautiful", "so stylish","so professional","lovely", "so lovely","very lovely", "glorious","so glorious","very glorious", "adorable", "excellent","amazing"],
|
30
|
+
[".", "..", "...", "!","!!","!!!"]
|
31
|
+
]
|
32
|
+
@infinite_tags = true
|
33
|
+
@pre_load = true
|
34
|
+
@pretty_print = true
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
end
|
@@ -0,0 +1,129 @@
|
|
1
|
+
%w[colorize mechanize io/console hashie json logger pp active_support/core_ext/numeric/time rbconfig].each {|gem| require gem}
|
2
|
+
|
3
|
+
class Instabot
|
4
|
+
include Version
|
5
|
+
include Modes
|
6
|
+
include Actions
|
7
|
+
include Banner
|
8
|
+
include Config
|
9
|
+
include Grabber
|
10
|
+
include Login
|
11
|
+
include Log
|
12
|
+
include Protocol
|
13
|
+
|
14
|
+
attr_accessor :users, :medias
|
15
|
+
|
16
|
+
def initialize(mode=:default)
|
17
|
+
|
18
|
+
@users = []
|
19
|
+
@medias = []
|
20
|
+
@log_counter = 0
|
21
|
+
@login_status = false
|
22
|
+
@lib_dir = "#{Dir.pwd}/lib"
|
23
|
+
@root_dir = "#{Dir.pwd}"
|
24
|
+
@logs_dir = "#@root_dir/logs"
|
25
|
+
@global_time = Time.new.strftime("%H-%M-%S--%y-%m-%d")
|
26
|
+
@error_404_max_times = 3
|
27
|
+
@error_404_times = 0
|
28
|
+
@local_stroage = {
|
29
|
+
:followed_users => [],
|
30
|
+
:unfollowed_users => [],
|
31
|
+
:liked_medias => [],
|
32
|
+
:commented_medias => []
|
33
|
+
}
|
34
|
+
@maximums = {
|
35
|
+
:follows_in_day => 0,
|
36
|
+
:unfollows_in_day => 0,
|
37
|
+
:likes_in_day => 0,
|
38
|
+
:comments_in_day => 0,
|
39
|
+
:max_follows_per_day => options[:max_follow_per_day],
|
40
|
+
:max_unfollows_per_day => options[:max_unfollow_per_day],
|
41
|
+
:max_likes_per_day => options[:max_like_per_day],
|
42
|
+
:max_comments_per_day => options[:max_comment_per_day]
|
43
|
+
}
|
44
|
+
|
45
|
+
# pp "maximums: #{@maximums}"
|
46
|
+
# @os ||= (
|
47
|
+
# host_os = RbConfig::CONFIG['host_os']
|
48
|
+
# case host_os
|
49
|
+
# when /mswin|msys|mingw|cygwin|bccwin|wince|emc/
|
50
|
+
# :windows
|
51
|
+
# when /darwin|mac os/
|
52
|
+
# :macosx
|
53
|
+
# when /linux/
|
54
|
+
# :linux
|
55
|
+
# when /solaris|bsd/
|
56
|
+
# :unix
|
57
|
+
# else
|
58
|
+
# raise Error::WebDriverError, "unknown os: #{host_os.inspect}"
|
59
|
+
# end
|
60
|
+
# )
|
61
|
+
|
62
|
+
|
63
|
+
intro(mode)
|
64
|
+
|
65
|
+
|
66
|
+
|
67
|
+
end
|
68
|
+
|
69
|
+
|
70
|
+
def options
|
71
|
+
return {
|
72
|
+
:username => Config.options.username,
|
73
|
+
:password => Config.options.password,
|
74
|
+
:tags => Config.options.tags,
|
75
|
+
:max_like_per_day => Config.options.max_like_per_day,
|
76
|
+
:max_follow_per_day => Config.options.max_follow_per_day,
|
77
|
+
:max_unfollow_per_day => Config.options.max_unfollow_per_day,
|
78
|
+
:max_comment_per_day => Config.options.max_comment_per_day,
|
79
|
+
:unwanted_list => Config.options.unwanted_list,
|
80
|
+
:white_list_users => Config.options.white_list_users,
|
81
|
+
:wait_per_action => Config.options.wait_per_action,
|
82
|
+
:comments => Config.options.comments,
|
83
|
+
:pre_load => Config.options.pre_load,
|
84
|
+
:pretty_print => Config.options.pretty_print
|
85
|
+
# :medias => [],
|
86
|
+
# :users => []
|
87
|
+
}
|
88
|
+
end
|
89
|
+
|
90
|
+
def custom_puts(text="")
|
91
|
+
pretty_print_mode = options[:pretty_print]
|
92
|
+
if pretty_print_mode
|
93
|
+
puts "#{text}"
|
94
|
+
else
|
95
|
+
puts "#{text}".colorize(color: :white, background: :default)
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
def custom_print(text="")
|
100
|
+
pretty_print_mode = options[:pretty_print]
|
101
|
+
empty_space = IO.console.winsize[1] - text.size
|
102
|
+
empty_space = 0 if empty_space < 0
|
103
|
+
if pretty_print_mode
|
104
|
+
print "\r#{text}"
|
105
|
+
# $stdout.flush
|
106
|
+
print " " * empty_space
|
107
|
+
# IO.console.flush
|
108
|
+
else
|
109
|
+
print "#{text}\n".white
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
113
|
+
|
114
|
+
|
115
|
+
def intro(mode)
|
116
|
+
trap("INT") { exit! }
|
117
|
+
print_banner
|
118
|
+
check_log_files
|
119
|
+
create_mechanic
|
120
|
+
custom_print "[+] ".cyan + "Processing successfully completed"
|
121
|
+
puts
|
122
|
+
# unless mode != :default
|
123
|
+
login
|
124
|
+
# end
|
125
|
+
|
126
|
+
end
|
127
|
+
|
128
|
+
|
129
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
module Protocol
|
2
|
+
def create_mechanic
|
3
|
+
puts Dir.glob("")
|
4
|
+
@agent = Mechanize.new
|
5
|
+
@agent.max_history = 2
|
6
|
+
# @agent.log = Logger.new(STDOUT)
|
7
|
+
@agent.ca_file = "./cacert.pem"
|
8
|
+
@agent.user_agent_alias = "Mac Safari"
|
9
|
+
# @agent.set_proxy()
|
10
|
+
custom_print "PROCESSING: ".cyan.bold + "protocol created"
|
11
|
+
end
|
12
|
+
|
13
|
+
|
14
|
+
def get_page(url)
|
15
|
+
response = @agent.get(url)
|
16
|
+
# @temp_jar = @agent.cookie_jar
|
17
|
+
# @temp_jar.save("#{@lib_dir}/cookies.yaml", session: true) # => saving the cookies
|
18
|
+
end
|
19
|
+
|
20
|
+
|
21
|
+
def set_mechanic_data(params={})
|
22
|
+
@cookies = Hash[@agent.cookies.map {|key, value| [key.name, key.value]}]
|
23
|
+
@params = params
|
24
|
+
@headers = {
|
25
|
+
'Cookie' => "mid=#{@cookies['mid']}; csrftoken=#{@cookies['csrftoken']}; sessionid=#{@cookies['sessionid']}; ds_user_id=#{@cookies['ds_user_id']}; rur=#{@cookies['rur']}; s_network=#{@cookies['s_network']}; ig_pr= 1; ig_vw=1920",
|
26
|
+
'X-CSRFToken' => "#{@cookies['csrftoken']}",
|
27
|
+
'X-Requested-With' => 'XMLHttpRequest',
|
28
|
+
'Content-Type' => 'application/x-www-form-urlencoded',
|
29
|
+
'X-Instagram-AJAX' => '1',
|
30
|
+
'Accept' => 'application/json, text/javascript, */*',
|
31
|
+
'User-Agent' => 'Mozilla/5.0 (Windows NT 6.3; WOW64; rv:52.0) Gecko/20100101 Firefox/52.0',
|
32
|
+
'Accept-Encoding' => 'gzip, deflate',
|
33
|
+
'Accept-Language' => "ru-RU,ru;q=0.8,en-US;q=0.6,en;q=0.4",
|
34
|
+
'Connection' => 'keep-alive',
|
35
|
+
# 'Content-Length' => '0',
|
36
|
+
'Host' => 'www.instagram.com',
|
37
|
+
'Origin' => 'https://www.instagram.com',
|
38
|
+
'Referer' => 'https://www.instagram.com/'
|
39
|
+
}
|
40
|
+
end
|
41
|
+
|
42
|
+
end
|
@@ -0,0 +1,131 @@
|
|
1
|
+
module Grabber
|
2
|
+
|
3
|
+
def get_user_informations(user_id)
|
4
|
+
# puts "=".cyan*10
|
5
|
+
begin
|
6
|
+
user_page = "https://www.instagram.com/web/friendships/#{user_id}/follow/"
|
7
|
+
response = get_page(user_page)
|
8
|
+
last_page = @agent.history.last.uri.to_s
|
9
|
+
username = last_page.split('/')[3]
|
10
|
+
response = @agent.get("https://instagram.com/#{username}/?__a=1")
|
11
|
+
rescue Exception => e
|
12
|
+
if response.code == "404"
|
13
|
+
puts "ERORR: [404] Notfound\t#{e.message}".red
|
14
|
+
exit!
|
15
|
+
elsif response.code == "403"
|
16
|
+
exit! if @error_403_times == 3
|
17
|
+
@error_403_times += 1
|
18
|
+
puts "ERROR: [403] (looks like you're banned from IG)".red
|
19
|
+
retry
|
20
|
+
end
|
21
|
+
end
|
22
|
+
data = JSON.parse(response.body)
|
23
|
+
data.extend Hashie::Extensions::DeepFind
|
24
|
+
|
25
|
+
# File.open("body.json", "w+") {|file| file.puts data.extend Hashie::Extensions::DeepFind }
|
26
|
+
|
27
|
+
@informations = {
|
28
|
+
followers: data.deep_find("followed_by")["count"],
|
29
|
+
following: data.deep_find("follows")["count"],
|
30
|
+
is_private: data.deep_find("is_private"),
|
31
|
+
is_verified: data.deep_find("is_verified"),
|
32
|
+
username: data.deep_find("username"),
|
33
|
+
full_name: data.deep_find("full_name"),
|
34
|
+
id: data.deep_find("id")
|
35
|
+
}
|
36
|
+
# puts @informations
|
37
|
+
end
|
38
|
+
|
39
|
+
def get_media_informations(media_id)
|
40
|
+
# puts "=".cyan*10
|
41
|
+
custom_puts "[+] ".cyan + "Trying to get media (#{media_id}) information"
|
42
|
+
begin
|
43
|
+
response = @agent.get("https://www.instagram.com/p/#{media_id}/?__a=1")
|
44
|
+
rescue Exception => e
|
45
|
+
if response.code == "404"
|
46
|
+
puts "ERORR: [404] Notfound\t#{e.message}".red
|
47
|
+
exit!
|
48
|
+
elsif response.code == "403"
|
49
|
+
exit! if @error_403_times == 3
|
50
|
+
@error_403_times += 1
|
51
|
+
puts "ERROR: [403] (looks like you're banned from IG)".red
|
52
|
+
retry
|
53
|
+
end
|
54
|
+
end
|
55
|
+
data = JSON.parse(response.body)
|
56
|
+
data.extend Hashie::Extensions::DeepFind
|
57
|
+
# pp data.extend Hashie::Extensions::DeepFind
|
58
|
+
|
59
|
+
# puts data.deep_find('id')
|
60
|
+
# puts data.deep_find('is_video')
|
61
|
+
# puts data.deep_find('comments_disabled')
|
62
|
+
# puts data.deep_find('viewer_has_liked')
|
63
|
+
# puts data.deep_find('has_blocked_viewer')
|
64
|
+
# puts data.deep_find('followed_by_viewer')
|
65
|
+
# puts data.deep_find('full_name')
|
66
|
+
# puts data.deep_find('is_private')
|
67
|
+
# puts data.deep_find('is_verified')
|
68
|
+
# puts data.deep_find('requested_by_viewer')
|
69
|
+
|
70
|
+
@informations = {
|
71
|
+
id: data.deep_find("id"),
|
72
|
+
is_video: data.deep_find("is_video"),
|
73
|
+
comments_disabled: data.deep_find("comments_disabled"),
|
74
|
+
viewer_has_liked: data.deep_find("viewer_has_liked"),
|
75
|
+
has_blocked_viewer: data.deep_find("has_blocked_viewer"),
|
76
|
+
followed_by_viewer: data.deep_find("followed_by_viewer"),
|
77
|
+
full_name: data.deep_find("full_name"),
|
78
|
+
is_private: data.deep_find("is_private"),
|
79
|
+
is_verified: data.deep_find("is_verified"),
|
80
|
+
requested_by_viewer: data.deep_find("requested_by_viewer"),
|
81
|
+
text: data.deep_find("text")
|
82
|
+
}
|
83
|
+
unless @infinite_tags == true
|
84
|
+
# puts "in infinity".upcase.cyan.bold
|
85
|
+
tags = @informations[:text].encode('UTF-8', {:invalid => :replace, :undef => :replace, :replace => '?'}).split(/\W+/)
|
86
|
+
id = 0
|
87
|
+
tags.each do |tag|
|
88
|
+
if tag == "_" || tag == "" || tag.nil?
|
89
|
+
tags.delete(tag)
|
90
|
+
else
|
91
|
+
id += 1
|
92
|
+
Config.options.tags << tag
|
93
|
+
end
|
94
|
+
end
|
95
|
+
custom_puts "\n[+] ".cyan + "[" + "#{id}".yellow + "] New tags added"
|
96
|
+
# pp Config.options.tags
|
97
|
+
end
|
98
|
+
# puts @informations
|
99
|
+
|
100
|
+
end
|
101
|
+
|
102
|
+
|
103
|
+
|
104
|
+
def search(tags=[])
|
105
|
+
tags.each do |tag|
|
106
|
+
url = "https://www.instagram.com/explore/tags/#{tag}/?__a=1"
|
107
|
+
custom_print "[+] ".cyan + "Searching in [##{tag}] tag"
|
108
|
+
response = @agent.get(url)
|
109
|
+
# puts response.body.to_s.cyan[0..50]
|
110
|
+
data = JSON.parse(response.body)
|
111
|
+
data.extend Hashie::Extensions::DeepFind
|
112
|
+
owners = data.deep_find_all("owner")
|
113
|
+
media_codes = data.deep_find_all("code")
|
114
|
+
owners.map { |id| users << id['id']}
|
115
|
+
media_codes.map {|code| medias << code}
|
116
|
+
Config.options.tags.delete(tag)
|
117
|
+
end
|
118
|
+
custom_puts "\n[+] ".cyan + "Total grabbed users [" + "#{users.size}".yellow + "]"
|
119
|
+
custom_puts "[+] ".cyan + "Total grabbed medias [" + "#{medias.size}".yellow + "]\n"
|
120
|
+
end
|
121
|
+
|
122
|
+
|
123
|
+
|
124
|
+
|
125
|
+
|
126
|
+
|
127
|
+
|
128
|
+
|
129
|
+
|
130
|
+
|
131
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
module Log
|
2
|
+
|
3
|
+
def check_log_files
|
4
|
+
custom_print "PROCESSING: ".cyan.bold + "checking log files"
|
5
|
+
if !File.exists?(@logs_dir)
|
6
|
+
Dir.mkdir(@logs_dir)
|
7
|
+
end
|
8
|
+
|
9
|
+
if File.exists?("#{@logs_dir}/logs.log")
|
10
|
+
# File.delete("#{@logs_dir}/logs.log")
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
def write_file(filename, text="")
|
15
|
+
File.open("#{@logs_dir}/#{filename}", "a+") {|file| file.print "#{text.chomp},"}
|
16
|
+
end
|
17
|
+
|
18
|
+
def log(text="",from="")
|
19
|
+
time = Time.new.strftime("%H:%M:%S %y-%m-%d")
|
20
|
+
File.open("#{@logs_dir}/logs-#{@global_time}.log","a+") do |log_file|
|
21
|
+
log_file.puts "[#{@log_counter}] [#{time}] [#{from}] -- : #{text}"
|
22
|
+
end
|
23
|
+
@log_counter += 1
|
24
|
+
end
|
25
|
+
|
26
|
+
def save_action_data(id=0,type=:default)
|
27
|
+
case type
|
28
|
+
when :follow
|
29
|
+
write_file("followed_users.txt",id)
|
30
|
+
when :unfollow
|
31
|
+
write_file("unfollowed_users.txt",id)
|
32
|
+
when :like
|
33
|
+
write_file("liked_medias.txt",id)
|
34
|
+
when :comment
|
35
|
+
write_file("commented_medias.txt",id)
|
36
|
+
when :default
|
37
|
+
puts "please choice a type"
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
end
|
42
|
+
|
43
|
+
|
@@ -0,0 +1,49 @@
|
|
1
|
+
module Login
|
2
|
+
|
3
|
+
def login
|
4
|
+
log("trying to login")
|
5
|
+
custom_print "[+] ".cyan + "Trying to login into [#{options[:username]}] account"
|
6
|
+
login_page = @agent.get("https://www.instagram.com/accounts/login/?force_classic_login")
|
7
|
+
page_form = login_page.forms.last
|
8
|
+
page_form.username = options[:username]
|
9
|
+
page_form.password = options[:password]
|
10
|
+
page = page_form.submit
|
11
|
+
if page.code == "200"
|
12
|
+
@login_status = true
|
13
|
+
log("successfully logged in")
|
14
|
+
custom_print "[+] ".cyan + "Successfully logged in".green.bold
|
15
|
+
else
|
16
|
+
@login_status = false
|
17
|
+
custom_print "[-] ".cyan + "Invalid username or password".red.bold
|
18
|
+
exit
|
19
|
+
end
|
20
|
+
puts
|
21
|
+
rescue Exception => e
|
22
|
+
log("a error detected: #{e.class} #{e}")
|
23
|
+
@login_status = false
|
24
|
+
custom_print "[-] ".cyan + "#{e.class} #{e.message}\n#{e.backtrace.inspect}".red
|
25
|
+
end
|
26
|
+
|
27
|
+
def logout
|
28
|
+
log("trying to logout")
|
29
|
+
custom_print "[+] ".cyan + "Trying to logging out"
|
30
|
+
set_mechanic_data
|
31
|
+
logout_page = @agent.get("https://www.instagram.com/accounts/logout/")
|
32
|
+
@logout_status = true
|
33
|
+
log("successfully logged out")
|
34
|
+
custom_print "[+] ".cyan + "Successfully logged out"
|
35
|
+
end
|
36
|
+
|
37
|
+
def check_login_status(mode=:default)
|
38
|
+
# custom_print "[+] ".cyan + "Checking login status"
|
39
|
+
log("checking loging status")
|
40
|
+
if @login_status
|
41
|
+
return true
|
42
|
+
else
|
43
|
+
custom_print "[-] ".cyan + "you're not logged in.".red.bold
|
44
|
+
return false
|
45
|
+
login if mode == :auto_retry
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
end
|
@@ -0,0 +1,242 @@
|
|
1
|
+
module Modes
|
2
|
+
|
3
|
+
def mode(mode=:default)
|
4
|
+
case mode
|
5
|
+
when :infinite
|
6
|
+
custom_print "[+] ".cyan + "Auto mode is turned on".yellow
|
7
|
+
search(options[:tags])
|
8
|
+
@next_day = Time.new + 1.days
|
9
|
+
puts
|
10
|
+
while true
|
11
|
+
# if @maximums[:likes_in_day] != @maximums[:max_likes_per_day] && @maximums[:follows_in_day] != @maximums[:max_follows_per_day] && @maximums[:unfollows_in_day] != @maximums[:max_unfollows_per_day] && @maximums[:comments_in_day] != @maximums[:max_comments_per_day]
|
12
|
+
if !maximums_are_full?
|
13
|
+
# custom_puts "[+] " + "".red
|
14
|
+
if @maximums[:follows_in_day] != @maximums[:max_follows_per_day]
|
15
|
+
@maximums[:follows_in_day] += 1
|
16
|
+
auto_follow
|
17
|
+
else
|
18
|
+
custom_puts "[+] ".cyan + "Maximum follows per day"
|
19
|
+
end
|
20
|
+
|
21
|
+
if @maximums[:unfollows_in_day] != @maximums[:max_unfollows_per_day]
|
22
|
+
@maximums[:unfollows_in_day] += 1
|
23
|
+
auto_unfollow
|
24
|
+
else
|
25
|
+
custom_puts "[+] ".cyan + "Maximum unfollows per day"
|
26
|
+
end
|
27
|
+
|
28
|
+
if @maximums[:likes_in_day] != @maximums[:max_likes_per_day]
|
29
|
+
@maximums[:likes_in_day] += 1
|
30
|
+
auto_like
|
31
|
+
else
|
32
|
+
custom_puts "[+] ".cyan + "Maximum likes per day"
|
33
|
+
end
|
34
|
+
|
35
|
+
if @maximums[:comments_in_day] != @maximums[:max_comments_per_day]
|
36
|
+
@maximums[:comments_in_day] += 1
|
37
|
+
auto_comment
|
38
|
+
else
|
39
|
+
custom_puts "[+] ".cyan + "Maximum comments per day"
|
40
|
+
end
|
41
|
+
# custom_print "maximums = #{@maximums}"
|
42
|
+
|
43
|
+
# exit
|
44
|
+
else
|
45
|
+
# custom_print "in check date ... "
|
46
|
+
check_date
|
47
|
+
sleep 1
|
48
|
+
end
|
49
|
+
end
|
50
|
+
when :clean_up
|
51
|
+
custom_puts "[+] ".cyan + "Clean up mode is turned on"
|
52
|
+
@local_stroage[:followed_users].each do |user|
|
53
|
+
unfollow(user)
|
54
|
+
end
|
55
|
+
when :default
|
56
|
+
custom_print "[-] ".cyan + "Please choose a mode".red
|
57
|
+
else
|
58
|
+
custom_print "[-] ".cyan + "Please choose a mode".red
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
|
63
|
+
|
64
|
+
|
65
|
+
|
66
|
+
|
67
|
+
|
68
|
+
|
69
|
+
|
70
|
+
|
71
|
+
def auto_follow
|
72
|
+
all_users = users
|
73
|
+
id = 0
|
74
|
+
custom_puts "[+] ".cyan + "#{all_users.size} users ready to follow"
|
75
|
+
# users.each do |user|
|
76
|
+
while @maximums[:follows_in_day] < @maximums[:max_follows_per_day]
|
77
|
+
begin
|
78
|
+
id += 1 if all_users[id].nil? || all_users[id] == []
|
79
|
+
get_user_informations(all_users[id])
|
80
|
+
# custom_print "user informations:".cyan
|
81
|
+
# @informations.map {|key,val| custom_print "#{key}: #{val}"}
|
82
|
+
custom_puts "[+] ".cyan + "Trying to follow a user [#{all_users[id]}]"
|
83
|
+
follow(@informations[:id])
|
84
|
+
custom_puts "\n[+] ".cyan + "User followed!".green.bold
|
85
|
+
@maximums[:follows_in_day] += 1
|
86
|
+
id += 1
|
87
|
+
# custom_print "development informations: ".cyan
|
88
|
+
# custom_print "follows_in_day = #{@maximums[:follows_in_day]} || max_follows_per_day = #{@maximums[:max_follows_per_day]} || id = #{id}"
|
89
|
+
fall_in_asleep
|
90
|
+
rescue Exception => e
|
91
|
+
puts "an error detected ... #{e} #{e.backtrace}\nignored"
|
92
|
+
id += 1
|
93
|
+
retry
|
94
|
+
end
|
95
|
+
end
|
96
|
+
# end
|
97
|
+
end
|
98
|
+
|
99
|
+
def auto_unfollow
|
100
|
+
# users.each do |user|
|
101
|
+
followed_users = @local_stroage[:followed_users]
|
102
|
+
custom_puts "[+] ".cyan + "#{followed_users.size} users ready to unfollow"
|
103
|
+
id = 0
|
104
|
+
while @maximums[:unfollows_in_day] < @maximums[:max_unfollows_per_day]
|
105
|
+
if @local_stroage[:followed_users].size < @maximums[:max_unfollows_per_day]
|
106
|
+
begin
|
107
|
+
# get_user_informations(unfollowed_users[id])
|
108
|
+
# custom_print "user informations:".cyan
|
109
|
+
# @informations.map {|key,val| custom_print "#{key}: #{val}"}
|
110
|
+
# custom_print "unfollowed_users[id] => #{unfollowed_users[id]}"
|
111
|
+
custom_puts "[+] ".cyan + "Trying to unfollow a user [#{followed_users[id]}]"
|
112
|
+
unfollow(followed_users[id])
|
113
|
+
custom_puts "\n[+] ".cyan + "User unfollowed".bold.green
|
114
|
+
@maximums[:unfollows_in_day] += 1
|
115
|
+
id += 1
|
116
|
+
# custom_print "unfollows_in_day = #{@maximums[:unfollows_in_day]} || max_unfollows_per_day = #{@maximums[:max_unfollows_per_day]} || id = #{id}"
|
117
|
+
fall_in_asleep
|
118
|
+
rescue Exception => e
|
119
|
+
puts "an error detected ... #{e}\nignored"
|
120
|
+
id += 1
|
121
|
+
retry
|
122
|
+
end
|
123
|
+
else
|
124
|
+
custom_print "[+] ".cyan + "[unfollow per day] is bigger than [follow per day]"
|
125
|
+
exit
|
126
|
+
end
|
127
|
+
end
|
128
|
+
end
|
129
|
+
|
130
|
+
def auto_like
|
131
|
+
# medias.each do |media|
|
132
|
+
all_medias = medias
|
133
|
+
custom_puts "[+] ".cyan + "#{all_medias.size} Medias ready to like"
|
134
|
+
id = 0
|
135
|
+
while @maximums[:likes_in_day] < @maximums[:max_likes_per_day]
|
136
|
+
begin
|
137
|
+
get_media_informations(all_medias[id])
|
138
|
+
# custom_print "media informations:".cyan
|
139
|
+
# @informations.map {|key,val| custom_print "#{key}: #{val}"}
|
140
|
+
custom_puts "[+] ".cyan + "Trying to like a media[#{all_medias[id]}]"
|
141
|
+
like(@informations[:id])
|
142
|
+
custom_puts "\n[+] ".cyan + "Media liked".green.bold
|
143
|
+
@maximums[:likes_in_day] += 1
|
144
|
+
# custom_print "likes_in_day = #{@maximums[:likes_in_day]} || max_likes_per_day = #{@maximums[:max_likes_per_day]}"
|
145
|
+
id += 1
|
146
|
+
fall_in_asleep
|
147
|
+
rescue Exception => e
|
148
|
+
puts "an error detected ... #{e}\n#{e.backtrace.inspect}\nignored"
|
149
|
+
id += 1
|
150
|
+
retry
|
151
|
+
end
|
152
|
+
end
|
153
|
+
end
|
154
|
+
|
155
|
+
def auto_comment
|
156
|
+
# medias.each do |media|
|
157
|
+
all_medias = medias
|
158
|
+
custom_puts "[+] ".cyan + "#{all_medias.size} Medias ready to send a comment"
|
159
|
+
id = 0
|
160
|
+
while @maximums[:comments_in_day] < @maximums[:max_comments_per_day]
|
161
|
+
begin
|
162
|
+
get_media_informations(all_medias[id])
|
163
|
+
id += 1 if @informations[:comments_disabled]
|
164
|
+
# custom_print "media informations:".cyan
|
165
|
+
# @informations.map {|key,val| custom_print "#{key}: #{val}"}
|
166
|
+
custom_puts "[+] ".cyan + "Trying to send a comment to media[#{all_medias[id]}]"
|
167
|
+
comment(@informations[:id], generate_a_comment)
|
168
|
+
custom_puts "\n[+] ".cyan + "comment successfully has been sent".green.bold
|
169
|
+
@maximums[:comments_in_day] += 1
|
170
|
+
# custom_print "comments_in_day = #{@maximums[:comments_in_day]} || max_comments_per_day = #{@maximums[:max_comments_per_day]}"
|
171
|
+
id += 1
|
172
|
+
fall_in_asleep
|
173
|
+
rescue Exception => e
|
174
|
+
puts "an error detected ... #{e}\n#{e.backtrace.inspect}\nignored"
|
175
|
+
id += 1
|
176
|
+
retry
|
177
|
+
end
|
178
|
+
end
|
179
|
+
end
|
180
|
+
|
181
|
+
def generate_a_comment
|
182
|
+
comments = options[:comments]
|
183
|
+
first = comments[0].sample
|
184
|
+
second = comments[1].sample
|
185
|
+
third = comments[2].sample
|
186
|
+
fourth = comments[3].sample
|
187
|
+
fifth = comments[4].sample
|
188
|
+
return "#{first} #{second} #{third} #{fourth}#{fifth}"
|
189
|
+
end
|
190
|
+
|
191
|
+
def check_date
|
192
|
+
# custom_print "checking time ..."
|
193
|
+
time = ((@next_day) - Time.new).to_i # => seconds elapsed ...
|
194
|
+
# custom_print "next day = #{@next_day}"
|
195
|
+
if time == 0
|
196
|
+
|
197
|
+
custom_print "[+] ".cyan + "It's a new day"
|
198
|
+
@local_stroage[:followed_users] = []
|
199
|
+
@local_stroage[:unfollowed_users] = []
|
200
|
+
@local_stroage[:liked_medias] = []
|
201
|
+
@local_stroage[:commented_medias] = []
|
202
|
+
@maximums[:follows_in_day] = 0
|
203
|
+
@maximums[:unfollows_in_day] = 0
|
204
|
+
@maximums[:likes_in_day] = 0
|
205
|
+
@maximums[:comments_in_day] = 0
|
206
|
+
# time = (((Time.new + 1.days).to_f - Time.new.to_f) * 24 * 60 * 60).to_i
|
207
|
+
@next_day = Time.new + 1.days
|
208
|
+
# custom_print "new next day = #{@next_day}"
|
209
|
+
# custom_print "new maximums = #{@maximums}"
|
210
|
+
# custom_print "new local stroage = #{@local_stroage}"
|
211
|
+
# custom_print "="*10
|
212
|
+
unless @infinite_tags == true
|
213
|
+
search(options[:tags])
|
214
|
+
end
|
215
|
+
|
216
|
+
else
|
217
|
+
custom_print "[+] ".cyan + "#{time} seconds remained"
|
218
|
+
end
|
219
|
+
# return true
|
220
|
+
end
|
221
|
+
|
222
|
+
def fall_in_asleep
|
223
|
+
time = options[:wait_per_action]
|
224
|
+
custom_puts "\n[+] ".cyan + "Waiting for #{time} seconds"
|
225
|
+
sleep time
|
226
|
+
end
|
227
|
+
|
228
|
+
def maximums_are_full?
|
229
|
+
if @maximums[:likes_in_day] == @maximums[:max_likes_per_day] && @maximums[:follows_in_day] == @maximums[:max_follows_per_day] && @maximums[:unfollows_in_day] == @maximums[:max_unfollows_per_day] && @maximums[:comments_in_day] == @maximums[:max_comments_per_day]
|
230
|
+
return true
|
231
|
+
else
|
232
|
+
return false
|
233
|
+
end
|
234
|
+
end
|
235
|
+
|
236
|
+
|
237
|
+
|
238
|
+
|
239
|
+
|
240
|
+
|
241
|
+
|
242
|
+
end
|
metadata
ADDED
@@ -0,0 +1,158 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: instabot
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.2
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- eVanilla
|
8
|
+
autorequire:
|
9
|
+
bindir: exe
|
10
|
+
cert_chain: []
|
11
|
+
date: 2017-10-29 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: bundler
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '1.15'
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '1.15'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: rake
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '10.0'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '10.0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: colorize
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: 0.8.1
|
48
|
+
type: :runtime
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: 0.8.1
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: mechanize
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - "~>"
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '2.7'
|
62
|
+
- - ">="
|
63
|
+
- !ruby/object:Gem::Version
|
64
|
+
version: 2.7.5
|
65
|
+
type: :runtime
|
66
|
+
prerelease: false
|
67
|
+
version_requirements: !ruby/object:Gem::Requirement
|
68
|
+
requirements:
|
69
|
+
- - "~>"
|
70
|
+
- !ruby/object:Gem::Version
|
71
|
+
version: '2.7'
|
72
|
+
- - ">="
|
73
|
+
- !ruby/object:Gem::Version
|
74
|
+
version: 2.7.5
|
75
|
+
- !ruby/object:Gem::Dependency
|
76
|
+
name: hashie
|
77
|
+
requirement: !ruby/object:Gem::Requirement
|
78
|
+
requirements:
|
79
|
+
- - "~>"
|
80
|
+
- !ruby/object:Gem::Version
|
81
|
+
version: '3.5'
|
82
|
+
- - ">="
|
83
|
+
- !ruby/object:Gem::Version
|
84
|
+
version: 3.5.6
|
85
|
+
type: :runtime
|
86
|
+
prerelease: false
|
87
|
+
version_requirements: !ruby/object:Gem::Requirement
|
88
|
+
requirements:
|
89
|
+
- - "~>"
|
90
|
+
- !ruby/object:Gem::Version
|
91
|
+
version: '3.5'
|
92
|
+
- - ">="
|
93
|
+
- !ruby/object:Gem::Version
|
94
|
+
version: 3.5.6
|
95
|
+
- !ruby/object:Gem::Dependency
|
96
|
+
name: activesupport
|
97
|
+
requirement: !ruby/object:Gem::Requirement
|
98
|
+
requirements:
|
99
|
+
- - "~>"
|
100
|
+
- !ruby/object:Gem::Version
|
101
|
+
version: '5.1'
|
102
|
+
- - ">="
|
103
|
+
- !ruby/object:Gem::Version
|
104
|
+
version: 5.1.4
|
105
|
+
type: :runtime
|
106
|
+
prerelease: false
|
107
|
+
version_requirements: !ruby/object:Gem::Requirement
|
108
|
+
requirements:
|
109
|
+
- - "~>"
|
110
|
+
- !ruby/object:Gem::Version
|
111
|
+
version: '5.1'
|
112
|
+
- - ">="
|
113
|
+
- !ruby/object:Gem::Version
|
114
|
+
version: 5.1.4
|
115
|
+
description: A instagram bot works without instagram api, only needs your username
|
116
|
+
and password
|
117
|
+
email:
|
118
|
+
- ''
|
119
|
+
executables: []
|
120
|
+
extensions: []
|
121
|
+
extra_rdoc_files: []
|
122
|
+
files:
|
123
|
+
- lib/instabot.rb
|
124
|
+
- lib/instabot/actions.rb
|
125
|
+
- lib/instabot/banner.rb
|
126
|
+
- lib/instabot/config.rb
|
127
|
+
- lib/instabot/core.rb
|
128
|
+
- lib/instabot/create_protocol.rb
|
129
|
+
- lib/instabot/grabber.rb
|
130
|
+
- lib/instabot/logger.rb
|
131
|
+
- lib/instabot/login.rb
|
132
|
+
- lib/instabot/modes.rb
|
133
|
+
- lib/instabot/version.rb
|
134
|
+
homepage: https://github.com/eVanilla/instabot.rb
|
135
|
+
licenses:
|
136
|
+
- MIT
|
137
|
+
metadata: {}
|
138
|
+
post_install_message:
|
139
|
+
rdoc_options: []
|
140
|
+
require_paths:
|
141
|
+
- lib
|
142
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
143
|
+
requirements:
|
144
|
+
- - ">="
|
145
|
+
- !ruby/object:Gem::Version
|
146
|
+
version: '0'
|
147
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
148
|
+
requirements:
|
149
|
+
- - ">="
|
150
|
+
- !ruby/object:Gem::Version
|
151
|
+
version: '0'
|
152
|
+
requirements: []
|
153
|
+
rubyforge_project:
|
154
|
+
rubygems_version: 2.6.4
|
155
|
+
signing_key:
|
156
|
+
specification_version: 4
|
157
|
+
summary: Ruby instagram bot
|
158
|
+
test_files: []
|