@elizaos/plugin-twitter 1.0.0-alpha.63 → 1.0.0-alpha.65
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.js +460 -919
- package/dist/index.js.map +1 -1
- package/dist/{node-GVRE5HAO.js → node-IZDTQWG6.js} +1 -1
- package/dist/node-IZDTQWG6.js.map +1 -0
- package/package.json +56 -53
- package/dist/node-GVRE5HAO.js.map +0 -1
package/dist/index.js
CHANGED
|
@@ -1,16 +1,16 @@
|
|
|
1
1
|
// src/index.ts
|
|
2
2
|
import {
|
|
3
3
|
ChannelType as ChannelType7,
|
|
4
|
-
|
|
4
|
+
EventType as EventType4,
|
|
5
5
|
Role,
|
|
6
6
|
Service,
|
|
7
7
|
createUniqueUuid as createUniqueUuid8,
|
|
8
|
-
logger as
|
|
8
|
+
logger as logger10
|
|
9
9
|
} from "@elizaos/core";
|
|
10
10
|
|
|
11
11
|
// src/actions/spaceJoin.ts
|
|
12
12
|
import {
|
|
13
|
-
logger as
|
|
13
|
+
logger as logger5,
|
|
14
14
|
stringToUuid
|
|
15
15
|
} from "@elizaos/core";
|
|
16
16
|
|
|
@@ -19,7 +19,7 @@ import {
|
|
|
19
19
|
ChannelType as ChannelType3,
|
|
20
20
|
ModelType as ModelType3,
|
|
21
21
|
createUniqueUuid as createUniqueUuid3,
|
|
22
|
-
logger as
|
|
22
|
+
logger as logger4
|
|
23
23
|
} from "@elizaos/core";
|
|
24
24
|
|
|
25
25
|
// src/client/api.ts
|
|
@@ -82,7 +82,7 @@ var Platform = class _Platform {
|
|
|
82
82
|
*/
|
|
83
83
|
static async importPlatform() {
|
|
84
84
|
if (PLATFORM_NODE) {
|
|
85
|
-
const { platform } = await import("./node-
|
|
85
|
+
const { platform } = await import("./node-IZDTQWG6.js");
|
|
86
86
|
return platform;
|
|
87
87
|
}
|
|
88
88
|
return genericPlatform;
|
|
@@ -272,10 +272,7 @@ import { CookieJar } from "tough-cookie";
|
|
|
272
272
|
import { TwitterApi } from "twitter-api-v2";
|
|
273
273
|
function withTransform(fetchFn, transform) {
|
|
274
274
|
return async (input, init) => {
|
|
275
|
-
const fetchArgs = await transform?.request?.(input, init) ?? [
|
|
276
|
-
input,
|
|
277
|
-
init
|
|
278
|
-
];
|
|
275
|
+
const fetchArgs = await transform?.request?.(input, init) ?? [input, init];
|
|
279
276
|
const res = await fetchFn(...fetchArgs);
|
|
280
277
|
return await transform?.response?.(res) ?? res;
|
|
281
278
|
};
|
|
@@ -475,10 +472,7 @@ async function getProfile(username, auth) {
|
|
|
475
472
|
responsive_web_graphql_timeline_navigation_enabled: true
|
|
476
473
|
}) ?? ""
|
|
477
474
|
);
|
|
478
|
-
params.set(
|
|
479
|
-
"fieldToggles",
|
|
480
|
-
stringify({ withAuxiliaryUserLabels: false }) ?? ""
|
|
481
|
-
);
|
|
475
|
+
params.set("fieldToggles", stringify({ withAuxiliaryUserLabels: false }) ?? "");
|
|
482
476
|
const res = await requestApi(
|
|
483
477
|
`https://twitter.com/i/api/graphql/G3KGOASz96M-Qu0nwmGXNg/UserByScreenName?${params.toString()}`,
|
|
484
478
|
auth
|
|
@@ -571,9 +565,7 @@ async function getScreenNameByUserId(userId, auth) {
|
|
|
571
565
|
if (legacy.screen_name == null || legacy.screen_name.length === 0) {
|
|
572
566
|
return {
|
|
573
567
|
success: false,
|
|
574
|
-
err: new Error(
|
|
575
|
-
`Either user with ID ${userId} does not exist or is private.`
|
|
576
|
-
)
|
|
568
|
+
err: new Error(`Either user with ID ${userId} does not exist or is private.`)
|
|
577
569
|
};
|
|
578
570
|
}
|
|
579
571
|
return {
|
|
@@ -641,10 +633,7 @@ var TwitterUserAuth = class extends TwitterGuestAuth {
|
|
|
641
633
|
} else if (next.subtask.subtask_id === "LoginEnterUserIdentifierSSO") {
|
|
642
634
|
next = await this.handleEnterUserIdentifierSSO(next, username);
|
|
643
635
|
} else if (next.subtask.subtask_id === "LoginEnterAlternateIdentifierSubtask") {
|
|
644
|
-
next = await this.handleEnterAlternateIdentifierSubtask(
|
|
645
|
-
next,
|
|
646
|
-
email
|
|
647
|
-
);
|
|
636
|
+
next = await this.handleEnterAlternateIdentifierSubtask(next, email);
|
|
648
637
|
} else if (next.subtask.subtask_id === "LoginEnterPassword") {
|
|
649
638
|
next = await this.handleEnterPassword(next, password);
|
|
650
639
|
} else if (next.subtask.subtask_id === "AccountDuplicationCheck") {
|
|
@@ -653,9 +642,7 @@ var TwitterUserAuth = class extends TwitterGuestAuth {
|
|
|
653
642
|
if (twoFactorSecret) {
|
|
654
643
|
next = await this.handleTwoFactorAuthChallenge(next, twoFactorSecret);
|
|
655
644
|
} else {
|
|
656
|
-
throw new Error(
|
|
657
|
-
"Requested two factor authentication code but no secret provided"
|
|
658
|
-
);
|
|
645
|
+
throw new Error("Requested two factor authentication code but no secret provided");
|
|
659
646
|
}
|
|
660
647
|
} else if (next.subtask.subtask_id === "LoginAcid") {
|
|
661
648
|
next = await this.handleAcid(next, email);
|
|
@@ -676,11 +663,7 @@ var TwitterUserAuth = class extends TwitterGuestAuth {
|
|
|
676
663
|
if (!this.isLoggedIn()) {
|
|
677
664
|
return;
|
|
678
665
|
}
|
|
679
|
-
await requestApi(
|
|
680
|
-
"https://api.twitter.com/1.1/account/logout.json",
|
|
681
|
-
this,
|
|
682
|
-
"POST"
|
|
683
|
-
);
|
|
666
|
+
await requestApi("https://api.twitter.com/1.1/account/logout.json", this, "POST");
|
|
684
667
|
this.deleteToken();
|
|
685
668
|
this.jar = new CookieJar2();
|
|
686
669
|
}
|
|
@@ -875,9 +858,7 @@ var TwitterUserAuth = class extends TwitterGuestAuth {
|
|
|
875
858
|
if (flow.errors?.length) {
|
|
876
859
|
return {
|
|
877
860
|
status: "error",
|
|
878
|
-
err: new Error(
|
|
879
|
-
`Authentication error (${flow.errors[0].code}): ${flow.errors[0].message}`
|
|
880
|
-
)
|
|
861
|
+
err: new Error(`Authentication error (${flow.errors[0].code}): ${flow.errors[0].message}`)
|
|
881
862
|
};
|
|
882
863
|
}
|
|
883
864
|
if (typeof flow.flow_token !== "string") {
|
|
@@ -965,10 +946,7 @@ async function grokChat(options, auth) {
|
|
|
965
946
|
return {
|
|
966
947
|
conversationId,
|
|
967
948
|
message: firstChunk.result.message,
|
|
968
|
-
messages: [
|
|
969
|
-
...messages,
|
|
970
|
-
{ role: "assistant", content: firstChunk.result.message }
|
|
971
|
-
],
|
|
949
|
+
messages: [...messages, { role: "assistant", content: firstChunk.result.message }],
|
|
972
950
|
rateLimit: {
|
|
973
951
|
isRateLimited: true,
|
|
974
952
|
message: firstChunk.result.message,
|
|
@@ -998,19 +976,17 @@ function parseDirectMessageConversations(data, userId) {
|
|
|
998
976
|
const conversations = inboxState?.conversations || {};
|
|
999
977
|
const entries = inboxState?.entries || [];
|
|
1000
978
|
const users = inboxState?.users || {};
|
|
1001
|
-
const parsedUsers = Object.values(users).map(
|
|
1002
|
-
|
|
1003
|
-
|
|
1004
|
-
|
|
1005
|
-
|
|
1006
|
-
|
|
1007
|
-
|
|
1008
|
-
|
|
1009
|
-
|
|
1010
|
-
|
|
1011
|
-
|
|
1012
|
-
})
|
|
1013
|
-
);
|
|
979
|
+
const parsedUsers = Object.values(users).map((user) => ({
|
|
980
|
+
id: user.id_str,
|
|
981
|
+
screenName: user.screen_name,
|
|
982
|
+
name: user.name,
|
|
983
|
+
profileImageUrl: user.profile_image_url_https,
|
|
984
|
+
description: user.description,
|
|
985
|
+
verified: user.verified,
|
|
986
|
+
protected: user.protected,
|
|
987
|
+
followersCount: user.followers_count,
|
|
988
|
+
friendsCount: user.friends_count
|
|
989
|
+
}));
|
|
1014
990
|
const messagesByConversation = {};
|
|
1015
991
|
entries.forEach((entry) => {
|
|
1016
992
|
if (entry.message) {
|
|
@@ -1177,11 +1153,7 @@ async function* getUserTimeline(query, maxProfiles, fetchFunc) {
|
|
|
1177
1153
|
let cursor = void 0;
|
|
1178
1154
|
let consecutiveEmptyBatches = 0;
|
|
1179
1155
|
while (nProfiles < maxProfiles) {
|
|
1180
|
-
const batch = await fetchFunc(
|
|
1181
|
-
query,
|
|
1182
|
-
maxProfiles,
|
|
1183
|
-
cursor
|
|
1184
|
-
);
|
|
1156
|
+
const batch = await fetchFunc(query, maxProfiles, cursor);
|
|
1185
1157
|
const { profiles, next } = batch;
|
|
1186
1158
|
cursor = next;
|
|
1187
1159
|
if (profiles.length === 0) {
|
|
@@ -1200,11 +1172,7 @@ async function* getTweetTimeline(query, maxTweets, fetchFunc) {
|
|
|
1200
1172
|
let nTweets = 0;
|
|
1201
1173
|
let cursor = void 0;
|
|
1202
1174
|
while (nTweets < maxTweets) {
|
|
1203
|
-
const batch = await fetchFunc(
|
|
1204
|
-
query,
|
|
1205
|
-
maxTweets,
|
|
1206
|
-
cursor
|
|
1207
|
-
);
|
|
1175
|
+
const batch = await fetchFunc(query, maxTweets, cursor);
|
|
1208
1176
|
const { tweets, next } = batch;
|
|
1209
1177
|
if (tweets.length === 0) {
|
|
1210
1178
|
break;
|
|
@@ -1243,10 +1211,7 @@ function parseRelationshipTimeline(timeline) {
|
|
|
1243
1211
|
if (itemContent?.userDisplayType === "User") {
|
|
1244
1212
|
const userResultRaw = itemContent.user_results?.result;
|
|
1245
1213
|
if (userResultRaw?.legacy) {
|
|
1246
|
-
const profile = parseProfile(
|
|
1247
|
-
userResultRaw.legacy,
|
|
1248
|
-
userResultRaw.is_blue_verified
|
|
1249
|
-
);
|
|
1214
|
+
const profile = parseProfile(userResultRaw.legacy, userResultRaw.is_blue_verified);
|
|
1250
1215
|
if (!profile.userId) {
|
|
1251
1216
|
profile.userId = userResultRaw.rest_id;
|
|
1252
1217
|
}
|
|
@@ -1275,21 +1240,11 @@ function getFollowers(userId, maxProfiles, auth) {
|
|
|
1275
1240
|
});
|
|
1276
1241
|
}
|
|
1277
1242
|
async function fetchProfileFollowing(userId, maxProfiles, auth, cursor) {
|
|
1278
|
-
const timeline = await getFollowingTimeline(
|
|
1279
|
-
userId,
|
|
1280
|
-
maxProfiles,
|
|
1281
|
-
auth,
|
|
1282
|
-
cursor
|
|
1283
|
-
);
|
|
1243
|
+
const timeline = await getFollowingTimeline(userId, maxProfiles, auth, cursor);
|
|
1284
1244
|
return parseRelationshipTimeline(timeline);
|
|
1285
1245
|
}
|
|
1286
1246
|
async function fetchProfileFollowers(userId, maxProfiles, auth, cursor) {
|
|
1287
|
-
const timeline = await getFollowersTimeline(
|
|
1288
|
-
userId,
|
|
1289
|
-
maxProfiles,
|
|
1290
|
-
auth,
|
|
1291
|
-
cursor
|
|
1292
|
-
);
|
|
1247
|
+
const timeline = await getFollowersTimeline(userId, maxProfiles, auth, cursor);
|
|
1293
1248
|
return parseRelationshipTimeline(timeline);
|
|
1294
1249
|
}
|
|
1295
1250
|
async function getFollowingTimeline(userId, maxItems, auth, cursor) {
|
|
@@ -1380,19 +1335,13 @@ async function followUser(username, auth) {
|
|
|
1380
1335
|
"X-Twitter-Client-Language": "en",
|
|
1381
1336
|
Authorization: `Bearer ${bearerToken}`
|
|
1382
1337
|
});
|
|
1383
|
-
await auth.installTo(
|
|
1338
|
+
await auth.installTo(headers, "https://api.twitter.com/1.1/friendships/create.json");
|
|
1339
|
+
const res = await auth.fetch("https://api.twitter.com/1.1/friendships/create.json", {
|
|
1340
|
+
method: "POST",
|
|
1384
1341
|
headers,
|
|
1385
|
-
|
|
1386
|
-
|
|
1387
|
-
|
|
1388
|
-
"https://api.twitter.com/1.1/friendships/create.json",
|
|
1389
|
-
{
|
|
1390
|
-
method: "POST",
|
|
1391
|
-
headers,
|
|
1392
|
-
body: new URLSearchParams(requestBody).toString(),
|
|
1393
|
-
credentials: "include"
|
|
1394
|
-
}
|
|
1395
|
-
);
|
|
1342
|
+
body: new URLSearchParams(requestBody).toString(),
|
|
1343
|
+
credentials: "include"
|
|
1344
|
+
});
|
|
1396
1345
|
if (!res.ok) {
|
|
1397
1346
|
throw new Error(`Failed to follow user: ${res.statusText}`);
|
|
1398
1347
|
}
|
|
@@ -1487,22 +1436,13 @@ function reconstructTweetHtml(tweet, photos, videos) {
|
|
|
1487
1436
|
return html;
|
|
1488
1437
|
}
|
|
1489
1438
|
function linkHashtagHtml(hashtag) {
|
|
1490
|
-
return `<a href="https://twitter.com/hashtag/${hashtag.replace(
|
|
1491
|
-
"#",
|
|
1492
|
-
""
|
|
1493
|
-
)}">${hashtag}</a>`;
|
|
1439
|
+
return `<a href="https://twitter.com/hashtag/${hashtag.replace("#", "")}">${hashtag}</a>`;
|
|
1494
1440
|
}
|
|
1495
1441
|
function linkCashtagHtml(cashtag) {
|
|
1496
|
-
return `<a href="https://twitter.com/search?q=%24${cashtag.replace(
|
|
1497
|
-
"$",
|
|
1498
|
-
""
|
|
1499
|
-
)}">${cashtag}</a>`;
|
|
1442
|
+
return `<a href="https://twitter.com/search?q=%24${cashtag.replace("$", "")}">${cashtag}</a>`;
|
|
1500
1443
|
}
|
|
1501
1444
|
function linkUsernameHtml(username) {
|
|
1502
|
-
return `<a href="https://twitter.com/${username.replace(
|
|
1503
|
-
"@",
|
|
1504
|
-
""
|
|
1505
|
-
)}">${username}</a>`;
|
|
1445
|
+
return `<a href="https://twitter.com/${username.replace("@", "")}">${username}</a>`;
|
|
1506
1446
|
}
|
|
1507
1447
|
function unwrapTcoUrlHtml(tweet, foundedMedia) {
|
|
1508
1448
|
return (tco) => {
|
|
@@ -1547,9 +1487,7 @@ function parseLegacyTweet(user, tweet) {
|
|
|
1547
1487
|
const hashtags = tweet.entities?.hashtags ?? [];
|
|
1548
1488
|
const mentions = tweet.entities?.user_mentions ?? [];
|
|
1549
1489
|
const media = tweet.extended_entities?.media ?? [];
|
|
1550
|
-
const pinnedTweets = new Set(
|
|
1551
|
-
user.pinned_tweet_ids_str ?? []
|
|
1552
|
-
);
|
|
1490
|
+
const pinnedTweets = new Set(user.pinned_tweet_ids_str ?? []);
|
|
1553
1491
|
const urls = tweet.entities?.urls ?? [];
|
|
1554
1492
|
const { photos, videos, sensitiveContent } = parseMediaGroups(media);
|
|
1555
1493
|
const tw = {
|
|
@@ -1630,10 +1568,7 @@ function parseResult(result) {
|
|
|
1630
1568
|
if (result?.legacy && noteTweetResultText) {
|
|
1631
1569
|
result.legacy.full_text = noteTweetResultText;
|
|
1632
1570
|
}
|
|
1633
|
-
const tweetResult = parseLegacyTweet(
|
|
1634
|
-
result?.core?.user_results?.result?.legacy,
|
|
1635
|
-
result?.legacy
|
|
1636
|
-
);
|
|
1571
|
+
const tweetResult = parseLegacyTweet(result?.core?.user_results?.result?.legacy, result?.legacy);
|
|
1637
1572
|
if (!tweetResult.success) {
|
|
1638
1573
|
return tweetResult;
|
|
1639
1574
|
}
|
|
@@ -1694,8 +1629,7 @@ function parseTimelineTweetsV2(timeline) {
|
|
|
1694
1629
|
function parseTimelineEntryItemContentRaw(content, entryId, isConversation = false) {
|
|
1695
1630
|
let result = content.tweet_results?.result ?? content.tweetResult?.result;
|
|
1696
1631
|
if (result?.__typename === "Tweet" || result?.__typename === "TweetWithVisibilityResults" && result?.tweet) {
|
|
1697
|
-
if (result?.__typename === "TweetWithVisibilityResults")
|
|
1698
|
-
result = result.tweet;
|
|
1632
|
+
if (result?.__typename === "TweetWithVisibilityResults") result = result.tweet;
|
|
1699
1633
|
if (result?.legacy) {
|
|
1700
1634
|
result.legacy.id_str = result.rest_id ?? entryId.replace("conversation-", "").replace("tweet-", "");
|
|
1701
1635
|
}
|
|
@@ -1712,11 +1646,7 @@ function parseTimelineEntryItemContentRaw(content, entryId, isConversation = fal
|
|
|
1712
1646
|
return null;
|
|
1713
1647
|
}
|
|
1714
1648
|
function parseAndPush(tweets, content, entryId, isConversation = false) {
|
|
1715
|
-
const tweet = parseTimelineEntryItemContentRaw(
|
|
1716
|
-
content,
|
|
1717
|
-
entryId,
|
|
1718
|
-
isConversation
|
|
1719
|
-
);
|
|
1649
|
+
const tweet = parseTimelineEntryItemContentRaw(content, entryId, isConversation);
|
|
1720
1650
|
if (tweet) {
|
|
1721
1651
|
tweets.push(tweet);
|
|
1722
1652
|
}
|
|
@@ -1847,10 +1777,7 @@ function parseSearchTimelineUsers(timeline) {
|
|
|
1847
1777
|
if (itemContent?.userDisplayType === "User") {
|
|
1848
1778
|
const userResultRaw = itemContent.user_results?.result;
|
|
1849
1779
|
if (userResultRaw?.legacy) {
|
|
1850
|
-
const profile = parseProfile(
|
|
1851
|
-
userResultRaw.legacy,
|
|
1852
|
-
userResultRaw.is_blue_verified
|
|
1853
|
-
);
|
|
1780
|
+
const profile = parseProfile(userResultRaw.legacy, userResultRaw.is_blue_verified);
|
|
1854
1781
|
if (!profile.userId) {
|
|
1855
1782
|
profile.userId = userResultRaw.rest_id;
|
|
1856
1783
|
}
|
|
@@ -1879,23 +1806,11 @@ function searchProfiles(query, maxProfiles, auth) {
|
|
|
1879
1806
|
});
|
|
1880
1807
|
}
|
|
1881
1808
|
async function fetchSearchTweets(query, maxTweets, searchMode, auth, cursor) {
|
|
1882
|
-
const timeline = await getSearchTimeline(
|
|
1883
|
-
query,
|
|
1884
|
-
maxTweets,
|
|
1885
|
-
searchMode,
|
|
1886
|
-
auth,
|
|
1887
|
-
cursor
|
|
1888
|
-
);
|
|
1809
|
+
const timeline = await getSearchTimeline(query, maxTweets, searchMode, auth, cursor);
|
|
1889
1810
|
return parseSearchTimelineTweets(timeline);
|
|
1890
1811
|
}
|
|
1891
1812
|
async function fetchSearchProfiles(query, maxProfiles, auth, cursor) {
|
|
1892
|
-
const timeline = await getSearchTimeline(
|
|
1893
|
-
query,
|
|
1894
|
-
maxProfiles,
|
|
1895
|
-
4 /* Users */,
|
|
1896
|
-
auth,
|
|
1897
|
-
cursor
|
|
1898
|
-
);
|
|
1813
|
+
const timeline = await getSearchTimeline(query, maxProfiles, 4 /* Users */, auth, cursor);
|
|
1899
1814
|
return parseSearchTimelineUsers(timeline);
|
|
1900
1815
|
}
|
|
1901
1816
|
async function getSearchTimeline(query, maxItems, searchMode, auth, cursor) {
|
|
@@ -2123,9 +2038,7 @@ async function fetchBrowseSpaceTopics(auth) {
|
|
|
2123
2038
|
if (data.errors && data.errors.length > 0) {
|
|
2124
2039
|
throw new Error(`API Errors: ${JSON.stringify(data.errors)}`);
|
|
2125
2040
|
}
|
|
2126
|
-
return data.data.browse_space_topics.categories.flatMap(
|
|
2127
|
-
(category) => category.subtopics
|
|
2128
|
-
);
|
|
2041
|
+
return data.data.browse_space_topics.categories.flatMap((category) => category.subtopics);
|
|
2129
2042
|
}
|
|
2130
2043
|
async function fetchCommunitySelectQuery(auth) {
|
|
2131
2044
|
const queryId = "Lue1DfmoW2cc0225t_8z1w";
|
|
@@ -2155,9 +2068,7 @@ async function fetchCommunitySelectQuery(auth) {
|
|
|
2155
2068
|
});
|
|
2156
2069
|
await updateCookieJar(auth.cookieJar(), response.headers);
|
|
2157
2070
|
if (!response.ok) {
|
|
2158
|
-
throw new Error(
|
|
2159
|
-
`Failed to fetch Community Select Query: ${await response.text()}`
|
|
2160
|
-
);
|
|
2071
|
+
throw new Error(`Failed to fetch Community Select Query: ${await response.text()}`);
|
|
2161
2072
|
}
|
|
2162
2073
|
const data = await response.json();
|
|
2163
2074
|
if (data.errors && data.errors.length > 0) {
|
|
@@ -2194,16 +2105,11 @@ async function fetchLiveVideoStreamStatus(mediaKey, auth) {
|
|
|
2194
2105
|
});
|
|
2195
2106
|
await updateCookieJar(auth.cookieJar(), response.headers);
|
|
2196
2107
|
if (!response.ok) {
|
|
2197
|
-
throw new Error(
|
|
2198
|
-
`Failed to fetch live video stream status: ${await response.text()}`
|
|
2199
|
-
);
|
|
2108
|
+
throw new Error(`Failed to fetch live video stream status: ${await response.text()}`);
|
|
2200
2109
|
}
|
|
2201
2110
|
return await response.json();
|
|
2202
2111
|
} catch (error) {
|
|
2203
|
-
console.error(
|
|
2204
|
-
`Error fetching live video stream status for mediaKey ${mediaKey}:`,
|
|
2205
|
-
error
|
|
2206
|
-
);
|
|
2112
|
+
console.error(`Error fetching live video stream status for mediaKey ${mediaKey}:`, error);
|
|
2207
2113
|
throw error;
|
|
2208
2114
|
}
|
|
2209
2115
|
}
|
|
@@ -2345,7 +2251,6 @@ async function fetchFollowingTimeline(count, seenTweetIds, auth) {
|
|
|
2345
2251
|
auth,
|
|
2346
2252
|
"GET"
|
|
2347
2253
|
);
|
|
2348
|
-
console.log("res", res);
|
|
2349
2254
|
if (!res.success) {
|
|
2350
2255
|
if (res.err instanceof ApiError) {
|
|
2351
2256
|
console.error("Error details:", res.err.data);
|
|
@@ -2663,10 +2568,7 @@ async function fetchTweets(userId, maxTweets, cursor, auth) {
|
|
|
2663
2568
|
if (cursor != null && cursor !== "") {
|
|
2664
2569
|
userTweetsRequest.variables.cursor = cursor;
|
|
2665
2570
|
}
|
|
2666
|
-
const res = await requestApi(
|
|
2667
|
-
userTweetsRequest.toRequestUrl(),
|
|
2668
|
-
auth
|
|
2669
|
-
);
|
|
2571
|
+
const res = await requestApi(userTweetsRequest.toRequestUrl(), auth);
|
|
2670
2572
|
if (!res.success) {
|
|
2671
2573
|
throw res.err;
|
|
2672
2574
|
}
|
|
@@ -2683,10 +2585,7 @@ async function fetchTweetsAndReplies(userId, maxTweets, cursor, auth) {
|
|
|
2683
2585
|
if (cursor != null && cursor !== "") {
|
|
2684
2586
|
userTweetsRequest.variables.cursor = cursor;
|
|
2685
2587
|
}
|
|
2686
|
-
const res = await requestApi(
|
|
2687
|
-
userTweetsRequest.toRequestUrl(),
|
|
2688
|
-
auth
|
|
2689
|
-
);
|
|
2588
|
+
const res = await requestApi(userTweetsRequest.toRequestUrl(), auth);
|
|
2690
2589
|
if (!res.success) {
|
|
2691
2590
|
throw res.err;
|
|
2692
2591
|
}
|
|
@@ -2724,12 +2623,7 @@ async function createCreateTweetRequestV2(text, auth, tweetId, options) {
|
|
|
2724
2623
|
if (options?.poll) {
|
|
2725
2624
|
optionsConfig = {
|
|
2726
2625
|
expansions: ["attachments.poll_ids"],
|
|
2727
|
-
pollFields: [
|
|
2728
|
-
"options",
|
|
2729
|
-
"duration_minutes",
|
|
2730
|
-
"end_datetime",
|
|
2731
|
-
"voting_status"
|
|
2732
|
-
]
|
|
2626
|
+
pollFields: ["options", "duration_minutes", "end_datetime", "voting_status"]
|
|
2733
2627
|
};
|
|
2734
2628
|
}
|
|
2735
2629
|
return await getTweetV2(tweetResponse.data.id, auth, optionsConfig);
|
|
@@ -2787,26 +2681,20 @@ function parseTweetV2ToV1(tweetV2, includes, defaultTweetData) {
|
|
|
2787
2681
|
parsedTweet.videos.push({
|
|
2788
2682
|
id: media.media_key,
|
|
2789
2683
|
preview: media.preview_image_url ?? "",
|
|
2790
|
-
url: media.variants?.find(
|
|
2791
|
-
(variant) => variant.content_type === "video/mp4"
|
|
2792
|
-
)?.url ?? ""
|
|
2684
|
+
url: media.variants?.find((variant) => variant.content_type === "video/mp4")?.url ?? ""
|
|
2793
2685
|
});
|
|
2794
2686
|
}
|
|
2795
2687
|
});
|
|
2796
2688
|
}
|
|
2797
2689
|
if (includes?.users?.length) {
|
|
2798
|
-
const user = includes.users.find(
|
|
2799
|
-
(user2) => user2.id === tweetV2.author_id
|
|
2800
|
-
);
|
|
2690
|
+
const user = includes.users.find((user2) => user2.id === tweetV2.author_id);
|
|
2801
2691
|
if (user) {
|
|
2802
2692
|
parsedTweet.username = user.username ?? defaultTweetData?.username ?? "";
|
|
2803
2693
|
parsedTweet.name = user.name ?? defaultTweetData?.name ?? "";
|
|
2804
2694
|
}
|
|
2805
2695
|
}
|
|
2806
2696
|
if (tweetV2?.geo?.place_id && includes?.places?.length) {
|
|
2807
|
-
const place = includes.places.find(
|
|
2808
|
-
(place2) => place2.id === tweetV2?.geo?.place_id
|
|
2809
|
-
);
|
|
2697
|
+
const place = includes.places.find((place2) => place2.id === tweetV2?.geo?.place_id);
|
|
2810
2698
|
if (place) {
|
|
2811
2699
|
parsedTweet.place = {
|
|
2812
2700
|
id: place.id,
|
|
@@ -2849,9 +2737,7 @@ async function createCreateTweetRequest(text, auth, tweetId, mediaData, hideLink
|
|
|
2849
2737
|
}
|
|
2850
2738
|
if (mediaData && mediaData.length > 0) {
|
|
2851
2739
|
const mediaIds = await Promise.all(
|
|
2852
|
-
mediaData.map(
|
|
2853
|
-
({ data, mediaType }) => uploadMedia(data, auth, mediaType)
|
|
2854
|
-
)
|
|
2740
|
+
mediaData.map(({ data, mediaType }) => uploadMedia(data, auth, mediaType))
|
|
2855
2741
|
);
|
|
2856
2742
|
variables.media.media_entities = mediaIds.map((id) => ({
|
|
2857
2743
|
media_id: id,
|
|
@@ -2941,9 +2827,7 @@ async function createCreateNoteTweetRequest(text, auth, tweetId, mediaData) {
|
|
|
2941
2827
|
};
|
|
2942
2828
|
if (mediaData && mediaData.length > 0) {
|
|
2943
2829
|
const mediaIds = await Promise.all(
|
|
2944
|
-
mediaData.map(
|
|
2945
|
-
({ data: data2, mediaType }) => uploadMedia(data2, auth, mediaType)
|
|
2946
|
-
)
|
|
2830
|
+
mediaData.map(({ data: data2, mediaType }) => uploadMedia(data2, auth, mediaType))
|
|
2947
2831
|
);
|
|
2948
2832
|
variables.media.media_entities = mediaIds.map((id) => ({
|
|
2949
2833
|
media_id: id,
|
|
@@ -3025,10 +2909,7 @@ async function fetchListTweets(listId, maxTweets, cursor, auth) {
|
|
|
3025
2909
|
if (cursor != null && cursor !== "") {
|
|
3026
2910
|
listTweetsRequest.variables.cursor = cursor;
|
|
3027
2911
|
}
|
|
3028
|
-
const res = await requestApi(
|
|
3029
|
-
listTweetsRequest.toRequestUrl(),
|
|
3030
|
-
auth
|
|
3031
|
-
);
|
|
2912
|
+
const res = await requestApi(listTweetsRequest.toRequestUrl(), auth);
|
|
3032
2913
|
if (!res.success) {
|
|
3033
2914
|
throw res.err;
|
|
3034
2915
|
}
|
|
@@ -3097,10 +2978,7 @@ async function getLatestTweet(user, includeRetweets, max, auth) {
|
|
|
3097
2978
|
async function getTweet(id, auth) {
|
|
3098
2979
|
const tweetDetailRequest = apiRequestFactory.createTweetDetailRequest();
|
|
3099
2980
|
tweetDetailRequest.variables.focalTweetId = id;
|
|
3100
|
-
const res = await requestApi(
|
|
3101
|
-
tweetDetailRequest.toRequestUrl(),
|
|
3102
|
-
auth
|
|
3103
|
-
);
|
|
2981
|
+
const res = await requestApi(tweetDetailRequest.toRequestUrl(), auth);
|
|
3104
2982
|
if (!res.success) {
|
|
3105
2983
|
throw res.err;
|
|
3106
2984
|
}
|
|
@@ -3129,11 +3007,7 @@ async function getTweetV2(id, auth, options = defaultOptions) {
|
|
|
3129
3007
|
return null;
|
|
3130
3008
|
}
|
|
3131
3009
|
const defaultTweetData = await getTweet(tweetData.data.id, auth);
|
|
3132
|
-
const parsedTweet = parseTweetV2ToV1(
|
|
3133
|
-
tweetData.data,
|
|
3134
|
-
tweetData?.includes,
|
|
3135
|
-
defaultTweetData
|
|
3136
|
-
);
|
|
3010
|
+
const parsedTweet = parseTweetV2ToV1(tweetData.data, tweetData?.includes, defaultTweetData);
|
|
3137
3011
|
return parsedTweet;
|
|
3138
3012
|
} catch (error) {
|
|
3139
3013
|
console.error(`Error fetching tweet ${id}:`, error);
|
|
@@ -3159,11 +3033,7 @@ async function getTweetsV2(ids, auth, options = defaultOptions) {
|
|
|
3159
3033
|
console.warn(`No tweet data found for IDs: ${ids.join(", ")}`);
|
|
3160
3034
|
return [];
|
|
3161
3035
|
}
|
|
3162
|
-
return (await Promise.all(
|
|
3163
|
-
tweetsV2.map(
|
|
3164
|
-
async (tweet) => await getTweetV2(tweet.id, auth, options)
|
|
3165
|
-
)
|
|
3166
|
-
)).filter((tweet) => tweet !== null);
|
|
3036
|
+
return (await Promise.all(tweetsV2.map(async (tweet) => await getTweetV2(tweet.id, auth, options)))).filter((tweet) => tweet !== null);
|
|
3167
3037
|
} catch (error) {
|
|
3168
3038
|
console.error(`Error fetching tweets for IDs: ${ids.join(", ")}`, error);
|
|
3169
3039
|
return [];
|
|
@@ -3269,13 +3139,10 @@ async function uploadMedia(mediaData, auth, mediaType) {
|
|
|
3269
3139
|
const statusParams = new URLSearchParams();
|
|
3270
3140
|
statusParams.append("command", "STATUS");
|
|
3271
3141
|
statusParams.append("media_id", mediaId);
|
|
3272
|
-
const statusResponse = await fetch(
|
|
3273
|
-
|
|
3274
|
-
|
|
3275
|
-
|
|
3276
|
-
headers
|
|
3277
|
-
}
|
|
3278
|
-
);
|
|
3142
|
+
const statusResponse = await fetch(`${uploadUrl}?${statusParams.toString()}`, {
|
|
3143
|
+
method: "GET",
|
|
3144
|
+
headers
|
|
3145
|
+
});
|
|
3279
3146
|
if (!statusResponse.ok) {
|
|
3280
3147
|
throw new Error(await statusResponse.text());
|
|
3281
3148
|
}
|
|
@@ -3315,9 +3182,7 @@ async function createQuoteTweetRequest(text, quotedTweetId, auth, mediaData) {
|
|
|
3315
3182
|
};
|
|
3316
3183
|
if (mediaData && mediaData.length > 0) {
|
|
3317
3184
|
const mediaIds = await Promise.all(
|
|
3318
|
-
mediaData.map(
|
|
3319
|
-
({ data, mediaType }) => uploadMedia(data, auth, mediaType)
|
|
3320
|
-
)
|
|
3185
|
+
mediaData.map(({ data, mediaType }) => uploadMedia(data, auth, mediaType))
|
|
3321
3186
|
);
|
|
3322
3187
|
variables.media.media_entities = mediaIds.map((id) => ({
|
|
3323
3188
|
media_id: id,
|
|
@@ -3462,9 +3327,7 @@ async function createCreateLongTweetRequest(text, auth, tweetId, mediaData) {
|
|
|
3462
3327
|
};
|
|
3463
3328
|
if (mediaData && mediaData.length > 0) {
|
|
3464
3329
|
const mediaIds = await Promise.all(
|
|
3465
|
-
mediaData.map(
|
|
3466
|
-
({ data, mediaType }) => uploadMedia(data, auth, mediaType)
|
|
3467
|
-
)
|
|
3330
|
+
mediaData.map(({ data, mediaType }) => uploadMedia(data, auth, mediaType))
|
|
3468
3331
|
);
|
|
3469
3332
|
variables.media.media_entities = mediaIds.map((id) => ({
|
|
3470
3333
|
media_id: id,
|
|
@@ -3519,10 +3382,7 @@ async function createCreateLongTweetRequest(text, auth, tweetId, mediaData) {
|
|
|
3519
3382
|
async function getArticle(id, auth) {
|
|
3520
3383
|
const tweetDetailRequest = apiRequestFactory.createTweetDetailArticleRequest();
|
|
3521
3384
|
tweetDetailRequest.variables.focalTweetId = id;
|
|
3522
|
-
const res = await requestApi(
|
|
3523
|
-
tweetDetailRequest.toRequestUrl(),
|
|
3524
|
-
auth
|
|
3525
|
-
);
|
|
3385
|
+
const res = await requestApi(tweetDetailRequest.toRequestUrl(), auth);
|
|
3526
3386
|
if (!res.success) {
|
|
3527
3387
|
throw res.err;
|
|
3528
3388
|
}
|
|
@@ -3865,11 +3725,7 @@ var Client = class {
|
|
|
3865
3725
|
let cursor;
|
|
3866
3726
|
let retrievedTweets = 0;
|
|
3867
3727
|
while (retrievedTweets < maxTweets) {
|
|
3868
|
-
const response = await this.getUserTweets(
|
|
3869
|
-
userId,
|
|
3870
|
-
maxTweets - retrievedTweets,
|
|
3871
|
-
cursor
|
|
3872
|
-
);
|
|
3728
|
+
const response = await this.getUserTweets(userId, maxTweets - retrievedTweets, cursor);
|
|
3873
3729
|
for (const tweet of response.tweets) {
|
|
3874
3730
|
yield tweet;
|
|
3875
3731
|
retrievedTweets++;
|
|
@@ -3925,12 +3781,7 @@ var Client = class {
|
|
|
3925
3781
|
);
|
|
3926
3782
|
}
|
|
3927
3783
|
async sendNoteTweet(text, replyToTweetId, mediaData) {
|
|
3928
|
-
return await createCreateNoteTweetRequest(
|
|
3929
|
-
text,
|
|
3930
|
-
this.auth,
|
|
3931
|
-
replyToTweetId,
|
|
3932
|
-
mediaData
|
|
3933
|
-
);
|
|
3784
|
+
return await createCreateNoteTweetRequest(text, this.auth, replyToTweetId, mediaData);
|
|
3934
3785
|
}
|
|
3935
3786
|
/**
|
|
3936
3787
|
* Send a long tweet (Note Tweet)
|
|
@@ -3940,12 +3791,7 @@ var Client = class {
|
|
|
3940
3791
|
* @returns
|
|
3941
3792
|
*/
|
|
3942
3793
|
async sendLongTweet(text, replyToTweetId, mediaData) {
|
|
3943
|
-
return await createCreateLongTweetRequest(
|
|
3944
|
-
text,
|
|
3945
|
-
this.auth,
|
|
3946
|
-
replyToTweetId,
|
|
3947
|
-
mediaData
|
|
3948
|
-
);
|
|
3794
|
+
return await createCreateLongTweetRequest(text, this.auth, replyToTweetId, mediaData);
|
|
3949
3795
|
}
|
|
3950
3796
|
/**
|
|
3951
3797
|
* Send a tweet
|
|
@@ -3955,12 +3801,7 @@ var Client = class {
|
|
|
3955
3801
|
* @returns
|
|
3956
3802
|
*/
|
|
3957
3803
|
async sendTweetV2(text, replyToTweetId, options) {
|
|
3958
|
-
return await createCreateTweetRequestV2(
|
|
3959
|
-
text,
|
|
3960
|
-
this.auth,
|
|
3961
|
-
replyToTweetId,
|
|
3962
|
-
options
|
|
3963
|
-
);
|
|
3804
|
+
return await createCreateTweetRequestV2(text, this.auth, replyToTweetId, options);
|
|
3964
3805
|
}
|
|
3965
3806
|
/**
|
|
3966
3807
|
* Fetches tweets and replies from a Twitter user.
|
|
@@ -4129,9 +3970,7 @@ var Client = class {
|
|
|
4129
3970
|
* @returns All cookies for the current session.
|
|
4130
3971
|
*/
|
|
4131
3972
|
async getCookies() {
|
|
4132
|
-
return await this.authTrends.cookieJar().getCookies(
|
|
4133
|
-
typeof document !== "undefined" ? document.location.toString() : twUrl
|
|
4134
|
-
);
|
|
3973
|
+
return await this.authTrends.cookieJar().getCookies(typeof document !== "undefined" ? document.location.toString() : twUrl);
|
|
4135
3974
|
}
|
|
4136
3975
|
/**
|
|
4137
3976
|
* Set cookies for the current session.
|
|
@@ -4186,12 +4025,7 @@ var Client = class {
|
|
|
4186
4025
|
* @returns The response from the Twitter API.
|
|
4187
4026
|
*/
|
|
4188
4027
|
async sendQuoteTweet(text, quotedTweetId, options) {
|
|
4189
|
-
return await createQuoteTweetRequest(
|
|
4190
|
-
text,
|
|
4191
|
-
quotedTweetId,
|
|
4192
|
-
this.auth,
|
|
4193
|
-
options?.mediaData
|
|
4194
|
-
);
|
|
4028
|
+
return await createQuoteTweetRequest(text, quotedTweetId, this.auth, options?.mediaData);
|
|
4195
4029
|
}
|
|
4196
4030
|
/**
|
|
4197
4031
|
* Likes a tweet with the given tweet ID.
|
|
@@ -4368,12 +4202,7 @@ var Client = class {
|
|
|
4368
4202
|
let cursor;
|
|
4369
4203
|
let prevCursor;
|
|
4370
4204
|
while (true) {
|
|
4371
|
-
const page = await fetchQuotedTweetsPage(
|
|
4372
|
-
quotedTweetId,
|
|
4373
|
-
maxTweetsPerPage,
|
|
4374
|
-
this.auth,
|
|
4375
|
-
cursor
|
|
4376
|
-
);
|
|
4205
|
+
const page = await fetchQuotedTweetsPage(quotedTweetId, maxTweetsPerPage, this.auth, cursor);
|
|
4377
4206
|
if (!page.tweets || page.tweets.length === 0) {
|
|
4378
4207
|
break;
|
|
4379
4208
|
}
|
|
@@ -4467,15 +4296,11 @@ async function authorizeToken(cookie) {
|
|
|
4467
4296
|
})
|
|
4468
4297
|
});
|
|
4469
4298
|
if (!resp.ok) {
|
|
4470
|
-
throw new Error(
|
|
4471
|
-
`authorizeToken => request failed with status ${resp.status}`
|
|
4472
|
-
);
|
|
4299
|
+
throw new Error(`authorizeToken => request failed with status ${resp.status}`);
|
|
4473
4300
|
}
|
|
4474
4301
|
const data = await resp.json();
|
|
4475
4302
|
if (!data.authorization_token) {
|
|
4476
|
-
throw new Error(
|
|
4477
|
-
"authorizeToken => Missing authorization_token in response"
|
|
4478
|
-
);
|
|
4303
|
+
throw new Error("authorizeToken => Missing authorization_token in response");
|
|
4479
4304
|
}
|
|
4480
4305
|
return data.authorization_token;
|
|
4481
4306
|
}
|
|
@@ -4517,9 +4342,7 @@ async function getTurnServers(cookie) {
|
|
|
4517
4342
|
body: JSON.stringify({ cookie })
|
|
4518
4343
|
});
|
|
4519
4344
|
if (!resp.ok) {
|
|
4520
|
-
throw new Error(
|
|
4521
|
-
`getTurnServers => request failed with status ${resp.status}`
|
|
4522
|
-
);
|
|
4345
|
+
throw new Error(`getTurnServers => request failed with status ${resp.status}`);
|
|
4523
4346
|
}
|
|
4524
4347
|
return resp.json();
|
|
4525
4348
|
}
|
|
@@ -4566,9 +4389,7 @@ async function createBroadcast(params) {
|
|
|
4566
4389
|
});
|
|
4567
4390
|
if (!resp.ok) {
|
|
4568
4391
|
const text = await resp.text();
|
|
4569
|
-
throw new Error(
|
|
4570
|
-
`createBroadcast => request failed with status ${resp.status} ${text}`
|
|
4571
|
-
);
|
|
4392
|
+
throw new Error(`createBroadcast => request failed with status ${resp.status} ${text}`);
|
|
4572
4393
|
}
|
|
4573
4394
|
const data = await resp.json();
|
|
4574
4395
|
return data;
|
|
@@ -4610,9 +4431,7 @@ async function startWatching(lifecycleToken, cookie) {
|
|
|
4610
4431
|
body: JSON.stringify(body)
|
|
4611
4432
|
});
|
|
4612
4433
|
if (!resp.ok) {
|
|
4613
|
-
throw new Error(
|
|
4614
|
-
`startWatching => request failed with status ${resp.status}`
|
|
4615
|
-
);
|
|
4434
|
+
throw new Error(`startWatching => request failed with status ${resp.status}`);
|
|
4616
4435
|
}
|
|
4617
4436
|
const json = await resp.json();
|
|
4618
4437
|
return json.session;
|
|
@@ -4630,9 +4449,7 @@ async function stopWatching(session, cookie) {
|
|
|
4630
4449
|
body: JSON.stringify(body)
|
|
4631
4450
|
});
|
|
4632
4451
|
if (!resp.ok) {
|
|
4633
|
-
throw new Error(
|
|
4634
|
-
`stopWatching => request failed with status ${resp.status}`
|
|
4635
|
-
);
|
|
4452
|
+
throw new Error(`stopWatching => request failed with status ${resp.status}`);
|
|
4636
4453
|
}
|
|
4637
4454
|
}
|
|
4638
4455
|
async function submitSpeakerRequest(params) {
|
|
@@ -4653,9 +4470,7 @@ async function submitSpeakerRequest(params) {
|
|
|
4653
4470
|
body: JSON.stringify(body)
|
|
4654
4471
|
});
|
|
4655
4472
|
if (!resp.ok) {
|
|
4656
|
-
throw new Error(
|
|
4657
|
-
`submitSpeakerRequest => request failed with status ${resp.status}`
|
|
4658
|
-
);
|
|
4473
|
+
throw new Error(`submitSpeakerRequest => request failed with status ${resp.status}`);
|
|
4659
4474
|
}
|
|
4660
4475
|
return resp.json();
|
|
4661
4476
|
}
|
|
@@ -4678,9 +4493,7 @@ async function cancelSpeakerRequest(params) {
|
|
|
4678
4493
|
body: JSON.stringify(body)
|
|
4679
4494
|
});
|
|
4680
4495
|
if (!resp.ok) {
|
|
4681
|
-
throw new Error(
|
|
4682
|
-
`cancelSpeakerRequest => request failed with status ${resp.status}`
|
|
4683
|
-
);
|
|
4496
|
+
throw new Error(`cancelSpeakerRequest => request failed with status ${resp.status}`);
|
|
4684
4497
|
}
|
|
4685
4498
|
return resp.json();
|
|
4686
4499
|
}
|
|
@@ -4699,9 +4512,7 @@ async function negotiateGuestStream(params) {
|
|
|
4699
4512
|
body: JSON.stringify(body)
|
|
4700
4513
|
});
|
|
4701
4514
|
if (!resp.ok) {
|
|
4702
|
-
throw new Error(
|
|
4703
|
-
`negotiateGuestStream => request failed with status ${resp.status}`
|
|
4704
|
-
);
|
|
4515
|
+
throw new Error(`negotiateGuestStream => request failed with status ${resp.status}`);
|
|
4705
4516
|
}
|
|
4706
4517
|
return resp.json();
|
|
4707
4518
|
}
|
|
@@ -4751,29 +4562,29 @@ async function unmuteSpeaker(params) {
|
|
|
4751
4562
|
throw new Error(`unmuteSpeaker => ${resp.status} ${text}`);
|
|
4752
4563
|
}
|
|
4753
4564
|
}
|
|
4754
|
-
function setupCommonChatEvents(chatClient,
|
|
4565
|
+
function setupCommonChatEvents(chatClient, logger11, emitter) {
|
|
4755
4566
|
chatClient.on("occupancyUpdate", (upd) => {
|
|
4756
|
-
|
|
4567
|
+
logger11.debug("[ChatEvents] occupancyUpdate =>", upd);
|
|
4757
4568
|
emitter.emit("occupancyUpdate", upd);
|
|
4758
4569
|
});
|
|
4759
4570
|
chatClient.on("guestReaction", (reaction) => {
|
|
4760
|
-
|
|
4571
|
+
logger11.debug("[ChatEvents] guestReaction =>", reaction);
|
|
4761
4572
|
emitter.emit("guestReaction", reaction);
|
|
4762
4573
|
});
|
|
4763
4574
|
chatClient.on("muteStateChanged", (evt) => {
|
|
4764
|
-
|
|
4575
|
+
logger11.debug("[ChatEvents] muteStateChanged =>", evt);
|
|
4765
4576
|
emitter.emit("muteStateChanged", evt);
|
|
4766
4577
|
});
|
|
4767
4578
|
chatClient.on("speakerRequest", (req) => {
|
|
4768
|
-
|
|
4579
|
+
logger11.debug("[ChatEvents] speakerRequest =>", req);
|
|
4769
4580
|
emitter.emit("speakerRequest", req);
|
|
4770
4581
|
});
|
|
4771
4582
|
chatClient.on("newSpeakerAccepted", (info) => {
|
|
4772
|
-
|
|
4583
|
+
logger11.debug("[ChatEvents] newSpeakerAccepted =>", info);
|
|
4773
4584
|
emitter.emit("newSpeakerAccepted", info);
|
|
4774
4585
|
});
|
|
4775
4586
|
chatClient.on("newSpeakerRemoved", (info) => {
|
|
4776
|
-
|
|
4587
|
+
logger11.debug("[ChatEvents] newSpeakerRemoved =>", info);
|
|
4777
4588
|
emitter.emit("newSpeakerRemoved", info);
|
|
4778
4589
|
});
|
|
4779
4590
|
}
|
|
@@ -4794,10 +4605,7 @@ var ChatClient = class extends EventEmitter {
|
|
|
4794
4605
|
* Establishes a WebSocket connection to the chat endpoint and sets up event handlers.
|
|
4795
4606
|
*/
|
|
4796
4607
|
async connect() {
|
|
4797
|
-
const wsUrl = `${this.endpoint}/chatapi/v1/chatnow`.replace(
|
|
4798
|
-
"https://",
|
|
4799
|
-
"wss://"
|
|
4800
|
-
);
|
|
4608
|
+
const wsUrl = `${this.endpoint}/chatapi/v1/chatnow`.replace("https://", "wss://");
|
|
4801
4609
|
this.logger.info("[ChatClient] Connecting =>", wsUrl);
|
|
4802
4610
|
this.ws = new WebSocket(wsUrl, {
|
|
4803
4611
|
headers: {
|
|
@@ -4862,24 +4670,22 @@ var ChatClient = class extends EventEmitter {
|
|
|
4862
4670
|
*/
|
|
4863
4671
|
reactWithEmoji(emoji) {
|
|
4864
4672
|
if (!this.ws || !this.connected) {
|
|
4865
|
-
this.logger.warn(
|
|
4866
|
-
"[ChatClient] Not connected or WebSocket missing; ignoring reactWithEmoji."
|
|
4867
|
-
);
|
|
4673
|
+
this.logger.warn("[ChatClient] Not connected or WebSocket missing; ignoring reactWithEmoji.");
|
|
4868
4674
|
return;
|
|
4869
4675
|
}
|
|
4870
4676
|
const payload = JSON.stringify({
|
|
4871
4677
|
body: JSON.stringify({ body: emoji, type: 2, v: 2 }),
|
|
4872
4678
|
kind: 1,
|
|
4873
4679
|
/*
|
|
4874
|
-
|
|
4875
|
-
|
|
4876
|
-
|
|
4877
|
-
|
|
4878
|
-
|
|
4879
|
-
|
|
4880
|
-
|
|
4881
|
-
|
|
4882
|
-
|
|
4680
|
+
// The 'sender' field is not required, it's not even verified by the server
|
|
4681
|
+
// Instead of passing attributes down here it's easier to ignore it
|
|
4682
|
+
sender: {
|
|
4683
|
+
user_id: null,
|
|
4684
|
+
twitter_id: null,
|
|
4685
|
+
username: null,
|
|
4686
|
+
display_name: null,
|
|
4687
|
+
},
|
|
4688
|
+
*/
|
|
4883
4689
|
payload: JSON.stringify({
|
|
4884
4690
|
room: this.spaceId,
|
|
4885
4691
|
body: JSON.stringify({ body: emoji, type: 2, v: 2 })
|
|
@@ -5120,10 +4926,7 @@ var JanusClient = class extends EventEmitter3 {
|
|
|
5120
4926
|
const evt = await evtPromise;
|
|
5121
4927
|
const data = evt.plugindata?.data;
|
|
5122
4928
|
this.publisherId = data.id;
|
|
5123
|
-
this.logger.debug(
|
|
5124
|
-
"[JanusClient] guest joined => publisherId=",
|
|
5125
|
-
this.publisherId
|
|
5126
|
-
);
|
|
4929
|
+
this.logger.debug("[JanusClient] guest joined => publisherId=", this.publisherId);
|
|
5127
4930
|
const publishers = data.publishers || [];
|
|
5128
4931
|
this.logger.debug("[JanusClient] existing publishers =>", publishers);
|
|
5129
4932
|
this.pc = new RTCPeerConnection({
|
|
@@ -5138,9 +4941,7 @@ var JanusClient = class extends EventEmitter3 {
|
|
|
5138
4941
|
this.setupPeerEvents();
|
|
5139
4942
|
this.enableLocalAudio();
|
|
5140
4943
|
await this.configurePublisher(sessionUUID);
|
|
5141
|
-
await Promise.all(
|
|
5142
|
-
publishers.map((pub) => this.subscribeSpeaker(pub.display, pub.id))
|
|
5143
|
-
);
|
|
4944
|
+
await Promise.all(publishers.map((pub) => this.subscribeSpeaker(pub.display, pub.id)));
|
|
5144
4945
|
this.logger.info("[JanusClient] Guest speaker negotiation complete");
|
|
5145
4946
|
}
|
|
5146
4947
|
/**
|
|
@@ -5158,9 +4959,7 @@ var JanusClient = class extends EventEmitter3 {
|
|
|
5158
4959
|
'discover feed_id from "publishers"'
|
|
5159
4960
|
);
|
|
5160
4961
|
const list = publishersEvt.plugindata.data.publishers;
|
|
5161
|
-
const pub = list.find(
|
|
5162
|
-
(p) => p.display === userId || p.periscope_user_id === userId
|
|
5163
|
-
);
|
|
4962
|
+
const pub = list.find((p) => p.display === userId || p.periscope_user_id === userId);
|
|
5164
4963
|
if (!pub) {
|
|
5165
4964
|
throw new Error(
|
|
5166
4965
|
`[JanusClient] subscribeSpeaker => No publisher found for userId=${userId}`
|
|
@@ -5216,9 +5015,7 @@ var JanusClient = class extends EventEmitter3 {
|
|
|
5216
5015
|
const val = Math.abs(frame.samples[i]);
|
|
5217
5016
|
if (val > maxVal) maxVal = val;
|
|
5218
5017
|
}
|
|
5219
|
-
this.logger.debug(
|
|
5220
|
-
`[AudioSink] userId=${userId}, maxAmplitude=${maxVal}`
|
|
5221
|
-
);
|
|
5018
|
+
this.logger.debug(`[AudioSink] userId=${userId}, maxAmplitude=${maxVal}`);
|
|
5222
5019
|
}
|
|
5223
5020
|
this.emit("audioDataFromSpeaker", {
|
|
5224
5021
|
userId,
|
|
@@ -5260,9 +5057,7 @@ var JanusClient = class extends EventEmitter3 {
|
|
|
5260
5057
|
*/
|
|
5261
5058
|
enableLocalAudio() {
|
|
5262
5059
|
if (!this.pc) {
|
|
5263
|
-
this.logger.warn(
|
|
5264
|
-
"[JanusClient] enableLocalAudio => No RTCPeerConnection"
|
|
5265
|
-
);
|
|
5060
|
+
this.logger.warn("[JanusClient] enableLocalAudio => No RTCPeerConnection");
|
|
5266
5061
|
return;
|
|
5267
5062
|
}
|
|
5268
5063
|
if (this.localAudioSource) {
|
|
@@ -5380,42 +5175,31 @@ var JanusClient = class extends EventEmitter3 {
|
|
|
5380
5175
|
h264_profile: "42e01f",
|
|
5381
5176
|
dummy_publisher: false
|
|
5382
5177
|
};
|
|
5383
|
-
const resp = await fetch(
|
|
5384
|
-
|
|
5385
|
-
{
|
|
5386
|
-
|
|
5387
|
-
|
|
5388
|
-
|
|
5389
|
-
|
|
5390
|
-
|
|
5391
|
-
|
|
5392
|
-
|
|
5393
|
-
|
|
5394
|
-
|
|
5395
|
-
|
|
5396
|
-
})
|
|
5397
|
-
}
|
|
5398
|
-
);
|
|
5178
|
+
const resp = await fetch(`${this.config.webrtcUrl}/${this.sessionId}/${this.handleId}`, {
|
|
5179
|
+
method: "POST",
|
|
5180
|
+
headers: {
|
|
5181
|
+
Authorization: this.config.credential,
|
|
5182
|
+
"Content-Type": "application/json",
|
|
5183
|
+
Referer: "https://x.com"
|
|
5184
|
+
},
|
|
5185
|
+
body: JSON.stringify({
|
|
5186
|
+
janus: "message",
|
|
5187
|
+
transaction,
|
|
5188
|
+
body
|
|
5189
|
+
})
|
|
5190
|
+
});
|
|
5399
5191
|
if (!resp.ok) {
|
|
5400
5192
|
throw new Error(`[JanusClient] createRoom failed => ${resp.status}`);
|
|
5401
5193
|
}
|
|
5402
5194
|
const json = await resp.json();
|
|
5403
5195
|
this.logger.debug("[JanusClient] createRoom =>", JSON.stringify(json));
|
|
5404
5196
|
if (json.janus === "error") {
|
|
5405
|
-
throw new Error(
|
|
5406
|
-
`[JanusClient] createRoom error => ${json.error?.reason || "Unknown"}`
|
|
5407
|
-
);
|
|
5197
|
+
throw new Error(`[JanusClient] createRoom error => ${json.error?.reason || "Unknown"}`);
|
|
5408
5198
|
}
|
|
5409
5199
|
if (json.plugindata?.data?.videoroom !== "created") {
|
|
5410
|
-
throw new Error(
|
|
5411
|
-
`[JanusClient] unexpected createRoom response => ${JSON.stringify(
|
|
5412
|
-
json
|
|
5413
|
-
)}`
|
|
5414
|
-
);
|
|
5200
|
+
throw new Error(`[JanusClient] unexpected createRoom response => ${JSON.stringify(json)}`);
|
|
5415
5201
|
}
|
|
5416
|
-
this.logger.debug(
|
|
5417
|
-
`[JanusClient] Room '${this.config.roomId}' created successfully`
|
|
5418
|
-
);
|
|
5202
|
+
this.logger.debug(`[JanusClient] Room '${this.config.roomId}' created successfully`);
|
|
5419
5203
|
}
|
|
5420
5204
|
/**
|
|
5421
5205
|
* Joins the created room as a publisher, for the host scenario.
|
|
@@ -5480,26 +5264,21 @@ var JanusClient = class extends EventEmitter3 {
|
|
|
5480
5264
|
throw new Error("[JanusClient] No session for sendJanusMessage");
|
|
5481
5265
|
}
|
|
5482
5266
|
const transaction = this.randomTid();
|
|
5483
|
-
const resp = await fetch(
|
|
5484
|
-
|
|
5485
|
-
{
|
|
5486
|
-
|
|
5487
|
-
|
|
5488
|
-
|
|
5489
|
-
|
|
5490
|
-
|
|
5491
|
-
|
|
5492
|
-
|
|
5493
|
-
|
|
5494
|
-
|
|
5495
|
-
|
|
5496
|
-
})
|
|
5497
|
-
}
|
|
5498
|
-
);
|
|
5267
|
+
const resp = await fetch(`${this.config.webrtcUrl}/${this.sessionId}/${handleId}`, {
|
|
5268
|
+
method: "POST",
|
|
5269
|
+
headers: {
|
|
5270
|
+
Authorization: this.config.credential,
|
|
5271
|
+
"Content-Type": "application/json"
|
|
5272
|
+
},
|
|
5273
|
+
body: JSON.stringify({
|
|
5274
|
+
janus: "message",
|
|
5275
|
+
transaction,
|
|
5276
|
+
body,
|
|
5277
|
+
jsep
|
|
5278
|
+
})
|
|
5279
|
+
});
|
|
5499
5280
|
if (!resp.ok) {
|
|
5500
|
-
throw new Error(
|
|
5501
|
-
`[JanusClient] sendJanusMessage failed => status=${resp.status}`
|
|
5502
|
-
);
|
|
5281
|
+
throw new Error(`[JanusClient] sendJanusMessage failed => status=${resp.status}`);
|
|
5503
5282
|
}
|
|
5504
5283
|
}
|
|
5505
5284
|
/**
|
|
@@ -5581,10 +5360,7 @@ var JanusClient = class extends EventEmitter3 {
|
|
|
5581
5360
|
return;
|
|
5582
5361
|
}
|
|
5583
5362
|
this.pc.addEventListener("iceconnectionstatechange", () => {
|
|
5584
|
-
this.logger.debug(
|
|
5585
|
-
"[JanusClient] ICE state =>",
|
|
5586
|
-
this.pc?.iceConnectionState
|
|
5587
|
-
);
|
|
5363
|
+
this.logger.debug("[JanusClient] ICE state =>", this.pc?.iceConnectionState);
|
|
5588
5364
|
if (this.pc?.iceConnectionState === "failed") {
|
|
5589
5365
|
this.emit("error", new Error("[JanusClient] ICE connection failed"));
|
|
5590
5366
|
}
|
|
@@ -5642,22 +5418,19 @@ var JanusClient = class extends EventEmitter3 {
|
|
|
5642
5418
|
periscope_user_id: this.config.userId
|
|
5643
5419
|
};
|
|
5644
5420
|
this.logger.info("[JanusClient] destroying room =>", body);
|
|
5645
|
-
const resp = await fetch(
|
|
5646
|
-
|
|
5647
|
-
{
|
|
5648
|
-
|
|
5649
|
-
|
|
5650
|
-
|
|
5651
|
-
|
|
5652
|
-
|
|
5653
|
-
|
|
5654
|
-
|
|
5655
|
-
|
|
5656
|
-
|
|
5657
|
-
|
|
5658
|
-
})
|
|
5659
|
-
}
|
|
5660
|
-
);
|
|
5421
|
+
const resp = await fetch(`${this.config.webrtcUrl}/${this.sessionId}/${this.handleId}`, {
|
|
5422
|
+
method: "POST",
|
|
5423
|
+
headers: {
|
|
5424
|
+
Authorization: this.config.credential,
|
|
5425
|
+
"Content-Type": "application/json",
|
|
5426
|
+
Referer: "https://x.com"
|
|
5427
|
+
},
|
|
5428
|
+
body: JSON.stringify({
|
|
5429
|
+
janus: "message",
|
|
5430
|
+
transaction,
|
|
5431
|
+
body
|
|
5432
|
+
})
|
|
5433
|
+
});
|
|
5661
5434
|
if (!resp.ok) {
|
|
5662
5435
|
throw new Error(`[JanusClient] destroyRoom failed => ${resp.status}`);
|
|
5663
5436
|
}
|
|
@@ -5679,21 +5452,18 @@ var JanusClient = class extends EventEmitter3 {
|
|
|
5679
5452
|
periscope_user_id: this.config.userId
|
|
5680
5453
|
};
|
|
5681
5454
|
this.logger.info("[JanusClient] leaving room =>", body);
|
|
5682
|
-
const resp = await fetch(
|
|
5683
|
-
|
|
5684
|
-
{
|
|
5685
|
-
|
|
5686
|
-
|
|
5687
|
-
|
|
5688
|
-
|
|
5689
|
-
|
|
5690
|
-
|
|
5691
|
-
|
|
5692
|
-
|
|
5693
|
-
|
|
5694
|
-
})
|
|
5695
|
-
}
|
|
5696
|
-
);
|
|
5455
|
+
const resp = await fetch(`${this.config.webrtcUrl}/${this.sessionId}/${this.handleId}`, {
|
|
5456
|
+
method: "POST",
|
|
5457
|
+
headers: {
|
|
5458
|
+
Authorization: this.config.credential,
|
|
5459
|
+
"Content-Type": "application/json"
|
|
5460
|
+
},
|
|
5461
|
+
body: JSON.stringify({
|
|
5462
|
+
janus: "message",
|
|
5463
|
+
transaction,
|
|
5464
|
+
body
|
|
5465
|
+
})
|
|
5466
|
+
});
|
|
5697
5467
|
if (!resp.ok) {
|
|
5698
5468
|
throw new Error(`[JanusClient] leaveRoom => error code ${resp.status}`);
|
|
5699
5469
|
}
|
|
@@ -5768,16 +5538,11 @@ var Space = class extends EventEmitter4 {
|
|
|
5768
5538
|
this.janusClient.on("subscribedSpeaker", ({ userId, feedId }) => {
|
|
5769
5539
|
const speaker = this.speakers.get(userId);
|
|
5770
5540
|
if (!speaker) {
|
|
5771
|
-
this.logger.debug(
|
|
5772
|
-
"[Space] subscribedSpeaker => no speaker found",
|
|
5773
|
-
userId
|
|
5774
|
-
);
|
|
5541
|
+
this.logger.debug("[Space] subscribedSpeaker => no speaker found", userId);
|
|
5775
5542
|
return;
|
|
5776
5543
|
}
|
|
5777
5544
|
speaker.janusParticipantId = feedId;
|
|
5778
|
-
this.logger.debug(
|
|
5779
|
-
`[Space] updated speaker => userId=${userId}, feedId=${feedId}`
|
|
5780
|
-
);
|
|
5545
|
+
this.logger.debug(`[Space] updated speaker => userId=${userId}, feedId=${feedId}`);
|
|
5781
5546
|
});
|
|
5782
5547
|
this.logger.debug("[Space] Publishing broadcast...");
|
|
5783
5548
|
await publishBroadcast({
|
|
@@ -5799,10 +5564,7 @@ var Space = class extends EventEmitter4 {
|
|
|
5799
5564
|
await this.chatClient.connect();
|
|
5800
5565
|
this.setupChatEvents();
|
|
5801
5566
|
}
|
|
5802
|
-
this.logger.info(
|
|
5803
|
-
"[Space] Initialized =>",
|
|
5804
|
-
broadcast.share_url.replace("broadcasts", "spaces")
|
|
5805
|
-
);
|
|
5567
|
+
this.logger.info("[Space] Initialized =>", broadcast.share_url.replace("broadcasts", "spaces"));
|
|
5806
5568
|
this.isInitialized = true;
|
|
5807
5569
|
for (const { plugin, config: pluginConfig } of this.plugins) {
|
|
5808
5570
|
plugin.init?.({ space: this, pluginConfig });
|
|
@@ -5836,12 +5598,7 @@ var Space = class extends EventEmitter4 {
|
|
|
5836
5598
|
throw new Error("[Space] No auth token available");
|
|
5837
5599
|
}
|
|
5838
5600
|
this.speakers.set(userId, { userId, sessionUUID });
|
|
5839
|
-
await this.callApproveEndpoint(
|
|
5840
|
-
this.broadcastInfo,
|
|
5841
|
-
this.authToken,
|
|
5842
|
-
userId,
|
|
5843
|
-
sessionUUID
|
|
5844
|
-
);
|
|
5601
|
+
await this.callApproveEndpoint(this.broadcastInfo, this.authToken, userId, sessionUUID);
|
|
5845
5602
|
await this.janusClient?.subscribeSpeaker(userId);
|
|
5846
5603
|
}
|
|
5847
5604
|
/**
|
|
@@ -5868,9 +5625,7 @@ var Space = class extends EventEmitter4 {
|
|
|
5868
5625
|
});
|
|
5869
5626
|
if (!resp.ok) {
|
|
5870
5627
|
const error = await resp.text();
|
|
5871
|
-
throw new Error(
|
|
5872
|
-
`[Space] Failed to approve speaker => ${resp.status}: ${error}`
|
|
5873
|
-
);
|
|
5628
|
+
throw new Error(`[Space] Failed to approve speaker => ${resp.status}: ${error}`);
|
|
5874
5629
|
}
|
|
5875
5630
|
this.logger.info("[Space] Speaker approved =>", userId);
|
|
5876
5631
|
}
|
|
@@ -5889,17 +5644,10 @@ var Space = class extends EventEmitter4 {
|
|
|
5889
5644
|
}
|
|
5890
5645
|
const speaker = this.speakers.get(userId);
|
|
5891
5646
|
if (!speaker) {
|
|
5892
|
-
throw new Error(
|
|
5893
|
-
`[Space] removeSpeaker => no speaker found for userId=${userId}`
|
|
5894
|
-
);
|
|
5647
|
+
throw new Error(`[Space] removeSpeaker => no speaker found for userId=${userId}`);
|
|
5895
5648
|
}
|
|
5896
5649
|
const { sessionUUID, janusParticipantId } = speaker;
|
|
5897
|
-
this.logger.debug(
|
|
5898
|
-
"[Space] removeSpeaker =>",
|
|
5899
|
-
sessionUUID,
|
|
5900
|
-
janusParticipantId,
|
|
5901
|
-
speaker
|
|
5902
|
-
);
|
|
5650
|
+
this.logger.debug("[Space] removeSpeaker =>", sessionUUID, janusParticipantId, speaker);
|
|
5903
5651
|
if (!sessionUUID || janusParticipantId === void 0) {
|
|
5904
5652
|
throw new Error(
|
|
5905
5653
|
`[Space] removeSpeaker => missing sessionUUID or feedId for userId=${userId}`
|
|
@@ -5908,9 +5656,7 @@ var Space = class extends EventEmitter4 {
|
|
|
5908
5656
|
const janusHandleId = this.janusClient.getHandleId();
|
|
5909
5657
|
const janusSessionId = this.janusClient.getSessionId();
|
|
5910
5658
|
if (!janusHandleId || !janusSessionId) {
|
|
5911
|
-
throw new Error(
|
|
5912
|
-
`[Space] removeSpeaker => missing Janus handle/session for userId=${userId}`
|
|
5913
|
-
);
|
|
5659
|
+
throw new Error(`[Space] removeSpeaker => missing Janus handle/session for userId=${userId}`);
|
|
5914
5660
|
}
|
|
5915
5661
|
await this.callRemoveEndpoint(
|
|
5916
5662
|
this.broadcastInfo,
|
|
@@ -5952,9 +5698,7 @@ var Space = class extends EventEmitter4 {
|
|
|
5952
5698
|
});
|
|
5953
5699
|
if (!resp.ok) {
|
|
5954
5700
|
const error = await resp.text();
|
|
5955
|
-
throw new Error(
|
|
5956
|
-
`[Space] Failed to remove speaker => ${resp.status}: ${error}`
|
|
5957
|
-
);
|
|
5701
|
+
throw new Error(`[Space] Failed to remove speaker => ${resp.status}: ${error}`);
|
|
5958
5702
|
}
|
|
5959
5703
|
this.logger.debug("[Space] Speaker removed => sessionUUID=", sessionUUID);
|
|
5960
5704
|
}
|
|
@@ -6163,10 +5907,7 @@ var SpaceParticipant = class extends EventEmitter5 {
|
|
|
6163
5907
|
use(plugin, config) {
|
|
6164
5908
|
const registration = { plugin, config };
|
|
6165
5909
|
this.plugins.add(registration);
|
|
6166
|
-
this.logger.debug(
|
|
6167
|
-
"[SpaceParticipant] Plugin added =>",
|
|
6168
|
-
plugin.constructor.name
|
|
6169
|
-
);
|
|
5910
|
+
this.logger.debug("[SpaceParticipant] Plugin added =>", plugin.constructor.name);
|
|
6170
5911
|
plugin.onAttach?.({ space: this, pluginConfig: config });
|
|
6171
5912
|
if (plugin.init) {
|
|
6172
5913
|
plugin.init({ space: this, pluginConfig: config });
|
|
@@ -6177,10 +5918,7 @@ var SpaceParticipant = class extends EventEmitter5 {
|
|
|
6177
5918
|
* Joins the Space as a listener: obtains HLS, chat token, etc.
|
|
6178
5919
|
*/
|
|
6179
5920
|
async joinAsListener() {
|
|
6180
|
-
this.logger.info(
|
|
6181
|
-
"[SpaceParticipant] Joining space as listener =>",
|
|
6182
|
-
this.spaceId
|
|
6183
|
-
);
|
|
5921
|
+
this.logger.info("[SpaceParticipant] Joining space as listener =>", this.spaceId);
|
|
6184
5922
|
this.cookie = await this.client.getPeriscopeCookie();
|
|
6185
5923
|
this.authToken = await authorizeToken(this.cookie);
|
|
6186
5924
|
const spaceMeta = await this.client.getAudioSpaceById(this.spaceId);
|
|
@@ -6222,9 +5960,7 @@ var SpaceParticipant = class extends EventEmitter5 {
|
|
|
6222
5960
|
*/
|
|
6223
5961
|
async requestSpeaker() {
|
|
6224
5962
|
if (!this.chatJwtToken) {
|
|
6225
|
-
throw new Error(
|
|
6226
|
-
"[SpaceParticipant] Must join as listener first (no chat token)."
|
|
6227
|
-
);
|
|
5963
|
+
throw new Error("[SpaceParticipant] Must join as listener first (no chat token).");
|
|
6228
5964
|
}
|
|
6229
5965
|
if (!this.authToken) {
|
|
6230
5966
|
throw new Error("[SpaceParticipant] No auth token available.");
|
|
@@ -6239,10 +5975,7 @@ var SpaceParticipant = class extends EventEmitter5 {
|
|
|
6239
5975
|
authToken: this.authToken
|
|
6240
5976
|
});
|
|
6241
5977
|
this.sessionUUID = session_uuid;
|
|
6242
|
-
this.logger.info(
|
|
6243
|
-
"[SpaceParticipant] Speaker request submitted =>",
|
|
6244
|
-
session_uuid
|
|
6245
|
-
);
|
|
5978
|
+
this.logger.info("[SpaceParticipant] Speaker request submitted =>", session_uuid);
|
|
6246
5979
|
return { sessionUUID: session_uuid };
|
|
6247
5980
|
}
|
|
6248
5981
|
/**
|
|
@@ -6267,10 +6000,7 @@ var SpaceParticipant = class extends EventEmitter5 {
|
|
|
6267
6000
|
chatToken: this.chatToken,
|
|
6268
6001
|
authToken: this.authToken
|
|
6269
6002
|
});
|
|
6270
|
-
this.logger.info(
|
|
6271
|
-
"[SpaceParticipant] Speaker request canceled =>",
|
|
6272
|
-
this.sessionUUID
|
|
6273
|
-
);
|
|
6003
|
+
this.logger.info("[SpaceParticipant] Speaker request canceled =>", this.sessionUUID);
|
|
6274
6004
|
this.sessionUUID = void 0;
|
|
6275
6005
|
}
|
|
6276
6006
|
/**
|
|
@@ -6279,13 +6009,9 @@ var SpaceParticipant = class extends EventEmitter5 {
|
|
|
6279
6009
|
*/
|
|
6280
6010
|
async becomeSpeaker() {
|
|
6281
6011
|
if (!this.sessionUUID) {
|
|
6282
|
-
throw new Error(
|
|
6283
|
-
"[SpaceParticipant] No sessionUUID (did you call requestSpeaker()?)."
|
|
6284
|
-
);
|
|
6012
|
+
throw new Error("[SpaceParticipant] No sessionUUID (did you call requestSpeaker()?).");
|
|
6285
6013
|
}
|
|
6286
|
-
this.logger.info(
|
|
6287
|
-
"[SpaceParticipant] Negotiating speaker role via Janus..."
|
|
6288
|
-
);
|
|
6014
|
+
this.logger.info("[SpaceParticipant] Negotiating speaker role via Janus...");
|
|
6289
6015
|
const turnServers = await getTurnServers(this.cookie);
|
|
6290
6016
|
this.logger.debug("[SpaceParticipant] turnServers =>", turnServers);
|
|
6291
6017
|
const nego = await negotiateGuestStream({
|
|
@@ -6308,16 +6034,10 @@ var SpaceParticipant = class extends EventEmitter5 {
|
|
|
6308
6034
|
});
|
|
6309
6035
|
await this.janusClient.initializeGuestSpeaker(this.sessionUUID);
|
|
6310
6036
|
this.janusClient.on("audioDataFromSpeaker", (data) => {
|
|
6311
|
-
this.logger.debug(
|
|
6312
|
-
"[SpaceParticipant] Received speaker audio =>",
|
|
6313
|
-
data.userId
|
|
6314
|
-
);
|
|
6037
|
+
this.logger.debug("[SpaceParticipant] Received speaker audio =>", data.userId);
|
|
6315
6038
|
this.handleAudioData(data);
|
|
6316
6039
|
});
|
|
6317
|
-
this.logger.info(
|
|
6318
|
-
"[SpaceParticipant] Now speaker on the Space =>",
|
|
6319
|
-
this.spaceId
|
|
6320
|
-
);
|
|
6040
|
+
this.logger.info("[SpaceParticipant] Now speaker on the Space =>", this.spaceId);
|
|
6321
6041
|
for (const { plugin } of this.plugins) {
|
|
6322
6042
|
plugin.onJanusReady?.(this.janusClient);
|
|
6323
6043
|
}
|
|
@@ -6327,9 +6047,7 @@ var SpaceParticipant = class extends EventEmitter5 {
|
|
|
6327
6047
|
*/
|
|
6328
6048
|
async removeFromSpeaker() {
|
|
6329
6049
|
if (!this.sessionUUID) {
|
|
6330
|
-
throw new Error(
|
|
6331
|
-
"[SpaceParticipant] No sessionUUID; cannot remove from speaker role."
|
|
6332
|
-
);
|
|
6050
|
+
throw new Error("[SpaceParticipant] No sessionUUID; cannot remove from speaker role.");
|
|
6333
6051
|
}
|
|
6334
6052
|
if (!this.authToken || !this.chatToken) {
|
|
6335
6053
|
throw new Error("[SpaceParticipant] Missing authToken or chatToken.");
|
|
@@ -6339,9 +6057,7 @@ var SpaceParticipant = class extends EventEmitter5 {
|
|
|
6339
6057
|
await this.janusClient.stop();
|
|
6340
6058
|
this.janusClient = void 0;
|
|
6341
6059
|
}
|
|
6342
|
-
this.logger.info(
|
|
6343
|
-
"[SpaceParticipant] Successfully removed from speaker role."
|
|
6344
|
-
);
|
|
6060
|
+
this.logger.info("[SpaceParticipant] Successfully removed from speaker role.");
|
|
6345
6061
|
}
|
|
6346
6062
|
/**
|
|
6347
6063
|
* Leaves the Space gracefully:
|
|
@@ -6369,9 +6085,7 @@ var SpaceParticipant = class extends EventEmitter5 {
|
|
|
6369
6085
|
*/
|
|
6370
6086
|
pushAudio(samples, sampleRate) {
|
|
6371
6087
|
if (!this.janusClient) {
|
|
6372
|
-
this.logger.warn(
|
|
6373
|
-
"[SpaceParticipant] Not a speaker yet; ignoring pushAudio."
|
|
6374
|
-
);
|
|
6088
|
+
this.logger.warn("[SpaceParticipant] Not a speaker yet; ignoring pushAudio.");
|
|
6375
6089
|
return;
|
|
6376
6090
|
}
|
|
6377
6091
|
this.janusClient.pushLocalAudio(samples, sampleRate);
|
|
@@ -6393,9 +6107,7 @@ var SpaceParticipant = class extends EventEmitter5 {
|
|
|
6393
6107
|
this.chatClient.on("newSpeakerAccepted", ({ userId }) => {
|
|
6394
6108
|
this.logger.debug("[SpaceParticipant] newSpeakerAccepted =>", userId);
|
|
6395
6109
|
if (!this.janusClient) {
|
|
6396
|
-
this.logger.warn(
|
|
6397
|
-
"[SpaceParticipant] No janusClient yet; ignoring new speaker..."
|
|
6398
|
-
);
|
|
6110
|
+
this.logger.warn("[SpaceParticipant] No janusClient yet; ignoring new speaker...");
|
|
6399
6111
|
return;
|
|
6400
6112
|
}
|
|
6401
6113
|
if (userId === this.janusClient.getHandleId()) {
|
|
@@ -6444,6 +6156,9 @@ var SpaceParticipant = class extends EventEmitter5 {
|
|
|
6444
6156
|
}
|
|
6445
6157
|
};
|
|
6446
6158
|
|
|
6159
|
+
// src/client/spaces/plugins/SttTtsPlugin.ts
|
|
6160
|
+
import { logger } from "@elizaos/core";
|
|
6161
|
+
|
|
6447
6162
|
// src/client/spaces/plugins/IdleMonitorPlugin.ts
|
|
6448
6163
|
var IdleMonitorPlugin = class {
|
|
6449
6164
|
/**
|
|
@@ -6481,10 +6196,7 @@ var IdleMonitorPlugin = class {
|
|
|
6481
6196
|
this.lastLocalAudioMs = Date.now();
|
|
6482
6197
|
originalPushAudio(samples, sampleRate);
|
|
6483
6198
|
};
|
|
6484
|
-
this.checkInterval = setInterval(
|
|
6485
|
-
() => this.checkIdle(),
|
|
6486
|
-
this.checkEveryMs
|
|
6487
|
-
);
|
|
6199
|
+
this.checkInterval = setInterval(() => this.checkIdle(), this.checkEveryMs);
|
|
6488
6200
|
}
|
|
6489
6201
|
/**
|
|
6490
6202
|
* Checks if we've exceeded idleTimeoutMs with no audio activity.
|
|
@@ -6495,9 +6207,7 @@ var IdleMonitorPlugin = class {
|
|
|
6495
6207
|
const lastAudio = Math.max(this.lastSpeakerAudioMs, this.lastLocalAudioMs);
|
|
6496
6208
|
const idleMs = now - lastAudio;
|
|
6497
6209
|
if (idleMs >= this.idleTimeoutMs) {
|
|
6498
|
-
this.logger?.warn(
|
|
6499
|
-
`[IdleMonitorPlugin] idleTimeout => no audio for ${idleMs}ms`
|
|
6500
|
-
);
|
|
6210
|
+
this.logger?.warn(`[IdleMonitorPlugin] idleTimeout => no audio for ${idleMs}ms`);
|
|
6501
6211
|
this.space?.emit("idleTimeout", { idleMs });
|
|
6502
6212
|
}
|
|
6503
6213
|
}
|
|
@@ -6525,10 +6235,10 @@ var IdleMonitorPlugin = class {
|
|
|
6525
6235
|
import { spawn } from "node:child_process";
|
|
6526
6236
|
import {
|
|
6527
6237
|
ChannelType,
|
|
6528
|
-
|
|
6238
|
+
EventType,
|
|
6529
6239
|
ModelType,
|
|
6530
6240
|
createUniqueUuid,
|
|
6531
|
-
logger
|
|
6241
|
+
logger as logger2
|
|
6532
6242
|
} from "@elizaos/core";
|
|
6533
6243
|
var VOLUME_WINDOW_SIZE = 100;
|
|
6534
6244
|
var SPEAKING_THRESHOLD = 0.05;
|
|
@@ -6549,12 +6259,10 @@ var SttTtsPlugin2 = class {
|
|
|
6549
6259
|
this.ttsAbortController = null;
|
|
6550
6260
|
}
|
|
6551
6261
|
onAttach(_space) {
|
|
6552
|
-
|
|
6262
|
+
logger2.log("[SttTtsPlugin] onAttach => space was attached");
|
|
6553
6263
|
}
|
|
6554
6264
|
async init(params) {
|
|
6555
|
-
|
|
6556
|
-
"[SttTtsPlugin] init => Space fully ready. Subscribing to events."
|
|
6557
|
-
);
|
|
6265
|
+
logger2.log("[SttTtsPlugin] init => Space fully ready. Subscribing to events.");
|
|
6558
6266
|
this.space = params.space;
|
|
6559
6267
|
this.janus = this.space?.janusClient;
|
|
6560
6268
|
const config = params.pluginConfig;
|
|
@@ -6589,13 +6297,10 @@ var SttTtsPlugin2 = class {
|
|
|
6589
6297
|
arr.push(data.samples);
|
|
6590
6298
|
if (!this.isSpeaking) {
|
|
6591
6299
|
this.userSpeakingTimer = setTimeout(() => {
|
|
6592
|
-
|
|
6593
|
-
"[SttTtsPlugin] start processing audio for user =>",
|
|
6594
|
-
data.userId
|
|
6595
|
-
);
|
|
6300
|
+
logger2.log("[SttTtsPlugin] start processing audio for user =>", data.userId);
|
|
6596
6301
|
this.userSpeakingTimer = null;
|
|
6597
6302
|
this.processAudio(data.userId).catch(
|
|
6598
|
-
(err) =>
|
|
6303
|
+
(err) => logger2.error("[SttTtsPlugin] handleSilence error =>", err)
|
|
6599
6304
|
);
|
|
6600
6305
|
}, SILENCE_DETECTION_THRESHOLD_MS);
|
|
6601
6306
|
} else {
|
|
@@ -6620,7 +6325,7 @@ var SttTtsPlugin2 = class {
|
|
|
6620
6325
|
if (this.ttsAbortController) {
|
|
6621
6326
|
this.ttsAbortController.abort();
|
|
6622
6327
|
this.isSpeaking = false;
|
|
6623
|
-
|
|
6328
|
+
logger2.log("[SttTtsPlugin] TTS playback interrupted");
|
|
6624
6329
|
}
|
|
6625
6330
|
}
|
|
6626
6331
|
}
|
|
@@ -6666,16 +6371,14 @@ var SttTtsPlugin2 = class {
|
|
|
6666
6371
|
}
|
|
6667
6372
|
this.isProcessingAudio = true;
|
|
6668
6373
|
try {
|
|
6669
|
-
|
|
6374
|
+
logger2.log("[SttTtsPlugin] Starting audio processing for user:", userId);
|
|
6670
6375
|
const chunks = this.pcmBuffers.get(userId) || [];
|
|
6671
6376
|
this.pcmBuffers.clear();
|
|
6672
6377
|
if (!chunks.length) {
|
|
6673
|
-
|
|
6378
|
+
logger2.warn("[SttTtsPlugin] No audio chunks for user =>", userId);
|
|
6674
6379
|
return;
|
|
6675
6380
|
}
|
|
6676
|
-
|
|
6677
|
-
`[SttTtsPlugin] Flushing STT buffer for user=${userId}, chunks=${chunks.length}`
|
|
6678
|
-
);
|
|
6381
|
+
logger2.log(`[SttTtsPlugin] Flushing STT buffer for user=${userId}, chunks=${chunks.length}`);
|
|
6679
6382
|
const totalLen = chunks.reduce((acc, c) => acc + c.length, 0);
|
|
6680
6383
|
const merged = new Int16Array(totalLen);
|
|
6681
6384
|
let offset = 0;
|
|
@@ -6684,19 +6387,16 @@ var SttTtsPlugin2 = class {
|
|
|
6684
6387
|
offset += c.length;
|
|
6685
6388
|
}
|
|
6686
6389
|
const wavBuffer = await this.convertPcmToWavInMemory(merged, 48e3);
|
|
6687
|
-
const sttText = await this.runtime.useModel(
|
|
6688
|
-
|
|
6689
|
-
wavBuffer
|
|
6690
|
-
);
|
|
6691
|
-
logger.log(`[SttTtsPlugin] Transcription result: "${sttText}"`);
|
|
6390
|
+
const sttText = await this.runtime.useModel(ModelType.TRANSCRIPTION, wavBuffer);
|
|
6391
|
+
logger2.log(`[SttTtsPlugin] Transcription result: "${sttText}"`);
|
|
6692
6392
|
if (!sttText || !sttText.trim()) {
|
|
6693
|
-
|
|
6393
|
+
logger2.warn("[SttTtsPlugin] No speech recognized for user =>", userId);
|
|
6694
6394
|
return;
|
|
6695
6395
|
}
|
|
6696
|
-
|
|
6396
|
+
logger2.log(`[SttTtsPlugin] STT => user=${userId}, text="${sttText}"`);
|
|
6697
6397
|
await this.handleUserMessage(sttText, userId);
|
|
6698
6398
|
} catch (error) {
|
|
6699
|
-
|
|
6399
|
+
logger2.error("[SttTtsPlugin] processAudio error =>", error);
|
|
6700
6400
|
} finally {
|
|
6701
6401
|
this.isProcessingAudio = false;
|
|
6702
6402
|
}
|
|
@@ -6709,7 +6409,7 @@ var SttTtsPlugin2 = class {
|
|
|
6709
6409
|
if (!this.isSpeaking) {
|
|
6710
6410
|
this.isSpeaking = true;
|
|
6711
6411
|
this.processTtsQueue().catch((err) => {
|
|
6712
|
-
|
|
6412
|
+
logger2.error("[SttTtsPlugin] processTtsQueue error =>", err);
|
|
6713
6413
|
});
|
|
6714
6414
|
}
|
|
6715
6415
|
}
|
|
@@ -6723,22 +6423,19 @@ var SttTtsPlugin2 = class {
|
|
|
6723
6423
|
this.ttsAbortController = new AbortController();
|
|
6724
6424
|
const { signal } = this.ttsAbortController;
|
|
6725
6425
|
try {
|
|
6726
|
-
const responseStream = await this.runtime.useModel(
|
|
6727
|
-
ModelType.TEXT_TO_SPEECH,
|
|
6728
|
-
text
|
|
6729
|
-
);
|
|
6426
|
+
const responseStream = await this.runtime.useModel(ModelType.TEXT_TO_SPEECH, text);
|
|
6730
6427
|
if (!responseStream) {
|
|
6731
|
-
|
|
6428
|
+
logger2.error("[SttTtsPlugin] TTS responseStream is null");
|
|
6732
6429
|
continue;
|
|
6733
6430
|
}
|
|
6734
|
-
|
|
6431
|
+
logger2.log("[SttTtsPlugin] Received ElevenLabs TTS stream");
|
|
6735
6432
|
await this.streamTtsStreamToJanus(responseStream, 48e3, signal);
|
|
6736
6433
|
if (signal.aborted) {
|
|
6737
|
-
|
|
6434
|
+
logger2.log("[SttTtsPlugin] TTS interrupted after streaming");
|
|
6738
6435
|
return;
|
|
6739
6436
|
}
|
|
6740
6437
|
} catch (err) {
|
|
6741
|
-
|
|
6438
|
+
logger2.error("[SttTtsPlugin] TTS streaming error =>", err);
|
|
6742
6439
|
} finally {
|
|
6743
6440
|
this.ttsAbortController = null;
|
|
6744
6441
|
}
|
|
@@ -6753,10 +6450,7 @@ var SttTtsPlugin2 = class {
|
|
|
6753
6450
|
return null;
|
|
6754
6451
|
}
|
|
6755
6452
|
const numericId = userId.replace("tw-", "");
|
|
6756
|
-
const roomId = createUniqueUuid(
|
|
6757
|
-
this.runtime,
|
|
6758
|
-
`twitter_generate_room-${this.spaceId}`
|
|
6759
|
-
);
|
|
6453
|
+
const roomId = createUniqueUuid(this.runtime, `twitter_generate_room-${this.spaceId}`);
|
|
6760
6454
|
const userUuid = createUniqueUuid(this.runtime, numericId);
|
|
6761
6455
|
const entity = await this.runtime.getEntityById(userUuid);
|
|
6762
6456
|
if (!entity) {
|
|
@@ -6776,10 +6470,7 @@ var SttTtsPlugin2 = class {
|
|
|
6776
6470
|
});
|
|
6777
6471
|
await this.runtime.ensureParticipantInRoom(userUuid, roomId);
|
|
6778
6472
|
const memory = {
|
|
6779
|
-
id: createUniqueUuid(
|
|
6780
|
-
this.runtime,
|
|
6781
|
-
`${roomId}-voice-message-${Date.now()}`
|
|
6782
|
-
),
|
|
6473
|
+
id: createUniqueUuid(this.runtime, `${roomId}-voice-message-${Date.now()}`),
|
|
6783
6474
|
agentId: this.runtime.agentId,
|
|
6784
6475
|
content: {
|
|
6785
6476
|
text: userText,
|
|
@@ -6792,10 +6483,7 @@ var SttTtsPlugin2 = class {
|
|
|
6792
6483
|
const callback = async (content, _files = []) => {
|
|
6793
6484
|
try {
|
|
6794
6485
|
const responseMemory = {
|
|
6795
|
-
id: createUniqueUuid(
|
|
6796
|
-
this.runtime,
|
|
6797
|
-
`${memory.id}-voice-response-${Date.now()}`
|
|
6798
|
-
),
|
|
6486
|
+
id: createUniqueUuid(this.runtime, `${memory.id}-voice-response-${Date.now()}`),
|
|
6799
6487
|
entityId: this.runtime.agentId,
|
|
6800
6488
|
agentId: this.runtime.agentId,
|
|
6801
6489
|
content: {
|
|
@@ -6819,7 +6507,7 @@ var SttTtsPlugin2 = class {
|
|
|
6819
6507
|
return [];
|
|
6820
6508
|
}
|
|
6821
6509
|
};
|
|
6822
|
-
this.runtime.emitEvent(
|
|
6510
|
+
this.runtime.emitEvent(EventType.VOICE_MESSAGE_RECEIVED, {
|
|
6823
6511
|
runtime: this.runtime,
|
|
6824
6512
|
message: memory,
|
|
6825
6513
|
callback
|
|
@@ -6852,11 +6540,7 @@ var SttTtsPlugin2 = class {
|
|
|
6852
6540
|
reject(new Error(`ffmpeg error code=${code}`));
|
|
6853
6541
|
return;
|
|
6854
6542
|
}
|
|
6855
|
-
const samples = new Int16Array(
|
|
6856
|
-
raw.buffer,
|
|
6857
|
-
raw.byteOffset,
|
|
6858
|
-
raw.byteLength / 2
|
|
6859
|
-
);
|
|
6543
|
+
const samples = new Int16Array(raw.buffer, raw.byteOffset, raw.byteLength / 2);
|
|
6860
6544
|
resolve(samples);
|
|
6861
6545
|
});
|
|
6862
6546
|
ff.stdin.write(mp3Buf);
|
|
@@ -6871,7 +6555,7 @@ var SttTtsPlugin2 = class {
|
|
|
6871
6555
|
const FRAME_SIZE = Math.floor(sampleRate * 0.01);
|
|
6872
6556
|
for (let offset = 0; offset + FRAME_SIZE <= samples.length; offset += FRAME_SIZE) {
|
|
6873
6557
|
if (this.ttsAbortController?.signal.aborted) {
|
|
6874
|
-
|
|
6558
|
+
logger2.log("[SttTtsPlugin] streamToJanus interrupted");
|
|
6875
6559
|
return;
|
|
6876
6560
|
}
|
|
6877
6561
|
const frame = new Int16Array(FRAME_SIZE);
|
|
@@ -6885,7 +6569,7 @@ var SttTtsPlugin2 = class {
|
|
|
6885
6569
|
return new Promise((resolve, reject) => {
|
|
6886
6570
|
stream.on("data", (chunk) => {
|
|
6887
6571
|
if (signal.aborted) {
|
|
6888
|
-
|
|
6572
|
+
logger2.log("[SttTtsPlugin] Stream aborted, stopping playback");
|
|
6889
6573
|
stream.destroy();
|
|
6890
6574
|
reject(new Error("TTS streaming aborted"));
|
|
6891
6575
|
return;
|
|
@@ -6894,7 +6578,7 @@ var SttTtsPlugin2 = class {
|
|
|
6894
6578
|
});
|
|
6895
6579
|
stream.on("end", async () => {
|
|
6896
6580
|
if (signal.aborted) {
|
|
6897
|
-
|
|
6581
|
+
logger2.log("[SttTtsPlugin] Stream ended but was aborted");
|
|
6898
6582
|
return reject(new Error("TTS streaming aborted"));
|
|
6899
6583
|
}
|
|
6900
6584
|
const mp3Buffer = Buffer.concat(chunks);
|
|
@@ -6907,13 +6591,13 @@ var SttTtsPlugin2 = class {
|
|
|
6907
6591
|
}
|
|
6908
6592
|
});
|
|
6909
6593
|
stream.on("error", (error) => {
|
|
6910
|
-
|
|
6594
|
+
logger2.error("[SttTtsPlugin] Error in TTS stream", error);
|
|
6911
6595
|
reject(error);
|
|
6912
6596
|
});
|
|
6913
6597
|
});
|
|
6914
6598
|
}
|
|
6915
6599
|
cleanup() {
|
|
6916
|
-
|
|
6600
|
+
logger2.log("[SttTtsPlugin] cleanup => releasing resources");
|
|
6917
6601
|
this.pcmBuffers.clear();
|
|
6918
6602
|
this.userSpeakingTimer = null;
|
|
6919
6603
|
this.ttsQueue = [];
|
|
@@ -6930,7 +6614,7 @@ import {
|
|
|
6930
6614
|
ModelType as ModelType2,
|
|
6931
6615
|
composePrompt,
|
|
6932
6616
|
createUniqueUuid as createUniqueUuid2,
|
|
6933
|
-
logger as
|
|
6617
|
+
logger as logger3
|
|
6934
6618
|
} from "@elizaos/core";
|
|
6935
6619
|
async function fetchMediaData(attachments) {
|
|
6936
6620
|
return Promise.all(
|
|
@@ -6945,15 +6629,11 @@ async function fetchMediaData(attachments) {
|
|
|
6945
6629
|
return { data: mediaBuffer, mediaType };
|
|
6946
6630
|
}
|
|
6947
6631
|
if (fs.existsSync(attachment.url)) {
|
|
6948
|
-
const mediaBuffer = await fs.promises.readFile(
|
|
6949
|
-
path.resolve(attachment.url)
|
|
6950
|
-
);
|
|
6632
|
+
const mediaBuffer = await fs.promises.readFile(path.resolve(attachment.url));
|
|
6951
6633
|
const mediaType = attachment.contentType || "image/png";
|
|
6952
6634
|
return { data: mediaBuffer, mediaType };
|
|
6953
6635
|
}
|
|
6954
|
-
throw new Error(
|
|
6955
|
-
`File not found: ${attachment.url}. Make sure the path is correct.`
|
|
6956
|
-
);
|
|
6636
|
+
throw new Error(`File not found: ${attachment.url}. Make sure the path is correct.`);
|
|
6957
6637
|
})
|
|
6958
6638
|
);
|
|
6959
6639
|
}
|
|
@@ -6979,7 +6659,7 @@ Only return the text, no additional formatting.
|
|
|
6979
6659
|
});
|
|
6980
6660
|
return output.trim();
|
|
6981
6661
|
} catch (err) {
|
|
6982
|
-
|
|
6662
|
+
logger3.error("[generateFiller] Error generating filler:", err);
|
|
6983
6663
|
return "";
|
|
6984
6664
|
}
|
|
6985
6665
|
}
|
|
@@ -6987,7 +6667,7 @@ async function speakFiller(runtime, sttTtsPlugin, fillerType, sleepAfterMs = 3e3
|
|
|
6987
6667
|
if (!sttTtsPlugin) return;
|
|
6988
6668
|
const text = await generateFiller(runtime, fillerType);
|
|
6989
6669
|
if (!text) return;
|
|
6990
|
-
|
|
6670
|
+
logger3.log(`[Space] Filler (${fillerType}) => ${text}`);
|
|
6991
6671
|
await sttTtsPlugin.speakText(text);
|
|
6992
6672
|
if (sleepAfterMs > 0) {
|
|
6993
6673
|
await new Promise((res) => setTimeout(res, sleepAfterMs));
|
|
@@ -7013,7 +6693,7 @@ Example:
|
|
|
7013
6693
|
const topics = response.split(",").map((t) => t.trim()).filter(Boolean);
|
|
7014
6694
|
return topics.length ? topics : ["Random Tech Chat", "AI Thoughts"];
|
|
7015
6695
|
} catch (err) {
|
|
7016
|
-
|
|
6696
|
+
logger3.error("[generateTopicsIfEmpty] GPT error =>", err);
|
|
7017
6697
|
return ["Random Tech Chat", "AI Thoughts"];
|
|
7018
6698
|
}
|
|
7019
6699
|
}
|
|
@@ -7022,9 +6702,7 @@ async function isAgentInSpace(client, spaceId) {
|
|
|
7022
6702
|
const agentName = client.state.TWITTER_USERNAME;
|
|
7023
6703
|
return space.participants.listeners.some(
|
|
7024
6704
|
(participant) => participant.twitter_screen_name === agentName
|
|
7025
|
-
) || space.participants.speakers.some(
|
|
7026
|
-
(participant) => participant.twitter_screen_name === agentName
|
|
7027
|
-
);
|
|
6705
|
+
) || space.participants.speakers.some((participant) => participant.twitter_screen_name === agentName);
|
|
7028
6706
|
}
|
|
7029
6707
|
|
|
7030
6708
|
// src/spaces.ts
|
|
@@ -7058,7 +6736,7 @@ var TwitterSpaceClient = class {
|
|
|
7058
6736
|
* Periodic check to launch or manage space
|
|
7059
6737
|
*/
|
|
7060
6738
|
async startPeriodicSpaceCheck() {
|
|
7061
|
-
|
|
6739
|
+
logger4.log("[Space] Starting periodic check routine...");
|
|
7062
6740
|
const interval = 2e4;
|
|
7063
6741
|
const routine = async () => {
|
|
7064
6742
|
try {
|
|
@@ -7079,7 +6757,7 @@ var TwitterSpaceClient = class {
|
|
|
7079
6757
|
}
|
|
7080
6758
|
this.checkInterval = setTimeout(routine, interval);
|
|
7081
6759
|
} catch (error) {
|
|
7082
|
-
|
|
6760
|
+
logger4.error("[Space] Error in routine =>", error);
|
|
7083
6761
|
this.checkInterval = setTimeout(routine, interval);
|
|
7084
6762
|
}
|
|
7085
6763
|
};
|
|
@@ -7096,11 +6774,11 @@ var TwitterSpaceClient = class {
|
|
|
7096
6774
|
if (this.lastSpaceEndedAt) {
|
|
7097
6775
|
const minIntervalMs = (this.decisionOptions.minIntervalBetweenSpacesMinutes ?? 60) * 6e4;
|
|
7098
6776
|
if (now - this.lastSpaceEndedAt < minIntervalMs) {
|
|
7099
|
-
|
|
6777
|
+
logger4.log("[Space] Too soon since last space => skip");
|
|
7100
6778
|
return false;
|
|
7101
6779
|
}
|
|
7102
6780
|
}
|
|
7103
|
-
|
|
6781
|
+
logger4.log("[Space] Deciding to launch a new Space...");
|
|
7104
6782
|
return true;
|
|
7105
6783
|
}
|
|
7106
6784
|
async generateSpaceConfig() {
|
|
@@ -7120,7 +6798,7 @@ var TwitterSpaceClient = class {
|
|
|
7120
6798
|
};
|
|
7121
6799
|
}
|
|
7122
6800
|
async startSpace(config) {
|
|
7123
|
-
|
|
6801
|
+
logger4.log("[Space] Starting a new Twitter Space...");
|
|
7124
6802
|
try {
|
|
7125
6803
|
this.currentSpace = new Space(this.twitterClient);
|
|
7126
6804
|
this.spaceStatus = "idle" /* IDLE */;
|
|
@@ -7166,52 +6844,43 @@ var TwitterSpaceClient = class {
|
|
|
7166
6844
|
}
|
|
7167
6845
|
});
|
|
7168
6846
|
if (this.runtime.getModel(ModelType3.TEXT_TO_SPEECH) && this.runtime.getModel(ModelType3.TRANSCRIPTION)) {
|
|
7169
|
-
|
|
6847
|
+
logger4.log("[Space] Using SttTtsPlugin");
|
|
7170
6848
|
this.currentSpace.use(this.sttTtsPlugin, {
|
|
7171
6849
|
runtime: this.runtime,
|
|
7172
6850
|
spaceId: this.spaceId
|
|
7173
6851
|
});
|
|
7174
6852
|
}
|
|
7175
6853
|
if (this.decisionOptions.enableIdleMonitor) {
|
|
7176
|
-
|
|
6854
|
+
logger4.log("[Space] Using IdleMonitorPlugin");
|
|
7177
6855
|
this.currentSpace.use(
|
|
7178
|
-
new IdleMonitorPlugin(
|
|
7179
|
-
this.decisionOptions.idleKickTimeoutMs ?? 6e4,
|
|
7180
|
-
1e4
|
|
7181
|
-
)
|
|
6856
|
+
new IdleMonitorPlugin(this.decisionOptions.idleKickTimeoutMs ?? 6e4, 1e4)
|
|
7182
6857
|
);
|
|
7183
6858
|
}
|
|
7184
6859
|
this.spaceStatus = "hosting" /* HOSTING */;
|
|
7185
6860
|
const spaceUrl = broadcastInfo.share_url.replace("broadcasts", "spaces");
|
|
7186
6861
|
await this.twitterClient.sendTweet(spaceUrl);
|
|
7187
|
-
|
|
6862
|
+
logger4.log(`[Space] Space started => ${spaceUrl}`);
|
|
7188
6863
|
await speakFiller(this.client.runtime, this.sttTtsPlugin, "WELCOME");
|
|
7189
6864
|
this.currentSpace.on("occupancyUpdate", (update) => {
|
|
7190
|
-
|
|
6865
|
+
logger4.log(`[Space] Occupancy => ${update.occupancy} participant(s).`);
|
|
7191
6866
|
});
|
|
7192
6867
|
this.currentSpace.on("speakerRequest", async (req) => {
|
|
7193
|
-
|
|
7194
|
-
`[Space] Speaker request from @${req.username} (${req.userId}).`
|
|
7195
|
-
);
|
|
6868
|
+
logger4.log(`[Space] Speaker request from @${req.username} (${req.userId}).`);
|
|
7196
6869
|
await this.handleSpeakerRequest(req);
|
|
7197
6870
|
});
|
|
7198
6871
|
this.currentSpace.on("idleTimeout", async (info) => {
|
|
7199
|
-
|
|
7200
|
-
await speakFiller(
|
|
7201
|
-
this.client.runtime,
|
|
7202
|
-
this.sttTtsPlugin,
|
|
7203
|
-
"IDLE_ENDING"
|
|
7204
|
-
);
|
|
6872
|
+
logger4.log(`[Space] idleTimeout => no audio for ${info.idleMs} ms.`);
|
|
6873
|
+
await speakFiller(this.client.runtime, this.sttTtsPlugin, "IDLE_ENDING");
|
|
7205
6874
|
await this.stopSpace();
|
|
7206
6875
|
});
|
|
7207
6876
|
process.on("SIGINT", async () => {
|
|
7208
|
-
|
|
6877
|
+
logger4.log("[Space] SIGINT => stopping space");
|
|
7209
6878
|
await speakFiller(this.client.runtime, this.sttTtsPlugin, "CLOSING");
|
|
7210
6879
|
await this.stopSpace();
|
|
7211
6880
|
process.exit(0);
|
|
7212
6881
|
});
|
|
7213
6882
|
} catch (error) {
|
|
7214
|
-
|
|
6883
|
+
logger4.error("[Space] Error launching Space =>", error);
|
|
7215
6884
|
this.spaceStatus = "idle" /* IDLE */;
|
|
7216
6885
|
throw error;
|
|
7217
6886
|
}
|
|
@@ -7222,9 +6891,7 @@ var TwitterSpaceClient = class {
|
|
|
7222
6891
|
async manageCurrentSpace() {
|
|
7223
6892
|
if (!this.spaceId || !this.currentSpace) return;
|
|
7224
6893
|
try {
|
|
7225
|
-
const audioSpace = await this.twitterClient.getAudioSpaceById(
|
|
7226
|
-
this.spaceId
|
|
7227
|
-
);
|
|
6894
|
+
const audioSpace = await this.twitterClient.getAudioSpaceById(this.spaceId);
|
|
7228
6895
|
const { participants } = audioSpace;
|
|
7229
6896
|
const numSpeakers = participants.speakers?.length || 0;
|
|
7230
6897
|
const totalListeners = participants.listeners?.length || 0;
|
|
@@ -7234,36 +6901,25 @@ var TwitterSpaceClient = class {
|
|
|
7234
6901
|
const speaker = this.activeSpeakers[i];
|
|
7235
6902
|
const elapsed = now - speaker.startTime;
|
|
7236
6903
|
if (elapsed > maxDur) {
|
|
7237
|
-
|
|
7238
|
-
`[Space] Speaker @${speaker.username} exceeded max duration => removing`
|
|
7239
|
-
);
|
|
6904
|
+
logger4.log(`[Space] Speaker @${speaker.username} exceeded max duration => removing`);
|
|
7240
6905
|
await this.removeSpeaker(speaker.userId);
|
|
7241
6906
|
this.activeSpeakers.splice(i, 1);
|
|
7242
|
-
await speakFiller(
|
|
7243
|
-
this.client.runtime,
|
|
7244
|
-
this.sttTtsPlugin,
|
|
7245
|
-
"SPEAKER_LEFT"
|
|
7246
|
-
);
|
|
6907
|
+
await speakFiller(this.client.runtime, this.sttTtsPlugin, "SPEAKER_LEFT");
|
|
7247
6908
|
}
|
|
7248
6909
|
}
|
|
7249
6910
|
await this.acceptSpeakersFromQueueIfNeeded();
|
|
7250
6911
|
if (numSpeakers > (this.decisionOptions.maxSpeakers ?? 1)) {
|
|
7251
|
-
|
|
6912
|
+
logger4.log("[Space] More than maxSpeakers => removing extras...");
|
|
7252
6913
|
await this.kickExtraSpeakers(participants.speakers);
|
|
7253
6914
|
}
|
|
7254
6915
|
const elapsedMinutes = (now - (this.startedAt || 0)) / 6e4;
|
|
7255
6916
|
if (elapsedMinutes > (this.decisionOptions.typicalDurationMinutes ?? 30) || numSpeakers === 0 && totalListeners === 0 && elapsedMinutes > 5) {
|
|
7256
|
-
|
|
7257
|
-
await speakFiller(
|
|
7258
|
-
this.client.runtime,
|
|
7259
|
-
this.sttTtsPlugin,
|
|
7260
|
-
"CLOSING",
|
|
7261
|
-
4e3
|
|
7262
|
-
);
|
|
6917
|
+
logger4.log("[Space] Condition met => stopping the Space...");
|
|
6918
|
+
await speakFiller(this.client.runtime, this.sttTtsPlugin, "CLOSING", 4e3);
|
|
7263
6919
|
await this.stopSpace();
|
|
7264
6920
|
}
|
|
7265
6921
|
} catch (error) {
|
|
7266
|
-
|
|
6922
|
+
logger4.error("[Space] Error in manageCurrentSpace =>", error);
|
|
7267
6923
|
}
|
|
7268
6924
|
}
|
|
7269
6925
|
/**
|
|
@@ -7284,11 +6940,11 @@ var TwitterSpaceClient = class {
|
|
|
7284
6940
|
const audioSpace = await this.twitterClient.getAudioSpaceById(this.spaceId);
|
|
7285
6941
|
const janusSpeakers = audioSpace?.participants?.speakers || [];
|
|
7286
6942
|
if (janusSpeakers.length < (this.decisionOptions.maxSpeakers ?? 1)) {
|
|
7287
|
-
|
|
6943
|
+
logger4.log(`[Space] Accepting speaker @${req.username} now`);
|
|
7288
6944
|
await speakFiller(this.client.runtime, this.sttTtsPlugin, "PRE_ACCEPT");
|
|
7289
6945
|
await this.acceptSpeaker(req);
|
|
7290
6946
|
} else {
|
|
7291
|
-
|
|
6947
|
+
logger4.log(`[Space] Adding speaker @${req.username} to the queue`);
|
|
7292
6948
|
this.speakerQueue.push(req);
|
|
7293
6949
|
}
|
|
7294
6950
|
}
|
|
@@ -7302,18 +6958,18 @@ var TwitterSpaceClient = class {
|
|
|
7302
6958
|
username: req.username,
|
|
7303
6959
|
startTime: Date.now()
|
|
7304
6960
|
});
|
|
7305
|
-
|
|
6961
|
+
logger4.log(`[Space] Speaker @${req.username} is now live`);
|
|
7306
6962
|
} catch (err) {
|
|
7307
|
-
|
|
6963
|
+
logger4.error(`[Space] Error approving speaker @${req.username}:`, err);
|
|
7308
6964
|
}
|
|
7309
6965
|
}
|
|
7310
6966
|
async removeSpeaker(userId) {
|
|
7311
6967
|
if (!this.currentSpace) return;
|
|
7312
6968
|
try {
|
|
7313
6969
|
await this.currentSpace.removeSpeaker(userId);
|
|
7314
|
-
|
|
6970
|
+
logger4.log(`[Space] Removed speaker userId=${userId}`);
|
|
7315
6971
|
} catch (error) {
|
|
7316
|
-
|
|
6972
|
+
logger4.error(`[Space] Error removing speaker userId=${userId} =>`, error);
|
|
7317
6973
|
}
|
|
7318
6974
|
}
|
|
7319
6975
|
/**
|
|
@@ -7325,7 +6981,7 @@ var TwitterSpaceClient = class {
|
|
|
7325
6981
|
const ms = this.decisionOptions.maxSpeakers ?? 1;
|
|
7326
6982
|
const extras = speakers.slice(ms);
|
|
7327
6983
|
for (const sp of extras) {
|
|
7328
|
-
|
|
6984
|
+
logger4.log(`[Space] Removing extra speaker => userId=${sp.user_id}`);
|
|
7329
6985
|
await this.removeSpeaker(sp.user_id);
|
|
7330
6986
|
const idx = this.activeSpeakers.findIndex((s) => s.userId === sp.user_id);
|
|
7331
6987
|
if (idx !== -1) {
|
|
@@ -7334,13 +6990,12 @@ var TwitterSpaceClient = class {
|
|
|
7334
6990
|
}
|
|
7335
6991
|
}
|
|
7336
6992
|
async stopSpace() {
|
|
7337
|
-
if (!this.currentSpace || this.spaceStatus !== "hosting" /* HOSTING */)
|
|
7338
|
-
return;
|
|
6993
|
+
if (!this.currentSpace || this.spaceStatus !== "hosting" /* HOSTING */) return;
|
|
7339
6994
|
try {
|
|
7340
|
-
|
|
6995
|
+
logger4.log("[Space] Stopping the current Space...");
|
|
7341
6996
|
await this.currentSpace.stop();
|
|
7342
6997
|
} catch (err) {
|
|
7343
|
-
|
|
6998
|
+
logger4.error("[Space] Error stopping Space =>", err);
|
|
7344
6999
|
} finally {
|
|
7345
7000
|
this.spaceStatus = "idle" /* IDLE */;
|
|
7346
7001
|
this.spaceId = void 0;
|
|
@@ -7353,7 +7008,7 @@ var TwitterSpaceClient = class {
|
|
|
7353
7008
|
}
|
|
7354
7009
|
async startParticipant(spaceId) {
|
|
7355
7010
|
if (this.spaceStatus !== "idle" /* IDLE */) {
|
|
7356
|
-
|
|
7011
|
+
logger4.warn("currently hosting/participating a space");
|
|
7357
7012
|
return null;
|
|
7358
7013
|
}
|
|
7359
7014
|
this.spaceParticipant = new SpaceParticipant(this.client.twitterClient, {
|
|
@@ -7367,7 +7022,7 @@ var TwitterSpaceClient = class {
|
|
|
7367
7022
|
this.spaceStatus = "participating" /* PARTICIPATING */;
|
|
7368
7023
|
return spaceId;
|
|
7369
7024
|
} catch (error) {
|
|
7370
|
-
|
|
7025
|
+
logger4.error(`failed to join space ${error}`);
|
|
7371
7026
|
return null;
|
|
7372
7027
|
}
|
|
7373
7028
|
}
|
|
@@ -7383,14 +7038,12 @@ var TwitterSpaceClient = class {
|
|
|
7383
7038
|
return;
|
|
7384
7039
|
}
|
|
7385
7040
|
if (this.participantStatus === "listener" /* LISTENER */) {
|
|
7386
|
-
|
|
7387
|
-
"[SpaceParticipant] Checking if we should request to speak..."
|
|
7388
|
-
);
|
|
7041
|
+
logger4.log("[SpaceParticipant] Checking if we should request to speak...");
|
|
7389
7042
|
this.participantStatus = "pending" /* PENDING */;
|
|
7390
7043
|
const { sessionUUID } = await this.spaceParticipant.requestSpeaker();
|
|
7391
7044
|
const handleSpeakerRemove = async (evt) => {
|
|
7392
7045
|
if (evt.sessionUUID === sessionUUID) {
|
|
7393
|
-
|
|
7046
|
+
logger4.debug("[SpaceParticipant] Speaker removed:", evt);
|
|
7394
7047
|
try {
|
|
7395
7048
|
await this.spaceParticipant.removeFromSpeaker();
|
|
7396
7049
|
} catch (err) {
|
|
@@ -7412,31 +7065,20 @@ var TwitterSpaceClient = class {
|
|
|
7412
7065
|
this.participantStatus = "listener" /* LISTENER */;
|
|
7413
7066
|
try {
|
|
7414
7067
|
await this.spaceParticipant.cancelSpeakerRequest();
|
|
7415
|
-
|
|
7416
|
-
"[SpaceParticipant] Speaker request canceled after timeout or error."
|
|
7417
|
-
);
|
|
7068
|
+
logger4.debug("[SpaceParticipant] Speaker request canceled after timeout or error.");
|
|
7418
7069
|
} catch (cancelErr) {
|
|
7419
|
-
console.error(
|
|
7420
|
-
"[SpaceParticipant] Could not cancel the request =>",
|
|
7421
|
-
cancelErr
|
|
7422
|
-
);
|
|
7070
|
+
console.error("[SpaceParticipant] Could not cancel the request =>", cancelErr);
|
|
7423
7071
|
}
|
|
7424
7072
|
});
|
|
7425
7073
|
}
|
|
7426
7074
|
}
|
|
7427
7075
|
async stopParticipant() {
|
|
7428
|
-
if (!this.spaceParticipant || this.spaceStatus !== "participating" /* PARTICIPATING */)
|
|
7429
|
-
return;
|
|
7076
|
+
if (!this.spaceParticipant || this.spaceStatus !== "participating" /* PARTICIPATING */) return;
|
|
7430
7077
|
try {
|
|
7431
|
-
|
|
7432
|
-
"[SpaceParticipant] Stopping the current space participant..."
|
|
7433
|
-
);
|
|
7078
|
+
logger4.log("[SpaceParticipant] Stopping the current space participant...");
|
|
7434
7079
|
await this.spaceParticipant.leaveSpace();
|
|
7435
7080
|
} catch (err) {
|
|
7436
|
-
|
|
7437
|
-
"[SpaceParticipant] Error stopping space participant =>",
|
|
7438
|
-
err
|
|
7439
|
-
);
|
|
7081
|
+
logger4.error("[SpaceParticipant] Error stopping space participant =>", err);
|
|
7440
7082
|
} finally {
|
|
7441
7083
|
this.spaceStatus = "idle" /* IDLE */;
|
|
7442
7084
|
this.participantStatus = "listener" /* LISTENER */;
|
|
@@ -7457,7 +7099,7 @@ var TwitterSpaceClient = class {
|
|
|
7457
7099
|
participant.off("newSpeakerAccepted", handler);
|
|
7458
7100
|
try {
|
|
7459
7101
|
await participant.becomeSpeaker();
|
|
7460
|
-
|
|
7102
|
+
logger4.debug("[SpaceParticipant] Successfully became speaker!");
|
|
7461
7103
|
resolve();
|
|
7462
7104
|
} catch (err) {
|
|
7463
7105
|
reject(err);
|
|
@@ -7502,7 +7144,7 @@ var spaceJoin_default = {
|
|
|
7502
7144
|
description: "Join a Twitter Space to participate in live audio conversations.",
|
|
7503
7145
|
handler: async (runtime, message, state, _options, callback, responses) => {
|
|
7504
7146
|
if (!state) {
|
|
7505
|
-
|
|
7147
|
+
logger5.error("State is not available.");
|
|
7506
7148
|
return false;
|
|
7507
7149
|
}
|
|
7508
7150
|
for (const response of responses) {
|
|
@@ -7517,16 +7159,16 @@ var spaceJoin_default = {
|
|
|
7517
7159
|
const client = manager.clients.get(clientKey).client;
|
|
7518
7160
|
const spaceManager = manager.clients.get(clientKey).space;
|
|
7519
7161
|
if (!spaceManager) {
|
|
7520
|
-
|
|
7162
|
+
logger5.error("space action - no space manager found");
|
|
7521
7163
|
return false;
|
|
7522
7164
|
}
|
|
7523
7165
|
if (spaceManager.spaceStatus !== "idle" /* IDLE */) {
|
|
7524
|
-
|
|
7166
|
+
logger5.warn("currently hosting/participating a space");
|
|
7525
7167
|
return false;
|
|
7526
7168
|
}
|
|
7527
7169
|
const tweet = message.content.tweet;
|
|
7528
7170
|
if (!tweet) {
|
|
7529
|
-
|
|
7171
|
+
logger5.warn("space action - no tweet found in message");
|
|
7530
7172
|
return false;
|
|
7531
7173
|
}
|
|
7532
7174
|
async function joinSpaceByUrls(tweet2) {
|
|
@@ -7542,7 +7184,7 @@ var spaceJoin_default = {
|
|
|
7542
7184
|
return !!spaceJoined2;
|
|
7543
7185
|
}
|
|
7544
7186
|
} catch (error) {
|
|
7545
|
-
|
|
7187
|
+
logger5.error("Error joining Twitter Space:", error);
|
|
7546
7188
|
}
|
|
7547
7189
|
}
|
|
7548
7190
|
}
|
|
@@ -7557,7 +7199,7 @@ var spaceJoin_default = {
|
|
|
7557
7199
|
}
|
|
7558
7200
|
}
|
|
7559
7201
|
} catch (error) {
|
|
7560
|
-
|
|
7202
|
+
logger5.error(`Error fetching tweets for ${userName}:`, error);
|
|
7561
7203
|
}
|
|
7562
7204
|
return false;
|
|
7563
7205
|
}
|
|
@@ -7616,7 +7258,7 @@ var spaceJoin_default = {
|
|
|
7616
7258
|
import {
|
|
7617
7259
|
ChannelType as ChannelType4,
|
|
7618
7260
|
createUniqueUuid as createUniqueUuid4,
|
|
7619
|
-
logger as
|
|
7261
|
+
logger as logger6
|
|
7620
7262
|
} from "@elizaos/core";
|
|
7621
7263
|
var RequestQueue = class {
|
|
7622
7264
|
constructor() {
|
|
@@ -7720,9 +7362,7 @@ var _ClientBase = class _ClientBase {
|
|
|
7720
7362
|
* @returns {Promise<Tweet | undefined>} A Promise that resolves to the cached tweet, or undefined if the tweet is not found in the cache.
|
|
7721
7363
|
*/
|
|
7722
7364
|
async getCachedTweet(tweetId) {
|
|
7723
|
-
const cached = await this.runtime.getCache(
|
|
7724
|
-
`twitter/tweets/${tweetId}`
|
|
7725
|
-
);
|
|
7365
|
+
const cached = await this.runtime.getCache(`twitter/tweets/${tweetId}`);
|
|
7726
7366
|
if (!cached) {
|
|
7727
7367
|
return void 0;
|
|
7728
7368
|
}
|
|
@@ -7740,9 +7380,7 @@ var _ClientBase = class _ClientBase {
|
|
|
7740
7380
|
if (cachedTweet) {
|
|
7741
7381
|
return cachedTweet;
|
|
7742
7382
|
}
|
|
7743
|
-
const tweet = await this.requestQueue.add(
|
|
7744
|
-
() => this.twitterClient.getTweet(tweetId)
|
|
7745
|
-
);
|
|
7383
|
+
const tweet = await this.requestQueue.add(() => this.twitterClient.getTweet(tweetId));
|
|
7746
7384
|
await this.cacheTweet(tweet);
|
|
7747
7385
|
return tweet;
|
|
7748
7386
|
}
|
|
@@ -7768,11 +7406,7 @@ var _ClientBase = class _ClientBase {
|
|
|
7768
7406
|
parseTweet(raw, depth = 0, maxDepth = 3) {
|
|
7769
7407
|
const canRecurse = depth < maxDepth;
|
|
7770
7408
|
const quotedStatus = raw.quoted_status_result?.result && canRecurse ? this.parseTweet(raw.quoted_status_result.result, depth + 1, maxDepth) : void 0;
|
|
7771
|
-
const retweetedStatus = raw.retweeted_status_result?.result && canRecurse ? this.parseTweet(
|
|
7772
|
-
raw.retweeted_status_result.result,
|
|
7773
|
-
depth + 1,
|
|
7774
|
-
maxDepth
|
|
7775
|
-
) : void 0;
|
|
7409
|
+
const retweetedStatus = raw.retweeted_status_result?.result && canRecurse ? this.parseTweet(raw.retweeted_status_result.result, depth + 1, maxDepth) : void 0;
|
|
7776
7410
|
const t = {
|
|
7777
7411
|
bookmarkCount: raw.bookmarkCount ?? raw.legacy?.bookmark_count ?? void 0,
|
|
7778
7412
|
conversationId: raw.conversationId ?? raw.legacy?.conversation_id_str,
|
|
@@ -7812,9 +7446,7 @@ var _ClientBase = class _ClientBase {
|
|
|
7812
7446
|
urls: raw.urls ?? raw.legacy?.entities?.urls ?? [],
|
|
7813
7447
|
userId: raw.userId ?? raw.legacy?.user_id_str ?? void 0,
|
|
7814
7448
|
username: raw.username ?? raw.core?.user_results?.result?.legacy?.screen_name ?? void 0,
|
|
7815
|
-
videos: raw.videos ?? raw.legacy?.entities?.media?.filter(
|
|
7816
|
-
(media) => media.type === "video"
|
|
7817
|
-
) ?? [],
|
|
7449
|
+
videos: raw.videos ?? raw.legacy?.entities?.media?.filter((media) => media.type === "video") ?? [],
|
|
7818
7450
|
views: raw.views?.count ? Number(raw.views.count) : 0,
|
|
7819
7451
|
sensitiveContent: raw.sensitiveContent
|
|
7820
7452
|
};
|
|
@@ -7831,9 +7463,7 @@ var _ClientBase = class _ClientBase {
|
|
|
7831
7463
|
if (!username) missing.push("TWITTER_USERNAME");
|
|
7832
7464
|
if (!password) missing.push("TWITTER_PASSWORD");
|
|
7833
7465
|
if (!email) missing.push("TWITTER_EMAIL");
|
|
7834
|
-
throw new Error(
|
|
7835
|
-
`Missing required Twitter credentials: ${missing.join(", ")}`
|
|
7836
|
-
);
|
|
7466
|
+
throw new Error(`Missing required Twitter credentials: ${missing.join(", ")}`);
|
|
7837
7467
|
}
|
|
7838
7468
|
const maxRetries = 3;
|
|
7839
7469
|
let retryCount = 0;
|
|
@@ -7850,38 +7480,28 @@ var _ClientBase = class _ClientBase {
|
|
|
7850
7480
|
] : null;
|
|
7851
7481
|
const cachedCookies = await this.getCachedCookies(username) || createTwitterCookies(authToken, ct0, guestId);
|
|
7852
7482
|
if (cachedCookies) {
|
|
7853
|
-
|
|
7483
|
+
logger6.info("Using cached cookies");
|
|
7854
7484
|
await this.setCookiesFromArray(cachedCookies);
|
|
7855
7485
|
}
|
|
7856
|
-
|
|
7486
|
+
logger6.log("Waiting for Twitter login");
|
|
7857
7487
|
if (await this.twitterClient.isLoggedIn()) {
|
|
7858
|
-
|
|
7488
|
+
logger6.info("Successfully logged in.");
|
|
7859
7489
|
break;
|
|
7860
7490
|
}
|
|
7861
|
-
await this.twitterClient.login(
|
|
7862
|
-
username,
|
|
7863
|
-
password,
|
|
7864
|
-
email,
|
|
7865
|
-
twitter2faSecret
|
|
7866
|
-
);
|
|
7491
|
+
await this.twitterClient.login(username, password, email, twitter2faSecret);
|
|
7867
7492
|
if (await this.twitterClient.isLoggedIn()) {
|
|
7868
|
-
|
|
7869
|
-
|
|
7870
|
-
await this.cacheCookies(
|
|
7871
|
-
username,
|
|
7872
|
-
await this.twitterClient.getCookies()
|
|
7873
|
-
);
|
|
7493
|
+
logger6.info("Successfully logged in.");
|
|
7494
|
+
logger6.info("Caching cookies");
|
|
7495
|
+
await this.cacheCookies(username, await this.twitterClient.getCookies());
|
|
7874
7496
|
break;
|
|
7875
7497
|
}
|
|
7876
7498
|
} catch (error) {
|
|
7877
7499
|
lastError = error instanceof Error ? error : new Error(String(error));
|
|
7878
|
-
|
|
7879
|
-
`Login attempt ${retryCount + 1} failed: ${lastError.message}`
|
|
7880
|
-
);
|
|
7500
|
+
logger6.error(`Login attempt ${retryCount + 1} failed: ${lastError.message}`);
|
|
7881
7501
|
retryCount++;
|
|
7882
7502
|
if (retryCount < maxRetries) {
|
|
7883
7503
|
const delay = 2 ** retryCount * 1e3;
|
|
7884
|
-
|
|
7504
|
+
logger6.info(`Retrying in ${delay / 1e3} seconds...`);
|
|
7885
7505
|
await new Promise((resolve) => setTimeout(resolve, delay));
|
|
7886
7506
|
}
|
|
7887
7507
|
}
|
|
@@ -7893,8 +7513,8 @@ var _ClientBase = class _ClientBase {
|
|
|
7893
7513
|
}
|
|
7894
7514
|
this.profile = await this.fetchProfile(username);
|
|
7895
7515
|
if (this.profile) {
|
|
7896
|
-
|
|
7897
|
-
|
|
7516
|
+
logger6.log("Twitter user ID:", this.profile.id);
|
|
7517
|
+
logger6.log("Twitter loaded:", JSON.stringify(this.profile, null, 10));
|
|
7898
7518
|
this.profile = {
|
|
7899
7519
|
id: this.profile.id,
|
|
7900
7520
|
username: this.profile.username,
|
|
@@ -7909,18 +7529,15 @@ var _ClientBase = class _ClientBase {
|
|
|
7909
7529
|
await this.populateTimeline();
|
|
7910
7530
|
}
|
|
7911
7531
|
async fetchOwnPosts(count) {
|
|
7912
|
-
|
|
7913
|
-
const homeTimeline = await this.twitterClient.getUserTweets(
|
|
7914
|
-
this.profile.id,
|
|
7915
|
-
count
|
|
7916
|
-
);
|
|
7532
|
+
logger6.debug("fetching own posts");
|
|
7533
|
+
const homeTimeline = await this.twitterClient.getUserTweets(this.profile.id, count);
|
|
7917
7534
|
return homeTimeline.tweets.map((t) => this.parseTweet(t));
|
|
7918
7535
|
}
|
|
7919
7536
|
/**
|
|
7920
7537
|
* Fetch timeline for twitter account, optionally only from followed accounts
|
|
7921
7538
|
*/
|
|
7922
7539
|
async fetchHomeTimeline(count, following) {
|
|
7923
|
-
|
|
7540
|
+
logger6.debug("fetching home timeline");
|
|
7924
7541
|
const homeTimeline = following ? await this.twitterClient.fetchFollowingTimeline(count, []) : await this.twitterClient.fetchHomeTimeline(count, []);
|
|
7925
7542
|
const processedTimeline = homeTimeline.filter((t) => t.__typename !== "TweetWithVisibilityResults").map((tweet) => this.parseTweet(tweet));
|
|
7926
7543
|
return processedTimeline;
|
|
@@ -7933,27 +7550,22 @@ var _ClientBase = class _ClientBase {
|
|
|
7933
7550
|
try {
|
|
7934
7551
|
const result = await this.requestQueue.add(
|
|
7935
7552
|
async () => await Promise.race([
|
|
7936
|
-
this.twitterClient.fetchSearchTweets(
|
|
7937
|
-
query,
|
|
7938
|
-
maxTweets,
|
|
7939
|
-
searchMode,
|
|
7940
|
-
cursor
|
|
7941
|
-
),
|
|
7553
|
+
this.twitterClient.fetchSearchTweets(query, maxTweets, searchMode, cursor),
|
|
7942
7554
|
timeoutPromise
|
|
7943
7555
|
])
|
|
7944
7556
|
);
|
|
7945
7557
|
return result ?? { tweets: [] };
|
|
7946
7558
|
} catch (error) {
|
|
7947
|
-
|
|
7559
|
+
logger6.error("Error fetching search tweets:", error);
|
|
7948
7560
|
return { tweets: [] };
|
|
7949
7561
|
}
|
|
7950
7562
|
} catch (error) {
|
|
7951
|
-
|
|
7563
|
+
logger6.error("Error fetching search tweets:", error);
|
|
7952
7564
|
return { tweets: [] };
|
|
7953
7565
|
}
|
|
7954
7566
|
}
|
|
7955
7567
|
async populateTimeline() {
|
|
7956
|
-
|
|
7568
|
+
logger6.debug("populating timeline...");
|
|
7957
7569
|
const cachedTimeline = await this.getCachedTimeline();
|
|
7958
7570
|
if (cachedTimeline) {
|
|
7959
7571
|
const existingMemories2 = await this.runtime.getMemoriesByRoomIds({
|
|
@@ -7962,9 +7574,7 @@ var _ClientBase = class _ClientBase {
|
|
|
7962
7574
|
(tweet) => createUniqueUuid4(this.runtime, tweet.conversationId)
|
|
7963
7575
|
)
|
|
7964
7576
|
});
|
|
7965
|
-
const existingMemoryIds2 = new Set(
|
|
7966
|
-
existingMemories2.map((memory) => memory.id.toString())
|
|
7967
|
-
);
|
|
7577
|
+
const existingMemoryIds2 = new Set(existingMemories2.map((memory) => memory.id.toString()));
|
|
7968
7578
|
const someCachedTweetsExist = cachedTimeline.some(
|
|
7969
7579
|
(tweet) => existingMemoryIds2.has(createUniqueUuid4(this.runtime, tweet.id))
|
|
7970
7580
|
);
|
|
@@ -7973,7 +7583,7 @@ var _ClientBase = class _ClientBase {
|
|
|
7973
7583
|
(tweet) => tweet.userId !== this.profile.id && !existingMemoryIds2.has(createUniqueUuid4(this.runtime, tweet.id))
|
|
7974
7584
|
);
|
|
7975
7585
|
for (const tweet of tweetsToSave2) {
|
|
7976
|
-
|
|
7586
|
+
logger6.log("Saving Tweet", tweet.id);
|
|
7977
7587
|
if (tweet.userId === this.profile.id) {
|
|
7978
7588
|
continue;
|
|
7979
7589
|
}
|
|
@@ -8017,19 +7627,20 @@ var _ClientBase = class _ClientBase {
|
|
|
8017
7627
|
source: "twitter",
|
|
8018
7628
|
inReplyTo: tweet.inReplyToStatusId ? createUniqueUuid4(this.runtime, tweet.inReplyToStatusId) : void 0
|
|
8019
7629
|
};
|
|
8020
|
-
await this.runtime.createMemory(
|
|
8021
|
-
|
|
8022
|
-
|
|
8023
|
-
|
|
8024
|
-
|
|
8025
|
-
|
|
8026
|
-
|
|
8027
|
-
|
|
7630
|
+
await this.runtime.createMemory(
|
|
7631
|
+
{
|
|
7632
|
+
id: createUniqueUuid4(this.runtime, tweet.id),
|
|
7633
|
+
entityId,
|
|
7634
|
+
content,
|
|
7635
|
+
agentId: this.runtime.agentId,
|
|
7636
|
+
roomId,
|
|
7637
|
+
createdAt: tweet.timestamp * 1e3
|
|
7638
|
+
},
|
|
7639
|
+
"messages"
|
|
7640
|
+
);
|
|
8028
7641
|
await this.cacheTweet(tweet);
|
|
8029
7642
|
}
|
|
8030
|
-
|
|
8031
|
-
`Populated ${tweetsToSave2.length} missing tweets from the cache.`
|
|
8032
|
-
);
|
|
7643
|
+
logger6.log(`Populated ${tweetsToSave2.length} missing tweets from the cache.`);
|
|
8033
7644
|
return;
|
|
8034
7645
|
}
|
|
8035
7646
|
}
|
|
@@ -8051,17 +7662,15 @@ var _ClientBase = class _ClientBase {
|
|
|
8051
7662
|
tableName: "messages",
|
|
8052
7663
|
roomIds: Array.from(roomIds)
|
|
8053
7664
|
});
|
|
8054
|
-
const existingMemoryIds = new Set(
|
|
8055
|
-
existingMemories.map((memory) => memory.id)
|
|
8056
|
-
);
|
|
7665
|
+
const existingMemoryIds = new Set(existingMemories.map((memory) => memory.id));
|
|
8057
7666
|
const tweetsToSave = allTweets.filter(
|
|
8058
7667
|
(tweet) => tweet.userId !== this.profile.id && !existingMemoryIds.has(createUniqueUuid4(this.runtime, tweet.id))
|
|
8059
7668
|
);
|
|
8060
|
-
|
|
7669
|
+
logger6.debug({
|
|
8061
7670
|
processingTweets: tweetsToSave.map((tweet) => tweet.id).join(",")
|
|
8062
7671
|
});
|
|
8063
7672
|
for (const tweet of tweetsToSave) {
|
|
8064
|
-
|
|
7673
|
+
logger6.log("Saving Tweet", tweet.id);
|
|
8065
7674
|
if (tweet.userId === this.profile.id) {
|
|
8066
7675
|
continue;
|
|
8067
7676
|
}
|
|
@@ -8105,14 +7714,17 @@ var _ClientBase = class _ClientBase {
|
|
|
8105
7714
|
source: "twitter",
|
|
8106
7715
|
inReplyTo: tweet.inReplyToStatusId ? createUniqueUuid4(this.runtime, tweet.inReplyToStatusId) : void 0
|
|
8107
7716
|
};
|
|
8108
|
-
await this.runtime.createMemory(
|
|
8109
|
-
|
|
8110
|
-
|
|
8111
|
-
|
|
8112
|
-
|
|
8113
|
-
|
|
8114
|
-
|
|
8115
|
-
|
|
7717
|
+
await this.runtime.createMemory(
|
|
7718
|
+
{
|
|
7719
|
+
id: createUniqueUuid4(this.runtime, tweet.id),
|
|
7720
|
+
entityId,
|
|
7721
|
+
content,
|
|
7722
|
+
agentId: this.runtime.agentId,
|
|
7723
|
+
roomId,
|
|
7724
|
+
createdAt: tweet.timestamp * 1e3
|
|
7725
|
+
},
|
|
7726
|
+
"messages"
|
|
7727
|
+
);
|
|
8116
7728
|
await this.cacheTweet(tweet);
|
|
8117
7729
|
}
|
|
8118
7730
|
await this.cacheTimeline(timeline);
|
|
@@ -8133,7 +7745,7 @@ var _ClientBase = class _ClientBase {
|
|
|
8133
7745
|
unique: false
|
|
8134
7746
|
});
|
|
8135
7747
|
if (recentMessage.length > 0 && recentMessage[0].content === message.content) {
|
|
8136
|
-
|
|
7748
|
+
logger6.debug("Message already saved", recentMessage[0].id);
|
|
8137
7749
|
} else {
|
|
8138
7750
|
await this.runtime.createMemory(message, "messages");
|
|
8139
7751
|
}
|
|
@@ -8169,21 +7781,13 @@ var _ClientBase = class _ClientBase {
|
|
|
8169
7781
|
return cached;
|
|
8170
7782
|
}
|
|
8171
7783
|
async cacheTimeline(timeline) {
|
|
8172
|
-
await this.runtime.setCache(
|
|
8173
|
-
`twitter/${this.profile.username}/timeline`,
|
|
8174
|
-
timeline
|
|
8175
|
-
);
|
|
7784
|
+
await this.runtime.setCache(`twitter/${this.profile.username}/timeline`, timeline);
|
|
8176
7785
|
}
|
|
8177
7786
|
async cacheMentions(mentions) {
|
|
8178
|
-
await this.runtime.setCache(
|
|
8179
|
-
`twitter/${this.profile.username}/mentions`,
|
|
8180
|
-
mentions
|
|
8181
|
-
);
|
|
7787
|
+
await this.runtime.setCache(`twitter/${this.profile.username}/mentions`, mentions);
|
|
8182
7788
|
}
|
|
8183
7789
|
async getCachedCookies(username) {
|
|
8184
|
-
const cached = await this.runtime.getCache(
|
|
8185
|
-
`twitter/${username}/cookies`
|
|
8186
|
-
);
|
|
7790
|
+
const cached = await this.runtime.getCache(`twitter/${username}/cookies`);
|
|
8187
7791
|
if (!cached) {
|
|
8188
7792
|
return void 0;
|
|
8189
7793
|
}
|
|
@@ -8217,11 +7821,7 @@ var _ClientBase = class _ClientBase {
|
|
|
8217
7821
|
try {
|
|
8218
7822
|
const username = this.profile.username;
|
|
8219
7823
|
const mentionsResponse = await this.requestQueue.add(
|
|
8220
|
-
() => this.twitterClient.fetchSearchTweets(
|
|
8221
|
-
`@${username}`,
|
|
8222
|
-
100,
|
|
8223
|
-
1 /* Latest */
|
|
8224
|
-
)
|
|
7824
|
+
() => this.twitterClient.fetchSearchTweets(`@${username}`, 100, 1 /* Latest */)
|
|
8225
7825
|
);
|
|
8226
7826
|
return mentionsResponse.tweets.map((tweet) => ({
|
|
8227
7827
|
id: tweet.id,
|
|
@@ -8235,7 +7835,7 @@ var _ClientBase = class _ClientBase {
|
|
|
8235
7835
|
retweetId: tweet.retweetedStatus?.id
|
|
8236
7836
|
}));
|
|
8237
7837
|
} catch (error) {
|
|
8238
|
-
|
|
7838
|
+
logger6.error("Error fetching Twitter interactions:", error);
|
|
8239
7839
|
return [];
|
|
8240
7840
|
}
|
|
8241
7841
|
}
|
|
@@ -8249,11 +7849,11 @@ var TWITTER_SERVICE_NAME = "twitter";
|
|
|
8249
7849
|
// src/interactions.ts
|
|
8250
7850
|
import {
|
|
8251
7851
|
ChannelType as ChannelType5,
|
|
8252
|
-
|
|
7852
|
+
EventType as EventType2,
|
|
8253
7853
|
ModelType as ModelType4,
|
|
8254
7854
|
composePrompt as composePrompt2,
|
|
8255
7855
|
createUniqueUuid as createUniqueUuid5,
|
|
8256
|
-
logger as
|
|
7856
|
+
logger as logger7
|
|
8257
7857
|
} from "@elizaos/core";
|
|
8258
7858
|
|
|
8259
7859
|
// src/types.ts
|
|
@@ -8299,9 +7899,7 @@ var TwitterInteractionClient = class {
|
|
|
8299
7899
|
*/
|
|
8300
7900
|
async start() {
|
|
8301
7901
|
const handleTwitterInteractionsLoop = () => {
|
|
8302
|
-
const interactionInterval = (this.state?.TWITTER_POLL_INTERVAL || this.runtime.getSetting(
|
|
8303
|
-
"TWITTER_POLL_INTERVAL"
|
|
8304
|
-
) || 120) * 1e3;
|
|
7902
|
+
const interactionInterval = (this.state?.TWITTER_POLL_INTERVAL || this.runtime.getSetting("TWITTER_POLL_INTERVAL") || 120) * 1e3;
|
|
8305
7903
|
this.handleTwitterInteractions();
|
|
8306
7904
|
setTimeout(handleTwitterInteractionsLoop, interactionInterval);
|
|
8307
7905
|
};
|
|
@@ -8311,18 +7909,11 @@ var TwitterInteractionClient = class {
|
|
|
8311
7909
|
* Asynchronously handles Twitter interactions by checking for mentions, processing tweets, and updating the last checked tweet ID.
|
|
8312
7910
|
*/
|
|
8313
7911
|
async handleTwitterInteractions() {
|
|
8314
|
-
|
|
7912
|
+
logger7.log("Checking Twitter interactions");
|
|
8315
7913
|
const twitterUsername = this.client.profile?.username;
|
|
8316
7914
|
try {
|
|
8317
|
-
const mentionCandidates = (await this.client.fetchSearchTweets(
|
|
8318
|
-
|
|
8319
|
-
20,
|
|
8320
|
-
1 /* Latest */
|
|
8321
|
-
)).tweets;
|
|
8322
|
-
logger6.log(
|
|
8323
|
-
"Completed checking mentioned tweets:",
|
|
8324
|
-
mentionCandidates.length
|
|
8325
|
-
);
|
|
7915
|
+
const mentionCandidates = (await this.client.fetchSearchTweets(`@${twitterUsername}`, 20, 1 /* Latest */)).tweets;
|
|
7916
|
+
logger7.log("Completed checking mentioned tweets:", mentionCandidates.length);
|
|
8326
7917
|
let uniqueTweetCandidates = [...mentionCandidates];
|
|
8327
7918
|
uniqueTweetCandidates = uniqueTweetCandidates.sort((a, b) => a.id.localeCompare(b.id)).filter((tweet) => tweet.userId !== this.client.profile.id);
|
|
8328
7919
|
for (const tweet of uniqueTweetCandidates) {
|
|
@@ -8330,10 +7921,10 @@ var TwitterInteractionClient = class {
|
|
|
8330
7921
|
const tweetId = createUniqueUuid5(this.runtime, tweet.id);
|
|
8331
7922
|
const existingResponse = await this.runtime.getMemoryById(tweetId);
|
|
8332
7923
|
if (existingResponse) {
|
|
8333
|
-
|
|
7924
|
+
logger7.log(`Already responded to tweet ${tweet.id}, skipping`);
|
|
8334
7925
|
continue;
|
|
8335
7926
|
}
|
|
8336
|
-
|
|
7927
|
+
logger7.log("New Tweet found", tweet.permanentUrl);
|
|
8337
7928
|
const entityId = createUniqueUuid5(
|
|
8338
7929
|
this.runtime,
|
|
8339
7930
|
tweet.userId === this.client.profile.id ? this.runtime.agentId : tweet.userId
|
|
@@ -8399,11 +7990,11 @@ var TwitterInteractionClient = class {
|
|
|
8399
7990
|
},
|
|
8400
7991
|
source: "twitter",
|
|
8401
7992
|
callback: async (response) => {
|
|
8402
|
-
|
|
7993
|
+
logger7.info("Received message response:", response);
|
|
8403
7994
|
return [];
|
|
8404
7995
|
}
|
|
8405
7996
|
};
|
|
8406
|
-
this.runtime.emitEvent(
|
|
7997
|
+
this.runtime.emitEvent(EventType2.MESSAGE_RECEIVED, messagePayload);
|
|
8407
7998
|
const mentionPayload = {
|
|
8408
7999
|
runtime: this.runtime,
|
|
8409
8000
|
message: {
|
|
@@ -8418,7 +8009,7 @@ var TwitterInteractionClient = class {
|
|
|
8418
8009
|
},
|
|
8419
8010
|
source: "twitter",
|
|
8420
8011
|
callback: async (response) => {
|
|
8421
|
-
|
|
8012
|
+
logger7.info("Received mention response:", response);
|
|
8422
8013
|
return [];
|
|
8423
8014
|
}
|
|
8424
8015
|
};
|
|
@@ -8488,7 +8079,7 @@ var TwitterInteractionClient = class {
|
|
|
8488
8079
|
tweet: interaction.targetTweet
|
|
8489
8080
|
};
|
|
8490
8081
|
this.runtime.emitEvent("TWITTER_LIKE_RECEIVED" /* LIKE_RECEIVED */, likePayload);
|
|
8491
|
-
this.runtime.emitEvent(
|
|
8082
|
+
this.runtime.emitEvent(EventType2.REACTION_RECEIVED, {
|
|
8492
8083
|
...basePayload,
|
|
8493
8084
|
reaction: {
|
|
8494
8085
|
type: "like",
|
|
@@ -8508,7 +8099,7 @@ var TwitterInteractionClient = class {
|
|
|
8508
8099
|
retweetId: interaction.retweetId
|
|
8509
8100
|
};
|
|
8510
8101
|
this.runtime.emitEvent("TWITTER_RETWEET_RECEIVED" /* RETWEET_RECEIVED */, retweetPayload);
|
|
8511
|
-
this.runtime.emitEvent(
|
|
8102
|
+
this.runtime.emitEvent(EventType2.REACTION_RECEIVED, {
|
|
8512
8103
|
...basePayload,
|
|
8513
8104
|
reaction: {
|
|
8514
8105
|
type: "retweet",
|
|
@@ -8534,7 +8125,7 @@ var TwitterInteractionClient = class {
|
|
|
8534
8125
|
}
|
|
8535
8126
|
};
|
|
8536
8127
|
this.runtime.emitEvent("TWITTER_QUOTE_RECEIVED" /* QUOTE_RECEIVED */, quotePayload);
|
|
8537
|
-
this.runtime.emitEvent(
|
|
8128
|
+
this.runtime.emitEvent(EventType2.REACTION_RECEIVED, {
|
|
8538
8129
|
...basePayload,
|
|
8539
8130
|
reaction: {
|
|
8540
8131
|
type: "quote",
|
|
@@ -8569,9 +8160,9 @@ var TwitterInteractionClient = class {
|
|
|
8569
8160
|
}
|
|
8570
8161
|
};
|
|
8571
8162
|
await this.client.cacheLatestCheckedTweetId();
|
|
8572
|
-
|
|
8163
|
+
logger7.log("Finished checking Twitter interactions");
|
|
8573
8164
|
} catch (error) {
|
|
8574
|
-
|
|
8165
|
+
logger7.error("Error handling Twitter interactions:", error);
|
|
8575
8166
|
}
|
|
8576
8167
|
}
|
|
8577
8168
|
/**
|
|
@@ -8592,10 +8183,10 @@ var TwitterInteractionClient = class {
|
|
|
8592
8183
|
thread
|
|
8593
8184
|
}) {
|
|
8594
8185
|
if (!message.content.text) {
|
|
8595
|
-
|
|
8186
|
+
logger7.log("Skipping Tweet with no text", tweet.id);
|
|
8596
8187
|
return { text: "", actions: ["IGNORE"] };
|
|
8597
8188
|
}
|
|
8598
|
-
|
|
8189
|
+
logger7.log("Processing Tweet: ", tweet.id);
|
|
8599
8190
|
const formatTweet = (tweet2) => {
|
|
8600
8191
|
return ` ID: ${tweet2.id}
|
|
8601
8192
|
From: ${tweet2.name} (@${tweet2.username})
|
|
@@ -8603,9 +8194,7 @@ var TwitterInteractionClient = class {
|
|
|
8603
8194
|
};
|
|
8604
8195
|
const currentPost = formatTweet(tweet);
|
|
8605
8196
|
const formattedConversation = thread.map(
|
|
8606
|
-
(tweet2) => `@${tweet2.username} (${new Date(
|
|
8607
|
-
tweet2.timestamp * 1e3
|
|
8608
|
-
).toLocaleString("en-US", {
|
|
8197
|
+
(tweet2) => `@${tweet2.username} (${new Date(tweet2.timestamp * 1e3).toLocaleString("en-US", {
|
|
8609
8198
|
hour: "2-digit",
|
|
8610
8199
|
minute: "2-digit",
|
|
8611
8200
|
month: "short",
|
|
@@ -8616,14 +8205,11 @@ var TwitterInteractionClient = class {
|
|
|
8616
8205
|
const imageDescriptionsArray = [];
|
|
8617
8206
|
try {
|
|
8618
8207
|
for (const photo of tweet.photos) {
|
|
8619
|
-
const description = await this.runtime.useModel(
|
|
8620
|
-
ModelType4.IMAGE_DESCRIPTION,
|
|
8621
|
-
photo.url
|
|
8622
|
-
);
|
|
8208
|
+
const description = await this.runtime.useModel(ModelType4.IMAGE_DESCRIPTION, photo.url);
|
|
8623
8209
|
imageDescriptionsArray.push(description);
|
|
8624
8210
|
}
|
|
8625
8211
|
} catch (error) {
|
|
8626
|
-
|
|
8212
|
+
logger7.error("Error Occured during describing image: ", error);
|
|
8627
8213
|
}
|
|
8628
8214
|
const state = await this.runtime.composeState(message);
|
|
8629
8215
|
state.values = {
|
|
@@ -8635,7 +8221,7 @@ var TwitterInteractionClient = class {
|
|
|
8635
8221
|
const tweetId = createUniqueUuid5(this.runtime, tweet.id);
|
|
8636
8222
|
const tweetExists = await this.runtime.getMemoryById(tweetId);
|
|
8637
8223
|
if (!tweetExists) {
|
|
8638
|
-
|
|
8224
|
+
logger7.log("tweet does not exist, saving");
|
|
8639
8225
|
const entityId = createUniqueUuid5(this.runtime, tweet.userId);
|
|
8640
8226
|
const roomId = createUniqueUuid5(this.runtime, tweet.conversationId);
|
|
8641
8227
|
await this.runtime.ensureConnection({
|
|
@@ -8678,25 +8264,19 @@ var TwitterInteractionClient = class {
|
|
|
8678
8264
|
const response = await this.runtime.useModel(ModelType4.TEXT_SMALL, {
|
|
8679
8265
|
prompt: shouldRespondPrompt
|
|
8680
8266
|
});
|
|
8681
|
-
const responseActions = (response.match(/(?:RESPOND|IGNORE|STOP)/g) || [
|
|
8682
|
-
"IGNORE"
|
|
8683
|
-
])[0];
|
|
8267
|
+
const responseActions = (response.match(/(?:RESPOND|IGNORE|STOP)/g) || ["IGNORE"])[0];
|
|
8684
8268
|
if (responseActions !== "RESPOND") {
|
|
8685
|
-
|
|
8686
|
-
`Not responding to tweet based on shouldRespond decision: ${responseActions}`
|
|
8687
|
-
);
|
|
8269
|
+
logger7.log(`Not responding to tweet based on shouldRespond decision: ${responseActions}`);
|
|
8688
8270
|
return { text: "", actions: [responseActions] };
|
|
8689
8271
|
}
|
|
8690
8272
|
const callback = async (response2, tweetId2) => {
|
|
8691
8273
|
try {
|
|
8692
8274
|
const tweetToReplyTo = tweetId2 || tweet.id;
|
|
8693
8275
|
if (this.isDryRun) {
|
|
8694
|
-
|
|
8695
|
-
`[DRY RUN] Would have replied to ${tweet.username} with: ${response2.text}`
|
|
8696
|
-
);
|
|
8276
|
+
logger7.info(`[DRY RUN] Would have replied to ${tweet.username} with: ${response2.text}`);
|
|
8697
8277
|
return [];
|
|
8698
8278
|
}
|
|
8699
|
-
|
|
8279
|
+
logger7.info(`Replying to tweet ${tweetToReplyTo}`);
|
|
8700
8280
|
const replyTweetResult = await this.client.requestQueue.add(
|
|
8701
8281
|
() => this.client.twitterClient.post("statuses/update", {
|
|
8702
8282
|
status: response2.text.substring(0, 280),
|
|
@@ -8725,11 +8305,11 @@ var TwitterInteractionClient = class {
|
|
|
8725
8305
|
await this.runtime.createMemory(responseMemory, "messages");
|
|
8726
8306
|
return [responseMemory];
|
|
8727
8307
|
} catch (error) {
|
|
8728
|
-
|
|
8308
|
+
logger7.error("Error replying to tweet:", error);
|
|
8729
8309
|
return [];
|
|
8730
8310
|
}
|
|
8731
8311
|
};
|
|
8732
|
-
this.runtime.emitEvent(
|
|
8312
|
+
this.runtime.emitEvent(EventType2.MESSAGE_RECEIVED, {
|
|
8733
8313
|
runtime: this.runtime,
|
|
8734
8314
|
message,
|
|
8735
8315
|
callback,
|
|
@@ -8748,20 +8328,22 @@ var TwitterInteractionClient = class {
|
|
|
8748
8328
|
const thread = [];
|
|
8749
8329
|
const visited = /* @__PURE__ */ new Set();
|
|
8750
8330
|
async function processThread(currentTweet, depth = 0) {
|
|
8751
|
-
|
|
8331
|
+
logger7.log("Processing tweet:", {
|
|
8752
8332
|
id: currentTweet.id,
|
|
8753
8333
|
inReplyToStatusId: currentTweet.inReplyToStatusId,
|
|
8754
8334
|
depth
|
|
8755
8335
|
});
|
|
8756
8336
|
if (!currentTweet) {
|
|
8757
|
-
|
|
8337
|
+
logger7.log("No current tweet found for thread building");
|
|
8758
8338
|
return;
|
|
8759
8339
|
}
|
|
8760
8340
|
if (depth >= maxReplies) {
|
|
8761
|
-
|
|
8341
|
+
logger7.log("Reached maximum reply depth", depth);
|
|
8762
8342
|
return;
|
|
8763
8343
|
}
|
|
8764
|
-
const memory = await this.runtime.getMemoryById(
|
|
8344
|
+
const memory = await this.runtime.getMemoryById(
|
|
8345
|
+
createUniqueUuid5(this.runtime, currentTweet.id)
|
|
8346
|
+
);
|
|
8765
8347
|
if (!memory) {
|
|
8766
8348
|
const roomId = createUniqueUuid5(this.runtime, tweet.conversationId);
|
|
8767
8349
|
const entityId = createUniqueUuid5(this.runtime, currentTweet.userId);
|
|
@@ -8773,53 +8355,51 @@ var TwitterInteractionClient = class {
|
|
|
8773
8355
|
source: "twitter",
|
|
8774
8356
|
type: ChannelType5.GROUP
|
|
8775
8357
|
});
|
|
8776
|
-
this.runtime.createMemory(
|
|
8777
|
-
|
|
8778
|
-
|
|
8779
|
-
|
|
8780
|
-
|
|
8781
|
-
|
|
8782
|
-
|
|
8783
|
-
|
|
8784
|
-
|
|
8358
|
+
this.runtime.createMemory(
|
|
8359
|
+
{
|
|
8360
|
+
id: createUniqueUuid5(this.runtime, currentTweet.id),
|
|
8361
|
+
agentId: this.runtime.agentId,
|
|
8362
|
+
content: {
|
|
8363
|
+
text: currentTweet.text,
|
|
8364
|
+
source: "twitter",
|
|
8365
|
+
url: currentTweet.permanentUrl,
|
|
8366
|
+
imageUrls: currentTweet.photos?.map((photo) => photo.url) || [],
|
|
8367
|
+
inReplyTo: currentTweet.inReplyToStatusId ? createUniqueUuid5(this.runtime, currentTweet.inReplyToStatusId) : void 0
|
|
8368
|
+
},
|
|
8369
|
+
createdAt: currentTweet.timestamp * 1e3,
|
|
8370
|
+
roomId,
|
|
8371
|
+
entityId: currentTweet.userId === this.twitterUserId ? this.runtime.agentId : createUniqueUuid5(this.runtime, currentTweet.userId)
|
|
8785
8372
|
},
|
|
8786
|
-
|
|
8787
|
-
|
|
8788
|
-
entityId: currentTweet.userId === this.twitterUserId ? this.runtime.agentId : createUniqueUuid5(this.runtime, currentTweet.userId)
|
|
8789
|
-
}, "messages");
|
|
8373
|
+
"messages"
|
|
8374
|
+
);
|
|
8790
8375
|
}
|
|
8791
8376
|
if (visited.has(currentTweet.id)) {
|
|
8792
|
-
|
|
8377
|
+
logger7.log("Already visited tweet:", currentTweet.id);
|
|
8793
8378
|
return;
|
|
8794
8379
|
}
|
|
8795
8380
|
visited.add(currentTweet.id);
|
|
8796
8381
|
thread.unshift(currentTweet);
|
|
8797
8382
|
if (currentTweet.inReplyToStatusId) {
|
|
8798
|
-
|
|
8383
|
+
logger7.log("Fetching parent tweet:", currentTweet.inReplyToStatusId);
|
|
8799
8384
|
try {
|
|
8800
|
-
const parentTweet = await this.twitterClient.getTweet(
|
|
8801
|
-
currentTweet.inReplyToStatusId
|
|
8802
|
-
);
|
|
8385
|
+
const parentTweet = await this.twitterClient.getTweet(currentTweet.inReplyToStatusId);
|
|
8803
8386
|
if (parentTweet) {
|
|
8804
|
-
|
|
8387
|
+
logger7.log("Found parent tweet:", {
|
|
8805
8388
|
id: parentTweet.id,
|
|
8806
8389
|
text: parentTweet.text?.slice(0, 50)
|
|
8807
8390
|
});
|
|
8808
8391
|
await processThread(parentTweet, depth + 1);
|
|
8809
8392
|
} else {
|
|
8810
|
-
|
|
8811
|
-
"No parent tweet found for:",
|
|
8812
|
-
currentTweet.inReplyToStatusId
|
|
8813
|
-
);
|
|
8393
|
+
logger7.log("No parent tweet found for:", currentTweet.inReplyToStatusId);
|
|
8814
8394
|
}
|
|
8815
8395
|
} catch (error) {
|
|
8816
|
-
|
|
8396
|
+
logger7.log("Error fetching parent tweet:", {
|
|
8817
8397
|
tweetId: currentTweet.inReplyToStatusId,
|
|
8818
8398
|
error
|
|
8819
8399
|
});
|
|
8820
8400
|
}
|
|
8821
8401
|
} else {
|
|
8822
|
-
|
|
8402
|
+
logger7.log("Reached end of reply chain at:", currentTweet.id);
|
|
8823
8403
|
}
|
|
8824
8404
|
}
|
|
8825
8405
|
await processThread.bind(this)(tweet, 0);
|
|
@@ -8843,9 +8423,9 @@ var TwitterInteractionClient = class {
|
|
|
8843
8423
|
// src/post.ts
|
|
8844
8424
|
import {
|
|
8845
8425
|
ChannelType as ChannelType6,
|
|
8846
|
-
|
|
8426
|
+
EventType as EventType3,
|
|
8847
8427
|
createUniqueUuid as createUniqueUuid6,
|
|
8848
|
-
logger as
|
|
8428
|
+
logger as logger8,
|
|
8849
8429
|
truncateToCompleteSentence
|
|
8850
8430
|
} from "@elizaos/core";
|
|
8851
8431
|
var TwitterPostClient = class {
|
|
@@ -8861,32 +8441,30 @@ var TwitterPostClient = class {
|
|
|
8861
8441
|
this.runtime = runtime;
|
|
8862
8442
|
this.twitterUsername = state?.TWITTER_USERNAME || this.runtime.getSetting("TWITTER_USERNAME");
|
|
8863
8443
|
this.isDryRun = this.state?.TWITTER_DRY_RUN || this.runtime.getSetting("TWITTER_DRY_RUN");
|
|
8864
|
-
|
|
8865
|
-
|
|
8866
|
-
|
|
8867
|
-
|
|
8444
|
+
logger8.log("Twitter Client Configuration:");
|
|
8445
|
+
logger8.log(`- Username: ${this.twitterUsername}`);
|
|
8446
|
+
logger8.log(`- Dry Run Mode: ${this.isDryRun ? "Enabled" : "Disabled"}`);
|
|
8447
|
+
logger8.log(
|
|
8868
8448
|
`- Auto-post: ${this.state?.TWITTER_ENABLE_POST_GENERATION || this.runtime.getSetting("TWITTER_ENABLE_POST_GENERATION") ? "disabled" : "enabled"}`
|
|
8869
8449
|
);
|
|
8870
|
-
|
|
8450
|
+
logger8.log(
|
|
8871
8451
|
`- Post Interval: ${this.state?.TWITTER_POST_INTERVAL_MIN || this.runtime.getSetting("TWITTER_POST_INTERVAL_MIN")}-${this.state?.TWITTER_POST_INTERVAL_MAX || this.runtime.getSetting("TWITTER_POST_INTERVAL_MAX")} minutes`
|
|
8872
8452
|
);
|
|
8873
|
-
|
|
8453
|
+
logger8.log(
|
|
8874
8454
|
`- Post Immediately: ${this.state?.TWITTER_POST_IMMEDIATELY || this.runtime.getSetting("TWITTER_POST_IMMEDIATELY") ? "enabled" : "disabled"}`
|
|
8875
8455
|
);
|
|
8876
8456
|
if (this.isDryRun) {
|
|
8877
|
-
|
|
8878
|
-
"Twitter client initialized in dry run mode - no actual tweets should be posted"
|
|
8879
|
-
);
|
|
8457
|
+
logger8.log("Twitter client initialized in dry run mode - no actual tweets should be posted");
|
|
8880
8458
|
}
|
|
8881
8459
|
}
|
|
8882
8460
|
/**
|
|
8883
8461
|
* Starts the Twitter post client, setting up a loop to periodically generate new tweets.
|
|
8884
8462
|
*/
|
|
8885
8463
|
async start() {
|
|
8886
|
-
|
|
8464
|
+
logger8.log("Starting Twitter post client...");
|
|
8887
8465
|
const tweetGeneration = this.runtime.getSetting("TWITTER_ENABLE_TWEET_GENERATION");
|
|
8888
8466
|
if (tweetGeneration === false) {
|
|
8889
|
-
|
|
8467
|
+
logger8.log("Tweet generation is disabled");
|
|
8890
8468
|
return;
|
|
8891
8469
|
}
|
|
8892
8470
|
const generateNewTweetLoop = async () => {
|
|
@@ -8943,7 +8521,7 @@ var TwitterPostClient = class {
|
|
|
8943
8521
|
timestamp: Date.now()
|
|
8944
8522
|
});
|
|
8945
8523
|
await client.cacheTweet(tweet);
|
|
8946
|
-
|
|
8524
|
+
logger8.log(`Tweet posted:
|
|
8947
8525
|
${tweet.permanentUrl}`);
|
|
8948
8526
|
await runtime.ensureRoomExists({
|
|
8949
8527
|
id: roomId,
|
|
@@ -8952,18 +8530,21 @@ var TwitterPostClient = class {
|
|
|
8952
8530
|
type: ChannelType6.FEED
|
|
8953
8531
|
});
|
|
8954
8532
|
await runtime.ensureParticipantInRoom(runtime.agentId, roomId);
|
|
8955
|
-
await runtime.createMemory(
|
|
8956
|
-
|
|
8957
|
-
|
|
8958
|
-
|
|
8959
|
-
|
|
8960
|
-
|
|
8961
|
-
|
|
8962
|
-
|
|
8533
|
+
await runtime.createMemory(
|
|
8534
|
+
{
|
|
8535
|
+
id: createUniqueUuid6(this.runtime, tweet.id),
|
|
8536
|
+
entityId: runtime.agentId,
|
|
8537
|
+
agentId: runtime.agentId,
|
|
8538
|
+
content: {
|
|
8539
|
+
text: rawTweetContent.trim(),
|
|
8540
|
+
url: tweet.permanentUrl,
|
|
8541
|
+
source: "twitter"
|
|
8542
|
+
},
|
|
8543
|
+
roomId,
|
|
8544
|
+
createdAt: tweet.timestamp
|
|
8963
8545
|
},
|
|
8964
|
-
|
|
8965
|
-
|
|
8966
|
-
}, "messages");
|
|
8546
|
+
"messages"
|
|
8547
|
+
);
|
|
8967
8548
|
}
|
|
8968
8549
|
/**
|
|
8969
8550
|
* Handles sending a note tweet with optional media data.
|
|
@@ -9005,12 +8586,12 @@ var TwitterPostClient = class {
|
|
|
9005
8586
|
);
|
|
9006
8587
|
const body = await standardTweetResult.json();
|
|
9007
8588
|
if (!body?.data?.create_tweet?.tweet_results?.result) {
|
|
9008
|
-
|
|
8589
|
+
logger8.error("Error sending tweet; Bad response:", body);
|
|
9009
8590
|
return;
|
|
9010
8591
|
}
|
|
9011
8592
|
return body.data.create_tweet.tweet_results.result;
|
|
9012
8593
|
} catch (error) {
|
|
9013
|
-
|
|
8594
|
+
logger8.error("Error sending standard Tweet:", error);
|
|
9014
8595
|
throw error;
|
|
9015
8596
|
}
|
|
9016
8597
|
}
|
|
@@ -9028,33 +8609,17 @@ var TwitterPostClient = class {
|
|
|
9028
8609
|
*/
|
|
9029
8610
|
async postTweet(runtime, client, tweetTextForPosting, roomId, rawTweetContent, twitterUsername, mediaData) {
|
|
9030
8611
|
try {
|
|
9031
|
-
|
|
8612
|
+
logger8.log("Posting new tweet:\n");
|
|
9032
8613
|
let result;
|
|
9033
8614
|
if (tweetTextForPosting.length > 280 - 1) {
|
|
9034
|
-
result = await this.handleNoteTweet(
|
|
9035
|
-
client,
|
|
9036
|
-
tweetTextForPosting,
|
|
9037
|
-
void 0,
|
|
9038
|
-
mediaData
|
|
9039
|
-
);
|
|
8615
|
+
result = await this.handleNoteTweet(client, tweetTextForPosting, void 0, mediaData);
|
|
9040
8616
|
} else {
|
|
9041
|
-
result = await this.sendStandardTweet(
|
|
9042
|
-
client,
|
|
9043
|
-
tweetTextForPosting,
|
|
9044
|
-
void 0,
|
|
9045
|
-
mediaData
|
|
9046
|
-
);
|
|
8617
|
+
result = await this.sendStandardTweet(client, tweetTextForPosting, void 0, mediaData);
|
|
9047
8618
|
}
|
|
9048
8619
|
const tweet = this.createTweetObject(result, client, twitterUsername);
|
|
9049
|
-
await this.processAndCacheTweet(
|
|
9050
|
-
runtime,
|
|
9051
|
-
client,
|
|
9052
|
-
tweet,
|
|
9053
|
-
roomId,
|
|
9054
|
-
rawTweetContent
|
|
9055
|
-
);
|
|
8620
|
+
await this.processAndCacheTweet(runtime, client, tweet, roomId, rawTweetContent);
|
|
9056
8621
|
} catch (error) {
|
|
9057
|
-
|
|
8622
|
+
logger8.error("Error sending tweet:");
|
|
9058
8623
|
throw error;
|
|
9059
8624
|
}
|
|
9060
8625
|
}
|
|
@@ -9066,7 +8631,7 @@ var TwitterPostClient = class {
|
|
|
9066
8631
|
try {
|
|
9067
8632
|
const userId = this.client.profile?.id;
|
|
9068
8633
|
if (!userId) {
|
|
9069
|
-
|
|
8634
|
+
logger8.error("Cannot generate tweet: Twitter profile not available");
|
|
9070
8635
|
return;
|
|
9071
8636
|
}
|
|
9072
8637
|
const worldId = createUniqueUuid6(this.runtime, userId);
|
|
@@ -9074,17 +8639,13 @@ var TwitterPostClient = class {
|
|
|
9074
8639
|
const callback = async (content) => {
|
|
9075
8640
|
try {
|
|
9076
8641
|
if (this.isDryRun) {
|
|
9077
|
-
|
|
8642
|
+
logger8.info(`[DRY RUN] Would post tweet: ${content.text}`);
|
|
9078
8643
|
return [];
|
|
9079
8644
|
}
|
|
9080
8645
|
const result = await this.postToTwitter(content.text, content.mediaData);
|
|
9081
|
-
console.log("result is", result);
|
|
9082
8646
|
const tweetId = result.rest_id || result.id_str || result.legacy?.id_str;
|
|
9083
8647
|
if (result) {
|
|
9084
|
-
const postedTweetId = createUniqueUuid6(
|
|
9085
|
-
this.runtime,
|
|
9086
|
-
tweetId
|
|
9087
|
-
);
|
|
8648
|
+
const postedTweetId = createUniqueUuid6(this.runtime, tweetId);
|
|
9088
8649
|
const postedMemory = {
|
|
9089
8650
|
id: postedTweetId,
|
|
9090
8651
|
entityId: this.runtime.agentId,
|
|
@@ -9107,12 +8668,11 @@ var TwitterPostClient = class {
|
|
|
9107
8668
|
}
|
|
9108
8669
|
return [];
|
|
9109
8670
|
} catch (error) {
|
|
9110
|
-
|
|
8671
|
+
logger8.error("Error posting tweet:", error);
|
|
9111
8672
|
return [];
|
|
9112
8673
|
}
|
|
9113
8674
|
};
|
|
9114
|
-
|
|
9115
|
-
this.runtime.emitEvent([EventTypes3.POST_GENERATED, "TWITTER_POST_GENERATED" /* POST_GENERATED */], {
|
|
8675
|
+
this.runtime.emitEvent([EventType3.POST_GENERATED, "TWITTER_POST_GENERATED" /* POST_GENERATED */], {
|
|
9116
8676
|
runtime: this.runtime,
|
|
9117
8677
|
callback,
|
|
9118
8678
|
worldId,
|
|
@@ -9120,7 +8680,7 @@ var TwitterPostClient = class {
|
|
|
9120
8680
|
roomId
|
|
9121
8681
|
});
|
|
9122
8682
|
} catch (error) {
|
|
9123
|
-
|
|
8683
|
+
logger8.error("Error generating tweet:", error);
|
|
9124
8684
|
}
|
|
9125
8685
|
}
|
|
9126
8686
|
/**
|
|
@@ -9135,9 +8695,9 @@ var TwitterPostClient = class {
|
|
|
9135
8695
|
if (mediaData && mediaData.length > 0) {
|
|
9136
8696
|
for (const media of mediaData) {
|
|
9137
8697
|
try {
|
|
9138
|
-
|
|
8698
|
+
logger8.warn("Media upload not currently supported with the modern Twitter API");
|
|
9139
8699
|
} catch (error) {
|
|
9140
|
-
|
|
8700
|
+
logger8.error("Error uploading media:", error);
|
|
9141
8701
|
}
|
|
9142
8702
|
}
|
|
9143
8703
|
}
|
|
@@ -9146,12 +8706,12 @@ var TwitterPostClient = class {
|
|
|
9146
8706
|
);
|
|
9147
8707
|
const body = await result.json();
|
|
9148
8708
|
if (!body?.data?.create_tweet?.tweet_results?.result) {
|
|
9149
|
-
|
|
8709
|
+
logger8.error("Error sending tweet; Bad response:", body);
|
|
9150
8710
|
return null;
|
|
9151
8711
|
}
|
|
9152
8712
|
return body.data.create_tweet.tweet_results.result;
|
|
9153
8713
|
} catch (error) {
|
|
9154
|
-
|
|
8714
|
+
logger8.error("Error posting to Twitter:", error);
|
|
9155
8715
|
throw error;
|
|
9156
8716
|
}
|
|
9157
8717
|
}
|
|
@@ -9163,7 +8723,7 @@ var TwitterPostClient = class {
|
|
|
9163
8723
|
import {
|
|
9164
8724
|
ModelType as ModelType6,
|
|
9165
8725
|
createUniqueUuid as createUniqueUuid7,
|
|
9166
|
-
logger as
|
|
8726
|
+
logger as logger9,
|
|
9167
8727
|
stringToUuid as stringToUuid2
|
|
9168
8728
|
} from "@elizaos/core";
|
|
9169
8729
|
var TEST_IMAGE_URL = "https://github.com/elizaOS/awesome-eliza/blob/main/assets/eliza-logo.jpg?raw=true";
|
|
@@ -9222,11 +8782,9 @@ var TwitterTestSuite = class {
|
|
|
9222
8782
|
throw new Error("Twitter client manager not found");
|
|
9223
8783
|
}
|
|
9224
8784
|
const clientId = stringToUuid2("default");
|
|
9225
|
-
this.twitterClient = manager.clients.get(
|
|
9226
|
-
manager.getClientKey(clientId, runtime.agentId)
|
|
9227
|
-
);
|
|
8785
|
+
this.twitterClient = manager.clients.get(manager.getClientKey(clientId, runtime.agentId));
|
|
9228
8786
|
if (this.twitterClient) {
|
|
9229
|
-
|
|
8787
|
+
logger9.debug("TwitterClient initialized successfully.");
|
|
9230
8788
|
} else {
|
|
9231
8789
|
throw new Error("TwitterClient failed to initialize.");
|
|
9232
8790
|
}
|
|
@@ -9247,7 +8805,7 @@ var TwitterTestSuite = class {
|
|
|
9247
8805
|
if (!profile || !profile.id) {
|
|
9248
8806
|
throw new Error("Profile fetch failed.");
|
|
9249
8807
|
}
|
|
9250
|
-
|
|
8808
|
+
logger9.log("Successfully fetched Twitter profile:", profile);
|
|
9251
8809
|
} catch (error) {
|
|
9252
8810
|
throw new Error(`Error fetching Twitter profile: ${error}`);
|
|
9253
8811
|
}
|
|
@@ -9266,9 +8824,7 @@ var TwitterTestSuite = class {
|
|
|
9266
8824
|
5,
|
|
9267
8825
|
1 /* Latest */
|
|
9268
8826
|
);
|
|
9269
|
-
|
|
9270
|
-
`Successfully fetched ${tweets.tweets.length} search tweets.`
|
|
9271
|
-
);
|
|
8827
|
+
logger9.debug(`Successfully fetched ${tweets.tweets.length} search tweets.`);
|
|
9272
8828
|
} catch (error) {
|
|
9273
8829
|
throw new Error(`Error fetching search tweets: ${error}`);
|
|
9274
8830
|
}
|
|
@@ -9286,9 +8842,7 @@ var TwitterTestSuite = class {
|
|
|
9286
8842
|
if (!timeline || timeline.length === 0) {
|
|
9287
8843
|
throw new Error("No tweets in home timeline.");
|
|
9288
8844
|
}
|
|
9289
|
-
|
|
9290
|
-
`Successfully fetched ${timeline.length} tweets from home timeline.`
|
|
9291
|
-
);
|
|
8845
|
+
logger9.log(`Successfully fetched ${timeline.length} tweets from home timeline.`);
|
|
9292
8846
|
} catch (error) {
|
|
9293
8847
|
throw new Error(`Error fetching home timeline: ${error}`);
|
|
9294
8848
|
}
|
|
@@ -9305,7 +8859,7 @@ var TwitterTestSuite = class {
|
|
|
9305
8859
|
if (!posts || posts.length === 0) {
|
|
9306
8860
|
throw new Error("No own posts found.");
|
|
9307
8861
|
}
|
|
9308
|
-
|
|
8862
|
+
logger9.log(`Successfully fetched ${posts.length} own posts.`);
|
|
9309
8863
|
} catch (error) {
|
|
9310
8864
|
throw new Error(`Error fetching own posts: ${error}`);
|
|
9311
8865
|
}
|
|
@@ -9330,7 +8884,7 @@ var TwitterTestSuite = class {
|
|
|
9330
8884
|
tweetText,
|
|
9331
8885
|
"test-username"
|
|
9332
8886
|
);
|
|
9333
|
-
|
|
8887
|
+
logger9.success("Successfully posted a test tweet.");
|
|
9334
8888
|
} catch (error) {
|
|
9335
8889
|
throw new Error(`Error posting a tweet: ${error}`);
|
|
9336
8890
|
}
|
|
@@ -9346,10 +8900,7 @@ var TwitterTestSuite = class {
|
|
|
9346
8900
|
try {
|
|
9347
8901
|
const roomId = createUniqueUuid7(runtime, "twitter_mock_room");
|
|
9348
8902
|
const postClient = this.twitterClient.post;
|
|
9349
|
-
const tweetText = await this.generateRandomTweetContent(
|
|
9350
|
-
runtime,
|
|
9351
|
-
"image_post"
|
|
9352
|
-
);
|
|
8903
|
+
const tweetText = await this.generateRandomTweetContent(runtime, "image_post");
|
|
9353
8904
|
const mediaData = await fetchMediaData([TEST_IMAGE]);
|
|
9354
8905
|
await postClient.postTweet(
|
|
9355
8906
|
runtime,
|
|
@@ -9360,7 +8911,7 @@ var TwitterTestSuite = class {
|
|
|
9360
8911
|
"test-username",
|
|
9361
8912
|
mediaData
|
|
9362
8913
|
);
|
|
9363
|
-
|
|
8914
|
+
logger9.success("Successfully posted a test tweet.");
|
|
9364
8915
|
} catch (error) {
|
|
9365
8916
|
throw new Error(`Error posting a tweet: ${error}`);
|
|
9366
8917
|
}
|
|
@@ -9376,7 +8927,7 @@ var TwitterTestSuite = class {
|
|
|
9376
8927
|
try {
|
|
9377
8928
|
const postClient = this.twitterClient.post;
|
|
9378
8929
|
await postClient.generateNewTweet();
|
|
9379
|
-
|
|
8930
|
+
logger9.success("Successfully generated a new tweet.");
|
|
9380
8931
|
} catch (error) {
|
|
9381
8932
|
throw new Error(`Error generating new tweet: ${error}`);
|
|
9382
8933
|
}
|
|
@@ -9415,7 +8966,7 @@ var TwitterTestSuite = class {
|
|
|
9415
8966
|
},
|
|
9416
8967
|
thread: []
|
|
9417
8968
|
});
|
|
9418
|
-
|
|
8969
|
+
logger9.success("Correct response decision.");
|
|
9419
8970
|
} catch (error) {
|
|
9420
8971
|
throw new Error(`Error handling tweet response: ${error}`);
|
|
9421
8972
|
}
|
|
@@ -9458,11 +9009,7 @@ var TwitterClientInstance = class {
|
|
|
9458
9009
|
constructor(runtime, state) {
|
|
9459
9010
|
this.client = new ClientBase(runtime, state);
|
|
9460
9011
|
this.post = new TwitterPostClient(this.client, runtime, state);
|
|
9461
|
-
this.interaction = new TwitterInteractionClient(
|
|
9462
|
-
this.client,
|
|
9463
|
-
runtime,
|
|
9464
|
-
state
|
|
9465
|
-
);
|
|
9012
|
+
this.interaction = new TwitterInteractionClient(this.client, runtime, state);
|
|
9466
9013
|
if (runtime.getSetting("TWITTER_SPACES_ENABLE") === true) {
|
|
9467
9014
|
this.space = new TwitterSpaceClient(this.client, runtime);
|
|
9468
9015
|
}
|
|
@@ -9482,14 +9029,13 @@ var _TwitterService = class _TwitterService extends Service {
|
|
|
9482
9029
|
return _TwitterService.instance;
|
|
9483
9030
|
}
|
|
9484
9031
|
async createClient(runtime, clientId, state) {
|
|
9485
|
-
console.log("Creating client", clientId);
|
|
9486
9032
|
if (runtime.getSetting("TWITTER_2FA_SECRET") === null) {
|
|
9487
9033
|
runtime.setSetting("TWITTER_2FA_SECRET", void 0, false);
|
|
9488
9034
|
}
|
|
9489
9035
|
try {
|
|
9490
9036
|
const existingClient = this.getClient(clientId, runtime.agentId);
|
|
9491
9037
|
if (existingClient) {
|
|
9492
|
-
|
|
9038
|
+
logger10.info(`Twitter client already exists for ${clientId}`);
|
|
9493
9039
|
return existingClient;
|
|
9494
9040
|
}
|
|
9495
9041
|
const client = new TwitterClientInstance(runtime, state);
|
|
@@ -9505,10 +9051,10 @@ var _TwitterService = class _TwitterService extends Service {
|
|
|
9505
9051
|
}
|
|
9506
9052
|
this.clients.set(this.getClientKey(clientId, runtime.agentId), client);
|
|
9507
9053
|
await this.emitServerJoinedEvent(runtime, client);
|
|
9508
|
-
|
|
9054
|
+
logger10.info(`Created Twitter client for ${clientId}`);
|
|
9509
9055
|
return client;
|
|
9510
9056
|
} catch (error) {
|
|
9511
|
-
|
|
9057
|
+
logger10.error(`Failed to create Twitter client for ${clientId}:`, error);
|
|
9512
9058
|
throw error;
|
|
9513
9059
|
}
|
|
9514
9060
|
}
|
|
@@ -9520,7 +9066,7 @@ var _TwitterService = class _TwitterService extends Service {
|
|
|
9520
9066
|
async emitServerJoinedEvent(runtime, client) {
|
|
9521
9067
|
try {
|
|
9522
9068
|
if (!client.client.profile) {
|
|
9523
|
-
|
|
9069
|
+
logger10.warn("Twitter profile not available yet, can't emit WORLD_JOINED event");
|
|
9524
9070
|
return;
|
|
9525
9071
|
}
|
|
9526
9072
|
const profile = client.client.profile;
|
|
@@ -9577,16 +9123,16 @@ var _TwitterService = class _TwitterService extends Service {
|
|
|
9577
9123
|
}
|
|
9578
9124
|
}
|
|
9579
9125
|
};
|
|
9580
|
-
runtime.emitEvent(["TWITTER_WORLD_JOINED" /* WORLD_JOINED */,
|
|
9126
|
+
runtime.emitEvent(["TWITTER_WORLD_JOINED" /* WORLD_JOINED */, EventType4.WORLD_JOINED], {
|
|
9581
9127
|
runtime,
|
|
9582
9128
|
world,
|
|
9583
9129
|
rooms: [homeTimelineRoom, mentionsRoom],
|
|
9584
9130
|
users: [twitterUser],
|
|
9585
9131
|
source: "twitter"
|
|
9586
9132
|
});
|
|
9587
|
-
|
|
9133
|
+
logger10.info(`Emitted WORLD_JOINED event for Twitter account ${username}`);
|
|
9588
9134
|
} catch (error) {
|
|
9589
|
-
|
|
9135
|
+
logger10.error("Failed to emit WORLD_JOINED event for Twitter:", error);
|
|
9590
9136
|
}
|
|
9591
9137
|
}
|
|
9592
9138
|
getClient(clientId, agentId) {
|
|
@@ -9599,9 +9145,9 @@ var _TwitterService = class _TwitterService extends Service {
|
|
|
9599
9145
|
try {
|
|
9600
9146
|
await client.service.stop();
|
|
9601
9147
|
this.clients.delete(key);
|
|
9602
|
-
|
|
9148
|
+
logger10.info(`Stopped Twitter client for ${clientId}`);
|
|
9603
9149
|
} catch (error) {
|
|
9604
|
-
|
|
9150
|
+
logger10.error(`Error stopping Twitter client for ${clientId}:`, error);
|
|
9605
9151
|
}
|
|
9606
9152
|
}
|
|
9607
9153
|
}
|
|
@@ -9619,16 +9165,11 @@ var _TwitterService = class _TwitterService extends Service {
|
|
|
9619
9165
|
try {
|
|
9620
9166
|
if (config.TWITTER_USERNAME && // Basic auth
|
|
9621
9167
|
config.TWITTER_PASSWORD && config.TWITTER_EMAIL) {
|
|
9622
|
-
|
|
9623
|
-
|
|
9624
|
-
await twitterClientManager.createClient(
|
|
9625
|
-
runtime,
|
|
9626
|
-
runtime.agentId,
|
|
9627
|
-
config
|
|
9628
|
-
);
|
|
9168
|
+
logger10.info("Creating default Twitter client from character settings");
|
|
9169
|
+
await twitterClientManager.createClient(runtime, runtime.agentId, config);
|
|
9629
9170
|
}
|
|
9630
9171
|
} catch (error) {
|
|
9631
|
-
|
|
9172
|
+
logger10.error("Failed to create default Twitter client:", error);
|
|
9632
9173
|
}
|
|
9633
9174
|
return twitterClientManager;
|
|
9634
9175
|
}
|
|
@@ -9641,7 +9182,7 @@ var _TwitterService = class _TwitterService extends Service {
|
|
|
9641
9182
|
await client.service.stop();
|
|
9642
9183
|
this.clients.delete(key);
|
|
9643
9184
|
} catch (error) {
|
|
9644
|
-
|
|
9185
|
+
logger10.error(`Error stopping Twitter client ${key}:`, error);
|
|
9645
9186
|
}
|
|
9646
9187
|
}
|
|
9647
9188
|
}
|