示例#1
0
class MeteoAlarmBot(bot.PollingBot):
    poll_interval = bot.IntParam(default=60)
    url = bot.Param(default="http://www.meteoalarm.eu/documents/rss/ee.rss")
    cc = bot.Param(default="EE")
    # You can also have file: url for testing,e.g.
    # url = "file:///<path>/vsroom/examples/public-sources/custom/ee.rss"
    
    old_events = dict()
    @threado.stream
    def poll(inner, self,something):
            
        yield timer.sleep(5)

        self.log.info("Downloading %r", self.url)
        try:
            info, fileobj = yield inner.sub(utils.fetch_url(self.url))
        except utils.FetchUrlFailed, fuf:
            self.log.error("Downloading failed: %r", fuf)
            return
        self.log.info("Downloaded")

        tree = ElementTree()
        try:
            tree.parse(fileobj)
        except ExpatError,e:
            self.log.error("Parsing source failed, %r", e)
            return
示例#2
0
class TwitterBot(bot.PollingBot):
    consumer_key = bot.Param()
    consumer_secret = bot.Param()
    access_token_key = bot.Param()
    access_token_secret = bot.Param()
    old_tweets = dict()

    def feed_keys(self, user, **keys):
        return [user]

    @threado.stream
    def poll(inner, self, user):
        yield timer.sleep(1)
        new_tweets = dict()
        api = twitter.Api(consumer_key=self.consumer_key,
                          consumer_secret=self.consumer_secret,
                          access_token_key=self.access_token_key,
                          access_token_secret=self.access_token_secret)
        try:
            userobj = api.GetUser(user)
            friends = api.GetFriends()
        except (URLError, twitter.TwitterError, ValueError, JSONDecodeError,
                socket.error), e:
            self.log.error("Twitter error: %s." % (e))
            return
        self.log.info('Fetching status for %s' % userobj.name)
        for friend in [userobj] + friends:
            status = friend.GetStatus()
            name = friend.screen_name
            if status == None: continue
            start = status.GetCreatedAtInSeconds()
            new_tweets[name] = friend

        #dedup
        for name, friend in new_tweets.iteritems():
            # 1. is this the same event that was sent previously, and
            # 2. is this older event than the recent one (twitter api
            #    sometimes returns non-latest tweet)
            old_friend = self.old_tweets.get(name)
            if old_friend == None:
                event = self.get_event(friend)
                inner.send(event)
                continue
            old_tweet = self.old_tweets.get(name).GetStatus()
            new_tweet = friend.GetStatus()
            prev_created = old_tweet.GetCreatedAtInSeconds()
            new_created = new_tweet.GetCreatedAtInSeconds()

            if prev_created < new_created:
                event = self.get_event(friend)
                inner.send(event)

        self.old_tweets = new_tweets
示例#3
0
class AutoshunBot(bot.PollingBot):
    COLUMNS = ["ip", "time", "info"]
    time_offset = 5

    feed_url = bot.Param(default=AUTOSHUN_CSV_URL)
    use_cymru_whois = bot.BoolParam()

    def poll(self):
        pipe = self._poll(url=self.feed_url)
        if self.use_cymru_whois:
            pipe = pipe | cymruwhois.augment("ip")
        return pipe | self._normalize()

    @idiokit.stream
    def _poll(self, url):
        self.log.info("Downloading %s" % url)
        try:
            info, fileobj = yield utils.fetch_url(url)
        except utils.FetchUrlFailed, fuf:
            self.log.error("Download failed: %r", fuf)
            idiokit.stop()
        self.log.info("Downloaded")

        # Grab time offset from first line of the CSV
        header = fileobj.readline()
        # Source file header row may sometimes be empty
        if header.startswith("Shunlist as of"):
            offset = -1 * int(header[-5:]) / 100  # ex: -0500 to 5
            self.time_offset = offset if -12 <= offset <= 12 else 5

        yield utils.csv_to_events(fileobj,
                                  columns=self.COLUMNS,
                                  charset=info.get_param("charset"))
示例#4
0
class DataplaneBot(bot.PollingBot):
    url = bot.Param()
    use_cymru_whois = bot.BoolParam()

    # The first column values (ASN and AS name) are ignored.
    COLUMNS = [None, None, "ip", "time", "category"]

    def poll(self):
        if self.use_cymru_whois:
            return self._poll() | cymruwhois.augment("ip")
        return self._poll()

    @idiokit.stream
    def _poll(self):
        self.log.info("Downloading %s" % self.url)
        try:
            info, fileobj = yield utils.fetch_url(self.url)
        except utils.FetchUrlFailed, fuf:
            self.log.error("Download failed: %r", fuf)
            return
        self.log.info("Downloaded")

        charset = info.get_param("charset")
        filtered = (x for x in fileobj if x.strip() and not x.startswith("#"))
        yield utils.csv_to_events(filtered,
                                  delimiter="|",
                                  columns=self.COLUMNS,
                                  charset=charset)
示例#5
0
class Receiver(bot.XMPPBot):
    room = bot.Param("""
        the room for receiving events from
    """)

    @idiokit.stream
    def main(self):
        xmpp = yield self.xmpp_connect()
        room = yield xmpp.muc.join(self.room)

        yield idiokit.pipe(
            room,
            events.stanzas_to_events(),
            self._recv()
        )

    @idiokit.stream
    def _recv(self):
        dumps = json.JSONEncoder(check_circular=False).encode

        while True:
            event = yield idiokit.next()

            out_dict = {}
            for key, value in event.items():
                out_dict.setdefault(key, []).append(value)

            print dumps(out_dict)
示例#6
0
class VxVaultBot(bot.PollingBot):
    feed_url = bot.Param(default=FEED_URL)

    @idiokit.stream
    def poll(self):
        self.log.info("Downloading {0}".format(self.feed_url))
        try:
            info, fileobj = yield utils.fetch_url(self.feed_url)
        except utils.FetchUrlFailed as fuf:
            raise bot.PollSkipped("failed to download {0} ({1})".format(
                self.feed_url, fuf))
        self.log.info("Downloaded")

        for line in fileobj:
            url, netloc = parseURL(line)
            if url is None:
                continue
            event = events.Event()
            event.add("url", url)
            if i_am_a_name(netloc):
                event.add("domain name", netloc)
            else:
                event.add("ip", netloc)
            event.add("feeder", "siri urz")
            event.add("feed", "vxvault")
            event.add("feed url", self.feed_url)
            event.add("type", "malware url")
            event.add("description",
                      "This host is most likely hosting a malware URL.")
            yield idiokit.send(event)
示例#7
0
class OpenBLBot(bot.PollingBot):
    feed_url = bot.Param(default=OPENBL_FEED_URL)
    use_cymru_whois = bot.BoolParam()

    def poll(self):
        pipe = self._poll(url=self.feed_url)
        if self.use_cymru_whois:
            pipe = pipe | cymruwhois.augment("ip")
        return pipe

    @idiokit.stream
    def _poll(self, url):
        self.log.info("Downloading %s" % url)
        try:
            info, fileobj = yield utils.fetch_url(url)
        except utils.FetchUrlFailed, fuf:
            raise bot.PollSkipped("failed to download {0!r} ({1})".format(url, fuf))
        self.log.info("Downloaded")

        for line in fileobj:
            event = _parse_line(line)
            if event is None:
                continue

            event.add("feeder", "openbl.org")
            event.add("feed", "openbl")
            event.add("description url", self.feed_url)
            event.add("type", "brute-force")
            event.add(
                "description",
                "This host has most likely been performing brute-force " +
                "attacks on one of the following services: FTP, SSH, POP3, " +
                "IMAP, IMAPS or POP3S."
            )
            yield idiokit.send(event)
示例#8
0
class MDLBot(bot.PollingBot):
    url = bot.Param(default="https://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),
            "domain name": event.values("url", parse_host),
            "description url": event.values("url", parse_description_url),
            "ip": event.values("ip", parse_ip),
            "asn": event.values("asn", parse_valid),
            "registrant": event.values("registrant", parse_valid),
            "description": event.values("description", parse_valid)
        })
示例#9
0
class TailBot(bot.FeedBot):
    path = bot.Param("path to the followed file")
    offset = bot.IntParam("file offset", default=None)

    @idiokit.stream
    def feed(self):
        for result in tail_file(self.path, self.offset):
            if result is None:
                yield idiokit.sleep(2.0)
                continue

            mtime, line = result
            keys = self.parse(line, mtime)
            if keys is None:
                continue

            event = events.Event()
            for key, value in keys.items():
                event.add(key, value)
            yield idiokit.send(event)

    def parse(self, line, mtime):
        line = line.rstrip()
        if not line:
            return

        line = utils.force_decode(line)
        return {"line": line}
示例#10
0
class StressBot(bot.FeedBot):
    data = bot.Param("event data")

    @idiokit.stream
    def feed(self):
        event = events.Event.from_unicode(self.data.decode("utf-8"))

        while True:
            yield idiokit.send(event)
class RollOverArchiveBot(archivebot.ArchiveBot):
    rollover = bot.Param("period for doing archive file rollover " +
                         "(day, week, month or year)")

    def archive_path(self, timestamp, room_name, event):
        path = archivebot.ArchiveBot.archive_path(self, timestamp, room_name,
                                                  event)
        path += "." + time.strftime(
            "%Y%m%d", current_timestamp(timestamp, self.rollover))
        return path
示例#12
0
class FakeBig5Bot(bot.XMPPBot):
    room_dst = bot.Param("the destination room")

    @threado.stream
    def main(inner, self):
        conn = yield self.xmpp_connect()
        dst = yield conn.muc.join(self.room_dst, self.bot_name)
        self.log.info("Joined room %r", self.room_dst), dst

        yield generate() | events_to_elements_with_delay_element(
        ) | dst | threado.dev_null()
示例#13
0
class HistorianService(bot.ServiceBot):
    bot_state_file = bot.Param()

    def __init__(self, bot_state_file=None, **keys):
        bot.ServiceBot.__init__(self, bot_state_file=None, **keys)

        self.rooms = taskfarm.TaskFarm(self.handle_room)
        self.db_dir = bot_state_file
        try:
            os.makedirs(self.db_dir)
        except OSError, ose:
            if errno.EEXIST != ose.errno:
                raise ose
示例#14
0
class AccessLogBot(TailBot):
    path = bot.Param("access_log file path")

    def parse(self, line, _):
        line = line.strip()
        if not line:
            return

        facts = dict(parse_log_line(line))
        if "timestamp" in facts:
            facts["timestamp"] = convert_date(facts["timestamp"])
        if "request" in facts:
            facts.update(parse_request(facts["request"]))
        if "user_agent" in facts:
            facts.update(parse_user_agent(facts["user_agent"]))
        return events.Event(facts)
示例#15
0
class Receiver(bot.XMPPBot):
    room = bot.Param("""
        the room for receiving events from
    """)
    rate_limit = bot.IntParam("""
        rate limit for the sent stream
    """, default=None)

    @idiokit.stream
    def main(self):
        xmpp = yield self.xmpp_connect()
        room = yield xmpp.muc.join(self.room)

        yield idiokit.pipe(
            self._read_stdin(),
            events.events_to_elements(),
            _rate_limiter(self.rate_limit),
            room,
            idiokit.consume()
        )

    @idiokit.stream
    def _read_stdin(self):
        loads = json.JSONDecoder(parse_float=unicode, parse_int=unicode).decode

        while True:
            yield select.select([sys.stdin], [], [])

            line = sys.stdin.readline()
            if not line:
                break
            if not line.strip():
                continue

            in_dict = loads(line)
            yield idiokit.send(events.Event(in_dict))
示例#16
0
class RansomwareTrackerBot(bot.PollingBot):
    feed_url = bot.Param(
        default="https://ransomwaretracker.abuse.ch/feeds/csv/")

    @idiokit.stream
    def poll(self):
        self.log.info("Downloading {0}".format(self.feed_url))
        try:
            info, fileobj = yield utils.fetch_url(self.feed_url)
        except utils.FetchUrlFailed as fuf:
            raise bot.PollSkipped("Download failed: {0}".format(fuf))

        lines = []
        for line in fileobj:
            line = line.strip()

            if line and not line.startswith("#"):
                lines.append(line)

        yield idiokit.pipe(
            utils.csv_to_events(tuple(lines),
                                columns=COLUMNS,
                                charset=info.get_param("charset", None)),
            _parse())
示例#17
0
class PhishTankBot(bot.PollingBot):
    application_key = bot.Param("registered application key for PhishTank")
    feed_url = bot.Param(default="http://data.phishtank.com/data/%s/online-valid.xml.bz2")

    def __init__(self, *args, **keys):
        bot.PollingBot.__init__(self, *args, **keys)

        self._etag = None

    @idiokit.stream
    def _handle_entry(self, entry, sites):
        details = entry.find("details")
        if details is None:
            return

        verification = entry.find("verification")
        if verification is None or parse_text(verification, "verified") != "yes":
            return

        status = entry.find("status")
        if status is None or parse_text(status, "online") != "yes":
            return

        url = parse_text(entry, "url")
        if not url:
            return

        event = events.Event({"feed": "phishtank", "url": url})

        domain = urlparse.urlparse(url).netloc
        if is_domain(domain):
            event.add("domain name", domain)

        detail_url = parse_text(entry, "phish_detail_url")
        if detail_url:
            event.add("description url", detail_url)

        target = parse_text(entry, "target")
        if target:
            event.add("target", target)

        history = {}
        for detail in details.findall("detail"):
            ip = parse_text(detail, "ip_address")
            if not ip:
                continue

            announcer = parse_text(detail, "announcing_network")
            if not announcer:
                continue

            detail_time = parse_text(detail, "detail_time")
            try:
                ts = datetime.strptime(detail_time, "%Y-%m-%dT%H:%M:%S+00:00")
            except (ValueError, TypeError):
                continue

            history[ts] = (ip, announcer)

        if history:
            latest = sorted(history.keys())[-1]
            ip, announcer = history[latest]

            url_data = sites.setdefault(url, set())
            if (ip, announcer) in url_data:
                return
            url_data.add((ip, announcer))

            event.add("ip", ip)
            event.add("asn", announcer)
            event.add("source time", latest.strftime("%Y-%m-%d %H:%M:%SZ"))

            yield idiokit.send(event)

    @idiokit.stream
    def poll(self):
        url = self.feed_url % self.application_key

        try:
            self.log.info("Checking if {0!r} has new data".format(url))
            info, _ = yield utils.fetch_url(HeadRequest(url))

            etag = info.get("etag", None)
            if etag is not None and self._etag == etag:
                raise bot.PollSkipped("no new data detected (ETag stayed the same)")

            self.log.info("Downloading data from {0!r}".format(url))
            _, fileobj = yield utils.fetch_url(url)
        except utils.FetchUrlFailed as error:
            raise bot.PollSkipped("failed to download {0!r} ({1})".format(url, error))

        self.log.info("Downloaded data from {0!r}".format(url))

        reader = BZ2Reader(fileobj)
        try:
            depth = 0
            sites = dict()

            for event, element in etree.iterparse(reader, events=("start", "end")):
                if event == "start" and element.tag == "entry":
                    depth += 1

                if event == "end" and element.tag == "entry":
                    yield self._handle_entry(element, sites)
                    depth -= 1

                if event == "end" and depth == 0:
                    element.clear()
        except SyntaxError as error:
            raise bot.PollSkipped("syntax error in report {0!r} ({1})".format(url, error))
        else:
            self._etag = etag

    def main(self, state):
        if state is None:
            state = None, None
        self._etag, wrapped_state = state

        return bot.PollingBot.main(self, wrapped_state) | self._add_etag_to_result()

    @idiokit.stream
    def _add_etag_to_result(self):
        state = yield idiokit.consume()
        idiokit.stop(self._etag, state)
示例#18
0
class DotBot(bot.Bot):
    bot_name = None

    config = bot.Param("configuration module")
    show_startups = bot.BoolParam()
    show_attributes = bot.BoolParam()

    def run(self):
        print "digraph G {"
        print "node [ shape=box, style=filled, color=lightgrey ];"

        dot = Dot(config.load_configs(self.config))
        services = dot.services()
        sessions = dot.sessions()

        def missing(x):
            return self.show_startups and x not in services

        for session in sessions:
            conf = dict(session.conf)
            path = session.path
            src = conf.pop("src_room", None)
            dst = conf.pop("dst_room", None)

            node = None
            if session.service != "roomgraph":
                node = "node " + session.service + " " + (src or "@") + " " + (
                    dst or "@")
                if missing(session.service):
                    print line(node,
                               label=session.service,
                               shape="ellipse",
                               fontsize=12,
                               fontcolor="white",
                               color="red")
                else:
                    print line(node,
                               label=session.service,
                               shape="ellipse",
                               fontsize=12,
                               style="")

            label_list = list()
            if path:
                label_list.append(".".join(path))
            if self.show_attributes:
                for item in conf.items():
                    label_list.append("  %r=%r" % item)
            label = "\\n".join(label_list)

            color = "red" if missing(session.service) else "black"
            if src is None:
                if node is not None and dst is not None:
                    print line(node,
                               dst,
                               label=label,
                               color=color,
                               fontsize=10)
            else:
                if node is not None and dst is None:
                    print line(src,
                               node,
                               label=label,
                               color=color,
                               fontsize=10)
                elif node is None and dst is not None:
                    print line(src, dst, label=label, color=color, fontsize=10)
                elif node is not None and dst is not None:
                    print line(src, node, label="", color=color, fontsize=10)
                    print line(node,
                               dst,
                               label=label,
                               color=color,
                               fontsize=10)

        print '}'
示例#19
0
class ArchiveBot(bot.ServiceBot):
    archive_dir = bot.Param("directory where archive files are written")

    def __init__(self, *args, **keys):
        super(ArchiveBot, self).__init__(*args, **keys)

        self.rooms = taskfarm.TaskFarm(self._handle_room, grace_period=0.0)
        self.archive_dir = _ensure_dir(self.archive_dir)

    @idiokit.stream
    def session(self, state, src_room):
        src_jid = yield self.xmpp.muc.get_full_room_jid(src_room)
        yield self.rooms.inc(src_jid.bare())

    @idiokit.stream
    def _handle_room(self, name):
        msg = "room {0!r}".format(name)

        attrs = events.Event({
            "type": "room",
            "service": self.bot_name,
            "room": unicode(name)
        })

        with self.log.stateful(repr(self.xmpp.jid), "room", repr(name)) as log:
            log.open("Joining " + msg, attrs, status="joining")
            room = yield self.xmpp.muc.join(name, self.bot_name)

            log.open("Joined " + msg, attrs, status="joined")
            try:
                yield idiokit.pipe(
                    room,
                    events.stanzas_to_events(),
                    self._archive(room.jid.bare())
                )
            finally:
                log.close("Left " + msg, attrs, status="left")

    def _archive(self, room_bare_jid):
        compress = utils.WaitQueue()
        room_name = _encode_room_jid(room_bare_jid)

        _dir = os.path.join(self.archive_dir, room_name)

        if _dir != os.path.normpath(_dir):
            raise ValueError("incorrect room name lands outside the archive directory")

        for root, _, filenames in os.walk(_dir):
            for filename in filenames:
                path = os.path.join(root, filename)
                if _is_compress_path(path):
                    compress.queue(0.0, path)

        return idiokit.pipe(
            self._collect(room_name, compress),
            self._compress(compress)
        )

    @idiokit.stream
    def _collect(self, room_name, compress):
        event = yield idiokit.next()

        while True:
            current = datetime.utcnow().day

            with _open_archive(self.archive_dir, time.time(), room_name) as archive:
                self.log.info("Opened archive {0!r}".format(archive.name))

                while current == datetime.utcnow().day:
                    json_dict = dict((key, event.values(key)) for key in event.keys())
                    archive.write(json.dumps(json_dict) + os.linesep)

                    event = yield idiokit.next()

            yield compress.queue(0.0, _rename(archive.name))

    @idiokit.stream
    def _compress(self, queue):
        while True:
            compress_path = yield queue.wait()

            try:
                path = yield idiokit.thread(_compress, compress_path)
                self.log.info("Compressed archive {0!r}".format(path))
            except ValueError:
                self.log.error("Invalid path {0!r}".format(compress_path))
示例#20
0
class OpenCollabReader(bot.FeedBot):
    poll_interval = bot.IntParam(default=60)

    collab_url = bot.Param()
    collab_user = bot.Param()
    collab_password = bot.Param(default=None)
    collab_ignore_cert = bot.BoolParam()
    collab_extra_ca_certs = bot.Param(default=None)

    def __init__(self, *args, **keys):
        bot.FeedBot.__init__(self, *args, **keys)

        if self.collab_password is None:
            self.collab_password = getpass.getpass("Collab password: "******"utf8") + self.collab_url).hexdigest()

    @idiokit.stream
    def feed(self, query, feed_all):
        collab = wiki.GraphingWiki(self.collab_url,
                                   ssl_verify_cert=not self.collab_ignore_cert,
                                   ssl_ca_certs=self.collab_extra_ca_certs)
        yield idiokit.thread(collab.authenticate, self.collab_user,
                             self.collab_password)

        yield idiokit.sleep(5)

        token = None
        current = dict()
        while True:
            try:
                result = yield idiokit.thread(collab.request, "IncGetMeta",
                                              query, token)
            except wiki.WikiFailure as fail:
                self.log.error("IncGetMeta failed: {0!r}".format(fail))
            else:
                incremental, token, (removed, updates) = result
                removed = set(removed)
                if not incremental:
                    removed.update(current)
                    current.clear()

                for page, keys in updates.iteritems():
                    event = current.setdefault(page, events.Event())
                    event.add("id:open", self.page_id(page))
                    event.add("gwikipagename", page)
                    event.add(
                        "collab url",
                        self.collab_url + urllib.quote(page.encode("utf8")))

                    removed.discard(page)

                    for key, (discarded, added) in keys.iteritems():
                        for value in map(normalize, discarded):
                            event.discard(key, value)

                        for value in map(normalize, added):
                            event.add(key, value)

                    if not feed_all:
                        yield idiokit.send(event)

                for page in removed:
                    current.pop(page, None)

                    event = events.Event()
                    event.add("id:close", self.page_id(page))
                    event.add("gwikipagename", page)
                    event.add("collab url", self.collab_url + page)

                    yield idiokit.send(event)

                if feed_all:
                    for page in current:
                        yield idiokit.send(current[page])

            yield idiokit.sleep(self.poll_interval)
示例#21
0
class BridgeBot(bot.Bot):
    xmpp_src_jid = bot.Param("the XMPP src JID")
    xmpp_src_password = bot.Param("the XMPP src password", default=None)
    xmpp_src_room = bot.Param("the XMPP src room")
    xmpp_src_host = bot.Param(
        "the XMPP src service host (default: autodetect)", default=None)
    xmpp_src_port = bot.IntParam(
        "the XMPP src service port (default: autodetect)", default=None)
    xmpp_src_ignore_cert = bot.BoolParam("""
        do not perform any verification for
        the XMPP service's SSL certificate
        """)
    xmpp_src_extra_ca_certs = bot.Param("""
        a PEM formatted file of CAs to be
        used in addition to the system CAs
        """,
                                        default=None)

    xmpp_dst_jid = bot.Param("the XMPP dst JID")
    xmpp_dst_password = bot.Param("the XMPP dst password", default=None)
    xmpp_dst_host = bot.Param(
        "the XMPP dst service host (default: autodetect)", default=None)
    xmpp_dst_port = bot.IntParam(
        "the XMPP dst service port (default: autodetect)", default=None)
    xmpp_dst_room = bot.Param("the XMPP dst room")
    xmpp_dst_ignore_cert = bot.BoolParam("""
        do not perform any verification for
        the XMPP service's SSL certificate
        """)
    xmpp_dst_extra_ca_certs = bot.Param("""
        a PEM formatted file of CAs to be
        used in addition to the system CAs
        """,
                                        default=None)

    def __init__(self, **keys):
        bot.Bot.__init__(self, **keys)

        if self.xmpp_src_password is None:
            self.xmpp_src_password = getpass.getpass("XMPP src password: "******"XMPP dst password: "******"Connecting to XMPP %s server with JID %r", _type, jid)
        connection = yield xmpp.connect(jid,
                                        password,
                                        host=host,
                                        port=port,
                                        ssl_verify_cert=verify_cert,
                                        ssl_ca_certs=ca_certs)

        self.log.info("Connected to XMPP %s server with JID %r", _type, jid)
        connection.core.presence()

        self.log.info("Joining %s room %r", _type, room_name)
        room = yield connection.muc.join(room_name, self.bot_name)

        self.log.info("Joined %s room %r", _type, room_name)
        idiokit.stop(room)

    @idiokit.stream
    def main(self):
        dst = yield self._join("dst", self.xmpp_dst_jid,
                               self.xmpp_dst_password, self.xmpp_dst_host,
                               self.xmpp_dst_port, self.xmpp_dst_ignore_cert,
                               self.xmpp_dst_extra_ca_certs,
                               self.xmpp_dst_room)
        src = yield self._join("src", self.xmpp_src_jid,
                               self.xmpp_src_password, self.xmpp_src_host,
                               self.xmpp_src_port, self.xmpp_src_ignore_cert,
                               self.xmpp_src_extra_ca_certs,
                               self.xmpp_src_room)

        yield src | peel_messages() | dst | idiokit.consume()

    def run(self):
        try:
            return idiokit.main_loop(self.main())
        except idiokit.Signal:
            pass
示例#22
0
class MailDirBot(bot.FeedBot):
    handler = handlers.HandlerParam()
    input_dir = bot.Param()
    work_dir = bot.Param()
    concurrency = bot.IntParam(default=1)
    poll_interval = bot.FloatParam(default=1)

    def __init__(self, *args, **keys):
        bot.FeedBot.__init__(self, *args, **keys)

        self.handler = handlers.load_handler(self.handler)

        self._queue = utils.WaitQueue()

    def feed_keys(self, *args, **keys):
        for nth_concurrent in range(1, self.concurrency + 1):
            yield (nth_concurrent, )

    def run(self):
        makedirs(self.work_dir)

        with lockfile(os.path.join(self.work_dir, ".lock")) as success:
            if not success:
                self.log.error(
                    u"Someone else is using the directory {0}".format(
                        self.work_dir))
            else:
                bot.FeedBot.run(self)

    @idiokit.stream
    def _poll_files(self):
        in_progress = os.path.join(self.work_dir, "in-progress")
        done = os.path.join(self.work_dir, "done")

        makedirs(in_progress)
        makedirs(done)

        for dirname, filename in iter_dir(in_progress):
            input_name = os.path.join(dirname, filename)
            output_name = os.path.join(done, filename)
            yield idiokit.send(input_name, output_name)

        while True:
            paths = itertools.chain(
                iter_dir(os.path.join(self.input_dir, "new")),
                iter_dir(os.path.join(self.input_dir, "cur")))

            for dirname, filename in paths:
                uuid_name = uuid.uuid4().hex + "." + filename
                input_name = os.path.join(in_progress, uuid_name)
                output_name = os.path.join(done, uuid_name)
                if try_rename(os.path.join(dirname, filename), input_name):
                    yield idiokit.send(input_name, output_name)

            yield idiokit.sleep(self.poll_interval)

    @idiokit.stream
    def _forward_files(self):
        while True:
            input_name, output_name = yield idiokit.next()

            ack = idiokit.Event()
            node = yield self._queue.queue(0, (input_name, output_name, ack))
            try:
                yield ack
            finally:
                yield self._queue.cancel(node)

    @idiokit.stream
    def main(self, state):
        yield self._poll_files() | self._forward_files()

    @idiokit.stream
    def feed(self, nth_concurrent):
        while True:
            input_name, output_name, ack = yield self._queue.wait()
            ack.succeed()

            msg = try_read_message(input_name)
            if msg is None:
                continue

            subject = escape_whitespace(
                msg.get_unicode("Subject", "<no subject>", errors="replace"))
            sender = escape_whitespace(
                msg.get_unicode("From", "<unknown sender>", errors="replace"))
            self.log.info(u"Handler #{0} handling mail '{1}' from {2}".format(
                nth_concurrent, subject, sender))

            handler = self.handler(log=self.log)
            yield handler.handle(msg)

            os.rename(input_name, output_name)
            self.log.info(u"Handler #{0} done with mail '{1}' from {2}".format(
                nth_concurrent, subject, sender))