DEV: Apply syntax_tree formatting to plugins/*

This commit is contained in:
David Taylor
2023-01-06 20:42:16 +00:00
parent 93e2dad656
commit 055310cea4
110 changed files with 3712 additions and 3158 deletions

View File

@ -23,18 +23,19 @@ module DiscourseNarrativeBot
topic_id: post.topic_id,
reply_to_post_number: post.post_number,
post_alert_options: defaut_post_alert_opts,
skip_validations: true
skip_validations: true,
}
new_post = PostCreator.create!(self.discobot_user, default_opts.merge(opts))
reset_rate_limits(post) if new_post
new_post
else
PostCreator.create!(self.discobot_user, {
post_alert_options: defaut_post_alert_opts,
raw: raw,
skip_validations: true
}.merge(opts))
PostCreator.create!(
self.discobot_user,
{ post_alert_options: defaut_post_alert_opts, raw: raw, skip_validations: true }.merge(
opts,
),
)
end
end
@ -53,7 +54,8 @@ module DiscourseNarrativeBot
data = DiscourseNarrativeBot::Store.get(user.id.to_s)
return unless data
key = "#{DiscourseNarrativeBot::PLUGIN_NAME}:reset-rate-limit:#{post.topic_id}:#{data['state']}"
key =
"#{DiscourseNarrativeBot::PLUGIN_NAME}:reset-rate-limit:#{post.topic_id}:#{data["state"]}"
if !(count = Discourse.redis.get(key))
count = 0
@ -76,12 +78,14 @@ module DiscourseNarrativeBot
valid = false
doc.css(".mention").each do |mention|
if User.normalize_username(mention.text) == "@#{self.discobot_username}"
valid = true
break
doc
.css(".mention")
.each do |mention|
if User.normalize_username(mention.text) == "@#{self.discobot_username}"
valid = true
break
end
end
end
valid
end
@ -94,8 +98,7 @@ module DiscourseNarrativeBot
topic = post.topic
return false if !topic
topic.pm_with_non_human_user? &&
topic.topic_allowed_users.where(user_id: -2).exists?
topic.pm_with_non_human_user? && topic.topic_allowed_users.where(user_id: -2).exists?
end
def cancel_timeout_job(user)
@ -107,9 +110,11 @@ module DiscourseNarrativeBot
cancel_timeout_job(user)
Jobs.enqueue_in(TIMEOUT_DURATION, :narrative_timeout,
Jobs.enqueue_in(
TIMEOUT_DURATION,
:narrative_timeout,
user_id: user.id,
klass: self.class.to_s
klass: self.class.to_s,
)
end
end

View File

@ -3,99 +3,101 @@
module DiscourseNarrativeBot
class AdvancedUserNarrative < Base
I18N_KEY = "discourse_narrative_bot.advanced_user_narrative".freeze
BADGE_NAME = 'Licensed'.freeze
BADGE_NAME = "Licensed".freeze
TRANSITION_TABLE = {
begin: {
next_state: :tutorial_edit,
next_instructions: Proc.new { I18n.t("#{I18N_KEY}.edit.instructions", i18n_post_args) },
init: {
action: :start_advanced_track
}
action: :start_advanced_track,
},
},
tutorial_edit: {
next_state: :tutorial_delete,
next_instructions: Proc.new { I18n.t("#{I18N_KEY}.delete.instructions", i18n_post_args) },
edit: {
action: :reply_to_edit
action: :reply_to_edit,
},
reply: {
next_state: :tutorial_edit,
action: :missing_edit
}
action: :missing_edit,
},
},
tutorial_delete: {
next_state: :tutorial_recover,
next_instructions: Proc.new { I18n.t("#{I18N_KEY}.recover.instructions", i18n_post_args) },
delete: {
action: :reply_to_delete
action: :reply_to_delete,
},
reply: {
next_state: :tutorial_delete,
action: :missing_delete
}
action: :missing_delete,
},
},
tutorial_recover: {
next_state: :tutorial_category_hashtag,
next_instructions: Proc.new do
category = Category.secured(Guardian.new(@user)).last
slug = category.slug
next_instructions:
Proc.new do
category = Category.secured(Guardian.new(@user)).last
slug = category.slug
if parent_category = category.parent_category
slug = "#{parent_category.slug}#{CategoryHashtag::SEPARATOR}#{slug}"
end
if parent_category = category.parent_category
slug = "#{parent_category.slug}#{CategoryHashtag::SEPARATOR}#{slug}"
end
I18n.t("#{I18N_KEY}.category_hashtag.instructions",
i18n_post_args(category: "##{slug}")
)
end,
I18n.t(
"#{I18N_KEY}.category_hashtag.instructions",
i18n_post_args(category: "##{slug}"),
)
end,
recover: {
action: :reply_to_recover
action: :reply_to_recover,
},
reply: {
next_state: :tutorial_recover,
action: :missing_recover
}
action: :missing_recover,
},
},
tutorial_category_hashtag: {
next_state: :tutorial_change_topic_notification_level,
next_instructions: Proc.new { I18n.t("#{I18N_KEY}.change_topic_notification_level.instructions", i18n_post_args) },
next_instructions:
Proc.new do
I18n.t("#{I18N_KEY}.change_topic_notification_level.instructions", i18n_post_args)
end,
reply: {
action: :reply_to_category_hashtag
}
action: :reply_to_category_hashtag,
},
},
tutorial_change_topic_notification_level: {
next_state: :tutorial_poll,
next_instructions: Proc.new { I18n.t("#{I18N_KEY}.poll.instructions", i18n_post_args) },
topic_notification_level_changed: {
action: :reply_to_topic_notification_level_changed
action: :reply_to_topic_notification_level_changed,
},
reply: {
next_state: :tutorial_change_topic_notification_level,
action: :missing_topic_notification_level_change
}
action: :missing_topic_notification_level_change,
},
},
tutorial_poll: {
prerequisite: Proc.new { SiteSetting.poll_enabled && @user.has_trust_level?(SiteSetting.poll_minimum_trust_level_to_create) },
prerequisite:
Proc.new do
SiteSetting.poll_enabled &&
@user.has_trust_level?(SiteSetting.poll_minimum_trust_level_to_create)
end,
next_state: :tutorial_details,
next_instructions: Proc.new { I18n.t("#{I18N_KEY}.details.instructions", i18n_post_args) },
reply: {
action: :reply_to_poll
}
action: :reply_to_poll,
},
},
tutorial_details: {
next_state: :end,
reply: {
action: :reply_to_details
}
}
action: :reply_to_details,
},
},
}
def self.badge_name
@ -103,7 +105,7 @@ module DiscourseNarrativeBot
end
def self.reset_trigger
I18n.t('discourse_narrative_bot.advanced_user_narrative.reset_trigger')
I18n.t("discourse_narrative_bot.advanced_user_narrative.reset_trigger")
end
def reset_bot(user, post)
@ -123,13 +125,18 @@ module DiscourseNarrativeBot
fake_delay
post = PostCreator.create!(
@user,
raw: I18n.t("#{I18N_KEY}.edit.bot_created_post_raw", i18n_post_args(discobot_username: self.discobot_username)),
topic_id: data[:topic_id],
skip_bot: true,
skip_validations: true
)
post =
PostCreator.create!(
@user,
raw:
I18n.t(
"#{I18N_KEY}.edit.bot_created_post_raw",
i18n_post_args(discobot_username: self.discobot_username),
),
topic_id: data[:topic_id],
skip_bot: true,
skip_validations: true,
)
set_state_data(:post_id, post.id)
post
@ -138,13 +145,18 @@ module DiscourseNarrativeBot
def init_tutorial_recover
data = get_data(@user)
post = PostCreator.create!(
@user,
raw: I18n.t("#{I18N_KEY}.recover.deleted_post_raw", i18n_post_args(discobot_username: self.discobot_username)),
topic_id: data[:topic_id],
skip_bot: true,
skip_validations: true
)
post =
PostCreator.create!(
@user,
raw:
I18n.t(
"#{I18N_KEY}.recover.deleted_post_raw",
i18n_post_args(discobot_username: self.discobot_username),
),
topic_id: data[:topic_id],
skip_bot: true,
skip_validations: true,
)
set_state_data(:post_id, post.id)
@ -172,18 +184,15 @@ module DiscourseNarrativeBot
opts = {
title: I18n.t("#{I18N_KEY}.title"),
target_usernames: @user.username,
archetype: Archetype.private_message
archetype: Archetype.private_message,
}
if @post &&
@post.topic.private_message? &&
@post.topic.topic_allowed_users.pluck(:user_id).include?(@user.id)
if @post && @post.topic.private_message? &&
@post.topic.topic_allowed_users.pluck(:user_id).include?(@user.id)
end
if @data[:topic_id]
opts = opts
.merge(topic_id: @data[:topic_id])
.except(:title, :target_usernames, :archetype)
opts = opts.merge(topic_id: @data[:topic_id]).except(:title, :target_usernames, :archetype)
end
post = reply_to(@post, raw, opts)
@ -213,9 +222,10 @@ module DiscourseNarrativeBot
fake_delay
unless @data[:attempted]
reply_to(@post, I18n.t("#{I18N_KEY}.edit.not_found",
i18n_post_args(url: Post.find_by(id: post_id).url)
))
reply_to(
@post,
I18n.t("#{I18N_KEY}.edit.not_found", i18n_post_args(url: Post.find_by(id: post_id).url)),
)
end
enqueue_timeout_job(@user)
@ -233,16 +243,15 @@ module DiscourseNarrativeBot
#{instance_eval(&@next_instructions)}
MD
PostCreator.create!(self.discobot_user,
raw: raw,
topic_id: @topic_id
)
PostCreator.create!(self.discobot_user, raw: raw, topic_id: @topic_id)
end
def missing_delete
return unless valid_topic?(@post.topic_id)
fake_delay
reply_to(@post, I18n.t("#{I18N_KEY}.delete.not_found", i18n_post_args)) unless @data[:attempted]
unless @data[:attempted]
reply_to(@post, I18n.t("#{I18N_KEY}.delete.not_found", i18n_post_args))
end
enqueue_timeout_job(@user)
false
end
@ -258,18 +267,19 @@ module DiscourseNarrativeBot
#{instance_eval(&@next_instructions)}
MD
PostCreator.create!(self.discobot_user,
raw: raw,
topic_id: @post.topic_id
)
PostCreator.create!(self.discobot_user, raw: raw, topic_id: @post.topic_id)
end
def missing_recover
return unless valid_topic?(@post.topic_id) &&
post_id = get_state_data(:post_id) && @post.id != post_id
unless valid_topic?(@post.topic_id) &&
post_id = get_state_data(:post_id) && @post.id != post_id
return
end
fake_delay
reply_to(@post, I18n.t("#{I18N_KEY}.recover.not_found", i18n_post_args)) unless @data[:attempted]
unless @data[:attempted]
reply_to(@post, I18n.t("#{I18N_KEY}.recover.not_found", i18n_post_args))
end
enqueue_timeout_job(@user)
false
end
@ -278,7 +288,7 @@ module DiscourseNarrativeBot
topic_id = @post.topic_id
return unless valid_topic?(topic_id)
if Nokogiri::HTML5.fragment(@post.cooked).css('.hashtag').size > 0
if Nokogiri::HTML5.fragment(@post.cooked).css(".hashtag").size > 0
raw = <<~MD
#{I18n.t("#{I18N_KEY}.category_hashtag.reply", i18n_post_args)}
@ -289,7 +299,9 @@ module DiscourseNarrativeBot
reply_to(@post, raw)
else
fake_delay
reply_to(@post, I18n.t("#{I18N_KEY}.category_hashtag.not_found", i18n_post_args)) unless @data[:attempted]
unless @data[:attempted]
reply_to(@post, I18n.t("#{I18N_KEY}.category_hashtag.not_found", i18n_post_args))
end
enqueue_timeout_job(@user)
false
end
@ -299,7 +311,12 @@ module DiscourseNarrativeBot
return unless valid_topic?(@post.topic_id)
fake_delay
reply_to(@post, I18n.t("#{I18N_KEY}.change_topic_notification_level.not_found", i18n_post_args)) unless @data[:attempted]
unless @data[:attempted]
reply_to(
@post,
I18n.t("#{I18N_KEY}.change_topic_notification_level.not_found", i18n_post_args),
)
end
enqueue_timeout_job(@user)
false
end
@ -316,10 +333,7 @@ module DiscourseNarrativeBot
fake_delay
post = PostCreator.create!(self.discobot_user,
raw: raw,
topic_id: @topic_id
)
post = PostCreator.create!(self.discobot_user, raw: raw, topic_id: @topic_id)
enqueue_timeout_job(@user)
post
@ -340,7 +354,9 @@ module DiscourseNarrativeBot
reply_to(@post, raw)
else
fake_delay
reply_to(@post, I18n.t("#{I18N_KEY}.poll.not_found", i18n_post_args)) unless @data[:attempted]
unless @data[:attempted]
reply_to(@post, I18n.t("#{I18N_KEY}.poll.not_found", i18n_post_args))
end
enqueue_timeout_job(@user)
false
end
@ -355,7 +371,9 @@ module DiscourseNarrativeBot
if Nokogiri::HTML5.fragment(@post.cooked).css("details").size > 0
reply_to(@post, I18n.t("#{I18N_KEY}.details.reply", i18n_post_args))
else
reply_to(@post, I18n.t("#{I18N_KEY}.details.not_found", i18n_post_args)) unless @data[:attempted]
unless @data[:attempted]
reply_to(@post, I18n.t("#{I18N_KEY}.details.not_found", i18n_post_args))
end
enqueue_timeout_job(@user)
false
end
@ -370,7 +388,9 @@ module DiscourseNarrativeBot
if @post.wiki
reply_to(@post, I18n.t("#{I18N_KEY}.wiki.reply", i18n_post_args))
else
reply_to(@post, I18n.t("#{I18N_KEY}.wiki.not_found", i18n_post_args)) unless @data[:attempted]
unless @data[:attempted]
reply_to(@post, I18n.t("#{I18N_KEY}.wiki.not_found", i18n_post_args))
end
enqueue_timeout_job(@user)
false
end
@ -379,9 +399,10 @@ module DiscourseNarrativeBot
def end_reply
fake_delay
reply_to(@post, I18n.t("#{I18N_KEY}.end.message",
i18n_post_args(certificate: certificate('advanced'))
))
reply_to(
@post,
I18n.t("#{I18N_KEY}.end.message", i18n_post_args(certificate: certificate("advanced"))),
)
end
def synchronize(user)

View File

@ -4,7 +4,8 @@ module DiscourseNarrativeBot
class Base
include Actions
class InvalidTransitionError < StandardError; end
class InvalidTransitionError < StandardError
end
def input(input, user, post: nil, topic_id: nil, skip: false)
new_post = nil
@ -30,16 +31,18 @@ module DiscourseNarrativeBot
next_opts = self.class::TRANSITION_TABLE.fetch(next_state)
prerequisite = next_opts[:prerequisite]
if (!prerequisite || instance_eval(&prerequisite)) && !(
SiteSetting.discourse_narrative_bot_skip_tutorials.present? &&
SiteSetting.discourse_narrative_bot_skip_tutorials.split("|").include?(next_state.to_s))
if (!prerequisite || instance_eval(&prerequisite)) &&
!(
SiteSetting.discourse_narrative_bot_skip_tutorials.present? &&
SiteSetting
.discourse_narrative_bot_skip_tutorials
.split("|")
.include?(next_state.to_s)
)
break
end
[:next_state, :next_instructions].each do |key|
opts[key] = next_opts[key]
end
%i[next_state next_instructions].each { |key| opts[key] = next_opts[key] }
end
rescue InvalidTransitionError
# For given input, no transition for current state
@ -78,16 +81,9 @@ module DiscourseNarrativeBot
end_reply
cancel_timeout_job(user)
BadgeGranter.grant(
Badge.find_by(name: self.class.badge_name),
user
)
BadgeGranter.grant(Badge.find_by(name: self.class.badge_name), user)
set_data(@user,
topic_id: new_post.topic_id,
state: :end,
track: self.class.to_s
)
set_data(@user, topic_id: new_post.topic_id, state: :end, track: self.class.to_s)
end
end
rescue => e
@ -116,25 +112,29 @@ module DiscourseNarrativeBot
@data = get_data(user) || {}
if post = Post.find_by(id: @data[:last_post_id])
reply_to(post, I18n.t("discourse_narrative_bot.timeout.message",
i18n_post_args(
username: user.username,
skip_trigger: TrackSelector.skip_trigger,
reset_trigger: "#{TrackSelector.reset_trigger} #{self.class.reset_trigger}"
)
), {}, skip_send_email: false)
reply_to(
post,
I18n.t(
"discourse_narrative_bot.timeout.message",
i18n_post_args(
username: user.username,
skip_trigger: TrackSelector.skip_trigger,
reset_trigger: "#{TrackSelector.reset_trigger} #{self.class.reset_trigger}",
),
),
{},
skip_send_email: false,
)
end
end
def certificate(type = nil)
options = {
user_id: @user.id,
date: Time.zone.now.strftime('%b %d %Y'),
format: :svg
}
options = { user_id: @user.id, date: Time.zone.now.strftime("%b %d %Y"), format: :svg }
options.merge!(type: type) if type
src = Discourse.base_url + DiscourseNarrativeBot::Engine.routes.url_helpers.certificate_path(options)
src =
Discourse.base_url +
DiscourseNarrativeBot::Engine.routes.url_helpers.certificate_path(options)
alt = CGI.escapeHTML(I18n.t("#{self.class::I18N_KEY}.certificate.alt"))
"<iframe class='discobot-certificate' src='#{src}' width='650' height='464' alt='#{alt}'></iframe>"
@ -192,7 +192,7 @@ module DiscourseNarrativeBot
end
def not_implemented
raise 'Not implemented.'
raise "Not implemented."
end
private

View File

@ -10,7 +10,7 @@ module DiscourseNarrativeBot
begin
Date.parse(date)
rescue ArgumentError => e
if e.message == 'invalid date'
if e.message == "invalid date"
Date.parse(Date.today.to_s)
else
raise e
@ -25,14 +25,20 @@ module DiscourseNarrativeBot
svg_default_width = 538.583
logo_container = logo_group(55, svg_default_width, 280)
ApplicationController.render(inline: read_template('new_user'), assigns: assign_options(svg_default_width, logo_container))
ApplicationController.render(
inline: read_template("new_user"),
assigns: assign_options(svg_default_width, logo_container),
)
end
def advanced_user_track
svg_default_width = 722.8
logo_container = logo_group(40, svg_default_width, 350)
ApplicationController.render(inline: read_template('advanced_user'), assigns: assign_options(svg_default_width, logo_container))
ApplicationController.render(
inline: read_template("advanced_user"),
assigns: assign_options(svg_default_width, logo_container),
)
end
private
@ -48,7 +54,7 @@ module DiscourseNarrativeBot
date: @date,
avatar_url: @avatar_url,
logo_group: logo_group,
name: name
name: name,
}
end

View File

@ -7,25 +7,26 @@ module DiscourseNarrativeBot
def self.roll(num_of_dice, range_of_dice)
if num_of_dice == 0 || range_of_dice == 0
return I18n.t('discourse_narrative_bot.dice.invalid')
return I18n.t("discourse_narrative_bot.dice.invalid")
end
output = +''
output = +""
if num_of_dice > MAXIMUM_NUM_OF_DICE
output << I18n.t('discourse_narrative_bot.dice.not_enough_dice', count: MAXIMUM_NUM_OF_DICE)
output << I18n.t("discourse_narrative_bot.dice.not_enough_dice", count: MAXIMUM_NUM_OF_DICE)
output << "\n\n"
num_of_dice = MAXIMUM_NUM_OF_DICE
end
if range_of_dice > MAXIMUM_RANGE_OF_DICE
output << I18n.t('discourse_narrative_bot.dice.out_of_range')
output << I18n.t("discourse_narrative_bot.dice.out_of_range")
output << "\n\n"
range_of_dice = MAXIMUM_RANGE_OF_DICE
end
output << I18n.t('discourse_narrative_bot.dice.results',
results: num_of_dice.times.map { rand(1..range_of_dice) }.join(", ")
output << I18n.t(
"discourse_narrative_bot.dice.results",
results: num_of_dice.times.map { rand(1..range_of_dice) }.join(", "),
)
end
end

View File

@ -3,9 +3,10 @@
module DiscourseNarrativeBot
class Magic8Ball
def self.generate_answer
I18n.t("discourse_narrative_bot.magic_8_ball.result", result: I18n.t(
"discourse_narrative_bot.magic_8_ball.answers.#{rand(1..20)}"
))
I18n.t(
"discourse_narrative_bot.magic_8_ball.result",
result: I18n.t("discourse_narrative_bot.magic_8_ball.answers.#{rand(1..20)}"),
)
end
end
end

View File

@ -1,136 +1,136 @@
# frozen_string_literal: true
require 'distributed_mutex'
require "distributed_mutex"
module DiscourseNarrativeBot
class NewUserNarrative < Base
I18N_KEY = "discourse_narrative_bot.new_user_narrative".freeze
BADGE_NAME = 'Certified'.freeze
BADGE_NAME = "Certified".freeze
TRANSITION_TABLE = {
begin: {
init: {
next_state: :tutorial_bookmark,
next_instructions: Proc.new { I18n.t("#{I18N_KEY}.bookmark.instructions", base_uri: Discourse.base_path) },
action: :say_hello
}
next_instructions:
Proc.new { I18n.t("#{I18N_KEY}.bookmark.instructions", base_uri: Discourse.base_path) },
action: :say_hello,
},
},
tutorial_bookmark: {
next_state: :tutorial_onebox,
next_instructions: Proc.new { I18n.t("#{I18N_KEY}.onebox.instructions", base_uri: Discourse.base_path) },
next_instructions:
Proc.new { I18n.t("#{I18N_KEY}.onebox.instructions", base_uri: Discourse.base_path) },
bookmark: {
action: :reply_to_bookmark
action: :reply_to_bookmark,
},
reply: {
next_state: :tutorial_bookmark,
action: :missing_bookmark
}
action: :missing_bookmark,
},
},
tutorial_onebox: {
next_state: :tutorial_emoji,
next_instructions: Proc.new { I18n.t("#{I18N_KEY}.emoji.instructions", base_uri: Discourse.base_path) },
next_instructions:
Proc.new { I18n.t("#{I18N_KEY}.emoji.instructions", base_uri: Discourse.base_path) },
reply: {
action: :reply_to_onebox
}
action: :reply_to_onebox,
},
},
tutorial_emoji: {
prerequisite: Proc.new { SiteSetting.enable_emoji },
next_state: :tutorial_mention,
next_instructions: Proc.new {
I18n.t("#{I18N_KEY}.mention.instructions",
discobot_username: self.discobot_username,
base_uri: Discourse.base_path)
},
next_instructions:
Proc.new do
I18n.t(
"#{I18N_KEY}.mention.instructions",
discobot_username: self.discobot_username,
base_uri: Discourse.base_path,
)
end,
reply: {
action: :reply_to_emoji
}
action: :reply_to_emoji,
},
},
tutorial_mention: {
prerequisite: Proc.new { SiteSetting.enable_mentions },
next_state: :tutorial_formatting,
next_instructions: Proc.new { I18n.t("#{I18N_KEY}.formatting.instructions", base_uri: Discourse.base_path) },
next_instructions:
Proc.new { I18n.t("#{I18N_KEY}.formatting.instructions", base_uri: Discourse.base_path) },
reply: {
action: :reply_to_mention
}
action: :reply_to_mention,
},
},
tutorial_formatting: {
next_state: :tutorial_quote,
next_instructions: Proc.new { I18n.t("#{I18N_KEY}.quoting.instructions", base_uri: Discourse.base_path) },
next_instructions:
Proc.new { I18n.t("#{I18N_KEY}.quoting.instructions", base_uri: Discourse.base_path) },
reply: {
action: :reply_to_formatting
}
action: :reply_to_formatting,
},
},
tutorial_quote: {
next_state: :tutorial_images,
next_instructions: Proc.new { I18n.t("#{I18N_KEY}.images.instructions", base_uri: Discourse.base_path) },
next_instructions:
Proc.new { I18n.t("#{I18N_KEY}.images.instructions", base_uri: Discourse.base_path) },
reply: {
action: :reply_to_quote
}
action: :reply_to_quote,
},
},
# Note: tutorial_images and tutorial_likes are mutually exclusive.
# The prerequisites should ensure only one of them is called.
tutorial_images: {
prerequisite: Proc.new { @user.has_trust_level?(SiteSetting.min_trust_to_post_embedded_media) },
prerequisite:
Proc.new { @user.has_trust_level?(SiteSetting.min_trust_to_post_embedded_media) },
next_state: :tutorial_likes,
next_instructions: Proc.new { I18n.t("#{I18N_KEY}.likes.instructions", base_uri: Discourse.base_path) },
next_instructions:
Proc.new { I18n.t("#{I18N_KEY}.likes.instructions", base_uri: Discourse.base_path) },
reply: {
action: :reply_to_image
action: :reply_to_image,
},
like: {
action: :track_images_like
}
action: :track_images_like,
},
},
tutorial_likes: {
prerequisite: Proc.new { !@user.has_trust_level?(SiteSetting.min_trust_to_post_embedded_media) },
prerequisite:
Proc.new { !@user.has_trust_level?(SiteSetting.min_trust_to_post_embedded_media) },
next_state: :tutorial_flag,
next_instructions: Proc.new {
I18n.t("#{I18N_KEY}.flag.instructions",
guidelines_url: url_helpers(:guidelines_url),
about_url: url_helpers(:about_index_url),
base_uri: Discourse.base_path)
},
next_instructions:
Proc.new do
I18n.t(
"#{I18N_KEY}.flag.instructions",
guidelines_url: url_helpers(:guidelines_url),
about_url: url_helpers(:about_index_url),
base_uri: Discourse.base_path,
)
end,
like: {
action: :reply_to_likes
action: :reply_to_likes,
},
reply: {
next_state: :tutorial_likes,
action: :missing_likes_like
}
action: :missing_likes_like,
},
},
tutorial_flag: {
prerequisite: Proc.new { SiteSetting.allow_flagging_staff },
next_state: :tutorial_search,
next_instructions: Proc.new { I18n.t("#{I18N_KEY}.search.instructions", base_uri: Discourse.base_path) },
next_instructions:
Proc.new { I18n.t("#{I18N_KEY}.search.instructions", base_uri: Discourse.base_path) },
flag: {
action: :reply_to_flag
action: :reply_to_flag,
},
reply: {
next_state: :tutorial_flag,
action: :missing_flag
}
action: :missing_flag,
},
},
tutorial_search: {
next_state: :end,
reply: {
action: :reply_to_search
}
}
action: :reply_to_search,
},
},
}
def self.badge_name
@ -138,7 +138,7 @@ module DiscourseNarrativeBot
end
def self.search_answer
':herb:'
":herb:"
end
def self.search_answer_emoji
@ -146,7 +146,7 @@ module DiscourseNarrativeBot
end
def self.reset_trigger
I18n.t('discourse_narrative_bot.new_user_narrative.reset_trigger')
I18n.t("discourse_narrative_bot.new_user_narrative.reset_trigger")
end
def reset_bot(user, post)
@ -173,7 +173,7 @@ module DiscourseNarrativeBot
topic = @post.topic
post = topic.first_post
MessageBus.publish('/new_user_narrative/tutorial_search', {}, user_ids: [@user.id])
MessageBus.publish("/new_user_narrative/tutorial_search", {}, user_ids: [@user.id])
raw = <<~MD
#{post.raw}
@ -184,7 +184,8 @@ module DiscourseNarrativeBot
PostRevisor.new(post, topic).revise!(
self.discobot_user,
{ raw: raw },
skip_validations: true, force_new_version: true
skip_validations: true,
force_new_version: true,
)
set_state_data(:post_version, post.reload.version || 0)
@ -198,13 +199,11 @@ module DiscourseNarrativeBot
end
def say_hello
raw = I18n.t(
"#{I18N_KEY}.hello.message",
i18n_post_args(
username: @user.username,
title: SiteSetting.title
raw =
I18n.t(
"#{I18N_KEY}.hello.message",
i18n_post_args(username: @user.username, title: SiteSetting.title),
)
)
raw = <<~MD
#{raw}
@ -213,9 +212,7 @@ module DiscourseNarrativeBot
MD
title = I18n.t("#{I18N_KEY}.hello.title", title: SiteSetting.title)
if SiteSetting.max_emojis_in_title == 0
title = title.gsub(/:([\w\-+]+(?::t\d)?):/, '').strip
end
title = title.gsub(/:([\w\-+]+(?::t\d)?):/, "").strip if SiteSetting.max_emojis_in_title == 0
opts = {
title: title,
@ -224,17 +221,13 @@ module DiscourseNarrativeBot
subtype: TopicSubtype.system_message,
}
if @post &&
@post.topic.private_message? &&
@post.topic.topic_allowed_users.pluck(:user_id).include?(@user.id)
if @post && @post.topic.private_message? &&
@post.topic.topic_allowed_users.pluck(:user_id).include?(@user.id)
opts = opts.merge(topic_id: @post.topic_id)
end
if @data[:topic_id]
opts = opts
.merge(topic_id: @data[:topic_id])
.except(:title, :target_usernames, :archetype)
opts = opts.merge(topic_id: @data[:topic_id]).except(:title, :target_usernames, :archetype)
end
post = reply_to(@post, raw, opts)
@ -249,7 +242,9 @@ module DiscourseNarrativeBot
fake_delay
enqueue_timeout_job(@user)
reply_to(@post, I18n.t("#{I18N_KEY}.bookmark.not_found", i18n_post_args)) unless @data[:attempted]
unless @data[:attempted]
reply_to(@post, I18n.t("#{I18N_KEY}.bookmark.not_found", i18n_post_args))
end
false
end
@ -292,7 +287,9 @@ module DiscourseNarrativeBot
reply
else
fake_delay
reply_to(@post, I18n.t("#{I18N_KEY}.onebox.not_found", i18n_post_args)) unless @data[:attempted]
unless @data[:attempted]
reply_to(@post, I18n.t("#{I18N_KEY}.onebox.not_found", i18n_post_args))
end
enqueue_timeout_job(@user)
false
end
@ -302,11 +299,12 @@ module DiscourseNarrativeBot
post_topic_id = @post.topic_id
return unless valid_topic?(post_topic_id)
post_liked = PostAction.exists?(
post_action_type_id: PostActionType.types[:like],
post_id: @data[:last_post_id],
user_id: @user.id
)
post_liked =
PostAction.exists?(
post_action_type_id: PostActionType.types[:like],
post_id: @data[:last_post_id],
user_id: @user.id,
)
if post_liked
set_state_data(:liked, true)
@ -358,18 +356,23 @@ module DiscourseNarrativeBot
like_post(@post)
else
raw = I18n.t(
"#{I18N_KEY}.images.like_not_found",
i18n_post_args(url: Post.find_by(id: @data[:last_post_id]).url)
)
raw =
I18n.t(
"#{I18N_KEY}.images.like_not_found",
i18n_post_args(url: Post.find_by(id: @data[:last_post_id]).url),
)
transition = false
end
else
raw = I18n.t(
"#{I18N_KEY}.images.not_found",
i18n_post_args(image_url: "#{Discourse.base_url}/plugins/discourse-narrative-bot/images/dog-walk.gif")
)
raw =
I18n.t(
"#{I18N_KEY}.images.not_found",
i18n_post_args(
image_url:
"#{Discourse.base_url}/plugins/discourse-narrative-bot/images/dog-walk.gif",
),
)
transition = false
end
@ -398,11 +401,12 @@ module DiscourseNarrativeBot
post_topic_id = @post.topic_id
return unless valid_topic?(post_topic_id)
post_liked = PostAction.exists?(
post_action_type_id: PostActionType.types[:like],
post_id: @data[:last_post_id],
user_id: @user.id
)
post_liked =
PostAction.exists?(
post_action_type_id: PostActionType.types[:like],
post_id: @data[:last_post_id],
user_id: @user.id,
)
if post_liked
raw = <<~MD
@ -425,7 +429,10 @@ module DiscourseNarrativeBot
post_topic_id = @post.topic_id
return unless valid_topic?(post_topic_id)
if Nokogiri::HTML5.fragment(@post.cooked).css("b", "strong", "em", "i", ".bbcode-i", ".bbcode-b").size > 0
if Nokogiri::HTML5
.fragment(@post.cooked)
.css("b", "strong", "em", "i", ".bbcode-i", ".bbcode-b")
.size > 0
raw = <<~MD
#{I18n.t("#{I18N_KEY}.formatting.reply", i18n_post_args)}
@ -439,7 +446,9 @@ module DiscourseNarrativeBot
reply
else
fake_delay
reply_to(@post, I18n.t("#{I18N_KEY}.formatting.not_found", i18n_post_args)) unless @data[:attempted]
unless @data[:attempted]
reply_to(@post, I18n.t("#{I18N_KEY}.formatting.not_found", i18n_post_args))
end
enqueue_timeout_job(@user)
false
end
@ -465,7 +474,9 @@ module DiscourseNarrativeBot
reply
else
fake_delay
reply_to(@post, I18n.t("#{I18N_KEY}.quoting.not_found", i18n_post_args)) unless @data[:attempted]
unless @data[:attempted]
reply_to(@post, I18n.t("#{I18N_KEY}.quoting.not_found", i18n_post_args))
end
enqueue_timeout_job(@user)
false
end
@ -491,7 +502,9 @@ module DiscourseNarrativeBot
reply
else
fake_delay
reply_to(@post, I18n.t("#{I18N_KEY}.emoji.not_found", i18n_post_args)) unless @data[:attempted]
unless @data[:attempted]
reply_to(@post, I18n.t("#{I18N_KEY}.emoji.not_found", i18n_post_args))
end
enqueue_timeout_job(@user)
false
end
@ -517,13 +530,13 @@ module DiscourseNarrativeBot
fake_delay
unless @data[:attempted]
reply_to(@post, I18n.t(
"#{I18N_KEY}.mention.not_found",
i18n_post_args(
username: @user.username,
discobot_username: self.discobot_username
)
))
reply_to(
@post,
I18n.t(
"#{I18N_KEY}.mention.not_found",
i18n_post_args(username: @user.username, discobot_username: self.discobot_username),
),
)
end
enqueue_timeout_job(@user)
@ -536,9 +549,13 @@ module DiscourseNarrativeBot
# Remove any incorrect flags so that they can try again
if @post.user_id == -2
@post.post_actions
@post
.post_actions
.where(user_id: @user.id)
.where("post_action_type_id IN (?)", (PostActionType.flag_types.values - [PostActionType.types[:inappropriate]]))
.where(
"post_action_type_id IN (?)",
(PostActionType.flag_types.values - [PostActionType.types[:inappropriate]]),
)
.destroy_all
end
@ -571,12 +588,18 @@ module DiscourseNarrativeBot
post_topic_id = @post.topic_id
return unless valid_topic?(post_topic_id)
if @post.raw.include?(NewUserNarrative.search_answer) || @post.raw.include?(NewUserNarrative.search_answer_emoji)
if @post.raw.include?(NewUserNarrative.search_answer) ||
@post.raw.include?(NewUserNarrative.search_answer_emoji)
fake_delay
reply_to(@post, I18n.t("#{I18N_KEY}.search.reply", i18n_post_args(search_url: url_helpers(:search_url))))
reply_to(
@post,
I18n.t("#{I18N_KEY}.search.reply", i18n_post_args(search_url: url_helpers(:search_url))),
)
else
fake_delay
reply_to(@post, I18n.t("#{I18N_KEY}.search.not_found", i18n_post_args)) unless @data[:attempted]
unless @data[:attempted]
reply_to(@post, I18n.t("#{I18N_KEY}.search.not_found", i18n_post_args))
end
enqueue_timeout_job(@user)
false
end
@ -587,16 +610,17 @@ module DiscourseNarrativeBot
reply_to(
@post,
I18n.t("#{I18N_KEY}.end.message",
I18n.t(
"#{I18N_KEY}.end.message",
i18n_post_args(
username: @user.username,
base_url: Discourse.base_url,
certificate: certificate,
discobot_username: self.discobot_username,
advanced_trigger: AdvancedUserNarrative.reset_trigger
)
advanced_trigger: AdvancedUserNarrative.reset_trigger,
),
),
topic_id: @data[:topic_id]
topic_id: @data[:topic_id],
)
end
@ -605,15 +629,12 @@ module DiscourseNarrativeBot
end
def welcome_topic
Topic.find_by(slug: 'welcome-to-discourse', archetype: Archetype.default) ||
Topic.find_by(slug: "welcome-to-discourse", archetype: Archetype.default) ||
Topic.recent(1).first
end
def url_helpers(url, opts = {})
Rails.application.routes.url_helpers.public_send(
url,
opts.merge(host: Discourse.base_url)
)
Rails.application.routes.url_helpers.public_send(url, opts.merge(host: Discourse.base_url))
end
end
end

View File

@ -1,24 +1,21 @@
# frozen_string_literal: true
require 'excon'
require "excon"
module DiscourseNarrativeBot
class QuoteGenerator
API_ENDPOINT = 'http://api.forismatic.com/api/1.0/'.freeze
API_ENDPOINT = "http://api.forismatic.com/api/1.0/".freeze
def self.format_quote(quote, author)
I18n.t('discourse_narrative_bot.quote.results', quote: quote, author: author)
I18n.t("discourse_narrative_bot.quote.results", quote: quote, author: author)
end
def self.generate(user)
quote, author =
if !user.effective_locale.start_with?('en')
if !user.effective_locale.start_with?("en")
translation_key = "discourse_narrative_bot.quote.#{rand(1..10)}"
[
I18n.t("#{translation_key}.quote"),
I18n.t("#{translation_key}.author")
]
[I18n.t("#{translation_key}.quote"), I18n.t("#{translation_key}.author")]
else
connection = Excon.new("#{API_ENDPOINT}?lang=en&format=json&method=getQuote")
response = connection.request(expects: [200, 201], method: :Get)

View File

@ -4,18 +4,12 @@ module DiscourseNarrativeBot
class TrackSelector
include Actions
GENERIC_REPLIES_COUNT_PREFIX = 'discourse-narrative-bot:track-selector-count:'.freeze
PUBLIC_DISPLAY_BOT_HELP_KEY = 'discourse-narrative-bot:track-selector:display-bot-help'.freeze
GENERIC_REPLIES_COUNT_PREFIX = "discourse-narrative-bot:track-selector-count:".freeze
PUBLIC_DISPLAY_BOT_HELP_KEY = "discourse-narrative-bot:track-selector:display-bot-help".freeze
TRACKS = [
AdvancedUserNarrative,
NewUserNarrative
]
TRACKS = [AdvancedUserNarrative, NewUserNarrative]
TOPIC_ACTIONS = [
:delete,
:topic_notification_level_changed
].each(&:freeze)
TOPIC_ACTIONS = %i[delete topic_notification_level_changed].each(&:freeze)
RESET_TRIGGER_EXACT_MATCH_LENGTH = 200
@ -118,7 +112,7 @@ module DiscourseNarrativeBot
trigger = "#{self.class.reset_trigger} #{klass.reset_trigger}"
if @post.raw.length < RESET_TRIGGER_EXACT_MATCH_LENGTH && @is_pm_to_bot
@post.raw.match(Regexp.new("\\b\\W\?#{trigger}\\W\?\\b", 'i'))
@post.raw.match(Regexp.new("\\b\\W\?#{trigger}\\W\?\\b", "i"))
else
match_trigger?(trigger)
end
@ -127,7 +121,7 @@ module DiscourseNarrativeBot
def bot_commands(hint = true)
raw =
if @user.manually_disabled_discobot?
I18n.t(self.class.i18n_key('random_mention.discobot_disabled'))
I18n.t(self.class.i18n_key("random_mention.discobot_disabled"))
elsif match_data = match_trigger?("#{self.class.dice_trigger} (\\d+)d(\\d+)")
DiscourseNarrativeBot::Dice.roll(match_data[1].to_i, match_data[2].to_i)
elsif match_trigger?(self.class.quote_trigger)
@ -137,20 +131,23 @@ module DiscourseNarrativeBot
elsif match_trigger?(self.class.help_trigger)
help_message
elsif hint
message = I18n.t(self.class.i18n_key('random_mention.reply'),
discobot_username: self.discobot_username,
help_trigger: self.class.help_trigger
)
message =
I18n.t(
self.class.i18n_key("random_mention.reply"),
discobot_username: self.discobot_username,
help_trigger: self.class.help_trigger,
)
if public_reply?
key = "#{PUBLIC_DISPLAY_BOT_HELP_KEY}:#{@post.topic_id}"
last_bot_help_post_number = Discourse.redis.get(key)
if !last_bot_help_post_number ||
(last_bot_help_post_number &&
@post.post_number - 10 > last_bot_help_post_number.to_i &&
(1.day.to_i - Discourse.redis.ttl(key)) > 6.hours.to_i)
(
last_bot_help_post_number &&
@post.post_number - 10 > last_bot_help_post_number.to_i &&
(1.day.to_i - Discourse.redis.ttl(key)) > 6.hours.to_i
)
Discourse.redis.setex(key, 1.day.to_i, @post.post_number)
message
end
@ -166,20 +163,24 @@ module DiscourseNarrativeBot
end
def help_message
message = I18n.t(
self.class.i18n_key('random_mention.tracks'),
discobot_username: self.discobot_username,
reset_trigger: self.class.reset_trigger,
tracks: [NewUserNarrative.reset_trigger, AdvancedUserNarrative.reset_trigger].join(', ')
)
message =
I18n.t(
self.class.i18n_key("random_mention.tracks"),
discobot_username: self.discobot_username,
reset_trigger: self.class.reset_trigger,
tracks: [NewUserNarrative.reset_trigger, AdvancedUserNarrative.reset_trigger].join(", "),
)
message << "\n\n#{I18n.t(self.class.i18n_key('random_mention.bot_actions'),
discobot_username: self.discobot_username,
dice_trigger: self.class.dice_trigger,
quote_trigger: self.class.quote_trigger,
quote_sample: DiscourseNarrativeBot::QuoteGenerator.generate(@user),
magic_8_ball_trigger: self.class.magic_8_ball_trigger
)}"
message << "\n\n#{
I18n.t(
self.class.i18n_key("random_mention.bot_actions"),
discobot_username: self.discobot_username,
dice_trigger: self.class.dice_trigger,
quote_trigger: self.class.quote_trigger,
quote_sample: DiscourseNarrativeBot::QuoteGenerator.generate(@user),
magic_8_ball_trigger: self.class.magic_8_ball_trigger,
)
}"
end
def generic_replies_key(user)
@ -193,18 +194,23 @@ module DiscourseNarrativeBot
case count
when 0
raw = I18n.t(self.class.i18n_key('do_not_understand.first_response'))
raw = I18n.t(self.class.i18n_key("do_not_understand.first_response"))
if state && state.to_sym != :end
raw = "#{raw}\n\n#{I18n.t(self.class.i18n_key('do_not_understand.track_response'), reset_trigger: reset_trigger, skip_trigger: self.class.skip_trigger)}"
raw =
"#{raw}\n\n#{I18n.t(self.class.i18n_key("do_not_understand.track_response"), reset_trigger: reset_trigger, skip_trigger: self.class.skip_trigger)}"
end
reply_to(@post, raw)
when 1
reply_to(@post, I18n.t(self.class.i18n_key('do_not_understand.second_response'),
base_path: Discourse.base_path,
reset_trigger: self.class.reset_trigger
))
reply_to(
@post,
I18n.t(
self.class.i18n_key("do_not_understand.second_response"),
base_path: Discourse.base_path,
reset_trigger: self.class.reset_trigger,
),
)
else
# Stay out of the user's way
end
@ -218,7 +224,9 @@ module DiscourseNarrativeBot
def skip_track?
if @is_pm_to_bot
@post.raw.match(/((^@#{self.discobot_username} #{self.class.skip_trigger})|(^#{self.class.skip_trigger}$))/i)
@post.raw.match(
/((^@#{self.discobot_username} #{self.class.skip_trigger})|(^#{self.class.skip_trigger}$))/i,
)
else
false
end
@ -233,24 +241,23 @@ module DiscourseNarrativeBot
def match_trigger?(trigger)
# we remove the leading <p> to allow for trigger to be at the end of a paragraph
cooked_trigger = cook(trigger)[3..-1]
regexp = Regexp.new(cooked_trigger, 'i')
regexp = Regexp.new(cooked_trigger, "i")
match = @post.cooked.match(regexp)
if @is_pm_to_bot
match || @post.raw.strip.match(Regexp.new("^#{trigger}$", 'i'))
match || @post.raw.strip.match(Regexp.new("^#{trigger}$", "i"))
else
match
end
end
def like_user_post
if @post.raw.match(/thank/i)
PostActionCreator.like(self.discobot_user, @post)
end
PostActionCreator.like(self.discobot_user, @post) if @post.raw.match(/thank/i)
end
def bot_mentioned?
@bot_mentioned ||= PostAnalyzer.new(@post.raw, @post.topic_id).raw_mentions.include?(self.discobot_username)
@bot_mentioned ||=
PostAnalyzer.new(@post.raw, @post.topic_id).raw_mentions.include?(self.discobot_username)
end
def public_reply?

View File

@ -8,8 +8,14 @@ module DiscourseNarrativeBot
def self.values
@values ||= [
{ name: 'discourse_narrative_bot.welcome_post_type.new_user_track', value: 'new_user_track' },
{ name: 'discourse_narrative_bot.welcome_post_type.welcome_message', value: 'welcome_message' }
{
name: "discourse_narrative_bot.welcome_post_type.new_user_track",
value: "new_user_track",
},
{
name: "discourse_narrative_bot.welcome_post_type.welcome_message",
value: "welcome_message",
},
]
end