config.dhall.sample 🔗
@@ -39,6 +39,7 @@
xep0157 = [
{ var = "support-addresses", value = "xmpp:+14169938000@cheogram.com" }
],
+ notify_admin = "muc_or_user@example.com",
sip_host = "sip.jmp.chat",
plans = [
{
Stephen Paul Weber created
Notify only once per day (using expiring redis key).
Can notify MUC or user, always sends directed presence first so it will join MUC
if not joined.
Ignore all messages direct to the component, mostly to throw out live messages
from MUC if we join that to notify.
config.dhall.sample | 1 +
lib/customer.rb | 2 +-
lib/customer_usage.rb | 30 +++++++++++++++++++++++++++++-
sgx_jmp.rb | 33 +++++++++++++++++++++------------
4 files changed, 52 insertions(+), 14 deletions(-)
@@ -39,6 +39,7 @@
xep0157 = [
{ var = "support-addresses", value = "xmpp:+14169938000@cheogram.com" }
],
+ notify_admin = "muc_or_user@example.com",
sip_host = "sip.jmp.chat",
plans = [
{
@@ -49,7 +49,7 @@ class Customer
def_delegators :@plan, :active?, :activate_plan_starting_now, :bill_plan,
:currency, :merchant_account, :plan_name
def_delegators :@sgx, :register!, :registered?
- def_delegator :@usage, :report, :usage_report
+ def_delegators :@usage, :usage_report, :message_usage, :incr_message_usage
def initialize(
customer_id,
@@ -7,7 +7,7 @@ class CustomerUsage
@customer_id = customer_id
end
- def report(range)
+ def usage_report(range)
EMPromise.all([
messages_by_day(range),
minutes_by_day(range)
@@ -16,6 +16,34 @@ class CustomerUsage
end
end
+ def expire_message_usage
+ today = Time.now.utc.to_date
+ REDIS.zremrangebylex(
+ "jmp_customer_outbound_messages-#{@customer_id}",
+ "-",
+ # Store message counts per day for 1 year
+ "[#{(today << 12).strftime('%Y%m%d')}"
+ )
+ end
+
+ def incr_message_usage(amount=1)
+ today = Time.now.utc.to_date
+ EMPromise.all([
+ expire_message_usage,
+ REDIS.zincrby(
+ "jmp_customer_outbound_messages-#{@customer_id}",
+ amount,
+ today.strftime("%Y%m%d")
+ )
+ ])
+ end
+
+ def message_usage(range)
+ messages_by_day(range).then do |by_day|
+ by_day.values.sum
+ end
+ end
+
def messages_by_day(range)
EMPromise.all(range.first.downto(range.last).map { |day|
REDIS.zscore(
@@ -163,28 +163,37 @@ before nil, to: /\Acustomer_/, from: /(\A|@)#{CONFIG[:sgx]}(\/|\Z)/ do |s|
halt
end
+# Ignore messages to component
+# Especially if we have the component join MUC for notifications
+message(to: /\A#{CONFIG[:component][:jid]}\Z/) {}
+
message do |m|
sentry_hub = new_sentry_hub(m, name: "message")
+ today = Time.now.utc.to_date
Customer.for_jid(m.from.stripped).then { |customer|
sentry_hub.current_scope.set_user(
id: customer.customer_id,
jid: m.from.stripped.to_s
)
- today = Time.now.utc.to_date
EMPromise.all([
- REDIS.zremrangebylex(
- "jmp_customer_outbound_messages-#{customer.customer_id}",
- "-",
- # Store message counts per day for 1 year
- "[#{(today << 12).strftime('%Y%m%d')}"
- ),
- REDIS.zincrby(
- "jmp_customer_outbound_messages-#{customer.customer_id}",
- 1,
- today.strftime("%Y%m%d")
- ),
+ customer,
+ customer.incr_message_usage,
+ REDIS.exists("jmp_usage_notify-#{customer.customer_id}"),
customer.stanza_from(m)
])
+ }.then { |(customer, _, already, _)|
+ next if already == 1
+
+ customer.message_usage((today..(today - 30))).then do |usage|
+ next unless usage > 500
+
+ BLATHER.join(CONFIG[:notify_admin], "sgx-jmp")
+ BLATHER.say(
+ CONFIG[:notify_admin],
+ "#{customer.customer_id} has used #{usage} messages since #{today - 30}"
+ )
+ REDIS.set("jmp_usage_notify-#{customer.customer_id}", ex: 60 * 60 * 24)
+ end
}.catch { |e| panic(e, sentry_hub) }
end