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.
1514 1515 1516 1517 1518 1519 1520 1521 1522 |
# File 'lib/rbot/irc.rb', line 1514 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.
1480 1481 1482 |
# File 'lib/rbot/irc.rb', line 1480 def capabilities @capabilities end |
#chanmodes ⇒ Object (readonly)
Returns the value of attribute chanmodes.
1478 1479 1480 |
# File 'lib/rbot/irc.rb', line 1478 def chanmodes @chanmodes end |
#channels ⇒ Object (readonly)
Returns the value of attribute channels.
1482 1483 1484 |
# File 'lib/rbot/irc.rb', line 1482 def channels @channels end |
#hostname ⇒ Object (readonly) Also known as: to_s
Returns the value of attribute hostname.
1478 1479 1480 |
# File 'lib/rbot/irc.rb', line 1478 def hostname @hostname end |
#supports ⇒ Object (readonly)
Returns the value of attribute supports.
1480 1481 1482 |
# File 'lib/rbot/irc.rb', line 1480 def supports @supports end |
#usermodes ⇒ Object (readonly)
Returns the value of attribute usermodes.
1478 1479 1480 |
# File 'lib/rbot/irc.rb', line 1478 def usermodes @usermodes end |
#users ⇒ Object (readonly)
Returns the value of attribute users.
1482 1483 1484 |
# File 'lib/rbot/irc.rb', line 1482 def users @users end |
#version ⇒ Object (readonly)
Returns the value of attribute version.
1478 1479 1480 |
# File 'lib/rbot/irc.rb', line 1478 def version @version end |
Instance Method Details
#casemap ⇒ Object
Returns the casemap of the server.
1725 1726 1727 |
# File 'lib/rbot/irc.rb', line 1725 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
)
1851 1852 1853 |
# File 'lib/rbot/irc.rb', line 1851 def channel(str) new_channel(str,nil,[],false) end |
#channel_names ⇒ Object
TODO Ho
1485 1486 1487 |
# File 'lib/rbot/irc.rb', line 1485 def channel_names @channels.map { |ch| ch.downcase } end |
#clear ⇒ Object
Clears the server
1588 1589 1590 1591 1592 |
# File 'lib/rbot/irc.rb', line 1588 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
1857 1858 1859 1860 1861 |
# File 'lib/rbot/irc.rb', line 1857 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.
1932 1933 1934 1935 1936 1937 1938 1939 1940 |
# File 'lib/rbot/irc.rb', line 1932 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
1925 1926 1927 |
# File 'lib/rbot/irc.rb', line 1925 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
1950 1951 1952 1953 1954 1955 1956 1957 1958 1959 1960 1961 |
# File 'lib/rbot/irc.rb', line 1950 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
1760 1761 1762 1763 1764 |
# File 'lib/rbot/irc.rb', line 1760 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
1872 1873 1874 1875 |
# File 'lib/rbot/irc.rb', line 1872 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
1752 1753 1754 1755 |
# File 'lib/rbot/irc.rb', line 1752 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
1865 1866 1867 1868 |
# File 'lib/rbot/irc.rb', line 1865 def has_user?(nick) return false if nick.nil_or_empty? user_nicks.index(nick.irc_downcase(casemap)) end |
#inspect ⇒ Object
1494 1495 1496 1497 1498 1499 1500 1501 1502 1503 1504 1505 1506 1507 1508 |
# File 'lib/rbot/irc.rb', line 1494 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
1569 1570 1571 1572 1573 |
# File 'lib/rbot/irc.rb', line 1569 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
1774 1775 1776 1777 1778 1779 1780 1781 1782 1783 1784 1785 1786 1787 1788 1789 1790 1791 1792 1793 1794 1795 1796 1797 1798 1799 1800 1801 1802 1803 1804 1805 1806 1807 1808 1809 1810 1811 1812 1813 1814 1815 1816 1817 1818 1819 1820 1821 1822 1823 1824 1825 1826 1827 1828 1829 1830 1831 1832 1833 1834 1835 1836 1837 1838 1839 1840 1841 1842 1843 1844 1845 |
# File 'lib/rbot/irc.rb', line 1774 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].chr # 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
1944 1945 1946 |
# File 'lib/rbot/irc.rb', line 1944 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
1884 1885 1886 1887 1888 1889 1890 1891 1892 1893 1894 1895 1896 1897 1898 1899 1900 1901 1902 1903 1904 1905 1906 1907 1908 1909 1910 1911 1912 1913 |
# File 'lib/rbot/irc.rb', line 1884 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
1625 1626 1627 1628 1629 1630 1631 1632 1633 1634 1635 1636 1637 1638 1639 1640 1641 1642 1643 1644 1645 1646 1647 1648 1649 1650 1651 1652 1653 1654 1655 1656 1657 1658 1659 1660 1661 1662 1663 1664 1665 1666 1667 1668 1669 1670 1671 1672 1673 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 |
# File 'lib/rbot/irc.rb', line 1625 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) { @supports[key] = val.to_irc_casemap } 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 } reparse.gsub!("(chantypes)",@supports[:chantypes]) parse_isupport(reparse) unless reparse.empty? end |
#parse_my_info(line) ⇒ Object
This method is used to parse a 004 RPL_MY_INFO line
1596 1597 1598 1599 1600 1601 1602 |
# File 'lib/rbot/irc.rb', line 1596 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
1561 1562 1563 1564 1565 |
# File 'lib/rbot/irc.rb', line 1561 def prefix_for_mode(mode) return @supports[:prefix][:prefixes][ @supports[:prefix][:modes].index(mode.to_sym) ] end |
#reset_capabilities ⇒ Object
Resets the server capabilities
1526 1527 1528 1529 1530 1531 1532 1533 1534 1535 1536 1537 1538 1539 1540 1541 1542 1543 1544 1545 1546 1547 1548 1549 1550 1551 1552 1553 1554 1555 1556 1557 |
# File 'lib/rbot/irc.rb', line 1526 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
1577 1578 1579 1580 1581 1582 1583 1584 |
# File 'lib/rbot/irc.rb', line 1577 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
)
1919 1920 1921 |
# File 'lib/rbot/irc.rb', line 1919 def user(str) new_user(str, false) end |
#user_nicks ⇒ Object
TODO Ho
1490 1491 1492 |
# File 'lib/rbot/irc.rb', line 1490 def user_nicks @users.map { |u| u.downcase } end |
#user_or_channel(name) ⇒ Object
Returns the actual User or Channel object matching name
1742 1743 1744 1745 1746 1747 1748 |
# File 'lib/rbot/irc.rb', line 1742 def user_or_channel(name) if supports[:chantypes].include?(name[0]) return channel(name) else return user(name) end end |