forum: automatically post new forum posts to Discord.
This commit is contained in:
2
.github/workflows/test.yaml
vendored
2
.github/workflows/test.yaml
vendored
@@ -44,6 +44,8 @@ jobs:
|
|||||||
DANBOORU_PAWOO_CLIENT_SECRET: ${{ secrets.DANBOORU_PAWOO_CLIENT_SECRET }}
|
DANBOORU_PAWOO_CLIENT_SECRET: ${{ secrets.DANBOORU_PAWOO_CLIENT_SECRET }}
|
||||||
DANBOORU_BARAAG_CLIENT_ID: ${{ secrets.DANBOORU_BARAAG_CLIENT_ID }}
|
DANBOORU_BARAAG_CLIENT_ID: ${{ secrets.DANBOORU_BARAAG_CLIENT_ID }}
|
||||||
DANBOORU_BARAAG_CLIENT_SECRET: ${{ secrets.DANBOORU_BARAAG_CLIENT_SECRET }}
|
DANBOORU_BARAAG_CLIENT_SECRET: ${{ secrets.DANBOORU_BARAAG_CLIENT_SECRET }}
|
||||||
|
DANBOORU_DISCORD_WEBHOOK_ID: ${{ secrets.DANBOORU_DISCORD_WEBHOOK_ID }}
|
||||||
|
DANBOORU_DISCORD_WEBHOOK_SECRET: ${{ secrets.DANBOORU_DISCORD_WEBHOOK_SECRET }}
|
||||||
DANBOORU_RAKISMET_KEY: ${{ secrets.DANBOORU_RAKISMET_KEY }}
|
DANBOORU_RAKISMET_KEY: ${{ secrets.DANBOORU_RAKISMET_KEY }}
|
||||||
DANBOORU_RAKISMET_URL: ${{ secrets.DANBOORU_RAKISMET_URL }}
|
DANBOORU_RAKISMET_URL: ${{ secrets.DANBOORU_RAKISMET_URL }}
|
||||||
DANBOORU_IP_REGISTRY_API_KEY: ${{ secrets.DANBOORU_IP_REGISTRY_API_KEY }}
|
DANBOORU_IP_REGISTRY_API_KEY: ${{ secrets.DANBOORU_IP_REGISTRY_API_KEY }}
|
||||||
|
|||||||
7
app/jobs/discord_notification_job.rb
Normal file
7
app/jobs/discord_notification_job.rb
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
class DiscordNotificationJob < ApplicationJob
|
||||||
|
retry_on Exception, attempts: 0
|
||||||
|
|
||||||
|
def perform(forum_post:)
|
||||||
|
forum_post.send_discord_notification
|
||||||
|
end
|
||||||
|
end
|
||||||
@@ -250,6 +250,29 @@ class DText
|
|||||||
text.gsub(/\A[[:space:]]+|[[:space:]]+\z/, "")
|
text.gsub(/\A[[:space:]]+|[[:space:]]+\z/, "")
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def self.to_markdown(dtext)
|
||||||
|
html_to_markdown(format_text(dtext))
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.html_to_markdown(html)
|
||||||
|
html = Nokogiri::HTML.fragment(html)
|
||||||
|
|
||||||
|
html.children.map do |node|
|
||||||
|
case node.name
|
||||||
|
when "div", "blockquote", "table"
|
||||||
|
"" # strip [expand], [quote], and [table] tags
|
||||||
|
when "br"
|
||||||
|
"\n"
|
||||||
|
when "text"
|
||||||
|
node.text.gsub(/_/, '\_').gsub(/\*/, '\*')
|
||||||
|
when "p", "h1", "h2", "h3", "h4", "h5", "h6"
|
||||||
|
html_to_markdown(node.inner_html) + "\n\n"
|
||||||
|
else
|
||||||
|
html_to_markdown(node.inner_html)
|
||||||
|
end
|
||||||
|
end.join
|
||||||
|
end
|
||||||
|
|
||||||
def self.from_html(text, inline: false, &block)
|
def self.from_html(text, inline: false, &block)
|
||||||
html = Nokogiri::HTML.fragment(text)
|
html = Nokogiri::HTML.fragment(text)
|
||||||
|
|
||||||
|
|||||||
56
app/logical/discord_api_client.rb
Normal file
56
app/logical/discord_api_client.rb
Normal file
@@ -0,0 +1,56 @@
|
|||||||
|
class DiscordApiClient
|
||||||
|
attr_reader :webhook_id, :webhook_secret, :http
|
||||||
|
|
||||||
|
def initialize(webhook_id: Danbooru.config.discord_webhook_id, webhook_secret: Danbooru.config.discord_webhook_secret, http: Danbooru::Http.new)
|
||||||
|
@webhook_id = webhook_id
|
||||||
|
@webhook_secret = webhook_secret
|
||||||
|
@http = http
|
||||||
|
end
|
||||||
|
|
||||||
|
def enabled?
|
||||||
|
webhook_id.present? && webhook_secret.present?
|
||||||
|
end
|
||||||
|
|
||||||
|
# https://discord.com/developers/docs/resources/webhook#execute-webhook
|
||||||
|
def post_message(forum_post)
|
||||||
|
return unless enabled?
|
||||||
|
|
||||||
|
http.post(webhook_url, params: { wait: true }, json: build_message(forum_post))
|
||||||
|
end
|
||||||
|
|
||||||
|
# https://discord.com/developers/docs/resources/channel#embed-object
|
||||||
|
def build_message(forum_post)
|
||||||
|
{
|
||||||
|
embeds: [{
|
||||||
|
title: forum_post.topic.title,
|
||||||
|
description: convert_dtext(forum_post.body),
|
||||||
|
timestamp: forum_post.created_at.iso8601,
|
||||||
|
url: Routes.url_for(forum_post),
|
||||||
|
author: {
|
||||||
|
name: forum_post.creator.name,
|
||||||
|
url: Routes.url_for(forum_post.creator)
|
||||||
|
},
|
||||||
|
fields: [
|
||||||
|
{
|
||||||
|
name: "Replies",
|
||||||
|
value: forum_post.topic.response_count,
|
||||||
|
inline: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Users",
|
||||||
|
value: forum_post.topic.forum_posts.distinct.count(:creator_id),
|
||||||
|
inline: true
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}]
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
def convert_dtext(dtext)
|
||||||
|
DText.to_markdown(dtext).truncate(2000)
|
||||||
|
end
|
||||||
|
|
||||||
|
def webhook_url
|
||||||
|
"https://discord.com/api/webhooks/#{webhook_id}/#{webhook_secret}"
|
||||||
|
end
|
||||||
|
end
|
||||||
@@ -23,6 +23,7 @@ class ForumPost < ApplicationRecord
|
|||||||
after_destroy(:if => ->(rec) {rec.updater_id != rec.creator_id}) do |rec|
|
after_destroy(:if => ->(rec) {rec.updater_id != rec.creator_id}) do |rec|
|
||||||
ModAction.log("#{CurrentUser.user.name} deleted forum ##{rec.id}", :forum_post_delete)
|
ModAction.log("#{CurrentUser.user.name} deleted forum ##{rec.id}", :forum_post_delete)
|
||||||
end
|
end
|
||||||
|
after_create_commit :async_send_discord_notification
|
||||||
|
|
||||||
deletable
|
deletable
|
||||||
mentionable(
|
mentionable(
|
||||||
@@ -153,6 +154,15 @@ class ForumPost < ApplicationRecord
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def async_send_discord_notification
|
||||||
|
DiscordNotificationJob.perform_later(forum_post: self)
|
||||||
|
end
|
||||||
|
|
||||||
|
def send_discord_notification
|
||||||
|
return unless policy(User.anonymous).show?
|
||||||
|
DiscordApiClient.new.post_message(self)
|
||||||
|
end
|
||||||
|
|
||||||
def build_response
|
def build_response
|
||||||
dup.tap do |x|
|
dup.tap do |x|
|
||||||
x.body = x.quoted_response
|
x.body = x.quoted_response
|
||||||
|
|||||||
@@ -394,6 +394,14 @@ module Danbooru
|
|||||||
def twitter_api_secret
|
def twitter_api_secret
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# If defined, Danbooru will automatically post new forum posts to the
|
||||||
|
# Discord channel belonging to this webhook.
|
||||||
|
def discord_webhook_id
|
||||||
|
end
|
||||||
|
|
||||||
|
def discord_webhook_secret
|
||||||
|
end
|
||||||
|
|
||||||
# you should override this
|
# you should override this
|
||||||
def email_key
|
def email_key
|
||||||
"zDMSATq0W3hmA5p3rKTgD"
|
"zDMSATq0W3hmA5p3rKTgD"
|
||||||
|
|||||||
Reference in New Issue
Block a user