У нас в телеграм-чаті каналу часто приносять посилання на твітер. Дивитися їх незручно, бо ти тикаєш посилання, щоб почитати коротенький текст. Логічно було б цей текст вставляти в прев'ю лінка, але твітер так робити не буде, бо їм потрібен енгейжмент.
Якось прочитав у блозі Swizec Teller пост про те як він зробив скріншотилку інстаграма на лямбді. Згадав про це і подумав — давай і собі зроблю! Впевнений що таких проєктів є ціла купа, але я хотів отримати задоволення від розробки, бо люблю робити продукти та програмувати😊.
Колись давно я хотів зробити бота який буде автоматично банити за матюки, проєкт провалився і зараз цей бот просто рахує статистику повідомлень (хто більше написав) та робить ще деяку дрібну роботу. Вирішив його розширити.
ШІ швидко підказав потрібний код:
def screenshot(link)
browser = Ferrum::Browser.new({browser_options: {'no-sandbox': nil}})
begin
browser.go_to(link)
browser.network.wait_for_idle(duration: 2, timeout: 30)
path = "tmp/tweet_#{Time.now.to_i}.jpeg"
browser.screenshot(path: path, selector: 'article[data-testid="tweet"]', quality: 95, format: "jpeg")
path
rescue StandardError => e
Rails.logger.error("Error capturing screenshot: #{e.message}")
nil
ensure
browser.reset
browser.quit
end
end
За 5 хв протестив локально — все працює як треба! Заливаю, не працює. WTF?
Починаю розбиратися. Спочатку думав що проблема в alpine на якому зібраний базовий образ. Потім думав що проблема у твітері який блокує запити. Потім в, тому що недостатньо пам'яті. Потім в, тому що браузер закривається. Перевів з альпіну на дебіан, переконався що курли на твітер з хоста проходять, додав пам'яті, зробив браузер перзистентним.
Але все одно скриншоти робились через раз. Я витратив ще купу часу на різних форумах у спробах розібратися що ж не так, адже все було максимально просто — бібліотека то тонкий врапер над процесом хроміума, там нічому було ламатися.
Врешті я здався і вирішив переписати все на Java. ШІ швидко підказав потрібний код на Selenium:
driver.get(url);
driver.manage().timeouts().implicitlyWait(Duration.ofSeconds(10));
WebElement element = driver.findElement(By.cssSelector(cssSelector));
File screenshotFile = element.getScreenshotAs(OutputType.FILE);
Я нашкрябав вебсервіс який би виставив ендпоїнт до інтернету. З минулого разу я згадав про Ulitimate Web Frameworks Benchmark, і такий думаю, давай не буду брати Spring Boot, а візьму vert.x. Сказано—зроблено—задеплоєно. Запускаю — не працює😅
Хром видає якісь крипто помилки, нічого не гуглиться. Заходжу на хост, запускаю хроміум вручну, той пише OOM. Фух, ясно, даю машині більше пам'яті, вуаля — все працює.
❓Наступна проблема—браузер не встигає завантажити прев'ю картинки або відео, які є у твіті. На жаль, я не знайшов як це нормально вирішити, тому просто додав 5 секунд очікування після відкриття сторінки. Можливо читачки та читачі підкажуть як більш елегантно це розв'язати?
Ну все, чатботи крутяться, скриншоти мутяться. Додав туди ще код який буде відповідати в телеграм, бо не хотілося робити муторну інтеграцію з основним сервісом.
Потім подивився що скриншоти треба в рамку, бо телеграм їх обрізає по висоті. Додав паддінгу 50px та й вспокоївся.
Три доби — жодної помилки, пам'ять не протікає, в середньому скриншот робиться за 7 секунд. Як на мене, це дуже багато, але вище написав що не знаю як виправити таймаут.
Бот — @chat_keeper_bot. Ви можете додати собі його в будь-який чат, і він теж буде працювати.
Сподобалось? Долучайтеся до мого телеграм каналу: https://t.me/full_of_hatred