Action
Publish to blyg
Last update
12 days ago
- Unlisted
One-tap Blygger fragments: commits the draft to your site’s GitHub repo. Setup: github.com/miguelito4/drafts-blyg
Steps
-
script
// Publish to blyg — a Drafts action that posts the current draft as a // Blygger fragment by committing it to your site's GitHub repo. // Paste this into a single Script step. Edit CONFIG below. // ---- config ---- const CONFIG = Object.assign({ owner: "YOUR_GITHUB_USER", // GitHub user or org that owns the site repo repo: "YOUR_SITE_REPO", // repo your blyg is built from branch: "main", // branch your deploy builds from dir: "content/blyg", // folder where fragment files live ext: ".md", maxChars: 500, // fragments are tweet-sized; refuse longer frontmatter: false, // true if your build does NOT add frontmatter commitPrefix: "blyg: ", }, typeof BLYG_CONFIG_OVERRIDE !== "undefined" ? BLYG_CONFIG_OVERRIDE : {}); // ---- end config ---- const PUBLISHED_TAG = "blyg-published"; function fail(msg) { app.displayErrorMessage(msg); context.fail(msg); } // UTC, sortable, becomes the fragment's permanent ID: 20260927T194200Z function idFromDate(d) { return d.toISOString().replace(/[-:]/g, "").replace(/\.\d+Z$/, "Z"); } // Use Drafts' Base64 if present; otherwise a UTF-8-safe fallback. function b64(str) { if (typeof Base64 !== "undefined" && Base64.encode) return Base64.encode(str); const bytes = unescape(encodeURIComponent(str)); const A = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; let out = ""; for (let i = 0; i < bytes.length; i += 3) { const n = (bytes.charCodeAt(i) << 16) | ((bytes.charCodeAt(i + 1) || 0) << 8) | (bytes.charCodeAt(i + 2) || 0); out += A[(n >> 18) & 63] + A[(n >> 12) & 63] + (i + 1 < bytes.length ? A[(n >> 6) & 63] : "=") + (i + 2 < bytes.length ? A[n & 63] : "="); } return out; } function buildBody(text, d) { if (!CONFIG.frontmatter) return text + "\n"; return `---\ncreated: ${d.toISOString()}\n---\n\n${text}\n`; } function explain(status) { switch (status) { case 401: return "GitHub rejected the token (401). Re-enter it: Drafts › Settings › Credentials."; case 403: return "Token lacks permission (403). It needs Contents: read & write on this repo."; case 404: return "Repo, branch or path not found (404). Check owner/repo/branch, and that the token can see the repo."; case 409: case 422: return `GitHub refused the write (${status}). A file with this ID may already exist.`; default: return `GitHub error ${status}. See the action log.`; } } function main() { if (CONFIG.owner.startsWith("YOUR_") || CONFIG.repo.startsWith("YOUR_")) { return fail("Set owner and repo in the action's CONFIG first."); } const text = draft.content.trim(); if (!text) return fail("Empty draft."); if (draft.hasTag(PUBLISHED_TAG)) return fail("Already published. Duplicate the draft to post again."); if (text.length > CONFIG.maxChars) { return fail(`${text.length} chars, over the ${CONFIG.maxChars} cap.`); } const cred = Credential.create( `GitHub blyg ${CONFIG.owner}/${CONFIG.repo}`, `Fine-grained token with access only to ${CONFIG.owner}/${CONFIG.repo}, Contents: read & write.` ); cred.addPasswordField("token", "Token"); if (!cred.authorize()) return fail("No GitHub token provided."); const now = new Date(); const id = idFromDate(now); const path = `${CONFIG.dir.replace(/\/+$/, "")}/${id}${CONFIG.ext}`; const resp = HTTP.create().request({ url: `https://api.github.com/repos/${CONFIG.owner}/${CONFIG.repo}/contents/${path}`, method: "PUT", headers: { "Authorization": `Bearer ${cred.getValue("token")}`, "Accept": "application/vnd.github+json", "X-GitHub-Api-Version": "2022-11-28", }, data: { message: CONFIG.commitPrefix + text.replace(/\s+/g, " ").slice(0, 60), content: b64(buildBody(text, now)), branch: CONFIG.branch, }, }); if (resp.success) { draft.addTag(PUBLISHED_TAG); draft.update(); app.displaySuccessMessage(`Published ${id}`); } else { console.log(resp.responseText); fail(explain(resp.statusCode)); } } main();
Options
-
After Success Trash Notification Info Log Level Info
Items available in the Drafts Directory are uploaded by community members. Use appropriate caution reviewing downloaded items before use.