Сергей Матвеенко
Yammy? Dummy? ... Botty!:) Простой бот на xmpppy
Сейчас появляется всё больше сервисов, использующих протокол XMPP (он же Jabber).
Например: juick.com, facebook.com, identi.ca.
Часто хочется написать своего бота, чтобы общаться с такими сервисами, может быть написать свой сервис или просто автоматически отвечать своим друзьям на глупые сообщения;)
В этом может помочь библиотека xmpppy.
Я использую вот такой класс, в качестве основы для моих ботов:
Как видно, в коде используются настройки бота. Они выглядят вот так:
Для любого нового бота теперь нужно создать класс-наследник BaseBot, в котором установить атрибут bot_name и реализовать методы messageHandler и presenceHandler. В словаре BOT должен существовать ключ соответствующий этому bot_name с настройками для этого бота.
Запуск бота осуществляется так:
, где MyBot — класс вашего бота, а параметр debug говорит сам за себя.
That's all folks!
Например: juick.com, facebook.com, identi.ca.
Часто хочется написать своего бота, чтобы общаться с такими сервисами, может быть написать свой сервис или просто автоматически отвечать своим друзьям на глупые сообщения;)
В этом может помочь библиотека xmpppy.
Я использую вот такой класс, в качестве основы для моих ботов:
.highlight .hll { background-color: #404040 }.highlight { background: #202020; color: #d0d0d0 }.highlight .c { color: #999999; font-style: italic } /* Comment */.highlight .err { color: #a61717; background-color: #e3d2d2 } /* Error */.highlight .g { color: #d0d0d0 } /* Generic */.highlight .k { color: #6ab825; font-weight: bold } /* Keyword */.highlight .l { color: #d0d0d0 } /* Literal */.highlight .n { color: #d0d0d0 } /* Name */.highlight .o { color: #d0d0d0 } /* Operator */.highlight .x { color: #d0d0d0 } /* Other */.highlight .p { color: #d0d0d0 } /* Punctuation */.highlight .cm { color: #999999; font-style: italic } /* Comment.Multiline */.highlight .cp { color: #cd2828; font-weight: bold } /* Comment.Preproc */.highlight .c1 { color: #999999; font-style: italic } /* Comment.Single */.highlight .cs { color: #e50808; font-weight: bold; background-color: #520000 } /* Comment.Special */.highlight .gd { color: #d22323 } /* Generic.Deleted */.highlight .ge { color: #d0d0d0; font-style: italic } /* Generic.Emph */.highlight .gr { color: #d22323 } /* Generic.Error */.highlight .gh { color: #ffffff; font-weight: bold } /* Generic.Heading */.highlight .gi { color: #589819 } /* Generic.Inserted */.highlight .go { color: #cccccc } /* Generic.Output */.highlight .gp { color: #aaaaaa } /* Generic.Prompt */.highlight .gs { color: #d0d0d0; font-weight: bold } /* Generic.Strong */.highlight .gu { color: #ffffff; text-decoration: underline } /* Generic.Subheading */.highlight .gt { color: #d22323 } /* Generic.Traceback */.highlight .kc { color: #6ab825; font-weight: bold } /* Keyword.Constant */.highlight .kd { color: #6ab825; font-weight: bold } /* Keyword.Declaration */.highlight .kn { color: #6ab825; font-weight: bold } /* Keyword.Namespace */.highlight .kp { color: #6ab825 } /* Keyword.Pseudo */.highlight .kr { color: #6ab825; font-weight: bold } /* Keyword.Reserved */.highlight .kt { color: #6ab825; font-weight: bold } /* Keyword.Type */.highlight .ld { color: #d0d0d0 } /* Literal.Date */.highlight .m { color: #3677a9 } /* Literal.Number */.highlight .s { color: #ed9d13 } /* Literal.String */.highlight .na { color: #bbbbbb } /* Name.Attribute */.highlight .nb { color: #24909d } /* Name.Builtin */.highlight .nc { color: #447fcf; text-decoration: underline } /* Name.Class */.highlight .no { color: #40ffff } /* Name.Constant */.highlight .nd { color: #ffa500 } /* Name.Decorator */.highlight .ni { color: #d0d0d0 } /* Name.Entity */.highlight .ne { color: #bbbbbb } /* Name.Exception */.highlight .nf { color: #447fcf } /* Name.Function */.highlight .nl { color: #d0d0d0 } /* Name.Label */.highlight .nn { color: #447fcf; text-decoration: underline } /* Name.Namespace */.highlight .nx { color: #d0d0d0 } /* Name.Other */.highlight .py { color: #d0d0d0 } /* Name.Property */.highlight .nt { color: #6ab825; font-weight: bold } /* Name.Tag */.highlight .nv { color: #40ffff } /* Name.Variable */.highlight .ow { color: #6ab825; font-weight: bold } /* Operator.Word */.highlight .w { color: #666666 } /* Text.Whitespace */.highlight .mf { color: #3677a9 } /* Literal.Number.Float */.highlight .mh { color: #3677a9 } /* Literal.Number.Hex */.highlight .mi { color: #3677a9 } /* Literal.Number.Integer */.highlight .mo { color: #3677a9 } /* Literal.Number.Oct */.highlight .sb { color: #ed9d13 } /* Literal.String.Backtick */.highlight .sc { color: #ed9d13 } /* Literal.String.Char */.highlight .sd { color: #ed9d13 } /* Literal.String.Doc */.highlight .s2 { color: #ed9d13 } /* Literal.String.Double */.highlight .se { color: #ed9d13 } /* Literal.String.Escape */.highlight .sh { color: #ed9d13 } /* Literal.String.Heredoc */.highlight .si { color: #ed9d13 } /* Literal.String.Interpol */.highlight .sx { color: #ffa500 } /* Literal.String.Other */.highlight .sr { color: #ed9d13 } /* Literal.String.Regex */.highlight .s1 { color: #ed9d13 } /* Literal.String.Single */.highlight .ss { color: #ed9d13 } /* Literal.String.Symbol */.highlight .bp { color: #24909d } /* Name.Builtin.Pseudo */.highlight .vc { color: #40ffff } /* Name.Variable.Class */.highlight .vg { color: #40ffff } /* Name.Variable.Global */.highlight .vi { color: #40ffff } /* Name.Variable.Instance */.highlight .il { color: #3677a9 } /* Literal.Number.Integer.Long */
class BotBase(object, xmpp.Client):
bot_name = None
class InvalidCommandError(Exception):
pass
def __init__(self, *args, **kwargs):
self.bot_settings = BOT[self.bot_name]
self.__class__.__name__ = 'Client'
xmpp.Client.__init__(self, server=self.bot_settings['HOST'],
*args, **kwargs)
def connect(self):
xmpp.Client.connect(self, use_srv=self.bot_settings['SERVER'])
return self.auth(self.bot_settings['USERNAME'],
self.bot_settings['PASSWWORD'], self.bot_settings['XMPP_RESOURCE'])
def run(self):
self.UnregisterDisconnectHandler(self.DisconnectHandler)
self.RegisterDisconnectHandler(self.reconnectAndReauth)
self.RegisterHandler('message', self.messageHandler)
self.RegisterHandler('presence', self.presenceHandler)
self.sendInitPresence(0)
while self.Process(1): pass
self.disconnect()
def messageHandler(self, connection, message):
raise NotImplementedError
def presenceHandler(self, connection, presence):
raise NotImplementedError
Как видно, в коде используются настройки бота. Они выглядят вот так:
.highlight .hll { background-color: #404040 }.highlight { background: #202020; color: #d0d0d0 }.highlight .c { color: #999999; font-style: italic } /* Comment */.highlight .err { color: #a61717; background-color: #e3d2d2 } /* Error */.highlight .g { color: #d0d0d0 } /* Generic */.highlight .k { color: #6ab825; font-weight: bold } /* Keyword */.highlight .l { color: #d0d0d0 } /* Literal */.highlight .n { color: #d0d0d0 } /* Name */.highlight .o { color: #d0d0d0 } /* Operator */.highlight .x { color: #d0d0d0 } /* Other */.highlight .p { color: #d0d0d0 } /* Punctuation */.highlight .cm { color: #999999; font-style: italic } /* Comment.Multiline */.highlight .cp { color: #cd2828; font-weight: bold } /* Comment.Preproc */.highlight .c1 { color: #999999; font-style: italic } /* Comment.Single */.highlight .cs { color: #e50808; font-weight: bold; background-color: #520000 } /* Comment.Special */.highlight .gd { color: #d22323 } /* Generic.Deleted */.highlight .ge { color: #d0d0d0; font-style: italic } /* Generic.Emph */.highlight .gr { color: #d22323 } /* Generic.Error */.highlight .gh { color: #ffffff; font-weight: bold } /* Generic.Heading */.highlight .gi { color: #589819 } /* Generic.Inserted */.highlight .go { color: #cccccc } /* Generic.Output */.highlight .gp { color: #aaaaaa } /* Generic.Prompt */.highlight .gs { color: #d0d0d0; font-weight: bold } /* Generic.Strong */.highlight .gu { color: #ffffff; text-decoration: underline } /* Generic.Subheading */.highlight .gt { color: #d22323 } /* Generic.Traceback */.highlight .kc { color: #6ab825; font-weight: bold } /* Keyword.Constant */.highlight .kd { color: #6ab825; font-weight: bold } /* Keyword.Declaration */.highlight .kn { color: #6ab825; font-weight: bold } /* Keyword.Namespace */.highlight .kp { color: #6ab825 } /* Keyword.Pseudo */.highlight .kr { color: #6ab825; font-weight: bold } /* Keyword.Reserved */.highlight .kt { color: #6ab825; font-weight: bold } /* Keyword.Type */.highlight .ld { color: #d0d0d0 } /* Literal.Date */.highlight .m { color: #3677a9 } /* Literal.Number */.highlight .s { color: #ed9d13 } /* Literal.String */.highlight .na { color: #bbbbbb } /* Name.Attribute */.highlight .nb { color: #24909d } /* Name.Builtin */.highlight .nc { color: #447fcf; text-decoration: underline } /* Name.Class */.highlight .no { color: #40ffff } /* Name.Constant */.highlight .nd { color: #ffa500 } /* Name.Decorator */.highlight .ni { color: #d0d0d0 } /* Name.Entity */.highlight .ne { color: #bbbbbb } /* Name.Exception */.highlight .nf { color: #447fcf } /* Name.Function */.highlight .nl { color: #d0d0d0 } /* Name.Label */.highlight .nn { color: #447fcf; text-decoration: underline } /* Name.Namespace */.highlight .nx { color: #d0d0d0 } /* Name.Other */.highlight .py { color: #d0d0d0 } /* Name.Property */.highlight .nt { color: #6ab825; font-weight: bold } /* Name.Tag */.highlight .nv { color: #40ffff } /* Name.Variable */.highlight .ow { color: #6ab825; font-weight: bold } /* Operator.Word */.highlight .w { color: #666666 } /* Text.Whitespace */.highlight .mf { color: #3677a9 } /* Literal.Number.Float */.highlight .mh { color: #3677a9 } /* Literal.Number.Hex */.highlight .mi { color: #3677a9 } /* Literal.Number.Integer */.highlight .mo { color: #3677a9 } /* Literal.Number.Oct */.highlight .sb { color: #ed9d13 } /* Literal.String.Backtick */.highlight .sc { color: #ed9d13 } /* Literal.String.Char */.highlight .sd { color: #ed9d13 } /* Literal.String.Doc */.highlight .s2 { color: #ed9d13 } /* Literal.String.Double */.highlight .se { color: #ed9d13 } /* Literal.String.Escape */.highlight .sh { color: #ed9d13 } /* Literal.String.Heredoc */.highlight .si { color: #ed9d13 } /* Literal.String.Interpol */.highlight .sx { color: #ffa500 } /* Literal.String.Other */.highlight .sr { color: #ed9d13 } /* Literal.String.Regex */.highlight .s1 { color: #ed9d13 } /* Literal.String.Single */.highlight .ss { color: #ed9d13 } /* Literal.String.Symbol */.highlight .bp { color: #24909d } /* Name.Builtin.Pseudo */.highlight .vc { color: #40ffff } /* Name.Variable.Class */.highlight .vg { color: #40ffff } /* Name.Variable.Global */.highlight .vi { color: #40ffff } /* Name.Variable.Instance */.highlight .il { color: #3677a9 } /* Literal.Number.Integer.Long */
BOT['dummy'] = {
'HOST': 'serge.matveenko.ru',
'USERNAME': 'dummy',
'PASSWWORD': 'dummy5',
'XMPP_RESOURCE': 'mybot-0.1',
'USER_AGENT': 'MyBot/',
'SERVER': 'serge.matveenko.ru',
'JID': 'lig@serge.matveenko.ru',
}
Для любого нового бота теперь нужно создать класс-наследник BaseBot, в котором установить атрибут bot_name и реализовать методы messageHandler и presenceHandler. В словаре BOT должен существовать ключ соответствующий этому bot_name с настройками для этого бота.
Запуск бота осуществляется так:
.highlight .hll { background-color: #404040 }.highlight { background: #202020; color: #d0d0d0 }.highlight .c { color: #999999; font-style: italic } /* Comment */.highlight .err { color: #a61717; background-color: #e3d2d2 } /* Error */.highlight .g { color: #d0d0d0 } /* Generic */.highlight .k { color: #6ab825; font-weight: bold } /* Keyword */.highlight .l { color: #d0d0d0 } /* Literal */.highlight .n { color: #d0d0d0 } /* Name */.highlight .o { color: #d0d0d0 } /* Operator */.highlight .x { color: #d0d0d0 } /* Other */.highlight .p { color: #d0d0d0 } /* Punctuation */.highlight .cm { color: #999999; font-style: italic } /* Comment.Multiline */.highlight .cp { color: #cd2828; font-weight: bold } /* Comment.Preproc */.highlight .c1 { color: #999999; font-style: italic } /* Comment.Single */.highlight .cs { color: #e50808; font-weight: bold; background-color: #520000 } /* Comment.Special */.highlight .gd { color: #d22323 } /* Generic.Deleted */.highlight .ge { color: #d0d0d0; font-style: italic } /* Generic.Emph */.highlight .gr { color: #d22323 } /* Generic.Error */.highlight .gh { color: #ffffff; font-weight: bold } /* Generic.Heading */.highlight .gi { color: #589819 } /* Generic.Inserted */.highlight .go { color: #cccccc } /* Generic.Output */.highlight .gp { color: #aaaaaa } /* Generic.Prompt */.highlight .gs { color: #d0d0d0; font-weight: bold } /* Generic.Strong */.highlight .gu { color: #ffffff; text-decoration: underline } /* Generic.Subheading */.highlight .gt { color: #d22323 } /* Generic.Traceback */.highlight .kc { color: #6ab825; font-weight: bold } /* Keyword.Constant */.highlight .kd { color: #6ab825; font-weight: bold } /* Keyword.Declaration */.highlight .kn { color: #6ab825; font-weight: bold } /* Keyword.Namespace */.highlight .kp { color: #6ab825 } /* Keyword.Pseudo */.highlight .kr { color: #6ab825; font-weight: bold } /* Keyword.Reserved */.highlight .kt { color: #6ab825; font-weight: bold } /* Keyword.Type */.highlight .ld { color: #d0d0d0 } /* Literal.Date */.highlight .m { color: #3677a9 } /* Literal.Number */.highlight .s { color: #ed9d13 } /* Literal.String */.highlight .na { color: #bbbbbb } /* Name.Attribute */.highlight .nb { color: #24909d } /* Name.Builtin */.highlight .nc { color: #447fcf; text-decoration: underline } /* Name.Class */.highlight .no { color: #40ffff } /* Name.Constant */.highlight .nd { color: #ffa500 } /* Name.Decorator */.highlight .ni { color: #d0d0d0 } /* Name.Entity */.highlight .ne { color: #bbbbbb } /* Name.Exception */.highlight .nf { color: #447fcf } /* Name.Function */.highlight .nl { color: #d0d0d0 } /* Name.Label */.highlight .nn { color: #447fcf; text-decoration: underline } /* Name.Namespace */.highlight .nx { color: #d0d0d0 } /* Name.Other */.highlight .py { color: #d0d0d0 } /* Name.Property */.highlight .nt { color: #6ab825; font-weight: bold } /* Name.Tag */.highlight .nv { color: #40ffff } /* Name.Variable */.highlight .ow { color: #6ab825; font-weight: bold } /* Operator.Word */.highlight .w { color: #666666 } /* Text.Whitespace */.highlight .mf { color: #3677a9 } /* Literal.Number.Float */.highlight .mh { color: #3677a9 } /* Literal.Number.Hex */.highlight .mi { color: #3677a9 } /* Literal.Number.Integer */.highlight .mo { color: #3677a9 } /* Literal.Number.Oct */.highlight .sb { color: #ed9d13 } /* Literal.String.Backtick */.highlight .sc { color: #ed9d13 } /* Literal.String.Char */.highlight .sd { color: #ed9d13 } /* Literal.String.Doc */.highlight .s2 { color: #ed9d13 } /* Literal.String.Double */.highlight .se { color: #ed9d13 } /* Literal.String.Escape */.highlight .sh { color: #ed9d13 } /* Literal.String.Heredoc */.highlight .si { color: #ed9d13 } /* Literal.String.Interpol */.highlight .sx { color: #ffa500 } /* Literal.String.Other */.highlight .sr { color: #ed9d13 } /* Literal.String.Regex */.highlight .s1 { color: #ed9d13 } /* Literal.String.Single */.highlight .ss { color: #ed9d13 } /* Literal.String.Symbol */.highlight .bp { color: #24909d } /* Name.Builtin.Pseudo */.highlight .vc { color: #40ffff } /* Name.Variable.Class */.highlight .vg { color: #40ffff } /* Name.Variable.Global */.highlight .vi { color: #40ffff } /* Name.Variable.Instance */.highlight .il { color: #3677a9 } /* Literal.Number.Integer.Long */
bot = MyBot.initBot(debug=False)
if not bot.connect():
raise IOError('Can not auth with server.')
bot.run()
, где MyBot — класс вашего бота, а параметр debug говорит сам за себя.
That's all folks!
- 30 Мар 16:03
