Last active
March 3, 2026 13:11
-
-
Save chrisdone-artificial/2485c695fa02e0527f13270ea65bb528 to your computer and use it in GitHub Desktop.
Slack->Todoist GreaseMonkey script
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| // ==UserScript== | |
| // @name Slack->Todoist | |
| // @version 1 | |
| // @match https://app.slack.com/* | |
| // ==/UserScript== | |
| const timer = setInterval(() => { | |
| const containers = Array.from(document.querySelectorAll(`div[data-qa="message_container"]:not([${TAG}])`)); | |
| if (containers.length == 0) { | |
| } else { | |
| containers.forEach((container) => { | |
| // Skip messages with a Todoist emoji on it | |
| if (container.querySelectorAll("img[aria-label='todoist emoji']").length != 0) | |
| return; | |
| container.setAttribute(TAG, 'true'); | |
| let div = document.createElement("div"); | |
| div.style = 'position: absolute; top: 5px; left: 5px; cursor: pointer; width: 16px; height: 16px; opacity: 0.5'; | |
| div.innerHTML = ICON; | |
| div.addEventListener('click', async (event) => { | |
| event.stopPropagation(); | |
| event.preventDefault(); | |
| const text = container.querySelector('[data-qa="message-text"]')?.innerText || container.querySelector('[data-qa="message_content"]')?.innerText || ''; | |
| const sender = container.querySelector('[data-qa="message_sender_name"]')?.innerText || 'Slack'; | |
| const ts = container.querySelector('a.c-timestamp[href]'); | |
| const summary = await summarizeAsk(sender, text); | |
| const params = new URLSearchParams(); | |
| params.set('content', '[slack] p2 ' + sender + ': ' + summary + ' today'); | |
| params.set('description', ts?.href + '\n' + text); | |
| const url = "todoist://openquickadd?" + params.toString(); | |
| window.location.href = url; | |
| }); | |
| div.addEventListener('mouseover', function() { | |
| div.style.opacity = '1'; | |
| }); | |
| div.addEventListener('mouseout', function() { | |
| div.style.opacity = '0.5'; | |
| }); | |
| container.append(div); | |
| }); | |
| } | |
| }, 500); | |
| // Summarise an "IRC message". | |
| const summarizeAsk = async (author, text) => { | |
| try { | |
| const response = await fetch("http://localhost:8080/v1/chat/completions", { | |
| method: "POST", | |
| headers: { | |
| "Content-Type": "application/json" | |
| }, | |
| body: JSON.stringify({ | |
| "model": "local-model", | |
| "messages": [ | |
| { | |
| "role": "system", | |
| "content": "You produce punchy titles of IRC messages for the user with no preamble or commentary." | |
| }, | |
| { | |
| "role": "user", "content": "In my next message I will send you an IRC message. Summarise it into a concise title. OK?" | |
| }, | |
| { | |
| "role": "assistant", "content": "OK, I'll wait for the message."}, | |
| { | |
| "role": "user", | |
| "content": '<' + author + '> ' + text | |
| } | |
| ], | |
| "temperature": 0.1 | |
| }) | |
| }); | |
| const data = await response.json(); | |
| return data.choices[0].message.content.trim().split(/\n/g)[0].replace(/"/g,''); | |
| } catch (error) { | |
| alert("Fetch error (check if server is running):", error); | |
| } | |
| }; | |
| const TAG = 'slack-todoist-tagged'; | |
| const ICON = `<svg fill="none" viewBox="0 0 32 32" xmlns="http://www.w3.org/2000/svg"> | |
| <path | |
| fill-rule="evenodd" | |
| clip-rule="evenodd" | |
| d="M4 0h24c2.2 0 4 1.8 4 4v24c0 2.2-1.8 4-4 4H4c-2.2 0-4-1.8-4-4v-5.374l.057.033c1.365.794 4.592 2.674 5.382 3.12.478.27.936.263 1.397-.003l6.328-3.641.012-.007.035-.02 6.575-3.784c.277-.16.291-.652-.02-.829l-.217-.124c-.316-.18-.726-.413-.901-.516a1.02 1.02 0 0 0-.998.012c-.154.09-10.5 6.038-10.847 6.235a1.349 1.349 0 0 1-1.338 0L0 19.927v-2.693l.057.033c1.365.795 4.592 2.674 5.382 3.12.478.27.936.264 1.397-.002.276-.16 3.307-1.903 6.367-3.664l.024-.014 6.559-3.775c.277-.16.291-.651-.02-.828l-.217-.124c-.316-.18-.726-.414-.901-.517a1.02 1.02 0 0 0-.998.012c-.154.09-10.5 6.039-10.847 6.235a1.349 1.349 0 0 1-1.338 0L0 14.535v-2.693l.056.033a943.17 943.17 0 0 0 5.383 3.12c.478.27.936.264 1.397-.002l6.374-3.668.008-.005c3.2-1.84 6.426-3.698 6.568-3.78.277-.16.291-.65-.02-.828l-.217-.124c-.317-.18-.727-.414-.901-.516a1.02 1.02 0 0 0-.998.012c-.154.089-10.5 6.038-10.847 6.235a1.349 1.349 0 0 1-1.338 0L0 9.143V4c0-2.2 1.8-4 4-4Z" | |
| fill="#E44232" | |
| /> | |
| <path | |
| d="M6.836 14.993c.276-.16 3.311-1.906 6.374-3.668l.008-.005c3.2-1.84 6.426-3.698 6.568-3.78.277-.16.29-.65-.02-.828l-.217-.124c-.316-.18-.727-.414-.902-.516a1.02 1.02 0 0 0-.997.012c-.155.089-10.501 6.038-10.847 6.235a1.349 1.349 0 0 1-1.339 0L0 9.143v2.698l.056.033c1.364.795 4.592 2.674 5.383 3.12.478.27.936.264 1.397-.002Z" | |
| fill="#fff" | |
| /> | |
| <path | |
| d="m6.836 20.385 6.366-3.664.024-.014 6.56-3.775c.277-.16.29-.651-.02-.828l-.217-.124c-.316-.18-.727-.414-.902-.517a1.02 1.02 0 0 0-.997.012c-.155.09-10.501 6.039-10.847 6.235a1.349 1.349 0 0 1-1.339 0L0 14.535v2.699l.057.033c1.365.795 4.591 2.674 5.382 3.12.478.27.936.264 1.397-.002Z" | |
| fill="#fff" | |
| /> | |
| <path | |
| d="m13.21 22.108-6.374 3.668c-.461.266-.919.273-1.397.003-.79-.446-4.018-2.326-5.382-3.12L0 22.626v-2.699l5.464 3.175c.413.238.925.235 1.339 0 .346-.197 10.692-6.146 10.847-6.235a1.02 1.02 0 0 1 .997-.012c.175.103.586.336.902.516l.218.124c.31.177.296.669.019.829l-6.575 3.784Z" | |
| fill="#fff" | |
| /> | |
| </svg>`; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment