Задать вопрос
  • Как с помощью CSS и HTML сделать такой эффект как на картинке?

    alsolovyev
    @alsolovyev
    ¯\_(ツ)_/¯ Enjoy life, Eat well & Laugh often
    Вариантов есть несколько: через background-image, через canvas, через SVG маски... Вот пример через bg:
    Ответ написан
    Комментировать
  • Как получить превью видео вконтакте?

    alsolovyev
    @alsolovyev
    ¯\_(ツ)_/¯ Enjoy life, Eat well & Laugh often
    Так а в чем проблема? Вас отправляют правильно https://dev.vk.com/ru/method/video.get
    Отправляете запрос на получение видео или списка видео. В запросе указываете id клипа или клипов через запятую и получаете в ответ json к в поле response.item[n].image список из картинок. Другого варианта нет, они иначе хранят ссылки на картинки (если конечно вы не сохраните ссылки на картинки у себя на стороне и не привяжите их к id клипа)
    Пример ответа

    {
      "response":{
        "count":1
        "items":[
          {
            "adding_date":1671701038,
            "can_comment":0,
            "can_like":1,
            "can_repost":1,
            "can_subscribe":1,
            "can_add_to_faves":1,
            "can_add":1,
            "comments":0,
            "date":1671701032,
            "description":"",
            "duration":15,
            "image":[
              {
                "url":"https://i.mycdn.me/getVideoPreview?id=3376734079543&idx=1&type=39&tkn=3uLZ5s_T4TtRsvZfIwLngp8Qdjs&fn=vid_s",
                "width":130,
                "height":96,
                "with_padding":1
              },
              {
                "url":"https://i.mycdn.me/getVideoPreview?id=3376734079543&idx=1&type=39&tkn=3uLZ5s_T4TtRsvZfIwLngp8Qdjs&fn=vid_m",
                "width":160,
                "height":120,
                "with_padding":1
              },
              {
                "url":"https://i.mycdn.me/getVideoPreview?id=3376734079543&idx=1&type=39&tkn=3uLZ5s_T4TtRsvZfIwLngp8Qdjs&fn=vid_l",
                "width":320,
                "height":240,
                "with_padding":1
              },
              {
                "url":"https://i.mycdn.me/getVideoPreview?id=3376734079543&idx=1&type=39&tkn=3uLZ5s_T4TtRsvZfIwLngp8Qdjs&fn=vid_x",
                "width":800,
                "height":450,
                "with_padding":1
              },
              {
                "url":"https://i.mycdn.me/getVideoPreview?id=3376734079543&idx=1&type=39&tkn=3uLZ5s_T4TtRsvZfIwLngp8Qdjs&fn=vid_w",
                "width":1280,
                "height":720
              },
              {
                "url":"https://i.mycdn.me/getVideoPreview?id=3376734079543&idx=1&type=39&tkn=3uLZ5s_T4TtRsvZfIwLngp8Qdjs&fn=vid_t",
                "width":320,
                "height":180
              },
              {
                "url":"https://i.mycdn.me/getVideoPreview?id=3376734079543&idx=1&type=39&tkn=3uLZ5s_T4TtRsvZfIwLngp8Qdjs&fn=vid_u",
                "width":720,
                "height":405
              }
            ],
            "first_frame":[
              {
                "url":"https://i.mycdn.me/getVideoPreview?id=3376734079543&idx=0&type=39&tkn=WK9Wdwpqr6z6g9umM95aW3Ch3QM&fn=vid_f",
                "width":720,
                "height":405
              },
              {
                "url":"https://i.mycdn.me/getVideoPreview?id=3376734079543&idx=0&type=39&tkn=WK9Wdwpqr6z6g9umM95aW3Ch3QM&fn=vid_md",
                "width":480,
                "height":270
              },
              {
                "url":"https://i.mycdn.me/getVideoPreview?id=3376734079543&idx=0&type=39&tkn=WK9Wdwpqr6z6g9umM95aW3Ch3QM&fn=vid_d",
                "width":240,
                "height":135
              },
              {
                "url":"https://i.mycdn.me/getVideoPreview?id=3376734079543&idx=0&type=39&tkn=WK9Wdwpqr6z6g9umM95aW3Ch3QM&fn=vid_sm",
                "width":128,
                "height":72
              },
              {
                "url":"https://i.mycdn.me/getVideoPreview?id=3376734079543&idx=0&type=39&tkn=WK9Wdwpqr6z6g9umM95aW3Ch3QM&fn=vid_w",
                "width":1280,
                "height":720
              },
              {
                "url":"https://i.mycdn.me/getVideoPreview?id=3376734079543&idx=0&type=39&tkn=WK9Wdwpqr6z6g9umM95aW3Ch3QM&fn=vid_h",
                "width":960,
                "height":540
              },
              {
                "url":"https://i.mycdn.me/getVideoPreview?id=3376734079543&idx=0&type=39&tkn=WK9Wdwpqr6z6g9umM95aW3Ch3QM&fn=vid_w",
                "width":1280,
                "height":720
              }
            ],
            "width":1920,
            "height":1080,
            "id":456242110,
            "owner_id":-22822305,
            "ov_id":"4833925212306",
            "title":"Анимированные vmoji в VK Звонках",
            "is_favorite":false,
            "player":"https://vk.com/video_ext.php?oid=-22822305&id=456242110&hash=e037414127166efe&__ref=vk.api&api_hash=1677682946870d1f6fa590a9b323_HAZDCNJWG42DA",
            "added":0,
            "repeat":1,
            "type":"video",
            "views":19271183,
            "likes":{
              "count":15007,
              "user_likes":0
            },
            "reposts":{
              "count":137,
              "user_reposted":0
            }
          }
        ]
      }
    }

    Ответ написан
  • Как в reactjs удалять компонент из массива так, чтобы перерисовывался компонент?

    alsolovyev
    @alsolovyev
    ¯\_(ツ)_/¯ Enjoy life, Eat well & Laugh often
    1. Зачем вам нужен тут Context? Добавьте useState со списком задач в main компонент и передавайте их в дочерние компоненты:
    export function MainNode() {
        const [tasks, setTasks] = useState(predefinedTasks)
    
        const addTask = (listName, task) => {
           // ..
           // setTasks 
           // ..
        }
    
        const removeTask = (listNaem, taskId) => {
            // ...
            // setTasks
            // ..
        }
    
        
        const moveTask = (fromListName, toListName, taskId) => {
            // ..
            // setTasks
            // ..
         }
    
        return (
            <main>
                <TasksContainer type="Backlog" tasks={tasks.backlog} addTask={addTask}/>
                <TasksContainer type="Ready" ... />
                <TasksContainer type="InProgress" ... />
                <TasksContainer type="Finished" ... /> 
            </main>
        )
    }


    2. Если вам необходимо по каким-то причинам использовать context, то по аналогии с примером выше:
    export const TaskContext = createContext();
    
    export const TaskProvider = ({ children }) => {
        const [tasks, setTasks] = useState(predefinedTasks)
    
        const addTask = (listName, task) => {
           // ..
           // setTasks 
           // ..
        }
    
        const removeTask = (listNaem, taskId) => {
            // ...
            // setTasks
            // ..
        }
    
        
        const moveTask = (fromListName, toListName, taskId) => {
            // ..
            // setTasks
            // ..
         }
    
        return (
            <TaskContext.Provider value={{ tasks, moveTask, addTask }}>
                {children}
            </TaskContext.Provider>
        );
    }


    После чего используйте:
    const TaskList = ({ listName }) => {
        const { tasks, moveTask, addTask } = useContext(TaskContext);
        // ....
    }


    Вам надо почитать как работает реактивность в React и разобраться почему изменения в объекте не триггерят рирендер компонента. Если по простому, то Вам нужно не просто добавлять (push) новый task в список, а полностью заменять весь объект (data) с тасками и не использовать для каждого компонента свой useState
    // так не работет
    tasks.backlog.push(...) 
    
    // так работает
    const tasks = {....} // объект с задачами 
    const updatedTasks = { // создаем новый объект с задачами
          ...tasks,
          [listName]: [...tasks[listName], newTask]
     };
    setTasks(updatedTasks) // обновляем состояние
    Ответ написан
    1 комментарий
  • Напишите код, которой переделает структуру данных вот в такую?

    alsolovyev
    @alsolovyev
    ¯\_(ツ)_/¯ Enjoy life, Eat well & Laugh often
    let events = {
        '2019-12-29': ['name1', 'name3', 'name5', 'name7'],
        '2019-12-30': ['name4', 'name8', 'name9'],
        '2019-12-31': ['name2', 'name6']
    };
    
    // Преобразуем объект в массив объектов с помощью метода reduce
    // Object.keys(events) возвращает массив дат (ключей объекта events)
    let result = Object.keys(events).reduce((acc, date) => {
        // acc (аккумулятор) — это значение, которое сохраняется между итерациями
        // date — это текущий элемент массива (в данном случае дата из объекта events)
    
        // На каждой итерации для текущей даты перебираем все события
        events[date].forEach(event => {
            // Добавляем объект { date, event } в аккумуляторный массив acc
            acc.push({ date, event });
        });
        // Возвращаем аккумулятор после обработки всех событий для текущей даты
        return acc;
    }, []); // [] — начальное значение аккумулятора, с которого начинается накапливание данных
    
    // Как работает reduce:
    // 1. В начале acc равен [] (пустой массив).
    // 2. На каждой итерации мы добавляем в acc новые объекты { date, event }.
    // 3. Когда все даты и события обработаны, reduce возвращает конечный аккумулятор — массив объектов.
    
    // Выводим результат в консоль
    console.log(result);
    Ответ написан
  • Как остановить бота без добавления в черный список?

    alsolovyev
    @alsolovyev
    ¯\_(ツ)_/¯ Enjoy life, Eat well & Laugh often
    Бот останавливается на сервере где запущен (если, конечно, программист не предусмотрел специальную команду, которая бы останавливала бы на сервере бота самостоятельно. Это надо у создателя спрашивать).
    А если вы хотите удалить переписку с ним, то настройки чата (3 точки) -> очистить историю чата.
    Ответ написан
    Комментировать
  • Собраный через pkg exe файл не работает без папки node_modules?

    alsolovyev
    @alsolovyev
    ¯\_(ツ)_/¯ Enjoy life, Eat well & Laugh often
    Разве NodeExternals не создан именно для того, чтобы исключать node_modules из сборки?
    When bundling with Webpack for the backend - you usually don't want to bundle its node_modules dependencies. This library creates an externals function that ignores node_modules when bundling in Webpack.
    Ответ написан
  • Что делать если при создании zipархива в gulp5 по сборке www.youtube.com/@FreelancerLifeStyle у меня ошибки в терминале не появляются ,но zip не появ?

    alsolovyev
    @alsolovyev
    ¯\_(ツ)_/¯ Enjoy life, Eat well & Laugh often
    partikond, у Вас на 7 строчке (return app.gulp.src(`${app.path.buildFolder}/.**/*.*`, {}) лишняя точка перед **. Из-за этого скрипт не видит файлы, которые надо добавить в архив. Удалите ее и будет работать:
    import { deleteAsync } from "del"
    import zipPlugin from "gulp-zip"
    
    export const zip = () => {
        deleteAsync(`./${app.path.rootFolder}.zip`);
     // return app.gulp.src(`${app.path.buildFolder}/.**/*.*`, {})
        return app.gulp.src(`${app.path.buildFolder}/**/*.*`, {})
            .pipe(app.plugins.plumber(
               app.plugins.notify.onError({
                    title: "ZIP",
                    message: "Error:<%= error.message %>"
               })
            )
                
            )
            .pipe(zipPlugin(`./${app.path.rootFolder}.zip`))
            .pipe(app.gulp.dest('./'));
        
    }
    Ответ написан
    Комментировать
  • YouTube не работает через wi-fi на Mac, как исправить?

    alsolovyev
    @alsolovyev
    ¯\_(ツ)_/¯ Enjoy life, Eat well & Laugh often
    https://github.com/xvzc/SpoofDPI
    создает локальный прокси на Mac, настраивает через networksetup и делит пакеты при отправки
    What SpoofDPI does to bypass this is to send the first 1 byte of a request to the server, and then send the rest.
    Ответ написан
    Комментировать
  • Можно ли поменять настройки daterangepicker js при срабатывании events?

    alsolovyev
    @alsolovyev
    ¯\_(ツ)_/¯ Enjoy life, Eat well & Laugh often
    А у Вас какая задача-то? Просто поменять расположение стрелки? Если да, то можно просто классы поменять. Собсно, есть opensright и opensleft, которые отвечают за расположение этой стрелки:
    $('.daterangepicker').addClass('opensleft').removeClass('opensright');
    // $('.daterangepicker').addClass('opensright').removeClass('opensleft');


    Если у Вас какая-то более сложная логика отображения стрелки, то у инстанса picker'а есть методы:
    - updateElement
    - updateCalendars
    - show
    - hide
    Думаю, что можно попробовать вызвать метод обновления picker'а после изменения настроек (скрыть/открыть опционально)

    Ну, или на крайний случай просто удалить picker (picker.remove()) и инициализировать его с новыми опциями (написать отдельную функцию для инициализации, которая будет принимать опции)
    Ответ написан
    1 комментарий
  • Как у swiper добиться такого эффекта слайдера?

    alsolovyev
    @alsolovyev
    ¯\_(ツ)_/¯ Enjoy life, Eat well & Laugh often
    У Вас на каждом шаге есть спец. селекторы для слайдов:
    1. swiper-slide
    2. swiper-slide-prev
    3. swiper-slide-active
    4. swiper-slide-next
    5. swiper-slide

    ну и добавляйте стили для них какие и куда вам нужны. Или можно через effect/creativeEffect задать стили

    Например:
    - через стили https://jsfiddle.net/13txkeL8
    - через effect https://jsfiddle.net/jz6tb8a5/
    Что-то такое нужно было?

    зы можно ссылку на сайт с каруселью?
    Ответ написан
    Комментировать
  • Как достать данные из тега?

    alsolovyev
    @alsolovyev
    ¯\_(ツ)_/¯ Enjoy life, Eat well & Laugh often
    66ce38f823106833102800.png
    66ce3c46df02d322388001.png

    Ваш код работает правильно, если он должен извлекать текст из первого элемента p в элементе td class="text-center".
    Однако, если ваша цель — извлечь дату из 4 колонки, то нужно изменить селектор для поиска.

    Если использовать парсер, то я бы сделал так:
    1. Нашел бы все строки tr, которые содержат данные
    2. Для каждой строки (tr) получил бы все колонки (td)
    3. Извлек бы нужные данные (например, дату) из соответствующей колонки
    4. Сохранил бы эти данные в массиве
    5. Дальше бы уже использовал бы

    Но можно же просто отправить запрос и получить все эти данные в формате json, так не проще?
    Вот ссылка, которую можно в браузере открыть - https://etender.gov.az/api/events?EventType=2&Page...
    Обычный GET запрос отправляете и получаете:
    {
      "currentPage": 1,
      "totalPages": 173,
      "pageSize": 15,
      "itemsInPage": 15,
      "totalItems": 2591,
      "items": [
        {
          "eventId": 314749,
          "eventType": 7,
          "eventStatus": 1,
          "buyerOrganizationName": "NAXÇIVAN MUXTAR RESPUBLİKASI QAZ İSTİSMAR XİDMƏTİ",
          "eventName": "Qaz tikinti quraşdırma materialları və avadanlıqlarının satınalınması",
          "publishDate": "2024-08-27T19:50:59",
          "endDate": "2024-09-18T18:00:00",
          "hasNewVersion": false,
          "awardedParticipantName": null,
          "awardedParticipantVoen": null,
          "documentViewType": 0,
          "actualVersionId": 0,
          "privateRfxId": 93247
        }
    .....
      ]
    }
    Ответ написан
    4 комментария
  • Как запустить файл на ПК при получении сообщения от пользователя ВК?

    alsolovyev
    @alsolovyev
    ¯\_(ツ)_/¯ Enjoy life, Eat well & Laugh often
    Статья на Habr: Как создать чат-бота для ВКонтакте, используя Pyth...

    Есть два варианта реализации:
    • Webhook (описано в статье):
      1. Подписываетесь на событие - новое сообщение
      2. Ожидаете событие
      3. Получаете сообщение
      4. Запускаете программу


    • Вызов API (попроще):
      1. Напишите скрипт, который отправляет запрос messages.getHistory
      2. Парсите сообщения (находите новое)
      3. Запускаете программу
      4. Добавляете этот скрипт в планировщик задач (cron) каждые N минут



    Для упрощения задачи можно использовать одну из следующих библиотек:
    1. vk_api
    2. vk (давно не обновлялась)


    Если не хочется заморачиваться с кодом, попробуйте использовать конструктор для автоматизации задач. Например, на make.com — веб-приложении, которое выполняет задачи по расписанию (аналогично cron). У них есть интеграция с VK.
    Ответ написан
    1 комментарий
  • Выезжающее меню с анимацией?

    alsolovyev
    @alsolovyev
    ¯\_(ツ)_/¯ Enjoy life, Eat well & Laugh often
    Обычно это называют Elastic SVG/Menu. Вот демо на tympanus. Там же можно и статью найти, которая объясняет реализацию.

    Если нравиться больше видео версия, то на YouTube есть плейлист с аналогичным туториалом - ссылка
    66bd9ec52a42d919375208.gif
    Ответ написан
    2 комментария
  • Как прописать путь для командной строки?

    alsolovyev
    @alsolovyev
    ¯\_(ツ)_/¯ Enjoy life, Eat well & Laugh often
    На Mac нет папки ~/Applications, но есть /Applications:
    cp -R ~/Downloads/myFile /Applications/Something.app/Contents
    Ответ написан
  • Как не пропускать css клас в комит?

    alsolovyev
    @alsolovyev
    ¯\_(ツ)_/¯ Enjoy life, Eat well & Laugh often
    Возможно, я неправильно понимаю задачу, но что Вам мешает передать в Nunjucks переменную и использовать ее для условного рендеринга?

    Что я имею ввиду:
    Пример для WebPack:
    nunjucks.config.js
    module.exports = {
      data: {
        isDev: process.env.NODE_ENV === 'development'
      }
    }

    template.njk
    <div {% if isDev %} class="debug" {% endif %} ></div>
    <!-- or -->
    <div class="{{ 'debug' if isDev }}"></div>


    Для 11ty по аналогии. Только использовать addGlobal
    Ответ написан
    3 комментария
  • Почему browserslist выдает ошибку?

    alsolovyev
    @alsolovyev
    ¯\_(ツ)_/¯ Enjoy life, Eat well & Laugh often
    Что Вас смущает в тексте ошибки? Есть даже ссылка, в которой можно найти причины и способы решения данной проблемы.

    Есть 3 способа:
    1. Изменить в autoprefixer опцию browsers на overrideBrowserslist

    autoprefixer({
      overrideBrowserslist: ['last 4 versions'], 
      cascade: false
    }),

    2. Удалить в autoprefixed опцию browsers. Добавить в package.json ключ browerslist:

    "browserslist": [
        "last 4 versions"
      ]

    3. Удалить в autoprefixed опцию browsers. Создать в корне проекта файл ".browserslistrc". В нем указать:

    last 4 versions

    1 спосбо лучше не использовать
    Ответ написан
    3 комментария
  • На что лучше подцепить html страничку, если это сайт визитка с одним разделом блога?

    alsolovyev
    @alsolovyev
    ¯\_(ツ)_/¯ Enjoy life, Eat well & Laugh often
    Для подобных целей народ давно придумал Jekyll - генератор статических сайтов(или ему подобные движки: Hugo и etc). Создаете шаблон для новостей(статей), добавляете массив данных, а движок генерирует папку со статическими html страницами для каждой новости(сортировку по дате или параметру, который вы укажите).

    В итогу мы избавляемся от cms, базы данных и других ненужных тяжелых элементов. Сервер отдает только статические html страницы.
    Ответ написан
    Комментировать
  • Как уменьшить длину плавного подчеркивания?

    alsolovyev
    @alsolovyev
    ¯\_(ツ)_/¯ Enjoy life, Eat well & Laugh often
    1. Поменяйте ссылку на https://jsfiddle.net/Mesuti/9Lezxdn5/2/
    2. Зачем Вы задали display: block? Block элементы растягиваются на всю ширину. Либо используйте inline, либо задайте inline-block
    Ответ написан
    3 комментария
  • Как указать объект?

    alsolovyev
    @alsolovyev
    ¯\_(ツ)_/¯ Enjoy life, Eat well & Laugh often
    const el = document.querySelector('.someClassName');
    window.scrollTo(0, el.scrollHeight);

    или
    window.scrollTo(0, document.querySelector('.someClassName').scrollHeight);
    Ответ написан
  • Как написать парсер для SPA?

    alsolovyev
    @alsolovyev
    ¯\_(ツ)_/¯ Enjoy life, Eat well & Laugh often
    контент от сервера загружается потом

    Получается есть какой-то запрос от клиента, так? Ищите этот запрос на сайте, а потом повторяйте его в своем парсере. Скорее всегда надо будет передавать какие-то данные в заголовке(csrftoken или еще чего) - ищите какие.
    Возьмем для примера авторизацию на сайте. Вы же не можете спарсить сайт если не будете авторизованы, так? Приходится авторизоваться силами парсера, получать какой-то токен, при следующем запросе передавать этот токен, чтобы сервер проверил его и отдал скрытые данные.

    Вот код авторизации на python для примера:
    import requests
    
    url = 'https://nlstar.com/ru/office4/login/'
    
    s = requests.Session()
    
    r = s.get(url)
    csrf_token = r.cookies['csrftoken']
    
    data = {
        'login':        '007-2400101',
        'password':         '377609',
        'csrfmiddlewaretoken': csrf_token
    
    }
    
    d = s.post(url, data=data, headers=dict(Referer=url))
    dd = s.get('https://nlstar.com/')
    print(dd.text)


    Очевидно, что нет единого паттерна решения этой задачи. Потому что каждый сайт имеет свою защиту(мб в Вашем случае ее нет вообще и Вам просто post запрос на определенный url надо послать). Ищите. Разбирайтесь.
    Ответ написан
    1 комментарий