-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathsamplebot.js
More file actions
205 lines (177 loc) · 7.51 KB
/
Copy pathsamplebot.js
File metadata and controls
205 lines (177 loc) · 7.51 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
const Redis = require('ioredis');
const { Scraper, SearchMode } = require('agent-twitter-client');
const cron = require('node-cron');
const { onchainAction } = require('./onChainAction.js');
const { getUsername } = require('./username.js');
const { PrivyClient } = require('@privy-io/server-auth');
const dotenv = require('dotenv');
const { Ollama } = require("@langchain/ollama");
const { ChatGroq } = require("@langchain/groq");
const { default: axios } = require('axios');
dotenv.config();
const redis = new Redis({
host: process.env.REDIS_HOST,
port: process.env.REDIS_PORT,
username: process.env.REDIS_USERNAME,
password: process.env.REDIS_PASSWORD,
});
const LAST_REPLIED_TWEET_KEY = 'lastRepliedTweetId';
async function loadLastRepliedTweetId() {
return await redis.get(LAST_REPLIED_TWEET_KEY);
}
async function saveLastRepliedTweetId(tweetId) {
await redis.set(LAST_REPLIED_TWEET_KEY, tweetId);
}
async function replyToTweet(scraper, tweet, privyClient, llm) {
try {
const tweetText = tweet.text;
const sender = tweet.username;
const senderinfo = await axios.get(`https://sendx-pi.vercel.app/api/userBalance?username=${sender}`);
if (senderinfo.data.data == null) {
console.log("User not found");
await scraper.sendTweet(`@${sender} Please register on https://sendx-pi.vercel.app `, tweet.id);
}
const balance = senderinfo.data.data.balance;
const { username, amount } = await getUsername(tweetText, llm, scraper, tweet.id);
console.log('Username:', username);
console.log('Amount:', amount);
if (balance < amount) {
console.log("Deposited funds are insufficient");
await scraper.sendTweet(`@${sender} Deposited funds are insufficient`, tweet.id);
return;
}
let user = await privyClient.getUserByTwitterUsername(username);
console.log('User already exists');
if (!user) {
console.log('User not found:', username);
const userDetails = await scraper.getProfile(username)
console.log('User details:', userDetails);
user = await privyClient.importUser({
linkedAccounts: [
{
type: 'twitter_oauth',
subject: userDetails.userId,
name: userDetails.name,
username: userDetails.username,
},
],
createSolanaWallet: true,
customMetadata: {
username: userDetails.username
},
});
console.log('User imported via twitter username:', user.wallet.address);
}
console.log("Waiting for 5 seconds");
//make the program wait here for 5 seconds
await new Promise(resolve => setTimeout(resolve, 5000));
console.log("5 seconds passed");
const prompt = `Send ${amount} SOL to ${user.wallet.address} , only return the transaction hash as output , nothing else.`;
console.log("Prompt:", prompt);
// const response = await onchainAction(prompt, llm); // @TODO: Uncomment when done testing
const response = await onchainAction(user.wallet.address, amount);
const updateDB = await axios.post("https://sendx-pi.vercel.app/api/userBalance", {
username: sender,
balance: balance - amount,
})
console.log(`Replying to tweet ID: ${tweet.id}`);
console.log('Response:', response);
await scraper.sendTweet(`https://solscan.io/tx/${response}?cluster=devnet`, tweet.id);
console.log('Replied to tweet ID:', tweet.id);
// Example: await scraper.replyToTweet(tweet.id, 'Your reply message here');
} catch (error) {
console.error('Error in replyToTweet function:', error);
await sendTweet(`@${sender} Error processing the transaction`, tweet.id);
throw error; // Re-throw the error to be caught in the main function
}
}
async function main(scraper, privyClient, llm) {
try {
const getTweets = await scraper.fetchSearchTweets(
`@${process.env.MY_USERNAME}`,
20,
SearchMode.Latest
);
// console.log('Fetched tweets:', getTweets);
const formattedTweets = getTweets.tweets.map(tweet => ({
id: tweet.id,
conversationId: tweet.conversationId,
mentions: tweet.mentions,
name: tweet.name,
permanentUrl: tweet.permanentUrl,
text: tweet.text,
userId: tweet.userId,
username: tweet.username,
isQuoted: tweet.isQuoted,
isReply: tweet.isReply,
isRetweet: tweet.isRetweet,
isPin: tweet.isPin,
timeParsed: tweet.timeParsed,
timestamp: tweet.timestamp,
html: tweet.html
}));
if (formattedTweets.length > 0) {
const lastRepliedTweetId = await loadLastRepliedTweetId();
console.log('Last replied tweet ID from DB:', lastRepliedTweetId);
const lastRepliedTweetIdNum = lastRepliedTweetId ? Number(lastRepliedTweetId) : 0;
for (const tweet of formattedTweets) {
const tweetIdNum = Number(tweet.id);
console.log('Processing tweet ID:', tweet.id);
if (tweetIdNum > lastRepliedTweetIdNum) {
// console.log('New tweet found:', tweet);
// Call your function to reply to the tweet
try {
await replyToTweet(scraper, tweet, privyClient, llm);
console.log('Replied to tweet ID:', tweet.id);
} catch (replyError) {
console.error('Error replying to tweet ID:', tweet.id, replyError);
}
} else {
console.log('Tweet ID already replied to:', tweet.id);
break;
}
}
console.log("for loop ended , going to save the last replied tweet id");
await saveLastRepliedTweetId(formattedTweets[ 0 ].id);
console.log('Updated last replied tweet ID to:', formattedTweets[ 0 ].id);
} else {
console.log('No tweets found.');
}
} catch (error) {
console.error('Error in main function:', error);
}
}
async function start() {
const scraper = new Scraper();
const client = new PrivyClient(
process.env.PRIVY_CLIENT_ID,
process.env.PRIVY_CLIENT_SECRET
);
// v1 login
console.log(process.env.MY_USERNAME, process.env.PASSWORD, process.env.EMAIL);
try {
await scraper.login(
process.env.MY_USERNAME,
process.env.PASSWORD,
process.env.EMAIL
);
console.log('Logged in successfully!');
} catch (error) {
console.error('Error logging in:', error);
return;
}
// const llm = new Ollama({
// model: "llama3.2", // Default value
// baseUrl: "http://127.0.0.1:11434", // Default value
// });
const llm = new ChatGroq({
model: "llama3-8b-8192",
});
// Schedule the main function to run every 20 seconds
cron.schedule('*/60 * * * * *', async () => {
console.log('Running the scheduled task...');
await main(scraper, client, llm);
console.log("_______________________________________________________________________________________________________________ \n");
});
}
start();