← Public packages
@kentcdodds/groupme
GroupMe REST API helpers for listing groups, reading messages, ranking activity, and preparing relevance-filtered digests for Kody agents.
src/types.ts
306 lines · 7.9 KB · TypeScript/**
* Shared TypeScript types for the GroupMe v3 REST API and this package's helpers.
*/
/** GroupMe API response envelope metadata. */
export type GroupMeMeta = {
code: number
errors?: string[] | null
}
/** Standard GroupMe API response wrapper. */
export type GroupMeEnvelope<T> = {
meta: GroupMeMeta
response: T | null
}
/** Attachment kinds returned on GroupMe messages. */
export type GroupMeAttachmentType =
| 'image'
| 'reply'
| 'mentions'
| 'location'
| 'video'
| 'emoji'
| string
/** Message attachment payload. Fields vary by attachment type. */
export type GroupMeAttachment = {
type: GroupMeAttachmentType
url?: string
name?: string
chars?: Array<{ placeholder: string; charmap: string[][] }>
source_url?: string
[key: string]: unknown
}
/** Compact preview of the latest group message. */
export type GroupMeMessagePreview = {
nickname: string
text: string
image_url: string
attachments: GroupMeAttachment[]
}
/** Message count and preview metadata on a group list item. */
export type GroupMeGroupMessagesMeta = {
count: number
last_message_id: string
last_message_created_at: number
last_message_updated_at: number
preview: GroupMeMessagePreview
}
/** Group list item returned by `GET /groups`. */
export type GroupMeGroup = {
id: string
group_id: string
name: string
description: string
image_url: string | null
type: string
phone_number?: string
creator_user_id?: string
created_at: number
updated_at: number
messages: GroupMeGroupMessagesMeta
[key: string]: unknown
}
/** Message returned by `GET /groups/:group_id/messages`. */
export type GroupMeMessage = {
id: string
group_id: string
text: string
name: string
avatar_url: string
created_at: number
user_id: string
sender_id: string
sender_type: string
system: boolean
attachments: GroupMeAttachment[]
[key: string]: unknown
}
/** Authenticated user returned by `GET /users/me`. */
export type GroupMeUser = {
id: string
name: string
email?: string
avatar_url?: string
[key: string]: unknown
}
/** HTTP method accepted by the low-level request helper. */
export type GroupMeHttpMethod = 'GET' | 'POST' | 'PUT' | 'DELETE'
/** Query parameters supported by the low-level request helper. */
export type GroupMeQuery = Record<
string,
string | number | boolean | null | undefined | Array<string | number>
>
/** Options for the low-level GroupMe request helper. */
export type GroupMeRequestOptions = {
/** API path such as `/groups` or full `https://api.groupme.com/v3/groups`. */
path: string
method?: GroupMeHttpMethod
query?: GroupMeQuery
body?: unknown
/** Throw `GroupMeRequestError` when the HTTP response is not ok. Default true. */
throwOnError?: boolean
headers?: Record<string, string>
}
/** Parsed response from the low-level request helper. */
export type GroupMeRequestResponse<T = unknown> = {
url: string
ok: boolean
status: number
statusText: string
data: GroupMeEnvelope<T> | T | null
text: string
}
/** Pagination options for message listing. */
export type GroupMeMessagePagination = {
/** Page size. GroupMe allows up to 100. Default 100. */
limit?: number
/** Return messages immediately before this message id. */
beforeId?: string
/** Return messages immediately after this message id. */
afterId?: string
/** Return the most recent messages created after this message id. */
sinceId?: string
}
/** Options for listing groups. */
export type GroupMeListGroupsOptions = {
/** Skip member lists for faster responses. Default true. */
omitMemberships?: boolean
/** Page size. Default 100. */
limit?: number
/** Pagination page number. */
page?: number
}
/** Options for listing messages in one group. */
export type GroupMeListMessagesOptions = GroupMeMessagePagination & {
groupId: string
}
/** Options for reading messages between instants in a named timezone. */
export type GroupMeMessagesInRangeOptions = {
groupId: string
/** Inclusive range start as `YYYY-MM-DD` in `timeZone`, or unix seconds. */
start: string | number
/** Exclusive range end as `YYYY-MM-DD` in `timeZone`, or unix seconds. */
end: string | number
/**
* IANA timezone used when `start`/`end` are date strings.
* Default `America/Denver`.
*/
timeZone?: string
/** Safety cap on pages fetched while scanning backward. Default 50. */
maxPages?: number
}
/** Result of a bounded message scan. */
export type GroupMeMessagesInRangeResult = {
groupId: string
timeZone: string
startUnix: number
endUnix: number
messageCount: number
pagesFetched: number
messages: GroupMeNormalizedMessage[]
}
/** Group ranked by most recent message activity. */
export type GroupMeActiveGroup = {
id: string
name: string
lastMessageAt: number
lastMessageAtIso: string
lastMessagePreview: string
lastMessageSender: string
messageCount: number
}
/** Options for ranking groups by recent activity. */
export type GroupMeListMostActiveGroupsOptions = {
/** Number of groups to return. Default 3. */
limit?: number
/** Forwarded to `listGroups`. */
omitMemberships?: boolean
}
/**
* Rule-based relevance profile for digest filtering.
*
* With no positive criteria (keywords, senderNames, mentions, patterns,
* attachmentTypes), all messages passing `excludeSystem` and `minTextLength`
* are kept.
*/
export type GroupMeRelevanceProfile = {
/** Case-insensitive keyword hits mark a message relevant. */
keywords?: string[]
/** Case-insensitive sender-name substrings mark a message relevant. */
senderNames?: string[]
/** Case-insensitive @mention or name substrings in message text. */
mentions?: string[]
/** Regex source strings; any match marks a message relevant. */
patterns?: string[]
/** Drop GroupMe system messages such as joins and edits. Default true. */
excludeSystem?: boolean
/** Drop blank or very short messages. Default 4 characters. */
minTextLength?: number
/** Attachment types that mark a message relevant, such as `image`. */
attachmentTypes?: string[]
}
/** Result of relevance filtering. */
export type GroupMeRelevanceFilterResult = {
inputCount: number
relevantCount: number
skippedCount: number
messages: GroupMeNormalizedMessage[]
}
/** Normalized message shape used by digest helpers. */
export type GroupMeNormalizedMessage = {
id: string
groupId: string
createdAt: number
createdAtIso: string
senderName: string
text: string
system: boolean
attachmentTypes: string[]
attachmentSummary: string
}
/** Options for `prepare-digest`. */
export type GroupMePrepareDigestOptions = {
/** Group id to read. Provide this or `groupName`. */
groupId?: string
/** Case-insensitive exact or substring group-name match. */
groupName?: string
start: string | number
end: string | number
timeZone?: string
relevance?: GroupMeRelevanceProfile
maxPages?: number
}
/** Structured digest input for downstream summarization. */
export type GroupMeDigestInput = {
group: { id: string; name: string }
window: {
timeZone: string
startUnix: number
endUnix: number
startDate: string
endDate: string
}
stats: {
totalMessages: number
relevantMessages: number
skippedMessages: number
pagesFetched: number
}
relevance: GroupMeRelevanceProfile
messages: GroupMeNormalizedMessage[]
}
/**
* Return exported GroupMe TypeScript type names for agent discovery.
* @returns Array of public type name strings.
* @example
* import types from 'kody:@kentcdodds/groupme/types'
* const names = await types()
* // => ['GroupMeGroup', 'GroupMeMessage', 'GroupMePrepareDigestOptions', ...]
*/
export default function describeGroupMeTypes() {
return [
'GroupMeMeta',
'GroupMeEnvelope',
'GroupMeAttachment',
'GroupMeGroup',
'GroupMeMessage',
'GroupMeUser',
'GroupMeRequestOptions',
'GroupMeRequestResponse',
'GroupMeListGroupsOptions',
'GroupMeListMessagesOptions',
'GroupMeMessagesInRangeOptions',
'GroupMeMessagesInRangeResult',
'GroupMeActiveGroup',
'GroupMeRelevanceProfile',
'GroupMeRelevanceFilterResult',
'GroupMeNormalizedMessage',
'GroupMePrepareDigestOptions',
'GroupMeDigestInput',
]
}