commit 561a3dd5398ef8cacf166a6df4ad4179682a0aad Author: TPD94 <> Date: Fri Nov 17 00:52:41 2023 -0500 CDRM-Bot 2.0 diff --git a/discord/bot-token.txt b/discord/bot-token.txt new file mode 100644 index 0000000..e69de29 diff --git a/helper_scripts/DB_Cache/__init__.py b/helper_scripts/DB_Cache/__init__.py new file mode 100644 index 0000000..c683f9d --- /dev/null +++ b/helper_scripts/DB_Cache/__init__.py @@ -0,0 +1,5 @@ +from . import cache_key +from . import check_database +from . import create_database +from . import key_count +from . import upload_database diff --git a/helper_scripts/DB_Cache/__pycache__/__init__.cpython-310.pyc b/helper_scripts/DB_Cache/__pycache__/__init__.cpython-310.pyc new file mode 100644 index 0000000..d83c26a Binary files /dev/null and b/helper_scripts/DB_Cache/__pycache__/__init__.cpython-310.pyc differ diff --git a/helper_scripts/DB_Cache/__pycache__/cache_key.cpython-310.pyc b/helper_scripts/DB_Cache/__pycache__/cache_key.cpython-310.pyc new file mode 100644 index 0000000..bbeffcd Binary files /dev/null and b/helper_scripts/DB_Cache/__pycache__/cache_key.cpython-310.pyc differ diff --git a/helper_scripts/DB_Cache/__pycache__/check_database.cpython-310.pyc b/helper_scripts/DB_Cache/__pycache__/check_database.cpython-310.pyc new file mode 100644 index 0000000..00dbb9e Binary files /dev/null and b/helper_scripts/DB_Cache/__pycache__/check_database.cpython-310.pyc differ diff --git a/helper_scripts/DB_Cache/__pycache__/create_database.cpython-310.pyc b/helper_scripts/DB_Cache/__pycache__/create_database.cpython-310.pyc new file mode 100644 index 0000000..28843d2 Binary files /dev/null and b/helper_scripts/DB_Cache/__pycache__/create_database.cpython-310.pyc differ diff --git a/helper_scripts/DB_Cache/__pycache__/key_count.cpython-310.pyc b/helper_scripts/DB_Cache/__pycache__/key_count.cpython-310.pyc new file mode 100644 index 0000000..a6f0d0d Binary files /dev/null and b/helper_scripts/DB_Cache/__pycache__/key_count.cpython-310.pyc differ diff --git a/helper_scripts/DB_Cache/__pycache__/upload_database.cpython-310.pyc b/helper_scripts/DB_Cache/__pycache__/upload_database.cpython-310.pyc new file mode 100644 index 0000000..8183844 Binary files /dev/null and b/helper_scripts/DB_Cache/__pycache__/upload_database.cpython-310.pyc differ diff --git a/helper_scripts/DB_Cache/cache_key.py b/helper_scripts/DB_Cache/cache_key.py new file mode 100644 index 0000000..a2696eb --- /dev/null +++ b/helper_scripts/DB_Cache/cache_key.py @@ -0,0 +1,16 @@ +# Import dependencies + +import sqlite3 +import os + +# Get the current working directory +main_directory = os.getcwd() + + +# Define cache function +def cache_keys(pssh: str, keys: str): + dbconnection = sqlite3.connect(f"{main_directory}\\keys\\database.db") + dbcursor = dbconnection.cursor() + dbcursor.execute("INSERT or REPLACE INTO database VALUES (?, ?)", (pssh, keys)) + dbconnection.commit() + dbconnection.close() \ No newline at end of file diff --git a/helper_scripts/DB_Cache/check_database.py b/helper_scripts/DB_Cache/check_database.py new file mode 100644 index 0000000..23007f8 --- /dev/null +++ b/helper_scripts/DB_Cache/check_database.py @@ -0,0 +1,24 @@ +# Import dependencies + +import sqlite3 +import os + +# Get the current working directory +main_directory = os.getcwd() + + +# Define check database function +def check_database(pssh: str): + dbconnection = sqlite3.connect(f"{main_directory}\\keys\\database.db") + dbcursor = dbconnection.cursor() + dbcursor.execute("SELECT keys FROM database WHERE pssh = :pssh", {"pssh": pssh}) + vaultkeys = dbcursor.fetchall() + if vaultkeys: + vaultkey = str(vaultkeys[0]) + stripped_vault_key = vaultkey.strip(",'()") + formatted_vault_key = stripped_vault_key.replace('\\n', '\n') + dbconnection.close() + return formatted_vault_key + else: + dbconnection.close() + return "Not found" diff --git a/helper_scripts/DB_Cache/create_database.py b/helper_scripts/DB_Cache/create_database.py new file mode 100644 index 0000000..2324361 --- /dev/null +++ b/helper_scripts/DB_Cache/create_database.py @@ -0,0 +1,21 @@ +# import dependencies + +import sqlite3 +import os + + +# Check to see if the database already exists, if not create a keys folder, and create the database. +def create_database(): + # Check to see if the "keys" directory exists, if not creates it + if "keys" not in os.listdir(): + os.makedirs('keys') + + # Change to the keys directory + os.chdir("keys") + + # Check to see if a database exists in keys directory, if not create it + if not os.path.isfile("database.db"): + dbconnection = sqlite3.connect("database.db") + dbcursor = dbconnection.cursor() + dbcursor.execute('CREATE TABLE IF NOT EXISTS "DATABASE" ( "pssh" TEXT, "keys" TEXT, PRIMARY KEY("pssh") )') + dbconnection.close() \ No newline at end of file diff --git a/helper_scripts/DB_Cache/key_count.py b/helper_scripts/DB_Cache/key_count.py new file mode 100644 index 0000000..53ce115 --- /dev/null +++ b/helper_scripts/DB_Cache/key_count.py @@ -0,0 +1,18 @@ +# Import dependencies + +import sqlite3 +import os + +# Get the current working directory +main_directory = os.getcwd() + + +# Define key count function +def key_count(): + dbconnection = sqlite3.connect("database.db") + dbcursor = dbconnection.cursor() + dbcursor.execute("SELECT COUNT (*) FROM database") + result = list(dbcursor) + formatted_result = str(result) + stripped_result = formatted_result.strip("[](),") + return stripped_result diff --git a/helper_scripts/DB_Cache/upload_database.py b/helper_scripts/DB_Cache/upload_database.py new file mode 100644 index 0000000..8f72d93 --- /dev/null +++ b/helper_scripts/DB_Cache/upload_database.py @@ -0,0 +1,21 @@ +# Import dependencies + +import sqlite3 +import os +import requests + +# Get the current working directory +main_directory = os.getcwd() + + +# Define upload database function +def upload_database(): + upload_name = "database.db" + files = { + 'files[]': (f'{upload_name}', open(f'{main_directory}\\keys\\database.db', 'rb')), + } + url = 'https://up1.fileditch.com/upload.php' + response = requests.post(url, files=files) + data = response.json() + upload_url = f"{data['files'][0]['url']}" + return upload_url diff --git a/helper_scripts/TPD_Keys/TPD_Keys_CDRM_Bot.py b/helper_scripts/TPD_Keys/TPD_Keys_CDRM_Bot.py new file mode 100644 index 0000000..0c8286b --- /dev/null +++ b/helper_scripts/TPD_Keys/TPD_Keys_CDRM_Bot.py @@ -0,0 +1,99 @@ +# import dependencies +import os +from pywidevine import PSSH +from pywidevine import Cdm +from pywidevine import Device +import requests +import glob + +# Get the current working directory +main_directory = os.getcwd() + +# Making sure a .wvd file exists and using that as the extracted device +try: + extracted_device = glob.glob(f'{main_directory}\\helper_scripts\\TPD_Keys\\CDMs\\*.wvd')[0] +except: + extracted_cdm = None + print(f"Please place a WVD in {main_directory}\\helper_scripts\\TPD_Keys\\CDMs") + + +# Defining decrypt function +def decrypt_content(pssh: str = None, license_url: str = None, + auth_token: str = None, xdt_auth_token: str = None, + service_certificate: bool = None): + # prepare pssh + try: + pssh = PSSH(pssh) + except: + return "Invalid PSSH" + + # load device + device = Device.load(extracted_device) + + # load CDM from device + cdm = Cdm.from_device(device) + + # open CDM session + session_id = cdm.open() + + # get service certificate if set to true + if service_certificate: + service_cert = requests.post( + url=license_url, + data=cdm.service_certificate_challenge + ) + if service_cert.status_code != 200: + return "Unable to retrieve service certificate" + service_cert = service_cert.content + cdm.set_service_certificate(session_id, service_cert) + + # get license challenge + challenge = cdm.get_license_challenge(session_id, pssh, privacy_mode=service_certificate) + + # send license challenge + if xdt_auth_token and auth_token is None: + licence = requests.post( + url=license_url, + data=challenge, + headers={ + 'x-dt-auth-token': xdt_auth_token, + } + ) + elif auth_token and xdt_auth_token is None: + licence = requests.post( + url=license_url, + data=challenge, + headers={ + 'Authorization': auth_token, + } + ) + else: + licence = requests.post( + url=license_url, + data=challenge + ) + if licence.status_code != 200: + return "Could not complete license challenge" + licence = licence.content + + # parse license challenge + cdm.parse_license(session_id, licence) + + # assign variable for returned keys + returned_keys = "" + for key in cdm.get_keys(session_id): + if key.type != "SIGNING": + returned_keys += f"{key.kid.hex}:{key.key.hex()}\n" + + # close session, disposes of session data + cdm.close(session_id) + + return returned_keys + + +def key_test(): + keys = decrypt_content( + pssh="AAAAW3Bzc2gAAAAA7e+LqXnWSs6jyCfc1R0h7QAAADsIARIQ62dqu8s0Xpa7z2FmMPGj2hoNd2lkZXZpbmVfdGVzdCIQZmtqM2xqYVNkZmFsa3IzaioCSEQyAA==", + license_url="https://cwip-shaka-proxy.appspot.com/no_auth", + service_certificate=True) + return keys diff --git a/helper_scripts/TPD_Keys/__init__.py b/helper_scripts/TPD_Keys/__init__.py new file mode 100644 index 0000000..ae5bb04 --- /dev/null +++ b/helper_scripts/TPD_Keys/__init__.py @@ -0,0 +1 @@ +from .TPD_Keys_CDRM_Bot import * \ No newline at end of file diff --git a/helper_scripts/TPD_Keys/__pycache__/TPD_Keys_CDRM_Bot.cpython-310.pyc b/helper_scripts/TPD_Keys/__pycache__/TPD_Keys_CDRM_Bot.cpython-310.pyc new file mode 100644 index 0000000..15bac55 Binary files /dev/null and b/helper_scripts/TPD_Keys/__pycache__/TPD_Keys_CDRM_Bot.cpython-310.pyc differ diff --git a/helper_scripts/TPD_Keys/__pycache__/__init__.cpython-310.pyc b/helper_scripts/TPD_Keys/__pycache__/__init__.cpython-310.pyc new file mode 100644 index 0000000..35a64e2 Binary files /dev/null and b/helper_scripts/TPD_Keys/__pycache__/__init__.cpython-310.pyc differ diff --git a/helper_scripts/anime_api/__init__.py b/helper_scripts/anime_api/__init__.py new file mode 100644 index 0000000..d3a3c58 --- /dev/null +++ b/helper_scripts/anime_api/__init__.py @@ -0,0 +1 @@ +from . import waifu_pics \ No newline at end of file diff --git a/helper_scripts/anime_api/__pycache__/__init__.cpython-310.pyc b/helper_scripts/anime_api/__pycache__/__init__.cpython-310.pyc new file mode 100644 index 0000000..ff1d556 Binary files /dev/null and b/helper_scripts/anime_api/__pycache__/__init__.cpython-310.pyc differ diff --git a/helper_scripts/anime_api/__pycache__/waifu_pics.cpython-310.pyc b/helper_scripts/anime_api/__pycache__/waifu_pics.cpython-310.pyc new file mode 100644 index 0000000..5b789ce Binary files /dev/null and b/helper_scripts/anime_api/__pycache__/waifu_pics.cpython-310.pyc differ diff --git a/helper_scripts/anime_api/waifu_pics.py b/helper_scripts/anime_api/waifu_pics.py new file mode 100644 index 0000000..2b90374 --- /dev/null +++ b/helper_scripts/anime_api/waifu_pics.py @@ -0,0 +1,16 @@ +# Import dependencies +import requests + + +# Define get image function +def get_image(): + image = requests.get(url="https://api.waifu.pics/sfw/waifu") + image = image.json()["url"] + return image + + +# Define get NSFW image +def get_image_nsfw(): + image = requests.get(url="https://api.waifu.pics/nsfw/waifu") + image = image.json()["url"] + return image diff --git a/main.py b/main.py new file mode 100644 index 0000000..4e6f965 --- /dev/null +++ b/main.py @@ -0,0 +1,136 @@ +# Import dependencies +import os + +import interactions + +from helper_scripts import TPD_Keys +from helper_scripts import DB_Cache +from helper_scripts import anime_api +from interactions import * + +# Get current working directory +main_directory = os.getcwd() + +# Define bot +bot = Client(intents=Intents.DEFAULT) + +# Check if discord bot token file exists, if not create file +if not os.path.isfile(f"{main_directory}\\discord\\bot-token.txt"): + with open(f'{main_directory}\\discord\\bot-token.txt', 'w') as discord_bot_token: + print("Please put your bot token in /discord/bot-token.txt") + discord_bot_token.write("Delete this and place your bot token on this line") + exit() + +# Check if bot token exists and if it has been changed +with open(f'{main_directory}\\discord\\bot-token.txt') as discord_bot_token: + bot_token = discord_bot_token.readline() + if bot_token == "Delete this and place your bot token on this line": + print("Please put your bot token in /discord/bot-token.txt") + exit() + +# Place your discord bot token here. +discord_bot_token = bot_token + +# Check / Create keys database if it doesn't exist +DB_Cache.create_database.create_database() + + +# Defining decrypt command +@slash_command( + name="decrypt", + description="Decrypt widevine protected content" +) +# PSSH slash option +@slash_option( + name="pssh", + description="Protection Scheme Specific Header", + required=True, + opt_type=OptionType.STRING, +) +@slash_option( + name="license_url", + description="License URL", + required=True, + opt_type=OptionType.STRING, +) +@slash_option( + name="auth_bearer", + description="Authorization: Bearer token", + required=False, + opt_type=OptionType.STRING, +) +@slash_option( + name="x_dt_auth", + description="X-DT-Auth token", + required=False, + opt_type=OptionType.STRING, +) +async def decrypt(ctx: SlashContext, pssh: str, license_url: str, + auth_bearer: str = None, x_dt_auth: str = None): + keys = TPD_Keys.decrypt_content(pssh=pssh, license_url=license_url, auth_token=auth_bearer, xdt_auth_token=x_dt_auth) + if keys != "Unable to retrieve service certificate" and keys != "Could not complete license challenge" and keys != "Invalid PSSH": + DB_Cache.cache_key.cache_keys(pssh=pssh, keys=keys) + embed = interactions.Embed(title="uWu") + embed.set_image(url=f"{anime_api.waifu_pics.get_image()}") + await ctx.send(f"Keys:\n\n```{keys}```", embed=embed) + else: + await ctx.send(f"An error occurred `{keys}`!") + + +# Defining search database command +@slash_command( + name="search_database", + description="Search CDRM-Bot's database" +) +@slash_option( + name="pssh", + description="Protection Scheme Specific Header", + required=True, + opt_type=OptionType.STRING, +) +async def search_database(ctx: SlashContext, pssh: str): + keys = DB_Cache.check_database.check_database(pssh=pssh) + if keys != "Not found": + await ctx.send(f"Found key for PSSH `{pssh}` :\n\n```{keys}```") + else: + await ctx.send(f"No keys found for `{pssh}`\n\n Why not use `/decrypt` and add it?") + + +# Defining key count command +@slash_command( + name="key_count", + description="Check how many keys I have!" +) +async def key_count(ctx: SlashContext): + await ctx.send(f"I have {DB_Cache.key_count.key_count()} keys in my vault!") + + +# Defining upload database command +@slash_command( + name="upload_database", + description="Upload my database to fileditch" +) +async def upload_database(ctx: SlashContext): + message = await ctx.send("Uploading...") + db_url = DB_Cache.upload_database.upload_database() + embed = interactions.Embed( + title="CDRM-Bot key database", + description=f"{db_url}" + ) + embed.set_footer(text="Brought to you by TPD94") + await message.edit(content="Finished!", embeds=embed) + + +# Defining uwu command +@slash_command( + name="uwu", + description="Send a NSFW image to #stuff-you-wouldnt-post-on-general" +) +async def uwu(ctx: SlashContext): + channel = await bot.fetch_channel(1123340072322863124, force=True) + embed = interactions.Embed(title="uWu") + embed.set_image(url=f"{anime_api.waifu_pics.get_image_nsfw()}") + uwu = await channel.send(embed=embed) + await ctx.send(f"Posted in #{uwu.channel.name}", ephemeral=True) + +bot.start(token=discord_bot_token) diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..f8078ee --- /dev/null +++ b/requirements.txt @@ -0,0 +1,3 @@ +discord-py-interactions +pywidevine +requests \ No newline at end of file