Skip to content

Commit

Permalink
Merge pull request #63 from FemiOje/make-telegram-client
Browse files Browse the repository at this point in the history
feat: Make telegram client
  • Loading branch information
ponderingdemocritus authored Jan 31, 2025
2 parents 8452385 + 968d9ef commit 32f5b6a
Show file tree
Hide file tree
Showing 7 changed files with 949 additions and 5 deletions.
17 changes: 17 additions & 0 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,23 @@ DRY_RUN=1
# Required Gateway Intents: Server Members, Message Content, Presence
DISCORD_TOKEN=

# Telegram Configuration
# TELEGRAM_STARTUP_CHAT_ID: Chat ID where startup notifications will be sent
TELEGRAM_STARTUP_CHAT_ID=

# GramJS Configuration (required for both bot and user clients)
# TELEGRAM_TOKEN: Bot token from @BotFather (required for bot mode)
TELEGRAM_TOKEN=

# Get these from https://my.telegram.org/apps
TELEGRAM_API_ID=
TELEGRAM_API_HASH=

# Optional: Session string for user authentication
# After first successful interactive login, the app will provide a session string
# Save it here to avoid interactive login in subsequent runs
TELEGRAM_USER_SESSION=

# Hyperliquid Trading Configuration
# HYPERLIQUID_MAIN_ADDRESS: Your main Hyperliquid address (format: 0x...)
# HYPERLIQUID_WALLET_ADDRESS: Your wallet address for trading (format: 0x...)
Expand Down
5 changes: 4 additions & 1 deletion .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,5 +9,8 @@
"search.exclude": {
"**/node_modules": true
},
"typescript.tsdk": "node_modules/typescript/lib"
"typescript.tsdk": "node_modules/typescript/lib",
"[typescript]": {
"editor.defaultFormatter": "vscode.typescript-language-features"
}
}
189 changes: 189 additions & 0 deletions examples/example-telegram.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,189 @@
import { Orchestrator } from "../packages/core/src/core/orchestrator";
import { HandlerRole } from "../packages/core/src/core/types";
import { TelegramClient } from "../packages/core/src/core/io/telegram";
import { RoomManager } from "../packages/core/src/core/room-manager";
import { ChromaVectorDB } from "../packages/core/src/core/vector-db";
import { MessageProcessor } from "../packages/core/src/core/processors/message-processor";
import { LLMClient } from "../packages/core/src/core/llm-client";
import { env } from "../packages/core/src/core/env";
import { LogLevel } from "../packages/core/src/core/types";
import chalk from "chalk";
import { defaultCharacter } from "../packages/core/src/core/character";
import { z } from "zod";
import readline from "readline";
import { MongoDb } from "../packages/core/src/core/db/mongo-db";
import { Consciousness } from "../packages/core/src/core/consciousness";
import { SchedulerService } from "../packages/core/src/core/schedule-service";
import { Logger } from "../packages/core/src/core/logger";


async function main() {
const loglevel = LogLevel.DEBUG;

// Ensure startup chat ID is set
if (!env.TELEGRAM_STARTUP_CHAT_ID) {
console.warn(chalk.yellow("⚠️ No TELEGRAM_STARTUP_CHAT_ID set - startup message will be skipped"));
}

// Initialize core dependencies
const vectorDb = new ChromaVectorDB("telegram_agent", {
chromaUrl: "http://localhost:8000",
logLevel: loglevel,
});

await vectorDb.purge(); // Clear previous session data

const roomManager = new RoomManager(vectorDb);

const llmClient = new LLMClient({
// model: "openrouter:deepseek/deepseek-r1", // Using a supported model
model: "openrouter:deepseek/deepseek-r1-distill-llama-70b",
temperature: 0.3,
});

// Initialize processor with default character personality
const processor = new MessageProcessor(
llmClient,
defaultCharacter,
loglevel
);
const scheduledTaskDb = new MongoDb(
"mongodb://localhost:27017",
"myApp",
"scheduled_tasks"
);

await scheduledTaskDb.connect();
console.log(chalk.green("✅ Scheduled task database connected"));

await scheduledTaskDb.deleteAll();

// Initialize core system
const orchestrator = new Orchestrator(
roomManager,
vectorDb,
processor,
scheduledTaskDb,
{
level: loglevel,
enableColors: true,
enableTimestamp: true,
}
);

const scheduler = new SchedulerService(
{
logger: new Logger({
level: loglevel,
enableColors: true,
enableTimestamp: true,
}),
orchestratorDb: scheduledTaskDb,
roomManager: roomManager,
vectorDb: vectorDb,
},
orchestrator,
10000
);

// Set up Telegram user client with credentials
const telegram = new TelegramClient(
{
session: env.TELEGRAM_USER_SESSION,
bot_token: env.TELEGRAM_TOKEN,
api_id: parseInt(env.TELEGRAM_API_ID as string),
api_hash: env.TELEGRAM_API_HASH,
is_bot: false,
},
loglevel,
);

// Set up Telegram bot client with credentials
// const telegram = new TelegramClient(
// {
// bot_token: env.TELEGRAM_TOKEN,
// api_id: parseInt(env.TELEGRAM_API_ID as string),
// api_hash: env.TELEGRAM_API_HASH,
// is_bot: true,
// session: undefined,
// },
// loglevel,
// );

// Wait for login to complete before setting up handlers
await telegram.initialize();

orchestrator.registerIOHandler({
name: "telegram_send_message",
role: HandlerRole.OUTPUT,
execute: async (data: unknown) => {
const messageData = data as {
content: string;
chatId: number;
};
return telegram.createSendMessageOutput().handler(messageData);
},
outputSchema: z
.object({
content: z.string(),
chatId: z.number().optional().describe("The chat ID for the message"),
})
.describe("This is for sending a message."),
});

// Register chat list scraper handler
orchestrator.registerIOHandler({
name: "telegram_chat_list_scraper",
role: HandlerRole.INPUT,
execute: async () => {
try {
console.log(chalk.blue("📊 Fetching chat list..."));
const result = await telegram.createChatListScraper().handler();
return result;
} catch (error) {
console.error(chalk.red("Error in chat list scraper:"), error);
return null;
}
}
});

scheduler.start();

await scheduler.scheduleTaskInDb(
"sleever",
"telegram_chat_list_scraper",
{},
60000 // 1 minute
);

// Set up readline interface
const rl = readline.createInterface({
input: process.stdin,
output: process.stdout,
});

// Start the prompt loop
console.log(chalk.cyan("🤖 Bot is now running and monitoring Telegram..."));
console.log(chalk.cyan("You can type messages in the console."));
console.log(chalk.cyan('Type "exit" to quit'));

// Handle graceful shutdown
process.on("SIGINT", async () => {
console.log(chalk.yellow("\n\nShutting down..."));

// Clean up resources
telegram.logout();
orchestrator.removeIOHandler("telegram_send_message");
orchestrator.removeIOHandler("telegram_chat_list_scraper");
rl.close();

console.log(chalk.green("✅ Shutdown complete"));
process.exit(0);
});
}

// Run the example
main().catch((error) => {
console.error(chalk.red("Fatal error:"), error);
process.exit(1);
});
2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
"twitter": "bun run examples/example-twitter.ts",
"server": "bun run examples/example-server.ts",
"discord": "bun run examples/example-discord.ts",
"telegram": "bun run examples/example-telegram.ts",
"hyperliquid": "bun run examples/example-hyperliquid.ts",
"api": "bun run examples/example-api.ts",
"ui": "pnpm --dir clients/example-ui run dev",
Expand All @@ -29,6 +30,7 @@
"mongodb": "^6.12.0",
"prettier": "^3.4.2",
"readline": "^1.3.0",
"telegram": "^2.26.16",
"ws": "^8.18.0",
"zod": "^3.24.1"
},
Expand Down
5 changes: 5 additions & 0 deletions packages/core/src/core/env.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,17 @@ const envSchema = z.object({
OPENROUTER_API_KEY: z.string(),
GRAPHQL_URL: z.string(),
DISCORD_TOKEN: z.string(),
TELEGRAM_TOKEN: z.string(),
TELEGRAM_API_ID: z.string(),
TELEGRAM_API_HASH: z.string(),
HYPERLIQUID_MAIN_ADDRESS: z.string(),
HYPERLIQUID_WALLET_ADDRESS: z.string(),
HYPERLIQUID_PRIVATE_KEY: z.string(),
WEBSOCKET_URL: z.string().default("ws://localhost:8080"),
DRY_RUN: z
.preprocess((val) => val === "1" || val === "true", z.boolean())
.default(true),
TELEGRAM_STARTUP_CHAT_ID: z.string().optional(),
TELEGRAM_USER_SESSION: z.string().optional(),
});
export const env = envSchema.parse(process.env);
Loading

0 comments on commit 32f5b6a

Please sign in to comment.