/jirc/base.py

https://github.com/lithium/pyjirc · Python · 155 lines · 118 code · 36 blank · 1 comment · 31 complexity · 69f66187eec82c942aea64cb7b1faa03 MD5 · raw file

  1. from pyxmpp.all import JID
  2. from jirc.irc import JircIrcClient
  3. from jirc.jabber import JircJabberClient
  4. from handler import Handler, Message
  5. from objdict import ObjDict
  6. import re
  7. import gevent
  8. import logging
  9. __all__ = ['Jirc']
  10. class Jirc(object):
  11. def __init__(self, settings):
  12. self.handler = Handler(self.handle_message)
  13. self.settings = settings
  14. self._prefix_re = re.compile("(?P<nick>[^!]+)!(?P<user>[^@]+)@(?P<host>.+)")
  15. self._jid_re = re.compile("(?P<node>[^@]+)@(?P<domain>[^/]+)(/(?P<resource>.+))?")
  16. self.jjc = JircJabberClient(settings.JABBER_JID, settings.JABBER_PASSWORD, server=settings.JABBER_SERVER, port=self.settings.get('JABBER_PORT', 5222))
  17. self.jjc.set_handler(self.handler)
  18. self.jic = JircIrcClient()
  19. self.jic.set_handler(self.handler)
  20. self.jabber_channels = {}
  21. self.irc_channels = {}
  22. self.irc_users = {}
  23. self.jabber_users = {}
  24. self.irc_connected = False
  25. self.jabber_connected = False
  26. self.greenlets = []
  27. for channel in self.settings.CHANNELS:
  28. self.jabber_channels[channel['irc']] = channel['jabber']
  29. self.irc_channels[channel['jabber']] = channel['irc']
  30. def _irc_connect(self):
  31. self.jic.open(self.settings.IRC_SERVER, port=self.settings.get('IRC_PORT', 6667));
  32. self.jic.connect_server(self.settings.IRC_SERVERNAME, self.settings.IRC_PASSWORD, info=self.settings.get('IRC_DESCRIPTION',None))
  33. def _jabber_connect(self):
  34. self.jjc.connect()
  35. def _irc_thread_(self):
  36. self._irc_connect()
  37. while True:
  38. self.jic.tick()
  39. def _jabber_thread_(self):
  40. self._jabber_connect()
  41. while True:
  42. self.jjc.tick()
  43. def loop(self):
  44. self.greenlets.append( gevent.spawn(self._irc_thread_) )
  45. self.greenlets.append( gevent.spawn(self._jabber_thread_) )
  46. self.running = True
  47. while self.running:
  48. self.handler.tick(block=True, timeout=6)
  49. def disconnect(self):
  50. for nick, data in self.jabber_users.items():
  51. self.jjc.part_room(data.room_jid, data.jid)
  52. for jid, data in self.irc_users.items():
  53. self.jic.quit_nick(data.irc_nick)
  54. self.jjc.disconnect()
  55. self.jic.disconnect()
  56. [g.kill() for g in self.greenlets]
  57. gevent.shutdown()
  58. def _create_jabber_user(self, nick, channel):
  59. jid = JID(nick, domain=self.settings.JABBER_JID, resource=nick)
  60. sender = self.jjc.join_room(channel, jid)
  61. self.jabber_users[nick] = ObjDict(jid=jid, sender=sender, room_jid=channel)
  62. def _fully_connected(self):
  63. for channel in self.settings.CHANNELS:
  64. irc_chan = self.jic.network_channels[channel['irc']]
  65. for nick in irc_chan.members.keys():
  66. self._create_jabber_user(nick, channel['jabber'])
  67. def handle_message(self, msg):
  68. logging.info(msg)
  69. if msg.what == 'IRC_CONNECT':
  70. self.irc_connected = True
  71. if self.jabber_connected:
  72. self._fully_connected()
  73. elif msg.what == 'JABBER_CONNECT':
  74. self.jabber_connected = True
  75. if self.irc_connected:
  76. self._fully_connected()
  77. elif msg.what == 'IRC_CHANNEL_MESSAGE':
  78. jid = self.jabber_channels.get(msg.subject, None)
  79. if jid is not None:
  80. jabber_user = self.jabber_users.get(msg.sender, None)
  81. if jabber_user:
  82. self.jjc.send_to_room(jabber_user.room_jid, jabber_user.jid, msg.body)
  83. elif msg.what == 'JABBER_CHANNEL_MESSAGE':
  84. chan = self.irc_channels.get(msg.subject, None)
  85. if chan is not None:
  86. irc_user = self.irc_users.get(msg.sender, None)
  87. if irc_user:
  88. self.jic.send_to_channel(irc_user.irc_nick, irc_user.irc_channel, msg.body)
  89. elif msg.what == 'JABBER_CHANNEL_JOIN':
  90. irc_nick = self.jic.unique_nick(msg.nick)
  91. jid = getattr(msg, 'jid', '%s@%s/%s' % (msg.nick, self.settings.JABBER_JID, irc_nick))
  92. jid = self._jid_re.match(jid).groupdict()
  93. channel = self._jid_re.match(msg.channel).groupdict()['node']
  94. if JID(msg.sender) not in [j.sender for j in self.jabber_users.values()] and msg.sender not in self.irc_users:
  95. # dont create IRC users for our own jabber users presence stanzas or for users weve already created
  96. self.irc_users[msg.sender] = ObjDict(jid=jid, irc_nick=irc_nick, irc_channel=channel,
  97. xmpp_nick=msg.nick, role=msg.role, affiliation=msg.affiliation)
  98. self.jic.introduce_nick(irc_nick, username=jid['node'], hostname=jid['domain'], info=jid['resource'])
  99. self.jic.join_channel(irc_nick, channel)
  100. elif msg.what == 'JABBER_NICK_CONFLICT':
  101. msg.sender
  102. for nick,jabber_user in self.jabber_users.items():
  103. if msg.sender == jabber_user.sender.as_utf8():
  104. nick = jabber_user.sender.resource + '_'
  105. jabber_user.sender = self.jjc.join_room(jabber_user.room_jid, jabber_user.jid, nick=nick)
  106. break
  107. elif msg.what == 'JABBER_CHANNEL_PART':
  108. irc_user = self.irc_users.get(msg.sender, None)
  109. if irc_user:
  110. self.jic.part_channel(irc_user.irc_nick, irc_user.irc_channel)
  111. self.jic.quit_nick(irc_user.irc_nick)
  112. del self.irc_users[msg.sender]
  113. elif msg.what == 'IRC_CHANNEL_JOIN':
  114. self._create_jabber_user(msg.sender, self.jabber_channels[msg.channel])
  115. elif msg.what == 'IRC_CHANNEL_PART':
  116. jabber_user = self.jabber_users.get(msg.sender, None)
  117. if jabber_user:
  118. self.jjc.part_room(jabber_user.room_jid, jabber_user.jid)
  119. del self.jabber_users[msg.sender]