facebook-cli 1.0.0

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.
@@ -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: []