first commit
This commit is contained in:
@@ -0,0 +1,24 @@
|
||||
// auth.guard.ts
|
||||
import { CanActivate, ExecutionContext, Injectable } from '@nestjs/common';
|
||||
import { TelegrafExecutionContext } from 'nestjs-telegraf';
|
||||
|
||||
@Injectable()
|
||||
export class AuthGuard implements CanActivate {
|
||||
// Danh sách ID được phép (có thể để trong file .env)
|
||||
private readonly allowedIds =(process.env.TELEGRAM_ALLOW_CHAT_IDS || '').split(',');
|
||||
|
||||
canActivate(context: ExecutionContext): boolean {
|
||||
console.log('AuthGuard');
|
||||
const ctx = TelegrafExecutionContext.create(context);
|
||||
const { chat } = ctx.getContext();
|
||||
|
||||
// Kiểm tra nếu chat_id nằm trong danh sách cho phép
|
||||
const isAllowed = this.allowedIds.includes(chat.id);
|
||||
|
||||
if (!isAllowed) {
|
||||
console.warn(`Truy cập trái phép từ ID: ${chat.id}`);
|
||||
}
|
||||
|
||||
return isAllowed;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
export const WIZARD_WRITER_SCENE_ID = 'WIZARD_WRITER_SCENE_ID';
|
||||
export const WIZARD_COMMENT_SCENE_ID = 'WIZARD_COMMENT_SCENE_ID';
|
||||
export const WIZARD_COMMENT2_SCENE_ID = 'WIZARD_COMMENT2_SCENE_ID';
|
||||
export const WIZARD_QUOTE_SCENE_MAIN = 'WIZARD_QUOTE_SCENE_MAIN';
|
||||
@@ -0,0 +1,110 @@
|
||||
// src/modules/telegram/telegram.processor.ts
|
||||
import {OnWorkerEvent, Processor, WorkerHost} from '@nestjs/bullmq';
|
||||
import {Job} from 'bullmq';
|
||||
import {InjectBot} from 'nestjs-telegraf';
|
||||
import {Context, Telegraf} from 'telegraf';
|
||||
import {Injectable} from "@nestjs/common";
|
||||
import {PublishPageService} from "../social-api/publish.page.service";
|
||||
import {isEmpty, toNumber} from "lodash";
|
||||
|
||||
@Injectable()
|
||||
@Processor('content_writer_completed_queue') // Lắng nghe hàng đợi của AI-B
|
||||
export class TelegramContentWriterCompletedProcessor extends WorkerHost {
|
||||
constructor(
|
||||
@InjectBot() private readonly bot: Telegraf<Context>,
|
||||
private readonly publishPageService: PublishPageService
|
||||
) {
|
||||
super();
|
||||
}
|
||||
|
||||
// Đây là logic xử lý task (nếu cần xử lý thêm ở tầng telegram)
|
||||
async process(job: Job<any>): Promise<any> {
|
||||
// Task viết bài đã được AI-B xử lý ở FacebookProcessor
|
||||
// Ở đây chúng ta có thể thực hiện các logic hậu kỳ nếu muốn
|
||||
console.log('TelegramProcessor_facebook_content_writer_completed_process ==> begin');
|
||||
// console.log({job});
|
||||
|
||||
const adminChatId = process.env.TELEGRAM_ADMIN_ID || 0;
|
||||
|
||||
console.log('TelegramProcessor_facebook_content_writer_completed_process=>posting')
|
||||
//console.log(fbContent);
|
||||
if (job.name === 'generate_post_completed') {
|
||||
const {id, needConfirm, content, autoPublish, telegramChatId, xSubmitProvider} = job.data;
|
||||
console.log({id, needConfirm, autoPublish, xSubmitProvider})
|
||||
const X_USERS = process.env.TWITTER_USERNAMES!.split(',');
|
||||
console.log({X_USERS});
|
||||
//console.log({job})
|
||||
// if (autoPublish) {
|
||||
// // await this.publishPageService.publishTwitter(id);
|
||||
// // await this.publishPageService.publishToFacebook(id);
|
||||
// const postId = toNumber(id);
|
||||
// await this.bot.telegram.sendMessage(adminChatId, '🤖Đã viết xong tin auto:');
|
||||
//
|
||||
// try {
|
||||
// await Promise.allSettled([
|
||||
// this.publishPageService.publishToFacebook(postId).then(() => {
|
||||
// this.bot.telegram.sendMessage(adminChatId, `Đăng bài lên FB số ${postId} thành công`);
|
||||
// }).catch(err => {
|
||||
// this.bot.telegram.sendMessage(adminChatId, `PublishToFacebook error ${err.message}`);
|
||||
//
|
||||
// }),
|
||||
// this.publishPageService.publishTwitter(postId, xSubmitProvider).then((resp) => {
|
||||
// this.bot.telegram.sendMessage(adminChatId, `Đăng bài lên X số ${postId} thành công via ${xSubmitProvider}, ${resp?.url}`);
|
||||
// }).catch(err => {
|
||||
// this.bot.telegram.sendMessage(adminChatId, `PublishToX error ${err.message}`);
|
||||
// }),
|
||||
// ]
|
||||
// )
|
||||
// } catch (e) {
|
||||
// await this.bot.telegram.sendMessage(adminChatId, `❌ Lỗi đăng bài: ${e.message}`);
|
||||
// }
|
||||
// return;
|
||||
// }
|
||||
await this.bot.telegram.sendMessage(telegramChatId || adminChatId, '🤖Đã viết xong:');
|
||||
await this.bot.telegram.sendMessage(telegramChatId || adminChatId,
|
||||
`${content}\n\n`,
|
||||
{
|
||||
// parse_mode: 'Markdown',
|
||||
reply_markup: {
|
||||
inline_keyboard: [
|
||||
...X_USERS.map((xuser) => {
|
||||
return [{
|
||||
text: `↗️X ${xuser}`,
|
||||
callback_data: `publish-post_twitter_${id}_${xuser}`
|
||||
}];
|
||||
}),
|
||||
[
|
||||
// {text: "↗️X", callback_data: `publish-post_twitter_${id}`},
|
||||
{text: "↗️FB", callback_data: `publish-post_facebook_${id}`},
|
||||
],
|
||||
[
|
||||
// {text: "↗️All", callback_data: `publish-post_all_${id}`},
|
||||
{text: "🗑️ Hủy bài", callback_data: `delete-post_${id}`}]
|
||||
]
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
return {};
|
||||
|
||||
//return fbContent;
|
||||
// const postFbId= await this.publishPageService.publishToFacebook(id)
|
||||
// const twId= await this.publishPageService.publishTwitter(id)
|
||||
// return job;
|
||||
return {
|
||||
//id: id,
|
||||
// postFbId,
|
||||
// twId,
|
||||
// content: postContent,
|
||||
//image: imageSuggestion,
|
||||
status: 'posted'
|
||||
};
|
||||
}
|
||||
|
||||
@OnWorkerEvent('failed')
|
||||
async onFailed(job: Job<any>, error: Error) {
|
||||
const adminChatId = process.env.TELEGRAM_ADMIN_ID || 0;
|
||||
const telegramChatId = job.data.telegramChatId
|
||||
await this.bot.telegram.sendMessage(telegramChatId || adminChatId, `❌ **Lỗi AI-B:** Job #${job.id} thất bại. \nLý do: ${error.message}`);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,70 @@
|
||||
import {Module, OnModuleInit} from '@nestjs/common';
|
||||
import {TelegramContentWriterCompletedProcessor} from "./telegram.content.writer.completed.processor";
|
||||
import {TelegramUpdates} from "./telegram.updates";
|
||||
import {ManagerModule} from "../manager/manager.module";
|
||||
import {PgPostService} from "../../shared/pg.post.service";
|
||||
import {PublishPageService} from "../social-api/publish.page.service";
|
||||
import {FacebookApi} from "../social-api/facebook.api";
|
||||
import {SocialModule} from "../social-api/social.module";
|
||||
import {InjectBot} from "nestjs-telegraf";
|
||||
import {Context, Telegraf} from "telegraf";
|
||||
import {XReaderService} from "../x-reader/x-reader.service";
|
||||
import {TrendsService} from "../trends/trends.service";
|
||||
import {CollectorModule} from "../collector/collector.module";
|
||||
import {WriterWizard} from "./wizard/writer.wizard";
|
||||
import {CommentWizard} from "./wizard/comment.wizard";
|
||||
import {QuoteWizard} from "./wizard/quote.wizard";
|
||||
import {XImageUploadService} from "../x-uploader/x-image.upload.service";
|
||||
import {Comment2Wizard} from "./wizard/comment2.wizard";
|
||||
import {SqsPostService} from "../sqs-module/sqs.post.service";
|
||||
|
||||
|
||||
@Module({
|
||||
imports: [
|
||||
ManagerModule,
|
||||
SocialModule,
|
||||
CollectorModule,
|
||||
],
|
||||
providers: [
|
||||
TelegramUpdates,
|
||||
TelegramContentWriterCompletedProcessor,
|
||||
FacebookApi,
|
||||
PgPostService,
|
||||
PublishPageService,
|
||||
XReaderService,
|
||||
TrendsService,
|
||||
WriterWizard,
|
||||
CommentWizard,
|
||||
QuoteWizard,
|
||||
Comment2Wizard,
|
||||
XImageUploadService,
|
||||
SqsPostService
|
||||
],
|
||||
})
|
||||
export class TelegramModule implements OnModuleInit{
|
||||
constructor(@InjectBot() private readonly bot: Telegraf<Context>) {}
|
||||
|
||||
async onModuleInit() {
|
||||
try {
|
||||
await this.bot.telegram.setMyCommands( [
|
||||
{ command: 'start', description: 'Khởi động bot' },
|
||||
{ command: 'help', description: 'Trợ giúp' },
|
||||
{ command: 'trendstat', description: 'trend statistic' },
|
||||
{ command: 'analyzenews', description: 'Tìm trend' },
|
||||
{ command: 'ask', description: 'Hoi AI' },
|
||||
{ command: 'write', description: 'Version mới, dùng 2 AI, 1 viết và 1 reviewer' },
|
||||
{ command: 'write_', description: 'Version mới, dùng 2 AI, 1 viết và 1 reviewer' },
|
||||
{ command: 'writecheap', description: 'Version cũ, dùng deepseek' },
|
||||
{ command: 'xreader', description: 'Lấy nội dung băng api' },
|
||||
{ command: 'xreader_browser', description: 'Lấy nội dung bằng trình duyệt' },
|
||||
{ command: 'collectrss', description: 'Lấy nội dung' },
|
||||
{ command: 'comment', description: 'Viet reply X' },
|
||||
{ command: 'comen', description: '/com[en,ja,vi,ko] comment as text' },
|
||||
]);
|
||||
console.log('✅ Đã cập nhật Menu commands thành công');
|
||||
} catch (error) {
|
||||
console.error('❌ Lỗi khi cập nhật Menu:', error);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,813 @@
|
||||
import {Action, Command, Ctx, On, Start, Update} from 'nestjs-telegraf';
|
||||
import {Context, Scenes} from 'telegraf';
|
||||
import {HttpException, Injectable} from "@nestjs/common";
|
||||
import {ManagerService} from "../manager/manager.service";
|
||||
import {PublishPageService} from "../social-api/publish.page.service";
|
||||
import {_toNum} from "../../shared/helper";
|
||||
import {XReaderService} from "../x-reader/x-reader.service";
|
||||
import {TrendsService} from "../trends/trends.service";
|
||||
import {get, isEmpty} from 'lodash'
|
||||
import {
|
||||
WIZARD_COMMENT2_SCENE_ID,
|
||||
WIZARD_COMMENT_SCENE_ID,
|
||||
WIZARD_QUOTE_SCENE_MAIN,
|
||||
WIZARD_WRITER_SCENE_ID
|
||||
} from "./telegram.constants";
|
||||
import {XImageUploadService} from "../x-uploader/x-image.upload.service";
|
||||
import {TextUtil} from "../../common/utils/text.util";
|
||||
import {XStrategy} from "../social-api/x-router.service";
|
||||
import {XCacheService} from "../x-cache/x-cache.service";
|
||||
import {SqsPostService} from "../sqs-module/sqs.post.service";
|
||||
|
||||
@Injectable()
|
||||
@Update()
|
||||
export class TelegramUpdates {
|
||||
|
||||
constructor(
|
||||
private readonly managerService: ManagerService,
|
||||
private readonly publishPageService: PublishPageService,
|
||||
private readonly xReaderService: XReaderService,
|
||||
private readonly trendsService: TrendsService,
|
||||
private readonly xUpload: XImageUploadService,
|
||||
private readonly cacheService: XCacheService,
|
||||
private readonly sqsPostService: SqsPostService
|
||||
) {
|
||||
}
|
||||
|
||||
@Start()
|
||||
async onStart(ctx: Context) {
|
||||
|
||||
await ctx.reply('Hệ thống Automation đã sẵn sàng! Gửi /help để xem lệnh.');
|
||||
}
|
||||
|
||||
@Command('help')
|
||||
async onHelpCommand(ctx: Context) {
|
||||
await ctx.reply('Sau đây là các tính năng... ' +
|
||||
'\n' +
|
||||
'/writecheap_[en|ja|ko|vi] your_topic... (viết bài bằng AI deepseek)\n' +
|
||||
'/write_[vi|en|ja|ko] your_topic... (viết bài bằng AI chatgpt + deepseek)\n' +
|
||||
'/manual_publish_post postNum\n' +
|
||||
'/analyzenews ... (tim trend,...) \n' +
|
||||
'/trendstat \n' +
|
||||
'/ask ... (hỏi với ai deepseek,...) \n' +
|
||||
'/trend_stat ... (...) \n' +
|
||||
'/xreader ... (...) \n' +
|
||||
'/xreaderbrowser ... (...) \n' +
|
||||
'/collectrss ... (...) \n' +
|
||||
'/comment link X... (...) \n' +
|
||||
'/quote link X... (...) \n' +
|
||||
'');
|
||||
}
|
||||
|
||||
@Command(['download', 'dl'])
|
||||
async onDownloadVideo(ctx) {
|
||||
// @ts-ignore
|
||||
const {command, payload} = ctx;
|
||||
|
||||
if (!payload) {
|
||||
await ctx.reply(`vui lòng đưa topic, ví dụ: /${command} link tiktok/fb`);
|
||||
return;
|
||||
}
|
||||
// Regex tổng hợp các loại link
|
||||
const tiktokRegex = /https?:\/\/(?:www\.|vm\.|vt\.|m\.)?tiktok\.com\/[^\s]+/gi;
|
||||
const youtubeRegex = /https?:\/\/(?:www\.)?(?:youtube\.com\/(?:watch\?v=|shorts\/)|youtu\.be\/)[^\s]+/gi;
|
||||
const facebookRegex = /https?:\/\/(?:www\.|fb\.)?(?:facebook\.com\/reels\/|watch\/)[^\s]+/gi;
|
||||
const mp4Regex = /https?:\/\/[^\s^"]+\.mp4(?:\?[^\s^"]*)?/gi;
|
||||
|
||||
// Cách 1: Lấy tất cả vào một mảng
|
||||
const allRegex = new RegExp(`${tiktokRegex.source}|${youtubeRegex.source}|${facebookRegex.source}|${mp4Regex.source}`, 'gi');
|
||||
const allLinks = payload.match(allRegex) || [];
|
||||
console.log({allLinks});
|
||||
|
||||
console.log("Tất cả link tìm thấy:", allLinks);
|
||||
|
||||
if (allLinks.length === 0) {
|
||||
await ctx.reply(`Khong tim thay link download`);
|
||||
return;
|
||||
}
|
||||
if (allLinks.length === 1) {
|
||||
await this.managerService.handleDownloadVideo(allLinks[0], ctx.chat.id);
|
||||
} else {
|
||||
await this.managerService.handleDownloadVideoMulti(allLinks, ctx.chat.id);
|
||||
}
|
||||
await ctx.reply(`vui lòng chờ download ....`);
|
||||
}
|
||||
|
||||
@Command('downloadmp4url')
|
||||
async onDownloadMp4Url(ctx) {
|
||||
// @ts-ignore
|
||||
const {command, payload} = ctx;
|
||||
|
||||
if (!payload) {
|
||||
await ctx.reply(`vui lòng đưa topic, ví dụ: /${command} link mp4`);
|
||||
return;
|
||||
}
|
||||
await ctx.reply(`vui lòng chờ download....`);
|
||||
await this.managerService.handleDownloadMp4Url(payload, 'x', ctx.chat.id);
|
||||
}
|
||||
|
||||
@Command('comment')
|
||||
async onWizardCommand(@Ctx() ctx: Scenes.SceneContext): Promise<void> {
|
||||
await ctx.scene.enter(WIZARD_COMMENT_SCENE_ID);
|
||||
}
|
||||
|
||||
@Command([
|
||||
'comvi',
|
||||
'comen',
|
||||
'comja',
|
||||
'comko',
|
||||
'comcn',
|
||||
])
|
||||
async onCommentAsTextCommand(@Ctx() ctx: Scenes.SceneContext): Promise<void> {
|
||||
|
||||
let language = 'en';
|
||||
// @ts-ignore
|
||||
let {command, payload} = ctx;
|
||||
if (['comvi', 'comvn', 'com_vi'].includes(command)) {
|
||||
language = 'vi';
|
||||
}
|
||||
if (['comko', 'comkr', 'com_ko'].includes(command)) {
|
||||
language = 'ko';
|
||||
}
|
||||
if (['comja', 'comjp', 'com_ja'].includes(command)) {
|
||||
language = 'ja';
|
||||
}
|
||||
if (['comcn'].includes(command)) {
|
||||
language = 'cn';
|
||||
}
|
||||
|
||||
if (!payload) {
|
||||
await ctx.reply(`vui lòng đưa topic, ví dụ: /${command} bitcoin approach $100000`);
|
||||
return;
|
||||
}
|
||||
const chatId = ctx.chat?.id;
|
||||
payload = payload.trim(); // Gets "my_payload"
|
||||
console.log({payload});
|
||||
let tweetId = undefined;
|
||||
let tweetUrl = undefined;
|
||||
let _linkX = payload.replace('twitter.com', 'x.com').split('?')[0];
|
||||
const match = _linkX.match(/status\/(\d+)/);
|
||||
if (match) {
|
||||
//nêu match => get content x
|
||||
const xpost = await this.xReaderService.readXPost(_linkX);
|
||||
console.log('==> content text:' + xpost.text);
|
||||
payload = xpost.text;
|
||||
tweetId = xpost.tweetId;
|
||||
tweetUrl = _linkX;
|
||||
} else {
|
||||
|
||||
}
|
||||
await ctx.scene.enter(WIZARD_COMMENT2_SCENE_ID, {
|
||||
language,
|
||||
userTopic: payload,
|
||||
tweetId,
|
||||
tweetUrl,
|
||||
chatId
|
||||
});
|
||||
}
|
||||
|
||||
@Command([
|
||||
'quote_vi',
|
||||
'quotevi',
|
||||
'quotevn',
|
||||
'quote_en',
|
||||
'quoteen',
|
||||
'quote_ja',
|
||||
'quoteja',
|
||||
'quote_jp',
|
||||
'quotejp',
|
||||
'quote_ko',
|
||||
'quoteko',
|
||||
'quotecn',
|
||||
])
|
||||
async onWizardQuote(@Ctx() ctx: Scenes.SceneContext): Promise<void> {
|
||||
// @ts-ignore
|
||||
let {command, payload} = ctx;
|
||||
if (['quote_jp', 'quotejp', 'quoteja'].includes(command)) {
|
||||
command = 'quote_ja';
|
||||
}
|
||||
if (['quote_vn', 'quotevi', 'quotevn'].includes(command)) {
|
||||
command = 'quote_vi';
|
||||
}
|
||||
if (['quoteen'].includes(command)) {
|
||||
command = 'quote_en';
|
||||
}
|
||||
if (['quoteko'].includes(command)) {
|
||||
command = 'quote_ko';
|
||||
}
|
||||
if (['quotecn'].includes(command)) {
|
||||
command = 'quote_cn';
|
||||
}
|
||||
if (!payload) {
|
||||
await ctx.reply(`vui lòng đưa url, ví dụ: /${command} link_x_post ?`);
|
||||
return;
|
||||
}
|
||||
const preferLanguage = command.split('_')[1];
|
||||
await ctx.scene.enter(WIZARD_QUOTE_SCENE_MAIN, {
|
||||
language: preferLanguage,
|
||||
linkUrl: payload,
|
||||
quoteText: '',
|
||||
quoteAs: 'quotelink',
|
||||
});
|
||||
}
|
||||
|
||||
@Command([
|
||||
'quoteentext',
|
||||
'quotevitext',
|
||||
'quotejatext',
|
||||
'quotekotext',
|
||||
'quotecntext',
|
||||
])
|
||||
async onQuoteAsTextCommand(@Ctx() ctx: Scenes.SceneContext): Promise<void> {
|
||||
// @ts-ignore
|
||||
let {command, payload} = ctx;
|
||||
let language = 'en';
|
||||
if (['quotevitext'].includes(command)) {
|
||||
language = 'vi';
|
||||
}
|
||||
|
||||
if (['quotejatext'].includes(command)) {
|
||||
language = 'ja';
|
||||
}
|
||||
if (['quotecntext'].includes(command)) {
|
||||
language = 'cn';
|
||||
}
|
||||
|
||||
if (['quotekotext'].includes(command)) {
|
||||
language = 'ko';
|
||||
}
|
||||
|
||||
if (!payload) {
|
||||
await ctx.reply(`ví dụ: /${command} nội dung quote ?`);
|
||||
return;
|
||||
}
|
||||
await ctx.scene.enter(WIZARD_QUOTE_SCENE_MAIN, {
|
||||
language: language,
|
||||
quoteText: payload,
|
||||
quoteAs: 'quotetext',
|
||||
});
|
||||
}
|
||||
|
||||
@Command('collectrss')
|
||||
async onCollectRssCommand(ctx: Context) {
|
||||
const result = await this.trendsService.collectAndStore('rss');
|
||||
|
||||
ctx.reply('Collection completed');
|
||||
await ctx.reply(JSON.stringify(result.stats));
|
||||
}
|
||||
|
||||
@Command(['writecheap_vi', 'writecheap_en', 'writecheap_ja', 'writecheap_ko'])
|
||||
async onWriteCheapCommand(@Ctx() ctx: Context) {
|
||||
// @ts-ignore
|
||||
const {command, payload} = ctx;
|
||||
const preferLanguage = command.split('_')[1];
|
||||
|
||||
if (!payload) {
|
||||
await ctx.reply(`vui lòng đưa topic, ví dụ: /${command} bitcoin approach $100000`);
|
||||
return;
|
||||
}
|
||||
await this.managerService.manualTrigger(payload, '', preferLanguage);
|
||||
|
||||
await ctx.reply(`Đang tìm kiếm tin tức về: ${payload} với ngôn ngữ ${preferLanguage}...`);
|
||||
}
|
||||
|
||||
@Command([
|
||||
'write_vn',
|
||||
'write_vi',
|
||||
'writevi',
|
||||
'write_en',
|
||||
'writeen',
|
||||
'write_jp',
|
||||
'write_ja',
|
||||
'writeja',
|
||||
'write_kr',
|
||||
'write_ko',
|
||||
'writeko',
|
||||
'writecn',
|
||||
'write_cn',
|
||||
])
|
||||
async onWriteSmartWithAIReviewerCommand(@Ctx() ctx: Scenes.SceneContext) {
|
||||
// @ts-ignore
|
||||
let {command, payload} = ctx;
|
||||
if (['write_jp', 'writejp', 'writeja'].includes(command)) {
|
||||
command = 'write_ja';
|
||||
}
|
||||
if (['write_kr', 'writekr', 'writeko'].includes(command)) {
|
||||
command = 'write_ko';
|
||||
}
|
||||
if (['write_vn', 'writevn', 'writevi'].includes(command)) {
|
||||
command = 'write_vi';
|
||||
}
|
||||
if (['writeen'].includes(command)) {
|
||||
command = 'write_en';
|
||||
}
|
||||
if (['writecn'].includes(command)) {
|
||||
command = 'write_cn';
|
||||
}
|
||||
const preferLanguage = command.split('_')[1];
|
||||
|
||||
if (!payload) {
|
||||
await ctx.reply(`vui lòng đưa topic, ví dụ: /${command} bitcoin approach $100000`);
|
||||
return;
|
||||
}
|
||||
const chatId = ctx.chat?.id;
|
||||
if (payload.length < 200) {
|
||||
//check has link X
|
||||
const detectSendLinkX = TextUtil.detectLinkX(payload);
|
||||
if (detectSendLinkX.hasLinkX) {
|
||||
const xpost = await this.xReaderService.readXPost(detectSendLinkX.url);
|
||||
payload = xpost.text;
|
||||
}
|
||||
}
|
||||
|
||||
await ctx.scene.enter(WIZARD_WRITER_SCENE_ID, {
|
||||
language: preferLanguage,
|
||||
userTopic: payload,
|
||||
chatId,
|
||||
});
|
||||
// await this.managerService.manualTriggerWrite2(payload, '', preferLanguage);
|
||||
|
||||
// await ctx.reply(`Đang tìm kiếm tin tức về: ${payload} với ngôn ngữ ${preferLanguage}...`);
|
||||
}
|
||||
|
||||
@Command('manual_publish_post')
|
||||
async manual_publish_post(@Ctx() ctx: Context) {
|
||||
// @ts-ignore
|
||||
const {command, payload} = ctx;
|
||||
if (!payload) {
|
||||
await ctx.reply('thiếu thông tin post num');
|
||||
return;
|
||||
}
|
||||
const postNo = 1 * payload;
|
||||
await ctx.reply(`Đang đẩy bài ${payload} lên Facebook, Twitter`);
|
||||
|
||||
await ctx.reply(
|
||||
`🤖 **Vui lòng chọn kênh**`,
|
||||
{
|
||||
parse_mode: 'Markdown',
|
||||
reply_markup: {
|
||||
inline_keyboard: [
|
||||
[
|
||||
{text: "🐦 Post X", callback_data: `publish-post_twitter_${postNo}`},
|
||||
{text: "🚀 Post FB", callback_data: `publish-post_facebook_${postNo}`},
|
||||
],
|
||||
[
|
||||
{text: "🐦 Post X via browser", callback_data: `publish-post_twitterbrowser_${postNo}`},
|
||||
{text: "🚀 Post all", callback_data: `publish-post_all_${postNo}`},
|
||||
],
|
||||
[{text: "🗑️ Hủy bài", callback_data: `delete-post_${postNo}`}]
|
||||
]
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
// await this.publishPageService.publishToFacebook(postNo).then(() => {
|
||||
// ctx.reply(`Đăng bài lên FB số ${postNo} thành công`);
|
||||
// }).catch(err => {
|
||||
// ctx.reply(`PublishToFacebook error ${err.message}`);
|
||||
// });
|
||||
// await this.publishPageService.publishTwitter(postNo).then(() => {
|
||||
// ctx.reply(`Đăng bài lên X số ${postNo} thành công`);
|
||||
// }).catch(err => {
|
||||
// ctx.reply(`PublishTwitter error ${err.message}`);
|
||||
// });
|
||||
|
||||
}
|
||||
|
||||
@Command('analyzenews')
|
||||
async onAnalyzeNews(ctx: Context) {
|
||||
// @ts-ignore
|
||||
const {command, payload} = ctx;
|
||||
|
||||
if (!payload) {
|
||||
await ctx.reply(`vui lòng đưa topic, ví dụ: /${command} Hot news today in japan ?`);
|
||||
return;
|
||||
}
|
||||
|
||||
await this.managerService.handleAnalyzeNewsTrend(payload);
|
||||
await ctx.reply(`vui lòng đưa chờ phân tích ....`);
|
||||
}
|
||||
|
||||
@Command('ask')
|
||||
async onAsk(ctx: Context) {
|
||||
// @ts-ignore
|
||||
const {command, payload} = ctx;
|
||||
|
||||
if (!payload) {
|
||||
await ctx.reply(`vui lòng đưa topic, ví dụ: /${command} Hot news today in japan ?`);
|
||||
return;
|
||||
}
|
||||
console.log(ctx.chat);
|
||||
await this.managerService.handleAskQues(payload, ctx.chat?.id);
|
||||
await ctx.reply(`vui lòng đưa chờ phân tích ....`);
|
||||
}
|
||||
|
||||
@Command('askx')
|
||||
async onAskXContext(ctx: Context) {
|
||||
// @ts-ignore
|
||||
const {command, payload} = ctx;
|
||||
|
||||
if (!payload) {
|
||||
await ctx.reply(`vui lòng đưa topic, ví dụ: /${command} Hot news today in japan ?`);
|
||||
return;
|
||||
}
|
||||
console.log(ctx.chat);
|
||||
await this.managerService.handleAskXContext(payload, ctx.chat?.id);
|
||||
await ctx.reply(`vui lòng đưa chờ phân tích ....`);
|
||||
}
|
||||
|
||||
@Command(['xreader', 'xreader_browser'])
|
||||
async onXReader(ctx: Context) {
|
||||
// @ts-ignore
|
||||
let {command, payload} = ctx;
|
||||
if (!payload) {
|
||||
await ctx.reply(`vui lòng đưa url, ví dụ: /${command} link_x_post ?`);
|
||||
return;
|
||||
}
|
||||
await ctx.reply(`vui lòng chờ phân tích ....`);
|
||||
|
||||
const content = await this.xReaderService.readXPost(
|
||||
payload,
|
||||
command === 'xreader_browser' ? 'browser' : 'any'
|
||||
).catch((err) => {
|
||||
ctx.reply(err.message);
|
||||
return err;
|
||||
});
|
||||
let textMessage = ``;
|
||||
try {
|
||||
textMessage += `🤖 crawler by: ${content.via} \n\n`;
|
||||
if (content) {
|
||||
textMessage += `====== CONTENT ===== \n\n`;
|
||||
textMessage += `text: ${content.text} \n----------------------- \n`;
|
||||
if (!isEmpty(content.images)) {
|
||||
textMessage += `images: ${content.images.join(' , ')} \n----------------------- \n`;
|
||||
}
|
||||
if (!isEmpty(content.videos)) {
|
||||
textMessage += `videos: ${content.videos.join(' , ')} \n`;
|
||||
}
|
||||
|
||||
if (!isEmpty(content.quoted)) {
|
||||
textMessage += `====== QUOTE ===== \n`;
|
||||
textMessage += `quoted text: ${get(content, 'quoted.text')} \n----------------------- \n`;
|
||||
if (!isEmpty(content?.quoted?.images)) {
|
||||
textMessage += `quoted images: ${get(content, 'quoted.images', []).join(' , ')} \n----------------------- \n`;
|
||||
}
|
||||
if (!isEmpty(content?.quoted?.videos)) {
|
||||
textMessage += `quoted videos: ${get(content, 'quoted.videos', []).join(' , ')} \n----------------------- \n`;
|
||||
}
|
||||
}
|
||||
}
|
||||
await ctx.reply(textMessage, {parse_mode: 'HTML'});
|
||||
} catch (err) {
|
||||
console.log(err);
|
||||
ctx.reply(err.message);
|
||||
}
|
||||
}
|
||||
|
||||
@Action(/publish-post_(.+)/)
|
||||
async onPublishFB(ctx: Context) {
|
||||
const telegramChatId = ctx.chat?.id;
|
||||
const callbackData = (ctx.callbackQuery as any).data;
|
||||
const social = callbackData.split('_')[1];
|
||||
const postId = _toNum(callbackData.split('_')[2]);
|
||||
const xUsername = callbackData.split('_')[3];
|
||||
|
||||
await ctx.answerCbQuery(`Đang đẩy bài lên Fb,X ${xUsername}...`);
|
||||
|
||||
const promiseSettedFunc = [];
|
||||
let allowTw = 0;
|
||||
let allowFb = 0;
|
||||
let twStrageryPost = XStrategy.API_ONLY;
|
||||
let publishTo: any = [];
|
||||
switch (social) {
|
||||
case 'all':
|
||||
allowTw = 1;
|
||||
allowFb = 1;
|
||||
publishTo = ['x', 'fb'];
|
||||
break;
|
||||
case 'twitter':
|
||||
allowTw = 1;
|
||||
publishTo = ['x'];
|
||||
twStrageryPost=XStrategy.BROWSER_FIRST
|
||||
break;
|
||||
case 'twitterbrowser':
|
||||
allowTw = 1;
|
||||
publishTo = ['x'];
|
||||
twStrageryPost = XStrategy.BROWSER_ONLY;
|
||||
break;
|
||||
case 'facebook':
|
||||
allowFb = 1;
|
||||
publishTo = ['fb'];
|
||||
break;
|
||||
}
|
||||
|
||||
try {
|
||||
// @ts-ignore
|
||||
const messageText = ctx.callbackQuery.message.text;
|
||||
|
||||
await this.sqsPostService.sendMessage(xUsername,
|
||||
{
|
||||
name: 'generate_post_completed',
|
||||
type: 'X_POSTER_TWEET',
|
||||
needConfirm: 1,
|
||||
content: messageText,
|
||||
autoPublish: 1,
|
||||
telegramChatId,
|
||||
xUsername,
|
||||
publishTo,
|
||||
xSubmitProvider: XStrategy.BROWSER_FIRST //cứ 3post api, có 1 post browser
|
||||
}
|
||||
)
|
||||
// const r = await this.publishPageService.relyX(messageText, tweetId)
|
||||
//@ts-ignore
|
||||
await ctx.editMessageText(`✅ ** Đã gửi tweet sang queue ${xUsername} ID bài viết: ${postId}`);
|
||||
|
||||
|
||||
// await Promise.allSettled([
|
||||
// allowFb && this.publishPageService.publishToFacebook(postId).then(() => {
|
||||
// ctx.reply(`Đăng bài lên FB số ${postId} thành công`);
|
||||
// }).catch(err => {
|
||||
// ctx.reply(`PublishToFacebook error ${err.message}`);
|
||||
// }),
|
||||
// allowTw && this.publishPageService.publishTwitter(postId, twStrageryPost).then((resp) => {
|
||||
// ctx.reply(`Đăng bài lên X số ${postId} thành công, ${resp?.url}`);
|
||||
// }).catch(err => {
|
||||
// ctx.reply(`PublishTwitter error ${err.message}`);
|
||||
// }),
|
||||
// ]
|
||||
// )
|
||||
|
||||
// await ctx.editMessageText(`✅ **ĐÃ ĐĂNG THÀNH CÔNG!**\nID bài viết: ${postId}`);
|
||||
} catch (e) {
|
||||
await ctx.reply(`❌ Lỗi gửi bài: ${e.message}`);
|
||||
}
|
||||
}
|
||||
|
||||
@Action(/delete-post_(.+)/)
|
||||
async onDelete(ctx: Context) {
|
||||
const callbackData = (ctx.callbackQuery as any).data;
|
||||
const postId = _toNum(callbackData.split('_')[1]);
|
||||
// console.log(ctx.match);
|
||||
console.log('delete_post_id=', postId);
|
||||
|
||||
await this.publishPageService.rejectedPost(postId);
|
||||
await ctx.answerCbQuery('Đã hủy bài viết.');
|
||||
await ctx.editMessageText('🗑️ Bài viết đã được loại bỏ khỏi hàng đợi.');
|
||||
}
|
||||
|
||||
// @ts-ignore
|
||||
@Command(['trendstat', 'trend_stat'])
|
||||
async onTrendStatCommand(ctx: Context) {
|
||||
await ctx.reply(`Đang query..`);
|
||||
|
||||
const {topTrends, byCategory} = await this.trendsService.getStats();
|
||||
|
||||
let message = ``;
|
||||
topTrends.forEach(trend => {
|
||||
message += `\n${trend.title} - ${trend.category} - ${trend.score}\n`;
|
||||
});
|
||||
await ctx.reply(message, {
|
||||
parse_mode: 'HTML'
|
||||
});
|
||||
|
||||
message = '';
|
||||
console.log({byCategory});
|
||||
byCategory.forEach(trend => {
|
||||
message += `\n${trend.category} - ${trend._count._all} - ${trend._avg.score} \n`;
|
||||
});
|
||||
await ctx.reply(message, {
|
||||
parse_mode: 'HTML'
|
||||
});
|
||||
ctx.reply('Done')
|
||||
}
|
||||
|
||||
@Action(/publish-reply-twitter1_(.+)/)
|
||||
async onActionSubmitReplyX1(ctx: Context) {
|
||||
const callbackData = (ctx.callbackQuery as any).data;
|
||||
// @ts-ignore
|
||||
const messageText = ctx.callbackQuery.message.text;
|
||||
|
||||
const callbackDataArr = callbackData.split('_');
|
||||
const tweetId = callbackDataArr[1];
|
||||
const xUsername = callbackDataArr[2];
|
||||
|
||||
await ctx.answerCbQuery('Đang đẩy reply lên Twitter...');
|
||||
|
||||
console.log(messageText);
|
||||
console.log(`publish-reply-twitter1_ ${tweetId} ${xUsername}`);
|
||||
const telegramChatId = ctx.chat?.id;
|
||||
try {
|
||||
const tweetUrl = await this.cacheService.getCacheTweetUrlById(tweetId);
|
||||
if (isEmpty(tweetUrl)) {
|
||||
throw new HttpException(`Không tìm thấy tweet url từ Id : ${tweetId}`, 500);
|
||||
}
|
||||
await this.sqsPostService.sendMessage(xUsername,
|
||||
{
|
||||
tweetId: tweetId,
|
||||
tweetUrl,
|
||||
// name: 'generate_comment_twitter_completed',
|
||||
type: 'X_POSTER_REPLY',
|
||||
needConfirm: 1,
|
||||
content: messageText,
|
||||
autoPublish: 1,
|
||||
telegramChatId,
|
||||
xUsername,
|
||||
xSubmitProvider: XStrategy.BROWSER_ONLY //cứ 3post api, có 1 post browser
|
||||
}
|
||||
)
|
||||
// const r = await this.publishPageService.relyX(messageText, tweetId)
|
||||
//@ts-ignore
|
||||
if (r.success) {
|
||||
await ctx.editMessageText(`✅ ** Reply success !**\n ID bài viết: ${tweetId}`);
|
||||
await ctx.reply(`✅ ** Reply success !`);
|
||||
} else {
|
||||
//@ts-ignore
|
||||
await ctx.reply(`❌ Lỗi reply: ${r.error} `);
|
||||
}
|
||||
} catch (err) {
|
||||
console.log(err);
|
||||
const detail = get(err, 'data.detail', '')
|
||||
await ctx.reply(`❌ Lỗi reply: ${err.message} `);
|
||||
await ctx.reply(`=> ${detail}`);
|
||||
}
|
||||
}
|
||||
|
||||
@Action(/publish-reply-twitter_(.+)/)
|
||||
async onActionSubmitReplyX(ctx: Context) {
|
||||
const callbackData = (ctx.callbackQuery as any).data;
|
||||
// @ts-ignore
|
||||
const messageText = ctx.callbackQuery.message.text;
|
||||
|
||||
const callbackDataArr = callbackData.split('_');
|
||||
const tweetId = callbackDataArr[1];
|
||||
const xUsername = callbackDataArr[2];
|
||||
|
||||
await ctx.answerCbQuery('Đang đẩy reply lên Twitter...');
|
||||
console.log(`Đang đẩy reply lên Twitter 0...`);
|
||||
|
||||
console.log(messageText);
|
||||
const telegramChatId = ctx.chat?.id;
|
||||
try {
|
||||
const tweetUrl = await this.cacheService.getCacheTweetUrlById(tweetId);
|
||||
if (isEmpty(tweetUrl)) {
|
||||
console.error(`Không tìm thấy tweet url từ Id : ${tweetId}`);
|
||||
throw new HttpException(`Không tìm thấy tweet url từ Id : ${tweetId}`, 500);
|
||||
}
|
||||
await this.sqsPostService.sendMessage(xUsername,
|
||||
{
|
||||
tweetId: tweetId,
|
||||
tweetUrl,
|
||||
// name: 'generate_comment_twitter_completed',
|
||||
type: 'X_POSTER_REPLY',
|
||||
needConfirm: 1,
|
||||
content: messageText,
|
||||
autoPublish: 1,
|
||||
telegramChatId,
|
||||
xUsername,
|
||||
xSubmitProvider: XStrategy.BROWSER_ONLY //cứ 3post api, có 1 post browser
|
||||
}
|
||||
)
|
||||
// const r = await this.publishPageService.relyX(messageText, tweetId)
|
||||
//@ts-ignore
|
||||
await ctx.editMessageText(`✅ ** Đã gửi tin sang queue ${xUsername} ID bài viết: ${tweetId}`);
|
||||
// await ctx.reply(`✅ Đã gửi tin sang queue ${xUsername}!, ID bài viết: ${tweetId}`);
|
||||
// else {
|
||||
// //@ts-ignore
|
||||
// await ctx.reply(`❌ Lỗi reply: ${r.error} `);
|
||||
// }
|
||||
} catch (err) {
|
||||
console.log(err);
|
||||
const detail = get(err, 'data.detail', '')
|
||||
await ctx.reply(`❌ Lỗi reply: ${err.message} `);
|
||||
await ctx.reply(`=> ${detail}`);
|
||||
}
|
||||
}
|
||||
|
||||
@Action(/publish-quote-twitter_(.+)/)
|
||||
async onActionSubmitQuoteX(ctx: Context) {
|
||||
const callbackData = (ctx.callbackQuery as any).data;
|
||||
// @ts-ignore
|
||||
const messageText = ctx.callbackQuery.message.text;
|
||||
|
||||
// const tweetId = callbackData.split('_')[1];
|
||||
const callbackDataArr = callbackData.split('_');
|
||||
const tweetId = callbackDataArr[1];
|
||||
const xUsername = callbackDataArr[2];
|
||||
|
||||
await ctx.answerCbQuery('Đang đẩy quote lên Twitter...');
|
||||
console.log(`Đang đẩy quote lên Twitter...`);
|
||||
|
||||
console.log(messageText);
|
||||
console.log(tweetId);
|
||||
console.log({xUsername, tweetId});
|
||||
|
||||
const telegramChatId = ctx.chat?.id;
|
||||
|
||||
try {
|
||||
const tweetUrl = await this.cacheService.getCacheTweetUrlById(tweetId);
|
||||
if (isEmpty(tweetUrl)) {
|
||||
console.error(`Không tìm thấy tweet url từ Id : ${tweetId}`);
|
||||
|
||||
throw new HttpException(`Không tìm thấy tweet url từ Id : ${tweetId}`, 500);
|
||||
}
|
||||
|
||||
await this.sqsPostService.sendMessage(xUsername,
|
||||
{
|
||||
tweetId: tweetId,
|
||||
tweetUrl,
|
||||
// name: 'generate_comment_twitter_completed',
|
||||
type: 'X_POSTER_QUOTE',
|
||||
needConfirm: 1,
|
||||
content: messageText,
|
||||
autoPublish: 1,
|
||||
telegramChatId,
|
||||
xUsername,
|
||||
xSubmitProvider: XStrategy.BROWSER_ONLY //cứ 3post api, có 1 post browser
|
||||
}
|
||||
)
|
||||
await ctx.reply(`✅ Gửi tin sang queue.`);
|
||||
//await this.publishPageService.quoteX(messageText, tweetId)
|
||||
//const r = await this.publishPageService.quoteX(messageText, tweetId)
|
||||
// @ts-ignore
|
||||
// if (r.success) {
|
||||
// await ctx.editMessageText(`✅ ** Quote success !**`);
|
||||
// await ctx.reply(`✅ ** Quote success !**`);
|
||||
// } else {
|
||||
// await ctx.reply(`❌ Lỗi quote`);
|
||||
// // @ts-ignore
|
||||
// await ctx.reply(r.error);
|
||||
// }
|
||||
} catch (err) {
|
||||
console.log(err);
|
||||
const detail = get(err, 'data.detail', '')
|
||||
await ctx.reply(`❌ Lỗi quote: ${err.message} `);
|
||||
await ctx.reply(`=> ${detail}`);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@Action([
|
||||
/delete-reply_(.+)/,
|
||||
/delete-quote_(.+)/
|
||||
])
|
||||
async onDeleteReplyX(ctx: Context) {
|
||||
const callbackData = (ctx.callbackQuery as any).data;
|
||||
const postId = _toNum(callbackData.split('_')[1]);
|
||||
// console.log(ctx.match);
|
||||
console.log('delete_post_id=', postId);
|
||||
|
||||
// await this.publishPageService.rejectedPost(postId);
|
||||
await ctx.answerCbQuery('Đã hủy bài viết.');
|
||||
await ctx.editMessageText('🗑️ Bài viết đã được loại bỏ khỏi hàng đợi.');
|
||||
}
|
||||
|
||||
@On('photo')
|
||||
async handlePhoto(@Ctx() ctx: Context) {
|
||||
try {
|
||||
const photos = (ctx.message as any).photo;
|
||||
const largest = photos[photos.length - 1];
|
||||
const fileId = largest.file_id;
|
||||
|
||||
// Lấy link để tải ảnh về (nếu cần)
|
||||
const fileUrl = await ctx.telegram.getFileLink(fileId);
|
||||
|
||||
await ctx.reply(`Đã nhận được ảnh! Bạn có thể xem tại: ${fileUrl}`);
|
||||
|
||||
// // 1. get file path
|
||||
// const res = await axios.get(
|
||||
// `https://api.telegram.org/bot${process.env.TELEGRAM_BOT_TOKEN}/getFile`,
|
||||
// {
|
||||
// params: {file_id: fileId},
|
||||
// }
|
||||
// );
|
||||
//
|
||||
// const filePath = res.data.result.file_path;
|
||||
//
|
||||
// // 2. build download url
|
||||
// const fileUrl = `https://api.telegram.org/file/bot${process.env.TELEGRAM_BOT_TOKEN}/${filePath}`;
|
||||
//
|
||||
// // 3. download buffer
|
||||
// const img = await axios.get(fileUrl, {
|
||||
// responseType: 'arraybuffer',
|
||||
// });
|
||||
//
|
||||
// const buffer = Buffer.from(img.data);
|
||||
|
||||
// 4. upload to X
|
||||
const mediaId = await this.xUpload.uploadImageFromUrl(fileUrl.toString());
|
||||
|
||||
|
||||
await ctx.reply(`✅ Uploaded mediaId: ${mediaId}`);
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
await ctx.reply('❌ Upload failed');
|
||||
}
|
||||
}
|
||||
|
||||
@Command('chatid')
|
||||
async onGetChatId(ctx: Context) {
|
||||
// @ts-ignore
|
||||
ctx.reply(ctx.chat.id)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,100 @@
|
||||
import {Action, Command, Ctx, Message, On, Wizard, WizardStep} from "nestjs-telegraf";
|
||||
import {WIZARD_COMMENT_SCENE_ID} from "../telegram.constants";
|
||||
import * as scenes from "telegraf/scenes";
|
||||
import {ManagerService} from "../../manager/manager.service";
|
||||
import {PublishPageService} from "../../social-api/publish.page.service";
|
||||
import {XReaderService} from "../../x-reader/x-reader.service";
|
||||
import {TrendsService} from "../../trends/trends.service";
|
||||
|
||||
@Wizard(WIZARD_COMMENT_SCENE_ID)
|
||||
export class CommentWizard {
|
||||
constructor(
|
||||
private readonly managerService: ManagerService,
|
||||
) {
|
||||
}
|
||||
|
||||
// Bắt lệnh /cancel để thoát
|
||||
@Command('cancel')
|
||||
async cancel(@Ctx() ctx: scenes.WizardContext) {
|
||||
await ctx.reply('Đã hủy quy trình.');
|
||||
return ctx.scene.leave(); // Thoát khỏi wizard ngay lập tức
|
||||
}
|
||||
|
||||
@WizardStep(1)
|
||||
async onSceneEnter(@Ctx() ctx: scenes.WizardContext) {
|
||||
// await ctx.wizard.next();
|
||||
// return 'Welcome to wizard scene ✋ Send me your name';
|
||||
|
||||
//@ts-ignore
|
||||
const text = ctx.message?.text;
|
||||
console.log(ctx.message);
|
||||
const linkX = text.split(' ')[1]; // Gets "my_payload"
|
||||
//
|
||||
// // Pass it as the second argument (initial state)
|
||||
//await ctx.scene.enter(WIZARD_COMMENT_SCENE_ID, {customPayload: payload});
|
||||
console.log(linkX);
|
||||
|
||||
let _linkX = linkX.replace('twitter.com', 'x.com').split('?')[0];
|
||||
const match = _linkX.match(/status\/(\d+)/);
|
||||
if (!match) {
|
||||
await ctx.reply('URL X không hợp lệ');
|
||||
return ctx.scene.leave();
|
||||
}
|
||||
const tweetId = match[1];
|
||||
|
||||
// 1. Lưu dữ liệu vào state
|
||||
(ctx.wizard.state as any).linkUrl = _linkX;
|
||||
(ctx.wizard.state as any).tweetId = tweetId;
|
||||
await ctx.sendMessage(
|
||||
`🤖 Bạn muốn viết bằng ngôn ngữ nào , bấm \cancel để huỷ `,
|
||||
{
|
||||
parse_mode: 'Markdown',
|
||||
reply_markup: {
|
||||
inline_keyboard: [
|
||||
[
|
||||
{text: "🇬🇧English", callback_data: `write_comment_en`},
|
||||
{text: "🇯🇵Japan", callback_data: `write_comment_ja`},
|
||||
],
|
||||
[
|
||||
{text: "🇰🇷Korea", callback_data: `write_comment_ko`},
|
||||
{text: "🇻🇳VN", callback_data: `write_comment_vi`},
|
||||
],
|
||||
[{text: "❌Cancel", callback_data: `write_comment_cancel`},]
|
||||
]
|
||||
}
|
||||
}
|
||||
);
|
||||
// const {payload} = ctx.scene;
|
||||
|
||||
// await ctx.reply(`Gứi link của bài X bạn cần reply`);
|
||||
|
||||
ctx.wizard.next();
|
||||
}
|
||||
|
||||
@WizardStep(2)
|
||||
@On('text')
|
||||
@Action(/write_comment_(.+)/)
|
||||
async step2(@Ctx() ctx: scenes.WizardContext) {
|
||||
// 1. Lấy dữ liệu từ nút bấm
|
||||
// @ts-ignore
|
||||
const selectedItem = ctx.match[1]
|
||||
if (selectedItem == 'cancel') {
|
||||
await ctx.reply('Đã hủy quy trình.');
|
||||
return ctx.scene.leave();
|
||||
}
|
||||
|
||||
// 2. Lưu vào state để dùng cho các bước sau (nếu cần)
|
||||
(ctx.wizard.state as any).selectedLanguage = selectedItem;
|
||||
|
||||
// 3. Phải gọi answerCbQuery để tắt biểu tượng "loading" trên nút bấm
|
||||
await ctx.answerCbQuery();
|
||||
|
||||
await ctx.reply(`Bạn đã chọn ${selectedItem}. Vui lòng chờ phân tích ...`);
|
||||
const url = (ctx.wizard.state as any).linkUrl;
|
||||
await this.managerService.manualTriggerCommentLinkTwitter(url, selectedItem);
|
||||
|
||||
// Chuyển sang bước 3 (nhận địa chỉ bằng text)
|
||||
// ctx.wizard.next();
|
||||
await ctx.scene.leave();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,227 @@
|
||||
import {Action, Command, Ctx, On, Wizard, WizardStep} from "nestjs-telegraf";
|
||||
import {WIZARD_COMMENT2_SCENE_ID} from "../telegram.constants";
|
||||
import * as scenes from "telegraf/scenes";
|
||||
import {ManagerService} from "../../manager/manager.service";
|
||||
import {TONE_HINTS_TELEGRAM_BUTTON} from "../../content-writer/prompts/templates";
|
||||
import {ANGLE_HINTS_TELEGRAM_BUTTON} from "../../content-writer/enum/angle.enum";
|
||||
|
||||
@Wizard(WIZARD_COMMENT2_SCENE_ID)
|
||||
export class Comment2Wizard {
|
||||
constructor(
|
||||
private readonly managerService: ManagerService,
|
||||
) {
|
||||
}
|
||||
|
||||
// Bắt lệnh /cancel để thoát
|
||||
@Command('cancel')
|
||||
async cancel(@Ctx() ctx: scenes.WizardContext) {
|
||||
await ctx.reply('Đã hủy quy trình.');
|
||||
return ctx.scene.leave(); // Thoát khỏi wizard ngay lập tức
|
||||
}
|
||||
|
||||
@WizardStep(1)
|
||||
async onSceneEnter(@Ctx() ctx: scenes.WizardContext) {
|
||||
//@ts-ignore
|
||||
const userTopic = ctx.message?.text;
|
||||
// console.log(ctx.message);
|
||||
// const userTopic = (ctx.wizard.state as any).userTopic;
|
||||
if (!userTopic) {
|
||||
await ctx.reply('Không có thông tin về chủ đề bạn cần viết bài');
|
||||
return ctx.scene.leave();
|
||||
}
|
||||
// @ts-ignore
|
||||
const inline_keyboards = [];
|
||||
Object.keys(TONE_HINTS_TELEGRAM_BUTTON).map(key => {
|
||||
// @ts-ignore
|
||||
inline_keyboards.push([{
|
||||
text: TONE_HINTS_TELEGRAM_BUTTON[key].text,
|
||||
callback_data: `comment_tone_${key}`
|
||||
}]);
|
||||
return;
|
||||
})
|
||||
await ctx.sendMessage(
|
||||
`🤖 Chọn phong cách viết , bấm \\cancel để huỷ `,
|
||||
{
|
||||
parse_mode: 'Markdown',
|
||||
reply_markup: {
|
||||
inline_keyboard: [
|
||||
...inline_keyboards,
|
||||
[
|
||||
{text: "🤖AI tự chọn", callback_data: `comment_tone_aineeddetect`},
|
||||
],
|
||||
[
|
||||
{text: "❌Cancel", callback_data: `comment_tone_cancel`},
|
||||
]
|
||||
]
|
||||
}
|
||||
}
|
||||
);
|
||||
ctx.wizard.next();
|
||||
}
|
||||
|
||||
@WizardStep(2)
|
||||
@On('text')
|
||||
@Action(/comment_tone_(.+)/)
|
||||
async step2(@Ctx() ctx: scenes.WizardContext) {
|
||||
|
||||
if (ctx.text == 'cancel') {
|
||||
await ctx.deleteMessage();
|
||||
await ctx.reply('Đã hủy quy trình.');
|
||||
return ctx.scene.leave();
|
||||
}
|
||||
// 1. Lấy dữ liệu từ nút bấm
|
||||
|
||||
// @ts-ignore
|
||||
if (ctx.match === undefined) {
|
||||
await ctx.reply('Đã hủy quy trình.');
|
||||
await ctx.deleteMessage();
|
||||
return ctx.scene.leave();
|
||||
}
|
||||
|
||||
let tone = undefined
|
||||
// @ts-ignore
|
||||
const selectedItem = ctx.match[1]
|
||||
|
||||
await ctx.answerCbQuery('Đã ghi nhận tone=' + selectedItem);
|
||||
if (selectedItem == 'cancel') {
|
||||
// Xóa tin nhắn hiện tại
|
||||
await ctx.deleteMessage();
|
||||
await ctx.reply('Đã hủy quy trình.');
|
||||
return ctx.scene.leave();
|
||||
}
|
||||
if (selectedItem == 'aineeddetect') {
|
||||
tone = undefined;
|
||||
} else {
|
||||
tone = selectedItem
|
||||
}
|
||||
|
||||
|
||||
// Xóa tin nhắn hiện tại
|
||||
await ctx.deleteMessage();
|
||||
|
||||
(ctx.wizard.state as any).tone = tone;
|
||||
// @ts-ignore
|
||||
const inline_keyboards = [];
|
||||
Object.keys(ANGLE_HINTS_TELEGRAM_BUTTON).map(key => {
|
||||
// @ts-ignore
|
||||
inline_keyboards.push([{
|
||||
text: ANGLE_HINTS_TELEGRAM_BUTTON[key].text,
|
||||
callback_data: `comment_agle_${key}`
|
||||
}]);
|
||||
return;
|
||||
})
|
||||
await ctx.sendMessage(
|
||||
`🤖 Chọn âm điệu , bấm \\cancel để huỷ `,
|
||||
{
|
||||
parse_mode: 'Markdown',
|
||||
reply_markup: {
|
||||
inline_keyboard: [
|
||||
...inline_keyboards,
|
||||
[
|
||||
{text: "🤖AI tự chọn", callback_data: `comment_agle_aineeddetect`},
|
||||
],
|
||||
[
|
||||
{text: "❌Cancel", callback_data: `comment_agle_cancel`},
|
||||
]
|
||||
]
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
ctx.wizard.next();
|
||||
}
|
||||
|
||||
@WizardStep(3)
|
||||
@On('text')
|
||||
@Action(/comment_agle_(.+)/)
|
||||
async step3(@Ctx() ctx: scenes.WizardContext) {
|
||||
if (ctx.text == 'cancel') {
|
||||
await ctx.deleteMessage();
|
||||
await ctx.reply('Đã hủy quy trình.');
|
||||
return ctx.scene.leave();
|
||||
}
|
||||
// 1. Lấy dữ liệu từ nút bấm
|
||||
|
||||
// @ts-ignore
|
||||
if (ctx.match === undefined) {
|
||||
await ctx.deleteMessage();
|
||||
await ctx.reply('Đã hủy quy trình.');
|
||||
return ctx.scene.leave();
|
||||
}
|
||||
|
||||
|
||||
|
||||
let agle = undefined
|
||||
// @ts-ignore
|
||||
const selectedItem = ctx.match[1]
|
||||
|
||||
await ctx.answerCbQuery('Đã ghi nhận agle:' + selectedItem);
|
||||
// Xóa tin nhắn hiện tại
|
||||
await ctx.deleteMessage();
|
||||
|
||||
if (selectedItem == 'cancel') {
|
||||
await ctx.reply('Đã hủy quy trình.');
|
||||
return ctx.scene.leave();
|
||||
}
|
||||
if (selectedItem == 'aineeddetect') {
|
||||
agle = undefined;
|
||||
} else {
|
||||
agle = selectedItem
|
||||
}
|
||||
|
||||
|
||||
(ctx.wizard.state as any).agle = agle;
|
||||
const chatId = (ctx.wizard.state as any).chatId;
|
||||
const tone = (ctx.wizard.state as any).tone;
|
||||
const tweetId = (ctx.wizard.state as any).tweetId;
|
||||
const tweetUrl = (ctx.wizard.state as any).tweetUrl;
|
||||
const userTopic = (ctx.wizard.state as any).userTopic;
|
||||
const language = (ctx.wizard.state as any).language;
|
||||
const postLength = undefined;
|
||||
|
||||
// @ts-ignore
|
||||
await ctx.reply(`
|
||||
Sẽ viết bài bằng ngôn ngữ ${language} độ dài ${postLength} với tone=${tone} và agle=${agle}.`);
|
||||
|
||||
await this.managerService.manualTriggerCommentAsText({
|
||||
agle: agle,
|
||||
comtext: userTopic,
|
||||
tone: tone,
|
||||
language: language,
|
||||
tweetId,
|
||||
tweetUrl,
|
||||
chatId,
|
||||
})
|
||||
await ctx.scene.leave();
|
||||
}
|
||||
|
||||
async doAskTone(ctx: scenes.WizardContext) {
|
||||
// @ts-ignore
|
||||
const inline_keyboards = [];
|
||||
Object.keys(TONE_HINTS_TELEGRAM_BUTTON).map(key => {
|
||||
// @ts-ignore
|
||||
inline_keyboards.push([{
|
||||
text: TONE_HINTS_TELEGRAM_BUTTON[key].text,
|
||||
callback_data: `comment_tone_${key}`
|
||||
}]);
|
||||
return;
|
||||
})
|
||||
await ctx.sendMessage(
|
||||
`🤖 Chọn phong cách viết , bấm \\cancel để huỷ `,
|
||||
{
|
||||
parse_mode: 'Markdown',
|
||||
reply_markup: {
|
||||
inline_keyboard: [
|
||||
...inline_keyboards,
|
||||
[
|
||||
{text: "🤖AI tự chọn", callback_data: `comment_tone_aineeddetect`},
|
||||
],
|
||||
[
|
||||
{text: "❌Cancel", callback_data: `comment_tone_cancel`},
|
||||
]
|
||||
]
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,143 @@
|
||||
import {Action, Command, Ctx, On, Wizard, WizardStep} from "nestjs-telegraf";
|
||||
import {WIZARD_QUOTE_SCENE_MAIN} from "../telegram.constants";
|
||||
import * as scenes from "telegraf/scenes";
|
||||
import {ManagerService} from "../../manager/manager.service";
|
||||
import {QUOTE_TYPE_TELEGRAM_BUTTON_SPECS} from "../../content-writer/prompts/quote.templates";
|
||||
|
||||
@Wizard(WIZARD_QUOTE_SCENE_MAIN)
|
||||
export class QuoteWizard {
|
||||
constructor(
|
||||
private readonly managerService: ManagerService,
|
||||
) {
|
||||
}
|
||||
|
||||
// Bắt lệnh /cancel để thoát
|
||||
@Command('cancel')
|
||||
async cancel(@Ctx() ctx: scenes.WizardContext) {
|
||||
await ctx.reply('Đã hủy quy trình.');
|
||||
return ctx.scene.leave(); // Thoát khỏi wizard ngay lập tức
|
||||
}
|
||||
|
||||
@WizardStep(1)
|
||||
async onSceneEnter(@Ctx() ctx: scenes.WizardContext) {
|
||||
|
||||
const isQuoteUrl = (ctx.wizard.state as any).quoteAs === 'quotelink';
|
||||
|
||||
//@ts-ignore
|
||||
const text = ctx.message?.text;
|
||||
console.log(ctx.message);
|
||||
if (isQuoteUrl) {
|
||||
const linkX = text.split(' ')[1]; // Gets "my_payload"
|
||||
|
||||
if (!linkX) {
|
||||
await ctx.reply('URL X không hợp lệ');
|
||||
return ctx.scene.leave();
|
||||
}
|
||||
|
||||
let _linkX = linkX.replace('twitter.com', 'x.com').split('?')[0];
|
||||
const match = _linkX.match(/status\/(\d+)/);
|
||||
if (!match) {
|
||||
await ctx.reply('URL X không hợp lệ');
|
||||
return ctx.scene.leave();
|
||||
}
|
||||
const tweetId = match[1];
|
||||
// 1. Lưu dữ liệu vào state
|
||||
(ctx.wizard.state as any).linkUrl = linkX;
|
||||
(ctx.wizard.state as any).tweetId = tweetId;
|
||||
}
|
||||
// @ts-ignore
|
||||
const inline_keyboards = [];
|
||||
Object.keys(QUOTE_TYPE_TELEGRAM_BUTTON_SPECS).map(key => {
|
||||
// @ts-ignore
|
||||
inline_keyboards.push([{
|
||||
text: QUOTE_TYPE_TELEGRAM_BUTTON_SPECS[key].text,
|
||||
callback_data: `quote_type_${key}`
|
||||
}]);
|
||||
return;
|
||||
})
|
||||
await ctx.sendMessage(
|
||||
`🤖 Chọn phong cách quote , bấm \\cancel để huỷ `,
|
||||
{
|
||||
parse_mode: 'Markdown',
|
||||
reply_markup: {
|
||||
inline_keyboard: [
|
||||
// @ts-ignore
|
||||
...inline_keyboards,
|
||||
[
|
||||
{text: "🤖AI tự chọn", callback_data: `quote_type_aineeddetect`},
|
||||
],
|
||||
[
|
||||
{text: "❌Cancel", callback_data: `quote_type_cancel`},
|
||||
]
|
||||
]
|
||||
}
|
||||
}
|
||||
);
|
||||
ctx.wizard.next();
|
||||
}
|
||||
|
||||
@WizardStep(2)
|
||||
@On('text')
|
||||
@Action(/quote_type_(.+)/)
|
||||
async step2(@Ctx() ctx: scenes.WizardContext) {
|
||||
await ctx.answerCbQuery('Đã ghi nhận');
|
||||
// Xóa tin nhắn hiện tại
|
||||
await ctx.deleteMessage();
|
||||
if (ctx.text == 'cancel') {
|
||||
await ctx.reply('Đã hủy quy trình.');
|
||||
return ctx.scene.leave();
|
||||
}
|
||||
// 1. Lấy dữ liệu từ nút bấm
|
||||
|
||||
// @ts-ignore
|
||||
if (ctx.match === undefined) {
|
||||
await ctx.reply('Đã hủy quy trình.');
|
||||
return ctx.scene.leave();
|
||||
}
|
||||
|
||||
let quoteType = undefined
|
||||
// @ts-ignore
|
||||
const selectedItem = ctx.match[1]
|
||||
if (selectedItem == 'cancel') {
|
||||
await ctx.reply('Đã hủy quy trình.');
|
||||
return ctx.scene.leave();
|
||||
}
|
||||
if (selectedItem == 'aineeddetect') {
|
||||
quoteType = undefined;
|
||||
} else {
|
||||
quoteType = selectedItem
|
||||
}
|
||||
// 2. Lưu vào state để dùng cho các bước sau (nếu cần)
|
||||
// (ctx.wizard.state as any).type = quoteType;
|
||||
|
||||
const language = (ctx.wizard.state as any).language;
|
||||
const quoteAs = (ctx.wizard.state as any).quoteAs;
|
||||
|
||||
const telegramChatId = ''+ctx?.chat?.id!;
|
||||
// @ts-ignore
|
||||
await ctx.reply(`Sẽ viết quote bằng ngôn ngữ ${language} với phong cách ${quoteType}-${QUOTE_TYPE_TELEGRAM_BUTTON_SPECS[quoteType]?.text!} ...`);
|
||||
|
||||
if (quoteAs === 'quotetext') {
|
||||
const userTopic = (ctx.wizard.state as any).quoteText;
|
||||
|
||||
await this.managerService.manualTriggerQuoteAsTextInput(
|
||||
userTopic,
|
||||
quoteType,
|
||||
language,
|
||||
telegramChatId
|
||||
)
|
||||
} else {
|
||||
const twitterUrl = (ctx.wizard.state as any).linkUrl;
|
||||
|
||||
await this.managerService.manualTriggerQuoteLinkTwitter(
|
||||
twitterUrl,
|
||||
quoteType,
|
||||
language,
|
||||
telegramChatId
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
await ctx.scene.leave();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,196 @@
|
||||
import {Action, Command, Ctx, On, Wizard, WizardStep} from "nestjs-telegraf";
|
||||
import {WIZARD_WRITER_SCENE_ID} from "../telegram.constants";
|
||||
import * as scenes from "telegraf/scenes";
|
||||
import {ManagerService} from "../../manager/manager.service";
|
||||
import {STYLE_HINTS_TELEGRAM_BUTTON, TONE_HINTS_TELEGRAM_BUTTON} from "../../content-writer/prompts/templates";
|
||||
|
||||
@Wizard(WIZARD_WRITER_SCENE_ID)
|
||||
export class WriterWizard {
|
||||
constructor(
|
||||
private readonly managerService: ManagerService,
|
||||
) {
|
||||
}
|
||||
|
||||
// Bắt lệnh /cancel để thoát
|
||||
@Command('cancel')
|
||||
async cancel(@Ctx() ctx: scenes.WizardContext) {
|
||||
await ctx.reply('Đã hủy quy trình.');
|
||||
return ctx.scene.leave(); // Thoát khỏi wizard ngay lập tức
|
||||
}
|
||||
|
||||
@WizardStep(1)
|
||||
async onSceneEnter(@Ctx() ctx: scenes.WizardContext) {
|
||||
//@ts-ignore
|
||||
const text = ctx.message?.text;
|
||||
console.log(ctx.message);
|
||||
const userTopic = (ctx.wizard.state as any).userTopic;
|
||||
if (!userTopic) {
|
||||
await ctx.reply('Không có thông tin về chủ đề bạn cần viết bài');
|
||||
return ctx.scene.leave();
|
||||
}
|
||||
// @ts-ignore
|
||||
const inline_keyboards = [];
|
||||
Object.keys(STYLE_HINTS_TELEGRAM_BUTTON).map(key => {
|
||||
// @ts-ignore
|
||||
inline_keyboards.push([{
|
||||
text: STYLE_HINTS_TELEGRAM_BUTTON[key].text,
|
||||
callback_data: `write_type_${key}`
|
||||
}]);
|
||||
return;
|
||||
})
|
||||
await ctx.sendMessage(
|
||||
`🤖 Chọn phong cách viết , bấm \\cancel để huỷ `,
|
||||
{
|
||||
parse_mode: 'Markdown',
|
||||
reply_markup: {
|
||||
inline_keyboard: [
|
||||
...inline_keyboards,
|
||||
[
|
||||
{text: "🤖AI tự chọn", callback_data: `write_type_aineeddetect`},
|
||||
],
|
||||
[
|
||||
{text: "❌Cancel", callback_data: `write_type_cancel`},
|
||||
]
|
||||
]
|
||||
}
|
||||
}
|
||||
);
|
||||
ctx.wizard.next();
|
||||
}
|
||||
|
||||
@WizardStep(2)
|
||||
@On('text')
|
||||
@Action(/write_type_(.+)/)
|
||||
async step2(@Ctx() ctx: scenes.WizardContext) {
|
||||
|
||||
if (ctx.text == 'cancel') {
|
||||
await ctx.deleteMessage();
|
||||
await ctx.reply('Đã hủy quy trình.');
|
||||
return ctx.scene.leave();
|
||||
}
|
||||
// 1. Lấy dữ liệu từ nút bấm
|
||||
|
||||
// @ts-ignore
|
||||
if (ctx.match === undefined) {
|
||||
await ctx.reply('Đã hủy quy trình.');
|
||||
await ctx.deleteMessage();
|
||||
return ctx.scene.leave();
|
||||
}
|
||||
|
||||
let writeType = undefined
|
||||
// @ts-ignore
|
||||
const selectedItem = ctx.match[1]
|
||||
|
||||
await ctx.answerCbQuery('Đã ghi nhận writing style=' + selectedItem);
|
||||
if (selectedItem == 'cancel') {
|
||||
// Xóa tin nhắn hiện tại
|
||||
await ctx.deleteMessage();
|
||||
await ctx.reply('Đã hủy quy trình.');
|
||||
return ctx.scene.leave();
|
||||
}
|
||||
if (selectedItem == 'aineeddetect') {
|
||||
writeType = undefined;
|
||||
} else {
|
||||
writeType = selectedItem
|
||||
}
|
||||
|
||||
|
||||
// Xóa tin nhắn hiện tại
|
||||
await ctx.deleteMessage();
|
||||
|
||||
(ctx.wizard.state as any).writeType = writeType;
|
||||
// @ts-ignore
|
||||
const inline_keyboards = [];
|
||||
Object.keys(TONE_HINTS_TELEGRAM_BUTTON).map(key => {
|
||||
// @ts-ignore
|
||||
inline_keyboards.push([{
|
||||
text: TONE_HINTS_TELEGRAM_BUTTON[key].text,
|
||||
callback_data: `write_tone_${key}`
|
||||
}]);
|
||||
return;
|
||||
})
|
||||
await ctx.sendMessage(
|
||||
`🤖 Chọn âm điệu , bấm \\cancel để huỷ `,
|
||||
{
|
||||
parse_mode: 'Markdown',
|
||||
reply_markup: {
|
||||
inline_keyboard: [
|
||||
...inline_keyboards,
|
||||
[
|
||||
{text: "🤖AI tự chọn", callback_data: `write_tone_aineeddetect`},
|
||||
],
|
||||
[
|
||||
{text: "❌Cancel", callback_data: `write_tone_cancel`},
|
||||
]
|
||||
]
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
ctx.wizard.next();
|
||||
}
|
||||
|
||||
@WizardStep(3)
|
||||
@On('text')
|
||||
@Action(/write_tone_(.+)/)
|
||||
async step3(@Ctx() ctx: scenes.WizardContext) {
|
||||
if (ctx.text == 'cancel') {
|
||||
await ctx.deleteMessage();
|
||||
await ctx.reply('Đã hủy quy trình.');
|
||||
return ctx.scene.leave();
|
||||
}
|
||||
// 1. Lấy dữ liệu từ nút bấm
|
||||
|
||||
// @ts-ignore
|
||||
if (ctx.match === undefined) {
|
||||
await ctx.deleteMessage();
|
||||
await ctx.reply('Đã hủy quy trình.');
|
||||
return ctx.scene.leave();
|
||||
}
|
||||
|
||||
|
||||
|
||||
let writeTone = undefined
|
||||
// @ts-ignore
|
||||
const selectedItem = ctx.match[1]
|
||||
|
||||
await ctx.answerCbQuery('Đã ghi nhận ngữ điệu:' + selectedItem);
|
||||
// Xóa tin nhắn hiện tại
|
||||
await ctx.deleteMessage();
|
||||
|
||||
if (selectedItem == 'cancel') {
|
||||
await ctx.reply('Đã hủy quy trình.');
|
||||
return ctx.scene.leave();
|
||||
}
|
||||
if (selectedItem == 'aineeddetect') {
|
||||
writeTone = undefined;
|
||||
} else {
|
||||
writeTone = selectedItem
|
||||
}
|
||||
|
||||
|
||||
(ctx.wizard.state as any).writeTone = writeTone;
|
||||
const writeType = (ctx.wizard.state as any).writeType;
|
||||
const userTopic = (ctx.wizard.state as any).userTopic;
|
||||
const language = (ctx.wizard.state as any).language;
|
||||
const telegramChatId = (ctx.wizard.state as any).chatId;
|
||||
const postLength = undefined;
|
||||
|
||||
// @ts-ignore
|
||||
await ctx.reply(`
|
||||
Sẽ viết bài bằng ngôn ngữ ${language} độ dài ${postLength} với phong cách ${writeType} và màu sắc ${writeTone} ...
|
||||
`);
|
||||
|
||||
await this.managerService.manualTriggerWriteWithReview({
|
||||
style: writeType,
|
||||
keyword: userTopic,
|
||||
tone: writeTone,
|
||||
language: language,
|
||||
telegramChatId,
|
||||
postLength
|
||||
})
|
||||
await ctx.scene.leave();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user