import {z} from 'zod' export type GetApiUsersIdCommentsArgs = {id: string, offset?: number | undefined, limit?: number | undefined, user_id?: string | undefined}; export type GetApiUsersIdCommentsOptions = {baseUrl: string, OAuth2?: string | undefined, fetch?: typeof fetch | undefined}; export const versionMetadata = z.object({service: z.string(), version: z.string()}); export const commentEntityType = z.enum(["Track", "FanClub", "Event"]); export const commentMention = z.object({user_id: z.number().int(), handle: z.string()}); export const replyComment = z.object({id: z.string(), entity_id: z.string(), entity_type: commentEntityType, user_id: z.string(), message: z.string(), mentions: z.array(commentMention).optional(), track_timestamp_s: z.number().int().optional(), react_count: z.number().int(), is_edited: z.boolean(), is_current_user_reacted: z.boolean().optional(), is_artist_reacted: z.boolean().optional(), created_at: z.string(), updated_at: z.string().optional(), video_url: z.string().nullable().optional(), parent_comment_id: z.number().int().optional()}); export const comment = z.object({id: z.string(), entity_id: z.string(), entity_type: commentEntityType, user_id: z.string().optional(), message: z.string(), mentions: z.array(commentMention).optional(), track_timestamp_s: z.number().int().optional(), react_count: z.number().int(), reply_count: z.number().int(), is_edited: z.boolean(), is_current_user_reacted: z.boolean().optional(), is_artist_reacted: z.boolean().optional(), is_tombstone: z.boolean().optional(), is_members_only: z.boolean().optional(), video_url: z.string().nullable().optional(), is_muted: z.boolean().optional(), created_at: z.string(), updated_at: z.string().optional(), replies: z.array(replyComment).optional(), parent_comment_id: z.number().int().optional()}); export const coverPhoto = z.object({"640x": z.string().optional(), "2000x": z.string().optional(), mirrors: z.array(z.string()).optional()}); export const profilePicture = z.object({"150x150": z.string().optional(), "480x480": z.string().optional(), "1000x1000": z.string().optional(), mirrors: z.array(z.string()).optional()}); export const playlistLibrary = z.object({contents: z.array(z.object({})).optional()}); export const user = z.object({album_count: z.number().int(), artist_pick_track_id: z.string().optional(), artist_coin_badge: z.object({mint: z.string().optional(), logo_uri: z.string().optional(), banner_image_url: z.string().optional(), ticker: z.string().optional()}), coin_flair_mint: z.string().optional(), bio: z.string().optional(), cover_photo: coverPhoto.optional(), followee_count: z.number().int(), follower_count: z.number().int(), handle: z.string(), id: z.string(), is_verified: z.boolean(), twitter_handle: z.string().optional(), instagram_handle: z.string().optional(), tiktok_handle: z.string().optional(), verified_with_twitter: z.boolean(), verified_with_instagram: z.boolean(), verified_with_tiktok: z.boolean(), website: z.string().optional(), donation: z.string().optional(), location: z.string().optional(), name: z.string(), playlist_count: z.number().int(), profile_picture: profilePicture.optional(), repost_count: z.number().int(), track_count: z.number().int(), is_deactivated: z.boolean(), is_available: z.boolean(), erc_wallet: z.string(), spl_wallet: z.string(), spl_usdc_wallet: z.string(), spl_usdc_payout_wallet: z.string().optional(), supporter_count: z.number().int(), supporting_count: z.number().int(), total_audio_balance: z.number().int(), wallet: z.string(), balance: z.string(), associated_wallets_balance: z.string(), total_balance: z.string(), waudio_balance: z.string(), associated_sol_wallets_balance: z.string(), blocknumber: z.number().int(), created_at: z.string(), is_storage_v2: z.boolean(), creator_node_endpoint: z.string().optional(), current_user_followee_follow_count: z.number().int(), does_current_user_follow: z.boolean(), does_current_user_subscribe: z.boolean(), does_follow_current_user: z.boolean(), handle_lc: z.string(), updated_at: z.string(), cover_photo_sizes: z.string().optional(), cover_photo_cids: coverPhoto.optional(), cover_photo_legacy: z.string().optional(), profile_picture_sizes: z.string().optional(), profile_picture_cids: profilePicture.optional(), profile_picture_legacy: z.string().optional(), has_collectibles: z.boolean(), playlist_library: playlistLibrary.optional(), allow_ai_attribution: z.boolean(), profile_type: z.string().optional()}); export const trackArtwork = z.object({"150x150": z.string().optional(), "480x480": z.string().optional(), "1000x1000": z.string().optional(), mirrors: z.array(z.string()).optional()}); export const remix = z.object({parent_track_id: z.string(), user: user, has_remix_author_reposted: z.boolean(), has_remix_author_saved: z.boolean()}); export const remixParent = z.object({tracks: z.array(remix).optional()}); export const albumBacklink = z.object({playlist_id: z.number().int(), playlist_name: z.string(), permalink: z.string()}); export const access = z.object({stream: z.boolean(), download: z.boolean()}); export const coverArt = z.object({"150x150": z.string().optional(), "480x480": z.string().optional(), "1000x1000": z.string().optional(), mirrors: z.array(z.string()).optional()}); export const fieldVisibility = z.object({mood: z.boolean(), tags: z.boolean(), genre: z.boolean(), share: z.boolean(), play_count: z.boolean(), remixes: z.boolean()}); export const repost = z.object({repost_item_id: z.string(), repost_type: z.string(), user_id: z.string()}); export const favorite = z.object({favorite_item_id: z.string(), favorite_type: z.string(), user_id: z.string(), created_at: z.string()}); export const stemParent = z.object({category: z.string(), parent_track_id: z.number().int()}); export const trackSegment = z.object({duration: z.number(), multihash: z.string()}); export const ddexResourceContributor = z.object({name: z.string().min(1), roles: z.array(z.string().min(1)), sequence_number: z.number().int().gte(0).optional()}); export const ddexRightsController = z.object({name: z.string().min(1), roles: z.array(z.string().min(1)), rights_share_unknown: z.string().optional()}); export const ddexCopyright = z.object({year: z.string().min(4).max(4), text: z.string().min(1)}); export const tipGate = z.object({tip_user_id: z.number().int()}); export const followGate = z.object({follow_user_id: z.number().int()}); export const paymentSplit = z.object({user_id: z.number().int(), percentage: z.number()}); export const usdcGate = z.object({price: z.number().int(), splits: z.array(paymentSplit)}); export const purchaseGate = z.object({usdc_purchase: usdcGate}); export const extendedTokenGate = z.object({token_mint: z.string(), token_amount: z.number().int()}); export const tokenGate = z.object({token_gate: extendedTokenGate}); export const accessGate = z.union([tipGate, followGate, purchaseGate, tokenGate]); export const urlWithMirrors = z.object({url: z.string().optional(), mirrors: z.array(z.string())}); export const track = z.object({artwork: trackArtwork, description: z.string().optional(), genre: z.string(), id: z.string(), track_cid: z.string().optional(), preview_cid: z.string().optional(), orig_file_cid: z.string().optional(), orig_filename: z.string().optional(), is_original_available: z.boolean(), mood: z.string().optional(), release_date: z.string().optional(), remix_of: remixParent, repost_count: z.number().int(), favorite_count: z.number().int(), comment_count: z.number().int(), tags: z.string().optional(), title: z.string(), user: user, collaborators: z.array(user).optional(), pending_collaborators: z.array(user).optional(), duration: z.number().int(), is_downloadable: z.boolean(), play_count: z.number().int(), permalink: z.string(), is_streamable: z.boolean().optional(), ddex_app: z.string().optional(), playlists_containing_track: z.array(z.number().int()).optional(), pinned_comment_id: z.number().int().optional(), album_backlink: albumBacklink.optional(), access: access, blocknumber: z.number().int(), create_date: z.string().optional(), cover_art_sizes: z.string(), cover_art_cids: coverArt.optional(), created_at: z.string(), credits_splits: z.string().optional(), isrc: z.string().optional(), license: z.string().optional(), iswc: z.string().optional(), field_visibility: fieldVisibility, followee_reposts: z.array(repost), has_current_user_reposted: z.boolean(), is_scheduled_release: z.boolean(), is_unlisted: z.boolean(), has_current_user_saved: z.boolean(), followee_favorites: z.array(favorite), route_id: z.string(), stem_of: stemParent.optional(), track_segments: z.array(trackSegment), updated_at: z.string(), user_id: z.string(), is_delete: z.boolean(), cover_art: z.string().optional(), is_available: z.boolean(), ai_attribution_user_id: z.number().int().optional(), allowed_api_keys: z.array(z.string()).optional(), audio_upload_id: z.string().optional(), preview_start_seconds: z.number().optional(), bpm: z.number().optional(), is_custom_bpm: z.boolean().optional(), musical_key: z.string().optional(), is_custom_musical_key: z.boolean().optional(), audio_analysis_error_count: z.number().int().optional(), comments_disabled: z.boolean().optional(), ddex_release_ids: z.object({}).optional(), artists: z.array(z.object({})).optional(), resource_contributors: z.array(ddexResourceContributor).nullable().optional(), indirect_resource_contributors: z.array(ddexResourceContributor).nullable().optional(), rights_controller: ddexRightsController.optional(), copyright_line: ddexCopyright.nullable().optional(), producer_copyright_line: ddexCopyright.nullable().optional(), parental_warning_type: z.string().nullable().optional(), is_stream_gated: z.boolean(), access_authorities: z.array(z.string()).nullable().optional(), feedback_requested: z.boolean().optional(), feedback_requested_at: z.string().nullable().optional(), stream_conditions: accessGate.optional(), is_download_gated: z.boolean(), download_conditions: accessGate.optional(), cover_original_song_title: z.string().optional(), cover_original_artist: z.string().optional(), is_owned_by_user: z.boolean(), stream: urlWithMirrors, download: urlWithMirrors, preview: urlWithMirrors}); export const playlistArtwork = z.object({"150x150": z.string().optional(), "480x480": z.string().optional(), "1000x1000": z.string().optional(), mirrors: z.array(z.string()).optional()}); export const playlistAddedTimestamp = z.object({metadata_timestamp: z.number().int().optional(), timestamp: z.number().int(), track_id: z.string()}); export const playlist = z.object({artwork: playlistArtwork.optional(), description: z.string().optional(), permalink: z.string(), id: z.string(), is_album: z.boolean(), is_image_autogenerated: z.boolean(), playlist_name: z.string(), playlist_contents: z.array(playlistAddedTimestamp), repost_count: z.number().int(), favorite_count: z.number().int(), total_play_count: z.number().int(), user: user, ddex_app: z.string().optional(), access: access, upc: z.string().optional(), track_count: z.number().int(), blocknumber: z.number().int(), created_at: z.string(), followee_reposts: z.array(repost), followee_favorites: z.array(favorite), has_current_user_reposted: z.boolean(), has_current_user_saved: z.boolean(), is_delete: z.boolean(), is_private: z.boolean(), updated_at: z.string(), added_timestamps: z.array(playlistAddedTimestamp), user_id: z.string(), tracks: z.array(track).optional(), cover_art: z.string().optional(), cover_art_sizes: z.string().optional(), cover_art_cids: playlistArtwork.optional(), is_stream_gated: z.boolean(), stream_conditions: accessGate.optional(), is_scheduled_release: z.boolean(), release_date: z.string().optional(), ddex_release_ids: z.object({}).optional(), artists: z.array(z.object({})).optional(), copyright_line: z.object({}).optional(), producer_copyright_line: z.object({}).optional(), parental_warning_type: z.string().nullable().optional()}); export const related = z.object({users: z.array(user).optional(), tracks: z.array(track).optional(), playlists: z.array(playlist).optional()}); export const userCommentsResponse = z.object({latest_chain_block: z.number().int(), latest_indexed_block: z.number().int(), latest_chain_slot_plays: z.number().int(), latest_indexed_slot_plays: z.number().int(), signature: z.string(), timestamp: z.string(), version: versionMetadata, data: z.array(comment).optional(), related: related.optional()}); export const validateResponse = async ( schema: { readonly '~standard': { readonly validate: (value: unknown) => ({ readonly value: Output; readonly issues?: undefined } | { readonly issues: ReadonlyArray<{ readonly message: string; readonly path?: ReadonlyArray | undefined }> }) | Promise<{ readonly value: Output; readonly issues?: undefined } | { readonly issues: ReadonlyArray<{ readonly message: string; readonly path?: ReadonlyArray | undefined }> }> } }, value: unknown ): Promise => { const result = await schema['~standard'].validate(value) if (result.issues !== undefined) { const detail = result.issues .map(({ message, path }) => path?.length ? `${path.map((segment) => String(typeof segment === 'object' ? segment.key : segment)).join('.')}: ${message}` : message ) .join('; ') throw new Error(`Response does not match the schema: ${detail}`, { cause: { issues: result.issues } }) } return result.value }; /** * Get user comment history * * GET /users/{id}/comments */ export const getApiUsersIdComments = async (args: GetApiUsersIdCommentsArgs, options: GetApiUsersIdCommentsOptions) => { const {baseUrl, fetch: fetchFn = fetch, OAuth2} = options ?? {} const query = new URLSearchParams() const headers = new Headers() headers.set('accept', "application/json") if (args.offset != null) query.append("offset", String(args.offset)) if (args.limit != null) query.append("limit", String(args.limit)) if (args.user_id != null) query.append("user_id", String(args.user_id)) if (OAuth2 !== undefined) headers.set('authorization', `Bearer ${OAuth2}`) const url = `${baseUrl.replace(/\/+$/, '')}/users/${encodeURIComponent(String(args.id))}/comments${query.size > 0 ? `?${query}` : ''}` const res = await fetchFn(url, {method: "GET", headers}) if (!res.ok) throw new Error(`Request failed with status ${res.status}`, {cause: {status: res.status, body: await res.text()}}) return validateResponse(userCommentsResponse, await res.json()) };