Mafia2008 commited on
Commit
8919e46
Β·
verified Β·
1 Parent(s): 0df5cf5

Update main.py

Browse files
Files changed (1) hide show
  1. main.py +24 -24
main.py CHANGED
@@ -1,6 +1,7 @@
1
  import os
2
  import math
3
  import logging
 
4
  from pyrogram import Client
5
  from pyrogram.session import Session, Auth
6
  from pyrogram import raw
@@ -10,17 +11,12 @@ from fastapi.responses import StreamingResponse
10
  import uvicorn
11
 
12
  # --- CONFIGURATION ---
13
- # These are loaded from the Secrets you set in Step 2
14
  API_ID = int(os.environ.get("API_ID"))
15
  API_HASH = os.environ.get("API_HASH")
16
  BOT_TOKEN = os.environ.get("BOT_TOKEN")
17
  STORAGE_CHANNEL = int(os.environ.get("STORAGE_CHANNEL"))
18
 
19
- app = FastAPI()
20
-
21
- # --- BOT CLIENT (No Login Required) ---
22
- # We use a Bot Token, so no phone number login is needed.
23
- # 'no_updates=True' makes it lighter (it won't read chat messages, only files).
24
  client = Client(
25
  "worker_bot",
26
  api_id=API_ID,
@@ -30,13 +26,29 @@ client = Client(
30
  no_updates=True
31
  )
32
 
33
- @app.on_event("startup")
34
- async def start_client():
 
 
35
  print("⏳ Connecting to Telegram...")
36
- await client.start()
37
- print("βœ… Worker Started & Connected!")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
38
 
39
- # --- STREAMING LOGIC ---
40
  class ByteStreamer:
41
  def __init__(self, client: Client):
42
  self.client = client
@@ -44,7 +56,6 @@ class ByteStreamer:
44
  async def yield_file(self, file_id, offset, first_part_cut, last_part_cut, part_count, chunk_size):
45
  client = self.client
46
 
47
- # 1. Create a direct Media Session (High Performance)
48
  ms = client.media_sessions.get(file_id.dc_id)
49
  if not ms:
50
  if file_id.dc_id != await client.storage.dc_id():
@@ -55,7 +66,6 @@ class ByteStreamer:
55
  ms = client.session
56
  client.media_sessions[file_id.dc_id] = ms
57
 
58
- # 2. Define File Location
59
  loc = raw.types.InputDocumentFileLocation(
60
  id=file_id.media_id,
61
  access_hash=file_id.access_hash,
@@ -63,7 +73,6 @@ class ByteStreamer:
63
  thumb_size=file_id.thumbnail_size
64
  )
65
 
66
- # 3. The Loop (Fetch Chunks)
67
  curr = 1
68
  while curr <= part_count:
69
  try:
@@ -75,7 +84,6 @@ class ByteStreamer:
75
  chunk = r.bytes
76
  if not chunk: break
77
 
78
- # Cut the first/last chunks if needed for seeking
79
  if part_count == 1:
80
  yield chunk[first_part_cut:last_part_cut]
81
  elif curr == 1:
@@ -95,8 +103,6 @@ class ByteStreamer:
95
  @app.get("/stream/{message_id}/{filename}")
96
  async def stream_handler(req: Request, message_id: int, filename: str):
97
  try:
98
- # 1. Fetch File Info directly from Channel (No Database needed)
99
- # We trust the Message ID passed in the URL
100
  msg = await client.get_messages(STORAGE_CHANNEL, message_id)
101
  media = msg.document or msg.video or msg.audio
102
 
@@ -106,8 +112,6 @@ async def stream_handler(req: Request, message_id: int, filename: str):
106
  file_id = FileId.decode(media.file_id)
107
  file_size = media.file_size
108
 
109
- # 2. Handle Video Seeking (Range Headers)
110
- # This allows the user to jump forward/backward in the video
111
  range_header = req.headers.get("Range", 0)
112
  from_bytes, until_bytes = 0, file_size - 1
113
  if range_header:
@@ -116,15 +120,13 @@ async def stream_handler(req: Request, message_id: int, filename: str):
116
  if s[1]: until_bytes = int(s[1])
117
 
118
  req_len = until_bytes - from_bytes + 1
119
- chunk_size = 1048576 # 1 MB Chunks
120
 
121
- # Math for calculating where to start downloading
122
  offset = (from_bytes // chunk_size) * chunk_size
123
  first_part_cut = from_bytes - offset
124
  last_part_cut = (until_bytes % chunk_size) + 1
125
  part_count = math.ceil(req_len / chunk_size)
126
 
127
- # 3. Start Streaming
128
  streamer = ByteStreamer(client)
129
  body = streamer.yield_file(file_id, offset, first_part_cut, last_part_cut, part_count, chunk_size)
130
 
@@ -143,6 +145,4 @@ async def stream_handler(req: Request, message_id: int, filename: str):
143
  raise HTTPException(404, "File Not Found")
144
 
145
  if __name__ == "__main__":
146
- # Hugging Face Spaces expect the app to run on port 7860
147
  uvicorn.run(app, host="0.0.0.0", port=7860)
148
-
 
1
  import os
2
  import math
3
  import logging
4
+ from contextlib import asynccontextmanager # <--- NEW IMPORT
5
  from pyrogram import Client
6
  from pyrogram.session import Session, Auth
7
  from pyrogram import raw
 
11
  import uvicorn
12
 
13
  # --- CONFIGURATION ---
 
14
  API_ID = int(os.environ.get("API_ID"))
15
  API_HASH = os.environ.get("API_HASH")
16
  BOT_TOKEN = os.environ.get("BOT_TOKEN")
17
  STORAGE_CHANNEL = int(os.environ.get("STORAGE_CHANNEL"))
18
 
19
+ # --- BOT CLIENT ---
 
 
 
 
20
  client = Client(
21
  "worker_bot",
22
  api_id=API_ID,
 
26
  no_updates=True
27
  )
28
 
29
+ # --- πŸš€ NEW LIFESPAN LOGIC ---
30
+ # This replaces @app.on_event("startup")
31
+ @asynccontextmanager
32
+ async def lifespan(app: FastAPI):
33
  print("⏳ Connecting to Telegram...")
34
+ try:
35
+ await client.start()
36
+ print("βœ… Worker Started & Connected!")
37
+ except Exception as e:
38
+ print(f"❌ Failed to connect: {e}")
39
+
40
+ yield # The application runs here
41
+
42
+ print("πŸ›‘ Stopping Worker...")
43
+ try:
44
+ await client.stop()
45
+ except:
46
+ pass
47
+
48
+ # Initialize FastAPI with the lifespan handler
49
+ app = FastAPI(lifespan=lifespan)
50
 
51
+ # --- STREAMING LOGIC (Unchanged) ---
52
  class ByteStreamer:
53
  def __init__(self, client: Client):
54
  self.client = client
 
56
  async def yield_file(self, file_id, offset, first_part_cut, last_part_cut, part_count, chunk_size):
57
  client = self.client
58
 
 
59
  ms = client.media_sessions.get(file_id.dc_id)
60
  if not ms:
61
  if file_id.dc_id != await client.storage.dc_id():
 
66
  ms = client.session
67
  client.media_sessions[file_id.dc_id] = ms
68
 
 
69
  loc = raw.types.InputDocumentFileLocation(
70
  id=file_id.media_id,
71
  access_hash=file_id.access_hash,
 
73
  thumb_size=file_id.thumbnail_size
74
  )
75
 
 
76
  curr = 1
77
  while curr <= part_count:
78
  try:
 
84
  chunk = r.bytes
85
  if not chunk: break
86
 
 
87
  if part_count == 1:
88
  yield chunk[first_part_cut:last_part_cut]
89
  elif curr == 1:
 
103
  @app.get("/stream/{message_id}/{filename}")
104
  async def stream_handler(req: Request, message_id: int, filename: str):
105
  try:
 
 
106
  msg = await client.get_messages(STORAGE_CHANNEL, message_id)
107
  media = msg.document or msg.video or msg.audio
108
 
 
112
  file_id = FileId.decode(media.file_id)
113
  file_size = media.file_size
114
 
 
 
115
  range_header = req.headers.get("Range", 0)
116
  from_bytes, until_bytes = 0, file_size - 1
117
  if range_header:
 
120
  if s[1]: until_bytes = int(s[1])
121
 
122
  req_len = until_bytes - from_bytes + 1
123
+ chunk_size = 1048576
124
 
 
125
  offset = (from_bytes // chunk_size) * chunk_size
126
  first_part_cut = from_bytes - offset
127
  last_part_cut = (until_bytes % chunk_size) + 1
128
  part_count = math.ceil(req_len / chunk_size)
129
 
 
130
  streamer = ByteStreamer(client)
131
  body = streamer.yield_file(file_id, offset, first_part_cut, last_part_cut, part_count, chunk_size)
132
 
 
145
  raise HTTPException(404, "File Not Found")
146
 
147
  if __name__ == "__main__":
 
148
  uvicorn.run(app, host="0.0.0.0", port=7860)