feat: pending 글 카테고리 변경 기능 추가
- /setcorner <번호> <카테고리>: 커맨드로 변경 - /pending 버튼에 🏷 카테고리 변경 버튼 추가 → 클릭 시 9개 카테고리 선택 버튼 표시 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -1163,6 +1163,9 @@ async def cmd_pending(update: Update, context: ContextTypes.DEFAULT_TYPE):
|
|||||||
[
|
[
|
||||||
InlineKeyboardButton("✅ 승인 발행", callback_data=f"approve:{filename}"),
|
InlineKeyboardButton("✅ 승인 발행", callback_data=f"approve:{filename}"),
|
||||||
InlineKeyboardButton("🗑 거부", callback_data=f"reject:{filename}"),
|
InlineKeyboardButton("🗑 거부", callback_data=f"reject:{filename}"),
|
||||||
|
],
|
||||||
|
[
|
||||||
|
InlineKeyboardButton("🏷 카테고리 변경", callback_data=f"setcorner:{filename}"),
|
||||||
]
|
]
|
||||||
])
|
])
|
||||||
await update.message.reply_text(
|
await update.message.reply_text(
|
||||||
@@ -1170,12 +1173,59 @@ async def cmd_pending(update: Update, context: ContextTypes.DEFAULT_TYPE):
|
|||||||
f"<b>{title}</b>\n"
|
f"<b>{title}</b>\n"
|
||||||
f"코너: {corner}\n"
|
f"코너: {corner}\n"
|
||||||
f"사유: {reason}\n\n"
|
f"사유: {reason}\n\n"
|
||||||
f"{body_preview}...",
|
f"{body_preview}...\n\n"
|
||||||
|
f"카테고리 변경: /setcorner {i} 재테크",
|
||||||
parse_mode='HTML',
|
parse_mode='HTML',
|
||||||
reply_markup=keyboard,
|
reply_markup=keyboard,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
async def cmd_setcorner(update: Update, context: ContextTypes.DEFAULT_TYPE):
|
||||||
|
"""/setcorner <번호> <카테고리> — pending 글 카테고리 변경"""
|
||||||
|
VALID_CORNERS = {"AI인사이트", "여행맛집", "스타트업", "TV로보는세상", "제품리뷰", "생활꿀팁", "건강정보", "재테크", "팩트체크"}
|
||||||
|
args = context.args
|
||||||
|
if len(args) < 2:
|
||||||
|
await update.message.reply_text(
|
||||||
|
"사용법: /setcorner <번호> <카테고리>\n"
|
||||||
|
"예: /setcorner 1 재테크\n"
|
||||||
|
f"카테고리: {', '.join(sorted(VALID_CORNERS))}"
|
||||||
|
)
|
||||||
|
return
|
||||||
|
sys.path.insert(0, str(BASE_DIR / 'bots'))
|
||||||
|
import publisher_bot
|
||||||
|
pending = publisher_bot.get_pending_list()
|
||||||
|
if not pending:
|
||||||
|
await update.message.reply_text("대기 글이 없습니다.")
|
||||||
|
return
|
||||||
|
try:
|
||||||
|
idx = int(args[0]) - 1
|
||||||
|
except ValueError:
|
||||||
|
await update.message.reply_text("❌ 번호를 숫자로 입력하세요.")
|
||||||
|
return
|
||||||
|
if not (0 <= idx < len(pending)):
|
||||||
|
await update.message.reply_text(f"❌ 1~{len(pending)} 사이 번호를 입력하세요.")
|
||||||
|
return
|
||||||
|
new_corner = args[1]
|
||||||
|
if new_corner not in VALID_CORNERS:
|
||||||
|
await update.message.reply_text(f"❌ 유효하지 않은 카테고리입니다.\n사용 가능: {', '.join(sorted(VALID_CORNERS))}")
|
||||||
|
return
|
||||||
|
filepath = pending[idx].get('_filepath', '')
|
||||||
|
if not filepath or not Path(filepath).exists():
|
||||||
|
await update.message.reply_text("❌ 파일을 찾을 수 없습니다.")
|
||||||
|
return
|
||||||
|
# 파일 수정
|
||||||
|
article = json.loads(Path(filepath).read_text(encoding='utf-8'))
|
||||||
|
old_corner = article.get('corner', '')
|
||||||
|
article['corner'] = new_corner
|
||||||
|
Path(filepath).write_text(json.dumps(article, ensure_ascii=False, indent=2), encoding='utf-8')
|
||||||
|
await update.message.reply_text(
|
||||||
|
f"✅ 카테고리 변경 완료!\n"
|
||||||
|
f"제목: {article.get('title','')[:50]}\n"
|
||||||
|
f"{old_corner} → {new_corner}\n\n"
|
||||||
|
f"👉 /pending 으로 승인하세요."
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
async def cmd_approve(update: Update, context: ContextTypes.DEFAULT_TYPE):
|
async def cmd_approve(update: Update, context: ContextTypes.DEFAULT_TYPE):
|
||||||
sys.path.insert(0, str(BASE_DIR / 'bots'))
|
sys.path.insert(0, str(BASE_DIR / 'bots'))
|
||||||
import publisher_bot
|
import publisher_bot
|
||||||
@@ -1235,6 +1285,34 @@ async def callback_approve_reject(update: Update, context: ContextTypes.DEFAULT_
|
|||||||
elif action == 'reject':
|
elif action == 'reject':
|
||||||
publisher_bot.reject_pending(str(filepath))
|
publisher_bot.reject_pending(str(filepath))
|
||||||
await query.edit_message_text(f"🗑 거부 완료\n\n{query.message.text_html or query.message.text}", parse_mode='HTML')
|
await query.edit_message_text(f"🗑 거부 완료\n\n{query.message.text_html or query.message.text}", parse_mode='HTML')
|
||||||
|
elif action == 'setcorner':
|
||||||
|
VALID_CORNERS = ["AI인사이트", "여행맛집", "스타트업", "TV로보는세상", "제품리뷰", "생활꿀팁", "건강정보", "재테크", "팩트체크"]
|
||||||
|
# 카테고리 선택 버튼 표시
|
||||||
|
buttons = [[InlineKeyboardButton(c, callback_data=f"docorner:{filename}:{c}")] for c in VALID_CORNERS]
|
||||||
|
await query.edit_message_reply_markup(reply_markup=InlineKeyboardMarkup(buttons))
|
||||||
|
elif action == 'docorner':
|
||||||
|
# filename:corner 형태로 파싱
|
||||||
|
parts = filename.split(':', 1)
|
||||||
|
real_filename = parts[0]
|
||||||
|
new_corner = parts[1] if len(parts) > 1 else ''
|
||||||
|
real_filepath = pending_dir / real_filename
|
||||||
|
if real_filepath.exists() and new_corner:
|
||||||
|
article = json.loads(real_filepath.read_text(encoding='utf-8'))
|
||||||
|
old_corner = article.get('corner', '')
|
||||||
|
article['corner'] = new_corner
|
||||||
|
real_filepath.write_text(json.dumps(article, ensure_ascii=False, indent=2), encoding='utf-8')
|
||||||
|
# 원래 버튼으로 복원
|
||||||
|
keyboard = InlineKeyboardMarkup([
|
||||||
|
[
|
||||||
|
InlineKeyboardButton("✅ 승인 발행", callback_data=f"approve:{real_filename}"),
|
||||||
|
InlineKeyboardButton("🗑 거부", callback_data=f"reject:{real_filename}"),
|
||||||
|
],
|
||||||
|
[InlineKeyboardButton("🏷 카테고리 변경", callback_data=f"setcorner:{real_filename}")]
|
||||||
|
])
|
||||||
|
await query.edit_message_text(
|
||||||
|
f"🏷 카테고리 변경: {old_corner} → {new_corner}\n{article.get('title','')[:50]}",
|
||||||
|
reply_markup=keyboard
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
async def cmd_report(update: Update, context: ContextTypes.DEFAULT_TYPE):
|
async def cmd_report(update: Update, context: ContextTypes.DEFAULT_TYPE):
|
||||||
@@ -1723,7 +1801,8 @@ async def main():
|
|||||||
app.add_handler(CommandHandler('approve', cmd_approve))
|
app.add_handler(CommandHandler('approve', cmd_approve))
|
||||||
app.add_handler(CommandHandler('reject', cmd_reject))
|
app.add_handler(CommandHandler('reject', cmd_reject))
|
||||||
app.add_handler(CommandHandler('pending', cmd_pending))
|
app.add_handler(CommandHandler('pending', cmd_pending))
|
||||||
app.add_handler(CallbackQueryHandler(callback_approve_reject, pattern=r'^(approve|reject):'))
|
app.add_handler(CallbackQueryHandler(callback_approve_reject, pattern=r'^(approve|reject|setcorner|docorner):'))
|
||||||
|
app.add_handler(CommandHandler('setcorner', cmd_setcorner))
|
||||||
app.add_handler(CommandHandler('report', cmd_report))
|
app.add_handler(CommandHandler('report', cmd_report))
|
||||||
app.add_handler(CommandHandler('idea', cmd_idea))
|
app.add_handler(CommandHandler('idea', cmd_idea))
|
||||||
app.add_handler(CommandHandler('topic', cmd_topic))
|
app.add_handler(CommandHandler('topic', cmd_topic))
|
||||||
|
|||||||
Reference in New Issue
Block a user