File size: 8,488 Bytes
038c7d7
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
import asyncio
import logging
import os
from datetime import datetime

from aiogram import Bot, Dispatcher, types
from aiogram.contrib.fsm_storage.memory import MemoryStorage
from aiogram.dispatcher import FSMContext
from aiogram.dispatcher.filters.state import State, StatesGroup
from aiogram.utils import executor
from apscheduler.schedulers.asyncio import AsyncIOScheduler
from apscheduler.triggers.cron import CronTrigger

# Настройки
BOT_TOKEN = "7903604359:AAFRZc1r8zqIQiX1N-VJJadRfmDf5ljf1Jg"  # Замените на токен вашего бота
INSTAGRAM_APP_ID = "YOUR_INSTAGRAM_APP_ID"  # Замените на ID вашего приложения Instagram
INSTAGRAM_APP_SECRET = "YOUR_INSTAGRAM_APP_SECRET"  # Замените на секрет вашего приложения Instagram
INSTAGRAM_REDIRECT_URI = "YOUR_INSTAGRAM_REDIRECT_URI"  # Замените на URI перенаправления

# Временное хранилище (для простоты)
user_data = {}
scheduled_posts = {}

# Временное хранилище для видео и описаний
video_data = {}

# Состояния для FSM
class ConnectAccount(StatesGroup):
    platform = State()

class UploadVideo(StatesGroup):
    video = State()
    description = State()
    publish_time = State()

logging.basicConfig(level=logging.INFO)
bot = Bot(token=BOT_TOKEN)
storage = MemoryStorage()
dp = Dispatcher(bot, storage=storage)
scheduler = AsyncIOScheduler()

# --- Хэндлеры ---

@dp.message_handler(commands=['start'])
async def send_welcome(message: types.Message):
    await message.reply("Привет! Этот бот поможет тебе планировать публикации в TikTok, Instagram и YouTube.")

@dp.message_handler(commands=['connect'])
async def connect_command(message: types.Message):
    keyboard = types.ReplyKeyboardMarkup(resize_keyboard=True, selective=True)
    keyboard.add("Instagram (тест)") # Пока добавим только Instagram для упрощения
    # keyboard.add("TikTok (скоро)")
    # keyboard.add("YouTube (скоро)")
    await message.reply("Выберите платформу для подключения:", reply_markup=keyboard)
    await ConnectAccount.platform.set()

@dp.message_handler(state=ConnectAccount.platform, text="Instagram (тест)")
async def process_connect_instagram(message: types.Message, state: FSMContext):
    # TODO: Реализовать OAuth 2.0 flow для Instagram
    auth_url = f"https://api.instagram.com/oauth/authorize?client_id={INSTAGRAM_APP_ID}&redirect_uri={INSTAGRAM_REDIRECT_URI}&scope=user_profile,user_media&response_type=code"
    await message.reply(f"Для подключения Instagram перейдите по ссылке:\n{auth_url}\n\nПосле авторизации вы будете перенаправлены на страницу с кодом. Скопируйте этот код и отправьте его мне.")
    await state.finish() # Временный финиш, обработка кода будет в отдельном хэндлере

@dp.message_handler(commands=['upload'])
async def upload_command(message: types.Message):
    await message.reply("Пожалуйста, отправьте видео для публикации.")
    await UploadVideo.video.set()

@dp.message_handler(state=UploadVideo.video, content_types=types.ContentType.VIDEO)
async def process_video(message: types.Message, state: FSMContext):
    async with state.proxy() as data:
        data['video'] = message.video.file_id
    await message.reply("Отлично! Теперь, пожалуйста, напишите описание к видео (или отправьте '-' если описания нет).")
    await UploadVideo.description.set()

@dp.message_handler(state=UploadVideo.description)
async def process_description(message: types.Message, state: FSMContext):
    async with state.proxy() as data:
        data['description'] = message.text if message.text != '-' else ""
    keyboard = types.ReplyKeyboardMarkup(resize_keyboard=True, selective=True)
    keyboard.add("Сейчас")
    keyboard.add("Указать время")
    await message.reply("Когда вы хотите опубликовать видео?", reply_markup=keyboard)
    await UploadVideo.publish_time.set()

@dp.message_handler(state=UploadVideo.publish_time, text="Сейчас")
async def process_publish_now(message: types.Message, state: FSMContext):
    async with state.proxy() as data:
        video_file = await bot.get_file(data['video'])
        video_path = video_file.file_path
        description = data['description']
        # TODO: Реализовать немедленную публикацию в выбранные соцсети
        await message.reply(f"Видео будет опубликовано прямо сейчас с описанием: {description}")
        # Временная имитация публикации
        await asyncio.sleep(2)
        await message.reply("Видео успешно опубликовано (имитация).")
    await state.finish()

@dp.message_handler(state=UploadVideo.publish_time, text="Указать время")
async def process_set_publish_time(message: types.Message):
    await message.reply("Пожалуйста, укажите желаемое время публикации в формате ГГГГ-ММ-ДД ЧЧ:ММ (например, 2025-03-22 15:00).")
    await dp.current_state().set_state(UploadVideo.publish_time) # Остаемся в этом состоянии для обработки времени

@dp.message_handler(state=UploadVideo.publish_time)
async def process_publish_time_input(message: types.Message, state: FSMContext):
    try:
        publish_at = datetime.strptime(message.text, '%Y-%m-%d %H:%M')
        if publish_at <= datetime.now():
            await message.reply("Указанное время уже прошло. Пожалуйста, выберите будущее время.")
            return
        async with state.proxy() as data:
            video_file = await bot.get_file(data['video'])
            video_path = video_file.file_path
            description = data['description']
            user_id = message.from_user.id
            post_id = f"{user_id}_{datetime.now().timestamp()}"
            scheduled_posts[post_id] = {
                'user_id': user_id,
                'video_path': video_path,
                'description': description,
                'publish_at': publish_at,
                'platforms': ['instagram'] # Пока только одна платформа
            }
            scheduler.add_job(publish_scheduled_post, 'date', run_date=publish_at, args=[bot, post_id, scheduled_posts])
            await message.reply(f"Видео запланировано к публикации на {publish_at.strftime('%Y-%m-%d %H:%M')} с описанием: {description}")
    except ValueError:
        await message.reply("Неверный формат времени. Пожалуйста, используйте формат ГГГГ-ММ-ДД ЧЧ:ММ.")
        return
    await state.finish()

async def publish_scheduled_post(bot: Bot, post_id: str, scheduled_posts: dict):
    post_data = scheduled_posts.get(post_id)
    if post_data:
        user_id = post_data['user_id']
        video_path = post_data['video_path']
        description = post_data['description']
        platforms = post_data['platforms']

        # TODO: Реализовать фактическую публикацию в Instagram API
        # Вам потребуется получить токен доступа пользователя
        await bot.send_message(user_id, f"Начинаю публикацию запланированного видео с описанием: {description} в {platforms}")
        # Временная имитация публикации
        await asyncio.sleep(5)
        await bot.send_message(user_id, f"Видео успешно опубликовано (имитация) в {platforms}.")
        del scheduled_posts[post_id]
    else:
        logging.warning(f"Запланированный пост с ID {post_id} не найден.")

async def main():
    scheduler.start()
    await dp.start_polling()

if __name__ == '__main__':
    asyncio.run(main())