first commit
Security: Sync from Public / sync-from-public (push) Has been cancelled
Test: Benchmark Nightly / build (push) Has been cancelled
Test: Benchmark Nightly / Notify Cats on failure (push) Has been cancelled
CI: Python / Checks (push) Has been cancelled
Test: Evals Python / Workflow Comparison Python (push) Has been cancelled
Util: Check Docs URLs / check-docs-urls (push) Has been cancelled
Test: Visual Storybook / Cloudflare Pages (push) Has been cancelled
Test: E2E Performance / build-and-test-performance (push) Has been cancelled
Test: Workflows Nightly / Run Workflow Tests (push) Has been cancelled
Util: Cleanup CI Docker Images / Delete stale CI images (push) Has been cancelled
Test: Benchmark Destroy Env / build (push) Has been cancelled
Util: Update Node Popularity / update-popularity (push) Has been cancelled
Test: E2E Coverage Weekly / Coverage Tests (push) Has been cancelled

This commit is contained in:
2026-03-17 16:22:57 +03:30
commit 3d5eaf9445
15349 changed files with 2847338 additions and 0 deletions
@@ -0,0 +1,124 @@
import type {
IExecuteFunctions,
IHookFunctions,
IDataObject,
JsonObject,
IHttpRequestMethods,
IRequestOptions,
} from 'n8n-workflow';
import { NodeApiError } from 'n8n-workflow';
/**
* Make an authenticated or unauthenticated API request to Reddit.
*/
export async function redditApiRequest(
this: IHookFunctions | IExecuteFunctions,
method: IHttpRequestMethods,
endpoint: string,
qs: IDataObject,
): Promise<any> {
const resource = this.getNodeParameter('resource', 0) as string;
const authRequired = ['profile', 'post', 'postComment'].includes(resource);
qs.api_type = 'json';
const options: IRequestOptions = {
headers: {
'user-agent': 'n8n',
},
method,
uri: authRequired
? `https://oauth.reddit.com/${endpoint}`
: `https://www.reddit.com/${endpoint}`,
qs,
json: true,
};
if (!Object.keys(qs).length) {
delete options.qs;
}
if (authRequired) {
try {
return await this.helpers.requestOAuth2.call(this, 'redditOAuth2Api', options);
} catch (error) {
throw new NodeApiError(this.getNode(), error as JsonObject);
}
} else {
try {
return await this.helpers.request.call(this, options);
} catch (error) {
throw new NodeApiError(this.getNode(), error as JsonObject);
}
}
}
/**
* Make an unauthenticated API request to Reddit and return all results.
*/
export async function redditApiRequestAllItems(
this: IHookFunctions | IExecuteFunctions,
method: IHttpRequestMethods,
endpoint: string,
qs: IDataObject,
): Promise<any> {
let responseData;
const returnData: IDataObject[] = [];
const resource = this.getNodeParameter('resource', 0);
const operation = this.getNodeParameter('operation', 0);
const returnAll = this.getNodeParameter('returnAll', 0, false) as boolean;
qs.limit = 100;
do {
responseData = await redditApiRequest.call(this, method, endpoint, qs);
if (!Array.isArray(responseData)) {
qs.after = responseData.data.after;
}
if (endpoint === 'api/search_subreddits.json') {
responseData.subreddits.forEach((child: any) => returnData.push(child as IDataObject));
} else if (resource === 'postComment' && operation === 'getAll') {
responseData[1].data.children.forEach((child: any) =>
returnData.push(child.data as IDataObject),
);
} else {
responseData.data.children.forEach((child: any) =>
returnData.push(child.data as IDataObject),
);
}
if (qs.limit && returnData.length >= qs.limit && !returnAll) {
return returnData;
}
} while (responseData.data?.after);
return returnData;
}
/**
* Handles a large Reddit listing by returning all items or up to a limit.
*/
export async function handleListing(
this: IExecuteFunctions,
i: number,
endpoint: string,
qs: IDataObject = {},
requestMethod: 'GET' | 'POST' = 'GET',
): Promise<any> {
let responseData;
const returnAll = this.getNodeParameter('returnAll', i);
if (returnAll) {
responseData = await redditApiRequestAllItems.call(this, requestMethod, endpoint, qs);
} else {
const limit = this.getNodeParameter('limit', i);
qs.limit = limit;
responseData = await redditApiRequestAllItems.call(this, requestMethod, endpoint, qs);
responseData = responseData.slice(0, limit);
}
return responseData;
}
@@ -0,0 +1,197 @@
import type { INodeProperties } from 'n8n-workflow';
export const postCommentOperations: INodeProperties[] = [
{
displayName: 'Operation',
name: 'operation',
type: 'options',
noDataExpression: true,
default: 'create',
options: [
{
name: 'Create',
value: 'create',
description: 'Create a top-level comment in a post',
action: 'Create a comment in a post',
},
{
name: 'Get Many',
value: 'getAll',
description: 'Retrieve many comments in a post',
action: 'Get many comments in a post',
},
{
name: 'Delete',
value: 'delete',
description: 'Remove a comment from a post',
action: 'Delete a comment from a post',
},
{
name: 'Reply',
value: 'reply',
description: 'Write a reply to a comment in a post',
action: 'Reply to a comment in a post',
},
],
displayOptions: {
show: {
resource: ['postComment'],
},
},
},
];
export const postCommentFields: INodeProperties[] = [
// ----------------------------------
// postComment: create
// ----------------------------------
{
displayName: 'Post ID',
name: 'postId',
type: 'string',
required: true,
default: '',
description:
'ID of the post to write the comment to. Found in the post URL: <code>/r/[subreddit_name]/comments/[post_id]/[post_title]</code>',
placeholder: 'l0me7x',
displayOptions: {
show: {
resource: ['postComment'],
operation: ['create'],
},
},
},
{
displayName: 'Comment Text',
name: 'commentText',
type: 'string',
required: true,
default: '',
description: 'Text of the comment. Markdown supported.',
displayOptions: {
show: {
resource: ['postComment'],
operation: ['create'],
},
},
},
// ----------------------------------
// postComment: getAll
// ----------------------------------
{
displayName: 'Subreddit',
name: 'subreddit',
type: 'string',
required: true,
default: '',
description: 'The name of subreddit where the post is',
displayOptions: {
show: {
resource: ['postComment'],
operation: ['getAll'],
},
},
},
{
displayName: 'Post ID',
name: 'postId',
type: 'string',
required: true,
default: '',
description:
'ID of the post to get all comments from. Found in the post URL: <code>/r/[subreddit_name]/comments/[post_id]/[post_title]</code>',
placeholder: 'l0me7x',
displayOptions: {
show: {
resource: ['postComment'],
operation: ['getAll'],
},
},
},
{
displayName: 'Return All',
name: 'returnAll',
type: 'boolean',
default: false,
description: 'Whether to return all results or only up to a given limit',
displayOptions: {
show: {
resource: ['postComment'],
operation: ['getAll'],
},
},
},
{
displayName: 'Limit',
name: 'limit',
type: 'number',
default: 100,
description: 'Max number of results to return',
typeOptions: {
minValue: 1,
maxValue: 100,
},
displayOptions: {
show: {
resource: ['postComment'],
operation: ['getAll'],
returnAll: [false],
},
},
},
// ----------------------------------
// postComment: delete
// ----------------------------------
{
displayName: 'Comment ID',
name: 'commentId',
type: 'string',
required: true,
default: '',
description:
'ID of the comment to remove. Found in the comment URL:<code>/r/[subreddit_name]/comments/[post_id]/[post_title]/[comment_id]</code>',
placeholder: 'gla7fmt',
displayOptions: {
show: {
resource: ['postComment'],
operation: ['delete'],
},
},
},
// ----------------------------------
// postComment: reply
// ----------------------------------
{
displayName: 'Comment ID',
name: 'commentId',
type: 'string',
required: true,
default: '',
description:
'ID of the comment to reply to. To be found in the comment URL: <code>www.reddit.com/r/[subreddit_name]/comments/[post_id]/[post_title]/[comment_id]</code>',
placeholder: 'gl9iroa',
displayOptions: {
show: {
resource: ['postComment'],
operation: ['reply'],
},
},
},
{
displayName: 'Reply Text',
name: 'replyText',
type: 'string',
required: true,
default: '',
description: 'Text of the reply. Markdown supported.',
displayOptions: {
show: {
resource: ['postComment'],
operation: ['reply'],
},
},
},
];
@@ -0,0 +1,431 @@
import type { INodeProperties } from 'n8n-workflow';
export const postOperations: INodeProperties[] = [
{
displayName: 'Operation',
name: 'operation',
type: 'options',
noDataExpression: true,
default: 'create',
options: [
{
name: 'Create',
value: 'create',
description: 'Submit a post to a subreddit',
action: 'Create a post',
},
{
name: 'Delete',
value: 'delete',
description: 'Delete a post from a subreddit',
action: 'Delete a post',
},
{
name: 'Get',
value: 'get',
description: 'Get a post from a subreddit',
action: 'Get a post',
},
{
name: 'Get Many',
value: 'getAll',
description: 'Get many posts from a subreddit',
action: 'Get many posts',
},
{
name: 'Search',
value: 'search',
description: 'Search posts in a subreddit or in all of Reddit',
action: 'Search for a post',
},
],
displayOptions: {
show: {
resource: ['post'],
},
},
},
];
export const postFields: INodeProperties[] = [
// ----------------------------------
// post: create
// ----------------------------------
{
displayName: 'Subreddit',
name: 'subreddit',
type: 'string',
required: true,
default: '',
description: 'Subreddit to create the post in',
displayOptions: {
show: {
resource: ['post'],
operation: ['create'],
},
},
},
{
displayName: 'Kind',
name: 'kind',
type: 'options',
options: [
{
name: 'Text Post',
value: 'self',
},
{
name: 'Link Post',
value: 'link',
},
{
name: 'Image Post',
value: 'image',
},
],
default: 'self',
description: 'The kind of the post to create',
displayOptions: {
show: {
resource: ['post'],
operation: ['create'],
},
},
},
{
displayName: 'Title',
name: 'title',
type: 'string',
required: true,
default: '',
description: 'Title of the post, up to 300 characters long',
displayOptions: {
show: {
resource: ['post'],
operation: ['create'],
},
},
},
{
displayName: 'URL',
name: 'url',
type: 'string',
required: true,
default: '',
description: 'URL of the post',
displayOptions: {
show: {
resource: ['post'],
operation: ['create'],
kind: ['link', 'image'],
},
},
},
{
displayName: 'Text',
name: 'text',
type: 'string',
required: true,
default: '',
description: 'Text of the post. Markdown supported.',
displayOptions: {
show: {
resource: ['post'],
operation: ['create'],
kind: ['self'],
},
},
},
{
displayName: 'Resubmit',
name: 'resubmit',
type: 'boolean',
default: false,
description:
'Whether the URL will be posted even if it was already posted to the subreddit before. Otherwise, the re-posting will trigger an error.',
displayOptions: {
show: {
resource: ['post'],
operation: ['create'],
kind: ['link', 'image'],
},
},
},
// ----------------------------------
// post: delete
// ----------------------------------
{
displayName: 'Post ID',
name: 'postId',
type: 'string',
required: true,
default: '',
description:
'ID of the post to delete. Found in the post URL: <code>/r/[subreddit_name]/comments/[post_id]/[post_title]</code>',
placeholder: 'gla7fmt',
displayOptions: {
show: {
resource: ['post'],
operation: ['delete'],
},
},
},
// ----------------------------------
// post: get
// ----------------------------------
{
displayName: 'Subreddit',
name: 'subreddit',
type: 'string',
required: true,
default: '',
description: 'The name of subreddit to retrieve the post from',
displayOptions: {
show: {
resource: ['post'],
operation: ['get'],
},
},
},
{
displayName: 'Post ID',
name: 'postId',
type: 'string',
required: true,
default: '',
description:
'ID of the post to retrieve. Found in the post URL: <code>/r/[subreddit_name]/comments/[post_id]/[post_title]</code>',
placeholder: 'l0me7x',
displayOptions: {
show: {
resource: ['post'],
operation: ['get'],
},
},
},
// ----------------------------------
// post: getAll
// ----------------------------------
{
displayName: 'Subreddit',
name: 'subreddit',
type: 'string',
required: true,
default: '',
description: 'The name of subreddit to retrieve the posts from',
displayOptions: {
show: {
resource: ['post'],
operation: ['getAll'],
},
},
},
{
displayName: 'Return All',
name: 'returnAll',
type: 'boolean',
default: false,
description: 'Whether to return all results or only up to a given limit',
displayOptions: {
show: {
resource: ['post'],
operation: ['getAll'],
},
},
},
{
displayName: 'Limit',
name: 'limit',
type: 'number',
default: 100,
description: 'Max number of results to return',
typeOptions: {
minValue: 1,
maxValue: 100,
},
displayOptions: {
show: {
resource: ['post'],
operation: ['getAll'],
returnAll: [false],
},
},
},
{
displayName: 'Filters',
name: 'filters',
type: 'collection',
displayOptions: {
show: {
resource: ['post'],
operation: ['getAll'],
},
},
default: {},
placeholder: 'Add Field',
options: [
{
displayName: 'Category',
name: 'category',
type: 'options',
default: 'top',
description: 'Category of the posts to retrieve',
options: [
{
name: 'Top Posts',
value: 'top',
},
{
name: 'Hot Posts',
value: 'hot',
},
{
name: 'New Posts',
value: 'new',
},
{
name: 'Rising Posts',
value: 'rising',
},
],
},
],
},
// ----------------------------------
// post: search
// ----------------------------------
{
displayName: 'Location',
name: 'location',
type: 'options',
default: 'subreddit',
description: 'Location where to search for posts',
options: [
{
name: 'All Reddit',
value: 'allReddit',
description: 'Search for posts in all of Reddit',
},
{
name: 'Subreddit',
value: 'subreddit',
description: 'Search for posts in a specific subreddit',
},
],
displayOptions: {
show: {
resource: ['post'],
operation: ['search'],
},
},
},
{
displayName: 'Subreddit',
name: 'subreddit',
type: 'string',
required: true,
default: '',
description: 'The name of subreddit to search in',
displayOptions: {
show: {
resource: ['post'],
operation: ['search'],
location: ['subreddit'],
},
},
},
{
displayName: 'Keyword',
name: 'keyword',
type: 'string',
default: '',
required: true,
description: 'The keyword for the search',
displayOptions: {
show: {
resource: ['post'],
operation: ['search'],
},
},
},
{
displayName: 'Return All',
name: 'returnAll',
type: 'boolean',
default: false,
description: 'Whether to return all results or only up to a given limit',
displayOptions: {
show: {
resource: ['post'],
operation: ['search'],
},
},
},
{
displayName: 'Limit',
name: 'limit',
type: 'number',
default: 100,
description: 'Max number of results to return',
typeOptions: {
minValue: 1,
maxValue: 100,
},
displayOptions: {
show: {
resource: ['post'],
operation: ['search'],
returnAll: [false],
},
},
},
{
displayName: 'Additional Fields',
name: 'additionalFields',
type: 'collection',
placeholder: 'Add Field',
default: {},
displayOptions: {
show: {
resource: ['post'],
operation: ['search'],
},
},
options: [
{
displayName: 'Sort',
name: 'sort',
placeholder: '',
type: 'options',
default: 'relevance',
description: 'The category to sort results by',
options: [
{
name: 'Comments',
value: 'comments',
},
{
name: 'Hot',
value: 'hot',
},
{
name: 'New',
value: 'new',
},
{
name: 'Relevance',
value: 'relevance',
},
{
name: 'Top',
value: 'top',
},
],
},
],
},
];
@@ -0,0 +1,110 @@
import type { INodeProperties } from 'n8n-workflow';
export const profileOperations: INodeProperties[] = [
{
displayName: 'Operation',
name: 'operation',
type: 'options',
noDataExpression: true,
displayOptions: {
show: {
resource: ['profile'],
},
},
options: [
{
name: 'Get',
value: 'get',
action: 'Get a profile',
},
],
default: 'get',
},
];
export const profileFields: INodeProperties[] = [
{
displayName: 'Details',
name: 'details',
type: 'options',
required: true,
default: 'identity',
description: 'Details of my account to retrieve',
options: [
{
name: 'Blocked Users',
value: 'blockedUsers',
description: 'Return the blocked users of the logged-in user',
},
{
name: 'Friends',
value: 'friends',
description: 'Return the friends of the logged-in user',
},
{
name: 'Identity',
value: 'identity',
description: 'Return the identity of the logged-in user',
},
{
name: 'Karma',
value: 'karma',
description: 'Return the subreddit karma for the logged-in user',
},
{
name: 'Preferences',
value: 'prefs',
description: 'Return the settings preferences of the logged-in user',
},
{
name: 'Saved',
value: 'saved',
description: 'Return the saved posts for the user',
},
{
name: 'Trophies',
value: 'trophies',
description: 'Return the trophies of the logged-in user',
},
],
displayOptions: {
show: {
resource: ['profile'],
operation: ['get'],
},
},
},
{
displayName: 'Return All',
name: 'returnAll',
type: 'boolean',
default: false,
description: 'Whether to return all results or only up to a given limit',
displayOptions: {
show: {
resource: ['profile'],
operation: ['get'],
details: ['saved'],
},
},
},
{
displayName: 'Limit',
name: 'limit',
type: 'number',
default: 100,
description: 'Max number of results to return',
typeOptions: {
minValue: 1,
maxValue: 100,
},
displayOptions: {
show: {
resource: ['profile'],
operation: ['get'],
details: ['saved'],
returnAll: [false],
},
},
},
];
@@ -0,0 +1,18 @@
{
"node": "n8n-nodes-base.reddit",
"nodeVersion": "1.0",
"codexVersion": "1.0",
"categories": ["Communication"],
"resources": {
"credentialDocumentation": [
{
"url": "https://docs.n8n.io/integrations/builtin/credentials/reddit/"
}
],
"primaryDocumentation": [
{
"url": "https://docs.n8n.io/integrations/builtin/app-nodes/n8n-nodes-base.reddit/"
}
]
}
}
@@ -0,0 +1,441 @@
import type {
IExecuteFunctions,
IDataObject,
INodeExecutionData,
INodeType,
INodeTypeDescription,
JsonObject,
} from 'n8n-workflow';
import { NodeApiError, NodeConnectionTypes } from 'n8n-workflow';
import { handleListing, redditApiRequest } from './GenericFunctions';
import { postCommentFields, postCommentOperations } from './PostCommentDescription';
import { postFields, postOperations } from './PostDescription';
import { profileFields, profileOperations } from './ProfileDescription';
import { subredditFields, subredditOperations } from './SubredditDescription';
import { userFields, userOperations } from './UserDescription';
export class Reddit implements INodeType {
description: INodeTypeDescription = {
displayName: 'Reddit',
name: 'reddit',
icon: 'file:reddit.svg',
group: ['transform'],
version: 1,
subtitle: '={{$parameter["operation"] + ": " + $parameter["resource"]}}',
description: 'Consume the Reddit API',
defaults: {
name: 'Reddit',
},
usableAsTool: true,
inputs: [NodeConnectionTypes.Main],
outputs: [NodeConnectionTypes.Main],
credentials: [
{
name: 'redditOAuth2Api',
required: true,
displayOptions: {
show: {
resource: ['postComment', 'post', 'profile'],
},
},
},
],
properties: [
{
displayName: 'Resource',
name: 'resource',
type: 'options',
noDataExpression: true,
options: [
{
name: 'Post',
value: 'post',
},
{
name: 'Post Comment',
value: 'postComment',
},
{
name: 'Profile',
value: 'profile',
},
{
name: 'Subreddit',
value: 'subreddit',
},
{
name: 'User',
value: 'user',
},
],
default: 'post',
},
...postCommentOperations,
...postCommentFields,
...profileOperations,
...profileFields,
...subredditOperations,
...subredditFields,
...postOperations,
...postFields,
...userOperations,
...userFields,
],
};
async execute(this: IExecuteFunctions): Promise<INodeExecutionData[][]> {
const items = this.getInputData();
const resource = this.getNodeParameter('resource', 0);
const operation = this.getNodeParameter('operation', 0);
let responseData;
const returnData: INodeExecutionData[] = [];
for (let i = 0; i < items.length; i++) {
try {
// *********************************************************************
// post
// *********************************************************************
if (resource === 'post') {
if (operation === 'create') {
// ----------------------------------
// post: create
// ----------------------------------
// https://www.reddit.com/dev/api/#POST_api_submit
const qs: IDataObject = {
title: this.getNodeParameter('title', i),
sr: this.getNodeParameter('subreddit', i),
kind: this.getNodeParameter('kind', i),
};
qs.kind === 'self'
? (qs.text = this.getNodeParameter('text', i))
: (qs.url = this.getNodeParameter('url', i));
if (qs.url) {
qs.resubmit = this.getNodeParameter('resubmit', i);
}
responseData = await redditApiRequest.call(this, 'POST', 'api/submit', qs);
responseData = responseData.json.data;
} else if (operation === 'delete') {
// ----------------------------------
// post: delete
// ----------------------------------
// https://www.reddit.com/dev/api/#POST_api_del
const postTypePrefix = 't3_';
const qs: IDataObject = {
id: postTypePrefix + (this.getNodeParameter('postId', i) as string),
};
await redditApiRequest.call(this, 'POST', 'api/del', qs);
responseData = { success: true };
} else if (operation === 'get') {
// ----------------------------------
// post: get
// ----------------------------------
const subreddit = this.getNodeParameter('subreddit', i);
const postId = this.getNodeParameter('postId', i) as string;
const endpoint = `r/${subreddit}/comments/${postId}.json`;
responseData = await redditApiRequest.call(this, 'GET', endpoint, {});
responseData = responseData[0].data.children[0].data;
} else if (operation === 'getAll') {
// ----------------------------------
// post: getAll
// ----------------------------------
// https://www.reddit.com/dev/api/#GET_hot
// https://www.reddit.com/dev/api/#GET_new
// https://www.reddit.com/dev/api/#GET_rising
// https://www.reddit.com/dev/api/#GET_{sort}
const subreddit = this.getNodeParameter('subreddit', i);
let endpoint = `r/${subreddit}.json`;
const { category } = this.getNodeParameter('filters', i) as { category: string };
if (category) {
endpoint = `r/${subreddit}/${category}.json`;
}
responseData = await handleListing.call(this, i, endpoint);
} else if (operation === 'search') {
// ----------------------------------
// post: search
// ----------------------------------
// https://www.reddit.com/dev/api/#GET_search
const location = this.getNodeParameter('location', i);
const qs = {
q: this.getNodeParameter('keyword', i),
restrict_sr: location === 'subreddit',
} as IDataObject;
const { sort } = this.getNodeParameter('additionalFields', i);
if (sort) {
qs.sort = sort;
}
let endpoint = '';
if (location === 'allReddit') {
endpoint = 'search.json';
} else {
const subreddit = this.getNodeParameter('subreddit', i);
endpoint = `r/${subreddit}/search.json`;
}
responseData = await handleListing.call(this, i, endpoint, qs);
const returnAll = this.getNodeParameter('returnAll', 0);
if (!returnAll) {
const limit = this.getNodeParameter('limit', 0);
responseData = responseData.splice(0, limit);
}
}
} else if (resource === 'postComment') {
// *********************************************************************
// postComment
// *********************************************************************
if (operation === 'create') {
// ----------------------------------
// postComment: create
// ----------------------------------
// https://www.reddit.com/dev/api/#POST_api_comment
const postTypePrefix = 't3_';
const qs: IDataObject = {
text: this.getNodeParameter('commentText', i),
thing_id: postTypePrefix + (this.getNodeParameter('postId', i) as string),
};
responseData = await redditApiRequest.call(this, 'POST', 'api/comment', qs);
responseData = responseData.json.data.things[0].data;
} else if (operation === 'getAll') {
// ----------------------------------
// postComment: getAll
// ----------------------------------
// https://www.reddit.com/r/{subrreddit}/comments/{postId}.json
const subreddit = this.getNodeParameter('subreddit', i);
const postId = this.getNodeParameter('postId', i) as string;
const endpoint = `r/${subreddit}/comments/${postId}.json`;
responseData = await handleListing.call(this, i, endpoint);
} else if (operation === 'delete') {
// ----------------------------------
// postComment: delete
// ----------------------------------
// https://www.reddit.com/dev/api/#POST_api_del
const commentTypePrefix = 't1_';
const qs: IDataObject = {
id: commentTypePrefix + (this.getNodeParameter('commentId', i) as string),
};
await redditApiRequest.call(this, 'POST', 'api/del', qs);
responseData = { success: true };
} else if (operation === 'reply') {
// ----------------------------------
// postComment: reply
// ----------------------------------
// https://www.reddit.com/dev/api/#POST_api_comment
const commentTypePrefix = 't1_';
const qs: IDataObject = {
text: this.getNodeParameter('replyText', i),
thing_id: commentTypePrefix + (this.getNodeParameter('commentId', i) as string),
};
responseData = await redditApiRequest.call(this, 'POST', 'api/comment', qs);
responseData = responseData.json.data.things[0].data;
}
} else if (resource === 'profile') {
// *********************************************************************
// profile
// *********************************************************************
if (operation === 'get') {
// ----------------------------------
// profile: get
// ----------------------------------
// https://www.reddit.com/dev/api/#GET_api_v1_me
// https://www.reddit.com/dev/api/#GET_api_v1_me_karma
// https://www.reddit.com/dev/api/#GET_api_v1_me_prefs
// https://www.reddit.com/dev/api/#GET_api_v1_me_trophies
// https://www.reddit.com/dev/api/#GET_prefs_{where}
const endpoints: { [key: string]: string } = {
identity: 'me',
blockedUsers: 'me/blocked',
friends: 'me/friends',
karma: 'me/karma',
prefs: 'me/prefs',
trophies: 'me/trophies',
};
const details = this.getNodeParameter('details', i) as string;
const endpoint = `api/v1/${endpoints[details]}`;
let username;
if (details === 'saved') {
({ name: username } = await redditApiRequest.call(this, 'GET', 'api/v1/me', {}));
}
responseData =
details === 'saved'
? await handleListing.call(this, i, `user/${username}/saved.json`)
: await redditApiRequest.call(this, 'GET', endpoint, {});
if (details === 'identity') {
responseData = responseData.features;
} else if (details === 'friends') {
responseData = responseData.data.children;
if (!responseData.length) {
throw new NodeApiError(this.getNode(), responseData as JsonObject);
}
} else if (details === 'karma') {
responseData = responseData.data;
if (!responseData.length) {
throw new NodeApiError(this.getNode(), responseData as JsonObject);
}
} else if (details === 'trophies') {
responseData = responseData.data.trophies.map((trophy: IDataObject) => trophy.data);
}
}
} else if (resource === 'subreddit') {
// *********************************************************************
// subreddit
// *********************************************************************
if (operation === 'get') {
// ----------------------------------
// subreddit: get
// ----------------------------------
// https://www.reddit.com/dev/api/#GET_r_{subreddit}_about
// https://www.reddit.com/dev/api/#GET_r_{subreddit}_about_rules
const subreddit = this.getNodeParameter('subreddit', i);
const content = this.getNodeParameter('content', i) as string;
const endpoint = `r/${subreddit}/about/${content}.json`;
responseData = await redditApiRequest.call(this, 'GET', endpoint, {});
if (content === 'rules') {
responseData = responseData.rules;
} else if (content === 'about') {
responseData = responseData.data;
}
} else if (operation === 'getAll') {
// ----------------------------------
// subreddit: getAll
// ----------------------------------
// https://www.reddit.com/dev/api/#GET_api_trending_subreddits
// https://www.reddit.com/dev/api/#POST_api_search_subreddits
// https://www.reddit.com/r/subreddits.json
const filters = this.getNodeParameter('filters', i);
if (filters.trending) {
const returnAll = this.getNodeParameter('returnAll', 0);
const endpoint = 'api/trending_subreddits.json';
responseData = await redditApiRequest.call(this, 'GET', endpoint, {});
responseData = responseData.subreddit_names.map((name: string) => ({ name }));
if (!returnAll) {
const limit = this.getNodeParameter('limit', 0);
responseData = responseData.splice(0, limit);
}
} else if (filters.keyword) {
const qs: IDataObject = {};
qs.query = filters.keyword;
const endpoint = 'api/search_subreddits.json';
responseData = await redditApiRequest.call(this, 'POST', endpoint, qs);
const returnAll = this.getNodeParameter('returnAll', 0);
if (!returnAll) {
const limit = this.getNodeParameter('limit', 0);
responseData = responseData.subreddits.splice(0, limit);
}
} else {
const endpoint = 'r/subreddits.json';
responseData = await handleListing.call(this, i, endpoint);
}
}
} else if (resource === 'user') {
// *********************************************************************
// user
// *********************************************************************
if (operation === 'get') {
// ----------------------------------
// user: get
// ----------------------------------
// https://www.reddit.com/dev/api/#GET_user_{username}_{where}
const username = this.getNodeParameter('username', i) as string;
const details = this.getNodeParameter('details', i) as string;
const endpoint = `user/${username}/${details}.json`;
responseData =
details === 'about'
? await redditApiRequest.call(this, 'GET', endpoint, {})
: await handleListing.call(this, i, endpoint);
if (details === 'about') {
responseData = responseData.data;
}
}
}
const executionData = this.helpers.constructExecutionMetaData(
this.helpers.returnJsonArray(responseData as JsonObject),
{ itemData: { item: i } },
);
returnData.push(...executionData);
} catch (error) {
if (this.continueOnFail()) {
const executionErrorData = this.helpers.constructExecutionMetaData(
this.helpers.returnJsonArray({ error: error.message }),
{ itemData: { item: i } },
);
returnData.push(...executionErrorData);
continue;
}
throw error;
}
}
return [returnData];
}
}
@@ -0,0 +1,138 @@
import type { INodeProperties } from 'n8n-workflow';
export const subredditOperations: INodeProperties[] = [
{
displayName: 'Operation',
name: 'operation',
type: 'options',
noDataExpression: true,
default: 'get',
options: [
{
name: 'Get',
value: 'get',
description: 'Retrieve background information about a subreddit',
action: 'Get a subreddit',
},
{
name: 'Get Many',
value: 'getAll',
description: 'Retrieve information about many subreddits',
action: 'Get many subreddits',
},
],
displayOptions: {
show: {
resource: ['subreddit'],
},
},
},
];
export const subredditFields: INodeProperties[] = [
// ----------------------------------
// subreddit: get
// ----------------------------------
{
displayName: 'Content',
name: 'content',
type: 'options',
required: true,
default: 'about',
description: 'Subreddit content to retrieve',
options: [
{
name: 'About',
value: 'about',
},
{
name: 'Rules',
value: 'rules',
},
],
displayOptions: {
show: {
resource: ['subreddit'],
operation: ['get'],
},
},
},
{
displayName: 'Subreddit',
name: 'subreddit',
type: 'string',
required: true,
default: '',
description: 'The name of subreddit to retrieve the content from',
displayOptions: {
show: {
resource: ['subreddit'],
operation: ['get'],
},
},
},
// ----------------------------------
// subreddit: getAll
// ----------------------------------
{
displayName: 'Return All',
name: 'returnAll',
type: 'boolean',
default: false,
description: 'Whether to return all results or only up to a given limit',
displayOptions: {
show: {
resource: ['subreddit'],
operation: ['getAll'],
},
},
},
{
displayName: 'Limit',
name: 'limit',
type: 'number',
default: 100,
description: 'Max number of results to return',
typeOptions: {
minValue: 1,
maxValue: 100,
},
displayOptions: {
show: {
resource: ['subreddit'],
operation: ['getAll'],
returnAll: [false],
},
},
},
{
displayName: 'Filters',
name: 'filters',
type: 'collection',
placeholder: 'Add Field',
default: {},
options: [
{
displayName: 'Keyword',
name: 'keyword',
type: 'string',
default: '',
description: 'The keyword for the subreddit search',
},
{
displayName: 'Trending',
name: 'trending',
type: 'boolean',
default: false,
description: 'Whether to fetch currently trending subreddits in all of Reddit',
},
],
displayOptions: {
show: {
resource: ['subreddit'],
operation: ['getAll'],
},
},
},
];
@@ -0,0 +1,109 @@
import type { INodeProperties } from 'n8n-workflow';
export const userOperations: INodeProperties[] = [
{
displayName: 'Operation',
name: 'operation',
type: 'options',
noDataExpression: true,
displayOptions: {
show: {
resource: ['user'],
},
},
options: [
{
name: 'Get',
value: 'get',
action: 'Get a user',
},
],
default: 'get',
},
];
export const userFields: INodeProperties[] = [
{
displayName: 'Username',
name: 'username',
type: 'string',
required: true,
default: '',
description: 'Reddit ID of the user to retrieve',
displayOptions: {
show: {
resource: ['user'],
operation: ['get'],
},
},
},
{
displayName: 'Details',
name: 'details',
type: 'options',
required: true,
default: 'about',
description: 'Details of the user to retrieve',
options: [
{
name: 'About',
value: 'about',
},
{
name: 'Comments',
value: 'comments',
},
{
name: 'Gilded',
value: 'gilded',
},
{
name: 'Overview',
value: 'overview',
},
{
name: 'Submitted',
value: 'submitted',
},
],
displayOptions: {
show: {
resource: ['user'],
operation: ['get'],
},
},
},
{
displayName: 'Return All',
name: 'returnAll',
type: 'boolean',
default: false,
description: 'Whether to return all results or only up to a given limit',
displayOptions: {
show: {
resource: ['user'],
operation: ['get'],
details: ['overview', 'submitted', 'comments', 'gilded'],
},
},
},
{
displayName: 'Limit',
name: 'limit',
type: 'number',
default: 100,
description: 'Max number of results to return',
typeOptions: {
minValue: 1,
maxValue: 100,
},
displayOptions: {
show: {
resource: ['user'],
operation: ['get'],
details: ['comments', 'gilded', 'overview', 'submitted'],
returnAll: [false],
},
},
},
];
@@ -0,0 +1,18 @@
{
"type": "object",
"properties": {
"drafts_count": {
"type": "integer"
},
"id": {
"type": "string"
},
"name": {
"type": "string"
},
"url": {
"type": "string"
}
},
"version": 1
}
@@ -0,0 +1,9 @@
{
"type": "object",
"properties": {
"success": {
"type": "boolean"
}
},
"version": 1
}
@@ -0,0 +1,253 @@
{
"type": "object",
"properties": {
"allow_live_comments": {
"type": "boolean"
},
"approved_at_utc": {
"type": "null"
},
"approved_by": {
"type": "null"
},
"archived": {
"type": "boolean"
},
"author": {
"type": "string"
},
"author_flair_richtext": {
"type": "array",
"items": {
"type": "object",
"properties": {
"a": {
"type": "string"
},
"e": {
"type": "string"
},
"t": {
"type": "string"
},
"u": {
"type": "string"
}
}
}
},
"author_flair_type": {
"type": "string"
},
"author_fullname": {
"type": "string"
},
"author_is_blocked": {
"type": "boolean"
},
"author_patreon_flair": {
"type": "boolean"
},
"author_premium": {
"type": "boolean"
},
"banned_at_utc": {
"type": "null"
},
"banned_by": {
"type": "null"
},
"can_gild": {
"type": "boolean"
},
"can_mod_post": {
"type": "boolean"
},
"category": {
"type": "null"
},
"clicked": {
"type": "boolean"
},
"content_categories": {
"type": "null"
},
"contest_mode": {
"type": "boolean"
},
"created": {
"type": "integer"
},
"created_utc": {
"type": "integer"
},
"discussion_type": {
"type": "null"
},
"domain": {
"type": "string"
},
"downs": {
"type": "integer"
},
"gilded": {
"type": "integer"
},
"hidden": {
"type": "boolean"
},
"hide_score": {
"type": "boolean"
},
"id": {
"type": "string"
},
"is_created_from_ads_ui": {
"type": "boolean"
},
"is_crosspostable": {
"type": "boolean"
},
"is_meta": {
"type": "boolean"
},
"is_original_content": {
"type": "boolean"
},
"is_reddit_media_domain": {
"type": "boolean"
},
"is_robot_indexable": {
"type": "boolean"
},
"is_self": {
"type": "boolean"
},
"is_video": {
"type": "boolean"
},
"link_flair_richtext": {
"type": "array",
"items": {
"type": "object",
"properties": {
"e": {
"type": "string"
},
"t": {
"type": "string"
}
}
}
},
"link_flair_type": {
"type": "string"
},
"locked": {
"type": "boolean"
},
"media_only": {
"type": "boolean"
},
"mod_note": {
"type": "null"
},
"mod_reason_by": {
"type": "null"
},
"mod_reason_title": {
"type": "null"
},
"name": {
"type": "string"
},
"no_follow": {
"type": "boolean"
},
"num_comments": {
"type": "integer"
},
"num_crossposts": {
"type": "integer"
},
"num_duplicates": {
"type": "integer"
},
"over_18": {
"type": "boolean"
},
"permalink": {
"type": "string"
},
"pinned": {
"type": "boolean"
},
"quarantine": {
"type": "boolean"
},
"removal_reason": {
"type": "null"
},
"removed_by": {
"type": "null"
},
"saved": {
"type": "boolean"
},
"score": {
"type": "integer"
},
"selftext": {
"type": "string"
},
"send_replies": {
"type": "boolean"
},
"spoiler": {
"type": "boolean"
},
"stickied": {
"type": "boolean"
},
"subreddit": {
"type": "string"
},
"subreddit_id": {
"type": "string"
},
"subreddit_name_prefixed": {
"type": "string"
},
"subreddit_subscribers": {
"type": "integer"
},
"subreddit_type": {
"type": "string"
},
"thumbnail": {
"type": "string"
},
"title": {
"type": "string"
},
"top_awarded_type": {
"type": "null"
},
"total_awards_received": {
"type": "integer"
},
"ups": {
"type": "integer"
},
"url": {
"type": "string"
},
"view_count": {
"type": "null"
},
"visited": {
"type": "boolean"
}
},
"version": 1
}
@@ -0,0 +1,315 @@
{
"type": "object",
"properties": {
"allow_live_comments": {
"type": "boolean"
},
"approved_at_utc": {
"type": "null"
},
"approved_by": {
"type": "null"
},
"archived": {
"type": "boolean"
},
"author": {
"type": "string"
},
"author_flair_richtext": {
"type": "array",
"items": {
"type": "object",
"properties": {
"a": {
"type": "string"
},
"e": {
"type": "string"
},
"t": {
"type": "string"
},
"u": {
"type": "string"
}
}
}
},
"author_flair_type": {
"type": "string"
},
"author_fullname": {
"type": "string"
},
"author_is_blocked": {
"type": "boolean"
},
"author_patreon_flair": {
"type": "boolean"
},
"author_premium": {
"type": "boolean"
},
"banned_at_utc": {
"type": "null"
},
"banned_by": {
"type": "null"
},
"can_gild": {
"type": "boolean"
},
"can_mod_post": {
"type": "boolean"
},
"category": {
"type": "null"
},
"clicked": {
"type": "boolean"
},
"contest_mode": {
"type": "boolean"
},
"created": {
"type": "integer"
},
"created_utc": {
"type": "integer"
},
"discussion_type": {
"type": "null"
},
"domain": {
"type": "string"
},
"downs": {
"type": "integer"
},
"gilded": {
"type": "integer"
},
"hidden": {
"type": "boolean"
},
"hide_score": {
"type": "boolean"
},
"id": {
"type": "string"
},
"is_created_from_ads_ui": {
"type": "boolean"
},
"is_crosspostable": {
"type": "boolean"
},
"is_meta": {
"type": "boolean"
},
"is_original_content": {
"type": "boolean"
},
"is_reddit_media_domain": {
"type": "boolean"
},
"is_robot_indexable": {
"type": "boolean"
},
"is_self": {
"type": "boolean"
},
"is_video": {
"type": "boolean"
},
"link_flair_richtext": {
"type": "array",
"items": {
"type": "object",
"properties": {
"e": {
"type": "string"
},
"t": {
"type": "string"
}
}
}
},
"link_flair_template_id": {
"type": "string"
},
"link_flair_type": {
"type": "string"
},
"locked": {
"type": "boolean"
},
"media_only": {
"type": "boolean"
},
"mod_note": {
"type": "null"
},
"mod_reason_by": {
"type": "null"
},
"mod_reason_title": {
"type": "null"
},
"name": {
"type": "string"
},
"no_follow": {
"type": "boolean"
},
"num_comments": {
"type": "integer"
},
"num_crossposts": {
"type": "integer"
},
"num_reports": {
"type": "null"
},
"over_18": {
"type": "boolean"
},
"permalink": {
"type": "string"
},
"pinned": {
"type": "boolean"
},
"post_hint": {
"type": "string"
},
"preview": {
"type": "object",
"properties": {
"enabled": {
"type": "boolean"
},
"images": {
"type": "array",
"items": {
"type": "object",
"properties": {
"id": {
"type": "string"
},
"resolutions": {
"type": "array",
"items": {
"type": "object",
"properties": {
"height": {
"type": "integer"
},
"url": {
"type": "string"
},
"width": {
"type": "integer"
}
}
}
},
"source": {
"type": "object",
"properties": {
"height": {
"type": "integer"
},
"url": {
"type": "string"
},
"width": {
"type": "integer"
}
}
}
}
}
}
}
},
"quarantine": {
"type": "boolean"
},
"removal_reason": {
"type": "null"
},
"removed_by": {
"type": "null"
},
"removed_by_category": {
"type": "null"
},
"report_reasons": {
"type": "null"
},
"saved": {
"type": "boolean"
},
"score": {
"type": "integer"
},
"selftext": {
"type": "string"
},
"send_replies": {
"type": "boolean"
},
"spoiler": {
"type": "boolean"
},
"stickied": {
"type": "boolean"
},
"subreddit": {
"type": "string"
},
"subreddit_id": {
"type": "string"
},
"subreddit_name_prefixed": {
"type": "string"
},
"subreddit_subscribers": {
"type": "integer"
},
"subreddit_type": {
"type": "string"
},
"thumbnail": {
"type": "string"
},
"title": {
"type": "string"
},
"top_awarded_type": {
"type": "null"
},
"total_awards_received": {
"type": "integer"
},
"ups": {
"type": "integer"
},
"url": {
"type": "string"
},
"url_overridden_by_dest": {
"type": "string"
},
"view_count": {
"type": "null"
},
"visited": {
"type": "boolean"
}
},
"version": 5
}
@@ -0,0 +1,244 @@
{
"type": "object",
"properties": {
"allow_live_comments": {
"type": "boolean"
},
"approved_at_utc": {
"type": "null"
},
"approved_by": {
"type": "null"
},
"archived": {
"type": "boolean"
},
"author": {
"type": "string"
},
"author_flair_richtext": {
"type": "array",
"items": {
"type": "object",
"properties": {
"e": {
"type": "string"
},
"t": {
"type": "string"
}
}
}
},
"author_flair_type": {
"type": "string"
},
"author_fullname": {
"type": "string"
},
"author_is_blocked": {
"type": "boolean"
},
"author_patreon_flair": {
"type": "boolean"
},
"author_premium": {
"type": "boolean"
},
"banned_at_utc": {
"type": "null"
},
"banned_by": {
"type": "null"
},
"can_gild": {
"type": "boolean"
},
"can_mod_post": {
"type": "boolean"
},
"category": {
"type": "null"
},
"clicked": {
"type": "boolean"
},
"contest_mode": {
"type": "boolean"
},
"created_utc": {
"type": "integer"
},
"discussion_type": {
"type": "null"
},
"domain": {
"type": "string"
},
"downs": {
"type": "integer"
},
"gilded": {
"type": "integer"
},
"hidden": {
"type": "boolean"
},
"hide_score": {
"type": "boolean"
},
"id": {
"type": "string"
},
"is_created_from_ads_ui": {
"type": "boolean"
},
"is_crosspostable": {
"type": "boolean"
},
"is_meta": {
"type": "boolean"
},
"is_original_content": {
"type": "boolean"
},
"is_reddit_media_domain": {
"type": "boolean"
},
"is_robot_indexable": {
"type": "boolean"
},
"is_self": {
"type": "boolean"
},
"is_video": {
"type": "boolean"
},
"link_flair_richtext": {
"type": "array",
"items": {
"type": "object",
"properties": {
"e": {
"type": "string"
},
"t": {
"type": "string"
}
}
}
},
"link_flair_template_id": {
"type": "string"
},
"link_flair_type": {
"type": "string"
},
"locked": {
"type": "boolean"
},
"media_only": {
"type": "boolean"
},
"mod_note": {
"type": "null"
},
"mod_reason_by": {
"type": "null"
},
"mod_reason_title": {
"type": "null"
},
"name": {
"type": "string"
},
"no_follow": {
"type": "boolean"
},
"num_comments": {
"type": "integer"
},
"num_crossposts": {
"type": "integer"
},
"over_18": {
"type": "boolean"
},
"permalink": {
"type": "string"
},
"pinned": {
"type": "boolean"
},
"quarantine": {
"type": "boolean"
},
"removal_reason": {
"type": "null"
},
"removed_by": {
"type": "null"
},
"removed_by_category": {
"type": "null"
},
"saved": {
"type": "boolean"
},
"score": {
"type": "integer"
},
"selftext": {
"type": "string"
},
"send_replies": {
"type": "boolean"
},
"spoiler": {
"type": "boolean"
},
"stickied": {
"type": "boolean"
},
"subreddit": {
"type": "string"
},
"subreddit_id": {
"type": "string"
},
"subreddit_name_prefixed": {
"type": "string"
},
"subreddit_subscribers": {
"type": "integer"
},
"subreddit_type": {
"type": "string"
},
"thumbnail": {
"type": "string"
},
"title": {
"type": "string"
},
"top_awarded_type": {
"type": "null"
},
"total_awards_received": {
"type": "integer"
},
"ups": {
"type": "integer"
},
"url": {
"type": "string"
},
"view_count": {
"type": "null"
},
"visited": {
"type": "boolean"
}
},
"version": 1
}
@@ -0,0 +1,189 @@
{
"type": "object",
"properties": {
"approved_at_utc": {
"type": "null"
},
"approved_by": {
"type": "null"
},
"archived": {
"type": "boolean"
},
"associated_award": {
"type": "null"
},
"author": {
"type": "string"
},
"author_flair_background_color": {
"type": "null"
},
"author_flair_css_class": {
"type": "null"
},
"author_flair_template_id": {
"type": "null"
},
"author_flair_text": {
"type": "null"
},
"author_flair_text_color": {
"type": "null"
},
"author_flair_type": {
"type": "string"
},
"author_fullname": {
"type": "string"
},
"author_is_blocked": {
"type": "boolean"
},
"author_patreon_flair": {
"type": "boolean"
},
"author_premium": {
"type": "boolean"
},
"banned_at_utc": {
"type": "null"
},
"banned_by": {
"type": "null"
},
"body": {
"type": "string"
},
"body_html": {
"type": "string"
},
"can_gild": {
"type": "boolean"
},
"can_mod_post": {
"type": "boolean"
},
"collapsed": {
"type": "boolean"
},
"collapsed_because_crowd_control": {
"type": "null"
},
"collapsed_reason": {
"type": "null"
},
"collapsed_reason_code": {
"type": "null"
},
"comment_type": {
"type": "null"
},
"controversiality": {
"type": "integer"
},
"created": {
"type": "integer"
},
"created_utc": {
"type": "integer"
},
"distinguished": {
"type": "null"
},
"downs": {
"type": "integer"
},
"edited": {
"type": "boolean"
},
"gilded": {
"type": "integer"
},
"id": {
"type": "string"
},
"is_submitter": {
"type": "boolean"
},
"likes": {
"type": "boolean"
},
"link_id": {
"type": "string"
},
"locked": {
"type": "boolean"
},
"mod_note": {
"type": "null"
},
"mod_reason_by": {
"type": "null"
},
"mod_reason_title": {
"type": "null"
},
"name": {
"type": "string"
},
"no_follow": {
"type": "boolean"
},
"parent_id": {
"type": "string"
},
"permalink": {
"type": "string"
},
"removal_reason": {
"type": "null"
},
"replies": {
"type": "string"
},
"rte_mode": {
"type": "string"
},
"saved": {
"type": "boolean"
},
"score": {
"type": "integer"
},
"score_hidden": {
"type": "boolean"
},
"send_replies": {
"type": "boolean"
},
"stickied": {
"type": "boolean"
},
"subreddit": {
"type": "string"
},
"subreddit_id": {
"type": "string"
},
"subreddit_name_prefixed": {
"type": "string"
},
"subreddit_type": {
"type": "string"
},
"top_awarded_type": {
"type": "null"
},
"total_awards_received": {
"type": "integer"
},
"unrepliable_reason": {
"type": "null"
},
"ups": {
"type": "integer"
}
},
"version": 1
}
@@ -0,0 +1,185 @@
{
"type": "object",
"properties": {
"approved_at_utc": {
"type": "null"
},
"approved_by": {
"type": "null"
},
"archived": {
"type": "boolean"
},
"associated_award": {
"type": "null"
},
"author": {
"type": "string"
},
"author_flair_richtext": {
"type": "array",
"items": {
"type": "object",
"properties": {
"a": {
"type": "string"
},
"e": {
"type": "string"
},
"t": {
"type": "string"
},
"u": {
"type": "string"
}
}
}
},
"author_flair_type": {
"type": "string"
},
"author_fullname": {
"type": "string"
},
"author_is_blocked": {
"type": "boolean"
},
"author_patreon_flair": {
"type": "boolean"
},
"author_premium": {
"type": "boolean"
},
"banned_at_utc": {
"type": "null"
},
"banned_by": {
"type": "null"
},
"body": {
"type": "string"
},
"body_html": {
"type": "string"
},
"can_gild": {
"type": "boolean"
},
"can_mod_post": {
"type": "boolean"
},
"collapsed": {
"type": "boolean"
},
"collapsed_because_crowd_control": {
"type": "null"
},
"collapsed_reason": {
"type": "null"
},
"comment_type": {
"type": "null"
},
"controversiality": {
"type": "integer"
},
"created": {
"type": "integer"
},
"created_utc": {
"type": "integer"
},
"depth": {
"type": "integer"
},
"downs": {
"type": "integer"
},
"gilded": {
"type": "integer"
},
"id": {
"type": "string"
},
"is_submitter": {
"type": "boolean"
},
"link_id": {
"type": "string"
},
"locked": {
"type": "boolean"
},
"mod_note": {
"type": "null"
},
"mod_reason_by": {
"type": "null"
},
"mod_reason_title": {
"type": "null"
},
"name": {
"type": "string"
},
"no_follow": {
"type": "boolean"
},
"num_reports": {
"type": "null"
},
"parent_id": {
"type": "string"
},
"permalink": {
"type": "string"
},
"removal_reason": {
"type": "null"
},
"report_reasons": {
"type": "null"
},
"saved": {
"type": "boolean"
},
"score": {
"type": "integer"
},
"score_hidden": {
"type": "boolean"
},
"send_replies": {
"type": "boolean"
},
"stickied": {
"type": "boolean"
},
"subreddit": {
"type": "string"
},
"subreddit_id": {
"type": "string"
},
"subreddit_name_prefixed": {
"type": "string"
},
"subreddit_type": {
"type": "string"
},
"top_awarded_type": {
"type": "null"
},
"total_awards_received": {
"type": "integer"
},
"unrepliable_reason": {
"type": "null"
},
"ups": {
"type": "integer"
}
},
"version": 1
}
@@ -0,0 +1,95 @@
{
"type": "object",
"properties": {
"awards_on_streams": {
"type": "boolean"
},
"chat_group_rollout": {
"type": "boolean"
},
"chat_subreddit": {
"type": "boolean"
},
"chat_user_settings": {
"type": "boolean"
},
"cookie_consent_banner": {
"type": "boolean"
},
"crowd_control_for_post": {
"type": "boolean"
},
"do_not_track": {
"type": "boolean"
},
"expensive_coins_package": {
"type": "boolean"
},
"images_in_comments": {
"type": "boolean"
},
"is_email_permission_required": {
"type": "boolean"
},
"mod_awards": {
"type": "boolean"
},
"mod_service_mute_reads": {
"type": "boolean"
},
"mod_service_mute_writes": {
"type": "boolean"
},
"modlog_copyright_removal": {
"type": "boolean"
},
"modmail_harassment_filter": {
"type": "boolean"
},
"mweb_xpromo_interstitial_comments_android": {
"type": "boolean"
},
"mweb_xpromo_interstitial_comments_ios": {
"type": "boolean"
},
"mweb_xpromo_modal_listing_click_daily_dismissible_android": {
"type": "boolean"
},
"mweb_xpromo_modal_listing_click_daily_dismissible_ios": {
"type": "boolean"
},
"mweb_xpromo_revamp_v2": {
"type": "object",
"properties": {
"experiment_id": {
"type": "integer"
},
"owner": {
"type": "string"
},
"variant": {
"type": "string"
}
}
},
"noreferrer_to_noopener": {
"type": "boolean"
},
"premium_subscriptions_table": {
"type": "boolean"
},
"promoted_trend_blanks": {
"type": "boolean"
},
"resized_styles_images": {
"type": "boolean"
},
"show_amp_link": {
"type": "boolean"
},
"use_pref_account_deployment": {
"type": "boolean"
}
},
"version": 1
}
@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" fill="#fff" fill-rule="evenodd" stroke="#000" stroke-linecap="round" stroke-linejoin="round" viewBox="0 0 513 514"><use xlink:href="#a" x=".5" y=".5"/><symbol id="a" overflow="visible"><g fill-rule="nonzero" stroke="none"><path fill="#ff4500" d="M0 76.8C0 34.253 34.253 0 76.8 0h358.4C477.747 0 512 34.253 512 76.8v358.4c0 42.547-34.253 76.8-76.8 76.8H76.8C34.253 512 0 477.747 0 435.2z"/><path d="M79 305c0-68.142 78.942-123 177-123s177 54.858 177 123-78.942 123-177 123S79 373.142 79 305"/><g fill="#ff4500"><path d="M199 347c35 29 79 29 114 0l12 11c-42 35-96 35-138 0z"/><use xlink:href="#b"/><use xlink:href="#b" x="-118"/></g></g><g fill="none" stroke="#fff"><use xlink:href="#b" x="75" y="-160" stroke-width="25"/><path stroke-width="22" d="M87 282c-45-22-5-92 40-50m298 50c45-22 5-92-40-50m-127-45 24-83 80 16"/></g></symbol><defs><path id="b" d="M287 285a27.94 27.94 0 1 1 56 0 27.94 27.94 0 1 1-56 0"/></defs></svg>

After

Width:  |  Height:  |  Size: 1007 B