├── .github └── workflows │ └── deploy.yml ├── .gitignore ├── README.md ├── index.js ├── package-lock.json ├── package.json └── wrangler.toml /.github/workflows/deploy.yml: -------------------------------------------------------------------------------- 1 | name: Deploy 2 | 3 | on: 4 | push: 5 | branches: 6 | - master 7 | 8 | jobs: 9 | deploy: 10 | runs-on: ubuntu-latest 11 | name: Deploy 12 | steps: 13 | - uses: actions/checkout@v2 14 | - name: Publish 15 | uses: cloudflare/wrangler-action@1.2.0 16 | with: 17 | apiToken: ${{ secrets.CLOUDFLARE_API_TOKEN }} -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /target 2 | /dist 3 | **/*.rs.bk 4 | Cargo.lock 5 | bin/ 6 | pkg/ 7 | wasm-pack.log 8 | worker/ 9 | node_modules/ 10 | .cargo-ok 11 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |

2 | 3 |

crowdin-discord-webhooks

4 |

5 | 6 | **crowdin-discord-webhooks** sends your Crowdin events to a Discord channel, no hosting or servers required! Simply point a Crowdin webhook to it and you're good to go! 7 | 8 | ![Image](https://i.imgur.com/UBxcYoA.jpg) 9 | 10 | ## Setup 11 | 12 | 1. Create a Discord Webhook in the channel you want to receive your events in and copy its URL 13 | 2. Replace `https://discordapp.com/api/webhooks` with `https://crowdinwebhooks.switchblade.xyz`, and save it temporarily somewhere like notepad 14 | 3. Go to your Crowdin Project settings, and navigate to the "API & Webhooks" tab 15 | 4. Click _"Add Webhook"_ and configure it like so: 16 | - **Name** can be whatever you want 17 | - Paste the Webhook URL from Step 2 on the **URL** field 18 | - Set the **Request Method** to `POST` 19 | - Set the **Content Type** to `application/json` 20 | - Select what events you want to be notified about 21 | 5. Click _"Test"_ on the right panel to check if your webhook is working 22 | 6. Click _"Add"_ and you should be good to go! 23 | 24 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | addEventListener('fetch', event => { 2 | event.respondWith(handleRequest(event.request)) 3 | }) 4 | 5 | async function handleRequest(request) { 6 | if (request.method === 'POST') { 7 | const path = new URL(request.url).pathname 8 | const crowdin = await request.json() 9 | switch (crowdin.event) { 10 | case 'file.translated': 11 | await sendWebhook(path, `:white_check_mark: **${crowdin.file}** is now fully translated to \`${crowdin.language}\` ${getFileUrl(crowdin)}\n---`) 12 | break 13 | case 'file.approved': 14 | await sendWebhook(path, `:ballot_box_with_check: The \`${crowdin.language}\` translation for **${crowdin.file}** is now fully approved. ${getFileUrl(crowdin)}\n---`) 15 | break 16 | case 'project.translated': 17 | await sendWebhook(path, `:confetti_ball: All strings have been translated to \`${crowdin.language}\`! ${getProjectUrl(crowdin)}\n---`) 18 | break 19 | case 'project.approved': 20 | await sendWebhook(path, `:tada: All \`${crowdin.language}\` strings have been approved! ${getProjectUrl(crowdin)}\n---`) 21 | break 22 | case 'translation.updated': 23 | await sendWebhook(path, `:up: The translation for a \`${crowdin.language}\` string in **${crowdin.file}** has been updated by **${crowdin.user}** ${getFileUrl(crowdin)}\n---`) 24 | break 25 | case 'suggestion.added': 26 | await sendWebhook(path, `:pencil: **${crowdin.user}** has added a new \`${crowdin.language}\` suggestion to a string in **${crowdin.file}** ${getFileUrl(crowdin)}\n---`) 27 | break 28 | case 'suggestion.updated': 29 | await sendWebhook(path, `:small_blue_diamond: **${crowdin.user}** has updated a \`${crowdin.language}\` suggestion to a string in **${crowdin.file}** ${getFileUrl(crowdin)}\n---`) 30 | break 31 | case 'suggestion.deleted': 32 | await sendWebhook(path, `:wastebasket: **${crowdin.user}** has deleted a \`${crowdin.language}\` suggestion to a string in **${crowdin.file}** ${getFileUrl(crowdin)}\n---`) 33 | break 34 | case 'suggestion.approved': 35 | await sendWebhook(path, `:thumbsup: **${crowdin.user}** has approved a \`${crowdin.language}\` suggestion to a string in **${crowdin.file}** ${getFileUrl(crowdin)}\n---`) 36 | break 37 | case 'suggestion.disapproved': 38 | await sendWebhook(path, `:thumbsdown: **${crowdin.user}** has unapproved a \`${crowdin.language}\` suggestion to a string in **${crowdin.file}** ${getFileUrl(crowdin)}\n---`) 39 | break 40 | case 'string.added': 41 | await sendWebhook(path, `:new: **${crowdin.user}** has added a new string to the project ${getProjectUrl(crowdin)}\n---`) 42 | break 43 | case 'string.deleted': 44 | await sendWebhook(path, `:wastebasket: **${crowdin.user}** has deleted a string from the project ${getProjectUrl(crowdin)}\n---`) 45 | break 46 | case 'string.updated': 47 | await sendWebhook(path, `:up: **${crowdin.user}** has updated a string in the project ${getProjectUrl(crowdin)}\n---`) 48 | break 49 | } 50 | return new Response('OK', {status: 200}) 51 | } 52 | } 53 | 54 | function getFileUrl (crowdin) { 55 | return `` 56 | } 57 | 58 | function getProjectUrl (crowdin) { 59 | return `` 60 | } 61 | 62 | async function sendWebhook(path, message) { 63 | return fetch(`https://discordapp.com/api/webhooks${path}`, { 64 | method: 'POST', 65 | headers: { 66 | 'Content-Type': 'application/json' 67 | }, 68 | body: JSON.stringify({ 69 | username: 'Crowdin', 70 | avatar_url: 'https://pbs.twimg.com/profile_images/1123967384891613184/Ug8TZcdB.png', 71 | content: message 72 | }) 73 | }) 74 | } -------------------------------------------------------------------------------- /package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "worker", 3 | "version": "1.0.0", 4 | "lockfileVersion": 1, 5 | "requires": true, 6 | "dependencies": { 7 | "prettier": { 8 | "version": "1.19.1", 9 | "resolved": "https://registry.npmjs.org/prettier/-/prettier-1.19.1.tgz", 10 | "integrity": "sha512-s7PoyDv/II1ObgQunCbB9PdLmUcBZcnWOcxDh7O0N/UwDEsHyqkW+Qh28jW+mVuCdx7gLB0BotYI1Y6uI9iyew==", 11 | "dev": true 12 | } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "crowdin-discord-webhooks", 3 | "version": "1.0.0", 4 | "description": "Discord Webhooks for Crowdin Projects", 5 | "main": "index.js", 6 | "author": "Pedro Fracassi ", 7 | "license": "MIT", 8 | "devDependencies": { 9 | "prettier": "^1.18.2" 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /wrangler.toml: -------------------------------------------------------------------------------- 1 | name = "crowdinwebhooks" 2 | type = "webpack" 3 | account_id = "0f5f74345473f28bf90d6fc8288f3d2a" 4 | route = "crowdinwebhooks.switchblade.xyz/*" 5 | zone_id = "30731c944bcd995463c5ecbc39726341" --------------------------------------------------------------------------------