we_chat 0.5.15

Sign up to get free protection for your applications and to get access to all the features.
Files changed (48) hide show
  1. checksums.yaml +7 -0
  2. data/README.rdoc +3 -0
  3. data/Rakefile +26 -0
  4. data/app/assets/javascripts/we_chat/application.js +13 -0
  5. data/app/assets/stylesheets/we_chat/application.css +15 -0
  6. data/app/controllers/we_chat/application_controller.rb +4 -0
  7. data/app/helpers/we_chat/application_helper.rb +4 -0
  8. data/app/views/layouts/we_chat/application.html.erb +14 -0
  9. data/config/routes.rb +4 -0
  10. data/lib/tasks/we_chat/access_token.rake +26 -0
  11. data/lib/we_chat/access_token.rb +56 -0
  12. data/lib/we_chat/acts_as_we_chat_entity.rb +72 -0
  13. data/lib/we_chat/category.rb +19 -0
  14. data/lib/we_chat/category_property.rb +20 -0
  15. data/lib/we_chat/category_property_item.rb +17 -0
  16. data/lib/we_chat/engine.rb +5 -0
  17. data/lib/we_chat/entity/base.rb +62 -0
  18. data/lib/we_chat/entity/creator.rb +67 -0
  19. data/lib/we_chat/entity/destroyer.rb +16 -0
  20. data/lib/we_chat/entity/identity_entity.rb +21 -0
  21. data/lib/we_chat/entity/named_entity.rb +21 -0
  22. data/lib/we_chat/entity/retriever.rb +21 -0
  23. data/lib/we_chat/error.rb +105 -0
  24. data/lib/we_chat/headers.rb +15 -0
  25. data/lib/we_chat/menu.rb +36 -0
  26. data/lib/we_chat/messaging/message.rb +46 -0
  27. data/lib/we_chat/messaging/message_validator.rb +15 -0
  28. data/lib/we_chat/messaging/responder.rb +92 -0
  29. data/lib/we_chat/multipart_ext.rb +12 -0
  30. data/lib/we_chat/product.rb +119 -0
  31. data/lib/we_chat/product_attribute.rb +23 -0
  32. data/lib/we_chat/rest/api.rb +17 -0
  33. data/lib/we_chat/rest/client.rb +41 -0
  34. data/lib/we_chat/rest/media.rb +18 -0
  35. data/lib/we_chat/rest/menu.rb +21 -0
  36. data/lib/we_chat/rest/request.rb +103 -0
  37. data/lib/we_chat/rest/store.rb +172 -0
  38. data/lib/we_chat/rest/template_message.rb +14 -0
  39. data/lib/we_chat/rest/user.rb +20 -0
  40. data/lib/we_chat/rest/utils.rb +27 -0
  41. data/lib/we_chat/sku.rb +55 -0
  42. data/lib/we_chat/sku_definition.rb +21 -0
  43. data/lib/we_chat/sku_definition_item.rb +17 -0
  44. data/lib/we_chat/subscriber.rb +32 -0
  45. data/lib/we_chat/symbolizable.rb +18 -0
  46. data/lib/we_chat/version.rb +3 -0
  47. data/lib/we_chat.rb +46 -0
  48. metadata +257 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: feb8514ae121d06ffb939ed48de578fbf4772d55
4
+ data.tar.gz: 4d29334931bdf43b6e214682f09bacf7bae6551d
5
+ SHA512:
6
+ metadata.gz: 9b98760c30df6ac196d261fb0fc9be4afbe702161b52d67a159e5907fb49d38888edb71a0e4d21b13bb875ccea00158d7dd89bf017edb3c46744be8f1a2b16b8
7
+ data.tar.gz: bb7ee269809961857a7b119a9bb1f4651f052b2c39d3ccda2af38a290bd5e90adbfefc114387e476cadcff7c7f9acf172efc7fd13fd67caea370037fa90024c1
data/README.rdoc ADDED
@@ -0,0 +1,3 @@
1
+ = WeChat
2
+
3
+ This project rocks and uses MIT-LICENSE.
data/Rakefile ADDED
@@ -0,0 +1,26 @@
1
+ begin
2
+ require 'bundler/setup'
3
+ rescue LoadError
4
+ puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
5
+ end
6
+
7
+ require 'rdoc/task'
8
+
9
+ RDoc::Task.new(:rdoc) do |rdoc|
10
+ rdoc.rdoc_dir = 'rdoc'
11
+ rdoc.title = 'WeChat'
12
+ rdoc.options << '--line-numbers'
13
+ rdoc.rdoc_files.include('README.rdoc')
14
+ rdoc.rdoc_files.include('lib/**/*.rb')
15
+ end
16
+
17
+ APP_RAKEFILE = File.expand_path("../spec/test_app/Rakefile", __FILE__)
18
+ load 'rails/tasks/engine.rake'
19
+
20
+
21
+ load 'rails/tasks/statistics.rake'
22
+
23
+
24
+
25
+ Bundler::GemHelper.install_tasks
26
+
@@ -0,0 +1,13 @@
1
+ // This is a manifest file that'll be compiled into application.js, which will include all the files
2
+ // listed below.
3
+ //
4
+ // Any JavaScript/Coffee file within this directory, lib/assets/javascripts, vendor/assets/javascripts,
5
+ // or any plugin's vendor/assets/javascripts directory can be referenced here using a relative path.
6
+ //
7
+ // It's not advisable to add code directly here, but if you do, it'll appear at the bottom of the
8
+ // compiled file.
9
+ //
10
+ // Read Sprockets README (https://github.com/sstephenson/sprockets#sprockets-directives) for details
11
+ // about supported directives.
12
+ //
13
+ //= require_tree .
@@ -0,0 +1,15 @@
1
+ /*
2
+ * This is a manifest file that'll be compiled into application.css, which will include all the files
3
+ * listed below.
4
+ *
5
+ * Any CSS and SCSS file within this directory, lib/assets/stylesheets, vendor/assets/stylesheets,
6
+ * or any plugin's vendor/assets/stylesheets directory can be referenced here using a relative path.
7
+ *
8
+ * You're free to add application-wide styles to this file and they'll appear at the bottom of the
9
+ * compiled file so the styles you add here take precedence over styles defined in any styles
10
+ * defined in the other CSS/SCSS files in this directory. It is generally better to create a new
11
+ * file per style scope.
12
+ *
13
+ *= require_tree .
14
+ *= require_self
15
+ */
@@ -0,0 +1,4 @@
1
+ module WeChat
2
+ class ApplicationController < ActionController::Base
3
+ end
4
+ end
@@ -0,0 +1,4 @@
1
+ module WeChat
2
+ module ApplicationHelper
3
+ end
4
+ end
@@ -0,0 +1,14 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <title>WeChat</title>
5
+ <%= stylesheet_link_tag "we_chat/application", media: "all" %>
6
+ <%= javascript_include_tag "we_chat/application" %>
7
+ <%= csrf_meta_tags %>
8
+ </head>
9
+ <body>
10
+
11
+ <%= yield %>
12
+
13
+ </body>
14
+ </html>
data/config/routes.rb ADDED
@@ -0,0 +1,4 @@
1
+ WeChat::Engine.routes.draw do
2
+ get 'referrer/register'
3
+
4
+ end
@@ -0,0 +1,26 @@
1
+ # desc "Explaining what the task does"
2
+ # task :we_chat do
3
+ # # Task goes here
4
+ # end
5
+
6
+ require 'we_chat'
7
+
8
+ namespace :we_chat do
9
+ namespace :access_token do
10
+ task :refresh => :environment do
11
+ if defined?(Rails) && (Rails.env == 'development')
12
+ Rails.logger = Logger.new(STDOUT)
13
+ end
14
+
15
+ access_token = WeChat::AccessToken.new(
16
+ WeChat::REST::Client.new,
17
+ WeChat.wechat_appid,
18
+ WeChat.wechat_secret,
19
+ WeChat.wechat_access_token_file_path
20
+ )
21
+ access_token.retrieve
22
+
23
+ Rails.logger.info "* [ACCESS_TOKEN]#{access_token.value}"
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,56 @@
1
+ require 'we_chat/rest/utils'
2
+ require 'we_chat/rest/request'
3
+ require 'we_chat/symbolizable'
4
+
5
+ module WeChat
6
+ class AccessToken
7
+ include WeChat::REST::Utils
8
+ include WeChat::Symbolizable
9
+
10
+ attr_reader :client, :appid, :secret, :access_token_file, :access_token_data
11
+
12
+ def initialize(client, appid, secret, access_token_file)
13
+ @client = client
14
+ @appid = appid
15
+ @secret = secret
16
+ @access_token_file = access_token_file
17
+ end
18
+
19
+ def retrieve
20
+ response = WeChat::REST::Request.new(client, :get, '/token',
21
+ params: {
22
+ grant_type: 'client_credential',
23
+ appid: appid,
24
+ secret: secret
25
+ }).perform
26
+
27
+ File.open(access_token_file, 'w') { |file| file.write(response.to_json) } if valid?(response)
28
+ return @access_token_data = response
29
+ end
30
+
31
+ def value
32
+ begin
33
+ @access_token_data ||= symbolize_keys!(JSON.parse(File.read(access_token_file)))
34
+ rescue => e
35
+ Rails.logger.debug e
36
+ retrieve
37
+ end
38
+ @access_token_data[:access_token]
39
+ end
40
+
41
+ def valid?(data)
42
+ access_token = data.nil? ? '' : data[:access_token]
43
+ !access_token.blank?
44
+ end
45
+
46
+ class << self
47
+
48
+ def get_access_token(file_path = nil)
49
+ file_path ||= WeChat.wechat_access_token_file_path
50
+ data = JSON.parse(File.read(file_path))
51
+ data["access_token"]
52
+ end
53
+
54
+ end
55
+ end
56
+ end
@@ -0,0 +1,72 @@
1
+ require 'we_chat/category'
2
+ require 'we_chat/product'
3
+ require 'we_chat/sku'
4
+ require 'we_chat/sku_definition_item'
5
+ require 'we_chat/category_property_item'
6
+ require 'we_chat/product_attribute'
7
+ require 'we_chat/category_property'
8
+ require 'we_chat/sku_definition'
9
+ require 'we_chat/subscriber'
10
+ require 'we_chat/menu'
11
+
12
+ module WeChat
13
+ module ActsAsWeChatEntity
14
+ extend ActiveSupport::Concern
15
+
16
+ included do
17
+
18
+ end
19
+
20
+ module ClassMethods
21
+ def acts_as_we_chat_entity(entity_name, options = {})
22
+ children_options = options[:children] || {}
23
+ children_definition = {}
24
+
25
+ module_including = "WeChat::#{entity_name.to_s.camelize}".constantize
26
+ include module_including
27
+
28
+ if module_including.const_defined?(:CHILDREN)
29
+ children_definition = generate_children_definition(module_including.const_get(:CHILDREN), children_options)
30
+ end
31
+
32
+ define_children_defintion_method(children_definition)
33
+ define_entity_name_method(entity_name)
34
+ end
35
+
36
+ def generate_children_definition(module_children_definition, children_options)
37
+ children_definition = {}
38
+ module_children_definition.map do |child_key, child_data_key|
39
+ option_item = children_options[child_key]
40
+ child_klass = default_child_class(option_item, child_key)
41
+ child_method = default_child_method(option_item, child_key)
42
+ children_definition[child_key] = { klass: child_klass, method: child_method, data_key: child_data_key }
43
+ end
44
+ children_definition
45
+ end
46
+
47
+ def default_child_class(klass_option, default)
48
+ return default.to_s.camelize.constantize if klass_option.nil? || klass_option[:klass].nil?
49
+ klass_option[:klass]
50
+ end
51
+
52
+ def default_child_method(method_option, default)
53
+ return default.to_s.pluralize if method_option.nil? || method_option[:method].nil?
54
+ method_option[:method]
55
+ end
56
+
57
+ def define_entity_name_method(entity_name)
58
+ define_singleton_method(:we_chat_entity_name) do
59
+ return entity_name
60
+ end
61
+ end
62
+
63
+ def define_children_defintion_method(children_definition)
64
+ define_singleton_method(:children_definition) do
65
+ return children_definition
66
+ end
67
+ end
68
+ end
69
+ end
70
+ end
71
+
72
+ ActiveRecord::Base.send :include, WeChat::ActsAsWeChatEntity
@@ -0,0 +1,19 @@
1
+ require 'we_chat/entity/named_entity'
2
+ require 'we_chat/entity/identity_entity'
3
+
4
+ module WeChat
5
+ module Category
6
+ extend ActiveSupport::Concern
7
+
8
+ include WeChat::Entity::NamedEntity
9
+ include WeChat::Entity::IdentityEntity
10
+
11
+ included do
12
+
13
+ end
14
+
15
+ module ClassMethods
16
+
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,20 @@
1
+ require 'we_chat/entity/named_entity'
2
+ require 'we_chat/entity/identity_entity'
3
+
4
+ module WeChat
5
+ module CategoryProperty
6
+ extend ActiveSupport::Concern
7
+ include WeChat::Entity::NamedEntity
8
+ include WeChat::Entity::IdentityEntity
9
+
10
+ CHILDREN = { category_property_item: :property_value }.freeze
11
+
12
+ included do
13
+
14
+ end
15
+
16
+ module ClassMethods
17
+
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,17 @@
1
+ require 'we_chat/entity/named_entity'
2
+ require 'we_chat/entity/identity_entity'
3
+
4
+ module WeChat
5
+ module CategoryPropertyItem
6
+ extend ActiveSupport::Concern
7
+ include WeChat::Entity::NamedEntity
8
+ include WeChat::Entity::IdentityEntity
9
+
10
+ included do
11
+ end
12
+
13
+ module ClassMethods
14
+
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,5 @@
1
+ module WeChat
2
+ class Engine < ::Rails::Engine
3
+ isolate_namespace WeChat
4
+ end
5
+ end
@@ -0,0 +1,62 @@
1
+ require_relative 'retriever'
2
+ require_relative 'creator'
3
+ require_relative 'destroyer'
4
+
5
+ module WeChat
6
+ module Entity
7
+ module Base
8
+ extend ActiveSupport::Concern
9
+
10
+ include Retriever
11
+ include Creator
12
+ include Destroyer
13
+
14
+ def to_we_chat_data
15
+ { id: self.we_chat_id, name: self.name }
16
+ end
17
+
18
+ def submitted_to_we_chat?
19
+ !(self.we_chat_id.nil? || self.we_chat_id.empty?)
20
+ end
21
+
22
+ def submit_to_we_chat
23
+ unless submitted_to_we_chat?
24
+ response = WeChat::REST::Client.default.send("#{self.class.we_chat_entity_name.to_s}_create".to_sym, self.to_we_chat_data)
25
+ set_we_chat_id(response)
26
+ end
27
+ end
28
+
29
+ def delete_from_we_chat
30
+ if submitted_to_we_chat?
31
+ self.class.delete_from_we_chat(self.we_chat_id)
32
+ reset_we_chat_id
33
+ end
34
+ end
35
+
36
+ def update_to_we_chat
37
+ if submitted_to_we_chat?
38
+ WeChat::REST::Client.default.send("#{self.class.we_chat_entity_name.to_s}_update".to_sym, self.to_we_chat_data)
39
+ else
40
+ submit_to_we_chat
41
+ end
42
+ end
43
+
44
+ def get_we_chat_id_from_data(data)
45
+ data[:we_chat_id]
46
+ end
47
+
48
+ def reset_we_chat_id
49
+ self.update_attributes!(we_chat_id: nil)
50
+ end
51
+
52
+ def set_we_chat_id(data)
53
+ self.update_attributes!(we_chat_id: get_we_chat_id_from_data(data))
54
+ end
55
+
56
+ module ClassMethods
57
+
58
+ end
59
+
60
+ end
61
+ end
62
+ end
@@ -0,0 +1,67 @@
1
+ require 'we_chat/error'
2
+
3
+ module WeChat
4
+ module Entity
5
+ module Creator
6
+ extend ActiveSupport::Concern
7
+
8
+ module ClassMethods
9
+
10
+ def create_by_we_chat_data(data)
11
+ instance = prepare_children(prepare_instance(data), data) unless data.nil?
12
+ instance || fail(WeChat::Error.new('Entity was created by WeChat data failed'))
13
+ end
14
+
15
+ private
16
+
17
+ def prepare_instance_data(data)
18
+ {}
19
+ end
20
+
21
+ def prepare_instance(data)
22
+ instance_data = prepare_instance_data(data)
23
+ instance = find_by_we_chat_id(instance_data[:we_chat_id])
24
+ if instance.nil?
25
+ instance = create(instance_data)
26
+ else
27
+ instance.update(instance_data)
28
+ end
29
+ instance
30
+ end
31
+
32
+ def prepare_children_data(data)
33
+ children_data = {}
34
+ children_definition.map do |key, value|
35
+ children_data[key] = prepare_one_type_of_children_data(data, key, value)
36
+ end
37
+
38
+ children_data
39
+ end
40
+
41
+ def prepare_one_type_of_children_data(data, child_type, definition)
42
+ data_key = definition[:data_key]
43
+ definition.merge(data: data[data_key])
44
+ end
45
+
46
+ def prepare_children(instance, data)
47
+ return nil if instance.nil?
48
+ children_data = prepare_children_data(data)
49
+ children_data.map do |key, value|
50
+ prepare_one_type_of_children(instance, key, value)
51
+ end
52
+ instance
53
+ end
54
+
55
+ def prepare_one_type_of_children(instance, child_type, child_data)
56
+ if child_data && child_data[:data]
57
+ child_data[:data].each do |item|
58
+ child_instance = child_data[:klass].send(:create_by_we_chat_data, item) if child_data[:klass].singleton_class.method_defined?(:create_by_we_chat_data)
59
+ instance.send(child_data[:method]) << child_instance if child_instance
60
+ end
61
+ end
62
+ end
63
+
64
+ end
65
+ end
66
+ end
67
+ end
@@ -0,0 +1,16 @@
1
+ module WeChat
2
+ module Entity
3
+ module Destroyer
4
+ extend ActiveSupport::Concern
5
+
6
+ module ClassMethods
7
+
8
+ def delete_from_we_chat(id)
9
+ WeChat::REST::Client.default.send("#{we_chat_entity_name.to_s}_delete".to_sym, id)
10
+ end
11
+
12
+ end
13
+
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,21 @@
1
+ require 'we_chat/entity/base'
2
+
3
+ module WeChat
4
+ module Entity
5
+ module IdentityEntity
6
+ extend ActiveSupport::Concern
7
+ include WeChat::Entity::Base
8
+
9
+ module ClassMethods
10
+
11
+ def prepare_instance_data(data)
12
+ result = super(data)
13
+ result[:we_chat_id] = data[:id]
14
+ result
15
+ end
16
+
17
+ end
18
+
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,21 @@
1
+ require 'we_chat/entity/base'
2
+
3
+ module WeChat
4
+ module Entity
5
+ module NamedEntity
6
+ extend ActiveSupport::Concern
7
+ include WeChat::Entity::Base
8
+
9
+ module ClassMethods
10
+
11
+ def prepare_instance_data(data)
12
+ result = super(data)
13
+ result[:name] = data[:name]
14
+ result
15
+ end
16
+
17
+ end
18
+
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,21 @@
1
+ module WeChat
2
+ module Entity
3
+ module Retriever
4
+ extend ActiveSupport::Concern
5
+
6
+ module ClassMethods
7
+
8
+ def retrieve_from_we_chat(id)
9
+ response = WeChat::REST::Client.default.send("#{we_chat_entity_name.to_s}_get".to_sym, id)
10
+ create_by_we_chat(get_instance_data_from_reponse(response))
11
+ end
12
+
13
+ def get_instance_data_from_reponse(response)
14
+ response
15
+ end
16
+
17
+ end
18
+
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,105 @@
1
+ module WeChat
2
+ # Custom error class for rescuing from all WeChat errors
3
+ class Error < StandardError
4
+ # @return [Integer]
5
+ attr_reader :code
6
+
7
+ # Raised when WeChat returns a 4xx HTTP status code
8
+ ClientError = Class.new(self)
9
+
10
+ # Raised when WeChat returns the HTTP status code 400
11
+ BadRequest = Class.new(ClientError)
12
+
13
+ # Raised when WeChat returns the HTTP status code 401
14
+ Unauthorized = Class.new(ClientError)
15
+
16
+ # Raised when WeChat returns the HTTP status code 403
17
+ Forbidden = Class.new(ClientError)
18
+
19
+ # Raised when a Tweet has already been favorited
20
+ AlreadyFavorited = Class.new(Forbidden)
21
+
22
+ # Raised when a Tweet has already been retweeted
23
+ AlreadyRetweeted = Class.new(Forbidden)
24
+
25
+ # Raised when a Tweet has already been posted
26
+ DuplicateStatus = Class.new(Forbidden)
27
+
28
+ # Raised when WeChat returns the HTTP status code 404
29
+ NotFound = Class.new(ClientError)
30
+
31
+ # Raised when WeChat returns the HTTP status code 406
32
+ NotAcceptable = Class.new(ClientError)
33
+
34
+ # Raised when WeChat returns the HTTP status code 422
35
+ UnprocessableEntity = Class.new(ClientError)
36
+
37
+ # Raised when WeChat returns the HTTP status code 429
38
+ TooManyRequests = Class.new(ClientError)
39
+
40
+ # Raised when WeChat returns a 5xx HTTP status code
41
+ ServerError = Class.new(self)
42
+
43
+ # Raised when WeChat returns the HTTP status code 500
44
+ InternalServerError = Class.new(ServerError)
45
+
46
+ # Raised when WeChat returns the HTTP status code 502
47
+ BadGateway = Class.new(ServerError)
48
+
49
+ # Raised when WeChat returns the HTTP status code 503
50
+ ServiceUnavailable = Class.new(ServerError)
51
+
52
+ # Raised when WeChat returns the HTTP status code 504
53
+ GatewayTimeout = Class.new(ServerError)
54
+
55
+ ERRORS = {
56
+ 400 => WeChat::Error::BadRequest,
57
+ 401 => WeChat::Error::Unauthorized,
58
+ 403 => WeChat::Error::Forbidden,
59
+ 404 => WeChat::Error::NotFound,
60
+ 406 => WeChat::Error::NotAcceptable,
61
+ 422 => WeChat::Error::UnprocessableEntity,
62
+ 429 => WeChat::Error::TooManyRequests,
63
+ 500 => WeChat::Error::InternalServerError,
64
+ 502 => WeChat::Error::BadGateway,
65
+ 503 => WeChat::Error::ServiceUnavailable,
66
+ 504 => WeChat::Error::GatewayTimeout,
67
+ }
68
+
69
+ class << self
70
+
71
+ # Create a new error from an HTTP response
72
+ #
73
+ # @param body [String]
74
+ # @param headers [Hash]
75
+ # @return [WeChat::Error]
76
+ def from_response(body, headers)
77
+ message, code = parse_error(body)
78
+ new(message, headers, code)
79
+ end
80
+
81
+ private
82
+
83
+ def parse_error(body)
84
+ if body.nil? || body.empty?
85
+ ['', -1]
86
+ elsif body[:errcode] && body[:errcode] != 0
87
+ [body[:errmsg], body[:errcode]]
88
+ else
89
+ ['', -1]
90
+ end
91
+ end
92
+ end
93
+
94
+ # Initializes a new Error object
95
+ #
96
+ # @param message [Exception, String]
97
+ # @param rate_limit [Hash]
98
+ # @param code [Integer]
99
+ # @return [WeChat::Error]
100
+ def initialize(message = '', headers = {}, code = nil)
101
+ super(message)
102
+ @code = code
103
+ end
104
+ end
105
+ end
@@ -0,0 +1,15 @@
1
+ module WeChat
2
+ class Headers
3
+ def initialize(client, request_method, url, options = {})
4
+ @client = client
5
+ @request_method = request_method.to_sym
6
+ @uri = Addressable::URI.parse(url)
7
+ @options = options
8
+ end
9
+
10
+ def request_headers
11
+ headers = {}
12
+ headers
13
+ end
14
+ end
15
+ end