bot.py 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242
  1. #! /usr/bin/env python
  2. import sys, random, string, ssl
  3. import irc.bot#, irc.strings
  4. from irc.client import ip_numstr_to_quad#, ip_quad_to_numstr
  5. from jaraco.stream import buffer
  6. from postgres import Postgres
  7. import commands.public, commands.admin, commands.games, commands.statistics
  8. import events.on_welcome, events.on_join, events.on_kick, events.on_mode, events.on_pubmsg, events.on_action, events.on_whoreply, events.on_nick
  9. #from common import log
  10. #from common.networkservices import NickServ
  11. #from events.common import Lastact, MessageStatistics, Inform
  12. bold = "\x02"
  13. italic = "\x1D"
  14. underline = "\x1F"
  15. reverse = "\x16" # swap background and foreground colors ("reverse video")
  16. reset = "\x0F"
  17. blue = "\x0302"
  18. green = "\x0303"
  19. red = "\x0304"
  20. grey = "\x0314"
  21. # class PyRot(irc.bot.SingleServerIRCBot):
  22. # def __init__(self, network, db, homechannel, nickname, username, password, host, port=6667, usessl=False, cmdchar="!", helpchar="@"):
  23. # self.network = network
  24. # self.db = db
  25. # self.homechannel = homechannel
  26. # self.password = password
  27. # self.cmdchar = cmdchar
  28. # self.helpchar = helpchar
  29. # self.protectees = {}
  30. # self.channelkeys = {}
  31. #
  32. # log.info("Starting pyRot, by tBKwtWS.")
  33. # log.info("Connecting to " + host + ":" + str(port) + "/" + self.homechannel)
  34. #
  35. # if usessl:
  36. # factory = irc.connection.Factory(wrapper=ssl.wrap_socket)
  37. # else:
  38. # factory = irc.connection.Factory()
  39. #
  40. # irc.client.ServerConnection.buffer_class = buffer.LenientDecodingLineBuffer
  41. # try:
  42. # irc.bot.SingleServerIRCBot.__init__(self, [(host, port)], nickname, username, connect_factory=factory)
  43. # except irc.client.ServerConnectionError:
  44. # sys.stderr.write(sys.exc_info()[1])
  45. #
  46. # # Events.
  47. # def on_nicknameinuse(self, connection, event):
  48. # log.info("Nickname in use, attempting to recover: " + connection.nickname)
  49. # connection.nick(connection.nickname + ''.join(random.choice(string.digits) for _ in range(3))) # Take temporary nick. Without this recovering via NickServ won't work.
  50. # NickServ.recover_nick(connection, self.password)
  51. #
  52. # def on_welcome(self, connection, event):
  53. # events.on_welcome.process_event(self, connection, event)
  54. #
  55. # def on_error(self, connection, event):
  56. # log.notice(str(event))
  57. # connection.privmsg(self.homechannel, "ERROR: " + str(event))
  58. # Inform.owners(self, connection, "Received error from server: " + str(event))
  59. #
  60. # def on_nick(self, connection, event):
  61. # events.on_nick.process_event(self, connection, event)
  62. #
  63. # def on_join(self, connection, event):
  64. # events.on_join.process_event(self, connection, event)
  65. #
  66. # def on_kick(self, connection, event):
  67. # events.on_kick.process_event(self, connection, event)
  68. #
  69. # def on_mode(self, connection, event):
  70. # events.on_mode.process_event(self, connection, event)
  71. #
  72. # def on_part(self, connection, event):
  73. # log.info(event)
  74. #
  75. # # Update protectees.
  76. # if event.target == self.homechannel and event.source.nick in self.protectees: # Protectee parted home channel.
  77. # del self.protectees[event.source.nick] # Delete from protectees.
  78. #
  79. # # Update last act.
  80. # if event.arguments:
  81. # Lastact.update(self, event.source.nick, "part", channel=event.target, lastact=event.arguments[0])
  82. # else:
  83. # Lastact.update(self, event.source.nick, "part", channel=event.target)
  84. #
  85. # def on_quit(self, connection, event):
  86. # log.info(event)
  87. #
  88. # # Update protectees.
  89. # if event.source.nick in self.protectees: # Protectee parted home channel.
  90. # del self.protectees[event.source.nick] # Delete from protectees.
  91. #
  92. # # Update last act.
  93. # if event.arguments:
  94. # Lastact.update(self, event.source.nick, "quit", lastact=event.arguments[0])
  95. # else:
  96. # Lastact.update(self, event.source.nick, "quit")
  97. #
  98. # def on_invite(self, connection, event):
  99. # log.notice(event)
  100. # if event.target == connection.get_nickname(): # Bot invited.
  101. # Inform.operators(self, connection, "Received invitation to " + red + event.arguments[0] + reset + " from " + red + event.source.nick + reset + ".")
  102. #
  103. # def on_topic(self, connection, event):
  104. # log.info(event)
  105. #
  106. # # Update last act.
  107. # Lastact.update(self, event.source.nick, "topic", channel=event.target, lastact=event.arguments[0])
  108. #
  109. # def on_pubmsg(self, connection, event):
  110. # events.on_pubmsg.process_event(self, connection, event)
  111. # commands.public.do_command(self, connection, event)
  112. # commands.admin.do_command(self, connection, event)
  113. # commands.statistics.do_command(self, connection, event)
  114. # commands.games.do_command(self, connection, event)
  115. #
  116. # def on_privmsg(self, connection, event):
  117. # log.info(event)
  118. # commands.public.do_command(self, connection, event)
  119. # commands.admin.do_command(self, connection, event)
  120. # commands.statistics.do_command(self, connection, event)
  121. # commands.games.do_command(self, connection, event)
  122. # if not event.source.nick == connection.get_nickname():
  123. # Inform.owners(self, connection, "PM from " + red + red + event.source.nick + grey + ": " + reset + event.arguments[0])
  124. #
  125. # def on_pubnotice(self, connection, event):
  126. # log.info(event)
  127. #
  128. # # Update last act.
  129. # Lastact.update(self, event.source.nick, "notice", channel=event.target, lastact=event.arguments[0])
  130. #
  131. # # Save statistic to database.
  132. # MessageStatistics.update(self, event, "notice")
  133. #
  134. # def on_privnotice(self, connection, event):
  135. # log.info(event)
  136. # commands.public.do_command(self, connection, event)
  137. # commands.admin.do_command(self, connection, event)
  138. # commands.statistics.do_command(self, connection, event)
  139. # commands.games.do_command(self, connection, event)
  140. # try:
  141. # if event.source.nick == connection.get_nickname():
  142. # return
  143. # elif event.source.nick == "NickServ":
  144. # if event.arguments[0].startswith("This nickname is registered"):
  145. # connection.privmsg("NickServ", "identify " + connection.nickname + " " + self.password) # Identify with NickServ.
  146. # if event.arguments[0] == "You are already identified.":
  147. # return
  148. # elif event.source.nick == "ChanServ":
  149. # if event.arguments[0].startswith("Key for channel ") and len(event.arguments[0]) > 5: # Received channel key.
  150. # self.channelkeys[event.arguments[0].split(' ')[3]] = event.arguments[0].split(' ')[5][:-1]
  151. # connection.join(event.arguments[0].split(' ')[3], event.arguments[0].split(' ')[5][:-1])
  152. # Inform.owners(self, connection, "Received " + red + event.arguments[0].split(" ")[3] + reset + " key: " + event.arguments.split(" ")[5][:-1])
  153. # if event.arguments[0] == "Password authentication required for that command.": # Not authenticated with NisckServ.
  154. # Inform.notice_owners(self, connection, "Not authenticated with NickServ. See " + blue + self.helpchar + "recovernick " + reset + "and " + blue + self.helpchar + "registernick" + reset + ".")
  155. # return
  156. # if event.arguments[0].startswith("You have been unbanned from ") or event.arguments[0].endswith(" autokick list is empty.") or event.arguments[0].startswith("You are already in ") or event.arguments[0] == "Syntax: UNBAN channel [nick]" or event.arguments[0] == "/msg ChanServ HELP UNBAN for more information":
  157. # return
  158. # if event.arguments[0].startswith("Channel ") and event.arguments[0].endswith(" has no key."):
  159. # return
  160. # elif event.source.nick == "Global":
  161. # return
  162. # Inform.notice_owners(self, connection, "Notice from " + red + red + event.source.nick + grey + ": " + reset + event.arguments[0])
  163. # except:
  164. # pass
  165. #
  166. # def on_action(self, connection, event):
  167. # events.on_action.process_event(self, connection, event)
  168. #
  169. #
  170. # def on_whoreply(self, connection, event):
  171. # events.on_whoreply.process_event(self, connection, event)
  172. #
  173. #
  174. # def on_keyset(self, connection, event):
  175. # log.info(event)
  176. # Inform.owners(self, connection, "keyset " + green + event.arguments[0] + reset + " from " + red + event.source)
  177. #
  178. # def on_yourhost(self, connection, event):
  179. # log.info(event)
  180. #
  181. # def on_yourebannedcreep(self, connection, event):
  182. # log.warning(event)
  183. #
  184. # def on_youwillbebanned(self, connection, event):
  185. # log.warning(event)
  186. # Inform.operators(self, connection, "I will be banned " + red + event.arguments[0] + reset + " from " + red + event.source)
  187. #
  188. #
  189. # # DCC stuff from originalexample file.
  190. # def on_dccmsg(self, c, e):
  191. # log.info(e)
  192. # # non-chat DCC messages are raw bytes; decode as text
  193. # text = e.arguments[0].decode('utf-8')
  194. # c.privmsg("You said: " + text)
  195. #
  196. # def on_dccchat(self, c, e):
  197. # log.info(e)
  198. # if len(e.arguments) != 2:
  199. # return
  200. # args = e.arguments[1].split()
  201. # if len(args) == 4:
  202. # try:
  203. # address = ip_numstr_to_quad(args[2])
  204. # port = int(args[3])
  205. # except ValueError:
  206. # return
  207. # self.dcc_connect(address, port)
  208. #
  209. # def main():
  210. #
  211. # # Check system arguments.
  212. # if len(sys.argv) != 2:
  213. # print(sys.argv)
  214. # print("Usage: rotbot <server ID from database>")
  215. # sys.exit(1)
  216. # instance = sys.argv[1] # Instance is the database network id.
  217. #
  218. # # Database.
  219. # db = Postgres("postgres://pyRot:4h8q(.@localhost/pyRot")
  220. #
  221. # # Get network from database.
  222. # try:
  223. # network = db.one("SELECT * FROM networks WHERE id=" + str(instance))
  224. # except:
  225. # print("Invalid network ID.")
  226. # sys.exit(1)
  227. # if network == None:
  228. # print("Invalid network ID.")
  229. # sys.exit(1)
  230. #
  231. # bot = PyRot(network.name, db, network.home_channel, network.nickname, network.username, network.password, network.host, network.port, network.use_ssl, network.command_character, network.help_character)
  232. # bot.start()
  233. #
  234. # if __name__ == "__main__":
  235. # try:
  236. # main()
  237. # except KeyboardInterrupt:
  238. # log.info('Interrupted by keyboard.')
  239. # sys.exit(0)