@elizaos/plugin-twitter 1.2.6 → 1.2.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.ts +3 -1222
- package/dist/index.js +152 -130
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -5,7 +5,10 @@ var __export = (target, all) => {
|
|
|
5
5
|
};
|
|
6
6
|
|
|
7
7
|
// src/index.ts
|
|
8
|
-
import { logger as
|
|
8
|
+
import { logger as logger10 } from "@elizaos/core";
|
|
9
|
+
|
|
10
|
+
// src/services/twitter.service.ts
|
|
11
|
+
import { Service, logger as logger8 } from "@elizaos/core";
|
|
9
12
|
|
|
10
13
|
// src/interactions.ts
|
|
11
14
|
import {
|
|
@@ -1983,6 +1986,17 @@ var parseActionResponseFromText = (text) => {
|
|
|
1983
1986
|
return { actions };
|
|
1984
1987
|
};
|
|
1985
1988
|
|
|
1989
|
+
// src/utils/settings.ts
|
|
1990
|
+
function getSetting(runtime, key, defaultValue) {
|
|
1991
|
+
if (runtime && typeof runtime.getSetting === "function") {
|
|
1992
|
+
const value = runtime.getSetting(key);
|
|
1993
|
+
if (value !== void 0 && value !== null) {
|
|
1994
|
+
return String(value);
|
|
1995
|
+
}
|
|
1996
|
+
}
|
|
1997
|
+
return process.env[key] ?? defaultValue;
|
|
1998
|
+
}
|
|
1999
|
+
|
|
1986
2000
|
// node_modules/zod/dist/esm/v3/external.js
|
|
1987
2001
|
var external_exports = {};
|
|
1988
2002
|
__export(external_exports, {
|
|
@@ -6077,15 +6091,6 @@ function getTargetUsers(targetUsersConfig) {
|
|
|
6077
6091
|
const users = parseTargetUsers(targetUsersConfig);
|
|
6078
6092
|
return users.filter((u) => u !== "*");
|
|
6079
6093
|
}
|
|
6080
|
-
function getSetting(runtime, key, defaultValue) {
|
|
6081
|
-
if (runtime && typeof runtime.getSetting === "function") {
|
|
6082
|
-
const value = runtime.getSetting(key);
|
|
6083
|
-
if (value !== void 0 && value !== null) {
|
|
6084
|
-
return String(value);
|
|
6085
|
-
}
|
|
6086
|
-
}
|
|
6087
|
-
return process.env[key] ?? defaultValue;
|
|
6088
|
-
}
|
|
6089
6094
|
async function validateTwitterConfig(runtime, config = {}) {
|
|
6090
6095
|
try {
|
|
6091
6096
|
const validatedConfig = {
|
|
@@ -6123,17 +6128,6 @@ async function validateTwitterConfig(runtime, config = {}) {
|
|
|
6123
6128
|
}
|
|
6124
6129
|
}
|
|
6125
6130
|
|
|
6126
|
-
// src/utils/settings.ts
|
|
6127
|
-
function getSetting2(runtime, key, defaultValue) {
|
|
6128
|
-
if (runtime && typeof runtime.getSetting === "function") {
|
|
6129
|
-
const value = runtime.getSetting(key);
|
|
6130
|
-
if (value !== void 0 && value !== null) {
|
|
6131
|
-
return String(value);
|
|
6132
|
-
}
|
|
6133
|
-
}
|
|
6134
|
-
return process.env[key] ?? defaultValue;
|
|
6135
|
-
}
|
|
6136
|
-
|
|
6137
6131
|
// src/interactions.ts
|
|
6138
6132
|
var TwitterInteractionClient = class {
|
|
6139
6133
|
/**
|
|
@@ -6149,7 +6143,7 @@ var TwitterInteractionClient = class {
|
|
|
6149
6143
|
this.client = client;
|
|
6150
6144
|
this.runtime = runtime;
|
|
6151
6145
|
this.state = state;
|
|
6152
|
-
const dryRunSetting = this.state?.TWITTER_DRY_RUN ??
|
|
6146
|
+
const dryRunSetting = this.state?.TWITTER_DRY_RUN ?? getSetting(this.runtime, "TWITTER_DRY_RUN") ?? process.env.TWITTER_DRY_RUN;
|
|
6153
6147
|
this.isDryRun = dryRunSetting === true || dryRunSetting === "true" || typeof dryRunSetting === "string" && dryRunSetting.toLowerCase() === "true";
|
|
6154
6148
|
}
|
|
6155
6149
|
/**
|
|
@@ -6164,7 +6158,7 @@ var TwitterInteractionClient = class {
|
|
|
6164
6158
|
return;
|
|
6165
6159
|
}
|
|
6166
6160
|
const engagementIntervalMinutes = parseInt(
|
|
6167
|
-
this.state?.TWITTER_ENGAGEMENT_INTERVAL ||
|
|
6161
|
+
this.state?.TWITTER_ENGAGEMENT_INTERVAL || getSetting(this.runtime, "TWITTER_ENGAGEMENT_INTERVAL") || process.env.TWITTER_ENGAGEMENT_INTERVAL || "30"
|
|
6168
6162
|
);
|
|
6169
6163
|
const interactionInterval = engagementIntervalMinutes * 60 * 1e3;
|
|
6170
6164
|
logger3.info(`Twitter interaction client will check every ${engagementIntervalMinutes} minutes`);
|
|
@@ -6189,11 +6183,11 @@ var TwitterInteractionClient = class {
|
|
|
6189
6183
|
logger3.log("Checking Twitter interactions");
|
|
6190
6184
|
const twitterUsername = this.client.profile?.username;
|
|
6191
6185
|
try {
|
|
6192
|
-
const repliesEnabled = (
|
|
6186
|
+
const repliesEnabled = (getSetting(this.runtime, "TWITTER_ENABLE_REPLIES") ?? process.env.TWITTER_ENABLE_REPLIES) !== "false";
|
|
6193
6187
|
if (repliesEnabled) {
|
|
6194
6188
|
await this.handleMentions(twitterUsername);
|
|
6195
6189
|
}
|
|
6196
|
-
const targetUsersConfig = (
|
|
6190
|
+
const targetUsersConfig = (getSetting(this.runtime, "TWITTER_TARGET_USERS") ?? process.env.TWITTER_TARGET_USERS) || "";
|
|
6197
6191
|
if (targetUsersConfig?.trim()) {
|
|
6198
6192
|
await this.handleTargetUserPosts(targetUsersConfig);
|
|
6199
6193
|
}
|
|
@@ -6267,7 +6261,7 @@ var TwitterInteractionClient = class {
|
|
|
6267
6261
|
*/
|
|
6268
6262
|
async processTargetUserTweets(tweets, username) {
|
|
6269
6263
|
const maxEngagementsPerRun = parseInt(
|
|
6270
|
-
|
|
6264
|
+
getSetting(this.runtime, "TWITTER_MAX_ENGAGEMENTS_PER_RUN") || process.env.TWITTER_MAX_ENGAGEMENTS_PER_RUN || "10"
|
|
6271
6265
|
);
|
|
6272
6266
|
let engagementCount = 0;
|
|
6273
6267
|
for (const tweet of tweets) {
|
|
@@ -6464,7 +6458,7 @@ Response (YES/NO):`;
|
|
|
6464
6458
|
);
|
|
6465
6459
|
let uniqueTweetCandidates = [...mentionCandidates];
|
|
6466
6460
|
uniqueTweetCandidates = uniqueTweetCandidates.sort((a, b) => a.id.localeCompare(b.id)).filter((tweet) => tweet.userId !== this.client.profile.id);
|
|
6467
|
-
const targetUsersConfig = (
|
|
6461
|
+
const targetUsersConfig = (getSetting(this.runtime, "TWITTER_TARGET_USERS") ?? process.env.TWITTER_TARGET_USERS) || "";
|
|
6468
6462
|
if (targetUsersConfig?.trim()) {
|
|
6469
6463
|
uniqueTweetCandidates = uniqueTweetCandidates.filter((tweet) => {
|
|
6470
6464
|
const shouldTarget = shouldTargetUser(
|
|
@@ -6480,7 +6474,7 @@ Response (YES/NO):`;
|
|
|
6480
6474
|
});
|
|
6481
6475
|
}
|
|
6482
6476
|
const maxInteractionsPerRun = parseInt(
|
|
6483
|
-
|
|
6477
|
+
getSetting(this.runtime, "TWITTER_MAX_ENGAGEMENTS_PER_RUN") || process.env.TWITTER_MAX_ENGAGEMENTS_PER_RUN || "10"
|
|
6484
6478
|
);
|
|
6485
6479
|
const tweetsToProcess = uniqueTweetCandidates.slice(0, maxInteractionsPerRun);
|
|
6486
6480
|
logger3.info(`Processing ${tweetsToProcess.length} of ${uniqueTweetCandidates.length} mention tweets (max: ${maxInteractionsPerRun})`);
|
|
@@ -6839,12 +6833,12 @@ var TwitterPostClient = class {
|
|
|
6839
6833
|
this.client = client;
|
|
6840
6834
|
this.state = state;
|
|
6841
6835
|
this.runtime = runtime;
|
|
6842
|
-
const dryRunSetting = this.state?.TWITTER_DRY_RUN ??
|
|
6836
|
+
const dryRunSetting = this.state?.TWITTER_DRY_RUN ?? getSetting(this.runtime, "TWITTER_DRY_RUN") ?? process.env.TWITTER_DRY_RUN;
|
|
6843
6837
|
this.isDryRun = dryRunSetting === true || dryRunSetting === "true" || typeof dryRunSetting === "string" && dryRunSetting.toLowerCase() === "true";
|
|
6844
6838
|
logger4.log("Twitter Post Client Configuration:");
|
|
6845
6839
|
logger4.log(`- Dry Run Mode: ${this.isDryRun ? "Enabled" : "Disabled"}`);
|
|
6846
6840
|
const postIntervalMinutes = parseInt(
|
|
6847
|
-
this.state?.TWITTER_POST_INTERVAL ||
|
|
6841
|
+
this.state?.TWITTER_POST_INTERVAL || getSetting(this.runtime, "TWITTER_POST_INTERVAL") || process.env.TWITTER_POST_INTERVAL || "120"
|
|
6848
6842
|
);
|
|
6849
6843
|
logger4.log(`- Post Interval: ${postIntervalMinutes} minutes`);
|
|
6850
6844
|
}
|
|
@@ -6867,7 +6861,7 @@ var TwitterPostClient = class {
|
|
|
6867
6861
|
return;
|
|
6868
6862
|
}
|
|
6869
6863
|
const postIntervalMinutes = parseInt(
|
|
6870
|
-
this.state?.TWITTER_POST_INTERVAL ||
|
|
6864
|
+
this.state?.TWITTER_POST_INTERVAL || getSetting(this.runtime, "TWITTER_POST_INTERVAL") || process.env.TWITTER_POST_INTERVAL || "120"
|
|
6871
6865
|
);
|
|
6872
6866
|
const interval = postIntervalMinutes * 60 * 1e3;
|
|
6873
6867
|
logger4.info(`Next tweet scheduled in ${postIntervalMinutes} minutes`);
|
|
@@ -6878,7 +6872,7 @@ var TwitterPostClient = class {
|
|
|
6878
6872
|
};
|
|
6879
6873
|
await new Promise((resolve) => setTimeout(resolve, 1e3));
|
|
6880
6874
|
const postImmediately = parseInt(
|
|
6881
|
-
this.state?.TWITTER_POST_INTERVAL ||
|
|
6875
|
+
this.state?.TWITTER_POST_INTERVAL || getSetting(this.runtime, "TWITTER_POST_INTERVAL") || process.env.TWITTER_POST_INTERVAL || "120"
|
|
6882
6876
|
) === 0;
|
|
6883
6877
|
if (postImmediately) {
|
|
6884
6878
|
logger4.info("TWITTER_POST_IMMEDIATELY is true, generating initial tweet now");
|
|
@@ -7094,9 +7088,9 @@ var TwitterTimelineClient = class {
|
|
|
7094
7088
|
this.twitterClient = client.twitterClient;
|
|
7095
7089
|
this.runtime = runtime;
|
|
7096
7090
|
this.state = state;
|
|
7097
|
-
const dryRunSetting = this.state?.TWITTER_DRY_RUN ??
|
|
7091
|
+
const dryRunSetting = this.state?.TWITTER_DRY_RUN ?? getSetting(this.runtime, "TWITTER_DRY_RUN") ?? process.env.TWITTER_DRY_RUN;
|
|
7098
7092
|
this.isDryRun = dryRunSetting === true || dryRunSetting === "true" || typeof dryRunSetting === "string" && dryRunSetting.toLowerCase() === "true";
|
|
7099
|
-
const timelineMode =
|
|
7093
|
+
const timelineMode = getSetting(this.runtime, "TWITTER_TIMELINE_MODE") ?? process.env.TWITTER_TIMELINE_MODE;
|
|
7100
7094
|
this.timelineType = timelineMode === "following" /* Following */ ? "following" /* Following */ : "foryou" /* ForYou */;
|
|
7101
7095
|
}
|
|
7102
7096
|
async start() {
|
|
@@ -7108,7 +7102,7 @@ var TwitterTimelineClient = class {
|
|
|
7108
7102
|
return;
|
|
7109
7103
|
}
|
|
7110
7104
|
const engagementIntervalMinutes = parseInt(
|
|
7111
|
-
this.state?.TWITTER_ENGAGEMENT_INTERVAL ||
|
|
7105
|
+
this.state?.TWITTER_ENGAGEMENT_INTERVAL || getSetting(this.runtime, "TWITTER_ENGAGEMENT_INTERVAL") || process.env.TWITTER_ENGAGEMENT_INTERVAL || "30"
|
|
7112
7106
|
);
|
|
7113
7107
|
const actionInterval = engagementIntervalMinutes * 60 * 1e3;
|
|
7114
7108
|
logger5.info(`Timeline client will check every ${engagementIntervalMinutes} minutes`);
|
|
@@ -7154,7 +7148,7 @@ var TwitterTimelineClient = class {
|
|
|
7154
7148
|
const tweets = await this.getTimeline(20);
|
|
7155
7149
|
logger5.info(`Fetched ${tweets.length} tweets from timeline`);
|
|
7156
7150
|
const maxActionsPerCycle = parseInt(
|
|
7157
|
-
|
|
7151
|
+
getSetting(this.runtime, "TWITTER_MAX_ENGAGEMENTS_PER_RUN") || process.env.TWITTER_MAX_ENGAGEMENTS_PER_RUN || "10"
|
|
7158
7152
|
);
|
|
7159
7153
|
const tweetDecisions = [];
|
|
7160
7154
|
for (const tweet of tweets) {
|
|
@@ -7452,7 +7446,7 @@ var TwitterDiscoveryClient = class {
|
|
|
7452
7446
|
this.client = client;
|
|
7453
7447
|
this.twitterClient = client.twitterClient;
|
|
7454
7448
|
this.runtime = runtime;
|
|
7455
|
-
const dryRunSetting = state?.TWITTER_DRY_RUN ??
|
|
7449
|
+
const dryRunSetting = state?.TWITTER_DRY_RUN ?? getSetting(this.runtime, "TWITTER_DRY_RUN") ?? process.env.TWITTER_DRY_RUN;
|
|
7456
7450
|
this.isDryRun = dryRunSetting === true || dryRunSetting === "true" || typeof dryRunSetting === "string" && dryRunSetting.toLowerCase() === "true";
|
|
7457
7451
|
this.config = this.buildDiscoveryConfig();
|
|
7458
7452
|
logger6.info("Twitter Discovery Config:", {
|
|
@@ -7487,13 +7481,13 @@ var TwitterDiscoveryClient = class {
|
|
|
7487
7481
|
return {
|
|
7488
7482
|
topics,
|
|
7489
7483
|
minFollowerCount: parseInt(
|
|
7490
|
-
|
|
7484
|
+
getSetting(this.runtime, "TWITTER_MIN_FOLLOWER_COUNT") || process.env.TWITTER_MIN_FOLLOWER_COUNT || "100"
|
|
7491
7485
|
),
|
|
7492
7486
|
maxFollowsPerCycle: parseInt(
|
|
7493
|
-
|
|
7487
|
+
getSetting(this.runtime, "TWITTER_MAX_FOLLOWS_PER_CYCLE") || process.env.TWITTER_MAX_FOLLOWS_PER_CYCLE || "5"
|
|
7494
7488
|
),
|
|
7495
7489
|
maxEngagementsPerCycle: parseInt(
|
|
7496
|
-
|
|
7490
|
+
getSetting(this.runtime, "TWITTER_MAX_ENGAGEMENTS_PER_RUN") || process.env.TWITTER_MAX_ENGAGEMENTS_PER_RUN || "10"
|
|
7497
7491
|
),
|
|
7498
7492
|
likeThreshold: 0.6,
|
|
7499
7493
|
replyThreshold: 0.8,
|
|
@@ -7522,7 +7516,7 @@ var TwitterDiscoveryClient = class {
|
|
|
7522
7516
|
logger6.error("Discovery cycle error:", error);
|
|
7523
7517
|
}
|
|
7524
7518
|
const baseInterval = parseInt(
|
|
7525
|
-
|
|
7519
|
+
getSetting(this.runtime, "TWITTER_DISCOVERY_INTERVAL") || process.env.TWITTER_DISCOVERY_INTERVAL || "30"
|
|
7526
7520
|
);
|
|
7527
7521
|
const variance = Math.random() * 20 - 10;
|
|
7528
7522
|
const nextInterval = (baseInterval + variance) * 60 * 1e3;
|
|
@@ -7588,7 +7582,7 @@ var TwitterDiscoveryClient = class {
|
|
|
7588
7582
|
const accounts = /* @__PURE__ */ new Map();
|
|
7589
7583
|
for (const topic of this.config.topics.slice(0, 5)) {
|
|
7590
7584
|
try {
|
|
7591
|
-
const popularQuery = `${topic} -is:retweet -is:reply
|
|
7585
|
+
const popularQuery = `${topic} -is:retweet -is:reply lang:en`;
|
|
7592
7586
|
logger6.debug(`Searching popular tweets for topic: ${topic}`);
|
|
7593
7587
|
const popularResults = await this.twitterClient.fetchSearchTweets(
|
|
7594
7588
|
popularQuery,
|
|
@@ -7596,10 +7590,11 @@ var TwitterDiscoveryClient = class {
|
|
|
7596
7590
|
0 /* Top */
|
|
7597
7591
|
);
|
|
7598
7592
|
for (const tweet of popularResults.tweets) {
|
|
7593
|
+
if ((tweet.likes || 0) < 10) continue;
|
|
7599
7594
|
const scored = this.scoreTweet(tweet, "topic");
|
|
7600
7595
|
tweets.push(scored);
|
|
7601
7596
|
}
|
|
7602
|
-
const verifiedQuery = `${topic} -is:retweet lang:en
|
|
7597
|
+
const verifiedQuery = `${topic} -is:retweet lang:en is:verified`;
|
|
7603
7598
|
logger6.debug(`Searching verified accounts for topic: ${topic}`);
|
|
7604
7599
|
const verifiedResults = await this.twitterClient.fetchSearchTweets(
|
|
7605
7600
|
verifiedQuery,
|
|
@@ -7634,7 +7629,7 @@ var TwitterDiscoveryClient = class {
|
|
|
7634
7629
|
const accounts = /* @__PURE__ */ new Map();
|
|
7635
7630
|
const topicQuery = this.config.topics.slice(0, 3).map((t) => `"${t}"`).join(" OR ");
|
|
7636
7631
|
try {
|
|
7637
|
-
const viralQuery = `${topicQuery}
|
|
7632
|
+
const viralQuery = `${topicQuery} -is:retweet has:mentions`;
|
|
7638
7633
|
logger6.debug(`Searching viral threads with query: ${viralQuery}`);
|
|
7639
7634
|
const searchResults = await this.twitterClient.fetchSearchTweets(
|
|
7640
7635
|
viralQuery,
|
|
@@ -7642,6 +7637,8 @@ var TwitterDiscoveryClient = class {
|
|
|
7642
7637
|
0 /* Top */
|
|
7643
7638
|
);
|
|
7644
7639
|
for (const tweet of searchResults.tweets) {
|
|
7640
|
+
const engagementScore = (tweet.likes || 0) + (tweet.retweets || 0) * 2;
|
|
7641
|
+
if (engagementScore < 50) continue;
|
|
7645
7642
|
const scored = this.scoreTweet(tweet, "thread");
|
|
7646
7643
|
tweets.push(scored);
|
|
7647
7644
|
const account = this.scoreAccount({
|
|
@@ -7666,7 +7663,7 @@ var TwitterDiscoveryClient = class {
|
|
|
7666
7663
|
const accounts = /* @__PURE__ */ new Map();
|
|
7667
7664
|
for (const topic of this.config.topics.slice(0, 3)) {
|
|
7668
7665
|
try {
|
|
7669
|
-
const influencerQuery = `${topic} -is:retweet
|
|
7666
|
+
const influencerQuery = `${topic} -is:retweet (is:verified OR has:links)`;
|
|
7670
7667
|
logger6.debug(`Searching for influencers in topic: ${topic}`);
|
|
7671
7668
|
const results = await this.twitterClient.fetchSearchTweets(
|
|
7672
7669
|
influencerQuery,
|
|
@@ -7674,6 +7671,8 @@ var TwitterDiscoveryClient = class {
|
|
|
7674
7671
|
0 /* Top */
|
|
7675
7672
|
);
|
|
7676
7673
|
for (const tweet of results.tweets) {
|
|
7674
|
+
const engagement = (tweet.likes || 0) + (tweet.retweets || 0) * 2;
|
|
7675
|
+
if (engagement < 20) continue;
|
|
7677
7676
|
const scored = this.scoreTweet(tweet, "topic");
|
|
7678
7677
|
tweets.push(scored);
|
|
7679
7678
|
const estimatedFollowers = Math.max(
|
|
@@ -8523,7 +8522,45 @@ _ClientBase._twitterClients = {};
|
|
|
8523
8522
|
var ClientBase = _ClientBase;
|
|
8524
8523
|
|
|
8525
8524
|
// src/services/twitter.service.ts
|
|
8526
|
-
|
|
8525
|
+
var TwitterClientInstance = class {
|
|
8526
|
+
constructor(runtime, state) {
|
|
8527
|
+
this.client = new ClientBase(runtime, state);
|
|
8528
|
+
const postEnabledSetting = getSetting(runtime, "TWITTER_ENABLE_POST") ?? process.env.TWITTER_ENABLE_POST;
|
|
8529
|
+
logger8.debug(`TWITTER_ENABLE_POST setting value: ${JSON.stringify(postEnabledSetting)}, type: ${typeof postEnabledSetting}`);
|
|
8530
|
+
const postEnabled = postEnabledSetting === "true" || postEnabledSetting === true;
|
|
8531
|
+
if (postEnabled) {
|
|
8532
|
+
logger8.info("Twitter posting is ENABLED - creating post client");
|
|
8533
|
+
this.post = new TwitterPostClient(this.client, runtime, state);
|
|
8534
|
+
} else {
|
|
8535
|
+
logger8.info("Twitter posting is DISABLED - set TWITTER_ENABLE_POST=true to enable automatic posting");
|
|
8536
|
+
}
|
|
8537
|
+
const repliesEnabled = (getSetting(runtime, "TWITTER_ENABLE_REPLIES") ?? process.env.TWITTER_ENABLE_REPLIES) !== "false";
|
|
8538
|
+
if (repliesEnabled) {
|
|
8539
|
+
logger8.info("Twitter replies/interactions are ENABLED");
|
|
8540
|
+
this.interaction = new TwitterInteractionClient(
|
|
8541
|
+
this.client,
|
|
8542
|
+
runtime,
|
|
8543
|
+
state
|
|
8544
|
+
);
|
|
8545
|
+
} else {
|
|
8546
|
+
logger8.info("Twitter replies/interactions are DISABLED");
|
|
8547
|
+
}
|
|
8548
|
+
const actionsEnabled = (getSetting(runtime, "TWITTER_ENABLE_ACTIONS") ?? process.env.TWITTER_ENABLE_ACTIONS) === "true";
|
|
8549
|
+
if (actionsEnabled) {
|
|
8550
|
+
logger8.info("Twitter timeline actions are ENABLED");
|
|
8551
|
+
this.timeline = new TwitterTimelineClient(this.client, runtime, state);
|
|
8552
|
+
} else {
|
|
8553
|
+
logger8.info("Twitter timeline actions are DISABLED");
|
|
8554
|
+
}
|
|
8555
|
+
const discoveryEnabled = (getSetting(runtime, "TWITTER_ENABLE_DISCOVERY") ?? process.env.TWITTER_ENABLE_DISCOVERY) === "true" || actionsEnabled && (getSetting(runtime, "TWITTER_ENABLE_DISCOVERY") ?? process.env.TWITTER_ENABLE_DISCOVERY) !== "false";
|
|
8556
|
+
if (discoveryEnabled) {
|
|
8557
|
+
logger8.info("Twitter discovery service is ENABLED");
|
|
8558
|
+
this.discovery = new TwitterDiscoveryClient(this.client, runtime, state);
|
|
8559
|
+
} else {
|
|
8560
|
+
logger8.info("Twitter discovery service is DISABLED - set TWITTER_ENABLE_DISCOVERY=true to enable");
|
|
8561
|
+
}
|
|
8562
|
+
}
|
|
8563
|
+
};
|
|
8527
8564
|
var _TwitterService = class _TwitterService extends Service {
|
|
8528
8565
|
constructor() {
|
|
8529
8566
|
super();
|
|
@@ -8533,9 +8570,48 @@ var _TwitterService = class _TwitterService extends Service {
|
|
|
8533
8570
|
static async start(runtime) {
|
|
8534
8571
|
const service = new _TwitterService();
|
|
8535
8572
|
service.runtime = runtime;
|
|
8573
|
+
try {
|
|
8574
|
+
await validateTwitterConfig(runtime);
|
|
8575
|
+
logger8.log("\u2705 Twitter configuration validated successfully");
|
|
8576
|
+
service.twitterClient = new TwitterClientInstance(runtime, {});
|
|
8577
|
+
await service.twitterClient.client.init();
|
|
8578
|
+
if (service.twitterClient.post) {
|
|
8579
|
+
logger8.log("\u{1F4EE} Starting Twitter post client...");
|
|
8580
|
+
await service.twitterClient.post.start();
|
|
8581
|
+
}
|
|
8582
|
+
if (service.twitterClient.interaction) {
|
|
8583
|
+
logger8.log("\u{1F4AC} Starting Twitter interaction client...");
|
|
8584
|
+
await service.twitterClient.interaction.start();
|
|
8585
|
+
}
|
|
8586
|
+
if (service.twitterClient.timeline) {
|
|
8587
|
+
logger8.log("\u{1F4CA} Starting Twitter timeline client...");
|
|
8588
|
+
await service.twitterClient.timeline.start();
|
|
8589
|
+
}
|
|
8590
|
+
if (service.twitterClient.discovery) {
|
|
8591
|
+
logger8.log("\u{1F50D} Starting Twitter discovery client...");
|
|
8592
|
+
await service.twitterClient.discovery.start();
|
|
8593
|
+
}
|
|
8594
|
+
logger8.log("\u2705 Twitter service started successfully");
|
|
8595
|
+
} catch (error) {
|
|
8596
|
+
logger8.error("\u{1F6A8} Failed to start Twitter service:", error);
|
|
8597
|
+
throw error;
|
|
8598
|
+
}
|
|
8536
8599
|
return service;
|
|
8537
8600
|
}
|
|
8538
8601
|
async stop() {
|
|
8602
|
+
if (this.twitterClient?.post) {
|
|
8603
|
+
await this.twitterClient.post.stop();
|
|
8604
|
+
}
|
|
8605
|
+
if (this.twitterClient?.interaction) {
|
|
8606
|
+
await this.twitterClient.interaction.stop();
|
|
8607
|
+
}
|
|
8608
|
+
if (this.twitterClient?.timeline) {
|
|
8609
|
+
await this.twitterClient.timeline.stop();
|
|
8610
|
+
}
|
|
8611
|
+
if (this.twitterClient?.discovery) {
|
|
8612
|
+
await this.twitterClient.discovery.stop();
|
|
8613
|
+
}
|
|
8614
|
+
logger8.log("Twitter service stopped");
|
|
8539
8615
|
}
|
|
8540
8616
|
};
|
|
8541
8617
|
_TwitterService.serviceType = "twitter";
|
|
@@ -8543,27 +8619,27 @@ var TwitterService = _TwitterService;
|
|
|
8543
8619
|
|
|
8544
8620
|
// src/actions/postTweet.ts
|
|
8545
8621
|
import {
|
|
8546
|
-
logger as
|
|
8622
|
+
logger as logger9,
|
|
8547
8623
|
ModelType as ModelType4
|
|
8548
8624
|
} from "@elizaos/core";
|
|
8549
8625
|
var postTweetAction = {
|
|
8550
8626
|
name: "POST_TWEET",
|
|
8551
8627
|
similes: ["TWEET", "SEND_TWEET", "TWITTER_POST", "POST_ON_TWITTER", "SHARE_ON_TWITTER"],
|
|
8552
8628
|
validate: async (runtime, message) => {
|
|
8553
|
-
|
|
8629
|
+
logger9.debug("Validating POST_TWEET action");
|
|
8554
8630
|
const text = message.content?.text?.trim();
|
|
8555
8631
|
if (!text || text.length === 0) {
|
|
8556
|
-
|
|
8632
|
+
logger9.error("No text content for tweet");
|
|
8557
8633
|
return false;
|
|
8558
8634
|
}
|
|
8559
8635
|
if (text.length > 280) {
|
|
8560
|
-
|
|
8636
|
+
logger9.warn(`Tweet too long: ${text.length} characters`);
|
|
8561
8637
|
}
|
|
8562
8638
|
return true;
|
|
8563
8639
|
},
|
|
8564
8640
|
description: "Post a tweet on Twitter",
|
|
8565
8641
|
handler: async (runtime, message, state, _options, callback) => {
|
|
8566
|
-
|
|
8642
|
+
logger9.info("Executing POST_TWEET action");
|
|
8567
8643
|
try {
|
|
8568
8644
|
const client = new ClientBase(runtime, {});
|
|
8569
8645
|
if (!client.twitterClient) {
|
|
@@ -8610,7 +8686,7 @@ Tweet:`;
|
|
|
8610
8686
|
tweetId = Date.now().toString();
|
|
8611
8687
|
}
|
|
8612
8688
|
const tweetUrl = `https://twitter.com/${client.profile.username}/status/${tweetId}`;
|
|
8613
|
-
|
|
8689
|
+
logger9.info(`Successfully posted tweet: ${tweetId}`);
|
|
8614
8690
|
await runtime.createMemory({
|
|
8615
8691
|
entityId: runtime.agentId,
|
|
8616
8692
|
content: {
|
|
@@ -8637,7 +8713,7 @@ View it here: ${tweetUrl}`,
|
|
|
8637
8713
|
throw new Error("Failed to post tweet - no response data");
|
|
8638
8714
|
}
|
|
8639
8715
|
} catch (error) {
|
|
8640
|
-
|
|
8716
|
+
logger9.error("Error posting tweet:", error);
|
|
8641
8717
|
if (callback) {
|
|
8642
8718
|
await callback({
|
|
8643
8719
|
text: `Sorry, I couldn't post the tweet. Error: ${error.message}`,
|
|
@@ -8697,91 +8773,37 @@ View it here: ${tweetUrl}`,
|
|
|
8697
8773
|
};
|
|
8698
8774
|
|
|
8699
8775
|
// src/index.ts
|
|
8700
|
-
var TwitterClientInstance = class {
|
|
8701
|
-
constructor(runtime, state) {
|
|
8702
|
-
this.client = new ClientBase(runtime, state);
|
|
8703
|
-
const getSetting3 = (key) => {
|
|
8704
|
-
if (runtime && typeof runtime.getSetting === "function") {
|
|
8705
|
-
return runtime.getSetting(key);
|
|
8706
|
-
}
|
|
8707
|
-
return void 0;
|
|
8708
|
-
};
|
|
8709
|
-
const postEnabledSetting = getSetting3("TWITTER_ENABLE_POST") ?? process.env.TWITTER_ENABLE_POST;
|
|
8710
|
-
logger9.debug(`TWITTER_ENABLE_POST setting value: ${JSON.stringify(postEnabledSetting)}, type: ${typeof postEnabledSetting}`);
|
|
8711
|
-
const postEnabled = postEnabledSetting === "true" || postEnabledSetting === true;
|
|
8712
|
-
if (postEnabled) {
|
|
8713
|
-
logger9.info("Twitter posting is ENABLED - creating post client");
|
|
8714
|
-
this.post = new TwitterPostClient(this.client, runtime, state);
|
|
8715
|
-
} else {
|
|
8716
|
-
logger9.info("Twitter posting is DISABLED - set TWITTER_ENABLE_POST=true to enable automatic posting");
|
|
8717
|
-
}
|
|
8718
|
-
const repliesEnabled = (getSetting3("TWITTER_ENABLE_REPLIES") ?? process.env.TWITTER_ENABLE_REPLIES) !== "false";
|
|
8719
|
-
if (repliesEnabled) {
|
|
8720
|
-
logger9.info("Twitter replies/interactions are ENABLED");
|
|
8721
|
-
this.interaction = new TwitterInteractionClient(
|
|
8722
|
-
this.client,
|
|
8723
|
-
runtime,
|
|
8724
|
-
state
|
|
8725
|
-
);
|
|
8726
|
-
} else {
|
|
8727
|
-
logger9.info("Twitter replies/interactions are DISABLED");
|
|
8728
|
-
}
|
|
8729
|
-
const actionsEnabled = (getSetting3("TWITTER_ENABLE_ACTIONS") ?? process.env.TWITTER_ENABLE_ACTIONS) === "true";
|
|
8730
|
-
if (actionsEnabled) {
|
|
8731
|
-
logger9.info("Twitter timeline actions are ENABLED");
|
|
8732
|
-
this.timeline = new TwitterTimelineClient(this.client, runtime, state);
|
|
8733
|
-
} else {
|
|
8734
|
-
logger9.info("Twitter timeline actions are DISABLED");
|
|
8735
|
-
}
|
|
8736
|
-
const discoveryEnabled = (getSetting3("TWITTER_ENABLE_DISCOVERY") ?? process.env.TWITTER_ENABLE_DISCOVERY) === "true" || actionsEnabled && (getSetting3("TWITTER_ENABLE_DISCOVERY") ?? process.env.TWITTER_ENABLE_DISCOVERY) !== "false";
|
|
8737
|
-
if (discoveryEnabled) {
|
|
8738
|
-
logger9.info("Twitter discovery service is ENABLED");
|
|
8739
|
-
this.discovery = new TwitterDiscoveryClient(this.client, runtime, state);
|
|
8740
|
-
} else {
|
|
8741
|
-
logger9.info("Twitter discovery service is DISABLED - set TWITTER_ENABLE_DISCOVERY=true to enable");
|
|
8742
|
-
}
|
|
8743
|
-
}
|
|
8744
|
-
};
|
|
8745
|
-
async function startTwitterClient(runtime) {
|
|
8746
|
-
try {
|
|
8747
|
-
logger9.log("\u{1F527} Initializing Twitter plugin...");
|
|
8748
|
-
await validateTwitterConfig(runtime);
|
|
8749
|
-
logger9.log("\u2705 Twitter configuration validated successfully");
|
|
8750
|
-
const twitterClient = new TwitterClientInstance(runtime, {});
|
|
8751
|
-
await twitterClient.client.init();
|
|
8752
|
-
await runtime.registerService(TwitterService);
|
|
8753
|
-
if (twitterClient.post) {
|
|
8754
|
-
logger9.log("\u{1F4EE} Starting Twitter post client...");
|
|
8755
|
-
await twitterClient.post.start();
|
|
8756
|
-
}
|
|
8757
|
-
if (twitterClient.interaction) {
|
|
8758
|
-
logger9.log("\u{1F4AC} Starting Twitter interaction client...");
|
|
8759
|
-
await twitterClient.interaction.start();
|
|
8760
|
-
}
|
|
8761
|
-
if (twitterClient.timeline) {
|
|
8762
|
-
logger9.log("\u{1F4CA} Starting Twitter timeline client...");
|
|
8763
|
-
await twitterClient.timeline.start();
|
|
8764
|
-
}
|
|
8765
|
-
if (twitterClient.discovery) {
|
|
8766
|
-
logger9.log("\u{1F50D} Starting Twitter discovery client...");
|
|
8767
|
-
await twitterClient.discovery.start();
|
|
8768
|
-
}
|
|
8769
|
-
logger9.log("\u2705 Twitter plugin started successfully");
|
|
8770
|
-
} catch (error) {
|
|
8771
|
-
logger9.error("\u{1F6A8} Failed to start Twitter plugin:", error);
|
|
8772
|
-
throw error;
|
|
8773
|
-
}
|
|
8774
|
-
}
|
|
8775
8776
|
var TwitterPlugin = {
|
|
8776
8777
|
name: "twitter",
|
|
8777
8778
|
description: "Twitter client with posting, interactions, and timeline actions",
|
|
8778
8779
|
actions: [postTweetAction],
|
|
8779
8780
|
services: [TwitterService],
|
|
8780
|
-
init:
|
|
8781
|
+
init: async (_config, runtime) => {
|
|
8782
|
+
logger10.log("\u{1F527} Initializing Twitter plugin...");
|
|
8783
|
+
const hasGetSetting = runtime && typeof runtime.getSetting === "function";
|
|
8784
|
+
const apiKey = hasGetSetting ? runtime.getSetting("TWITTER_API_KEY") : process.env.TWITTER_API_KEY;
|
|
8785
|
+
const apiSecretKey = hasGetSetting ? runtime.getSetting("TWITTER_API_SECRET_KEY") : process.env.TWITTER_API_SECRET_KEY;
|
|
8786
|
+
const accessToken = hasGetSetting ? runtime.getSetting("TWITTER_ACCESS_TOKEN") : process.env.TWITTER_ACCESS_TOKEN;
|
|
8787
|
+
const accessTokenSecret = hasGetSetting ? runtime.getSetting("TWITTER_ACCESS_TOKEN_SECRET") : process.env.TWITTER_ACCESS_TOKEN_SECRET;
|
|
8788
|
+
if (!apiKey || !apiSecretKey || !accessToken || !accessTokenSecret) {
|
|
8789
|
+
const missing = [];
|
|
8790
|
+
if (!apiKey) missing.push("TWITTER_API_KEY");
|
|
8791
|
+
if (!apiSecretKey) missing.push("TWITTER_API_SECRET_KEY");
|
|
8792
|
+
if (!accessToken) missing.push("TWITTER_ACCESS_TOKEN");
|
|
8793
|
+
if (!accessTokenSecret) missing.push("TWITTER_ACCESS_TOKEN_SECRET");
|
|
8794
|
+
logger10.warn(
|
|
8795
|
+
`Twitter API credentials not configured - Twitter functionality will be limited. Missing: ${missing.join(", ")}`
|
|
8796
|
+
);
|
|
8797
|
+
logger10.warn(
|
|
8798
|
+
"To enable Twitter functionality, please provide the missing credentials in your .env file"
|
|
8799
|
+
);
|
|
8800
|
+
} else {
|
|
8801
|
+
logger10.log("\u2705 Twitter credentials found");
|
|
8802
|
+
}
|
|
8803
|
+
}
|
|
8781
8804
|
};
|
|
8782
8805
|
var index_default = TwitterPlugin;
|
|
8783
8806
|
export {
|
|
8784
|
-
TwitterClientInstance,
|
|
8785
8807
|
TwitterPlugin,
|
|
8786
8808
|
index_default as default
|
|
8787
8809
|
};
|