File size: 8,666 Bytes
5d668bd
 
 
1d28cec
5d668bd
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1d28cec
 
5d668bd
 
1d28cec
5d668bd
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
04eb236
5d668bd
 
04eb236
5d668bd
 
 
04eb236
5d668bd
04eb236
5d668bd
 
 
04eb236
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
5d668bd
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
import os
import time
import asyncio
from pyrogram import Client, filters, ContinuePropagation
from pyrogram.types import InlineKeyboardMarkup, InlineKeyboardButton, CallbackQuery
from helper.utils import progress_for_pyrogram
from plugins.file_rename import extract_season_episode, extract_quality

# Dictionary to store ongoing audio operations
audio_ops = {}

@Client.on_message(filters.private & filters.command("audio") & filters.reply)
async def audio_command(client, message):
    replied = message.reply_to_message
    if not (replied.video or replied.document):
        return await message.reply_text("Please reply to a video or document file with /audio")

    file_id = replied.video.file_id if replied.video else replied.document.file_id
    
    # Store message id for callback
    keyboard = InlineKeyboardMarkup([
        [
            InlineKeyboardButton("πŸ”‡ Remove Audio", callback_data=f"aud_rm_{replied.id}"),
            InlineKeyboardButton("πŸ”€ Reorder Audio", callback_data=f"aud_re_{replied.id}")
        ],
        [
            InlineKeyboardButton("βš™οΈ Set Default Audio", callback_data=f"aud_def_{replied.id}")
        ]
    ])
    
    await message.reply_text(
        "**Audio Management Options:**\n\n"
        "Choose what you want to do with the audio tracks of this file.\n"
        "*(Note: You will be asked to enter track numbers. Track 1 = 0, Track 2 = 1)*",
        reply_markup=keyboard
    )

@Client.on_callback_query(filters.regex(r"^aud_"))
async def audio_callback(client, query: CallbackQuery):
    data = query.data.split("_")
    action = data[1] # rm, re, def
    msg_id = int(data[2])
    
    user_id = query.from_user.id
    
    if action == "rm":
        text = "Reply to this message with the audio track number you want to REMOVE.\n\nExample: `1` (removes 2nd track)"
    elif action == "re":
        text = "Reply to this message with the new order of tracks (comma separated).\n\nExample: `1,0` (swaps track 1 and 2)"
    elif action == "def":
        text = "Reply to this message with the track number you want to set as DEFAULT.\n\nExample: `1` (sets 2nd track as default)"
        
    prompt = await query.message.edit_text(text)
    
    # Save state
    audio_ops[user_id] = {
        "action": action,
        "msg_id": msg_id,
        "prompt_id": prompt.id
    }

@Client.on_message(filters.private & filters.reply)
async def process_audio_input(client, message):
    user_id = message.from_user.id
    if user_id not in audio_ops:
        raise ContinuePropagation

    op = audio_ops[user_id]
    if message.reply_to_message.id != op["prompt_id"]:
        raise ContinuePropagation
        
    action = op["action"]
    msg_id = op["msg_id"]
    user_input = message.text.strip()
    
    del audio_ops[user_id] # Clear state
    
    target_msg = await client.get_messages(message.chat.id, msg_id)
    if not target_msg:
        return await message.reply_text("Original message not found.")
        
    status = await message.reply_text("πŸ“₯ Downloading file for audio processing...")
    
    try:
        # Download
        file_name = target_msg.video.file_name if target_msg.video else target_msg.document.file_name
        if not file_name:
            file_name = "downloaded_video.mkv"
            
        download_path = f"downloads/{user_id}_{file_name}"
        
        start_time = time.time()
        file_path = await client.download_media(
            target_msg,
            file_name=download_path,
            progress=progress_for_pyrogram,
            progress_args=("Downloading...", status, start_time)
        )
        
        await status.edit("βš™οΈ Processing audio with FFmpeg... This may take a while.")
        
        output_path = f"downloads/processed_{user_id}_{file_name}"
        
        # Build FFmpeg command based on action
        if action == "rm":
            track_idx = int(user_input)
            # Remove specific audio track (negative mapping)
            cmd = f'ffmpeg -i "{file_path}" -map 0 -map -0:a:{track_idx} -c copy "{output_path}" -y'
            
        elif action == "re":
            tracks = user_input.split(",")
            # Reorder: map video, then map audio tracks in specified order
            # Example: ffmpeg -i in.mkv -map 0:v -map 0:a:1 -map 0:a:0 -c copy out.mkv
            maps = "-map 0:v " + " ".join([f"-map 0:a:{t.strip()}" for t in tracks])
            # Also map subtitles if any
            maps += " -map 0:s? "
            cmd = f'ffmpeg -i "{file_path}" {maps} -c copy "{output_path}" -y'
            
        elif action == "def":
            track_idx = int(user_input)
            # Set default track disposition
            cmd = f'ffmpeg -i "{file_path}" -map 0 -c copy -disposition:a:0 0 -disposition:a:{track_idx} default "{output_path}" -y'
            
        # Run FFmpeg
        process = await asyncio.create_subprocess_shell(
            cmd,
            stdout=asyncio.subprocess.PIPE,
            stderr=asyncio.subprocess.PIPE
        )
        stdout, stderr = await process.communicate()
        
        if process.returncode != 0:
            await status.edit(f"❌ FFmpeg error: \n```\n{stderr.decode()[:500]}\n```")
            return
            
        await status.edit("πŸ“€ Uploading processed file...")
        
        # Upload
        start_time = time.time()
        await client.send_document(
            chat_id=message.chat.id,
            document=output_path,
            caption=f"Processed: {file_name}\nAction: {action}",
            file_name=file_name,
            progress=progress_for_pyrogram,
            progress_args=("Uploading...", status, start_time)
        )
        
        await status.delete()
        
        # Cleanup
        os.remove(file_path)
        os.remove(output_path)
        
    except ValueError:
        await status.edit("❌ Invalid input! Please enter numbers only.")
    except Exception as e:
        await status.edit(f"❌ Error: {str(e)}")
        

@Client.on_message(filters.private & filters.command(["setaudioorder", "set_auto_audio_order"]))
async def set_audio_order(client, message):
    if len(message.command) < 2:
        return await message.reply_text("Usage: /set_auto_audio_order 1,0,2\nTo reset, use /reset_auto_audio_order")
    order = message.command[1]
    from helper.database import codeflixbots
    await codeflixbots.set_audio_order(message.from_user.id, order)
    await message.reply_text(f"βœ… Auto Uploader Audio order saved as `{order}`. It will be applied automatically to auto uploader jobs.")

@Client.on_message(filters.private & filters.command(["resetaudioorder", "reset_auto_audio_order"]))
async def reset_audio_order(client, message):
    from helper.database import codeflixbots
    await codeflixbots.set_audio_order(message.from_user.id, None)
    await message.reply_text("βœ… Auto Uploader Audio order reset to default.\n\n")

@Client.on_message(filters.private & filters.command(["set_leech_audio_order"]))
async def set_leech_audio_order(client, message):
    if len(message.command) < 2:
        return await message.reply_text("Usage: /set_leech_audio_order 1,0,2\nTo reset, use /reset_leech_audio_order")
    order = message.command[1]
    from helper.database import codeflixbots
    await codeflixbots.set_merge_audio_order(message.from_user.id, order)
    await message.reply_text(f"βœ… Leech/Rename Audio order saved as `{order}`. It will be applied automatically for normal files.")

@Client.on_message(filters.private & filters.command(["reset_leech_audio_order"]))
async def reset_leech_audio_order(client, message):
    from helper.database import codeflixbots
    await codeflixbots.set_merge_audio_order(message.from_user.id, None)
    await message.reply_text("βœ… Leech/Rename Audio order reset to default.")

@Client.on_message(filters.private & filters.command("setdefaultaudio"))
async def set_default_audio(client, message):
    if len(message.command) < 2:
        return await message.reply_text("Usage: /setdefaultaudio 0\nTo reset, use /resetdefaultaudio")
    default_track = message.command[1]
    from helper.database import codeflixbots
    await codeflixbots.set_audio_default(message.from_user.id, default_track)
    await message.reply_text(f"βœ… Default audio track set to `{default_track}`. It will be applied automatically.")

@Client.on_message(filters.private & filters.command("resetdefaultaudio"))
async def reset_default_audio(client, message):
    from helper.database import codeflixbots
    await codeflixbots.set_audio_default(message.from_user.id, None)
    await message.reply_text("βœ… Default audio track reset.")