GeekPark/gpk_account

View on GitHub
app/models/concerns/pushable.rb

Summary

Maintainability
A
0 mins
Test Coverage
module Pushable
  extend ActiveSupport::Concern

  def set_notification_info(title: '', extra_info: {}, to: [])
    Rails.logger.info("title是")
    Rails.logger.info(title)
    Rails.logger.info(@title)
    @title      = title
    @extra_info = extra_info
    @target     = to
    self
  end

  def quietly(quiet = true)
    @quiet = quiet
    self
  end

  def development_only(dev_only = true)
    @development_only = dev_only
    self
  end

  def without_android(x = true)
    @without_android = x
    self
  end

  def without_ios(x = true)
    @without_ios = x
    self
  end

  def jpush_notification(at: :now)
    payload = generate_payload

    return if @target.is_a?(Array) && @target.map { |t| t.devices.most_recent&.registration_id }.compact.blank?

    return if Rails.env.test?

    case at
    when :now
      JPush::JPushClientPusher.push(payload)
    else
      scheduled_payload = JPush::Schedule::SchedulePayload.new(
        'test_task',
        JPush::Schedule::Trigger.new.set_single(at),
        payload
      )
      JPush::Schedule.create(scheduled_payload)
    end
  end

  private

  def notification_platform
    platform = %w(ios android)
    platform.delete('android') if @without_android
    platform.delete('ios')     if @without_ios
    platform
  end

  def generate_payload
    apns_prod = @development_only || Rails.env.production?
    JPush::Push::PushPayload.new(
      platform:     notification_platform,
      audience:     target_audience,
      notification: to_jpush_notification,
      message:      'hello'
    ).set_options(apns_production: apns_prod)
  end

  def ios_options
    Rails.logger.info("title是")
    Rails.logger.info(instance_variables.map {|a| [a, instance_variable_get(:@a)]})

    options = {
      alert:            @title,
      contentavailable: false,
      mutablecontent:   nil,
      category:         nil,
      extras: { data: @extra_info, type: self.class.notifi_type }
    }

    unless @quietly
      # options[:sound] = 'Sounds.mp3'
      options[:sound] = 'sosumi.aiff'
      options[:badge] = 1
      Rails.logger.info("声音")
      Rails.logger.info(options.inspect)
    end

    options[:mutablecontent] = true if content_type == 'topic_type'

    # 文章类型的推送不显示角标
    options[:badge] = 0 if content_type == 'topic_type'

    set_post_type(options)

    Rails.logger.info("title是")
    Rails.logger.info(options)

    options
  end

  def android_options
    options = {
      alert: @title,
      extras: { data: @extra_info, type: self.class.notifi_type }
    }
    options[:alert_type] = 0 if @quietly

    set_post_type(options)
    
    options[:builder_id] = 2 if content_type == 'topic_type'

    set_parent_type(options) if content_type == 'comment'

    options
  end

  def set_post_type(options)
    if content_type == 'topic_type'
      post = JSON.parse(Faraday.get(ENV["MAIN_BASE"] + "posts/#{redirect}").body)
      options[:extras].merge!(post_type: post["post"]["post_type"])
      options[:extras].merge!(attachment: post["post"]["cover_url"])
    end
  end

  def set_parent_type(options)
      if Faraday.get(ENV["MAIN_BASE"] + "posts/#{direct_id}").success?
        options[:extras][:data].merge!(parent_type: "post")
      else
        options[:extras][:data].merge!(parent_type: "question")
      end
  end

  def to_jpush_notification
    notification = JPush::Push::Notification.new
    notification.set_ios     ios_options
    notification.set_android android_options
  end

  def target_audience
    return 'all' if @target == :all || @target == 'all'

    reg_ids = if Rails.env.test? || !@target.is_a?(Array)
                []
              else
                @target.map do |u|
                  u.devices.most_recent&.registration_id
                end.compact
              end

    audience = JPush::Push::Audience.new
    audience.set_registration_id(reg_ids)
  end

  class_methods do
    attr_reader :notifi_type
    def notification_type(type)
      @notifi_type = type if %w(broadcast notification).include?(type)
    end
  end
end