Ru-Board.club
← Вернуться в раздел «Прикладное программирование»

» Написание instant messaging Бота на AutoIt

Автор: vicbox777
Дата сообщения: 24.04.2009 13:52
Мне интересно...
Скрипт - Хорош! Я вот у себя, пытаюсь вникнуть в суть рабботы с jabber-оь на примере Qipa-инфиум. И был занят с изучением уснановки статусов. Их там где-то 12. Вычеслил, как ставяться статусы - Готов поболтать, Злой, депрессия, Дома, на работе и т.д. Код такой:

Код: '<presence xml:lang="en">' & _
    '<priority>30</priority>' & _
    '<show>chat</show>' & _
    '<x xmlns="qip:x:status" value="5"/><x xmlns="/x-status"></x>'& _
    '<title>Testovaya Versiya</title>' & _
    '<status>Test status text 2</status>' & _
    '</presence>'
Автор: sproxy
Дата сообщения: 24.04.2009 15:20
vicbox777 14:52 24-04-2009
Цитата:
В сети, не в сети, готов поболтать.

по идее там целый список, все что показывается в возможных статусах на jabber/icq - то должно работать.

а '<x xmlns="qip:x:status" value="5"/><x xmlns="/x-status"></x>'& _ - это же икс-статус (та фигня где телефон, шарики, сердечки и т.д.).
его наличие должно зависит от возможности сервера, к нему же, так же, относиться текст x-статус сообщения...
уммм - верно )

все прибамбасы статусов, картинок - чего угодно - это все от сервера - если сервер поддерживает - то значит можно использовать ))


Цитата:
после этого в переменной $sMessageUTF8 - нормальный текст.

good )


Цитата:
Opt("GUIResizeMode", $GUI_DOCKAUTO)

если про мой скрипт - то там растяжка/положение по разному для разных элементов.

а с
Цитата:
Opt("GUIResizeMode", $GUI_DOCKAUTO)
дико выходит - уменьшение/увеличение размера кнопки - имхо, перебор )))
в моем скрипте - весь GUI только для тестирования, не задовался целью из него, что то делать )
Автор: ynbIpb
Дата сообщения: 24.04.2009 17:59
sproxy, Классно, но вот на джеббер.орг еррор в самом конце...

Код:

>>> RECV:
Jid: ynbIpb@jabber.org
<iq type="error" id="Auth_2-1">
<query xmlns="jabber:iq:auth">
<username>ynbIpb</username>
</query>
<error code="406" type="modify">
<not-acceptable xmlns="urn:ietf:params:xml:ns:xmpp-stanzas"/>
<text xmlns="urn:ietf:params:xml:ns:xmpp-stanzas">Не указан ресурс</text>
</error>
</iq>

Автор: vicbox777
Дата сообщения: 24.04.2009 18:43
Удалось найти решение, как отправить текст (из скрипта jabbera) на Русском языке. Вот так:
Код: $typed = GUICtrlRead($hMainWin_Message_Input) ;читаем текст из поля ввода
$sMessageBinaryUTF8=StringToBinary($typed,4)
$sMessageANSI=
BinaryToString ($sMessageBinaryUTF8 , 1 )
$typed=$sMessageANSI
Автор: sproxy
Дата сообщения: 24.04.2009 21:52
ynbIpb 18:59 24-04-2009
Цитата:
Классно, но вот на джеббер.орг еррор в самом конце...

не спишите так )) - все только начинается.
там ошибка в аутентификации, причем та, которая возникает, если выслать запрос, но не указать все необходимые данные.
примерно, там не хватает:

Код: [no]<password>тут должены быть пароль</password>
<resource>AU3J</resource>[/no]
Автор: XpycTMD
Дата сообщения: 26.04.2009 14:38
sproxy 04:20 24-04-2009
Цитата:
кому интересно - то, что уже готово

Если в твоей UDF при добавлении JID оставить поле Port пустым, то появляется ошибка: Enter correct Password.
А если заполнить (например 5222), а потом сразу выбрать Edit JID по поле Password принимает значение поля Port.
Вот что пишется в [more=Console: XML]<<< SEND: Connection to server
Jid: Mapagep@jabber.org, port: 5222
Start TCP service: Successful
Connection to server: 208.68.163.220, port: 5222, please wait...
Result: Successful, socket Id: 1504

<<< SEND: Authorization
Jid: Mapagep@jabber.org, lang: ru, resource: AU3J
<?xml version="1.0"?>
<stream:stream to="jabber.org" xmlns="jabber:client" xmlns:stream="http://etherx.jabber.org/streams" xml:lang="ru">
<iq type="get" id="Auth_1">
<query xmlns="jabber:iq:auth">
<username>Mapagep</username>
</query>
</iq>

>>> RECV:
Jid: Mapagep@jabber.org
<?xml version="1.0"?>
<stream:stream xmlns="jabber:client" xmlns:stream="http://etherx.jabber.org/streams" id="2243685055" from="jabber.org" xml:lang="en">
<iq type="result" id="Auth_1">
<query xmlns="jabber:iq:auth">
<username>Mapagep</username>
<password/>
<digest/>
<resource/>
</query>
</iq>

<<< SEND: Authorization
Jid: Mapagep@jabber.org, lang: ru, resource: AU3J
<iq type="set" id="Auth_2-1">
<query xmlns="jabber:iq:auth">
<username>Mapagep</username>
<password>5222</password>
<resource>AU3J</resource>
</query>
</iq>

>>> RECV:
Jid: Mapagep@jabber.org
<iq type="error" id="Auth_2-1">
<query xmlns="jabber:iq:auth">
<username>Mapagep</username>
<password>5222</password>
<resource>AU3J</resource>
</query>
<error code="401" type="auth">
<not-authorized xmlns="urn:ietf:params:xml:ns:xmpp-stanzas"/>
</error>
</iq>

<<< SEND: Disconnect from server
Jid: Mapagep@jabber.org
Result: Successful[/more]

Косяк скорей всего потому что не правильно отрабатывает вот этот блок
Код: 420 ;~ Check Password
421 Local $sPass = StringStripWS(GUICtrlRead($hJidWin_Pass), 8)
422 If $sPass == '' Then
423 GUICtrlSetData($hJidWin_Pass, '')
424 GUICtrlSetState($hJidWin_Pass, $GUI_FOCUS)
425 _ToolTip(3, 'Enter correct Password', $aJidWin_Pos[0]+20, $aJidWin_Pos[1]+60+45, '', Default, 1)
426 Return
427 EndIf
428
429
;~ Check Port
430 Local $iPort = StringStripWS(GUICtrlRead($hJidWin_Pass), 8)
431 If $iPort == '' OR $iPort == 0 OR NOT StringIsDigit($iPort) Then
432 GUICtrlSetData($hJidWin_Port, '')
433 GUICtrlSetState($hJidWin_Port, $GUI_FOCUS)
434 _ToolTip(3, 'Enter correct Port', $aJidWin_Pos[0]+20, $aJidWin_Pos[1]+60+45*2, '', Default, 1)
435 Return
436 EndIf
Автор: ynbIpb
Дата сообщения: 26.04.2009 17:15
точно вот и у меня ошибка из-за этого была. в поле пароля был порт.
Автор: vicbox777
Дата сообщения: 26.04.2009 18:38
Если добавить новый Jid, а после этого нажать Connect и после удачного конекта, нажать Exit либо закрыть окно,- у меня скрипт надолго зависает... Я просто добавил в функцию _Pro_Exit() первой строкой вызов функции _MainWin_Disconnect(), а дальше все как было, и скрипт выходит быстро и без зависания.
Автор: sproxy
Дата сообщения: 27.04.2009 08:35
XpycTMD
класс ) ну да, - издержки поризводства (<password>5222</password>)

vicbox777
все из за TCPSend/Recv.............вы решили мою мега проблему, дело в том, что есть OnAutoItExit (он для UDF) и в нем как раз и происходит отключение всех подключений перед выходом. конечно до этого это было в _Pro_Exit, да и варьировал по разному - не помогало.....а этот вариант - походу помогает онитересно как будет, если подключить сразу несколько Jid и во время их подключения выйти..........сначало не было call-back функций, просто по таймеру проверялось ни пришло ли чего нового, и вот с этим таймером все очень весело висло. именно это и послужило появлению call back.....с ними помойму лучше.
Автор: vicbox777
Дата сообщения: 27.04.2009 12:36

Цитата:
итересно как будет, если подключить сразу несколько Jid и во время их подключения выйти...

Пробовал на 3-х Jid-ах. Выбрал 1 - нажал Connect, потом сразу 2-Connect и 3-Connect, потом нажал - Exit, - вышел без зависания.(Пробовал несколько раз.)
Автор: sproxy
Дата сообщения: 27.04.2009 17:35
vicbox777
, веселая мистика - есть над чем пофантазировать )))
Автор: vicbox777
Дата сообщения: 27.04.2009 21:32
Ех, если полностью удалил все Jid-ы. Потом добавил один, и второй, запустил по-очереди, и сразу - Выход, то вновь зависает...
Если выключить и опять запустить, уже те 2 Jida что были, по очереди, и потом Exit, вновь не зависает.

Пробовал взять один jid и поредактировать через Edit Jid, сначала половину имени удалил и сохранил, потом вновь Нажал Edit Jid -дописал и сохранил. Запустил, -вышел нормально. Проблема кроется именно в Add Jid. Ибо только если добавлять новый Jid, то потом после запуска--> выхода, зависает... Выходит какая то функция внутри Add Jid не "отключается" и потом тянетскрипт...хотя вроде таких нету...
Но если вконце функции _JidWin_Close() добавить MsgBox(0,"","уже",1), то что не делать, и не добавлять, выход из программы без зависания.
P.S. Вместо MsgBox-a можно добавить ToolTip("уже"), тоже -Зависания не наблюдается... Вот это мистика!
Автор: ynbIpb
Дата сообщения: 07.05.2009 20:03
Всплыл тут на оф форуме ещё один протокол: YMSG Protocol Support (Yahoo-Oo-oO!)
Автор: vicbox777
Дата сообщения: 22.05.2009 21:17
Что то не кто не делиться своими разработками... Пока sproxy доделывает jabber.udf я тут покумекал, и сделал icqbota. Суть такая, есть посредник, написанный на Delphi (Исходники и описания прилагаются, и если уже возникнет такое желание, то разобраться думаю сможет каждый, ибо и я с дельфи знаком около недели , и познакомился специально для этой цели, но думаю с задачей справился, благо примеров в инете хватает..., хотя од себя добавляю, что код не имеет каких то скрытых там секретов - мне это не нужно), и этот посредник - icqbot только передает другой программе написанной на autoit комманды от удаленного админа, а от него в свою очередь пересылает комманды, если таковые будут, удаленному админу. Все настройки хранятся в ini файле, в текстовом файле в архиве, есть подробное описание работы этого дуэта, все что нужно, это добавить команды, которые нужны вам, уже есть встроенные комманды, для начала, эти комманды встроенные в icqbot, при желании сможете добавть какие то еще функции сюда, гугл вам в помощь так как и послужил мне , хотя по моему все что нужно от посредника icqbot делает, и комманды лучше сразу добавлять в Autoit-программу, для которой собственно я и складал из чужих советов этого посредника бота . Вот список встроенных комманд:
. - просто проверка состояния подключения клиента
.ShowDesk - показать иконки рабочего стола
.HideDesk - спрятать иконки рабочего стола
.ShowStart - показать пуск
.Hidestart - спрятать пуск
.ShowTaskBar - показать таскбар
.HideTaskBar - спрятать таскбар
.ShowClock - показать часы
.HideClock - спрятать часы
.TimePC - время установки системы
.TimePowerPC - время работы компьютера
.Command - список комманд
.Cdo - открыть привод компакт дисков
.Сdc - закрыть привод компакт дисков
.Info - информация о компьютере
.Off - выключить компьютер
.Reboot - перезагрузка
.DriveList - список дисков
.Getclb - буфер обмена (текст)
.Setclb: - занести в буфер обмена (текст)
.Close - закрыть клиент(будут закрыты обе проги - icqbot и AutReceiver)
.GetProc - получить список процессов
.OpenUrl: - открыть ссылку в стандарном браузере
.KillProc: - убить процесс
.MesWarn:Текст,Заголовок - вывод на экран компа сообщения об ошибке
Вот ссылка на закачку: Загрузить (размер 869 Кб)
Код самого Receiver-a, Autoitскрипта вот:
[more]
Код: #NoTrayIcon
#include <WindowsConstants.au3>
#include <EditConstants.au3>
#include <GUIConstantsEx.au3>
#include <Misc.au3>

;Предотвращение запуска 2 копий проги
if _Singleton(@ScriptName,1) = 0 Then
Exit
Endif

Opt('WinTitleMatchMode', 3)
Global $Send_Button, $sMsg_To_IcqWindow,$hWnd_IcqWindow
;global const $WM_COPYDATA = 0x004A

; $sMsg-это полученное сообщение от ICQBota(сообщение передается через wm_copydata). А $Flag -если $Flag = 1 то значит сообщение прибыло
Global $sMsg, $Flag = 0
;нужно знать заголовок окна для передачи сообщения
global $WinICQTitle =IniRead ( "Config.ini", "ICQ", "WinICQTitle:", "клиент 007" )
;нужно указать заголовок окна для получения сообщения(будет из ICQBota отсылаться сообщения именно окну с таким заголовком)
global $Title=IniRead ( "Config.ini", "Receiver", "WinAutTitle:", "#Receiver" )
;Если $VisibleAutWindow будет 1 (true) то это окно (AutoitReceiver) при запуске будет видимым, нужно для отладки, а если будет 0 (false) то окно будет невидимое, и значится только в процессах.
Global $VisibleAutWindow=IniRead ( "Config.ini", "Receiver", "VisibleAutWindow:", "0" )
;взятая настройка из ini - отсылать сообщение на AdminUin, или нет.
Global $Mess_OnRecvMessage=IniRead ( "Config.ini", "General", "Mess_OnRecvMessage:", "0" )
;взятая настройка из ini - если true(1) то будет производится поиск окна ICQBota и если его нету, то будет запускаться ICQBot
Global $ReStart_ICQandReceiver=IniRead ( "Config.ini", "General", "ReStart_ICQandReceiver:", "0" )
;взятая настройка из ini - имя ICQBot(нужно для запуска программы из этого скрипта)
Global $NameICQProg=IniRead ( "Config.ini", "ICQ", "NameICQProg:", "ICQBot" )


#Region начало создания gui
$hGUI=GUICreate($Title, 421, 182,(@DesktopWidth/2)-(421/2),(@DesktopHeight/2)-(182/2-182))
GUICtrlCreateLabel(" Принятые с IcqBot-a сообщения:", 0, 0, 173, 17)
$Edit_NewMessage=
GUICtrlCreateEdit("", 0, 24, 417, 73, BitOR($ES_AUTOVSCROLL, $WS_VSCROLL, $ES_WANTRETURN))
GUICtrlCreateLabel(" Создание для IcqBot-a сообщения:", 0, 104, 183, 17)
$Edit_SendNewMessage=
GUICtrlCreateEdit("", 0, 124, 361, 53, BitOR($ES_AUTOVSCROLL, $WS_VSCROLL, $ES_WANTRETURN))
$Send_Button =
GUICtrlCreateButton("Send", 368, 124, 49, 53)
;Если True(в ini - 1) то окно видимо (для отладки)
If $VisibleAutWindow=1 then GUISetState(@SW_SHOW)
#EndRegion создания gui
;
;
GUIRegisterMsg($WM_COPYDATA, '_WM_COPYDATA')
;Если True то запускаем Adlib
If $ReStart_ICQandReceiver=1 then AdlibEnable( "_GetwinExistsICQBot",1000) ; create timer
While 1
$nMsg =
GUIGetMsg()
Switch $nMsg
Case $GUI_EVENT_CLOSE
Exit
Case
$Send_Button
$sMsg_To_IcqWindow
=
GUICtrlRead($Edit_SendNewMessage)
$hWnd_IcqWindow = WinGetHandle($WinICQTitle)
if (not @error) and ($sMsg_To_IcqWindow > '') then
_SendData($hWnd_IcqWindow, $sMsg_To_IcqWindow)
Guictrlsetdata($Edit_SendNewMessage,"")
endif
EndSwitch
if $Flag then
$Flag = 0
_RecvMessage()
endif
WEnd

Func
_GetwinExistsICQBot()
if winExists($WinICQTitle)<>1 then Run ($NameICQProg)
EndFunc
;_GetwinExistsICQBot()

func _SendData($hWnd, $sData)
local $tCOPYDATA, $tMsg
$tMsg
=
DllStructCreate('char[' & StringLen($sData) + 1 & ']')
DllStructSetData($tMsg, 1, $sData)
$tCOPYDATA =
DllStructCreate('dword;dword;ptr')
DllStructSetData($tCOPYDATA, 2, StringLen($sData) + 1)
DllStructSetData($tCOPYDATA, 3, DllStructGetPtr($tMsg))
$Ret =
DllCall('user32.dll', 'lparam', 'SendMessage', 'hwnd', $hWnd, 'int', $WM_COPYDATA, 'wparam', 0, 'lparam', DllStructGetPtr($tCOPYDATA))
if (@error) or ($Ret[0] = -1) then
return
0
endif
return
1
endfunc
; _SendData


func _WM_COPYDATA($hWnd, $msgID, $wParam, $lParam)
local $tCOPYDATA =
DllStructCreate('dword;dword;ptr', $lParam)
local $tMsg =
DllStructCreate('char[' & DllStructGetData($tCOPYDATA, 2) & ']', DllStructGetData($tCOPYDATA, 3))
$sMsg =
DllStructGetData($tMsg, 1)
; For Receiver
$Flag = 1
return 0
endfunc
; _WM_COPYDATA

Func _RecvMessage()
$hWnd_IcqWindow = WinGetHandle($WinICQTitle)
GUICtrlSetData($Edit_NewMessage,$sMsg)
;если в ini-файле отмечено, чтоб отправлять сообщение при удачном получении, то дальше как раз это и будет делаться
if $Mess_OnRecvMessage=1 then
if
$hWnd_IcqWindow <>"" then
_SendData($hWnd_IcqWindow, 'Сообщение получено в AutoitReceiver, Boss!')
endif
;дальше как раз будут обрабатываться принятые сообщения
Switch $sMsg
Case 'close'
;это пусть будет, ибо нужно для удаленного выключения обоих программ , притом слово closе лучше пусть будет таким, ибо идет привязка к нему с icqbot-а
AdlibDisable
()
If WinExists($WinICQTitle,"")=1 then WinClose($WinICQTitle,"")
Exit
;---------------------------------------------------------------------------------
Case 'a1'
MsgBox(262208,"Приятное сообщение!","Поздравляем, все работает должным образом!",5)
Case 'a2'
;команда пишеться тута
Case 'a3'
;команда пишеться тута
Case 'a4'
;команда пишеться тута
Case 'a5'
;команда пишеться тута
Case 'a6'
;команда пишеться тута
Case 'a7'
;команда пишеться тута
Case 'a8'
;команда пишеться тута
Case 'a9'
EndSwitch
EndFunc ;_RecvMessage()

Автор: sproxy
Дата сообщения: 22.05.2009 21:41
vicbox777 22:17 22-05-2009
Цитата:
Пока sproxy доделывает

нифига он не доделывает.....он в большой жизненой проблеме.....вернусь к разработкам через неделю......
Автор: timsky
Дата сообщения: 23.05.2009 16:26
sproxy
Удачи в решении проблемы!
Автор: ynbIpb
Дата сообщения: 23.05.2009 17:03

Цитата:
Что то не кто не делиться своими разработками

Да... что-то все приостановились в ожидании джаббера.
Ты vicbox777 молодец, что не забросил. Обязательно гляну твои наработки.
sproxy, надеюсь всё наладится, ждём, но не торопим.

и вопрос в тему: вот хочу функцию чтоб возвращала не только список процессов но и абсолютные пути к ним, как бы это сделать?
сейчас выглядит примерно так:

Код: $otvet=""
$Process = ProcessList()
for $i = 1 to $Process[0][0]
$otvet&= $Process[$i][0]&":"&$Process[$i][1]&@CRLF
next
MsgBox(0,"",$otvet)
Автор: vicbox777
Дата сообщения: 23.05.2009 20:26

Цитата:
чтоб возвращала не только список процессов но и абсолютные пути к ним
Вот можно так, это функция CreatoR-a, я только переделал, чтоб можно было показать в сообщении, ибо изначально там был двухмерный массив, который можно токо отобразить как - ArrayDisplay...Но я думаю, что нам же нужно именно чтоб в сообщении...
Код: #include <Array.au3>
$Processlist=
_ProcessListEx()
If $Processlist==-1 then
MsgBox(0,"Внимание","Ошибка при получении списка процессов")
else
MsgBox(0,"результат",$Processlist)
Endif

;=====================================================================
Func _ProcessListEx($sResourceName="", $sInResString="", $iWholeWord=1)
Local $aProcList =
ProcessList()
Local $hKernel32_Dll =
DllOpen('Kernel32.dll'), $hPsapi_Dll = DllOpen('Psapi.dll')
Local $aOpenProc, $aProcPath, $sFileVersion, $aRet_List[1][1]

If $hKernel32_Dll = -1 Then Return -1

If $hPsapi_Dll = -1 Then $hPsapi_Dll =
DllOpen(@SystemDir & '\Psapi.dll')
If $hPsapi_Dll = -1 Then $hPsapi_Dll =
DllOpen(@WindowsDir & '\Psapi.dll')
If $hPsapi_Dll = -1 Then Return -1

Local $vStruct =
DllStructCreate('int[1024]')
Local $pStructPtr =
DllStructGetPtr($vStruct)
Local $iStructSize =
DllStructGetSize($vStruct)

For $i = 1 To UBound($aProcList)-1
$aOpenProc =
DllCall($hKernel32_Dll, 'hwnd', 'OpenProcess', _
'int', BitOR(0x0400, 0x0010), 'int', 0, 'int', $aProcList[$i][1])

If Not IsArray($aOpenProc) Or Not $aOpenProc[0] Then ContinueLoop

DllCall($hPsapi_Dll, 'int', 'EnumProcessModules', _
'hwnd', $aOpenProc[0], _
'ptr', $pStructPtr, _
'int', $iStructSize, _
'int*', 0)

$aProcPath =
DllCall($hPsapi_Dll, 'int', 'GetModuleFileNameEx', _
'hwnd', $aOpenProc[0], _
'int',
DllStructGetData($vStruct, 1), _
'str', '', _
'int', 2048)

DllCall($hKernel32_Dll, 'int', 'CloseHandle', 'int', $aOpenProc[0])

If Not IsArray($aProcPath) Or StringLen($aProcPath[3]) = 0 Then ContinueLoop

$sFileVersion = FileGetVersion($aProcPath[3], $sResourceName)

If $sResourceName = "" Or $sFileVersion = $sInResString Or _
(
$iWholeWord = 0 And StringInStr($sFileVersion, $sInResString)) Then

$aRet_List[0][0] += 1
ReDim $aRet_List[$aRet_List[0][0]+1][3]
$aRet_List[$aRet_List[0][0]][0] = $aProcList[$i][0]
;Process Name
$aRet_List[$aRet_List[0][0]][1] = $aProcList[$i][1] ;PID (Process ID)
$aRet_List[$aRet_List[0][0]][2] = $aProcPath[3] ;Process File Path
EndIf
Next

DllClose($hKernel32_Dll)
DllClose($hPsapi_Dll)

If $aRet_List[0][0] < 1 Then Return -1



Local $avArray[1],$k,$PList
for $k+=1 to $aRet_List[0][0]
_ArrayAdd($avArray, $aRet_List[$k][0]&":"&$aRet_List[$k][1]&" ("&$aRet_List[$k][2]&")")
Next

$PList=
_ArrayToString($avArray, @CRLF, 1,$aRet_List[0][0])
Return $PList
EndFunc
Автор: ynbIpb
Дата сообщения: 23.05.2009 21:15
Да действительно эта сложнее..
Скачал твоего бота. Ну чтож Супер мне понравилось! работает как часы (не то что TOC протокол)
Можно по тихоньку клепать команды, пока нет джаббера.
Но! вроде как пришли к выводу, что команды, которые требуют значительно времени на выполнение (копирование файлов например) следует выносить в отдельные модули чтоб не замораживать работу скрипта. sproxy обещал показать хитрую API, чтоб передавать ответ из модуля основному скрипту, вобщем нужно наладить взаимодействие.
з.ы.
Видимо компонет Царя часто используют в зловредных целях, что мой антивирь (NOD32 2.7) параноидально орёт на скомпиленый EXE. Немного неудобно, но ничего.
Автор: vicbox777
Дата сообщения: 23.05.2009 22:46

Цитата:
sproxy обещал показать хитрую API, чтоб передавать ответ из модуля основному скрипту

Это я как раз и реализовал у себя в боте для "беседы" между двумя прогами, можеш это в коде Receiver.au3 увидеть...
Попытался отправить длинное сообщение, и обнаружил, что, например qiq инфиум если сообщение длинное, разбивает при отправке сообщение на несколько, причем длина 1 сообщения примерно 2 тысячи знаков, и адресату сообщение приходит кусками...хотя пишут, что можно отправлять до 7 тысяч знаков в одном сообщении. Да, непонятно это мне. Только сейчас узнал про такую проблемму. Попробовал в боте отправить длинное сообщение (около 3 тысячи знаков),-не отправляется. Около 2 тысяч отправил - пришло нормально.
Думаю если обратное сообщение будет слишком длинным, то лучще будет разбивать такое сообщение из автоит скрипта (так будет попроще и потом отсылать один за другим),если оно большое на несколько...знать бы на сколько именно знаков, мне кажеться гдето между 1800 и 2000. Узнал уже: 2500!. A разбивать можно примерно так:[more]
Код: $Text="Какой то очень длинный текст"

Local $Lenstring,$begin,$end, $Text1
if StringLen ( $Text ) >2500 then
$Lenstring=StringLen ( $Text )
$begin=1
$end=2500
while 1
$Text1=StringMid ( $Text, $begin, $end )
MsgBox(0,"Сообщение по кускам",$Text1)
;вместо сообщения - отправка по icq
$begin=$end+1
if ($Lenstring-($end+2500))<=0 then
$end=$end+($Lenstring-$end)
$Text1=StringMid ($Text, $begin, $end )
MsgBox(0,"Последний кусок",$Text1)
;вместо сообщения - отправка по icq
ExitLoop
else
$end=$end+2500
endif
wend
elseif
StringLen ($Text)<=2500 then
MsgBox(0,"Целое сообщение",$Text)
;вместо сообщения - отправка по icq
Endif

Автор: ynbIpb
Дата сообщения: 26.05.2009 21:27
Поковырявшись, пришёл к выводу, что метод обработки команд в рессивере не годится.
Switch $sMsg
Case 'a1'
;команда пишеться тута
Case 'a2'
;команда пишеться тута
EndSwitch
Ибо есть команды, которые передают параметры, а так же не будет срабатывать если команда находится в середине сообщения.
Например:
;получение списка файлов\папок указанной директории
;команда для вызова этой функции: !dir путь_к_каталогу (Пример: !dir C:\ или !dir C:\Program Files)

Как тут быть? не хочется уходить от этого способа, очень удобный.
пока сделал что-то типа этого:

Код: $result01 = StringInStr ($sMsg, "!process")
if Not $result01 = 0 then
$bot_reply = _Process_bot()
_SendData($hWnd_IcqWindow, $bot_reply)
endif
Автор: vicbox777
Дата сообщения: 27.05.2009 23:46

Цитата:
Как тут быть? не хочется уходить от этого способа, очень удобный.

Вот и мне на ифки (if...then...endif) тоже не хочется переходить, поэтому, почему бы не сделать так?:
Код: $sMsg="!dir C:\"

Switch $sMsg
Case 'a1'
;команда пишеться тута

Case "!dir"&stringregexpreplace($sMsg,"!dir(.*)","\1")
MsgBox(0,"",
_FileList_bot($sMsg))
;команда пишеться тута

EndSwitch

;-------------------------------Функции------------------------------------
#Include
<File.au3>
;~~~~~~~~~~~~~~
; функция _FileList_bot получает список файлов\папок указанной директории и отправляет хозяину
; команда для вызова этой функции: !dir путь_к_каталогу (Пример: !dir C:\ или !dir C:\Program Files)
;$sMsg - весь текст сообщения;
;~~~~~~~~~~~~~~
Func _FileList_bot($sMsg)
Local $sPath, $FileList, $otvet=''
$sPath=
StringRegExpReplace($sMsg,".*dir(?:\s)*(.*)","\1")
IF Not $sPath = 0 then
$FileList=
_FileListToArray($sPath)
If @Error=1 Then Return "Path Not Found."
If @Error=4 Then Return "No files\folders found in dir"
If IsArray($FileList) Then
for
$i = 1 to $FileList[0]
$otvet&= $FileList[$i]&@CRLF
next
endIf
Return
$otvet
Else
Return
"не указан путь."
EndIF
EndFunc
Автор: ynbIpb
Дата сообщения: 28.05.2009 07:30
Отличная идея!
теперь даже не важно есть пробел или нет после !dir
По поводу посредника: Не мог бы ты перекомпилировать Icqbot.exe выкинув из него все встроенные боткоманды, пусть он будет только посредником. А все функци будем писать на втором модуле. И ещё можно ли сделать чтоб фраза отстукивания хозяину "Я в Сети, Boss!" бралась из ini файла.
Автор: vicbox777
Дата сообщения: 29.05.2009 00:11

Цитата:
перекомпилировать Icqbot.exe выкинув из него все встроенные боткоманды, пусть он будет только посредником.

Раз надо - сделал.
Вот ссылка на программу (исходники прилагаются)Скачать обновленную версию Autoit-Delphi-IcqBot (850 Kb). Список изменений: Выброшены все встроенные в icqbot.exe команды, кроме единcтсенной(команду .close, которая закрывает обе проги, все таки оставил). И еще, раз я уже взялся за переделку, то, в связи с тем, что мной было замечено, что icqbot отказывается пересылать текст, где знаков больше 2500 тысяч, я доделал, чтобы если сообщение очень большое (больше 2500 знаков), то такие сообщения будут автоматом разбиваться icqboto-м,и по 2500 тыс.знаков отсылаться одна за другой; Таким образом можна переслать даже очень большое сообщение (правда больше 10 000 знаков не пробовал) и притом эти сообщения приходят почти как одно, только отделенные в контакт листе ником и датой... Еще по просьбе коллеги, было добавлено в ini файл опцию, где можно указать текст, которым бот будет отвечать, если нужно, своему хозяину при коннекте, получении сообщения.(В связи с этим скрипт-код Receivera тоже изменил, так что имейте в виду)

P.S. Когда были убраны все встроенные в icqbot.exe команды, то на этом сайте по он-лайн проверке файлов на вирусы: http://www.virustotal.com/ru/ , в результате проверки файла icqbot.exe 40-ми антивирусами, вирусов не обнаружено!
Автор: ynbIpb
Дата сообщения: 29.05.2009 07:23


Цитата:
сообщения будут автоматом разбиваться icqboto-м,и по 2500 тыс.знаков

Это хорошее решение, чтоб не напрягать Autoit.

Цитата:
добавлено в ini файл опцию

За это спасибо.

Цитата:
вирусов не обнаружено!

Как раз по этой причине я и просил выкинуть команды, так как по всей видимости эвристический анализатор найдя в EXE'шнике функции сбора иформации о системе и тд, выдавал тревогу.

---------------
Уже обживаю потихоньку бота, выделил под него шестизнак.
Функции вынес в отдельный файл Bot_functions.au3, в качестве списка процессов всётаки выбрал этот вариант:
[more=_Process_bot]

Код: ;~~~~~~~~~~~~~~
; функция _Process_bot получает список запущеных процессов и отправляет хозяину
; команда для вызова этой функции: !proclist
;~~~~~~~~~~~~~~

Func _Process_bot()
Local $otvet = ""
Local $Process=""
_ComputerGetProcesses($Process)
For $i = 1 To $Process[0][0]
If $Process[$i][2] = "" Then
$path_proc = $Process[$i][0]
Else
$path_proc = $Process[$i][2]
EndIf
$otvet &= $path_proc & ":" & $Process[$i][1] & @CRLF
Next
Return
$otvet ;возвращаем сформированный список процессов
EndFunc
;----------------
Func _ComputerGetProcesses(ByRef $aProcessInfo)
Local $colItems, $objWMIService, $objItem
Local $cI_Compname = @ComputerName
Local $wbemFlagReturnImmediately = 0x10
Local $wbemFlagForwardOnly = 0x20
Dim $aProcessInfo[1][3], $i = 1
$objWMIService = ObjGet("winmgmts:\\" & $cI_Compname & "\root\CIMV2")
$colItems = $objWMIService.ExecQuery("SELECT * FROM Win32_Process", "WQL", $wbemFlagReturnImmediately + $wbemFlagForwardOnly)
If IsObj($colItems) Then
For
$objItem In $colItems
ReDim $aProcessInfo[UBound($aProcessInfo) + 1][3]
$aProcessInfo[$i][0] = $objItem.Name
$aProcessInfo[$i][1] = $objItem.ProcessId
$aProcessInfo[$i][2] = $objItem.ExecutablePath
$i += 1
Next
$aProcessInfo[0][0] = UBound($aProcessInfo) - 1
If $aProcessInfo[0][0] < 1 Then
SetError(1, 1, 0)
EndIf
Else

SetError(1, 2, 0)
EndIf
EndFunc
;_ComputerGetProcesses
Автор: vicbox777
Дата сообщения: 30.05.2009 17:15
ynbIpb 07:23 29-05-2009
Цитата:
как всётаки это работает stringregexpreplace($sMsg,"!dir(.*)","\1")

Сдесь .* - это любой текст (точка - это любой символ, а звездочка указывает на то что эти символы могут, как присуствовать, так и отсуствовать), который идет после слова !dir, а так как этот "любой текс" заключен в кавычки, то это называется 1 групировка. Так вот назначение как раз этой функции в этом случае: Case "!dir"&stringregexpreplace($sMsg,"!dir(.*)","\1"),- это вернуть весь текст который идет после слова !dir, а 1 групировка именно производит захват этого текста, а параметр "\1" как раз возвращает только текст этой групировки. "\1", еще можно было бы записать как "$1".

В этом случае: $sPath=StringRegExpReplace($sMsg,".*dir(?:\s)*(.*)","\1"), тоже самое, за исключением того что это - (?:\s)* означает, любое количество пробелов, которые могут, как присуствовать, так и нет, а это ?: означает, не захватывать эту групировку, но можно было бы написать и так: $sPath=StringRegExpReplace($sMsg,".*dir(\s)*(.*)","\2")...


Цитата:
Я тут подумал может в функциях работы с файлами передавать пути в кавычках?
Ведь например в оперции копирования, нужно будет передать 2 пути...
например: !copy "откуда" "куда"

В кавычках, так в кавычках, я не против. А насчет параметров, которые нужно будет извне передавать в скрипт, а потом правильно их обработать, то проще будет так:
Код: $sTekst='!Copy "1параметр" "2параметр" "и т.д. параметр"'
$arrayOFparametrs=
StringRegExp($sTekst, '(?:"(.*?)")+', 3)
If (Not @Error) Then
for
$i = 0 to UBound($arrayOFparametrs) - 1
msgbox
(0, "$arrayOFparametrs["& $i&"]", $arrayOFparametrs[$i])
Next
EndIf
Автор: ynbIpb
Дата сообщения: 30.05.2009 19:40
Ну вроде понял...
Как бы на этом методе реализовать вытаскивание двух групп в кавычках "" , пример которого я показал выше, слишком много строк.
Автор: vicbox777
Дата сообщения: 30.05.2009 19:50

Цитата:
реализовать вытаскивание двух групп в кавычках ""

Смотри выше, в этом случае удобнее использовать функцию: StringRegExp, которая возвращает массив совпадений...
Или параметры могут быть не отделены ничем ,идти рядом:
Код: $sTekst='!Copy "1параметр""2параметр" "и т.д. параметр"'
$arrayOFparametrs=
StringRegExp($sTekst, '(?:"(.*?)")+?', 3)
If (Not @Error) Then
for
$i = 0 to UBound($arrayOFparametrs) - 1
msgbox
(0, "$arrayOFparametrs["& $i&"]", $arrayOFparametrs[$i])
Next
EndIf
Автор: ynbIpb
Дата сообщения: 31.05.2009 13:19
Отличная реализация! всё понял.
пора пополнять коллекцию команд...
Вот сварганил удаление файла, вроде продумал все варианты чтоб скрипт не упал от ошибки. Работает даже если послать команду в таком виде:
!filedel а теперь удалика мне этот файлег: "C:\common\хитрая папка\file.txt" нука нука


Код: ;~~~~~~~~~~~~~~
; функция _Filedel_bot удаляет файл в указанной директории, даже с атрибутом только для чтения.
; команда для вызова этой функции: !filedel "путь_к_файлу" (Пример: !filedel "C:\file.exe" )
; если в качестве пути указать путь к папке, то удалятся все файлы, находящиеся в ней.
;~~~~~~~~~~~~~~

Func _Filedel_bot($sMsg)
Local $otvet=""
$filepath = StringRegExp($sMsg, '(?:"(.*?)")+?', 3); выявляем путь к файлу из всего текста сообщения
If IsArray ($filepath) Then ; если результат является массивом, то продолжаем работу с файлом
$attrib = FileGetAttrib($filepath[0]); проверяем атрибуты файла
If StringInStr($attrib, "R") Then ; если атрибут, только для чтения
FileSetAttrib($filepath[0], "-R",1) ; снимаем этот атрибут
EndIf
$result_filedel = FileDelete($filepath[0])
Else ; Иначе выставляем результат удаления - 0
$result_filedel = 0
EndIf
If
$result_filedel = 1 Then; если результат удаления - 1 то отвечаем, что всё ОК
$otvet= "File was deleted successfully!"
Else; если результат удаления - 0 то отвечаем, что всё плохо
$otvet= "Can not delete a file or file does not exist!"
EndIf
Return
$otvet ; возвращаем сформированный ответ из функции
EndFunc
Автор: vicbox777
Дата сообщения: 31.05.2009 20:17

Цитата:
Тут подумал о команде !dir, можно ли сделать чтоб он различал каталоги и файлы? Ведь не всегда отсутствие расширения является признаком, что это папка. Например чтоб команда брала каталог в квадратные скобки [папка]

Можно, я взял функцию _FileListToArray() из UDF - file.au3, и немного изменил её, теперь она ( FileListToArray() -я так ее назвал, только убрал 1 символ из оригинального названия, чтоб не было конфликта с UDF) будет в списке функций, а библиотека file.au3, не нужна:

Код: $sMsg="!dir c:\"
MsgBox(0,"папки и файлы",
_FileList_bot($sMsg) )

;-------------------------------Функции------------------------------------
;~~~~~~~~~~~~~~
; функция _FileList_bot получает список файлов\папок указанной директории и отправляет хозяину
; команда для вызова этой функции: !dir путь_к_каталогу (Пример: !dir C:\ или !dir C:\Program Files)
;$sMsg - весь текст сообщения;
;~~~~~~~~~~~~~~
Func _FileList_bot($sMsg)
Local $sPath, $FileList, $otvet=''
$sPath=
StringRegExpReplace($sMsg,".*dir(?:\s)*(.*)","\1")
IF Not $sPath = 0 then
$FileList=
FileListToArray($sPath)
If @Error=1 Then Return "Path Not Found."
If @Error=4 Then Return "No files\folders found in dir"
If IsArray($FileList) Then
for
$i = 1 to $FileList[0]
$otvet&= $FileList[$i]&@CRLF
next
endIf
Return
$otvet
Else
Return
"No Path"
EndIF
EndFunc


Func
FileListToArray($sPath)
Local $hSearch, $sFile, $asFileList[1]
If Not FileExists($sPath) Then Return SetError(1, 1, "")
If (StringMid($sPath, StringLen($sPath), 1) = "\") Then $sPath = StringTrimRight($sPath, 1)
; needed for Win98 for x:\ root dir
$hSearch = FileFindFirstFile($sPath & "\*")
If $hSearch = -1 Then Return SetError(4, 4, "")
While 1
$sFile = FileFindNextFile($hSearch)
If @error Then
SetError(0)
ExitLoop
EndIf
$asFileList[0] += 1
If UBound($asFileList) <= $asFileList[0] Then
ReDim $asFileList[UBound($asFileList) * 2]
If StringInStr(FileGetAttrib($sPath & "\0" ), "D") = 0 Then
If
StringInStr(FileGetAttrib($sPath&"\"&$sFile), "D") Then
$asFileList[$asFileList[0]] = "["&$sFile&"]"
Else
$asFileList[$asFileList[0]] = $sFile
EndIf
EndIF
WEnd
FileClose($hSearch)
ReDim $asFileList[$asFileList[0] + 1] ; Trim unused slots
Return $asFileList
EndFunc
;==>FileListToArray

Страницы: 12345

Предыдущая тема: HEX редактирование LINUX программ


Форум Ru-Board.club — поднят 15-09-2016 числа. Цель - сохранить наследие старого Ru-Board, истории становления российского интернета. Сделано для людей.