Files
archived-hc-harbor/app/models/physical_mail.rb
2025-10-30 13:57:21 -04:00

124 lines
3.4 KiB
Ruby

class PhysicalMail < ApplicationRecord
belongs_to :user
include PublicActivity::Model
# tracked only: [ :update ], owner: :user, params: {
# mission_type: ->(controller, model) { model.mission_type },
# humanized_mission_type: ->(controller, model) { model.humanized_mission_type }
# }
after_create :create_streak_activity, if: :first_time_7_streak?
after_update :create_sent_activity, if: :became_sent?
scope :going_out, -> { where(status: :pending).or(where(status: :sent)) }
enum :status, {
pending: 0,
sent: 1,
failed: 2
}
enum :mission_type, {
admin_mail: 0,
first_time_7_streak: 1
}
def self.instant_mission_types
%w[first_time_7_streak]
end
scope :pending_delivery, -> {
where(status: :pending)
.joins(:user)
.joins("INNER JOIN mailing_addresses ON mailing_addresses.user_id = users.id")
}
def link_to_theseus
return nil if theseus_id.nil?
"https://hack.club/#{theseus_id}"
end
def humanized_mission_type
return "Your first 7-day streak" if first_time_7_streak?
mission_type.titleize
end
def deliver!
return if status == :sent || theseus_id.present?
slug = "hackatime-#{mission_type.to_s.gsub("_", "-")}"
endpoint = if self.class.instant_mission_types.include?(mission_type)
"https://mail.hackclub.com/api/v1/letter_queues/instant/#{slug}-instant"
else
"https://mail.hackclub.com/api/v1/letter_queues/#{slug}"
end
flavors = FlavorText.compliment
flavors.concat(FlavorText.rare_compliment) if rand(10) == 0
return nil unless user.mailing_address.present?
# authorization: Bearer <token>
response = HTTP.auth("Bearer #{ENV["MAIL_HACKCLUB_TOKEN"]}").post(endpoint, json: {
recipient_email: user.email_addresses.first.email,
address: {
first_name: user.mailing_address.first_name,
last_name: user.mailing_address.last_name,
line_1: user.mailing_address.line_1,
line_2: user.mailing_address.line_2,
city: user.mailing_address.city,
state: user.mailing_address.state,
postal_code: user.mailing_address.zip_code,
country: user.mailing_address.country
},
rubber_stamps: flavors.sample,
idempotency_key: "physical_mail_#{id}",
metadata: {
attributes: attributes
}
})
if response.status.success?
data = JSON.parse(response.body.to_s)
puts "Successfully delivered physical mail: #{data["id"]}"
update(status: :sent, theseus_id: data["id"])
else
update(status: :failed)
raise "Failed to deliver physical mail: #{response.body}"
end
rescue OpenSSL::SSL::SSLError => e
Rails.logger.warn "SSL error during mail delivery (request likely succeeded): #{e.message}"
update(status: :sent)
rescue => e
update(status: :failed)
raise e
end
private
def user_address
user.mailing_address
end
def became_sent?
saved_change_to_status? && status == "sent" && status_before_last_save == "pending"
end
def create_streak_activity
create_activity :first_streak_achieved, owner: user, params: {
mission_type: mission_type,
humanized_mission_type: humanized_mission_type
}
end
def create_sent_activity
create_activity :mail_sent, owner: user, params: {
mission_type: mission_type,
humanized_mission_type: humanized_mission_type
}
end
end