aliyun_mns 0.1.8

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 ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 3b3b4b5740bf6cbd5ee9ec4b6cc33dfbb17bee83
4
+ data.tar.gz: 61533b2009472fc0832f2ada9d4bc2cbe67a3223
5
+ SHA512:
6
+ metadata.gz: 8ff4c5407b28d5b2702309246a7b7a932079c978fe23e28a27dbb919c8d9e91b13cb61e653c3c18ddd36bdd0092db0a4de140d528c38af8aeec9b5d5de75fe46
7
+ data.tar.gz: 1004b4347d52e90cc3ad9c71ab04b6086948fe1ef2c970f9dacb8ebd1ab37188f557b719f252b8815a241b3ea505d518785220f1415a0b8a378b00ed04e883bd
data/.gitignore ADDED
@@ -0,0 +1,9 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /Gemfile.lock
4
+ /_yardoc/
5
+ /coverage/
6
+ /doc/
7
+ /pkg/
8
+ /spec/reports/
9
+ /tmp/
data/.idea/.rakeTasks ADDED
@@ -0,0 +1,7 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <Settings><!--This file was automatically generated by Ruby plugin.
3
+ You are allowed to:
4
+ 1. Remove rake task
5
+ 2. Add existing rake tasks
6
+ To add existing rake tasks automatically delete this file and reload the project.
7
+ --><RakeGroup description="" fullCmd="" taksId="rake"><RakeTask description="Build aliyun_mns-0.1.0.gem into the pkg directory" fullCmd="build" taksId="build" /><RakeTask description="Remove any temporary products" fullCmd="clean" taksId="clean" /><RakeTask description="Remove any generated file" fullCmd="clobber" taksId="clobber" /><RakeTask description="Build and install aliyun_mns-0.1.0.gem into system gems" fullCmd="install" taksId="install" /><RakeGroup description="" fullCmd="" taksId="install"><RakeTask description="Build and install aliyun_mns-0.1.0.gem into system gems without network access" fullCmd="install:local" taksId="local" /></RakeGroup><RakeTask description="Create tag v0.1.0 and build and push aliyun_mns-0.1.0.gem to Rubygems" fullCmd="release[remote]" taksId="release[remote]" /><RakeTask description="Run RSpec code examples" fullCmd="spec" taksId="spec" /><RakeTask description="" fullCmd="default" taksId="default" /><RakeTask description="" fullCmd="release" taksId="release" /><RakeGroup description="" fullCmd="" taksId="release"><RakeTask description="" fullCmd="release:guard_clean" taksId="guard_clean" /><RakeTask description="" fullCmd="release:rubygem_push" taksId="rubygem_push" /><RakeTask description="" fullCmd="release:source_control_push" taksId="source_control_push" /></RakeGroup></RakeGroup></Settings>
@@ -0,0 +1,38 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <module type="RUBY_MODULE" version="4">
3
+ <component name="NewModuleRootManager">
4
+ <content url="file://$MODULE_DIR$" />
5
+ <orderEntry type="inheritedJdk" />
6
+ <orderEntry type="sourceFolder" forTests="false" />
7
+ <orderEntry type="library" scope="PROVIDED" name="activesupport (v5.0.0.1, RVM: ruby-2.3.1) [gem]" level="application" />
8
+ <orderEntry type="library" scope="PROVIDED" name="bundler (v1.12.5, RVM: ruby-2.3.1) [gem]" level="application" />
9
+ <orderEntry type="library" scope="PROVIDED" name="codeclimate-test-reporter (v0.6.0, RVM: ruby-2.3.1) [gem]" level="application" />
10
+ <orderEntry type="library" scope="PROVIDED" name="concurrent-ruby (v1.0.2, RVM: ruby-2.3.1) [gem]" level="application" />
11
+ <orderEntry type="library" scope="PROVIDED" name="diff-lcs (v1.2.5, RVM: ruby-2.3.1) [gem]" level="application" />
12
+ <orderEntry type="library" scope="PROVIDED" name="docile (v1.1.5, RVM: ruby-2.3.1) [gem]" level="application" />
13
+ <orderEntry type="library" scope="PROVIDED" name="domain_name (v0.5.20160826, RVM: ruby-2.3.1) [gem]" level="application" />
14
+ <orderEntry type="library" scope="PROVIDED" name="http-cookie (v1.0.2, RVM: ruby-2.3.1) [gem]" level="application" />
15
+ <orderEntry type="library" scope="PROVIDED" name="i18n (v0.7.0, RVM: ruby-2.3.1) [gem]" level="application" />
16
+ <orderEntry type="library" scope="PROVIDED" name="json (v2.0.2, RVM: ruby-2.3.1) [gem]" level="application" />
17
+ <orderEntry type="library" scope="PROVIDED" name="mime-types (v3.1, RVM: ruby-2.3.1) [gem]" level="application" />
18
+ <orderEntry type="library" scope="PROVIDED" name="mime-types-data (v3.2016.0521, RVM: ruby-2.3.1) [gem]" level="application" />
19
+ <orderEntry type="library" scope="PROVIDED" name="mini_portile2 (v2.1.0, RVM: ruby-2.3.1) [gem]" level="application" />
20
+ <orderEntry type="library" scope="PROVIDED" name="minitest (v5.9.0, RVM: ruby-2.3.1) [gem]" level="application" />
21
+ <orderEntry type="library" scope="PROVIDED" name="netrc (v0.11.0, RVM: ruby-2.3.1) [gem]" level="application" />
22
+ <orderEntry type="library" scope="PROVIDED" name="nokogiri (v1.6.8, RVM: ruby-2.3.1) [gem]" level="application" />
23
+ <orderEntry type="library" scope="PROVIDED" name="pkg-config (v1.1.7, RVM: ruby-2.3.1) [gem]" level="application" />
24
+ <orderEntry type="library" scope="PROVIDED" name="rake (v10.5.0, RVM: ruby-2.3.1) [gem]" level="application" />
25
+ <orderEntry type="library" scope="PROVIDED" name="rest-client (v2.0.0, RVM: ruby-2.3.1) [gem]" level="application" />
26
+ <orderEntry type="library" scope="PROVIDED" name="rspec (v3.5.0, RVM: ruby-2.3.1) [gem]" level="application" />
27
+ <orderEntry type="library" scope="PROVIDED" name="rspec-core (v3.5.3, RVM: ruby-2.3.1) [gem]" level="application" />
28
+ <orderEntry type="library" scope="PROVIDED" name="rspec-expectations (v3.5.0, RVM: ruby-2.3.1) [gem]" level="application" />
29
+ <orderEntry type="library" scope="PROVIDED" name="rspec-mocks (v3.5.0, RVM: ruby-2.3.1) [gem]" level="application" />
30
+ <orderEntry type="library" scope="PROVIDED" name="rspec-support (v3.5.0, RVM: ruby-2.3.1) [gem]" level="application" />
31
+ <orderEntry type="library" scope="PROVIDED" name="simplecov (v0.12.0, RVM: ruby-2.3.1) [gem]" level="application" />
32
+ <orderEntry type="library" scope="PROVIDED" name="simplecov-html (v0.10.0, RVM: ruby-2.3.1) [gem]" level="application" />
33
+ <orderEntry type="library" scope="PROVIDED" name="thread_safe (v0.3.5, RVM: ruby-2.3.1) [gem]" level="application" />
34
+ <orderEntry type="library" scope="PROVIDED" name="tzinfo (v1.2.2, RVM: ruby-2.3.1) [gem]" level="application" />
35
+ <orderEntry type="library" scope="PROVIDED" name="unf (v0.1.4, RVM: ruby-2.3.1) [gem]" level="application" />
36
+ <orderEntry type="library" scope="PROVIDED" name="unf_ext (v0.0.7.2, RVM: ruby-2.3.1) [gem]" level="application" />
37
+ </component>
38
+ </module>
data/.idea/misc.xml ADDED
@@ -0,0 +1,14 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <project version="4">
3
+ <component name="ProjectLevelVcsManager" settingsEditedManually="false">
4
+ <OptionsSetting value="true" id="Add" />
5
+ <OptionsSetting value="true" id="Remove" />
6
+ <OptionsSetting value="true" id="Checkout" />
7
+ <OptionsSetting value="true" id="Update" />
8
+ <OptionsSetting value="true" id="Status" />
9
+ <OptionsSetting value="true" id="Edit" />
10
+ <ConfirmationsSetting value="0" id="Add" />
11
+ <ConfirmationsSetting value="0" id="Remove" />
12
+ </component>
13
+ <component name="ProjectRootManager" version="2" project-jdk-name="RVM: ruby-2.3.1" project-jdk-type="RUBY_SDK" />
14
+ </project>
data/.idea/modules.xml ADDED
@@ -0,0 +1,8 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <project version="4">
3
+ <component name="ProjectModuleManager">
4
+ <modules>
5
+ <module fileurl="file://$PROJECT_DIR$/.idea/aliyun_mns.iml" filepath="$PROJECT_DIR$/.idea/aliyun_mns.iml" />
6
+ </modules>
7
+ </component>
8
+ </project>
data/.idea/vcs.xml ADDED
@@ -0,0 +1,6 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <project version="4">
3
+ <component name="VcsDirectoryMappings">
4
+ <mapping directory="$PROJECT_DIR$" vcs="Git" />
5
+ </component>
6
+ </project>
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --format documentation
2
+ --color
data/.travis.yml ADDED
@@ -0,0 +1,5 @@
1
+ sudo: false
2
+ language: ruby
3
+ rvm:
4
+ - 2.3.1
5
+ before_install: gem install bundler -v 1.12.5
@@ -0,0 +1,49 @@
1
+ # Contributor Code of Conduct
2
+
3
+ As contributors and maintainers of this project, and in the interest of
4
+ fostering an open and welcoming community, we pledge to respect all people who
5
+ contribute through reporting issues, posting feature requests, updating
6
+ documentation, submitting pull requests or patches, and other activities.
7
+
8
+ We are committed to making participation in this project a harassment-free
9
+ experience for everyone, regardless of level of experience, gender, gender
10
+ identity and expression, sexual orientation, disability, personal appearance,
11
+ body size, race, ethnicity, age, religion, or nationality.
12
+
13
+ Examples of unacceptable behavior by participants include:
14
+
15
+ * The use of sexualized language or imagery
16
+ * Personal attacks
17
+ * Trolling or insulting/derogatory comments
18
+ * Public or private harassment
19
+ * Publishing other's private information, such as physical or electronic
20
+ addresses, without explicit permission
21
+ * Other unethical or unprofessional conduct
22
+
23
+ Project maintainers have the right and responsibility to remove, edit, or
24
+ reject comments, commits, code, wiki edits, issues, and other contributions
25
+ that are not aligned to this Code of Conduct, or to ban temporarily or
26
+ permanently any contributor for other behaviors that they deem inappropriate,
27
+ threatening, offensive, or harmful.
28
+
29
+ By adopting this Code of Conduct, project maintainers commit themselves to
30
+ fairly and consistently applying these principles to every aspect of managing
31
+ this project. Project maintainers who do not follow or enforce the Code of
32
+ Conduct may be permanently removed from the project team.
33
+
34
+ This code of conduct applies both within project spaces and in public spaces
35
+ when an individual is representing the project or its community.
36
+
37
+ Instances of abusive, harassing, or otherwise unacceptable behavior may be
38
+ reported by contacting a project maintainer at zhangbin@skio.cn. All
39
+ complaints will be reviewed and investigated and will result in a response that
40
+ is deemed necessary and appropriate to the circumstances. Maintainers are
41
+ obligated to maintain confidentiality with regard to the reporter of an
42
+ incident.
43
+
44
+ This Code of Conduct is adapted from the [Contributor Covenant][homepage],
45
+ version 1.3.0, available at
46
+ [http://contributor-covenant.org/version/1/3/0/][version]
47
+
48
+ [homepage]: http://contributor-covenant.org
49
+ [version]: http://contributor-covenant.org/version/1/3/0/
data/Gemfile ADDED
@@ -0,0 +1,5 @@
1
+ source 'https://ruby.taobao.org'
2
+
3
+ # Specify your gem's dependencies in mqs.gemspec
4
+ gemspec
5
+ gem "codeclimate-test-reporter", group: :test, require: nil
data/LICENSE.txt ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2016 jason
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,141 @@
1
+ # AliyunMns
2
+
3
+ aliyun mns 通过http api操作topic
4
+
5
+ ## Installation
6
+
7
+ Add this line to your application's Gemfile:
8
+
9
+ ```ruby
10
+ gem 'aliyun_mns', :git => 'https://github.com/zhangbin/aliyun_mns.git'
11
+ ```
12
+ ## Rails configuration
13
+ if you are going to use this gem in a rails environment.
14
+ You need to create a configuration file at <RAILS_ROOT>/config/aliyun_mns.yml.
15
+ In this way, you can use different set of topics for your development or production environments.
16
+
17
+ development:
18
+ access_key_id: 'ccess_key_id'
19
+ access_key_secret: 'access_key_secret'
20
+ endpoint: '$id.mns.cn-hangzhou.aliyuncs.com'
21
+
22
+ production:
23
+ access_key_id: 'ccess_key_id'
24
+ access_key_secret: 'access_key_secret'
25
+ endpoint: '$id.mns.cn-hangzhou.aliyuncs.com'
26
+
27
+ ## Config in an application
28
+
29
+ At last you can also config the gem in place, by excute the following code before invoking and queue service.
30
+
31
+ AliyunMns.configure do |config|
32
+
33
+ config.access_key_id = "access_key_id"
34
+ config.access_key_secret = "access_key_secret"
35
+ config.endpoint = "$id.mns.cn-hangzhou.aliyuncs.com"
36
+
37
+ end
38
+
39
+ And then execute:
40
+
41
+ $ bundle install
42
+
43
+
44
+ # Usage
45
+ ## about topic
46
+
47
+ create
48
+
49
+ AliyunMns::Topic["aTopic"].create
50
+
51
+ delete
52
+
53
+ AliyunMns::Topic["aTopic"].delete
54
+
55
+ find all topics
56
+
57
+ AliyunMns::Topic.topics
58
+
59
+ get topic attributes
60
+
61
+ request:
62
+ topic = AliyunMns::Topic["topic_name"].get_topic_attributes
63
+
64
+ response:
65
+ # topic_name 主题名称
66
+ # create_time 主题的创建时间,从 1970-1-1 00:00:00到现在的秒值
67
+ # last_modify_time 修改主题属性信息的最近时间,从 1970-1-1 00:00:00 到现在的秒值
68
+ # maximum_message_size 发送到该主题的消息体最大长度,单位为 Byte
69
+ # message_retention_period 消息在主题中最长存活时间,从发送到该主题开始经过此参数指定的时间后,不论消息是否被成功推送给用户都将被删除,单位为秒
70
+ # message_count 当前该主题中消息数目
71
+ # logging_enabled 是否开启日志管理功能,True表示启用,False表示停用
72
+
73
+ {
74
+ :topic_name=>"topic_name",
75
+ :create_time=>"1472442458",
76
+ :last_modify_time=>"1472442458",
77
+ :maximum_message_size=>"65536",
78
+ :message_retention_period=>"86400",
79
+ :message_ount=>"5",
80
+ :logging_enabled=>"False"
81
+ }
82
+
83
+
84
+ subscribe
85
+
86
+ AliyunMns::Topic["atopic", "atopic-subscribe"].subscribe(
87
+ {
88
+ :Endpoint => "http://Endpoint_url",
89
+ :FilterTag => "send-sms",
90
+ :NotifyStrategy => "BACKOFF_RETRY",
91
+ :NotifyContentFormat => "JSON"
92
+ }
93
+ )
94
+
95
+ unsubscribe
96
+
97
+ AliyunMns::Topic["aopic", "atopic-subscribe"].unsubscribe
98
+
99
+ publish message
100
+
101
+ AliyunMns::Topic["atopic"].publish_message(
102
+ {
103
+ :MessageBody => "test message",
104
+ :MessageTag => "publish_message"
105
+ }
106
+ )
107
+
108
+ ## about queue
109
+
110
+ create
111
+
112
+ AliyunMns::Queue["aqueue"].create
113
+
114
+ delete
115
+
116
+ AliyunMns::Queue["aqueue"].delete
117
+
118
+ send message
119
+
120
+ AliyunMns::Queue["aqueue"].send_message("send_message")
121
+
122
+ receive message
123
+
124
+ message = AliyunMns::Queue["aqueue"].receive_message
125
+
126
+ ## Development
127
+
128
+ After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
129
+
130
+ To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
131
+
132
+ ## Contributing
133
+
134
+ Bug reports and pull requests are welcome on GitHub at https://github.com/zhangbin/aliyun_mns. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [Contributor Covenant](http://contributor-covenant.org) code of conduct.
135
+
136
+
137
+ ## License
138
+
139
+ The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).
140
+
141
+ # aliyun_mns
data/Rakefile ADDED
@@ -0,0 +1,7 @@
1
+ #!/usr/bin/env rake
2
+ require File.join('bundler', 'gem_tasks')
3
+ require File.join('rspec', 'core', 'rake_task')
4
+
5
+ RSpec::Core::RakeTask.new(:spec)
6
+
7
+ task :default => :spec
@@ -0,0 +1,38 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'aliyun_mns/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "aliyun_mns"
8
+ spec.version = AliyunMns::VERSION
9
+ spec.authors = ["jason"]
10
+ spec.email = ["zhangbin.zj@gmail.com"]
11
+
12
+ spec.summary = "aliyun mns http api"
13
+ spec.description = "aliyun mns http api for topic"
14
+ spec.homepage = "https://github.com/zhangbin/aliyun_mns.git"
15
+ spec.license = "MIT"
16
+
17
+ # Prevent pushing this gem to RubyGems.org. To allow pushes either set the 'allowed_push_host'
18
+ # to allow pushing to a single host or delete this section to allow pushing to any host.
19
+ if spec.respond_to?(:metadata)
20
+ # spec.metadata['allowed_push_host'] = "http://mygemserver.com"
21
+ else
22
+ raise "RubyGems 2.0 or newer is required to protect against public gem pushes."
23
+ end
24
+
25
+ spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
26
+ spec.bindir = "exe"
27
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
28
+ spec.require_paths = ["lib"]
29
+
30
+ spec.add_dependency 'nokogiri', '>= 1.6'
31
+ spec.add_dependency 'activesupport', '>= 4.1'
32
+ spec.add_dependency "rest-client"
33
+
34
+
35
+ spec.add_development_dependency "bundler", "~> 1.12"
36
+ spec.add_development_dependency "rake", "~> 10.0"
37
+ spec.add_development_dependency "rspec", "~> 3.0"
38
+ end
data/bin/console ADDED
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "bundler/setup"
4
+ require "aliyun_mns"
5
+
6
+ # You can add fixtures and/or initialization code here to make experimenting
7
+ # with your gem easier. You can also use a different console, if you like.
8
+
9
+ # (If you use this, don't forget to add pry to your Gemfile!)
10
+ # require "pry"
11
+ # Pry.start
12
+
13
+ require "irb"
14
+ IRB.start
data/bin/setup ADDED
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+ set -vx
5
+
6
+ bundle install
7
+
8
+ # Do any other automated setup that you need to do here
data/lib/aliyun_mns.rb ADDED
@@ -0,0 +1,44 @@
1
+ require 'active_support'
2
+ require 'active_support/core_ext'
3
+ require 'rest-client'
4
+ require 'nokogiri'
5
+ require 'yaml'
6
+ require 'openssl'
7
+ require "aliyun_mns/version"
8
+ class Hash
9
+ def self.xml_array content, *path
10
+ o = xml_object(content, *path)
11
+ return (o.is_a?(Array) ? o : [o]).reject { |n| n.empty? }
12
+ end
13
+
14
+ def self.xml_object content, *path
15
+ h = from_xml(content)
16
+ path.reduce(h) { |memo, node| memo = memo[node] || {} }
17
+ end
18
+ end
19
+ module AliyunMns
20
+ require 'aliyun_mns/request'
21
+
22
+ class << self
23
+ def configuration
24
+ @configuration ||= begin
25
+ if defined? Rails
26
+ config_file = Rails.root.join("config/aliyun_mns.yml")
27
+ else
28
+ # config_file = File.expand_path("config/aliyun_mns.yml")
29
+ config_file = File.expand_path('../../config/aliyun_mns.yml', __FILE__)
30
+ end
31
+
32
+ if (File.exist?(config_file))
33
+ config = YAML.load(ERB.new(File.new(config_file).read).result)
34
+ config = config[Rails.env] if defined? Rails
35
+ end
36
+ OpenStruct.new(config || {access_id: "", key: "", region: "", owner_id: ""})
37
+ end
38
+ end
39
+
40
+ def configure
41
+ yield(configuration)
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,57 @@
1
+ module AliyunMns
2
+ class Message
3
+ attr_reader :queue, :id, :body_md5, :body, :receipt_handle, :enqueue_at, :first_enqueue_at, :next_visible_at, :dequeue_count, :priority
4
+
5
+ def initialize(queue, content)
6
+ h = Hash.xml_object(content, "Message")
7
+ @queue = queue
8
+ @id = h["MessageId"]
9
+ @body_md5 = h["MessageBodyMD5"]
10
+ @body = h["MessageBody"]
11
+ @enqueue_at = Time.at(h["EnqueueTime"].to_i/1000.0)
12
+ @first_enqueue_at = Time.at(h["FirstDequeueTime"].to_i/1000.0)
13
+ @dequeue_count = h["DequeueCount"].to_i
14
+ @priority = h["Priority"].to_i
15
+ @receipt_handle = h["ReceiptHandle"]
16
+ @next_visible_at = Time.at(h["NextVisibleTime"].to_i/1000.0)
17
+ end
18
+
19
+ #删除消息
20
+ def delete
21
+ check_receipt_handle
22
+ AliyunMns::Request.delete(queue.messages_path, params: {:ReceiptHandle => receipt_handle})
23
+ end
24
+
25
+ #修改消息可见时间
26
+ def change_visibility(seconds)
27
+ check_receipt_handle
28
+ AliyunMns::Request.put(queue.messages_path, params: {:ReceiptHandle => receipt_handle, :VisibilityTimeout => seconds})
29
+ end
30
+
31
+ def to_s
32
+ s = {
33
+ "队列" => queue.name,
34
+ "ID" => id,
35
+ "MD5" => body_md5,
36
+ "Receipt handle" => receipt_handle,
37
+ "Enqueue at" => enqueue_at,
38
+ "First enqueue at" => first_enqueue_at,
39
+ "Next visible at" => next_visible_at,
40
+ "Dequeue count" => dequeue_count,
41
+ "Priority" => priority
42
+ }.collect { |k, v| "#{k}: #{v}" }
43
+
44
+ sep = "=============================================>"
45
+ s.unshift sep
46
+ s << sep
47
+ s << body
48
+ s.join("\n")
49
+ end
50
+
51
+ private
52
+ def check_receipt_handle
53
+ raise "No receipt handle for this operation" unless receipt_handle
54
+ end
55
+
56
+ end
57
+ end
@@ -0,0 +1,22 @@
1
+ module AliyunMns
2
+ class Notification
3
+ attr_reader :message, :message_id, :message_MD5, :message_tag, :publish_time, :subscriber, :subscription_name,
4
+ :topic_name, :topic_owner, :message_format, :message_controller, :action, :send_record
5
+
6
+ def initialize(content_hash)
7
+ @message_id = content_hash["MessageId"]
8
+ @message_MD5 = content_hash["MessageMD5"]
9
+ @message = content_hash["Message"]
10
+ @message_tag = content_hash["MessageTag"]
11
+ @publish_time = content_hash["PublishTime"]
12
+ @subscriber = content_hash["Subscriber"]
13
+ @subscription_name = content_hash["SubscriptionName"]
14
+ @topic_name = content_hash["TopicName"]
15
+ @topic_owner = content_hash["TopicOwner"]
16
+ @message_format = content_hash["format"]
17
+ @message_controller = content_hash["Controller"]
18
+ @action = content_hash["Action"]
19
+ @send_record = content_hash["SendRecord"]
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,72 @@
1
+ module AliyunMns
2
+ class Queue
3
+ require_relative 'message'
4
+ attr_reader :name
5
+
6
+ delegate :to_s, to: :name
7
+
8
+ class << self
9
+ def [] name
10
+ Queue.new(name)
11
+ end
12
+
13
+ def queues(opts = {})
14
+ mqs_options = {query: "x-mns-prefix", offset: "x-mns-marker", size: "x-mns-ret-number"}
15
+ mqs_headers = opts.slice(*mqs_options.keys).reduce({}) { |mqs_headers, item| k, v = *item; mqs_headers.merge!(mqs_options[k] => v) }
16
+ response = Request.get("/queues", mqs_headers: mqs_headers)
17
+ Hash.xml_array(response, "Queues", "Queue").collect { |item| Queue.new(URI(item["QueueURL"]).path.sub!(/^\/queues\//, "")) }
18
+ end
19
+ end
20
+
21
+ def initialize(name)
22
+ @name = name
23
+ end
24
+
25
+ #创建队列
26
+ def create(opts = {})
27
+ Request.put(queue_path) do |request|
28
+ msg_options = {
29
+ :VisibilityTimeout => 30,
30
+ :DelaySeconds => 0,
31
+ :MaximumMessageSize => 65536,
32
+ :MessageRetentionPeriod => 345600,
33
+ :PollingWaitSeconds => 0
34
+ }.merge(opts)
35
+ request.content(:Queue, msg_options)
36
+ end
37
+ end
38
+
39
+ #删除队列
40
+ def delete
41
+ Request.delete(queue_path)
42
+ end
43
+
44
+ #发送消息
45
+ def send_message(message, opts = {})
46
+ Request.post(messages_path) do |request|
47
+ msg_options = {
48
+ :DelaySeconds => 0,
49
+ :Priority => 8
50
+ }.merge(opts)
51
+ request.content(:Message, msg_options.merge(:MessageBody => message.to_s))
52
+ end
53
+ end
54
+
55
+ #消费消息
56
+ def receive_message(wait_seconds = nil)
57
+ request_opts = {}
58
+ request_opts.merge!(params: {waitseconds: wait_seconds}) if wait_seconds
59
+ result = Request.get(messages_path, request_opts)
60
+ Message.new(self, result)
61
+ end
62
+
63
+ def queue_path
64
+ "/queues/#{name}"
65
+ end
66
+
67
+ def messages_path
68
+ "/queues/#{name}/messages"
69
+ end
70
+
71
+ end
72
+ end
@@ -0,0 +1,89 @@
1
+ require 'base64'
2
+ module AliyunMns
3
+
4
+ class RequestException < Exception
5
+ attr_reader :content
6
+ delegate :[], to: :content
7
+
8
+ def initialize(ex)
9
+ @content = Hash.xml_object(ex.to_s, "Error")
10
+ rescue
11
+ @content = {"Message" => ex.message}
12
+ end
13
+ end
14
+
15
+ class Request
16
+ attr_reader :uri, :method, :body, :content_md5, :content_type, :content_length, :mqs_headers
17
+ delegate :access_key_id, :access_key_secret, :endpoint, to: :configuration
18
+
19
+ class << self
20
+ [:get, :delete, :put, :post].each do |m|
21
+ define_method m do |*args, &block|
22
+ options = {method: m, path: args[0], mqs_headers: {}, params: {}}
23
+ options.merge!(args[1]) if args[1].is_a?(Hash)
24
+
25
+ request = AliyunMns::Request.new(options)
26
+ block.call(request) if block
27
+ request.execute
28
+ end
29
+ end
30
+ end
31
+
32
+ def initialize(method: "get", path: "/", mqs_headers: {}, params: {})
33
+ conf = {
34
+ host: endpoint,
35
+ path: path
36
+ }
37
+ conf.merge!(query: params.to_query) unless params.empty?
38
+ @uri = URI::HTTP.build(conf)
39
+ # @uri = URI::HTTP.build([nil, conf[:host], port, conf[:path], nil, nil])
40
+ @method = method
41
+ @mqs_headers = mqs_headers.merge("x-mns-version" => "2015-06-06")
42
+ end
43
+
44
+ def content(type, values={})
45
+ ns = "http://mns.aliyuncs.com/doc/v1/"
46
+ builder = Nokogiri::XML::Builder.new(:encoding => 'UTF-8') do |xml|
47
+ xml.send(type.to_sym, xmlns: ns) do |b|
48
+ values.each { |k, v| b.send k.to_sym, v }
49
+ end
50
+ end
51
+ @body = builder.to_xml
52
+ @content_md5 = Base64::encode64(Digest::MD5.hexdigest(body)).chop
53
+ @content_length = body.size
54
+ @content_type = "text/xml;charset=utf-8"
55
+ end
56
+
57
+ def execute
58
+ date = DateTime.now.httpdate
59
+ headers = {
60
+ "Authorization" => authorization(date),
61
+ "Content-Length" => content_length || 0,
62
+ "Content-Type" => content_type,
63
+ "Content-MD5" => content_md5,
64
+ "Date" => date,
65
+ "Host" => uri.host
66
+ }.merge(mqs_headers).reject { |k, v| v.nil? }
67
+ begin
68
+ RestClient.send *[method, uri.to_s, body, headers].compact
69
+ rescue RestClient::Exception => ex
70
+ raise RequestException.new(ex)
71
+ end
72
+ end
73
+
74
+ private
75
+ def configuration
76
+ AliyunMns.configuration
77
+ end
78
+
79
+ def authorization(date)
80
+ canonical_resource = [uri.path, uri.query].compact.join("?")
81
+ canonical_mq_headers = mqs_headers.sort.collect { |k, v| "#{k.downcase}:#{v}" }.join("\n")
82
+ method = self.method.to_s.upcase
83
+ signature = [method, content_md5 || "", content_type || "", date, canonical_mq_headers, canonical_resource].join("\n")
84
+ sha1 = OpenSSL::HMAC.digest("sha1", access_key_secret, signature)
85
+ "MNS #{access_key_id}:#{Base64.encode64(sha1).chop}"
86
+ end
87
+
88
+ end
89
+ end
@@ -0,0 +1,94 @@
1
+ module AliyunMns
2
+ class Topic
3
+ attr_reader :name, :subscription_name
4
+ delegate :to_s, to: :name
5
+
6
+ class << self
7
+ def [](name, subscription_name = nil)
8
+ Topic.new(name, subscription_name)
9
+ end
10
+
11
+ def topics(opts = {})
12
+ mqs_options = {query: "x-mns-prefix", offset: "x-mns-marker", size: "x-mns-ret-number"}
13
+ mqs_headers = opts.slice(*mqs_options.keys).reduce({}) { |mqs_headers, item| k, v = *item; mqs_headers.merge!(mqs_options[k] => v) }
14
+ response = Request.get("/topics", mqs_headers: mqs_headers)
15
+ Hash.xml_array(response, "Topics", "Topic").collect { |item| Topic.new(URI(item["TopicURL"]).path.sub!(/^\/topics\//, "")) }
16
+ end
17
+ end
18
+
19
+ def initialize(name, subscription_name = nil)
20
+ @name = name
21
+ @subscription_name = subscription_name unless subscription_name.nil?
22
+ end
23
+
24
+ #创建topic
25
+ def create(opts={})
26
+ Request.put(topic_path) do |request|
27
+ msg_options = {
28
+ :MaximumMessageSize => 65536
29
+ }.merge(opts)
30
+ request.content :Topic, msg_options
31
+ end
32
+ end
33
+
34
+ # 删除topic
35
+ def delete
36
+ Request.delete(topic_path)
37
+ end
38
+
39
+ # 获取topic属性
40
+ def get_topic_attributes
41
+ topic_hash = Hash.from_xml(Request.get(topic_path))
42
+ {
43
+ :topic_name => topic_hash["Topic"]["TopicName"],
44
+ :create_time => topic_hash["Topic"]["CreateTime"],
45
+ :last_modify_time => topic_hash["Topic"]["LastModifyTime"],
46
+ :maximum_message_size => topic_hash["Topic"]["MaximumMessageSize"],
47
+ :message_retention_period => topic_hash["Topic"]["MessageRetentionPeriod"],
48
+ :message_ount => topic_hash["Topic"]["MessageCount"],
49
+ :logging_enabled => topic_hash["Topic"]["LoggingEnabled"]
50
+ }
51
+
52
+ end
53
+
54
+ #订阅topic
55
+ def subscribe(opts = {})
56
+ if opts[:Endpoint].nil? || opts[:Endpoint].blank?
57
+ raise RequestException.new(Exception.new("subscribe parameters invalid"))
58
+ else
59
+ Request.put(subscribe_path) do |request|
60
+ request.content(:Subscription, opts)
61
+ end
62
+ end
63
+ end
64
+
65
+ #退订topic
66
+ def unsubscribe
67
+ Request.delete(subscribe_path)
68
+ end
69
+
70
+ #发布消息
71
+ def publish_message(opts = {})
72
+ if opts[:MessageBody].nil? || opts[:MessageBody].blank?
73
+ raise RequestException.new(Exception.new("publish message parameters invalid"))
74
+ else
75
+ Request.post(message_path) do |request|
76
+ request.content(:Message, opts)
77
+ end
78
+ end
79
+ end
80
+
81
+ def topic_path
82
+ "/topics/#{name}"
83
+ end
84
+
85
+ def subscribe_path
86
+ "/topics/#{name}/subscriptions/#{subscription_name}"
87
+ end
88
+
89
+ def message_path
90
+ "/topics/#{name}/messages"
91
+ end
92
+
93
+ end
94
+ end
@@ -0,0 +1,3 @@
1
+ module AliyunMns
2
+ VERSION = "0.1.8"
3
+ end
metadata ADDED
@@ -0,0 +1,151 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: aliyun_mns
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.8
5
+ platform: ruby
6
+ authors:
7
+ - jason
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2016-09-10 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: nokogiri
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '1.6'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '1.6'
27
+ - !ruby/object:Gem::Dependency
28
+ name: activesupport
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '4.1'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '4.1'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rest-client
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: bundler
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: '1.12'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: '1.12'
69
+ - !ruby/object:Gem::Dependency
70
+ name: rake
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - "~>"
74
+ - !ruby/object:Gem::Version
75
+ version: '10.0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - "~>"
81
+ - !ruby/object:Gem::Version
82
+ version: '10.0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: rspec
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - "~>"
88
+ - !ruby/object:Gem::Version
89
+ version: '3.0'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - "~>"
95
+ - !ruby/object:Gem::Version
96
+ version: '3.0'
97
+ description: aliyun mns http api for topic
98
+ email:
99
+ - zhangbin.zj@gmail.com
100
+ executables: []
101
+ extensions: []
102
+ extra_rdoc_files: []
103
+ files:
104
+ - ".gitignore"
105
+ - ".idea/.rakeTasks"
106
+ - ".idea/aliyun_mns.iml"
107
+ - ".idea/misc.xml"
108
+ - ".idea/modules.xml"
109
+ - ".idea/vcs.xml"
110
+ - ".rspec"
111
+ - ".travis.yml"
112
+ - CODE_OF_CONDUCT.md
113
+ - Gemfile
114
+ - LICENSE.txt
115
+ - README.md
116
+ - Rakefile
117
+ - aliyun_mns.gemspec
118
+ - bin/console
119
+ - bin/setup
120
+ - lib/aliyun_mns.rb
121
+ - lib/aliyun_mns/message.rb
122
+ - lib/aliyun_mns/notification.rb
123
+ - lib/aliyun_mns/queue.rb
124
+ - lib/aliyun_mns/request.rb
125
+ - lib/aliyun_mns/topic.rb
126
+ - lib/aliyun_mns/version.rb
127
+ homepage: https://github.com/zhangbin/aliyun_mns.git
128
+ licenses:
129
+ - MIT
130
+ metadata: {}
131
+ post_install_message:
132
+ rdoc_options: []
133
+ require_paths:
134
+ - lib
135
+ required_ruby_version: !ruby/object:Gem::Requirement
136
+ requirements:
137
+ - - ">="
138
+ - !ruby/object:Gem::Version
139
+ version: '0'
140
+ required_rubygems_version: !ruby/object:Gem::Requirement
141
+ requirements:
142
+ - - ">="
143
+ - !ruby/object:Gem::Version
144
+ version: '0'
145
+ requirements: []
146
+ rubyforge_project:
147
+ rubygems_version: 2.5.1
148
+ signing_key:
149
+ specification_version: 4
150
+ summary: aliyun mns http api
151
+ test_files: []