facebook-cli 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: bf355c2240f7b7be619e73de13c23b91bc464b12
4
+ data.tar.gz: 8fac877170cfebfadd4bc0b9c4ae66d59c5e9138
5
+ SHA512:
6
+ metadata.gz: 2687e272aed37d79b35eb51126977aa1047b1751fdac8483c6b80c84d325b49dea3c814d990b065e8abf24c88697758a61095d717f301ddbb996b371506ecae0
7
+ data.tar.gz: 0fe2391fd1f630b93ebdb23370449ebef5742798d897564292b5199d4f8b1664e4915167896cecd86cb843ae5a4fd6b7bfe3efffe18bb4a67dd7a0955208e549
@@ -0,0 +1,5 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ $:.unshift "#{File.dirname(__FILE__)}/../lib"
4
+
5
+ require 'fbcli'
@@ -0,0 +1,161 @@
1
+ require 'gli'
2
+ require 'yaml'
3
+ require 'fbcli/auth'
4
+ require 'fbcli/format'
5
+ require 'fbcli/facebook'
6
+
7
+ CONFIG_FILE = "config.yml"
8
+
9
+ include GLI::App
10
+
11
+ program_desc "Facebook command line interface"
12
+
13
+ version '1.0.0'
14
+
15
+ flag [:token], :desc => 'Provide Facebook access token', :required => false
16
+ flag [:format], :desc => 'Output format (values: text, html)', :default_value => "text"
17
+
18
+ pre do |global_options,command|
19
+ $config = YAML.load_file(CONFIG_FILE)
20
+
21
+ if $config['app_id'].nil? or $config['app_secret'].nil?
22
+ exit_now! <<~EOM
23
+ It looks like you are running #{$0} for the first time.
24
+
25
+ The following steps are necessary to use the Facebook API:
26
+
27
+ - Create a new application at: https://developers.facebook.com/apps
28
+ - In the Settings tab, add "localhost" to the App Domains
29
+ - Save the App ID and App Secret in "config.yml"
30
+
31
+ After that, run: #{$0} login
32
+ EOM
33
+ end
34
+
35
+ $format = global_options[:format]
36
+
37
+ if $format == "html" and command.name != :login
38
+ puts <<~EOM
39
+ <!doctype html>
40
+ <html lang=en>
41
+ <head>
42
+ <meta charset=utf-8>
43
+ </head>
44
+ <body>
45
+ EOM
46
+ end
47
+
48
+ # Success
49
+ true
50
+ end
51
+
52
+ post do |global_options,command|
53
+ if $format == "html" and command.name != :login
54
+ puts <<~EOM
55
+ </body>
56
+ </html>
57
+ EOM
58
+ end
59
+ end
60
+
61
+ on_error do |exception|
62
+ puts exception.message
63
+
64
+ # Suppress GLI's built-in error handling
65
+ false
66
+ end
67
+
68
+ desc "Log into Facebook and receive an access token"
69
+ command :login do |c|
70
+ c.flag [:port], :desc => 'Local TCP port to serve Facebook login redirect page', :default_value => '3333'
71
+ c.action do |global_options,options,args|
72
+ token, expiration = FBCLI::listen_for_auth_code(options['port'], $config['app_id'], $config['app_secret'])
73
+
74
+ if not token.nil?
75
+ $config['access_token'] = token
76
+
77
+ File.open(CONFIG_FILE,'w') do |f|
78
+ f.write $config.to_yaml
79
+ end
80
+
81
+ puts "Your access token: #{token}"
82
+ puts
83
+ puts "Expires in: #{FBCLI::expiration_str(expiration.to_i)}"
84
+ puts
85
+ puts "Have fun!"
86
+ end
87
+ end
88
+ end
89
+
90
+ desc "Show your name and profile ID"
91
+ command :me do |c|
92
+ c.action do |global_options,options,args|
93
+ data = FBCLI::request_data global_options, ""
94
+ FBCLI::write "Name: #{data["name"]}"
95
+ FBCLI::write "Your profile ID: #{data["id"]}"
96
+ end
97
+ end
98
+
99
+ desc "List the pages you have 'Liked'"
100
+ command :likes do |c|
101
+ c.action do |global_options,options,args|
102
+ FBCLI::page_items global_options, "likes" do |item|
103
+ FBCLI::write item["name"]
104
+ FBCLI::write FBCLI::link item["id"]
105
+ FBCLI::write
106
+ end
107
+ end
108
+ end
109
+
110
+ desc "List the people you are friends with (some limitations)"
111
+ long_desc <<~EOM
112
+ As of Graph API v2.0 Facebook no longer provides access to your full friends list.
113
+ As an alternative, we now request 'invitable_friends' which only includes friends
114
+ you are allowed to invite to use your app.
115
+
116
+ See: https://developers.facebook.com/docs/apps/faq#faq_1694316010830088
117
+ EOM
118
+ command :friends do |c|
119
+ c.action do |global_options,options,args|
120
+ FBCLI::page_items global_options, "invitable_friends" do |item|
121
+ FBCLI::write item["name"]
122
+ end
123
+ end
124
+ end
125
+
126
+ desc "List the posts on your profile"
127
+ command :feed do |c|
128
+ c.action do |global_options,options,args|
129
+ FBCLI::page_items global_options, "feed" do |item|
130
+ profile_id, post_id = item["id"].split '_', 2
131
+
132
+ FBCLI::write item["message"] if item.has_key?("message")
133
+ FBCLI::write FBCLI::link "#{profile_id}/posts/#{post_id}"
134
+ FBCLI::write "Created: #{FBCLI::date(item["created_time"])}"
135
+ FBCLI::write "--"
136
+ end
137
+ end
138
+ end
139
+
140
+ consumePhoto = Proc.new do |item|
141
+ FBCLI::write item["name"] unless not item.key?("name")
142
+ FBCLI::write FBCLI::link "#{item["id"]}"
143
+ FBCLI::write "Created: #{FBCLI::date(item["created_time"])}"
144
+ FBCLI::write "--"
145
+ end
146
+
147
+ desc "List photos you have uploaded"
148
+ command :photos do |c|
149
+ c.action do |global_options,options,args|
150
+ FBCLI::page_items global_options, "photos?type=uploaded", &consumePhoto
151
+ end
152
+ end
153
+
154
+ desc "List photos you are tagged in"
155
+ command :photosof do |c|
156
+ c.action do |global_options,options,args|
157
+ FBCLI::page_items global_options, "photos", &consumePhoto
158
+ end
159
+ end
160
+
161
+ exit run(ARGV)
@@ -0,0 +1,70 @@
1
+ require 'net/http'
2
+ require 'uri'
3
+ require 'webrick'
4
+ require 'json'
5
+
6
+ module FBCLI
7
+ API_VERSION = "2.7"
8
+
9
+ def self.listen_for_auth_code(port, app_id, app_secret)
10
+ uri = "https://www.facebook.com/dialog/oauth?client_id=#{app_id}" +
11
+ "&redirect_uri=http://localhost:#{port}/" +
12
+ "&scope=user_likes,user_friends,user_photos,user_posts"
13
+
14
+ puts "Please open: #{uri}"
15
+ puts
16
+ puts "Waiting for authorization code on port #{port}..."
17
+ puts
18
+
19
+ server = WEBrick::HTTPServer.new(
20
+ :Port => port,
21
+ :SSLEnable => false,
22
+ :Logger => WEBrick::Log.new(File.open(File::NULL, 'w')),
23
+ :AccessLog => []
24
+ )
25
+
26
+ access_token = nil
27
+
28
+ server.mount_proc '/' do |req, res|
29
+ key, value = req.query_string.split '=', 2
30
+
31
+ if key == "code"
32
+ access_token = get_access_token(port, app_id, value, app_secret)
33
+ else
34
+ puts "Received unexpected request: #{req.query_string}"
35
+ # TODO: Handle forseeable cases
36
+ end
37
+
38
+ res.body = 'You may now close this window.'
39
+ server.shutdown
40
+ end
41
+
42
+ # Allow CTRL+C intervention
43
+ trap 'INT' do server.shutdown end
44
+
45
+ # This thread will block execution until server shuts down
46
+ server.start
47
+
48
+ # Return access token
49
+ access_token
50
+ end
51
+
52
+ def self.get_access_token(port, app_id, auth_code, app_secret)
53
+ auth_uri = "https://graph.facebook.com/v#{API_VERSION}/oauth/access_token?" +
54
+ "client_id=#{app_id}" +
55
+ "&redirect_uri=http://localhost:#{port}/" +
56
+ "&client_secret=#{app_secret}" +
57
+ "&code=#{auth_code}"
58
+
59
+ res = Net::HTTP.get_response(URI.parse(auth_uri))
60
+ res = JSON.parse(res.body)
61
+
62
+ [res["access_token"], res["expires_in"]]
63
+ end
64
+
65
+ def self.expiration_str(seconds)
66
+ h, m = seconds.divmod(60 * 3600)
67
+
68
+ "#{h} hours and #{m.div 3600} minutes"
69
+ end
70
+ end
@@ -0,0 +1,42 @@
1
+ require 'koala'
2
+
3
+ module FBCLI
4
+ def self.init_api(global_options)
5
+ if not global_options[:token].nil?
6
+ $config['access_token'] = global_options[:token]
7
+ end
8
+
9
+ if $config['access_token'].nil? or $config['access_token'].empty?
10
+ exit_now! "You must first acquire an access token; run: #{$0} login"
11
+ end
12
+
13
+ Koala::Facebook::API.new($config['access_token'])
14
+ end
15
+
16
+ def self.request_data(global_options, cmd)
17
+ api = init_api(global_options)
18
+
19
+ begin
20
+ data = api.get_connections("me", cmd)
21
+ rescue Koala::Facebook::APIError => e
22
+ exit_now! \
23
+ "Koala #{e.fb_error_type} (code #{e.fb_error_code})" +
24
+ if not e.http_status.nil? then " HTTP status: #{e.http_status}" else "" end +
25
+ "\n #{e.fb_error_message}"
26
+ end
27
+
28
+ data
29
+ end
30
+
31
+ def self.page_items(global_options, cmd)
32
+ items = request_data(global_options, cmd)
33
+
34
+ while not items.nil? do
35
+ items.each { |item|
36
+ yield item
37
+ }
38
+
39
+ items = items.next_page
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,27 @@
1
+ module FBCLI
2
+ # Facebook returns dates in ISO 8601 format
3
+ def self.date(fb_date)
4
+ Time.parse(fb_date).httpdate
5
+ end
6
+
7
+ def self.link(path, format = $format)
8
+ url = "https://www.facebook.com/#{path}"
9
+
10
+ case format
11
+ when "html"
12
+ "<a href=\"#{url}\">#{url}</a>"
13
+ else
14
+ url
15
+ end
16
+ end
17
+
18
+ def self.write(str = "", format = $format)
19
+ str = "" if str.nil?
20
+
21
+ if format == "html"
22
+ str = " " + str + "<br>"
23
+ end
24
+
25
+ puts str.encode('utf-8')
26
+ end
27
+ end
metadata ADDED
@@ -0,0 +1,49 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: facebook-cli
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ platform: ruby
6
+ authors:
7
+ - Ildar Sagdejev
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2016-09-21 00:00:00.000000000 Z
12
+ dependencies: []
13
+ description: A limited command line interface to the Facebook Graph API
14
+ email: specious@gmail.com
15
+ executables:
16
+ - facebook-cli
17
+ extensions: []
18
+ extra_rdoc_files: []
19
+ files:
20
+ - bin/facebook-cli
21
+ - lib/fbcli.rb
22
+ - lib/fbcli/auth.rb
23
+ - lib/fbcli/facebook.rb
24
+ - lib/fbcli/format.rb
25
+ homepage: https://github.com/specious/facebook-cli
26
+ licenses:
27
+ - MIT
28
+ metadata: {}
29
+ post_install_message:
30
+ rdoc_options: []
31
+ require_paths:
32
+ - lib
33
+ required_ruby_version: !ruby/object:Gem::Requirement
34
+ requirements:
35
+ - - ">="
36
+ - !ruby/object:Gem::Version
37
+ version: '2.3'
38
+ required_rubygems_version: !ruby/object:Gem::Requirement
39
+ requirements:
40
+ - - ">="
41
+ - !ruby/object:Gem::Version
42
+ version: '0'
43
+ requirements: []
44
+ rubyforge_project:
45
+ rubygems_version: 2.5.1
46
+ signing_key:
47
+ specification_version: 4
48
+ summary: Facebook command line utility
49
+ test_files: []