diff options
| author | Maria Lisina <sekoohaka.sarisan@gmail.com> | 2026-02-06 04:20:11 +0300 |
|---|---|---|
| committer | Maria Lisina <sekoohaka.sarisan@gmail.com> | 2026-02-06 04:20:11 +0300 |
| commit | 0671dc134a9e122ce2c0348f3f4deeb2d274d524 (patch) | |
| tree | f9bb88f626c1d68be98216e32b3e02f08701dac3 /operators | |
| parent | 1e79ebd5f9a288563c8bb25acacd37bd55abc2d4 (diff) | |
*/*: Rename agents to operators for alphabetical order
Signed-off-by: Maria Lisina <sekoohaka.sarisan@gmail.com>
Diffstat (limited to 'operators')
32 files changed, 2093 insertions, 0 deletions
diff --git a/operators/callback_delete.zsh b/operators/callback_delete.zsh new file mode 100644 index 0000000..a2334bf --- /dev/null +++ b/operators/callback_delete.zsh @@ -0,0 +1,54 @@ +# Copyright (C) 2024-2026 Maria Lisina +# Copyright (C) 2024-2026 Danil Lisin +# SPDX-License-Identifier: Apache-2.0 + +chat_id="$(jq -r '.callback_query.message.chat.id' <<< "${update}")" +message_id="$(jq -r '.callback_query.message.message_id' <<< "${update}")" + +if ! output_data="$( + curl --connect-timeout ${connrefused_timeout} \ + --data-urlencode "chat_id=${chat_id}" \ + --data-urlencode "message_id=${message_id}" \ + --get \ + --max-time ${internal_timeout} \ + --proxy "${internal_proxy}" \ + --retry 1 \ + --retry-connrefused \ + --retry-max-time $((internal_timeout - connrefused_timeout)) \ + --silent \ + --user-agent "${useragent}" \ + "${api_address}/bot${api_token}/deleteMessage" +)" +then + notification_text="Failed to delete message" + + log_text="deleteMessage (${update_id}): Failed to access Telegram Bot API" + source "${units}/log.zsh" + + return +fi + +if ! jq -e '.' <<< "${output_data}" > /dev/null +then + notification_text="An unknown error occurred" + + log_text="deleteMessage (${update_id}): An unknown error occurred" + source "${units}/log.zsh" + + return +fi + +if [[ "$(jq -r '.ok' <<< "${output_data}")" != "true" ]] +then + notification_text="Failed to delete message" + error_description="$(jq -r '.description' "${output_file}")" + + if [[ "${error_description}" != "null" ]] + then + log_text="deleteMessage (${update_id}): ${error_description}" + else + log_text="deleteMessage (${update_id}): An unknown error occurred" + fi + + source "${units}/log.zsh" +fi diff --git a/operators/callback_post.zsh b/operators/callback_post.zsh new file mode 100644 index 0000000..301001f --- /dev/null +++ b/operators/callback_post.zsh @@ -0,0 +1,61 @@ +# Copyright (C) 2024-2026 Maria Lisina +# Copyright (C) 2024-2026 Danil Lisin +# SPDX-License-Identifier: Apache-2.0 + +ib_lock=0 +source "${units}/ib_common.zsh" + +if [[ -n "${notification_text}" ]] +then + return +fi + +ib_hash="$(sha1sum <<< "${user_id}${ib_board}${ib_query}" | cut -d ' ' -f 1)" +ib_file="${cache}/${ib_hash}.json" + +until mkdir "${cache}/${ib_hash}.lock" +do + sleep 1 +done + +source "${units}/ib_file.zsh" + +if [[ -n "${notification_text}" ]] +then + rmdir "${cache}/${ib_hash}.lock" + return +fi + +source "${units}/ib_post.zsh" + +link_preview_options="$( + jq --null-input --compact-output \ + --arg url "${ib_sample_url}" \ + '{"url": $url, "prefer_small_media": true, "show_above_text": true}' +)" + +keyboard_text1="Post link" +keyboard_url1="${ib_url}$(urlencode <<< "${ib_id}")" + +reply_markup="$( + jq --null-input --compact-output \ + --arg text1 "${keyboard_text1}" \ + --arg url1 "${keyboard_url1}" \ + '{"inline_keyboard": [[{"text": $text1, "url": $url1}]]}' +)" + +if [[ ${#ib_tags} -gt 0 ]] +then + keyboard_text1="Tags (${#ib_tags})" + keyboard_data1="tags ${ib_board} ${ib_post_id}" + + reply_markup="$( + jq --compact-output \ + --arg text1 "${keyboard_text1}" \ + --arg data1 "${keyboard_data1}" \ + '.inline_keyboard[0] += [{"text": $text1, "callback_data": $data1}]' \ + <<< "${reply_markup}" + )" +fi + +rmdir "${cache}/${ib_hash}.lock" diff --git a/operators/callback_short.zsh b/operators/callback_short.zsh new file mode 100644 index 0000000..a48a27c --- /dev/null +++ b/operators/callback_short.zsh @@ -0,0 +1,54 @@ +# Copyright (C) 2024-2026 Maria Lisina +# Copyright (C) 2024-2026 Danil Lisin +# SPDX-License-Identifier: Apache-2.0 + +until mkdir "${user_config}_shorts.lock" +do + sleep 1 +done + +if [[ -n "${1}" ]] +then + short_query="${@}" + shift ${#} +else + notification_text="You must specify query" + + rmdir "${user_config}_shorts.lock" + return +fi + +shorts_config="${user_config}/shorts" + +if ! mkdir -p "${shorts_config}" +then + notification_text="Failed to create user config" + + rmdir "${user_config}_shorts.lock" + return +fi + +short_hash="$(sha1sum <<< "${short_query}" | cut -d ' ' -f 1)" +short="${shorts_config}/${short_hash}" +shorts=($(ls -1 "${shorts_config}")) + +if [[ -f "${short}" ]] +then + rm -f "${short}" + notification_text="Removed shortcut" +elif [[ ${#shorts} -le ${shorts_limit} ]] +then + printf "%s\n" "${short_query}" > "${short}" + notification_text="Saved shortcut" +else + notification_text="Too many shortcuts" +fi + +shorts=($(ls -1 "${shorts_config}")) + +if [[ ${#shorts} -eq 0 ]] +then + rmdir "${shorts_config}" +fi + +rmdir "${user_config}_shorts.lock" diff --git a/operators/callback_stop.zsh b/operators/callback_stop.zsh new file mode 100644 index 0000000..d2eab2c --- /dev/null +++ b/operators/callback_stop.zsh @@ -0,0 +1,70 @@ +# Copyright (C) 2024-2026 Maria Lisina +# Copyright (C) 2024-2026 Danil Lisin +# SPDX-License-Identifier: Apache-2.0 + +if [[ -n "${1}" ]] +then + data_name="${1}" + check_table=(${data_table[@]}) + shift +fi + +while [[ ${#check_table} -ge 2 ]] +do + if [[ "${data_name}" == "${check_table[1]}" ]] + then + break + elif [[ "${check_table[1]}" == "${check_table[-2]}" ]] + then + notification_text="No requested data found" + return + fi + + shift 2 check_table +done + +if mkdir "${user_config}_stop.lock" +then + notification_text="Click again to confirm data removal" + return +fi + +for lock in ${user_locks[@]} +do + until mkdir "${user_config}_${lock}.lock" + do + sleep 1 + done +done + +if [[ -n "${data_name}" ]] +then + if ! rm -fr "${user_config}/${check_table[1]}" + then + notification_text="Something went wrong, try again later" + fi +else + if ! rm -fr "${user_config}" + then + notification_text="Something went wrong, try again later" + fi +fi + +if [[ -d "${user_config}" ]] +then + user_data=($(ls -1 "${user_config}")) + + if [[ ${#user_data} -eq 0 ]] + then + rmdir "${user_config}" + fi +fi + +source "${units}/stop.zsh" + +for lock in ${user_locks[@]} +do + rmdir "${user_config}_${lock}.lock" +done + +rmdir "${user_config}_stop.lock" diff --git a/operators/callback_tags.zsh b/operators/callback_tags.zsh new file mode 100644 index 0000000..803c0dd --- /dev/null +++ b/operators/callback_tags.zsh @@ -0,0 +1,144 @@ +# Copyright (C) 2024-2026 Maria Lisina +# Copyright (C) 2024-2026 Danil Lisin +# SPDX-License-Identifier: Apache-2.0 + +ib_lock=0 +source "${units}/ib_common.zsh" + +if [[ -n "${notification_text}" ]] +then + return +fi + +ib_hash="$(sha1sum <<< "${user_id}${ib_board}${ib_query}" | cut -d ' ' -f 1)" +ib_file="${cache}/${ib_hash}.json" + +until mkdir "${cache}/${ib_hash}.lock" +do + sleep 1 +done + +source "${units}/ib_file.zsh" + +if [[ -n "${notification_text}" ]] +then + rmdir "${cache}/${ib_hash}.lock" + return +fi + +ib_file_size="$(jq -r ".${ib_iarray}[0].${ib_isize}" "${ib_file}")" +ib_file_url="$(jq -r ".${ib_iarray}[0].${ib_ifile}" "${ib_file}")" +ib_sample_url="$(jq -r ".${ib_iarray}[0].${ib_isample}" "${ib_file}")" +ib_preview_url="$(jq -r ".${ib_iarray}[0].${ib_ipreview}" "${ib_file}")" +ib_width="$(jq -r ".${ib_iarray}[0].${ib_iwidth}" "${ib_file}")" +ib_height="$(jq -r ".${ib_iarray}[0].${ib_iheight}" "${ib_file}")" +ib_tags=($(jq -r ".${ib_iarray}[0].${ib_itags}" "${ib_file}")) +ib_groups_offset=${1:-0} +ib_tags_offset=${1:-0} + +source "${units}/ib_size.zsh" +source "${units}/ib_meta.zsh" + +if [[ -z "${ib_tags}" || "${ib_tags}" == "null" ]] +then + notification_text="Failed to get tags" + + rmdir "${cache}/${ib_hash}.lock" + return +fi + +while [[ ${#ib_groups} -ge 2 ]] +do + ib_group_tags=($(jq -r ".${ib_iarray}[0].${ib_groups[1]}" "${ib_file}" | htmlescape)) + ib_group_name="${ib_groups[2]}" + + if [[ -z "${ib_group_tags}" || "${ib_group_tags}" == "null" ]] + then + shift 2 ib_groups + continue + fi + + if [[ ${#ib_group_tags} -gt ${ib_groups_offset} ]] + then + shift ${ib_groups_offset} ib_group_tags + ib_groups_offset=0 + else + ib_groups_offset=$((ib_groups_offset - $#ib_group_tags)) + shift 2 ib_groups + continue + fi + + ib_group_text="$(printf "%s\n<b>%s:</b>" "${output_text}" "${ib_group_name}")" + + while [[ ${#ib_group_tags} -gt 0 ]] + do + ib_tag="<code>${ib_group_tags[1]}</code>" + + if [[ $(($#ib_group_text + $#ib_tag)) -gt 2048 ]] + then + break 2 + fi + + ib_group_text="${ib_group_text} ${ib_tag}" + ib_tags_count=$((ib_tags_count + 1)) + + output_text="${ib_group_text}" + shift 1 ib_group_tags + done + + shift 2 ib_groups +done + +if [[ -z "${output_text}" ]] +then + notification_text="No tags found" + + rmdir "${cache}/${ib_hash}.lock" + return +fi + +link_preview_options="$( + jq --null-input --compact-output \ + --arg url "${ib_sample_url}" \ + '{"url": $url, "prefer_small_media": true, "show_above_text": true}' +)" + +keyboard_text1="Back" +keyboard_data1="post ${ib_board} ${ib_post_id}" + +reply_markup="$( + jq --null-input --compact-output \ + --arg text1 "${keyboard_text1}" \ + --arg data1 "${keyboard_data1}" \ + '{"inline_keyboard": [[{"text": $text1, "callback_data": $data1}]]}' +)" + +if [[ ${ib_tags_offset} -gt 0 ]] +then + keyboard_text1="Over" + keyboard_data1="tags ${ib_board} ${ib_post_id}" + + reply_markup="$( + jq --compact-output \ + --arg text1 "${keyboard_text1}" \ + --arg data1 "${keyboard_data1}" \ + '.inline_keyboard[0] += [{"text": $text1, "callback_data": $data1}]' \ + <<< "${reply_markup}" + )" +fi + +if [[ $(($#ib_tags - ib_tags_offset - ib_tags_count)) -gt 0 ]] +then + keyboard_text1="Next" + keyboard_data1="tags ${ib_board} ${ib_post_id} $((ib_tags_offset + ib_tags_count))" + + reply_markup="$( + jq --compact-output \ + --arg text1 "${keyboard_text1}" \ + --arg data1 "${keyboard_data1}" \ + '.inline_keyboard[0] += [{"text": $text1, "callback_data": $data1}]' \ + <<< "${reply_markup}" + )" +fi + +rmdir "${cache}/${ib_hash}.lock" diff --git a/operators/command_authorize.zsh b/operators/command_authorize.zsh new file mode 100644 index 0000000..a8be540 --- /dev/null +++ b/operators/command_authorize.zsh @@ -0,0 +1,40 @@ +# Copyright (C) 2024-2026 Maria Lisina +# Copyright (C) 2024-2026 Danil Lisin +# SPDX-License-Identifier: Apache-2.0 + +if [[ -n "${1}" ]] +then + ib_board="${1}" + source "${units}/ib_config.zsh" + source "${units}/ib_authconfig.zsh" + + if [[ -z "${ib_auth}" ]] + then + output_text="Unsupported Image Board" + return + fi + + shift +else + output_text="You must specify Image Board" + return +fi + +if [[ -n "${1}" ]] +then + ib_login="${1}" + shift +fi + +if [[ -n "${1}" ]] +then + ib_key="${1}" + shift +fi + +source "${units}/ib_lock.zsh" + +if [[ -z "${output_text}" ]] +then + output_text="Authorized successfully" +fi diff --git a/operators/command_donate.zsh b/operators/command_donate.zsh new file mode 100644 index 0000000..fa7518c --- /dev/null +++ b/operators/command_donate.zsh @@ -0,0 +1,10 @@ +# Copyright (C) 2024-2026 Maria Lisina +# Copyright (C) 2024-2026 Danil Lisin +# SPDX-License-Identifier: Apache-2.0 + +if [[ -n "${nocommand_donate}" ]] +then + exit 0 +fi + +output_text="${donate_content}" diff --git a/operators/command_export.zsh b/operators/command_export.zsh new file mode 100644 index 0000000..fe68802 --- /dev/null +++ b/operators/command_export.zsh @@ -0,0 +1,29 @@ +# Copyright (C) 2024-2026 Maria Lisina +# Copyright (C) 2024-2026 Danil Lisin +# SPDX-License-Identifier: Apache-2.0 + +if [[ "${chat_id}" != "${target_user}" ]] +then + output_text="For security reasons you can execute this command only in direct messages" + return +fi + +for lock in ${user_locks[@]} +do + until mkdir "${user_config}_${lock}.lock" + do + sleep 1 + done +done + +source "${units}/export.zsh" + +for lock in ${user_locks[@]} +do + rmdir "${user_config}_${lock}.lock" +done + +if [[ -z "${output_text}" ]] +then + exit 0 +fi diff --git a/operators/command_hash.zsh b/operators/command_hash.zsh new file mode 100644 index 0000000..d8bb677 --- /dev/null +++ b/operators/command_hash.zsh @@ -0,0 +1,75 @@ +# Copyright (C) 2024-2026 Maria Lisina +# Copyright (C) 2024-2026 Danil Lisin +# SPDX-License-Identifier: Apache-2.0 + +if [[ -n "${1}" ]] +then + ib_post_md5="${1}" + shift +else + output_text="You must specify MD5 hash" + return +fi + +if ! [[ ${#ib_post_md5} -eq 32 ]] +then + output_text="Invalid MD5 hash" + return +fi + +ib_post="${cache}/${update_id}_id.txt" +ib_sample="${cache}/${update_id}_sample.txt" + +for lock in "${ib_post}" "${ib_sample}" +do + until mkdir "${lock%.*}.lock" + do + sleep 1 + done +done + +for ib_board in {a..z} +do + source "${units}/ib_config.zsh" + source "${units}/ib_hash.zsh" & + wait + + if ! [[ -f "${ib_post}" ]] + then + continue + fi + + ib_id="$(< "${ib_post}")" + + keyboard_text1="${ib_name}" + keyboard_query1="post ${ib_board} ${ib_id}" + + reply_markup="$( + jq --compact-output \ + --argjson offset "$(printf "%u" "${keyboard_offset}")" \ + --arg text1 "${keyboard_text1}" \ + --arg query1 "${keyboard_query1}" \ + '.inline_keyboard[$offset] += [{"text": $text1, "switch_inline_query_current_chat": $query1}]' \ + <<< "${reply_markup:-"{}"}" + )" + + keyboard_offset=$((keyboard_offset + 0.5)) +done + +if [[ -f "${ib_sample}" ]] +then + output_text="$(printf "<b>MD5:</b> <code>%s</code>" "${ib_post_md5}")" + + link_preview_options="$( + jq --null-input --compact-output \ + --arg url "$(< "${ib_sample}")" \ + '{"url": $url, "prefer_small_media": true, "show_above_text": true}' + )" +else + output_text="No results found" +fi + +for lock in "${ib_post}" "${ib_sample}" +do + rmdir "${lock%.*}.lock" +done diff --git a/operators/command_help.zsh b/operators/command_help.zsh new file mode 100644 index 0000000..2d86678 --- /dev/null +++ b/operators/command_help.zsh @@ -0,0 +1,10 @@ +# Copyright (C) 2024-2026 Maria Lisina +# Copyright (C) 2024-2026 Danil Lisin +# SPDX-License-Identifier: Apache-2.0 + +output_text="${help_content}" + +link_preview_options="$( + jq --null-input --compact-output \ + '{"is_disabled": true}' +)" diff --git a/operators/command_original.zsh b/operators/command_original.zsh new file mode 100644 index 0000000..adeebdf --- /dev/null +++ b/operators/command_original.zsh @@ -0,0 +1,154 @@ +# Copyright (C) 2024-2026 Maria Lisina +# Copyright (C) 2024-2026 Danil Lisin +# SPDX-License-Identifier: Apache-2.0 + +source "${units}/ib_name.zsh" + +if [[ -n "${output_text}" ]] +then + return +fi + +source "${units}/ib_common.zsh" + +if [[ -n "${output_text}" ]] +then + return +fi + +ib_hash="$(sha1sum <<< "${user_id}${ib_board}${ib_query}" | cut -d ' ' -f 1)" +ib_file="${cache}/${ib_hash}.json" + +until mkdir "${cache}/${ib_hash}.lock" +do + sleep 1 +done + +source "${units}/ib_file.zsh" + +if [[ -n "${output_text}" ]] +then + rmdir "${cache}/${ib_hash}.lock" + return +fi + +source "${units}/ib_original.zsh" + +if [[ -n "${ib_file_url}" && "${ib_file_url}" != "null" ]] +then + keyboard_text1="Original file link" + keyboard_url1="${ib_file_url}" + + reply_markup="$( + jq --null-input --compact-output \ + --arg text1 "${keyboard_text1}" \ + --arg url1 "${keyboard_url1}" \ + '{"inline_keyboard": [[{"text": $text1, "url": $url1}]]}' + )" +fi + +if [[ -n "${output_text}" ]] +then + rmdir "${cache}/${ib_hash}.lock" + return +fi + +if ! output_data="$( + curl --connect-timeout ${connrefused_timeout} \ + --data-urlencode "chat_id=${chat_id}" \ + --data-urlencode "message_thread_id=${message_thread_id}" \ + --data-urlencode "action=upload_document" \ + --get \ + --max-time ${internal_timeout} \ + --proxy "${internal_proxy}" \ + --retry 1 \ + --retry-connrefused \ + --retry-max-time $((internal_timeout - connrefused_timeout)) \ + --silent \ + --user-agent "${useragent}" \ + "${api_address}/bot${api_token}/sendChatAction" +)" +then + log_text="sendChatAction (${update_id}): Failed to access Telegram Bot API" + source "${units}/log.zsh" +fi + +if [[ -z "${log_text}" ]] && ! jq -e '.' <<< "${output_data}" > /dev/null +then + log_text="sendChatAction (${update_id}): An unknown error occurred" + source "${units}/log.zsh" +fi + +if [[ -z "${log_text}" && "$(jq -r '.ok' <<< "${output_data}")" != "true" ]] +then + error_description="$(jq -r '.description' <<< "${output_data}")" + + if [[ "${error_description}" != "null" ]] + then + log_text="sendChatAction (${update_id}): ${error_description}" + else + log_text="sendChatAction (${update_id}): An unknown error occurred" + fi + + source "${units}/log.zsh" +fi + +if ! output_data="$( + curl --connect-timeout ${connrefused_timeout} \ + --data-urlencode "chat_id=${chat_id}" \ + --data-urlencode "message_thread_id=${message_thread_id}" \ + --data-urlencode "document=${ib_file_url}" \ + --data-urlencode "thumbnail=${ib_preview_url}" \ + --data-urlencode "reply_parameters=${reply_parameters}" \ + --data-urlencode "reply_markup=${reply_markup}" \ + --get \ + --max-time ${internal_timeout} \ + --proxy "${internal_proxy}" \ + --retry 1 \ + --retry-connrefused \ + --retry-max-time $((internal_timeout - connrefused_timeout)) \ + --silent \ + --user-agent "${useragent}" \ + "${api_address}/bot${api_token}/sendDocument" +)" +then + output_text="Failed to send original file" + + log_text="sendDocument (${update_id}): Failed to access Telegram Bot API" + source "${units}/log.zsh" + + rmdir "${cache}/${ib_hash}.lock" + return +fi + +if ! jq -e '.' <<< "${output_data}" > /dev/null +then + output_text="An unknown error occurred" + + log_text="sendDocument (${update_id}): An unknown error occurred" + source "${units}/log.zsh" + + rmdir "${cache}/${ib_hash}.lock" + return +fi + +if [[ "$(jq -r '.ok' <<< "${output_data}")" != "true" ]] +then + output_text="Failed to send original file" + error_description="$(jq -r '.description' <<< "${output_data}")" + + if [[ "${error_description}" != "null" ]] + then + log_text="sendDocument (${update_id}): ${error_description}" + else + log_text="sendDocument (${update_id}): An unknown error occurred" + fi + + source "${units}/log.zsh" + + rmdir "${cache}/${ib_hash}.lock" + return +fi + +rmdir "${cache}/${ib_hash}.lock" +exit 0 diff --git a/operators/command_ping.zsh b/operators/command_ping.zsh new file mode 100644 index 0000000..83ffb3b --- /dev/null +++ b/operators/command_ping.zsh @@ -0,0 +1,112 @@ +# Copyright (C) 2024-2026 Maria Lisina +# Copyright (C) 2024-2026 Danil Lisin +# SPDX-License-Identifier: Apache-2.0 + +output_text="Measuring..." +latency_init=$(strftime %s%N) + +if ! output_data="$( + curl --connect-timeout ${connrefused_timeout} \ + --data-urlencode "chat_id=${chat_id}" \ + --data-urlencode "message_thread_id=${message_thread_id}" \ + --data-urlencode "text=${output_text}" \ + --data-urlencode "reply_parameters=${reply_parameters}" \ + --get \ + --max-time ${internal_timeout} \ + --proxy "${internal_proxy}" \ + --retry 1 \ + --retry-connrefused \ + --retry-max-time $((internal_timeout - connrefused_timeout)) \ + --silent \ + --user-agent "${useragent}" \ + "${api_address}/bot${api_token}/sendMessage" +)" +then + output_text="Failed to measure latency" + + log_text="sendMessage (${update_id}): Failed to access Telegram Bot API" + source "${units}/log.zsh" + + return +fi + +latency_fin=$(strftime %s%N) + +if ! jq -e '.' <<< "${output_data}" > /dev/null +then + output_text="An unknown error occurred" + + log_text="sendMessage (${update_id}): An unknown error occurred" + source "${units}/log.zsh" + + return +fi + +if [[ "$(jq -r '.ok' <<< "${output_data}")" != "true" ]] +then + output_text="Failed to measure latency" + error_description="$(jq -r '.description' <<< "${output_data}")" + + if [[ "${error_description}" != "null" ]] + then + log_text="sendMessage (${update_id}): ${error_description}" + else + log_text="sendMessage (${update_id}): An unknown error occurred" + fi + + source "${units}/log.zsh" + return +fi + +chat_id="$(jq -r '.result.chat.id' <<< "${output_data}")" +message_id="$(jq -r '.result.message_id' <<< "${output_data}")" + +latency=$(((latency_fin - latency_init) / 1000000)) +output_text="$(printf "<b>Latency:</b> %ums" "${latency}")" + +if ! output_data="$( + curl --connect-timeout ${connrefused_timeout} \ + --data-urlencode "chat_id=${chat_id}" \ + --data-urlencode "message_id=${message_id}" \ + --data-urlencode "text=${output_text}" \ + --data-urlencode "parse_mode=HTML" \ + --get \ + --max-time ${internal_timeout} \ + --proxy "${internal_proxy}" \ + --retry 1 \ + --retry-connrefused \ + --retry-max-time $((internal_timeout - connrefused_timeout)) \ + --silent \ + --user-agent "${useragent}" \ + "${api_address}/bot${api_token}/editMessageText" +)" +then + log_text="editMessageText (${update_id}): Failed to access Telegram Bot API" + source "${units}/log.zsh" + + exit 0 +fi + +if ! jq -e '.' <<< "${output_data}" > /dev/null +then + log_text="editMessageText (${update_id}): An unknown error occurred" + source "${units}/log.zsh" + + exit 0 +fi + +if [[ "$(jq -r '.ok' <<< "${output_data}")" != "true" ]] +then + error_description="$(jq -r '.description' <<< "${output_data}")" + + if [[ "${error_description}" != "null" ]] + then + log_text="editMessageText (${update_id}): ${error_description}" + else + log_text="editMessageText (${update_id}): An unknown error occurred" + fi + + source "${units}/log.zsh" +fi + +exit 0 diff --git a/operators/command_post.zsh b/operators/command_post.zsh new file mode 100644 index 0000000..2ead112 --- /dev/null +++ b/operators/command_post.zsh @@ -0,0 +1,67 @@ +# Copyright (C) 2024-2026 Maria Lisina +# Copyright (C) 2024-2026 Danil Lisin +# SPDX-License-Identifier: Apache-2.0 + +source "${units}/ib_name.zsh" + +if [[ -n "${output_text}" ]] +then + return +fi + +source "${units}/ib_common.zsh" + +if [[ -n "${output_text}" ]] +then + return +fi + +ib_hash="$(sha1sum <<< "${user_id}${ib_board}${ib_query}" | cut -d ' ' -f 1)" +ib_file="${cache}/${ib_hash}.json" + +until mkdir "${cache}/${ib_hash}.lock" +do + sleep 1 +done + +source "${units}/ib_file.zsh" + +if [[ -n "${output_text}" ]] +then + rmdir "${cache}/${ib_hash}.lock" + return +fi + +source "${units}/ib_post.zsh" + +link_preview_options="$( + jq --null-input --compact-output \ + --arg url "${ib_sample_url}" \ + '{"url": $url, "prefer_small_media": true, "show_above_text": true}' +)" + +keyboard_text1="Post link" +keyboard_url1="${ib_url}$(urlencode <<< "${ib_id}")" + +reply_markup="$( + jq --null-input --compact-output \ + --arg text1 "${keyboard_text1}" \ + --arg url1 "${keyboard_url1}" \ + '{"inline_keyboard": [[{"text": $text1, "url": $url1}]]}' +)" + +if [[ ${#ib_tags} -gt 0 ]] +then + keyboard_text1="Tags (${#ib_tags})" + keyboard_data1="tags ${ib_board} ${ib_post_id}" + + reply_markup="$( + jq --compact-output \ + --arg text1 "${keyboard_text1}" \ + --arg data1 "${keyboard_data1}" \ + '.inline_keyboard[0] += [{"text": $text1, "callback_data": $data1}]' \ + <<< "${reply_markup}" + )" +fi + +rmdir "${cache}/${ib_hash}.lock" diff --git a/operators/command_prpr.zsh b/operators/command_prpr.zsh new file mode 100644 index 0000000..a6db455 --- /dev/null +++ b/operators/command_prpr.zsh @@ -0,0 +1,5 @@ +# Copyright (C) 2024-2026 Maria Lisina +# Copyright (C) 2024-2026 Danil Lisin +# SPDX-License-Identifier: Apache-2.0 + +output_text="ฅ^•ﻌ•^ฅ" diff --git a/operators/command_short.zsh b/operators/command_short.zsh new file mode 100644 index 0000000..cc551e3 --- /dev/null +++ b/operators/command_short.zsh @@ -0,0 +1,46 @@ +# Copyright (C) 2024-2026 Maria Lisina +# Copyright (C) 2024-2026 Danil Lisin +# SPDX-License-Identifier: Apache-2.0 + +if [[ -n "${1}" ]] +then + short_query="${@}" + shift ${#} +else + output_text="You must specify query" + return +fi + +if [[ ${#short_query} -gt 256 ]] +then + output_text="Query is too long" + return +fi + +output_text="<b>Shortcut:</b> <code>$(htmlescape <<< "${short_query}")</code>" + +keyboard_text1="Open inline" +keyboard_query1="${short_query}" + +reply_markup="$( + jq --null-input --compact-output \ + --arg text1 "${keyboard_text1}" \ + --arg query1 "${keyboard_query1}" \ + '{"inline_keyboard": [[{"text": $text1, "switch_inline_query_current_chat": $query1}]]}' +)" + +short_query="short ${short_query}" + +if [[ ${#short_query} -le 64 ]] +then + keyboard_text1="Manage" + keyboard_data1="${short_query}" + + reply_markup="$( + jq --compact-output \ + --arg text1 "${keyboard_text1}" \ + --arg data1 "${keyboard_data1}" \ + '.inline_keyboard[0] += [{"text": $text1, "callback_data": $data1}]' \ + <<< "${reply_markup}" + )" +fi diff --git a/operators/command_shorts.zsh b/operators/command_shorts.zsh new file mode 100644 index 0000000..f52b531 --- /dev/null +++ b/operators/command_shorts.zsh @@ -0,0 +1,53 @@ +# Copyright (C) 2024-2026 Maria Lisina +# Copyright (C) 2024-2026 Danil Lisin +# SPDX-License-Identifier: Apache-2.0 + +until mkdir "${user_config}_shorts.lock" +do + sleep 1 +done + +shorts_config="${user_config}/shorts" + +if [[ -d "${shorts_config}" ]] +then + shorts=($(ls -1 "${shorts_config}")) +fi + +if [[ ${#shorts} -eq 0 ]] +then + output_text="You have no saved shortcuts yet" + + rmdir "${user_config}_shorts.lock" + return +fi + +output_text="<b>Saved shortcuts:</b> ${#shorts} / ${shorts_limit}" + +keyboard_text1="Open inline" +keyboard_query1="shorts " + +reply_markup="$( + jq --null-input --compact-output \ + --arg text1 "${keyboard_text1}" \ + --arg query1 "${keyboard_query1}" \ + --arg text2 "${keyboard_text2}" \ + --arg data2 "${keyboard_data2}" \ + '{"inline_keyboard": [[{"text": $text1, "switch_inline_query_current_chat": $query1}]]}' +)" + +if [[ "${chat_id}" == "${target_user}" ]] +then + keyboard_text1="Remove all" + keyboard_data1="stop shorts" + + reply_markup="$( + jq --compact-output \ + --arg text1 "${keyboard_text1}" \ + --arg data1 "${keyboard_data1}" \ + '.inline_keyboard[0] += [{"text": $text1, "callback_data": $data1}]' \ + <<< "${reply_markup}" + )" +fi + +rmdir "${user_config}_shorts.lock" diff --git a/operators/command_source.zsh b/operators/command_source.zsh new file mode 100644 index 0000000..9553bc6 --- /dev/null +++ b/operators/command_source.zsh @@ -0,0 +1,99 @@ +# Copyright (C) 2024-2026 Maria Lisina +# Copyright (C) 2024-2026 Danil Lisin +# SPDX-License-Identifier: Apache-2.0 + +if [[ -n "${nocommand_source}" ]] +then + exit 0 +fi + +until mkdir "${user_config}_source.lock" +do + sleep 1 +done + +source "${units}/sn_auth.zsh" + +rmdir "${user_config}_source.lock" + +if [[ -n "${output_text}" ]] +then + return +fi + +source "${units}/sn_get.zsh" + +if [[ -n "${output_text}" ]] +then + return +fi + +source_table=( + danbooru_id d "Danbooru" + gelbooru_id g "Gelbooru" + idol_id i "Idol Complex" + konachan_id k "Konachan.com" + sankaku_id s "Sankaku Channel" + yandere_id y "yande.re" +) + +minimum_similarity="$(jq -r ".header.minimum_similarity" <<< "${sn_data}")" + +for ((idx = 0; idx >= 0; idx++)) +do + similarity="$(jq -r ".results.[${idx}].header.similarity" <<< "${sn_data}")" + + if [[ "${similarity}" == "null" ]] + then + break + fi + + if [[ ${highest_similarity} -lt ${similarity} ]] + then + highest_similarity=${similarity} + highest_index=${idx} + fi +done + +if [[ ${highest_similarity} -lt ${minimum_similarity} || ${highest_similarity} -lt 70.00 ]] +then + output_text="No results found" + return +fi + +thumbnail="$(jq -r ".results.[${highest_index}].header.thumbnail" <<< "${sn_data}")" +link_preview_options="$( + jq --null-input --compact-output \ + --arg url "${thumbnail}" \ + '{"url": $url, "prefer_small_media": true, "show_above_text": true}' +)" + +index_name="$(jq -r ".results.[${highest_index}].header.index_name" <<< "${sn_data}")" +index_md5="$(cut -d '_' -f 1 <<< "${index_name##* }")" + +output_text="$(printf "<b>SauceNAO</b>\n<b>Similarity:</b> %.2f%%" "${highest_similarity}")" +output_text="$(printf "%s\n<b>MD5:</b> <code>%s</code>" "${output_text}" "${index_md5}")" + +while [[ ${#source_table} -ge 3 ]] +do + if ! jq -e ".results.[${highest_index}].data|has(\"${source_table[1]}\")" <<< "${sn_data}" > /dev/null + then + shift 3 source_table + continue + fi + + keyboard_text1="${source_table[3]}" + keyboard_query1="post ${source_table[2]} ${index_md5}" + + reply_markup="$( + jq --compact-output \ + --argjson offset "$(printf "%u" "${keyboard_offset}")" \ + --arg text1 "${keyboard_text1}" \ + --arg query1 "${keyboard_query1}" \ + '.inline_keyboard[$offset] += [{"text": $text1, "switch_inline_query_current_chat": $query1}]' \ + <<< "${reply_markup:-"{}"}" + )" + + keyboard_offset=$((keyboard_offset + 0.5)) + shift 3 source_table +done diff --git a/operators/command_stop.zsh b/operators/command_stop.zsh new file mode 100644 index 0000000..1ddf10c --- /dev/null +++ b/operators/command_stop.zsh @@ -0,0 +1,24 @@ +# Copyright (C) 2024-2026 Maria Lisina +# Copyright (C) 2024-2026 Danil Lisin +# SPDX-License-Identifier: Apache-2.0 + +if [[ "${chat_id}" != "${target_user}" ]] +then + output_text="For security reasons you can execute this command only in direct messages" + return +fi + +for lock in ${user_locks[@]} +do + until mkdir "${user_config}_${lock}.lock" + do + sleep 1 + done +done + +source "${units}/stop.zsh" + +for lock in ${user_locks[@]} +do + rmdir "${user_config}_${lock}.lock" +done diff --git a/operators/inline_donate.zsh b/operators/inline_donate.zsh new file mode 100644 index 0000000..a823311 --- /dev/null +++ b/operators/inline_donate.zsh @@ -0,0 +1,22 @@ +# Copyright (C) 2024-2026 Maria Lisina +# Copyright (C) 2024-2026 Danil Lisin +# SPDX-License-Identifier: Apache-2.0 + +if [[ -n "${nocommand_donate}" ]] +then + source "${operators}/inline_help.zsh" + return +fi + +output_title="Donate" +output_text="${donate_content}" +output_description="Click to send details" + +results="$( + jq --null-input --compact-output \ + --arg id "${query_id}" \ + --arg title "${output_title}" \ + --arg text "${output_text}" \ + --arg description "${output_description}" \ + '[{"type": "article", "id": $id, "title": $title, "input_message_content": {"message_text": $text, "parse_mode": "HTML"}, "description": $description}]' +)" diff --git a/operators/inline_help.zsh b/operators/inline_help.zsh new file mode 100644 index 0000000..2ac9455 --- /dev/null +++ b/operators/inline_help.zsh @@ -0,0 +1,16 @@ +# Copyright (C) 2024-2026 Maria Lisina +# Copyright (C) 2024-2026 Danil Lisin +# SPDX-License-Identifier: Apache-2.0 + +output_title="Sekoohaka Bot" +output_text="${help_content}" +output_description="Click to send help message" + +results="$( + jq --null-input --compact-output \ + --arg id "${query_id}" \ + --arg title "${output_title}" \ + --arg text "${output_text}" \ + --arg description "${output_description}" \ + '[{"type": "article", "id": $id, "title": $title, "input_message_content": {"message_text": $text, "parse_mode": "HTML", "link_preview_options": {"is_disabled": true}}, "description": $description}]' +)" diff --git a/operators/inline_none.zsh b/operators/inline_none.zsh new file mode 100644 index 0000000..c6b0a2e --- /dev/null +++ b/operators/inline_none.zsh @@ -0,0 +1,24 @@ +# Copyright (C) 2024-2026 Maria Lisina +# Copyright (C) 2024-2026 Danil Lisin +# SPDX-License-Identifier: Apache-2.0 + +until mkdir "${user_config}_shorts.lock" +do + sleep 1 +done + +shorts_config="${user_config}/shorts" + +if [[ -d "${shorts_config}" ]] +then + shorts=($(ls -1 "${shorts_config}")) +fi + +if [[ ${#shorts} -gt 0 ]] +then + command="shorts" +else + command="help" +fi + +rmdir "${user_config}_shorts.lock" diff --git a/operators/inline_original.zsh b/operators/inline_original.zsh new file mode 100644 index 0000000..5e9caac --- /dev/null +++ b/operators/inline_original.zsh @@ -0,0 +1,90 @@ +# Copyright (C) 2024-2026 Maria Lisina +# Copyright (C) 2024-2026 Danil Lisin +# SPDX-License-Identifier: Apache-2.0 + +ib_lock=0 +source "${units}/ib_common.zsh" + +if [[ -n "${output_text}" ]] +then + results="$( + jq --null-input --compact-output \ + --arg id "${query_id}" \ + --arg title "${output_title}" \ + --arg text "${output_text}" \ + --arg description "${output_text}" \ + '[{"type": "article", "id": $id, "title": $title, "input_message_content": {"message_text": $text}, "description": $description}]' + )" + + return +fi + +ib_hash="$(sha1sum <<< "${user_id}${ib_board}${ib_query}" | cut -d ' ' -f 1)" +ib_file="${cache}/${ib_hash}.json" + +until mkdir "${cache}/${ib_hash}.lock" +do + sleep 1 +done + +source "${units}/ib_file.zsh" + +if [[ -n "${output_text}" ]] +then + results="$( + jq --null-input --compact-output \ + --arg id "${query_id}" \ + --arg title "${output_title}" \ + --arg text "${output_text}" \ + --arg description "${output_text}" \ + '[{"type": "article", "id": $id, "title": $title, "input_message_content": {"message_text": $text}, "description": $description}]' + )" + + rmdir "${cache}/${ib_hash}.lock" + return +fi + +source "${units}/ib_original.zsh" + +if [[ -n "${output_text}" ]] +then + output_title="An error occurred" + + results="$( + jq --null-input --compact-output \ + --arg id "${query_id}" \ + --arg title "${output_title}" \ + --arg text "${output_text}" \ + --arg description "${output_text}" \ + '[{"type": "article", "id": $id, "title": $title, "input_message_content": {"message_text": $text}, "description": $description}]' + )" +else + output_title="Original file of post ${ib_post_id}" + output_description="Click to send original file" + + results="$( + jq --null-input --compact-output \ + --arg id "${query_id}" \ + --arg title "${output_title}" \ + --arg document_url "${ib_file_url}" \ + --arg description "${output_description}" \ + --arg thumbnail_url "${ib_preview_url}" \ + '[{"type": "document", "id": $id, "title": $title, "document_url": $document_url, "mime_type": "application/zip", "description": $description, "thumbnail_url", $thumbnail_url}]' + )" +fi + +if [[ -n "${ib_file_url}" && "${ib_file_url}" != "null" ]] +then + keyboard_text1="Original file link" + keyboard_url1="${ib_file_url}" + + results="$( + jq --compact-output \ + --arg text1 "${keyboard_text1}" \ + --arg url1 "${keyboard_url1}" \ + '.[0] += {"reply_markup": {"inline_keyboard": [[{"text": $text1, "url": $url1}]]}}' \ + <<< "${results}" + )" +fi + +rmdir "${cache}/${ib_hash}.lock" diff --git a/operators/inline_post.zsh b/operators/inline_post.zsh new file mode 100644 index 0000000..92d7199 --- /dev/null +++ b/operators/inline_post.zsh @@ -0,0 +1,82 @@ +# Copyright (C) 2024-2026 Maria Lisina +# Copyright (C) 2024-2026 Danil Lisin +# SPDX-License-Identifier: Apache-2.0 + +ib_lock=0 +source "${units}/ib_common.zsh" + +if [[ -n "${output_text}" ]] +then + results="$( + jq --null-input --compact-output \ + --arg id "${query_id}" \ + --arg title "${output_title}" \ + --arg text "${output_text}" \ + --arg description "${output_text}" \ + '[{"type": "article", "id": $id, "title": $title, "input_message_content": {"message_text": $text}, "description": $description}]' + )" + + return +fi + +ib_hash="$(sha1sum <<< "${user_id}${ib_board}${ib_query}" | cut -d ' ' -f 1)" +ib_file="${cache}/${ib_hash}.json" + +until mkdir "${cache}/${ib_hash}.lock" +do + sleep 1 +done + +source "${units}/ib_file.zsh" + +if [[ -n "${output_text}" ]] +then + results="$( + jq --null-input --compact-output \ + --arg id "${query_id}" \ + --arg title "${output_title}" \ + --arg text "${output_text}" \ + --arg description "${output_text}" \ + '[{"type": "article", "id": $id, "title": $title, "input_message_content": {"message_text": $text}, "description": $description}]' + )" + + rmdir "${cache}/${ib_hash}.lock" + return +fi + +source "${units}/ib_post.zsh" + +output_title="Information of post ${ib_post_id}" +output_description="Click to send post information" + +keyboard_text1="Post link" +keyboard_url1="${ib_url}$(urlencode <<< "${ib_id}")" + +results="$( + jq --null-input --compact-output \ + --arg id "${query_id}" \ + --arg title "${output_title}" \ + --arg text "${output_text}" \ + --arg url "${ib_sample_url}" \ + --arg text1 "${keyboard_text1}" \ + --arg url1 "${keyboard_url1}" \ + --arg description "${output_description}" \ + --arg thumbnail_url "${ib_preview_url}" \ + '[{"type": "article", "id": $id, "title": $title, "input_message_content": {"message_text": $text, "parse_mode": "HTML", "link_preview_options": {"url": $url, "prefer_small_media": true, "show_above_text": true}}, "reply_markup": {"inline_keyboard": [[{"text": $text1, "url": $url1}]]}, "description": $description, "thumbnail_url": $thumbnail_url}]' +)" + +if [[ ${#ib_tags} -gt 0 ]] +then + keyboard_text1="Tags (${#ib_tags})" + keyboard_data1="tags ${ib_board} ${ib_post_id}" + + results="$( + jq --compact-output \ + --arg text1 "${keyboard_text1}" \ + --arg data1 "${keyboard_data1}" \ + '.[0].reply_markup.inline_keyboard[0] += [{"text": $text1, "callback_data": $data1}]' \ + <<< "${results}" + )" +fi + +rmdir "${cache}/${ib_hash}.lock" diff --git a/operators/inline_search.zsh b/operators/inline_search.zsh new file mode 100644 index 0000000..93133fc --- /dev/null +++ b/operators/inline_search.zsh @@ -0,0 +1,151 @@ +# Copyright (C) 2024-2026 Maria Lisina +# Copyright (C) 2024-2026 Danil Lisin +# SPDX-License-Identifier: Apache-2.0 + +case "${command}" in + ("pools" | l) + ib_mode="l" + inline_options="aq" + ;; + ("posts" | p) + ib_mode="p" + inline_options="ampq" + ;; + ("tags" | t) + ib_mode="t" + inline_options="aq" + ;; + (*) + set -- ${inline_query[@]} + source "${operators}/inline_none.zsh" + + case "${command}" in + ("shorts") + source "${operators}/inline_shorts.zsh" + ;; + ("help") + source "${operators}/inline_help.zsh" + ;; + esac + + return + ;; +esac + +ib_lock=0 +source "${units}/ib_search.zsh" + +if [[ -n "${output_text}" ]] +then + keyboard_text1="Resume" + keyboard_query1="${command} ${ib_board} ${inline_page}" + + if [[ -n "${search_query}" ]] + then + keyboard_query1="${keyboard_query1} ${search_query}" + fi + + results="$( + jq --null-input --compact-output \ + --arg id "${query_id}" \ + --arg title "${output_title}" \ + --arg text "${output_text}" \ + --arg text1 "${keyboard_text1}" \ + --arg query1 "${keyboard_query1}" \ + --arg description "${output_text}" \ + '[{"type": "article", "id": $id, "title": $title, "input_message_content": {"message_text": $text}, "reply_markup": {"inline_keyboard": [[{"text": $text1, "switch_inline_query_current_chat": $query1}]]}, "description": $description}]' + )" + + return +fi + +ib_hash="$(sha1sum <<< "${user_id}${ib_mode}${ib_board}${ib_page}${ib_query}" | cut -d ' ' -f 1)" +ib_file="${cache}/${ib_hash}.json" + +until mkdir "${cache}/${ib_hash}.lock" +do + sleep 1 +done + +source "${units}/ib_file.zsh" + +if [[ -n "${output_text}" ]] +then + keyboard_text1="Resume" + keyboard_query1="${command} ${ib_board} ${inline_page}" + + if [[ -n "${search_query}" ]] + then + keyboard_query1="${keyboard_query1} ${search_query}" + fi + + results="$( + jq --null-input --compact-output \ + --arg id "${query_id}" \ + --arg title "${output_title}" \ + --arg text "${output_text}" \ + --arg text1 "${keyboard_text1}" \ + --arg query1 "${keyboard_query1}" \ + --arg description "${output_text}" \ + '[{"type": "article", "id": $id, "title": $title, "input_message_content": {"message_text": $text}, "reply_markup": {"inline_keyboard": [[{"text": $text1, "switch_inline_query_current_chat": $query1}]]}, "description": $description}]' + )" + + rmdir "${cache}/${ib_hash}.lock" + return +fi + +ib_ids=("${(@f)$(jq -r ".${ib_iarray}[].${ib_iid}" "${ib_file}")}") + +case "${ib_mode}" in + (l) + ib_created_ats=("${(@f)$(jq -r ".${ib_iarray}[].${ib_icreated}" "${ib_file}")}") + ib_pools=("${(@f)$(jq -r ".${ib_iarray}[].${ib_ipool}" "${ib_file}")}") + ib_counts=("${(@f)$(jq -r ".${ib_iarray}[].${ib_icount}" "${ib_file}")}") + ;; + (p) + ib_created_ats=("${(@f)$(jq -r ".${ib_iarray}[].${ib_icreated}" "${ib_file}")}") + ib_file_sizes=("${(@f)$(jq -r ".${ib_iarray}[].${ib_isize}" "${ib_file}")}") + ib_file_urls=("${(@f)$(jq -r ".${ib_iarray}[].${ib_ifile}" "${ib_file}")}") + ib_sample_urls=("${(@f)$(jq -r ".${ib_iarray}[].${ib_isample}" "${ib_file}")}") + ib_preview_urls=("${(@f)$(jq -r ".${ib_iarray}[].${ib_ipreview}" "${ib_file}")}") + ib_widths=("${(@f)$(jq -r ".${ib_iarray}[].${ib_iwidth}" "${ib_file}")}") + ib_heights=("${(@f)$(jq -r ".${ib_iarray}[].${ib_iheight}" "${ib_file}")}") + ;; + (t) + ib_tags=("${(@f)$(jq -r ".${ib_iarray}[].${ib_itag}" "${ib_file}")}") + ib_counts=("${(@f)$(jq -r ".${ib_iarray}[].${ib_icount}" "${ib_file}")}") + ;; +esac + +for ((idx = 1; idx > 0; idx++)) +do + ib_id="${ib_ids[idx]}" + + if [[ -z "${ib_id}" || "${ib_id}" == "null" ]] + then + break + fi + + case "${ib_mode}" in + (l) + source "${operators}/inline_search_pools.zsh" + ;; + (p) + source "${operators}/inline_search_posts.zsh" + ;; + (t) + source "${operators}/inline_search_tags.zsh" + ;; + esac + + results+=(${result}) +done + +results="$(jq -sc <<< ${results[@]})" + +if [[ -n "${ib_autopaging}" ]] +then + next_offset=$((inline_page + 1)) +fi + +rmdir "${cache}/${ib_hash}.lock" diff --git a/operators/inline_search_pools.zsh b/operators/inline_search_pools.zsh new file mode 100644 index 0000000..476dd9a --- /dev/null +++ b/operators/inline_search_pools.zsh @@ -0,0 +1,74 @@ +# Copyright (C) 2024-2026 Maria Lisina +# Copyright (C) 2024-2026 Danil Lisin +# SPDX-License-Identifier: Apache-2.0 + +ib_created_at="${ib_created_ats[idx]}" +ib_pool="${ib_pools[idx]}" +ib_count="${ib_counts[idx]}" + +unset ib_date_text +source "${units}/ib_date.zsh" + +if [[ -n "${ib_ispace}" ]] +then + ib_pool="$(tr "${ib_ispace}" ' ' <<< "${ib_pool}")" +fi + +if [[ ${#ib_pool} -gt 1024 ]] +then + ib_pool="$(cut -c 1-1024 <<< "${ib_pool}")..." +fi + +output_title="${ib_pool:- }" +output_text="$(printf "<b>%s</b>\n<b>ID:</b> <code>%s</code>" "${ib_name}" "${ib_id}")" + +if [[ -n "${ib_date_text}" ]] +then + output_text="$(printf "%s\n<b>Date:</b> <code>%s</code>" "${output_text}" "${ib_date_text}")" +fi + +output_text="$(printf "%s\n<b>Name:</b> %s" "${output_text}" "$(htmlescape <<< "${ib_pool}")")" +output_text="$(printf "%s\n<b>Post count:</b> %s" "${output_text}" "${ib_count}")" +output_description="Click to send pool information" + +keyboard_text1="Pool link" +keyboard_url1="${ib_url}$(urlencode <<< "${ib_id}")" +keyboard_text2="Resume" +keyboard_query2="${command} ${ib_board} ${inline_page}" + +if [[ -n "${search_query}" ]] +then + keyboard_query2="${keyboard_query2} ${search_query}" +fi + +result="$( + jq --null-input --compact-output \ + --arg id "${ib_id}" \ + --arg title "${output_title}" \ + --arg text "${output_text}" \ + --arg description "${output_description}" \ + --arg text1 "${keyboard_text1}" \ + --arg url1 "${keyboard_url1}" \ + --arg text2 "${keyboard_text2}" \ + --arg query2 "${keyboard_query2}" \ + '{"type": "article", "id": $id, "title": $title, "input_message_content": {"message_text": $text, "parse_mode": "HTML"}, "description": $description, "reply_markup": {"inline_keyboard": [[{"text": $text1, "url": $url1}, {"text": $text2, "switch_inline_query_current_chat": $query2}]]}}' +)" + +if [[ -n "${ib_quick}" ]] +then + keyboard_text1="Search posts" + keyboard_query1="posts ${ib_board} pool:${ib_id}" + + if [[ -n "${ib_iorder}" ]] + then + keyboard_query1="${keyboard_query1} ${ib_iorder}" + fi + + result="$( + jq --compact-output \ + --arg text1 "${keyboard_text1}" \ + --arg query1 "${keyboard_query1}" \ + '.reply_markup.inline_keyboard += [[{"text": $text1, "switch_inline_query_current_chat": $query1}]]' \ + <<< "${result}" + )" +fi diff --git a/operators/inline_search_posts.zsh b/operators/inline_search_posts.zsh new file mode 100644 index 0000000..1af741d --- /dev/null +++ b/operators/inline_search_posts.zsh @@ -0,0 +1,134 @@ +# Copyright (C) 2024-2026 Maria Lisina +# Copyright (C) 2024-2026 Danil Lisin +# SPDX-License-Identifier: Apache-2.0 + +ib_created_at="${ib_created_ats[idx]}" +ib_file_size="${ib_file_sizes[idx]}" +ib_file_url="${ib_file_urls[idx]}" +ib_sample_url="${ib_sample_urls[idx]}" +ib_preview_url="${ib_preview_urls[idx]}" +ib_width="${ib_widths[idx]}" +ib_height="${ib_heights[idx]}" + +unset ib_date_text ib_resolution_text ib_type_text ib_size_text +source "${units}/ib_date.zsh" +source "${units}/ib_meta.zsh" + +if [[ -n "${ib_preview}" ]] +then + case "${ib_type}" in + (gif | video) + ib_sample_url="${ib_preview_url}" + ib_type="photo" + ;; + esac +fi + +output_text="$(printf "<b>%s</b>\n<b>ID:</b> <code>%s</code>" "${ib_name}" "${ib_id}")" + +if [[ -n "${ib_date_text}" ]] +then + output_text="$(printf "%s\n<b>Date:</b> <code>%s</code>" "${output_text}" "${ib_date_text}")" +fi + +if [[ -n "${ib_metadata}" ]] +then + if [[ -n "${ib_resolution_text}" ]] + then + output_text="$(printf "%s\n<b>Resolution:</b> %s" "${output_text}" "${ib_resolution_text}")" + fi + + if [[ -n "${ib_size_text}" ]] + then + output_text="$(printf "%s\n<b>Size:</b> %s" "${output_text}" "${ib_size_text}")" + fi + + if [[ -n "${ib_type_text}" ]] + then + output_text="$(printf "%s\n<b>Type:</b> %s" "${output_text}" "${ib_type_text}")" + fi +fi + +keyboard_text1="Post link" +keyboard_url1="${ib_url}$(urlencode <<< "${ib_id}")" +keyboard_text2="Resume" +keyboard_query2="${command} ${ib_board} ${inline_page}" + +if [[ -n "${search_query}" ]] +then + keyboard_query2="${keyboard_query2} ${search_query}" +fi + +case "${ib_type}" in + (photo) + result="$( + jq --null-input --compact-output \ + --arg id "${ib_id}" \ + --arg photo_url "${ib_sample_url}" \ + --arg thumbnail_url "${ib_preview_url}" \ + --arg photo_width "${ib_width}" \ + --arg photo_height "${ib_height}" \ + --arg caption "${output_text}" \ + --arg text1 "${keyboard_text1}" \ + --arg url1 "${keyboard_url1}" \ + --arg text2 "${keyboard_text2}" \ + --arg query2 "${keyboard_query2}" \ + '{"type": "photo", "id": $id, "photo_url": $photo_url, "thumbnail_url": $thumbnail_url, "photo_width": $photo_width, "photo_height": $photo_height, "caption": $caption, "parse_mode": "HTML", "reply_markup": {"inline_keyboard": [[{"text": $text1, "url": $url1}, {"text": $text2, "switch_inline_query_current_chat": $query2}]]}}' + )" + ;; + (gif) + result="$( + jq --null-input --compact-output \ + --arg id "${ib_id}" \ + --arg gif_url "${ib_file_url}" \ + --arg thumbnail_url "${ib_preview_url}" \ + --arg gif_width "${ib_width}" \ + --arg gif_height "${ib_height}" \ + --arg caption "${output_text}" \ + --arg text1 "${keyboard_text1}" \ + --arg url1 "${keyboard_url1}" \ + --arg text2 "${keyboard_text2}" \ + --arg query2 "${keyboard_query2}" \ + '{"type": "gif", "id": $id, "gif_url": $gif_url, "thumbnail_url": $thumbnail_url, "gif_width": $gif_width, "gif_height": $gif_height, "caption": $caption, "parse_mode": "HTML", "reply_markup": {"inline_keyboard": [[{"text": $text1, "url": $url1}, {"text": $text2, "switch_inline_query_current_chat": $query2}]]}}' + )" + ;; + (video) + result="$( + jq --null-input --compact-output \ + --arg id "${ib_id}" \ + --arg mpeg4_url "${ib_file_url}" \ + --arg thumbnail_url "${ib_preview_url}" \ + --arg mpeg4_width "${ib_width}" \ + --arg mpeg4_height "${ib_height}" \ + --arg caption "${output_text}" \ + --arg text1 "${keyboard_text1}" \ + --arg url1 "${keyboard_url1}" \ + --arg text2 "${keyboard_text2}" \ + --arg query2 "${keyboard_query2}" \ + '{"type": "mpeg4_gif", "id": $id, "mpeg4_url": $mpeg4_url, "thumbnail_url": $thumbnail_url, "mpeg4_width": $mpeg4_width, "mpeg4_height": $mpeg4_height, "caption": $caption, "parse_mode": "HTML", "reply_markup": {"inline_keyboard": [[{"text": $text1, "url": $url1}, {"text": $text2, "switch_inline_query_current_chat": $query2}]]}}' + )" + ;; +esac + +if [[ -n "${ib_quick}" ]] +then + keyboard_text1="Original" + keyboard_query1="original ${ib_board} ${ib_id}" + keyboard_text2="Post" + keyboard_query2="post ${ib_board} ${ib_id}" + + result="$( + jq --compact-output \ + --arg text1 "${keyboard_text1}" \ + --arg query1 "${keyboard_query1}" \ + --arg text2 "${keyboard_text2}" \ + --arg query2 "${keyboard_query2}" \ + '.reply_markup.inline_keyboard += [[{"text": $text1, "switch_inline_query_current_chat": $query1}, {"text": $text2, "switch_inline_query_current_chat": $query2}]]' \ + <<< "${result}" + )" +fi + +if [[ "${cache_mode}" == "advanced" ]] +then + source "${units}/ib_cache.zsh" & +fi diff --git a/operators/inline_search_tags.zsh b/operators/inline_search_tags.zsh new file mode 100644 index 0000000..aea0184 --- /dev/null +++ b/operators/inline_search_tags.zsh @@ -0,0 +1,59 @@ +# Copyright (C) 2024-2026 Maria Lisina +# Copyright (C) 2024-2026 Danil Lisin +# SPDX-License-Identifier: Apache-2.0 + +ib_tag="${ib_tags[idx]}" +ib_count="${ib_counts[idx]}" + +if [[ -n "${ib_irecode}" ]] && ib_tag_recode="$(recode ${ib_irecode}..ASCII <<< "${ib_tag}")" +then + ib_tag="${ib_tag_recode}" +fi + +if [[ ${#ib_tag} -gt 1024 ]] +then + ib_tag="$(cut -c 1-1024 <<< "${ib_tag}")..." +fi + +output_title="${ib_tag:- }" +output_text="$(printf "<b>%s</b>\n<b>ID:</b> <code>%s</code>" "${ib_name}" "${ib_id}")" +output_text="$(printf "%s\n<b>Name:</b> <code>%s</code>" "${output_text}" "$(htmlescape <<< "${ib_tag}")")" +output_text="$(printf "%s\n<b>Post count:</b> %s" "${output_text}" "${ib_count}")" +output_description="Click to send tag information" + +keyboard_text1="Wiki link" +keyboard_url1="${ib_url}$(urlencode <<< "${ib_tag}")" +keyboard_text2="Resume" +keyboard_query2="${command} ${ib_board} ${inline_page}" + +if [[ -n "${search_query}" ]] +then + keyboard_query2="${keyboard_query2} ${search_query}" +fi + +result="$( + jq --null-input --compact-output \ + --arg id "${ib_id}" \ + --arg title "${output_title}" \ + --arg text "${output_text}" \ + --arg description "${output_description}" \ + --arg text1 "${keyboard_text1}" \ + --arg url1 "${keyboard_url1}" \ + --arg text2 "${keyboard_text2}" \ + --arg query2 "${keyboard_query2}" \ + '{"type": "article", "id": $id, "title": $title, "input_message_content": {"message_text": $text, "parse_mode": "HTML"}, "description": $description, "reply_markup": {"inline_keyboard": [[{"text": $text1, "url": $url1}, {"text": $text2, "switch_inline_query_current_chat": $query2}]]}}' +)" + +if [[ -n "${ib_quick}" ]] +then + keyboard_text1="Search posts" + keyboard_query1="posts ${ib_board} ${ib_tag}" + + result="$( + jq --compact-output \ + --arg text1 "${keyboard_text1}" \ + --arg query1 "${keyboard_query1}" \ + '.reply_markup.inline_keyboard += [[{"text": $text1, "switch_inline_query_current_chat": $query1}]]' \ + <<< "${result}" + )" +fi diff --git a/operators/inline_short.zsh b/operators/inline_short.zsh new file mode 100644 index 0000000..84dd3d4 --- /dev/null +++ b/operators/inline_short.zsh @@ -0,0 +1,57 @@ +# Copyright (C) 2024-2026 Maria Lisina +# Copyright (C) 2024-2026 Danil Lisin +# SPDX-License-Identifier: Apache-2.0 + +if [[ -n "${1}" ]] +then + short_query="${@}" + shift ${#} +else + output_title="Invalid arguments" + output_text="You must specify query" + + results="$( + jq --null-input --compact-output \ + --arg id "${query_id}" \ + --arg title "${output_title}" \ + --arg text "${output_text}" \ + --arg description "${output_text}" \ + '[{"type": "article", "id": $id, "title": $title, "input_message_content": {"message_text": $text}, "description": $description}]' + )" + + return +fi + +output_title="Shortcut" +output_text="<b>Shortcut:</b> <code>$(htmlescape <<< "${short_query}")</code>" +output_description="${short_query}" + +keyboard_text1="Open inline" +keyboard_query1="${short_query}" + +results="$( + jq --null-input --compact-output \ + --arg id "${query_id}" \ + --arg title "${output_title}" \ + --arg text "${output_text}" \ + --arg text1 "${keyboard_text1}" \ + --arg query1 "${keyboard_query1}" \ + --arg description "${output_description}" \ + '[{"type": "article", "id": $id, "title": $title, "input_message_content": {"message_text": $text, "parse_mode": "HTML"}, "reply_markup": {"inline_keyboard": [[{"text": $text1, "switch_inline_query_current_chat": $query1}]]}, "description": $description}]' +)" + +short_query="short ${short_query}" + +if [[ ${#short_query} -le 64 ]] +then + keyboard_text1="Manage" + keyboard_data1="${short_query}" + + results="$( + jq --compact-output \ + --arg text1 "${keyboard_text1}" \ + --arg data1 "${keyboard_data1}" \ + '.[0].reply_markup.inline_keyboard[0] += [{"text": $text1, "callback_data": $data1}]' \ + <<< "${results}" + )" +fi diff --git a/operators/inline_shorts.zsh b/operators/inline_shorts.zsh new file mode 100644 index 0000000..ea40e95 --- /dev/null +++ b/operators/inline_shorts.zsh @@ -0,0 +1,112 @@ +# Copyright (C) 2024-2026 Maria Lisina +# Copyright (C) 2024-2026 Danil Lisin +# SPDX-License-Identifier: Apache-2.0 + +until mkdir "${user_config}_shorts.lock" +do + sleep 1 +done + +shorts_config="${user_config}/shorts" +source "${units}/shorts_search.zsh" + +if [[ -n "${output_text}" ]] +then + results="$( + jq --null-input --compact-output \ + --arg id "${query_id}" \ + --arg title "${output_title}" \ + --arg text "${output_text}" \ + --arg description "${output_text}" \ + '[{"type": "article", "id": $id, "title": $title, "input_message_content": {"message_text": $text}, "description": $description}]' + )" + + if [[ "${chat_type}" == "sender" ]] + then + keyboard_text1="Resume" + keyboard_query1="${command} ${inline_page}" + + if [[ -n "${search_query}" ]] + then + keyboard_query1="${keyboard_query1} ${search_query}" + fi + + results="$( + jq --compact-output \ + --arg text1 "${keyboard_text1}" \ + --arg query1 "${keyboard_query1}" \ + '.[0] += {"reply_markup": {"inline_keyboard": [[{"text": $text1, "switch_inline_query_current_chat": $query1}]]}}' \ + <<< "${results}" + )" + fi + + rmdir "${user_config}_shorts.lock" + return +fi + +for ((idx = 1; idx <= ${inline_limit} && idx <= ${#shorts}; idx++)) +do + short_query="$(< "${shorts_config}/${shorts[idx]}")" + + output_title="Shortcut" + output_text="<b>Shortcut:</b> <code>$(htmlescape <<< "${short_query}")</code>" + output_description="${short_query}" + + keyboard_text1="Open inline" + keyboard_query1="${short_query}" + + result="$( + jq --null-input --compact-output \ + --arg id "${shorts[idx]}" \ + --arg title "${output_title}" \ + --arg text "${output_text}" \ + --arg text1 "${keyboard_text1}" \ + --arg query1 "${keyboard_query1}" \ + --arg description "${output_description}" \ + '{"type": "article", "id": $id, "title": $title, "input_message_content": {"message_text": $text, "parse_mode": "HTML"}, "reply_markup": {"inline_keyboard": [[{"text": $text1, "switch_inline_query_current_chat": $query1}]]}, "description": $description}' + )" + + if [[ "${chat_type}" == "sender" ]] + then + keyboard_text1="Resume" + keyboard_query1="${command} ${inline_page}" + + if [[ -n "${search_query}" ]] + then + keyboard_query1="${keyboard_query1} ${search_query}" + fi + + result="$( + jq --compact-output \ + --arg text1 "${keyboard_text1}" \ + --arg query1 "${keyboard_query1}" \ + '.reply_markup.inline_keyboard[0] += [{"text": $text1, "switch_inline_query_current_chat": $query1}]' \ + <<< "${result}" + )" + fi + + if [[ -n "${shorts_quick}" ]] + then + keyboard_text1="Manage" + keyboard_data1="short ${short_query}" + + result="$( + jq --compact-output \ + --arg text1 "${keyboard_text1}" \ + --arg data1 "${keyboard_data1}" \ + '.reply_markup.inline_keyboard += [[{"text": $text1, "callback_data": $data1}]]' \ + <<< "${result}" + )" + fi + + results+=(${result}) +done + +results="$(jq -sc <<< "${results[@]}")" + +if [[ -n "${shorts_autopaging}" ]] +then + next_offset=$((inline_page + 1)) +fi + +rmdir "${user_config}_shorts.lock" diff --git a/operators/timer_uncache.zsh b/operators/timer_uncache.zsh new file mode 100644 index 0000000..4af2543 --- /dev/null +++ b/operators/timer_uncache.zsh @@ -0,0 +1,26 @@ +# Copyright (C) 2024-2026 Maria Lisina +# Copyright (C) 2024-2026 Danil Lisin +# SPDX-License-Identifier: Apache-2.0 + +if [[ -n "${no_clear}" ]] +then + return +fi + +for file in $(find "${cache}" -follow -type f) +do + if ! mkdir "${file%.*}.lock" + then + continue + fi + + file_ctime=$(strftime %s) + file_mtime=$(stat +mtime "${file}") + + if [[ $((file_ctime - file_mtime)) -gt ${cache_time} ]] + then + rm -f "${file}" + fi + + rmdir "${file%.*}.lock" +done diff --git a/operators/timer_unlock.zsh b/operators/timer_unlock.zsh new file mode 100644 index 0000000..9736116 --- /dev/null +++ b/operators/timer_unlock.zsh @@ -0,0 +1,14 @@ +# Copyright (C) 2024-2026 Maria Lisina +# Copyright (C) 2024-2026 Danil Lisin +# SPDX-License-Identifier: Apache-2.0 + +for dir in $(find "${cache}" "${users}" -follow -name "*.lock") +do + dir_ctime=$(strftime %s) + dir_mtime=$(stat +mtime "${dir}") + + if [[ $((dir_ctime - dir_mtime)) -gt 30 ]] + then + rmdir "${dir}" + fi +done diff --git a/operators/url_parser.zsh b/operators/url_parser.zsh new file mode 100644 index 0000000..b24c1bf --- /dev/null +++ b/operators/url_parser.zsh @@ -0,0 +1,125 @@ +# Copyright (C) 2024-2026 Maria Lisina +# Copyright (C) 2024-2026 Danil Lisin +# SPDX-License-Identifier: Apache-2.0 + +url_table=( + a / 5 "https://safebooru.donmai.us/posts/.*" + a / 3 "safebooru.donmai.us/posts/.*" + d / 5 "https://danbooru.donmai.us/posts/.*" + d / 3 "danbooru.donmai.us/posts/.*" + g = 4 "https://gelbooru.com/index.php?page=post&s=view&id=.*" + g = 4 "gelbooru.com/index.php?page=post&s=view&id=.*" + i / 6 "https://www.idolcomplex.com/.*/posts/.*" + i / 4 "www.idolcomplex.com/.*/posts/.*" + i / 4 "idolcomplex.com/.*/posts/.*" + i / 5 "https://www.idolcomplex.com/posts/.*" + i / 3 "www.idolcomplex.com/posts/.*" + i / 3 "idolcomplex.com/posts/.*" + k / 6 "https://konachan.com/post/show/.*" + k / 4 "konachan.com/post/show/.*" + s / 6 "https://www.sankakucomplex.com/.*/posts/.*" + s / 4 "www.sankakucomplex.com/.*/posts/.*" + i / 4 "sankakucomplex.com/.*/posts/.*" + s / 5 "https://www.sankakucomplex.com/posts/.*" + s / 3 "www.sankakucomplex.com/posts/.*" + i / 3 "sankakucomplex.com/posts/.*" + y / 6 "https://yande.re/post/show/.*" + y / 4 "yande.re/post/show/.*" +) + +ib_mode="p" + +while [[ ${#url_table} -ge 4 ]] +do + if grep -qx "${url_table[4]}" <<< ${command} + then + ib_board="${url_table[1]}" + ib_post_id="$(cut -d ${url_table[2]} -f ${url_table[3]} <<< ${command} | cut -d '?' -f 1)" + + break + fi + + shift 4 url_table +done + +if [[ -z "${ib_post_id}" ]] +then + exit 0 +fi + +source "${units}/ib_config.zsh" +source "${units}/ib_authconfig.zsh" + +if [[ ${#ib_post_id} -gt 32 ]] +then + exit 0 +elif [[ ${#ib_post_id} -eq 32 ]] +then + ib_query="md5:${ib_post_id}" +else + ib_query="id:${ib_post_id}" +fi + +ib_hash="$(sha1sum <<< "${user_id}${ib_board}${ib_query}" | cut -d ' ' -f 1)" +ib_file="${cache}/${ib_hash}.json" + +until mkdir "${cache}/${ib_hash}.lock" +do + sleep 1 +done + +source "${units}/ib_file.zsh" + +if [[ -n "${output_text}" ]] +then + keyboard_text1="Delete" + keyboard_data1="delete" + + reply_markup="$( + jq --null-input --compact-output \ + --arg text1 "${keyboard_text1}" \ + --arg data1 "${keyboard_data1}" \ + '{"inline_keyboard": [[{"text": $text1, "callback_data": $data1}]]}' + )" + + rmdir "${cache}/${ib_hash}.lock" + return +fi + +source "${units}/ib_post.zsh" + +link_preview_options="$( + jq --null-input --compact-output \ + --arg url "${ib_sample_url}" \ + '{"url": $url, "prefer_small_media": true, "show_above_text": true}' +)" + +keyboard_text1="Post link" +keyboard_url1="${ib_url}$(urlencode <<< "${ib_id}")" +keyboard_text2="Delete" +keyboard_data2="delete" + +reply_markup="$( + jq --null-input --compact-output \ + --arg text1 "${keyboard_text1}" \ + --arg url1 "${keyboard_url1}" \ + --arg text2 "${keyboard_text2}" \ + --arg data2 "${keyboard_data2}" \ + '{"inline_keyboard": [[{"text": $text1, "url": $url1}], [{"text": $text2, "callback_data": $data2}]]}' +)" + +if [[ ${#ib_tags} -gt 0 ]] +then + keyboard_text1="Tags (${#ib_tags})" + keyboard_data1="tags ${ib_board} ${ib_post_id}" + + reply_markup="$( + jq --compact-output \ + --arg text1 "${keyboard_text1}" \ + --arg data1 "${keyboard_data1}" \ + '.inline_keyboard[0] += [{"text": $text1, "callback_data": $data1}]' \ + <<< "${reply_markup}" + )" +fi + +rmdir "${cache}/${ib_hash}.lock" |
