ما تغيّر، الأحدث أولًا. ما زال اسم المستودع على GitHub هو linkedin-scheduler.
v2.0.0
Worker على Cloudflare في حسابك الخاص
التثبيت بزر Deploy to Cloudflare، أو بوكيل برمجة، أو يدويًا.
كل دفعة تنشر الـ Worker الخاص بك وتزامن المنشورات إلى D1 والوسائط إلى Workers KV. يُرسل فقط ما تغيّر.
في كل دقيقة: حجز ذرّي، وإعادة المحاولة كل دقيقة لمدة 10 دقائق، والردود الغامضة لا تُعاد أبدًا، والنص نفسه لا يُنشر مرتين.
تعرض صفحة /status قائمة الانتظار والسجل والمدة المتبقية للرمز.
يمكن للفيديوهات الأكبر من 25 ميغابايت أن تذهب إلى حاوية R2 اختيارية.
إصلاحات
لم تعد النسخة الجديدة ترتبط بقاعدة بيانات موجودة عن طريق الخطأ: الاسم الافتراضي صار my-linkedin-scheduler، وتتحقق المزامنة من أن القاعدة تخص هذا المشروع قبل كتابة أي شيء.
دليل لتحديث نسخة إلى إصدار جديد.
v1
خمس محاولات لكل خانة
تُعاد المحاولة الفاشلة بعد دقيقتين، حتى 9:08، ثم في الخانة التالية.
v1.0.0
الإصدار الأول، على جهازك
ناشر بلغة Python يشغّله cron: منشور جاهز واحد على الأكثر في كل تشغيل، على ملفك الشخصي، عبر الواجهة البرمجية الرسمية لـ LinkedIn.
افتتاحيات بخط عريض عبر Unicode، وتعليق أول للروابط، وصور وفيديو.
You are installing **linkedin-scheduler** for the user: an open-source Cloudflare Worker that publishes
LinkedIn posts written as Markdown files, on the user's personal profile, through LinkedIn's official API.
Everything runs on the user's own Cloudflare account (Worker, D1, KV) and their own private GitHub
repository. Talk to the user in their language. Explain each step before running it, and stop to ask
whenever a choice belongs to them.
## Rules
- **The token is the user's.** Never ask them to paste the LinkedIn token or `ADMIN_TOKEN` into the chat,
never print or write them to a file, never commit them. They type them into `wrangler secret put` or
the Cloudflare dashboard themselves.
- **Never publish a real post** unless the user says so for that post. For tests, keep `DRY_RUN` at `1`
or use `visibility: CONNECTIONS` with their explicit agreement.
- **Never deploy over an existing Worker** without asking: run `pnpm exec wrangler deployments list
--name <name>` first and read the whole output. If the name is taken, choose another `name` in
`wrangler.jsonc` with the user.
- Keep the safety rules in `src/core/scheduler.ts` as they are (atomic claim, `unknown` never retried,
same text never twice, 10-minute window).
## 1. Learn and check the repo
Read `README.md`, `docs/install.md`, `docs/writing-posts.md` and `docs/scheduling.md`. Done when you can
say what a post file looks like, what makes a post go out, and what stops it from going out twice.
```bash
node --version # 22 or newer
pnpm install
pnpm test && pnpm typecheck
git remote -v # must be the user's own repository, and private
```
If the repository is public or is `cjdotdev/linkedin-scheduler` itself, stop: the user first creates a
private copy ("Use this template" → Private, or `gh repo create <name> --template
cjdotdev/linkedin-scheduler --private --clone` if `gh` is installed and signed in).
## 2. LinkedIn app and token (the user does the clicks)
Walk the user through `docs/linkedin-setup.md` steps 1 and 2, one step at a time, waiting for them:
create the app (it needs a LinkedIn Page), add **Share on LinkedIn** and **Sign In with LinkedIn using
OpenID Connect**, generate a token with `openid`, `profile`, `w_member_social`. They keep the token for
step 3; ask them to note the expiry date (today + 60 days).
## 3. Install on Cloudflare
```bash
pnpm run setup
```
It signs in to Cloudflare (a browser window opens), creates the D1 database and the KV namespace, writes
their ids into `wrangler.jsonc`, asks the timezone, deploys, then asks for the secrets: the user types
`LINKEDIN_ACCESS_TOKEN`, `LINKEDIN_TOKEN_EXPIRES` and `ADMIN_TOKEN` themselves. Suggest
`openssl rand -hex 24` for `ADMIN_TOKEN` and tell them to keep it.
Then set `DRY_RUN` to `1` for the first test:
`pnpm exec wrangler deploy --var DRY_RUN:1` (the next normal deploy puts it back to `0`).
## 4. Deploy on every push
Commit `wrangler.jsonc` and `scheduler.json` (ids are not secrets) and push. Then the user connects the
repository once: Cloudflare dashboard → Workers & Pages → the Worker → Settings → Build → Connect →
their repository, branch `main`, deploy command `pnpm run deploy`. Open that page for them if you can,
and wait until they confirm.
## 5. A first post
Copy `posts/texts/_example.md` to `posts/texts/<today>-test.md`, set a time 3 minutes ahead (get the real
time with `curl -sI https://www.cloudflare.com | grep -i '^date'`, never the machine's clock), `status:
ready`, `visibility: CONNECTIONS`. Commit and push, wait for the build, then:
```bash
curl -H "Authorization: Bearer <ADMIN_TOKEN, typed by the user>" https://<worker>.workers.dev/status
```
With `DRY_RUN=1` it shows `posted` with a `dry-run` link. Ask the user whether to post for real; if yes,
redeploy with `DRY_RUN` at `0` (a normal push does it) and schedule a new test post with a new text.
## Done when
- `pnpm test` passes, the Worker answers `{"ok":true}` on `/`, and `/status` lists the test post.
- Pushes deploy through Workers Builds (the user saw a build succeed).
- The user knows: how to write a post (`docs/writing-posts.md`), that the token expires on the date they
noted and how to renew it (`docs/linkedin-setup.md#renew-the-token`), and where to look when something
fails (`docs/troubleshooting.md`).