Friday, September 20, 2024 2:46:28 AM
> settings

Customize


Authenticate

> community.rb
# frozen_string_literal: true

module ESM
  class Community < ApplicationRecord
    ALPHABET = ("a".."z").to_a.freeze

    before_create :generate_community_id
    before_create :generate_public_id
    after_create :create_command_configurations
    after_create :create_notifications

    attribute :public_id, :uuid
    attribute :community_id, :string
    attribute :community_name, :text
    attribute :guild_id, :string
    attribute :logging_channel_id, :string
    attribute :log_reconnect_event, :boolean, default: false
    attribute :log_xm8_event, :boolean, default: true
    attribute :log_discord_log_event, :boolean, default: true
    attribute :log_error_event, :boolean, default: true
    attribute :player_mode_enabled, :boolean, default: true
    attribute :territory_admin_ids, :json, default: []
    attribute :welcome_message_enabled, :boolean, default: true
    attribute :welcome_message, :string, default: ""
    attribute :created_at, :datetime
    attribute :updated_at, :datetime

    has_many :command_configurations, dependent: :destroy
    has_many :cooldowns, dependent: :destroy
    has_many :id_defaults, class_name: "CommunityDefault", dependent: :destroy
    has_many :notifications, dependent: :destroy
    has_many :servers, dependent: :destroy
    has_many :user_aliases, dependent: :nullify
    has_many :user_defaults, dependent: :nullify
    has_many :user_notification_routes, foreign_key: :destination_community_id, dependent: :destroy

    alias_attribute :name, :community_name

    module ESM
      ID = "452568470765305866"
    end

    def self.community_ids
      ::ESM.cache.fetch("community_ids", expires_in: ::ESM.config.cache.community_ids) do
        ApplicationRecord.connection_pool.with_connection { pluck(:community_id) }
      end
    end

    def self.correct(id)
      checker = DidYouMean::SpellChecker.new(dictionary: community_ids)
      checker.correct(id)
    end

    def self.find_by_community_id(id)
      includes(:servers).order(:community_id).where("community_id ilike ?", id).first
    end

    def self.find_by_guild_id(id)
      includes(:servers).order(:guild_id).where(guild_id: id).first
    end

    def self.find_by_server_id(id)
      return if id.blank?

      joins(:servers).order(:guild_id).where(servers: {server_id: id}).first
    end

    def self.from_discord(discord_server)
      return if discord_server.nil?

      community = order(:guild_id).where(guild_id: discord_server.id).first_or_initialize
      community.update!(community_name: discord_server.name)
      community
    end

    def logging_channel
      ::ESM.bot.channel(logging_channel_id)
    rescue
      nil
    end

    def discord_server
      ::ESM.bot.server(guild_id)
    rescue
      nil
    end

    def log_event(event, message)
      return if logging_channel_id.blank?

      # Only allow logging events to logging channel if permission has been given
      case event
      when :xm8
        return if !log_xm8_event
      when :discord_log
        return if !log_discord_log_event
      when :reconnect
        return if !log_reconnect_event
      when :error
        return if !log_error_event
      else
        raise ::ESM::Exception::Error, "Attempted to log :#{event} to #{guild_id} without explicit permission.\nMessage:\n#{message}"
      end

      # Check this first to avoid an infinite loop if the bot cannot send a message to this channel
      # since this method is called from the #deliver method for this exact reason.
      channel = logging_channel
      return if channel.nil?

      ::ESM.bot.deliver(message, to: channel)
    end

    def modifiable_by?(guild_member)
      return true if guild_member.permission?(:administrator) || guild_member.owner?

      # Check for roles
      dashboard_access_role_ids.any? { |role_id| guild_member.role?(role_id) }
    end

    private

    def generate_community_id
      return if community_id.present?

      count = 0
      new_id = nil

      loop do
        # Attempt to generate an id. Top rated comment from this answer: https://stackoverflow.com/a/88341
        new_id = ALPHABET.sample(4).join
        count += 1

        # Our only saviors
        break if count > 10_000
        break if self.class.find_by_community_id(new_id).nil?
      end

      # Yup. Add to the community_ids so our spell checker works
      self.class.community_ids << new_id
      self.community_id = new_id
    end

    def generate_public_id
      return if public_id.present?

      self.public_id = SecureRandom.uuid
    end

    def create_command_configurations
      configurations = ::ESM::Command.configurations.map { |c| c.merge(community_id: id) }
      ::ESM::CommandConfiguration.import(configurations)
    end

    def create_notifications
      ::ESM::Notification::DEFAULTS.each do |category, notifications|
        notifications =
          notifications.map do |notification|
            {
              community_id: id,
              notification_type: notification["type"],
              notification_title: notification["title"],
              notification_description: notification["description"],
              notification_color: notification["color"],
              notification_category: category
            }
          end

        ::ESM::Notification.import(notifications)
      end
    end
  end
end
All opinions represented herein are my own
- © 2024 itsthedevman
- build 340fbb8