user-tools.ts•9.23 kB
import { getRedditClient } from "../client/reddit-client";
import { formatUserInfo } from "../utils/formatters";
import { McpError, ErrorCode } from "@modelcontextprotocol/sdk/types.js";
export async function getUserInfo(params: { username: string }) {
const { username } = params;
const client = getRedditClient();
if (!client) {
throw new McpError(
ErrorCode.InternalError,
"Reddit client not initialized"
);
}
try {
console.log(`[Tool] Getting info for u/${username}`);
const user = await client.getUser(username);
const formattedUser = formatUserInfo(user);
return {
content: [
{
type: "text",
text: `
# User Information: u/${formattedUser.username}
## Profile Overview
- Username: u/${formattedUser.username}
- Karma:
- Comment Karma: ${formattedUser.karma.commentKarma.toLocaleString()}
- Post Karma: ${formattedUser.karma.postKarma.toLocaleString()}
- Total Karma: ${formattedUser.karma.totalKarma.toLocaleString()}
- Account Status: ${formattedUser.accountStatus.join(", ")}
- Account Created: ${formattedUser.accountCreated}
- Profile URL: ${formattedUser.profileUrl}
## Activity Analysis
- ${formattedUser.activityAnalysis.replace(/\n - /g, "\n- ")}
## Recommendations
- ${formattedUser.recommendations.replace(/\n - /g, "\n- ")}
`,
},
],
};
} catch (error) {
console.error(`[Error] Error getting user info: ${error}`);
throw new McpError(
ErrorCode.InternalError,
`Failed to fetch user data: ${error}`
);
}
}
export async function getUserPosts(params: { username: string; sort?: string; limit?: number }) {
const { username, sort = "new", limit = 25 } = params;
const client = getRedditClient();
if (!client) {
throw new McpError(
ErrorCode.InternalError,
"Reddit client not initialized"
);
}
try {
console.log(`[Tool] Getting posts for u/${username}`);
const posts = await client.getUserPosts(username, sort, limit);
if (posts.length === 0) {
return {
content: [
{
type: "text",
text: `# Posts de u/${username}\n\nAucun post trouvé pour cet utilisateur.`,
},
],
};
}
const postsText = posts.map((post, index) => {
const postedDate = new Date(post.createdUtc * 1000).toLocaleString('fr-FR');
const scoreText = post.score >= 0 ? `+${post.score}` : `${post.score}`;
return `
### ${index + 1}. ${post.title}
- **Subreddit**: r/${post.subreddit}
- **Score**: ${scoreText} (${Math.round(post.upvoteRatio * 100)}% positifs)
- **Commentaires**: ${post.numComments}
- **Type**: ${post.isSelf ? 'Post texte' : 'Lien'}
- **Posté**: ${postedDate}
${post.linkFlairText ? `- **Flair**: ${post.linkFlairText}` : ''}
- **Lien**: https://reddit.com${post.permalink}
${post.selftext && post.selftext.length > 0 ? `\n**Contenu**: ${post.selftext.substring(0, 200)}${post.selftext.length > 200 ? '...' : ''}` : ''}
`;
}).join('\n');
return {
content: [
{
type: "text",
text: `# Posts récents de u/${username}
**Tri**: ${sort}
**Nombre de posts**: ${posts.length}
${postsText}`,
},
],
};
} catch (error) {
console.error(`[Error] Error getting user posts: ${error}`);
throw new McpError(
ErrorCode.InternalError,
`Failed to fetch user posts: ${error}`
);
}
}
export async function getUserComments(params: { username: string; sort?: string; limit?: number }) {
const { username, sort = "new", limit = 25 } = params;
const client = getRedditClient();
if (!client) {
throw new McpError(
ErrorCode.InternalError,
"Reddit client not initialized"
);
}
try {
console.log(`[Tool] Getting comments for u/${username}`);
const comments = await client.getUserComments(username, sort, limit);
if (comments.length === 0) {
return {
content: [
{
type: "text",
text: `# Commentaires de u/${username}\n\nAucun commentaire trouvé pour cet utilisateur.`,
},
],
};
}
const commentsText = comments.map((comment, index) => {
const postedDate = new Date(comment.createdUtc * 1000).toLocaleString('fr-FR');
const scoreText = comment.score >= 0 ? `+${comment.score}` : `${comment.score}`;
const controversialText = comment.controversiality > 0 ? ' (Controversé)' : '';
return `
### ${index + 1}. Commentaire dans r/${comment.subreddit}
- **Post**: ${comment.submissionTitle}
- **Score**: ${scoreText}${controversialText}
- **Posté**: ${postedDate}
- **Lien**: ${comment.permalink}
**Contenu**: ${comment.body.substring(0, 300)}${comment.body.length > 300 ? '...' : ''}
`;
}).join('\n');
return {
content: [
{
type: "text",
text: `# Commentaires récents de u/${username}
**Tri**: ${sort}
**Nombre de commentaires**: ${comments.length}
${commentsText}`,
},
],
};
} catch (error) {
console.error(`[Error] Error getting user comments: ${error}`);
throw new McpError(
ErrorCode.InternalError,
`Failed to fetch user comments: ${error}`
);
}
}
export async function getUserActivity(params: { username: string; limit?: number }) {
const { username, limit = 50 } = params;
const client = getRedditClient();
if (!client) {
throw new McpError(
ErrorCode.InternalError,
"Reddit client not initialized"
);
}
try {
console.log(`[Tool] Getting activity overview for u/${username}`);
const { posts, comments } = await client.getUserOverview(username, "new", limit);
const user = await client.getUser(username);
// Analyser les subreddits les plus actifs
const subredditActivity: { [key: string]: { posts: number; comments: number } } = {};
posts.forEach(post => {
if (!subredditActivity[post.subreddit]) {
subredditActivity[post.subreddit] = { posts: 0, comments: 0 };
}
subredditActivity[post.subreddit].posts++;
});
comments.forEach(comment => {
if (!subredditActivity[comment.subreddit]) {
subredditActivity[comment.subreddit] = { posts: 0, comments: 0 };
}
subredditActivity[comment.subreddit].comments++;
});
const topSubreddits = Object.entries(subredditActivity)
.map(([name, activity]) => ({
name,
total: activity.posts + activity.comments,
posts: activity.posts,
comments: activity.comments
}))
.sort((a, b) => b.total - a.total)
.slice(0, 10);
// Statistiques de score
const postScores = posts.map(p => p.score);
const commentScores = comments.map(c => c.score);
const avgPostScore = postScores.length > 0 ? Math.round(postScores.reduce((a, b) => a + b, 0) / postScores.length) : 0;
const avgCommentScore = commentScores.length > 0 ? Math.round(commentScores.reduce((a, b) => a + b, 0) / commentScores.length) : 0;
const maxPostScore = postScores.length > 0 ? Math.max(...postScores) : 0;
const maxCommentScore = commentScores.length > 0 ? Math.max(...commentScores) : 0;
const accountAge = Math.floor((Date.now() / 1000 - user.createdUtc) / (24 * 60 * 60));
const topSubredditsText = topSubreddits.map((sr, index) =>
`${index + 1}. **r/${sr.name}** - ${sr.total} activités (${sr.posts} posts, ${sr.comments} commentaires)`
).join('\n');
return {
content: [
{
type: "text",
text: `# Analyse d'activité détaillée - u/${username}
## 📊 Statistiques générales
- **Âge du compte**: ${accountAge} jours
- **Karma total**: ${user.totalKarma.toLocaleString()}
- **Posts récents analysés**: ${posts.length}
- **Commentaires récents analysés**: ${comments.length}
## 📈 Performance
- **Score moyen des posts**: ${avgPostScore}
- **Score moyen des commentaires**: ${avgCommentScore}
- **Meilleur post**: ${maxPostScore} points
- **Meilleur commentaire**: ${maxCommentScore} points
## 🎯 Subreddits les plus actifs
${topSubredditsText}
## 📅 Activité récente
- **Posts dans les dernières données**: ${posts.length}
- **Commentaires dans les dernières données**: ${comments.length}
- **Ratio posts/commentaires**: ${posts.length > 0 ? Math.round((comments.length / posts.length) * 100) / 100 : 'N/A'}
## 💡 Analyse comportementale
${posts.length > comments.length ?
'- **Profil**: Créateur de contenu - publie plus qu\'il ne commente' :
'- **Profil**: Participant actif - commente plus qu\'il ne publie'}
${avgPostScore > avgCommentScore ?
'- **Engagement**: Les posts génèrent plus d\'engagement que les commentaires' :
'- **Engagement**: Les commentaires sont mieux reçus que les posts'}
${topSubreddits.length > 0 ?
`- **Communauté principale**: Très actif dans r/${topSubreddits[0].name}` :
'- **Communauté**: Activité dispersée dans plusieurs subreddits'}`,
},
],
};
} catch (error) {
console.error(`[Error] Error getting user activity: ${error}`);
throw new McpError(
ErrorCode.InternalError,
`Failed to fetch user activity: ${error}`
);
}
}