PageRenderTime 73ms CodeModel.GetById 35ms RepoModel.GetById 1ms app.codeStats 0ms

/plugins/News/plugin.py

https://github.com/moruk/Limnoria
Python | 218 lines | 143 code | 20 blank | 55 comment | 22 complexity | ea229e1b6c046a094c7e148ec941e300 MD5 | raw file
  1. ###
  2. # Copyright (c) 2003-2005, Daniel DiPaolo
  3. # All rights reserved.
  4. #
  5. # Redistribution and use in source and binary forms, with or without
  6. # modification, are permitted provided that the following conditions are met:
  7. #
  8. # * Redistributions of source code must retain the above copyright notice,
  9. # this list of conditions, and the following disclaimer.
  10. # * Redistributions in binary form must reproduce the above copyright notice,
  11. # this list of conditions, and the following disclaimer in the
  12. # documentation and/or other materials provided with the distribution.
  13. # * Neither the name of the author of this software nor the name of
  14. # contributors to this software may be used to endorse or promote products
  15. # derived from this software without specific prior written consent.
  16. #
  17. # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
  18. # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  19. # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  20. # ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
  21. # LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
  22. # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
  23. # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
  24. # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
  25. # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  26. # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  27. # POSSIBILITY OF SUCH DAMAGE.
  28. ###
  29. import time
  30. import supybot.dbi as dbi
  31. import supybot.conf as conf
  32. import supybot.utils as utils
  33. from supybot.commands import *
  34. import supybot.plugins as plugins
  35. import supybot.ircutils as ircutils
  36. import supybot.callbacks as callbacks
  37. from supybot.i18n import PluginInternationalization, internationalizeDocstring
  38. _ = PluginInternationalization('News')
  39. class DbiNewsDB(plugins.DbiChannelDB):
  40. class DB(dbi.DB):
  41. class Record(dbi.Record):
  42. __fields__ = [
  43. 'subject',
  44. 'text',
  45. 'at',
  46. 'expires',
  47. 'by',
  48. ]
  49. def __str__(self):
  50. user = plugins.getUserName(self.by)
  51. if self.expires == 0:
  52. s = format(_('%s (Subject: %q, added by %s on %s)'),
  53. self.text, self.subject, self.by,
  54. utils.str.timestamp(self.at))
  55. else:
  56. s = format(_('%s (Subject: %q, added by %s on %s, '
  57. 'expires at %s)'),
  58. self.text, self.subject, user,
  59. utils.str.timestamp(self.at),
  60. utils.str.timestamp(self.expires))
  61. return s
  62. def __init__(self, filename):
  63. # We use self.__class__ here because apparently DB isn't in our
  64. # scope. python--
  65. self.__parent = super(self.__class__, self)
  66. self.__parent.__init__(filename)
  67. def add(self, subject, text, at, expires, by):
  68. return self.__parent.add(self.Record(at=at, by=by, text=text,
  69. subject=subject, expires=expires))
  70. def getOld(self, id=None):
  71. now = time.time()
  72. if id:
  73. return self.get(id)
  74. else:
  75. L = [R for R in self if R.expires < now and R.expires != 0]
  76. if not L:
  77. raise dbi.NoRecordError
  78. else:
  79. return L
  80. def get(self, id=None):
  81. now = time.time()
  82. if id:
  83. return self.__parent.get(id)
  84. else:
  85. L = [R for R in self if R.expires >= now or R.expires == 0]
  86. if not L:
  87. raise dbi.NoRecordError
  88. return L
  89. def change(self, id, f):
  90. news = self.get(id)
  91. s = '%s: %s' % (news.subject, news.text)
  92. s = f(s)
  93. (news.subject, news.text) = s.split(': ', 1)
  94. self.set(id, news)
  95. NewsDB = plugins.DB('News', {'flat': DbiNewsDB})
  96. class News(callbacks.Plugin):
  97. def __init__(self, irc):
  98. self.__parent = super(News, self)
  99. self.__parent.__init__(irc)
  100. self.db = NewsDB()
  101. def die(self):
  102. self.__parent.die()
  103. self.db.close()
  104. @internationalizeDocstring
  105. def add(self, irc, msg, args, channel, user, at, expires, news):
  106. """[<channel>] <expires> <subject>: <text>
  107. Adds a given news item of <text> to a channel with the given <subject>.
  108. If <expires> isn't 0, that news item will expire <expires> seconds from
  109. now. <channel> is only necessary if the message isn't sent in the
  110. channel itself.
  111. """
  112. try:
  113. (subject, text) = news.split(': ', 1)
  114. except ValueError:
  115. raise callbacks.ArgumentError
  116. id = self.db.add(channel, subject, text, at, expires, user.id)
  117. irc.replySuccess(format(_('(News item #%i added)'), id))
  118. add = wrap(add, ['channeldb', 'user', 'now', 'expiry', 'text'])
  119. @internationalizeDocstring
  120. def news(self, irc, msg, args, channel, id):
  121. """[<channel>] [<id>]
  122. Display the news items for <channel> in the format of '(#id) subject'.
  123. If <id> is given, retrieve only that news item; otherwise retrieve all
  124. news items. <channel> is only necessary if the message isn't sent in
  125. the channel itself.
  126. """
  127. if not id:
  128. try:
  129. records = self.db.get(channel)
  130. items = [format('(#%i) %s', R.id, R.subject) for R in records]
  131. s = format(_('News for %s: %s'), channel, '; '.join(items))
  132. irc.reply(s)
  133. except dbi.NoRecordError:
  134. irc.reply(format(_('No news for %s.'), channel))
  135. else:
  136. try:
  137. record = self.db.get(channel, id)
  138. irc.reply(str(record))
  139. except dbi.NoRecordError, id:
  140. irc.errorInvalid(_('news item id'), id)
  141. news = wrap(news, ['channeldb', additional('positiveInt')])
  142. @internationalizeDocstring
  143. def remove(self, irc, msg, args, channel, id):
  144. """[<channel>] <id>
  145. Removes the news item with <id> from <channel>. <channel> is only
  146. necessary if the message isn't sent in the channel itself.
  147. """
  148. try:
  149. self.db.remove(channel, id)
  150. irc.replySuccess()
  151. except dbi.NoRecordError:
  152. irc.errorInvalid(_('news item id'), id)
  153. remove = wrap(remove, ['channeldb', 'positiveInt'])
  154. @internationalizeDocstring
  155. def change(self, irc, msg, args, channel, id, replacer):
  156. """[<channel>] <id> <regexp>
  157. Changes the news item with <id> from <channel> according to the
  158. regular expression <regexp>. <regexp> should be of the form
  159. s/text/replacement/flags. <channel> is only necessary if the message
  160. isn't sent on the channel itself.
  161. """
  162. try:
  163. self.db.change(channel, id, replacer)
  164. irc.replySuccess()
  165. except dbi.NoRecordError:
  166. irc.errorInvalid(_('news item id'), id)
  167. change = wrap(change, ['channeldb', 'positiveInt', 'regexpReplacer'])
  168. @internationalizeDocstring
  169. def old(self, irc, msg, args, channel, id):
  170. """[<channel>] [<id>]
  171. Returns the old news item for <channel> with <id>. If no number is
  172. given, returns all the old news items in reverse order. <channel> is
  173. only necessary if the message isn't sent in the channel itself.
  174. """
  175. if id:
  176. try:
  177. record = self.db.getOld(channel, id)
  178. irc.reply(str(record))
  179. except dbi.NoRecordError, id:
  180. irc.errorInvalid(_('news item id'), id)
  181. else:
  182. try:
  183. records = self.db.getOld(channel)
  184. items = [format('(#%i) %s', R.id, R.subject) for R in records]
  185. s = format(_('Old news for %s: %s'), channel, '; '.join(items))
  186. irc.reply(s)
  187. except dbi.NoRecordError:
  188. irc.reply(format(_('No old news for %s.'), channel))
  189. old = wrap(old, ['channeldb', additional('positiveInt')])
  190. Class = News
  191. # vim:set shiftwidth=4 softtabstop=4 expandtab textwidth=79: