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.
- checksums.yaml +7 -0
- data/CHANGELOG +0 -0
- data/Gemfile +3 -0
- data/Guardfile +5 -0
- data/INSTALL +0 -0
- data/LICENSE +201 -0
- data/README.textile +183 -0
- data/Rakefile +14 -0
- data/chatty_crow.gemspec +37 -0
- data/lib/chatty-crow.rb +1 -0
- data/lib/chatty_crow.rb +119 -0
- data/lib/chatty_crow/action_mailer_extension.rb +31 -0
- data/lib/chatty_crow/config.rb +64 -0
- data/lib/chatty_crow/contacts_request.rb +79 -0
- data/lib/chatty_crow/error.rb +26 -0
- data/lib/chatty_crow/error/channel_not_found.rb +6 -0
- data/lib/chatty_crow/error/invalid_attributes.rb +21 -0
- data/lib/chatty_crow/error/invalid_return.rb +7 -0
- data/lib/chatty_crow/error/unauthorized_request.rb +6 -0
- data/lib/chatty_crow/notification_request.rb +54 -0
- data/lib/chatty_crow/railtie.rb +10 -0
- data/lib/chatty_crow/request.rb +53 -0
- data/lib/chatty_crow/request/android.rb +23 -0
- data/lib/chatty_crow/request/ios.rb +16 -0
- data/lib/chatty_crow/request/jabber.rb +17 -0
- data/lib/chatty_crow/request/mail.rb +264 -0
- data/lib/chatty_crow/request/skype.rb +17 -0
- data/lib/chatty_crow/request/sms.rb +17 -0
- data/lib/chatty_crow/response.rb +34 -0
- data/lib/chatty_crow/response/contacts_add.rb +43 -0
- data/lib/chatty_crow/response/contacts_remove.rb +35 -0
- data/lib/chatty_crow/response/notification.rb +19 -0
- data/lib/chatty_crow/version.rb +4 -0
- data/lib/chattycrow.rb +1 -0
- data/test/android_test.rb +57 -0
- data/test/attachment_test.rb +13 -0
- data/test/base_parser_test.rb +125 -0
- data/test/configuration_test.rb +37 -0
- data/test/contacts_test.rb +90 -0
- data/test/factories/stewie.jpeg +0 -0
- data/test/helper.rb +63 -0
- data/test/mail_test.rb +62 -0
- data/test/response_test.rb +33 -0
- metadata +251 -0
data/lib/chatty-crow.rb
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
require File.dirname(__FILE__) + '/chatty_crow.rb'
|
data/lib/chatty_crow.rb
ADDED
|
@@ -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,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,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,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
|