require “set” require “cinch/target”
module Cinch
# @attr limit # @attr secret # @attr moderated # @attr invite_only # @attr key # # @version 2.0.0 class Channel < Target include Syncable include Helpers def initialize(name, bot) @bot = bot @name = name # TODO raise if not a channel end def users sync_get(:users) end def topic sync_get(:topic, lambda {@bot.irc.send "TOPIC #@name"}) end def bans sync_get(:bans, lambda {@bot.irc.send "MODE #@name +b"}) end def owners sync_get(:owners, lambda { if !@bot.irc.network.owner_list_mode sync_set(:owners, []) return end @bot.irc.send "MODE #@name +#{@bot.irc.network.owner_list_mode}" }) end def modes sync_get(:modes, lambda {@bot.irc.send "MODE #@name"}) end # @group Checks # @param [User, String] user An {User}-object or a nickname # @return [Boolean] Check if a user is in the channel # @since 1.1.0 # @version 1.1.2 def has_user?(user) users.has_key?(User(user)) end # @return [Boolean] true if `user` is opped in the channel # @since 1.1.0 def opped?(user) users[User(user)].include? "o" end # @return [Boolean] true if `user` is half-opped in the channel # @since 1.1.0 def half_opped?(user) users[User(user)].include? "h" end # @return [Boolean] true if `user` is voiced in the channel # @since 1.1.0 def voiced?(user) users[User(user)].include? "v" end # @endgroup # @group User groups # @return [Array<User>] All ops in the channel # @since 2.0.0 def ops users.select {|user, modes| modes.include?("o")}.keys end # @return [Array<User>] All half-ops in the channel # @since 2.0.0 def half_ops users.select {|user, modes| modes.include?("h")}.keys end # @return [Array<User>] All voiced users in the channel # @since 2.0.0 def voiced users.select {|user, modes| modes.include?("v")}.keys end # @return [Array<User>] All admins in the channel # @since 2.0.0 def admins users.select {|user, modes| modes.include?("a")}.keys end # @endgroup # @return [Integer] The maximum number of allowed users in the # channel. 0 if unlimited. def limit modes["l"].to_i end def limit=(val) if val == -1 or val.nil? mode "-l" else mode "+l #{val}" end end # @return [Boolean] true if the channel is secret (+s) def secret? modes["s"] end alias_method :secret, :secret? def secret=(bool) if bool mode "+s" else mode "-s" end end # @return [Boolean] true if the channel is moderated def moderated? modes["m"] end alias_method :moderated, :moderated? def moderated=(bool) if bool mode "+m" else mode "-m" end end # @return [Boolean] true if the channel is invite only (+i) def invite_only? modes["i"] end alias_method :invite_only, :invite_only? def invite_only=(bool) if bool mode "+i" else mode "-i" end end # @return [String, nil] The channel's key (aka password) def key modes["k"] end def key=(new_key) if new_key.nil? mode "-k #{key}" else mode "+k #{new_key}" end end # @api private # @return [void] def sync_modes sync_await(:users) sync_unset(:users) if @bot.irc.isupport["WHOX"] @bot.irc.send "WHO #@name %acfhnru" else @bot.irc.send "WHO #@name" end end # @group Channel Manipulation # Bans someone from the channel. # # @param [Mask, String, #mask] target the mask, or an object having a mask, to ban # @return [Mask] the mask used for banning # @see #unban #unban for unbanning users def ban(target) mask = Mask.from(target) @bot.irc.send "MODE #@name +b #{mask}" mask end # Unbans someone from the channel. # # @param [Mask, String, #mask] target the mask to unban # @return [Mask] the mask used for unbanning # @see #ban #ban for banning users def unban(target) mask = Mask.from(target) @bot.irc.send "MODE #@name -b #{mask}" mask end # Ops a user. # # @param [String, User] user the user to op # @return [void] def op(user) @bot.irc.send "MODE #@name +o #{user}" end # Deops a user. # # @param [String, User] user the user to deop # @return [void] def deop(user) @bot.irc.send "MODE #@name -o #{user}" end # Voices a user. # # @param [String, User] user the user to voice # @return [void] def voice(user) @bot.irc.send "MODE #@name +v #{user}" end # Devoices a user. # # @param [String, User] user the user to devoice # @return [void] def devoice(user) @bot.irc.send "MODE #@name -v #{user}" end # Invites a user to the channel. # # @param [String, User] user the user to invite # @return [void] def invite(user) @bot.irc.send("INVITE #{user} #@name") end undef_method(:topic=) # Sets the topic. # # @param [String] new_topic the new topic # @raise [Exceptions::TopicTooLong] Raised if the bot is operating # in {Bot#strict? strict mode} and when the new topic is too long. def topic=(new_topic) if new_topic.size > @bot.irc.isupport["TOPICLEN"] && @bot.strict? raise Exceptions::TopicTooLong, new_topic end @bot.irc.send "TOPIC #@name :#{new_topic}" end # Kicks a user from the channel. # # @param [String, User] user the user to kick # @param [String] reason a reason for the kick # @raise [Exceptions::KickReasonTooLong] # @return [void] def kick(user, reason = nil) if reason.to_s.size > @bot.irc.isupport["KICKLEN"] && @bot.strict? raise Exceptions::KickReasonTooLong, reason end @bot.irc.send("KICK #@name #{user} :#{reason}") end # Removes a user from the channel. # # This uses the REMOVE command, which is a non-standardized # extension. Unlike a kick, it makes a user part. This prevents # auto-rejoin scripts from firing and might also be perceived as # less aggressive by some. Not all IRC networks support this # command. # # @param [User] user the user to remove # @param [String] reason a reason for the removal # @return [void] def remove(user, reason = nil) @bot.irc.send("REMOVE #@name #{user} :#{reason}") end # Sets or unsets modes. Most of the time you won't need this but # use setter methods like {Channel#invite_only=}. # # @param [String] s a mode string # @return [void] # @example # channel.mode "+n" def mode(s) @bot.irc.send "MODE #@name #{s}" end # Causes the bot to part from the channel. # # @param [String] message the part message. # @return [void] def part(message = nil) @bot.irc.send "PART #@name :#{message}" end # Joins the channel # # @param [String] key the channel key, if any. If none is # specified but @key is set, @key will be used # @return [void] def join(key = nil) if key.nil? and self.key != true key = self.key end @bot.irc.send "JOIN #{[@name, key].compact.join(" ")}" end # @endgroup # @api private # @return [User] The added user def add_user(user, modes = []) # XXX @users[user] = modes user end # @api private # @return [User, nil] The removed user def remove_user(user) # XXX @users.delete(user) end # Removes all users # # @api private # @return [void] def clear_users # XXX @users.clear end # @note The aliases `msg` and `privmsg` are deprecated and will be # removed in a future version. def send(text, notice = false) # TODO deprecate 'notice' argument text = text.to_s if @modes["c"] # Remove all formatting and colors if the channel doesn't # allow colors. text = Cinch::Formatting.unformat(text) end super(text, notice) end alias_method :msg, :send # deprecated alias_method :privmsg, :send # deprecated undef_method(:msg) # yardoc hack undef_method(:privmsg) # yardoc hack # @deprecated def msg(*args) Cinch::Utilities::Deprecation.print_deprecation("2.2.0", "Channel#msg", "Channel#send") send(*args) end # @deprecated def privmsg(*args) Cinch::Utilities::Deprecation.print_deprecation("2.2.0", "Channel#privmsg", "Channel#send") send(*args) end # @return [Fixnum] def hash @name.hash end # @return [String] # @note The alias `to_str` is deprecated and will be removed in a # future version. Channel objects should not be treated like # strings. def to_s @name end alias_method :to_str, :to_s # deprecated undef_method(:to_str) # yardoc hack def to_str Cinch::Utilities::Deprecation.print_deprecation("2.2.0", "Channel#to_str", "Channel#to_s") to_s end # @return [String] def inspect "#<Channel name=#{@name.inspect}>" end end
end