retro-sdk 0.1.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
retro_sdk/__init__.py ADDED
@@ -0,0 +1,3 @@
1
+ from .client import Retro
2
+
3
+ __all__ = ['Retro']
retro_sdk/client.py ADDED
@@ -0,0 +1,257 @@
1
+ import requests
2
+
3
+ class Retro:
4
+ def __init__(self, refresh_token=None):
5
+ self.refresh_token = refresh_token
6
+ self.access_token = None
7
+ self.last_checked_time = None
8
+ self.web_api_key = "AIzaSyDVXcY0s4ZeREh43EYzsHqbEWcCJ6Ism5w"
9
+ if refresh_token:
10
+ self._refresh_auth_token()
11
+
12
+ def _refresh_auth_token(self):
13
+ url = f"https://securetoken.googleapis.com/v1/token?key={self.web_api_key}"
14
+ payload = {"grantType": "refresh_token", "refreshToken": self.refresh_token}
15
+ r = requests.post(url, json=payload)
16
+ try:
17
+ r.raise_for_status()
18
+ except requests.HTTPError as e:
19
+ print(f"Error: {r.text}")
20
+ raise
21
+ self.access_token = r.json().get("access_token")
22
+
23
+ def set_last_checked_time(self, time):
24
+ self.last_checked_time = time
25
+
26
+ def get_last_checked_time(self):
27
+ return self.last_checked_time
28
+
29
+ def get_auth_header(self):
30
+ return {"Authorization": f"Firebase {self.access_token}"}
31
+
32
+ def get_refresh_token(self, token, verbose=False):
33
+ url = f"https://www.googleapis.com/identitytoolkit/v3/relyingparty/verifyCustomToken?key={self.web_api_key}"
34
+ headers = {"content-type": "application/json"}
35
+ payload = {"token": token, "returnSecureToken": True}
36
+ r = requests.post(url, headers=headers, json=payload)
37
+ try:
38
+ r.raise_for_status()
39
+ except requests.HTTPError as e:
40
+ print(f"Error: {r.text}")
41
+ raise
42
+ r_json = r.json()
43
+ self.refresh_token = r_json["refreshToken"]
44
+ print(r_json)
45
+ if not verbose:
46
+ return
47
+ return r_json
48
+
49
+ def send_code(self, phone_number, custom_data=None, verbose=False):
50
+ # phone number must be in international format
51
+ # custom payload format
52
+ # {
53
+ # "data": {
54
+ # "deviceId": device_id,
55
+ # "appVersion": app_version,
56
+ # "phoneNumber": phone_number,
57
+ # "platform": platform,
58
+ # "osVersion": os_version,
59
+ # "dispatchId": dispatch_id,
60
+ # "deviceModel": device_model
61
+ # }
62
+ # }
63
+ url = "https://us-central1-retro-media.cloudfunctions.net/sendCode"
64
+ headers = {"content-type": "application/json"}
65
+ if custom_data==None:
66
+ payload = {
67
+ "data": {
68
+ "phoneNumber": phone_number
69
+ }
70
+ }
71
+ else:
72
+ payload = custom_data
73
+
74
+ r = requests.post(url, headers=headers, json=payload)
75
+ try:
76
+ r.raise_for_status()
77
+ except requests.HTTPError as e:
78
+ print(f"Error: {r.text}")
79
+ raise
80
+ r_json = r.json()
81
+ self.prev_authenticationUuid = r_json["result"]["authenticationUuid"]
82
+ self.phone_number = phone_number
83
+ if not verbose:
84
+ return r_json["result"]["authenticationUuid"]
85
+ return r_json
86
+
87
+ def verify_code(self, code, authenticationUuid=None, verbose=False):
88
+ url = "https://us-central1-retro-media.cloudfunctions.net/verifyCode"
89
+ headers = {"content-type": "application/json"}
90
+ payload = {"data": {"authenticationUuid": authenticationUuid if authenticationUuid else self.prev_authenticationUuid, "code": code}}
91
+ r = requests.post(url, headers=headers, json=payload)
92
+ try:
93
+ r.raise_for_status()
94
+ except requests.HTTPError as e:
95
+ print(f"Error: {r.text}")
96
+ raise
97
+ r_json = r.json()
98
+ self.access_token = r_json["result"]["token"]
99
+ self.get_refresh_token(self.access_token)
100
+ if not verbose:
101
+ return
102
+ return r_json
103
+
104
+ def download_profile_photo(self, user_id, filename, output_path): # make it return the image in some reasonable format
105
+ url = f"https://firebasestorage.googleapis.com/v0/b/retro-media-multi/o/profilePhotos%2F{user_id}%2F{filename}?alt=media"
106
+ r = requests.get(url, headers=self.get_auth_header())
107
+ try:
108
+ r.raise_for_status()
109
+ except requests.HTTPError as e:
110
+ print(f"Error: {r.text}")
111
+ raise
112
+ with open(output_path, "wb") as f:
113
+ f.write(r.content)
114
+ return True
115
+
116
+ def get_media_metadata(self, user_id, week, filename):
117
+ url = f"https://firebasestorage.googleapis.com/v0/b/retro-media-multi/o/media%2F{user_id}%2F{week}%2F{filename}"
118
+ r = requests.get(url, headers=self.get_auth_header())
119
+ try:
120
+ r.raise_for_status()
121
+ except requests.HTTPError as e:
122
+ print(f"Error: {r.text}")
123
+ raise
124
+ return r.json()
125
+
126
+ def list_files_in_folder(self, user_id, week):
127
+ url = "https://firebasestorage.googleapis.com/v0/b/retro-media-multi/o"
128
+ r = requests.get(url, headers=self.get_auth_header(), params={"prefix": f"media/{user_id}/{week}/", "delimiter": "/"})
129
+ try:
130
+ r.raise_for_status()
131
+ except requests.HTTPError as e:
132
+ print(f"Error: {r.text}")
133
+ raise
134
+ return r.json()
135
+
136
+ def get_filenames_in_folder(self, user_id, week):
137
+ data = self.list_files_in_folder(user_id, week)
138
+ items = data.get("items", [])
139
+ return [item["name"] for item in items] if items else []
140
+
141
+ def download_media_file(self, user_id, week, filename, output_path):
142
+ url = f"https://firebasestorage.googleapis.com/v0/b/retro-media-multi/o/media%2F{user_id}%2F{week}%2F{filename}?alt=media"
143
+ r = requests.get(url, headers=self.get_auth_header(), allow_redirects=True)
144
+ try:
145
+ r.raise_for_status()
146
+ except requests.HTTPError as e:
147
+ print(f"Error: {r.text}")
148
+ raise
149
+ with open(output_path, "wb") as f:
150
+ f.write(r.content)
151
+ return True
152
+
153
+ def profile_weeks(self, user_id, verbose=False):
154
+ url = "https://us-central1-retro-media.cloudfunctions.net/profileWeeks"
155
+ headers = {"content-type": "application/json", "Authorization": f"Bearer {self.access_token}"}
156
+ payload = {"data": {"uid": user_id}}
157
+ r = requests.post(url, headers=headers, json=payload)
158
+ try:
159
+ r.raise_for_status()
160
+ except requests.HTTPError as e:
161
+ print(f"Error: {r.text}")
162
+ raise
163
+ r_json = r.json()
164
+ if verbose:
165
+ return r_json
166
+ return r_json["result"]
167
+
168
+ def set_username(self, username, verbose=False):
169
+ url = "https://us-central1-retro-media.cloudfunctions.net/setUsername"
170
+ headers = {"content-type": "application/json", "Authorization": f"Bearer {self.access_token}"}
171
+ payload = {"data": {"username": username}}
172
+ r = requests.post(url, headers=headers, json=payload)
173
+ try:
174
+ r.raise_for_status()
175
+ except requests.HTTPError as e:
176
+ print(f"Error: {r.text}")
177
+ raise
178
+ if not verbose:
179
+ return
180
+ return r.json()
181
+
182
+ def send_friend_request(self, user_id, verbose=False):
183
+ url = "https://us-central1-retro-media.cloudfunctions.net/requestFriend"
184
+ headers = {"content-type": "application/json", "Authorization": f"Bearer {self.access_token}"}
185
+ payload = {"data": {"uid": user_id}}
186
+ r = requests.post(url, headers=headers, json=payload)
187
+ try:
188
+ r.raise_for_status()
189
+ except requests.HTTPError as e:
190
+ print(f"Error: {r.text}")
191
+ raise
192
+ if not verbose:
193
+ return
194
+ return r.json()
195
+
196
+ def cancel_friend_request(self, user_id, verbose=False):
197
+ url = "https://us-central1-retro-media.cloudfunctions.net/cancelFriendRequest"
198
+ headers = {"content-type": "application/json", "Authorization": f"Bearer {self.access_token}"}
199
+ payload = {"data": {"uid": user_id}}
200
+ r = requests.post(url, headers=headers, json=payload)
201
+ try:
202
+ r.raise_for_status()
203
+ except requests.HTTPError as e:
204
+ print(f"Error: {r.text}")
205
+ raise
206
+ if not verbose:
207
+ return
208
+ return r.json()
209
+
210
+ def unfriend(self, user_id, verbose=False):
211
+ url = "https://us-central1-retro-media.cloudfunctions.net/unfriend"
212
+ headers = {"content-type": "application/json", "Authorization": f"Bearer {self.access_token}"}
213
+ payload = {"data": {"uid": user_id}}
214
+ r = requests.post(url, headers=headers, json=payload)
215
+ try:
216
+ r.raise_for_status()
217
+ except requests.HTTPError as e:
218
+ print(f"Error: {r.text}")
219
+ raise
220
+ if not verbose:
221
+ return
222
+ return r.json()
223
+
224
+ def get_people_you_may_also_know(self, user_id, verbose=False):
225
+ url = "https://us-central1-retro-media.cloudfunctions.net/getPeopleYouMayAlsoKnow"
226
+ headers = {"content-type": "application/json", "Authorization": f"Bearer {self.access_token}"}
227
+ payload = {"data": {"uid": user_id}}
228
+ r = requests.post(url, headers=headers, json=payload)
229
+ try:
230
+ r.raise_for_status()
231
+ except requests.HTTPError as e:
232
+ print(f"Error: {r.text}")
233
+ raise
234
+ r_json = r.json()
235
+ if not verbose:
236
+ return r_json["result"]["peopleYouMayAlsoKnow"]
237
+ return r_json
238
+
239
+ def send_code_v2(self, phone_number, verbose=False):
240
+ url = "https://us-central1-retro-media.cloudfunctions.net/sendCodeV2"
241
+ headers = {"content-type": "application/json"}
242
+
243
+ def search_users(self, username, page=0): # figure out how paginating works/how to request a later page. get all pages if num > 0 (?)
244
+ url = "https://39g8v6v6qe-dsn.algolia.net/1/indexes/users/query"
245
+ headers = {"X-Algolia-API-Key": "574f0e95c4fbfe204867000799037e69", "X-Algolia-Application-Id": "39G8V6V6QE"}
246
+ r = requests.post(url, headers=headers, json={"query": username})
247
+ try:
248
+ r.raise_for_status()
249
+ except requests.HTTPError as e:
250
+ print(f"Error: {r.text}")
251
+ raise
252
+ return r.json()
253
+
254
+ def get_user_id_from_username(self, username):
255
+ results = self.search_users(username)
256
+ hits = results.get("hits", [])
257
+ return results[0].get("objectID") if hits else None
@@ -0,0 +1,7 @@
1
+ Metadata-Version: 2.4
2
+ Name: retro-sdk
3
+ Version: 0.1.0
4
+ Summary: python sdk for retro, the photo sharing app!
5
+ License-File: LICENSE
6
+ Requires-Python: >=3.8
7
+ Requires-Dist: requests
@@ -0,0 +1,6 @@
1
+ retro_sdk/__init__.py,sha256=Et20PuBrVk_EGUREW4PNqyAMbXal98zGA7SaxFLav3A,46
2
+ retro_sdk/client.py,sha256=gcB6mjX0H_WYP5hIitYAZabjqrNwehI751lXdj1Trks,10360
3
+ retro_sdk-0.1.0.dist-info/METADATA,sha256=XssAXQMx3Vp758Hg_RS6IA95OqoVNJ2QWUOqgq-arw8,176
4
+ retro_sdk-0.1.0.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
5
+ retro_sdk-0.1.0.dist-info/licenses/LICENSE,sha256=P_qoGY0EubHZ4AKG0F2UbX7M7MCo3boK6dACbMlVaCU,1066
6
+ retro_sdk-0.1.0.dist-info/RECORD,,
@@ -0,0 +1,4 @@
1
+ Wheel-Version: 1.0
2
+ Generator: hatchling 1.27.0
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Sofia Egan
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.