Skip to content

Commit

Permalink
improve daily news tweet:
Browse files Browse the repository at this point in the history
- fix formating
- add new env file to have a dedicated twitter account for scrapping
- tweet in morning
  • Loading branch information
Addy-bsf committed Jan 30, 2025
1 parent ff4f7e5 commit dc127a0
Show file tree
Hide file tree
Showing 2 changed files with 61 additions and 39 deletions.
5 changes: 5 additions & 0 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,11 @@ TWITTER_PASSWORD= # Account password
TWITTER_EMAIL= # Account email
TWITTER_2FA_SECRET=

# Scraper Twitter Account (for data collection)
SCRAPER_TWITTER_USERNAME= # Dedicated scraper account username
SCRAPER_TWITTER_PASSWORD= # Dedicated scraper account password
SCRAPER_TWITTER_EMAIL= # Dedicated scraper account email

TWITTER_POLL_INTERVAL=120 # How often (in seconds) the bot should check for interactions
TWITTER_SEARCH_ENABLE=FALSE # Enable timeline search, WARNING this greatly increases your chance of getting banned
TWITTER_TARGET_USERS= # Comma separated list of Twitter user names to interact with
Expand Down
95 changes: 56 additions & 39 deletions packages/client-twitter/src/scheduled-tweets/daily-news.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,20 +2,21 @@ import {
composeContext,
elizaLogger,
generateText,
IAgentRuntime,
ModelClass,
stringToUuid,
IAgentRuntime,
} from "@elizaos/core";
import { Scraper, SearchMode, Tweet, ScheduledTweet } from "agent-twitter-client";
import { Scraper, SearchMode } from "agent-twitter-client";
import { ScheduledTweet } from "./types";

const SOLANA_ACCOUNTS = [
'S0LBigFinance',
'magFOMO',
'StepDevInsights',
'SolanaFloor',
'solana_daily',
'SolanaStatus',
'solananew'
"S0LBigFinance",
"magFOMO",
"StepDevInsights",
"SolanaFloor",
"solana_daily",
"SolanaStatus",
"solananew",
];

const dailyNewsSummaryTemplate = `
Expand Down Expand Up @@ -45,7 +46,7 @@ export const dailyNewsTweet: ScheduledTweet = {
id: "daily-news",
frequency: "daily",
timeCondition: {
hour: 21, // 9 PM
hour: 8, // 8 am
},
generateContent: async (runtime: IAgentRuntime) => {
let scraper: Scraper | null = null;
Expand All @@ -55,12 +56,14 @@ export const dailyNewsTweet: ScheduledTweet = {
elizaLogger.info("Initializing Twitter scraper...");

// Get credentials from environment
const username = process.env.TWITTER_USERNAME;
const password = process.env.TWITTER_PASSWORD;
const email = process.env.TWITTER_EMAIL;
const username = process.env.SCRAPER_TWITTER_USERNAME;
const password = process.env.SCRAPER_TWITTER_PASSWORD;
const email = process.env.SCRAPER_TWITTER_EMAIL;

if (!username || !password || !email) {
throw new Error("Missing Twitter credentials in environment");
throw new Error(
"Missing Twitter scraper credentials in environment"
);
}

// Login to Twitter
Expand All @@ -78,12 +81,17 @@ export const dailyNewsTweet: ScheduledTweet = {
50,
SearchMode.Latest
);
elizaLogger.info(`Found ${accountTweets?.tweets?.length || 0} tweets for ${account}`);
elizaLogger.info(
`Found ${accountTweets?.tweets?.length || 0} tweets for ${account}`
);
if (accountTweets?.tweets?.length) {
searchResults.push(...accountTweets.tweets);
}
} catch (error) {
elizaLogger.error(`Error fetching tweets for ${account}:`, error);
elizaLogger.error(
`Error fetching tweets for ${account}:`,
error
);
}
}

Expand All @@ -98,13 +106,18 @@ export const dailyNewsTweet: ScheduledTweet = {
});

if (!recentTweets.length) {
elizaLogger.warn("No recent tweets found from specified Solana accounts");
elizaLogger.warn(
"No recent tweets found from specified Solana accounts"
);
return null;
}

// Format tweets for the template
const formattedTweets = recentTweets
.map((tweet) => `@${tweet.username || 'unknown'}: ${tweet.text || ''}`)
.map(
(tweet) =>
`@${tweet.username || "unknown"}: ${tweet.text || ""}`
)
.join("\n\n");

// Create a room ID for this summary
Expand All @@ -127,36 +140,37 @@ export const dailyNewsTweet: ScheduledTweet = {
);

// Generate summary
let summary;
if (runtime.generateText) {
const templateWithTweets = dailyNewsSummaryTemplate.replace('{{tweets}}', formattedTweets);

summary = await runtime.generateText({
context: {
template: templateWithTweets,
state
},
modelClass: ModelClass.SMALL
});
} else {
elizaLogger.warn("No generateText available, using template directly");
summary = dailyNewsSummaryTemplate.replace('{{tweets}}', formattedTweets);
}
const templateWithTweets = dailyNewsSummaryTemplate.replace(
"{{tweets}}",
formattedTweets
);

const context = composeContext({
state,
template: templateWithTweets,
});

const summary = await generateText({
runtime,
context,
modelClass: ModelClass.SMALL,
});

// Clean and format the summary
const cleanedSummary = summary
let cleanedSummary = summary
.replace(/```json\s*|\s*```/g, "")
.replace(/^['"](.*)['"]$/g, "$1")
.replace(/\\n/g, "\n")
.trim();

if (cleanedSummary.length > 280) {
elizaLogger.warn("Generated summary exceeds 280 character limit. Truncating...");
return { content: cleanedSummary.slice(0, 277) + "..." };
elizaLogger.warn(
"Generated summary exceeds 280 character limit. Truncating..."
);
cleanedSummary = cleanedSummary.slice(0, 277) + "...";
}

return { content: cleanedSummary };

} catch (error) {
elizaLogger.error("Error generating daily news tweet:", error);
if (error instanceof Error) {
Expand All @@ -171,9 +185,12 @@ export const dailyNewsTweet: ScheduledTweet = {
await scraper.logout();
elizaLogger.info("Successfully logged out from Twitter");
} catch (logoutError) {
elizaLogger.warn("Error during Twitter logout:", logoutError);
elizaLogger.warn(
"Error during Twitter logout:",
logoutError
);
}
}
}
},
};
};

0 comments on commit dc127a0

Please sign in to comment.