Skip to content

Instantly share code, notes, and snippets.

@Romern
Created February 18, 2024 18:34
Show Gist options
  • Save Romern/63d6f43de6a5668fcd86efd86b689d07 to your computer and use it in GitHub Desktop.
Save Romern/63d6f43de6a5668fcd86efd86b689d07 to your computer and use it in GitHub Desktop.
Download Studydrive course files
import hashlib
import requests
# app hat ratelimiting für session:
# 'x-ratelimit-limit': '30', 'x-ratelimit-remaining': '0', 'retry-after': '56', 'x-ratelimit-reset': '1708281174'
# from de.veedapp.veed.api_clients.getDocumentStorageUrl
download_secret = "studydrive-app-download-7>%jsc"
base_url = "https://gateway.production-01.studydrive.net"
session = requests.session()
def generate_download_token(document_id):
return hashlib.md5((download_secret + str(document_id)).encode("ascii")).hexdigest()
def get_download_link(document_id, session):
resp = session.get(f"{base_url}/legacy-api/v1/documents/{document_id}/download?converted_file=true&download-token={generate_download_token(document_id)}&preview=true", allow_redirects=False)
if resp.headers.get("Location") is None:
print(resp.headers)
print(resp.text)
return resp.headers.get("Location")
def get_course_documents(course_id, session):
document_ids = []
has_next_page = True
current_page = 0
while has_next_page:
resp = session.get(f"{base_url}/legacy-api/v1/feed/courses/{course_id}/documents?page={current_page}")
resp_json = resp.json()
document_ids += [f["file_id"] for f in resp_json["files"] if f.get("file_id")]
has_next_page = resp_json["last_page"] > current_page
current_page += 1
return document_ids
# values from libnative-lib.so and de.veedapp.veed.entities.Keys.getRandomSeedKey
# basically //SHA256(input_seed + VALUEfromnative).KEYfromnative
def _generate_seed_and_generate_session():
session = requests.session()
# get cookies
resp = session.get("https://www.studydrive.net/app-api-version")
for c in list(resp.cookies):
session.cookies.set(c.name, c.value)
# get seed
getSeedKeyST = {
"*5b8v$c8D%&t4Nbf": "CBf&r8WTq#!GMWcKVDXaIkOvxI&bS@IRqadCtPe28MMd*QTA2T2g$*RjUnmbyfl7",
"54qRT5W5&O!p1AC7": "c1Sv2Xz3IJy^#ljRKmgx#Sf$U1XKMAX4jVzVeS!^eHQP!sRxjjeK2msSt&0!X20Z",
"84V*x5*x#z9xE7Ic": "eaDA1%7#@*5osw7&uoO176AE$t*dliy*YrXkev4zDQ9PX21808yD4!wVO8MDj7JX",
"xOt#VgqVC^91e@@J": "lb7QjiGFczZwIlgpHtTb!fa6QkPF$wVXg43^kZt9434Cf%JpZU0SwHY1@SIiWnwe",
"vxx!%uL0v!1c3@Mm": "C2@X%o3O$#$h*fLCZK*SJVjdp8uNJ%*NVj5NrsCNFZi8TZpDRJpWGJiEDG$BRjFD"
}
resp = session.get(f"{base_url}/auth/v1/seed")
seed = resp.json()["seed"]
native_seed = list(getSeedKeyST.items())[0]
client_secret = hashlib.sha256((seed + native_seed[1]).encode("ascii")).hexdigest() + "." + native_seed[0]
# set headers
session.headers = {
"X-SD-Platform": "Android",
"X-SD-Build": "773",
"User-Agent": "Studydrive/3.18.1 (com.studydrive.app; build:2019; iOS 17.2.1) Alamofire/5.4.4",
"Sd-Client-Secret": client_secret
}
return session
def login(username, password):
session = _generate_seed_and_generate_session()
burp0_data = {
"email": username,
"password": password
}
resp = session.post(f"{base_url}/users/v1/auth/login", data=burp0_data)
resp.raise_for_status()
session.headers["Authorization"] = "Bearer " + resp.json()["access_token"]
return session
session = login("username", "password")
for d in get_course_documents(259059, session):
print(get_download_link(d, session))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment