import { BackoffOptions } from 'exponential-backoff';
import { isDmChannelId, isGroupChannelId, isGroupDmChannelId } from '../api/apiUtils';
import { Stringified } from '../utils';

import * as api from '../api';
import * as db from '../db';
import * as domain from '../domain';
import * as ub from '../urbit';
export { isDmChannelId, isGroupChannelId, isGroupDmChannelId };
export declare const IMAGE_REGEX: RegExp;
export declare const AUDIO_REGEX: RegExp;
export declare const VIDEO_REGEX: RegExp;
export declare const URL_REGEX: RegExp;
export declare const PATP_REGEX: RegExp;
export declare const IMAGE_URL_REGEX: RegExp;
export declare const REF_REGEX: RegExp;
export declare const REF_URL_REGEX: RegExp;
export declare const PUNCTUATION_REGEX: RegExp;
export declare const SIG_LIKES: string[];
export declare function isValidUrl(str?: string): boolean;
export type NicknameValidationErrorType = 'confusable_characters' | 'invalid_patp' | 'wrong_user_id';
export type NicknameValidationResult = {
    isValid: true;
} | {
    isValid: false;
    errorType: NicknameValidationErrorType;
};
/**
 * Validates a nickname against several rules:
 * - Cannot contain characters that look like ~ (confusable characters)
 * - If it contains ~, it must be a valid patp
 * - If it contains a patp, it must be the current user's ID
 *
 * Uses Unicode normalization (NFKC) to handle confusable characters before validation.
 *
 * @param nickname The nickname to validate
 * @param currentUserId The current user's ID (patp)
 * @returns A validation result object with isValid flag and optional errorType
 */
export declare function validateNickname(nickname: string, currentUserId: string): NicknameValidationResult;
/**
 * Returns a user-friendly error message for a nickname validation error.
 * @param errorType The type of validation error
 * @returns A human-readable error message
 */
export declare function getNicknameErrorMessage(errorType: NicknameValidationErrorType): string;
export declare function asyncWithDefault<T>(cb: () => Promise<T>, def: T): Promise<T>;
export declare function getFlagParts(flag: string): {
    ship: string;
    name: string;
};
export declare function getNestParts(nest: string): {
    type: string;
    ship: string;
    name: string;
};
export declare function getPrettyAppName(kind: 'chat' | 'diary' | 'heap'): "Chat" | "Gallery" | "Notebook";
export declare function jsonFetch<T>(info: RequestInfo, init?: RequestInit): Promise<T>;
export declare const validOembedCheck: (embed: any, url: string) => boolean;
export declare function isImageUrl(url: string): boolean;
export declare function makePrettyTime(date: Date): string;
export declare function makePrettyTimeFromMs(ms: number): string;
export declare function makePrettyDay(date: Date): string;
export declare function makePrettyDaysSince(date: Date): string;
export declare function makePrettyShortDate(date: Date): string;
export declare function makeShortDate(date: Date): string;
export interface DayTimeDisplay {
    original: Date;
    diff: number;
    day: string;
    time: string;
    asString: string;
}
export declare function makePrettyDayAndTime(date: Date): DayTimeDisplay;
export interface DateDayTimeDisplay extends DayTimeDisplay {
    fullDate: string;
}
export declare function makePrettyDayAndDateAndTime(date: Date): DateDayTimeDisplay;
export declare function containsOnlyEmoji(input: string): boolean;
export declare function normalizeUrbitColor(color?: string | null): string | null;
/**
 * Generates a safe ID from a given text.
 * @param text The text to generate a safe ID from.
 * @param prefix Optional prefix for the ID, defaults to 'id'.
 * @returns A safe ID.
 */
export declare const generateSafeId: (text: string, prefix?: string) => string;
/**
 * Returns true if the two dates happened on current calendar day, in local
 * timezone.
 *
 * TODO: Currently this calculation will be off by an hour when crossing
 * daylight savings time. We're doing it this way because date operations are
 * quite slow in RN/Hermes.
 */
export declare const isSameDay: (a: number, b: number) => boolean;
export declare const isToday: (date: number) => boolean;
export declare const appendContactIdToReplies: (existingReplies: string[], contactId: string) => string[];
export declare function convertToAscii(str: string): string;
export declare const createShortCodeFromTitle: (title: string) => string;
export declare function extractInlinesFromContent(story: api.PostContent): ub.Inline[];
export declare function extractReferencesFromContent(story: api.PostContent): domain.ContentReference[];
export declare function extractBlocksFromContent(story: api.PostContent): ub.Block[];
export declare const extractContentTypes: (content: Stringified<api.PostContent> | api.PostContent) => {
    inlines: ub.Inline[];
    references: domain.ContentReference[];
    blocks: ub.Block[];
    story: (domain.ContentReference | ub.Verse)[];
};
export declare const extractContentTypesFromPost: (post: db.Post | {
    content: api.PostContent;
}) => {
    inlines: ub.Inline[];
    references: domain.ContentReference[];
    blocks: ub.Block[];
    story: (domain.ContentReference | ub.Verse)[];
};
export declare const isTextPost: (post: db.Post) => boolean;
export declare const isReferencePost: (post: db.Post) => boolean;
export declare const isImagePost: (post: db.Post) => boolean;
export declare const isRichLinkPost: (post: db.Post) => boolean;
export declare function getRichLinkMetadata(block: ub.Block): {
    url: string;
    title?: string;
    description?: string;
    image?: string;
} | undefined;
export declare const findFirstImageBlock: (blocks: ub.Block[]) => ub.Image | null;
export declare const textPostIsLinkedImage: (post: db.Post) => boolean;
export declare const textPostIsLink: (post: db.Post) => boolean;
export declare const textPostIsReference: (post: db.Post) => boolean;
export declare const getPostTypeFromChannelId: ({ channelId, parentId, }: {
    channelId?: string | null;
    parentId?: string | null;
}) => db.PostType;
export declare const getCompositeGroups: (groups: db.Group[], base: Partial<db.Group>[]) => db.Group[];
export type RetryConfig = Pick<BackoffOptions, 'startingDelay' | 'numOfAttempts' | 'maxDelay'>;
export declare const withRetry: <T>(fn: () => Promise<T>, config?: RetryConfig) => Promise<T>;
/**
 * Random id value for group or channel, 4 bits of entropy, eg 0v2a.lmibb -> v2almibb
 */
export declare function getRandomId(): string;
/**
 * Simple one way transform for identifying distinct values while
 * obscuring sensitive information, eg ~latter-bolden/garden -> rfn4hj
 */
export declare function simpleHash(input: string): string;
export declare function getModelAnalytics({ post, group, channel, }: {
    post?: Partial<db.Post> | null;
    group?: Partial<db.Group> | null;
    channel?: Partial<db.Channel> | null;
}): Record<string, string | boolean>;
export declare function escapeRegExp(text: string): string;
//# sourceMappingURL=utils.d.ts.map