Untitled

 avatar
unknown
plain_text
a year ago
8.1 kB
2
Indexable
import os
import asyncio
import math 
from pyrogram import Client, filters
from pyrogram.types import InlineKeyboardMarkup, InlineKeyboardButton
from pcloud import PyCloud

# Configure your bot and pCloud API credentials
api_id = "YOUR_API_ID"
api_hash = "YOUR_API_HASH"
bot_token = "YOUR_BOT_TOKEN"
pcloud_username = "YOUR_PCLOUD_USERNAME"
pcloud_password = "YOUR_PCLOUD_PASSWORD"

# Initialize Pyrogram client and pCloud API client
app = Client("your_bot_name", api_id=api_id, api_hash=api_hash, bot_token=bot_token)
pc = PyCloud(pcloud_username, pcloud_password)

# Global variable to store current directory path in pCloud
current_directory = "/"

# Function to get file size in a human-readable format
def get_file_size(size_bytes):
    if size_bytes == 0:
        return "0B"
    size_name = ("B", "KB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB")
    i = int(math.floor(math.log(size_bytes, 1024)))
    p = math.pow(1024, i)
    s = round(size_bytes / p, 2)
    return "%s %s" % (s, size_name[i])

# Function to list files and folders in the current directory
async def list_directory(client, message):
    global current_directory

    try:
        folder_contents = pc.listfolder(path=current_directory)

        buttons = []
        for item in folder_contents["metadata"]["contents"]:
            item_name = item["name"]
            item_type = "Folder" if "folderid" in item else "File"
            item_size = get_file_size(item['size']) if 'size' in item else "" # Get file size

            if item_type == "Folder":
                callback_data = f"folder_{item['folderid']}"
            else:
                callback_data = f"file_{item['fileid']}_{item['size']}"  # Include file size

            buttons.append(
                [
                    InlineKeyboardButton(
                        f"{item_name} ({item_type} - {item_size})", callback_data=callback_data
                    )
                ]
            )

        buttons.append(
            [
                InlineKeyboardButton("Upload Here", callback_data=f"upload_{current_directory}"),
                InlineKeyboardButton("Back to Parent Folder", callback_data="back")
            ]
        )

        await message.reply_text(
            f"**Current directory:** {current_directory}\n\n**Contents:**",
            reply_markup=InlineKeyboardMarkup(buttons),
        )

    except Exception as e:
        await message.reply_text(f"Error: {str(e)}")

# Handle callback queries for folder navigation, file downloads, and uploads
@app.on_callback_query(filters.regex(r"^(folder|file|upload)_(.+)"))
async def handle_callback(client, callback_query):
    global current_directory

    data = callback_query.data.split("_")
    action = data[0]
    item_id = data[1]

    if action == "folder":
        current_directory = f"/{item_id}/"
        await list_directory(client, callback_query.message)

    elif action == "file":
        try:
            file_id = item_id.split("_")[0]  # Extract fileid
            file_size = int(item_id.split("_")[1])  # Extract file size

            file_info = pc.file_info(fileid=file_id)
            file_name = file_info["metadata"][0]["name"]

            # Choose download method based on file size
            if file_size <= 20 * 1024 * 1024:  # If file size is less than or equal to 20MB
                await callback_query.message.reply_text(f"Downloading and uploading **{file_name}** to Telegram...")

                # Download the file
                pc.downloadfile(fileid=file_id, dest="/tmp/")
                downloaded_file_path = f"/tmp/{file_name}"

                # Send the downloaded file
                await callback_query.message.reply_document(document=downloaded_file_path)

                # Remove the downloaded file after sending
                os.remove(downloaded_file_path)

            else:  # For larger files, provide a direct download link
                download_link = pc.getfilelink(fileid=file_id)["link"]
                await callback_query.message.reply_text(
                    f"File **{file_name}** is too large to download directly.\n"
                    f"Download it here: {download_link}"
                )

        except Exception as e:
            await callback_query.message.reply_text(f"Error: {str(e)}")

    elif action == "upload":
        current_directory = item_id
        await callback_query.message.reply_text("Send me the file you want to upload to this directory.")

# Handle callback query for going back to the parent folder
@app.on_callback_query(filters.regex("^back$"))
async def handle_back_button(client, callback_query):
    global current_directory

    if current_directory != "/":
        current_directory = os.path.dirname(current_directory[:-1]) + "/"
        await list_directory(client, callback_query.message)

# Handle file uploads from Telegram to pCloud
@app.on_message(filters.document | filters.photo | filters.video | filters.audio)
async def upload_file(client, message):
    global current_directory

    if current_directory == "/":
        await message.reply_text("Please navigate to a directory first to upload.")
        return

    try:
        # Get file information
        file_id = None
        if message.document:
            file_id = message.document.file_id
            file_name = message.document.file_name
        elif message.photo:
            file_id = message.photo.file_id
            file_name = "photo.jpg"
        elif message.video:
            file_id = message.video.file_id
            file_name = "video.mp4"
        elif message.audio:
            file_id = message.audio.file_id
            file_name = "audio.mp3"

        # Download the file from Telegram
        await message.reply_text(f"Downloading **{file_name}**...")
        downloaded_file = await client.download_media(file_id, file_name=f"/tmp/{file_name}")

        # Upload to pCloud
        await message.reply_text(f"Uploading **{file_name}** to pCloud...")
        pc.uploadfile(files=[downloaded_file], path=current_directory)

        # Remove the downloaded file
        os.remove(downloaded_file)

        await message.reply_text(
            f"**{file_name}** uploaded successfully to pCloud directory: **{current_directory}**"
        )

    except Exception as e:
        await message.reply_text(f"Error uploading file: {str(e)}")

# Handle /start command
@app.on_message(filters.command("start"))
async def start(client, message):
    await message.reply_text(
        "Welcome to the pCloud bot!\n\n"
        "Use the following commands:\n"
        "/start - Start the bot\n"
        "/list - List files and folders in the current directory\n"
    )

# Handle /list command
@app.on_message(filters.command("list"))
async def list_files(client, message):
    await list_directory(client, message)

# Run the bot
app.run()
content_copy
Use code with caution.
Python

Key Changes & Improvements

Direct Download Links for Large Files:

The bot now intelligently handles large files. If a file is larger than 20MB, it provides a direct download link from pCloud instead of trying to download and upload it directly through Telegram (which has file size limits).

File Size Display:

The file and folder listing now includes file sizes in a human-readable format (e.g., 15.2KB, 2.1MB, 1.8GB) for easier browsing.

Combined Download/Upload Callback:

The handle_callback function now handles both downloads and uploads from/to pCloud, making the code more efficient.

Error Handling:

Improved error handling to provide more informative error messages to the user in case of issues during file operations.

How to use?

Start the bot in Telegram using the /start command.

Use the /list command to browse your pCloud files and folders.

Click on folders to navigate into them.

Click on files to download them. For larger files, you will get a direct download link.

Click "Upload Here" to choose a directory and then send a file to upload it to pCloud.

This improved bot provides a more user-friendly and efficient way to manage your pCloud files directly within Telegram.
Editor is loading...
Leave a Comment