mirror of
https://github.com/anthropics/claude-plugins-official.git
synced 2026-03-21 11:53:08 +00:00
Compare commits
4 Commits
add-plugin
...
kenneth/di
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5c58308be4 | ||
|
|
90accf6fd2 | ||
|
|
562a27feec | ||
|
|
8140fbad22 |
@@ -25,7 +25,7 @@ import {
|
|||||||
type Attachment,
|
type Attachment,
|
||||||
} from 'discord.js'
|
} from 'discord.js'
|
||||||
import { randomBytes } from 'crypto'
|
import { randomBytes } from 'crypto'
|
||||||
import { readFileSync, writeFileSync, mkdirSync, readdirSync, rmSync, statSync, renameSync, realpathSync } from 'fs'
|
import { readFileSync, writeFileSync, mkdirSync, readdirSync, rmSync, statSync, renameSync, realpathSync, chmodSync } from 'fs'
|
||||||
import { homedir } from 'os'
|
import { homedir } from 'os'
|
||||||
import { join, sep } from 'path'
|
import { join, sep } from 'path'
|
||||||
|
|
||||||
@@ -37,6 +37,8 @@ const ENV_FILE = join(STATE_DIR, '.env')
|
|||||||
// Load ~/.claude/channels/discord/.env into process.env. Real env wins.
|
// Load ~/.claude/channels/discord/.env into process.env. Real env wins.
|
||||||
// Plugin-spawned servers don't get an env block — this is where the token lives.
|
// Plugin-spawned servers don't get an env block — this is where the token lives.
|
||||||
try {
|
try {
|
||||||
|
// Token is a credential — lock to owner. No-op on Windows (would need ACLs).
|
||||||
|
chmodSync(ENV_FILE, 0o600)
|
||||||
for (const line of readFileSync(ENV_FILE, 'utf8').split('\n')) {
|
for (const line of readFileSync(ENV_FILE, 'utf8').split('\n')) {
|
||||||
const m = line.match(/^(\w+)=(.*)$/)
|
const m = line.match(/^(\w+)=(.*)$/)
|
||||||
if (m && process.env[m[1]] === undefined) process.env[m[1]] = m[2]
|
if (m && process.env[m[1]] === undefined) process.env[m[1]] = m[2]
|
||||||
@@ -421,7 +423,7 @@ const mcp = new Server(
|
|||||||
'',
|
'',
|
||||||
'Messages from Discord arrive as <channel source="discord" chat_id="..." message_id="..." user="..." ts="...">. If the tag has attachment_count, the attachments attribute lists name/type/size — call download_attachment(chat_id, message_id) to fetch them. Reply with the reply tool — pass chat_id back. Use reply_to (set to a message_id) only when replying to an earlier message; the latest message doesn\'t need a quote-reply, omit reply_to for normal responses.',
|
'Messages from Discord arrive as <channel source="discord" chat_id="..." message_id="..." user="..." ts="...">. If the tag has attachment_count, the attachments attribute lists name/type/size — call download_attachment(chat_id, message_id) to fetch them. Reply with the reply tool — pass chat_id back. Use reply_to (set to a message_id) only when replying to an earlier message; the latest message doesn\'t need a quote-reply, omit reply_to for normal responses.',
|
||||||
'',
|
'',
|
||||||
'reply accepts file paths (files: ["/abs/path.png"]) for attachments. Use react to add emoji reactions, and edit_message to update a message you previously sent (e.g. progress → result).',
|
'reply accepts file paths (files: ["/abs/path.png"]) for attachments. Use react to add emoji reactions, and edit_message for interim progress updates. Edits don\'t trigger push notifications — when a long task completes, send a new reply so the user\'s device pings.',
|
||||||
'',
|
'',
|
||||||
"fetch_messages pulls real Discord history. Discord's search API isn't available to bots — if the user asks you to find an old message, fetch more history or ask them roughly when it was.",
|
"fetch_messages pulls real Discord history. Discord's search API isn't available to bots — if the user asks you to find an old message, fetch more history or ask them roughly when it was.",
|
||||||
'',
|
'',
|
||||||
@@ -469,7 +471,7 @@ mcp.setRequestHandler(ListToolsRequestSchema, async () => ({
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'edit_message',
|
name: 'edit_message',
|
||||||
description: 'Edit a message the bot previously sent. Useful for progress updates (send "working…" then edit to the result).',
|
description: 'Edit a message the bot previously sent. Useful for interim progress updates. Edits don\'t trigger push notifications — send a new reply when a long task completes so the user\'s device pings.',
|
||||||
inputSchema: {
|
inputSchema: {
|
||||||
type: 'object',
|
type: 'object',
|
||||||
properties: {
|
properties: {
|
||||||
|
|||||||
@@ -80,7 +80,8 @@ as the correct long-term choice. Don't skip the lockdown offer.
|
|||||||
2. `mkdir -p ~/.claude/channels/discord`
|
2. `mkdir -p ~/.claude/channels/discord`
|
||||||
3. Read existing `.env` if present; update/add the `DISCORD_BOT_TOKEN=` line,
|
3. Read existing `.env` if present; update/add the `DISCORD_BOT_TOKEN=` line,
|
||||||
preserve other keys. Write back, no quotes around the value.
|
preserve other keys. Write back, no quotes around the value.
|
||||||
4. Confirm, then show the no-args status so the user sees where they stand.
|
4. `chmod 600 ~/.claude/channels/discord/.env` — the token is a credential.
|
||||||
|
5. Confirm, then show the no-args status so the user sees where they stand.
|
||||||
|
|
||||||
### `clear` — remove the token
|
### `clear` — remove the token
|
||||||
|
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ import {
|
|||||||
import { Bot, InputFile, type Context } from 'grammy'
|
import { Bot, InputFile, type Context } from 'grammy'
|
||||||
import type { ReactionTypeEmoji } from 'grammy/types'
|
import type { ReactionTypeEmoji } from 'grammy/types'
|
||||||
import { randomBytes } from 'crypto'
|
import { randomBytes } from 'crypto'
|
||||||
import { readFileSync, writeFileSync, mkdirSync, readdirSync, rmSync, statSync, renameSync, realpathSync } from 'fs'
|
import { readFileSync, writeFileSync, mkdirSync, readdirSync, rmSync, statSync, renameSync, realpathSync, chmodSync } from 'fs'
|
||||||
import { homedir } from 'os'
|
import { homedir } from 'os'
|
||||||
import { join, extname, sep } from 'path'
|
import { join, extname, sep } from 'path'
|
||||||
|
|
||||||
@@ -30,6 +30,8 @@ const ENV_FILE = join(STATE_DIR, '.env')
|
|||||||
// Load ~/.claude/channels/telegram/.env into process.env. Real env wins.
|
// Load ~/.claude/channels/telegram/.env into process.env. Real env wins.
|
||||||
// Plugin-spawned servers don't get an env block — this is where the token lives.
|
// Plugin-spawned servers don't get an env block — this is where the token lives.
|
||||||
try {
|
try {
|
||||||
|
// Token is a credential — lock to owner. No-op on Windows (would need ACLs).
|
||||||
|
chmodSync(ENV_FILE, 0o600)
|
||||||
for (const line of readFileSync(ENV_FILE, 'utf8').split('\n')) {
|
for (const line of readFileSync(ENV_FILE, 'utf8').split('\n')) {
|
||||||
const m = line.match(/^(\w+)=(.*)$/)
|
const m = line.match(/^(\w+)=(.*)$/)
|
||||||
if (m && process.env[m[1]] === undefined) process.env[m[1]] = m[2]
|
if (m && process.env[m[1]] === undefined) process.env[m[1]] = m[2]
|
||||||
@@ -341,7 +343,7 @@ const mcp = new Server(
|
|||||||
'',
|
'',
|
||||||
'Messages from Telegram arrive as <channel source="telegram" chat_id="..." message_id="..." user="..." ts="...">. If the tag has an image_path attribute, Read that file — it is a photo the sender attached. Reply with the reply tool — pass chat_id back. Use reply_to (set to a message_id) only when replying to an earlier message; the latest message doesn\'t need a quote-reply, omit reply_to for normal responses.',
|
'Messages from Telegram arrive as <channel source="telegram" chat_id="..." message_id="..." user="..." ts="...">. If the tag has an image_path attribute, Read that file — it is a photo the sender attached. Reply with the reply tool — pass chat_id back. Use reply_to (set to a message_id) only when replying to an earlier message; the latest message doesn\'t need a quote-reply, omit reply_to for normal responses.',
|
||||||
'',
|
'',
|
||||||
'reply accepts file paths (files: ["/abs/path.png"]) for attachments. Use react to add emoji reactions, and edit_message to update a message you previously sent (e.g. progress → result).',
|
'reply accepts file paths (files: ["/abs/path.png"]) for attachments. Use react to add emoji reactions, and edit_message for interim progress updates. Edits don\'t trigger push notifications — when a long task completes, send a new reply so the user\'s device pings.',
|
||||||
'',
|
'',
|
||||||
"Telegram's Bot API exposes no history or search — you only see messages as they arrive. If you need earlier context, ask the user to paste it or summarize.",
|
"Telegram's Bot API exposes no history or search — you only see messages as they arrive. If you need earlier context, ask the user to paste it or summarize.",
|
||||||
'',
|
'',
|
||||||
@@ -389,7 +391,7 @@ mcp.setRequestHandler(ListToolsRequestSchema, async () => ({
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'edit_message',
|
name: 'edit_message',
|
||||||
description: 'Edit a message the bot previously sent. Useful for progress updates (send "working…" then edit to the result).',
|
description: 'Edit a message the bot previously sent. Useful for interim progress updates. Edits don\'t trigger push notifications — send a new reply when a long task completes so the user\'s device pings.',
|
||||||
inputSchema: {
|
inputSchema: {
|
||||||
type: 'object',
|
type: 'object',
|
||||||
properties: {
|
properties: {
|
||||||
|
|||||||
@@ -77,7 +77,8 @@ offer.
|
|||||||
2. `mkdir -p ~/.claude/channels/telegram`
|
2. `mkdir -p ~/.claude/channels/telegram`
|
||||||
3. Read existing `.env` if present; update/add the `TELEGRAM_BOT_TOKEN=` line,
|
3. Read existing `.env` if present; update/add the `TELEGRAM_BOT_TOKEN=` line,
|
||||||
preserve other keys. Write back, no quotes around the value.
|
preserve other keys. Write back, no quotes around the value.
|
||||||
4. Confirm, then show the no-args status so the user sees where they stand.
|
4. `chmod 600 ~/.claude/channels/telegram/.env` — the token is a credential.
|
||||||
|
5. Confirm, then show the no-args status so the user sees where they stand.
|
||||||
|
|
||||||
### `clear` — remove the token
|
### `clear` — remove the token
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user