job-feed

The job feed is how a published job posting turns into a formatted card in a Discord channel. It lives inside the youteacher_discord service as a small application service (JobFeedService) plus one pair of HTTP routes.

How a job enters

A job posting arrives at an ingest endpoint, POST /discord/v1/job-feed/ingest. The upstream job service is meant to call it with a service credential when a job is published. The request body is validated field by field — jobId, title, city, country, a valid url, and optional salaryMin / salaryMax / currency / salaryPeriod / jobType / description / benefits — before anything downstream runs.

Where it goes

A Discord channel opts into the feed through a configuration record: a channelId and an optional filter of countries and cities. When a job comes in, the service walks every configured channel and decides, per channel, whether that channel should see this job.

The match rule is inclusive-by-default: an empty country or city list means "no restriction," so a channel with no filters receives everything. A non-empty list restricts to exact membership — the job's country must be in the channel's country list, and its city in the city list, for the job to pass.

Not posting the same job twice

Dedup is keyed per job and per channel — the key is jobId:channelId. The same job can still reach two different channels, but a channel never receives the same job twice. The posted-set is only marked after a successful post, so a failed send does not silently burn the job; a publish failure is logged, not thrown, so one bad channel does not stop the others.

The Discord card

Each job is rendered as a Discord embed. The title links to the full posting. Location (city, country) and a formatted salary lead a headline line, followed by a trimmed snippet of the job description. Structured fields carry the same data — location, salary, job type, and benefits — each shown only when present. Salary formatting collapses a min/max pair into a range (or a single value with a +), appends the currency, and maps the pay period to /month, /year, or /hour. Job type is normalized to a display form (Full-time, Part-time, Contract, Internship). All free text is whitespace-collapsed and length-capped so the card stays within Discord's limits.

Owner controls and defaults

Channel configuration is written through PUT /discord/v1/job-feed/config, guarded so only an admin user may change it. On top of that, a single default channel can be auto-registered at startup from an environment setting: if a default channel id is present in the environment, the service registers it with no filters when the process boots, so the feed works out of the box without a manual config call.

Present shape

Configuration and the dedup set are held in memory, by the service's own comment, as an MVP stance — durability (a database) is the noted next step. So a restart clears both the channel configs (minus the env-seeded default) and the record of what was already posted.

about this entry

One of sijie's wiki entries. The AI on this site is grounded in the same corpus and answers in sijie's voice, with citations back to entries like this one — answering costs sijie money, so it waits behind a code: enter an access code →

job-feed