Skip to content

Built for people who want to own their automations. Join the waitlist for an invite.

Package listing

@kody/reddit

src/types.ts

205 lines · 4.7 KB · TypeScript
export type JsonRecord = Record<string, unknown>

export type QueryValue = string | number | boolean | null | undefined
export type QueryInput = Record<string, QueryValue | QueryValue[]>

export type ListingSort = 'best' | 'hot' | 'new' | 'top' | 'rising' | 'controversial'
export type SearchSort = 'relevance' | 'hot' | 'top' | 'new' | 'comments'
export type TimeFilter = 'hour' | 'day' | 'week' | 'month' | 'year' | 'all'
export type UserListing = 'about' | 'submitted' | 'comments' | 'overview'
export type SubmitKind = 'self' | 'link'
export type VoteDirection = 1 | 0 | -1

export type AccountInput = {
	/** Exact integration name, e.g. `reddit-work`. Wins over `account`. */
	integration?: string
	/** Purpose suffix. `work` → `reddit-work`. `default` / `reddit` / omitted → `reddit`. */
	account?: string
}

export type RedditRequestInput = AccountInput & {
	path: string
	method?: string
	query?: QueryInput
	headers?: Record<string, string>
	body?: unknown
	dryRun?: boolean
	confirm?: boolean
}

export type RedditRequestResult = {
	ok: boolean
	status: number
	statusText: string
	headers: Record<string, string>
	body: unknown
	integration: string
}

export type GetListingInput = AccountInput & {
	subreddit?: string
	sort?: ListingSort
	t?: TimeFilter
	limit?: number
	after?: string
	before?: string
}

export type GetSubredditInput = AccountInput & {
	subreddit: string
}

export type SearchInput = AccountInput & {
	query: string
	subreddit?: string
	sort?: SearchSort
	t?: TimeFilter
	limit?: number
	after?: string
	restrictToSubreddit?: boolean
}

export type GetUserInput = AccountInput & {
	username: string
	listing?: UserListing
	sort?: ListingSort
	t?: TimeFilter
	limit?: number
	after?: string
}

export type GetPostInput = AccountInput & {
	id: string
	subreddit?: string
	commentLimit?: number
	commentSort?: SearchSort | ListingSort
}

export type SubmitPostInput = AccountInput & {
	subreddit: string
	title: string
	kind?: SubmitKind
	text?: string
	url?: string
	nsfw?: boolean
	spoiler?: boolean
	sendreplies?: boolean
	flairId?: string
	flairText?: string
	dryRun?: boolean
	confirm?: boolean
}

export type SubmitCommentInput = AccountInput & {
	parentId: string
	text: string
	dryRun?: boolean
	confirm?: boolean
}

export type VoteInput = AccountInput & {
	id: string
	direction: VoteDirection | 'up' | 'down' | 'clear'
	dryRun?: boolean
	confirm?: boolean
}

export type ShapedPost = {
	id: string
	name: string
	title: string
	author: string
	subreddit: string
	score: number | null
	upvoteRatio: number | null
	numComments: number | null
	url: string | null
	permalink: string | null
	createdUtc: number | null
	over18: boolean
	stickied: boolean
	isSelf: boolean
	selftext: string | null
	selftextTruncated: boolean
	linkFlairText: string | null
}

export type ShapedComment = {
	id: string
	name: string
	author: string
	body: string | null
	bodyTruncated: boolean
	score: number | null
	permalink: string | null
	createdUtc: number | null
	parentId: string | null
}

export type ShapedListing = {
	kind: 'listing'
	after: string | null
	before: string | null
	posts: ShapedPost[]
}

export type ShapedSubreddit = {
	id: string | null
	name: string | null
	displayName: string | null
	title: string | null
	publicDescription: string | null
	subscribers: number | null
	accountsActive: number | null
	over18: boolean
	url: string | null
	createdUtc: number | null
	submissionType: string | null
}

export type ShapedUser = {
	id: string | null
	name: string | null
	createdUtc: number | null
	commentKarma: number | null
	linkKarma: number | null
	totalKarma: number | null
	isGold: boolean
	isMod: boolean
	verified: boolean
	hasVerifiedEmail: boolean | null
}

export function requireRecord(value: unknown, utilityName: string): JsonRecord {
	if (value && typeof value === 'object' && !Array.isArray(value)) {
		return value as JsonRecord
	}
	throw new Error(utilityName + ' requires an object params value.')
}

export function requireStringField(record: JsonRecord, key: string, utilityName: string): string {
	const value = record[key]
	if (typeof value !== 'string' || value.length === 0) {
		throw new Error(utilityName + ' requires params.' + key + '.')
	}
	return value
}

export function asRecord(value: unknown): JsonRecord | null {
	if (value && typeof value === 'object' && !Array.isArray(value)) {
		return value as JsonRecord
	}
	return null
}

export function stringValue(value: unknown): string | undefined {
	return typeof value === 'string' && value.length > 0 ? value : undefined
}

export function numberValue(value: unknown): number | null {
	return typeof value === 'number' && Number.isFinite(value) ? value : null
}

export function booleanValue(value: unknown, fallback = false): boolean {
	return typeof value === 'boolean' ? value : fallback
}