[TASK] Initial import.

This commit is contained in:
Jan Philipp Timme 2014-05-14 19:38:19 +02:00
commit 97009ab8d2
7 changed files with 169 additions and 0 deletions

2
.gitignore vendored Normal file
View File

@ -0,0 +1,2 @@
*.pyc
*.cache

2
Makefile Normal file
View File

@ -0,0 +1,2 @@
run:
twistd -n monitorbot

0
monitor/__init__.py Normal file
View File

64
monitor/bot.py Normal file
View File

@ -0,0 +1,64 @@
from twisted.internet import protocol
from twisted.python import log
from twisted.words.protocols import irc
class MonitorBot(irc.IRCClient):
def connectionMade(self):
"""Called when a connection is made."""
self.nickname = self.factory.nickname
self.realname = self.factory.realname
irc.IRCClient.connectionMade(self)
log.msg("connectionMade")
def connectionLost(self, reason):
"""Called when a connection is lost."""
irc.IRCClient.connectionLost(self, reason)
log.msg("connectionLost {!r}".format(reason))
# callbacks for events
def signedOn(self):
"""Called when bot has successfully signed on to server."""
log.msg("Signed on")
if self.nickname != self.factory.nickname:
log.msg('Your nickname was already occupied, actual nickname is "{}".'.format(self.nickname))
self.join(self.factory.channel)
def joined(self, channel):
"""Called when the bot joins the channel."""
log.msg("[{nick} has joined {channel}]".format(nick=self.nickname, channel=self.factory.channel,))
def privmsg(self, user, channel, msg):
"""Called when the bot receives a message."""
sendTo = None
prefix = ''
senderNick = user.split('!', 1)[0]
if channel == self.nickname:
# Reply back in the query / privmsg
sendTo = senderNick
elif msg.startswith(self.nickname):
# Reply back on the channel
sendTo = channel
prefix = senderNick + ': ' #Mark message so people know what is going on
else:
msg = msg.lower()
if msg in ['!hi']:
sendTo = channel
prefix = senderNick + ': '
if sendTo:
reply = "Hello."
self.msg(sendTo, prefix + reply)
log.msg(
"sent message to {receiver}, triggered by {sender}:\n\t{reply}"
.format(receiver=sendTo, sender=senderNick, reply=reply)
)
class MonitorBotFactory(protocol.ClientFactory):
protocol = MonitorBot
def __init__(self, channel, nickname, realname):
"""Initialize the bot factory with our settings."""
self.channel = channel
self.nickname = nickname
self.realname = realname

3
requirements.txt Normal file
View File

@ -0,0 +1,3 @@
coverage
pyopenssl
twisted

8
settings.ini Normal file
View File

@ -0,0 +1,8 @@
[irc]
endpoint = tcp:host=irc.euirc.net:port=6667
nickName = ftpd
realName = bot: provides tracking of an ftp
channel = #Tonari.
[fsmonitor]
path=/home/kuzuru-ftp/

View File

@ -0,0 +1,90 @@
from ConfigParser import ConfigParser
from twisted.application.service import IServiceMaker, Service
from twisted.internet.endpoints import clientFromString
from twisted.plugin import IPlugin
from twisted.python import usage, log
from zope.interface import implementer
from twisted.internet import inotify
from twisted.python import filepath
from monitor.bot import MonitorBotFactory
class MonitorBotService(Service):
_bot = None
def __init__(self, endpoint, channel, nickname, realname, path):
self._endpoint = endpoint
self._channel = channel
self._nickname = nickname
self._realname = realname
self._path = path
def startService(self):
"""Construct a client & connect to server."""
from twisted.internet import reactor
"""Define callbacks."""
def connected(bot):
self._bot = bot
def failure(err):
log.err(err, _why='Could not connect to specified server.')
reactor.stop()
client = clientFromString(reactor, self._endpoint)
factory = MonitorBotFactory(
self._channel,
self._nickname,
self._realname
)
def fsnotify(ignored, filepath, mask):
msg = "event %s on %s" % (', '.join(inotify.humanReadableMask(mask)), filepath)
self._bot.msg(self._channel, msg)
pass
notifier = inotify.INotify()
notifier.startReading()
notifier.watch(filepath.FilePath(self._path), autoAdd=True, recursive=True, callbacks=[fsnotify])
"""Attach defined callbacks."""
return client.connect(factory).addCallbacks(connected, failure)
def stopService(self):
"""Disconnect."""
if self._bot and self._bot.transport.connected:
self._bot.transport.loseConnection()
class Options(usage.Options):
optParameters = [
['config', 'c', 'settings.ini', 'Configuration file.'],
]
@implementer(IServiceMaker, IPlugin)
class BotServiceMaker(object):
tapname = "monitorbot"
description = "IRC bot that provides verbose monitoring of an fs path."
options = Options
def makeService(self, options):
"""Read the config and construct the monitorbot service."""
config = ConfigParser()
config.read([options['config']])
return MonitorBotService(
endpoint=config.get('irc', 'endpoint'),
channel=config.get('irc', 'channel'),
nickname=config.get('irc', 'nickname'),
realname=config.get('irc', 'realname'),
path=config.get('fsmonitor', 'path'),
)
# Now construct an object which *provides* the relevant interfaces
# The name of this variable is irrelevant, as long as there is *some*
# name bound to a provider of IPlugin and IServiceMaker.
serviceMaker = BotServiceMaker()