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.
92 lines • 3.51 kB
JavaScript
import { RedditError } from "../../types/reddit.js";
export class RedditAuthService {
constructor(config) {
this.config = config;
this.tokenEndpoint = "https://www.reddit.com/api/v1/access_token";
this.accessToken = null;
this.tokenExpiresAt = null;
this.userAgent = `${config.appName}/${config.appVersion} by ${config.username}`;
}
async initialize() {
await this.refreshAccessToken();
}
async getAuthHeaders() {
const token = await this.getAccessToken();
return {
Authorization: `Bearer ${token}`,
"User-Agent": this.userAgent,
Accept: "application/json",
};
}
async getAccessToken() {
if (!this.accessToken || this.isTokenExpired()) {
await this.refreshAccessToken();
}
return this.accessToken;
}
async fetchUserInfo() {
const token = await this.getAccessToken();
const response = await fetch("https://oauth.reddit.com/api/v1/me", {
headers: {
Authorization: `Bearer ${token}`,
"User-Agent": this.userAgent,
},
});
if (!response.ok) {
throw new RedditError(`Failed to fetch user info: ${response.statusText}`, "API_ERROR");
}
const data = await response.json();
return {
id: data.id,
name: data.name,
created_utc: data.created_utc,
comment_karma: data.comment_karma,
link_karma: data.link_karma,
is_gold: data.is_gold,
is_mod: data.is_mod,
has_verified_email: data.has_verified_email,
};
}
async fetchUserPreferences() {
const token = await this.getAccessToken();
const response = await fetch("https://oauth.reddit.com/api/v1/me/prefs", {
headers: {
Authorization: `Bearer ${token}`,
"User-Agent": this.userAgent,
},
});
if (!response.ok) {
throw new RedditError(`Failed to fetch user preferences: ${response.statusText}`, "API_ERROR");
}
const prefs = await response.json();
return {
enable_notifications: prefs.enable_notifications ?? true,
show_nsfw: prefs.over_18 ?? false,
default_comment_sort: prefs.default_comment_sort ?? "best",
theme: prefs.theme ?? "dark",
language: prefs.language ?? "en",
};
}
isTokenExpired() {
return !this.tokenExpiresAt || Date.now() >= this.tokenExpiresAt;
}
async refreshAccessToken() {
const auth = Buffer.from(`${this.config.clientId}:${this.config.clientSecret}`).toString("base64");
const response = await fetch(this.tokenEndpoint, {
method: "POST",
headers: {
Authorization: `Basic ${auth}`,
"Content-Type": "application/x-www-form-urlencoded",
"User-Agent": this.userAgent,
},
body: `grant_type=refresh_token&refresh_token=${this.config.refreshToken}`,
});
if (!response.ok) {
throw new RedditError(`Failed to refresh access token: ${response.statusText}`, "AUTH_ERROR");
}
const data = await response.json();
this.accessToken = data.access_token;
this.tokenExpiresAt = Date.now() + data.expires_in * 1000;
}
}
//# sourceMappingURL=reddit-auth-service.js.map