chatty_crow 1.2.1

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.
Files changed (44) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGELOG +0 -0
  3. data/Gemfile +3 -0
  4. data/Guardfile +5 -0
  5. data/INSTALL +0 -0
  6. data/LICENSE +201 -0
  7. data/README.textile +183 -0
  8. data/Rakefile +14 -0
  9. data/chatty_crow.gemspec +37 -0
  10. data/lib/chatty-crow.rb +1 -0
  11. data/lib/chatty_crow.rb +119 -0
  12. data/lib/chatty_crow/action_mailer_extension.rb +31 -0
  13. data/lib/chatty_crow/config.rb +64 -0
  14. data/lib/chatty_crow/contacts_request.rb +79 -0
  15. data/lib/chatty_crow/error.rb +26 -0
  16. data/lib/chatty_crow/error/channel_not_found.rb +6 -0
  17. data/lib/chatty_crow/error/invalid_attributes.rb +21 -0
  18. data/lib/chatty_crow/error/invalid_return.rb +7 -0
  19. data/lib/chatty_crow/error/unauthorized_request.rb +6 -0
  20. data/lib/chatty_crow/notification_request.rb +54 -0
  21. data/lib/chatty_crow/railtie.rb +10 -0
  22. data/lib/chatty_crow/request.rb +53 -0
  23. data/lib/chatty_crow/request/android.rb +23 -0
  24. data/lib/chatty_crow/request/ios.rb +16 -0
  25. data/lib/chatty_crow/request/jabber.rb +17 -0
  26. data/lib/chatty_crow/request/mail.rb +264 -0
  27. data/lib/chatty_crow/request/skype.rb +17 -0
  28. data/lib/chatty_crow/request/sms.rb +17 -0
  29. data/lib/chatty_crow/response.rb +34 -0
  30. data/lib/chatty_crow/response/contacts_add.rb +43 -0
  31. data/lib/chatty_crow/response/contacts_remove.rb +35 -0
  32. data/lib/chatty_crow/response/notification.rb +19 -0
  33. data/lib/chatty_crow/version.rb +4 -0
  34. data/lib/chattycrow.rb +1 -0
  35. data/test/android_test.rb +57 -0
  36. data/test/attachment_test.rb +13 -0
  37. data/test/base_parser_test.rb +125 -0
  38. data/test/configuration_test.rb +37 -0
  39. data/test/contacts_test.rb +90 -0
  40. data/test/factories/stewie.jpeg +0 -0
  41. data/test/helper.rb +63 -0
  42. data/test/mail_test.rb +62 -0
  43. data/test/response_test.rb +33 -0
  44. metadata +251 -0
@@ -0,0 +1 @@
1
+ require File.dirname(__FILE__) + '/chatty_crow.rb'
@@ -0,0 +1,119 @@
1
+ require 'rest-client'
2
+ require 'chatty_crow/config'
3
+ require 'chatty_crow/error'
4
+ require 'chatty_crow/response'
5
+ require 'chatty_crow/request'
6
+ require 'chatty_crow/request/android'
7
+ require 'chatty_crow/request/ios'
8
+ require 'chatty_crow/request/jabber'
9
+ require 'chatty_crow/request/mail'
10
+ require 'chatty_crow/request/skype'
11
+ require 'chatty_crow/request/sms'
12
+ require 'chatty_crow/notification_request'
13
+ require 'chatty_crow/contacts_request'
14
+
15
+ # Load Rails Components
16
+ #
17
+ # * Railitie - load config/chatty_crow.yml settings!
18
+ # * ActionMailer - extension to easy send mails via cc
19
+ if defined?(::Rails) && ::Rails::VERSION::MAJOR >= 3
20
+ require 'chatty_crow/railtie'
21
+ require 'chatty_crow/action_mailer_extension'
22
+ end
23
+
24
+ # ChattyCrow global default module entry point to easy send notifications
25
+ #
26
+ # # Mail
27
+ # response = ChattyCrow.send_mail
28
+ #
29
+ # # Create mail & send by .deliver!
30
+ # mail = ChattyCrow.create_mail subject: 'test'
31
+ #
32
+ # # IOS
33
+ # response = ChattyCrow.send_ios data: 'news'
34
+ #
35
+ # # Android
36
+ # response = ChattyCrow.send_android data: 'news', contats: [ 'test1' ]
37
+ #
38
+ # # Skype
39
+ # response = ChattyCrow.send_skype data: 'news'
40
+ #
41
+ # # Jabber
42
+ # response = ChattyCrow.send_android data: 'news'
43
+ #
44
+ # # Sms
45
+ # response = ChattyCrow.send_sms 'news'
46
+ #
47
+ # Or work with contacts
48
+ #
49
+ # # Get all contacts
50
+ # response = ChattyCrow.get_contacts
51
+ #
52
+ # # Add contact
53
+ # response = ChattyCrow.add_contacts 'test1', 'test2'
54
+ #
55
+ # # Remove contacts
56
+ # response = ChattyCrow.remove_contacts 'test1', 'test2'
57
+ module ChattyCrow
58
+ def self.send_mail(*args)
59
+ NotificationRequest.send(Request::Mail, *args)
60
+ end
61
+
62
+ def self.create_mail(*args)
63
+ Request::Mail.new(*args)
64
+ end
65
+
66
+ def self.send_ios(*args)
67
+ NotificationRequest.send(Request::Ios, *args)
68
+ end
69
+
70
+ def self.send_android(*args)
71
+ NotificationRequest.send(Request::Android, *args)
72
+ end
73
+
74
+ def self.send_skype(*args)
75
+ NotificationRequest.send(Request::Skype, *args)
76
+ end
77
+
78
+ def self.send_jabber(*args)
79
+ NotificationRequest.send(Request::Jabber, *args)
80
+ end
81
+
82
+ def self.send_sms(*args)
83
+ NotificationRequest.send(Request::Sms, *args)
84
+ end
85
+
86
+ def self.get_contacts(options = {})
87
+ ContactsRequest.get(options)
88
+ end
89
+
90
+ def self.add_contacts(*args)
91
+ ContactsRequest.add(*args)
92
+ end
93
+
94
+ def self.remove_contacts(*args)
95
+ ContactsRequest.remove(*args)
96
+ end
97
+
98
+ # Helper method for wrapping non-array objects
99
+ # @param object [Object] Something
100
+ # @return [Array] Array
101
+ def self.wrap(object)
102
+ if object.nil?
103
+ []
104
+ elsif object.respond_to?(:to_ary)
105
+ object.to_ary || [object]
106
+ else
107
+ [object]
108
+ end
109
+ end
110
+
111
+ # Helper method for extrat options from array!
112
+ def self.extract_options!(args)
113
+ if args.last.is_a?(Hash) && args.last.instance_of?(Hash)
114
+ args.pop
115
+ else
116
+ {}
117
+ end
118
+ end
119
+ end
@@ -0,0 +1,31 @@
1
+ module ChattyCrow
2
+ # Action Mailer Rails Extension to easy use
3
+ # ChattyCrow without modification actuall code
4
+ module ActionMailerExtension
5
+ def self.included(base)
6
+ base.class_eval do
7
+ class << self
8
+ attr_accessor :cc_channel
9
+ end
10
+
11
+ # Instance mail request
12
+ attr_accessor :cc_mail
13
+
14
+ # Override message with chatty crow message
15
+ def message
16
+ @cc_mail ||= ChattyCrow::Request::Mail.new(self.class, @_message)
17
+ end
18
+ end
19
+ base.extend(ClassMethods)
20
+ end
21
+
22
+ # Class methods
23
+ module ClassMethods
24
+ # Set other than default channel
25
+ # @param channel [String] Different channel
26
+ def chatty_crow_channel(channel)
27
+ self.cc_channel = channel
28
+ end
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,64 @@
1
+ require 'yaml'
2
+
3
+ # Configuration module
4
+ module ChattyCrow
5
+ def self.configure
6
+ yield configuration
7
+ end
8
+
9
+ def self.configuration
10
+ @configuration ||= Configuration.new
11
+ end
12
+
13
+ def self.configure_from_yaml(path)
14
+ yaml = YAML.load_file(path)[Rails.env]
15
+ return unless yaml
16
+ configuration.host = yaml['host']
17
+ configuration.token = yaml['token']
18
+ configuration.default_channel = yaml['default_channel']
19
+ end
20
+
21
+ def self.configure_from_rails
22
+ path = ::Rails.root.join('config', 'chatty_crow.yml')
23
+ configure_from_yaml(path) if File.exist?(path)
24
+ end
25
+
26
+ def self.default_headers(channel, token)
27
+ {
28
+ 'Token' => token || configuration.token,
29
+ 'Channel' => channel || configuration.default_channel,
30
+ 'Accept' => 'application/json'
31
+ }
32
+ end
33
+
34
+ # Configuration class
35
+ class Configuration
36
+ # Server settings
37
+ # Default https://chatty-crow.com (https for secure connection)
38
+ attr_accessor :host
39
+
40
+ # User and channel settings
41
+ attr_accessor :token, :default_channel
42
+
43
+ # Open and read timeouts
44
+ attr_accessor :http_open_timeout
45
+ attr_accessor :http_read_timeout
46
+
47
+ # Call urls
48
+ attr_reader :notification_url, :contacts_url
49
+
50
+ def initialize
51
+ self.host = 'https://chatty-crow.com/api/v1/'
52
+ @token = nil
53
+ @default_channel = nil
54
+ @http_open_timeout = 2
55
+ @http_read_timeout = 5
56
+ end
57
+
58
+ def host=(s)
59
+ @host = s
60
+ @notification_url = s + (s[-1] == '/' ? '' : '/') + 'notification'
61
+ @contacts_url = s + (s[-1] == '/' ? '' : '/') + 'contacts'
62
+ end
63
+ end
64
+ end
@@ -0,0 +1,79 @@
1
+ require 'restclient'
2
+
3
+ # Send request to contacts chattycrow API
4
+ module ChattyCrow
5
+ # Module contains request for contacts
6
+ module ContactsRequest
7
+ # Add contact request
8
+ # @params args [Arguments]
9
+ # @return [Response::ContactsAdd] Instance
10
+ def self.add(*args)
11
+ # Send contact request
12
+ send_contact_request(Response::ContactsAdd, :post, *args)
13
+ end
14
+
15
+ # Remove contact request
16
+ # @params args [Arguments]
17
+ # @return [Response::ContactsRemove] Instance
18
+ def self.remove(*args)
19
+ # Send contact request
20
+ send_contact_request(Response::ContactsRemove, :delete, *args)
21
+ end
22
+
23
+ # Return default contacts url
24
+ def self.contacts_url
25
+ ChattyCrow.configuration.contacts_url
26
+ end
27
+
28
+ # Method prepare data from add/remove contact
29
+ # @params klass [Class] Initializable class for response
30
+ # @params method [String] HTTP method
31
+ # @params *ąrgs [Arguments]
32
+ def self.send_contact_request(klass, method, *args)
33
+ # Parse options
34
+ options = ChattyCrow.extract_options!(args)
35
+
36
+ # Invalid argument
37
+ fail ::ArgumentError if args.length == 0
38
+
39
+ # Set as payload
40
+ options[:payload] = { contacts: args }
41
+
42
+ # Send command
43
+ execute(options.merge(method: method)) do |response|
44
+ klass.new response
45
+ end
46
+ end
47
+
48
+ # Method actually sends created request to server
49
+ #
50
+ # @param options [Hash] Options for request
51
+ # @param resp_block [Block] Block what to do with sucessfull response
52
+ # @return [Object] Block given execute or RestClient::Response
53
+ def self.execute(options, &resp_block)
54
+ # Prepare options (url + headers)
55
+ options[:url] = contacts_url
56
+ options[:headers] = ChattyCrow.default_headers(options.delete(:channel), options.delete(:token))
57
+
58
+ # Send request
59
+ RestClient::Request.execute(options) do |response, request, result, &block|
60
+ case response.code
61
+ when 200, 201
62
+ if block_given?
63
+ resp_block.call(response)
64
+ else
65
+ response
66
+ end
67
+ when 301, 302, 307
68
+ response.follow_redirection(request, result, &block)
69
+ when 401
70
+ fail Error::UnauthorizedRequest, response
71
+ when 404
72
+ fail Error::ChannelNotFound, response
73
+ else
74
+ fail Error::InvalidReturn, response
75
+ end
76
+ end
77
+ end
78
+ end
79
+ end
@@ -0,0 +1,26 @@
1
+ # Parent of all ChattyCrow errors
2
+ module ChattyCrow
3
+ module Error
4
+ # Parent of all chatty crow error
5
+ # designed to accept RestClient::Response
6
+ class ChattyCrowError < StandardError
7
+ # Json parsed response body
8
+ attr_accessor :response_body, :response
9
+
10
+ def initialize(response = nil)
11
+ @response = response
12
+ if @response && @response.body
13
+ @response_body = JSON.parse(@response.body)
14
+ super(@response_body['msg']) if @response_body['msg']
15
+ end
16
+ rescue JSON::ParserError
17
+ @response_body = nil
18
+ end
19
+ end
20
+ end
21
+ end
22
+
23
+ Dir[File.dirname(__FILE__) + '/error/*.rb'].sort.each do |path|
24
+ filename = File.basename(path)
25
+ require "chatty_crow/error/#{filename}"
26
+ end
@@ -0,0 +1,6 @@
1
+ module ChattyCrow
2
+ module Error
3
+ class ChannelNotFound < ChattyCrowError
4
+ end
5
+ end
6
+ end
@@ -0,0 +1,21 @@
1
+ module ChattyCrow
2
+ module Error
3
+ # Invalid attributes exception
4
+ # throws when some of attributes is missing
5
+ class InvalidAttributes < ChattyCrowError
6
+ # List of invalid attributes
7
+ attr_accessor :attributes
8
+
9
+ def initialize(response = nil)
10
+ super response
11
+
12
+ # Get parameters from response
13
+ if @response_body && @response_body['parameters']
14
+ @attributes = @response_body['parameters']
15
+ else
16
+ @attributes = []
17
+ end
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,7 @@
1
+ module ChattyCrow
2
+ module Error
3
+ # Something weird happend!
4
+ class InvalidReturn < ChattyCrowError
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,6 @@
1
+ module ChattyCrow
2
+ module Error
3
+ class UnauthorizedRequest < ChattyCrowError
4
+ end
5
+ end
6
+ end
@@ -0,0 +1,54 @@
1
+ require 'rest_client'
2
+
3
+ module ChattyCrow
4
+ # Notification request
5
+ # use for send different kind
6
+ # of notifications
7
+ class NotificationRequest
8
+ # Prepare and send request
9
+ # @param klass [Object] Notification specific class
10
+ # @param args [Array] Arguments
11
+ def self.send(klass, *args)
12
+ instance = klass.new(*args)
13
+ execute(instance)
14
+ end
15
+
16
+ # :nodoc:
17
+ def self.notification_url
18
+ ChattyCrow.configuration.notification_url
19
+ end
20
+
21
+ # Method actually sends created request to server
22
+ # @param instance [Request::Base] Request children class
23
+ # @param raise_errors [Boolean] Raise errors if error?
24
+ # @return [Object] Raise an exception or return Response::Notification
25
+ def self.execute(instance, raise_errors = true)
26
+ options = instance.to_json.merge(url: notification_url, method: :post)
27
+
28
+ RestClient::Request.execute(options) do |response, request, result, &block|
29
+ begin
30
+ case response.code
31
+ when 200, 201
32
+ Response::Notification.new response
33
+ when 301, 302, 307
34
+ response.follow_redirection(request, result, &block)
35
+ when 400
36
+ fail Error::InvalidAttributes, response
37
+ when 401
38
+ fail Error::UnauthorizedRequest, response
39
+ when 404
40
+ fail Error::ChannelNotFound, response
41
+ else
42
+ fail Error::InvalidReturn, response
43
+ end
44
+ rescue => e
45
+ if raise_errors
46
+ raise e
47
+ else
48
+ false
49
+ end
50
+ end
51
+ end # RestClient
52
+ end # Execute
53
+ end
54
+ end
@@ -0,0 +1,10 @@
1
+ module ChattyCrow
2
+ # ChattyCrow rails integration
3
+ class Railtie < ::Rails::Railtie
4
+ initializer 'chatty_crow.initialize_from_rails' do
5
+ config.after_initialize do
6
+ ChattyCrow.configure_from_rails
7
+ end
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,53 @@
1
+ module ChattyCrow
2
+ module Request
3
+ # Parent of all requests to ChattyCrow API
4
+ class BaseRequest
5
+ # Methods
6
+ attr_accessor :contacts, :payload, :channel, :token
7
+
8
+ # Intialize options!
9
+ attr_accessor :arguments, :options, :arguments_flatten
10
+
11
+ # Intialize (almost everwhere called by super)
12
+ # @param args [Array] options for request
13
+ def initialize(*args)
14
+ # Error when attributes not exists!
15
+ fail ::ArgumentError if args.empty?
16
+
17
+ # Parse options and arguments
18
+ # Arguments can be simple message!
19
+ @options = ChattyCrow.extract_options!(args)
20
+ @arguments = args
21
+
22
+ # Create flatten arguments for (skype/android/sms.. requests)
23
+ @arguments_flatten = args.join(', ') if args.any?
24
+
25
+ # Recipients
26
+ @contacts = ChattyCrow.wrap(@options.delete(:contacts)).compact
27
+
28
+ # Channel
29
+ @channel = @options.delete(:channel)
30
+
31
+ # Token
32
+ @token = @options.delete(:token)
33
+ end
34
+
35
+ # Return chatty crow default headers for specific channel
36
+ def headers
37
+ ChattyCrow.default_headers(@channel, @token)
38
+ end
39
+
40
+ # Get request for send
41
+ # @return [Hash] Request
42
+ def to_json
43
+ {
44
+ payload: {
45
+ payload: payload,
46
+ contacts: @contacts
47
+ },
48
+ headers: headers
49
+ }
50
+ end
51
+ end
52
+ end
53
+ end