mirror of
https://github.com/discourse/discourse.git
synced 2025-05-30 07:11:34 +08:00
FEATURE: Custom unsubscribe options (#17090)
With this change, plugins can create custom unsubscribe keys, extend the unsubscribe view with custom preferences, and decide how they are updated.
This commit is contained in:
@ -6,38 +6,17 @@ class EmailController < ApplicationController
|
||||
skip_before_action :check_xhr, :preload_json, :redirect_to_login_if_required
|
||||
|
||||
def unsubscribe
|
||||
@not_found = true
|
||||
@watched_count = nil
|
||||
key = UnsubscribeKey.find_by(key: params[:key])
|
||||
@found = key.present?
|
||||
|
||||
if key = UnsubscribeKey.find_by(key: params[:key])
|
||||
if @user = key.user
|
||||
post = key.post
|
||||
@topic = post&.topic || key.topic
|
||||
@digest_unsubscribe = !@topic && !SiteSetting.disable_digest_emails
|
||||
@type = key.unsubscribe_key_type
|
||||
@not_found = false
|
||||
if @found
|
||||
UnsubscribeKey
|
||||
.get_unsubscribe_strategy_for(key)
|
||||
&.prepare_unsubscribe_options(self)
|
||||
|
||||
if current_user.present? && (@user != current_user)
|
||||
@different_user = @user.name
|
||||
@return_url = request.original_url
|
||||
end
|
||||
|
||||
watching = TopicUser.notification_levels[:watching]
|
||||
|
||||
@unsubscribed_from_all = @user.user_option.unsubscribed_from_all?
|
||||
|
||||
if @topic
|
||||
@watching_topic = TopicUser.exists?(user_id: @user.id, notification_level: watching, topic_id: @topic.id)
|
||||
if @topic.category_id
|
||||
if CategoryUser.exists?(user_id: @user.id, notification_level: CategoryUser.watching_levels, category_id: @topic.category_id)
|
||||
@watched_count = TopicUser.joins(:topic)
|
||||
.where(user: @user, notification_level: watching, "topics.category_id" => @topic.category_id)
|
||||
.count
|
||||
end
|
||||
end
|
||||
else
|
||||
@digest_frequencies = digest_frequencies(@user)
|
||||
end
|
||||
if current_user.present? && (@user != current_user)
|
||||
@different_user = @user.name
|
||||
@return_url = request.original_url
|
||||
end
|
||||
end
|
||||
end
|
||||
@ -46,80 +25,24 @@ class EmailController < ApplicationController
|
||||
RateLimiter.new(nil, "unsubscribe_#{request.ip}", 10, 1.minute).performed!
|
||||
|
||||
key = UnsubscribeKey.find_by(key: params[:key])
|
||||
raise Discourse::NotFound unless key && key.user
|
||||
|
||||
topic = key&.post&.topic || key.topic
|
||||
raise Discourse::NotFound if key.nil? || key.user.nil?
|
||||
user = key.user
|
||||
updated = UnsubscribeKey.get_unsubscribe_strategy_for(key)
|
||||
&.unsubscribe(params)
|
||||
|
||||
updated = false
|
||||
if updated
|
||||
cache_key = "unsub_#{SecureRandom.hex}"
|
||||
Discourse.cache.write cache_key, user.email, expires_in: 1.hour
|
||||
|
||||
if topic
|
||||
if params["unwatch_topic"]
|
||||
TopicUser.where(topic_id: topic.id, user_id: user.id)
|
||||
.update_all(notification_level: TopicUser.notification_levels[:tracking])
|
||||
updated = true
|
||||
end
|
||||
|
||||
if params["unwatch_category"] && topic.category_id
|
||||
TopicUser.joins(:topic)
|
||||
.where(:user => user,
|
||||
:notification_level => TopicUser.notification_levels[:watching],
|
||||
"topics.category_id" => topic.category_id)
|
||||
.update_all(notification_level: TopicUser.notification_levels[:tracking])
|
||||
|
||||
CategoryUser.where(user_id: user.id,
|
||||
category_id: topic.category_id,
|
||||
notification_level: CategoryUser.watching_levels
|
||||
)
|
||||
.destroy_all
|
||||
updated = true
|
||||
end
|
||||
|
||||
if params["mute_topic"]
|
||||
TopicUser.where(topic_id: topic.id, user_id: user.id)
|
||||
.update_all(notification_level: TopicUser.notification_levels[:muted])
|
||||
updated = true
|
||||
end
|
||||
end
|
||||
|
||||
if params["disable_mailing_list"]
|
||||
user.user_option.update_columns(mailing_list_mode: false)
|
||||
updated = true
|
||||
end
|
||||
|
||||
if params['digest_after_minutes']
|
||||
digest_frequency = params['digest_after_minutes'].to_i
|
||||
|
||||
user.user_option.update_columns(
|
||||
digest_after_minutes: digest_frequency,
|
||||
email_digests: digest_frequency.positive?
|
||||
)
|
||||
updated = true
|
||||
end
|
||||
|
||||
if params["unsubscribe_all"]
|
||||
user.user_option.update_columns(email_digests: false,
|
||||
email_level: UserOption.email_level_types[:never],
|
||||
email_messages_level: UserOption.email_level_types[:never],
|
||||
mailing_list_mode: false)
|
||||
updated = true
|
||||
end
|
||||
|
||||
unless updated
|
||||
redirect_back fallback_location: path("/")
|
||||
else
|
||||
|
||||
key = "unsub_#{SecureRandom.hex}"
|
||||
Discourse.cache.write key, user.email, expires_in: 1.hour
|
||||
|
||||
url = path("/email/unsubscribed?key=#{key}")
|
||||
if topic
|
||||
url += "&topic_id=#{topic.id}"
|
||||
url = path("/email/unsubscribed?key=#{cache_key}")
|
||||
if key.associated_topic
|
||||
url += "&topic_id=#{key.associated_topic.id}"
|
||||
end
|
||||
|
||||
redirect_to url
|
||||
else
|
||||
redirect_back fallback_location: path("/")
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
def unsubscribed
|
||||
@ -130,31 +53,4 @@ class EmailController < ApplicationController
|
||||
topic = Topic.find_by(id: params[:topic_id].to_i) if @topic_id
|
||||
@topic = topic if topic && Guardian.new(nil).can_see?(topic)
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def digest_frequencies(user)
|
||||
frequency_in_minutes = user.user_option.digest_after_minutes
|
||||
email_digests = user.user_option.email_digests
|
||||
frequencies = DigestEmailSiteSetting.values.dup
|
||||
never = frequencies.delete_at(0)
|
||||
allowed_frequencies = %w[never weekly every_month every_six_months]
|
||||
|
||||
result = frequencies.reduce(frequencies: [], current: nil, selected: nil, take_next: false) do |memo, v|
|
||||
memo[:current] = v[:name] if v[:value] == frequency_in_minutes && email_digests
|
||||
next(memo) unless allowed_frequencies.include?(v[:name])
|
||||
|
||||
memo.tap do |m|
|
||||
m[:selected] = v[:value] if m[:take_next] && email_digests
|
||||
m[:frequencies] << [I18n.t("unsubscribe.digest_frequency.#{v[:name]}"), v[:value]]
|
||||
m[:take_next] = !m[:take_next] && m[:current]
|
||||
end
|
||||
end
|
||||
|
||||
result.slice(:frequencies, :current, :selected).tap do |r|
|
||||
r[:frequencies] << [I18n.t("unsubscribe.digest_frequency.#{never[:name]}"), never[:value]]
|
||||
r[:selected] ||= never[:value]
|
||||
r[:current] ||= never[:name]
|
||||
end
|
||||
end
|
||||
end
|
||||
|
Reference in New Issue
Block a user