instabot 0.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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: []
|