-
Notifications
You must be signed in to change notification settings - Fork 6
/
Copy pathstart.py
289 lines (252 loc) · 11.7 KB
/
start.py
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
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
from telethon import TelegramClient, events, Button
from telethon.tl.types import DocumentAttributeAudio, DocumentAttributeVideo, DocumentAttributeFilename
from download_from_url import download_file, get_size
from file_handler import send_to_transfersh_async, progress, progressb
from progress_for_telethon import progress2
import json, logging, cryptg, os, time, datetime, aiohttp, asyncio, requests
from tools import execute
from hachoir.metadata import extractMetadata
from hachoir.parser import createParser
from thumbnail_video import thumb_creator
from ffprobe import stream_creator
from telethon.tl.types import DocumentAttributeVideo, DocumentAttributeAudio
logging.basicConfig(
level=logging.DEBUG,
handlers=[logging.FileHandler('log.txt'), logging.StreamHandler()],
format="%(asctime)s - %(name)s - %(levelname)s - %(message)s"
)
#basicConfig(format="[%(levelname) 5s/%(asctime)s] %(name)s: %(message)s", level=INFO)
LOGGER = logging.getLogger(__name__)
#log: logging.Logger = logging.getLogger("FastTelethon")
logging.getLogger("telethon").setLevel(logging.WARNING)
api_id = int(os.environ.get("API_ID"))
api_hash = os.environ.get("API_HASH")
bot_token =os.environ.get("BOT_TOKEN")
# Array to store users who are authorized to use the bot
AUTH_USERS = set(int(x) for x in os.environ.get("AUTH_USERS", "").split())
download_path = "Downloads/"
bot = TelegramClient('Encoder bot', api_id, api_hash).start(bot_token=bot_token)
HELP_TXT = """
I am a FFmpeg robot. I can convert All Type of Media.
for using me, you have to know about ffmpeg options.
the source and destination name must be deferent.
press /encode to start the proccess. then send your
media file or direct link. type your extension with ".".
`.mkv`
`_360p.mp4`
`_new.aac`
`2.mp3`.
and finaly type your ffmpeg options.
Examples:
Extract Audio without encoding:
`-vn -sn -c:a copy`
Extract Video without encoding:
`-sn -an -c:v copy`
mp3 bitrate 256k:
`-c:a libmp3lame -ab 256k`
trimm video - from minute 10 to minute 20:
`-ss 00:10:00 -to 00:20:00 -c copy`
mp4 + aac resolution 720*576
`-c:v libx264 -s 720*576 -c:a aac -ab 64k`
"""
@bot.on(events.NewMessage(pattern='/start'))
async def start(event):
await event.respond(f"Hi! Send /encode To Start.\n\nFor more info see /help")
raise events.StopPropagation
@bot.on(events.NewMessage(pattern='/help'))
async def help(event):
await event.respond(f"{HELP_TXT}")
raise events.StopPropagation
@bot.on(events.NewMessage(pattern='/encode'))
async def echo(update):
########################################################## Authorization
user = await update.get_chat()
if user.id not in AUTH_USERS:
await update.reply("sorry ! you cant use this bot.\n\ndeploy your own bot:\n[Repository_Link](https://github.com/prxpostern/TGFFmpeg001)")
return
########################################################## Step1
msg1 = await update.respond(f"**Step1:** Send Your Media File or URL. \n\n To Cancel press /cancel")
try:
async with bot.conversation(update.message.chat_id) as cv:
update2 = await cv.wait_event(events.NewMessage(update.message.chat_id))
except Exception as e:
LOGGER.info(f"Conversation 1 Error: {e}")
await msg1.delete()
await update.respond(f"**Conversation 1 Error:**\n\n{e}")
return
await msg1.delete()
#LOGGER.info(f"{update2}")
if update2.text == "/cancel":
await update.respond(f"Operation Cancelled By User. \nSend /encode to Start Again!")
return
if not update2.message.message.startswith("/") and not update2.message.message.startswith("http") and update2.message.media:
url_size = get_size(update2.message.document.size)
url_fn_attr = next(filter(lambda x: isinstance(x, DocumentAttributeFilename), update2.message.document.attributes), None)
url_fn = url_fn_attr.file_name if url_fn_attr else 'Unknown'
#url_fn = update2.message.document.attributes.file_name
#url_fn = await update2.get_chat()
#urlfn = json.loads(url_fn)
LOGGER.info(f"Source Info: {url_fn} --- {url_size}")
else:
if "|" in update2.text:
url , cfname = update2.text.split("|", 1)
cfname = cfname.strip()
filename = os.path.join(download_path, cfname)
else:
url = update2.text
if os.path.splitext(url)[1]:
filename = os.path.join(download_path, os.path.basename(url))
else:
await update2.reply("No Extension ! Use Custom Filename.")
return
url = url.strip()
filename = filename.replace('%25','_')
filename = filename.replace(' ','_')
filename = filename.replace('%40','@')
url_fn = os.path.basename(filename)
r = requests.get(url, allow_redirects=True, stream=True)
url_size = int(r.headers.get("content-length", 0))
url_size = get_size(url_size)
########################################################## Step2
msg2 = await update2.reply(f"**Source Info:**\n\nFile: `{url_fn}`\nSize: `{url_size}`\n\n**Step2:** Enter The Extension : \n Examples: \n `_.mkv` \n `_320p.mp4` \n `_.mp3` \n `32k.aac` \n `_.m4a` \n\nTo Cancel press /cancel")
try:
async with bot.conversation(update.message.chat_id) as cv:
ext1 = await cv.wait_event(events.NewMessage(update.message.chat_id))
except Exception as e:
LOGGER.info(f"Conversation 2 Error: {e}")
await msg2.delete()
await update.respond(f"**Conversation 2 Error:**\n\n{e}")
return
await msg2.delete()
if ext1.text == "/cancel":
await update.respond(f"Operation Cancelled By User. \nSend /encode to Start Again!")
return
########################################################## Step3
msg3 = await ext1.reply(
f"Source Info:**\n\nFile: `{url_fn}`\nSize: `{url_size}`\n\n**Step3:** Enter FFmpeg Options: \n\n `-sn -vn -c:a copy` \n\n `-ar 48000 -ab 256k -f mp3` \n\n `-c:s copy -c:a copy -c:v libx264` \n\n `-c:v libx264 -s 320*240 -c:a libmp3lame -ar 48000 -ab 64k -f mp4` \n\n `-c:v libx264 -vf scale=\"240:-2\" -c:a aac -ab 64k` \n\nTo Cancel press /cancel"
)
try:
async with bot.conversation(update.message.chat_id) as cv:
ffcmd1 = await cv.wait_event(events.NewMessage(update.message.chat_id))
except Exception as e:
LOGGER.info(f"Conversation 3 Error: {e}")
await update.respond(f"**Conversation 3 Error:**\n\n{e}")
await msg3.delete()
return
await msg3.delete()
if ffcmd1.text == "/cancel":
await update.respond(f"Operation Cancelled By User. \nSend /encode to Start Again!")
return
########################################################## Download
msg4 = await update.respond(f"`Processing ...`")
if not os.path.isdir(download_path):
os.mkdir(download_path)
if not update2.message.message.startswith("/") and not update2.message.message.startswith("http") and update2.message.media:
await msg4.edit(f"**⬇️ Trying to Download Media ...**")
start = time.time()
file_path = await bot.download_media(update2.message, download_path, progress_callback=lambda d, t: asyncio.get_event_loop().create_task(
progress2(d, t, msg4, start, "⬇️ Downloading Status:")))
else:
start = time.time()
try:
file_path = await download_file(url, filename, msg4, start, bot)
except Exception as e:
LOGGER.info(f"Error: {e}")
await msg4.delete()
await update.respond(f"Download Link is Invalid or Not Accessible !\n\n**Error:** {e}")
try:
os.remove(file_path)
LOGGER.info(f"Deleted: {file_path}")
except Exception as e:
LOGGER.info(f"Error Deleted: {e}")
pass
return
LOGGER.info(f"file downloaded to {file_path}")
await msg4.edit(f"✅ Successfully Downloaded.")
await asyncio.sleep(1)
ext2 = ext1.text
ffcmd2 = ffcmd1.text
ponlyname = os.path.splitext(file_path)[0]
file_loc2 = f"{ponlyname}{ext2}"
name = os.path.basename(file_loc2)
ffcmd4 = f"ffmpeg -i \"{file_path}\" {ffcmd2} \"{file_loc2}\" -y"
msg5 = await ffcmd1.reply(f"`{ffcmd4}` \n\n Encoding ... \n\n **PLZ Wait 😍 ...**")
await asyncio.sleep(1)
await msg4.delete()
########################################################## Encode
out, err, rcode, pid = await execute(f"{ffcmd4}")
if rcode != 0:
LOGGER.info(f"FFMPEG ERROR: {err}")
await msg5.edit(f"**FFmpeg: Error Occured.**\n\n{err}")
try:
os.remove(file_path)
LOGGER.info(f"Deleted: {file_path}")
os.remove(file_loc2)
LOGGER.info(f"Deleted: {file_loc2}")
except:
pass
return
LOGGER.info(out)
try:
os.remove(file_path)
LOGGER.info(f"Deleted: {file_path}")
except Exception as e:
LOGGER.info(f"{file_path} Error Deleted: {e}")
pass
########################################################## Upload
probe = await stream_creator(file_loc2)
duration = int(float(probe["format"]["duration"]))
video_type = ['.mp4','.mkv','.avi','.webm','.wmv','.mov']
vcheck = os.path.splitext(file_loc2)[1]
if vcheck in video_type:
LOGGER.info(f"Generating thumbnail")
thumbnail = await thumb_creator(file_loc2)
thumbnail = str(thumbnail)
video_stream = next((stream for stream in probe['streams'] if stream['codec_type'] == 'video'), None)
width = int(video_stream['width'] if 'width' in video_stream else 0)
height = int(video_stream['height'] if 'height' in video_stream else 0)
LOGGER.info(f"width:{width} - height:{height} - duration:{duration} - thumbnail:{thumbnail}")
else:
thumbnail = None
LOGGER.info(f"Audio - duration:{duration}")
size = os.path.getsize(file_loc2)
size = get_size(size)
await msg5.edit(f"⬆️ Uploading to Telegram ...")
start = time.time()
try:
await bot.send_file(
update.message.chat_id,
file=str(file_loc2),
thumb=thumbnail,
caption=f"`{name}` [{size}]",
reply_to=update2.message,
force_document=False,
supports_streaming=True,
progress_callback=lambda d, t: asyncio.get_event_loop().create_task(progress2(d, t, msg5, start, "⬆️ Uploading Status:", file=str(file_loc2)))
)
except Exception as e:
LOGGER.info(f"Uploading To Telegram Failed: {e}")
await update.respond(f"❌ Uploading To Telegram Failed\n\n**Error:**\n{e}")
finally:
await msg5.delete()
await update.respond(f"Send /encode to Start New Encoding")
try:
os.remove(file_loc2)
LOGGER.info(f"Deleted: {file_loc2}")
except Exception as e:
LOGGER.info(f"{file_loc2} Error Deleted: {e}")
pass
#try:
#msg6 = await update.respond(f"⬆️ Uploading to `transfer.sh`... \n\n**Name: **`{name}`\n\n**Size:** {size_of_file}")
#download_link, final_date, size = await send_to_transfersh_async(file_loc2, msg6)
#await msg6.edit(f"✅ Successfully Uploaded to `Transfer.sh` !\n\n**Name: **`{name}`\n\n**Size:** {size}\n\n**Link:** `{download_link}` \n **ExpireDate:** {final_date}")
#except Exception as e:
#print(e)
#await update.respond(f"❌ Uploading to `TRANSFER.SH` Failed \n\n **Error:** {e}")
def main():
"""Start the bot."""
print("\nBot started ...\n")
LOGGER.info(f"\nBot started ...\n")
bot.run_until_disconnected()
if __name__ == '__main__':
main()