Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 1 addition & 2 deletions examples/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,5 +8,4 @@ This directory contains example implementations showing how to use the library w

2. Run the examples using:

npm run telegram-example # for telegram bot
npm run twitter-example # for twitter bot
please refer to each example's README.md for more information on how to run the examples.
6 changes: 4 additions & 2 deletions examples/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@
"name": "examples",
"private": true,
"dependencies": {
"@virtuals-protocol/game": "^0.1.9",
"@virtuals-protocol/game": "^0.1.11",
"@virtuals-protocol/game-telegram-plugin": "^0.1.4",
"@virtuals-protocol/game-twitter-plugin": "^0.1.8",
"dotenv": "^16.4.7",
"openai": "^4.81.0",
"twitter-api-v2": "^1.15.0"
Expand All @@ -12,6 +14,6 @@
"build": "tsc -p ./tsconfig.json",
"twitter-example": "ts-node twitter-example/twitter.ts",
"telegram-example": "ts-node telegram-example/tg.ts",
"state-management": "ts-node state-management/index.ts"
"state-management": "ts-node state-management/index.ts"
}
}
105 changes: 105 additions & 0 deletions examples/telegram-example/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
# Telegram Plugin for Virtuals Game

This plugin allows you to integrate Telegram functionalities into your Virtuals Game.

## Installation

To install the plugin, use npm or yarn:

```bash
npm install @virtuals-protocol/game-telegram-plugin
```

or

```bash
yarn add @virtuals-protocol/game-telegram-plugin
```

## Usage

### Importing the Plugin

First, import the `TelegramPlugin` class from the plugin:

```typescript
import TelegramPlugin from "@virtuals-protocol/game-telegram-plugin";
```

### Creating a Worker

Create a worker with the necessary Telegram credentials:

```typescript
const telegramPlugin = new TelegramPlugin({
credentials: {
botToken: "<BOT_TOKEN>",
},
});
```

### Creating an Agent

Create an agent and add the worker to it:

```typescript
import { GameAgent } from "@virtuals-protocol/game";

const agent = new GameAgent("<API_TOKEN>", {
name: "Telegram Bot",
goal: "Auto reply message",
description: "A bot that can post send message and pinned message",
workers: [
telegramPlugin.getWorker(),
],
});
```

### Running the Agent

Initialize and run the agent:

```typescript
(async () => {
await agent.init();

const agentTgWorker = agent.getWorkerById(telegramPlugin.getWorker().id);
const task = "PROMPT";

await agentTgWorker.runTask(task, {
verbose: true, // Optional: Set to true to log each step
});
})();
```

## Available Functions

The `TelegramPlugin` provides several functions that can be used by the agent:

- `sendMessageFunction`: Send message.
- `sendMediaFunction`: Send media.
- `createPollFunction`: Create poll.
- `pinnedMessageFunction`: Pinned message.
- `unPinnedMessageFunction`: Unpinned message.
- `deleteMessageFunction`: Delete message.

## Event Handlers
The plugin also supports custom handlers for the following Telegram events:
### Handling Incoming Messages
To handle incoming messages, use the `onMessage` method to listen on:
```typescript
telegramPlugin.onMessage((msg) => {
console.log("Received message:", msg);
});
```
### Handling Poll Answers
To handle poll answers, use the `onPollAnswer` method:
```typescript
telegramPlugin.onPollAnswer((pollAnswer) => {
console.log("Received poll answer:", pollAnswer);
});
```

## License

This project is licensed under the MIT License.
212 changes: 124 additions & 88 deletions examples/telegram-example/tg.ts
Original file line number Diff line number Diff line change
@@ -1,108 +1,144 @@
import {
ExecutableGameFunctionResponse,
ExecutableGameFunctionStatus,
GameAgent,
GameFunction,
GameWorker,
} from "@virtuals-protocol/game";
import dotenv from 'dotenv';
import path from 'path';
import { GameAgent } from "@virtuals-protocol/game";
import TelegramPlugin from "@virtuals-protocol/game-telegram-plugin";

// Load environment variables from the correct location
dotenv.config({ path: path.join(__dirname, '.env') });

const generateImageFunction = new GameFunction({
name: "generate_image",
description: "Generate an image",
args: [
{
name: "image_description",
description: "The description of the image to generate",
},
] as const,
executable: async (args, logger) => {
try {
// TODO: Implement generate image with url
logger(`Generating image with description: ${args.image_description}`);

return new ExecutableGameFunctionResponse(
ExecutableGameFunctionStatus.Done,
"Image generated with URL: https://example.com/image.png"
);
} catch (e) {
return new ExecutableGameFunctionResponse(
ExecutableGameFunctionStatus.Failed,
"Failed to generate image"
);
}
// Create a worker with the functions
// Replace <BOT_TOKEN> with your Telegram bot token
const telegramPlugin = new TelegramPlugin({
credentials: {
botToken: "<BOT_TOKEN>",
},
});

const replyMessageFunction = new GameFunction({
name: "reply_message",
description: "Reply to a message",
args: [
{ name: "message", description: "The message to reply" },
{
name: "media_url",
description: "The media url to attach to the message",
optional: true,
},
] as const,

executable: async (args, logger) => {
try {
// TODO: Implement replying to message with image
if (args.media_url) {
logger(`Reply with media: ${args.media_url}`);
}

// TODO: Implement replying to message
logger(`Replying to message: ${args.message}`);

return new ExecutableGameFunctionResponse(
ExecutableGameFunctionStatus.Done,
`Replied with message: ${args.message}`
);
} catch (e) {
return new ExecutableGameFunctionResponse(
ExecutableGameFunctionStatus.Failed,
"Failed to reply to message"
);
}
},
telegramPlugin.onMessage(async (msg) => {
console.log('Custom message handler:', msg);
});

const telegramWorker = new GameWorker({
id: "telegram",
name: "telegram",
description: "Telegram worker",
functions: [generateImageFunction, replyMessageFunction],
telegramPlugin.onPollAnswer((pollAnswer) => {
console.log('Custom poll answer handler:', pollAnswer);
// You can process the poll answer as needed
});

const agent = new GameAgent(process.env.API_KEY!, {
/**
* The agent will be able to send messages and pin messages automatically
* Replace <API_TOKEN> with your API token
*/
const autoReplyAgent = new GameAgent("<API_TOKEN>", {
name: "Telegram Bot",
goal: "Interact with Telegram",
description: "Telegram agent",
workers: [telegramWorker],
goal: "Auto reply message",
description: "This agent will auto reply to messages",
workers: [
telegramPlugin.getWorker({
// Define the functions that the worker can perform, by default it will use the all functions defined in the plugin
functions: [
telegramPlugin.sendMessageFunction,
telegramPlugin.pinnedMessageFunction,
telegramPlugin.unPinnedMessageFunction,
telegramPlugin.createPollFunction,
telegramPlugin.sendMediaFunction,
telegramPlugin.deleteMessageFunction,
],
}),
],
});

/**
* Initialize the agent and start listening for messages
* The agent will automatically reply to messages
*/
(async () => {
autoReplyAgent.setLogger((autoReplyAgent, message) => {
console.log(`-----[${autoReplyAgent.name}]-----`);
console.log(message);
console.log("\n");
});

await autoReplyAgent.init();
telegramPlugin.onMessage(async (msg) => {
const agentTgWorker = autoReplyAgent.getWorkerById(telegramPlugin.getWorker().id);
const task = "Reply to chat id: " + msg.chat.id + " and the incoming is message: " + msg.text + " and the message id is: " + msg.message_id;

await agentTgWorker.runTask(task, {
verbose: true, // Optional: Set to true to log each step
});
});
})();

/**
* The agent is a Financial Advisor designed to provide financial advice and assistance
*/
const financialAdvisorAgent = new GameAgent("<API_TOKEN>", {
name: "Financial Advisor Bot",
goal: "Provide financial advice and assistance",
description: "A smart bot designed to answer financial questions, provide investment tips, assist with budgeting, and manage financial tasks like pinning important messages or deleting outdated ones for better organization.",
workers: [
telegramPlugin.getWorker({
// Define the functions that the worker can perform, by default it will use the all functions defined in the plugin
functions: [
telegramPlugin.sendMessageFunction,
telegramPlugin.pinnedMessageFunction,
telegramPlugin.unPinnedMessageFunction,
telegramPlugin.createPollFunction,
telegramPlugin.sendMediaFunction,
telegramPlugin.deleteMessageFunction,
],
}),
],
});

(async () => {
// define custom logger
agent.setLogger((agent, msg) => {
console.log(`-----[${agent.name}]-----`);
console.log(msg);
financialAdvisorAgent.setLogger((financialAdvisorAgent, message) => {
console.log(`-----[${financialAdvisorAgent.name}]-----`);
console.log(message);
console.log("\n");
});

await agent.init();
await financialAdvisorAgent.init();
telegramPlugin.onMessage(async (msg) => {
const agentTgWorker = financialAdvisorAgent.getWorkerById(telegramPlugin.getWorker().id);
const task = "Reply to chat id: " + msg.chat.id + " and the incoming is message: " + msg.text + " and the message id is: " + msg.message_id;

await agentTgWorker.runTask(task, {
verbose: true, // Optional: Set to true to log each step
});
});
})();

/**
* The agent is a Nutritionist Bot designed for nutritional counseling and support
*/
const nutritionistAgent = new GameAgent("<API_TOKEN>", {
name: "Nutritionist Bot",
goal: "Provide evidence-based information and guidance about the impacts of food and nutrition on the health and wellbeing of humans.",
description: "A smart bot designed to answer food and nutrition questions, provide personalized nutrition plans, nutritional counseling, motivate and support users in achieving their health goals.",
workers: [
telegramPlugin.getWorker({
// Define the functions that the worker can perform, by default it will use the all functions defined in the plugin
functions: [
telegramPlugin.sendMessageFunction,
telegramPlugin.pinnedMessageFunction,
telegramPlugin.unPinnedMessageFunction,
telegramPlugin.createPollFunction,
telegramPlugin.sendMediaFunction,
telegramPlugin.deleteMessageFunction,
],
}),
],
});

const agentTgWorker = agent.getWorkerById(telegramWorker.id);
(async () => {
nutritionistAgent.setLogger((nutritionistAgent, message) => {
console.log(`-----[${nutritionistAgent.name}]-----`);
console.log(message);
console.log("\n");
});

const task =
"Gotten a message from user. Message content: hey! i will need help with my project, i need an image of a cat hugging AI. Can you help me with that? Give me something that cool and cute!";
await nutritionistAgent.init();
telegramPlugin.onMessage(async (msg) => {
const agentTgWorker = nutritionistAgent.getWorkerById(telegramPlugin.getWorker().id);
const task = "Reply professionally to chat id: " + msg.chat.id + " and the incoming is message: " + msg.text + " and the message id is: " + msg.message_id;

await agentTgWorker.runTask(task, {
verbose: true, // Optional: Set to true to log each step
await agentTgWorker.runTask(task, {
verbose: true, // Optional: Set to true to log each step
});
});
})();
Loading