<commit_before># -*- coding: utf-8 -*-
require 'socket'
require "thread"
require "ostruct"
require "cinch/rubyext/module"
require "cinch/rubyext/queue"
require "cinch/rubyext/string"
require "cinch/rubyext/infinity"

require "cinch/exceptions"

require "cinch/helpers"
require "cinch/logger/logger"
require "cinch/logger/null_logger"
require "cinch/logger/formatted_logger"
require "cinch/syncable"
require "cinch/message"
require "cinch/message_queue"
require "cinch/irc"
require "cinch/channel"
require "cinch/user"
require "cinch/constants"
require "cinch/callback"
require "cinch/ban"
require "cinch/mask"
require "cinch/isupport"
require "cinch/plugin"

module Cinch

  class Bot
    # @return [Config]
    attr_accessor :config
    # @return [IRC]
    attr_accessor :irc
    # @return [Logger]
    attr_accessor :logger
    # @return [Array<Channel>] All channels the bot currently is in
    attr_reader :channels
    # @return [String]
    attr_reader :host
    # @return [Mask]
    attr_reader :mask
    # @return [String]
    attr_reader :user
    # @return [String]
    attr_reader :realname
    # @return [Time]
    attr_reader :signed_on_at

    # Helper method for turning a String into a {Channel} object.
    #
    # @param [String] channel a channel name
    # @return [Channel] a {Channel} object
    # @example
    #   on :message, /^please join (#.+)$/ do |target|
    #     Channel(target).join
    #   end
    def Channel(channel)
      return channel if channel.is_a?(Channel)
      Channel.find_ensured(channel, self)
    end

    # Helper method for turning a String into an {User} object.
    #
    # @param [String] user a user's nickname
    # @return [User] an {User} object
    # @example
    #   on :message, /^tell me everything about (.+)$/ do |target|
    #     user = User(target)
    #     reply "%s is named %s and connects from %s" % [user.nick, user.name, user.host]
    #   end
    def User(user)
      return user if user.is_a?(User)
      User.find_ensured(user, self)
    end

    # @return [void]
    # @see Logger#debug
    def debug(msg)
      @logger.debug(msg)
    end

    # @return [Boolean]
    def strict?
      @config.strictness == :strict
    end

    # @yield
    def initialize(&b)
      @logger = Logger::FormattedLogger.new($stderr)
      @events = {}
      @config = OpenStruct.new({
                                 :server => "localhost",
                                 :port   => 6667,
                                 :ssl    => false,
                                 :password => <PASSWORD>,
                                 :nick   => "cinch",
                                 :realname => "cinch",
                                 :verbose => true,
                                 :messages_per_second => 0.5,
                                 :server_queue_size => 10,
                                 :strictness => :forgiving,
                                 :message_split_start => '... ',
                                 :message_split_end   => ' ...',
                                 :max_messages => nil,
                                 :plugins => OpenStruct.new({
                                                              :plugins => [],
                                                              :prefix  => "!",
                                                              :options => Hash.new {|h,k| h[k] = {}},
                                                            }),
                                 :channels => [],
                                 :encoding => nil,
                               })

      @semaphores = {}
      @plugins = []
      @callback = Callback.new(self)
      @channels = []

      on :connect do
        bot.config.channels.each do |channel|
          bot.join channel
        end
      end

      instance_eval(&b) if block_given?
    end

    # This method is used to set a bot's options. It indeed does
    # nothing else but yielding {Bot#config}, but it makes for a nice DSL.
    #
    # @yieldparam [Struct] config the bot's config
    # @return [void]
    def configure(&block)
      @callback.instance_exec(@config, &block)
    end

    # Since Cinch uses threads, all handlers can be run
    # simultaneously, even the same handler multiple times. This also
    # means, that your code has to be thread-safe. Most of the time,
    # this is not a problem, but if you are accessing stored data, you
    # will most likely have to synchronize access to it. Instead of
    # managing all mutexes yourself, Cinch provides a synchronize
    # method, which takes a name and block.
    #
    # Synchronize blocks with the same name share the same mutex,
    # which means that only one of them will be executed at a time.
    #
    # @param [String, Symbol] name a name for the synchronize block.
    # @return [void]
    # @yield
    #
    # @example
    #    configure do |c|
    #      …
    #      @i = 0
    #    end
    #
    #    on :channel, /^start counting!/ do
    #      synchronize(:my_counter) do
    #        10.times do
    #          val = @i
    #          # at this point, another thread might've incremented :i already.
    #          # this thread wouldn't know about it, though.
    #          @i = val + 1
    #        end
    #      end
    #    end
    def synchronize(name, &block)
      semaphore = (@semaphores[name] ||= Mutex.new)
      semaphore.synchronize(&block)
    end

    # Registers a handler.
    #
    # @param [String, Symbol, Integer] event the event to match. Available<commit_msg>thread safe synchronization patch from raggi<commit_after># -*- coding: utf-8 -*-
require 'socket'
require "thread"
require "ostruct"
require "cinch/rubyext/module"
require "cinch/rubyext/queue"
require "cinch/rubyext/string"
require "cinch/rubyext/infinity"

require "cinch/exceptions"

require "cinch/helpers"
require "cinch/logger/logger"
require "cinch/logger/null_logger"
require "cinch/logger/formatted_logger"
require "cinch/syncable"
require "cinch/message"
require "cinch/message_queue"
require "cinch/irc"
require "cinch/channel"
require "cinch/user"
require "cinch/constants"
require "cinch/callback"
require "cinch/ban"
require "cinch/mask"
require "cinch/isupport"
require "cinch/plugin"

module Cinch

  class Bot
    # @return [Config]
    attr_accessor :config
    # @return [IRC]
    attr_accessor :irc
    # @return [Logger]
    attr_accessor :logger
    # @return [Array<Channel>] All channels the bot currently is in
    attr_reader :channels
    # @return [String]
    attr_reader :host
    # @return [Mask]
    attr_reader :mask
    # @return [String]
    attr_reader :user
    # @return [String]
    attr_reader :realname
    # @return [Time]
    attr_reader :signed_on_at

    # Helper method for turning a String into a {Channel} object.
    #
    # @param [String] channel a channel name
    # @return [Channel] a {Channel} object
    # @example
    #   on :message, /^please join (#.+)$/ do |target|
    #     Channel(target).join
    #   end
    def Channel(channel)
      return channel if channel.is_a?(Channel)
      Channel.find_ensured(channel, self)
    end

    # Helper method for turning a String into an {User} object.
    #
    # @param [String] user a user's nickname
    # @return [User] an {User} object
    # @example
    #   on :message, /^tell me everything about (.+)$/ do |target|
    #     user = User(target)
    #     reply "%s is named %s and connects from %s" % [user.nick, user.name, user.host]
    #   end
    def User(user)
      return user if user.is_a?(User)
      User.find_ensured(user, self)
    end

    # @return [void]
    # @see Logger#debug
    def debug(msg)
      @logger.debug(msg)
    end

    # @return [Boolean]
    def strict?
      @config.strictness == :strict
    end

    # @yield
    def initialize(&b)
      @logger = Logger::FormattedLogger.new($stderr)
      @events = {}
      @config = OpenStruct.new({
                                 :server => "localhost",
                                 :port   => 6667,
                                 :ssl    => false,
                                 :password => <PASSWORD>,
                                 :nick   => "cinch",
                                 :realname => "cinch",
                                 :verbose => true,
                                 :messages_per_second => 0.5,
                                 :server_queue_size => 10,
                                 :strictness => :forgiving,
                                 :message_split_start => '... ',
                                 :message_split_end   => ' ...',
                                 :max_messages => nil,
                                 :plugins => OpenStruct.new({
                                                              :plugins => [],
                                                              :prefix  => "!",
                                                              :options => Hash.new {|h,k| h[k] = {}},
                                                            }),
                                 :channels => [],
                                 :encoding => nil,
                               })

      @semaphores_mutex = Mutex.new
      @semaphores = Hash.new { |h,k| h[k] = Mutex.new }
      @plugins = []
      @callback = Callback.new(self)
      @channels = []

      on :connect do
        bot.config.channels.each do |channel|
          bot.join channel
        end
      end

      instance_eval(&b) if block_given?
    end

    # This method is used to set a bot's options. It indeed does
    # nothing else but yielding {Bot#config}, but it makes for a nice DSL.
    #
    # @yieldparam [Struct] config the bot's config
    # @return [void]
    def configure(&block)
      @callback.instance_exec(@config, &block)
    end

    # Since Cinch uses threads, all handlers can be run
    # simultaneously, even the same handler multiple times. This also
    # means, that your code has to be thread-safe. Most of the time,
    # this is not a problem, but if you are accessing stored data, you
    # will most likely have to synchronize access to it. Instead of
    # managing all mutexes yourself, Cinch provides a synchronize
    # method, which takes a name and block.
    #
    # Synchronize blocks with the same name share the same mutex,
    # which means that only one of them will be executed at a time.
    #
    # @param [String, Symbol] name a name for the synchronize block.
    # @return [void]
    # @yield
    #
    # @example
    #    configure do |c|
    #      …
    #      @i = 0
    #    end
    #
    #    on :channel, /^start counting!/ do
    #      synchronize(:my_counter) do
    #        10.times do
    #          val = @i
    #          # at this point, another thread might've incremented :i already.
    #          # this thread wouldn't know about it, though.
    #          @i = val + 1
    #        end
    #      end
    #    end
    def synchronize(name, &block)
      # Must run the default block +/ fetch in a thread safe way in order to
      # ensure we always get the same mutex for a given name.
      semaphore = @semaphores_mutex.synchronize { @semaphores[name] }
      semaphore.synchronize(&block)
    end

    # Registers a handler.
    #
    # @param [String, Symbol, Integer] event the event to match. Available
{'fraction_non_alphanumeric': 0.10268131868131868, 'fraction_numerical': 0.002285714285714286, 'mean_word_length': 1.6363847045191193, 'pattern_counts': {'":': 0, '<': 7, '<?xml version=': 0, '>': 45, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 48, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2798882', 'n_tokens_mistral': 3267, 'n_tokens_neox': 3177, 'n_words': 979}