Guest User

Untitled

a guest
Mar 3rd, 2026
157
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 13.37 KB | None | 0 0
  1. # Plan: Add MAX (max.ru) as a Platform
  2.  
  3. ## Context
  4.  
  5. The user wants to add MAX (max.ru) — a Russian social messenger — as a new posting platform in Skyfall Autoposter. MAX provides a Bot API at `platform-api.max.ru` analogous to Telegram's Bot API: bots are authorized with a token, can send messages to chats/channels, and support file uploads (images, video, audio, files). The integration should follow the same patterns used for Telegram (the most recently added platform), which will serve as the direct structural template.
  6.  
  7. **MAX Bot API key facts:**
  8. - Base URL: `https://platform-api.max.ru`
  9. - Auth: `Authorization: <token>` header (no query param)
  10. - Send message: `POST /messages?chat_id={id}` body: `{ text, attachments, format, notify }`
  11. - Text limit: 4000 characters
  12. - Upload files: `POST /uploads?type={image|video|audio|file}` → returns `{ url, token }`
  13. - Images/files: upload to `url`, reference in message as `{ type: "image"/"file", payload: { token } }`
  14. - Video/audio: upload to `url`, reference with `token` in payload
  15. - Supported: JPG/PNG/GIF (image), MP4/MOV/MKV/WEBM (video), MP3/WAV (audio), any (file)
  16. - Max file size: 4 GB
  17. - Note: after upload, server processing may take time → `attachment.not.ready` error requires retry
  18. - Test bot info: `GET /me`
  19. - Rate limit: 30 req/s
  20.  
  21. ---
  22.  
  23. ## Files to Create
  24.  
  25. ### 1. `src/platforms/config/max.js`
  26. Axios client factory — mirrors `src/platforms/config/telegram.js`.
  27. - Credential field: `botToken`
  28. - `baseURL`: `https://platform-api.max.ru`
  29. - Auth via `Authorization` header added to every request (via axios `headers.Authorization`)
  30. - Proxy support via `createProxyAgent()` / `isProxyConfigured()`
  31. - Timeout: `60000` (uploads can be slow)
  32.  
  33. ### 2. `src/platforms/services/maxService.js`
  34. Platform service — mirrors `src/platforms/services/telegramService.js` structure.
  35.  
  36. **Functions:**
  37. - `testConnection(credentials)` → `GET /me` → returns `{ success, user: { id, username, name } }`
  38. - `sendPost(options, credentials)` where options = `{ chatId, text, filePaths }`
  39. - No files → `POST /messages?chat_id={chatId}` with `{ text }`
  40. - With files → upload each via `POST /uploads?type={type}`, collect tokens, send message with `attachments` array
  41. - Retry logic for `attachment.not.ready` errors (up to 3 retries with 2s delays)
  42. - Caption limit: 4000 chars (MAX applies text to message body, not caption)
  43.  
  44. **Upload flow per file:**
  45. 1. `POST /uploads?type=image|video|audio|file` → get `{ url, token }`
  46. 2. PUT file binary to returned `url`
  47. 3. Add `{ type: "image"|"video"|"audio"|"file", payload: { token } }` to attachments array
  48. 4. `POST /messages?chat_id={chatId}` with `{ text, attachments }`
  49.  
  50. **Helper:** `parseMaxError(error)` for friendly error messages.
  51.  
  52. ### 3. `src/platforms/handlers/MaxHandler.js`
  53. Extends `PlatformHandler` — mirrors `src/platforms/handlers/TelegramHandler.js`.
  54.  
  55. - `getPlatformId()` → `'max'`
  56. - `getPlatformName()` → `'MAX'`
  57. - `getCredentialFields()` → `[{ name: 'botToken', label: 'Bot Token', type: 'password', required: true, sensitive: true }]`
  58. - `getJobFields()` → `[{ name: 'accountId', ... }, { name: 'chatId', ... }]`
  59. - `validateJob()` — checks accountId, credentials, chatId, and content/media presence; text ≤ 4000
  60. - `processJob()` — calls `maxService.sendPost()`; returns `createSuccessResult({ messageId, chatId })`
  61. - `testConnection()` — calls `maxService.testConnection()`
  62. - `getAccountIdentifier()` — returns bot `name` or `@username`
  63.  
  64. Local `categorizeMaxError(msg)` function mapping error strings to `ErrorCategory.*`.
  65.  
  66. ### 4. `public/js/platforms/max.js`
  67. Frontend module — mirrors `public/js/platforms/telegram.js`.
  68.  
  69. - Class `MaxPlatform` with `init()`, `destroy()`, `loadInitialData()`, `setupStateSubscriptions()`, `setupEventListeners()`
  70. - State keys: `platforms.max.accounts`, `platforms.max.selectedAccountId`, `platforms.max.chatId`
  71. - Actions: `max-test-account`, `max-delete-account` (event delegation)
  72. - Form submission for `#max-account-form` → `addAccount({ botToken })`
  73. - Renders account list in `#max-accounts-list`
  74. - Manages account selector `#max-account` in compose form
  75. - Shows/hides `#max-account-form-container`
  76. - Export singleton: `export const maxPlatform = new MaxPlatform()`
  77.  
  78. ---
  79.  
  80. ## Files to Modify
  81.  
  82. ### 5. `public/index.html`
  83. Four additions:
  84.  
  85. **a) Platform toggle checkbox** (after the Telegram toggle, ~line 67):
  86. ```html
  87. <label class="platform-toggle">
  88. <input type="checkbox" name="platform" value="max" id="platform-max">
  89. <i class="fas fa-comment-dots"></i>
  90. MAX
  91. </label>
  92. ```
  93.  
  94. **b) Compose content section** (after `#telegram-content-section`):
  95. ```html
  96. <section id="max-content-section" class="platform-content" style="display: none;">
  97. <header class="platform-content-header">
  98. <i class="fas fa-comment-dots"></i> MAX
  99. </header>
  100. <textarea id="max-content" name="max-content" rows="6"
  101. placeholder="Message for MAX..." maxlength="4000"></textarea>
  102. <div class="char-counter" id="max-char-counter">
  103. <span class="count">0</span> / 4000
  104. </div>
  105. </section>
  106. ```
  107.  
  108. **c) Compose options section** (after `#telegram-options`):
  109. ```html
  110. <div id="max-options" style="display: none;">
  111. <div class="form-group">
  112. <label for="max-account">MAX Bot *</label>
  113. <select id="max-account" name="maxAccount">
  114. <option value="">Select bot...</option>
  115. </select>
  116. <div class="error-message" id="max-account-error"></div>
  117. </div>
  118. <div class="form-group">
  119. <label for="max-chat-id">Chat ID *</label>
  120. <input type="text" id="max-chat-id" name="maxChatId"
  121. placeholder="Numeric chat/channel ID">
  122. <small class="field-hint">The numeric chat_id of the target chat or channel.</small>
  123. <div class="error-message" id="max-chat-id-error"></div>
  124. </div>
  125. </div>
  126. ```
  127.  
  128. **d) Settings page platform card** (after Telegram card, before Discord card):
  129. ```html
  130. <div class="platform-card">
  131. <header class="platform-header">
  132. <div class="platform-info">
  133. <i class="fas fa-comment-dots platform-icon"></i>
  134. <div>
  135. <h4>MAX Bots</h4>
  136. <p class="platform-description">Manage MAX bot accounts for channel/group posting</p>
  137. </div>
  138. </div>
  139. <button type="button" class="btn btn-primary btn-sm" id="add-max-account-btn">
  140. <i class="fas fa-plus"></i> Add Bot
  141. </button>
  142. </header>
  143. <div class="platform-body">
  144. <div id="max-accounts-list" class="accounts-list">
  145. <div class="loading-state"><i class="fas fa-spinner fa-spin"></i> Loading bots...</div>
  146. </div>
  147. <div id="max-account-form-container" style="display: none;">
  148. <h4>Add MAX Bot</h4>
  149. <form id="max-account-form" class="config-form">
  150. <div class="form-row">
  151. <div class="form-group">
  152. <label for="max-bot-token">Bot Token *</label>
  153. <input type="password" id="max-bot-token" name="botToken"
  154. placeholder="Your MAX bot token" required>
  155. <small class="field-hint">Bot token from the MAX Developer Portal</small>
  156. </div>
  157. </div>
  158. <aside class="config-instructions">
  159. <h5>Setup Instructions:</h5>
  160. <ol>
  161. <li>Go to <strong>business.max.ru</strong> and create a bot</li>
  162. <li>After moderation approval, get the token from <strong>Чат-боты → Интеграция → Получить токен</strong></li>
  163. <li>Add the bot to your channel/group as an Administrator</li>
  164. <li>Get the numeric Chat ID from the channel URL or bot updates</li>
  165. </ol>
  166. </aside>
  167. <div class="config-actions">
  168. <button type="submit" class="btn btn-primary">
  169. <i class="fas fa-save"></i> Add Bot
  170. </button>
  171. <button type="button" class="btn btn-secondary" id="cancel-max-account-btn">
  172. <i class="fas fa-times"></i> Cancel
  173. </button>
  174. </div>
  175. <div id="max-account-form-result" class="test-result"></div>
  176. </form>
  177. </div>
  178. </div>
  179. </div>
  180. ```
  181.  
  182. ### 6. `public/js/main.js`
  183. - Add import: `import { maxPlatform } from './platforms/max.js';`
  184. - Add `maxPlatform.init()` in `init()` (after `telegramPlatform.init()`)
  185. - Add `maxPlatform.destroy?.()` in cleanup
  186.  
  187. ### 7. `public/js/modules/compose.js`
  188. **a) Cache new DOM elements** in `setup()` (`this.elements` object):
  189. ```javascript
  190. maxContent: document.getElementById('max-content'),
  191. maxContentSection: document.getElementById('max-content-section'),
  192. maxCharCounter: document.getElementById('max-char-counter'),
  193. maxOptions: document.getElementById('max-options'),
  194. maxAccount: document.getElementById('max-account'),
  195. maxChatId: document.getElementById('max-chat-id'),
  196. ```
  197.  
  198. **b) Add event listeners** in `setupEventListeners()`:
  199. ```javascript
  200. if (this.elements.maxContent) {
  201. this.elements.maxContent.addEventListener('input', (e) => {
  202. state.setState('compose.platformContent.max', e.target.value);
  203. });
  204. }
  205. if (this.elements.maxAccount) {
  206. this.elements.maxAccount.addEventListener('change', (e) => {
  207. state.setState('platforms.max.selectedAccountId', e.target.value);
  208. });
  209. }
  210. if (this.elements.maxChatId) {
  211. this.elements.maxChatId.addEventListener('input', (e) => {
  212. state.setState('platforms.max.chatId', e.target.value);
  213. });
  214. }
  215. ```
  216.  
  217. **c) Show/hide UI** in `updatePlatformUI()` (after Telegram section):
  218. ```javascript
  219. if (this.elements.maxContentSection) {
  220. this.elements.maxContentSection.style.display = platforms.max ? 'block' : 'none';
  221. }
  222. if (this.elements.maxOptions) {
  223. this.elements.maxOptions.style.display = platforms.max ? 'block' : 'none';
  224. }
  225. if (platforms.max) {
  226. const maxAccounts = state.getState('platforms.max.accounts') || [];
  227. const selectedAccountId = state.getState('platforms.max.selectedAccountId');
  228. if ((!selectedAccountId || selectedAccountId === '') && maxAccounts.length > 0) {
  229. state.setState('platforms.max.selectedAccountId', maxAccounts[0].id);
  230. }
  231. }
  232. ```
  233.  
  234. **d) Add to `platformOrder`** for copy-to-all:
  235. ```javascript
  236. const platformOrder = ['x', 'bluesky', 'discord', 'telegram', 'max', 'e6ai'];
  237. ```
  238.  
  239. **e) Read state in `gatherFormData()`** (after telegram block):
  240. ```javascript
  241. const maxAccountId = state.getState('platforms.max.selectedAccountId');
  242. const maxChatId = state.getState('platforms.max.chatId') || '';
  243. ```
  244.  
  245. **f) Add to `buildPostPayload()`** (after telegram block):
  246. ```javascript
  247. if (formData.platforms.max) {
  248. platformData.max = {
  249. accountId: formData.maxAccountId,
  250. chatId: formData.maxChatId,
  251. content: formData.platformContent.max || ''
  252. };
  253. }
  254. ```
  255.  
  256. ### 8. `public/js/utils/errorMessages.js`
  257. Add `max` to `getPlatformName()` and `getPlatformHelp()`:
  258. ```javascript
  259. // getPlatformName
  260. max: 'MAX',
  261.  
  262. // getPlatformHelp
  263. max: {
  264. AUTH_ERROR: 'Check your MAX bot token. Ensure the bot is approved and added as Administrator to the channel.',
  265. NETWORK_ERROR: 'Cannot reach MAX servers. Check internet connection and proxy settings.',
  266. PLATFORM_ERROR: 'MAX API error. Verify the Chat ID is correct and the bot has posting permissions.',
  267. VALIDATION_ERROR: 'Check Chat ID (numeric). Text limit: 4000 chars.'
  268. }
  269. ```
  270.  
  271. ### 9. `public/js/utils/validation.js`
  272. Add `max` to `PLATFORM_LIMITS`:
  273. ```javascript
  274. max: 4000,
  275. ```
  276.  
  277. ---
  278.  
  279. ## Key Implementation Notes
  280.  
  281. 1. **No custom route file needed** — `createAccountRouter('max')` auto-registers `/api/max/accounts/*` routes via the platform auto-discovery system.
  282.  
  283. 2. **File upload flow for MAX** differs from Telegram's multipart approach:
  284. - Step 1: `POST /uploads?type=image` → `{ url, token }`
  285. - Step 2: PUT file binary to `url`
  286. - Step 3: Attach `{ type: "image", payload: { token } }` in message body
  287. - Implement retry (up to 3×, 2s interval) for `attachment.not.ready` errors
  288.  
  289. 3. **Media handling** — MAX supports multiple attachments in a single message (unlike Telegram's media groups), so all files go into a single `POST /messages` with an `attachments` array.
  290.  
  291. 4. **Icon** — MAX doesn't have a Font Awesome brand icon; use `fas fa-comment-dots` as a generic messenger icon.
  292.  
  293. 5. **chat_id** is numeric (integer) in the MAX API — validate and coerce to number in the handler.
  294.  
  295. ---
  296.  
  297. ## Verification Steps
  298.  
  299. 1. Start the server: `npm start`
  300. 2. Open Settings → add a MAX bot token → verify "Add Bot" calls `POST /api/max/accounts` and the bot appears in the list with its name
  301. 3. Click Test (plug icon) → verify `POST /api/max/accounts/{id}/test` returns bot info
  302. 4. Go to Compose → check MAX toggle → verify content section and options appear
  303. 5. Post a text-only message to a MAX chat → verify message arrives in MAX chat
  304. 6. Post with an image file → verify image arrives in MAX chat
  305. 7. Post with multiple files → verify all files arrive in a single MAX message
  306. 8. Delete the bot → verify it's removed from the list
  307. 9. Test error handling: bad token → verify `AUTH_ERROR` message; bad chat_id → verify `PLATFORM_ERROR`
Advertisement
Add Comment
Please, Sign In to add comment