@anthuanvasquez/devlogs 1.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md ADDED
@@ -0,0 +1,15 @@
1
+ # Changelog
2
+
3
+ All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.
4
+
5
+ ### [1.0.1](https://github.com/anthuanvasquez/dev-logs/compare/v1.0.0...v1.0.1) (2026-02-12)
6
+
7
+ ## 1.0.0 (2026-02-12)
8
+
9
+
10
+ ### Features
11
+
12
+ * add script to run commands across all projects from json list ([9961fb3](https://github.com/anthuanvasquez/dev-logs/commit/9961fb351c894ac2faf5b28bdbe231ee695b53fc))
13
+ * add telegram support and interactive destination prompt ([541a893](https://github.com/anthuanvasquez/dev-logs/commit/541a8931fafa84b594d75df1ee76570f19451aca))
14
+ * implement CLI arguments for date range and destination flags ([d9bffd8](https://github.com/anthuanvasquez/dev-logs/commit/d9bffd8f2aeba466c32ed2b5a0152fc983e8f762))
15
+ * initial commit with project structure and dependencies ([ea14907](https://github.com/anthuanvasquez/dev-logs/commit/ea14907ac92c00798d77270b3956914d3d4dc336))
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Anthuan Vásquez
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,123 @@
1
+ # devlogs 📝
2
+
3
+ <p align="center">
4
+ <img src="docs/logo.png" alt="devlogs Logo" width="200" style="image-rendering: pixelated;">
5
+ </p>
6
+
7
+ > Automated daily commit reports powered by Gemini AI, delivered to Discord and Telegram.
8
+
9
+ ## Features
10
+
11
+ - 🔍 **Scans commits** from the current day.
12
+ - 🤖 **Generates a concise summary** using Google Gemini AI.
13
+ - 🚀 **Sends reports** to Discord Webhooks and/or Telegram Bots.
14
+ - interactive **CLI prompt** to choose destination if both are configured.
15
+ - 📦 **Supports multiple projects** via a script.
16
+
17
+ ## Prerequisites
18
+
19
+ - **Node.js** (v18 or higher recommended)
20
+ - **Git** installed and available in PATH.
21
+ - A **Google Gemini API Key** (Get it [here](https://aistudio.google.com/)).
22
+ - A **Discord Webhook URL** (optional).
23
+ - A **Telegram Bot Token** and **Chat ID** (optional).
24
+
25
+ ## Installation
26
+
27
+ ### From NPM (Recommended)
28
+
29
+ ```bash
30
+ npx devlogs
31
+ ```
32
+
33
+ ### From Source
34
+
35
+ 1. Clone the repository:
36
+ ```bash
37
+ git clone https://github.com/anthuanvasquez/devlogs.git
38
+ cd devlogs
39
+ ```
40
+
41
+ 2. Install dependencies:
42
+ ```bash
43
+ npm install
44
+ ```
45
+
46
+ 3. Link the package globally:
47
+ ```bash
48
+ npm link
49
+ ```
50
+
51
+ ## Configuration
52
+
53
+ Create a `.env` file in the root of your project or where you intend to run the script (or set them as system environment variables):
54
+
55
+ ```bash
56
+ # Required
57
+ GEMINI_API_KEY=your_gemini_api_key
58
+
59
+ # Optional (at least one is required)
60
+ DISCORD_WEBHOOK_URL=your_discord_webhook_url
61
+ TELEGRAM_BOT_TOKEN=your_telegram_bot_token
62
+ TELEGRAM_CHAT_ID=your_telegram_chat_id
63
+ ```
64
+
65
+ ## Usage
66
+
67
+ Navigate to any git repository and run:
68
+ `devlogs [today|yesterday] [--discord] [--telegram]`
69
+
70
+ ```bash
71
+ # Default (today, ask if multiple targets)
72
+ devlogs
73
+
74
+ # Report for yesterday
75
+ devlogs yesterday
76
+
77
+ # Force send to Discord (skip prompt)
78
+ devlogs today --discord
79
+
80
+ # Force send to Telegram (skip prompt)
81
+ devlogs yesterday --telegram
82
+
83
+ # Send to both without prompt
84
+ devlogs --discord --telegram
85
+ ```
86
+
87
+ If multiple destinations are configured, you will be prompted to choose:
88
+ `¿Dónde deseas enviar el reporte? (discord/telegram/ambos) [ambos]:`
89
+
90
+ ### Running for Multiple Projects
91
+
92
+ You can create a `projects.json` file with an array of absolute paths to your projects:
93
+
94
+ ```json
95
+ [
96
+ "/path/to/project-a",
97
+ "/path/to/project-b"
98
+ ]
99
+ ```
100
+
101
+ Then run the included script:
102
+
103
+ ```bash
104
+ ./run-all-projects.sh
105
+ ```
106
+
107
+ ## Automating with Cron
108
+
109
+ To run it automatically every day at 6:00 PM:
110
+
111
+ 1. Open your crontab:
112
+ ```bash
113
+ crontab -e
114
+ ```
115
+
116
+ 2. Add the following line (adjust paths accordingly):
117
+ ```bash
118
+ 0 18 * * 1-5 /path/to/dev-logs/run-all-projects.sh >> /tmp/cron_devlogs.txt 2>&1
119
+ ```
120
+
121
+ ## License
122
+
123
+ MIT
package/index.js ADDED
@@ -0,0 +1,165 @@
1
+ import { GoogleGenerativeAI } from "@google/generative-ai";
2
+ import { execSync } from "child_process";
3
+ import fs from "fs";
4
+ import path from "path";
5
+ import readline from "readline";
6
+ import 'dotenv/config';
7
+
8
+ const DISCORD_WEBHOOK_URL = process.env.DISCORD_WEBHOOK_URL;
9
+ const GEMINI_API_KEY = process.env.GEMINI_API_KEY;
10
+ const TELEGRAM_BOT_TOKEN = process.env.TELEGRAM_BOT_TOKEN;
11
+ const TELEGRAM_CHAT_ID = process.env.TELEGRAM_CHAT_ID;
12
+
13
+ const genAI = new GoogleGenerativeAI(GEMINI_API_KEY);
14
+ const model = genAI.getGenerativeModel({ model: "gemini-flash-lite-latest" });
15
+
16
+ async function sendToDiscord(message) {
17
+ if (!DISCORD_WEBHOOK_URL) return;
18
+
19
+ console.log("🚀 Enviando a Discord...");
20
+
21
+ await fetch(DISCORD_WEBHOOK_URL, {
22
+ method: 'POST',
23
+ headers: { 'Content-Type': 'application/json' },
24
+ body: JSON.stringify({ content: message })
25
+ });
26
+
27
+ console.log("✅ Reporte enviado a Discord con éxito.");
28
+ }
29
+
30
+ async function sendToTelegram(message) {
31
+ if (!TELEGRAM_BOT_TOKEN || !TELEGRAM_CHAT_ID) return;
32
+
33
+ console.log("✈️ Enviando a Telegram...");
34
+
35
+ const url = `https://api.telegram.org/bot${TELEGRAM_BOT_TOKEN}/sendMessage`;
36
+
37
+ await fetch(url, {
38
+ method: 'POST',
39
+ headers: { 'Content-Type': 'application/json' },
40
+ body: JSON.stringify({
41
+ chat_id: TELEGRAM_CHAT_ID,
42
+ text: message,
43
+ parse_mode: 'Markdown'
44
+ })
45
+ });
46
+
47
+ console.log("✅ Reporte enviado a Telegram con éxito.");
48
+ }
49
+
50
+ function askQuestion(query) {
51
+ const rl = readline.createInterface({
52
+ input: process.stdin,
53
+ output: process.stdout,
54
+ });
55
+
56
+ return new Promise(resolve => rl.question(query, ans => {
57
+ rl.close();
58
+ resolve(ans);
59
+ }));
60
+ }
61
+
62
+ async function main() {
63
+ try {
64
+ const projectRoot = process.cwd();
65
+ let projectName = "Proyecto Desconocido";
66
+
67
+ try {
68
+ const packageJson = JSON.parse(fs.readFileSync(path.join(projectRoot, 'package.json'), 'utf8'));
69
+ projectName = packageJson.name || path.basename(projectRoot);
70
+ } catch (e) {
71
+ projectName = path.basename(projectRoot);
72
+ }
73
+
74
+ projectName = projectName.charAt(0).toUpperCase() + projectName.slice(1);
75
+
76
+ const args = process.argv.slice(2);
77
+ const when = args.includes('yesterday') ? 'yesterday' : 'today';
78
+ const forceDiscord = args.includes('--discord');
79
+ const forceTelegram = args.includes('--telegram');
80
+
81
+ const dateOptions = { weekday: 'long', day: 'numeric', month: 'long' };
82
+ const dateObj = new Date();
83
+
84
+ if (when === 'yesterday') {
85
+ dateObj.setDate(dateObj.getDate() - 1);
86
+ }
87
+
88
+ const dayName = dateObj.toLocaleDateString('es-ES', { weekday: 'long' });
89
+ const dayNum = dateObj.getDate();
90
+ const formattedDate = `${dayName.charAt(0).toUpperCase() + dayName.slice(1)} ${dayNum}`;
91
+
92
+ console.log(`🔍 Buscando commits de ${when === 'today' ? 'hoy' : 'ayer'} para: ${projectName}...`);
93
+
94
+ let commits = "";
95
+
96
+ try {
97
+ let gitCommand = 'git log --since="00:00" --oneline --no-merges';
98
+ if (when === 'yesterday') {
99
+ gitCommand = 'git log --since="yesterday 00:00" --until="today 00:00" --oneline --no-merges';
100
+ }
101
+ commits = execSync(gitCommand, { encoding: 'utf8' }).trim();
102
+ } catch (error) {
103
+ console.error("⚠️ No es un repositorio git o hubo un error.");
104
+ return;
105
+ }
106
+
107
+ if (!commits) {
108
+ console.log(`✅ No hay commits ${when === 'today' ? 'hoy' : 'ayer'}. ¡A descansar!`);
109
+ return;
110
+ }
111
+
112
+ const hasDiscord = !!DISCORD_WEBHOOK_URL;
113
+ const hasTelegram = !!(TELEGRAM_BOT_TOKEN && TELEGRAM_CHAT_ID);
114
+
115
+ if (!hasDiscord && !hasTelegram) {
116
+ throw new Error("❌ No se encontró configuración para Discord ni Telegram en el archivo .env");
117
+ }
118
+
119
+ let target = "";
120
+
121
+ if (forceDiscord || forceTelegram) {
122
+ if (forceDiscord && forceTelegram) target = "ambos";
123
+ else if (forceDiscord) target = "discord";
124
+ else target = "telegram";
125
+ } else if (hasDiscord && hasTelegram) {
126
+ const answer = await askQuestion("¿Dónde deseas enviar el reporte? (discord/telegram/ambos) [ambos]: ");
127
+ target = answer.toLowerCase().trim() || "ambos";
128
+ } else if (hasDiscord) {
129
+ target = "discord";
130
+ } else {
131
+ target = "telegram";
132
+ }
133
+
134
+ const prompt = `
135
+ Actúa como un Tech Lead conciso.
136
+ Tengo estos commits realizados ${when === 'today' ? 'hoy' : 'ayer'} en el proyecto "${projectName}":
137
+
138
+ ${commits}
139
+
140
+ Genera un resumen muy breve en formato lista (markdown).
141
+ - Agrupa tareas similares.
142
+ - Usa emojis técnicos.
143
+ - Destaca si hubo corrección de bugs o nuevas features.
144
+ - NO pongas título, solo los bullets.
145
+ `;
146
+
147
+ console.log("🤖 Generando reporte con Gemini Flash...");
148
+
149
+ const result = await model.generateContent(prompt);
150
+ const aiSummary = result.response.text();
151
+ const finalMessage = `## 📝 Resumen Diario - ${formattedDate} - ${projectName}\n\n${aiSummary}`;
152
+
153
+ if (target === "discord" || target === "ambos") {
154
+ await sendToDiscord(finalMessage);
155
+ }
156
+
157
+ if (target === "telegram" || target === "ambos") {
158
+ await sendToTelegram(finalMessage);
159
+ }
160
+ } catch (error) {
161
+ console.error("❌ Error:", error.message || error);
162
+ }
163
+ }
164
+
165
+ main();
package/package.json ADDED
@@ -0,0 +1,45 @@
1
+ {
2
+ "name": "@anthuanvasquez/devlogs",
3
+ "description": "Genera reportes diarios de commits y envialos a Discord",
4
+ "version": "1.0.1",
5
+ "main": "index.js",
6
+ "bin": {
7
+ "devlogs": "./index.js"
8
+ },
9
+ "keywords": [
10
+ "git",
11
+ "report",
12
+ "ai",
13
+ "gemini",
14
+ "discord",
15
+ "telegram",
16
+ "developer",
17
+ "tools"
18
+ ],
19
+ "author": "Anthuan Vasquez",
20
+ "license": "MIT",
21
+ "repository": {
22
+ "type": "git",
23
+ "url": "git+https://github.com/anthuanvasquez/dev-logs.git"
24
+ },
25
+ "bugs": {
26
+ "url": "https://github.com/anthuanvasquez/dev-logs/issues"
27
+ },
28
+ "homepage": "https://github.com/anthuanvasquez/dev-logs#readme",
29
+ "type": "module",
30
+ "scripts": {
31
+ "test": "echo \"Error: no test specified\" && exit 1",
32
+ "release": "standard-version",
33
+ "release:minor": "standard-version --release-as minor",
34
+ "release:patch": "standard-version --release-as patch",
35
+ "release:major": "standard-version --release-as major",
36
+ "publish": "npm publish --access public"
37
+ },
38
+ "dependencies": {
39
+ "@google/generative-ai": "^0.24.1",
40
+ "dotenv": "^17.2.4"
41
+ },
42
+ "devDependencies": {
43
+ "standard-version": "^9.5.0"
44
+ }
45
+ }