Commit d4c5e0e3 by Victor Wang

init commit

parents
.DS_Store
.rvmrc
*.gem
*.rbc
.bundle
.config
.yardoc
Gemfile.lock
InstalledFiles
_yardoc
coverage
doc/
lib/bundler/man
pkg
rdoc
spec/reports
test/tmp
test/version_tmp
tmp
spec/public
spec/test.log
spec/tmp
## Specific to RubyMotion:
.dat*
.repl_history
build/
## Documentation cache and generated files:
/.yardoc/
/_yardoc/
/doc/
/rdoc/
## Environment normalisation:
/.bundle/
/lib/bundler/man/
# for a library or gem, you might want to ignore these files since the code is
# intended to run in multiple environments; otherwise, check them in:
# Gemfile.lock
.ruby-version
.ruby-gemset
# unless supporting rvm < 1.11.0 or doing something fancy, ignore this:
.rvmrc
source 'https://rubygems.org'
# Specify your gem's dependencies in igetui-ruby.gemspec
gemspec
Copyright (c) 2014 Victor Wang
MIT License
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
# Igetui::Ruby
TODO: Write a gem description
## Installation
Add this line to your application's Gemfile:
gem 'igetui-ruby'
And then execute:
$ bundle
Or install it yourself as:
$ gem install igetui-ruby
## Usage
TODO: Write usage instructions here
## Contributing
1. Fork it ( http://github.com/<my-github-username>/igetui-ruby/fork )
2. Create your feature branch (`git checkout -b my-new-feature`)
3. Commit your changes (`git commit -am 'Add some feature'`)
4. Push to the branch (`git push origin my-new-feature`)
5. Create new Pull Request
require "bundler/gem_tasks"
require 'rake/testtask'
Rake::TestTask.new do |t|
t.pattern = "test/*_test.rb"
end
# coding: utf-8
lib = File.expand_path('../lib', __FILE__)
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
require 'igetui/version'
Gem::Specification.new do |spec|
spec.name = "igetui-ruby"
spec.version = IGeTui::VERSION
spec.authors = ["Victor Wang"]
spec.email = ["QQ: 22674812"]
spec.summary = "igetui.com ruby sdk"
spec.description = "igetui.com ruby sdk"
spec.homepage = "https://github.com/wjp2013/igetui-ruby"
spec.license = "MIT"
# spec.files = `git ls-files -z`.split("\x0")
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
spec.require_paths = ["lib"]
spec.extra_rdoc_files = ["README.md"]
spec.add_development_dependency "bundler", "~> 1.5"
spec.add_development_dependency "rake"
spec.add_dependency "ruby-protocol-buffers", '~> 1.5', '>= 1.5.1'
spec.add_development_dependency "minitest", '~> 5.4', '>= 5.4.0'
end
require 'forwardable'
require 'net/http'
require 'uri'
require 'json'
require 'digest/md5'
require 'base64'
module IGeTui
class << self
extend Forwardable
API_URL = "http://sdk.open.api.igexin.com/apiex.htm"
attr_reader :pusher
def_delegators :pusher, :push_message_to_single
def_delegators :pusher, :push_message_to_list
def_delegators :pusher, :push_message_to_app
def_delegators :pusher, :stop
def_delegators :pusher, :get_client_id_status
def_delegators :pusher, :get_content_id, :cancel_content_id
def pusher(app_id, api_key, master_secret)
@pusher ||= IGeTui::Pusher.new(API_URL, app_id, api_key, master_secret)
end
end
end
require "igetui/version"
require 'protobuf/GtReq.pb'
require "igetui/template"
require "igetui/message"
require "igetui/pusher"
require "igetui/client"
module IGeTui
class Client
attr_accessor :client_id
def initialize(client_id)
@client_id = client_id
end
end
end
module IGeTui
class Message
attr_accessor :is_offline, :offline_expire_time, :data
def initialize
@is_offline = true
@offline_expire_time = 1000 * 3600 * 12
@data = BaseTemplate.new
end
end
SingleMessage = Class.new(Message)
ListMessage = Class.new(Message)
class AppMessage < Message
attr_accessor :app_id_list, :phone_type_list, :province_list, :tag_list
def initialize
@app_id_list = []
@phone_type_list = []
@province_list = []
@tag_list = []
super
end
end
end
module IGeTui
class Pusher
attr_reader :host, :app_id, :app_key, :master_secret
def initialize(host, app_id, app_key, master_secret)
@host = host
@app_id = app_id
@app_key = app_key
@master_secret = master_secret
end
def push_message_to_single(message, client)
template = message.data
data = {
'action' => 'pushMessageToSingleAction',
'appkey' => app_key,
'clientData' => base64Str(template),
'transmissionContent' => template.transmission_content,
'isOffline' => message.is_offline,
'offlineExpireTime' => message.offline_expire_time,
'appId' => app_id,
'clientId' => client.client_id,
'type' => 2, #default is message
'pushType' => template.get_push_type
}
http_post_json(data)
end
def push_message_to_list(content_id, clients)
target_list = clients.inject([]) do |list, cilent|
list << { 'appId' => app_id, 'clientId' => cilent.client_id }
end
# seems that we miss 'pushType'
data = {
'action' => 'pushMessageToListAction',
'appkey' => app_key,
'contentId' => content_id,
'needDetails' => true,
'targetList' => target_list,
'type' => 2
}
http_post_json(data)
end
def push_message_to_app(message)
template = message.data
data = {
'action' => 'pushMessageToAppAction',
'appkey' => app_key,
'clientData' => base64Str(template),
'transmissionContent' => template.transmission_content,
'isOffline' => message.is_offline,
'offlineExpireTime' => message.offline_expire_time,
'appIdList' => message.app_id_list,
'phoneTypeList' => message.phone_type_list,
'provinceList' => message.province_list,
'tagList' => message.tag_list,
'type' => 2,
'pushType' => template.get_push_type
}
http_post_json(data)
end
def stop(content_id)
data = {
'action' => 'stopTaskAction',
'appkey' => @appKey,
'contentId' => content_id
}
ret = http_post_json(data)
ret['result'] == 'ok'
end
def get_client_id_status(client_id)
data = {
'action' => 'getClientIdStatusAction',
'appkey' => app_key,
'appId' => app_id,
'clientId' => client_id
}
http_post_json(data)
end
def get_content_id(message)
template = message.data
data = {
'action' => 'getContentIdAction',
'appkey' => app_key,
'clientData' => base64Str(template),
'transmissionContent' => template.transmission_content,
'isOffline' => message.is_offline,
'offlineExpireTime' => message.offline_expire_time,
'pushType' => template.get_push_type
}
ret = http_post_json(data)
ret['result'] == 'ok' ? ret['contentId'] : ''
end
def cancel_content_id(content_id)
data = {
'action' => 'cancleContentIdAction',
'contentId' => content_id,
}
ret = http_post_json(data)
ret['result'] == 'ok'
end
private
def base64Str(template)
string = template.get_transparent(self).serialize_to_string
Base64.strict_encode64 string
end
def connect
time_stamp = Time.now.to_i
sign = Digest::MD5.hexdigest(app_key + time_stamp.to_s + master_secret)
data = {
action: 'connect',
appkey: app_key,
timeStamp: time_stamp,
sign: sign
}
ret = http_post(data)
ret['result'] == 'success'
end
def http_post_json(params)
params['version'] = '3.0.0.0'
ret = http_post(params)
if ret && ret['result'] == 'sign_error'
connect
ret = http_post(params)
end
ret
end
def http_post(params)
params['version'] = '3.0.0.0'
data = params.to_json
url = URI.parse(host)
req = Net::HTTP::Post.new(url.path, initheader = { 'Content-Type' => 'application/json' })
req.body = data
is_fail = true
retry_time_limit = 3
try_time = 0
while is_fail && try_time < retry_time_limit
begin
res = Net::HTTP.new(url.host, url.port).start { |http| http.request(req) }
is_fail = false
rescue
is_fail = true
try_time += 1
puts ('try ' + try_time.to_s + ' time failed, time out.')
end
end
JSON.parse res.body
end
end
end
require 'igetui/template/base_template'
require 'igetui/template/transmission_template'
require 'igetui/template/notification_template'
module IGeTui
class BaseTemplate
attr_accessor :transmission_type, :transmission_content
def initialize
@push_info = nil
end
def get_transparent(pusher)
transparent = GtReq::Transparent.new
transparent.id = ''
transparent.messageId = ''
transparent.taskId = ''
transparent.action = 'pushmessage'
transparent.actionChain = get_action_chain
transparent.pushInfo = get_push_info
transparent.appId = pusher.app_id
transparent.appKey = pusher.app_key
transparent
end
def get_action_chain; end
def get_push_type; end
def get_push_info
unless @push_info
@push_info = GtReq::PushInfo.new
@push_info.actionKey = ''
@push_info.badge = ''
@push_info.message = ''
@push_info.sound = ''
end
@push_info
end
# Need TEST:
# iOS Pusher need the top three fields of 'push_info' are required.
# the others can be blank string.
def set_push_info(action_loc_key, badge, message, sound, payload, loc_key, loc_args, launch_image)
@push_info = GtReq::PushInfo.new
@push_info.actionLocKey = action_loc_key
@push_info.badge = badge
@push_info.message = message
@push_info.sound = sound if sound
@push_info.payload = payload if payload
@push_info.locKey = loc_key if loc_key
@push_info.locArgs = loc_args if loc_args
@push_info.launchImage = launch_image if launch_image
args = {
loc_key: loc_key,
loc_args: locArgs,
message: message,
action_loc_key: action_loc_key,
launch_image: launch_image,
badge: badge,
sound: sound,
payload: payload
}
Validate.new.validate(args)
@push_info
end
end
end
module IGeTui
class NotificationTemplate < BaseTemplate
attr_accessor :title, :text, :logo, :logo_url
attr_accessor :is_ring, :is_vibrate, :is_clearable
def initialize
@title = ''
@text = ''
@logo = ''
@logo_url = ''
@transmission_type = 0
@transmission_content = ''
@is_ring = true
@is_vibrate = true
@is_clearable = false
super
end
def get_action_chain
# set actionchain
actionChain1 = GtReq::ActionChain.new
actionChain1.actionId = 1
actionChain1.type = GtReq::ActionChain::Type::Goto
actionChain1.next = 10000
# notification
actionChain2 = GtReq::ActionChain.new
actionChain2.actionId = 10000
actionChain2.type = GtReq::ActionChain::Type::Notification
actionChain2.title = title
actionChain2.text = text
actionChain2.logo = logo
actionChain2.logoURL = logo_url
actionChain2.ring = is_ring
actionChain2.clearable = is_clearable
actionChain2.buzz = is_vibrate
actionChain2.next = 10010
# goto
actionChain3 = GtReq::ActionChain.new
actionChain3.actionId = 10010
actionChain3.type = GtReq::ActionChain::Type::Goto
actionChain3.next = 10030
# appStartUp
appStartUp = GtReq::AppStartUp.new(android: '', symbia: '', ios: '')
# start web
actionChain4 = GtReq::ActionChain.new
actionChain4.actionId = 10030
actionChain4.type = GtReq::ActionChain::Type::Startapp
actionChain4.appid = ''
actionChain4.autostart = @transmission_type == 1
actionChain4.appstartupid = appStartUp
actionChain4.failedAction = 100
actionChain4.next = 100
# end
actionChain5 = GtReq::ActionChain.new
actionChain5.actionId = 100
actionChain5.type = GtReq::ActionChain::Type::Eoa
[actionChain1, actionChain2, actionChain3, actionChain4, actionChain5]
end
def get_push_type
"NotifyMsg"
end
end
end
module IGeTui
class TransmissionTemplate < BaseTemplate
def initialize
@transmission_type = 0
@transmission_content = ''
super
end
def get_action_chain
# set actionChain
actionChain1 = GtReq::ActionChain.new
actionChain1.actionId = 1
actionChain1.type = GtReq::ActionChain::Type::Goto
actionChain1.next = 10030
# appStartUp
appStartUp = GtReq::AppStartUp.new(android: '', symbia: '', ios: '')
# start up app
actionChain2 = GtReq::ActionChain.new
actionChain2.actionId = 10030
actionChain2.type = GtReq::ActionChain::Type::Startapp
actionChain2.appid = ''
actionChain2.autostart = transmission_type == 1
actionChain2.appstartupid = appStartUp
actionChain2.failedAction = 100
actionChain2.next = 100
# end
actionChain3 = GtReq::ActionChain.new
actionChain3.actionId = 100
actionChain3.type = GtReq::ActionChain::Type::Eoa
[actionChain1, actionChain2, actionChain3]
end
def get_push_type
"TransmissionMsg"
end
end
end
require 'json'
module IGeTui
class Validate
def validate(args = {})
payload_map = get_payload(args)
json = JSON.generate payload_map
if (json.length > 256)
raise ArgumentError.new("PushInfo length over limit: #{json.length}. Allowed: 256.")
end
end
def get_payload(args = {})
apnsMap = Hash.new
sound = "default" unless validate_length(args, :sound)
apnsMap["sound"] = args[:sound]
alertMap = Hash.new
if validate_length(args, :launch_image)
alertMap["launch-image"] = args[:launch_image]
end
if validate_length(args, :loc_key)
alertMap["loc-key"] = args[:loc_key]
if validate_length(args, :loc_args)
alertMap["loc-args"] = args[:loc_args].split(", ")
end
elsif validate_length(nil, message)
alertMap["body"] = message
end
apnsMap["alert"] = alertMap
if validate_length(args, :action_loc_key)
apnsMap["action-loc-key"] = args[:action_loc_key]
end
apnsMap["badge"] = badge
h = Hash.new
h["aps"] = apnsMap
h["payload"] = payload if validate_length(nil, payload)
return h
end
private
def validate_length(args = {}, key)
if key.class == Symbol
args[key] && args[key].length > 0
else
key && key.length > 0
end
end
end
end
module IGeTui
VERSION = "0.0.1"
end
require 'minitest/autorun'
require './lib/igetui'
class PusherTest < MiniTest::Unit::TestCase
# before run test, you need to change the variables in setup method.
def setup
@app_id = 'YOUR APP ID'
@app_key = 'YOUR APP KEY'
@master_secret = 'YOUR MASTER SECRET'
@cid_1 = 'CLIENT ID ONE'
@cid_2 = 'CLIENT ID TWO'
@pusher = IGeTui.pusher(@app_id, @app_key, @master_secret)
@client_1 = IGeTui::Client.new(@cid_1)
@client_2 = IGeTui::Client.new(@cid_2)
end
def test_status
ret = @pusher.get_client_id_status(@cid_1)
assert_equal ret["result"], "Online"
end
def test_to_single_notification
single_message = IGeTui::SingleMessage.new
single_message.data = notification_template
ret = @pusher.push_message_to_single(single_message, @client_1)
assert_equal ret["result"], "ok"
end
def test_to_single_transmission
single_message = IGeTui::SingleMessage.new
single_message.data = transmission_template
ret = @pusher.push_message_to_single(single_message, @client_1)
assert_equal ret["result"], "ok"
end
def test_to_list_transmission
list_message = IGeTui::ListMessage.new
list_message.data = transmission_template
client_list = [@client_1, @client_2]
content_id = @pusher.get_content_id(list_message)
ret = @pusher.push_message_to_list(content_id, client_list)
assert_equal ret["result"], "ok"
end
def test_to_app_notification
app_message = IGeTui::AppMessage.new
app_message.data = notification_template
app_message.app_id_list = [@app_id]
# app_message.province_list = ['浙江', '上海']
# app_message.tag_list = ['开心']
ret = @pusher.push_message_to_app(app_message)
assert_equal ret["result"], "ok"
end
private
def notification_template
template = IGeTui::NotificationTemplate.new
template.logo = 'push.png'
template.logo_url = 'http://www.igetui.com/wp-content/uploads/2013/08/logo_getui1.png'
template.title = '测试标题'
template.text = '测试文本'
template
end
def transmission_template
template = IGeTui::TransmissionTemplate.new
# Notice: content should be string.
content = {
action: "notification",
title: "标题aaa",
content: "内容",
type: "article",
id: "4274"
}
content = content.to_s.gsub(":", "").gsub("=>", ":")
template.transmission_content = content
template
end
end
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment