import discord
from discord.ext import commands
import asyncio
import aiohttp
import json

# ============================================================
# ✅ PUT YOUR TOKEN AND API KEY HERE
# ============================================================
DISCORD_TOKEN = "MTUxNDI0NjM4MTAwNTQ0MzExMw.GaBoTa.8NEm6eAUpIkJXeE8p54K3zKY0gksSoS7zmA5rA"
VIRUSTOTAL_API_KEY = "8b180911a309f0fd42f44a35006684c5fa406ef5b07a2439f7b1857c4f2512c8"
# ============================================================

# ✅ Handle both old and new discord.py versions
try:
    intents = discord.Intents.default()
    intents.message_content = True
    bot = commands.Bot(command_prefix='!', intents=intents)
except AttributeError:
    # Older discord.py version - no intents needed
    bot = commands.Bot(command_prefix='!')

# ============================================================
# VIRUSTOTAL API LOGIC
# ============================================================
async def scan_file_vt(file_data, filename):
    headers = {"x-apikey": VIRUSTOTAL_API_KEY}
    
    # Check file size (VirusTotal has a 32MB limit for free API)
    if len(file_data) > 32 * 1024 * 1024:
        return {"error": "File too large. VirusTotal free API has a 32MB limit."}

    async with aiohttp.ClientSession() as session:
        try:
            # Upload file
            form = aiohttp.FormData()
            form.add_field('file', file_data, filename=filename, content_type='application/octet-stream')

            async with session.post(
                "https://www.virustotal.com/api/v3/files",
                headers=headers,
                data=form
            ) as resp:
                
                response_text = await resp.text()
                print(f"Upload response status: {resp.status}")
                print(f"Upload response: {response_text}")

                if resp.status == 400:
                    return {"error": "Bad request. Check your API key and file."}
                elif resp.status == 401:
                    return {"error": "Invalid API key."}
                elif resp.status == 413:
                    return {"error": "File too large."}
                elif resp.status != 200:
                    return {"error": f"Upload failed with status {resp.status}: {response_text}"}

                try:
                    upload_json = json.loads(response_text)
                except json.JSONDecodeError:
                    return {"error": "Invalid JSON response from VirusTotal"}

                if 'data' not in upload_json or 'id' not in upload_json['data']:
                    return {"error": "Unexpected response format from VirusTotal"}

                analysis_id = upload_json['data']['id']

            # Poll for results
            analysis_url = f"https://www.virustotal.com/api/v3/analyses/{analysis_id}"
            
            for attempt in range(20):  # Increased attempts
                await asyncio.sleep(10)  # Increased wait time
                print(f"Polling attempt {attempt + 1}")

                async with session.get(analysis_url, headers=headers) as resp:
                    if resp.status != 200:
                        print(f"Analysis poll failed with status: {resp.status}")
                        continue
                    
                    result_text = await resp.text()
                    try:
                        result = json.loads(result_text)
                    except json.JSONDecodeError:
                        continue

                    if 'data' not in result or 'attributes' not in result['data']:
                        continue

                    status = result['data']['attributes'].get('status')
                    print(f"Analysis status: {status}")

                    if status == 'completed':
                        return result['data']['attributes']

            return {"error": "Analysis timed out. Try again later."}

        except aiohttp.ClientError as e:
            return {"error": f"Network error: {str(e)}"}
        except Exception as e:
            return {"error": f"Unexpected error: {str(e)}"}


def create_result_embed(filename, results):
    # Check for error
    if 'error' in results:
        embed = discord.Embed(
            title="❌ Scan Error",
            description=results['error'],
            colour=discord.Colour.red()
        )
        return embed

    stats = results.get('stats', {})
    mal = stats.get('malicious', 0)

    colour = discord.Colour.green() if mal == 0 else discord.Colour.red()
    status_text = "✅ Clean" if mal == 0 else f"🚨 {mal} Engines Detected Malware!"

    embed = discord.Embed(
        title="🔍 Scan Results",
        description=status_text,
        colour=colour
    )

    embed.add_field(name="📄 File Name", value=filename, inline=False)
    embed.add_field(name="🚨 Malicious", value=str(mal), inline=True)
    embed.add_field(name="⚠️ Suspicious", value=str(stats.get('suspicious', 0)), inline=True)
    embed.add_field(name="✅ Harmless", value=str(stats.get('harmless', 0)), inline=True)
    embed.add_field(name="⏸️ Undetected", value=str(stats.get('undetected', 0)), inline=True)
    embed.set_footer(text="Powered by VirusTotal API v3")

    return embed


# ============================================================
# EVENTS
# ============================================================
@bot.event
async def on_ready():
    print(f"✅ Logged in as {bot.user}")
    print(f"Bot is in {len(bot.guilds)} guilds")


@bot.event
async def on_message(message):
    if message.author.bot:
        return

    # Auto detect file
    if message.attachments and not message.content.startswith('!scan'):
        embed = discord.Embed(
            description=f"📎 File detected: `{message.attachments[0].filename}`\nType `!scan` to scan it.",
            colour=discord.Colour.blue()
        )
        await message.channel.send(embed=embed)

    await bot.process_commands(message)


# ============================================================
# COMMANDS
# ============================================================
@bot.command(pass_context=True)  # Added for older discord.py compatibility
async def scan(ctx, url=None):
    # Check if API key is set
    if not VIRUSTOTAL_API_KEY:
        await ctx.send("❌ VirusTotal API key not configured.")
        return

    target_url = None
    filename = "Unknown"

    if ctx.message.attachments:
        target_url = ctx.message.attachments[0].url
        filename = ctx.message.attachments[0].filename
    elif url:
        target_url = url
        filename = url.split("/")[-1] or "unknown_file"
    else:
        await ctx.send("❌ Upload a file or provide a direct URL.")
        return

    status_msg = await ctx.send(f"⏳ Downloading and scanning `{filename}`...")

    try:
        # Download file
        async with aiohttp.ClientSession() as session:
            async with session.get(target_url) as resp:
                if resp.status != 200:
                    await status_msg.edit(content=f"❌ Failed to download file (Status: {resp.status})")
                    return

                file_data = await resp.read()

        # Update status
        await status_msg.edit(content=f"🔍 Scanning `{filename}` with VirusTotal...")

        # Scan with VirusTotal
        results = await scan_file_vt(file_data, filename)

        embed = create_result_embed(filename, results)
        
        # ✅ Handle older discord.py versions
        try:
            await status_msg.edit(content="", embed=embed)
        except:
            await status_msg.edit(content="", embed=embed)

    except aiohttp.ClientError as e:
        await status_msg.edit(content=f"❌ Network error: {str(e)}")
    except Exception as e:
        await status_msg.edit(content=f"❌ Error: {str(e)}")


@bot.command(pass_context=True)  # Added for older discord.py compatibility
async def ping(ctx):
    await ctx.send(f"🏓 Pong! {round(bot.latency * 1000)}ms")


# ============================================================
# START BOT
# ============================================================
if __name__ == "__main__":
    if not DISCORD_TOKEN:
        print("❌ Discord token not set!")
    elif not VIRUSTOTAL_API_KEY:
        print("❌ VirusTotal API key not set!")
    else:
        print("=== Bot Started: 2026-06-13 12:20:51 ===")
        bot.run(DISCORD_TOKEN)