fuck_facebook 0.3.0 → 0.5.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 9f15615d0c24e530547c2a40e4509d434bc25578dde17737a5b8d8ef5fe2e68f
4
- data.tar.gz: e3c8a9d379b9df92d0d986bfb1dba35846779d32d4cf1bbf16ae39d1f778fae4
3
+ metadata.gz: 26fe62245cbbcf826c49ee9f89fa3d889ebbb27a662c6076777a17ab181b8715
4
+ data.tar.gz: 59ddf6a1f3450188862019d37e7e75cab558c4948b3be3a1e08997318a108505
5
5
  SHA512:
6
- metadata.gz: cffa79b7c7b58717a8507ba129668db846b40e6682621527b7799665d4fa74a5032a27ef471da20659ee01cd57662e82d85f76aff5b01e43a547d638e0c70374
7
- data.tar.gz: 4acc110f1bb5e7115b28a429594a5fc8459f402fcffe88391a7189687791d677e857117049227d656d977c00b5daac88b4bded2780b1044b81fdce8cc603f0e6
6
+ metadata.gz: b51a6b441c836d9073bbb7312238beee8f902e48b16a87d4e84723db31f661e31a2adb180792e8c0c51020373b43ed67b6afbc4736bd522391a5cbe1cf8890f3
7
+ data.tar.gz: 7d11525734de217266e14b3b49adb8b177adfe8b9d50a20bcb19aea3929029c701fc9bac9188a1a5b223f828fb4a4a57e642b45de074b10abd5b5c01ddb9ea85
data/.gitignore CHANGED
@@ -11,3 +11,5 @@
11
11
  .rspec_status
12
12
 
13
13
  *.gem
14
+
15
+ fuck_facebook_error*.png
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- fuck_facebook (0.2.1)
4
+ fuck_facebook (0.5.1)
5
5
  activesupport (~> 6.1)
6
6
  highline (~> 2.0)
7
7
  mail (~> 2.7)
data/README.md CHANGED
@@ -26,6 +26,9 @@ This way if you have emails going out for new messages, you won't get notified f
26
26
  Here's a complete config file along with an explanation of each option:
27
27
 
28
28
  ```yaml
29
+ errors:
30
+ min_minutes_between_reports: 0 # Only report error if one has not occured in the past X minutes
31
+ include_screenshot: false # Generates a screenshot with the error report
29
32
  smtp:
30
33
  from_email: sender@example.com
31
34
  to_email: receiver@example.com
@@ -36,6 +39,8 @@ smtp:
36
39
  authentication: plain
37
40
  ```
38
41
 
42
+ Place this file in `~/.local/share/fuck-facebook/config.yaml`
43
+
39
44
  These options can be passed as environment variables, by:
40
45
  * Joining the keys with `_`
41
46
  * Capitalizing the entire string
data/bin/fuck-facebook CHANGED
@@ -7,59 +7,23 @@ require_relative '../src/facebook_connection'
7
7
  require_relative '../src/config'
8
8
  require_relative '../src/initializers/mail_initializer'
9
9
  require_relative '../src/senders'
10
-
11
- options = {
12
- headless: true,
13
- clear_cookies: false,
14
- unread_messages: false,
15
- messages: false,
16
- sender: 'stdout'
17
- }
18
-
19
- OptionParser.new do |opts|
20
- opts.banner = 'Usage: fuck-facebook.rb [options]'
21
-
22
- opts.on('-h', '--[no-]headless', 'Run in a headless browser') do |v|
23
- options[:headless] = v
24
- end
25
-
26
- opts.on('--clear-cookies') do |v|
27
- options[:clear_cookies] = v
28
- end
29
-
30
- opts.on('--unread-messages') do |v|
31
- options[:unread_messages] = v
32
- end
33
-
34
- opts.on('--messages') do |v|
35
- options[:messages] = v
36
- end
37
-
38
- opts.on('--login') do |v|
39
- options[:login] = v
40
- end
41
-
42
- opts.on('--sender=SENDER') do |sender|
43
- options[:sender] = sender
44
- end
45
- end.parse!
46
-
47
- facebook_connection = FacebookConnection.new(headless: options[:headless])
48
-
49
- facebook_connection.cookie_handler.clear! if options[:clear_cookies]
50
-
51
- facebook_connection.login if options[:login]
52
-
53
- messages =
54
- if options[:unread_messages]
55
- facebook_connection.message_handler.unread
56
- elsif options[:messages]
57
- facebook_connection.message_handler.messages
58
- else
59
- []
60
- end
61
-
62
- sender = Senders.by_name(options[:sender])
63
- sender.send_messages(messages)
64
-
65
- facebook_connection.close
10
+ require_relative '../src/args_parser'
11
+ require_relative '../src/message_sender'
12
+ require_relative '../src/error_reporter'
13
+
14
+ options = ArgsParser.parse_args
15
+ facebook_connection = nil
16
+
17
+ begin
18
+ facebook_connection = FacebookConnection.new(headless: options[:headless])
19
+ raise 'Error triggered by --simulate-error flag' if options[:simulate_error]
20
+
21
+ facebook_connection.cookie_handler.clear! if options[:clear_cookies]
22
+ facebook_connection.login if options[:login]
23
+ message_sender = MessageSender.new(options[:sender], facebook_connection)
24
+ message_sender.send_unread_messages if options[:unread_messages]
25
+ message_sender.send_messages if options[:messages]
26
+ facebook_connection.close
27
+ rescue StandardError => e
28
+ ErrorReporter.report_error(options[:sender], e, facebook_connection: facebook_connection)
29
+ end
@@ -1,3 +1,3 @@
1
1
  module FuckFacebook
2
- VERSION = '0.3.0'.freeze
2
+ VERSION = '0.5.1'.freeze
3
3
  end
@@ -0,0 +1,82 @@
1
+ class ArgsParser
2
+ DEFAULT_OPTIONS = {
3
+ headless: true,
4
+ clear_cookies: false,
5
+ unread_messages: false,
6
+ messages: false,
7
+ sender: 'stdout',
8
+ simulate_error: false
9
+ }.freeze
10
+
11
+ AVAILABLE_OPTIONS = [
12
+ {
13
+ short: '-h',
14
+ long: '--[no-]headless',
15
+ message: 'Run in a headless browser',
16
+ option: :headless
17
+ },
18
+ {
19
+ short: nil,
20
+ long: '--clear-cookies',
21
+ message: 'Clears all cookies',
22
+ option: :clear_cookies
23
+ },
24
+ {
25
+ short: nil,
26
+ long: '--unread-messages',
27
+ message: 'Outputs all unread messages sent since the last check',
28
+ option: :unread_messages
29
+ },
30
+ {
31
+ short: nil,
32
+ long: '--messages',
33
+ message: 'Outputs all messages sent since the last check',
34
+ option: :messages
35
+ },
36
+ {
37
+ short: nil,
38
+ long: '--login',
39
+ message: 'Prompts for details to login to Facebook account',
40
+ option: :login
41
+ },
42
+ {
43
+ short: nil,
44
+ long: '--sender=SENDER',
45
+ message: 'Send results to either stdout or email',
46
+ option: :sender
47
+ },
48
+ {
49
+ short: nil,
50
+ long: '--simulate-error',
51
+ message: 'Simulates an error so you can see how it will be outputted',
52
+ option: :simulate_error
53
+ }
54
+ ].freeze
55
+
56
+ def self.parse_args
57
+ passed_options = DEFAULT_OPTIONS.dup
58
+
59
+ OptionParser.new do |opts|
60
+ generate_banner(opts)
61
+
62
+ AVAILABLE_OPTIONS.each do |available_option|
63
+ parser_for_available_option(opts, available_option, passed_options)
64
+ end
65
+ end.parse!
66
+
67
+ passed_options
68
+ end
69
+
70
+ private_class_method def self.generate_banner(opts)
71
+ opts.banner = 'Usage: fuck-facebook.rb [options]'
72
+ end
73
+
74
+ private_class_method def self.parser_for_available_option(opts, available_option, passed_options)
75
+ args = [available_option[:long], available_option[:message]]
76
+ args = [available_option[:short]] + args if available_option[:short]
77
+
78
+ opts.on(*args) do |v|
79
+ passed_options[available_option[:option]] = v
80
+ end
81
+ end
82
+ end
data/src/config.rb CHANGED
@@ -3,15 +3,16 @@ require 'yaml'
3
3
  class Config
4
4
  CONFIG_FILE_PATH = "#{ENV['HOME']}/.local/share/fuck-facebook/config.yaml".freeze
5
5
 
6
- def self.option(*path)
6
+ def self.option(*path, default: nil, type: nil)
7
7
  env_var = "FF_#{path.join('_').upcase}"
8
- return ENV[env_var] if ENV[env_var]
9
-
10
8
  path_strings = path.map(&:to_s)
11
- config.dig(*path_strings)
12
- end
13
9
 
14
- private
10
+ value = config.dig(*path_strings)
11
+ value = ENV[env_var] if ENV[env_var]
12
+ value = default if value.nil?
13
+
14
+ cast_value_to_type(value, type)
15
+ end
15
16
 
16
17
  def self.config
17
18
  create_config_file_if_not_exists!
@@ -19,9 +20,26 @@ class Config
19
20
  YAML.load_file(CONFIG_FILE_PATH)
20
21
  end
21
22
 
22
- def self.create_config_file_if_not_exists!
23
+ private_class_method def self.create_config_file_if_not_exists!
23
24
  dirname = File.dirname(CONFIG_FILE_PATH)
24
25
  FileUtils.mkdir_p(dirname) unless File.directory?(dirname)
25
26
  File.write(CONFIG_FILE_PATH, '{}') unless File.exist?(CONFIG_FILE_PATH)
26
27
  end
28
+
29
+ private_class_method def self.cast_value_to_type(value, type)
30
+ case type
31
+ when :boolean
32
+ cast_value_to_boolean(value)
33
+ when :float
34
+ value.to_f
35
+ end
36
+ end
37
+
38
+ private_class_method def self.cast_value_to_boolean(value)
39
+ if [true, false].include?(value)
40
+ value
41
+ elsif value.is_a?(String)
42
+ value == 'true'
43
+ end
44
+ end
27
45
  end
@@ -0,0 +1,44 @@
1
+ class ErrorReporter
2
+ def self.report_error(sender_name, error, facebook_connection: nil)
3
+ raise error unless report_error?
4
+
5
+ Storage.set(:last_error_reported_time, Time.now)
6
+
7
+ screenshot = include_screenshot?(facebook_connection) ? create_screenshot(facebook_connection) : nil
8
+
9
+ Senders.by_name(sender_name).send_error(error, screenshot: screenshot)
10
+ raise error
11
+ end
12
+
13
+ private_class_method def self.include_screenshot?(facebook_connection)
14
+ include_screenshot_config = Config.option(
15
+ :errors,
16
+ :include_screenshot,
17
+ default: false,
18
+ type: :boolean
19
+ )
20
+
21
+ include_screenshot_config && facebook_connection.present?
22
+ end
23
+
24
+ private_class_method def self.create_screenshot(facebook_connection)
25
+ facebook_connection.driver.screenshot_as(:png)
26
+ rescue StandardError
27
+ nil
28
+ end
29
+
30
+ private_class_method def self.report_error?
31
+ min_minutes_between_reports = Config.option(
32
+ :errors,
33
+ :min_minutes_between_reports,
34
+ default: 0,
35
+ type: :float
36
+ )
37
+
38
+ last_error_reported_time = Storage.get(:last_error_reported_time, default: Time.new(2000))
39
+
40
+ next_report_time = last_error_reported_time + min_minutes_between_reports.minutes
41
+
42
+ Time.now > next_report_time
43
+ end
44
+ end
@@ -53,13 +53,12 @@ class MessageHandler
53
53
  end
54
54
 
55
55
  def messages_after_last_message_time(messages)
56
- last_message_time = Storage.get(:last_message_time, default: Time.new(2004, 2, 4))
56
+ last_message_check_time = Storage.get(:last_message_check_time, default: Time.new(2004, 2, 4))
57
+ last_check_time_with_buffer = last_message_check_time - 5.minutes
57
58
 
58
- messages_to_return = messages.select { _1.timestamp > last_message_time }
59
+ messages_to_return = messages.select { _1.timestamp > last_check_time_with_buffer }
59
60
 
60
- last_message_time = messages.map(&:timestamp).max
61
-
62
- Storage.set(:last_message_time, last_message_time)
61
+ Storage.set(:last_message_check_time, Time.now)
63
62
 
64
63
  messages_to_return
65
64
  end
@@ -0,0 +1,25 @@
1
+ class MessageSender
2
+ attr_accessor :sender_name, :facebook_connection
3
+
4
+ def initialize(sender_name, facebook_connection)
5
+ @sender_name = sender_name
6
+ @facebook_connection = facebook_connection
7
+ end
8
+
9
+ def send_unread_messages
10
+ messages = facebook_connection.message_handler.unread
11
+ send_array_of_messages(messages)
12
+ end
13
+
14
+ def send_messages
15
+ messages = facebook_connection.message_handler.messages
16
+ send_array_of_messages(messages)
17
+ end
18
+
19
+ private
20
+
21
+ def send_array_of_messages(messages)
22
+ sender = Senders.by_name(sender_name)
23
+ sender.send_messages(messages)
24
+ end
25
+ end
data/src/senders/email.rb CHANGED
@@ -10,5 +10,15 @@ module Senders
10
10
  end
11
11
  end
12
12
  end
13
+
14
+ def self.send_error(error, screenshot: nil)
15
+ Mail.deliver do
16
+ from Config.option(:smtp, :from_email)
17
+ to Config.option(:smtp, :to_email)
18
+ subject 'Error occurred during Fuck Facebook command'
19
+ body error.full_message(highlight: false)
20
+ add_file filename: 'error_screenshot.png', content: screenshot if screenshot
21
+ end
22
+ end
13
23
  end
14
24
  end
@@ -5,5 +5,14 @@ module Senders
5
5
  puts message
6
6
  end
7
7
  end
8
+
9
+ def self.send_error(error, screenshot: nil)
10
+ puts error
11
+ return if screenshot.nil?
12
+
13
+ filename = "fuck_facebook_error_#{Time.now.iso8601}.png"
14
+ File.write(filename, screenshot)
15
+ puts "Screenshot of error page saved as #{filename}"
16
+ end
8
17
  end
9
18
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: fuck_facebook
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.0
4
+ version: 0.5.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Keeyan Nejad
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2021-12-23 00:00:00.000000000 Z
11
+ date: 2021-12-25 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport
@@ -94,13 +94,16 @@ files:
94
94
  - fuck_facebook.gemspec
95
95
  - lib/fuck_facebook.rb
96
96
  - lib/fuck_facebook/version.rb
97
+ - src/args_parser.rb
97
98
  - src/authenticator.rb
98
99
  - src/config.rb
99
100
  - src/cookie_handler.rb
101
+ - src/error_reporter.rb
100
102
  - src/facebook_connection.rb
101
103
  - src/fb_duration.rb
102
104
  - src/initializers/mail_initializer.rb
103
105
  - src/message_handler.rb
106
+ - src/message_sender.rb
104
107
  - src/models/message.rb
105
108
  - src/models/message_thread.rb
106
109
  - src/models/user.rb