systemprompt-mcp-reddit
Version:
A specialized Model Context Protocol (MCP) server that enables you to search, read, and interact with Reddit content, leveraging an AI Agent to help with each operation.
214 lines • 8.21 kB
JavaScript
/**
* Type guards and transformation utilities for Reddit API responses
*/
export const isRedditPostData = (data) => {
const post = data;
return (typeof post?.id === "string" &&
typeof post?.title === "string" &&
typeof post?.author === "string" &&
typeof post?.subreddit === "string" &&
typeof post?.permalink === "string");
};
export const transformPost = (data) => {
if (!isRedditPostData(data)) {
throw new Error("Invalid post data received from Reddit API");
}
return {
id: data.id,
title: data.title,
author: data.author,
subreddit: data.subreddit,
selftext: data.selftext || undefined,
url: data.url || undefined,
score: Number(data.score),
createdUtc: Number(data.created_utc),
numComments: Number(data.num_comments),
permalink: data.permalink,
};
};
export const isRedditCommentData = (data) => {
const comment = data;
return (typeof comment?.id === "string" &&
typeof comment?.author === "string" &&
typeof comment?.body === "string" &&
typeof comment?.permalink === "string");
};
export const transformComment = (data) => {
if (!isRedditCommentData(data)) {
throw new Error("Invalid comment data received from Reddit API");
}
return {
id: data.id,
author: data.author,
body: data.body,
score: Number(data.score),
createdUtc: Number(data.created_utc),
permalink: data.permalink,
};
};
export const isRedditSubredditData = (data) => {
const subreddit = data;
return (typeof subreddit?.display_name === "string" &&
typeof subreddit?.title === "string" &&
typeof subreddit?.public_description === "string");
};
export const transformSubreddit = (data) => {
if (!isRedditSubredditData(data)) {
throw new Error("Invalid subreddit data received from Reddit API");
}
const rules = Array.isArray(data.rules) ? data.rules : [];
return {
displayName: data.display_name,
title: data.title,
publicDescription: data.public_description,
subscribers: Number(data.subscribers),
createdUtc: Number(data.created_utc),
over18: Boolean(data.over18),
allowedPostTypes: extractAllowedPostTypes(data),
rules: rules.map((rule) => ({
title: rule.short_name || rule.title,
description: rule.description,
})),
postRequirements: {
title: {
minLength: typeof data.title_min_length === "number" ? data.title_min_length : undefined,
maxLength: typeof data.title_max_length === "number" ? data.title_max_length : undefined,
allowedPrefixes: Array.isArray(data.allowed_title_prefixes)
? data.allowed_title_prefixes
: undefined,
bannedPhrases: Array.isArray(data.banned_title_phrases)
? data.banned_title_phrases
: undefined,
},
body: {
required: typeof data.body_required === "boolean" ? data.body_required : undefined,
minLength: typeof data.body_min_length === "number" ? data.body_min_length : undefined,
maxLength: typeof data.body_max_length === "number" ? data.body_max_length : undefined,
},
flairRequired: typeof data.flair_required === "boolean" ? data.flair_required : undefined,
},
};
};
export const transformNotification = (data) => {
// Determine notification type and subject
let type = "other";
let subject = String(data.subject || "");
// For comment replies, we need to check link_title to determine if it's a post or comment reply
if (data.was_comment) {
const id = String(data.parent_id || "");
if (id.startsWith("t3_")) {
type = "post_reply";
// For post replies, use the post title as subject
subject = String(data.link_title || "Comment on your post");
}
else {
type = "comment_reply";
// For comment replies, use a descriptive subject
subject = "Reply to your comment";
}
}
else if (data.subject === "username mention") {
type = "username_mention";
subject = "Username mention";
}
else if (data.subject && !data.was_comment) {
type = "message";
// For messages, use the original subject
subject = String(data.subject);
}
return {
id: String(data.name || ""), // name contains the full ID with prefix
name: String(data.name || ""),
type,
subject,
body: String(data.body || ""),
createdUtc: Number(data.created_utc || 0),
date: data.date instanceof Date ? data.date : new Date(),
author: String(data.author || "[deleted]"),
subreddit: typeof data.subreddit === "string" ? data.subreddit : undefined,
context: typeof data.context === "string" ? data.context : undefined,
parentId: typeof data.parent_id === "string" ? data.parent_id : undefined,
isNew: Boolean(data.new),
permalink: typeof data.permalink === "string" ? data.permalink : data.context,
};
};
export const transformMessage = (data) => {
return {
id: String(data.name || ""),
type: "message",
subject: String(data.subject || ""),
parent_id: String(data.parent_id || data.name || ""),
author: String(data.author || "[deleted]"),
body: String(data.body || ""),
created_utc: Number(data.created_utc || 0),
unread: Boolean(data.new),
};
};
export function transformToConfigNotification(notification) {
if (notification.type === "message") {
return {
id: notification.id,
type: "message",
subject: notification.subject,
parent_id: notification.parentId || notification.id,
author: notification.author,
body: notification.body,
created_utc: notification.createdUtc,
unread: notification.isNew,
};
}
return {
id: notification.id,
type: notification.type,
subject: notification.subject,
parent_id: notification.parentId || "",
subreddit: notification.subreddit || "",
author: notification.author,
body: notification.body || "",
created_utc: notification.createdUtc,
permalink: notification.permalink || "",
unread: notification.isNew,
};
}
const extractAllowedPostTypes = (data) => {
const types = [];
if (data.submission_type === "any" || data.submission_type === "self") {
types.push("text");
}
if (data.submission_type === "any" || data.submission_type === "link") {
types.push("link");
}
return types.length > 0 ? types : ["text", "link"];
};
export const isSubscribedSubredditData = (data) => {
const subreddit = data;
return (typeof subreddit?.id === "string" &&
typeof subreddit?.name === "string" &&
typeof subreddit?.display_name === "string" &&
typeof subreddit?.title === "string" &&
typeof subreddit?.public_description === "string" &&
typeof subreddit?.subscribers === "number" &&
typeof subreddit?.over18 === "boolean" &&
typeof subreddit?.url === "string" &&
typeof subreddit?.created_utc === "number" &&
typeof subreddit?.subreddit_type === "string");
};
export const transformSubscribedSubreddit = (data) => {
if (!isSubscribedSubredditData(data)) {
throw new Error("Invalid subscribed subreddit data received from Reddit API");
}
return {
id: data.id,
name: data.name,
displayName: data.display_name,
title: data.title,
subscribers: data.subscribers,
description: data.public_description,
isNsfw: data.over18,
url: data.url,
icon: data.icon_img,
createdUtc: data.created_utc,
type: data.subreddit_type,
};
};
//# sourceMappingURL=reddit-transformers.js.map