SalexAI commited on
Commit
a3a5495
·
verified ·
1 Parent(s): 507ae32

Create app.py

Browse files
Files changed (1) hide show
  1. app.py +89 -0
app.py ADDED
@@ -0,0 +1,89 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from fastapi import FastAPI
2
+ from fastapi.middleware.cors import CORSMiddleware
3
+ import requests
4
+ import json
5
+
6
+ app = FastAPI()
7
+
8
+ # Allow all CORS so browser apps can call this
9
+ app.add_middleware(
10
+ CORSMiddleware,
11
+ allow_origins=["*"],
12
+ allow_methods=["*"],
13
+ allow_headers=["*"],
14
+ )
15
+
16
+ BASE_62_CHAR_SET = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
17
+
18
+ def base62_to_int(e):
19
+ t = 0
20
+ for n in range(len(e)):
21
+ t = t * 62 + BASE_62_CHAR_SET.index(e[n])
22
+ return t
23
+
24
+ def get_base_url(token):
25
+ t = token[0]
26
+ n = base62_to_int(token[1]) if t == "A" else base62_to_int(token[1:3])
27
+ server_partition = n
28
+ base_url = f"https://p{server_partition:02d}-sharedstreams.icloud.com/{token}/sharedstreams/"
29
+ return base_url
30
+
31
+ def get_redirected_base_url(base_url, token):
32
+ url = base_url + "webstream"
33
+ headers = {
34
+ 'Origin': 'https://www.icloud.com',
35
+ 'Content-Type': 'text/plain',
36
+ }
37
+ data = '{"streamCtag":null}'
38
+ response = requests.post(url, headers=headers, data=data, allow_redirects=False)
39
+
40
+ if response.status_code == 330:
41
+ body = response.json()
42
+ new_base_url = f"https://{body['X-Apple-MMe-Host']}/{token}/sharedstreams/"
43
+ return new_base_url
44
+ return base_url
45
+
46
+ def get_metadata(base_url):
47
+ url = base_url + "webstream"
48
+ headers = {
49
+ 'Origin': 'https://www.icloud.com',
50
+ 'Content-Type': 'text/plain',
51
+ }
52
+ data = '{"streamCtag":null}'
53
+ response = requests.post(url, headers=headers, data=data)
54
+ return response.json().get("photos", [])
55
+
56
+ def get_asset_urls(base_url, guids):
57
+ url = base_url + "webasseturls"
58
+ headers = {
59
+ 'Origin': 'https://www.icloud.com',
60
+ 'Content-Type': 'text/plain',
61
+ }
62
+ data = json.dumps({"photoGuids": guids})
63
+ response = requests.post(url, headers=headers, data=data)
64
+ return response.json().get("items", {})
65
+
66
+ @app.get("/album/{token}")
67
+ def get_album(token: str):
68
+ try:
69
+ base_url = get_base_url(token)
70
+ base_url = get_redirected_base_url(base_url, token)
71
+ metadata = get_metadata(base_url)
72
+ guids = [p["photoGuid"] for p in metadata]
73
+ urls = get_asset_urls(base_url, guids)
74
+
75
+ video_list = []
76
+ for photo in metadata:
77
+ for derivative in photo.get("derivatives", {}).values():
78
+ if derivative.get("mediaAssetType") == "video":
79
+ checksum = derivative.get("checksum")
80
+ if checksum in urls:
81
+ video_url = f"https://{urls[checksum]['url_location']}{urls[checksum]['url_path']}"
82
+ video_list.append({
83
+ "caption": photo.get("caption", ""),
84
+ "url": video_url
85
+ })
86
+ return {"videos": video_list}
87
+
88
+ except Exception as e:
89
+ return {"error": str(e)}