facy 1.2.9.rc1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 8dea1a2158dbc7708ea9c5ea389cd691a7b3a7e8
4
+ data.tar.gz: b5b33c9358d8e6afb39eb5fa52dfef9a0b68949f
5
+ SHA512:
6
+ metadata.gz: 59f1a7c30b3c0ef84edeedb55d69867ac9aff3c211f68a2c83fe89b7235e1abcd1bc499c823d1cd31e6ed29d605b162b3cb4985e50e41659406161ba12c4a48d
7
+ data.tar.gz: a6571b1d6a67012fdd217b19dbe853bcf9cf0fa9df7ae9b4a88a5028ed996bb1a1bce42b4c06d3caa14679b790592688b2fae0d41adb117908c34158d9f17fc4
data/.gitignore ADDED
@@ -0,0 +1,34 @@
1
+ *.gem
2
+ *.rbc
3
+ /.config
4
+ /coverage/
5
+ /InstalledFiles
6
+ /pkg/
7
+ /spec/reports/
8
+ /test/tmp/
9
+ /test/version_tmp/
10
+ /tmp/
11
+
12
+ ## Specific to RubyMotion:
13
+ .dat*
14
+ .repl_history
15
+ build/
16
+
17
+ ## Documentation cache and generated files:
18
+ /.yardoc/
19
+ /_yardoc/
20
+ /doc/
21
+ /rdoc/
22
+
23
+ ## Environment normalisation:
24
+ /.bundle/
25
+ /lib/bundler/man/
26
+
27
+ # for a library or gem, you might want to ignore these files since the code is
28
+ # intended to run in multiple environments; otherwise, check them in:
29
+ # Gemfile.lock
30
+ # .ruby-version
31
+ # .ruby-gemset
32
+
33
+ # unless supporting rvm < 1.11.0 or doing something fancy, ignore this:
34
+ .rvmrc
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in facy.gemspec
4
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2014 dxhuy1988
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,32 @@
1
+ # Facy
2
+ Facy is a terminal client for facebook, which support streaming-like feature.
3
+ Only supports Ruby 1.9 and later.
4
+ To install facy, we need ruby pre-installed, please refer to https://www.ruby-lang.org/en/installation/ to know how to install ruby.
5
+ I recommend rvm to control the version of installed ruby.
6
+
7
+
8
+ - **Homepage**: http://huydx.com/facy
9
+ - **Installation guide**: https://github.com/huydx/facy/wiki/Installation-Guide
10
+ - **Usage guide**: https://github.com/huydx/facy/wiki/Usage-guide
11
+
12
+ ![](http://i.gyazo.com/01de9c8da6191b79bcec201048361f58.png)
13
+
14
+ ## Installation
15
+ Install it yourself as:
16
+ ```
17
+ $ gem install facy
18
+ ```
19
+ and then refer to the [wiki page](https://github.com/huydx/facy/wiki/Installation-Guide) to complete the initial setup process. To setup facy, you need to register facebook developer account, and create your own facebook app.
20
+ - To register facebook developer account, go to: https://developers.facebook.com/docs/create-developer-account
21
+ - After registerd, you can go to https://developers.facebook.com/apps to create your new app
22
+ - And then you'are able to setup facy follow https://github.com/huydx/facy/wiki/Installation-Guide
23
+
24
+
25
+
26
+ ## Contributing
27
+
28
+ 1. Fork it ( http://github.com/huydx/facy/fork )
29
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
30
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
31
+ 4. Push to the branch (`git push origin my-new-feature`)
32
+ 5. Create new Pull Request
data/Rakefile ADDED
@@ -0,0 +1 @@
1
+ require "bundler/gem_tasks"
data/bin/facy ADDED
@@ -0,0 +1,18 @@
1
+ #!/usr/bin/env ruby
2
+ # coding: utf-8
3
+ #
4
+ print "\e[31m"
5
+ puts %q{
6
+ _/ ____\____ ____ ___.__.
7
+ \ __\\__ \ _/ ___< | |
8
+ | | / __ \\ \___\___ |
9
+ |__| (____ /\___ > ____|
10
+ \/ \/\/
11
+ }
12
+ print "\e[0m"
13
+ require 'facy'
14
+ Facy.parse(ARGV)
15
+ puts "Fetching facebook stream at first time may takes a while ♩ ♪ ♫ ♬"
16
+ puts ""
17
+
18
+ Facy.start({})
data/config.yml ADDED
@@ -0,0 +1,4 @@
1
+ ---
2
+ app_id:
3
+ permission: friends_status,manage_notifications,publish_actions,read_friendlists,read_stream,user_status
4
+ granted:
data/facy.gemspec ADDED
@@ -0,0 +1,27 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'facy/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "facy"
8
+ spec.version = Facy::VERSION
9
+ spec.authors = ["dxhuy1988"]
10
+ spec.email = ["doxuanhuy@gmail.com"]
11
+ spec.summary = %q{facy: terminal client for facebook}
12
+ spec.description = %q{facy: first colorful terminal client for facebook}
13
+ spec.homepage = "https://github.com/huydx/facy"
14
+ spec.license = "MIT"
15
+
16
+ spec.files = `git ls-files`.split("\n") + ['config.yml']
17
+ spec.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
18
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
+ spec.require_paths = ["lib"]
20
+
21
+ spec.add_runtime_dependency "bundler", "~> 1.5"
22
+ spec.add_runtime_dependency "koala", "~>1.10"
23
+ spec.add_runtime_dependency "activesupport", "~>4.0"
24
+ spec.add_runtime_dependency "launchy", "~>2.4"
25
+ spec.add_runtime_dependency "eventmachine", "~>1.0"
26
+ spec.add_runtime_dependency "rmagick", "~>2.13"
27
+ end
data/lib/facy.rb ADDED
@@ -0,0 +1,32 @@
1
+ %w(
2
+ rmagick
3
+ koala
4
+ readline
5
+ yaml
6
+ thread
7
+ launchy
8
+ eventmachine
9
+ active_support
10
+ active_support/core_ext
11
+ active_support/dependencies
12
+ ).each { |lib| require lib }
13
+
14
+ Thread.abort_on_exception = true
15
+ Encoding.default_external = Encoding.find('UTF-8')
16
+
17
+ %w(
18
+ core_ext
19
+ core
20
+ logger
21
+ get_token
22
+ output
23
+ command
24
+ help
25
+ facebook
26
+ input_queue
27
+ command
28
+ converter
29
+ exception
30
+ option_parser
31
+ image_viewer
32
+ ).each { |file| require_dependency File.expand_path("../facy/#{file}", __FILE__) }
@@ -0,0 +1,180 @@
1
+ module Facy
2
+ module Command
3
+ def commands
4
+ @commands ||= []
5
+ end
6
+
7
+ def command(pattern, options={}, &block)
8
+ commands << {pattern: pattern, block: block}
9
+ end
10
+
11
+ def execute(text)
12
+ text.strip!
13
+ rule, target = match_single_command(text) || match_target_command(text)
14
+ commands.each do |c|
15
+ if rule.to_s == c[:pattern].to_s.split(":").first
16
+ c[:block].call(target)
17
+ return
18
+ end
19
+ end
20
+ rescue Exception => e
21
+ error e
22
+ log(:error, e.message)
23
+ log(:error, e.backtrace)
24
+ end
25
+
26
+ def match_target_command(text)
27
+ text =~ /^:(\S*) (.+)$/
28
+ return [$1, $2] if $1 && $2
29
+ return nil
30
+ end
31
+
32
+ def match_single_command(text)
33
+ text =~ /^:(\S*)$/
34
+ return $1
35
+ end
36
+ end
37
+
38
+ extend Command
39
+
40
+ init do
41
+ commands.clear
42
+ command :post do |text|
43
+ async {
44
+ ret = facebook_post(text)
45
+ instant_output(Item.new(
46
+ info: :info,
47
+ content: "post '#{text}' has been posted to your wall")
48
+ ) if ret["id"]
49
+ }
50
+ end
51
+ help :post, 'post to your own wall', ':post [content]'
52
+
53
+ command :like do |post_code|
54
+ post_code = "$#{post_code}"
55
+ item = post_code_reverse_map[post_code]
56
+ post_id = item.id if item.is_a?(Item)
57
+ async {
58
+ ret = facebook_like(post_id)
59
+ instant_output(Item.new(info: :info, content: "like success")) if ret
60
+ }
61
+ end
62
+ help :like, 'like a post', ':like [code]'
63
+
64
+ command :exit do
65
+ stop_process
66
+ end
67
+ help :exit, 'quit facy', ":exit"
68
+
69
+ command :open do |post_code|
70
+ post_code = "$#{post_code}"
71
+ item = post_code_reverse_map[post_code]
72
+ link = item.data.link if item.is_a?(Item)
73
+ p link
74
+ if link
75
+ browse(link)
76
+ else
77
+ async { instant_output(Item.new(info: :error, content: "sorry this post can not be openned")) }
78
+ end
79
+ end
80
+ help :open, 'open a post in browser', ':open [code]'
81
+
82
+ command :comment do |content|
83
+ content = content.split(" ")
84
+ post_code = "$#{content.first}"
85
+ comment = content.tap{|c|c.shift}.join(' ')
86
+
87
+ item = post_code_reverse_map[post_code]
88
+ post_id = item.id if item.is_a?(Item)
89
+
90
+ async {
91
+ ret = facebook_comment(post_id, comment)
92
+ instant_output(Item.new(info: :info, content: 'comment success')) if ret
93
+ }
94
+ end
95
+ help :comment, 'comment to a post,', ':comment [code] [content]'
96
+
97
+ command :seen do |notif_code|
98
+ async {
99
+ ret = facebook_set_seen(notif_code)
100
+ instant_output(Item.new(info: :info, content: 'unseen success')) if ret
101
+ }
102
+ end
103
+
104
+ command :view_raw do |post_code|
105
+ post_code = "$#{post_code}"
106
+ item = post_code_reverse_map[post_code]
107
+
108
+ print JSON.pretty_generate(item.raw)
109
+ puts ""
110
+ end
111
+ help :view_raw, "view raw json output of a post", ":view_raw [post_code]"
112
+
113
+ command :view_img do |post_code|
114
+ if config[:enable_img_view]
115
+ post_code = "$#{post_code}"
116
+ item = post_code_reverse_map[post_code]
117
+
118
+ if item.data.picture
119
+ view_img(item.data.picture)
120
+ else
121
+ instant_output(Item.new(info: :error, content: "this post has no image link"))
122
+ end
123
+ else
124
+ instant_output(Item.new(info: :error, content: "use facy -enable_img_view to enable image viewer"))
125
+ end
126
+ end
127
+
128
+ command :view_comments do |post_code|
129
+ post_code = "$#{post_code}"
130
+ item = post_code_reverse_map[post_code]
131
+ comments = item.data.comments
132
+
133
+ unless comments.empty?
134
+ comments.each do |cm|
135
+ instant_output(Item.new(info: :comment, from: cm["from"]["name"], message: cm["message"]))
136
+ end
137
+ end
138
+ end
139
+ help :view_comments, "view a comment from a post", ":view_comments [code]"
140
+
141
+ command :view_likes do |post_code|
142
+ post_code = "$#{post_code}"
143
+ item = post_code_reverse_map[post_code]
144
+ likes = item.data.likes
145
+ unless likes.empty?
146
+ likes.each do |lk|
147
+ instant_output(Item.new(info: :like, from: lk["name"]))
148
+ end
149
+ end
150
+ end
151
+
152
+ command :dump_log do
153
+ if config[:debug_log]
154
+ dump_log
155
+ instant_output(Item.new(info: :info, content: "dump log success to #{log_file}"))
156
+ else
157
+ instant_output(Item.new(
158
+ info: :info,
159
+ content: "you need to start $facy -debug option to enable log"
160
+ ))
161
+ end
162
+ end
163
+ help :dump_log, "dump debug log to file", ":dump_log"
164
+
165
+ command :commands do
166
+ helps.each do |help|
167
+ puts ":#{help[:target].to_s.colorize(38,5,8)} #{help[:usage]}"
168
+ end
169
+ end
170
+ help :commands, "list all available commands", ":commands"
171
+
172
+ completion_proc = proc {|s|
173
+ commands
174
+ .map{|c|c[:pattern]}
175
+ .map{|c|":#{c.to_s}"}
176
+ .grep(/^#{Regexp.escape(s)}/)
177
+ }
178
+ Readline.completion_proc = completion_proc
179
+ end
180
+ end
@@ -0,0 +1,91 @@
1
+ # coding: utf-8
2
+
3
+ module Facy
4
+ module Converter
5
+ #convert facebook graph return to Item#class
6
+ def graph2item(graph_item)
7
+ id = graph_item["id"]
8
+ if id =~ /^notif_(.+)$/
9
+ item = Item.new({
10
+ id: id,
11
+ info: :notification,
12
+ data: {
13
+ user: graph_item["from"]["name"],
14
+ content: graph_item["title"],
15
+ },
16
+ date: graph_item["created_time"],
17
+ })
18
+ else
19
+ content =
20
+ case graph_item["type"]
21
+ when "status"
22
+ if graph_item["message"].nil?
23
+ graph_item["story"]
24
+ else
25
+ graph_item["message"]
26
+ end
27
+ when "photo"
28
+ "share a photo: #{graph_item['message'] || graph_item['link']}"
29
+ when "checkin"
30
+ "checkin"
31
+ when "video"
32
+ "share a video: #{graph_item['message']}"
33
+ when "link"
34
+ "#{graph_item["message"]} #{graph_item["link"]}"
35
+ end
36
+
37
+ link =
38
+ (graph_item["actions"] && graph_item["actions"].first["link"]) ||
39
+ graph_item["link"]
40
+
41
+ likes = graph_item["likes"] && graph_item["likes"]["data"] || []
42
+ comments = graph_item["comments"] && graph_item["comments"]["data"] || []
43
+
44
+ like_count = likes.size
45
+ comment_count = comments.size
46
+
47
+ item = Item.new({
48
+ id: graph_item["id"],
49
+ info: :feed,
50
+ data: {
51
+ type: graph_item["type"],
52
+ user: graph_item["from"]["name"],
53
+ content: content,
54
+ picture: graph_item["picture"],
55
+ link: link,
56
+ like_count: like_count,
57
+ likes: likes,
58
+ comment_count: comment_count,
59
+ comments: comments,
60
+ date: DateTime.parse(graph_item["created_time"]),
61
+ },
62
+ date: graph_item["created_time"],
63
+ })
64
+ end
65
+ item.raw = graph_item
66
+ return item
67
+ end
68
+ end
69
+
70
+ extend Converter
71
+
72
+ class DeepStruct < OpenStruct
73
+ def initialize(hash=nil)
74
+ @table = {}
75
+ @hash_table = {}
76
+
77
+ if hash
78
+ hash.each do |k,v|
79
+ @table[k.to_sym] = (v.is_a?(Hash) ? self.class.new(v) : v)
80
+ @hash_table[k.to_sym] = v
81
+ new_ostruct_member(k)
82
+ end
83
+ end
84
+ end
85
+
86
+ def to_h
87
+ @hash_table
88
+ end
89
+ end
90
+ class Item < DeepStruct; end
91
+ end