Телеграм-бот для скриншотів твітера

У нас в телеграм-чаті каналу часто приносять посилання на твітер. Дивитися їх незручно, бо ти тикаєш посилання, щоб почитати коротенький текст. Логічно було б цей текст вставляти в прев'ю лінка, але твітер так робити не буде, бо їм потрібен енгейжмент.

Якось прочитав у блозі 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