• Как вытаскивать cookie на java+selenide?

    grantur5707
    @grantur5707
    Full Stack Web Developer
    Извлекайте cookie непосредственно из браузера, используя встроенные возможности Selenide и WebDriver.

    import com.codeborne.selenide.Selenide;
    import org.openqa.selenium.Cookie;
    import java.util.Set;
    
    public class CookieExample {
        public static void main(String[] args) {
            Selenide.open("https://example.com/login");
    
            Set<Cookie> cookies = Selenide.getWebDriver().manage().getCookies();
    
            for (Cookie cookie : cookies) {
                if (cookie.getName().equals("refresh")) {
                    String refreshToken = cookie.getValue();
                    System.out.println("Refresh Token: " + refreshToken);
                }
            }
        }
    }


    Не забудьте подключить зависимость в build.gradle для Selenide:

    dependencies {
        implementation 'com.codeborne:selenide:6.10.0'
    }
    Ответ написан
  • Как решить проблему с узкой шириной текста возле float элементов?

    grantur5707
    @grantur5707
    Full Stack Web Developer
    Можно попробовать использовать комбинацию float с псевдоклассом :has() для проверки ширины контейнера или текста, рядом с которым располагается изображение.

    .container:has(.image) {
      display: block;
    }
    
    .container:has(.image:only-child) {
      text-align: center;
    }
    
    .container:has(.image) p {
      display: inline-block;
      min-width: 150px;
      width: calc(100% - 200px);
    }
    
    .image {
      float: left;
      max-width: 150px;
      margin: 0 10px 10px 0;
    }
    
    .container:has(.image) p:not(:only-child) {
      clear: both;
      display: block;
      text-align: center;
    }
    Ответ написан
    Комментировать
  • Нажатие на картинку обводится, как убрать?

    grantur5707
    @grantur5707
    Full Stack Web Developer
    .case-wrapper {
        position: relative;
        cursor: pointer;
        user-select: none;
        -webkit-tap-highlight-color: transparent;
        outline: none;
        background: transparent;
        border: none;
        padding: 0;
        margin: 0;
        box-shadow: none;
    }
    
    .case-wrapper:focus {
        outline: none;
        box-shadow: none;
    }
    
    .case-wrapper::-moz-focus-inner {
        border: 0;
    }
    Ответ написан
    Комментировать
  • .toggleClass не анимирует раскрытие и скрытие блока - что не так?

    grantur5707
    @grantur5707
    Full Stack Web Developer
    Вы неверно выбрали метод .toggleClass(), он не анимирует изменение высоты элемента.
    Вы можете использовать .slideToggle() в совокупности с .toggleClass():

    $(".show-more").click(function () {
        if($("#text-more").hasClass("expanded")) {
            $(this).text("показать все товары");
        } else {
            $(this).text("скрыть товары");
        }
        $("#text-more").slideToggle(1000).toggleClass("expanded");
    });
    Ответ написан
  • Тесты в django. Не создается задача через форму, на локал хосте все работает как надо. Что исправить?

    grantur5707
    @grantur5707
    Full Stack Web Developer
    Проверьте, как вы передаёте данные формы при отправке POST-запроса. В test_post_task_create, вы используете form_data = TaskCreateForm(data={...}).data, что может некорректно собирать данные для отправки в запросе.

    ef test_post_task_create(self):
        form_data = {
            'name': 'Totoro',
            'description': 'must watch it!',
            'status': self.status2.id, 
        }
        response = self.client.post(reverse('task_create'), form_data, follow=True)
        
        self.assertEqual(response.status_code, 302)
        self.assertTrue(Task.objects.filter(name='Totoro').exists())
        task = Task.objects.get(name='Totoro')
        self.assertEqual(task.author_id, self.user.id)
        self.assertEqual(task.author.first_name, 'Al')
        self.assertRedirects(response, '/tasks/')
        self.assertEqual(task.status.id, self.status2.id)
    Ответ написан
  • Как правильно в Generatepress добавить функцию, которая работала в «обычном» темплейте?

    grantur5707
    @grantur5707
    Full Stack Web Developer
    Чтобы ваша функция работала в теме GeneratePress, её нужно добавить в файл functions.php вашей дочерней темы (если вы используете дочернюю тему) или в раздел кастомных функций через админку, если вы не хотите изменять файлы темы напрямую.
    Ответ написан
    Комментировать
  • Как переслать фото из частной группы в бот Telebot?

    grantur5707
    @grantur5707
    Full Stack Web Developer
    import random
    
    media_ids = {
        'photos': [],
        'videos': []
    }
    
    @bot.message_handler(content_types=['photo', 'video'])
    def save_media(message):
        group_id_1 = 'MYGROUP_ID'
        if message.chat.id == int(group_id_1):
            if message.content_type == 'photo':
                file_id = message.photo[-1].file_id
                media_ids['photos'].append(file_id)
            elif message.content_type == 'video':
                file_id = message.video.file_id
                media_ids['videos'].append(file_id)
    
    @bot.message_handler(content_types=['text'])
    def media_frwrd(message):
        if message.chat.type == 'private':
            if message.text == 'Фото':
                if media_ids['photos']:
                    random_photo_id = random.choice(media_ids['photos'])
                    bot.send_photo(message.chat.id, random_photo_id)
                else:
                    bot.send_message(message.chat.id, "Нет доступных фото.")
            elif message.text == 'Видео':
                if media_ids['videos']:
                    random_video_id = random.choice(media_ids['videos'])
                    bot.send_video(message.chat.id, random_video_id)
                else:
                    bot.send_message(message.chat.id, "Нет доступных видео.")
    Ответ написан
    1 комментарий
  • Как отцентировать текст внутри div?

    grantur5707
    @grantur5707
    Full Stack Web Developer
    Проблема может быть связана с особенностями шрифта, который используется для плюса. Попробуйте добавить свойство line-height, чтобы оно совпадало с высотой элемента:
    .createButton {
        height: 3rem;
        width: 3rem;
        border-radius: 50%;
        color: #FFF;
        background: var(--green-color);
        display: flex;
        align-items: center;
        justify-content: center;
        font-size: 3rem;
        font-weight: 600;
        line-height: 1;
    }
    Ответ написан
  • Как сменить кодировку при парсинге XLSX файла (Excel) в Java?

    grantur5707
    @grantur5707
    Full Stack Web Developer
    Код с BufferedReader и кодировкой CP1251 не подходит для работы с XLSX. Для работы с файлами Excel через Apache POI вам нужно использовать FileInputStream:

    import org.apache.poi.xssf.usermodel.XSSFSheet;
    import org.apache.poi.xssf.usermodel.XSSFWorkbook;
    import java.io.FileInputStream;
    import java.io.IOException;
    
    public class Main {
        public static void main(String[] args) throws IOException {
            FileInputStream file = new FileInputStream("C:\\Users\\user\\Downloads\\report.xlsx");
            XSSFWorkbook workbook = new XSSFWorkbook(file);
            XSSFSheet sheet = workbook.getSheetAt(0);
    
    
            workbook.close();
            file.close();
        }
    }
    Ответ написан
    Комментировать
  • Можно ли как то сделать ответное сообщение через forward_messages или алтернативу?

    grantur5707
    @grantur5707
    Full Stack Web Developer
    forward_messages не поддерживает возможность ответа на сообщение напрямую через параметр reply_to_message_id.
    Как вариант, можно комбинировать пересылку и отправку ответа:

    forwarded_message = await app.forward_messages(chat_id=destination_chat_id, from_chat_id=source_chat_id, message_ids=message_id)
    
    await app.send_message(chat_id=destination_chat_id, text="Ответ на пересланное сообщение", reply_to_message_id=forwarded_message.message_id)
    Ответ написан
    Комментировать
  • Как удалить Content-Security-Policy?

    grantur5707
    @grantur5707
    Full Stack Web Developer
    Наверное, одним из универсальных вариантов будет использование прокси-сервера, который вам поможет обойти заголовки CSP путем маршрутизации запросов через сервер, где эти заголовки могут быть изменены.

    На node.js он разворачивается довольно просто:

    const http = require('http');
    const httpProxy = require('http-proxy');
    
    const proxy = httpProxy.createProxyServer({});
    
    http.createServer(function(req, res) {
        proxy.web(req, res, {
            target: 'https://game-analytics.ru',
            changeOrigin: true,
            selfHandleResponse: true
        });
    
        proxy.on('proxyRes', function(proxyRes, req, res) {
            let body = [];
    
            proxyRes.on('data', function(chunk) {
                body.push(chunk);
            });
    
            proxyRes.on('end', function() {
                body = Buffer.concat(body);
                res.setHeader('Content-Security-Policy', '');
                res.writeHead(proxyRes.statusCode, proxyRes.headers);
                res.end(body);
            });
        });
    
    }).listen(3000, () => {
        console.log('Прокси-сервер запущен на порту 3000');
    });


    В вашем коде используйте прокси-адрес при создании iframe окна:

    <html lang="ru">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>Создание Iframe через JavaScript</title>
    </head>
    <body>
    <div id="iframe-container"></div>
    <script>
        document.addEventListener('DOMContentLoaded', function() {
            const iframe = document.createElement('iframe');
            iframe.setAttribute('src', 'http://localhost:3000');
            document.getElementById('iframe-container').appendChild(iframe);    
        });
    </script>
    </body>
    </html>
    Ответ написан
  • Какой обработчик в pyrogram использовать, чтобы ловить вход в группу(чат) user-бота?

    grantur5707
    @grantur5707
    Full Stack Web Developer
    Так в pyrogram нет прямого обработчика, который тебе нужен, но ты можешь попробовать использовать событие, которое отслеживает изменения статуса члена чата через обработчик on_chat_member_updated

    @app.on_chat_member_updated()
    async def on_chat_member_updated(client, chat_member_updated: ChatMemberUpdated):
        if chat_member_updated.new_chat_member.user.is_self:
            while True:
                message = "Какое-то сообщение..."
                await client.send_message(chat_member_updated.chat.id, message)
                await asyncio.sleep(180)
    Ответ написан
  • Добавление и получение данных в locacal и session storage с помощью selenium python, как реализовать?

    grantur5707
    @grantur5707
    Full Stack Web Developer
    С использованием библиотеки selenium python, полагаю, никак.
    Разве что костылями выполнять через javascript:

    from selenium import webdriver
    
    driver = webdriver.Chrome()
    
    driver.get("https://google.com")
    
    driver.execute_script("window.localStorage.setItem('key', 'value');")
    driver.execute_script("window.sessionStorage.setItem('key', 'value');")
    
    local_storage_value = driver.execute_script("return window.localStorage.getItem('key');")
    session_storage_value = driver.execute_script("return window.sessionStorage.getItem('key');


    Но я бы посоветовал использовать Playwright, там есть поддержка управления сессиями и хранилищами в более удобном виде.
    Ответ написан
    5 комментариев
  • Как сделать динамическое добавление на ajax, чтобы записи не дублировались?

    grantur5707
    @grantur5707
    Full Stack Web Developer
    1. Используй метод .off() для удаления предыдущих обработчиков событий перед добавлением нового.
    2. Исправь код AJAX, чтобы ограничить количество перерисовок элементов.

    $("#modal").off('submit').on('submit', function (e) { 
        e.preventDefault();
        var form_data = $(this).serialize();
    
        $.ajax({
            type: "POST",
            url: "user/add.php",
            data: form_data,
            success: function (html) {
                document.getElementById("shadow").style.display = "none";
                document.getElementById("modal").style.display = "none";
                $('#modal').trigger('reset');
                $("#main").append(html);
            }
        });
    });


    add.php:

    require "../database/Task.php";
    
    if (isset($_POST['title']) && isset($_POST['description'])) {
        $task_mess = new Task;
        $task_mess->add_task($_POST['title'], $_POST['description']);
    
        $new_task = $task_mess->get_last_task();
    
        echo "<div class='task'>
                <h3>{$new_task['title']}</h3>
                <p>{$new_task['description']}</p>
              </div>";
    }
    Ответ написан
    2 комментария
  • Как сделать в строке замену нескольких конкретных одинаковых символов на один такой?

    grantur5707
    @grantur5707
    Full Stack Web Developer
    Если я правильно понял задачу, то тебе нужно заменить несколько подряд идущих запятых или точек на одну точку в строке.

    Набросал примерную логику, получилось как-то так:

    #include <stdio.h>
    #include <stdlib.h>
    
    int main() {
        char str[12];
        double number = 0;
        printf("Enter a number to edit: ");
        gets(str);
        int i = 0, j = 0;
        char editedStr[12];
        int dot_found = 0;
    
        printf("Entered number :      %s\n", str);
    
        while (str[i] != '\0') {
            if (str[i] == ',' || str[i] == '.') {
                if (!dot_found) {
                    editedStr[j++] = '.';
                    dot_found = 1;
                }
            } else {
                editedStr[j++] = str[i];
                dot_found = 0;
            }
            ++i;
        }
        editedStr[j] = '\0';
    
        printf("Edited number but not converted:      %s\n", editedStr);
    
        number = atof(editedStr);
        printf("Edited number: %f\n", number);
    
        return 0;
    }
    Ответ написан
    Комментировать
  • Как отключить автоматическое завершение работы браузера при выходе из функции в Playwright?

    grantur5707
    @grantur5707
    Full Stack Web Developer
    Привет!

    Не очень понял трактовку твоего вопроса
    Я просто не могу выделить части кода в отдельные методы. Мне нужно чтобы мой код размещался в разных методах...


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

    Вот, например, так:

    IBrowser browser;
    IPage page;
    
    async Task InitializeBrowserAsync()
    {
        var playwright = await Playwright.CreateAsync();
        browser = await playwright.Chromium.LaunchAsync(new BrowserTypeLaunchOptions { Headless = false });
        page = await browser.NewPageAsync();
    }
    
    async Task CreateRegistryAsync()
    {
        await page.GetByRole(AriaRole.Button, new() { Name = "Создать реестр" }).ClickAsync();
        string strKitCategory = templateSheet.GetCell(currentSheetRow, (int)ExcellTemplateTableSheet.ColumnType.kitCategory);
        await page.GetByText(strKitCategory).ClickAsync();
    }
    
    async Task FillDetailsAsync()
    {
        string rChKit = templateSheet.GetCell(currentSheetRow, (int)ExcellTemplateTableSheet.ColumnType.RCHKit);
        await page.GetByLabel("Комплект РЧ").FillAsync(rChKit);
        await page.GetByText(rChKit).ClickAsync();
    }
    
    async Task SubmitRegistryAsync()
    {
        string worcksDescription = templateSheet.GetCell(currentSheetRow, (int)ExcellTemplateTableSheet.ColumnType.descriptionOfWorks);
        await page.GetByLabel("Описание работ").FillAsync(worcksDescription);
        await page.GetByRole(AriaRole.Button, new() { Name = "Создать", Exact = true }).ClickAsync();
    }
    
    async Task MainAsync()
    {
        await InitializeBrowserAsync();
        await CreateRegistryAsync();
        await FillDetailsAsync();
        await SubmitRegistryAsync();
    }


    Если важно сохранять не только браузер, но и сессию пользователя, можешь использовать persistent context:

    async Task InitializePersistentContextAsync()
    {
        var playwright = await Playwright.CreateAsync();
        var browser = await playwright.Chromium.LaunchPersistentContextAsync("PATH", new BrowserTypeLaunchPersistentContextOptions { Headless = false });
        page = browser.Pages.First();
    }
    Ответ написан