Websites/app/models/e621_webhook.rb
2024-05-02 22:04:43 -05:00

160 lines
4.9 KiB
Ruby

# frozen_string_literal: true
class E621Webhook < ApplicationRecord
validate :validate_max_per_channel, on: :create
validate :validate_max_per_guild, on: :create
after_create do
send_creation_message
send_update(E621Status.current)
end
after_destroy do
webhook&.delete unless skip_delete_webhook
send_deletion_message
end
attr_reader :skip_delete_webhook
MAX_PER_CHANNEL = 1
MAX_PER_GUILD = 5
SUCCESS_COLOR = 0x008000
WARNING_COLOR = 0xFFA500
ERROR_COLOR = 0xFF0000
E621_COLOR = 0x012E57
def self.from_struct(data, creator_id = nil)
hook = create(
webhook_id: data.id,
webhook_token: data.token,
channel_id: data.channel_id,
creator_id: creator_id,
guild_id: data.guild_id,
)
if hook.errors[:channel_id].include?("has too many webhooks")
hook.send_too_many_channel_message
hook.destroy
return :too_many_channel
end
if hook.errors[:guild_id].include?("has too many webhooks")
hook.send_too_many_guild_message
hook.destroy
return :too_many_guild
end
hook
end
def validate_max_per_channel
return if channel_id.blank?
return if E621Webhook.for_channel(channel_id).count < MAX_PER_CHANNEL
errors.add(:channel_id, "has too many webhooks")
end
def validate_max_per_guild
return if guild_id.blank?
return if E621Webhook.for_guild(guild_id).count < MAX_PER_GUILD
errors.add(:guild_id, "has too many webhooks")
end
module WebhookMethods
def webhook
return nil unless webhook_id && webhook_token
Requests::DiscordWebhook.new(id: webhook_id, token: webhook_token)
end
def embed(**data)
{
thumbnail: {
url: "https://status.e621.ws/icon.png",
},
url: "https://status.e621.ws",
timestamp: Time.now.iso8601,
color: E621_COLOR,
**data,
}
end
def notification_webhook
Websites.config.e621_status_check_logs_webhook
end
def send_creation_message
execute({
embeds: [
embed(title: "E621 Status Check", description: "This webhook has been setup to receive status updates for e621's api#{creator_id.present? ? " by <@#{creator_id}>" : ''}."),
],
})
notification_webhook.execute({
embeds: [
embed(title: "Status Check Webhook Added", description: "A status check has been added in the channel **#{channel_id}** of the guild **#{guild_id}**#{creator_id.present? ? " by <@#{creator_id}>" : ''}.", color: SUCCESS_COLOR),
],
})
end
def send_deletion_message
notification_webhook.execute({
embeds: [
embed(title: "Status Check Webhook Removed", description: "A status check has been removed in the channel **#{channel_id}** of the guild **#{guild_id}**#{creator_id.present? ? " by <@#{creator_id}>" : ''}.", color: ERROR_COLOR),
],
})
end
def send_too_many_guild_message
execute({
embeds: [
embed(title: "E621 Status Check", description: "You've already enabled #{MAX_PER_GUILD} status checks in this server. Please delete the other webhooks before adding a new check. This webhook will be automatically deleted.", color: ERROR_COLOR),
],
})
end
def send_too_many_channel_message
execute({
embeds: [
embed(title: "E621 Status Check", description: "You already have a status check enabled in this channel. Delete the other webhook to use a new webhook. This webhook will be automatically deleted.", color: ERROR_COLOR),
],
})
end
def send_update(status)
status_text = E621Status::STATUS_MESSAGES[status.status]
fields = [
{ name: "Status", value: "#{status.status} #{status_text.present? ? "(#{status_text})" : ''}", inline: true },
{ name: "State", value: E621Status::STATES[status.state] || (status.available ? "up" : "down"), inline: true },
]
# noinspection RubyMismatchedArgumentType
fields << { name: "Note", value: status.note, inline: false } if status.note.present?
color = status.available ? SUCCESS_COLOR : status.status == 403 ? WARNING_COLOR : ERROR_COLOR
execute({
embeds: [
embed(title: "E621 Status Update", description: "E621's api is **#{status.available ? 'available' : 'unavailable'}**.", color: color,
fields: fields,
timestamp: status.created_at.iso8601,
footer: { text: "Since" }),
],
})
end
def execute(body)
r = webhook&.execute(body)
if webhook.nil? || Requests::DiscordWebhook.is_deleted(r)
@skip_delete_webhook = true
destroy
end
r
end
end
module SearchMethods
def for_guild(id)
where(guild_id: id)
end
def for_channel(id)
where(channel_id: id)
end
end
include WebhookMethods
extend SearchMethods
end