Commit 04818c90 by liangyuzhe

代码重构

parent d2b2b524
......@@ -37,3 +37,5 @@
# Ignore master key for decrypting credentials and more.
/config/master.key
/config/database.yml
ruby-2.6.0
\ No newline at end of file
ruby-2.6.5
\ No newline at end of file
......@@ -2,12 +2,13 @@ source 'https://gems.ruby-china.com'
git_source(:github) { |repo| "https://github.com/#{repo}.git" }
ruby '2.6.0'
ruby '2.6.5'
# Bundle edge Rails instead: gem 'rails', github: 'rails/rails'
gem 'rails', '~> 5.2.2', '>= 5.2.2.1'
gem 'rails', '~> 6.0.1'
# Use sqlite3 as the database for Active Record
gem 'sqlite3'
# gem 'sqlite3'
gem 'mysql2', '~> 0.5.3'
# Use Puma as the app server
gem 'puma', '~> 3.11'
# Use SCSS for stylesheets
......
GEM
remote: https://gems.ruby-china.com/
specs:
actioncable (5.2.3)
actionpack (= 5.2.3)
actioncable (6.0.1)
actionpack (= 6.0.1)
nio4r (~> 2.0)
websocket-driver (>= 0.6.1)
actionmailer (5.2.3)
actionpack (= 5.2.3)
actionview (= 5.2.3)
activejob (= 5.2.3)
actionmailbox (6.0.1)
actionpack (= 6.0.1)
activejob (= 6.0.1)
activerecord (= 6.0.1)
activestorage (= 6.0.1)
activesupport (= 6.0.1)
mail (>= 2.7.1)
actionmailer (6.0.1)
actionpack (= 6.0.1)
actionview (= 6.0.1)
activejob (= 6.0.1)
mail (~> 2.5, >= 2.5.4)
rails-dom-testing (~> 2.0)
actionpack (5.2.3)
actionview (= 5.2.3)
activesupport (= 5.2.3)
actionpack (6.0.1)
actionview (= 6.0.1)
activesupport (= 6.0.1)
rack (~> 2.0)
rack-test (>= 0.6.3)
rails-dom-testing (~> 2.0)
rails-html-sanitizer (~> 1.0, >= 1.0.2)
actionview (5.2.3)
activesupport (= 5.2.3)
rails-html-sanitizer (~> 1.0, >= 1.2.0)
actiontext (6.0.1)
actionpack (= 6.0.1)
activerecord (= 6.0.1)
activestorage (= 6.0.1)
activesupport (= 6.0.1)
nokogiri (>= 1.8.5)
actionview (6.0.1)
activesupport (= 6.0.1)
builder (~> 3.1)
erubi (~> 1.4)
rails-dom-testing (~> 2.0)
rails-html-sanitizer (~> 1.0, >= 1.0.3)
activejob (5.2.3)
activesupport (= 5.2.3)
rails-html-sanitizer (~> 1.1, >= 1.2.0)
activejob (6.0.1)
activesupport (= 6.0.1)
globalid (>= 0.3.6)
activemodel (5.2.3)
activesupport (= 5.2.3)
activerecord (5.2.3)
activemodel (= 5.2.3)
activesupport (= 5.2.3)
arel (>= 9.0)
activestorage (5.2.3)
actionpack (= 5.2.3)
activerecord (= 5.2.3)
activemodel (6.0.1)
activesupport (= 6.0.1)
activerecord (6.0.1)
activemodel (= 6.0.1)
activesupport (= 6.0.1)
activestorage (6.0.1)
actionpack (= 6.0.1)
activejob (= 6.0.1)
activerecord (= 6.0.1)
marcel (~> 0.3.1)
activesupport (5.2.3)
activesupport (6.0.1)
concurrent-ruby (~> 1.0, >= 1.0.2)
i18n (>= 0.7, < 2)
minitest (~> 5.1)
tzinfo (~> 1.1)
addressable (2.6.0)
public_suffix (>= 2.0.2, < 4.0)
airbrussh (1.3.1)
zeitwerk (~> 2.2)
addressable (2.7.0)
public_suffix (>= 2.0.2, < 5.0)
airbrussh (1.4.0)
sshkit (>= 1.6.1, != 1.7.0)
archive-zip (0.12.0)
io-like (~> 0.3.0)
arel (9.0.0)
bindex (0.7.0)
bootsnap (1.4.4)
bindex (0.8.1)
bootsnap (1.4.5)
msgpack (~> 1.0)
builder (3.2.3)
byebug (11.0.1)
capistrano (3.11.0)
capistrano (3.11.2)
airbrussh (>= 1.0.0)
i18n
rake (>= 10.0.0)
sshkit (>= 1.9.0)
capistrano-bundler (1.5.0)
capistrano-bundler (1.6.0)
capistrano (~> 3.1)
capistrano-rails (1.4.0)
capistrano (~> 3.1)
......@@ -67,23 +80,22 @@ GEM
capistrano-rvm (0.1.2)
capistrano (~> 3.0)
sshkit (~> 1.2)
capistrano-sidekiq (1.0.2)
capistrano-sidekiq (1.0.3)
capistrano (>= 3.9.0)
sidekiq (>= 3.4)
sidekiq (>= 3.4, < 6.0)
capistrano3-puma (3.1.1)
capistrano (~> 3.7)
capistrano-bundler
puma (~> 3.4)
capybara (3.20.2)
capybara (3.29.0)
addressable
mini_mime (>= 0.1.3)
nokogiri (~> 1.8)
rack (>= 1.6.0)
rack-test (>= 0.6.3)
regexp_parser (~> 1.2)
regexp_parser (~> 1.5)
xpath (~> 3.2)
childprocess (1.0.1)
rake (< 13.0)
childprocess (3.0.0)
chromedriver-helper (2.1.1)
archive-zip (~> 0.10)
nokogiri (~> 1.8)
......@@ -96,17 +108,17 @@ GEM
coffee-script-source (1.12.2)
concurrent-ruby (1.1.5)
connection_pool (2.2.2)
crass (1.0.4)
erubi (1.8.0)
crass (1.0.5)
erubi (1.9.0)
execjs (2.7.0)
ffi (1.11.1)
ffi (1.11.3)
globalid (0.4.2)
activesupport (>= 4.2.0)
god (0.13.7)
httparty (0.13.7)
json (~> 1.8)
multi_xml (>= 0.5.2)
i18n (1.6.0)
i18n (1.7.0)
concurrent-ruby (~> 1.0)
igetui-ruby (1.2.2)
json (~> 1.8, >= 1.8.1)
......@@ -119,7 +131,7 @@ GEM
rb-fsevent (~> 0.9, >= 0.9.4)
rb-inotify (~> 0.9, >= 0.9.7)
ruby_dep (~> 1.2)
loofah (2.2.3)
loofah (2.4.0)
crass (~> 1.0.2)
nokogiri (>= 1.5.9)
mail (2.7.1)
......@@ -128,62 +140,65 @@ GEM
mimemagic (~> 0.3.2)
method_source (0.9.2)
mimemagic (0.3.3)
mini_mime (1.0.1)
mini_mime (1.0.2)
mini_portile2 (2.4.0)
minitest (5.11.3)
msgpack (1.2.10)
minitest (5.13.0)
msgpack (1.3.1)
multi_xml (0.6.0)
net-scp (1.2.1)
net-ssh (>= 2.6.5)
net-ssh (5.1.0)
nio4r (2.3.1)
nokogiri (1.10.3)
mysql2 (0.5.3)
net-scp (2.0.0)
net-ssh (>= 2.6.5, < 6.0.0)
net-ssh (5.2.0)
nio4r (2.5.2)
nokogiri (1.10.7)
mini_portile2 (~> 2.4.0)
public_suffix (3.0.3)
puma (3.12.1)
public_suffix (4.0.1)
puma (3.12.2)
rack (2.0.7)
rack-protection (2.0.5)
rack-protection (2.0.7)
rack
rack-test (1.1.0)
rack (>= 1.0, < 3)
rails (5.2.3)
actioncable (= 5.2.3)
actionmailer (= 5.2.3)
actionpack (= 5.2.3)
actionview (= 5.2.3)
activejob (= 5.2.3)
activemodel (= 5.2.3)
activerecord (= 5.2.3)
activestorage (= 5.2.3)
activesupport (= 5.2.3)
rails (6.0.1)
actioncable (= 6.0.1)
actionmailbox (= 6.0.1)
actionmailer (= 6.0.1)
actionpack (= 6.0.1)
actiontext (= 6.0.1)
actionview (= 6.0.1)
activejob (= 6.0.1)
activemodel (= 6.0.1)
activerecord (= 6.0.1)
activestorage (= 6.0.1)
activesupport (= 6.0.1)
bundler (>= 1.3.0)
railties (= 5.2.3)
railties (= 6.0.1)
sprockets-rails (>= 2.0.0)
rails-dom-testing (2.0.3)
activesupport (>= 4.2.0)
nokogiri (>= 1.6)
rails-html-sanitizer (1.0.4)
loofah (~> 2.2, >= 2.2.2)
rails-html-sanitizer (1.3.0)
loofah (~> 2.3)
rails_param (0.10.2)
railties (5.2.3)
actionpack (= 5.2.3)
activesupport (= 5.2.3)
railties (6.0.1)
actionpack (= 6.0.1)
activesupport (= 6.0.1)
method_source
rake (>= 0.8.7)
thor (>= 0.19.0, < 2.0)
rake (12.3.2)
thor (>= 0.20.3, < 2.0)
rake (13.0.1)
rb-fsevent (0.10.3)
rb-inotify (0.10.0)
ffi (~> 1.0)
redis (3.3.5)
redis-actionpack (5.0.2)
actionpack (>= 4.0, < 6)
redis-actionpack (5.1.0)
actionpack (>= 4.0, < 7)
redis-rack (>= 1, < 3)
redis-store (>= 1.1.0, < 2)
redis-activesupport (5.0.7)
activesupport (>= 3, < 6)
redis-activesupport (5.2.0)
activesupport (>= 3, < 7)
redis-store (>= 1.3, < 2)
redis-rack (2.0.5)
redis-rack (2.0.6)
rack (>= 1.5, < 3)
redis-store (>= 1.2, < 2)
redis-rails (5.0.2)
......@@ -192,32 +207,31 @@ GEM
redis-store (>= 1.2, < 2)
redis-store (1.6.0)
redis (>= 2.2, < 5)
regexp_parser (1.5.0)
regexp_parser (1.6.0)
ruby-protocol-buffers (1.6.1)
ruby_dep (1.5.0)
rubyzip (1.2.2)
rubyzip (2.0.0)
sass (3.7.4)
sass-listen (~> 4.0.0)
sass-listen (4.0.0)
rb-fsevent (~> 0.9, >= 0.9.4)
rb-inotify (~> 0.9, >= 0.9.7)
sass-rails (5.0.7)
railties (>= 4.0.0, < 6)
sass-rails (5.1.0)
railties (>= 5.2.0)
sass (~> 3.1)
sprockets (>= 2.8, < 4.0)
sprockets-rails (>= 2.0, < 4.0)
tilt (>= 1.1, < 3)
selenium-webdriver (3.142.2)
childprocess (>= 0.5, < 2.0)
rubyzip (~> 1.2, >= 1.2.2)
selenium-webdriver (3.142.6)
childprocess (>= 0.5, < 4.0)
rubyzip (>= 1.2.2)
settingslogic (2.0.9)
sidekiq (4.2.10)
concurrent-ruby (~> 1.0)
connection_pool (~> 2.2, >= 2.2.0)
rack-protection (>= 1.5.0)
redis (~> 3.2, >= 3.2.1)
spring (2.0.2)
activesupport (>= 4.2)
spring (2.1.0)
spring-watcher-listen (2.0.1)
listen (>= 2.7, < 4.0)
spring (>= 1.2, < 3.0)
......@@ -228,30 +242,30 @@ GEM
actionpack (>= 4.0)
activesupport (>= 4.0)
sprockets (>= 3.0.0)
sqlite3 (1.4.1)
sshkit (1.18.0)
sshkit (1.20.0)
net-scp (>= 1.1.2)
net-ssh (>= 2.8.0)
thor (0.20.3)
thread_safe (0.3.6)
tilt (2.0.9)
turbolinks (5.2.0)
tilt (2.0.10)
turbolinks (5.2.1)
turbolinks-source (~> 5.2)
turbolinks-source (5.2.0)
tzinfo (1.2.5)
thread_safe (~> 0.1)
uglifier (4.1.20)
uglifier (4.2.0)
execjs (>= 0.3.0, < 3)
web-console (3.7.0)
actionview (>= 5.0)
activemodel (>= 5.0)
web-console (4.0.1)
actionview (>= 6.0.0)
activemodel (>= 6.0.0)
bindex (>= 0.4.0)
railties (>= 5.0)
websocket-driver (0.7.0)
railties (>= 6.0.0)
websocket-driver (0.7.1)
websocket-extensions (>= 0.1.0)
websocket-extensions (0.1.3)
websocket-extensions (0.1.4)
xpath (3.2.0)
nokogiri (~> 1.8)
zeitwerk (2.2.2)
PLATFORMS
ruby
......@@ -272,8 +286,9 @@ DEPENDENCIES
igetui-ruby
jbuilder (~> 2.5)
listen (>= 3.0.5, < 3.2)
mysql2 (~> 0.5.3)
puma (~> 3.11)
rails (~> 5.2.2, >= 5.2.2.1)
rails (~> 6.0.1)
rails_param (~> 0.10.2)
redis-rails (~> 5.0, >= 5.0.2)
sass-rails (~> 5.0)
......@@ -282,14 +297,13 @@ DEPENDENCIES
sidekiq (~> 4.1, >= 4.1.2)
spring
spring-watcher-listen (~> 2.0.0)
sqlite3
turbolinks (~> 5)
tzinfo-data
uglifier (>= 1.3.0)
web-console (>= 3.3.0)
RUBY VERSION
ruby 2.6.0p0
ruby 2.6.5p114
BUNDLED WITH
1.17.2
1.17.3
class ApplicationController < ActionController::Base
rescue_from StandardError, with: :rescue_all
include Token
def rescue_all(e)
ErrorLog.error(e)
......
module Token
extend ActiveSupport::Concern
ACCESS_TOEKN_EXPIRE_TIME = 7200
class << self
def key(app_name)
"push:api:#{app_name}:access_token"
def validate_token(app_name, token)
!! (token == get_token(app_name))
end
def token_ttl(app_name)
$redis.ttl(tkey(app_name))
end
def generate_token(app_name)
token = SecureRandom.hex(32)
$redis.set(key(app_name), token, ex: ACCESS_TOEKN_EXPIRE_TIME)
$redis.set(tkey(app_name), token, ex: ACCESS_TOEKN_EXPIRE_TIME)
token
end
def token(app_name)
$redis.get(key(app_name))
end
private
def ttl(app_name)
$redis.ttl(key(app_name))
def tkey(app_name)
"push:api:#{app_name}:access_token"
end
def get_token(app_name)
$redis.get(tkey(app_name))
end
end
\ No newline at end of file
......@@ -9,44 +9,113 @@ class PushsController < ApplicationController
app_setting = Settings.send(params[:app_name].to_sym) rescue {}
if app_setting['app_id'] == params[:app_id] && app_setting['app_secret'] == params[:app_secret]
render json: { code: 0, message: 'success', token: Token.generate_token(params[:app_name]), ttl: Token.ttl(params[:app_name])}
render json: { code: 0, message: 'success', token: generate_token(params[:app_name]), ttl: token_ttl(params[:app_name])}
else
render json: { code: -1, message: '应用不存在或者app_id/app_secret不匹配'}
end
end
# app_name 应用名称
# user_device_ids 设备ids
# message 推送信息的json 字符串
# igetui_opts 个推推送的额外选项
def push
def single
param! :app_name, String, required: true
param! :device_ids_opts, String, required: true
# param! :device_ids_opts, String, required: true
param! :message, String, required: true
param! :igetui_opts, String
param! :app_type, String
param! :sync_push, String
param! :user_id, String, required: true
igetui_opts = JSON.parse(params[:igetui_opts]) rescue {}
message = JSON.parse(params[:message]) rescue {}
device_ids_opts = JSON.parse(params[:device_ids_opts]) rescue {}
user_id = JSON.parse(params[:user_id]) rescue ""
user_device_exist = UserDevice.where(user_id: user_id).exists?
unless user_device_exist
render json: { code: -1, message: 'user_device找不到,user_id错误'}
end
token = token_and_options(request).first
if token == Token.token(params[:app_name])
if params.has_key?(:sync_push)
if validate_token(params[:app_name], token)
push_sync(params[:sync_push], {user_ids: Array.new(user_id), message: message, app_type: params[:app_type], igetui_opts: igetui_opts.merge(pusher_type: 'push_message_to_single')})
render json: { code: 0, message: 'success', describe: '异步任务正在处理'}
else
render json: { code: -1, message: 'token 错误/过期'}
end
end
def batch
param! :app_name, String, required: true
# param! :device_ids_opts, String, required: true
param! :message, String, required: true
param! :igetui_opts, String
param! :app_type, String
param! :sync_push, String
param! :user_ids, Array, required: true
igetui_opts = JSON.parse(params[:igetui_opts]) rescue {}
message = JSON.parse(params[:message]) rescue {}
user_ids = JSON.parse(params[:user_ids]) rescue []
user_devices_exists = UserDevice.where(user_id: user_ids).exists?
unless user_devices_exists
render json: { code: -1, message: 'user_device找不到,user_ids错误'}
end
token = token_and_options(request).first
if validate_token(params[:app_name], token)
push_sync(params[:sync_push], {user_ids: user_ids, message: message, app_type: params[:app_type], igetui_opts: igetui_opts.merge(pusher_type: 'push_message_to_list')})
render json: { code: 0, message: 'success', describe: '异步任务正在处理'}
else
render json: { code: -1, message: 'token 错误/过期'}
end
end
# app_name 应用名称
# user_device_ids 设备ids
# message 推送信息的json 字符串
# # igetui_opts 个推推送的额外选项
# def push
# param! :app_name, String, required: true
# # param! :device_ids_opts, String, required: true
# param! :message, String, required: true
# param! :igetui_opts, String
# param! :app_type, String
# param! :sync_push, String
# param! :user_ids, Array, required: true
#
# igetui_opts = JSON.parse(params[:igetui_opts]) rescue {}
# message = JSON.parse(params[:message]) rescue {}
# user_ids = JSON.parse(params[:user_ids]) rescue {}
#
# token = token_and_options(request).first
# if token == Token.token(params[:app_name])
# push_sync(params[:sync_push], {user_ids: user_ids, message: message, igetui_opts: igetui_opts})
#
# render json: { code: 0, message: 'success', describe: '异步任务正在处理'}
# else
# render json: { code: -1, message: 'token 错误/过期'}
# end
# end
private
def push_sync(sync_push, opts={})
if sync_push
timeout_seconds = $redis.get('push_timeout').to_i
if timeout_seconds > 0
Timeout.timeout(timeout_seconds) {
::PushWorker.new.perform(device_ids_opts, message, igetui_opts, params[:app_type])
::PushWorker.new.perform(opts)
}
else
::PushWorker.new.perform(device_ids_opts, message, igetui_opts, params[:app_type])
::PushWorker.new.perform(opts)
end
else
::PushWorker.perform_async(device_ids_opts, message, igetui_opts, params[:app_type])
end
render json: { code: 0, message: 'success', describe: '异步任务正在处理'}
else
render json: { code: -1, message: 'token 错误/过期'}
::PushWorker.perform_async(opts)
end
end
end
class UserDevice < ApplicationRecord
# 当前app端传递的platform的值:
# android: igetui, xiaomi, huawei
# iso: igetui 目前还不清楚为啥不用apns,暂时不修改
enum platform: %i[igetui apns xiaomi huawei]
enum device_platform: %i[ios android]
# 用于区分当前的应用,为了推送准备, 因为推送需要根据不同的应用使用不同的 id,secret等。
enum app_type: %i[ik_duli lx_duli lx_yun]
end
\ No newline at end of file
module Push
module Huawei
module Huawei
class Base
ACCESS_TOKEN_KEY = "push:huawei_push:access_token".freeze
TOKEN_URL = 'https://login.cloud.huawei.com/oauth2/v2/token'.freeze
PUSH_URL = 'https://api.push.hicloud.com/pushsend.do'.freeze
ACCESS_TOEKN_EXPIRE_TIME = 3500
BATCH_PUSH_MAX = 80
class << self
def initialize(device_ids, message)
@device_tokens = device_ids
@message = message
end
# 4a7d376b47c847634571a86b37e93272 测试使用的device_token
def push(device_tokens, message)
def perform
device_tokens = @device_tokens
message = @message
handle_token_res if access_token.blank?
device_tokens.each_slice(BATCH_PUSH_MAX) do |device_token_array|
res = res_push(message, device_token_array)
......@@ -19,7 +26,7 @@ module Push
end
end
rescue StandardError => err
Push::Log.error(err)
::Log.error(err)
end
def res_push(message, device_tokens)
......@@ -43,7 +50,7 @@ module Push
}
}
}
Push::Log.info("huawei_payload: #{payload}, device_tokens: #{device_tokens}")
::Log.info("huawei_payload: #{payload}, device_tokens: #{device_tokens}")
params = {
access_token: CGI.escape(access_token),
nsp_svc: CGI.escape('openpush.message.api.send'),
......@@ -85,9 +92,8 @@ module Push
def post(url, body)
headers = { 'Content-Type' => 'application/x-www-form-urlencoded' }
response = HTTParty.post(url, body: body, headers: headers, timeout: 5)
Push::Log.info("huawei_push: \n access_token: #{access_token} expire_time: #{$redis.ttl(Push::Huawei::ACCESS_TOKEN_KEY)}\n url: #{url}\n body: #{body}\n response: #{response}")
::Log.info("huawei_push: \n access_token: #{access_token} expire_time: #{$redis.ttl(Push::Huawei::ACCESS_TOKEN_KEY)}\n url: #{url}\n body: #{body}\n response: #{response}")
JSON.parse(response.body)
end
end
end
end
module Igetui
class AndroidPusher
include Singleton
def self.pusher
$android_pusher ||=
IGeTui.pusher(
Settings.platform_settings.igetui.android['app_id'],
Settings.platform_settings.igetui.android['app_key'],
Settings.platform_settings.igetui.android['master_secret']
)
end
end
end
\ No newline at end of file
module Igetui
class Base
def initialize(user_device_ids, opts)
opts = HashWithIndifferentAccess.new(opts)
@template_data = opts[:template_data]
@igetui_opts = opts[:igetui_opts]
@user_device_ids = user_device_ids
@pusher = pusher(opts[:device_platform])
@pusher_type = opts[:pusher_type]
end
def perform
@template_data[:push_type] ||= config[:push_type]
@igetui_opts[:transmission_type] ||= 0
@igetui_opts[:transmission_content] = @template_data.as_json
template_type = 'TransmissionTemplate'
template_data = @igetui_opts
result = push_message_to(@pusher, @pusher_type, template_type, template_data, @user_device_ids)
::Log.info("igetui_push: \n template_data: #{template_data}\n user_device_ids: #{@user_device_ids}\n response: #{result}")
end
private
def pusher(device_platform)
case device_platform
when 'android'
Igetui::AndroidPusher.pusher
when 'ios'
Igetui::IosPusher.pusher
end
end
def push_message_to(pusher, pusher_type, template_type, template_data, client_id)
client_id_list = Array(client_id)
template = set_template_data(template_type, template_data)
case pusher_type
when 'push_message_to_single'
message = IGeTui::SingleMessage.new
message.data = template
client_id_list.map do |client_id|
client = IGeTui::Client.new(client_id)
pusher.push_message_to_single(message, client)
end
when 'push_message_to_list'
message = IGeTui::ListMessage.new
message.data = template
content_id = pusher.get_content_id(message)
clients = client_id_list.map { |client_id| IGeTui::Client.new(client_id) }
pusher.push_message_to_list(content_id, clients)
when 'push_message_to_app'
message = IGeTui::AppMessage.new
message.data = template
message.app_id_list = client_id_list
pusher.push_message_to_app(message)
end
end
def set_template_data(template_type, template_data)
@template ||= "IGeTui::#{template_type}".constantize.new
case template_type
when 'NotificationTemplate', 'NotyPopLoadTemplate', 'LinkTemplate'
template_data.reverse_merge!(Settings.platform_settings.igetui['template_base'])
template_data.each do |k, v|
@template.send("#{k}=", v)
end
@template.set_push_info(*template_data[:push_info]) if template_data.key? :push_info
when 'TransmissionTemplate'
@template.transmission_content = template_data[:transmission_content].is_a?(Hash) ? template_data[:transmission_content].to_json : template_data[:transmission_content]
@template.transmission_type = template_data[:transmission_type] if template_data.key?(:transmission_type)
@template.set_push_info(*template_data[:push_info]) if template_data.key? :push_info
end
end
end
end
module Igetui
class IosPusher
include Singleton
def self.pusher
$android_pusher ||=
IGeTui.pusher(
Settings.platform_settings.igetui.ios['app_id'],
Settings.platform_settings.igetui.ios['app_key'],
Settings.platform_settings.igetui.ios['master_secret']
)
end
end
end
\ No newline at end of file
module Push
class << self
# 调用推送服务,推送信息
# message 要推送的具体信息
# opts 是hash类型,主要是一些其他的信息。
# 由于历史遗留问题,封装的不够好,这里主要用来处理个推的一些参数。
# 目前华为推送,小米推送不会用到这里的信息。
# device_ids_opts, 用户设备信息是hash数组。
# device_ids_opts = {
# igetui: [],
# apns: [],
# xiaomi: [],
# huawei: []
# }
def push(device_ids_opts, message, igetui_opts = {}, app_type = nil)
Settings.platform = app_type || Settings::DEFAULT
Push::Log.info("*************** push_service ***************:\n device_ids_opts: #{device_ids_opts}, message: #{message}, igetui_opts: #{igetui_opts} platform: #{Settings.platform}")
message = message.with_indifferent_access
igetui_opts = igetui_opts.with_indifferent_access
# igetui
Push::Igetui.push(device_ids_opts['igetui'], message, igetui_opts) if device_ids_opts['igetui'].present?
Push::Igetui.push(device_ids_opts['apns'], message, igetui_opts) if device_ids_opts['apns'].present?
# xiaomi
# https://dev.mi.com/console/doc/detail?pId=1163 文档中心
Push::Xiaomi.push(device_ids_opts['xiaomi'], message) if device_ids_opts['xiaomi'].present?
# huawei
# https://developer.huawei.com/consumer/cn/service/hms/catalog/huaweipush_agent.html?page=hmssdk_huaweipush_api_reference_agent_s1 接入文档
Push::Huawei.push(device_ids_opts['huawei'], message) if device_ids_opts['huawei'].present?
# etc
rescue StandardError => err
Push::Log.error(err)
end
end
end
module Push
module Igetui
class << self
def push(user_device_ids, template_data = {}, opts = {})
# 包装成igetui 真正需要的参数格式
opts[:transmission_content] = template_data
if user_device_ids.size > 1
push_transmission_to_list_igetui(user_device_ids, opts)
else
push_transmission_to_igetui(user_device_ids, opts)
end
rescue StandardError => err
::Push::Log.error(err)
end
def config
{
push_type: 2
}
end
def push_transmission_to_igetui(user_device_id, template_data = {})
template_data = handle_template_data(template_data)
push_igetui_with_asnyc(
user_device_id,
template_data,
template_type: 'TransmissionTemplate'
)
end
def push_transmission_to_list_igetui(user_device_ids, template_data = {})
template_data = handle_template_data(template_data)
push_list_igetui_with_asnyc(
user_device_ids,
template_data,
template_type: 'TransmissionTemplate', pusher_type: 'push_message_to_list'
)
end
private
def handle_template_data(template_data)
template_data = HashWithIndifferentAccess.new(template_data)
transmission_content = HashWithIndifferentAccess.new(template_data.delete(:transmission_content))
transmission_content[:push_type] ||= config[:push_type]
template_data[:transmission_type] ||= 0
template_data[:transmission_content] = transmission_content.as_json
template_data
end
def push_igetui_with_asnyc(user_device_id, template_data = {}, opts = nil)
return if template_data.blank?
opts ||= HashWithIndifferentAccess.new(template_type: 'TransmissionTemplate')
template_data = HashWithIndifferentAccess.new(template_data)
perform(template_data, opts, user_device_id)
end
def push_list_igetui_with_asnyc(user_device_ids, template_data = {}, opts = { pusher_type: 'push_message_to_list' })
return if user_device_ids.blank? || template_data.blank?
opts ||= HashWithIndifferentAccess.new(template_type: 'TransmissionTemplate')
perform(template_data, opts, user_device_ids)
end
def perform(template_data, opts, user_device_ids)
opts = HashWithIndifferentAccess.new(opts)
igetui = Igetui::Push.new(template_data, opts)
result = igetui.push_message_to(user_device_ids)
::Push::Log.info("igetui_push: \n template_data: #{template_data}\n opts: #{opts}\n user_device_ids: #{user_device_ids}\n response: #{result}")
end
end
end
end
\ No newline at end of file
module Push
module Igetui
class Push
attr_accessor :pusher, :pusher_type, :template_type, :template, :template_data
PUSHERTYPES = %w[push_message_to_single push_message_to_list push_message_to_app].freeze
TEMPLATETYPES = %w[LinkTemplate NotificationTemplate TransmissionTemplate NotyPopLoadTemplate].freeze
DEVICEPLATFORMS = %w[android ios].freeze
def initialize(template_data, opts = {})
opts = HashWithIndifferentAccess.new(opts)
@template_data = HashWithIndifferentAccess.new(template_data || {})
@pusher_type = PUSHERTYPES.include?((opts[:pusher_type]).to_s) ? opts[:pusher_type] : 'push_message_to_single'
@template_type = TEMPLATETYPES.include?((opts[:template_type]).to_s) ? opts[:template_type] : 'NotificationTemplate'
::Push::Log.info("@template_data is #{@template_data.to_json}")
set_message
set_template_data
@message.data = @template
end
def push_message_to(client_id)
client_id_list = Array(client_id)
case pusher_type
when 'push_message_to_single'
client_id_list.map do |client_id|
client = IGeTui::Client.new(client_id)
pusher.push_message_to_single(@message, client)
end
when 'push_message_to_list'
content_id = pusher.get_content_id(@message)
clients = client_id_list.map { |client_id| IGeTui::Client.new(client_id) }
pusher.push_message_to_list(content_id, clients)
when 'push_message_to_app'
@message.app_id_list = client_id_list
pusher.push_message_to_app(@message)
end
end
private
def pusher
@pusher ||=
if DEVICEPLATFORMS.include?((@template_data['device_platform'].to_s))
case @template_data['device_platform'].to_s
when 'android'
IGeTui.pusher(
Settings.platform_settings.igetui.android['app_id'],
Settings.platform_settings.igetui.android['app_key'],
Settings.platform_settings.igetui.android['master_secret']
)
when 'ios'
IGeTui.pusher(
Settings.platform_settings.igetui.ios['app_id'],
Settings.platform_settings.igetui.ios['app_key'],
Settings.platform_settings.igetui.ios['master_secret']
)
end
else
::Push::Log.info("设备类型不正确#{@device_platform}")
raise "Failed to create pusher"
end
end
def set_message
@message = case pusher_type
when 'push_message_to_single'
IGeTui::SingleMessage.new
when 'push_message_to_list'
IGeTui::ListMessage.new
when 'push_message_to_app'
IGeTui::AppMessage.new
end
end
def set_template_data
@template = "IGeTui::#{template_type}".constantize.new
case template_type
when 'NotificationTemplate', 'NotyPopLoadTemplate', 'LinkTemplate'
@template_data.reverse_merge!(Settings.platform_settings.igetui['template_base'])
@template_data.each do |k, v|
@template.send("#{k}=", v)
end
@template.set_push_info(*@template_data[:push_info]) if @template_data.key? :push_info
when 'TransmissionTemplate'
@template.transmission_content = @template_data[:transmission_content].is_a?(Hash) ? @template_data[:transmission_content].to_json : @template_data[:transmission_content]
@template.transmission_type = @template_data[:transmission_type] if @template_data.key?(:transmission_type)
@template.set_push_info(*@template_data[:push_info]) if @template_data.key? :push_info
end
end
end
end
end
#push功能的代理选择用哪种推送工具1.个推 2.小米 3.华为
class PushToolClient
def initialize(opts={})
opts = HashWithIndifferentAccess.new(opts)
@user_ids = opts[:user_ids]
@opts = opts
end
def do_push
Settings.platform = @opts[:app_type] || Settings::DEFAULT
@push_device_collections ||= UserDevice.where(user_id: @user_ids).group_by(&:platform)
@igetui_push_device_collections ||= @push_device_collections.group_by(&:device_platform)
igetui_android_device_ids = @igetui_push_device_collections['android'].map(&:device_id)
igetui_ios_device_ids = @igetui_push_device_collections['ios'].map(&:device_id)
Igetui::Base.new(igetui_android_device_ids, @opts.merge(device_platform: 'android')).perform if igetui_android_device_ids.present?
Igetui::Base.new(igetui_ios_device_ids, @opts.merge(device_platform: 'ios')).perform if igetui_ios_device_ids.present?
#现在好像不用了
# Push::IgetuiIos.push(@push_collections[:igetui_ios], @opts) if @push_collections[:apns].present?
# Push::IgetuiAndroid.push(@push_collections[:igetui_android], @opts) if @push_collections[:apns].present?
xiaomi_device_ids = @push_device_collections['xiaomi'].map(&:device_id)
huawei_device_ids = @push_device_collections['huawei'].map(&:device_id)
Xiaomi::Base.new.(xiaomi_device_ids, @opts[:message]).perform if xiaomi_device_ids.present?
Huawei::Base.new.(huawei_device_ids, @opts[:message]).perform if huawei_device_ids.present?
end
end
\ No newline at end of file
module Push
module Xiaomi
module Xiaomi
class Base
PUSH_URL = 'https://api.xmpush.xiaomi.com/v3/message/regid'.freeze
BATCH_PUSH_MAX = 80
class << self
def push(registration_ids, payload)
def initialize(device_ids, message)
@registration_ids = device_ids
@payload = message
end
def perform
registration_ids = @registration_ids
payload = @payload
registration_ids.each_slice(BATCH_PUSH_MAX) do |registration_ids_array|
registration_id = registration_ids_array.join(',')
post(message(payload, registration_id))
end
rescue StandardError => err
Push::Log.error(err)
::Log.error(err)
end
def message(payload, registration_id)
......@@ -45,9 +52,8 @@ module Push
"Authorization": "key=#{Settings.platform_settings.xiaomi['app_secret']}"
},
timeout: 5)
Push::Log.info("xiaomi_push: \n url: #{PUSH_URL}\n params: #{params}\n response: #{response}")
::Log.info("xiaomi_push: \n url: #{PUSH_URL}\n params: #{params}\n response: #{response}")
response
end
end
end
end
......@@ -2,8 +2,9 @@ class PushWorker
include Sidekiq::Worker
sidekiq_options queue: :push
def perform(device_ids_opts, message, igetui_opts, platform = nil)
Push.push(device_ids_opts, message, igetui_opts, platform)
def perform(opts)
::PushToolClient.do_push(opts)
# Push.push(user_ids, message, igetui_opts, platform)
rescue StandardError => e
ErrorLog.error(e)
end
......
......@@ -5,13 +5,17 @@
# gem 'sqlite3'
#
default: &default
adapter: sqlite3
adapter: mysql2
encoding: utf8
host: rm-m5ef10gzq1n5e7b9abo.mysql.rds.aliyuncs.com
username: crm_rw
password: pHB+!*Uv9Rl9
pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>
timeout: 5000
development:
<<: *default
database: db/development.sqlite3
database: crm_dev
# Warning: The database defined as "test" will be erased and
# re-generated from your development database when you run "rake".
......
default: &default
adapter: mysql2
encoding: utf8
host: rm-m5ef10gzq1n5e7b9abo.mysql.rds.aliyuncs.com
username: crm_rw
password: pHB+!*Uv9Rl9
pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>
timeout: 5000
development:
<<: *default
database: crm_dev
# Warning: The database defined as "test" will be erased and
# re-generated from your development database when you run "rake".
# Do not set this db to the same as development or production.
test:
<<: *default
database: db/test.sqlite3
production:
<<: *default
database: db/production.sqlite3
module Push
module Log
module Log
class << self
def info(info)
logger.tagged(Time.zone.now) { logger.info info }
......@@ -16,5 +15,4 @@ module Push
@logger ||= ActiveSupport::TaggedLogging.new(::Logger.new("#{Rails.root}/log/various_push.log", 'weekly'))
end
end
end
end
\ No newline at end of file
Rails.application.routes.draw do
# For details on the DSL available within this file, see http://guides.rubyonrails.org/routing.html
post 'api/v1/token', to: 'pushs#token'
post 'api/v1/push', to: 'pushs#push'
post 'api/v1/single', to: 'pushs#single'
post 'api/v1/batch', to: 'pushs#batch'
require 'sidekiq/web'
mount Sidekiq::Web => '/sidekiq'
......
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