Skip to content

Commit 6dcc6be

Browse files
marketing enhanced
1 parent f486f6f commit 6dcc6be

File tree

6 files changed

+120
-421
lines changed

6 files changed

+120
-421
lines changed

characters/neuronlink.character.json

+4-4
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"name": "NeuronLink",
33
"plugins": [],
4-
"clients": ["discord"],
4+
"clients": ["discord","telegram"],
55
"modelProvider": "ollama",
66
"settings": {
77
"secrets": {},
@@ -35,7 +35,7 @@
3535
}
3636
},
3737
{
38-
"user": "NeuronLink_Architect",
38+
"user": "NeuronLink_Community_Member",
3939
"content": {
4040
"text": "I've been deep in this fascinating project that lets AI models work together like a team. If you're into AI dev, would love your thoughts! Drop by our Discord: discord.gg/neuronlink"
4141
}
@@ -49,7 +49,7 @@
4949
}
5050
},
5151
{
52-
"user": "NeuronLink_Architect",
52+
"user": "NeuronLink_Community_Member",
5353
"content": {
5454
"text": "Right? I'm actually working on something that makes them even smarter by working together. We're still early in development - perfect time to get involved if you're interested! neuronlink.ai"
5555
}
@@ -63,7 +63,7 @@
6363
}
6464
},
6565
{
66-
"user": "NeuronLink_Architect",
66+
"user": "NeuronLink_Community_Member",
6767
"content": {
6868
"text": "We've got a great community of AI devs building something cool together. Always looking for fresh perspectives! Check out what we're up to: discord.gg/neuronlink"
6969
}

packages/client-discord/src/messageManager.ts

+77-87
Original file line numberDiff line numberDiff line change
@@ -23,12 +23,12 @@ import { DiscordUserClient } from './discordUserClient';
2323

2424
// Constants
2525
const MARKETING_CONSTANTS = {
26-
MIN_MARKETING_INTERVAL: 15 * 60 * 1000, // 15 minutes
27-
MAX_MARKETING_INTERVAL: 45 * 60 * 1000, // 45 minutes
28-
BASE_WAIT_TIME: 6 * 60 * 60 * 1000, // 6 hours
29-
MIN_MESSAGES_BEFORE_REPLY: 20,
30-
TIME_REDUCTION_PER_MESSAGE: 15 * 60 * 1000, // 15 minutes
31-
MIN_WAIT_TIME: 30 * 60 * 1000, // 30 minutes
26+
MIN_MARKETING_INTERVAL: 2 * 60 * 1000, // 2 minutes
27+
MAX_MARKETING_INTERVAL: 2 * 60 * 1000, // 2 minutes
28+
BASE_WAIT_TIME: 4 * 60 * 1000, // 4 minutes
29+
MIN_MESSAGES_BEFORE_REPLY: 2, // Reduced for testing
30+
TIME_REDUCTION_PER_MESSAGE: 1 * 60 * 1000, // 1 minute
31+
MIN_WAIT_TIME: 2 * 60 * 1000, // 2 minutes
3232
MAX_MARKETING_MESSAGES_PER_GROUP: 96
3333
};
3434

@@ -69,8 +69,8 @@ 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
72+
private readonly MIN_MARKETING_INTERVAL = 2 * 60 * 1000; // 2 minutes
73+
private readonly MAX_MARKETING_INTERVAL = 2 * 60 * 1000; // 2 minutes
7474
private readonly MAX_MARKETING_MESSAGES_PER_CHANNEL = 96; // Max messages per channel per day
7575
private marketingEnabled: boolean = false;
7676

@@ -108,23 +108,26 @@ export class MessageManager {
108108
private scheduleNextMarketingMessage(channelName: string): void {
109109
if (!this.marketingEnabled) return;
110110

111-
const interval = Math.floor(
112-
Math.random() * (this.MAX_MARKETING_INTERVAL - this.MIN_MARKETING_INTERVAL) + this.MIN_MARKETING_INTERVAL
113-
);
111+
const interval = this.MIN_MARKETING_INTERVAL; // Use fixed 2-minute interval for testing
112+
elizaLogger.log(`Scheduling next marketing message for ${channelName} in ${Math.floor(interval/1000)} seconds`);
114113

115114
setTimeout(async () => {
116115
try {
117116
if (!this.marketingEnabled) return;
118117

119-
const channel = await this.client.getChannelByName(channelName);
118+
const channels = await this.client.getChannels();
119+
const channel = channels.find(c => c.name === channelName);
120+
120121
if (channel && channel instanceof TextChannel) {
121122
await this.sendMarketingMessage(channel);
122123
}
124+
125+
// Schedule next message immediately after sending
123126
this.scheduleNextMarketingMessage(channelName);
124127
} catch (error) {
125128
elizaLogger.error('Error in marketing message schedule:', error);
126-
// Retry after a delay
127-
setTimeout(() => this.scheduleNextMarketingMessage(channelName), this.MIN_MARKETING_INTERVAL);
129+
// Retry after a short delay
130+
setTimeout(() => this.scheduleNextMarketingMessage(channelName), 5000);
128131
}
129132
}, interval);
130133
}
@@ -157,58 +160,73 @@ export class MessageManager {
157160
}
158161

159162
private canSendMarketingMessage(channel: TextChannel): boolean {
160-
const channelName = this.normalizeChannelName(channel.name);
161-
const lastMessageTime = this.lastMarketingTimes.get(channelName) || 0;
162-
const messageCount = this.channelMessageCounts.get(channelName) || 0;
163-
const timeReduction = this.channelTimeReductions.get(channelName) || 0;
164-
163+
const channelName = channel.name;
165164
const now = Date.now();
166-
const timeSinceLastMessage = now - lastMessageTime;
167-
const waitTime = Math.max(
168-
MARKETING_CONSTANTS.MIN_WAIT_TIME,
169-
MARKETING_CONSTANTS.BASE_WAIT_TIME - timeReduction
170-
);
171-
172-
return timeSinceLastMessage >= waitTime &&
173-
messageCount >= MARKETING_CONSTANTS.MIN_MESSAGES_BEFORE_REPLY;
174-
}
175-
176-
private updateChannelActivity(channel: TextChannel): void {
177-
const channelName = this.normalizeChannelName(channel.name);
178-
const messageCount = (this.channelMessageCounts.get(channelName) || 0) + 1;
179-
this.channelMessageCounts.set(channelName, messageCount);
180-
181-
const timeReduction = Math.min(
182-
messageCount * MARKETING_CONSTANTS.TIME_REDUCTION_PER_MESSAGE,
183-
MARKETING_CONSTANTS.BASE_WAIT_TIME - MARKETING_CONSTANTS.MIN_WAIT_TIME
184-
);
185-
this.channelTimeReductions.set(channelName, timeReduction);
186-
}
165+
const lastMessageTime = this.lastMarketingTimes.get(channelName) || 0;
166+
167+
// For testing: Only check if 2 minutes have passed since last message
168+
const timeOk = (now - lastMessageTime) >= this.MIN_MARKETING_INTERVAL;
169+
170+
elizaLogger.log(`Marketing check for ${channelName}:`, {
171+
timePassedSeconds: Math.floor((now - lastMessageTime) / 1000),
172+
requiredWaitTimeSeconds: Math.floor(this.MIN_MARKETING_INTERVAL / 1000),
173+
canSend: timeOk
174+
});
187175

188-
private resetChannelCounters(channel: TextChannel): void {
189-
const channelName = this.normalizeChannelName(channel.name);
190-
this.channelMessageCounts.set(channelName, 0);
191-
this.channelTimeReductions.set(channelName, 0);
192-
this.lastMarketingTimes.set(channelName, Date.now());
176+
return timeOk;
193177
}
194178

195179
async sendMarketingMessage(channel: TextChannel): Promise<void> {
196180
try {
197-
const response = await generateMessageResponse(this.runtime, {
198-
text: '',
199-
fromId: '',
181+
elizaLogger.log(`Attempting to send marketing message to ${channel.name}`);
182+
183+
// Check if we can send a message
184+
if (!this.canSendMarketingMessage(channel)) {
185+
elizaLogger.log(`Cannot send marketing message to ${channel.name} yet`);
186+
return;
187+
}
188+
189+
// Generate marketing message using character's marketing style
190+
const marketingPrompt = {
191+
text: "Generate a marketing message",
192+
context: {
193+
channelName: channel.name,
194+
channelTopic: channel.topic || '',
195+
marketingGoal: "Engage users and promote discussion"
196+
},
197+
fromId: 'marketing',
200198
timestamp: new Date().toISOString()
201-
});
199+
};
202200

201+
const response = await generateMessageResponse(this.runtime, marketingPrompt);
202+
203203
if (response) {
204-
await channel.send(response.text);
204+
elizaLogger.log(`Sending marketing message to ${channel.name}: ${response}`);
205+
await channel.send(response);
205206
this.resetChannelCounters(channel);
207+
} else {
208+
elizaLogger.error('Failed to generate marketing message');
206209
}
207210
} catch (error) {
208-
elizaLogger.error('Error sending marketing message:', error);
211+
elizaLogger.error('Error sending marketing message:', {
212+
error: error instanceof Error ? error.message : String(error),
213+
stack: error instanceof Error ? error.stack : undefined,
214+
channel: channel.name
215+
});
209216
}
210217
}
211218

219+
private updateChannelActivity(channel: TextChannel): void {
220+
// Simplified version for testing
221+
const channelName = channel.name;
222+
this.lastMarketingTimes.set(channelName, Date.now());
223+
}
224+
225+
private resetChannelCounters(channel: TextChannel): void {
226+
const channelName = channel.name;
227+
this.lastMarketingTimes.set(channelName, Date.now());
228+
}
229+
212230
async getChatState(message: Message): Promise<State> {
213231
const channelId = message.channel.id;
214232

@@ -393,57 +411,29 @@ export class MessageManager {
393411

394412
async handleMessage(message: Message): Promise<{ text: string } | null> {
395413
try {
396-
// Skip messages from the bot itself
397-
const botId = this.client.getUserId();
398-
if (message.author.id === botId) {
399-
return null;
400-
}
401-
402414
elizaLogger.log('🔄 Starting message processing:', {
403415
text: message.content,
404416
channelId: message.channel.id,
405417
userId: message.author.id
406418
});
407419

408-
// Check if we should respond
409-
const shouldRespond = await this.shouldRespondToMessage(message.content, message.channel.id);
410-
if (!shouldRespond) {
411-
// Update channel activity for marketing even if we don't respond
412-
if (message.channel instanceof TextChannel) {
413-
this.updateChannelActivity(message.channel);
414-
}
415-
return null;
420+
// Update channel activity for marketing
421+
if (message.channel instanceof TextChannel) {
422+
this.updateChannelActivity(message.channel);
416423
}
417424

418-
// Create memory for the message
419-
await this.createMessageMemory(message);
420-
421-
// Prepare chat state
425+
// Get chat state
422426
const state = await this.getChatState(message);
423-
424-
elizaLogger.log('🧠 Preparing response with context:', {
425-
messageLength: message.content.length,
426-
contextLength: state.context?.length || 0,
427-
characterName: this.runtime.character?.name
428-
});
429-
430-
// Generate response using character's personality
427+
428+
// Generate response
431429
const response = await this.generateResponse(message, state);
430+
432431
if (!response) {
433-
elizaLogger.warn('No response generated');
432+
elizaLogger.log('ℹ️ No response to send');
434433
return null;
435434
}
436435

437-
// Update chat state with the new message and response
438-
this.updateChatState(message, response);
439-
440-
// If this is a marketing channel, reset marketing counters after response
441-
if (message.channel instanceof TextChannel && this.marketingEnabled) {
442-
this.resetChannelCounters(message.channel);
443-
}
444-
445436
return { text: response };
446-
447437
} catch (error) {
448438
elizaLogger.error('❌ Error handling message:', {
449439
error: error instanceof Error ? error.message : String(error),

packages/client-telegram/src/messageManager.ts

+14-26
Original file line numberDiff line numberDiff line change
@@ -127,12 +127,12 @@ export class MessageManager {
127127
private groupTimeReductions: Map<string, number> = new Map(); // Track accumulated time reductions
128128

129129
// Base timing constants
130-
private readonly MIN_MARKETING_INTERVAL = 15 * 60 * 1000; // 15 minutes
131-
private readonly MAX_MARKETING_INTERVAL = 45 * 60 * 1000; // 45 minutes
132-
private readonly BASE_WAIT_TIME = 6 * 60 * 60 * 1000; // 6 hours base wait time
133-
private readonly MIN_MESSAGES_BEFORE_REPLY = 20; // Minimum messages before allowing reply
134-
private readonly TIME_REDUCTION_PER_MESSAGE = 15 * 60 * 1000; // 15 minutes reduction per active period
135-
private readonly MIN_WAIT_TIME = 30 * 60 * 1000; // Minimum 30 minutes between messages
130+
private readonly MIN_MARKETING_INTERVAL = 2 * 60 * 1000; // 2 minutes
131+
private readonly MAX_MARKETING_INTERVAL = 2 * 60 * 1000; // 2 minutes
132+
private readonly BASE_WAIT_TIME = 4 * 60 * 1000; // 4 minutes
133+
private readonly MIN_MESSAGES_BEFORE_REPLY = 2; // Reduced for testing
134+
private readonly TIME_REDUCTION_PER_MESSAGE = 1 * 60 * 1000; // 1 minute
135+
private readonly MIN_WAIT_TIME = 2 * 60 * 1000; // 2 minutes
136136
private readonly MAX_MARKETING_MESSAGES_PER_GROUP = 96; // Max marketing messages per group per day
137137
private marketingEnabled: boolean = false;
138138

@@ -218,29 +218,17 @@ export class MessageManager {
218218
const groupId = dialog.id.toString();
219219
const now = Date.now();
220220
const lastMessageTime = this.lastMarketingTimes.get(groupId) || 0;
221-
const messageCount = this.groupMessageCounts.get(groupId) || 0;
222-
const timeReduction = this.groupTimeReductions.get(groupId) || 0;
223-
224-
// Calculate required wait time with reductions
225-
const requiredWaitTime = Math.max(
226-
this.MIN_WAIT_TIME,
227-
this.BASE_WAIT_TIME - timeReduction
228-
);
229-
230-
// Check if enough time has passed and enough messages have been posted
231-
const timeOk = (now - lastMessageTime) >= requiredWaitTime;
232-
const messagesOk = messageCount >= this.MIN_MESSAGES_BEFORE_REPLY;
233-
221+
222+
// For testing: Only check if 2 minutes have passed since last message
223+
const timeOk = (now - lastMessageTime) >= this.MIN_MARKETING_INTERVAL;
224+
234225
elizaLogger.log(`Marketing check for ${dialog.title}:`, {
235-
timePassedMinutes: Math.floor((now - lastMessageTime) / (60 * 1000)),
236-
requiredWaitTimeMinutes: Math.floor(requiredWaitTime / (60 * 1000)),
237-
messageCount,
238-
minMessages: this.MIN_MESSAGES_BEFORE_REPLY,
239-
timeReductionMinutes: Math.floor(timeReduction / (60 * 1000)),
240-
canSend: timeOk && messagesOk
226+
timePassedSeconds: Math.floor((now - lastMessageTime) / 1000),
227+
requiredWaitTimeSeconds: Math.floor(this.MIN_MARKETING_INTERVAL / 1000),
228+
canSend: timeOk
241229
});
242230

243-
return timeOk && messagesOk;
231+
return timeOk;
244232
}
245233

246234
private updateGroupActivity(dialog: Dialog) {

0 commit comments

Comments
 (0)