new_contents: import time
  import socket
  import urllib
  
  import idiokit
  from abusehelper.core import utils, bot, events
  
  
  def parse_valid(value, badset=frozenset(["", "-"])):
      if value.strip() in badset:
          return None
      return value
  
  
  def parse_timestamp(value, in_format="%Y/%m/%d_%H:%M", out_format="%Y-%m-%d %H:%M:%SZ"):
      try:
          struct = time.strptime(value, in_format)
      except ValueError:
          return None
      return time.strftime(out_format, struct)
  
  
  def parse_url(url):
      url = parse_valid(url)
      if url is None:
          return None
  
      # We're told that in this case HTTP is a rather safe bet, as
      # there have been very few occurrences HTTPS sites in MDL.
      return "http://" + url
  
  
  def parse_host(url):
      url = parse_valid(url)
      if url is None:
          return None
      return url.split("/")[0]
  
  
  def parse_description_url(url):
      host = parse_host(url)
      if host is None:
          return None
      return "http://www.malwaredomainlist.com/mdl.php?" + urllib.urlencode({ "search": host })
  
  
  def parse_ip(value):
      for addr_type in (socket.AF_INET, socket.AF_INET6):
          try:
              return socket.inet_ntop(addr_type, socket.inet_pton(addr_type, value))
          except (ValueError, socket.error):
              pass
      return None
  
  
  class MDLBot(bot.PollingBot):
      url = bot.Param(default="http://www.malwaredomainlist.com/updatescsv.php")
  
      _columns = ["timestamp", "url", "ip", "reverse", "description", "registrant", "asn"]
  
      @idiokit.stream
      def poll(self):
          self.log.info("Downloading updates from {0!r}".format(self.url))
          try:
              info, fileobj = yield utils.fetch_url(self.url)
          except utils.FetchUrlFailed as fuf:
              raise bot.PollSkipped("Downloading {0!r} failed ({1})".format(self.url, fuf))
          self.log.info("Updates downloaded from {0!r}".format(self.url))
  
          yield idiokit.pipe(
              utils.csv_to_events(fileobj, columns=self._columns),
              idiokit.map(self._normalize))
  
      def _normalize(self, event):
          yield events.Event({
              "feed": "mdl",
              "feed url": self.url,
              "type": "malware",
              "source time": event.values("timestamp", parse_timestamp),
              "url": event.values("url", parse_url),
              "host": event.values("url", parse_host),
              "description url": event.values("url", parse_description_url),
              "ip": event.values("ip", parse_ip),
              "description": event.values("description", parse_valid)
          })
  
  
  if __name__ == "__main__":
      MDLBot.from_command_line().execute()
  
subject: Add a bot using the MDL CSV updates feed, producing mdlrssbot style output. Name the bot independently of the source format (be it CSV or XML or whatever).