С чего нужно начинать написание скрипта? На мой взгляд, любой кто решил написать скрипт должен четко понимать следующее: * Что он делает. Каков будет конечный результат. * Ясно понимать что делает каждая строчка написанного им скрипта. * Поискать решение аналогичных задач в исходниках или других проектах. * Возможно, переписать все по-своему
Давайте для начала создадим простенький скрипт. Который по команде
будет выводить содержимое некого текстового файла. Но прежде чем что-то
создавать подробно разберем шаги, которые обычно предпринимаются при
написании нового скрипта: анализ существующих примеров и разбор
реализации похожих вещей в исходных текстах. Начнем разбор с тестового скрипта change_nick.bsh, идущего в комплекте с дистрибутивом JimBot. view source print? 1.import ru.jimbot.modules.AbstractServer; 2.import ru.jimbot.util.*; 3.import ru.jimbot.modules.chat.*; 4.import ru.jimbot.modules.*;
Данный фрагмент дополняет область видимости программы скрипта. В данном
случае добавляются класс AbstractServer, который является интерфейсом к
любому сервису бота (и чату, и анекботу). Далее импортируются все
классы из util, chat и modules. Подробнее их можно посмотреть в
исходниках. При запуске скрипта в него передаются ссылки на следующие переменные:
* cmd - переменная возвращает экземпляр класса ChatCommandProc, в
котором обрабатываются все команды бота. Прошу обратить внимание при
копировании его исходников, при обращении к методам этого класса не
забывайте добавлять переменную cmd. * proc - возвращает экземпляр
класса IcqProtocol. Это активный процесс приема-передачи сообщений,
через который пришла данная команда. Для ответа юзеру напрямую нужно
поместить ответ в очередь исходящих этого процесса. Иначе - в общую
очередь чата для рассылки всем присутствующим. * msg - текст сообщения, содержащий нашу команду. Его можно проанализировать на предмет передачи дополнительных параметров. * uin - УИН того кто отправил эту команду.
Двинемся дальше.В следующем блоке кода происходит установка скрипта как
обработчика команды. Выполняется при запуске бота. При выполнении самой
команды - игнорируется. view source print? 1.//Установка скрипта как обработчика команды 2.if(in.equals("install")){ 3. cmd.addCommand("!chnick", new Cmd("!chnick","$n $c",39,name)); 4. cmd.addAuth("chnick","команда изменения ника другого пользователя"); 5. out="Ok"; 6. return; 7.}
Далее мы видим проверку полномочий. Происходит вызов методов класса
ChatCommandProc через переменную cmd. В первой строке происходит
проверка на то в чате ли пользователь, и не админ ли он. Админам
позволительно запускать команду находясь вне чата. Во второй строке
происходит проверка на заданный объект полномочий. Его мы заменим на
свой для своей команды. view source print? 1.// Проверим полномочия 2.if(!cmd.isChat(proc,uin) && !cmd.psp.testAdmin(uin)) return; 3.if(!cmd.auth(proc,uin, "chnick")) return;
Оторвемся немного от анализа скрипта и вспомним зачем мы вообще все это
затеяли. Нам нужно написать скрипт для вывода содержимого текстового
файла. Вспомним, где мы такое уже видели? В команде !help и !rules.
Полезли в исходный текст класса ChatCommandProc в поисках реализации
этих команд.
commands.put("!help", new Cmd("!help","",2)); 2.commands.put("!chat", new Cmd("!chat","",3)); 3.commands.put("!exit", new Cmd("!exit","",4)); 4.commands.put("!rules", new Cmd("!rules","",5)); 5.commands.put("!stat", new Cmd("!stat","",6)); 6.commands.put("!gofree", new Cmd("!gofree","",7)); 7.commands.put("!go", new Cmd("!go","$n",8)); 8.commands.put("!invite", new Cmd("!invite","",9)); Мы видим, что код функции !help - 2, найдем где происходит ее вызов. view source print? 01.switch (tst){ 02.case 1: 03. proc.mq.add(uin,MainProps.getAbout()); 04. break; 05.case 2: 06. commandHelp(proc, uin); 07. break; 08.case 3: 09. goChat(proc, uin); 10. if(psp.getBooleanProperty("chat.getUserInfoOnChat")) 11. proc.mq.add(uin, "", 1); //proc.recUserInfo(uin,"0"); 12. break; 13.case 4: 14. exitChat(proc, uin); 15. break; Видим, что для кода 2 происходит вызов метода commandHelp нашего класса. Найдем его реализацию ниже. view source print? 01./** 02. * !help 03. */ 04.private void commandHelp(IcqProtocol proc, String uin){ 05. String[] s = psp.getHelp1().split("<br>"); 06. for(int i=0;i<s.length;i++){ 07. proc.mq.add(uin,s[i]); 08. } 09. if(srv.us.authorityCheck(uin, "exthelp")){ 10. s = psp.getHelp2().split("<br>"); 11. for(int i=0;i<s.length;i++){ 12. proc.mq.add(uin,s[i]); 13. } 14. } 15.}
Все оказалось не так просто как мы думали В данном месте вы получаем
готовое значение текстовой переменной, уже прочитанное из файла,
разбиваем его на куски и выводим пользователю. Будем копать дальше.
Найдем определение переменной psp. view source print? 1.private long new_ver_test_time = 0; 2.public ChatProps psp; 3.private boolean firstStartMsg = false; Это оказался объект класса ChatProps. Теперь нужно найти этот класс и реализацию в нем метода getHelp1(). view source print? 01.public String getHelp1(){ 02. return loadText("./text/help1.txt"); 03.} 04. 05.public String getHelp2(){ 06. return loadText("./text/help2.txt"); 07.} 08. 09.public String loadText(String fname){ 10. String s = ""; 11. try { 12. BufferedReader r = new BufferedReader(new InputStreamReader(new FileInputStream(fname),"windows-1251")); 13. while (r.ready()) { 14. s += r.readLine() + "\n"; 15. } 16. r.close(); 17. } catch (Exception ex) { 18. ex.printStackTrace(); 19. } 20. return s; 21.}
Вот в общем то и все. Мы видим, что метод loadText полностью нам
подходит - читает заданный текcтовый файл и возвращает его содержимое в
виде строковой переменной. Более того, этот метод объявлен как public,
значит мы можем использовать уже созданный экземпляр класса ChatProps
для вызова этого метода. Чем и займемся в следующей серии
|