@classytic/social 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (121) hide show
  1. package/CHANGELOG.md +65 -0
  2. package/LICENSE +21 -0
  3. package/README.md +368 -0
  4. package/dist/base-Bw7e52V8.mjs +246 -0
  5. package/dist/base-Bw7e52V8.mjs.map +1 -0
  6. package/dist/base-DBtKFiSX.d.mts +226 -0
  7. package/dist/base-DBtKFiSX.d.mts.map +1 -0
  8. package/dist/chunk-DQk6qfdC.mjs +18 -0
  9. package/dist/client/index.d.mts +44 -0
  10. package/dist/client/index.d.mts.map +1 -0
  11. package/dist/client/index.mjs +154 -0
  12. package/dist/client/index.mjs.map +1 -0
  13. package/dist/common/index.d.mts +3 -0
  14. package/dist/common/index.mjs +7 -0
  15. package/dist/contracts-Cdwa4zlg.d.mts +121 -0
  16. package/dist/contracts-Cdwa4zlg.d.mts.map +1 -0
  17. package/dist/contracts-lCa069IK.mjs +221 -0
  18. package/dist/contracts-lCa069IK.mjs.map +1 -0
  19. package/dist/env-Bl0cwwjC.mjs +955 -0
  20. package/dist/env-Bl0cwwjC.mjs.map +1 -0
  21. package/dist/env-DxOZHf0p.d.mts +394 -0
  22. package/dist/env-DxOZHf0p.d.mts.map +1 -0
  23. package/dist/errors-Cm6LeKf7.mjs +32 -0
  24. package/dist/errors-Cm6LeKf7.mjs.map +1 -0
  25. package/dist/facebook-l_4CghaA.mjs +95 -0
  26. package/dist/facebook-l_4CghaA.mjs.map +1 -0
  27. package/dist/http-DpcLSR1M.mjs +197 -0
  28. package/dist/http-DpcLSR1M.mjs.map +1 -0
  29. package/dist/index.d.mts +42 -0
  30. package/dist/index.d.mts.map +1 -0
  31. package/dist/index.mjs +71 -0
  32. package/dist/index.mjs.map +1 -0
  33. package/dist/instagram-BGaeUFU2.mjs +90 -0
  34. package/dist/instagram-BGaeUFU2.mjs.map +1 -0
  35. package/dist/linkedin-70whtVKa.mjs +101 -0
  36. package/dist/linkedin-70whtVKa.mjs.map +1 -0
  37. package/dist/meta-D3vcJU1c.mjs +126 -0
  38. package/dist/meta-D3vcJU1c.mjs.map +1 -0
  39. package/dist/pkce-jq5II68b.mjs +72 -0
  40. package/dist/pkce-jq5II68b.mjs.map +1 -0
  41. package/dist/polling-DZ1apXtA.mjs +25 -0
  42. package/dist/polling-DZ1apXtA.mjs.map +1 -0
  43. package/dist/providers/facebook.d.mts +135 -0
  44. package/dist/providers/facebook.d.mts.map +1 -0
  45. package/dist/providers/facebook.mjs +450 -0
  46. package/dist/providers/facebook.mjs.map +1 -0
  47. package/dist/providers/instagram.d.mts +122 -0
  48. package/dist/providers/instagram.d.mts.map +1 -0
  49. package/dist/providers/instagram.mjs +496 -0
  50. package/dist/providers/instagram.mjs.map +1 -0
  51. package/dist/providers/linkedin.d.mts +145 -0
  52. package/dist/providers/linkedin.d.mts.map +1 -0
  53. package/dist/providers/linkedin.mjs +574 -0
  54. package/dist/providers/linkedin.mjs.map +1 -0
  55. package/dist/providers/reddit.d.mts +102 -0
  56. package/dist/providers/reddit.d.mts.map +1 -0
  57. package/dist/providers/reddit.mjs +657 -0
  58. package/dist/providers/reddit.mjs.map +1 -0
  59. package/dist/providers/telegram.d.mts +139 -0
  60. package/dist/providers/telegram.d.mts.map +1 -0
  61. package/dist/providers/telegram.mjs +517 -0
  62. package/dist/providers/telegram.mjs.map +1 -0
  63. package/dist/providers/tiktok.d.mts +116 -0
  64. package/dist/providers/tiktok.d.mts.map +1 -0
  65. package/dist/providers/tiktok.mjs +676 -0
  66. package/dist/providers/tiktok.mjs.map +1 -0
  67. package/dist/providers/twitter.d.mts +150 -0
  68. package/dist/providers/twitter.d.mts.map +1 -0
  69. package/dist/providers/twitter.mjs +628 -0
  70. package/dist/providers/twitter.mjs.map +1 -0
  71. package/dist/providers/whatsapp.d.mts +79 -0
  72. package/dist/providers/whatsapp.d.mts.map +1 -0
  73. package/dist/providers/whatsapp.mjs +376 -0
  74. package/dist/providers/whatsapp.mjs.map +1 -0
  75. package/dist/providers/youtube.d.mts +153 -0
  76. package/dist/providers/youtube.d.mts.map +1 -0
  77. package/dist/providers/youtube.mjs +902 -0
  78. package/dist/providers/youtube.mjs.map +1 -0
  79. package/dist/reddit-B10kS4Se.mjs +126 -0
  80. package/dist/reddit-B10kS4Se.mjs.map +1 -0
  81. package/dist/schemas/index.d.mts +819 -0
  82. package/dist/schemas/index.d.mts.map +1 -0
  83. package/dist/schemas/index.mjs +31 -0
  84. package/dist/schemas/index.mjs.map +1 -0
  85. package/dist/security-BXhfebWm.d.mts +338 -0
  86. package/dist/security-BXhfebWm.d.mts.map +1 -0
  87. package/dist/shared-Fvc6xQku.mjs +100 -0
  88. package/dist/shared-Fvc6xQku.mjs.map +1 -0
  89. package/dist/telegram-FaUHpZgB.mjs +107 -0
  90. package/dist/telegram-FaUHpZgB.mjs.map +1 -0
  91. package/dist/tiktok-B_bMk4G-.mjs +94 -0
  92. package/dist/tiktok-B_bMk4G-.mjs.map +1 -0
  93. package/dist/twitter-BC22zfuc.mjs +98 -0
  94. package/dist/twitter-BC22zfuc.mjs.map +1 -0
  95. package/dist/types-BFE4psYI.d.mts +102 -0
  96. package/dist/types-BFE4psYI.d.mts.map +1 -0
  97. package/dist/types-Bv27tcT0.d.mts +230 -0
  98. package/dist/types-Bv27tcT0.d.mts.map +1 -0
  99. package/dist/types-BwkKyqpi.d.mts +253 -0
  100. package/dist/types-BwkKyqpi.d.mts.map +1 -0
  101. package/dist/types-CJrHMDV9.mjs +27 -0
  102. package/dist/types-CJrHMDV9.mjs.map +1 -0
  103. package/dist/types-ClbVc2rc.d.mts +117 -0
  104. package/dist/types-ClbVc2rc.d.mts.map +1 -0
  105. package/dist/types-D91N16Ym.d.mts +242 -0
  106. package/dist/types-D91N16Ym.d.mts.map +1 -0
  107. package/dist/types-DfLp_ibQ.d.mts +178 -0
  108. package/dist/types-DfLp_ibQ.d.mts.map +1 -0
  109. package/dist/types-DfjDgEoJ.d.mts +88 -0
  110. package/dist/types-DfjDgEoJ.d.mts.map +1 -0
  111. package/dist/types-Dp5Z9VBr.mjs +23 -0
  112. package/dist/types-Dp5Z9VBr.mjs.map +1 -0
  113. package/dist/types-hriBJTsU.d.mts +129 -0
  114. package/dist/types-hriBJTsU.d.mts.map +1 -0
  115. package/dist/types-rn6UuLL8.d.mts +184 -0
  116. package/dist/types-rn6UuLL8.d.mts.map +1 -0
  117. package/dist/whatsapp-CFp7ryR4.mjs +101 -0
  118. package/dist/whatsapp-CFp7ryR4.mjs.map +1 -0
  119. package/dist/youtube-Bs0fdY7H.mjs +98 -0
  120. package/dist/youtube-Bs0fdY7H.mjs.map +1 -0
  121. package/package.json +148 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"reddit.mjs","names":["ERROR_HINTS"],"sources":["../../src/providers/reddit/index.ts"],"sourcesContent":["/**\n * Reddit Provider\n * ===============\n * Full Reddit API integration with OAuth 2.0.\n *\n * Supports:\n * - OAuth 2.0 (authorization code with permanent duration)\n * - Post CRUD (create text/link/image, get, delete, search)\n * - Comments (create, reply, delete, list)\n * - Voting (upvote, downvote, unvote)\n * - Subreddit info and rules\n * - User profile and public user data\n * - Subreddit browsing (hot, new, top, rising)\n *\n * @see https://www.reddit.com/dev/api/\n * @see https://github.com/reddit-archive/reddit/wiki/OAuth2\n */\n\nimport { PlatformProvider, type AccountInfo, type OAuthTokens, type UploadResult, type TestResult, type CredentialField, type ProviderMetadata, type AuthUrlOptions, type ProviderConfig } from '../../base.js';\nimport { SocialError } from '../../errors.js';\nimport { RedditCredentialsSchema } from '../../schemas/reddit.js';\nimport { httpRequest } from '../../common/http.js';\nimport type { z } from 'zod';\nimport type {\n RedditCredentials,\n CreatePostParams,\n CreatePostResult,\n CreateCommentParams,\n RedditPost,\n RedditComment,\n RedditSubreddit,\n SubredditRule,\n RedditListing,\n RedditListingParams,\n RedditSearchParams,\n RedditSortOrder,\n RedditTimeFilter,\n VoteDirection,\n RedditUserProfile,\n RedditProfileDetail,\n} from './types.js';\nimport { REDDIT_ERROR_HINTS as ERROR_HINTS } from './types.js';\n\nexport type { RedditCredentials, CreatePostParams, CreatePostResult, CreateCommentParams, RedditPost, RedditComment, RedditSubreddit, SubredditRule, RedditListing, RedditListingParams, RedditSearchParams, VoteDirection, RedditUserProfile } from './types.js';\n\n// ---------------------------------------------------------------------------\n// Constants\n// ---------------------------------------------------------------------------\n\nconst OAUTH_API = 'https://oauth.reddit.com';\nconst PUBLIC_API = 'https://www.reddit.com';\nconst AUTH_URL = 'https://www.reddit.com/api/v1/authorize';\nconst TOKEN_URL = 'https://www.reddit.com/api/v1/access_token';\nconst REVOKE_URL = 'https://www.reddit.com/api/v1/revoke_token';\n\nconst USER_AGENT = 'web:com.classytic.social:v0.1.0 (by /u/classytic)';\n\nconst DEFAULT_SCOPES = [\n 'identity', 'edit', 'history', 'mysubreddits',\n 'read', 'save', 'submit', 'vote', 'subscribe',\n 'privatemessages', 'flair',\n];\n\nconst SCOPE_DESCRIPTIONS: Record<string, string> = {\n 'identity': 'Access your Reddit username and account information',\n 'edit': 'Edit your posts and comments',\n 'history': 'Access your voting and browsing history',\n 'mysubreddits': 'View your subscribed subreddits',\n 'read': 'Read posts, comments, and subreddit information',\n 'save': 'Save and unsave posts and comments',\n 'submit': 'Create new posts and comments',\n 'vote': 'Upvote and downvote content',\n 'subscribe': 'Subscribe and unsubscribe from subreddits',\n 'privatemessages': 'Read and send private messages',\n 'flair': 'Set and manage flair on posts',\n};\n\n// ---------------------------------------------------------------------------\n// Provider\n// ---------------------------------------------------------------------------\n\nexport class RedditProvider extends PlatformProvider {\n constructor(config: ProviderConfig = {}) {\n super(config);\n this.name = 'reddit';\n this.displayName = 'Reddit';\n this.authType = 'oauth2';\n }\n\n // ─── Auth ────────────────────────────────────────────────────────────\n\n getAuthUrl(state: string, credData?: Record<string, any>, options?: AuthUrlOptions): string {\n const clientId = credData?.clientId;\n if (!clientId) throw new SocialError('reddit', 'Client ID is required', { statusCode: 400 });\n\n const redirectUri = credData?.redirectUri || this.config.redirectUri\n || `http://localhost:${this.config.port || 8060}/api/oauth/reddit/callback`;\n\n const params = new URLSearchParams({\n client_id: clientId,\n response_type: 'code',\n state,\n redirect_uri: redirectUri,\n duration: 'permanent',\n scope: DEFAULT_SCOPES.join(' '),\n });\n\n return `${AUTH_URL}?${params.toString()}`;\n }\n\n async exchangeCode(code: string, credData?: Record<string, any>): Promise<OAuthTokens> {\n const clientId = credData?.clientId;\n const clientSecret = credData?.clientSecret;\n if (!clientId || !clientSecret) {\n throw new SocialError('reddit', 'Client ID and Client Secret are required for token exchange', { statusCode: 400 });\n }\n\n const redirectUri = credData?.redirectUri || this.config.redirectUri\n || `http://localhost:${this.config.port || 8060}/api/oauth/reddit/callback`;\n\n const body = new URLSearchParams({\n grant_type: 'authorization_code',\n code,\n redirect_uri: redirectUri,\n });\n\n const response = await fetch(TOKEN_URL, {\n method: 'POST',\n headers: {\n 'Authorization': `Basic ${btoa(`${clientId}:${clientSecret}`)}`,\n 'Content-Type': 'application/x-www-form-urlencoded',\n 'User-Agent': USER_AGENT,\n },\n body: body.toString(),\n });\n\n const data = await response.json() as Record<string, unknown>;\n\n if (!response.ok || data.error) {\n throw new SocialError('reddit', `Token exchange failed: ${data.error || response.statusText}`, {\n statusCode: response.status,\n errorCode: data.error as string,\n hint: ERROR_HINTS['INVALID_GRANT'] || 'Ensure your Client ID, Client Secret, and redirect URI are correct.',\n originalError: new Error(JSON.stringify(data)),\n });\n }\n\n return {\n access_token: data.access_token as string,\n refresh_token: data.refresh_token as string | undefined,\n expires_in: data.expires_in as number | undefined,\n token_type: data.token_type as string | undefined,\n scope: data.scope as string | undefined,\n };\n }\n\n async refreshToken(refreshToken: string, credData?: Record<string, any>): Promise<OAuthTokens> {\n const clientId = credData?.clientId;\n const clientSecret = credData?.clientSecret;\n if (!clientId || !clientSecret) {\n throw new SocialError('reddit', 'Client ID and Client Secret are required for token refresh', { statusCode: 400 });\n }\n\n const body = new URLSearchParams({\n grant_type: 'refresh_token',\n refresh_token: refreshToken,\n });\n\n const response = await fetch(TOKEN_URL, {\n method: 'POST',\n headers: {\n 'Authorization': `Basic ${btoa(`${clientId}:${clientSecret}`)}`,\n 'Content-Type': 'application/x-www-form-urlencoded',\n 'User-Agent': USER_AGENT,\n },\n body: body.toString(),\n });\n\n const data = await response.json() as Record<string, unknown>;\n\n if (!response.ok || data.error) {\n throw new SocialError('reddit', `Token refresh failed: ${data.error || response.statusText}`, {\n statusCode: response.status,\n errorCode: data.error as string,\n hint: 'The refresh token may have been revoked. Re-authenticate.',\n });\n }\n\n return {\n access_token: data.access_token as string,\n refresh_token: data.refresh_token as string | undefined,\n expires_in: data.expires_in as number | undefined,\n token_type: data.token_type as string | undefined,\n scope: data.scope as string | undefined,\n };\n }\n\n async revokeToken(accessToken: string, credData?: Record<string, any>): Promise<void> {\n const clientId = credData?.clientId;\n const clientSecret = credData?.clientSecret;\n if (!clientId || !clientSecret) return;\n\n const body = new URLSearchParams({\n token: accessToken,\n token_type_hint: 'access_token',\n });\n\n await fetch(REVOKE_URL, {\n method: 'POST',\n headers: {\n 'Authorization': `Basic ${btoa(`${clientId}:${clientSecret}`)}`,\n 'Content-Type': 'application/x-www-form-urlencoded',\n 'User-Agent': USER_AGENT,\n },\n body: body.toString(),\n }).catch(() => {}); // Best-effort\n }\n\n // ─── Account ─────────────────────────────────────────────────────────\n\n async getAccountInfo(accessToken: string): Promise<AccountInfo> {\n const data = await this._api('GET', '/api/v1/me', accessToken);\n\n return {\n id: data.id,\n name: data.name,\n username: data.name,\n profileImage: data.icon_img?.split('?')[0] ?? null,\n linkKarma: data.link_karma,\n commentKarma: data.comment_karma,\n totalKarma: data.total_karma,\n createdUtc: data.created_utc,\n hasVerifiedEmail: data.has_verified_email,\n isGold: data.is_gold,\n isMod: data.is_mod,\n };\n }\n\n async testCredential(credentialData: Record<string, any>): Promise<TestResult> {\n try {\n const tokenData = typeof credentialData.oauthTokenData === 'string'\n ? JSON.parse(credentialData.oauthTokenData)\n : credentialData.oauthTokenData;\n\n if (!tokenData?.access_token) {\n return { status: 'Error', message: 'No access token found. Complete OAuth authorization first.' };\n }\n\n const info = await this.getAccountInfo(tokenData.access_token);\n return {\n status: 'OK',\n message: `Connected as u/${info.name} (${info.totalKarma} karma)`,\n data: { id: info.id, name: info.name, username: info.name },\n };\n } catch (err) {\n const msg = err instanceof Error ? err.message : String(err);\n return { status: 'Error', message: msg };\n }\n }\n\n // ─── Post CRUD ───────────────────────────────────────────────────────\n\n /**\n * Create a post (text, link, or image).\n */\n async createPost(accessToken: string, params: CreatePostParams): Promise<CreatePostResult> {\n const body: Record<string, string> = {\n api_type: 'json',\n sr: params.subreddit,\n title: params.title,\n kind: params.kind,\n resubmit: String(params.resubmit ?? true),\n send_replies: String(params.sendReplies ?? true),\n };\n\n if (params.kind === 'self' && params.text) {\n body.text = params.text;\n }\n if ((params.kind === 'link' || params.kind === 'image') && params.url) {\n body.url = params.url;\n }\n if (params.nsfw) body.nsfw = 'true';\n if (params.spoiler) body.spoiler = 'true';\n if (params.flairId) body.flair_id = params.flairId;\n if (params.flairText) body.flair_text = params.flairText;\n\n const data = await this._api('POST', '/api/submit', accessToken, body, true);\n\n const json = data.json;\n if (json?.errors?.length) {\n const [errorCode, errorMsg] = json.errors[0];\n throw new SocialError('reddit', `Post creation failed: ${errorMsg}`, {\n statusCode: 400,\n errorCode,\n hint: ERROR_HINTS[errorCode] || null,\n });\n }\n\n const postData = json?.data;\n return {\n id: postData?.id ?? '',\n name: postData?.name ?? '',\n url: postData?.url ?? `https://reddit.com${postData?.permalink ?? ''}`,\n };\n }\n\n /**\n * Get a single post with its comments.\n */\n async getPost(accessToken: string, subreddit: string, postId: string): Promise<{ post: RedditPost; comments: RedditComment[] }> {\n // Reddit returns an array: [0] = post listing, [1] = comments listing\n const data = await this._api('GET', `/r/${subreddit}/comments/${postId}.json`, accessToken);\n\n const postRaw = data[0]?.data?.children?.[0]?.data;\n if (!postRaw) {\n throw new SocialError('reddit', `Post ${postId} not found in r/${subreddit}`, {\n statusCode: 404,\n hint: ERROR_HINTS['NOT_FOUND'],\n });\n }\n\n const comments = (data[1]?.data?.children || [])\n .filter((c: any) => c.kind === 't1')\n .map((c: any) => this._parseComment(c.data));\n\n return {\n post: this._parsePost(postRaw),\n comments,\n };\n }\n\n /**\n * Delete a post or comment by fullname (t3_ or t1_ prefix).\n */\n async deleteContent(accessToken: string, fullname: string): Promise<{ success: boolean }> {\n await this._api('POST', '/api/del', accessToken, { id: fullname }, true);\n return { success: true };\n }\n\n async deletePost(accessToken: string, fullname: string): Promise<unknown> {\n return this.deleteContent(accessToken, fullname);\n }\n\n /**\n * Get posts from a subreddit.\n */\n async getSubredditPosts(\n accessToken: string,\n subreddit: string,\n params: RedditListingParams = {},\n ): Promise<RedditListing<RedditPost>> {\n const sort = params.sort || 'hot';\n const qs = new URLSearchParams();\n if (params.limit) qs.set('limit', String(Math.min(params.limit, 100)));\n if (params.after) qs.set('after', params.after);\n if (params.before) qs.set('before', params.before);\n if (params.time && (sort === 'top' || sort === 'controversial')) {\n qs.set('t', params.time);\n }\n\n const queryStr = qs.toString();\n const endpoint = `/r/${subreddit}/${sort}.json${queryStr ? `?${queryStr}` : ''}`;\n\n const data = await this._api('GET', endpoint, accessToken);\n\n return {\n items: (data.data?.children || []).map((c: any) => this._parsePost(c.data)),\n after: data.data?.after ?? null,\n before: data.data?.before ?? null,\n };\n }\n\n /**\n * Search posts across Reddit or within a specific subreddit.\n */\n async searchPosts(accessToken: string, params: RedditSearchParams): Promise<RedditListing<RedditPost>> {\n const qs = new URLSearchParams({\n q: params.query,\n sort: params.sort || 'relevance',\n t: params.time || 'all',\n limit: String(params.limit || 25),\n type: params.type || 'link',\n restrict_sr: params.subreddit ? 'true' : 'false',\n });\n if (params.after) qs.set('after', params.after);\n\n const base = params.subreddit ? `/r/${params.subreddit}` : '';\n const data = await this._api('GET', `${base}/search.json?${qs.toString()}`, accessToken);\n\n return {\n items: (data.data?.children || []).map((c: any) => this._parsePost(c.data)),\n after: data.data?.after ?? null,\n before: data.data?.before ?? null,\n };\n }\n\n // ─── Comments ────────────────────────────────────────────────────────\n\n /**\n * Create a comment on a post or reply to a comment.\n */\n async createComment(accessToken: string, params: CreateCommentParams): Promise<RedditComment> {\n const data = await this._api('POST', '/api/comment', accessToken, {\n api_type: 'json',\n thing_id: params.parentFullname,\n text: params.text,\n }, true);\n\n const json = data.json;\n if (json?.errors?.length) {\n const [errorCode, errorMsg] = json.errors[0];\n throw new SocialError('reddit', `Comment creation failed: ${errorMsg}`, {\n statusCode: 400,\n errorCode,\n hint: ERROR_HINTS[errorCode] || null,\n });\n }\n\n const commentData = json?.data?.things?.[0]?.data;\n if (!commentData) {\n throw new SocialError('reddit', 'Unexpected response format from Reddit API', { statusCode: 502 });\n }\n\n return this._parseComment(commentData);\n }\n\n /**\n * Get comments for a post.\n */\n async getPostComments(\n accessToken: string,\n subreddit: string,\n postId: string,\n params: { limit?: number; sort?: 'confidence' | 'top' | 'new' | 'controversial' | 'old' | 'qa' } = {},\n ): Promise<RedditComment[]> {\n const qs = new URLSearchParams();\n if (params.limit) qs.set('limit', String(Math.min(params.limit, 100)));\n if (params.sort) qs.set('sort', params.sort);\n\n const queryStr = qs.toString();\n const data = await this._api('GET', `/r/${subreddit}/comments/${postId}.json${queryStr ? `?${queryStr}` : ''}`, accessToken);\n\n return (data[1]?.data?.children || [])\n .filter((c: any) => c.kind === 't1')\n .map((c: any) => this._parseComment(c.data));\n }\n\n // ─── Voting ──────────────────────────────────────────────────────────\n\n /**\n * Vote on a post or comment.\n * @param dir - 1 = upvote, 0 = unvote, -1 = downvote\n */\n async vote(accessToken: string, fullname: string, dir: VoteDirection): Promise<{ success: boolean }> {\n await this._api('POST', '/api/vote', accessToken, { id: fullname, dir: String(dir) }, true);\n return { success: true };\n }\n\n // ─── Subreddit ───────────────────────────────────────────────────────\n\n /**\n * Get subreddit information.\n */\n async getSubredditInfo(accessToken: string, subreddit: string): Promise<RedditSubreddit> {\n const data = await this._api('GET', `/r/${subreddit}/about.json`, accessToken);\n return this._parseSubreddit(data.data);\n }\n\n /**\n * Get subreddit rules.\n */\n async getSubredditRules(accessToken: string, subreddit: string): Promise<SubredditRule[]> {\n const data = await this._api('GET', `/r/${subreddit}/about/rules.json`, accessToken);\n return (data.rules || []).map((r: any) => ({\n kind: r.kind,\n shortName: r.short_name,\n description: r.description,\n violationReason: r.violation_reason,\n priority: r.priority,\n createdUtc: r.created_utc,\n }));\n }\n\n /**\n * Search for subreddits.\n */\n async searchSubreddits(\n accessToken: string,\n query: string,\n opts: { limit?: number } = {},\n ): Promise<RedditSubreddit[]> {\n const qs = new URLSearchParams({ query, limit: String(opts.limit || 25) });\n const data = await this._api('POST', `/api/search_subreddits.json?${qs.toString()}`, accessToken, {}, true);\n\n return (data.subreddits || []).map((s: any) => ({\n id: s.name,\n name: s.name,\n displayName: s.name,\n displayNamePrefixed: `r/${s.name}`,\n title: s.name,\n publicDescription: '',\n subscribers: s.subscriber_count ?? 0,\n activeUserCount: s.active_user_count ?? 0,\n createdUtc: 0,\n over18: false,\n subredditType: 'public' as const,\n iconImg: s.icon_img,\n url: `/r/${s.name}/`,\n }));\n }\n\n // ─── User Profile ────────────────────────────────────────────────────\n\n /**\n * Get authenticated user's profile details.\n */\n async getProfile(accessToken: string, detail: RedditProfileDetail = 'identity'): Promise<RedditUserProfile> {\n if (detail === 'identity') {\n const data = await this._api('GET', '/api/v1/me', accessToken);\n return {\n id: data.id,\n name: data.name,\n iconImg: data.icon_img?.split('?')[0],\n createdUtc: data.created_utc,\n linkKarma: data.link_karma,\n commentKarma: data.comment_karma,\n totalKarma: data.total_karma,\n isGold: data.is_gold,\n isMod: data.is_mod,\n hasVerifiedEmail: data.has_verified_email,\n };\n }\n\n if (detail === 'karma') {\n const data = await this._api('GET', '/api/v1/me/karma', accessToken);\n return {\n id: '', name: '', createdUtc: 0, linkKarma: 0, commentKarma: 0, totalKarma: 0,\n isGold: false, isMod: false, hasVerifiedEmail: false,\n subredditKarma: (data.data || []).map((k: any) => ({\n subreddit: k.sr,\n linkKarma: k.link_karma,\n commentKarma: k.comment_karma,\n })),\n };\n }\n\n // trophies, friends, blocked, prefs, saved\n const endpointMap: Record<string, string> = {\n trophies: '/api/v1/me/trophies',\n friends: '/api/v1/me/friends',\n blocked: '/api/v1/me/blocked',\n prefs: '/api/v1/me/prefs',\n saved: '/user/me/saved.json',\n };\n\n const data = await this._api('GET', endpointMap[detail]!, accessToken);\n // Return raw data wrapped in profile shape\n return {\n id: '', name: '', createdUtc: 0, linkKarma: 0, commentKarma: 0, totalKarma: 0,\n isGold: false, isMod: false, hasVerifiedEmail: false,\n ...data,\n } as RedditUserProfile;\n }\n\n /**\n * Get a public user's information.\n */\n async getUser(accessToken: string, username: string): Promise<RedditUserProfile> {\n const data = await this._api('GET', `/user/${username}/about.json`, accessToken);\n const user = data.data;\n return {\n id: user.id,\n name: user.name,\n iconImg: user.icon_img?.split('?')[0],\n createdUtc: user.created_utc,\n linkKarma: user.link_karma,\n commentKarma: user.comment_karma,\n totalKarma: (user.link_karma ?? 0) + (user.comment_karma ?? 0),\n isGold: user.is_gold ?? false,\n isMod: user.is_mod ?? false,\n hasVerifiedEmail: user.has_verified_email ?? false,\n };\n }\n\n // ─── Save / Unsave ──────────────────────────────────────────────────\n\n async saveContent(accessToken: string, fullname: string): Promise<{ success: boolean }> {\n await this._api('POST', '/api/save', accessToken, { id: fullname }, true);\n return { success: true };\n }\n\n async unsaveContent(accessToken: string, fullname: string): Promise<{ success: boolean }> {\n await this._api('POST', '/api/unsave', accessToken, { id: fullname }, true);\n return { success: true };\n }\n\n // ─── Upload (base interface) ─────────────────────────────────────────\n\n async uploadPhoto(params: any): Promise<UploadResult> {\n const { tokens, title, caption, description } = params;\n const imageUrl = params.videoUrl || params.imageUrl || params.url;\n\n if (!imageUrl) {\n throw new SocialError('reddit', 'Image URL is required for Reddit image posts', { statusCode: 400 });\n }\n if (!params.subreddit) {\n throw new SocialError('reddit', 'Subreddit is required for Reddit posts', { statusCode: 400 });\n }\n\n const result = await this.createPost(tokens.access_token, {\n subreddit: params.subreddit,\n title: title || caption || description || 'Image Post',\n kind: 'image',\n url: imageUrl,\n });\n\n return {\n platformPostId: result.id,\n platformUrl: result.url,\n status: 'published',\n uploadedAt: new Date(),\n };\n }\n\n async sendMessage(accessToken: string, subreddit: string, text: string): Promise<unknown> {\n // Reddit doesn't have traditional \"messaging\" — create a text post as the equivalent\n return this.createPost(accessToken, {\n subreddit,\n title: text.substring(0, 300),\n kind: 'self',\n text,\n });\n }\n\n // ─── Credential Schema & Metadata ────────────────────────────────────\n\n getCredentialZodSchema(): z.ZodType {\n return RedditCredentialsSchema;\n }\n\n getCredentialSchema(): CredentialField[] {\n return [\n {\n name: 'clientId',\n displayName: 'Client ID',\n type: 'text',\n required: true,\n description: 'Reddit app Client ID from reddit.com/prefs/apps',\n placeholder: 'abc123...',\n },\n {\n name: 'clientSecret',\n displayName: 'Client Secret',\n type: 'password',\n required: true,\n description: 'Reddit app Client Secret',\n placeholder: 'secret...',\n },\n ];\n }\n\n getMetadata(): ProviderMetadata {\n return {\n name: this.name,\n displayName: this.displayName,\n authType: this.authType,\n icon: 'reddit',\n brandColor: '#FF4500',\n description: 'Post to Reddit communities, browse subreddits, and manage content',\n scopes: DEFAULT_SCOPES,\n scopeDescriptions: SCOPE_DESCRIPTIONS,\n setupGuide: [\n { step: 1, title: 'Create a Reddit App', description: 'Go to reddit.com/prefs/apps → \"Create another app\". Select \"web app\" type.' },\n { step: 2, title: 'Set redirect URI', description: 'Set the redirect URI to your callback URL (e.g., http://localhost:8060/api/oauth/reddit/callback).' },\n { step: 3, title: 'Copy credentials', description: 'The Client ID is shown under the app name. The Client Secret is labeled \"secret\".' },\n { step: 4, title: 'User-Agent', description: 'Reddit requires a descriptive User-Agent header. This is handled automatically by the provider.' },\n ],\n supportsScheduling: false,\n supportsEnvironment: false,\n redirectUriPattern: '/api/oauth/reddit/callback',\n credentialSchema: this.getCredentialSchema(),\n };\n }\n\n // ─── Private Helpers ─────────────────────────────────────────────────\n\n /**\n * Core API request helper.\n * Uses OAuth endpoint for authenticated requests, public endpoint otherwise.\n */\n private async _api(\n method: string,\n endpoint: string,\n accessToken: string,\n body?: Record<string, string>,\n isForm = false,\n ): Promise<any> {\n const baseUrl = accessToken ? OAUTH_API : PUBLIC_API;\n const url = endpoint.startsWith('http') ? endpoint : `${baseUrl}${endpoint}`;\n\n const result = await httpRequest<any>('reddit', {\n method: method.toUpperCase() as 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE',\n url,\n bearer: accessToken || undefined,\n headers: { 'User-Agent': USER_AGENT },\n json: body && !isForm ? body : undefined,\n urlencoded: body && isForm ? body : undefined,\n timeout: 30_000,\n retry: { attempts: 2 },\n parseError: (raw, status) => {\n if (raw && typeof raw === 'object') {\n const r = raw as Record<string, unknown>;\n const errorReason = r.reason as string | undefined;\n return {\n message: (r.message as string) || (r.error as string) || `Reddit API error (${status})`,\n errorCode: errorReason || (r.error as string | undefined) || null,\n hint: ERROR_HINTS[String(status)] || (errorReason ? ERROR_HINTS[errorReason] : null) || null,\n };\n }\n return null;\n },\n });\n\n return result.status === 204 ? { success: true } : result.data;\n }\n\n private _parsePost(raw: Record<string, any>): RedditPost {\n return {\n id: raw.id,\n name: raw.name,\n title: raw.title,\n author: raw.author,\n subreddit: raw.subreddit,\n subredditId: raw.subreddit_id,\n selftext: raw.selftext || '',\n selftextHtml: raw.selftext_html,\n url: raw.url,\n permalink: `https://reddit.com${raw.permalink}`,\n domain: raw.domain,\n score: raw.score ?? 0,\n ups: raw.ups ?? 0,\n downs: raw.downs ?? 0,\n numComments: raw.num_comments ?? 0,\n createdUtc: raw.created_utc,\n isSelf: raw.is_self ?? false,\n isVideo: raw.is_video ?? false,\n over18: raw.over_18 ?? false,\n spoiler: raw.spoiler ?? false,\n stickied: raw.stickied ?? false,\n locked: raw.locked ?? false,\n archived: raw.archived ?? false,\n thumbnail: raw.thumbnail !== 'self' && raw.thumbnail !== 'default' ? raw.thumbnail : undefined,\n linkFlairText: raw.link_flair_text,\n authorFlairText: raw.author_flair_text,\n mediaUrl: raw.url_overridden_by_dest || raw.url,\n };\n }\n\n private _parseComment(raw: Record<string, any>): RedditComment {\n return {\n id: raw.id,\n name: raw.name,\n author: raw.author,\n body: raw.body,\n bodyHtml: raw.body_html,\n score: raw.score ?? 0,\n ups: raw.ups ?? 0,\n downs: raw.downs ?? 0,\n createdUtc: raw.created_utc,\n parentId: raw.parent_id,\n linkId: raw.link_id,\n subreddit: raw.subreddit,\n depth: raw.depth ?? 0,\n isSubmitter: raw.is_submitter ?? false,\n stickied: raw.stickied ?? false,\n edited: raw.edited ?? false,\n permalink: `https://reddit.com${raw.permalink || ''}`,\n };\n }\n\n private _parseSubreddit(raw: Record<string, any>): RedditSubreddit {\n return {\n id: raw.id,\n name: raw.name,\n displayName: raw.display_name,\n displayNamePrefixed: raw.display_name_prefixed,\n title: raw.title,\n publicDescription: raw.public_description,\n description: raw.description,\n subscribers: raw.subscribers ?? 0,\n activeUserCount: raw.active_user_count,\n createdUtc: raw.created_utc,\n over18: raw.over18 ?? false,\n subredditType: raw.subreddit_type || 'public',\n iconImg: raw.icon_img?.split('?')[0],\n bannerImg: raw.banner_background_image?.split('?')[0],\n communityIcon: raw.community_icon?.split('?')[0],\n url: raw.url,\n };\n }\n}\n"],"mappings":"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"}
@@ -0,0 +1,139 @@
1
+ import { d as ProviderMetadata, i as CredentialField, l as ProviderConfig, s as PlatformProvider } from "../base-DBtKFiSX.mjs";
2
+ import { C as TelegramMessage, D as TelegramUploadVideoResult, E as TelegramUploadVideoParams, O as TelegramUser, S as TelegramCredentialData, T as TelegramTestResult, _ as SendStickerOptions, a as CopyMessageOptions, b as TelegramBotInfo, c as ForwardMessageOptions, d as SendAudioOptions, f as SendDocumentOptions, g as SendPhotoOptions, h as SendMessageOptions, i as ChatMember, l as MediaGroupItem, m as SendMediaGroupOptions, n as ChatAction, o as DiscoveredChat, p as SendLocationOptions, r as ChatAdministrator, s as EditMessageOptions, t as AnswerCallbackQueryOptions, u as PinMessageOptions, v as SendVideoOptions, w as TelegramParseMode, x as TelegramChat, y as TelegramApiResponse } from "../types-Bv27tcT0.mjs";
3
+ import { z } from "zod";
4
+
5
+ //#region src/providers/telegram/index.d.ts
6
+ declare class TelegramProvider extends PlatformProvider {
7
+ constructor(config?: ProviderConfig);
8
+ /**
9
+ * Make a request to the Telegram Bot API
10
+ * @private
11
+ * @param method - Bot API method name (e.g. 'sendMessage')
12
+ * @param botToken - Bot token from @BotFather
13
+ * @param body - Request body (JSON or FormData for file uploads)
14
+ * @returns API response result
15
+ */
16
+ _api(method: string, botToken: string, body?: Record<string, any> | FormData | null): Promise<any>;
17
+ /**
18
+ * Get bot identity and verify token validity
19
+ */
20
+ getAccountInfo(accessToken: string): Promise<{
21
+ id: string;
22
+ name: string;
23
+ username: string;
24
+ profileImage: null;
25
+ }>;
26
+ /**
27
+ * Test credential validity
28
+ */
29
+ testCredential(credentialData: TelegramCredentialData): Promise<TelegramTestResult>;
30
+ /**
31
+ * Get chat/channel information
32
+ * @param botToken
33
+ * @param chatId - Channel username (@channel) or numeric ID
34
+ */
35
+ getChat(botToken: string, chatId: string | number): Promise<TelegramChat>;
36
+ /**
37
+ * Get subscriber/member count for a chat
38
+ * @param botToken
39
+ * @param chatId
40
+ * @returns Member count
41
+ */
42
+ getChatMemberCount(botToken: string, chatId: string | number): Promise<number>;
43
+ /**
44
+ * Discover chats the bot has interacted with recently.
45
+ * Uses getUpdates (only works when no webhook is active, falls back gracefully).
46
+ */
47
+ discoverChats(botToken: string): Promise<DiscoveredChat[]>;
48
+ /**
49
+ * Send a text message
50
+ * @param botToken
51
+ * @param chatId
52
+ * @param text - Message text (1-4096 characters)
53
+ * @param options
54
+ */
55
+ sendMessage(botToken: string, chatId: string | number, text: string, options?: SendMessageOptions): Promise<TelegramMessage>;
56
+ /**
57
+ * Send a photo with optional caption
58
+ * @param botToken
59
+ * @param chatId
60
+ * @param photo - Photo URL or file_id
61
+ * @param options
62
+ */
63
+ sendPhoto(botToken: string, chatId: string | number, photo: string, options?: SendPhotoOptions): Promise<TelegramMessage>;
64
+ /**
65
+ * Send a video with optional caption
66
+ * @param botToken
67
+ * @param chatId
68
+ * @param video - Video URL or file_id
69
+ * @param options
70
+ */
71
+ sendVideo(botToken: string, chatId: string | number, video: string, options?: SendVideoOptions): Promise<TelegramMessage>;
72
+ /**
73
+ * Send a document/file
74
+ * @param botToken
75
+ * @param chatId
76
+ * @param document - Document URL or file_id
77
+ * @param options
78
+ */
79
+ sendDocument(botToken: string, chatId: string | number, document: string, options?: SendDocumentOptions): Promise<TelegramMessage>;
80
+ /**
81
+ * Send a media group (album) of 2-10 photos/videos
82
+ * @param botToken
83
+ * @param chatId
84
+ * @param media
85
+ * @param options
86
+ */
87
+ sendMediaGroup(botToken: string, chatId: string | number, media: MediaGroupItem[], options?: SendMediaGroupOptions): Promise<TelegramMessage[]>;
88
+ /**
89
+ * Pin a message in a chat
90
+ * @param botToken
91
+ * @param chatId
92
+ * @param messageId
93
+ * @param options
94
+ */
95
+ pinMessage(botToken: string, chatId: string | number, messageId: number, options?: PinMessageOptions): Promise<true>;
96
+ /**
97
+ * Delete a message
98
+ * @param botToken
99
+ * @param chatId
100
+ * @param messageId
101
+ */
102
+ deleteMessage(botToken: string, chatId: string | number, messageId: number): Promise<true>;
103
+ /**
104
+ * Edit a text message
105
+ * @param botToken
106
+ * @param chatId
107
+ * @param messageId
108
+ * @param text - New message text
109
+ * @param options
110
+ */
111
+ editMessage(botToken: string, chatId: string | number, messageId: number, text: string, options?: EditMessageOptions): Promise<TelegramMessage>;
112
+ getChatAdministrators(botToken: string, chatId: string | number): Promise<ChatAdministrator[]>;
113
+ getChatMember(botToken: string, chatId: string | number, userId: number): Promise<ChatMember>;
114
+ leaveChat(botToken: string, chatId: string | number): Promise<true>;
115
+ setChatTitle(botToken: string, chatId: string | number, title: string): Promise<true>;
116
+ setChatDescription(botToken: string, chatId: string | number, description: string): Promise<true>;
117
+ sendLocation(botToken: string, chatId: string | number, latitude: number, longitude: number, options?: SendLocationOptions): Promise<TelegramMessage>;
118
+ sendAudio(botToken: string, chatId: string | number, audio: string, options?: SendAudioOptions): Promise<TelegramMessage>;
119
+ sendSticker(botToken: string, chatId: string | number, sticker: string, options?: SendStickerOptions): Promise<TelegramMessage>;
120
+ sendChatAction(botToken: string, chatId: string | number, action: ChatAction): Promise<true>;
121
+ forwardMessage(botToken: string, chatId: string | number, fromChatId: string | number, messageId: number, options?: ForwardMessageOptions): Promise<TelegramMessage>;
122
+ copyMessage(botToken: string, chatId: string | number, fromChatId: string | number, messageId: number, options?: CopyMessageOptions): Promise<{
123
+ message_id: number;
124
+ }>;
125
+ answerCallbackQuery(botToken: string, callbackQueryId: string, options?: AnswerCallbackQueryOptions): Promise<true>;
126
+ /**
127
+ * Upload a video to a Telegram channel/chat
128
+ * Telegram supports video by URL (up to 50MB for URL, 2GB for binary upload via multipart).
129
+ *
130
+ * @param params - Upload parameters
131
+ */
132
+ uploadVideo(params: TelegramUploadVideoParams): Promise<TelegramUploadVideoResult>;
133
+ getCredentialZodSchema(): z.ZodType;
134
+ getCredentialSchema(): CredentialField[];
135
+ getMetadata(): ProviderMetadata;
136
+ }
137
+ //#endregion
138
+ export { type AnswerCallbackQueryOptions, type ChatAction, type ChatAdministrator, type ChatMember, type CopyMessageOptions, type DiscoveredChat, type EditMessageOptions, type ForwardMessageOptions, type MediaGroupItem, type PinMessageOptions, type SendAudioOptions, type SendDocumentOptions, type SendLocationOptions, type SendMediaGroupOptions, type SendMessageOptions, type SendPhotoOptions, type SendStickerOptions, type SendVideoOptions, type TelegramApiResponse, type TelegramBotInfo, type TelegramChat, type TelegramCredentialData, type TelegramMessage, type TelegramParseMode, TelegramProvider, type TelegramTestResult, type TelegramUploadVideoParams, type TelegramUploadVideoResult, type TelegramUser };
139
+ //# sourceMappingURL=telegram.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"telegram.d.mts","names":[],"sources":["../../src/providers/telegram/index.ts"],"mappings":"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"}