|
1 | | -# discord-player |
2 | | -Discord music player. |
| 1 | +**HyCom API** |
3 | 2 |
|
| 3 | +A lightweight TypeScript client for the [HyCom](https://hycom.ir) public API. This package provides convenient functions to fetch authors, posts, tags, site statistics, and QR codes, handling all network requests internally. |
4 | 4 |
|
5 | | -## Introduction |
6 | | - |
7 | | -This repository provides a fully-typed `MusicPlayer` class for Discord self-bots, along with a strongly-typed event system using an `enum`. You get: |
| 5 | +--- |
8 | 6 |
|
9 | | -* A single `MusicPlayer.ts` implementation that extends `EventEmitter` and emits fixed, well-typed events |
10 | | -* A `src/types.ts` file defining `MusicPlayerEvent` (as an `enum`), the payload interfaces for each event, and a `TypedEmitter` interface for full type-safety |
| 7 | +## Features |
11 | 8 |
|
12 | | -You can install, import, and start listening to player events in seconds, without touching raw channel messaging. |
| 9 | +* Fetch top authors by views |
| 10 | +* Retrieve posts by author |
| 11 | +* List popular tags |
| 12 | +* Explore and search posts with pagination and sorting |
| 13 | +* Get site-wide statistics |
| 14 | +* Generate QR codes for any URL |
13 | 15 |
|
14 | 16 | --- |
15 | 17 |
|
16 | 18 | ## Installation |
17 | 19 |
|
18 | | -```bash |
19 | | -npm install --save @persian-caesar/discord-player |
20 | | -``` |
21 | | - |
22 | | -> **Note:** |
23 | | -> This package provides the player and its types. You still need to install the actual playback libraries as peer dependencies: |
| 20 | +Install via npm or yarn: |
24 | 21 |
|
25 | 22 | ```bash |
26 | | -npm install @discordjs/voice ytdl-core-discord ytdl-core play-dl @distube/ytdl-core soundcloud-downloader ffmpeg-static @discordjs/opus libsodium-wrappers |
| 23 | +npm install @persian-caesar/hycom-api |
| 24 | +# or |
| 25 | +yarn add @persian-caesar/hycom-api |
27 | 26 | ``` |
28 | 27 |
|
29 | 28 | --- |
30 | 29 |
|
31 | | -## Quick Start (TypeScript) |
| 30 | +## Quick Start |
32 | 31 |
|
33 | 32 | ```ts |
34 | | -import { MusicPlayer, MusicPlayerEvent } from "@persian-caesar/discord-player"; |
35 | | -import type { VoiceChannel } from "@persian-caesar/discord-player"; |
36 | | - |
37 | | -// Assume you already have a VoiceChannel object: |
38 | | -const voiceChannel: VoiceChannel = /* your voice channel instance */; |
39 | | - |
40 | | -const player = new MusicPlayer(voiceChannel, 50, { |
41 | | - autoLeaveOnEmptyQueue: true, |
42 | | - autoLeaveOnIdleMs: 300_000, |
43 | | -}); |
44 | | - |
45 | | -// Listen for events |
46 | | -player.on(MusicPlayerEvent.Start, ({ url, history, metadata }) => { |
47 | | - console.log(`▶️ Now playing: ${url}`); |
48 | | -}); |
49 | | - |
50 | | -player.on(MusicPlayerEvent.QueueAdd, ({ url, queue }) => { |
51 | | - console.log(`➕ Added to queue: ${url} (queue length: ${queue.length})`); |
52 | | -}); |
53 | | - |
54 | | -player.on(MusicPlayerEvent.Finish, ({ history }) => { |
55 | | - console.log("⏹️ Playback finished."); |
56 | | -}); |
57 | | - |
58 | | -player.on(MusicPlayerEvent.Error, (error) => { |
59 | | - console.error("❌ Player error:", error.message); |
60 | | -}); |
| 33 | +import { |
| 34 | + topAuthor, |
| 35 | + authorPosts, |
| 36 | + getTags, |
| 37 | + explore, |
| 38 | + siteInformation, |
| 39 | + lastPosts, |
| 40 | + searchPosts, |
| 41 | + qrCode |
| 42 | +} from '@persian-caesar/hycom-api'; |
| 43 | + |
| 44 | +async function main() { |
| 45 | + // 1. Get top 5 authors by view count |
| 46 | + const authors = await topAuthor(5); |
| 47 | + console.log('Top Authors:', authors); |
| 48 | + |
| 49 | + // 2. Retrieve latest posts by a specific author |
| 50 | + const postsByAuthor = await authorPosts('john-doe', 10, 'newest'); |
| 51 | + console.log("John Doe's Posts:", postsByAuthor); |
| 52 | + |
| 53 | + // 3. List 15 most popular tags |
| 54 | + const tags = await getTags(15); |
| 55 | + console.log('Tags:', tags); |
| 56 | + |
| 57 | + // 4. Explore posts: page 2, sorted by most viewed, filtered by 'javascript' |
| 58 | + const exploreResults = await explore('', 2, 12, 'most_viewed', 'javascript'); |
| 59 | + console.log('Explore Results:', exploreResults); |
| 60 | + |
| 61 | + // 5. Fetch site information |
| 62 | + const siteInfo = await siteInformation(); |
| 63 | + console.log('Site Information:', siteInfo); |
| 64 | + |
| 65 | + // 6. Get the 8 most recent posts |
| 66 | + const recent = await lastPosts(8); |
| 67 | + console.log('Recent Posts:', recent); |
| 68 | + |
| 69 | + // 7. Search posts by keyword |
| 70 | + const searchResults = await searchPosts('nodejs', 10, 1); |
| 71 | + console.log('Search Results:', searchResults); |
| 72 | + |
| 73 | + // 8. Generate a QR code for a URL |
| 74 | + const qrBuffer = await qrCode('https://example.com'); |
| 75 | + // Save the QR buffer to disk in Node.js |
| 76 | + import * as fs from 'fs'; |
| 77 | + fs.writeFileSync('qrcode.png', qrBuffer); |
| 78 | + console.log('QR code saved!'); |
| 79 | +} |
61 | 80 |
|
62 | | -// Start playing |
63 | | -await player.play("https://youtu.be/dQw4w9WgXcQ"); |
| 81 | +main().catch(console.error); |
64 | 82 | ``` |
65 | 83 |
|
66 | | ---- |
67 | | - |
68 | | - |
69 | | -## Quick Start (JavaScript) |
70 | | - |
71 | | -```ts |
72 | | -// @persian-caesar/discord-player ships with JSDoc types, so plain JS works too: |
73 | | -const { MusicPlayer, MusicPlayerEvent } = require("@persian-caesar/discord-player"); |
74 | | - |
75 | | -/** |
76 | | - * @type {import("@persian-caesar/discord-player").VoiceChannel} |
77 | | - */ |
78 | | -const voiceChannel = /* your voice channel instance */; |
79 | | - |
80 | | -const player = new MusicPlayer(voiceChannel, 50, { |
81 | | - autoLeaveOnEmptyQueue: true, |
82 | | - autoLeaveOnIdleMs: 300_000, |
83 | | -}); |
84 | | - |
85 | | -player.on(MusicPlayerEvent.Start, ({ url, history, metadata }) => { |
86 | | - console.log("▶️ Now playing:", url); |
87 | | -}); |
88 | | - |
89 | | -player.play("https://youtu.be/dQw4w9WgXcQ"); |
| 84 | +## Usage in JavaScript |
| 85 | + |
| 86 | +If you're using plain JavaScript (CommonJS), import and use the library like this: |
| 87 | + |
| 88 | +```js |
| 89 | +const { |
| 90 | + topAuthor, |
| 91 | + authorPosts, |
| 92 | + getTags, |
| 93 | + explore, |
| 94 | + siteInformation, |
| 95 | + lastPosts, |
| 96 | + searchPosts, |
| 97 | + qrCode |
| 98 | +} = require('@persian-caesar/hycom-api'); |
| 99 | + |
| 100 | +(async () => { |
| 101 | + try { |
| 102 | + // Example: fetch top 3 authors |
| 103 | + const authors = await topAuthor(3); |
| 104 | + console.log('Top 3 Authors:', authors); |
| 105 | + |
| 106 | + // Fetch posts by author 'jane-doe-456' |
| 107 | + const posts = await authorPosts('jane-doe-456', 5, 'most_viewed'); |
| 108 | + console.log("Jane Doe's Posts:", posts); |
| 109 | + |
| 110 | + // List tags |
| 111 | + const tags = await getTags(10); |
| 112 | + console.log('Popular Tags:', tags); |
| 113 | + |
| 114 | + // Explore articles with pagination |
| 115 | + const exploreResults = await explore('javascript', 1, 8, 'recommended', 'nodejs'); |
| 116 | + console.log('Explore Results:', exploreResults); |
| 117 | + |
| 118 | + // Site information |
| 119 | + const info = await siteInformation(); |
| 120 | + console.log('Site Info:', info); |
| 121 | + |
| 122 | + // Last posts |
| 123 | + const recent = await lastPosts(6); |
| 124 | + console.log('Recent Posts:', recent); |
| 125 | + |
| 126 | + // Search posts |
| 127 | + const search = await searchPosts('api', 5, 1); |
| 128 | + console.log('Search Results:', search); |
| 129 | + |
| 130 | + // Generate QR code |
| 131 | + const qrBuffer = await qrCode('https://example.com'); |
| 132 | + const fs = require('fs'); |
| 133 | + fs.writeFileSync('qrcode_js.png', qrBuffer); |
| 134 | + console.log('QR code saved as qrcode_js.png'); |
| 135 | + } catch (error) { |
| 136 | + console.error('Error:', error); |
| 137 | + } |
| 138 | +})(); |
90 | 139 | ``` |
91 | 140 |
|
92 | 141 | --- |
93 | 142 |
|
94 | 143 | ## API Reference |
95 | 144 |
|
96 | | -### `class MusicPlayer` |
97 | | - |
98 | | -#### Constructor |
99 | | - |
100 | | -```ts |
101 | | -new MusicPlayer( |
102 | | - channel: VoiceChannel, |
103 | | - initialVolume?: number, // default: 100 => 100% |
104 | | - options?: MusicPlayerOptions, // { autoLeaveOnEmptyQueue?: boolean, autoLeaveOnIdleMs?: number } |
105 | | -) |
106 | | -``` |
107 | | - |
108 | | -* `autoLeaveOnEmptyQueue` (default `true`): automatically disconnect when queue ends |
109 | | -* `autoLeaveOnIdleMs` (default `5 * 60_000` ms): time before auto-disconnect on idle |
110 | | - |
111 | | -#### Methods |
112 | | - |
113 | | -| Method | Description | |
114 | | -| ---------------------------- | ----------------------------------------- | |
115 | | -| `play(input: string)` | Search & play or enqueue a track | |
116 | | -| `pause()` | Pause playback | |
117 | | -| `resume()` | Resume playback | |
118 | | -| `setVolume(percent: number)` | Set volume (0–200%) | |
119 | | -| `skip()` | Skip current track | |
120 | | -| `previous()` | Go back to previous track | |
121 | | -| `shuffle()` | Shuffle the queue | |
122 | | -| `toggleLoopQueue()` | Toggle queue repeat | |
123 | | -| `toggleLoopTrack()` | Toggle single-track repeat | |
124 | | -| `stop(disconnect?: boolean)` | Stop playback (and optionally disconnect) | |
125 | | -| `disconnect()` | Force disconnect immediately | |
126 | | -| `getQueue(): string[]` | Get copy of current queue URLs | |
127 | | -| `getVolume(): number` | Get current volume as percentage | |
| 145 | +| Function | Description | Parameters | Returns | | |
| 146 | +| --------------------------------------------------- | -------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------- | --------------------------------- | -------- | |
| 147 | +| `topAuthor(limit?)` | Fetches authors sorted by total views | `limit` (number, default `10`): number of authors to return (1–50) | `Author[]` | | |
| 148 | +| `authorPosts(name, limit?, sort?)` | Retrieves published posts by a given author | `name` (string): display name and profile ID (e.g., "jane-doe-123")<br>`limit` (number, default `10`)<br>`sort` ("newest" | "most\_viewed", default "newest") | `Post[]` | |
| 149 | +| `getTags(limit?)` | Returns tags with their associated post counts | `limit` (number, default `20`): number of tags (1–100) | `Tag[]` | | |
| 150 | +| `explore(search?, page?, limit?, sort?, tag?)` | Paginated list of articles with filtering and sorting | `search` (string)<br>`page` (number, default `1`)<br>`limit` (number, default `12`)<br>`sort` ("recommended" | | | |
| 151 | +| "newest" | | | | | |
| 152 | +| "most\_viewed", default "newest")<br>`tag` (string) | `Post[]` | | | | |
| 153 | +| `siteInformation()` | Site statistics including last post, total views, posts, and authors | — | `SiteInformation` | | |
| 154 | +| `lastPosts(limit?)` | Fetches the most recent published posts | `limit` (number, default `10`) | `Post[]` | | |
| 155 | +| `searchPosts(query, limit?, page?)` | Searches posts by title, tags, or author | `query` (string): search term<br>`limit` (number, default `10`)<br>`page` (number, default `1`) | `Post[]` | | |
| 156 | +| `qrCode(url)` | Generates a QR code image buffer for the specified URL | `url` (string): URL to encode | `Buffer` | | |
128 | 157 |
|
129 | 158 | --- |
130 | 159 |
|
131 | | -### `enum MusicPlayerEvent` |
132 | | - |
133 | | -```ts |
134 | | -export enum MusicPlayerEvent { |
135 | | - Start = "start", |
136 | | - QueueAdd = "queueAdd", |
137 | | - Pause = "pause", |
138 | | - Resume = "resume", |
139 | | - Stop = "stop", |
140 | | - Skip = "skip", |
141 | | - Previous = "previous", |
142 | | - Shuffle = "shuffle", |
143 | | - LoopQueue = "loopQueue", |
144 | | - LoopTrack = "loopTrack", |
145 | | - VolumeChange = "volumeChange", |
146 | | - Finish = "finish", |
147 | | - Disconnect = "disconnect", |
148 | | - Error = "error", |
149 | | -} |
150 | | -``` |
151 | | - |
152 | | -Each event emits a strongly-typed payload: |
| 160 | +## Types |
153 | 161 |
|
154 | | -```ts |
155 | | -// examples of payload shapes |
156 | | -Start → { url: string; history: string[]; metadata: TrackMetadata; } |
157 | | -QueueAdd → { url: string; queue: TrackMetadata[] } |
158 | | -Pause/Resume → no payload |
159 | | -VolumeChange → { volume: number } |
160 | | -Skip/Previous → { history: string[] } |
161 | | -Shuffle → { queue: TrackMetadata[] } |
162 | | -LoopQueue/Track → { enabled: boolean } |
163 | | -Finish → { history: string[] } |
164 | | -Disconnect → no payload |
165 | | -Error → Error instance |
166 | | -``` |
| 162 | +All response data types are defined in `types.ts`. Key interfaces include: |
167 | 163 |
|
168 | | -For full payload definitions, see `src/types.ts`. |
| 164 | +* `Author`: metadata about an author (name, profile ID, views) |
| 165 | +* `Post`: article information (title, summary, image, stats) |
| 166 | +* `Tag`: tag slug and post count |
| 167 | +* `SiteInformation`: overall site metrics |
| 168 | +* `QrCodeResponse`: raw Base64 QR code string |
169 | 169 |
|
170 | 170 | --- |
171 | 171 |
|
172 | | -## Documentation & Support |
| 172 | +## License |
173 | 173 |
|
174 | | -* **Repository**: [https://github.com/Persian-Caesar/discord-player](https://github.com/Persian-Caesar/discord-player) |
175 | | -* **Issues**: [https://github.com/Persian-Caesar/discord-player/issues](https://github.com/Persian-Caesar/discord-player/issues) |
176 | | -* **License**: MIT |
| 174 | +This project is licensed under the MIT License. See the [LICENSE](./LICENSE) file for details. |
177 | 175 |
|
178 | 176 | --- |
179 | 177 |
|
|
0 commit comments