godcrm/backend/routes/v3/telegram/channelOps.js
GOD CRM Release f89e074dd1
Some checks failed
CI / Lint / Typecheck / Test / Build (push) Has been cancelled
CI / PostgreSQL Integration Tests (push) Has been cancelled
GOD CRM — public scrubbed snapshot
Governed substrate for autonomous agents: scoped identity (passports),
audited actions, MCP workspace. Infra IPs and secrets redacted for public release.
2026-08-10 04:01:45 +03:00

123 lines
3.8 KiB
JavaScript

// backend/routes/v3/telegram/channelOps.js
// Channel posting API: post, stats, schedule
import { apiLogger, sendChannelPost, sendChannelPhoto, getChannelMemberCount, dbRun, isPostgres } from './shared.js';
/**
* Register channel operation routes on the given router.
*/
export default function registerChannelOps(router) {
/**
* POST /api/v3/telegram/channel/post
* Post content to the @godcrm Telegram channel.
* Body: { text, photo_url?, disable_preview?, reply_markup? }
* Returns: { success, message_id }
*/
router.post('/channel/post', async (req, res) => {
try {
const { text, photo_url, disable_preview, reply_markup } = req.body;
if (!text && !photo_url) {
return res.status(400).json({ success: false, error: 'Either text or photo_url is required' });
}
const options = {};
if (disable_preview) options.disable_web_page_preview = true;
if (reply_markup) options.reply_markup = reply_markup;
let result;
if (photo_url) {
result = await sendChannelPhoto(photo_url, text || '', options);
} else {
result = await sendChannelPost(text, options);
}
if (!result.success) {
return res.status(500).json({ success: false, error: result.error });
}
res.json({ success: true, message_id: result.messageId });
} catch (err) {
apiLogger.error({ err }, '[Telegram] Channel post error');
res.status(500).json({ success: false, error: err.message });
}
});
/**
* GET /api/v3/telegram/channel/stats
* Get channel statistics (member count, etc.)
*/
router.get('/channel/stats', async (req, res) => {
try {
const memberCount = await getChannelMemberCount();
res.json({
success: true,
channel: '@godcrm',
channel_url: 'https://t.me/godcrm',
members: memberCount.success ? memberCount.count : null,
});
} catch (err) {
res.status(500).json({ success: false, error: err.message });
}
});
/**
* POST /api/v3/telegram/channel/schedule
* Schedule a post for later publishing (stores in content queue).
* Body: { text, photo_url?, publish_at }
* For now: stores to DB, a cron job will pick up and publish.
*/
router.post('/channel/schedule', async (req, res) => {
try {
const { text, photo_url, publish_at } = req.body;
if (!text) {
return res.status(400).json({ success: false, error: 'text is required' });
}
if (!publish_at) {
return res.status(400).json({ success: false, error: 'publish_at is required (ISO 8601)' });
}
// Store scheduled post in content pipeline table (2603) or a dedicated scheduled posts table
const rowData = JSON.stringify({
title: text.substring(0, 100),
body: text,
photo_url: photo_url || null,
status: 'scheduled',
platform: 'telegram',
publish_at: publish_at,
content_type: 'post',
created_at: new Date().toISOString(),
});
let result;
if (isPostgres()) {
result = await dbRun(
`INSERT INTO table_rows (table_id, data, created_at, updated_at)
VALUES (2603, $1::jsonb, NOW(), NOW())
RETURNING id`,
[rowData]
);
} else {
result = await dbRun(
`INSERT INTO table_rows (table_id, data, created_at, updated_at)
VALUES (2603, ?, datetime('now'), datetime('now'))`,
[rowData]
);
}
const rowId = result?.rows?.[0]?.id || result?.lastInsertRowid;
res.json({
success: true,
row_id: rowId,
publish_at,
status: 'scheduled',
});
} catch (err) {
apiLogger.error({ err }, '[Telegram] Channel schedule error');
res.status(500).json({ success: false, error: err.message });
}
});
}