# frozen_string_literal: true module Discorb # # Represents a text channel. # class TextChannel < GuildChannel # @return [String] The topic of the channel. attr_reader :topic # @return [Boolean] Whether the channel is nsfw. attr_reader :nsfw # @return [Discorb::Snowflake] The id of the last message. attr_reader :last_message_id # @return [Integer] The rate limit per user (Slowmode) in the channel. attr_reader :rate_limit_per_user alias slowmode rate_limit_per_user # @return [Time] The time when the last pinned message was pinned. attr_reader :last_pin_timestamp alias last_pinned_at last_pin_timestamp # @return [Integer] The default value of duration of auto archive. attr_reader :default_auto_archive_duration include Messageable # @return [{Integer => Symbol}] The auto archive duration map. # @private DEFAULT_AUTO_ARCHIVE_DURATION = { 60 => :hour, 1440 => :day, 4320 => :three_days, 10080 => :week, }.freeze @channel_type = 0 # @!attribute [r] threads # @return [Array] The threads in the channel. def threads guild.threads.select { |thread| thread.parent == self } end # # Edits the channel. # @async # @macro edit # # @param [String] name The name of the channel. # @param [Integer] position The position of the channel. # @param [Discorb::CategoryChannel, nil] category The parent of channel. Specify `nil` to remove the parent. # @param [Discorb::CategoryChannel, nil] parent Alias of `category`. # @param [String] topic The topic of the channel. # @param [Boolean] nsfw Whether the channel is nsfw. # @param [Boolean] announce Whether the channel is announce channel. # @param [Integer] rate_limit_per_user The rate limit per user (Slowmode) in the channel. # @param [Integer] slowmode Alias of `rate_limit_per_user`. # @param [Integer] default_auto_archive_duration The default auto archive duration of the channel. # @param [Integer] archive_in Alias of `default_auto_archive_duration`. # @param [String] reason The reason of editing the channel. # # @return [Async::Task] The edited channel. # def edit( name: Discorb::Unset, position: Discorb::Unset, category: Discorb::Unset, parent: Discorb::Unset, topic: Discorb::Unset, nsfw: Discorb::Unset, announce: Discorb::Unset, rate_limit_per_user: Discorb::Unset, slowmode: Discorb::Unset, default_auto_archive_duration: Discorb::Unset, archive_in: Discorb::Unset, reason: nil ) Async do payload = {} payload[:name] = name if name != Discorb::Unset payload[:announce] = announce ? 5 : 0 if announce != Discorb::Unset payload[:position] = position if position != Discorb::Unset payload[:topic] = topic || "" if topic != Discorb::Unset payload[:nsfw] = nsfw if nsfw != Discorb::Unset slowmode = rate_limit_per_user if slowmode == Discorb::Unset payload[:rate_limit_per_user] = slowmode || 0 if slowmode != Discorb::Unset parent = category if parent == Discorb::Unset payload[:parent_id] = parent&.id if parent != Discorb::Unset default_auto_archive_duration ||= archive_in if default_auto_archive_duration != Discorb::Unset payload[:default_auto_archive_duration] = default_auto_archive_duration end @client.http.request(Route.new("/channels/#{@id}", "//channels/:channel_id", :patch), payload, audit_log_reason: reason).wait self end end alias modify edit # # Create webhook in the channel. # @async # # @param [String] name The name of the webhook. # @param [Discorb::Image] avatar The avatar of the webhook. # # @return [Async::Task] The created webhook. # def create_webhook(name, avatar: nil) Async do payload = {} payload[:name] = name payload[:avatar] = avatar.to_s if avatar _resp, data = @client.http.request( Route.new("/channels/#{@id}/webhooks", "//channels/:channel_id/webhooks", :post), payload ).wait Webhook.from_data(@client, data) end end # # Fetch webhooks in the channel. # @async # # @return [Async::Task>] The webhooks in the channel. # def fetch_webhooks Async do _resp, data = @client.http.request(Route.new("/channels/#{@id}/webhooks", "//channels/:channel_id/webhooks", :get)).wait data.map { |webhook| Webhook.new([@client, webhook]) } end end # # Bulk delete messages in the channel. # @async # # @param [Discorb::Message] messages The messages to delete. # @param [Boolean] force Whether to ignore the validation for message (14 days limit). # # @return [Async::Task] The task. # def delete_messages!(*messages, force: false) Async do messages = messages.first if messages.length == 1 && messages.first.is_a?(Array) unless force time = Time.now messages.delete_if do |message| next false unless message.is_a?(Message) time - message.created_at > 60 * 60 * 24 * 14 end end message_ids = messages.map { |m| Discorb::Utils.try(m, :id).to_s } @client.http.request( Route.new("/channels/#{@id}/messages/bulk-delete", "//channels/:channel_id/messages/bulk-delete", :post), { messages: message_ids } ).wait end end alias bulk_delete! delete_messages! alias destroy_messages! delete_messages! # # Follow the existing announcement channel. # @async # # @param [Discorb::NewsChannel] target The channel to follow. # @param [String] reason The reason of following the channel. # # @return [Async::Task] The task. # def follow_from(target, reason: nil) Async do @client.http.request(Route.new("/channels/#{target.id}/followers", "//channels/:channel_id/followers", :post), { webhook_channel_id: @id }, audit_log_reason: reason).wait end end # # Start thread in the channel. # @async # # @param [String] name The name of the thread. # @param [Discorb::Message] message The message to start the thread. # @param [:hour, :day, :three_days, :week] auto_archive_duration The duration of auto-archiving. # @param [Boolean] public Whether the thread is public. # @param [Integer] rate_limit_per_user The rate limit per user. # @param [Integer] slowmode Alias of `rate_limit_per_user`. # @param [String] reason The reason of starting the thread. # # @return [Async::Task] The started thread. # def start_thread( name, message: nil, auto_archive_duration: nil, public: true, rate_limit_per_user: nil, slowmode: nil, reason: nil ) auto_archive_duration ||= @default_auto_archive_duration auto_archive_duration_value = DEFAULT_AUTO_ARCHIVE_DURATION.key(auto_archive_duration) Async do _resp, data = if message.nil? @client.http.request( Route.new("/channels/#{@id}/threads", "//channels/:channel_id/threads", :post), { name: name, auto_archive_duration: auto_archive_duration_value, type: public ? 11 : 10, rate_limit_per_user: rate_limit_per_user || slowmode, }, audit_log_reason: reason, ).wait else @client.http.request( Route.new("/channels/#{@id}/messages/#{Utils.try(message, :id)}/threads", "//channels/:channel_id/messages/:message_id/threads", :post), { name: name, auto_archive_duration: auto_archive_duration_value, }, audit_log_reason: reason, ).wait end Channel.make_channel(@client, data) end end alias create_thread start_thread # # Fetch archived threads in the channel. # @async # # @return [Async::Task>] The archived threads in the channel. # def fetch_archived_public_threads Async do _resp, data = @client.http.request(Route.new("/channels/#{@id}/threads/archived/public", "//channels/:channel_id/threads/archived/public", :get)).wait data.map { |thread| Channel.make_channel(@client, thread) } end end # # Fetch archived private threads in the channel. # @async # # @return [Async::Task>] The archived private threads in the channel. # def fetch_archived_private_threads Async do _resp, data = @client.http.request(Route.new("/channels/#{@id}/threads/archived/private", "//channels/:channel_id/threads/archived/private", :get)).wait data.map { |thread| Channel.make_channel(@client, thread) } end end # # Fetch joined archived private threads in the channel. # @async # # @param [Integer] limit The limit of threads to fetch. # @param [Time] before # # @return [Async::Task>] The joined archived private threads in the channel. # def fetch_joined_archived_private_threads(limit: nil, before: nil) Async do if limit.nil? before = 0 threads = [] loop do _resp, data = @client.http.request( Route.new( "/channels/#{@id}/users/@me/threads/archived/private?before=#{before}", "//channels/:channel_id/users/@me/threads/archived/private", :get ) ).wait threads += data[:threads].map { |thread| Channel.make_channel(@client, thread) } before = data[:threads][-1][:id] break unless data[:has_more] end threads else _resp, data = @client.http.request( Route.new( "/channels/#{@id}/users/@me/threads/archived/private?limit=#{limit}&before=#{before}", "//channels/:channel_id/users/@me/threads/archived/private", :get ) ).wait data.map { |thread| Channel.make_channel(@client, thread) } end end end private def _set_data(data) @topic = data[:topic] @nsfw = data[:nsfw] @last_message_id = data[:last_message_id] @rate_limit_per_user = data[:rate_limit_per_user] @last_pin_timestamp = data[:last_pin_timestamp] && Time.iso8601(data[:last_pin_timestamp]) @default_auto_archive_duration = DEFAULT_AUTO_ARCHIVE_DURATION[data[:default_auto_archive_duration]] super end end # # Represents a news channel (announcement channel). # class NewsChannel < TextChannel @channel_type = 5 # # Follow the existing announcement channel from self. # @async # # @param [Discorb::TextChannel] target The channel to follow to. # @param [String] reason The reason of following the channel. # # @return [Async::Task] The task. # def follow_to(target, reason: nil) Async do @client.http.request(Route.new("/channels/#{@id}/followers", "//channels/:channel_id/followers", :post), { webhook_channel_id: target.id }, audit_log_reason: reason).wait end end end end