/irclogs/provider/db.py

https://github.com/heimojuh/trac-irclogs-plugin · Python · 136 lines · 89 code · 16 blank · 31 comment · 13 complexity · 18d43e546f16c08e5709472d03ba68b5 MD5 · raw file

  1. """
  2. Parse logs from db into structured data.
  3. """
  4. # Copyright (c) 2009, Robert Corsaro
  5. import re
  6. from time import strptime, strftime
  7. from datetime import datetime, timedelta
  8. from pytz import timezone, UnknownTimeZoneError
  9. from trac.core import *
  10. from trac.config import Option
  11. from trac.db.api import DatabaseManager
  12. from irclogs.api import IIRCLogsProvider, IRCChannelManager
  13. ENCODED_FIELDS = ('network', 'channel', 'nick', 'type', 'message', 'comment')
  14. class DBIRCLogProvider(Component):
  15. """
  16. Provide logs from irc log table.
  17. [irclogs]
  18. format = gozer
  19. # or
  20. channel.test.channel = #test
  21. channel.test.provider = db
  22. The database must contain a table named `chatlog`. The table definiton
  23. should match:
  24. CREATE TABLE chatlog (
  25. id SERIAL PRIMARY KEY,
  26. time DATETIME DEFAULT now(),
  27. network VARCHAR(256) NOT NULL,
  28. target VARCHAR(256) NOT NULL,
  29. nick VARCHAR(256) NOT NULL,
  30. type VARCHAR(256) NOT NULL,
  31. msg TEXT NOT NULL
  32. );
  33. If using the Gozerbot chatlog plugin, it will create this table
  34. automatically in not already present.
  35. """
  36. implements(IIRCLogsProvider)
  37. # IRCLogsProvider interface
  38. def get_events_in_range(self, ch, start, end):
  39. global ENCODED_FIELDS
  40. ch_mgr = IRCChannelManager(self.env)
  41. self.log.debug(ch.settings())
  42. def_tzname = self.config.get('irclogs', 'timezone', 'utc')
  43. tzname = ch.setting('timezone', def_tzname)
  44. try:
  45. tz = timezone(tzname)
  46. except UnknownTimeZoneError:
  47. self.log.warn("input timezone %s not supported, irclogs will be "\
  48. "parsed as UTC")
  49. tzname = 'UTC'
  50. tz = timezone(tzname)
  51. cnx = self._getdb(ch)
  52. try:
  53. ttz = timezone(start.tzname())
  54. except UnknownTimeZoneError:
  55. self.log.warn("timezone %s not supported, irclog output will be "\
  56. "%s"%(start.tzname(), tzname))
  57. ttz = tz
  58. try:
  59. self.log.debug("""executing
  60. SELECT * FROM chatlog
  61. WHERE network = %s AND target = %s AND time >= %s AND
  62. time < %s ORDER BY "time" """)
  63. self.log.debug("with %s, %s, %s, %s"%(ch.network() or '', ch.channel(), start, end))
  64. cur = cnx.cursor()
  65. cur.execute("""
  66. SELECT * FROM chatlog
  67. WHERE network = %s AND target = %s AND time >= %s AND
  68. time < %s ORDER BY "time" """,(
  69. ch.network() or '',
  70. ch.channel(),
  71. start,
  72. end
  73. )
  74. )
  75. ignore_charset = False
  76. for l in cur:
  77. timestamp = l[1]
  78. timestamp = tz.localize(timestamp)
  79. dt = ttz.normalize(timestamp.astimezone(ttz))
  80. line = {
  81. 'timestamp': dt,
  82. 'network': l[2],
  83. 'channel': l[3],
  84. 'nick': l[4],
  85. 'type': l[5],
  86. 'message': l[6],
  87. 'comment': l[6],
  88. 'action': l[6].lstrip('* ')
  89. }
  90. ignore_charset = ignore_charset or isinstance(line['message'],
  91. unicode)
  92. if (not ignore_charset) and ch.setting('charset'):
  93. for k in ENCODED_FIELDS:
  94. line[k] = unicode(line[k], ch.setting('charset'),
  95. errors='ignore')
  96. continue
  97. yield line
  98. cnx.close()
  99. except Exception, e:
  100. cnx.close()
  101. self.log.error(e)
  102. raise e
  103. def name(self):
  104. return 'db'
  105. # end IRCLogsProvider interface
  106. def _getdb(self, channel):
  107. dbm = IRCLogDatabaseManager(self.env)
  108. trac_db = self.config.get('trac', 'database')
  109. irc_db = self.config.get('irclogs', 'database', trac_db)
  110. chan_db = channel.setting('database', irc_db)
  111. dbm.set_database(chan_db)
  112. return dbm.get_connection()
  113. class IRCLogDatabaseManager(DatabaseManager):
  114. """ Provide access to chatlog db """
  115. connection_uri = None
  116. def set_database(self, database):
  117. self.connection_uri = database