• Можете помочь с выводом запроса SQL и желательно объяснить в какой момент что происходит?

    @Khamzabek
    Нет, результатом вывода будет только одна строка - либо "Первый", либо "Второй", в зависимости от значения переменной vID.

    Теперь разберем запрос более подробно:

    1. Объявляются две переменные - vID типа number и vGG типа varchar2.
    2. В блоке SELECT происходит выборка столбца GG из временной таблицы, созданной с помощью оператора UNION ALL. Эта временная таблица представляет собой объединение двух множеств: первое множество имеет столбцы ID=1 и GG='Первый', а второе - ID=2 и GG='Второй'.
    3. В условии WHERE выбирается строка, у которой значение столбца ID равно значению переменной vID.
    4. Результат выборки записывается в переменную vGG.
    5. В блоке dbms_output выводится строка, содержащая значение переменной vGG.

    Таким образом, если перед запуском данного блока кода значение переменной vID было установлено равным 1, то на выходе мы получим строку "Первый". Если значение переменной vID было установлено равным 2, то на выходе мы получим строку "Второй". Если же в таблице отсутствует строка с указанным значением ID, то блок SELECT не вернет никаких строк, что может привести к ошибке выполнения.
    Ответ написан
    Комментировать
  • Где ошибка в запросе?

    @Khamzabek
    Ошибка в запросе заключается в неправильном форматировании строкового литерала. Во-первых, не хватает символа "||" перед строкой "from", так как он должен быть объединен со строкой "select". Во-вторых, также не хватает символа "||" перед строкой "on", так как он должен быть объединен со строкой "join". В-третьих, в строке "on (t.' v_trg_pk" не хватает символа "||" перед переменной "v_trg_pk". Кроме того, необходимо добавить символы ";" в конце запроса.

    Исправленный запрос:

    v_sql := 'merge into ' || in_trg_table || ' t'
    || ' using (select s.address, s.city, m.trg_pk_id'
    || ' from ' || v_src_table || ' s join ' || v_map_table || ' m'
    || ' on m.src_pk_id = s.cust_id ) sc'
    || ' on (t.' || v_trg_pk || ' = sc.trg_pk_id)'
    || ' when matched then update set '
    || 't.ADDRESS=sc.ADDRESS,t.CITY=sc.CITY;';
    Ответ написан
    Комментировать
  • Как исправить ошибку с display none?

    @Khamzabek
    Для того чтобы скрипт работал корректно, необходимо убедиться, что он вызывается после того, как все элементы страницы загрузились и были полностью инициализированы.

    Для этого можно использовать событие "DOMContentLoaded", которое срабатывает, когда загружены все элементы страницы. Например, так:
    document.addEventListener('DOMContentLoaded', function() {
      document.getElementById('connect_wallet').addEventListener('click', event => {
            const metamask = document.getElementById("metamask");
            const phantom = document.getElementById("phantom");
    
            if (metamask.style.display === "none" && phantom.style.display === "none") {
              metamask.style.display = "";
              phantom.style.display = "";
            } else {
              metamask.style.display = "none";
              phantom.style.display = "none";
            }
          });
    });

    Также убедитесь, что элементы с id "metamask" и "phantom" действительно существуют на странице. Если эти элементы генерируются динамически, то нужно дождаться их появления на странице и только после этого привязываться к ним.
    Ответ написан
    Комментировать
  • Как на Vite сгенерировать приложение в виде виджета для сторонних сайтов?

    @Khamzabek
    Для того чтобы собрать проект в режиме Production и получить файлы, которые можно загружать на любой сайт, нужно использовать команду `npm run build` для Vite.

    Эта команда соберет проект в папку `dist` и создаст оптимизированные файлы для продакшн, которые можно загрузить на любой сайт с помощью тега `script`.

    Например:
    ```
    <div id="widget-app" data-config="{....}"></div>
    <script type='text/javascript' src="https://domain.com/app.js"></script>
    
    ```


    если вы предполагаете, что ваш файл будет расположен на `https://domain.com/app.js`, тогда созданный Вами файл нужно поместить в папку сопоставимо с `https://domain.com/`, и назвать файл `app.js`.

    Когда вы загрузите html-код на ваш сайт и добавите эту строку кода, ваш виджет должен работать.
    Ответ написан
  • Как передать реальный IP клиента через nginx и zerotier?

    @Khamzabek
    Для правильной передачи IP клиента в данной ситуации необходимо добавить в настройки прокси следующую строку:

    proxy_set_header X-Real-IP $remote_addr;

    исходя из того, что она уже присутствует в настройках прокси, возможно проблема заключается в том, что запрос клиента не проходит через прокси, а направляется напрямую на VPS (nginx), из-за чего прокси не может зафиксировать и передать IP клиента. В таком случае необходимо настроить перенаправление (redirect) всех запросов с внешнего IP адреса на VPS (nginx) на Zerotier LAN (192.160.22.1), например, используя iptables.
    Ответ написан
  • Можно ли получить стутус изменения данных в indexedDB?

    @Khamzabek
    Да, есть способ: метод put возвращает объект IDBRequest, у которого есть событие onsuccess. Если запись была добавлена, то onsuccess вызовется без ошибок. Если запись была изменена, то событие onsuccess вызовется с объектом IDBKeyRange.

    Пример:
    function dbput(table, data){
        let openRequest = indexedDB.open('mydb', 1);
        openRequest.onsuccess = function() {
            let db = openRequest.result;
            let transaction = db.transaction(table, 'readwrite');
            let objectStore = transaction.objectStore(table);
            let request = objectStore.put(data);
            request.onsuccess = function(event) {
                if(event.target.result instanceof IDBKeyRange) {
                    console.log('Record updated')
                } else {
                    console.log('Record added')
                }
            };
            db.close();
        };
    }
    Ответ написан
  • Telegram.error.BadRequest: File must be non-empty, ошибка в создании телеграм бота?

    @Khamzabek
    Ошибка возникает из-за того, что переменная `image`, передаваемая в функцию `send_image`, не содержит данных. Это может произойти, если функция `get_board` возвращает пустой результат.

    Один из способов решения этой проблемы - добавить проверку на пустоту переменной `image` внутри функции `send_image` и не отправлять фото, если переменная пустая:

    ```
    def send_image(bot, update, image):
    if not image:
    update.message.reply_text('Failed to generate board!')
    return
    bio = BytesIO()
    bio.name = 'image.png'
    try:
    svg2png(image, write_to=bio)
    except ET.ParseError:
    print("Error: Failed to parse SVG image")
    bio.seek(0)
    bot.send_photo(chat_id=update.message.chat_id, photo=bio)
    ```

    Кроме того, можно добавить обработку исключения `ValueError` в функции `get_board` и возвращать `None`, если происходит ошибка:

    ```
    def get_board(board):
    board_string = chess.svg.board(board=board)
    board_string = board_string.replace('\n', '')
    output = BytesIO()
    try:
    cairosvg.svg2png(bytestring=board_string, write_to=output)
    except (ET.ParseError, ValueError):
    print("Error: Failed to generate board")
    return None
    output.seek(0)
    return output.getvalue()
    ```

    Таким образом, если svg-изображение не удается преобразовать в png или `board` содержит ошибки, функции будут возвращать значение `None`, и в функции `send_image` не будет попыток отправить пустое изображение.
    Ответ написан
    Комментировать
  • Как сделать относительный импорт без родительского пакета?

    @Khamzabek
    Один из способов решения этой проблемы состоит в добавлении директории проекта в sys.path. Это можно сделать в самом начале module2, например так:

    import os
    import sys

    # Добавляем путь к директории проекта в sys.path
    project_directory = os.path.abspath(os.path.join(os.path.dirname(__file__), ".."))
    sys.path.append(project_directory)

    # Теперь можно импортировать module1
    from module1 import *
    Ответ написан
    1 комментарий
  • Как досрочно выйти из состояния в aiogram с помощью инлайн кнопки?

    @Khamzabek
    Если вы используете состояния, то вы можете поместить все обработчики в состояния и при нажатии на кнопки вызывать переходы в другие состояния. Для реализации кнопки отмены можно создать отдельное состояние, которое будет обрабатывать команду отмены, и при ее вызове производить переход в это состояние.

    Пример реализации:

    ```python
    from aiogram.dispatcher.filters import Command
    from aiogram.types import Message, CallbackQuery
    from aiogram.dispatcher import FSMContext
    from aiogram.dispatcher import FSMContext
    from aiogram.dispatcher.filters.state import State, StatesGroup
    from aiogram.types import ReplyKeyboardMarkup, KeyboardButton, InlineKeyboardMarkup, InlineKeyboardButton

    class Registration(StatesGroup):
    email = State()
    cancel = State()

    async def start_handler(message: Message):
    keyboard_markup = ReplyKeyboardMarkup(resize_keyboard=True, selective=True)
    keyboard_markup.add(KeyboardButton(text='Отмена'))
    await message.answer(text='Введите email:', reply_markup=keyboard_markup)
    await Registration.email.set()

    async def email_handler(message: Message, state: FSMContext):
    email = message.text
    await state.update_data(email=email) # сохраняем email в состоянии
    await message.answer(f'Вы ввели email {email}')
    keyboard_markup = InlineKeyboardMarkup()
    keyboard_markup.add(InlineKeyboardButton('Отмена', callback_data='cancel'))
    await message.answer(text='Вы хотите сохранить email?', reply_markup=keyboard_markup)
    await Registration.next() # переходим в следующее состояние

    async def cancel_handler(callback_query: CallbackQuery, state: FSMContext):
    await state.reset_state() # очищаем все состояния
    await callback_query.answer(text='Отменено') # отправляем ответ пользователю
    await callback_query.message.delete_reply_markup() # удаляем клавиатуру

    async def save_handler(callback_query: CallbackQuery, state: FSMContext):
    data = await state.get_data() # получаем данные из состояния
    # сохраняем email в базу данных или выполняем другие действия
    await callback_query.answer(text='Email сохранен')
    await callback_query.message.delete_reply_markup() # удаляем клавиатуру
    await state.finish() # завершаем состояние

    # добавляем обработчики состояний
    dp.register_message_handler(start_handler, commands='register')
    dp.register_message_handler(email_handler, state=Registration.email, content_types=types.ContentTypes.TEXT)
    dp.register_callback_query_handler(cancel_handler, state=Registration.cancel, text='cancel')
    dp.register_callback_query_handler(save_handler, state=Registration.email, text='Да')

    ```

    В примере мы добавляем два состояния: `email` и `cancel`, а также три обработчика событий:
    - `start_handler` - начало регистрации, при вызове этой команды мы переходим в состояние `email` и выводим клавиатуру с кнопкой "Отмена".
    - `email_handler` - обработчик ввода email, сохраняет email в состояние и переходит в состояние `cancel`. В этом состоянии мы выводим кнопку "Отмена" и кнопку "Да" для сохранения email.
    - `cancel_handler` - обработчик кнопки "Отмена", удаляет клавиатуру и очищает все состояния.
    - `save_handler` - обработчик кнопки "Да", сохраняет email и завершает состояние.

    Кнопка "Отмена" вводится в ReplyKeyboardMarkup в обработчике `start_handler`. Кнопка "Отмена" в InlineKeyboardMarkup вводится в обработчике `email_handler`.
    Ответ написан
    2 комментария
  • Как обернуть текст в тег span?

    @Khamzabek
    jQuery(function($){
      $('#loadmore').click(function(){
        $(this).text('Загружаю...'); // изменяем текст кнопки, вы также можете добавить прелоадер
        var data = {
          'action': 'loadmore',
          'query': true_posts,
          'page' : current_page
        };
        $.ajax({
          url:ajaxurl, // обработчик
          data:data, // данные
          type:'POST', // тип запроса
          success:function(data){
            if( data ) { 
              $('#loadmore').html('<div class="loadmore-wrapper"><span>Загрузить ещё</span></div>').before(data); // вставляем новые посты
              current_page++; // увеличиваем номер страницы на единицу
              if (current_page == max_pages) $("#loadmore").remove(); // если последняя страница, удаляем кнопку
            } else {
              $('#loadmore').remove(); // если мы дошли до последней страницы постов, скроем кнопку
            }
          }
        });
      });
    }); 
    
    В данном коде нужно изменить строку:
    
    $('#loadmore').text('Загрузить ещё').before(data);
    
    на
    
    $('#loadmore').html('<div class="loadmore-wrapper"><span>Загрузить ещё</span></div>').before(data); 
    
    Это добавит новый div с классом "loadmore-wrapper", внутри которого будет тег span с текстом "Загрузить ещё".

    Вот что на это думает ChatGpt
    Ответ написан
    Комментировать