### Build and Start Megalodon Project Source: https://github.com/h3poteto/megalodon/blob/master/example/webpack/README.md Execute the build and start commands for the Megalodon project and its browser workspace. Access the application at http://127.0.0.1:8000 after starting. ```bash $ yarn workspace megalodon build $ yarn workspace browser build $ yarn workspace browser start ``` -------------------------------- ### Install Megalodon using npm, pnpm, or yarn Source: https://github.com/h3poteto/megalodon/blob/master/README.md Use the appropriate package manager command to install the Megalodon library in your project. ```sh # npm npm install -S megalodon # pnpm pnpm add megalodon # yarn yarn add megalodon ``` -------------------------------- ### Manage Account Lists Source: https://context7.com/h3poteto/megalodon/llms.txt Create and manage curated account lists. Includes functions to get all lists, create new lists, add accounts, view members, fetch list timelines, rename, and delete lists. ```typescript import generator, { Entity, Response } from 'megalodon' const client = generator('mastodon', 'https://mastodon.social', process.env.ACCESS_TOKEN!) // Get all lists const lists: Response = await client.getLists() lists.data.forEach(l => console.log(l.id, l.title)) ``` ```typescript // Create a list const newList: Response = await client.createList('TypeScript devs') const listId = newList.data.id ``` ```typescript // Add accounts to list await client.addAccountsToList(listId, ['ACCOUNT_ID_1', 'ACCOUNT_ID_2']) ``` ```typescript // View list members const members = await client.getAccountsInList(listId, { limit: 40 }) console.log('Members:', members.data.map(a => a.acct)) ``` ```typescript // Fetch list timeline const timeline = await client.getListTimeline(listId, { limit: 20 }) timeline.data.forEach(s => console.log(`@${s.account.acct}: ${s.content}`)) ``` ```typescript // Rename and delete await client.updateList(listId, 'TypeScript & JavaScript devs') await client.deleteList(listId) ``` -------------------------------- ### Get Instance Information with Megalodon Source: https://context7.com/h3poteto/megalodon/llms.txt Query server metadata, trending tags, and custom emoji sets. No authentication is required for basic instance info. ```typescript import generator, { Entity, Response } from 'megalodon' const client = generator('mastodon', 'https://mastodon.social') // Get instance info (no auth required) const instance: Response = await client.getInstance() console.log('Title:', instance.data.title) console.log('Description:', instance.data.description) console.log('Users:', instance.data.stats.user_count) console.log('Version:', instance.data.version) // Get trending hashtags const trends: Response = await client.getInstanceTrends(10) trends.data.forEach(t => console.log(`#${t.name} — ${t.history?.[0]?.uses} uses today`)) // Get custom emojis const emojis: Response = await client.getInstanceCustomEmojis() emojis.data.forEach(e => console.log(`:${e.shortcode}: → ${e.url}`)) // Profile directory const directory = await client.getInstanceDirectory({ limit: 20, order: 'active', local: true }) directory.data.forEach(a => console.log(`@${a.acct}`)) ``` -------------------------------- ### Instantiate Mastodon Client with Instance Methods Source: https://github.com/h3poteto/megalodon/blob/master/migration_guide.md In v3.0.0, methods like registerApp, createApp, generateAuthUrl, fetchAccessToken, and refreshToken are now instance methods. Instantiate the Mastodon client first, then call these methods on the client instance. ```typescript import { Mastodon } from 'megalodon' const client = new Mastodon(...) client.registerApp('TestApp') ``` -------------------------------- ### Polls: Get and Vote with Megalodon Source: https://context7.com/h3poteto/megalodon/llms.txt Retrieves poll details and allows users to submit votes. Votes are submitted by option index. ```typescript import generator, { Entity, Response } from 'megalodon' const client = generator('mastodon', 'https://mastodon.social', process.env.ACCESS_TOKEN!) // Get poll details const poll: Response = await client.getPoll('POLL_ID') console.log('Question options:', poll.data.options.map(o => `${o.title} (${o.votes_count} votes)`)) console.log('Expires at:', poll.data.expires_at) console.log('Multiple choice:', poll.data.multiple) // Vote: submit index 0 (first option) const voted: Response = await client.votePoll('POLL_ID', [0]) console.log('Own votes:', voted.data.own_votes) console.log('Votes count:', voted.data.votes_count) ``` -------------------------------- ### Fetch Home Timeline with Megalodon Source: https://github.com/h3poteto/megalodon/blob/master/README.md Instantiate the client with your server URL and access token, then call `getHomeTimeline()` to retrieve posts. Ensure you have a valid access token and the correct server URL. ```ts import generator, { Entity, Response } from 'megalodon' const BASE_URL: string = 'https://mastodon.social' const access_token: string = '...' const client = generator('mastodon', BASE_URL, access_token) client.getHomeTimeline() .then((res: Response>) => { console.log(res.data) }) ``` -------------------------------- ### Register Application with Megalodon Source: https://github.com/h3poteto/megalodon/blob/master/README.md Register a new application on a Fediverse server using `registerApp()`. This method requires the application name and optional options. It returns application credentials and an authorization URL. ```ts import generator, { OAuth } from 'megalodon' const BASE_URL: string = 'https://mastodon.social' let clientId: string let clientSecret: string const client = generator('mastodon', BASE_URL) client.registerApp('Test App', {}) .then(appData => { clientId = appData.client_id clientSecret = appData.client_secret console.log('Authorization URL is generated.') console.log(appData.url) }) ``` -------------------------------- ### Make a Post with Megalodon Source: https://github.com/h3poteto/megalodon/blob/master/README.md Use the `postStatus()` method to create a new post. Provide the post content as a string argument. The method returns a Promise that resolves with the posted status entity. ```ts import generator, { Entity, Response } from 'megalodon' const BASE_URL: string = 'https://mastodon.social' const access_token: string = '...' const post: string = 'test post' const client = generator('mastodon', BASE_URL, access_token) client.postStatus(post) .then((res: Response) => { console.log(res.data) }) ``` -------------------------------- ### Set Environment Variables for Mastodon Source: https://github.com/h3poteto/megalodon/blob/master/example/webpack/README.md Configure necessary environment variables before building and running the project. Ensure MASTODON_URL and MASTODON_ACCESS_TOKEN are set. ```bash $ export MASTODON_URL=wss://mastodon.social $ export MASTODON_ACCESS_TOKEN=foobar ``` -------------------------------- ### Create a Platform Client with generator Source: https://context7.com/h3poteto/megalodon/llms.txt Use the `generator` function to create a client instance for a specific Fediverse platform. Provide the platform name, base URL, and an optional access token. Supported platforms include 'mastodon', 'pleroma', 'friendica', 'firefish', 'gotosocial', and 'pixelfed'. ```typescript import generator, { MegalodonInterface } from 'megalodon' // Mastodon (authenticated) const mastodon: MegalodonInterface = generator( 'mastodon', 'https://mastodon.social', process.env.MASTODON_ACCESS_TOKEN! ) // Pleroma (unauthenticated — public endpoints only) const pleroma: MegalodonInterface = generator('pleroma', 'https://pleroma.example') // Supported SNS values: 'mastodon' | 'pleroma' | 'friendica' | 'firefish' | 'gotosocial' | 'pixelfed' const firefish: MegalodonInterface = generator('firefish', 'https://firefish.social', process.env.FF_TOKEN!) ``` -------------------------------- ### Upload Media with Megalodon Source: https://github.com/h3poteto/megalodon/blob/master/README.md Use `uploadMedia()` to upload a file, such as an image. The file content should be provided as a Buffer. This method is useful for attaching media to posts. ```ts import generator, { Entity, Response } from 'megalodon' import fs from 'fs' const BASE_URL: string = 'https://mastodon.social' const access_token: string = '...' const image = fs.readFileSync("test-image.png") const client = generator('mastodon', BASE_URL, access_token) client.uploadMedia(image) .then((res: Response) => { console.log(res.data) }) ``` -------------------------------- ### Detect Server Software with Megalodon Source: https://github.com/h3poteto/megalodon/blob/master/README.md Use the `detector` function when the server's software is unknown. Provide the server URL to automatically detect its software (e.g., mastodon, pleroma, firefish). ```typescript import { detector } from 'megalodon' const FIRST_URL = 'https://mastodon.social' const SECOND_URL = 'https://firefish.social' const first_server = await detector(FIRST_URL) const second_server = await detector(SECOND_URL) console.log(first_server) // mastodon console.log(second_server) // firefish ``` -------------------------------- ### Instance Info Source: https://context7.com/h3poteto/megalodon/llms.txt Query server metadata, trending tags, and custom emoji sets. This API does not require authentication. ```APIDOC ## Instance Info API ### Description Query server metadata, trending tags, and custom emoji sets. This API provides information about the Mastodon instance. ### Methods - `getInstance(): Promise>`: Retrieves general instance information. - `getInstanceTrends(limit?: number): Promise>`: Retrieves trending hashtags. - `getInstanceCustomEmojis(): Promise>`: Retrieves custom emoji sets. - `getInstanceDirectory(params?: { local?: boolean, guest?: boolean, limit?: number, offset?: number, order?: 'active' | 'new', i?: string }): Promise>`: Retrieves accounts from the instance directory. ### Parameters #### `getInstanceTrends` Parameters - **limit** (number) - Optional - The maximum number of trending tags to return. #### `getInstanceDirectory` Parameters - **local** (boolean) - Optional - Whether to only show local users. - **guest** (boolean) - Optional - Whether to only show guest users. - **limit** (number) - Optional - The maximum number of accounts to return. - **offset** (number) - Optional - The number of accounts to skip. - **order** ('active' | 'new') - Optional - The order in which to return accounts. - **i** (string) - Optional - Used for filtering by a specific domain. ### Request Example (Get Instance Info) ```typescript const instance = await client.getInstance() ``` ### Response Example (Get Instance Info) ```json { "id": "1", "name": "Mastodon", "software_version": "4.1.3", "version": "4.1.3", "user_count": 100000, "status_count": 5000000, "disk_space": 100000000000, "configuration": { "urls": { "streaming": "wss://mastodon.social" }, "translation": { "enabled": true }, "accounts": { "max_வைத்_length": 16 } }, "description": "The official Mastodon instance.", "email_required": false, "invites_enabled": false, "thumbnail": null, "languages": ["en"] } ``` ``` -------------------------------- ### OAuth2 Authorization with registerApp and fetchAccessToken Source: https://context7.com/h3poteto/megalodon/llms.txt Register an OAuth application, generate an authorization URL, and then exchange an authorization code for an access token. This process involves multiple steps, including refreshing the token. ```typescript import generator, { OAuth } from 'megalodon' const BASE_URL = 'https://mastodon.social' const client = generator('mastodon', BASE_URL) let clientId: string let clientSecret: string // Step 1: Register app and get authorization URL const appData: OAuth.AppData = await client.registerApp('My App', { scopes: ['read', 'write', 'follow'], redirect_uris: 'urn:ietf:wg:oauth:2.0:oob', website: 'https://myapp.example' }) clientId = appData.client_id clientSecret = appData.client_secret console.log('Visit this URL to authorize:', appData.url) // Step 2: Exchange authorization code for access token const code = 'CODE_FROM_BROWSER' const tokenData: OAuth.TokenData = await client.fetchAccessToken(clientId, clientSecret, code) console.log('access_token:', tokenData.access_token) console.log('refresh_token:', tokenData.refresh_token) // tokenData.expires_in: number | null // tokenData.scope: string | null // Step 3: Refresh an expiring token const newTokenData = await client.refreshToken(clientId, clientSecret, tokenData.refresh_token!) console.log('new access_token:', newTokenData.access_token) ``` -------------------------------- ### `detector` — Auto-detect server software Source: https://context7.com/h3poteto/megalodon/llms.txt Queries the server's `/.well-known/nodeinfo` endpoint and returns the platform name string. Throws `NodeinfoError` if the server type cannot be determined. ```APIDOC ## `detector` — Auto-detect server software ### Description Queries the server's `/.well-known/nodeinfo` endpoint and returns the platform name string. Throws `NodeinfoError` if the server type cannot be determined. ### Usage ```typescript import { detector } from 'megalodon' import axios from 'axios' // Basic usage const sns = await detector('https://mastodon.social') console.log(sns) // "mastodon" // With a custom axios instance (e.g. for proxy support) const instance = axios.create({ timeout: 5000 }) const sns2 = await detector('https://firefish.social', instance) console.log(sns2) // "firefish" // Error handling try { const sns3 = await detector('https://unknown-server.example') } catch (err) { console.error(err.message) // "Unknown SNS" or "Could not find nodeinfo" } ``` ``` -------------------------------- ### Auto-detect Server Software with detector Source: https://context7.com/h3poteto/megalodon/llms.txt The `detector` utility automatically identifies the Fediverse software running on a given server by querying its NodeInfo endpoint. It can optionally accept a pre-configured axios instance for custom configurations like proxy support. Errors during detection will throw a `NodeinfoError`. ```typescript import { detector } from 'megalodon' import axios from 'axios' // Basic usage const sns = await detector('https://mastodon.social') console.log(sns) // "mastodon" // With a custom axios instance (e.g. for proxy support) const instance = axios.create({ timeout: 5000 }) const sns2 = await detector('https://firefish.social', instance) console.log(sns2) // "firefish" // Error handling try { const sns3 = await detector('https://unknown-server.example') } catch (err) { console.error(err.message) // "Unknown SNS" or "Could not find nodeinfo" } ``` -------------------------------- ### Publish a Status Source: https://context7.com/h3poteto/megalodon/llms.txt Creates a new post with optional media attachments, content warning, poll, visibility, scheduled time, language, and quote. ```APIDOC ## postStatus — Publish a Status ### Description Creates a new post with optional media attachments, content warning, poll, visibility, scheduled time, language, and quote. ### Method `POST` ### Endpoint `/api/v1/statuses` ### Parameters #### Request Body - **status** (string) - Required - The text content of the post. - **in_reply_to_id** (string) - Optional - ID of the status to reply to. - **sensitive** (boolean) - Optional - Mark the content as sensitive. - **spoiler_text** (string) - Optional - Text to be shown as a content warning. - **visibility** (string) - Optional - Visibility of the post ('public', 'unlisted', 'private', 'direct', 'local'). Defaults to 'public'. - **media_ids** (string[]) - Optional - Array of media IDs to attach. - **scheduled_at** (string) - Optional - ISO 8601 timestamp for scheduling the post. - **language** (string) - Optional - Language of the post (ISO 639-1 code). - **poll** (object) - Optional - Poll options for the post. - **options** (string[]) - Required - Array of poll option strings. - **expires_in** (number) - Required - Duration in seconds until the poll closes. - **multiple** (boolean) - Optional - Allow multiple choices. - **hide_totals** (boolean) - Optional - Hide vote counts until the poll ends. ### Request Example ```typescript // Simple text post const res = await client.postStatus('Hello, Fediverse!') // Reply with CW and private visibility await client.postStatus('spoiler content here', { in_reply_to_id: '109876543210', spoiler_text: 'CW: discussion', visibility: 'private', language: 'en' }) // Scheduled post const scheduledAt = new Date() scheduledAt.setMinutes(scheduledAt.getMinutes() + 10) await client.postStatus('Scheduled post!', { scheduled_at: scheduledAt.toISOString(), visibility: 'public' }) // Post with a poll await client.postStatus('Which do you prefer?', { poll: { options: ['Dogs', 'Cats', 'Both'], expires_in: 86400, multiple: false, hide_totals: false }, visibility: 'public' }) ``` ### Response #### Success Response (200) - `data` (Entity.Status | Entity.ScheduledStatus): The created status or scheduled status object. ### Response Example ```typescript console.log((res.data as Entity.Status).url) ``` ``` -------------------------------- ### Lists Management Source: https://context7.com/h3poteto/megalodon/llms.txt Create and manage curated account lists, including adding/removing accounts and fetching list timelines. ```APIDOC ## getLists / createList / addAccountsToList — Lists Create and manage curated account lists with their own timelines. ### getLists Retrieves all curated lists for the current user. ### Response #### Success Response (200) - **lists** (array) - An array of list objects, each containing `id` and `title`. ### createList Creates a new curated list. ### Parameters #### Request Body - **title** (string) - Required - The title of the new list. ### Response #### Success Response (200) - **List** (object) - The newly created list object, including its `id` and `title`. ### addAccountsToList Adds one or more accounts to a specified list. ### Parameters #### Path Parameters - **id** (string) - Required - The ID of the list to add accounts to. #### Request Body - **account_ids** (array) - Required - An array of account IDs to add to the list. ### getAccountsInList Retrieves the accounts that are members of a specific list. ### Parameters #### Path Parameters - **id** (string) - Required - The ID of the list. #### Query Parameters - **limit** (integer) - Optional - The maximum number of accounts to return. ### Response #### Success Response (200) - **accounts** (array) - An array of account objects that are members of the list. ### getListTimeline Fetches the timeline of statuses from accounts within a specific list. ### Parameters #### Path Parameters - **id** (string) - Required - The ID of the list. #### Query Parameters - **limit** (integer) - Optional - The maximum number of statuses to return. ### Response #### Success Response (200) - **statuses** (array) - An array of status objects from accounts in the list. ### updateList Renames a specified list. ### Parameters #### Path Parameters - **id** (string) - Required - The ID of the list to update. #### Request Body - **title** (string) - Required - The new title for the list. ### deleteList Deletes a specified list. ### Parameters #### Path Parameters - **id** (string) - Required - The ID of the list to delete. ``` -------------------------------- ### `generator` — Create a platform client Source: https://context7.com/h3poteto/megalodon/llms.txt Returns a `MegalodonInterface` client for the specified Fediverse platform. Accepts an optional `accessToken`, custom `userAgent`, and an optional pre-configured `axios` instance. ```APIDOC ## `generator` — Create a platform client ### Description Returns a `MegalodonInterface` client for the specified Fediverse platform. Accepts an optional `accessToken`, custom `userAgent`, and an optional pre-configured `axios` instance. ### Usage ```typescript import generator, { MegalodonInterface } from 'megalodon' // Mastodon (authenticated) const mastodon: MegalodonInterface = generator( 'mastodon', 'https://mastodon.social', process.env.MASTODON_ACCESS_TOKEN! ) // Pleroma (unauthenticated — public endpoints only) const pleroma: MegalodonInterface = generator('pleroma', 'https://pleroma.example') // Supported SNS values: 'mastodon' | 'pleroma' | 'friendica' | 'firefish' | 'gotosocial' | 'pixelfed' const firefish: MegalodonInterface = generator('firefish', 'https://firefish.social', process.env.FF_TOKEN!) ``` ``` -------------------------------- ### `registerApp` / `fetchAccessToken` — OAuth2 Authorization Source: https://context7.com/h3poteto/megalodon/llms.txt Registers an OAuth application on the target server, generates an authorization URL for the user to visit, then exchanges the authorization code for an access token. ```APIDOC ## `registerApp` / `fetchAccessToken` — OAuth2 Authorization ### Description Registers an OAuth application on the target server, generates an authorization URL for the user to visit, then exchanges the authorization code for an access token. ### Usage ```typescript import generator, { OAuth } from 'megalodon' const BASE_URL = 'https://mastodon.social' const client = generator('mastodon', BASE_URL) let clientId: string let clientSecret: string // Step 1: Register app and get authorization URL const appData: OAuth.AppData = await client.registerApp('My App', { scopes: ['read', 'write', 'follow'], redirect_uris: 'urn:ietf:wg:oauth:2.0:oob', website: 'https://myapp.example' }) clientId = appData.client_id clientSecret = appData.client_secret console.log('Visit this URL to authorize:', appData.url) // Step 2: Exchange authorization code for access token const code = 'CODE_FROM_BROWSER' const tokenData: OAuth.TokenData = await client.fetchAccessToken(clientId, clientSecret, code) console.log('access_token:', tokenData.access_token) console.log('refresh_token:', tokenData.refresh_token) // tokenData.expires_in: number | null // tokenData.scope: string | null // Step 3: Refresh an expiring token const newTokenData = await client.refreshToken(clientId, clientSecret, tokenData.refresh_token!) console.log('new access_token:', newTokenData.access_token) ``` ``` -------------------------------- ### Status Interactions Source: https://context7.com/h3poteto/megalodon/llms.txt Favourite (like), boost (reblog), and bookmark statuses, with corresponding undo methods. ```APIDOC ## favouriteStatus / reblogStatus / bookmarkStatus — Status Interactions ### Description Favourite (like), boost (reblog), and bookmark statuses, with corresponding undo methods. ### Methods - `favouriteStatus(statusId: string)` - `unfavouriteStatus(statusId: string)` - `reblogStatus(statusId: string)` - `unreblogStatus(statusId: string)` - `bookmarkStatus(statusId: string)` - `unbookmarkStatus(statusId: string)` - `pinStatus(statusId: string)` - `unpinStatus(statusId: string)` - `getStatusRebloggedBy(statusId: string, params?: { limit?: number, since_id?: string, max_id?: string })` - `getStatusFavouritedBy(statusId: string, params?: { limit?: number, since_id?: string, max_id?: string })` ### Request Example ```typescript const statusId = '109876543210987654' // Favourite / unfavourite const fav = await client.favouriteStatus(statusId) await client.unfavouriteStatus(statusId) // Boost / unboost const boost = await client.reblogStatus(statusId) await client.unreblogStatus(statusId) // Bookmark / unbookmark const bm = await client.bookmarkStatus(statusId) await client.unbookmarkStatus(statusId) // Pin / unpin to profile await client.pinStatus(statusId) await client.unpinStatus(statusId) // See who boosted / favourited const boosters = await client.getStatusRebloggedBy(statusId) const favoriters = await client.getStatusFavouritedBy(statusId) ``` ### Response #### Success Response - `favouriteStatus`, `unfavouriteStatus`, `reblogStatus`, `unreblogStatus`, `bookmarkStatus`, `unbookmarkStatus`, `pinStatus`, `unpinStatus`: Returns the updated status object. - `getStatusRebloggedBy`, `getStatusFavouritedBy`: Returns an array of account objects. ### Response Example ```typescript console.log('favourites_count:', fav.data.favourites_count) console.log('reblogs_count:', boost.data.reblogs_count) console.log('bookmarked:', bm.data.bookmarked) console.log('Boosted by:', boosters.data.map(a => a.acct)) ``` ``` -------------------------------- ### Media Attachments Source: https://context7.com/h3poteto/megalodon/llms.txt Upload image, video, or audio files as attachments. On some servers large files return an `AsyncAttachment` that must be polled via `getMedia`. ```APIDOC ## uploadMedia / getMedia / updateMedia — Media Attachments ### Description Upload image, video, or audio files as attachments. On some servers large files return an `AsyncAttachment` that must be polled via `getMedia`. ### Method `client.uploadMedia(stream, params)` `client.getMedia(id)` `client.updateMedia(id, params)` ### Parameters #### uploadMedia - **stream** (ReadableStream) - The media file stream to upload. - **params** (object) - Optional parameters for the upload. - **description** (string) - Alt text for the media. - **focus** (string) - Focus coordinate for the media (e.g., '0.0,0.5'). #### getMedia - **id** (string) - The ID of the media attachment to retrieve. #### updateMedia - **id** (string) - The ID of the media attachment to update. - **params** (object) - Parameters to update. - **description** (string) - Updated alt text for the media. ### Request Example ```typescript // Upload from a readable stream const imageStream = fs.createReadStream('./photo.png') const upload = await client.uploadMedia(imageStream, { description: 'A photo of a sunset', focus: '0.0,0.5' }) // If async, poll until ready let attachment; if ('url' in upload.data && upload.data.url === null) { // AsyncAttachment — poll let media = await client.getMedia(upload.data.id) while (!('url' in media.data) || media.data.url === null) { await new Promise(r => setTimeout(r, 1000)) media = await client.getMedia(upload.data.id) } attachment = media.data } else { attachment = upload.data } // Post the status with the attachment await client.postStatus('Check out this photo!', { media_ids: [attachment.id], sensitive: false }) // Update alt text after upload await client.updateMedia(attachment.id, { description: 'Updated alt text' }) ``` ### Response #### Success Response (200) - **Attachment** (object) - Details of the uploaded media. - **AsyncAttachment** (object) - Details for an asynchronous upload process. #### Response Example ```json { "id": "12345", "type": "image", "url": "https://mastodon.social/media/12345.png", "preview_url": "https://mastodon.social/media/12345_preview.png", "description": "A photo of a sunset", "blurhash": "..." } ``` ``` -------------------------------- ### Publish a Status Source: https://context7.com/h3poteto/megalodon/llms.txt Creates a new post with optional media attachments, content warning, poll, visibility, scheduled time, language, and quote. Supports simple text posts, replies, scheduled posts, and posts with polls. ```typescript import generator, { Entity, Response } from 'megalodon' const client = generator('mastodon', 'https://mastodon.social', process.env.ACCESS_TOKEN!) // Simple text post const res: Response = await client.postStatus('Hello, Fediverse!') console.log((res.data as Entity.Status).url) // Reply with CW and private visibility await client.postStatus('spoiler content here', { in_reply_to_id: '109876543210', spoiler_text: 'CW: discussion', visibility: 'private', // 'public' | 'unlisted' | 'private' | 'direct' | 'local' language: 'en' }) // Scheduled post (must be at least 5 minutes in the future) const scheduledAt = new Date() scheduledAt.setMinutes(scheduledAt.getMinutes() + 10) const scheduled = await client.postStatus('Scheduled post!', { scheduled_at: scheduledAt.toISOString(), visibility: 'public' }) console.log((scheduled.data as Entity.ScheduledStatus).scheduled_at) // Post with a poll await client.postStatus('Which do you prefer?', { poll: { options: ['Dogs', 'Cats', 'Both'], expires_in: 86400, // 24 hours in seconds multiple: false, hide_totals: false }, visibility: 'public' }) ``` -------------------------------- ### Generate SNS Client using Generator Function Source: https://github.com/h3poteto/megalodon/blob/master/migration_guide.md The default export is now a generator function that creates a client instance for a specified SNS (mastodon, pleroma, misskey). Pass the SNS name, URL, and access token to this function. ```typescript import generator from 'megalodon' const client = generator(sns_name, url, access_token) ``` -------------------------------- ### Fetch Access Token with Megalodon Source: https://github.com/h3poteto/megalodon/blob/master/README.md After obtaining an authorization code from the user, use `fetchAccessToken()` with the client ID, client secret, and authorization code to retrieve the access and refresh tokens. ```ts const code = '...' // Authorization code client.fetchAccessToken(clientId, clientSecret, code) .then((tokenData: OAuth.TokenData) => { console.log(tokenData.access_token) console.log(tokenData.refresh_token) }) .catch((err: Error) => console.error(err)) ``` -------------------------------- ### Handle WebSocket Streams with Megalodon Source: https://github.com/h3poteto/megalodon/blob/master/README.md Connect to a user's streaming API using `userStreaming()`. Listen for events like 'connect', 'update', 'notification', 'delete', 'error', 'heartbeat', 'close', and 'parser-error' to process real-time updates. ```ts import generator, { Entity } from 'megalodon' const BASE_URL: string = 'https://pleroma.io' const access_token: string = '...' const client = generator('pleroma', BASE_URL, access_token) client.userStreaming().then(stream => { stream.on('connect', () => { console.log('connect') }) stream.on('update', (status: Entity.Status) => { console.log(status) }) stream.on('notification', (notification: Entity.Notification) => { console.log(notification) }) stream.on('delete', (id: number) => { console.log(id) }) stream.on('error', (err: Error) => { console.error(err) }) stream.on('heartbeat', () => { console.log('thump.') }) stream.on('close', () => { console.log('close') }) stream.on('parser-error', (err: Error) => { console.error(err) }) }) ``` -------------------------------- ### Upload Media with Megalodon Source: https://context7.com/h3poteto/megalodon/llms.txt Uploads media files (image, video, audio) as attachments. Handles asynchronous uploads by polling for completion. Requires the `fs` module for stream operations. ```typescript import generator, { Entity, Response } from 'megalodon' import * as fs from 'fs' const client = generator('mastodon', 'https://mastodon.social', process.env.ACCESS_TOKEN!) // Upload from a readable stream const imageStream = fs.createReadStream('./photo.png') const upload: Response = await client.uploadMedia(imageStream, { description: 'A photo of a sunset', focus: '0.0,0.5' }) // If async, poll until ready let attachment: Entity.Attachment if ('url' in upload.data && upload.data.url === null) { // AsyncAttachment — poll let media = await client.getMedia(upload.data.id) while (!('url' in media.data) || media.data.url === null) { await new Promise(r => setTimeout(r, 1000)) media = await client.getMedia(upload.data.id) } attachment = media.data as Entity.Attachment } else { attachment = upload.data as Entity.Attachment } // Post the status with the attachment await client.postStatus('Check out this photo!', { media_ids: [attachment.id], sensitive: false }) // Update alt text after upload await client.updateMedia(attachment.id, { description: 'Updated alt text' }) ``` -------------------------------- ### Unified SNS Client Handling Source: https://github.com/h3poteto/megalodon/blob/master/migration_guide.md Combine the detector and generator functions to create a unified interface for interacting with multiple SNS endpoints. First, detect the SNS type from the URL, then generate the appropriate client. ```typescript import generator, { detector } from 'megalodon' const sns = await detector(url) const client = generator(sns, url, access_token) client.getHomeTimeline() ``` -------------------------------- ### Manage Content Filters with Megalodon Source: https://context7.com/h3poteto/megalodon/llms.txt Use this to create, list, update, and delete keyword filters for specific timeline contexts. Ensure the ACCESS_TOKEN is set in your environment. ```typescript import generator, { Entity, Response, FilterContext } from 'megalodon' const client = generator('mastodon', 'https://mastodon.social', process.env.ACCESS_TOKEN!) // List existing filters const filters: Response = await client.getFilters() filters.data.forEach(f => console.log(f.phrase, f.context)) // Create a filter const filter: Response = await client.createFilter( 'spoiler phrase', [FilterContext.Home, FilterContext.Notifications, FilterContext.Public], { irreversible: false, whole_word: true, expires_in: '2026-12-31T00:00:00.000Z' } ) console.log('Filter ID:', filter.data.id) // Update a filter await client.updateFilter( filter.data.id, 'updated phrase', [FilterContext.Home], { whole_word: false } ) // Delete a filter await client.deleteFilter(filter.data.id) ``` -------------------------------- ### Manage Account Relationships Source: https://context7.com/h3poteto/megalodon/llms.txt Look up accounts by ID or Webfinger address, and manage follow, block, mute, and subscription relationships. Also retrieves account statuses with filters. ```typescript import generator, { Entity, Response } from 'megalodon' const client = generator('mastodon', 'https://mastodon.social', process.env.ACCESS_TOKEN!) // Get account by ID const account: Response = await client.getAccount('ACCOUNT_ID') console.log(`@${account.data.acct} — ${account.data.followers_count} followers`) ``` ```typescript // Lookup by Webfinger address const found = await client.lookupAccount('alice@mastodon.social') console.log(found.data.id) ``` ```typescript // Follow / unfollow await client.followAccount('ACCOUNT_ID', { reblog: true }) await client.unfollowAccount('ACCOUNT_ID') ``` ```typescript // Block / unblock await client.blockAccount('ACCOUNT_ID') await client.unblockAccount('ACCOUNT_ID') ``` ```typescript // Mute / unmute (including notifications) await client.muteAccount('ACCOUNT_ID', true) await client.unmuteAccount('ACCOUNT_ID') ``` ```typescript // Check relationship const rel: Response = await client.getRelationship('ACCOUNT_ID') console.log('following:', rel.data.following, 'blocked_by:', rel.data.blocked_by) ``` ```typescript // Get account statuses with filters const statuses = await client.getAccountStatuses('ACCOUNT_ID', { limit: 20, exclude_replies: true, only_media: false }) ``` -------------------------------- ### Account Management Source: https://context7.com/h3poteto/megalodon/llms.txt Retrieve account information, and manage follow, block, mute, and subscription relationships. ```APIDOC ## getAccount / followAccount / blockAccount / muteAccount — Account Management Look up accounts and manage follow, block, mute, and subscription relationships. ### getAccount Retrieves a specific account's information by its ID. ### Parameters #### Path Parameters - **id** (string) - Required - The ID of the account to retrieve. ### Response #### Success Response (200) - **Account** (object) - Detailed information about the account, including `acct` and `followers_count`. ### lookupAccount Looks up an account by its Webfinger address. ### Parameters #### Path Parameters - **address** (string) - Required - The Webfinger address of the account (e.g., 'alice@mastodon.social'). ### Response #### Success Response (200) - **Account** (object) - Information about the found account, including its `id`. ### followAccount Follows a specified account. ### Parameters #### Path Parameters - **id** (string) - Required - The ID of the account to follow. #### Request Body - **reblog** (boolean) - Optional - Whether to reblog posts from this account. ### unfollowAccount Unfollows a specified account. ### Parameters #### Path Parameters - **id** (string) - Required - The ID of the account to unfollow. ### blockAccount Blocks a specified account. ### Parameters #### Path Parameters - **id** (string) - Required - The ID of the account to block. ### unblockAccount Unblocks a specified account. ### Parameters #### Path Parameters - **id** (string) - Required - The ID of the account to unblock. ### muteAccount Mutes a specified account, optionally including notifications. ### Parameters #### Path Parameters - **id** (string) - Required - The ID of the account to mute. - **notifications** (boolean) - Optional - Whether to also mute notifications from this account. ### unmuteAccount Unmutes a specified account. ### Parameters #### Path Parameters - **id** (string) - Required - The ID of the account to unmute. ### getRelationship Retrieves the relationship between the current user and a specified account. ### Parameters #### Path Parameters - **id** (string) - Required - The ID of the account to check the relationship with. ### Response #### Success Response (200) - **Relationship** (object) - An object detailing the relationship, including `following` and `blocked_by`. ### getAccountStatuses Retrieves statuses posted by a specific account, with filtering options. ### Parameters #### Path Parameters - **id** (string) - Required - The ID of the account whose statuses to retrieve. #### Query Parameters - **limit** (integer) - Optional - The maximum number of statuses to return. - **exclude_replies** (boolean) - Optional - Whether to exclude replies from the results. - **only_media** (boolean) - Optional - Whether to only return statuses that contain media. ### Response #### Success Response (200) - **statuses** (array) - An array of status objects posted by the account. ``` -------------------------------- ### Manage Timeline Markers with Megalodon Source: https://context7.com/h3poteto/megalodon/llms.txt Save and restore read positions for home and notifications timelines. Requires an ACCESS_TOKEN. ```typescript import generator, { Entity, Response } from 'megalodon' const client = generator('mastodon', 'https://mastodon.social', process.env.ACCESS_TOKEN!) // Get saved positions const markers: Response> = await client.getMarkers(['home', 'notifications']) const m = markers.data as Entity.Marker console.log('Home last read:', m.home?.last_read_id) console.log('Notifications last read:', m.notifications?.last_read_id) // Save current positions const saved: Response = await client.saveMarkers({ home: { last_read_id: '109876543210987654' }, notifications: { last_read_id: '105917259070666683' } }) console.log('Saved marker:', saved.data) ``` -------------------------------- ### Call Mastodon APIs with Dedicated Methods Source: https://github.com/h3poteto/megalodon/blob/master/migration_guide.md v2.x's generic API call method is deprecated. Use the new dedicated methods for each Mastodon API endpoint, such as getHomeTimeline(), for improved type safety and clarity. ```typescript import { Mastodon } from 'megalodon' const client = new Mastodon(...) client.getHomeTimeline() ``` -------------------------------- ### Scheduled Statuses Source: https://context7.com/h3poteto/megalodon/llms.txt Manage queued scheduled posts. ```APIDOC ## getScheduledStatuses / scheduleStatus / cancelScheduledStatus — Scheduled Statuses ### Description Manage queued scheduled posts. ### Method `client.getScheduledStatuses(params)` `client.scheduleStatus(statusId, scheduledAt)` `client.cancelScheduledStatus(statusId)` ### Parameters #### getScheduledStatuses - **params** (object) - Optional parameters. - **limit** (number) - Maximum number of results to return. #### scheduleStatus - **statusId** (string) - The ID of the status to schedule. - **scheduledAt** (string) - ISO 8601 Datetime string for when to schedule the post. #### cancelScheduledStatus - **statusId** (string) - The ID of the scheduled status to cancel. ### Request Example ```typescript // List all scheduled statuses const scheduled = await client.getScheduledStatuses({ limit: 20 }) scheduled.data.forEach(s => console.log(s.id, s.scheduled_at, s.params.text)) // Reschedule a post const newTime = new Date() newTime.setHours(newTime.getHours() + 2) await client.scheduleStatus(scheduled.data[0].id, newTime.toISOString()) // Cancel a scheduled status await client.cancelScheduledStatus(scheduled.data[0].id) ``` ### Response #### Success Response (200) - **ScheduledStatus[]** (array) - An array of scheduled status objects. - **null** - Indicates successful cancellation or rescheduling. #### Response Example ```json [ { "id": "12345", "scheduled_at": "2023-12-31T12:00:00Z", "params": { "text": "My scheduled post content" }, "media_attachments": [] } ] ``` ``` -------------------------------- ### Real-time WebSocket Streaming with Megalodon Source: https://context7.com/h3poteto/megalodon/llms.txt Open persistent WebSocket connections to receive real-time events like new posts, notifications, and status updates. Supports user, tag, and local public streams. Includes automatic reconnection and heartbeat detection. ```typescript import generator, { Entity } from 'megalodon' const client = generator('mastodon', 'https://mastodon.social', process.env.ACCESS_TOKEN!) // User stream (home timeline + notifications) const userStream = await client.userStreaming() userStream.on('connect', () => console.log('Connected')) userStream.on('update', (status: Entity.Status) => { console.log(`New post from @${status.account.acct}: ${status.content}`) }) userStream.on('notification', (notification: Entity.Notification) => { console.log(`Notification [${notification.type}] from @${notification.account?.acct}`) }) userStream.on('status_update', (status: Entity.Status) => { console.log(`Edited post: ${status.url}`) }) userStream.on('delete', (id: string) => console.log('Deleted status:', id)) userStream.on('heartbeat', () => console.log('thump.')) userStream.on('error', (err: Error) => console.error('Stream error:', err)) userStream.on('close', () => console.log('Connection closed')) userStream.on('parser-error', (err: Error) => console.error('Parse error:', err)) // Stop streaming setTimeout(() => userStream.stop(), 60000) // Tag stream (no auth needed) const tagStream = await client.tagStreaming('typescript') tagStream.on('update', (status: Entity.Status) => console.log(status.url)) // Local public stream const localStream = await client.localStreaming() localStream.on('update', (s: Entity.Status) => console.log(`@${s.account.acct}: ${s.content}`)) ``` -------------------------------- ### Subscribe to Web Push Notifications Source: https://context7.com/h3poteto/megalodon/llms.txt Subscribe to server-sent Web Push notifications for a browser endpoint. Requires endpoint and keys for subscription. Alerts can be configured for various events. ```typescript import generator, { Entity, Response } from 'megalodon' const client = generator('mastodon', 'https://mastodon.social', process.env.ACCESS_TOKEN!) // Subscribe const sub: Response = await client.subscribePushNotification( { endpoint: 'https://push.example.com/endpoint/abc123', keys: { p256dh: 'BASE64_ECDH_PUBLIC_KEY', auth: 'BASE64_AUTH_SECRET' } }, { alerts: { follow: true, favourite: true, reblog: true, mention: true, poll: false } } ) console.log('Server key:', sub.data.server_key) ``` ```typescript // Update alert types await client.updatePushSubscription({ alerts: { follow: false, mention: true, favourite: false, reblog: false } }) ``` ```typescript // Remove subscription await client.deletePushSubscription() ```