Windows-GPU-UNLOCK
This is Windows GPU UNLOCK: RTX3090 UEFI port, Korean no-reset Windows boot guide, verified source and benchmark evidence
AI translation
Привіт! Щодня о 11:00 і 20:00 надсилаю свіжі вакансії Product Design та UI/UX з DOU і Djinni. Набридне, пиши /stop
Translation pending
OtherPython · JavaScriptGitHub @eugene-jetOnlineOwner unconfirmed
Have you tried it? One tap is enough. No sign-in needed.
Twice-daily Telegram digest of Product Design / UI/UX vacancies scraped from DOU and Djinni, triggered on a punctual Cloudflare Worker cron. Subscribe: https://t.me/JobsbroBot · Digest: https://job-searcher-trigger.evnikmoroz.workers.dev/latest
Taken from the repository README
Loading the full README.
Read the full README ↗A twice-daily Telegram digest of fresh Product Design and UI/UX jobs — scraped from DOU and Djinni, delivered on time.
job-searcher watches two Ukrainian job boards, keeps only the Product Design /
UI/UX vacancies posted in the last three days, and pushes a tidy, grouped digest
to a Telegram chat every morning and evening. The same digest is archived as a
dated Markdown file in reports/, so there is a permanent,
browsable history. There are no servers to run and nothing to pip install: the
scraping runs on GitHub Actions, and the punctual twice-a-day schedule is driven
by a small Cloudflare Worker.
Each run posts a message like this to Telegram — the same content is saved as a
dated file such as
reports/report-2026-09-26.md:
Design вакансії 🧑💻✨
🕒 26-09-2026 21:00 (Київ)
За останні 3 дні (24/26-09-2026)🔵 Djinni (6/72) · 🗂️ Всі вакансії
⦿ 25-09-2026
• Product UI/UX Designer — Asocial · Remote
• UX/UI Product Designer — B2BSoft · Remote
⦿ 24-09-2026
• Product designer — bodo · UKR
• Product UX/UI Designer — In Sync · Remote
• Trainee/Junior UX/UI Designer — BasMar Software · UA
• UI/UX Designer — Vista Auction · Remote🟢 DOU (3/261) · 🗂️ Всі вакансії
⦿ 25-09-2026
• Senior Product Designer — WhiteTech · віддалено
• UI/UX Designer — VCHASNO GROUP · Київ, віддалено
⦿ 24-09-2026
• UX Designer / Product Designer — Perla Helsa · Київ
openpyxl, used solely to write the Excel
analytics workbook (the standard library cannot produce an .xlsx with a
chart).Alongside the daily digest, every run records the scanned vacancy total each board carried that day — the raw count the board itself shows, before the relevance filter (so DOU's whole Design category and Djinni's Product Design + UI/UX tag listing) — and keeps a running time series:
data/vacancy_counts.csv is the source of
truth — one row per calendar day with the columns date, dou, djinni. A
second run on the same day overwrites that day's numbers with the latest; a
source that failed to scrape is left blank (a gap), not recorded as 0.Both files are committed by the same auto-merged pull request as the Markdown report, so the history builds itself. The workbook's document properties are set deterministically from the data, so a run whose counts did not change produces no spurious binary diff.
The bot's own audience is tracked separately, by the Worker:
pip install -r requirements.txt
python3 daily_report.py
This writes reports/report-YYYY-MM-DD.md, updates
data/vacancy_counts.csv and reports/vacancy-analytics.xlsx, and prints a
short summary to stdout. Telegram delivery is skipped locally — it only sends
when the TELEGRAM_BOT_TOKEN and TELEGRAM_CHAT_ID environment variables are
set.
The parsing, report-rendering and analytics helpers are covered by an offline
unit-test suite in tests/. The tests run against in-memory fixtures
and never touch the network, so they are fast and reproducible:
pip install -r requirements-dev.txt
python3 -m pytest
The same suite runs in CI on every push and pull request
(.github/workflows/tests.yml).
scrapers.py fetches and normalizes vacancies from both boards using only
the Python standard library. DOU is paginated through its xhr-load endpoint
and its Ukrainian "day month" list date is parsed; Djinni is read from the
JobPosting JSON-LD on each results page, including its datePosted. Only
titles matching the Product Design / UI/UX filter are kept.daily_report.py runs the scrapers and, for each kept Djinni vacancy, reads
the vacancy page's "Оновлено" (updated) date and uses it in place of the
published date when present, so a re-bumped posting resurfaces. It keeps the
vacancies whose date falls within the window (WINDOW_DAYS, default 3 = today
and the two previous days), groups them by source, sorts newest first, stamps
the generation time in
Europe/Kyiv, writes the Markdown report, and sends the Telegram message(s). If
a source fails, the report notes the error; if both fail it exits non-zero so
no empty report is committed.analytics.py upserts the day's per-source scanned totals (the raw count
each board returns before the relevance filter) into
data/vacancy_counts.csv and regenerates reports/vacancy-analytics.xlsx
(the Counts sheet plus a line chart) with openpyxl. See
Analytics.trigger/ is a Cloudflare Worker that acts as the clock. Its cron calls
the workflow's workflow_dispatch entry point on time — see
trigger/README.md for a one-time deploy.The report runs as a GitHub Actions workflow
(.github/workflows/daily.yml). It is triggered
twice a day — at 11:00 and 20:00 Europe/Kyiv, all year round — by the
Cloudflare Worker in trigger/, which calls the workflow's
workflow_dispatch entry point. The Worker's cron runs on UTC, so it picks the
report ticks by their Kyiv time: 08:00 and 17:00 UTC in summer, 09:00 and 18:00
UTC in winter. GitHub Actions' own schedule: was removed: it
ran on a best-effort basis and routinely fired tens of minutes to several hours
late (or was dropped under load), so the punctual Worker cron replaced it.
Each run sends the digest to Telegram and, when the report changed, lands the
Markdown file in reports/ through an auto-merged pull request on a short-lived
branch rather than pushing to main directly. GitHub-hosted runners have the
outbound network access the boards need; the scraping runs there because the
Claude Code cloud sandbox blocks those connections by egress policy.
Telegram delivery is enabled by two repository secrets, TELEGRAM_BOT_TOKEN and
TELEGRAM_CHAT_ID; without them the script just writes the report and skips the
notification. TELEGRAM_CHAT_ID may list several comma-separated destinations
(for example a personal DM alongside a channel).
Optionally the digest can run as a subscription bot: people open
@JobsbroBot and press /start, and each receives the
report in their own DM. Pressing /start also sends the current digest right
away — the Worker serves it from its own storage in about a second, and keeps
that copy no more than half an hour old with a refresh run, every half hour
through the day, that scrapes and stores but sends nothing (rate-limited to one
digest per chat every 10 minutes), so a new subscriber neither waits for the next
scheduled run nor for a scrape. Subscribers are stored by the Cloudflare
Worker in trigger/, and the report reads the active list (via the
SUBSCRIBERS_URL secret) on top of any static TELEGRAM_CHAT_ID, retiring
anyone who blocked the bot (via DEACTIVATE_URL). This is what makes the user
count meaningful — see trigger/README.md for the setup and
the /stats endpoint that reports how many people use the bot.
The digest itself is also readable as a web page, at
/latest — the
same vacancies the bot sends on /start, refreshed every half hour, so the link
can be opened or passed on without subscribing.
A shareable dashboard charts active and total subscribers over time. Both pages show only what any subscriber would see — vacancies on one, aggregate counts with no chat ids on the other — so the links are safe to share.
Trigger a run by hand any time from the Actions tab (Run workflow) or with:
gh workflow run "Daily design vacancy report"
To put a one-off note above the digest's heading, for example to explain why a
digest is being sent again, pass the notice input. Only that run's recipients
see it; the digest the bot serves on /start leaves it out.
gh workflow run "Daily design vacancy report" -f notice="⚠️ Text of the note"
The relevance filter (in scrapers.py, RELEVANT) matches Product Design,
UI/UX and Graphic Design titles in English and Ukrainian: product design,
ui/ux, ux/ui, ux designer, ui designer, user experience,
user interface, head of design (a leadership title that often names no
specialty), vibe-code designer and vibe designer (a designer who builds
with AI coding tools), graphic design (which also catches graphic designer), plus
Ukrainian forms such as графічний дизайнер, продуктовий дизайнер,
продакт-дизайнер, UX-дизайнер, UI-дизайнер and дизайнер інтерфейсів. The
Ukrainian rules anchor on the specialty word, so a bare дизайнер is not
matched. Adjust that regular expression to widen or narrow the report.
The digest itself is narrower than the scraper. RELEVANT is built from two
patterns — PRODUCT_UI_UX and the graphic-design one — and
daily_report._prepare keeps only the titles matching PRODUCT_UI_UX. That
still matters for DOU, whose listing is the board's whole Design category and so
carries graphic-design titles the digest drops. Djinni is scoped by tag instead,
and DJINNI_URLS asks only for Product Design and UI UX, so graphic-design
vacancies reach neither the digest nor the scanned total that feeds the
analytics series. A title naming both families (Graphic/UX Designer) counts as
UI/UX and is sent. Restoring graphic-design roles means putting the
Graphic%20Design tag back in DJINNI_URLS and dropping the PRODUCT_UI_UX
filter in _prepare.
A vacancy that asks for vibe coding stays where it is but gets a
⚡ vibe coding mark at the end of its line. daily_report.VIBE_CODING looks
for the practice and the tools (Claude Code, Lovable, v0, Bolt, Figma Make,
Replit, Windsurf) in the title and the description. Djinni descriptions arrive
with the listing, while DOU needs one page load per vacancy in the window to
read its description. The welcome digest sent on /start skips those page
loads, so there a DOU vacancy is marked only when its title shows it.