File size: 4,675 Bytes
52dc5f7
 
 
 
 
 
 
ecb5535
52dc5f7
eb586a3
52dc5f7
eb586a3
 
52dc5f7
ecb5535
52dc5f7
 
ecb5535
51919c9
52dc5f7
 
 
4f9dc53
d15eefe
52dc5f7
d15eefe
eb586a3
d15eefe
eb586a3
52dc5f7
4f9dc53
d15eefe
ecb5535
d15eefe
ecb5535
52dc5f7
 
 
 
 
 
4f9dc53
52dc5f7
 
 
eb586a3
 
 
ecb5535
d15eefe
 
 
ecb5535
 
4f9dc53
d15eefe
 
 
 
 
 
 
 
 
 
ecb5535
52dc5f7
 
 
 
4f9dc53
 
52dc5f7
4f9dc53
 
52dc5f7
4f9dc53
 
ecb5535
 
 
 
4f9dc53
ecb5535
4f9dc53
ecb5535
4f9dc53
ecb5535
4f9dc53
 
 
 
ecb5535
4f9dc53
 
 
 
ecb5535
d15eefe
ecb5535
4f9dc53
ecb5535
 
52dc5f7
 
 
eb586a3
52dc5f7
11ddc70
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
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 FileResponse
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 files
UPLOAD_DIR = tempfile.gettempdir()

app = FastAPI()

# NOTE: The in-memory file_map has been REMOVED for a stateless design.

async def upload_to_telegram(file_path: str):
    """Uploads a file and returns the full Telegram message object."""
    if not all([SESSION_STRING, API_ID, API_HASH]):
        raise ValueError("Server is not configured with Telegram credentials.")
    async with TelegramClient(StringSession(SESSION_STRING), API_ID, API_HASH) as client:
        try:
            # force_document=True ensures it's treated as a file with a consistent filename
            message = await client.send_file(TARGET_CHANNEL, file_path, force_document=True)
            if not message or not message.media:
                raise HTTPException(status_code=500, detail="Upload failed to return a valid message.")
            return message
        except Exception as e:
            raise HTTPException(status_code=500, detail=f"Failed to upload to Telegram: {e}")

@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())

        message = await upload_to_telegram(file_location)
        doc = message.document
        
        original_filename = next((attr.file_name for attr in doc.attributes if hasattr(attr, 'file_name')), file.filename)

        return {
            "message": "File uploaded successfully. Use the 'message_id' to download.",
            "channel": TARGET_CHANNEL,
            "telegram_details": {
                "message_id": message.id,
                "file_id": doc.id,
                "file_reference": doc.file_reference.hex() if doc.file_reference else None,
                "filename": original_filename,
                "size_bytes": doc.size,
                "mime_type": doc.mime_type,
                "date": message.date.isoformat()
            }
        }
    finally:
        if os.path.exists(file_location):
            os.remove(file_location)

@app.get("/v1/download/{message_id}")
async def download_file(message_id: int):
    """
    Downloads a file from Telegram using its unique message_id from the channel.
    This method is stateless and resilient to server restarts.
    """
    if not all([SESSION_STRING, API_ID, API_HASH]):
        raise HTTPException(status_code=500, detail="Server is not configured for downloads.")

    download_path = None
    try:
        async with TelegramClient(StringSession(SESSION_STRING), API_ID, API_HASH) as client:
            # Fetch the message directly using its ID
            message = await client.get_messages(TARGET_CHANNEL, ids=message_id)
            
            if not message or not message.media:
                raise HTTPException(status_code=404, detail=f"A message with ID '{message_id}' was not found or contains no media.")

            # Determine the original filename for the response
            original_filename = message.file.name if message.file and message.file.name else f"download_{message_id}"

            # Download the file to a temporary location on the server
            download_path = await client.download_media(message, file=UPLOAD_DIR)
            
            # Stream the file back to the client
            return FileResponse(download_path, media_type='application/octet-stream', filename=original_filename)

    except Exception as e:
        raise HTTPException(status_code=500, detail=f"Failed to download from Telegram: {e}")
    finally:
        # Crucially, clean up the temporary file from the server after sending it
        if download_path and os.path.exists(download_path):
            os.remove(download_path)

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)