FbRuby 0.0.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/Gemfile +6 -0
- data/LICENSE +21 -0
- data/README.md +876 -0
- data/lib/FbRuby/chats.rb +369 -0
- data/lib/FbRuby/comments.rb +178 -0
- data/lib/FbRuby/createaccount.rb +142 -0
- data/lib/FbRuby/exceptions.rb +25 -0
- data/lib/FbRuby/facebook.rb +453 -0
- data/lib/FbRuby/groups.rb +260 -0
- data/lib/FbRuby/login.rb +297 -0
- data/lib/FbRuby/messenger.rb +272 -0
- data/lib/FbRuby/posts.rb +267 -0
- data/lib/FbRuby/settings.rb +282 -0
- data/lib/FbRuby/tempmail.rb +56 -0
- data/lib/FbRuby/user.rb +550 -0
- data/lib/FbRuby/utils.rb +412 -0
- data/lib/FbRuby.rb +21 -0
- metadata +114 -0
data/lib/FbRuby/utils.rb
ADDED
@@ -0,0 +1,412 @@
|
|
1
|
+
require 'cgi'
|
2
|
+
require 'zlib'
|
3
|
+
require 'json'
|
4
|
+
require 'stringio'
|
5
|
+
require 'nokogiri'
|
6
|
+
require 'rest-client'
|
7
|
+
require_relative 'exceptions.rb'
|
8
|
+
|
9
|
+
# https://stackoverflow.com/a/34678301/14861946
|
10
|
+
Nokogiri::XML::Node.send(:define_method, 'xpath_regex') { |*args|
|
11
|
+
xpath = args[0]
|
12
|
+
rgxp = /\/([a-z]+)\[@([a-z\-]+)~=\/(.*?)\/\]/
|
13
|
+
xpath.gsub!(rgxp) { |s| m = s.match(rgxp); "/#{m[1]}[regex(.,'#{m[2]}','#{m[3]}')]" }
|
14
|
+
self.xpath(xpath, Class.new {
|
15
|
+
def regex node_set, attr, regex
|
16
|
+
node_set.find_all { |node| node[attr] =~ /#{regex}/ }
|
17
|
+
end
|
18
|
+
}.new)
|
19
|
+
}
|
20
|
+
|
21
|
+
class RestClient::Response
|
22
|
+
|
23
|
+
#include RestClient::AbstractResponse
|
24
|
+
|
25
|
+
def body(decompress = true)
|
26
|
+
encoding = self.headers[:content_encoding]
|
27
|
+
response = String.new(self)
|
28
|
+
|
29
|
+
if encoding == "gzip" and decompress and !response.empty?
|
30
|
+
return Zlib::GzipReader.new(StringIO.new(response)).read
|
31
|
+
elsif encoding == "deflate" and decompress and !response.empty?
|
32
|
+
return Zlib::Inflate.inflate(response)
|
33
|
+
else
|
34
|
+
return response
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
def to_s
|
39
|
+
return body
|
40
|
+
end
|
41
|
+
|
42
|
+
def ok?
|
43
|
+
if (400..500).to_a.member? (code)
|
44
|
+
return false
|
45
|
+
else
|
46
|
+
return true
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
def parse_html
|
51
|
+
return Nokogiri::HTML(body)
|
52
|
+
end
|
53
|
+
|
54
|
+
def parse_xml
|
55
|
+
return Nokogiri::XML(body)
|
56
|
+
end
|
57
|
+
|
58
|
+
def json
|
59
|
+
return JSON.parse(body)
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
class RestClient::Payload::Multipart
|
64
|
+
def create_file_field(s, k, v)
|
65
|
+
begin
|
66
|
+
s.write("Content-Disposition: form-data;")
|
67
|
+
s.write(" name=\"#{k}\";") unless (k.nil? || k=='')
|
68
|
+
s.write(" filename=\"#{v.respond_to?(:original_filename) ? v.original_filename : File.basename(v.path)}\"#{EOL}")
|
69
|
+
s.write("Content-Type: #{v.respond_to?(:content_type) ? v.content_type : mime_for(v.path)}#{EOL}")
|
70
|
+
s.write(EOL)
|
71
|
+
while (data = v.read(8124))
|
72
|
+
s.write(data)
|
73
|
+
end
|
74
|
+
rescue IOError
|
75
|
+
ensure
|
76
|
+
v.close if v.respond_to?(:close)
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
module FbRuby
|
82
|
+
# utility
|
83
|
+
module Utils
|
84
|
+
# requests Session
|
85
|
+
class Session
|
86
|
+
|
87
|
+
@@default_user_agent = "Mozilla/5.0 (Linux; Android 9; SM-N976V) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/76.0.3809.89 Mobile Safari/537.36"
|
88
|
+
@@headers = {'Accept-Encoding'=> 'gzip, deflate', 'Accept'=> '*/*', 'Connection'=> 'keep-alive'}
|
89
|
+
@@facebook_exceptions = true
|
90
|
+
|
91
|
+
class << self
|
92
|
+
def default_user_agent
|
93
|
+
return @@default_user_agent
|
94
|
+
end
|
95
|
+
|
96
|
+
def default_headers
|
97
|
+
return @@headers
|
98
|
+
end
|
99
|
+
|
100
|
+
def facebook_exceptions
|
101
|
+
return @@facebook_exceptions
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
attr_reader :options, :headers, :cookies
|
106
|
+
|
107
|
+
def initialize(headers = {}, cookies = {})
|
108
|
+
@headers = headers.empty? ? @@headers : headers
|
109
|
+
|
110
|
+
if cookies.instance_of?(Hash)
|
111
|
+
@cookies = cookies
|
112
|
+
else
|
113
|
+
@cookies = FbRuby::Utils::parse_cookies_header(cookies)
|
114
|
+
end
|
115
|
+
|
116
|
+
@options = {
|
117
|
+
verify_ssl: true,
|
118
|
+
max_redirects: 10,
|
119
|
+
timeout: 30,
|
120
|
+
open_timeout: 30,
|
121
|
+
user_agent: @headers.member?('user-agent') ? @headers['user-agent'] : @@default_user_agent,
|
122
|
+
follow_redirect: true}
|
123
|
+
end
|
124
|
+
|
125
|
+
def get(url, params = {}, headers = {}, options = {})
|
126
|
+
if params.length > 0
|
127
|
+
url = URI(url.to_s)
|
128
|
+
url.query = URI.encode_www_form(params.to_a)
|
129
|
+
end
|
130
|
+
|
131
|
+
request(:get, url, {}, headers, nil, options)
|
132
|
+
end
|
133
|
+
|
134
|
+
def post(url, data = {}, headers = {}, options = {})
|
135
|
+
request(:post, url, {}, headers, data, options)
|
136
|
+
end
|
137
|
+
|
138
|
+
def put(url, data = {}, headers = {}, options = {})
|
139
|
+
request(:put, url, {}, headers, data, options)
|
140
|
+
end
|
141
|
+
|
142
|
+
def delete(url, headers = {}, options = {})
|
143
|
+
request(:delete, url, {}, headers, nil, options)
|
144
|
+
end
|
145
|
+
|
146
|
+
def head(url, headers = {}, options = {})
|
147
|
+
request(:head, url, {}, headers, nil, options)
|
148
|
+
end
|
149
|
+
|
150
|
+
def get_without_sessions(url)
|
151
|
+
return RestClient.get(url.to_s, cookies: @cookies)
|
152
|
+
end
|
153
|
+
|
154
|
+
def post_without_sessions(url, data = {})
|
155
|
+
begin
|
156
|
+
return RestClient.post(url.to_s, data, cookies: @cookies)
|
157
|
+
rescue RestClient::Found => err
|
158
|
+
return get_without_sessions(err.response.headers[:location])
|
159
|
+
end
|
160
|
+
end
|
161
|
+
|
162
|
+
def get_cookie_str
|
163
|
+
return FbRuby::Utils::cookie_hash_to_str(@cookies)
|
164
|
+
end
|
165
|
+
|
166
|
+
def get_cookie_dict
|
167
|
+
if @cookies.instance_of? (Hash)
|
168
|
+
return @cookies
|
169
|
+
else
|
170
|
+
return FbRuby::Utils::parse_cookies_header(@cookies)
|
171
|
+
end
|
172
|
+
end
|
173
|
+
|
174
|
+
def get_cookie_hash
|
175
|
+
return get_cookie_dict
|
176
|
+
end
|
177
|
+
|
178
|
+
private
|
179
|
+
|
180
|
+
def request(method, url, params = {}, headers = {}, data = nil, options = {})
|
181
|
+
url = url.to_s if url.kind_of? (URI)
|
182
|
+
# url = URI::DEFAULT_PARSER.escape(url)
|
183
|
+
headers = @headers.merge(headers)
|
184
|
+
headers['Cookies'] = @cookies.map { |k, v| "#{k}=#{v}" }.join('; ') unless @cookies.empty?
|
185
|
+
|
186
|
+
begin
|
187
|
+
response = RestClient::Request.execute(method: method,url: url,headers: headers,cookies: @cookies,payload: data,params: params,**@options.merge(options)) do |response|
|
188
|
+
if [301,302, 307].include? (response.code)
|
189
|
+
# request(method,response.headers[:location],params,headers,data,options)
|
190
|
+
response.follow_redirection
|
191
|
+
else
|
192
|
+
response.return!
|
193
|
+
end
|
194
|
+
end
|
195
|
+
rescue RestClient::MovedPermanently, RestClient::Found => req_err
|
196
|
+
new_url = req_err.response.headers[:location]
|
197
|
+
response = get(new_url)
|
198
|
+
rescue RestClient::ExceptionWithResponse => req_err
|
199
|
+
response = req_err.response
|
200
|
+
end
|
201
|
+
|
202
|
+
# Perbarui cookie setelah menerima respons
|
203
|
+
update_cookies(response.cookies)
|
204
|
+
|
205
|
+
if @@facebook_exceptions
|
206
|
+
html = response.parse_html
|
207
|
+
unless html.at_xpath("//a[starts-with(@href,\"/home.php?rand=\")]").nil?
|
208
|
+
bugnub = html.xpath_regex("//a[@href~=/^\/bugnub\/\?(.*)=ErrorPage/]").first
|
209
|
+
div_err = html.at_css('div#root')
|
210
|
+
err_msg = "Terjadi Kesalahan :("
|
211
|
+
div_err_msg = div_err.at_css('div[class]')
|
212
|
+
err_msg = div_err_msg.css('text()').map(&:text).join(" ") unless div_err_msg.nil?
|
213
|
+
|
214
|
+
if bugnub.nil?
|
215
|
+
raise FbRuby::Exceptions::PageNotFound.new(err_msg)
|
216
|
+
else
|
217
|
+
raise FbRuby::Exceptions::FacebookError.new(err_msg)
|
218
|
+
end
|
219
|
+
end
|
220
|
+
|
221
|
+
if !html.at_css('div#root[@role="main"]').nil? && !html.at_css('a[class][@target="_self"][@href^="/?"]').nil? #html.at_css("a[@href^=\"#{URI.join(@url, '/help/contact/')}\"]").nil?
|
222
|
+
err_msg = html.at_css('div#root[@role="main"]')
|
223
|
+
err_msg = err_msg.parent unless err_msg.parent.nil?
|
224
|
+
|
225
|
+
raise FbRuby::Exceptions::AccountTemporaryBanned.new(err_msg.css('text()').map(&:text).join("\n"))
|
226
|
+
end
|
227
|
+
|
228
|
+
|
229
|
+
end
|
230
|
+
|
231
|
+
return response
|
232
|
+
end
|
233
|
+
|
234
|
+
def update_cookies(cookie_header)
|
235
|
+
return if cookie_header.nil? || cookie_header.empty?
|
236
|
+
|
237
|
+
cookie_header.each do |key, value|
|
238
|
+
@cookies[key] = value
|
239
|
+
end
|
240
|
+
end
|
241
|
+
end
|
242
|
+
|
243
|
+
class ThreadPool
|
244
|
+
|
245
|
+
def initialize(size:)
|
246
|
+
@size = size
|
247
|
+
@jobs = Queue.new
|
248
|
+
@pool = Array.new(size) do
|
249
|
+
Thread.new do
|
250
|
+
catch(:exit) do
|
251
|
+
loop do
|
252
|
+
job, args = @jobs.pop
|
253
|
+
job.call(*args)
|
254
|
+
end
|
255
|
+
end
|
256
|
+
end
|
257
|
+
end
|
258
|
+
end
|
259
|
+
|
260
|
+
def schedule(*args, &block)
|
261
|
+
@jobs << [block, args]
|
262
|
+
end
|
263
|
+
|
264
|
+
def shutdown
|
265
|
+
@size.times do
|
266
|
+
schedule { throw :exit }
|
267
|
+
end
|
268
|
+
|
269
|
+
@pool.map(&:join)
|
270
|
+
end
|
271
|
+
end
|
272
|
+
|
273
|
+
def self.randomString(length)
|
274
|
+
chars = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'
|
275
|
+
return Array.new(length) { chars[rand(chars.size)] }.join
|
276
|
+
end
|
277
|
+
|
278
|
+
def self.parse_cookies_header(value)
|
279
|
+
return {} unless value
|
280
|
+
|
281
|
+
value.split(/; */n).each_with_object({}) do |cookie, cookies|
|
282
|
+
next if cookie.empty?
|
283
|
+
key, value = cookie.split('=', 2)
|
284
|
+
cookies[key] = (unescape(value) rescue value) unless cookies.key?(key)
|
285
|
+
end
|
286
|
+
end
|
287
|
+
|
288
|
+
def self.cookie_hash_to_str(cookie_hash, chomp = true, strip = true)
|
289
|
+
if cookie_hash.instance_of? (Hash)
|
290
|
+
cookies = cookie_hash.map{|key, value| "#{key}=#{value}"}.compact.join(';')
|
291
|
+
cookies.strip! if strip
|
292
|
+
cookies.chomp! if chomp
|
293
|
+
|
294
|
+
return cookies
|
295
|
+
end
|
296
|
+
end
|
297
|
+
|
298
|
+
def self.convert_file_size(size_in_bytes)
|
299
|
+
units = %w[bytes KB MB GB TB PB EB]
|
300
|
+
return "#{size_in_bytes} #{units[0]}" if size_in_bytes < 1024
|
301
|
+
|
302
|
+
exponent = (Math.log(size_in_bytes) / Math.log(1024)).to_i
|
303
|
+
converted_size = size_in_bytes.to_f / 1024 ** exponent
|
304
|
+
converted_size = converted_size.round(2)
|
305
|
+
return "#{converted_size} #{units[exponent]}"
|
306
|
+
end
|
307
|
+
|
308
|
+
def self.create_timeline(nokogiri_obj, request_session, message, file = nil, location = nil,feeling = nil,filter_type = '-1', **kwargs)
|
309
|
+
host = URI("https://mbasic.facebook.com/")
|
310
|
+
form = nokogiri_obj.at_xpath("//form[starts-with(@action,'/composer/mbasic')]")
|
311
|
+
action = URI.join(host,form['action'])
|
312
|
+
formData = {}
|
313
|
+
form.css("input[type = 'hidden'][name][value]").each{|i| formData[i['name']] = i['value']}
|
314
|
+
|
315
|
+
# lanjutkan nanti untuk foto
|
316
|
+
unless file.nil?
|
317
|
+
file_data = formData.clone
|
318
|
+
file_data['view_photo'] = "Submit"
|
319
|
+
formFile = request_session.post(action, data = file_data).parse_html.at_xpath("//form[starts-with(@action,'/composer/mbasic')]")
|
320
|
+
dataFile = {"add_photo_done"=>"Submit","filter_type"=>filter_type}
|
321
|
+
formFile.css("input[type = 'hidden']").each{|i| dataFile[i['name']] = i['value']}
|
322
|
+
upload = FbRuby::Utils::upload_photo(request_session, URI.join(host,formFile['action']), file, dataFile)
|
323
|
+
imgIds = []
|
324
|
+
upload.each do |f|
|
325
|
+
action = URI.join(host,f.parse_html.at_css('form')['action'])
|
326
|
+
f.parse_html.css("input[type = 'hidden'][name][value]").each do |t|
|
327
|
+
if t['name'] == "photo_ids[]"
|
328
|
+
imgIds << t['value']
|
329
|
+
else
|
330
|
+
formData[t['name']] = t['value']
|
331
|
+
end
|
332
|
+
|
333
|
+
end
|
334
|
+
end
|
335
|
+
formData['photo_ids[]'] = imgIds.join(' , ')
|
336
|
+
end
|
337
|
+
|
338
|
+
unless location.nil?
|
339
|
+
lok_data = formData.clone
|
340
|
+
lok_data['view_location'] = "Submit"
|
341
|
+
formLok = request_session.post(action, data = lok_data).parse_html.at_xpath("//form[starts-with(@action,'/places/selector')]")
|
342
|
+
dataLok = {"query"=>location}
|
343
|
+
formLok.css("input[type = 'hidden'][name][value]").each{|i| dataLok[i['name']] = i['value']}
|
344
|
+
cari = request_session.get(URI.join(host,formLok['action']), params = dataLok).parse_html
|
345
|
+
result = cari.at_xpath("//a[starts-with(@href,'/composer/mbasic') and contains(@href,'at=')] | //a[starts-with(@href,'%2Fcomposer%2Fmbasic') and contains(@href,'at=')]")
|
346
|
+
raise FbRuby::Exceptions::FacebookError.new("Lokasi dengan nama #{location} tidak di temukan:(") if result.nil?
|
347
|
+
formData['at'] = result['href'].match(/at=(\d+)/)[1]
|
348
|
+
end
|
349
|
+
|
350
|
+
unless feeling.nil?
|
351
|
+
fel_data = formData.clone
|
352
|
+
fel_data['view_minutiae'] = "Submit"
|
353
|
+
felUrl = request_session.post(action, data = fel_data).parse_html.at_xpath("//a[starts-with(@href,'/composer/mbasic') and contains(@href,'ogaction')]")
|
354
|
+
raise FbRuby::Exceptions::FacebookError.new("Tidak dapat menembahkan feeling:(") if felUrl.nil?
|
355
|
+
felForm = request_session.get(URI.join(host,felUrl['href'])).parse_html.at_xpath("//form[starts-with(@action,'/composer/mbasic')]")
|
356
|
+
felData = {"mnt_query"=>feeling}
|
357
|
+
felForm.css("input[type = 'hidden'][name][value]").each{|i| felData[i['name']] = i['value']}
|
358
|
+
cari = request_session.get(URI.join(host,felForm['action']), params = felData).parse_html
|
359
|
+
result = cari.at_xpath("//a[starts-with(@href,'/composer/mbasic') and contains(@href,'ogaction')]")
|
360
|
+
raise FbRuby::Exceptions::FacebookError.new("Feeling dengan nama #{feeling} tidak di temukan!") if result.nil?
|
361
|
+
formData['ogaction'] = result['href'].match(/ogaction=(\d+)/)[1]
|
362
|
+
formData['ogphrase'] = feeling
|
363
|
+
end
|
364
|
+
|
365
|
+
formData['view_post'] = "Submit"
|
366
|
+
formData['xc_message'] = message
|
367
|
+
formData.update(kwargs)
|
368
|
+
|
369
|
+
begin
|
370
|
+
posting = request_session.post(action, data = formData)
|
371
|
+
return posting.ok?
|
372
|
+
rescue FbRuby::Exceptions::PageNotFound
|
373
|
+
return true
|
374
|
+
end
|
375
|
+
end
|
376
|
+
|
377
|
+
def self.upload_photo(request_session, upload_url, files, data = {}, headers = {}, separator = '|', default_key = 'file', max_number = 3)
|
378
|
+
max_size = 4194304 # Maksimal ukuran foto (4MB)
|
379
|
+
support_file = ['.jpg','.png','.webp','.gif','.tiff','.heif','.jpeg']
|
380
|
+
photo = []
|
381
|
+
reqList = []
|
382
|
+
|
383
|
+
unless files.kind_of?(Hash)
|
384
|
+
number = 0
|
385
|
+
files = files.split(separator) if files.kind_of? (String)
|
386
|
+
files.each do |f|
|
387
|
+
number = 0 if number >= max_number
|
388
|
+
number += 1
|
389
|
+
photo << {"#{default_key}#{number}"=>f}
|
390
|
+
end
|
391
|
+
else
|
392
|
+
files.each{|k,v| photo << {k=>v}}
|
393
|
+
end
|
394
|
+
|
395
|
+
photo.each_slice(max_number.to_i) do |img|
|
396
|
+
mydata = data.clone
|
397
|
+
|
398
|
+
img.each do |khaneysia|
|
399
|
+
key = khaneysia.keys.first
|
400
|
+
path = khaneysia.values.first
|
401
|
+
ext = File.extname(path)
|
402
|
+
raise FbRuby::Exceptions::FacebookError.new("Ukuran file #{File.basename(path)} terlalu besar sehingga file tersebut tidak bisa di upload. File harus berukuran kurang dari #{FbRuby::Utils::convert_file_size(max_size)} :)") if File.size(path) > max_size
|
403
|
+
raise FbRuby::Exceptions::FacebookError.new("Hanya bisa mengupload file dengan extensi #{support_file.join(', ')}, tidak bisa mengupload file dengan extensi #{ext}") unless support_file.include? (ext)
|
404
|
+
mydata.update({key=>File.new(path,"rb")})
|
405
|
+
end
|
406
|
+
reqList << request_session.post(upload_url,mydata,headers)
|
407
|
+
end
|
408
|
+
|
409
|
+
return reqList
|
410
|
+
end
|
411
|
+
end
|
412
|
+
end
|
data/lib/FbRuby.rb
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
#--
|
4
|
+
# Copyright 2024 by Rahmat adha
|
5
|
+
# All rights reserved.
|
6
|
+
# See LICENSE for permissions.
|
7
|
+
#++
|
8
|
+
|
9
|
+
require_relative "FbRuby/user.rb"
|
10
|
+
require_relative "FbRuby/posts.rb"
|
11
|
+
require_relative "FbRuby/login.rb"
|
12
|
+
require_relative "FbRuby/chats.rb"
|
13
|
+
require_relative "FbRuby/utils.rb"
|
14
|
+
require_relative "FbRuby/groups.rb"
|
15
|
+
require_relative "FbRuby/tempmail.rb"
|
16
|
+
require_relative "FbRuby/settings.rb"
|
17
|
+
require_relative "FbRuby/facebook.rb"
|
18
|
+
require_relative "FbRuby/comments.rb"
|
19
|
+
require_relative "FbRuby/messenger.rb"
|
20
|
+
require_relative "FbRuby/exceptions.rb"
|
21
|
+
require_relative "FbRuby/createaccount.rb"
|
metadata
ADDED
@@ -0,0 +1,114 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: FbRuby
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.2
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Rahmat adha
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2024-07-08 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: rest-client
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '2.1'
|
20
|
+
- - ">="
|
21
|
+
- !ruby/object:Gem::Version
|
22
|
+
version: 2.1.0
|
23
|
+
type: :runtime
|
24
|
+
prerelease: false
|
25
|
+
version_requirements: !ruby/object:Gem::Requirement
|
26
|
+
requirements:
|
27
|
+
- - "~>"
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: '2.1'
|
30
|
+
- - ">="
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
version: 2.1.0
|
33
|
+
- !ruby/object:Gem::Dependency
|
34
|
+
name: nokogiri
|
35
|
+
requirement: !ruby/object:Gem::Requirement
|
36
|
+
requirements:
|
37
|
+
- - "~>"
|
38
|
+
- !ruby/object:Gem::Version
|
39
|
+
version: '1.15'
|
40
|
+
- - ">="
|
41
|
+
- !ruby/object:Gem::Version
|
42
|
+
version: 1.15.3
|
43
|
+
type: :runtime
|
44
|
+
prerelease: false
|
45
|
+
version_requirements: !ruby/object:Gem::Requirement
|
46
|
+
requirements:
|
47
|
+
- - "~>"
|
48
|
+
- !ruby/object:Gem::Version
|
49
|
+
version: '1.15'
|
50
|
+
- - ">="
|
51
|
+
- !ruby/object:Gem::Version
|
52
|
+
version: 1.15.3
|
53
|
+
- !ruby/object:Gem::Dependency
|
54
|
+
name: yard
|
55
|
+
requirement: !ruby/object:Gem::Requirement
|
56
|
+
requirements:
|
57
|
+
- - "~>"
|
58
|
+
- !ruby/object:Gem::Version
|
59
|
+
version: '0.9'
|
60
|
+
type: :development
|
61
|
+
prerelease: false
|
62
|
+
version_requirements: !ruby/object:Gem::Requirement
|
63
|
+
requirements:
|
64
|
+
- - "~>"
|
65
|
+
- !ruby/object:Gem::Version
|
66
|
+
version: '0.9'
|
67
|
+
description: Library ini di gunakan untuk scraping web facebook
|
68
|
+
email:
|
69
|
+
- rahmadadha11@gmail.com
|
70
|
+
executables: []
|
71
|
+
extensions: []
|
72
|
+
extra_rdoc_files: []
|
73
|
+
files:
|
74
|
+
- Gemfile
|
75
|
+
- LICENSE
|
76
|
+
- README.md
|
77
|
+
- lib/FbRuby.rb
|
78
|
+
- lib/FbRuby/chats.rb
|
79
|
+
- lib/FbRuby/comments.rb
|
80
|
+
- lib/FbRuby/createaccount.rb
|
81
|
+
- lib/FbRuby/exceptions.rb
|
82
|
+
- lib/FbRuby/facebook.rb
|
83
|
+
- lib/FbRuby/groups.rb
|
84
|
+
- lib/FbRuby/login.rb
|
85
|
+
- lib/FbRuby/messenger.rb
|
86
|
+
- lib/FbRuby/posts.rb
|
87
|
+
- lib/FbRuby/settings.rb
|
88
|
+
- lib/FbRuby/tempmail.rb
|
89
|
+
- lib/FbRuby/user.rb
|
90
|
+
- lib/FbRuby/utils.rb
|
91
|
+
homepage: https://github.com/MR-X-Junior/fbruby
|
92
|
+
licenses:
|
93
|
+
- MIT
|
94
|
+
metadata: {}
|
95
|
+
post_install_message:
|
96
|
+
rdoc_options: []
|
97
|
+
require_paths:
|
98
|
+
- lib
|
99
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - ">="
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: 3.0.0
|
104
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
105
|
+
requirements:
|
106
|
+
- - ">="
|
107
|
+
- !ruby/object:Gem::Version
|
108
|
+
version: '0'
|
109
|
+
requirements: []
|
110
|
+
rubygems_version: 3.4.10
|
111
|
+
signing_key:
|
112
|
+
specification_version: 4
|
113
|
+
summary: Facebook Scraper
|
114
|
+
test_files: []
|