Merged in fix_plg_email_delivery_timeing_issue (pull request #70)
fix PLG email timing Approved-by: Seth Call
This commit is contained in:
commit
6a6e4cde09
|
|
@ -3,7 +3,14 @@
|
|||
execute "ALTER TABLE users ADD COLUMN trial_expires_reminder1_sent_at TIMESTAMP"
|
||||
execute "ALTER TABLE users ADD COLUMN trial_expires_reminder2_sent_at TIMESTAMP"
|
||||
execute "ALTER TABLE users ADD COLUMN trial_expires_reminder3_sent_at TIMESTAMP"
|
||||
end
|
||||
|
||||
# slide in some more production indexes
|
||||
execute "CREATE INDEX index_users_on_first_music_session_at ON users USING btree (first_music_session_at)"
|
||||
# subscription_sync_code
|
||||
execute "CREATE INDEX index_users_on_subscription_sync_code ON users USING btree (subscription_sync_code)"
|
||||
# first_certified_gear_at
|
||||
execute "CREATE INDEX index_users_on_first_certified_gear_at ON users USING btree (first_certified_gear_at)"
|
||||
end
|
||||
def self.down
|
||||
execute "ALTER TABLE users DROP COLUMN trial_expires_reminder1_sent_at"
|
||||
execute "ALTER TABLE users DROP COLUMN trial_expires_reminder2_sent_at"
|
||||
|
|
|
|||
|
|
@ -436,7 +436,7 @@ module JamRuby
|
|||
sendgrid_substitute('@USERID', [user.id])
|
||||
sendgrid_unique_args :type => "profile_complete_reminder2"
|
||||
|
||||
mail(:to => user.email, :subject => "Take 2 minutes to fill out your JamKazam profile now") do |format|
|
||||
mail(:to => user.email, :subject => I18n.t('user_mailer.profile_complete_reminder2.subject')) do |format|
|
||||
format.text
|
||||
format.html { render layout: "user_mailer_beta" }
|
||||
end
|
||||
|
|
@ -448,7 +448,7 @@ module JamRuby
|
|||
sendgrid_substitute('@USERID', [user.id])
|
||||
sendgrid_unique_args :type => "profile_complete_reminder3"
|
||||
|
||||
mail(:to => user.email, :subject => "Last reminder to update your JamKazam profile") do |format|
|
||||
mail(:to => user.email, :subject => I18n.t('user_mailer.profile_complete_reminder3.subject')) do |format|
|
||||
format.text
|
||||
format.html { render layout: "user_mailer_beta" }
|
||||
end
|
||||
|
|
|
|||
|
|
@ -4,20 +4,22 @@ module JamRuby
|
|||
|
||||
def self.send_reminders
|
||||
begin
|
||||
cutoff_date = Date.parse(Rails.application.config.profile_complete_reminders_effective_from_date) # Define a cutoff date for the profile completion emails
|
||||
#If the user has not updated their profile 1 day after signup, then send reminder email1
|
||||
reminder1_users.find_each do |user|
|
||||
reminder1_users(cutoff_date).find_each do |user|
|
||||
puts "reminder1_users user: #{user.id}"
|
||||
UserMailer.profile_complete_reminder1(user).deliver_now
|
||||
User.where(id: user.id).update_all(profile_complete_reminder1_sent_at: Time.now)
|
||||
end
|
||||
|
||||
#If the user has not updated their profile 3 days after signup, then send reminder email2
|
||||
reminder2_users.find_each do |user|
|
||||
reminder2_users(cutoff_date).find_each do |user|
|
||||
UserMailer.profile_complete_reminder2(user).deliver_now
|
||||
User.where(id: user.id).update_all(profile_complete_reminder2_sent_at: Time.now)
|
||||
end
|
||||
|
||||
#If the user has not updated their profile 5 days after signup, then send reminder email3
|
||||
reminder3_users.find_each do |user|
|
||||
reminder3_users(cutoff_date).find_each do |user|
|
||||
UserMailer.profile_complete_reminder3(user).deliver_now
|
||||
User.where(id: user.id).update_all(profile_complete_reminder3_sent_at: Time.now)
|
||||
end
|
||||
|
|
@ -31,18 +33,20 @@ module JamRuby
|
|||
User.where("users.profile_completed_at IS NULL AND users.subscribe_email = ?", true)
|
||||
end
|
||||
|
||||
def self.reminder1_users
|
||||
EmailProfileReminder.prospect_users.where("users.created_at < ? AND users.profile_complete_reminder1_sent_at IS NULL", 1.day.ago)
|
||||
def self.reminder1_users(cutoff_date)
|
||||
# ensure that the user has had the account for at least one day
|
||||
puts "reminder1_users cutoff_date: #{cutoff_date}"
|
||||
EmailProfileReminder.prospect_users.where("users.created_at > ? AND users.profile_complete_reminder1_sent_at IS NULL AND (NOW() - users.created_at) > INTERVAL '1 day'", cutoff_date)
|
||||
end
|
||||
|
||||
def self.reminder2_users
|
||||
EmailProfileReminder.prospect_users.where("users.created_at < ? AND users.profile_complete_reminder1_sent_at IS NOT NULL AND users.profile_complete_reminder2_sent_at IS NULL", 3.days.ago)
|
||||
def self.reminder2_users(cutoff_date)
|
||||
# ensure that the user has had the account for at least three days and guard against rapid back-to-back emails
|
||||
EmailProfileReminder.prospect_users.where("users.created_at > ? AND users.profile_complete_reminder1_sent_at < ? AND users.profile_complete_reminder1_sent_at IS NOT NULL AND users.profile_complete_reminder2_sent_at IS NULL", cutoff_date, 2.days.ago)
|
||||
end
|
||||
|
||||
def self.reminder3_users
|
||||
EmailProfileReminder.prospect_users.where("users.created_at < ? AND users.profile_complete_reminder2_sent_at IS NOT NULL AND users.profile_complete_reminder3_sent_at IS NULL", 5.days.ago)
|
||||
def self.reminder3_users(cutoff_date)
|
||||
# ensure that user has had the profile for 5 days and guard against rapid back-to-back emails
|
||||
EmailProfileReminder.prospect_users.where("users.created_at > ? AND users.profile_complete_reminder2_sent_at < ? AND users.profile_complete_reminder2_sent_at IS NOT NULL AND users.profile_complete_reminder3_sent_at IS NULL", cutoff_date, 2.days.ago)
|
||||
end
|
||||
|
||||
|
||||
end
|
||||
end
|
||||
|
|
@ -28,19 +28,19 @@ module JamRuby
|
|||
end
|
||||
|
||||
def self.prospect_users
|
||||
User.where("users.first_certified_gear_at IS NULL")
|
||||
User.where("users.first_certified_gear_at IS NULL AND users.subscribe_email = ?", true)
|
||||
end
|
||||
|
||||
def self.reminder1_users(cutoff_date)
|
||||
GearSetupReminder.prospect_users.where("users.created_at < ? AND users.created_at > ? AND users.gear_setup_reminder1_sent_at IS NULL", 1.day.ago, cutoff_date)
|
||||
GearSetupReminder.prospect_users.where("users.created_at > ? AND users.gear_setup_reminder1_sent_at IS NULL AND (NOW() - users.created_at) > INTERVAL '1 day'", cutoff_date)
|
||||
end
|
||||
|
||||
def self.reminder2_users(cutoff_date)
|
||||
GearSetupReminder.prospect_users.where("users.created_at < ? AND users.created_at > ? AND users.gear_setup_reminder1_sent_at IS NOT NULL AND users.gear_setup_reminder2_sent_at IS NULL", 3.days.ago, cutoff_date)
|
||||
GearSetupReminder.prospect_users.where("users.created_at > ? AND users.gear_setup_reminder1_sent_at IS NOT NULL AND users.gear_setup_reminder2_sent_at IS NULL AND users.gear_setup_reminder1_sent_at < ?", cutoff_date, 2.days.ago)
|
||||
end
|
||||
|
||||
def self.reminder3_users(cutoff_date)
|
||||
GearSetupReminder.prospect_users.where("users.created_at < ? AND users.created_at > ? AND users.gear_setup_reminder2_sent_at IS NOT NULL AND users.gear_setup_reminder3_sent_at IS NULL", 5.days.ago, cutoff_date)
|
||||
GearSetupReminder.prospect_users.where("users.created_at > ? AND users.gear_setup_reminder2_sent_at IS NOT NULL AND users.gear_setup_reminder3_sent_at IS NULL AND users.gear_setup_reminder2_sent_at < ?", cutoff_date, 2.days.ago)
|
||||
end
|
||||
|
||||
end
|
||||
|
|
|
|||
|
|
@ -36,11 +36,11 @@ module JamRuby
|
|||
end
|
||||
|
||||
def self.reminder2_users(cutoff_date)
|
||||
GroupSessionReminder.prospect_users.where("users.created_at > ? AND users.group_session_reminder1_sent_at IS NOT NULL AND users.group_session_reminder2_sent_at IS NULL AND users.first_music_session_at < ?", cutoff_date, 3.days.ago)
|
||||
GroupSessionReminder.prospect_users.where("users.created_at > ? AND users.group_session_reminder1_sent_at IS NOT NULL AND users.group_session_reminder2_sent_at IS NULL AND users.first_music_session_at < ? AND group_session_reminder1_sent_at < ?", cutoff_date, 3.days.ago, 1.day.ago)
|
||||
end
|
||||
|
||||
def self.reminder3_users(cutoff_date)
|
||||
GroupSessionReminder.prospect_users.where("users.created_at > ? AND users.group_session_reminder2_sent_at IS NOT NULL AND users.group_session_reminder3_sent_at IS NULL AND users.first_music_session_at < ?", cutoff_date, 5.days.ago)
|
||||
GroupSessionReminder.prospect_users.where("users.created_at > ? AND users.group_session_reminder2_sent_at IS NOT NULL AND users.group_session_reminder3_sent_at IS NULL AND users.first_music_session_at < ? AND group_session_reminder2_sent_at < ?", cutoff_date, 5.days.ago, 1.day.ago)
|
||||
end
|
||||
|
||||
end
|
||||
|
|
|
|||
|
|
@ -27,19 +27,19 @@ module JamRuby
|
|||
end
|
||||
|
||||
def self.prospect_users
|
||||
User.where("users.first_music_session_at IS NULL")
|
||||
User.where("users.first_music_session_at IS NULL AND first_certified_gear_at IS NOT NULL")
|
||||
end
|
||||
|
||||
def self.reminder1_users(cutoff_date)
|
||||
TestGearReminder.prospect_users.where("users.first_certified_gear_at < ? AND users.created_at >= ? AND users.test_gear_reminder1_sent_at IS NULL", 1.day.ago, cutoff_date)
|
||||
TestGearReminder.prospect_users.where("users.created_at > ? AND users.test_gear_reminder1_sent_at IS NULL AND (NOW() - users.first_certified_gear_at) > INTERVAL '1 day'", cutoff_date)
|
||||
end
|
||||
|
||||
def self.reminder2_users(cutoff_date)
|
||||
TestGearReminder.prospect_users.where("users.first_certified_gear_at < ? AND users.created_at >= ? AND users.test_gear_reminder1_sent_at IS NOT NULL AND users.test_gear_reminder2_sent_at IS NULL", 3.days.ago, cutoff_date)
|
||||
TestGearReminder.prospect_users.where("users.created_at > ? AND users.test_gear_reminder1_sent_at IS NOT NULL AND users.test_gear_reminder2_sent_at IS NULL AND users.test_gear_reminder1_sent_at < ?", cutoff_date, 2.days.ago)
|
||||
end
|
||||
|
||||
def self.reminder3_users(cutoff_date)
|
||||
TestGearReminder.prospect_users.where("users.first_certified_gear_at < ? AND users.created_at > ? AND users.test_gear_reminder2_sent_at IS NOT NULL AND users.test_gear_reminder3_sent_at IS NULL", 5.days.ago, cutoff_date)
|
||||
TestGearReminder.prospect_users.where("users.created_at > ? AND users.test_gear_reminder2_sent_at IS NOT NULL AND users.test_gear_reminder3_sent_at IS NULL AND users.test_gear_reminder2_sent_at < ?", cutoff_date, 2.days.ago)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -8,24 +8,26 @@ module JamRuby
|
|||
class TrialExpiresReminder
|
||||
@@log = Logging.logger[TrialExpiresReminder]
|
||||
|
||||
FIRST_NOTIFICATION_CHECK = 1.day.ago.to_s
|
||||
SECOND_NOTIFICATION_CHECK = 5.days.ago.to_s
|
||||
THIRD_NOTIFICATION_CHECK = 9.days.ago
|
||||
FIRST_NOTIFICATION_CHECK = 1.day.ago
|
||||
# unused here, but just as a form of simple documentation...
|
||||
# SECOND_NOTIFICATION_CHECK = 4.days (from the previous reminder)
|
||||
# THIRD_NOTIFICATION_CHECK = 4.days (from the previous reminder)
|
||||
|
||||
def self.prospect_users(cutoff_date)
|
||||
User.where("(users.subscription_trial_ends_at IS NOT NULL AND users.subscription_trial_ends_at > ?)", cutoff_date)
|
||||
User.where("(users.subscription_trial_ends_at IS NOT NULL AND users.created_at > ?)", cutoff_date)
|
||||
end
|
||||
|
||||
# trial_ended | in_trial
|
||||
def self.reminder1_users(cutoff_date)
|
||||
prospect_users(cutoff_date).where("users.subscription_last_checked_at < ? AND users.subscription_trial_ends_at < ? AND users.trial_expires_reminder1_sent_at IS NULL", 1.day.ago, FIRST_NOTIFICATION_CHECK)
|
||||
prospect_users(cutoff_date).where("users.subscription_sync_code = 'trial_ended' AND users.subscription_trial_ends_at < ? AND users.trial_expires_reminder1_sent_at IS NULL", FIRST_NOTIFICATION_CHECK)
|
||||
end
|
||||
|
||||
def self.reminder2_users(cutoff_date)
|
||||
prospect_users(cutoff_date).where("users.subscription_last_checked_at < ? AND users.subscription_trial_ends_at < ? AND trial_expires_reminder1_sent_at IS NOT NULL AND users.trial_expires_reminder2_sent_at IS NULL", 1.day.ago, SECOND_NOTIFICATION_CHECK)
|
||||
prospect_users(cutoff_date).where("users.subscription_sync_code = 'trial_ended' AND trial_expires_reminder1_sent_at IS NOT NULL AND users.trial_expires_reminder2_sent_at IS NULL AND (NOW() - trial_expires_reminder1_sent_at) > INTERVAL '4 days'")
|
||||
end
|
||||
|
||||
def self.reminder3_users(cutoff_date)
|
||||
prospect_users(cutoff_date).where("users.subscription_last_checked_at < ? AND users.subscription_trial_ends_at < ? AND trial_expires_reminder2_sent_at IS NOT NULL AND users.trial_expires_reminder3_sent_at IS NULL", 1.day.ago, THIRD_NOTIFICATION_CHECK)
|
||||
prospect_users(cutoff_date).where("users.subscription_sync_code = 'trial_ended' AND trial_expires_reminder2_sent_at IS NOT NULL AND users.trial_expires_reminder3_sent_at IS NULL AND (NOW() - trial_expires_reminder2_sent_at) > INTERVAL '4 days'")
|
||||
end
|
||||
|
||||
def self.send_reminders
|
||||
|
|
|
|||
|
|
@ -19,13 +19,19 @@ describe TrialExpiresReminder do
|
|||
ActionMailer::Base.deliveries.clear
|
||||
end
|
||||
|
||||
def no_more_emails_sent
|
||||
UserMailer.deliveries.clear
|
||||
TrialExpiresReminder.send_reminders
|
||||
expect(ActionMailer::Base.deliveries.count).to eq(0)
|
||||
end
|
||||
|
||||
it "sends reminder emails to users whose trials are about to expire" do
|
||||
user1.subscription_trial_ends_at = 1.days.from_now
|
||||
user1.subscription_last_checked_at = 2.days.ago
|
||||
user1.subscription_sync_code = 'trial_ended'
|
||||
user1.save!
|
||||
|
||||
user2.subscription_trial_ends_at = 1.days.ago
|
||||
user2.subscription_last_checked_at = 2.days.ago
|
||||
user2.subscription_trial_ends_at = 2.days.ago
|
||||
user2.subscription_sync_code = 'trial_ended'
|
||||
user2.save!
|
||||
|
||||
TrialExpiresReminder.send_reminders
|
||||
|
|
@ -36,11 +42,14 @@ describe TrialExpiresReminder do
|
|||
expect(ActionMailer::Base.deliveries.last.subject).to include("Your free gold trial has expired, but you have great options to keep playing!")
|
||||
|
||||
expect(user2.reload.trial_expires_reminder1_sent_at).not_to be_nil
|
||||
|
||||
no_more_emails_sent
|
||||
end
|
||||
|
||||
it "does not send reminder emails to users who have already received them" do
|
||||
user1.subscription_trial_ends_at = 1.days.ago
|
||||
user1.subscription_last_checked_at = 2.days.ago
|
||||
user1.reload
|
||||
user1.subscription_trial_ends_at = 1.days.ago + 1.hour
|
||||
user1.subscription_sync_code = 'trial_ended'
|
||||
user1.trial_expires_reminder1_sent_at = Time.now
|
||||
user1.save!
|
||||
|
||||
|
|
@ -50,31 +59,38 @@ describe TrialExpiresReminder do
|
|||
end
|
||||
|
||||
it "sends the second reminder email to users whose trials are about to expire" do
|
||||
user1.subscription_trial_ends_at = 4.days.ago
|
||||
user1.subscription_last_checked_at = 1.days.ago
|
||||
user1.trial_expires_reminder1_sent_at = Time.now
|
||||
user1.reload
|
||||
user2.reload
|
||||
|
||||
# pretend that the first reminder email was sent 2 days ago
|
||||
user1.subscription_trial_ends_at = 4.days.ago + 1.hour
|
||||
user1.subscription_sync_code = 'trial_ended'
|
||||
user1.trial_expires_reminder1_sent_at = 5.days.ago
|
||||
user1.save!
|
||||
|
||||
user2.subscription_trial_ends_at = 5.days.ago
|
||||
user2.subscription_last_checked_at = 1.days.ago
|
||||
user2.subscription_trial_ends_at = 4.days.ago + 1.hour
|
||||
user2.subscription_sync_code = 'trial_ended'
|
||||
user2.trial_expires_reminder1_sent_at = Time.now
|
||||
user2.save!
|
||||
|
||||
TrialExpiresReminder.send_reminders
|
||||
|
||||
expect(ActionMailer::Base.deliveries.count).to eq(1)
|
||||
expect(ActionMailer::Base.deliveries.map(&:to).flatten).to include(user2.email)
|
||||
expect(ActionMailer::Base.deliveries.map(&:to).flatten).to include(user1.email)
|
||||
# Check if the second reminder email was sent by verifying the subject
|
||||
expect(ActionMailer::Base.deliveries.last.subject).to include("Don’t forget to check your options to keep playing")
|
||||
|
||||
expect(user2.reload.trial_expires_reminder2_sent_at).not_to be_nil
|
||||
expect(user1.reload.trial_expires_reminder2_sent_at).not_to be_nil
|
||||
|
||||
no_more_emails_sent
|
||||
end
|
||||
|
||||
it "sends the third reminder email to users whose trials are about to expire" do
|
||||
user1.subscription_trial_ends_at = 10.days.ago
|
||||
user1.subscription_last_checked_at = 1.days.ago
|
||||
user1.trial_expires_reminder1_sent_at = 6.days.ago
|
||||
user1.trial_expires_reminder2_sent_at = 4.days.ago
|
||||
user1.reload
|
||||
user1.subscription_trial_ends_at = 10.days.ago + 1.hour
|
||||
user1.subscription_sync_code = 'trial_ended'
|
||||
user1.trial_expires_reminder1_sent_at = 8.days.ago
|
||||
user1.trial_expires_reminder2_sent_at = 9.days.ago
|
||||
user1.save!
|
||||
|
||||
TrialExpiresReminder.send_reminders
|
||||
|
|
@ -85,22 +101,28 @@ describe TrialExpiresReminder do
|
|||
expect(ActionMailer::Base.deliveries.last.subject).to include("One last reminder!")
|
||||
|
||||
expect(user1.reload.trial_expires_reminder3_sent_at).not_to be_nil
|
||||
|
||||
no_more_emails_sent
|
||||
end
|
||||
|
||||
it "sends first and second and third reminder emails to users whose trials are about to expire" do
|
||||
user1.reload
|
||||
user2.reload
|
||||
user3.reload
|
||||
|
||||
user1.subscription_trial_ends_at = 2.days.ago
|
||||
user1.subscription_last_checked_at = 1.days.ago
|
||||
user1.subscription_sync_code = 'trial_ended'
|
||||
user1.save!
|
||||
|
||||
user2.subscription_trial_ends_at = 6.days.ago
|
||||
user2.subscription_last_checked_at = 1.days.ago
|
||||
user2.trial_expires_reminder1_sent_at = 4.days.ago
|
||||
user2.subscription_trial_ends_at = 2.days.ago
|
||||
user2.trial_expires_reminder1_sent_at = 5.days.ago
|
||||
user2.subscription_sync_code = 'trial_ended'
|
||||
user2.save!
|
||||
|
||||
user3.subscription_trial_ends_at = 10.days.ago
|
||||
user3.subscription_last_checked_at = 2.days.ago
|
||||
user3.trial_expires_reminder1_sent_at = 6.days.ago
|
||||
user3.trial_expires_reminder2_sent_at = 4.days.ago
|
||||
user3.subscription_trial_ends_at = 2.days.ago
|
||||
user3.trial_expires_reminder1_sent_at = 8.days.ago
|
||||
user3.trial_expires_reminder2_sent_at = 9.days.ago
|
||||
user3.subscription_sync_code = 'trial_ended'
|
||||
user3.save!
|
||||
|
||||
TrialExpiresReminder.send_reminders
|
||||
|
|
@ -112,5 +134,6 @@ describe TrialExpiresReminder do
|
|||
expect(ActionMailer::Base.deliveries.count).to eq(3)
|
||||
expect(ActionMailer::Base.deliveries.map(&:to).flatten).to include(user1.email, user2.email, user3.email)
|
||||
|
||||
no_more_emails_sent
|
||||
end
|
||||
end
|
||||
|
|
@ -523,6 +523,7 @@ if defined?(Bundler)
|
|||
config.signup_survey_url = "https://www.surveymonkey.com/r/WVBKLYL"
|
||||
|
||||
config.signup_survey_cutoff_date = "2025-06-10"
|
||||
config.profile_complete_reminders_effective_from_date = "2025-06-10"
|
||||
config.gear_setup_reminders_effective_from_date = "2025-06-10"
|
||||
config.test_gear_reminders_effective_from_date = "2025-07-24"
|
||||
config.group_session_reminders_effective_from_date = "2025-08-12"
|
||||
|
|
|
|||
|
|
@ -128,6 +128,7 @@ SampleApp::Application.configure do
|
|||
config.send_user_match_mail_only_to_jamkazam_team = false
|
||||
config.signup_survey_url = "https://www.surveymonkey.com/r/WVBKLYL"
|
||||
config.signup_survey_cutoff_date = "2025-06-10"
|
||||
config.profile_complete_reminders_effective_from_date = "2025-06-10"
|
||||
config.gear_setup_reminders_effective_from_date = "2025-06-10"
|
||||
config.test_gear_reminders_effective_from_date = "2025-07-24"
|
||||
config.group_session_reminders_effective_from_date = "2025-08-12"
|
||||
|
|
|
|||
|
|
@ -84,7 +84,7 @@ en:
|
|||
regards: "Best Regards,"
|
||||
signature: "JamKazam Team"
|
||||
profile_complete_reminder2:
|
||||
subject: "Complete your JamKazam profile"
|
||||
subject: "Take 2 minutes to fill out your JamKazam profile now"
|
||||
greeting: "Hello"
|
||||
paragraph1: "We share your profile with JamKazam members who may be a good fit to play music with you during your first week on the platform via an automated email feature. Don’t miss this opportunity to connect. Click the button below to update your profile now, before it’s shared with others!"
|
||||
update_profile: "Update Profile"
|
||||
|
|
@ -92,7 +92,7 @@ en:
|
|||
regards: "Best Regards,"
|
||||
signature: "JamKazam Team"
|
||||
profile_complete_reminder3:
|
||||
subject: "Complete your JamKazam profile"
|
||||
subject: "Last reminder to update your JamKazam profile"
|
||||
greeting: "Hello"
|
||||
paragraph1: "Your profile is your key to connecting with other musicians on JamKazam. It lets others know what instruments you play at what level of proficiency and what kinds of music you like to play. This lets our existing community find and reach out to you to connect and play, and this information also powers our automated matchmaking features that make recommendations to you. If you think you might want to play music live online on JamKazam, please click the button below now to fill out your profile!"
|
||||
update_profile: "Update Profile"
|
||||
|
|
|
|||
Loading…
Reference in New Issue