如何正确添加第二个线程到python bot

时间:2015-01-08 00:16:16

标签: python twitter twisted

我开始时我不是python程序员......我已经为我的IRC频道修改了一个扭曲的机器人。我现在正在尝试集成第二个线程,这样我就可以每隔30分钟在通道上获得Twitter更新,而不会中断正常的IRC命令。

我已经测试了Twitter更新代码本身并且工作正常......但是我不确定如何将它添加到机器人中的类和函数中并使用扭曲的框架来发送信息。

这是推特更新的代码块:

# For Twitter feed
from twitter import *
from thread import start_new_thread
from datetime import datetime, timedelta
from twitter_app_credentials import *
twitter = Twitter(
auth=OAuth(access_token_key, access_token_secret, consumer_key, consumer_secret))

def twitterthread(self, channel):
    userlist = ['victorbrca', 'MississaugaLUG']
    keepthread = 1
    while keepthread > 0:
        for user in userlist:
            raw = twitter.statuses.user_timeline(screen_name=user,count=1)[0]
            create_date = raw['created_at'].encode('utf-8')
            date = re.sub(r'\+[0-9]{4}', 'UTC', create_date)
            cdate = datetime.strptime(date, '%a %b %d %H:%M:%S %Z %Y')
            current_time = datetime.now() - timedelta(minutes = 30)
            if cdate > current_time:
                tweet = ("@%s: %s" % (raw["user"]["screen_name"], raw["text"]))
                print tweet
                time.sleep(10)
            else:
                print "no new tweets"
            time.sleep(10)

我想通过一个命令或当bot加入频道时启动它,但是没有多个线程同时运行。

这是机器人最后一次提交的样子(试图让它运行起来) - Commit

这是默认的扭曲机器人的样子:

# Copyright (c) 2001-2009 Twisted Matrix Laboratories.
# See LICENSE for details.


"""
An example IRC log bot - logs a channel's events to a file.

If someone says the bot's name in the channel followed by a ':',
e.g.

  <foo> logbot: hello!

the bot will reply:

  <logbot> foo: I am a log bot

Run this script with two arguments, the channel name the bot should
connect to, and file to log to, e.g.:

  $ python ircLogBot.py test test.log

will log channel #test to the file 'test.log'.
"""


# twisted imports
from twisted.words.protocols import irc
from twisted.internet import reactor, protocol
from twisted.python import log

# system imports
import time, sys


class MessageLogger:
    """
    An independent logger class (because separation of application
    and protocol logic is a good thing).
    """
    def __init__(self, file):
        self.file = file

    def log(self, message):
        """Write a message to the file."""
        timestamp = time.strftime("[%H:%M:%S]", time.localtime(time.time()))
        self.file.write('%s %s\n' % (timestamp, message))
        self.file.flush()

    def close(self):
        self.file.close()


class LogBot(irc.IRCClient):
    """A logging IRC bot."""

    nickname = "twistedbot"

    def connectionMade(self):
        irc.IRCClient.connectionMade(self)
        self.logger = MessageLogger(open(self.factory.filename, "a"))
        self.logger.log("[connected at %s]" % 
                        time.asctime(time.localtime(time.time())))

    def connectionLost(self, reason):
        irc.IRCClient.connectionLost(self, reason)
        self.logger.log("[disconnected at %s]" % 
                        time.asctime(time.localtime(time.time())))
        self.logger.close()


    # callbacks for events

    def signedOn(self):
        """Called when bot has succesfully signed on to server."""
        self.join(self.factory.channel)

    def joined(self, channel):
        """This will get called when the bot joins the channel."""
        self.logger.log("[I have joined %s]" % channel)

    def privmsg(self, user, channel, msg):
        """This will get called when the bot receives a message."""
        user = user.split('!', 1)[0]
        self.logger.log("<%s> %s" % (user, msg))

        # Check to see if they're sending me a private message
        if channel == self.nickname:
            msg = "It isn't nice to whisper!  Play nice with the group."
            self.msg(user, msg)
            return

        # Otherwise check to see if it is a message directed at me
        if msg.startswith(self.nickname + ":"):
            msg = "%s: I am a log bot" % user
            self.msg(channel, msg)
            self.logger.log("<%s> %s" % (self.nickname, msg))

    def action(self, user, channel, msg):
        """This will get called when the bot sees someone do an action."""
        user = user.split('!', 1)[0]
        self.logger.log("* %s %s" % (user, msg))

    # irc callbacks

    def irc_NICK(self, prefix, params):
        """Called when an IRC user changes their nickname."""
        old_nick = prefix.split('!')[0]
        new_nick = params[0]
        self.logger.log("%s is now known as %s" % (old_nick, new_nick))


    # For fun, override the method that determines how a nickname is changed on
    # collisions. The default method appends an underscore.
    def alterCollidedNick(self, nickname):
        """
        Generate an altered version of a nickname that caused a collision in an
        effort to create an unused related name for subsequent registration.
        """
        return nickname + '^'



class LogBotFactory(protocol.ClientFactory):
    """A factory for LogBots.

    A new protocol instance will be created each time we connect to the server.
    """

    # the class of the protocol to build when new connection is made
    protocol = LogBot

    def __init__(self, channel, filename):
        self.channel = channel
        self.filename = filename

    def clientConnectionLost(self, connector, reason):
        """If we get disconnected, reconnect to server."""
        connector.connect()

    def clientConnectionFailed(self, connector, reason):
        print "connection failed:", reason
        reactor.stop()


if __name__ == '__main__':
    # initialize logging
    log.startLogging(sys.stdout)

    # create factory protocol and application
    f = LogBotFactory(sys.argv[1], sys.argv[2])

    # connect factory to this host and port
    reactor.connectTCP("irc.freenode.net", 6667, f)

    # run bot
    reactor.run()

感谢。

2 个答案:

答案 0 :(得分:0)

不要使用线程。使用https://github.com/dustin/twitty-twistertwisted.internet.task.LoopingCall

答案 1 :(得分:0)

我找到了一种方法,可以使用Jean-Paul关于使用LoopingCall的想法来满足我的需要。

我定义了一个检查Twitter更新的函数:

def twitterFeed(self, channel):
        twitter_userlist = ['victorbrca', 'MississaugaLUG']
        for user in twitter_userlist:
            RawTweet = twitter.statuses.user_timeline(screen_name=user,count=1)[0]
            RawTweetDate = RawTweet['created_at']
            UTCRawTweetDate = re.sub(r'\+[0-9]{4}', 'UTC', RawTweetDate)
            TweetDateToTime = datetime.strptime(UTCRawTweetDate, '%a %b %d %H:%M:%S %Z %Y')
            TweetDate = TweetDateToTime.strftime('%Y-%b-%d %H:%M')
            GetFiveMinAgo = datetime.utcnow() - timedelta(minutes = 5)
            FiveMinAgo = GetFiveMinAgo.strftime('%Y-%b-%d %H:%M')
            if FiveMinAgo < TweetDate:
                CurrentTime = datetime.utcnow()
                diff = relativedelta(CurrentTime, TweetDateToTime)
                if diff.minutes < 1:
                    Ago = "%s seconds ago" % diff.seconds
                else:
                    Ago = "%s minutes ago" % diff.minutes
                tweet = ("@%s: %s (%s)" % (RawTweet["user"]["screen_name"], RawTweet["text"], Ago))
                msg = tweet.encode('utf-8')
                self.sendLine("PRIVMSG %s :%s" % (channel, msg))

通过LoopingCall(现在)使用命令调用该函数:

# Start Twitter feed
elif msg == "!starttwitter" and user == authorized_user:
    task = LoopingCall(self.twitterFeed, channel)
    task.start(300)

感谢所有回复。