usr bin env python coding utf-8 import xmpp import commands import tim

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import xmpp
import commands
import time
import re
ADMIN_NAMES = [u'ВАШ@jabber.ru'] # ни с кем другим бот не будет общаться
BOT_NAME = ''
BOT_PASS = ''
########################################################################
class Bot():
CHAR_LIMIT = 1000 # кол-во символов за сообщение (от сервера)
TIMEOUT = 1 # пауза между ними
VERBOSE = 1 # вывод помногословней :)
#----------------------------------------------------------------------
def __init__(self, bot_jid, bot_pass, admin):
self.admin = admin
self.log = []
''' системные команды из питона не могут сменить pwd
родительского процесса - путь приходится сохранять и
делать cd перед командой '''
self.CWD = '~'
''' cтрока с прелестями функционального программирования
сначала отбирает из пространства имен те имена, что начинаются
на "cmd_", потом этот префикс отрезается. Тип не проверяется,
поэтому не надо создавать переменных класса с таким префиксом :)
Зато написав функцию с таким префиксом можно выполнять ее с ботом,
ибо ВНИМАНИЕ! - бот ваших алиасов не знает! '''
self.own_commands = map(lambda x: x.replace('cmd_', ''),
filter(lambda x: x.startswith('cmd_') == 1,
dir(self.__class__)))
''' соединяется с сервером, подробнее - в документации по xmpppy,
она идет с хорошими примерами. Или смотреть здесь:
http://xmpppy-guide.berlios.de/nightly/ '''
jid=xmpp.protocol.JID(bot_jid)
conn = xmpp.Client(jid.getDomain(), debug=[])
conn.connect()
conn.auth(jid.getNode(), bot_pass, resource=jid.getResource())
conn.sendInitPresence()
conn.RegisterHandler('message', self.messageCB)
conn.RegisterHandler('presence', self.presenceCB)
''' что-то вроде коннекта события
"message" - входящее сообщение
"presence" - запрос статуса (?)
с функцией-обработчиком, СB = callback ;) '''
if self.VERBOSE: print 'Own_commands', self.own_commands
''' запуск бесконечного цикла до прерывания с клавиатуры '''
while 1:
try:
conn.Process(1)
''' типа: "Я готов к обработке!"'''
except KeyboardInterrupt: break
#----------------------------------------------------------------------
def presenceCB(self, conn, msg):
user = msg.getFrom()
''' если это запрос авторизации от админа '''
if msg.getType() == "subscribe" and user.getStripped() in self.admin:
conn.send(xmpp.protocol.Presence(to = user, typ = 'subscribed')) # авторизуем
conn.send(xmpp.Presence(to = user, typ = 'subscribe')) # отправляем втречный запрос
#----------------------------------------------------------------------
def messageCB(self, conn, msg):
text=msg.getBody()
user=msg.getFrom().getStripped()
# getStripped() - отправитель без ресурса jabber (типа '/qutim')
if isinstance(text, unicode):
text = text.encode('utf-8') # иначе на русском символе мы запнемся
''' проверяем админ ли нам написал '''
if user not in self.admin:
conn.send(xmpp.protocol.Message(msg.getFrom(), 'Идите лесом.'))
''' функция отправки сообщения:
conn.send(xmpp.protocol.Message( JID, MESSAGE ) '''
if self.VERBOSE: print 'Нас пытались взломать!'
else:
if self.VERBOSE: print '%s: %s' % (user, text)
args = re.split(r'\s+', text)
''' разбивка на слова. Регулярка здесь потому, что
bash автоматически объединяет пробелы, а бот в своих
командах - нет '''
cmd = args.pop(0)
''' теперь args содержит все слова сообщения,
кроме первого, но возможно, что пустой список '''
if cmd in self.own_commands:
exec('self.cmd_%s(conn, msg, args)' % cmd)
''' вообще-то exec() - команда с дурной славой,
ибо там может оказаться и "import os; os.system('rm -rf /*')"
но здесь мы, во-первых, проверили пользователя,
а во-вторых - ограничились набором own_commands '''
else:
self.status, self.output = commands.getstatusoutput('(cd %s && %s)'
% (self.CWD, text))
''' commands.getstatusoutput возвращает
код выполнения последней системной команды
Вообще же это обертка на os.popen().read() '''
while self.output <> '':
conn.send(xmpp.protocol.Message(msg.getFrom(), self.output[:self.CHAR_LIMIT]))
''' при попытке от`cat`ать большой файл и отослать его,
меня отсылал куда подальше сервер джаббера.
То же было при отсутствии задержки.
В общем, эксперементируйте с константами - это не пределы '''
self.output = self.output[self.CHAR_LIMIT:]
time.sleep(self.TIMEOUT)
### LOG ###
self.log.append('%s:%s "%s" %s' % (time.localtime().tm_hour,
time.localtime().tm_min,
text,
self.status))
'''
#------------------------------------------------------------------
# Так можно писать свои дополнительные комманды
#------------------------------------------------------------------
def cmd_ИМЯ-КОММАНДЫ(self, conn, msg, args):
# args - список аргументов-СТРОК (уже без имени комманды)
# conn.send(xmpp.protocol.Message(msg.getFrom(), MESSAGE)
# self.status = 0
# будьте так любезны рапортовать об успехе/неудаче :)
'''
#----------------------------------------------------------------------
def cmd_cd(self, conn, msg, args):
""" cd args['path'] """
if args:
self.CWD = args[0]
else:
self.CWD = '~'
conn.send(xmpp.protocol.Message(msg.getFrom(), 'pwd = %s' % commands.getoutput('(cd %s && pwd)' % self.CWD)))
self.status = 0
#----------------------------------------------------------------------
def cmd_h(self, conn, msg, args):
""" args['n'] последних комманд """
if not args: args = ['3']
if args[0].isdigit():
n = int(args[0])
conn.send(xmpp.protocol.Message(msg.getFrom(), '\n'.join(self.log[-n:])))
self.status = 0
else:
conn.send(xmpp.protocol.Message(msg.getFrom(), 'h [кол-во команд]'))
self.status = 1
if __name__ == "__main__":
bot = Bot(BOT_NAME, BOT_PASS, ADMIN_NAMES)