rkihacker commited on
Commit
d78e844
·
verified ·
1 Parent(s): 69bfb34

Update main.py

Browse files
Files changed (1) hide show
  1. main.py +53 -48
main.py CHANGED
@@ -2,8 +2,9 @@ import os
2
  import asyncio
3
  from telethon.sync import TelegramClient
4
  from telethon.sessions import StringSession
5
- from fastapi import FastAPI, UploadFile, File, HTTPException, BackgroundTasks
6
- from fastapi.responses import FileResponse
 
7
  import uvicorn
8
  import tempfile
9
 
@@ -15,24 +16,11 @@ API_HASH = os.environ.get('API_HASH')
15
  # The Telegram channel to use as file storage
16
  TARGET_CHANNEL = 'https://t.me/TestNAI01'
17
 
18
- # Use the system's temporary directory for transient files
19
  UPLOAD_DIR = tempfile.gettempdir()
20
 
21
  app = FastAPI()
22
 
23
- async def upload_to_telegram(file_path: str):
24
- """Uploads a file and returns the full Telegram message object."""
25
- if not all([SESSION_STRING, API_ID, API_HASH]):
26
- raise ValueError("Server is not configured with Telegram credentials.")
27
- async with TelegramClient(StringSession(SESSION_STRING), API_ID, API_HASH) as client:
28
- try:
29
- message = await client.send_file(TARGET_CHANNEL, file_path, force_document=True)
30
- if not message or not message.media:
31
- raise HTTPException(status_code=500, detail="Upload failed to return a valid message.")
32
- return message
33
- except Exception as e:
34
- raise HTTPException(status_code=500, detail=f"Failed to upload to Telegram: {e}")
35
-
36
  @app.post("/v1/upload")
37
  async def upload_file(file: UploadFile = File(...)):
38
  """
@@ -43,55 +31,72 @@ async def upload_file(file: UploadFile = File(...)):
43
  with open(file_location, "wb+") as file_object:
44
  file_object.write(file.file.read())
45
 
46
- message = await upload_to_telegram(file_location)
47
- doc = message.document
48
-
49
- original_filename = next((attr.file_name for attr in doc.attributes if hasattr(attr, 'file_name')), file.filename)
 
 
 
50
 
51
- # Return details without the channel link, as requested.
52
- return {
53
- "message": "File uploaded successfully. Use the 'message_id' to download.",
54
- "telegram_details": {
55
- "message_id": message.id,
56
- "file_id": doc.id,
57
- "file_reference": doc.file_reference.hex() if doc.file_reference else None,
58
- "filename": original_filename,
59
- "size_bytes": doc.size,
60
- "mime_type": doc.mime_type,
61
- "date": message.date.isoformat()
62
  }
63
- }
 
64
  finally:
65
  if os.path.exists(file_location):
66
  os.remove(file_location)
67
 
68
  @app.get("/v1/download/{message_id}")
69
- async def download_file(message_id: int, background_tasks: BackgroundTasks):
70
  """
71
- Downloads a file from Telegram using its unique message_id from the channel.
72
- This method is stateless and resilient to server restarts.
73
  """
74
  if not all([SESSION_STRING, API_ID, API_HASH]):
75
  raise HTTPException(status_code=500, detail="Server is not configured for downloads.")
76
 
77
  try:
78
  async with TelegramClient(StringSession(SESSION_STRING), API_ID, API_HASH) as client:
 
79
  message = await client.get_messages(TARGET_CHANNEL, ids=message_id)
80
 
81
- if not message or not message.media:
82
- raise HTTPException(status_code=440, detail=f"A message with ID '{message_id}' was not found or contains no media.")
83
 
84
- original_filename = message.file.name if message.file and message.file.name else f"download_{message_id}"
85
- download_path = await client.download_media(message, file=UPLOAD_DIR)
86
-
87
- # **THE FIX IS HERE:**
88
- # The os.remove is now a background task. It will only run AFTER the
89
- # FileResponse has been fully sent to the client, preventing the error.
90
- if download_path:
91
- background_tasks.add_task(os.remove, download_path)
 
 
 
 
92
 
93
- return FileResponse(download_path, media_type='application/octet-stream', filename=original_filename)
 
 
 
 
 
94
 
95
  except Exception as e:
96
- # Catch potential errors like file not found in Telegram
97
- raise HTTPException(status_code=500, detail=f"Failed to download from Telegram: {e}")
 
 
 
 
 
 
2
  import asyncio
3
  from telethon.sync import TelegramClient
4
  from telethon.sessions import StringSession
5
+ from telethon.tl.functions.upload import GetFileRequest
6
+ from fastapi import FastAPI, UploadFile, File, HTTPException
7
+ from fastapi.responses import RedirectResponse
8
  import uvicorn
9
  import tempfile
10
 
 
16
  # The Telegram channel to use as file storage
17
  TARGET_CHANNEL = 'https://t.me/TestNAI01'
18
 
19
+ # Use the system's temporary directory for transient uploads
20
  UPLOAD_DIR = tempfile.gettempdir()
21
 
22
  app = FastAPI()
23
 
 
 
 
 
 
 
 
 
 
 
 
 
 
24
  @app.post("/v1/upload")
25
  async def upload_file(file: UploadFile = File(...)):
26
  """
 
31
  with open(file_location, "wb+") as file_object:
32
  file_object.write(file.file.read())
33
 
34
+ async with TelegramClient(StringSession(SESSION_STRING), API_ID, API_HASH) as client:
35
+ message = await client.send_file(TARGET_CHANNEL, file_location, force_document=True)
36
+ if not message or not message.media:
37
+ raise HTTPException(status_code=500, detail="Upload failed to return a valid message.")
38
+
39
+ doc = message.document
40
+ original_filename = next((attr.file_name for attr in doc.attributes if hasattr(attr, 'file_name')), file.filename)
41
 
42
+ return {
43
+ "message": "File uploaded successfully. Use the 'message_id' to download.",
44
+ "telegram_details": {
45
+ "message_id": message.id,
46
+ "filename": original_filename,
47
+ "size_bytes": doc.size,
48
+ "mime_type": doc.mime_type,
49
+ "date": message.date.isoformat()
50
+ }
 
 
51
  }
52
+ except Exception as e:
53
+ raise HTTPException(status_code=500, detail=f"Failed to upload to Telegram: {e}")
54
  finally:
55
  if os.path.exists(file_location):
56
  os.remove(file_location)
57
 
58
  @app.get("/v1/download/{message_id}")
59
+ async def download_file(message_id: int):
60
  """
61
+ Generates a direct, temporary download link from Telegram's CDN and redirects the client to it.
62
+ This is extremely fast and efficient.
63
  """
64
  if not all([SESSION_STRING, API_ID, API_HASH]):
65
  raise HTTPException(status_code=500, detail="Server is not configured for downloads.")
66
 
67
  try:
68
  async with TelegramClient(StringSession(SESSION_STRING), API_ID, API_HASH) as client:
69
+ # Get the message object
70
  message = await client.get_messages(TARGET_CHANNEL, ids=message_id)
71
 
72
+ if not message or not message.document:
73
+ raise HTTPException(status_code=404, detail=f"A message with ID '{message_id}' was not found or is not a file.")
74
 
75
+ # Get the data center information where the file is stored
76
+ dc_id, location = message.document.dc_id, message.document
77
+
78
+ # Use a low-level request to generate a temporary download URL
79
+ # This is the key to creating a CDN link
80
+ req = GetFileRequest(
81
+ location=location,
82
+ cdn_supported=True,
83
+ offset=0,
84
+ limit=0
85
+ )
86
+ result = await client(req)
87
 
88
+ # The result contains the temporary URL.
89
+ # Format: https://{cdn_redirect_ip}/.../{file_token}
90
+ cdn_url = f"https://{result.cdn_redirect}/file/{result.bytes.hex()}"
91
+
92
+ # Immediately redirect the user's client to this URL
93
+ return RedirectResponse(url=cdn_url, status_code=307)
94
 
95
  except Exception as e:
96
+ raise HTTPException(status_code=500, detail=f"Failed to generate download link: {e}")
97
+
98
+ if __name__ == "__main__":
99
+ if not all([SESSION_STRING, API_ID, API_HASH]):
100
+ print("FATAL ERROR: The environment variables SESSION_STRING, API_ID, and API_HASH must be set.")
101
+ else:
102
+ uvicorn.run(app, host="0.0.0.0", port=8000)