remoterf 0.0.7.27__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.
Potentially problematic release.
This version of remoterf might be problematic. Click here for more details.
- remoteRF/__init__.py +0 -0
- remoteRF/common/__init__.py +2 -0
- remoteRF/common/grpc/__init__.py +1 -0
- remoteRF/common/grpc/grpc_pb2.py +59 -0
- remoteRF/common/grpc/grpc_pb2_grpc.py +97 -0
- remoteRF/common/utils/__init__.py +4 -0
- remoteRF/common/utils/ansi_codes.py +120 -0
- remoteRF/common/utils/api_token.py +31 -0
- remoteRF/common/utils/list_string.py +5 -0
- remoteRF/common/utils/process_arg.py +80 -0
- remoteRF/core/__init__.py +2 -0
- remoteRF/core/acc_login.py +4 -0
- remoteRF/core/app.py +481 -0
- remoteRF/core/certs/__init__.py +0 -0
- remoteRF/core/certs/ca.crt +32 -0
- remoteRF/core/certs/ca.key +52 -0
- remoteRF/core/certs/cert.pem +19 -0
- remoteRF/core/certs/key.pem +28 -0
- remoteRF/core/certs/server.crt +19 -0
- remoteRF/core/certs/server.key +28 -0
- remoteRF/core/grpc_acc.py +52 -0
- remoteRF/core/grpc_client.py +97 -0
- remoteRF/drivers/__init__.py +0 -0
- remoteRF/drivers/adalm_pluto/__init__.py +1 -0
- remoteRF/drivers/adalm_pluto/pluto_remote.py +250 -0
- remoterf-0.0.7.27.dist-info/METADATA +150 -0
- remoterf-0.0.7.27.dist-info/RECORD +30 -0
- remoterf-0.0.7.27.dist-info/WHEEL +5 -0
- remoterf-0.0.7.27.dist-info/entry_points.txt +2 -0
- remoterf-0.0.7.27.dist-info/top_level.txt +1 -0
remoteRF/core/app.py
ADDED
|
@@ -0,0 +1,481 @@
|
|
|
1
|
+
from . import *
|
|
2
|
+
from ..common.utils import *
|
|
3
|
+
|
|
4
|
+
import getpass
|
|
5
|
+
import os
|
|
6
|
+
import datetime
|
|
7
|
+
import time
|
|
8
|
+
import ast
|
|
9
|
+
|
|
10
|
+
from prompt_toolkit import PromptSession
|
|
11
|
+
|
|
12
|
+
account = RemoteRFAccount()
|
|
13
|
+
session = PromptSession()
|
|
14
|
+
|
|
15
|
+
def welcome():
|
|
16
|
+
printf("Welcome to Remote RF Account System. (all times are in PST)", (Sty.BOLD, Sty.BLUE))
|
|
17
|
+
try:
|
|
18
|
+
inpu = session.prompt(stylize("Please ", Sty.DEFAULT, "login", Sty.GREEN, " or ", Sty.DEFAULT, "register", Sty.RED, " to continue. (", Sty.DEFAULT, 'l', Sty.GREEN, "/", Sty.DEFAULT, 'r', Sty.RED, "):", Sty.DEFAULT))
|
|
19
|
+
if inpu == 'r':
|
|
20
|
+
print("Registering new account ...")
|
|
21
|
+
account.username = input("Username: ")
|
|
22
|
+
double_check = True
|
|
23
|
+
while double_check:
|
|
24
|
+
password = getpass.getpass("Password (Hidden): ")
|
|
25
|
+
password2 = getpass.getpass("Confirm Password: ")
|
|
26
|
+
if password == password2:
|
|
27
|
+
double_check = False
|
|
28
|
+
else:
|
|
29
|
+
print("Passwords do not match. Try again")
|
|
30
|
+
|
|
31
|
+
account.password = password
|
|
32
|
+
account.email = input("Email: ") # TODO: Email verification.
|
|
33
|
+
# check if login was valid
|
|
34
|
+
os.system('cls' if os.name == 'nt' else 'clear')
|
|
35
|
+
|
|
36
|
+
if not account.create_user():
|
|
37
|
+
welcome()
|
|
38
|
+
else:
|
|
39
|
+
account.username = input("Username: ")
|
|
40
|
+
account.password = getpass.getpass("Password (Hidden): ")
|
|
41
|
+
# check if login was valid
|
|
42
|
+
if not account.login_user():
|
|
43
|
+
os.system('cls' if os.name == 'nt' else 'clear')
|
|
44
|
+
print("Invalid login. Try again. Contact admin(s) if you forgot your password.")
|
|
45
|
+
welcome()
|
|
46
|
+
except KeyboardInterrupt:
|
|
47
|
+
exit()
|
|
48
|
+
except EOFError:
|
|
49
|
+
exit()
|
|
50
|
+
|
|
51
|
+
def title():
|
|
52
|
+
printf(f"Remote RF Account System", Sty.BOLD)
|
|
53
|
+
# printf(f"Logged in as: ", Sty.DEFAULT, f'{account.username}', Sty.MAGENTA)
|
|
54
|
+
printf(f"Input ", Sty.DEFAULT, "'help' ", Sty.BRIGHT_GREEN, "for avaliable commands.", Sty.DEFAULT)
|
|
55
|
+
|
|
56
|
+
def commands():
|
|
57
|
+
printf("Commands:", Sty.BOLD)
|
|
58
|
+
printf("'clear' ", Sty.MAGENTA, "- Clear Terminal", Sty.DEFAULT)
|
|
59
|
+
printf("'getdev' ", Sty.MAGENTA, "- View Devices", Sty.DEFAULT)
|
|
60
|
+
printf("'help' or 'h'", Sty.MAGENTA, "- Show this help message", Sty.DEFAULT)
|
|
61
|
+
printf("'perms' ", Sty.MAGENTA, "- View Permissions", Sty.DEFAULT)
|
|
62
|
+
printf("'exit' or 'quit'", Sty.MAGENTA, "- Exit", Sty.DEFAULT)
|
|
63
|
+
printf("'getres' ", Sty.MAGENTA, "- View All Reservations", Sty.DEFAULT)
|
|
64
|
+
printf("'myres' ", Sty.MAGENTA, "- View My Reservations", Sty.DEFAULT)
|
|
65
|
+
printf("'cancelres' ", Sty.MAGENTA, "- Cancel a Reservation", Sty.DEFAULT)
|
|
66
|
+
printf("'resdev' ", Sty.MAGENTA, "- Reserve a Device", Sty.DEFAULT)
|
|
67
|
+
printf("'resdev -n' ", Sty.MAGENTA, "- Naive reserve device", Sty.DEFAULT)
|
|
68
|
+
# printf("'resdev s' ", Sty.MAGENTA, "- Reserve a Device (by single date)", Sty.DEFAULT)
|
|
69
|
+
# check if user is admin
|
|
70
|
+
# if account.get_perms().results['UC'] == 'Admin':
|
|
71
|
+
|
|
72
|
+
def clear():
|
|
73
|
+
os.system('cls' if os.name == 'nt' else 'clear')
|
|
74
|
+
title()
|
|
75
|
+
|
|
76
|
+
def reservations():
|
|
77
|
+
data = account.get_reservations()
|
|
78
|
+
if 'ace' in data.results:
|
|
79
|
+
print(f"Error: {unmap_arg(data.results['ace'])}")
|
|
80
|
+
return
|
|
81
|
+
entries = []
|
|
82
|
+
|
|
83
|
+
for key, value in data.results.items():
|
|
84
|
+
parts = unmap_arg(value).split(',')
|
|
85
|
+
# Create a dictionary for each entry with named fields
|
|
86
|
+
entry = {
|
|
87
|
+
'username': parts[0],
|
|
88
|
+
'device_id': int(parts[1]), # Convert device_id to integer for proper numerical sorting
|
|
89
|
+
'start_time': datetime.datetime.strptime(parts[2], '%Y-%m-%d %H:%M:%S'), # Convert start_time to datetime
|
|
90
|
+
'end_time': parts[3]
|
|
91
|
+
}
|
|
92
|
+
entries.append(entry)
|
|
93
|
+
|
|
94
|
+
if (entries == []):
|
|
95
|
+
printf("No reservations found.", Sty.BOLD)
|
|
96
|
+
return
|
|
97
|
+
|
|
98
|
+
printf("Reservations:", Sty.BOLD)
|
|
99
|
+
|
|
100
|
+
# Sort the entries by device_id and then by start_time
|
|
101
|
+
sorted_entries = sorted(entries, key=lambda x: (x['device_id'], x['start_time']))
|
|
102
|
+
|
|
103
|
+
# Format the sorted entries into strings
|
|
104
|
+
for entry in sorted_entries:
|
|
105
|
+
printf(f'Device ID: ', Sty.RED, f'{entry["device_id"]}', Sty.MAGENTA, f', Start Time: ', Sty.RED, f'{entry["start_time"].strftime("%Y-%m-%d %H:%M:%S")}', Sty.BLUE, f', End Time: ', Sty.RED, f'{entry["end_time"]}', Sty.BLUE)
|
|
106
|
+
|
|
107
|
+
def my_reservations():
|
|
108
|
+
data = account.get_reservations()
|
|
109
|
+
if 'ace' in data.results:
|
|
110
|
+
print(f"Error: {unmap_arg(data.results['ace'])}")
|
|
111
|
+
return
|
|
112
|
+
entries = []
|
|
113
|
+
|
|
114
|
+
for key, value in data.results.items():
|
|
115
|
+
parts = unmap_arg(value).split(',')
|
|
116
|
+
# Create a dictionary for each entry with named fields
|
|
117
|
+
entry = {
|
|
118
|
+
'username': parts[0],
|
|
119
|
+
'device_id': int(parts[1]), # Convert device_id to integer for proper numerical sorting
|
|
120
|
+
'start_time': datetime.datetime.strptime(parts[2], '%Y-%m-%d %H:%M:%S'), # Convert start_time to datetime
|
|
121
|
+
'end_time': parts[3]
|
|
122
|
+
}
|
|
123
|
+
entries.append(entry)
|
|
124
|
+
|
|
125
|
+
if (entries == []):
|
|
126
|
+
printf("No reservations found.", Sty.BOLD)
|
|
127
|
+
return
|
|
128
|
+
|
|
129
|
+
printf("Reservations under: ", Sty.BOLD, f'{account.username}', Sty.MAGENTA)
|
|
130
|
+
|
|
131
|
+
# Sort the entries by device_id and then by start_time
|
|
132
|
+
sorted_entries = sorted(entries, key=lambda x: (x['device_id'], x['start_time']))
|
|
133
|
+
|
|
134
|
+
for entry in sorted_entries:
|
|
135
|
+
if account.username == entry['username']:
|
|
136
|
+
printf(f'Device ID: ', Sty.RED, f'{entry["device_id"]}', Sty.MAGENTA, f', Start Time: ', Sty.RED, f'{entry["start_time"].strftime("%Y-%m-%d %H:%M:%S")}', Sty.BLUE, f', End Time: ', Sty.RED, f'{entry["end_time"]}', Sty.BLUE)
|
|
137
|
+
|
|
138
|
+
def cancel_my_reservation():
|
|
139
|
+
## print all of ur reservations and their ids
|
|
140
|
+
## ask for id to cancel
|
|
141
|
+
## remove said reservation
|
|
142
|
+
data = account.get_reservations()
|
|
143
|
+
if 'ace' in data.results:
|
|
144
|
+
print(f"Error: {unmap_arg(data.results['ace'])}")
|
|
145
|
+
return
|
|
146
|
+
|
|
147
|
+
entries:list = []
|
|
148
|
+
|
|
149
|
+
for key, value in data.results.items():
|
|
150
|
+
parts = unmap_arg(value).split(',')
|
|
151
|
+
# Create a dictionary for each entry with named fields
|
|
152
|
+
entry = {
|
|
153
|
+
'id': -1,
|
|
154
|
+
'internal_id': key,
|
|
155
|
+
'username': parts[0],
|
|
156
|
+
'device_id': int(parts[1]), # Convert device_id to integer for proper numerical sorting
|
|
157
|
+
'start_time': datetime.datetime.strptime(parts[2], '%Y-%m-%d %H:%M:%S'), # Convert start_time to datetime
|
|
158
|
+
'end_time': parts[3]
|
|
159
|
+
}
|
|
160
|
+
if account.username == entry['username']:
|
|
161
|
+
entries.append(entry)
|
|
162
|
+
|
|
163
|
+
printf("Current Reservation(s) under ", Sty.BOLD, f'{account.username}:', Sty.MAGENTA)
|
|
164
|
+
|
|
165
|
+
sorted_entries = sorted(entries, key=lambda x: (x['device_id'], x['start_time'])) # sort by device_id and start_time
|
|
166
|
+
for i, entry in enumerate(sorted_entries): # label all reservations with unique id
|
|
167
|
+
entry['id'] = i
|
|
168
|
+
printf(f'Reservation ID: ', Sty.GRAY, f'{i}', Sty.MAGENTA, f' Device ID: ', Sty.GRAY, f'{entry["device_id"]}', Sty.BRIGHT_GREEN, f' Start Time: ', Sty.GRAY, f'{entry["start_time"].strftime("%Y-%m-%d %H:%M:%S")}', Sty.BLUE, f' End Time: ', Sty.GRAY, f'{entry["end_time"]}', Sty.BLUE)
|
|
169
|
+
# print(f"Reservation ID {i}, Device ID: {entry['device_id']}, Start Time: {entry['start_time'].strftime('%Y-%m-%d %H:%M:%S')}, End Time: {entry['end_time']}")
|
|
170
|
+
|
|
171
|
+
if sorted_entries == []:
|
|
172
|
+
printf("No reservations found.", Sty.BOLD)
|
|
173
|
+
return
|
|
174
|
+
|
|
175
|
+
inpu = session.prompt(stylize("Enter the ID of the reservation you would like to cancel ", Sty.BOLD, '(abort with any non number key input)', Sty.RED, ': ', Sty.BOLD))
|
|
176
|
+
|
|
177
|
+
if inpu.isdigit():
|
|
178
|
+
id = int(inpu)
|
|
179
|
+
if id >= len(sorted_entries):
|
|
180
|
+
print("Invalid ID.")
|
|
181
|
+
return
|
|
182
|
+
|
|
183
|
+
# grab the reservation
|
|
184
|
+
for entry in sorted_entries:
|
|
185
|
+
if entry['id'] == id:
|
|
186
|
+
db_id = entry['internal_id']
|
|
187
|
+
if session.prompt(stylize(f'Cancel reservation ID ', Sty.DEFAULT, f'{id}', Sty.MAGENTA, f' Device ID: ', Sty.DEFAULT, f'{entry["device_id"]}', Sty.BRIGHT_GREEN, f' Start Time: ', Sty.GRAY, f'{entry["start_time"].strftime("%Y-%m-%d %H:%M:%S")}', Sty.BLUE, f' End Time: ', Sty.DEFAULT, f'{entry["end_time"]}', Sty.BLUE, f' ? (y/n):', Sty.DEFAULT)) == 'y':
|
|
188
|
+
response = account.cancel_reservation(db_id)
|
|
189
|
+
if 'ace' in response.results:
|
|
190
|
+
print(f"Error: {unmap_arg(response.results['ace'])}")
|
|
191
|
+
elif 'UC' in response.results:
|
|
192
|
+
printf(f"Reservation ID ", Sty.DEFAULT, f'{id}', Sty.BRIGHT_BLUE, ' successfully canceled.', Sty.DEFAULT)
|
|
193
|
+
else:
|
|
194
|
+
print("Aborting. User canceled action.")
|
|
195
|
+
return
|
|
196
|
+
|
|
197
|
+
print(f"Error: No reservation found with ID {id}.")
|
|
198
|
+
else:
|
|
199
|
+
print("Aborting. A non integer key was given.")
|
|
200
|
+
|
|
201
|
+
def devices():
|
|
202
|
+
data = account.get_devices()
|
|
203
|
+
if 'ace' in data.results:
|
|
204
|
+
print(f"Error: {unmap_arg(data.results['ace'])}")
|
|
205
|
+
return
|
|
206
|
+
printf("Devices:", Sty.BOLD)
|
|
207
|
+
|
|
208
|
+
for key in sorted(data.results, key=int):
|
|
209
|
+
printf(f"Device ID:", Sty.DEFAULT, f' {key}', Sty.MAGENTA, f" Device Name: ", Sty.DEFAULT, f"{unmap_arg(data.results[key])}", Sty.GRAY)
|
|
210
|
+
|
|
211
|
+
def get_datetime(question:str):
|
|
212
|
+
timestamp = session.prompt(stylize(f'{question}', Sty.DEFAULT, ' (YYYY-MM-DD HH:MM): ', Sty.GRAY))
|
|
213
|
+
return datetime.datetime.strptime(timestamp + ':00', '%Y-%m-%d %H:%M:%S')
|
|
214
|
+
|
|
215
|
+
def reserve():
|
|
216
|
+
try:
|
|
217
|
+
id = session.prompt(stylize("Enter the device ID you would like to reserve: ", Sty.DEFAULT))
|
|
218
|
+
token = account.reserve_device(int(id), get_datetime("Reserve Start Time"), get_datetime("Reserve End Time"))
|
|
219
|
+
if token != '':
|
|
220
|
+
printf(f"Reservation successful. Thy Token -> ", Sty.BOLD, f"{token}", Sty.BG_GREEN)
|
|
221
|
+
printf(f"Please keep this token safe, as it is not saved on server side, and cannot be regenerated/reretrieved. ", Sty.DEFAULT)
|
|
222
|
+
except Exception as e:
|
|
223
|
+
printf(f"Error: {e}", Sty.BRIGHT_RED)
|
|
224
|
+
|
|
225
|
+
def perms():
|
|
226
|
+
data = account.get_perms()
|
|
227
|
+
if 'ace' in data.results:
|
|
228
|
+
print(f"Error: {unmap_arg(data.results['ace'])}")
|
|
229
|
+
return
|
|
230
|
+
|
|
231
|
+
results = ast.literal_eval(unmap_arg(data.results['UC']))[0]
|
|
232
|
+
printf(f'Permission Level: ', Sty.BOLD, f'{results[0]}', Sty.BLUE)
|
|
233
|
+
if results[0] == 'Normal User':
|
|
234
|
+
print(unmap_arg(data.results['details']))
|
|
235
|
+
elif results[0] == 'Power User':
|
|
236
|
+
printf(f'Max Reservations: ', Sty.DEFAULT, f'{results[3]}', Sty.MAGENTA)
|
|
237
|
+
printf(f'Max Reservation Duration (min): ', Sty.DEFAULT, f'{int(results[4]/60)}', Sty.MAGENTA)
|
|
238
|
+
printf(f'Device IDs allowed Access to: ', Sty.DEFAULT, f'{results[5]}', Sty.MAGENTA)
|
|
239
|
+
elif results[0] == 'Admin':
|
|
240
|
+
printf(f'No restrictions on reservation count or duration.', Sty.DEFAULT)
|
|
241
|
+
else:
|
|
242
|
+
printf(f"Error: Unknown permission level {results[0]}", Sty.BRIGHT_RED)
|
|
243
|
+
|
|
244
|
+
# New block scheduling
|
|
245
|
+
|
|
246
|
+
def fetch_all_reservations():
|
|
247
|
+
data = account.get_reservations()
|
|
248
|
+
if 'ace' in data.results:
|
|
249
|
+
print(f"Error: {unmap_arg(data.results['ace'])}")
|
|
250
|
+
return []
|
|
251
|
+
entries = []
|
|
252
|
+
|
|
253
|
+
for key, value in data.results.items():
|
|
254
|
+
parts = unmap_arg(value).split(',')
|
|
255
|
+
# Convert both start and end times to datetime objects.
|
|
256
|
+
entry = {
|
|
257
|
+
'username': parts[0],
|
|
258
|
+
'device_id': int(parts[1]), # Stored as an int
|
|
259
|
+
'start_time': datetime.datetime.strptime(parts[2], '%Y-%m-%d %H:%M:%S'),
|
|
260
|
+
'end_time': datetime.datetime.strptime(parts[3], '%Y-%m-%d %H:%M:%S')
|
|
261
|
+
}
|
|
262
|
+
entries.append(entry)
|
|
263
|
+
return entries
|
|
264
|
+
|
|
265
|
+
def fetch_reservations_for_range(start_day: datetime.date, end_day: datetime.date):
|
|
266
|
+
"""
|
|
267
|
+
Fetch all reservations (via fetch_all_reservations) and filter those whose start_time date falls between start_day and end_day (inclusive).
|
|
268
|
+
Returns a dictionary keyed by (device_id, day) (device_id as string, day as datetime.date) with a list of reservation tuples.
|
|
269
|
+
"""
|
|
270
|
+
all_res = fetch_all_reservations() # This calls the network only once.
|
|
271
|
+
res_dict = {}
|
|
272
|
+
for res in all_res:
|
|
273
|
+
res_day = res['start_time'].date()
|
|
274
|
+
if start_day <= res_day <= end_day:
|
|
275
|
+
key = (str(res['device_id']), res_day)
|
|
276
|
+
res_dict.setdefault(key, []).append((res['start_time'], res['end_time']))
|
|
277
|
+
return res_dict
|
|
278
|
+
|
|
279
|
+
def is_slot_conflicting(slot: tuple, reservations: list):
|
|
280
|
+
"""Return True if the slot overlaps with any reservation in the provided list."""
|
|
281
|
+
slot_start, slot_end = slot
|
|
282
|
+
for res_start, res_end in reservations:
|
|
283
|
+
if slot_start < res_end and slot_end > res_start:
|
|
284
|
+
return True
|
|
285
|
+
return False
|
|
286
|
+
|
|
287
|
+
def interactive_reserve_next_days(block_minutes=60):
|
|
288
|
+
"""
|
|
289
|
+
Interactive function that:
|
|
290
|
+
1) Displays a menu of all devices (0-based indexing).
|
|
291
|
+
2) Prompts the user for which device they want.
|
|
292
|
+
3) Prompts how many days (starting today) to check for available reservations.
|
|
293
|
+
4) Prompts for an optional block duration in minutes (default = 60).
|
|
294
|
+
5) Displays the free time slots (in 'block_minutes' increments) for that device,
|
|
295
|
+
over the indicated number of days, also 0-based indexed.
|
|
296
|
+
6) Reserves the chosen slot on that device, after confirmation.
|
|
297
|
+
"""
|
|
298
|
+
try:
|
|
299
|
+
# --- 1) Fetch and display all devices ---
|
|
300
|
+
data = account.get_devices()
|
|
301
|
+
if 'ace' in data.results:
|
|
302
|
+
print(f"Error: {unmap_arg(data.results['ace'])}")
|
|
303
|
+
return
|
|
304
|
+
|
|
305
|
+
print("Devices:")
|
|
306
|
+
# Sort devices by integer key
|
|
307
|
+
sorted_device_ids = sorted(data.results.keys(), key=int)
|
|
308
|
+
|
|
309
|
+
for idx, dev_id in enumerate(sorted_device_ids):
|
|
310
|
+
dev_name = unmap_arg(data.results[dev_id])
|
|
311
|
+
print(f"{idx}. Device ID: {dev_id} Name: {dev_name}")
|
|
312
|
+
|
|
313
|
+
# --- 2) Prompt user to pick a device by 0-based index ---
|
|
314
|
+
device_selection = input("Which device do you want? (enter the 0-based index) ")
|
|
315
|
+
try:
|
|
316
|
+
device_selection = int(device_selection)
|
|
317
|
+
if device_selection < 0 or device_selection >= len(sorted_device_ids):
|
|
318
|
+
print("Invalid selection.")
|
|
319
|
+
return
|
|
320
|
+
except ValueError:
|
|
321
|
+
print("Invalid input. Please enter a number.")
|
|
322
|
+
return
|
|
323
|
+
|
|
324
|
+
chosen_device_id = sorted_device_ids[device_selection]
|
|
325
|
+
|
|
326
|
+
# --- 3) Prompt user for the number of days ---
|
|
327
|
+
num_days = int(input("Enter the number of days to check for available reservations (starting today): "))
|
|
328
|
+
|
|
329
|
+
# --- 4) Optionally override block_minutes ---
|
|
330
|
+
# user_block_input = input(f"Enter block duration in minutes (e.g. 15, 30, 60, 120). Press Enter to default ({block_minutes}): ").strip()
|
|
331
|
+
# if user_block_input:
|
|
332
|
+
# try:
|
|
333
|
+
# block_minutes = int(user_block_input)
|
|
334
|
+
# except ValueError:
|
|
335
|
+
# print("Invalid block duration. Using default of 60 minutes.")
|
|
336
|
+
# block_minutes = 60
|
|
337
|
+
|
|
338
|
+
# --- 5) Find all free time slots for the chosen device over the next `num_days` days ---
|
|
339
|
+
|
|
340
|
+
today = datetime.date.today()
|
|
341
|
+
end_day = today + datetime.timedelta(days=num_days - 1)
|
|
342
|
+
|
|
343
|
+
# We only need one call to fetch reservations for the range:
|
|
344
|
+
reservations_range = fetch_reservations_for_range(today, end_day)
|
|
345
|
+
|
|
346
|
+
# We'll keep a list of (day, (slot_start, slot_end)) for which the device is free
|
|
347
|
+
available_slots = []
|
|
348
|
+
|
|
349
|
+
now = datetime.datetime.now()
|
|
350
|
+
|
|
351
|
+
# Helper to build time slots of length 'block_minutes' starting at 00:00 up to 24:00
|
|
352
|
+
def build_time_slots(date: datetime.date, block_size: int):
|
|
353
|
+
slots = []
|
|
354
|
+
start_of_day = datetime.datetime.combine(date, datetime.time(0, 0))
|
|
355
|
+
minutes_in_day = 24 * 60 # 1440
|
|
356
|
+
current_offset = 0
|
|
357
|
+
while current_offset < minutes_in_day:
|
|
358
|
+
slot_start = start_of_day + datetime.timedelta(minutes=current_offset)
|
|
359
|
+
slot_end = slot_start + datetime.timedelta(minutes=block_size)
|
|
360
|
+
# Stop if slot_end bleeds into the next calendar day
|
|
361
|
+
if slot_end.date() != date:
|
|
362
|
+
break
|
|
363
|
+
slots.append((slot_start, slot_end))
|
|
364
|
+
current_offset += block_size
|
|
365
|
+
return slots
|
|
366
|
+
|
|
367
|
+
# Build free slots for each day in [today, end_day]
|
|
368
|
+
for i in range(num_days):
|
|
369
|
+
day = today + datetime.timedelta(days=i)
|
|
370
|
+
all_slots = build_time_slots(day, block_minutes)
|
|
371
|
+
|
|
372
|
+
# The reservations for the chosen device on this day:
|
|
373
|
+
key = (str(chosen_device_id), day)
|
|
374
|
+
day_reservations = reservations_range.get(key, [])
|
|
375
|
+
|
|
376
|
+
for slot in all_slots:
|
|
377
|
+
slot_start, slot_end = slot
|
|
378
|
+
# Skip if it's for "today" and the slot ends in the past
|
|
379
|
+
if day == today and slot_end <= now:
|
|
380
|
+
continue
|
|
381
|
+
|
|
382
|
+
# Check for conflict
|
|
383
|
+
if not is_slot_conflicting(slot, day_reservations):
|
|
384
|
+
available_slots.append((day, slot))
|
|
385
|
+
|
|
386
|
+
if not available_slots:
|
|
387
|
+
print(f"No available time slots for device {chosen_device_id} in the next {num_days} days.")
|
|
388
|
+
return
|
|
389
|
+
|
|
390
|
+
# Sort by day, then by slot start time
|
|
391
|
+
available_slots.sort(key=lambda x: (x[0], x[1][0]))
|
|
392
|
+
|
|
393
|
+
# --- Display the available slots, using 0-based index ---
|
|
394
|
+
print(f"\nAvailable time slots for device {chosen_device_id} over the next {num_days} days:")
|
|
395
|
+
last_day = None
|
|
396
|
+
for idx, (day, slot) in enumerate(available_slots):
|
|
397
|
+
slot_start_str = slot[0].strftime('%I:%M %p')
|
|
398
|
+
slot_end_str = slot[1].strftime('%I:%M %p')
|
|
399
|
+
if day != last_day:
|
|
400
|
+
# Print a header for the day
|
|
401
|
+
day_header = f"{day.strftime('%Y-%m-%d')} ({day.strftime('%a')}) {day.strftime('%b')}. {day.day}"
|
|
402
|
+
print("\n" + day_header)
|
|
403
|
+
last_day = day
|
|
404
|
+
|
|
405
|
+
print(f" {idx}. {slot_start_str} - {slot_end_str}")
|
|
406
|
+
|
|
407
|
+
# Prompt user to pick a slot by 0-based index
|
|
408
|
+
selection = input("Select a slot by index: ")
|
|
409
|
+
try:
|
|
410
|
+
selection = int(selection)
|
|
411
|
+
if selection < 0 or selection >= len(available_slots):
|
|
412
|
+
print("Invalid selection.")
|
|
413
|
+
return
|
|
414
|
+
except ValueError:
|
|
415
|
+
print("Invalid input. Please enter a number.")
|
|
416
|
+
return
|
|
417
|
+
|
|
418
|
+
chosen_day, chosen_slot = available_slots[selection]
|
|
419
|
+
slot_start_str = chosen_slot[0].strftime('%I:%M %p')
|
|
420
|
+
slot_end_str = chosen_slot[1].strftime('%I:%M %p')
|
|
421
|
+
|
|
422
|
+
confirmation = input(
|
|
423
|
+
f"You have selected a reservation on {chosen_day.strftime('%Y-%m-%d')} "
|
|
424
|
+
f"from {slot_start_str} to {slot_end_str} on device {chosen_device_id}. "
|
|
425
|
+
f"Confirm reservation? (y/n): "
|
|
426
|
+
).strip().lower()
|
|
427
|
+
|
|
428
|
+
if confirmation != 'y':
|
|
429
|
+
print("Reservation cancelled.")
|
|
430
|
+
return
|
|
431
|
+
|
|
432
|
+
# print(f"device_id : {chosen_device_id}, start_time : {chosen_slot[0]}, end_time : {chosen_slot[1]}")
|
|
433
|
+
|
|
434
|
+
# --- 6) Reserve the chosen slot on the chosen device ---
|
|
435
|
+
token = account.reserve_device(int(chosen_device_id), chosen_slot[0], chosen_slot[1])
|
|
436
|
+
if token:
|
|
437
|
+
print(f"Reservation successful on device {chosen_device_id} for "
|
|
438
|
+
f"{chosen_day.strftime('%Y-%m-%d')} {slot_start_str}-{slot_end_str}.")
|
|
439
|
+
print(f"Thy Token -> {token}")
|
|
440
|
+
print("Please keep this token safe, as it is not saved on server side "
|
|
441
|
+
"and cannot be retrieved again.")
|
|
442
|
+
|
|
443
|
+
except Exception as e:
|
|
444
|
+
print(f"Error: {e}")
|
|
445
|
+
|
|
446
|
+
welcome()
|
|
447
|
+
clear()
|
|
448
|
+
|
|
449
|
+
while True:
|
|
450
|
+
try:
|
|
451
|
+
inpu = session.prompt(stylize(f'{account.username}@remote_rf: ', Sty.BLUE))
|
|
452
|
+
if inpu == "clear":
|
|
453
|
+
clear()
|
|
454
|
+
elif inpu == "getdev":
|
|
455
|
+
devices()
|
|
456
|
+
elif inpu == "help" or inpu == "h":
|
|
457
|
+
commands()
|
|
458
|
+
elif inpu == "perms":
|
|
459
|
+
perms()
|
|
460
|
+
elif inpu == "quit" or inpu == "exit":
|
|
461
|
+
break
|
|
462
|
+
elif inpu == "getres":
|
|
463
|
+
reservations()
|
|
464
|
+
elif inpu == "myres":
|
|
465
|
+
my_reservations()
|
|
466
|
+
# elif inpu == "resdev s":
|
|
467
|
+
# interactive_reserve_all()
|
|
468
|
+
elif inpu == "resdev":
|
|
469
|
+
interactive_reserve_next_days(block_minutes=30) # 30 minutes FOR NOW (change if need be)
|
|
470
|
+
elif inpu == 'cancelres':
|
|
471
|
+
cancel_my_reservation()
|
|
472
|
+
elif inpu == 'resdev -n':
|
|
473
|
+
# check if user is admin
|
|
474
|
+
# if account.get_perms().results['UC'] == 'Admin':
|
|
475
|
+
reserve()
|
|
476
|
+
else:
|
|
477
|
+
print(f"Unknown command: {inpu}")
|
|
478
|
+
except KeyboardInterrupt:
|
|
479
|
+
break
|
|
480
|
+
except EOFError:
|
|
481
|
+
break
|
|
File without changes
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
-----BEGIN CERTIFICATE-----
|
|
2
|
+
MIIFmzCCA4OgAwIBAgIURcP62Zj3L/2bVIIdFu+UcAMklBQwDQYJKoZIhvcNAQEL
|
|
3
|
+
BQAwXTELMAkGA1UEBhMCVVMxDjAMBgNVBAgMBVN0YXRlMQ0wCwYDVQQHDARDaXR5
|
|
4
|
+
MRUwEwYDVQQKDAxDb21wYW55IE5hbWUxGDAWBgNVBAMMD3d3dy5leGFtcGxlLmNv
|
|
5
|
+
bTAeFw0yNDA2MjcyMDQ3MTNaFw0yNTA2MjcyMDQ3MTNaMF0xCzAJBgNVBAYTAlVT
|
|
6
|
+
MQ4wDAYDVQQIDAVTdGF0ZTENMAsGA1UEBwwEQ2l0eTEVMBMGA1UECgwMQ29tcGFu
|
|
7
|
+
eSBOYW1lMRgwFgYDVQQDDA93d3cuZXhhbXBsZS5jb20wggIiMA0GCSqGSIb3DQEB
|
|
8
|
+
AQUAA4ICDwAwggIKAoICAQCc92USDLn60Ju8+/fIMMsgIRD71cfuO2R0nD0+Tfe7
|
|
9
|
+
QOvnGpY7xSmtFbzjXadqjjqM8JsADyOJzudYf+KhfbfMcX6WYj1Flx3XVrjws5Nf
|
|
10
|
+
XPSYYT/uo+vBKJl7rFCYdrGFPVTI8oBz9EsdURriXOGn+rhUP4vIcx/0SKYQvWgI
|
|
11
|
+
oJ8huQ1A7bgrfl2qhyjYa+4AhMAF+YtWSI4fsSR3hwb2wR2Xb8zenVvaTAoc0GvY
|
|
12
|
+
TgxQ5Xue2UD/qR/wezGDQozPIsLXAYiK7fIvHxq1rzhAOOIGEtyp2uMAoq7NtYfu
|
|
13
|
+
5ZgRcoD/O6pAPKZKdpC6toGu3kqj2W7bAWAeZzMOCa3DxYCa+r+dW96fhGhA5HLc
|
|
14
|
+
4rwZDVa3hK1d8n0NmkkX2LUdFT5KXuB6InyeXKK/ZKNEAnxSn3cdaqKZWr9Bxbsz
|
|
15
|
+
G9osCNOzN8IQGILTGdQlGirraCQM+P0SvVFj8C22Mo5tuBG1eal1vFvO9LMwl2GP
|
|
16
|
+
SnZ4QB8BXpwAVEpOWe72lLRE99+5GhZvWQAi4RQ+0Mn2xwyJY8gkrK5i5m8kHKzs
|
|
17
|
+
naIfpRrtZ9oo821WTisVYQq5U7QUbPaiE4xEOMEDTiOSatvxQMqu6OGDWLxlqcgv
|
|
18
|
+
Fh317R+H6dhn+hLTGe6wnCozPTHqZoqv664gTs7KFHUgI/gU/dBc3oI/VEyrmuTI
|
|
19
|
+
GwIDAQABo1MwUTAdBgNVHQ4EFgQU/iskMPrT7yToKDJudHOUHRhnRG0wHwYDVR0j
|
|
20
|
+
BBgwFoAU/iskMPrT7yToKDJudHOUHRhnRG0wDwYDVR0TAQH/BAUwAwEB/zANBgkq
|
|
21
|
+
hkiG9w0BAQsFAAOCAgEAJpU4vErO68CduIzqr925gmKzUeSOqoXCLJGvlbUl3HWa
|
|
22
|
+
ieba6oL33UjB/6s5BUHjqTtUiYa1hHoPsI6S9HC7cCaykdWzrtPOrXpF/G4clT8H
|
|
23
|
+
3xkk7lQNwYH0+OP3ITbrY0OiqsTBjVY0ltKOOqzrzRMHcAw6Jc1Zp/7tYv9ZzqYx
|
|
24
|
+
NiwDYlGO8rhyGa2k1zNazJbh7YT0hBKPYkhqF/jheMFBwT3cpw6rJomP3rcSUaK2
|
|
25
|
+
0DP+v4taW7xxfxf8vI2Xdhy9XLdqyVNq0btFxy2cAOj19zSjnHvPlwXSjuRPht0W
|
|
26
|
+
4ZV7moOQYNAGG2376j/LFD5tojkJLWEsiOAd5ve/6FovkPiDfVnPpvTCsidnvqA3
|
|
27
|
+
nNvTV5UJOBYzM1zI8xfDRa5Mg2ggQR75fvXjTo2Jo/FDx+PN70brXJM/1zuH0Znh
|
|
28
|
+
z7Y03uS8cbkLiXgtp/8x9KIRASG/WFMMNtG/YmPcufCGhHlAELI6iKLdcQ5+8dHk
|
|
29
|
+
pmDiRWixBnkyNXu152TZBLvGUHtOAzw3aTZsir+CCdlNeNNqEW1FV21WAsYzDT2M
|
|
30
|
+
TsCr/azaguNozPlapt+nORWMyMR1jr7zcE2XBfmMZzLzf5t7V8RC2UoeSy09fFjT
|
|
31
|
+
vA6swXwe32eKYfeNJSvjiajlqXhZUrQJFBCHhOBgKQxFvU4OzVpPy8q7yszRCtg=
|
|
32
|
+
-----END CERTIFICATE-----
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
-----BEGIN PRIVATE KEY-----
|
|
2
|
+
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
|
|
51
|
+
dnNqQyFgF4k8C3gXyqzTr+Zlc4xaFQ==
|
|
52
|
+
-----END PRIVATE KEY-----
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
-----BEGIN CERTIFICATE-----
|
|
2
|
+
MIIDFDCCAfygAwIBAgIUaORvuL3d7VVDuewDxgBibhqrWqkwDQYJKoZIhvcNAQEL
|
|
3
|
+
BQAwETEPMA0GA1UEAwwGdW51c2VkMB4XDTI0MDYyNzIxMDU1OVoXDTI1MDYyNzIx
|
|
4
|
+
MDU1OVowETEPMA0GA1UEAwwGdW51c2VkMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A
|
|
5
|
+
MIIBCgKCAQEAlT1YZUyg3YZXzHxP6/dS7vmH/unpODa5vSFTnKnOF+lR1GSCok4j
|
|
6
|
+
ItBS9LeUjFcCxAlDBXU+ICQZVGi65udELi00wdewMF/uQb/6dyAb6TVVZUf/LGrM
|
|
7
|
+
rgg4kGfZhSP8IoB+n5qMGIwsypi3Ta1SAKL8xDypSxqqfbC2jeYTJy/3OwNMMs2C
|
|
8
|
+
vqWshdgIHn+hgY0Ge2zkx4GLi6P4ubmSfog6Nxk/2OrCUKmfXn359WawKEzfrXaY
|
|
9
|
+
UOzW9HmfGfF40u66i1TpACNc/BDR4eYaRZEizPLDWdrpz7JWyHBxEojclwvbLfT5
|
|
10
|
+
fSza69x2XGSP39sb3L10dZA0TKe2+j8qJQIDAQABo2QwYjAdBgNVHQ4EFgQUUlVE
|
|
11
|
+
SRlVWR+2IYH8JwBmyy5ntP4wHwYDVR0jBBgwFoAUUlVESRlVWR+2IYH8JwBmyy5n
|
|
12
|
+
tP4wDwYDVR0TAQH/BAUwAwEB/zAPBgNVHREECDAGhwTAqAFrMA0GCSqGSIb3DQEB
|
|
13
|
+
CwUAA4IBAQAvTM1MsqhQo47SNWgn2coGyHHrKFmK7XnFgw9raN9EKJJA67dfv+rj
|
|
14
|
+
ttl+SXuxRFlkQjP8VbHkopyiiL8qNUjW4N4Un4RSEvHZG5oJtQ83a6pwjW3cud1J
|
|
15
|
+
O8+whCU0QCxsXIapNDvsZyaE9rnH+Quq5lyOxrxqGgpEtJG1dTU81Cgpk25ODH1n
|
|
16
|
+
JNxC9vm4bbOBjJdB3YcAJ/K6iIepyP//owN9U2IiIsmpxpdvJi1P/Lp4zD3EHhzF
|
|
17
|
+
MmTwJBCxjOkN66VFjecLXeLlYvs8Xx45BZav+3D3H45XUvafn2cqR2pcmdMOkZAC
|
|
18
|
+
JHTjecrfKzWmnSTxxiY7qWWvxJPUp5KC
|
|
19
|
+
-----END CERTIFICATE-----
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
-----BEGIN PRIVATE KEY-----
|
|
2
|
+
MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCVPVhlTKDdhlfM
|
|
3
|
+
fE/r91Lu+Yf+6ek4Nrm9IVOcqc4X6VHUZIKiTiMi0FL0t5SMVwLECUMFdT4gJBlU
|
|
4
|
+
aLrm50QuLTTB17AwX+5Bv/p3IBvpNVVlR/8sasyuCDiQZ9mFI/wigH6fmowYjCzK
|
|
5
|
+
mLdNrVIAovzEPKlLGqp9sLaN5hMnL/c7A0wyzYK+payF2Agef6GBjQZ7bOTHgYuL
|
|
6
|
+
o/i5uZJ+iDo3GT/Y6sJQqZ9effn1ZrAoTN+tdphQ7Nb0eZ8Z8XjS7rqLVOkAI1z8
|
|
7
|
+
ENHh5hpFkSLM8sNZ2unPslbIcHESiNyXC9st9Pl9LNrr3HZcZI/f2xvcvXR1kDRM
|
|
8
|
+
p7b6PyolAgMBAAECggEAIkNWhVFJuHpEs42R0siySWvQIYIF+ZI04/tgBR6GEr7O
|
|
9
|
+
Ou9Ff6plTjOabBUuvWanm6bNtJXViM8I4rR1vpf3cwuNaniQupZ3rrA6+nkMd2b3
|
|
10
|
+
f1x/dOzjJ4x7Igo5qiPYGfq6t31lrygVi4DyypphcoR4+Du+GWBapqc4zky1doAm
|
|
11
|
+
iXYU08/Q4hToP1VJGNo9chMuOcSrJeiA0RgYlnkCfbL591PGf7VuQzS+PcbcnbiA
|
|
12
|
+
ODOFdBez39+Dlo4nZosIlgLgFPSX/M57zP6WgRcVkLqL75rECqtcs/52dJ73uxMu
|
|
13
|
+
a5GukSY5z5A4r0hCGOZDDqpW2B+IRfAqzSL/ViS7gQKBgQDN0o7GgOsLBqeoj27W
|
|
14
|
+
xOzT1dX39AkFsvdI8f47B1blYFd3egN5y0nLWLEbK/LcpanrCX+nkRz/M51DNGKa
|
|
15
|
+
1lvMDDwt/99wSKUJFhO1SvuA6SB1DlPgLNRqXZu2cwzpZs1xJU6oVyK70ih3uWmW
|
|
16
|
+
lmi109pDlOkBPSHkIUx5GNXQpQKBgQC5n28/R3VV0L4zzWokewWbHtXVp87owXlh
|
|
17
|
+
6typ/Stz98kkMNmQNkkQyQ3SxeBNXMkItLA9yYw2MDhDm6ZdyP+ZUdTv+FwMjg5M
|
|
18
|
+
1FEty94LUAscDbu4QSADR0cfNQH/oPavPMWoFj/eTGnRVY76uKAzgkIPZP112Gqg
|
|
19
|
+
IYaPcs87gQKBgQCtzFrbrAjNqrTwVQ3XNTp2Nl8TnXHw6gp+AjoXRj9OOWgib1l4
|
|
20
|
+
Av0xRJdoxlexkgJFgiPVL2g45zCoixeof9HMH5jBjwryGaWiYo4JzGNLm4/YyFxz
|
|
21
|
+
M+e6WYkfK09/11sra8FbzRh7WR7q2hobGq8YuufXoWqPrTttE+ErcJk8MQKBgCTq
|
|
22
|
+
qothQNrCWzGeRt/ef6zsIwcNCr+LywJIXX6JVV0JCL3j4UEnKrzl35PtusBoFatf
|
|
23
|
+
lDWVogcc6/O2Pw4j7YGmnrzjHht5HSr2hvaetxh04ODBcnYgrac5Q9HXDwCyGJ2d
|
|
24
|
+
booRcr5ZYCo74+XFVkcoPs8k/Ku1UO9r+4EICmMBAoGAdFXHggoQu7fz0maZoH1o
|
|
25
|
+
TgFVhD8p4McuN+L0ddOWvS7l+0Lz/9J2KKmHRElfpMvJsSoXGp7Anyymwqukw8zq
|
|
26
|
+
iD/ZqGavuzcRWPWO6W514asHU1AxLSYGFqNuCYag/jElcWhgQyHojPMypaDM2Xfv
|
|
27
|
+
rgkCz2uZ2Zg2/GJ65CtboCA=
|
|
28
|
+
-----END PRIVATE KEY-----
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
-----BEGIN CERTIFICATE-----
|
|
2
|
+
MIIDJDCCAgygAwIBAgIUTLqudWuu46JkqxA1UOVcHkhZz0swDQYJKoZIhvcNAQEL
|
|
3
|
+
BQAwGTEXMBUGA1UEAwwOMTY0LjY3LjE5NS4yMDcwHhcNMjQxMDI1MjAzNTAzWhcN
|
|
4
|
+
MjUxMDI1MjAzNTAzWjAZMRcwFQYDVQQDDA4xNjQuNjcuMTk1LjIwNzCCASIwDQYJ
|
|
5
|
+
KoZIhvcNAQEBBQADggEPADCCAQoCggEBALCAm+cnf98MpcPLB9n6NEYoDU7ye/74
|
|
6
|
+
iEenNiFV440qKQ2y0fV9qZ5+AeaUpFbrZPyClOBQhJxg1SrZnhQkBJD2GOiX0vxh
|
|
7
|
+
LqugFCCgfoCJEyX/oJXogGcNPlcrkN5ATFfD7n/9MIvdcpSisF34/jQvqjZXzkd2
|
|
8
|
+
1KpqHH+bwxCUCoe2YENIVpEs3gbojaPsgbsJECHy3CsG9pS7/FNPGnoI6UdXrXSl
|
|
9
|
+
RIQToERlyk0UgKsGWwj+FGdJavOlU/um7Q1C/oxNeCaZPGSQzJOrCiPt/HGimCAn
|
|
10
|
+
2BMOro2X9KfKnT4cUMIZzeSvjdTx6IgrpjSN+XdzeFpcoUZRMpxtdPECAwEAAaNk
|
|
11
|
+
MGIwHQYDVR0OBBYEFIVpaHQqtgoiCyJQpsUZqAXEvTuUMB8GA1UdIwQYMBaAFIVp
|
|
12
|
+
aHQqtgoiCyJQpsUZqAXEvTuUMA8GA1UdEwEB/wQFMAMBAf8wDwYDVR0RBAgwBocE
|
|
13
|
+
pEPDzzANBgkqhkiG9w0BAQsFAAOCAQEAEUiXzwMbEry2ptVu/Q9FV8hmhbpgveve
|
|
14
|
+
Hh5PniP3UQfxlRZnZ4UEN14FHIV7d9o9FUedGmnC95hnURHd5YlLE3JTNTN5lyqp
|
|
15
|
+
zWySGS1oGsTog6ctl7Psey6Detgxj5B8lA+z3Tp7Ud2sANejFhoYNrzkFrbyLLnW
|
|
16
|
+
1BjPJlMZBBW2+yVd8zQPXAfAQwdqeuBns9XSDuY5MvRaJd8yfXjP1SksBBaanqCN
|
|
17
|
+
9Fj/LXtjZrTu1FqZ7I0rUp/obR+avoeu/qHx6TkZ741SDhJ1wGJzW/+21yDdQe7P
|
|
18
|
+
kf4iOINrN3FaQv35oo2fgINgWoZYRrEsKkRbEZvUX2/yAg2le1WkKA==
|
|
19
|
+
-----END CERTIFICATE-----
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
-----BEGIN PRIVATE KEY-----
|
|
2
|
+
MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCwgJvnJ3/fDKXD
|
|
3
|
+
ywfZ+jRGKA1O8nv++IhHpzYhVeONKikNstH1famefgHmlKRW62T8gpTgUIScYNUq
|
|
4
|
+
2Z4UJASQ9hjol9L8YS6roBQgoH6AiRMl/6CV6IBnDT5XK5DeQExXw+5//TCL3XKU
|
|
5
|
+
orBd+P40L6o2V85HdtSqahx/m8MQlAqHtmBDSFaRLN4G6I2j7IG7CRAh8twrBvaU
|
|
6
|
+
u/xTTxp6COlHV610pUSEE6BEZcpNFICrBlsI/hRnSWrzpVP7pu0NQv6MTXgmmTxk
|
|
7
|
+
kMyTqwoj7fxxopggJ9gTDq6Nl/Snyp0+HFDCGc3kr43U8eiIK6Y0jfl3c3haXKFG
|
|
8
|
+
UTKcbXTxAgMBAAECggEAHlas9am7eBqTb7k5a0VvsNN3nideGvCbdD2Qt2AtEfm6
|
|
9
|
+
PsmK/3iPLFgaeYj5SpuBq0nCz1/nu32Fhq0LWAjs5AH5PBnEwW7u9783Vnhf5jYp
|
|
10
|
+
nXF4J+xkDdKf8Znid+Fzfe6G02cw7gmthVEFodGH2G6NAnRLV8tcOMKujVy3xeRz
|
|
11
|
+
XVqL9ttbllCboYQQ5yZH9+wahAV0YT5FogttvKhd3jiPRAZ5sITxq+ibnLx3upqc
|
|
12
|
+
Tzz4VSCymuoX5Aq010bjvrA9yWcFeP4lHru4ArTZS9zsZ9BgCoT2MxBv9qmg/fwv
|
|
13
|
+
/SZ+/WvHWj0dhSonh5TWv2be0JWWMZu6cWKoFAs68QKBgQDc9dmZZagY+y93frCj
|
|
14
|
+
38MjVfFUtUbauXW2Q83EiMjOPU3UAH7igE564OPAM5YRTtbzT7qohwokHS6FrXgB
|
|
15
|
+
NEdes6qQfaCvaqnG75ylpRKKL1abWSBjb28jNYvSJdvM7z38+XjLNRXeoiDFju5g
|
|
16
|
+
4nU7Yru4aXRlwvTCmLh6VSD9JQKBgQDMfe8zJHQHpMG/edcYE0858F/IsXZAVM4c
|
|
17
|
+
vnEwRGAEOvLRLbf2FkyC8UmQ0JxaXRCxyeSl5JRuMjpImmfvOEdI9OZvVolbuIM3
|
|
18
|
+
QrY7SL//CqcNuQWm6OvGy3+QrrFHEVsEdMKEB7bbDo0+Eyl87U+8sXge7wkTp7OW
|
|
19
|
+
10uOm3F83QKBgHF5zROLcoXJ0jnDFYJDc1rdU0AWjNndbwd40N8DBGVudF7RFljK
|
|
20
|
+
XgObJTvbAlHHNHrmUk0kdN/RIMhEKyIrMBABozHrYq9Tzvc8rS0glmHjJ85GOmz2
|
|
21
|
+
mJPzdugoyzX3E9WsZQ2vKJkamEv9OI0HH/+smA2AEugD9GFPv0YMHBIFAoGAOxws
|
|
22
|
+
CJyA7bSyTKbrhgoO3LCe/2RMyku5SJXEIi+hkZd4mP6eLoRDmZYlrbafe39rU/kI
|
|
23
|
+
Huvz++aI8nOvl3atJGmmMojRK7IqO88M3hYpaY+qukzBVX3+qXgpZ6kXlXNu29rk
|
|
24
|
+
X0XblXafXVIsq+/tHJ4wGsD93rCbOP8C2DYWmAECgYEAn5KaWkAJCH1GGurJD/jU
|
|
25
|
+
w/M1eU4tMRecI/9E2J38PuANfcQ972Jl252ZK/1aR/rysFlrdkZSzDfEuiQFphhu
|
|
26
|
+
BmOqFELKbsst+ijc/jTR8KQLHqr4nFk0PCE8HwrLc2LBN45kr3LdqwmehobU80+s
|
|
27
|
+
nvDLTTO6AjP462kETu05Nrk=
|
|
28
|
+
-----END PRIVATE KEY-----
|