Телеграмма для Mikrotik...

Здесь выкладываем скрипты
Правила форума
Уважаемые Пользователи форума, обратите внимание!
Ни при каких обстоятельствах, Администрация форума, не несёт ответственности за какой-либо, прямой или косвенный, ущерб причиненный в результате использования материалов, взятых на этом Сайте или на любом другом сайте, на который имеется гиперссылка с данного Сайта. Возникновение неисправностей, потерю программ или данных в Ваших устройствах, даже если Администрация будет явно поставлена в известность о возможности такого ущерба.
Просим Вас быть предельно осторожными и внимательными, в использовании материалов раздела. Учитывать не только Ваши пожелания, но и границы возможностей вашего оборудования.
Ответить
Аватара пользователя
Brook
Сообщения: 127
Зарегистрирован: 24 май 2022, 00:29

Здравствуйте друзья.

Хочу представить вашему вниманию Телеграм бота, который написан на Mikrotik Script и работает в среде маршрутизатора без использования сторонних сервисов.

Его разработка стала возможной после того, как один из авторов Хабра выложил в общий доступ библиотеку, с помощью которой можно парсить JSON объекты в ассоциативный массив на Микротике. Автора зовут Александр @Chupakabra303. Спасибо ему за это большое. Ещё у автора есть хорошие статьи по исследованию переменных и функций.

Так же по функциям есть отличный материал на всё том же Хабре от уважаемого Сергея Sertik13. Всем кто хочет разобраться в этом вопросе - очень рекомендую.

Ну а я, собрав воедино, в том числе и эти знания, написал бота, который теперь очень помогает мне в работе. Информацию по нему начал выкладывать на своём канале. Всем, кому интересно - добро пожаловать https://t.me/mikRobot_RU

Бот модульный, написан с использованием функций. Первая его версия была почти монолитной, что было очень не удобно с точки зрения отладки и обновления. Функции этот вопрос решают. Так же написаны библиотечные функции для Телеграмма, типа SendMessage, EditMessage и т.д. Их я скоро планирую выложить в общий доступ, как и основную часть кода.

 Вот так это выглядит в самом микротике

Изображение
 А это главное окно бота

Изображение

Больше информации на канале. Прошу сильно не пинать, публикую в первый раз. Конструктивная критика приветствуется.

С наличием свободного времени, конечно, не очень. Но буду рад и постараюсь ответить на ваши вопросы, если таковые возникнут.

Код бота опубликован, поэтому - License

 UPD: 20.07.2022 Архитектура приложения и код функции teSendMessage

В общих чертах про архитектуру приложения.
Главный модуль забирает у Телеграмма сообщения двух типов, Message и Callback. Это текстовые сообщения и нажатия на инлайн-кнопку.
Парсит полученный объект в многомерный ассоциативный массив с помощью библиотеки JParseFunctions.

 Код получения и парсинга сообщений для примера

Код: Выделить всё

:local tgUrl "https://api.telegram.org/$botID/getUpdates\?&allowed_updates=[%22message%22,%22callback_query%22]&offset=$Jtoffset&timeout=5"
:local fetchData [/tool fetch ascii=yes url=$tgUrl as-value output=user]
:if ([:len [:tostr ($fetchData->"data")]] != 0) do={
	:set fetchData ($fetchData->"data")
	:set JSONIn $fetchData
	:set JParseOut [$fJParse]
	:if ([:len ($JParseOut->"result")] != 0) do={
		:set JParseOut ($JParseOut->"result")
	} else={error message="no data..." }
}

Далее определяется тип полученного объекта и проверяются разрешения пользователя на работу с устройством.

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

Обработчик сообщений получает на вход объект в виде массива, определяет команду и обрабатывает её.

Если было нажатие на кнопку, то вызывается функция обработки Callbackов. У неё одна задача - определить от какого модуля пришло сообщение и вызвать функцию его обработки, в которой находится вся логика и формируются параметры для передачи в функцию построения ответного сообщения.

Она формирует объект для Телеграмма, с текстовой информацией, медиа, кнопками и отправляет его пользователю.

Каждая функция возвращает значение в то место, откуда была вызвана. Оно обрабатывается и передаётся по цепочке в обратном порядке.
Главный модуль увеличивает счетчик сообщений на единицу и ждёт новый объект. Это если вкратце.

Не спеша начну выкладывать код общих функций.
Настройки для них хранятся в массиве и получаются во время работы.
Чтобы адаптировать их для общего пользования, буду переносить такие настройки в параметры самих функций. Итак...

 Функция teSendMessage

Код: Выделить всё


#---------------------------------------------------teSendMessage--------------------------------------------------------------
#   Function sends a message to the recipient.
#   Params for this function:

#   1.  fChatID       -   Recipient id
#   2.  fText         -   Message text
#   3.  fReplyMarkup  -   Reply markup (may be empty)
#   4.  fBotID        -   ID for bot

#   Function return $messageID or 0 or "lengthError"
#---------------------------------------------------teSendMessage--------------------------------------------------------------

:global teSendMessage
:if (!any $teSendMessage) do={ :global teSendMessage do={

	:local botID $fBotID

	:local disableWebPagePreview true
	:local parseMode "html"

	:local tgUrl []; :local result []; :local content []
	:if ([:len $fText] >= 4096) do={:return [error message="lengthError"]}

	:if ([:len $fReplyMarkup] != 0) do={
		:set tgUrl "https://api.telegram.org/$botID/sendmessage\?chat_id=$fChatID&text=$fText&parse_mode=$parseMode&disable_web_page_preview=$disableWebPagePreview&reply_markup=$fReplyMarkup"
	}
	:if ([:len $fReplyMarkup] = 0) do={
		:set tgUrl "https://api.telegram.org/$botID/sendmessage\?chat_id=$fChatID&text=$fText&parse_mode=$parseMode&disable_web_page_preview=$disableWebPagePreview"
	}

	do {
    	:set content [:tool fetch ascii=yes url=$tgUrl as-value output=user]
 	} on-error={ :return 0 }

	:if ($content->"status" = "finished")	do={
	    :local tmpStr [:pick ($content->"data") ([:find ($content->"data") "message_id"]) ([:find ($content->"data") "_id"]+20)]
	    :local messageID [:pick $tmpStr ([:find $tmpStr "message_id"]+12) ([:find $tmpStr ","])]
	    :set result $messageID
	    :return $result
	} else={ :return 0 }
     }
}


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

fChatID - ID чата, куда отправляем
fText - Текст сообщения
fBotID - ID бота в формате "botxxxxxxxxx:FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
fReplyMarkup - это клавиатура, которую можно прицепить к сообщению. Она формируется отдельной функцией. Её выложу позже.

Возвращает ID сообщения, если оно успешно доставлено. 0 (ноль), если доставить не получилось,
или ошибку "lengthError", если длина текста >= 4096 (ограничение Telegram на длину сообщения)

В приведенном ниже примере результат возвращается в переменную messageID

Код: Выделить всё

#	Сообщение с текстом и клавиатурой

	:global teSendMessage
	
	:local botID "botxxxxxxxxx:FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
	:local sendText "Any text..."
	:local chatID 1234567890
	
	:local messageID [$teSendMessage fBotID=$botID fChatID=$chatID fText=$sendText fReplyMarkup=$replyMarkup]

Код: Выделить всё

#	Сообщение только с текстом

	:global teSendMessage

	:local botID "botxxxxxxxxx:FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
	:local sendText "Any text..."
	:local chatID 1234567890
	
	:local messageID [$teSendMessage fBotID=$botID fChatID=$chatID fText=$sendText]
 Функция отправки сообщения с фотографией teSendPhoto

Параметры:

fChatID - ID чата, куда отправляем
fPhoto - url изображения или его file_id из Telegram
fText - текст сообщения
fBotID - ID бота в формате "botxxxxxxxxx:FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
fReplyMarkup - клавиатура.

 Код teSendPhoto

Код: Выделить всё

#---------------------------------------------------teSendPhoto--------------------------------------------------------------

#   Function sends a message to the recipient.
#   Params for this function:

#   1.  fChatID       -   Recipient id
#   2.  fPhoto        -   Message Photo
#   3.  fText         -   Message text
#   4.  fReplyMarkup  -   Reply markup (may be empty)
#   5.  fBotID        -   ID for bot

#   Function return $messageID or 0 or "lengthError"

#   if the global variable fDBGteSendPhoto=true, then a debug event will be logged

#---------------------------------------------------teSendPhoto--------------------------------------------------------------

:global teSendPhoto
:if (!any $teSendPhoto) do={ :global teSendPhoto do={

	:local botID $fBotID

	:local disableWebPagePreview true
	:local parseMode "html"

  	:local tgUrl []; :local result []; :local content []

  	:if ([:len $fText] = 0) do={:set $fText " "}
  	:if ([:len $fText] >= 1024) do={:return [error message="lengthError"]}
 
  	:if ([:len $fReplyMarkup] != 0) do={
	   :set tgUrl "https://api.telegram.org/$botID/sendphoto\?chat_id=$fChatID&photo=$fPhoto&caption=$fText&parse_mode=$parseMode&reply_markup=$fReplyMarkup"
   	}
   	:if ([:len $fReplyMarkup] = 0) do={
	   :set tgUrl "https://api.telegram.org/$botID/sendphoto\?chat_id=$fChatID&photo=$fPhoto&caption=$fText&parse_mode=$parseMode"
   	}

	do {
    	   :set content [:tool fetch ascii=yes url=$tgUrl as-value output=user]
  	} on-error={ :return 0 }

	:if ($content->"status" = "finished")	do={
    	   :local tmpStr [:pick ($content->"data") ([:find ($content->"data") "message_id"]) ([:find ($content->"data") "_id"]+20)]
	   :local messageID [:pick $tmpStr ([:find $tmpStr "message_id"]+12) ([:find $tmpStr ","])]
	   :set result $messageID
    	   :return $result
  	} else={ :return 0 }
    }
}

Возвращает ID сообщения, если оно успешно доставлено. 0 (ноль), если доставить не удалось,
или ошибку "lengthError", если длина текста >= 1024. (ограничение Telegram на длину подписи к фотографии)

Варианты использования:

Код: Выделить всё

#	Сообщение с текстом фотографией и клавиатурой

	:global teSendPhoto
	
	:local botID "botxxxxxxxxx:FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
	:local sendText "Any text..."
	:local chatID 1234567890
	:local image "https://habrastorage.org/webt/kz/uh/xm/kzuhxmsrjq7mrzqin8aznrrhclw.jpeg"
	
	:local messageID [$teSendPhoto fBotID=$botID fChatID=$chatID fPhoto=$imageRoot fText=$sendText fReplyMarkup=$replyMarkup]

Код: Выделить всё

#	Сообщение только с текстом и фото

	:global teSendPhoto

	:local botID "botxxxxxxxxx:FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
	:local sendText "Any text..."
	:local chatID 1234567890
	:local image "https://habrastorage.org/webt/kz/uh/xm/kzuhxmsrjq7mrzqin8aznrrhclw.jpeg"
	
	:local messageID [$teSendPhoto fBotID=$botID fChatID=$chatID fPhoto=$imageRoot fText=$sendText]
-
-
 UPD: 22.07.2022 Функция редактирования текстового сообщения teEditMessage

Параметры:

fChatID - ID чата, куда отправляем
fMessageID - номер редактируемого сообщения
fText - текст сообщения
fReplyMarkup - клавиатура.
fBotID - ID бота в формате "botxxxxxxxxx:FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"


 Код teEditMessage

Код: Выделить всё


#---------------------------------------------------teEditMessage--------------------------------------------------------------

#   Function edits the specified message
#   Params for this function:

#   1.  fChatID       -   Recipient id
#   2.  fMessageID    -   id for edited message
#   3.  fText         -   Message text
#   4.  fReplyMarkup  -   Reply markup (may be empty)
#   5.  fBotID        -   ID for bot

#   Function return message ID or 0 or "lengthError"

#---------------------------------------------------teEditMessage--------------------------------------------------------------

:global teEditMessage
:if (!any $teEditMessage) do={ :global teEditMessage do={

	:local botID $fBotID
	:local disableWebPagePreview true
	:local parseMode "html"

	:local tgUrl []; :local result []; :local content []

	:if ([:len $fText] = 0) do={:set $fText " "}
	:if ([:len $fText] >= 4096) do={:return [error message="lengthError"]}

	:if ([:len $fReplyMarkup] != 0) do={
		:set tgUrl "https://api.telegram.org/$botID/editMessageText\?chat_id=$fChatID&message_id=$fMessageID&text=$fText&parse_mode=$parseMode&disable_web_page_preview=$disableWebPagePreview&reply_markup=$fReplyMarkup"
	} else={
		:set tgUrl "https://api.telegram.org/$botID/editMessageText\?chat_id=$fChatID&message_id=$fMessageID&text=$fText&parse_mode=$parseMode&disable_web_page_preview=$disableWebPagePreview"
	}

  do {
  	:set content [:tool fetch ascii=yes url=$tgUrl as-value output=user]

  	:if ($content->"status" = "finished")	do={
  	:local tmpStr [:pick ($content->"data") ([:find ($content->"data") "message_id"]) ([:find ($content->"data") "_id"]+20)]
  	:local messageID [:pick $tmpStr ([:find $tmpStr "message_id"]+12) ([:find $tmpStr ","])]
  	:set result $messageID
  	:return $result
  	} else={ :return 0	}
  } on-error={ :return 0 }
 }
}


Варианты использования:

Код: Выделить всё

#	Редактирование сообщения с текстом и клавиатурой

	:global teEditMessage
	
	:local botID "botxxxxxxxxx:FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
	:local sendText "Any text..."
	:local chatID 1234567890
	:local messageID 12345
	
	:set messageID [$teEditMessage fBotID=$botID fChatID=$chatID fMessageID=$messageID fText=$sendText fReplyMarkup=$replyMarkup]

Код: Выделить всё

#	Редактирование сообщения только с текстом

	:global teEditMessage

	:local botID "botxxxxxxxxx:FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
	:local sendText "Any text..."
	:local chatID 1234567890
	:local messageID 12345

	:set messageID [$teEditMessage fBotID=$botID fChatID=$chatID fMessageID=$messageID fText=$sendText]
Возвращает ID сообщения, если оно успешно отредактировано. 0 (ноль), если отредактировать не удалось,
или ошибку "lengthError", если длина текста >= 4096. (ограничение Telegram на длину сообщения)

 Функция редактирования подписи к медиа сообщению teEditCaption

Параметры:

fChatID - ID чата, куда отправляем
fMessageID - номер редактируемого сообщения
fText - текст сообщения
fReplyMarkup - клавиатура (не обязательный параметр)
fBotID - ID бота в формате "botxxxxxxxxx:FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"

 Код функции teEditCaption

Код: Выделить всё


#---------------------------------------------------teEditCaption--------------------------------------------------------------

#   Function edits the specified message caption
#   Params for this function:

#   1.  fChatID       -   Recipient id
#   2.  fMessageID    -   id for edited message
#   3.  fText         -   Message text
#   4.  fBotID        -   ID for bot

#   Function return message ID or 0 or "lengthError"

#---------------------------------------------------teEditCaption--------------------------------------------------------------

:global teEditCaption
:if (!any $teEditCaption) do={ :global teEditCaption do={

	:local botID $fBotID

	:local disableWebPagePreview true
	:local parseMode "html"

	:local tgUrl []; :local result []; :local content []

	:if ([:len $fText] = 0) do={:set $fText " "}
	:if ([:len $fText] >= 1024) do={:return [error message="lengthCaptionError"]}

	:if ([:len $fReplyMarkup] != 0) do={
		:set tgUrl "https://api.telegram.org/$botID/editMessageCaption\?chat_id=$fChatID&message_id=$fMessageID&caption=$fText&parse_mode=$parseMode&reply_markup=$fReplyMarkup"
	} else={
		:set tgUrl "https://api.telegram.org/$botID/editMessageCaption\?chat_id=$fChatID&message_id=$fMessageID&caption=$fText&parse_mode=$parseMode"
	}

	do {
	:set content [:tool fetch ascii=yes url=$tgUrl as-value output=user]
	:if ($content->"status" = "finished")	do={
	:local tmpStr [:pick ($content->"data") ([:find ($content->"data") "message_id"]) ([:find ($content->"data") "_id"]+20)]
	:local messageID [:pick $tmpStr ([:find $tmpStr "message_id"]+12) ([:find $tmpStr ","])]
  	:set result $messageID; :return $result
  	} else={:return 0 }
  } on-error={ :return 0 }
 }
}

Варианты использования:

Код: Выделить всё


	:global teEditCaption

	:local botID "botxxxxxxxxx:FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
	:local sendText "Any text..."
	:local chatID 1234567890
	:local messageID 12345

	:set messageID [$teEditCaption fBotID=$botID fChatID=$chatID fMessageID=$messageID fText=$sendText fReplyMarkup=$replyMarkup]

Возвращает ID сообщения, если оно успешно отредактировано. 0 (ноль), если отредактировать не удалось,
или ошибку "lengthError", если длина текста >= 1024. (ограничение Telegram на длину сообщения)

 Функция редактирования медиа сообщения teEditMedia

Параметры:

fChatID - ID чата, куда отправляем
fMessageID - номер редактируемого сообщения
fMediaType - тип медиа сообщения (animation, document, audio, photo, video)
fMediaLink - ссылка на новое медиа
fMediaCaption - текст подписи
fReplyMarkup - клавиатура (не обязательный параметр)
fBotID - ID бота в формате "botxxxxxxxxx:FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"

 Код функции teEditMedia

Код: Выделить всё


#---------------------------------------------------teEditMedia--------------------------------------------------------------

#   Params for this function:

#   1.  fChatID       -   Recipient id
#   2.  fMessageID    -   id for edited message

#   3.  fMediaType    -   This object represents the content of a media message to be edit. It should be one of:
#                         animation, document, audio, photo, video

#   4.  fMediaLink    -   Message media,
#   5.  fMediaCaption -   Message caption
#   6.  fReplyMarkup  -   Reply markup (may be empty)
#   7.  fBotID        -   ID for bot

#   Function return message ID or 0 or "lengthError"

#---------------------------------------------------teEditMedia--------------------------------------------------------------

:global teEditMedia
:if (!any $teEditMedia) do={ :global teEditMedia do={

	:local botID $fBotID

	:local disableWebPagePreview true
	:local parseMode "html"

	:local tgUrl []; :local result []; :local content []
	:local newMedia []

	:if ([:len $fMediaCaption] >= 1024) do={:return [error message="lengthError"]}

	:local inputMediaType "\7B\22type\22:\22$fMediaType"
	:local inputMediaLink "\22,\22media\22:\22"
	:local inputMediaCaption "\22,\22caption\22:\22"
	:local endMedia "\22\7D"

	:if ([:len $fMediaCaption] = 0) do={
		:set newMedia "$inputMediaType$inputMediaLink$fMediaLink$endMedia"
	} else={
		:set newMedia "$inputMediaType$inputMediaLink$fMediaLink$inputMediaCaption$fMediaCaption$endMedia"
	}

	:if ([:len $fReplyMarkup] != 0) do={
		:set tgUrl "https://api.telegram.org/$botID/editMessageMedia\?chat_id=$fChatID&message_id=$fMessageID&media=$newMedia&parse_mode=$parseMode&reply_markup=$fReplyMarkup"
	} else={
		:set tgUrl "https://api.telegram.org/$botID/editMessageMedia\?chat_id=$fChatID&message_id=$fMessageID&media=$newMedia&parse_mode=$parseMode"
	}

	do {
	:set content [:tool fetch ascii=yes url=$tgUrl as-value output=user]

  	:if ($content->"status" = "finished")	do={
		:local tmpStr [:pick ($content->"data") ([:find ($content->"data") "message_id"]) ([:find ($content->"data") "_id"]+20)]
		:local messageID [:pick $tmpStr ([:find $tmpStr "message_id"]+12) ([:find $tmpStr ","])]
  		:set result $messageID
  		:return $result
  	} else={ :return 0	}
  } on-error={ :return 0 }
 }
}

Варианты использования:

Код: Выделить всё


	:global teEditMedia

	:local botID "botxxxxxxxxx:FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
	:local sendText "Any text..."
	:local chatID 1234567890
	:local messageID 12345
	:local mediaType "photo"
	:local fMediaLink "https://habrastorage.org/webt/kz/uh/xm/kzuhxmsrjq7mrzqin8aznrrhclw.jpeg"
	
	:set messageID [$teEditMedia fBotID=$botID fChatID=$chatID fMessageID=$messageID fMediaType=$mediaType fMediaCaption=$sendText fReplyMarkup=$replyMarkup]
Возвращает ID сообщения, если оно успешно отредактировано. 0 (ноль), если отредактировать не удалось,
или ошибку "lengthError", если длина текста >= 1024. (ограничение Telegram на длину сообщения)

 Функция редактирования клавиатуры teEditMessageReplyMarkup


Параметры:

fChatID - ID чата, куда отправляем
fMessageID - номер редактируемого сообщения
fReplyMarkup - клавиатура
fBotID - ID бота в формате "botxxxxxxxxx:FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"

 Код функции teEditMessageReplyMarkup

Код: Выделить всё


#---------------------------------------------------teEditMessageReplyMarkup--------------------------------------------------------------

#   Function edits the specified message reply_markup
#   Params for this function:

#   1.  fChatID       -   Recipient id
#   2.  fMessageID    -   id for edited message
#   3.  fReplyMarkup  -   Reply markup
#   4.  fBotID        -   ID for bot

#   Function return message ID or 0

#---------------------------------------------------teEditMessageReplyMarkup--------------------------------------------------------------

:global teEditMessageReplyMarkup
:if (!any $teEditMessageReplyMarkup) do={ :global teEditMessageReplyMarkup do={

	:local botID $fBotID

	:local disableWebPagePreview true
	:local parseMode "html"

	:local tgUrl []; :local result []; :local content []

	:if ([:len $fReplyMarkup] != 0) do={
		:set tgUrl "https://api.telegram.org/$botID/editMessageReplyMarkup\?chat_id=$fChatID&message_id=$fMessageID&reply_markup=$fReplyMarkup"
	} else={ :return 0 }

	do {
		:set content [:tool fetch ascii=yes url=$tgUrl as-value output=user]
	} on-error={ :return 0 }

  	:if ($content->"status" = "finished")	do={

	      	:local tmpStr [:pick ($content->"data") ([:find ($content->"data") "message_id"]) ([:find ($content->"data") "_id"]+20)]
      		:local messageID [:pick $tmpStr ([:find $tmpStr "message_id"]+12) ([:find $tmpStr ","])]
	  	:set result $messageID
  		:return $result

  	} else={ :return 0 }
 }
}


Варианты использования:

Код: Выделить всё


	:global teEditMessageReplyMarkup
	:global teBuildKeyboard

	:local botID "botxxxxxxxxx:FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
	:local chatID 1234567890
	:local messageID 12345
	:local replyMarkup [$teBuildKeyboard fButtonsKeyBoard=$lineButtons fReplyKeyboard=false]
	
	:set messageID [$teEditMessageReplyMarkup fBotID=$botID fChatID=$chatID fMessageID=$messageID fReplyMarkup=$replyMarkup] 
	
Возвращает ID сообщения, если оно успешно отредактировано. 0 (ноль), если отредактировать не удалось.

 Функция добавления команд в меню Телеграм teSetMyCommands

Это те команды, которые добавляются через botFather и отображаются при вводе символа /
Через API их тоже можно добавлять. Этим и занимается данная функция. Имейте ввиду, что при добавлении новых, старые удаляются.

Параметры:

fCommands - команды, которые надо добавить. Формат - команда;описание. Может быть несколько. Разделяются запятой.
fBotID - ID бота в формате "botxxxxxxxxx:FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"

 Код функции teSetMyCommands

Код: Выделить всё


#---------------------------------------------------teSetMyCommands--------------------------------------------------------------

#   Params for this function:

#   1.  fCommands     -   commands with descriptions
#   2.  fBotID        -   ID for bot


#   command         -   text of the command; 1-32 characters. Can contain only lowercase English letters, digits and underscores.
#   description     -   description of the command; 1-256 characters

#   Usage example:

#   $teSetMyCommands fCommands="command;description"
#   $teSetMyCommands fCommands="command;description,command;description"

#   $teSetMyCommands fCommands="getifaces;Get interfaces list,getusers;Get users list"

#   Function return 1 or 0

#---------------------------------------------------teSetMyCommands--------------------------------------------------------------

:global teSetMyCommands
:if (!any $teSetMyCommands) do={ :global teSetMyCommands do={

  :local botID $fBotID

  :local tgUrl []; :local content []

  :local commandsList [:toarray $fCommands]
  :local cmdItems []
  :local command []

  :foreach i in=$commandsList do={
    :local command [:pick $i 0 [find $i ";"]]
    :local description [:pick $i ([find $i ";"] + 1) [:len $i]]
    :local startCommand "\7B\22command\22:\22$command\22"
    :local commandDescription ",\22description\22:\22$description\22\7D,"
    :set command "$startCommand$commandDescription$endCommand"
    :set $cmdItems ($cmdItems . $command)
  }
  :set cmdItems [:pick $cmdItems 0 ([:len $cmdItems] - 1)]

  :local start "\5B"
  :local end "\5D"
  :set commandsList "$start$cmdItems$end"

  :set tgUrl "https://api.telegram.org/$botID/setMyCommands\?commands=$commandsList"

do {
    :set content [:tool fetch ascii=yes url=$tgUrl as-value output=user]
    :if ($content->"status" = "finished") do={ :return 1 }
  } on-error={ :return 0 }
 }
}



Варианты использования:

Код: Выделить всё


#	будет отправлено три команды с описанием

#	interfaces
#	users
#	chatid
	
	:global teSetMyCommands 
	:local botID "botxxxxxxxxx:FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
	
	$teSetMyCommands fBotID=$botID fCommands="interfaces;Get interfaces list,users;Get users list,chatid;Get ID of current chat"
	
Возвращает 1, если все хорошо и 0 (ноль), если не очень.

-
 UPD: 23.07.2022 Функция удаления сообщения teDeleteMessage

Боты могут удалять сообщения не старше 48 часов. Если сообщение старше, то функция попытается его отредактировать, заменив текст на сообщение о том, что удалить не получится и его можно удалить вручную. Если сообщения с таким номером вообще нет, тогда вернет false

Параметры:

fChatID - ID чата
fMessageID - номер удаляемого сообщения
fUserName - имя пользователя Телеграм (не обязательно)
fDeviceName - имя устройства (не обязательно)
fBotID - ID бота в формате "botxxxxxxxxx:FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"

 Код функции teDeleteMessage

Код: Выделить всё


#---------------------------------------------------teDeleteMessage--------------------------------------------------------------

#   Function delete the specified message
#   Params for this function:

#   1.  fChatID      -   Recipient id
#   2.  fMessageID   -   id for edited message
#   3.  fUserName    -   user Name from Telegram
#   4.  fBotID       -   ID for bot
#   5.  fDeviceName  -   name of device

#   Function return message true or false

#---------------------------------------------------teDeleteMessage--------------------------------------------------------------

:global teDeleteMessage
:if (!any $teDeleteMessage) do={ :global teDeleteMessage do={

	:global teEditMessage

	:local botID $fBotID
	:local deviceName $fDeviceName

	:local oneFeed "%0D%0A"
	:local doubleFeed "%0D%0A%0D%0A"

	:local tgUrl []; :local content []

	:set tgUrl "https://api.telegram.org/$botID/deletemessage\?chat_id=$fChatID&message_id=$fMessageID"

	:do {
		:set content [:tool fetch url=$tgUrl as-value output=user]
  	} on-error={

		:local headerText "\F0\9F\97\91  <b>$deviceName</b> $oneFeed----------------------------------------------------$doubleFeed"
		:local bodyText ("<b>$fUserName,</b> the bot cannot delete messages older than 48 hours. $doubleFeed" )
		:local footerText ("<b>The function on the device worked normally.</b> $doubleFeed"."You can delete this message manually.$oneFeed")
		:local sendText "$headerText$bodyText$footerText"

		:if ([$teEditMessage fChatID=$fChatID fMessageID=$fMessageID fText=$sendText] != 0) do={
			:return true
		} else={ :return false }
  	}
	:if ($content->"status" = "finished")	do={
		:return true
	} else={ :return false }
    }
}

Варианты использования:

Код: Выделить всё


	:global teDeleteMessage 

	:local chatID 1234567890
	:local messageID 12345
	:local userName "user name"
	:local botID "botxxxxxxxxx:FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
	
	:local result [$teDeleteMessage fBotID=$botID fChatID=$chatID fMessageID=$messageID fUserName=$userName]

Возвращает true, если все хорошо и false, если не очень.

 Функция ответа на нажатие кнопки teAnswerCallbackQuery

Когда боту прилетает сообщение с типом Callback (нажатие на кнопку), то можно на него ответить. В Телеграмме это будет выглядеть, как всплывающее сообщение.

Параметры:

fQueryID - ID callback-а
fAnswerText - текст ответа
fAlert - тип ответа (не обязательно)
fBotID - ID бота в формате "botxxxxxxxxx:FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"

 Код функции teAnswerCallbackQuery

Код: Выделить всё


#---------------------------------------------------teAnswerCallbackQuery--------------------------------------------------------------

#   Function sends a response to a button click
#   Params for this function:

#   1.  fQueryID          -   query id
#   2.  fAnswerText   -   text for answer
#   3.  fAlert               -   alert type (true or false) may be  empty
#   4.  fBotID             -   ID for bot

#   Function return message true or false

#---------------------------------------------------teAnswerCallbackQuery--------------------------------------------------------------

:global teAnswerCallbackQuery
:if (!any $teAnswerCallbackQuery) do={ :global teAnswerCallbackQuery do={

	:local botID $fBotID

	:local tgUrl []; :local content []

	:if ([:len $fAlert] = 0) do={ :set $fAlert false }

	:set tgUrl "https://api.telegram.org/$botID/answerCallbackQuery\?callback_query_id=$fQueryID&text=$fAnswerText&show_alert=fAlert"

	do {
		:set content [:tool fetch ascii=yes url=$tgUrl as-value output=user]
	} on-error={ :return false }

	:if ($content->"status" = "finished")	do={
		:return true
	} else={ :return false }
    }
}


Варианты использования:

Код: Выделить всё


	:global teAnswerCallbackQuery

	:local fQueryID 12345
	:local answerText "Answer Text"
	:local botID "botxxxxxxxxx:FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
	
	:local result [$teAnswerCallbackQuery fBotID=$botID fQueryID=$queryID fAnswerText=$answerText]

Возвращает true, если все хорошо и false, если не очень.

-
 UPD: 26.07.2022 Функция построения кнопки teBuildButton

К сообщению можно прикрепить клавиатуру, которая состоит из inline кнопок.
Для этого надо сформировать объект InlineButton в формате JSON. Функция строит
такой объект и возвращает в виде строки. Получается кнопка, которая вставляется в клавиатуру.

В качестве параметров в функцию передается fPictButton - это эмоджи в hex формате, fTextButton - текст кнопки,
дальше на выбор:

url - тип строка, любой url адрес;
SwitchCurrentChat - тип строка, вставляет в поле для ввода имя бота и текст, присвоенный этой переменной;
fTextCallBack - тип строка, это текст команды, которая прилетает в ответ на нажатие кнопки.

 Код функции teBuildButton

Код: Выделить всё


#---------------------------------------------------teBuildButton--------------------------------------------------------------

#   Function build button and returns it in text format
#   Params for this function:

#   1.  fPictButton     			-   picture for the button from Emoji Unicode Tables
#   2.  fTextButton     			-   text for the button
#   3.  fUrlButton	   			  -   URL for the button
#   4.  fSwitchCurrentChat	  -   URL for the button
#   5.  fTextCallBack    			-   callback for the button


#---------------------------------------------------teBuildButton--------------------------------------------------------------

:global teBuildButton
:if (!any $teBuildButton) do={ :global teBuildButton do={

	:local startButton "\7B\22text\22: \22 "
	:local startUrl "\22,\22url\22: \22"
	:local startCallBack " \22,\22callback_data\22: \22"
	:local startSwitchCurrentChat " \22,\22switch_inline_query_current_chat\22: \22"
	:local endButton "\22\7D"
	:local button []

	:set button "$startButton$fPictButton$fTextButton$startCallBack$fTextCallBack$endButton"

	:if ([:len $fUrlButton] != 0) do={
		:set button "$startButton$fPictButton$fTextButton$startUrl$fUrlButton$startCallBack$fTextCallBack$endButton"
	}
	:if ([:len $fSwitchCurrentChat] != 0) do={
		:set button "$startButton$fPictButton$fTextButton$startSwitchCurrentChat$fSwitchCurrentChat$endButton"
	}
	:put "teBuildButton = $button"
	:return $button
	}
}



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

Рассмотрим подробнее параметр fTextCallBack. Ему присвоено значение "teCallbackLeaseCard,isBlocked,true"

Код: Выделить всё

    
    :global teBuildButton 
    :local pictDeny "\E2\9B\94"
    :local buttonDenyCallBackText "teCallbackLeaseCard,isBlocked,true"
    
    :local buttonDeny [$teBuildButton fPictButton=$pictDeny fTextButton="  Deny" fTextCallBack=$buttonDenyCallBackText]

В данном случае:
teCallbackLeaseCard - это имя функции, которой будет передано управление;
isBlocked - команда, которая будет выполнена этой функцией.
true - значение этой команды

Значения переменной fTextCallBack перечисляются через запятую, так удобно парсить команду в массив.
Их может быть несколько, но не более 64 символов из-за ограничений Телеграм.

В примере выше, функция возвратит результат в переменную buttonDeny в виде строки.

 Функция построения клавиатуры teBuildKeyboard

Сформированные функцией teBuildButton кнопки, передаются в функцию teBuildKeyboard.
К сообщению можно прикрепить два вида клавиатур на выбор. Это Inline или Reply клавиатура.

Их различия в том, что Inline прикрепляется к телу сообщения, а Reply выводится внизу взамен
стандартной.

 Код функции teBuildKeyboard

Код: Выделить всё


#---------------------------------------------------teBuildKeyboard--------------------------------------------------------------

#   Function builds a keyboard from an array of buttons
#   and return keyBoard in text format
#   Params for this function:

#   1.  fButtonsKeyBoard      -   an array of buttons formed by a function teBuildButton
#   2.  fReplyKeyboard        -   keyboard type, reply or inline (true or false)
#   3.  fReplyOneTime         -   Requests clients to hide the keyboard as soon as it's been used (true or false)
#   4.  fReplyResize          -   Requests clients to resize the keyboard vertically for optimal fit (true or false)
#   5.  fPlaceholder          -   The placeholder to be shown in the input field when the keyboard is active; 1-64 characters (hint in the input field)
#   6.  fReplySelective       -   Use this parameter if you want to show the keyboard to specific users only (true or false)

#---------------------------------------------------teBuildKeyboard--------------------------------------------------------------

:global teBuildKeyboard
:if (!any $teBuildKeyboard) do={ :global teBuildKeyboard do={

  :local keyBoard []
  :local startKeyBoard []
  :local resizeKeyboard []
  :local ontimeKeyboard []
  :local inputFieldPlaceholder []
  :local selectiveKeyboard []

  :if ($fReplyResize = false or [:len $fReplyResize] = 0) do={
    :set resizeKeyboard "\5D\5D,\22resize_keyboard\22:false"
  } else={
    :set resizeKeyboard "\5D\5D,\22resize_keyboard\22:true"
  }

  :if ($fReplyOneTime = false or [:len $fReplyOneTime] = 0) do={
    :set ontimeKeyboard ",\22one_time_keyboard\22:false"
  } else={
    :set ontimeKeyboard ",\22one_time_keyboard\22:true"
  }

  :if ($fReplySelective = false  or [:len $fReplySelective] = 0) do={
    :set selectiveKeyboard ",\22selective\22:false"
  } else={
    :set selectiveKeyboard ",\22selective\22:true"
  }

  :if ([:len $fPlaceholder] != 0) do={
    :if ([:len $fPlaceholder] > 64) do={:set $fPlaceholder [:pick $fPlaceholder 0 63]}
    :set inputFieldPlaceholder ",\22input_field_placeholder\22:\22$fPlaceholder\22"
  } else={
    :set inputFieldPlaceholder ""
  }

  :local endReplyKeyBoard "\7D"
  :local endKeyBoard "\5D\5D\7D"

	:if ($fReplyKeyboard = true) do={
		:set startKeyBoard "\7B\22keyboard\22: \5B\5B"
    :set keyBoard "$startKeyBoard$fButtonsKeyBoard$resizeKeyboard$ontimeKeyboard$inputFieldPlaceholder$selectiveKeyboard$endReplyKeyBoard"
	} else={
		:set startKeyBoard "\7B\22inline_keyboard\22: \5B\5B"
		:set keyBoard "$startKeyBoard$fButtonsKeyBoard$endKeyBoard"
	}
	:return $keyBoard
	}
}



В примере ниже формируются две кнопки, buttonDeny и buttonAllow .
Они объединяются в одну строку в переменной buttons .

Переменная :local NB "," содержит признак новой кнопки. Если ее вставить между двух кнопок, то они будут располагаться в одной строке.

Переменная :local NL "\5D,\5B" признак новой линии. Если ее вставить между двух кнопок, то они будут располагаться одна под другой.

Между кнопок обязательно должен присутствовать один из этих разделителей.

Код: Выделить всё

    :global teBuildButton 
    :global teBuildKeyboard 

    :local pictDeny "\E2\9B\94"
    :local buttonDenyCallBackText "teCallbackLeaseCard,isBlocked,true"
    :local buttonDeny [$teBuildButton fPictButton=$pictDeny fTextButton="  Deny" fTextCallBack=$buttonDenyCallBackText]

    :local pictAllow "\E2\9C\85"
    :local buttonAllowCallBackText "teCallbackLeaseCard,isBlocked,false"
    :local buttonAllow [$teBuildButton fPictButton=$pictAllow fTextButton="  Allow" fTextCallBack=$buttonAllowCallBackText]
    
    :local NB ","	
    :local NL "\5D,\5B"
    :local buttons "$buttonDeny$NB$buttonAllow "

    :local replyMarkup [$teBuildKeyboard fButtonsKeyBoard=$buttons fReplyKeyboard=false]
Функция вернет в переменную replyMarkup сформированную клавиатуру в виде строки.
Теперь мы можем прикрепить её к нашему сообщению.

Код: Выделить всё

#	Сообщение с текстом и клавиатурой

	:global teSendMessage
	
	:local botID "botxxxxxxxxx:FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
	:local sendText "Any text..."
	:local chatID 1234567890
	
	:local messageID [$teSendMessage fBotID=$botID fChatID=$chatID fText=$sendText fReplyMarkup=$replyMarkup]
 Функция для построения кнопки teBuildReplyButton

Как писал выше, клавиатуры бывают двух типов, это Inline или Reply . Для построения последней, нужна
кнопка типа ReplyButton.

Функция teBuildReplyButton строит такую кнопку.

 Код функции teBuildReplyButton

Код: Выделить всё


#---------------------------------------------------teBuildReplyButton--------------------------------------------------------------

#   Function build reply button and returns it in text format
#   Params for this function:

#   1.  fPictButton      -   picture for the button from Emoji Unicode Tables
#   2.  fTextButton      -   text for the button

#---------------------------------------------------teBuildReplyButton--------------------------------------------------------------

:global teBuildReplyButton
:if (!any $teBuildReplyButton) do={ :global teBuildReplyButton do={

	:local startButton "\22"
	:local endButton "\22"

	:local button "$startButton$fPictButton$fTextButton$endButton"
	:return $button
	}
}


В параметрах указываются:

fPictButton - тип строка, содержит эмоджи в формате hex
fTextButton - текст кнопки. Этот текст будет отправлен в качестве сообщения, при нажатии на кнопку.

Код: Выделить всё


	:global teBuildReplyButton
	:global teBuildKeyboard 

	:local pictStatic "\F0\9F\93\8C"
	:local textStaticButton " Make static"
	:local buttonStatic [$teBuildReplyButton fPictButton=$pictStatic fTextButton=$textStaticButton ]

	:local pictNonStatic "\E2\9A\99"
	:local textNonStatiсButton " Non static"
	:local buttonNonStatic [$teBuildReplyButton fPictButton=$pictNonStatic fTextButton=$textNonStatiсButton ]

	:local NB ","	
	:local NL "\5D,\5B"

	:local buttons "$buttonStatic$NL$buttonNonStatic "

	:local replyMarkup [$teBuildKeyboard fButtonsKeyBoard=$buttons fReplyKeyboard=true]
	
Функция teBuildReplyButton возвращает кнопку ReplyButton в текстовом виде.

В этом примере строятся две кнопки buttonStatic и buttonNonStatic .
Они объединяются в одну строку в переменной buttons .

Переменная :local NB "," содержит признак новой кнопки. Если ее вставить между двух кнопок, то они будут располагаться в одной строке.
Переменная :local NL "\5D,\5B" признак новой линии. Если ее вставить между двух кнопок, то они будут располагаться одна под другой.

Между кнопок обязательно должен присутствовать один из этих разделителей.

Переменная buttons передается в качестве параметра в функцию teBuildKeyboard.
Для построения Reply клавиатуры параметр fReplyKeyboard должен быть равен true.

-
 UPD: 12.08.2022 Функция генерации рандомного значения teGenValue

Эта функция генерирует рандомную строку, обращаясь к ресурсу www.random.org
С её помощью можно генерировать пароли различной длины и состава.

 Код функции teGenValue

Код: Выделить всё

#---------------------------------------------------teGenValue--------------------------------------------------------------

#   Function generates a value with the specified parameters using the www.random.com website API
#		and returns it in text format
#   Params for this function:

#   1.  fValueLen      -   value length
#   2.  fDigits 	     -   on/off digits
#   3.  fUpperAlpha    -   on/off upper case characters
#   3.  fLowerAlpha    -   on/off lowercase characters
#   3.  fUnique    		 -   on/off uniqueness


#---------------------------------------------------teGenValue--------------------------------------------------------------

:global teGenValue
:if (!any $teGenValue) do={ :global teGenValue do={

	:local newValue []

	:if ([:len $fValueLen] = 0) do={ :set $fValueLen 8 }
	:if ([:len $fDigits] = 0) do={ :set $fDigits "on" }
	:if ([:len $fUpperAlpha] = 0) do={ :set $fUpperAlpha "on" }
	:if ([:len $fLowerAlpha] = 0) do={ :set $fLowerAlpha "on" }
	:if ([:len $fUnique] = 0) do={ :set $fUnique "on" }

	:local valueURL "https://www.random.org/strings/?num=1&len=$fValueLen&digits=$fDigits&upperalpha=$fUpperAlpha&loweralpha=$fLowerAlpha&unique=$fUnique&format=plain&rnd=new"

	do {
	:set newValue [:tool fetch ascii=yes url=$valueURL as-value output=user]
	} on-error={ :return false }
	
	:if ($newValue->"status" = "finished")	do={
		:set newValue ($newValue->"data")
		:set newValue ($newValue [:pick $newValue 0 $fValueLen])
	} else={
		:set newValue false
	}
	:return $newValue
 }
}

Параметры:

fValueLen - желаемая длина строки, тип num
fDigits - использовать цифры on/off
fUpperAlpha - использовать верхний регистр on/off
fLowerAlpha - использовать нижний регистр on/off
fUnique - признак уникальности каждого символа on/off

По-умолчанию длина строки=8, все опции включены.

Варианты использования

Код: Выделить всё

:global teGenValue

:local newSecret [$teGenValue fValueLen=10 fDigits=on fUpperAlpha=on fLowerAlpha=on fUnique=on]
Функция возвращает сгенерированную строку или false, если что-то пошло не так.




mikrotik,telegram,bot
Последний раз редактировалось Brook 21 авг 2022, 20:21, всего редактировалось 37 раз.


Sertik
Сообщения: 1598
Зарегистрирован: 15 сен 2017, 09:03

Очень интересно ! Обязательно посмотрю. Автору респект !


фрагменты скриптов, готовые работы, статьи, полезные приемы, ссылки
viewtopic.php?f=14&t=13947
Аватара пользователя
podarok66
Модератор
Сообщения: 4355
Зарегистрирован: 11 фев 2012, 18:49
Откуда: МО

Спасибо, милости просим на форум.


Мануалы изучил и нигде не ошибся? Фаервол отключил? Очереди погасил? Витая пара проверена? ... Тогда Netinstal'ом железку прошей и настрой ее заново. Что, все равно не фурычит? Тогда к нам. Если не подскажем, хоть посочувствуем...
Аватара пользователя
Brook
Сообщения: 127
Зарегистрирован: 24 май 2022, 00:29

Добавлять новый код буду в первое сообщение, чтобы не пришлось его искать по всему топику.
Наверное так будет удобнее...


Sertik
Сообщения: 1598
Зарегистрирован: 15 сен 2017, 09:03

Уважаемый, Brook !

Вы прибавьте, пожалуйста, инструкцию по сборке всего в рабочую систему.
Копируем Ваши функции в скрипт, запускаем, функции помещаются в окружение под именами глобальных переменных ...
А дальше ? Кто главный скрипт ? Как получить доступ к Вашему боту ? Нужно как-то регистрироваться, где, как ? Платно, пока бесплатно, дальше платно ? Как всё будет для пользователя ?


фрагменты скриптов, готовые работы, статьи, полезные приемы, ссылки
viewtopic.php?f=14&t=13947
Аватара пользователя
Brook
Сообщения: 127
Зарегистрирован: 24 май 2022, 00:29

Согласен. Давайте немного поясню.

Сейчас я выкладываю библиотеку для работы с Телеграм, которую можно использовать в своих скриптах.
Сегодня добавлю функции построения кнопок и клавиатур.

Каждая функция разворачивается в глобальную переменную и находится в постоянном доступе.
Её можно вызвать в любой момент из консоли или скрипта.

 Покажу на примере

Отправим фото c подписью в чат, вызвав функцию teSendPhoto .

Код: Выделить всё


:local botID "bot..."
:local chatID 1234567890
:local image "https://habrastorage.org/webt/kz/uh/xm/kzuhxmsrjq7mrzqin8aznrrhclw.jpeg"
:local text "<b>Hello, World!!!</b>"

:put [$teSendPhoto fBotID=$botID fChatID=$chatID fPhoto=$image fText=$text ]

Если функция уже развернута, то попробуйте выполнить эту команду в терминале, только подставьте свой chatID и botID

Изображение

Получится следующий результат.

Изображение

Функция вернет номер сообщения, который присвоил Телеграм. В данном случае 2602. Теперь, можно редактировать это сообщение, зная его номер.


Функций в составе, пока 36. Из них, как из кирпичей, строится бот.

Во главе скрипт mainBot. Он работает в бесконечном цикле и принимает обновления от Телеграмм. В зависимости от типа сообщения вызывается функция обработчик, которая в свою очередь вызывает другие функции.

 Скрин кода
Изображение

Полный код состоит из 56 скриптов. Разворачивается скриптом автоматически. Настройки хранятся в массиве.

 Настройки выглядят вот так...

Изображение

Планировалось создать сайт и опубликовать всё там. Для пользователя бесплатным сделать ядро бота. Чтобы все желающие
могли добавлять свой функционал. Примеры и инструкции разместить там же.

В базе будет скелет бота с Terminal, System menu, Scripts и Interfaces. Модули ppp, dhcp и users хотели монетизировать, но не дорого.

У инвестора небольшие проблемы и о точных сроках сказать пока ничего не могу. Поэтому выкладываю для сообщества библиотеки уже сейчас, чтобы их могли использовать все желающие. Если в ближайшее время найдется другой инвестор, возможно к концу лета всё запустим.
Последний раз редактировалось Brook 05 авг 2022, 11:50, всего редактировалось 1 раз.


Sertik
Сообщения: 1598
Зарегистрирован: 15 сен 2017, 09:03

Спасибо, здорово !
Кроме инвесторов почему бы Вам не открыть что-то типа благотворительного счёта для "пожертвований по желанию" для разработчиков.
Чтобы можно было переводить пожертвования с помощью SMS, например.
Видно же что делается не поделка, а хорошая функциональная вещь ... Понятно, что есть риск быть обвиненными в мошенничестве, я не силён в юридических аспектах подобных "благотворительных переводов", но как то это же делается и вполне законно.

Я, конечно, не инвестор, но целиком на Вашей стороне и с удовольствием перевел бы некую сумму ... Думаю, что на форуме нашлись бы люди, которые сделали бы тоже самое ...


фрагменты скриптов, готовые работы, статьи, полезные приемы, ссылки
viewtopic.php?f=14&t=13947
Аватара пользователя
Brook
Сообщения: 127
Зарегистрирован: 24 май 2022, 00:29

Благодарю за отзыв.

Есть конечно вариант с донатами, но мне он не очень нравится. По закону донат - это дар, не облагается налогом и, чисто юридически, не предполагает встречных обязательств. Но появляются обязательства человеческие. Люди, которые перечислят деньги, будут надеяться на какой-то результат. Но его может не быть, если не наберется необходимая сумма. Это репутационные риски.

Рассмотрел бы другой вариант. Чтобы запустить проект, нужен сайт и технический писатель, для создания мануалов и примеров. Если среди сообщества найдутся люди, готовые помочь с этим, то можно попробовать. В качестве благодарности, таким людям могу предложить полный код бота, со всеми модулями, текущими и будущими, т.к. функционал со временем будет расширяться.

Кстати по поводу функционала. В Микротике нет никакой СУБД (системы управления базами данных). А было бы неплохо хранить данные в базе. У меня уже есть наработки по этой теме. Можно создать реляционную СУБД на основе двумерных массивов, с языком запросов, похожим на SQL.

Частично это задумка реализована в функции teDbSave, её код выложу позже. Она сохраняет массив, развернутый в глобальной переменной, в скрипт, который при запуске разворачивает этот массив обратно в глобальную переменную. Получается такой саморазворачивающийся массив данных, который не обнулится при перезапуске устройства. Сохранять массив можно по шедулеру или после каждого изменения.


Sertik
Сообщения: 1598
Зарегистрирован: 15 сен 2017, 09:03

Насчет последнего ... Не совсем то, но может пригодится ...
Функция сохранения глобальных переменных в /ip firewall layer7

viewtopic.php?f=14&t=13768


фрагменты скриптов, готовые работы, статьи, полезные приемы, ссылки
viewtopic.php?f=14&t=13947
Аватара пользователя
Brook
Сообщения: 127
Зарегистрирован: 24 май 2022, 00:29

Sertik писал(а): 27 июл 2022, 14:02 Насчет последнего ... Не совсем то, но может пригодится ...
Функция сохранения глобальных переменных в /ip firewall layer7

viewtopic.php?f=14&t=13768
Да, я читал этот пост. Там сохраняется в поле Regexp, но речь только о переменных.
Кстати, массив хранится в переменной не так, как объявляется.

 Вот один из способов создания двумерного массива
Изображение
-
 Он развернется в глобальную переменную в таком виде
Изображение

Чтобы он сам развернулся обратно без ошибок, его надо сохранить так же, как на скрине выше.
Это не слишком сложная задача. Но, что в layer7, что в Scripts, есть ограничение на длину текста.
Писать надо в файл. Там таких ограничений нет.

Кстати, хочу поделиться одним наблюдением. Как известно, ограничение на длину переменной в
Микротик 4096 байт. Но на глобальные переменные, это ограничение не действует.

Похоже, что ограничивается только оперативной памятью. Можете сами провести эксперимент.
Эта команда добавляет в глобальный массив 1 132 197 строковых элемента "str=$key"

Изображение

На вкладке Environment эта переменная с массивом не отобразится. Но в памяти массив будет
лежать и все его элементы будут доступны. Этот факт делает возможным создание СУБД.

В данном случае, на моем RB4011 массив занял примерно 25 Мб оперативной памяти.

UPD:
Писать надо в файл. Там таких ограничений нет.
Они есть но другие, примерно 64 Кб. получилось сохранить в один файл из массива.
А если сохранять скрипты командой Export в один файл, то ограничений по размеру не увидел.


Ответить