Skip to content

Commit 5479adc

Browse files
Complete working setup
1 parent 778ac50 commit 5479adc

File tree

3 files changed

+177
-9
lines changed

3 files changed

+177
-9
lines changed

QUICKSTART.md

+122
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,122 @@
1+
# Quickstart Guide for Discord and Telegram Integration
2+
3+
This guide provides quick setup instructions for integrating Discord and Telegram with Eliza.
4+
5+
## ⚠️ Discord Setup
6+
7+
### Important Warning
8+
```diff
9+
- CAUTION: Using this on a user account is prohibited by the Discord TOS and can lead to the account block.
10+
- Use at your own risk. We recommend using official bot accounts instead.
11+
```
12+
13+
### Getting Discord User Token
14+
1. Log into Discord in your web browser
15+
2. Open Developer Console (F12 or Ctrl+Shift+I)
16+
3. Paste and run the following code in the console:
17+
18+
```javascript
19+
window.webpackChunkdiscord_app.push([
20+
[Math.random()],
21+
{},
22+
req => {
23+
if (!req.c) return;
24+
for (const m of Object.keys(req.c)
25+
.map(x => req.c[x].exports)
26+
.filter(x => x)) {
27+
if (m.default && m.default.getToken !== undefined) {
28+
return copy(m.default.getToken());
29+
}
30+
if (m.getToken !== undefined) {
31+
return copy(m.getToken());
32+
}
33+
}
34+
},
35+
]);
36+
window.webpackChunkdiscord_app.pop();
37+
console.log('%cWorked!', 'font-size: 50px');
38+
console.log(`%cYou now have your token in the clipboard!`, 'font-size: 16px');
39+
```
40+
41+
4. The token will be copied to your clipboard
42+
5. Add the token to your `.env` file:
43+
```env
44+
DISCORD_USER_TOKEN=your_token_here
45+
DISCORD_ALLOWED_CHANNELS=channel1,channel2
46+
```
47+
48+
## 🤖 Telegram Setup
49+
50+
### Creating Telegram Application
51+
1. Visit [Telegram API Development Tools](https://my.telegram.org/apps)
52+
2. Log in with your phone number
53+
3. Create a new application
54+
4. You will receive:
55+
- API ID (number)
56+
- API Hash (string)
57+
58+
### Environment Setup
59+
Add the following to your `.env` file:
60+
```env
61+
TELEGRAM_API_ID=your_api_id
62+
TELEGRAM_API_HASH=your_api_hash
63+
TELEGRAM_ALLOWED_GROUPS=group1,group2
64+
```
65+
66+
## Quick Implementation
67+
68+
### Discord Client
69+
```typescript
70+
import { DiscordUserClient } from '@eliza/client-discord';
71+
72+
const client = new DiscordUserClient(runtime);
73+
await client.start();
74+
```
75+
76+
### Telegram Client
77+
```typescript
78+
import { TelegramUserClient } from '@eliza/client-telegram';
79+
80+
const client = new TelegramUserClient(runtime);
81+
await client.start();
82+
```
83+
84+
## Character Configuration
85+
Update your character configuration to specify which clients to use:
86+
87+
```json
88+
{
89+
"name": "YourBot",
90+
"clients": ["discord", "telegram"],
91+
"modelProvider": "your_provider",
92+
"settings": {
93+
"secrets": {}
94+
}
95+
}
96+
```
97+
98+
## Marketing Features
99+
Both clients support automated marketing with these defaults:
100+
- Message Interval: 15-45 minutes
101+
- Daily Limit: 96 messages per channel/group
102+
103+
Enable marketing:
104+
```typescript
105+
// Discord
106+
await discordClient.messageManager.startMarketing();
107+
108+
// Telegram
109+
await telegramClient.messageManager.startMarketing();
110+
```
111+
112+
## Common Issues
113+
114+
### Discord
115+
- Token Invalid: Regenerate token using the console script
116+
- Rate Limits: Ensure you're not sending too many messages too quickly
117+
- Channel Access: Verify the channels in DISCORD_ALLOWED_CHANNELS exist
118+
119+
### Telegram
120+
- API ID/Hash Invalid: Double-check values on my.telegram.org
121+
- Session Errors: Clear session data and restart
122+
- Group Access: Ensure bot is member of groups in TELEGRAM_ALLOWED_GROUPS

characters/neuronlink.character.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"name": "NeuronLink",
33
"plugins": [],
4-
"clients": ["telegram"],
4+
"clients": ["discord"],
55
"modelProvider": "ollama",
66
"settings": {
77
"secrets": {},

packages/client-discord/src/messageManager.ts

+54-8
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,9 @@ export class MessageManager {
6969
private lastMarketingTimes: Map<string, number> = new Map();
7070
private channelMessageCounts: Map<string, number> = new Map();
7171
private channelTimeReductions: Map<string, number> = new Map();
72+
private readonly MIN_MARKETING_INTERVAL = 15 * 60 * 1000; // 15 minutes
73+
private readonly MAX_MARKETING_INTERVAL = 45 * 60 * 1000; // 45 minutes
74+
private readonly MAX_MARKETING_MESSAGES_PER_CHANNEL = 96; // Max messages per channel per day
7275
private marketingEnabled: boolean = false;
7376

7477
constructor(runtime: IAgentRuntime, client: DiscordUserClient) {
@@ -78,9 +81,52 @@ export class MessageManager {
7881
}
7982

8083
async startMarketing(): Promise<void> {
81-
elizaLogger.log('Starting Discord marketing...');
82-
this.marketingEnabled = true;
83-
await this.initializeChannelMarketing();
84+
try {
85+
elizaLogger.log('Starting Discord marketing...');
86+
87+
// Get allowed channels from settings
88+
const allowedChannelsStr = this.runtime.getSetting('DISCORD_ALLOWED_CHANNELS');
89+
if (allowedChannelsStr?.trim()) {
90+
const channels = allowedChannelsStr.split(',').map(name => name.trim());
91+
this.targetChannels = new Set(channels);
92+
elizaLogger.log('📢 Marketing initialized for channels:', Array.from(this.targetChannels));
93+
}
94+
95+
this.marketingEnabled = true;
96+
elizaLogger.log('✅ Marketing started successfully');
97+
98+
// Start marketing for each target channel
99+
for (const channelName of this.targetChannels) {
100+
this.scheduleNextMarketingMessage(channelName);
101+
}
102+
} catch (error) {
103+
elizaLogger.error('❌ Failed to start marketing:', error);
104+
throw error;
105+
}
106+
}
107+
108+
private scheduleNextMarketingMessage(channelName: string): void {
109+
if (!this.marketingEnabled) return;
110+
111+
const interval = Math.floor(
112+
Math.random() * (this.MAX_MARKETING_INTERVAL - this.MIN_MARKETING_INTERVAL) + this.MIN_MARKETING_INTERVAL
113+
);
114+
115+
setTimeout(async () => {
116+
try {
117+
if (!this.marketingEnabled) return;
118+
119+
const channel = await this.client.getChannelByName(channelName);
120+
if (channel && channel instanceof TextChannel) {
121+
await this.sendMarketingMessage(channel);
122+
}
123+
this.scheduleNextMarketingMessage(channelName);
124+
} catch (error) {
125+
elizaLogger.error('Error in marketing message schedule:', error);
126+
// Retry after a delay
127+
setTimeout(() => this.scheduleNextMarketingMessage(channelName), this.MIN_MARKETING_INTERVAL);
128+
}
129+
}, interval);
84130
}
85131

86132
async stopMarketing(): Promise<void> {
@@ -123,7 +169,7 @@ export class MessageManager {
123169
MARKETING_CONSTANTS.BASE_WAIT_TIME - timeReduction
124170
);
125171

126-
return timeSinceLastMessage >= waitTime &&
172+
return timeSinceLastMessage >= waitTime &&
127173
messageCount >= MARKETING_CONSTANTS.MIN_MESSAGES_BEFORE_REPLY;
128174
}
129175

@@ -165,7 +211,7 @@ export class MessageManager {
165211

166212
async getChatState(message: Message): Promise<State> {
167213
const channelId = message.channel.id;
168-
214+
169215
// Format character data
170216
const character = this.runtime.character;
171217
const characterData = {
@@ -280,10 +326,10 @@ export class MessageManager {
280326
}
281327

282328
const text = messageText.toLowerCase();
283-
329+
284330
// Check if message contains character's name or aliases
285331
const nameMatch = text.includes(this.runtime.character.name.toLowerCase());
286-
332+
287333
// Check if message matches character's topics
288334
const topics = this.runtime.character.topics || [];
289335
const topicMatch = topics.some(topic => {
@@ -295,7 +341,7 @@ export class MessageManager {
295341

296342
// Get character's response rules
297343
const responseRules = this.runtime.character.style?.response_rules || [];
298-
344+
299345
// Check against response patterns
300346
const respondPatterns = responseRules
301347
.filter(rule => rule.toLowerCase().startsWith('respond:'))

0 commit comments

Comments
 (0)