Class: Irc::Server
Overview
An IRC Server represents the Server the client is connected to.
Instance Attribute Summary collapse
-
#capabilities ⇒ Object
readonly
Returns the value of attribute capabilities.
-
#chanmodes ⇒ Object
readonly
Returns the value of attribute chanmodes.
-
#channels ⇒ Object
readonly
Returns the value of attribute channels.
-
#hostname ⇒ Object
(also: #to_s)
readonly
Returns the value of attribute hostname.
-
#supports ⇒ Object
readonly
Returns the value of attribute supports.
-
#usermodes ⇒ Object
readonly
Returns the value of attribute usermodes.
-
#users ⇒ Object
readonly
Returns the value of attribute users.
-
#version ⇒ Object
readonly
Returns the value of attribute version.
Instance Method Summary collapse
-
#casemap ⇒ Object
Returns the casemap of the server.
-
#channel(str) ⇒ Object
Returns the Channel with the given name on the server, creating it if necessary.
-
#channel_names ⇒ Object
TODO Ho.
-
#clear ⇒ Object
Clears the server.
-
#delete_channel(name) ⇒ Object
Remove Channel name from the list of
Channel
s. -
#delete_user(someuser) ⇒ Object
Remove User someuser from the list of
User
s. -
#delete_user_from_channel(user, channel) ⇒ Object
Deletes User user from Channel channel.
-
#find_users(mask) ⇒ Object
Finds all
User
s on server whose Netmask matches mask. -
#get_channel(name) ⇒ Object
(also: #get_chan)
Returns the channel with name name, if available.
-
#get_user(nick) ⇒ Object
Returns the user with nick nick, if available.
-
#has_channel?(name) ⇒ Boolean
(also: #has_chan?)
Checks if the receiver already has a channel with the given name.
-
#has_user?(nick) ⇒ Boolean
Checks if the receiver already has a user with the given nick.
-
#initialize ⇒ Server
constructor
Create a new Server, with all instance variables reset to nil (for scalar variables), empty channel and user lists and @supports initialized to the default values for all known supported features.
- #inspect ⇒ Object
-
#mode_for_prefix(pfx) ⇒ Object
Convert a prefix (@, +, %, …) to the corresponding mode (o, v, h, …).
-
#new_channel(name, topic = nil, users = [], fails = true) ⇒ Object
Create a new Channel object bound to the receiver and add it to the list of
Channel
s on the receiver, unless the channel was present already. -
#new_netmask(str) ⇒ Object
Create a new Netmask object with the appropriate casemap.
-
#new_user(str, fails = true) ⇒ Object
Create a new User object bound to the receiver and add it to the list of
User
s on the receiver, unless the User was present already. -
#parse_isupport(line) ⇒ Object
This method is used to parse a 005 RPL_ISUPPORT line.
-
#parse_my_info(line) ⇒ Object
This method is used to parse a 004 RPL_MY_INFO line.
-
#prefix_for_mode(mode) ⇒ Object
Convert a mode (o, v, h, …) to the corresponding prefix (@, +, %, …).
-
#reset_capabilities ⇒ Object
Resets the server capabilities.
-
#reset_lists ⇒ Object
Resets the Channel and User list.
-
#user(str) ⇒ Object
Returns the User with the given Netmask on the server, creating it if necessary.
-
#user_nicks ⇒ Object
TODO Ho.
-
#user_or_channel(name) ⇒ Object
Returns the actual User or Channel object matching name.
-
#user_or_channel?(name) ⇒ Boolean
Returns User or Channel depending on what name can be a name of.
Constructor Details
#initialize ⇒ Server
Create a new Server, with all instance variables reset to nil (for scalar variables), empty channel and user lists and @supports initialized to the default values for all known supported features.
1563 1564 1565 1566 1567 1568 1569 1570 1571 |
# File 'lib/rbot/irc.rb', line 1563 def initialize @hostname = @version = @usermodes = @chanmodes = nil @channels = ChannelList.new @users = UserList.new reset_capabilities end |
Instance Attribute Details
#capabilities ⇒ Object (readonly)
Returns the value of attribute capabilities.
1529 1530 1531 |
# File 'lib/rbot/irc.rb', line 1529 def capabilities @capabilities end |
#chanmodes ⇒ Object (readonly)
Returns the value of attribute chanmodes.
1527 1528 1529 |
# File 'lib/rbot/irc.rb', line 1527 def chanmodes @chanmodes end |
#channels ⇒ Object (readonly)
Returns the value of attribute channels.
1531 1532 1533 |
# File 'lib/rbot/irc.rb', line 1531 def channels @channels end |
#hostname ⇒ Object (readonly) Also known as: to_s
Returns the value of attribute hostname.
1527 1528 1529 |
# File 'lib/rbot/irc.rb', line 1527 def hostname @hostname end |
#supports ⇒ Object (readonly)
Returns the value of attribute supports.
1529 1530 1531 |
# File 'lib/rbot/irc.rb', line 1529 def supports @supports end |
#usermodes ⇒ Object (readonly)
Returns the value of attribute usermodes.
1527 1528 1529 |
# File 'lib/rbot/irc.rb', line 1527 def usermodes @usermodes end |
#users ⇒ Object (readonly)
Returns the value of attribute users.
1531 1532 1533 |
# File 'lib/rbot/irc.rb', line 1531 def users @users end |
#version ⇒ Object (readonly)
Returns the value of attribute version.
1527 1528 1529 |
# File 'lib/rbot/irc.rb', line 1527 def version @version end |
Instance Method Details
#casemap ⇒ Object
Returns the casemap of the server.
1786 1787 1788 |
# File 'lib/rbot/irc.rb', line 1786 def casemap @supports[:casemapping] end |
#channel(str) ⇒ Object
Returns the Channel with the given name on the server, creating it if necessary. This is a short form for new_channel(str, nil, [], false
)
1912 1913 1914 |
# File 'lib/rbot/irc.rb', line 1912 def channel(str) new_channel(str,nil,[],false) end |
#channel_names ⇒ Object
TODO Ho
1534 1535 1536 |
# File 'lib/rbot/irc.rb', line 1534 def channel_names @channels.map { |ch| ch.downcase } end |
#clear ⇒ Object
Clears the server
1637 1638 1639 1640 1641 |
# File 'lib/rbot/irc.rb', line 1637 def clear reset_lists reset_capabilities @hostname = @version = @usermodes = @chanmodes = nil end |
#delete_channel(name) ⇒ Object
Remove Channel name from the list of Channel
s
1918 1919 1920 1921 1922 |
# File 'lib/rbot/irc.rb', line 1918 def delete_channel(name) idx = has_channel?(name) raise "Tried to remove unmanaged channel #{name}" unless idx @channels.delete_at(idx) end |
#delete_user(someuser) ⇒ Object
Remove User someuser from the list of User
s. someuser must be specified with the full Netmask.
1993 1994 1995 1996 1997 1998 1999 2000 2001 |
# File 'lib/rbot/irc.rb', line 1993 def delete_user(someuser) idx = has_user?(someuser) raise "Tried to remove unmanaged user #{user}" unless idx have = self.user(someuser) @channels.each { |ch| delete_user_from_channel(have, ch) } @users.delete_at(idx) end |
#delete_user_from_channel(user, channel) ⇒ Object
Deletes User user from Channel channel
1986 1987 1988 |
# File 'lib/rbot/irc.rb', line 1986 def delete_user_from_channel(user, channel) channel.delete_user(user) end |
#find_users(mask) ⇒ Object
Finds all User
s on server whose Netmask matches mask
2011 2012 2013 2014 2015 2016 2017 2018 2019 2020 2021 2022 |
# File 'lib/rbot/irc.rb', line 2011 def find_users(mask) nm = new_netmask(mask) @users.inject(UserList.new) { |list, user| if user.user == "*" or user.host == "*" list << user if user.nick.irc_downcase(casemap) =~ nm.nick.irc_downcase(casemap).to_irc_regexp else list << user if user.matches?(nm) end list } end |
#get_channel(name) ⇒ Object Also known as: get_chan
Returns the channel with name name, if available
1821 1822 1823 1824 1825 |
# File 'lib/rbot/irc.rb', line 1821 def get_channel(name) return nil if name.nil_or_empty? idx = has_channel?(name) channels[idx] if idx end |
#get_user(nick) ⇒ Object
Returns the user with nick nick, if available
1933 1934 1935 1936 |
# File 'lib/rbot/irc.rb', line 1933 def get_user(nick) idx = has_user?(nick) @users[idx] if idx end |
#has_channel?(name) ⇒ Boolean Also known as: has_chan?
Checks if the receiver already has a channel with the given name
1813 1814 1815 1816 |
# File 'lib/rbot/irc.rb', line 1813 def has_channel?(name) return false if name.nil_or_empty? channel_names.index(name.irc_downcase(casemap)) end |
#has_user?(nick) ⇒ Boolean
Checks if the receiver already has a user with the given nick
1926 1927 1928 1929 |
# File 'lib/rbot/irc.rb', line 1926 def has_user?(nick) return false if nick.nil_or_empty? user_nicks.index(nick.irc_downcase(casemap)) end |
#inspect ⇒ Object
1543 1544 1545 1546 1547 1548 1549 1550 1551 1552 1553 1554 1555 1556 1557 |
# File 'lib/rbot/irc.rb', line 1543 def inspect chans, users = [@channels, @users].map {|d| d.sort { |a, b| a.downcase <=> b.downcase }.map { |x| x.inspect } } str = self.__to_s__[0..-2] str << " @hostname=#{hostname}" str << " @channels=#{chans}" str << " @users=#{users}" str << ">" end |
#mode_for_prefix(pfx) ⇒ Object
Convert a prefix (@, +, %, …) to the corresponding mode (o, v, h, …). See also prefix_for_mode
1618 1619 1620 1621 1622 |
# File 'lib/rbot/irc.rb', line 1618 def mode_for_prefix(pfx) return @supports[:prefix][:modes][ @supports[:prefix][:prefixes].index(pfx.to_sym) ] end |
#new_channel(name, topic = nil, users = [], fails = true) ⇒ Object
Create a new Channel object bound to the receiver and add it to the list of Channel
s on the receiver, unless the channel was present already. In this case, the default action is to raise an exception, unless fails is set to false. An exception can also be raised if str is nil or empty, again only if fails is set to true; otherwise, the method just returns nil
1835 1836 1837 1838 1839 1840 1841 1842 1843 1844 1845 1846 1847 1848 1849 1850 1851 1852 1853 1854 1855 1856 1857 1858 1859 1860 1861 1862 1863 1864 1865 1866 1867 1868 1869 1870 1871 1872 1873 1874 1875 1876 1877 1878 1879 1880 1881 1882 1883 1884 1885 1886 1887 1888 1889 1890 1891 1892 1893 1894 1895 1896 1897 1898 1899 1900 1901 1902 1903 1904 1905 1906 |
# File 'lib/rbot/irc.rb', line 1835 def new_channel(name, topic=nil, users=[], fails=true) if name.nil_or_empty? raise "Tried to look for empty or nil channel name #{name.inspect}" if fails return nil end ex = get_chan(name) if ex raise "Channel #{name} already exists on server #{self}" if fails return ex else prefix = name[0,1] # Give a warning if the new Channel goes over some server limits. # # FIXME might need to raise an exception # warn "#{self} doesn't support channel prefix #{prefix}" unless @supports[:chantypes].include?(prefix) warn "#{self} doesn't support channel names this long (#{name.length} > #{@supports[:channellen]})" unless name.length <= @supports[:channellen] # Next, we check if we hit the limit for channels of type +prefix+ # if the server supports +chanlimit+ # @supports[:chanlimit].keys.each { |k| next unless k.include?(prefix) count = 0 channel_names.each { |n| count += 1 if k.include?(n[0]) } # raise IndexError, "Already joined #{count} channels with prefix #{k}" if count == @supports[:chanlimit][k] warn "Already joined #{count}/#{@supports[:chanlimit][k]} channels with prefix #{k}, we may be going over server limits" if count >= @supports[:chanlimit][k] } # So far, everything is fine. Now create the actual Channel # chan = Channel.new(name, topic, users, :server => self) # We wade through +prefix+ and +chanmodes+ to create appropriate # lists and flags for this channel @supports[:prefix][:modes].each { |mode| chan.create_mode(mode, Channel::UserMode) } if @supports[:prefix][:modes] @supports[:chanmodes].each { |k, val| if val case k when :typea val.each { |mode| chan.create_mode(mode, Channel::ModeTypeA) } when :typeb val.each { |mode| chan.create_mode(mode, Channel::ModeTypeB) } when :typec val.each { |mode| chan.create_mode(mode, Channel::ModeTypeC) } when :typed val.each { |mode| chan.create_mode(mode, Channel::ModeTypeD) } end end } @channels << chan # debug "Created channel #{chan.inspect}" return chan end end |
#new_netmask(str) ⇒ Object
Create a new Netmask object with the appropriate casemap
2005 2006 2007 |
# File 'lib/rbot/irc.rb', line 2005 def new_netmask(str) str.to_irc_netmask(:server => self) end |
#new_user(str, fails = true) ⇒ Object
Create a new User object bound to the receiver and add it to the list of User
s on the receiver, unless the User was present already. In this case, the default action is to raise an exception, unless fails is set to false. An exception can also be raised if str is nil or empty, again only if fails is set to true; otherwise, the method just returns nil
1945 1946 1947 1948 1949 1950 1951 1952 1953 1954 1955 1956 1957 1958 1959 1960 1961 1962 1963 1964 1965 1966 1967 1968 1969 1970 1971 1972 1973 1974 |
# File 'lib/rbot/irc.rb', line 1945 def new_user(str, fails=true) if str.nil_or_empty? raise "Tried to look for empty or nil user name #{str.inspect}" if fails return nil end tmp = str.to_irc_user(:server => self) old = get_user(tmp.nick) # debug "Tmp: #{tmp.inspect}" # debug "Old: #{old.inspect}" if old # debug "User already existed as #{old.inspect}" if tmp.known? if old.known? # debug "Both were known" # Do not raise an error: things like Freenode change the hostname after identification warning "User #{tmp.nick} has inconsistent Netmasks! #{self} knows #{old.inspect} but access was tried with #{tmp.inspect}" if old != tmp raise "User #{tmp} already exists on server #{self}" if fails end if old.fullform.downcase != tmp.fullform.downcase old.replace(tmp) # debug "Known user now #{old.inspect}" end end return old else warn "#{self} doesn't support nicknames this long (#{tmp.nick.length} > #{@supports[:nicklen]})" unless tmp.nick.length <= @supports[:nicklen] @users << tmp return @users.last end end |
#parse_isupport(line) ⇒ Object
This method is used to parse a 005 RPL_ISUPPORT line
See the RPL_ISUPPORT draft
1674 1675 1676 1677 1678 1679 1680 1681 1682 1683 1684 1685 1686 1687 1688 1689 1690 1691 1692 1693 1694 1695 1696 1697 1698 1699 1700 1701 1702 1703 1704 1705 1706 1707 1708 1709 1710 1711 1712 1713 1714 1715 1716 1717 1718 1719 1720 1721 1722 1723 1724 1725 1726 1727 1728 1729 1730 1731 1732 1733 1734 1735 1736 1737 1738 1739 1740 1741 1742 1743 1744 1745 1746 1747 1748 1749 1750 1751 1752 1753 1754 1755 1756 1757 1758 1759 1760 1761 1762 1763 1764 1765 1766 1767 1768 1769 1770 1771 1772 1773 1774 1775 1776 1777 1778 1779 1780 1781 1782 |
# File 'lib/rbot/irc.rb', line 1674 def parse_isupport(line) debug "Parsing ISUPPORT #{line.inspect}" ar = line.split(' ') reparse = [] ar.each { |en| prekey, val = en.split('=', 2) if prekey =~ /^-(.*)/ key = $1.downcase.to_sym val = false else key = prekey.downcase.to_sym end case key when :casemapping noval_warn(key, val) { if val == 'charset' reparse << "CASEMAPPING=(charset)" else # TODO some servers offer non-standard CASEMAPPINGs in the form # locale.charset[-options], which indicate an extended set of # allowed characters (mostly for nicks). This might be supported # with hooks for the unicode core module @supports[key] = val.to_irc_casemap end } when :chanlimit, :idchan, :maxlist, :targmax noval_warn(key, val) { groups = val.split(',') groups.each { |g| k, v = g.split(':') @supports[key][k] = v.to_i || 0 if @supports[key][k] == 0 warn "Deleting #{key} limit of 0 for #{k}" @supports[key].delete(k) end } } when :chanmodes noval_warn(key, val) { groups = val.split(',') @supports[key][:typea] = groups[0].scan(/./).map { |x| x.to_sym} @supports[key][:typeb] = groups[1].scan(/./).map { |x| x.to_sym} @supports[key][:typec] = groups[2].scan(/./).map { |x| x.to_sym} @supports[key][:typed] = groups[3].scan(/./).map { |x| x.to_sym} } when :channellen, :kicklen, :modes, :topiclen if val @supports[key] = val.to_i else @supports[key] = nil end when :chantypes @supports[key] = val # can also be nil when :excepts val ||= 'e' @supports[key] = val when :invex val ||= 'I' @supports[key] = val when :maxchannels noval_warn(key, val) { reparse << "CHANLIMIT=(chantypes):#{val} " } when :maxtargets noval_warn(key, val) { @supports[:targmax]['PRIVMSG'] = val.to_i @supports[:targmax]['NOTICE'] = val.to_i } when :network noval_warn(key, val) { @supports[key] = val } when :nicklen noval_warn(key, val) { @supports[key] = val.to_i } when :prefix if val val.scan(/\((.*)\)(.*)/) { |m, p| @supports[key][:modes] = m.scan(/./).map { |x| x.to_sym} @supports[key][:prefixes] = p.scan(/./).map { |x| x.to_sym} } else @supports[key][:modes] = nil @supports[key][:prefixes] = nil end when :safelist val_warn(key, val) { @supports[key] = val.nil? ? true : val } when :statusmsg noval_warn(key, val) { @supports[key] = val.scan(/./) } when :std noval_warn(key, val) { @supports[key] = val.split(',') } else @supports[key] = val.nil? ? true : val end } unless reparse.empty? reparse_str = reparse.join(" ") reparse_str.gsub!("(chantypes)",@supports[:chantypes]) reparse_str.gsub!("(charset)",@supports[:charset] || 'rfc1459') parse_isupport(reparse_str) end end |
#parse_my_info(line) ⇒ Object
This method is used to parse a 004 RPL_MY_INFO line
1645 1646 1647 1648 1649 1650 1651 |
# File 'lib/rbot/irc.rb', line 1645 def parse_my_info(line) ar = line.split(' ') @hostname = ar[0] @version = ar[1] @usermodes = ar[2] @chanmodes = ar[3] end |
#prefix_for_mode(mode) ⇒ Object
Convert a mode (o, v, h, …) to the corresponding prefix (@, +, %, …). See also mode_for_prefix
1610 1611 1612 1613 1614 |
# File 'lib/rbot/irc.rb', line 1610 def prefix_for_mode(mode) return @supports[:prefix][:prefixes][ @supports[:prefix][:modes].index(mode.to_sym) ] end |
#reset_capabilities ⇒ Object
Resets the server capabilities
1575 1576 1577 1578 1579 1580 1581 1582 1583 1584 1585 1586 1587 1588 1589 1590 1591 1592 1593 1594 1595 1596 1597 1598 1599 1600 1601 1602 1603 1604 1605 1606 |
# File 'lib/rbot/irc.rb', line 1575 def reset_capabilities @supports = { :casemapping => 'rfc1459'.to_irc_casemap, :chanlimit => {}, :chanmodes => { :typea => nil, # Type A: address lists :typeb => nil, # Type B: needs a parameter :typec => nil, # Type C: needs a parameter when set :typed => nil # Type D: must not have a parameter }, :channellen => 50, :chantypes => "#&!+", :excepts => nil, :idchan => {}, :invex => nil, :kicklen => nil, :maxlist => {}, :modes => 3, :network => nil, :nicklen => 9, :prefix => { :modes => [:o, :v], :prefixes => [:"@", :+] }, :safelist => nil, :statusmsg => nil, :std => nil, :targmax => {}, :topiclen => nil } @capabilities = {} end |
#reset_lists ⇒ Object
Resets the Channel and User list
1626 1627 1628 1629 1630 1631 1632 1633 |
# File 'lib/rbot/irc.rb', line 1626 def reset_lists @users.reverse_each { |u| delete_user(u) } @channels.reverse_each { |u| delete_channel(u) } end |
#user(str) ⇒ Object
Returns the User with the given Netmask on the server, creating it if necessary. This is a short form for new_user(str, false
)
1980 1981 1982 |
# File 'lib/rbot/irc.rb', line 1980 def user(str) new_user(str, false) end |
#user_nicks ⇒ Object
TODO Ho
1539 1540 1541 |
# File 'lib/rbot/irc.rb', line 1539 def user_nicks @users.map { |u| u.downcase } end |
#user_or_channel(name) ⇒ Object
Returns the actual User or Channel object matching name
1803 1804 1805 1806 1807 1808 1809 |
# File 'lib/rbot/irc.rb', line 1803 def user_or_channel(name) if supports[:chantypes].include?(name[0]) return channel(name) else return user(name) end end |