fuck_facebook 0.2.1 → 0.5.0

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: fd816f264c73ea38c4349c8110cade9787ae11f92de9b37ad8a1f6fbef9b2059
4
- data.tar.gz: e2862a3aee723788f459ab7b84acf84ca2b3bda8ef6176e51a1018915cb350d7
3
+ metadata.gz: 4444d134e1ae1d10b948ae6432691f99c1c22498aea2f0530359b0c93a1df967
4
+ data.tar.gz: b276c6b4a680c546b2b34366b5e28cd1af620ef7800ae7f2964bbded6235eff8
5
5
  SHA512:
6
- metadata.gz: aa5dfc850834b1ab4efd759eb853ac2bdc25c6a9cb739ee704b2e2182fc917fc43b85c504c75ad7394074f0549abd8e372906911a68da64ea0a4c78766d0d39b
7
- data.tar.gz: 8ebea4e69e013d5c2f7f7345755c5ed39768bdbcd231587ae06c64e196e718d2f57293ea9714c84cf61008bc104d05c1dfd90df7548c8eade979d76a5391f129
6
+ metadata.gz: 2e9a2254136c1886d20e7f164bbf1cf9d06d1a6191ed7522df717db580b6eea1b48f9ab5c9caebb9b84c75bc24f8467e0c92b30d5bae5f1131a99b7a6bb93b94
7
+ data.tar.gz: 5b930019d90be80fb751a487c2b71b0021278dc1952fd2a61baac57b7e88a4bcfc33be612699193bd6caeeb1c43a5fb0b7a231fce555d41c32e6d69a6cb93185
data/.gitignore CHANGED
@@ -11,3 +11,5 @@
11
11
  .rspec_status
12
12
 
13
13
  *.gem
14
+
15
+ fuck_facebook_error*.png
data/.ruby-version CHANGED
@@ -1 +1 @@
1
- 3.0.1
1
+ 3.0.2
data/CONTRIBUTING.md ADDED
@@ -0,0 +1,23 @@
1
+ # Developer Guide
2
+
3
+ ## Pushing a new version of the gem
4
+
5
+ **Note:** You must have been granted access to deploy new versions of the `fuck_facebook` gem
6
+
7
+ * Bump the version in `lib/fuck_facebook/version.rb`
8
+ * Build the gem with `gem build fuck_facebook.gemspec`
9
+ * Push the gem with `gem push fuck_facebook-VERSION.gem` replacing `VERSION` with the new version number
10
+
11
+ ## Pushing a new version of the Docker image
12
+
13
+ **Note:** You must have been granted access to deploy new versions of the `fuck_facebook` Docker image
14
+
15
+ * Build the image:
16
+
17
+ ```
18
+ docker build . -t keeyan/fuck_facebook:VERSION --build-arg version=VERSION
19
+ ```
20
+
21
+ Replace `VERSION` with the version number
22
+
23
+ * Push the image with `docker push keeyan/fuck_facebook:VERSION` replacing `VERSION` with the version number
data/Dockerfile ADDED
@@ -0,0 +1,15 @@
1
+ FROM ruby:3.0.2-bullseye
2
+
3
+ RUN apt-get update && apt-get install -y chromium-driver
4
+
5
+ RUN useradd --create-home --shell /bin/bash fuckfacebook
6
+
7
+ USER fuckfacebook
8
+ WORKDIR /home/fuckfacebook
9
+
10
+ RUN mkdir -p /home/fuckfacebook/.local/share/fuck-facebook
11
+ VOLUME /home/fuckfacebook/.local/share/fuck-facebook
12
+
13
+ ARG version
14
+ COPY fuck_facebook-$version.gem .
15
+ RUN gem install fuck_facebook-$version.gem
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- fuck_facebook (0.1.2)
4
+ fuck_facebook (0.4.1)
5
5
  activesupport (~> 6.1)
6
6
  highline (~> 2.0)
7
7
  mail (~> 2.7)
@@ -10,7 +10,7 @@ PATH
10
10
  GEM
11
11
  remote: https://rubygems.org/
12
12
  specs:
13
- activesupport (6.1.4)
13
+ activesupport (6.1.4.4)
14
14
  concurrent-ruby (~> 1.0, >= 1.0.2)
15
15
  i18n (>= 1.6, < 2)
16
16
  minitest (>= 5.1)
@@ -21,13 +21,13 @@ GEM
21
21
  coderay (1.1.3)
22
22
  concurrent-ruby (1.1.9)
23
23
  highline (2.0.3)
24
- i18n (1.8.10)
24
+ i18n (1.8.11)
25
25
  concurrent-ruby (~> 1.0)
26
26
  mail (2.7.1)
27
27
  mini_mime (>= 0.1.1)
28
28
  method_source (1.0.0)
29
- mini_mime (1.1.0)
30
- minitest (5.14.4)
29
+ mini_mime (1.1.2)
30
+ minitest (5.15.0)
31
31
  parallel (1.20.1)
32
32
  parser (3.0.1.1)
33
33
  ast (~> 2.4.1)
@@ -56,7 +56,7 @@ GEM
56
56
  tzinfo (2.0.4)
57
57
  concurrent-ruby (~> 1.0)
58
58
  unicode-display_width (2.0.0)
59
- zeitwerk (2.4.2)
59
+ zeitwerk (2.5.1)
60
60
 
61
61
  PLATFORMS
62
62
  ruby
@@ -67,4 +67,4 @@ DEPENDENCIES
67
67
  rubocop
68
68
 
69
69
  BUNDLED WITH
70
- 2.2.15
70
+ 2.2.22
data/README.md CHANGED
@@ -1,3 +1,51 @@
1
1
  # Fuck Facebook
2
2
 
3
3
  A collection of tools to help you use Facebook when you don't want to
4
+
5
+ ## Usage
6
+
7
+ Run `fuck-facebook --help` to get a list of options and explanations.
8
+
9
+ To get all unread messages (that haven't already been reported) run these commands:
10
+
11
+ ```
12
+ fuck-facebook --login
13
+ ```
14
+
15
+ You only need to login once
16
+
17
+ ```
18
+ fuck-facebook --unread-messages
19
+ ```
20
+
21
+ This will only show you unread messages that have been received since the last time you checked.
22
+ This way if you have emails going out for new messages, you won't get notified for the same message each time.
23
+
24
+ ## Config
25
+
26
+ Here's a complete config file along with an explanation of each option:
27
+
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
32
+ smtp:
33
+ from_email: sender@example.com
34
+ to_email: receiver@example.com
35
+ address: smtp.example.com
36
+ port: 587
37
+ user_name: some_user_name
38
+ password: 123456
39
+ authentication: plain
40
+ ```
41
+
42
+ Place this file in `~/.local/share/fuck-facebook/config.yaml`
43
+
44
+ These options can be passed as environment variables, by:
45
+ * Joining the keys with `_`
46
+ * Capitalizing the entire string
47
+ * Prefixing the key with `FF_`
48
+
49
+ For example the `smtp` `from_email` will become `FF_SMTP_FROM_EMAIL`
50
+
51
+ Environment variables take precedent over the config file.
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.2.1'.freeze
2
+ VERSION = '0.5.0'.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,12 +3,17 @@ 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)
7
+ env_var = "FF_#{path.join('_').upcase}"
8
+ return ENV[env_var] if ENV[env_var]
9
+
7
10
  path_strings = path.map(&:to_s)
8
- config.dig(*path_strings)
9
- end
11
+ value = config.dig(*path_strings)
10
12
 
11
- private
13
+ return value if value
14
+
15
+ default
16
+ end
12
17
 
13
18
  def self.config
14
19
  create_config_file_if_not_exists!
@@ -16,7 +21,7 @@ class Config
16
21
  YAML.load_file(CONFIG_FILE_PATH)
17
22
  end
18
23
 
19
- def self.create_config_file_if_not_exists!
24
+ private_class_method def self.create_config_file_if_not_exists!
20
25
  dirname = File.dirname(CONFIG_FILE_PATH)
21
26
  FileUtils.mkdir_p(dirname) unless File.directory?(dirname)
22
27
  File.write(CONFIG_FILE_PATH, '{}') unless File.exist?(CONFIG_FILE_PATH)
@@ -0,0 +1,32 @@
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
+ Config.option(:errors, :include_screenshot) && facebook_connection.present?
15
+ end
16
+
17
+ private_class_method def self.create_screenshot(facebook_connection)
18
+ facebook_connection.driver.screenshot_as(:png)
19
+ rescue StandardError
20
+ nil
21
+ end
22
+
23
+ private_class_method def self.report_error?
24
+ min_minutes_between_reports = Config.option(:errors, :min_minutes_between_reports, default: 0)
25
+
26
+ last_error_reported_time = Storage.get(:last_error_reported_time, default: Time.new(2000))
27
+
28
+ next_report_time = last_error_reported_time + min_minutes_between_reports.minutes
29
+
30
+ Time.now > next_report_time
31
+ end
32
+ end
@@ -31,6 +31,8 @@ class FacebookConnection
31
31
 
32
32
  options = Selenium::WebDriver::Chrome::Options.new
33
33
  options.add_argument('--disable-notifications')
34
+ options.add_argument('--no-sandbox')
35
+ options.add_argument('--disable-dev-shm-usage')
34
36
  options.add_argument('--headless') if headless
35
37
  options.add_option('detach', true) unless headless
36
38
 
@@ -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.2.1
4
+ version: 0.5.0
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-11-13 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
@@ -81,6 +81,8 @@ files:
81
81
  - ".rubocop.yml"
82
82
  - ".ruby-version"
83
83
  - CHANGELOG.md
84
+ - CONTRIBUTING.md
85
+ - Dockerfile
84
86
  - Gemfile
85
87
  - Gemfile.lock
86
88
  - LICENSE.txt
@@ -92,13 +94,16 @@ files:
92
94
  - fuck_facebook.gemspec
93
95
  - lib/fuck_facebook.rb
94
96
  - lib/fuck_facebook/version.rb
97
+ - src/args_parser.rb
95
98
  - src/authenticator.rb
96
99
  - src/config.rb
97
100
  - src/cookie_handler.rb
101
+ - src/error_reporter.rb
98
102
  - src/facebook_connection.rb
99
103
  - src/fb_duration.rb
100
104
  - src/initializers/mail_initializer.rb
101
105
  - src/message_handler.rb
106
+ - src/message_sender.rb
102
107
  - src/models/message.rb
103
108
  - src/models/message_thread.rb
104
109
  - src/models/user.rb
@@ -135,7 +140,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
135
140
  - !ruby/object:Gem::Version
136
141
  version: '0'
137
142
  requirements: []
138
- rubygems_version: 3.2.15
143
+ rubygems_version: 3.2.22
139
144
  signing_key:
140
145
  specification_version: 4
141
146
  summary: A collection of tools to help you use Facebook when you don't want to