Версия для печати темы

Нажмите сюда для просмотра этой темы в обычном формате

UoKit.com Форумы _ Плагины и доп. ПО _ Telegram lua api for pilot

Автор: Madeus 8.8.2022, 20:54

За основу взят https://github.com/wrxck/telegram-bot-lua и внесены фиксы для реалий пилота.

Исправлены ошибки появившиеся в связи с даунгрейдом lua, оригинал написан под lua 5.3, в пилоте lua 5.1.
Добавлена поддержка кириллицы в кодировке win1251 для пилота.
Добавлена поддержка lua-cjson, в оригинале используется dkjson, делал для себя желающие могут откатиться, исходник есть в архиве.
Так же прилагаются все необходимые библиотеки для работы включая ssl 32 bit.

Для использования вам понадобятся:

Распаковать в корень папки пилота.

Примеры использования.

Отправить боту сообщение / фото / файл. Можно использовать как информационные сообщения о состоянии вашего скрипта
Пример 1
Код
--lua
local api = require('telegram.core').configure(TOKEN) -- вместо TOKEN указываем свой полученный в @BotFather
local chat_id = CHAT_ID -- вместо CHAT_ID указываем свой, узнать можно с помощью ботов коих немало в сети

api.send_message(chat_id, 'Hello bot') -- отправить сообщение
api.send_photo(chat_id, [[c:\photo.jpg]]) -- отправить фото
api.send_document(chat_id, [[c:\file.txt]]) -- отправить файл


В следующем примере полноценный бот по задумке открывается в нулевой "0" вкладке (можно запускать пилот с флагом /r0 для автоматического запуска бота. "с:\uopilot\uopilot.exe" /r0).
Умеет:
Пример бот
Код
--lua
local api = require('telegram.core').configure(TOKEN) -- вместо TOKEN указываем свой полученный в @BotFather
local chat_id = CHAT_ID -- вместо CHAT_ID указываем свой, узнать можно с помощью ботов коих немало в сети

local function start_keyboard()
  local keyboard = {['inline_keyboard'] = {{}}}
  local count_scipts = scripts()
  local row = 1
  local count = 0
  for i = 2, #count_scipts do
    count = count + 1
    if count == 8 then
      row = row + 1
      table.insert(keyboard.inline_keyboard, {})
      count = 0
    end
    table.insert(keyboard.inline_keyboard[row], {['text'] = count_scipts[i][1], ['callback_data'] = 'Start ' .. count_scipts[i][1]})
  end
  return keyboard
end

local function stop_keyboard()
  local keyboard = {['inline_keyboard'] = {{}}}
  local count_scipts = scripts()
  local row = 1
  local count = 0
  for i = 2, #count_scipts do
    count = count + 1
    if count == 8 then
      row = row + 1
      table.insert(keyboard.inline_keyboard, {})
      count = 0
    end
    table.insert(keyboard.inline_keyboard[row], {['text'] = count_scipts[i][1], ['callback_data'] = 'Stop ' .. count_scipts[i][1]})
  end
  return keyboard
end

local function status_keyboard()
  local keyboard = {['inline_keyboard'] = {{}}}
  local count_scipts = scripts()
  local row = 1
  local count = 0
  for i = 2, #count_scipts do
    count = count + 1
    if count == 8 then
      row = row + 1
      table.insert(keyboard.inline_keyboard, {})
      count = 0
    end
    table.insert(keyboard.inline_keyboard[row], {['text'] = count_scipts[i][1], ['callback_data'] = 'Script ' .. count_scipts[i][1] .. ' Status ' .. count_scipts[i][3]})
  end
  return keyboard
end

api.send_message(chat_id, 'Pilot online', nil, true, false, nil, api.keyboard():row(api.row():button('Start script'):button('Stop script')):row(api.row():button('Status script'):button('Log')):row(api.row():button('Screenshot')))

local subs = {runing = 'сейчас запущен', stoped = 'сейчас остановлен'}

function api.on_callback_query(callback_query)
  local script_num, status
  local message = callback_query.message
  if callback_query.data:match('Start') then
    script_num = callback_query.data:match('Start (%d+)')
    if script_num then
      api.edit_message_text(message.chat.id, message.message_id, 'Запустил срипт ' .. script_num)
      start_script(script_num)
    end
  elseif callback_query.data:match('Stop') then
    script_num = callback_query.data:match('Stop (%d+)')
    if script_num then
      api.edit_message_text(message.chat.id, message.message_id, 'Остановил скрипт ' .. script_num)
      stop_script(script_num)
    end
  elseif callback_query.data:match('Status') then
    script_num, status = callback_query.data:match('Script (%d+) Status (%S+)')
    if script_num and status then
      api.edit_message_text(message.chat.id, message.message_id, 'Скрипт ' .. script_num .. ' ' .. string.gsub(status, '(%w+)', subs))
    end
  end
end

function api.on_message(message)
  if message.chat.id == chat_id then
    if message.text and message.text:match('Screenshot') then
      printscreen (0, 0, 0, 0, 0, 'screen.jpg')
      api.send_photo(chat_id, 'screen.jpg')
    elseif message.text and message.text:match('Start script') then
      api.send_message(message.chat.id, 'Выбери какой скрипт запустить:', nil, true, false, nil, start_keyboard())
    elseif message.text and message.text:match('Stop script') then
      api.send_message(message.chat.id, 'Выбери какой скрипт остановить:', nil, true, false, nil, stop_keyboard())
    elseif message.text and message.text:match('Status script') then
      api.send_message(message.chat.id, 'Выбери какой скрипт проверить:', nil, true, false, nil, status_keyboard())
    elseif message.text and message.text:match('Log') then
      local log_path = 'pilot_log.txt'
      log('save', log_path)
      local log_file = io.open(log_path)
      local log_text = log_file:read('*a')
      log_file:close()
      if #log_text > 0 then
--      api.send_document(message.chat.id, log_path) -- если нужно отправить файл лога раскоментируй строку
        api.send_message(message.chat.id, log_text)
      else
        api.send_message(message.chat.id, 'Log пустой')
      end
    elseif message.text and message.text:match('Terminate') then -- что бы закрыть окно любой программы отправь боту сообщение вида 'Terminate #заголовок окна#' например 'Terminate Блокнот'
      local terminate_window = message.text:match('Terminate%s+(.+)')
      if terminate_window then
        local handle = findwindow(terminate_window)
        if handle then
          terminate(terminate_window)
          api.send_message(message.chat.id, 'Окно ' .. terminate_window .. ' закрыто')
        else
          api.send_message(message.chat.id, 'Окно ' .. terminate_window .. ' не найдено')
        end
      end
    end
  end
end

api.run(1, 100)



Прикрепленные файлы
Прикрепленный файл  telegram.zip ( 2,83 мегабайт ) Кол-во скачиваний: 136

Автор: apaul 16.11.2022, 18:17

Добрый день. Подскажите как отправить боту файл, а то сходу не взлетело. Бот просто не видит message c отправкой, соответственно и получить file_id для дальнейшего скачивания не представляется возможным (.

Автор: DarkMaster 16.11.2022, 20:45

а обычные сообщения он видит?

Автор: Madeus 16.11.2022, 22:06

Вы отправляете файл боту? А цель какая и какой размер файла?

Автор: apaul 17.11.2022, 0:23

Цитата(DarkMaster @ 16.11.2022, 20:45) *

а обычные сообщения он видит?

Обычные сообщения видит прекрасно, работает стабильно и замечательно biggrin.gif
Цитата(Madeus @ 16.11.2022, 22:06) *

Вы отправляете файл боту? А цель какая и какой размер файла?

Да, есть желание отправить файл боту. Про ограничение размера в 20Мб я в курсе, мои задачи это покрывает с огромным запасом. Хочу сделать с его помощью возможность удаленной корректировки рабочих файлов проекта пилота, т.е. будет пересылаться архив в 20-30кБ.

Автор: DarkMaster 17.11.2022, 0:40

телеги нет - тестить не могу, но при таких объемах можно этот архив и не файлом, а обычным сообщением отослать)

Автор: Madeus 17.11.2022, 1:57

Все стандартно только нужно подключить 2 библы, они уже есть в архиве просто добавь в начало 2 первые строчки

Код
local ltn12 = require('ltn12')
local https = require('ssl.https')

function api.on_message(message)
  if message.document then
    rr = api.get_file(message.document.file_id)
    https.request{
      url = 'https://api.telegram.org/file/bot' .. api.token .. '/' .. rr.result.file_path,
      sink = ltn12.sink.file(io.open('E:\\' .. rr.result.file_path, 'wb'))
    }
  end
end

В данном примере файл сохранится в "E:\documents\" имена телеграм дает по порядку file_1 и тд., расширение будет то же что и отправишь. С каким именем скачивать решать уже тебе. Можно так
Код
sink = ltn12.sink.file(io.open('E:\\file.zip', 'wb'))

Будет перезаписывать файл с именем file.zip

Автор: apaul 17.11.2022, 18:55

Цитата(Madeus @ 17.11.2022, 1:57) *

Все стандартно только нужно подключить 2 библы,

Спасибо, теперь разобрался. Оказалось, как обычно, сам накосячил - изначально создал группу с 2мя участниками - ботом и собой. С текстовыми командами вида "/bla-bla" оно работает прекрасно, а для перехвата иных сообщений, включая message.document, надо либо бота делать администратором группы, либо работать не через группу, а через приват.

Автор: Madeus 24.11.2022, 17:41

Обновил архив, заменил cjson.dll по ошибке положил туда не ту версию, осталась после тестов (дикий тормоз) теперь все летает, хотя вряд ли кто-то заметит разницу, она явно видна на "жирных" json`ах.

Автор: TheQQmaster 6.1.2023, 3:09

how to config this to capture only 2nd monitor for screenshot ?

Цитата
printscreen (0, 0, 0, 0, 0, 'screen.jpg')


Автор: DarkMaster 6.1.2023, 12:51

Desktop area have shared coordinates. As example if you have 2 monitors and they was positioned in horizontal line and have full hd resolution, then frist monitor will start from 0, 0 end at 1919, 1079, second will start from 1920, 0 and will and at 3839, 1079.

But be careful with positioning. It can have almost any offset. For be sure in offset if you have non standard config you can check it paint by placing full screenshot or check it in register:

HKEY_CURRENT_CONFIG\System\CurrentControlSet\Control\Video

or


For anyone that is looking for the key in Windows 7 it is in one of the folders in:

HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\GraphicsDrivers\Configuration\

Look for Position.cx and Position.cy in each of the subfolders; you have to edit the hex string.

Автор: TheQQmaster 6.1.2023, 20:29

Цитата(DarkMaster @ 6.1.2023, 11:51) *

Desktop area have shared coordinates. As example if you have 2 monitors and they was positioned in horizontal line and have full hd resolution, then frist monitor will start from 0, 0 end at 1919, 1079, second will start from 1920, 0 and will and at 3839, 1079.

But be careful with positioning. It can have almost any offset. For be sure in offset if you have non standard config you can check it paint by placing full screenshot or check it in register:

HKEY_CURRENT_CONFIG\System\CurrentControlSet\Control\Video

or
For anyone that is looking for the key in Windows 7 it is in one of the folders in:

HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\GraphicsDrivers\Configuration\

Look for Position.cx and Position.cy in each of the subfolders; you have to edit the hex string.

thx, solved smile.gif
u could respond russian, i understand ,but bad with typing

Автор: Madeus 18.2.2023, 22:15

Для мониторов с большим разрешением скрин экрана сильно пережимается телегой, и если нужны мелкие детали можно отправлять файлом.
Заменить

Код
api.send_photo(chat_id, 'screen.jpg')

на
Код
api.send_document(chat_id, 'screen.jpg')

Русская версия Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)