File size: 4,004 Bytes
52dc5f7 d78e844 849ac8b 52dc5f7 ecb5535 52dc5f7 eb586a3 52dc5f7 eb586a3 52dc5f7 ecb5535 52dc5f7 d78e844 51919c9 52dc5f7 4f9dc53 52dc5f7 eb586a3 d78e844 ecb5535 849ac8b d78e844 d15eefe d78e844 52dc5f7 4f9dc53 d78e844 52dc5f7 849ac8b 52dc5f7 4f9dc53 ecb5535 849ac8b ecb5535 849ac8b ecb5535 849ac8b 4f9dc53 849ac8b d78e844 |
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 |
import os
import asyncio
from telethon.sync import TelegramClient
from telethon.sessions import StringSession
from fastapi import FastAPI, UploadFile, File, HTTPException
from fastapi.responses import StreamingResponse
import uvicorn
import tempfile
# --- Configuration from environment variables ---
SESSION_STRING = os.environ.get('SESSION_STRING')
API_ID = os.environ.get('API_ID')
API_HASH = os.environ.get('API_HASH')
# The Telegram channel to use as file storage
TARGET_CHANNEL = 'https://t.me/TestNAI01'
# Use the system's temporary directory for transient uploads
UPLOAD_DIR = tempfile.gettempdir()
app = FastAPI()
@app.post("/v1/upload")
async def upload_file(file: UploadFile = File(...)):
"""
Uploads a file to Telegram and returns its persistent message_id and other details.
"""
file_location = os.path.join(UPLOAD_DIR, file.filename)
try:
with open(file_location, "wb+") as file_object:
file_object.write(file.file.read())
async with TelegramClient(StringSession(SESSION_STRING), API_ID, API_HASH) as client:
message = await client.send_file(TARGET_CHANNEL, file_location, force_document=True)
if not message or not message.media:
raise HTTPException(status_code=500, detail="Upload failed to return a valid message.")
doc = message.document
original_filename = next((attr.file_name for attr in doc.attributes if hasattr(attr, 'file_name')), file.filename)
# Simplified response with only the essentials
return {
"message": "File uploaded successfully. Use the 'message_id' to download.",
"telegram_details": {
"message_id": message.id,
"filename": original_filename,
"size_bytes": doc.size,
"date": message.date.isoformat()
}
}
except Exception as e:
raise HTTPException(status_code=500, detail=f"Failed to upload to Telegram: {e}")
finally:
if os.path.exists(file_location):
os.remove(file_location)
@app.get("/v1/download/{message_id}")
async def download_file(message_id: int):
"""
Streams a file directly from Telegram to the client, ensuring a fast download start.
"""
if not all([SESSION_STRING, API_ID, API_HASH]):
raise HTTPException(status_code=500, detail="Server is not configured for downloads.")
client = TelegramClient(StringSession(SESSION_STRING), API_ID, API_HASH)
await client.connect()
try:
message = await client.get_messages(TARGET_CHANNEL, ids=message_id)
if not message or not message.media:
raise HTTPException(status_code=404, detail=f"Message not found or has no media.")
except Exception as e:
await client.disconnect()
raise HTTPException(status_code=500, detail=f"Could not retrieve file details: {e}")
original_filename = message.file.name if message.file and message.file.name else f"download_{message_id}"
mime_type = message.file.mime_type if message.file else 'application/octet-stream'
headers = {
'Content-Disposition': f'attachment; filename="{original_filename}"'
}
async def file_iterator():
"""This async generator streams the file and ensures the client disconnects."""
try:
# Stream the file chunk by chunk
async for chunk in client.iter_download(message):
yield chunk
finally:
# Crucially, disconnect after the download is complete or fails
await client.disconnect()
return StreamingResponse(file_iterator(), media_type=mime_type, headers=headers)
if __name__ == "__main__":
if not all([SESSION_STRING, API_ID, API_HASH]):
print("FATAL ERROR: The environment variables SESSION_STRING, API_ID, and API_HASH must be set.")
else:
uvicorn.run(app, host="0.0.0.0", port=8000) |