|
| 1 | +#!/usr/bin/env -S deno run --no-lock --allow-net --allow-env |
| 2 | + |
| 3 | +import { io } from "npm:socket.io-client@4.7.2" |
| 4 | + |
| 5 | +const SESSION_NAME = process.env.CUCKOO_SESSION |
| 6 | +const PARTICIPANT_NAME = process.env.CUCKOO_PARTICIPANT_NAME |
| 7 | +const CUCKOO_URL = `https://cuckoo.team/${SESSION_NAME}` |
| 8 | +const ANSI_RESET = "\x1b[0m" |
| 9 | +const TOMATO_FOREGROUND = "\x1b[38;2;78;80;191m" |
| 10 | +const BREAK_FOREGROUND = "\x1b[38;2;179;212;252m" |
| 11 | +const PAUSE_FOREGROUND = "\x1b[38;2;83;83;98m" |
| 12 | +const CLEAR_LINE = "\r\x1b[K" |
| 13 | +const ICONS = { |
| 14 | + work: " ", |
| 15 | + break: " ", |
| 16 | + running: " ", |
| 17 | + paused: " ", |
| 18 | +} |
| 19 | +const DEFAULTS = { |
| 20 | + timeDisplay: "00:00", |
| 21 | + isRunning: false, |
| 22 | + isBreak: false, |
| 23 | +} |
| 24 | +const STATE = { |
| 25 | + timeDisplay: DEFAULTS.timeDisplay, |
| 26 | + isRunning: DEFAULTS.isRunning, |
| 27 | + isBreak: DEFAULTS.isBreak, |
| 28 | +} |
| 29 | + |
| 30 | +function write(text) { |
| 31 | + Deno.stdout.writeSync(new TextEncoder().encode(text)) |
| 32 | +} |
| 33 | + |
| 34 | +function renderTimer() { |
| 35 | + const icon = STATE.isBreak ? ICONS.break : ICONS.work |
| 36 | + const status = STATE.isRunning ? ICONS.running : ICONS.paused |
| 37 | + const color = STATE.isBreak ? BREAK_FOREGROUND : TOMATO_FOREGROUND |
| 38 | + write(`${CLEAR_LINE}${color}${icon}${ANSI_RESET} ${status} ${STATE.timeDisplay}`) |
| 39 | +} |
| 40 | + |
| 41 | +function start() { |
| 42 | + write("Connecting...") |
| 43 | + const socket = io(CUCKOO_URL, { |
| 44 | + transports: ["websocket"], |
| 45 | + reconnection: true, |
| 46 | + reconnectionDelay: 1000, |
| 47 | + reconnectionDelayMax: 5000, |
| 48 | + reconnectionAttempts: 5, |
| 49 | + }) |
| 50 | + |
| 51 | + socket.on("connect", () => { |
| 52 | + write(`${CLEAR_LINE} Url: ${CUCKOO_URL}`) |
| 53 | + console.log() |
| 54 | + console.log(` User: ${PARTICIPANT_NAME}`) |
| 55 | + socket.emit("update user", PARTICIPANT_NAME) |
| 56 | + }) |
| 57 | + |
| 58 | + socket.on("update timer", (data) => { |
| 59 | + STATE.timeDisplay = data.currentFormatted |
| 60 | + STATE.isRunning = data.current > 0 |
| 61 | + renderTimer() |
| 62 | + }) |
| 63 | + |
| 64 | + socket.on("update settings", (data) => { |
| 65 | + STATE.isBreak = data.sessions?.currentType === "breakTime" |
| 66 | + STATE.isRunning = !data.flags?._isTimerPaused |
| 67 | + renderTimer() |
| 68 | + }) |
| 69 | + |
| 70 | + socket.on("finish timer", () => { |
| 71 | + STATE.isRunning = DEFAULTS.isRunning |
| 72 | + STATE.timeDisplay = DEFAULTS.timeDisplay |
| 73 | + renderTimer() |
| 74 | + }) |
| 75 | + |
| 76 | + socket.on("disconnect", () => console.log("Disconnected from Cuckoo")) |
| 77 | + socket.on("connect_error", (err) => console.error("Connection error:", err.message)) |
| 78 | +} |
| 79 | + |
| 80 | +start() |
| 81 | +await new Promise(() => {}); // Don't exit |
0 commit comments