MENG21 commited on
Commit
7de960a
·
1 Parent(s): 4dcf425
Files changed (3) hide show
  1. app.py +38 -27
  2. encrypted_grades.csv +1 -1
  3. requirements.txt +2 -1
app.py CHANGED
@@ -8,6 +8,7 @@ from dotenv import load_dotenv
8
  from google.oauth2.credentials import Credentials
9
  from google_auth_oauthlib.flow import Flow
10
  from google.auth.transport.requests import Request
 
11
  import json
12
  import logging
13
  from oauthlib.oauth2.rfc6749.errors import InvalidGrantError
@@ -96,42 +97,45 @@ def load_data():
96
  st.error(f"Error decrypting file: {str(e)}")
97
  return pd.DataFrame()
98
 
 
 
 
 
 
 
 
 
 
 
99
  # Main function to run the Streamlit app
100
  def main():
101
  st.title('📚 Student Grade Lookup')
102
  st.markdown("---")
103
 
104
  if not is_logged_in():
105
- st.write("Please log in with your CSPC Google account to access the grade lookup.")
106
 
107
  if st.button("Login with Google"):
108
  flow = create_flow()
109
  authorization_url, _ = flow.authorization_url(prompt="consent")
110
  st.markdown(f"[Login with Google]({authorization_url})")
111
  else:
112
- st.write("You are logged in.")
113
- # Load the data
114
- df = load_data()
115
-
116
- # Create two columns
117
- col1, col2 = st.columns([2, 1])
118
-
119
- with col1:
120
- # Create an input field for the student ID
121
- student_id = st.text_input('Enter Student ID:', placeholder="e.g., C21101100")
122
-
123
- with col2:
124
- st.write("")
125
- st.write("")
126
- search_button = st.button('Search', use_container_width=True)
127
-
128
- if student_id and search_button:
129
  # Search for the student in the dataframe
130
- student = df[df['ID'].astype(str) == student_id]
131
 
132
  if not student.empty:
133
  st.markdown("---")
134
- st.subheader('Student Information:')
135
 
136
  # Display student information in a more structured way
137
  col1, col2 = st.columns(2)
@@ -141,7 +145,7 @@ def main():
141
  st.write(f"{student['NAME'].values[0]}")
142
 
143
  st.markdown("<p class='big-font'>ID</p>", unsafe_allow_html=True)
144
- st.write(f"{student_id}")
145
 
146
  with col2:
147
  st.markdown("<p class='big-font'>Grade</p>", unsafe_allow_html=True)
@@ -176,10 +180,11 @@ def main():
176
  warning_message = "Warning: Your current status is Conditional. You need to pass or achieve a higher grade in the final term to improve your standing."
177
  st.markdown(f"<p class='warning-message'>{warning_message}</p>", unsafe_allow_html=True)
178
  else:
179
- st.error('Student ID not found. Please try again.')
180
 
181
  if st.button("Logout"):
182
- del st.session_state['credentials']
 
183
  st.rerun()
184
 
185
  # Function to handle OAuth callback
@@ -189,17 +194,23 @@ def handle_callback():
189
  flow.fetch_token(code=st.query_params["code"])
190
  credentials = flow.credentials
191
  st.session_state['credentials'] = credentials.to_json()
 
192
  logging.debug("Token fetch successful")
193
  st.success("Authentication successful!")
194
- return credentials
 
195
  except Exception as e:
196
- pass
197
- # logging.error(f"Error during authentication: {str(e)}")
198
- # st.error(f"Authentication failed: {str(e)}")
 
 
199
 
200
  if __name__ == '__main__':
201
  logging.debug("Starting the application")
202
  if 'code' in st.query_params:
203
  logging.debug("Authorization code found in query parameters")
204
  handle_callback()
 
 
205
  main()
 
8
  from google.oauth2.credentials import Credentials
9
  from google_auth_oauthlib.flow import Flow
10
  from google.auth.transport.requests import Request
11
+ from googleapiclient.discovery import build
12
  import json
13
  import logging
14
  from oauthlib.oauth2.rfc6749.errors import InvalidGrantError
 
97
  st.error(f"Error decrypting file: {str(e)}")
98
  return pd.DataFrame()
99
 
100
+ # Function to get user info
101
+ def get_user_info(credentials):
102
+ try:
103
+ service = build('oauth2', 'v2', credentials=credentials)
104
+ user_info = service.userinfo().get().execute()
105
+ return user_info
106
+ except Exception as e:
107
+ logging.error(f"Error getting user info: {str(e)}")
108
+ return None
109
+
110
  # Main function to run the Streamlit app
111
  def main():
112
  st.title('📚 Student Grade Lookup')
113
  st.markdown("---")
114
 
115
  if not is_logged_in():
116
+ st.write("Please log in with your CSPC Google account to access your grade.")
117
 
118
  if st.button("Login with Google"):
119
  flow = create_flow()
120
  authorization_url, _ = flow.authorization_url(prompt="consent")
121
  st.markdown(f"[Login with Google]({authorization_url})")
122
  else:
123
+ credentials = Credentials.from_authorized_user_info(json.loads(st.session_state['credentials']))
124
+ user_info = get_user_info(credentials)
125
+
126
+ if user_info:
127
+ st.write(f"Welcome, {user_info['name']}!")
128
+ user_email = user_info['email']
129
+
130
+ # Load the data
131
+ df = load_data()
132
+
 
 
 
 
 
 
 
133
  # Search for the student in the dataframe
134
+ student = df[df['EMAIL'].str.lower() == user_email.lower()]
135
 
136
  if not student.empty:
137
  st.markdown("---")
138
+ st.subheader('Your Grade Information:')
139
 
140
  # Display student information in a more structured way
141
  col1, col2 = st.columns(2)
 
145
  st.write(f"{student['NAME'].values[0]}")
146
 
147
  st.markdown("<p class='big-font'>ID</p>", unsafe_allow_html=True)
148
+ st.write(f"{student['ID'].values[0]}")
149
 
150
  with col2:
151
  st.markdown("<p class='big-font'>Grade</p>", unsafe_allow_html=True)
 
180
  warning_message = "Warning: Your current status is Conditional. You need to pass or achieve a higher grade in the final term to improve your standing."
181
  st.markdown(f"<p class='warning-message'>{warning_message}</p>", unsafe_allow_html=True)
182
  else:
183
+ st.error('Your email is not found in our records. Please contact the administrator.')
184
 
185
  if st.button("Logout"):
186
+ for key in list(st.session_state.keys()):
187
+ del st.session_state[key]
188
  st.rerun()
189
 
190
  # Function to handle OAuth callback
 
194
  flow.fetch_token(code=st.query_params["code"])
195
  credentials = flow.credentials
196
  st.session_state['credentials'] = credentials.to_json()
197
+ st.session_state['authenticated'] = True
198
  logging.debug("Token fetch successful")
199
  st.success("Authentication successful!")
200
+ time.sleep(2) # Give user time to see the success message
201
+ st.rerun() # Rerun the app to clear the URL parameters
202
  except Exception as e:
203
+ logging.error(f"Error during authentication: {str(e)}")
204
+ st.error(f"Authentication failed: {str(e)}")
205
+ st.session_state['authenticated'] = False
206
+ if 'credentials' in st.session_state:
207
+ del st.session_state['credentials']
208
 
209
  if __name__ == '__main__':
210
  logging.debug("Starting the application")
211
  if 'code' in st.query_params:
212
  logging.debug("Authorization code found in query parameters")
213
  handle_callback()
214
+ elif st.session_state.get('authenticated', False):
215
+ st.success("You are already authenticated.")
216
  main()
encrypted_grades.csv CHANGED
@@ -1 +1 @@
1
- gAAAAABnCzvQkdijpH0UWU-RFltkNepJxjW0BPNe4oq_z9UAdEthgq-Mo8uV18Akp3Utsif5XaULqMqRWOHMn6fuh3nzdorLwkx2NTTTAJ9lFcY_E4eqpWb5npvMkIstJPKZfuOk98u0hs4BDdL0s2ZoR7RWDGM20SSINqoypdL4rUEb3I4xhKLOC1qTcDVvYCDzPLhEr4Mp_bgEH241XfflcVdr2Ak940nJk8gPTqW-TYHG_m_VsmEq5Fu2tpv-UKcthJ6jsH4HjPbp_Z25tZJUJWhHGlTN5V_kmCpPbDQKGSOm9xjoelzLQcfxPSvqJAFfn5ky0XhdZ69gGTXDePZ6ghCjuORc68VsLUuBjvoiBhXZ0RRcka0QQqw5PQ2OLZZjnHjc-8YN2QKMqAr9Fqr5iHPL46ISmdhQhiE4X49T8n-FHTVhViOhl4Z22CMk9zSdJwPV5qw-3S0gAfEDZEnFlzr84AqUiHbVIG08QiQqvZUrh73HCytrBuh_cvGBxf-VlMwETfLuG5MdWYRyKWOwyKz1GAThURgSrAI8AxJa8lnbt6955R82q6yaj4MiqQaW09xNKkRs0V8exntBOGixR5bR5dxY9s6rjk9p94nXuu1ua-FV4e6AG15Dvk3xib68trXkwfJIONY5QiM7-yD5vb7XbFO4T5V3MQAqUvhseGTIdnkyNdd5vz7SHVyWW7hWqjLcuM0A2RuO7P0WiRsJd7UgjvbCns1rmdkc7c2INVNp8BC9UUk7F5vCj4Ekqpxo8i8Z7EbL-81sBLV4aGIcbEhIJPoKMYuJTzl4_lJkg6CQ0hy3NuDBrSaDptngG1J7J2CfOC7GCA8HEiDpmMg_K_FdiK2qLKXvBryFmwfgiuOPFzXYxsgrB8HpTJe83VikG3sqnLGDBOOo90UFW6eZQrRNWsotJXgz7PaVGIGmmPRzX0Q65YOVSwfM4pZwaJxTFVQV5PKexg4O2hRWH8NEgssKQck5OqnA-iBmbhP_MsF3ZhPTsz1ocQTiwYc1msVNUTjauRNf9Xtf-NvakbiXHpPOSgO4oWWJnZxitUS5YvH1WD8rom4P3IapviF5tIJ8TjJPUE3JxyksU7M4egvTOHHzKbiprQ1VBgJY1CFfjGr11l_BSLQfOyIXlkmTU6dZIlQj23jRDiAvP2aSVvGwzZwDhWOJLxSIopeBKaEKSXbrU-4HNpYU2ff2b5Z-S21g0Uq83Of_k0t2v3XloUWRuL1AEcsAPVkF_v_xKwTP6obeYtAIEKTqMWGluUOvDczIrP1HX2O2_NC9QpzG2PYJKbu1qSRiPccXi3ABfHieOsIweGb7tIxniDiyQrelvUb9kTQYqx9e7xMS-L1o979ZsahjMXTT1H2OEIex-qiuso5ya6KBioFqs2nW_29WShXyeScsJo1rqR78QSoCcNRiAVfiqclspeDThA6SJaV0Z0EUKZGPiOoqPl8spbPXldapaNCBwy700xCRCvECKlp7a-pH048n4QhoamdB4Xp9rxwkD2CBpLT5GxRD_lSJpQpbLo4hxWs3maOTkAQkLC32-l_BmkF5WtoBr4NyP-boQ6AufhAWiYDEKca7RTqCjv7J0JXLGwzgCpbHCNqvgD4P9pML2IQGZma12D070hQeqhJXz_dagOt-dcL4EYENENvfXFLMv31sxOWLFX_YJYk7M3493hx-vAcO4RuHZUoZXRqSJs0AHqmnVABAE5qY4bOCKy3zqFV7iEIXTzbLrGDlz0lK0gF0H28eTvD8n-BlM-qumDOA9iX5Te7MlNIjjQUk17XN6jRcdVKrcx4nVj68zKYywucbv4UnGKrIl26RYYVpduVvQIdTg-AZ1brD6-unM_04RRwSbJdfUhxsPik_UBCSeuWokmHFzQSDxF5wnpJLync6_pGeXh9y8sJxk7rt71lzh_kh1oIBdg7SSU5esuTbTY3jL1AdNgA8wraxFII-uygP7Ljm49bUlvUl0zN3pwM7qIgDc00RHYwzoa4VslaS1g09Pqc3VX-oRukQzLAMczpq17ovFQvipHWYinSjly486HWGuktK-b1bMQ2fgD5BYqJYlzI1tpZfK9enozUr1EEbFg7fJwoRCBrt8Rt-HfCqvoctwZXS3JvW-v6uf81y5RIHdCsiBVlCsJ88PFT_F84yGw7Ka5fedd5q3FBHyCxjBB_k_2FAd95phRbGrvOcvGI4Nei1X7SZOwJSR50Hm-bMtb9jbTL-zNMF1ub8P7gPeF2LIBVWnYIoj_Ncj-My9Ett75J03bc6x_CLW5VDqLJHx63PJ1Vi1wLkkkk7EIbJCXAzw3bmf4o2iqQg2EqCGNJQqlryMGFtKlloO8bjmKep9ln9fdMg9nj1Je-W5jiVA5M4ks5RV_FnasYJj7zZi4eaAPVMsMSFIf6U1rUMlfOZkLJM_lpOfavmZCykcFq9p0LlfnM8PzNHvEmlcFXC8tiwtxBgpxZk38S7XK-8uJQq4440aAMwNOKz7Qm24WxIKf1KuNBCPmRpGTGaSTJLEWnGRWo1Dxv7fXQt4llAm-EbNOUB5LpSclxcosZeO_w20-D5BzjsVlHq1DT69OZ16MnBrVcnOGOfKNAGWGD2ctDvsSzjF9f7j1NaSlZQs2RhuHqOEpe_bYoC-w-Wn3GoAWVhfhq0WGSI-lhzD4kgv2FLUgAG-7b0MGXbD57gKSmz6TKcKq82k3JmUcozx2g13dy9uJW7tDrFN2QkLnfTsI6JSJwf81M8EnLAv7l7p6C8lp6k2FteNX3b6hYTe0UUzJy8JVMgiWpdpt_kn0X1F59R6au3Iq30fUU7d7yieSwdgbRbb4KZVUQBaxK7bclIm6S8AturXJTyYsZxCbd2Doz-RS6AcDT6_cWMmqITwYkGgOLLzIfTpvLhtyDJcmGH7aRJjQuVZs_De3h4kLn3VwRrf2YD3L57tZa6RyStlYsp87ZksQCtC8fgzsZr95INq8nQmRnMT9hGIAACYBspTPgMdoUPh2t37MACVSUT_Sc4XFxERL4mIzmy-PuKi6OinXQ4TLu9dr-7bU0QS-R79YWvinKE1ZWaDp3fw6bOMeOrNj39YVGTrUYBlWXf0-dnqafduSIiIY7z8K6y7TqM-Jp4su8ePjr1a5xaVRQ8D5tik4m1IztgT8M5Cq9wq2nklW_u539SwJ6HcVs8CVYPF25TqtfxKn4huLOviAEaHQ5VwLDYdt0jQ94BShdk94H_vG5dnMri_Z22GdjnZHJHT5S4nJp2YCVME7ihO6YmpNUwExOWOlNROiYxTu-4faf1AN-IsCB1DLicEoyLgF8xTL5pB9fhdxJwqduqmDMGR5zipcl0GbMJzAx7PHc0kSS5sfPiNQc9WuUcI4tZT-FXy0WwqtHq018ounp_GPfqJ467ET2iSijh1SjET7I8uUIw7xQFKxbYINYDs1wnWh4PY7ym-LQvOEZRbUG_j9FRMy2rBoz-C3kK8E7Rl6dAv7QmyYKaLnMY4Q8o4i65lhRUpOzhCjiqkWJvUF1c-WVQmUdjumCviyo4yjn_6K5vSP344FKlGgw8CxZGlh4r45j-7yRncZ2NSlg4DFKFZaPMIf4-_5-_LflVLGP1NSElRWbqTSIVB0ZqjAeCXasxqFSWceoE52IHiOiHBAgM_C6MWkB6_3-2NhZjAV8GecOl6Wutgcwgm9jtp6r4MD3JkQeogyUrMT5KQl8hh9Jd58UDMGQYmgQqrST7JnSoz8rBa3n9H3YkZfgM31jBbBpiihmcS80NjIJCJjFpEqTnZ1ILUbfBBxDgJGlrk4NTuXtz4LRAB1oz2kXgwDaMx8uJjahS3az_1pBcq6amEX7FK0bnItBu1S-CMw14n-PW4wFR_P1HXKfvRyNifupQfqwyQ3gn-pcm22vUeIH171wNWe0odMrUgJ_NS1V2X4aC8sb9v6ZYfMVzPzKX_RUkM4gv0AMfC8wcECji9_5xViZgF4N2XR4TqX3KlD-WqrPUJZl1shQfrbal_ylhhBJFsM4OtH9UFjCqmoIZehHyTp07iZRPbqSPR0Z-LbubBs--L0PaR2YnQSr89XVC4JHMQZNzZ4LrlZA0LHI8EMs9GG4Ic9kGKVg03LiBDb1vyb42LIeizojwBhHFwVtMOgPLSNW3DU9Jk0NFM7ymC7bDpQ0uwLtFsImAGTivhs9JqMh4QjGHwpUWzgIPpxGLOuyFNs0Id25L5rdh06X4h7MvEkRrwXXNhUZz8eMWXbI9VX_SUVpYF8JQwWDmOK7aV9lCrTQIQ7Nt0if5GMark-UKJygb29ZOrt5NyGUDJ8wth7VQNLFirsKA_o653K_RWDu85vkH6RpfgjvFYOFY5fsqVYso0bT0_ieYIk-PN0w1gEEHiCqTzLymci3eB4YTGv907WyHJteMjL2sgWy-GqQJlh0PXUx-xKmSLaZP46-ylm3956xTnnsoHmOKAOpe9BGTL17D2hciWfyXPv2qwam7Dy6tytG6DB2g-efKM0kYwqohKCtrCmZDqnYuZu1y4nyG-KRWRprAwA_CmuOU_DLDHvYdMIOyCGwW1bew9zqfHbqjQMVVYhTNZ2-hxPwzj9yOUxP9AICHFldHmuqHrow2JPMPJ4c5Yc98OJDOTSMlV7A5UROH9xNnnjE6bDvYBkKcqY45HVbhsZYalCqfVrrCvIemYh3VdSW8qaeVRCSzTJvY9r8JcKGn9SqLKR82mO_eksrDcoxcVtPT1eb3Ocmkc7MTvehGvHFJ8L76rv5qdQ4Pd5qoiJe9aL-k5E5-TdFYHJzNU17NbolUQJDG4684O8jMHTd8Q4ZOT6FN8L0snahEgm3AbvSdawzDDz2BnMVWVW41CVKhg85oCgTdMz8L2KA4HxUortPdkdGUhjte9IPRPFodACJTlrEbFJRrg6eyUWzxWEQv0myC1ay3CQR3FpRlonBtImPTXkvqVS4XuGID3pbF9rxxJKbHkxgvtzJom8I2iCp1h7iO_mMo1_XUGvevrDqHboX0yeFsz2Y-QcMTeNoZ4UaMMKkWXqMD-9bb867TNB4hDpt2yLK1xZv0DSKTz1iJ4b_DAmosp6Unnn18ncd8AzQM5hSn5Q==
 
1
+ gAAAAABnC1i2yFabbB-OM79Oj1t0FtsrKYI3bVog_tXt4BlspouWua6MmzCNM5mcyJ-Ww0nUy0Q4LLdzgA0RZ8P90l1ff3JaNG7jI_BcmSApOdWIRl-f0UU99qzZsa2nW6l6T6rYR_uhVQ6eYG6wg1nF0QP6ogzbD7tELtOHfYwUh7wZKzpz8FrBMll7MNjZOXaM9rUsMDJc-jc3QlEgPbQwEW58AupiYltQw5t6rczU1xHUeVMIfnEjD_nwKFsQGDEoBVclsbdKicSVKTC0xODrZascD4JiKG2moXB_4iDEvb9RI9brfcts616mjLE-6Bp4qV6732aHzKobzGvjFMkCBXdm3ly9mbEyoDoRQZ9woNJB-vJ_dF2wczf291ujZvm-ug-Z0YqU9QcC8rETUfvqz-HV4mUfSeCIbsrOgxL9iJd9AtcCS6cMvucPF1IT3_DbMEa9-IIrszxm2XQiJoUYHBINFEjoVy_odhTU1l-qn-qOOLX6hU_uEqHcPBn2CmLOVH2To2zTGHzU5Uni8SeCIdHkLcBMIypbfOOTkvcHly6ZkQllHwPAEUpydXKD2efQpCZJVG2n9f8kNdeoqPmu5RBdC3B8z9ZASGaPH7hyIwzwM93F5HofDrhaSJY8gM8Hj7GXSN9iTA1RekRV0lrQ2EuPYZVWvCbkd9LhjOfyqKt_ntPXih1U8qMQ4kxjYVKHJyflPpCzaIbw8JTzo_U_W93kJozSEAxSOpM8-avjdlF-JrZXOcP-FgxwavyYFxFTu1tJH3vG8torI2hMDksY5Gz4YxzAPOJKx86k97NpQU4pqYJtZiXRtuPrUqzR_WlJtopAlZlVQjLu5uM6VsxKSg9j6wGkyy4XKBxUJPeo4tdrpxEO3ZHIoIQ4UfvZ6qCMRYvJj4njlcfT9rlFvT49_hO7FKYnP3NAJLRdrP81S3UCVMJnOKURw24JJpiG5R-rfkrssIhCH248N4deZhpG8HciIedyAa2GyV68QUqF8HY2UUdDK5HIXRwf60Zoys-4z7zFTsJUweihJieG0q-RuRW0A_1CE2n_EmJAgo7YCFRLykukqaerSN5-LAd6o1kkuKitAJcFVnWA_JNlwhWD-990-3xzaj-zkEYtztI-0x3vtXIxesd0jxRynR3uyx3q9nIbkz7lT1ltorKbGgVrvcFyI6GS0a3-PXMsHrDUfQhP2yN449uuXLmiNzqUcRv83MFfH_6XkJV9RIsWAjS-Ao1NtT-QzPOxXx77Olq7sVz0JLe52YMD-yJXIBeHgMErAgg-88yq8Sii_6qGbgBtA3qD2IEV-BVi_9-tOM379RBu2zfT-T3jzOIknEUhHaPPUz3DACCbmGZcZZn87TfKZ-j3IOaJWCHxS0O2qyiWD8xNSqT9-acVvTGMSBw7gkVyzirr4_n38xHSl9yw3PyKwE5b4cTh5AUA_FgChywmdpyPmVjcho-LVT7HaAv6YgDZX3mnNCZ1AkljqBqSCgLbwtAqw_jHvzvQVyysOtauEwrgGTqVShs7IagB_F-vhYbo--FgukPNEMXDT8tikG-GYvZaHppiSfcdcWnZ6yi8YlKD4zdYz7ykCHpHgma0575DhzeQokakz4MGYMhhJ7xa1Tb3M9lPU6yCkRMLTQuv6UG7FSUAPzJO90SkUgWVCkZrtBSCzqGrEpxmyPolGof4I1MDuyFuYP5njNQbymX8jPzz3Q8zWrIBDLa0HZnQAOlfYrfi673Ovd0YJPBYuwCkU8ZgOGrqqROE1iQsttz30SOzJWBasuuu4v5vOezSk3N4Z6i_5XHuxaSoaaZ7mDa9wqDFAPkSZjteouiC6qI_PfilDuiBcE2YyypTnEEiClKh_bAOjL_hhSE_pcNAUG3f2CJn3XWPbvXqk58XJIJXNpimKZfoHmW9Li_JLJO-hHYNngBwaL7qITcWd8TLHw_LACORL0OPH4TO--0gBWPaH4L-dlphyHZ3MYC5xn4roxotDeXOpIWKKTsOVaFSWDR-v1N2kB5IDYQy5G_pnw3II3AZT-XsVAvsCuoD9gfstJTjxXMVQCnh7Z4cK6maGbxawDdv2hBeEyVBPg4rc8Bg2vMO3Qat46b7IYo7BHh99L94Y1AvNzRCVIA1PBIAXrpLO7AikbhJoi4ZVdaH96G0adxwAsdUVIeu_kd0p-cIn8jao8Tue-RpURZLJdzkMUFGzRnuoeW9iVx8iS5VBOdBDIK31-63hPrqbMcrwojZ3KdP2ni74tgBfhKwP9KChd9stXA5Ka1quq8WcoA7GFJt7o9ilCe6odqFIbtkhTANYBSegddq6_DJ5IBwqu81h3H-XzmkL4remUbmZgwGjwDkfKO88LEBhSgf3e2Szo_nIM063Gttk1xjk9va_HtKahL-FdNQdnhAtaYJina5OtXspjk0gX4oavVF9lI9SkN-tP_dOALUMqoK4wakL0pxBsfyEc9jOFWoNnD214T7dPg1-CsrbclmXz3UVuVdB4xW_hGKsbuXsj-JjxjRkWaiz9sm5LHFCrDwzg1C-ieMUM0l3baK_NkDZz3Bn3nR1ESaacUW-TS3jRshCFJVVhSVkpOlRabE52gkUTZ4uyufZVMzv11wPaO4pRd8U3uiV4aXT4wlX2AWYmy5cpiTLidhyTrU0EjWKnsjKQNZAD6fACpudBpm_HaTWrI-4WPx1xCOegi4IX_5sVCaziUl0BU77fCp7owvcX-Ojx6R5BYzxWbDBbKrqHYbfjXxv8f8_zga0elotZmQRMxUbUy1QmXYaTL0zDBMD6qJYGiad-sJqWoDkyyOOTGXlRVd1xqjXA7NVE95UNelnNjz9anSW-0HUbgt6w6NHkB0RY83cND9R_np7Hmf8YyGgrHXQYUqhvOTEkuDJqQJ11t9cUqK22HyrLSeqpAItWLwTdCYZAieI8lOD0BXiiI9WlifafTW1xvo7KFb0NR7orr8NSVaDx5IVm2DwtJ0aSOBp2mv3MbyjxvAhggKw6TB9x6oZUxzwaYzdQkIEYbmjvcWUOkSFeClQVMd2lnPL5Jzx7J37hHR0GBJ0xOQh3YHmN-4p6c-diOJsXrnFLRcleZ_u2XUpJeRNkpugLAnW58BmwYslKh3h6oaBYH9eXgYniKtYcjtGy4FVvGJO-u-Q715vDrEvoWimdBYthlRMs5h73cK81zWPFF7BizmFbzJvRnZd3k0TCH18_Fg1bX238jYcO9d8uZGiDKsIR1_5Hy3ZfpCXLzA1ID5qGRs3YRHzEW5w_YTQNGviEyYPyPI45XdYZWKY0sGq9EKWZGdiZKfikIh-JpL6uZgDRkeZaXmL8l7zIlPcQVw-1ehPYX7U7jeA5XRr2s0biEFxv_Lu7__fkx3PjXDJ9egtsiKRqX-yAXWcsD2C1TIPaDQJ8F31jOBizXDoRc-nmaz_VFVyc84el24RZqpfI94Yv1CgSQ4Np2jdO0BWbbt2WCcyp3ZfZShK5cf3w1_7nUo3zuT1Mx5dZp-wLttvBRXlIZyG3cox2MMaEePgZ-i0o3ElX0H1VuS-vhb1DneF0a51PoR8MwnNJdi9aZx9GToUdcXiS3Mkuz1Ll1HDP3L8-jV93otcntBzPJtwAZjZ3mCfVyKDL5yTmN6ureT5JilWEX_oMZ37as1OecicJIOlglnqAMNqhYsg2yMddofYvTx1p4CypbaxDV1M3gC0eo0zn9-njggdz6hTIdsDHAA2F7K3Ccf0eBtxNRyHGIxfKl-wEcYzNW9iBB1SjbOZ97rofCU7FNjynswJ-MqXaBomIpFkFy2NMOO_9zjh7vb3Ru4_xE7O5JWsPt0qw3Qbig67jFLWTnUYM0-wMWxqzKoAucEjO3qIO4l7SY8TTQ4ch2r8m3M4FlfuyXfV9dYfKvCdkgKXOeZXOM_A3ba_Mhuk9NyDhLTvESNU769O9WmJJLtMdILnU8vKzXt4e0u5yKyoFXMTiqPzo6ELZLxsjWtkYpbkIC1glNSUQUKuIYnadWImy7Vsa9OTvhqp3p6_uz_VThZvxubd6Gq5U9Hr3MSxa76MdrZh1r3y02oY-WNyCl04tWT9nvmxMCAmfq3m3YgzGSw6rzq_bllSYeFVPiB2L0TuJGONzDuCKIGJNs6M05pFyHPgSt_1UfnG5DFZ6cheqL2HKNjXw_pjflBQvI8abwIsdBx_hPCR13ugaHltW9IDOjRCLN75mnwvVaOl2I0iNno8-Zkk44q1SvGuNrsAnqxs2TbQORICwsj0Ns6gtScqvwNYQGrnCbT_p5fSC_ex0gMEaN_HOgHeXWogorxVCLGMzJn3B20JbCYyDYGMydY59jbNW100kBuTAxF28NM72C3T_dqEUhBGSY-DyWgDWigM4FpLXcx6gB_kaN13OscXiiBUfytq3FFB3tYB7GBLzDSgyJZDu7wtsf7fR8j1FUgbBKZF8X6orsFYu3e2Tx9Ldi8wZL06D7fBE9CxhvXLZRir1__aH33OA4U1i_7Vqlvq6lgbdxsRAxPwDIOUhUuS225_ODL0VKT2x_VEEIjo2DWtFXQzqvZoFnRNJMI5DVnV7pz3xzMGQluidUz2PebjpQiL9xfPzGbLF20JM1Ik6qh1eEOB9pROgg5eMuYGABc-fNqQ2G4mYoSkhofoV2RIzrPHgrHG3wIC3He8toecMsk48sqWRj4Wgyo4lUEjcSDRVrARsyncKOzxMgIIav3Um_bASN1pSzu2pmy9-wk-b5brDatPla1RfWdF-irYDYdBrNqBM6zqtKstMZjTCiws_k0x35t899_mC8bTsx8mwAUUdJJ11N0Z1eWKHH6omvhsYeIzeJlHI75LgHlgCPP93zMfBXfp6B0PIBZz0tSCL5awLul7OC0RsDN9dzTPCIxxvQ6aaKlQ__ZRkJaRBbyg2s80Ues9Fb8GCkWfPlyaFtjjKO0fz0C5xjac7kEViqzzNZANC0krLsCwffXINeu5vgKY_fcT2Nq9yDyez6WrxX1GcW1Ih0fzirPEEah7niQRCTqb0bcfcXER60w4fFiYcC3pWD_Bj7WICtFe0OrTszplx87_cFIlVjrCAn3JL4koofBfP1AVn-1QxeKc8uDQmZILrdHuYRQnCEH-xEzgbqleDM3MKwoxZcHcBGwUFRW8J5jIRm006x9Or68wKu4tUhUvRr8HbfaCjjsjLqS2czgbPy2DWFoZcQJgk_iTc6VSFz6QJRwbXJJJkgU98PX9vFoC3-4b4tXhWx2kvrymi_LOuMA7DTK21Sy0tjDNxc53-7JK3GbweN9dylwT6a2pao1iZhLUF5BEud1wIORtCJM_y7vAFVhyThwzgJ5lrGjMnWqw7EqSZcthdC7i3EJjRXsuGCelD9lMeUwpdFSte1Ww6RdVLYo5s214aLiFPey5eeLZGVmppgxKJvlxBdVKak_H6SZAO0KaogPKeKB5GVypTOBGg6RZCAU5frZFm0dM7-YPz3q3cWz8rTwTL8MVdmYTJkdMtkEM_TaOHndnmSO0_Hu8ZBipUn-1D4hTuNrLJy9MayKcs-rwbWypcxYHX76WMZ_4WkTLk4V5CanM7_-6q1f2Radx32WLEz-YWsDaVqPmrv_UDfDXveUY4FTEpxa1LRzAXT50Iq9amM6fqA2JndwHuzaSPHtvfEz-PukuTVF0UoOvurXxHrROmMmkWM3TQ5u5g==
requirements.txt CHANGED
@@ -5,4 +5,5 @@ cryptography==40.0.2
5
  python-dotenv==1.0.0
6
  google-auth==2.22.0
7
  google-auth-oauthlib==1.0.0
8
- google-auth-httplib2==0.1.0
 
 
5
  python-dotenv==1.0.0
6
  google-auth==2.22.0
7
  google-auth-oauthlib==1.0.0
8
+ google-auth-httplib2==0.1.0
9
+ google-api-python-client==2.105.0