def get_ifc_response(update, context): ifc_file_name = context.user_data['ifc_file_name'] json_obj = getJson(files_dir / ifc_file_name) all_files = getJson(files_dir / 'files.json') option = update.message.text chat_id = update.message.chat_id if (option == 'Load an IFC file'): try: update.message.reply_text(show_all_file_type(all_files, 'ifc')) except: update.message.reply_text('You have no files stored of type IFC. Try using /sendfile to store one. ') return ConversationHandler.END update.message.reply_text('Which IFC file would you like to load? Type the name of the file') return GET_IFC_FILE elif (option == 'View'): all_points, all_triangles = get_all_triangles_points(files_dir / ifc_file_name) mesh = get_mesh(all_points, all_triangles) show_building(mesh) bot = context.bot [bot.send_photo(chat_id=chat_id, photo=open(f'{i}.png', 'rb')) for i in range(1, 5)] return ConversationHandler.END elif (option == 'Get analysis'): return start_analysis(update, context) elif (option == 'Stretch'): update.message.reply_text('Provide the range along the z axis you would like to stretch, ' 'and the amount you would like to stretch in the following format:\n' '<code>min_z, max_z, amount</code>') return GET_STRETCH_PARAMETERS elif (option == 'View stretched'): update.message.reply_text('Showing stretched building: ') all_points, all_triangles = get_all_triangles_points('duplex_A_stretched.json') mesh = get_mesh(all_points, all_triangles) show_building(mesh) bot = context.bot [bot.send_photo(chat_id=chat_id, photo=open(f'{i}.png', 'rb')) for i in range(1, 5)] return ConversationHandler.END elif (option == 'View wire frame'): all_points, all_triangles = get_all_triangles_points(files_dir / ifc_file_name) mesh = get_mesh(all_points, all_triangles) show_wire_mesh(mesh) bot = context.bot [bot.send_photo(chat_id=chat_id, photo=open(f'{i}.png', 'rb')) for i in range(1, 5)] return ConversationHandler.END elif (option == 'Get .ply file'): #send ply file bot = context.bot # try: # bot.send_document(chat_id=chat_id, document=open("ply0.ply",'rb')) # return ConversationHandler.END all_points, all_triangles = get_all_triangles_points(files_dir / ifc_file_name) get_mesh(all_points, all_triangles) bot.send_document(chat_id=chat_id, document=open("ply0.ply",'rb')) return ConversationHandler.END else: update.message.reply_text('Invalid option', reply_markup=ReplyKeyboardRemove()) return ConversationHandler.END
def give_info(update, context): # get beats.json beats_path = context.user_data['beats_path'] json_obj = getJson(beats_path) user = update.message.from_user # metric desired METRIC = update.message.text context.user_data['METRIC'] = METRIC logger.info("Metric user %s desires: %s", user.first_name, METRIC) TEAM_INDEX = context.user_data['TEAM_INDEX'] SEGMENT_INDEX = context.user_data['SEGMENT_INDEX'] try: if (METRIC == 'Height'): update.message.reply_text('The height of the building is: ' + str(getHeight(json_obj, TEAM_INDEX, SEGMENT_INDEX)), reply_markup=ReplyKeyboardRemove()) elif (METRIC == 'Volume'): update.message.reply_text('The volume of the building is: ' + str(getVolume(json_obj, TEAM_INDEX, SEGMENT_INDEX)), reply_markup=ReplyKeyboardRemove()) elif (METRIC == 'Floor Area'): update.message.reply_text('The floor area is: ' + str(getFloorArea(json_obj, TEAM_INDEX, SEGMENT_INDEX)), reply_markup=ReplyKeyboardRemove()) elif (METRIC == 'Cancel'): update.message.reply_text('Cancelling action, try /viewbeats to try again.', reply_markup=ReplyKeyboardRemove()) return ConversationHandler.END else: update.message.reply_text('Invalid input. Cancelling action, try /viewbeats to try again.', reply_markup=ReplyKeyboardRemove()) except: update.message.reply_text('Invalid measurements. Cancelling action, try /viewbeats to try again', reply_markup=ReplyKeyboardRemove()) return ConversationHandler.END
def request_file(update, context): response = update.message.text context.user_data['file_type'] = response.lower() file_type = context.user_data['file_type'] custom_file_categories = [] try: custom_file_categories = getJson(files_dir / 'file_categories.json') except: custom_file_categories = [] if (file_type not in ['image', 'beats', 'ifc', 'cancel', 'add new category'] and file_type not in custom_file_categories): update.message.reply_text( 'Invalid input. Send file cancelled. Type /sendfile to try again.', reply_markup=ReplyKeyboardRemove()) return ConversationHandler.END elif (file_type == 'cancel'): update.message.reply_text( 'Send file cancelled. Type /sendfile to try again.', reply_markup=ReplyKeyboardRemove()) return ConversationHandler.END elif (file_type == 'add new category'): update.message.reply_text('Write a category name:') return GET_NEW_CATEGORY update.message.reply_text( f"Send a(n) {file_type} file to me, if you would like to cancel type 'cancel'", reply_markup=ReplyKeyboardRemove()) if (file_type == 'image'): update.message.reply_text( "Make sure to send it as a photo, not as a file") return GET_A_FILE
def save_file_type(update, context, file_name, file_title, file_description, file_type, user): file_id = context.user_data['file_id'] j = getJson(files_dir / 'files.json') if not (file_type in j.keys()): j[file_type] = [] counter = 0 duplicate = False for item in j[file_type]: if item['name'] == file_name: duplicate = True update.message.reply_text( f'The file name \'{file_name}\' is already in use') elif item['name'][:-4] == file_name: counter += 1 if duplicate: update.message.reply_text( f'Uploading file as \'{file_name} ({counter})\'') file_name += f" ({counter})" j[file_type].append({ "name": file_name, "uploaded_by": user.name, "date": str(datetime.now()), 'file_id': file_id, 'file_name': file_title, 'description': file_description }) with Path(files_dir / 'files.json').open(mode='w') as outfile: json.dump(j, outfile, indent=4)
def show(update, context): file_type = update.message.text file_type = file_type.lower() context.user_data['file_type'] = file_type j = getJson(files_dir / 'files.json') if file_type.lower() == 'cancel': update.message.reply_text( "Cancelling transaction. \n" "Try again with /filemanage or upload a new file with /sendfile", reply_markup=ReplyKeyboardRemove()) return ConversationHandler.END elif file_type not in j.keys(): update.message.reply_text( "There are currently no files stored for this format \n" "View other file formats with /filemanage or upload a new file with /sendfile", reply_markup=ReplyKeyboardRemove()) return ConversationHandler.END elif (j[file_type] == []): update.message.reply_text( "There are currently no files stored for this format \n" "View other file formats with /filemanage or upload a new file with /sendfile", reply_markup=ReplyKeyboardRemove()) return ConversationHandler.END reply_keyboard = [['Download', 'Delete', 'Cancel']] update.message.reply_text(show_all_file_type(j, file_type)) update.message.reply_text( "Would you like to download a file, or remove a file", reply_markup=ReplyKeyboardMarkup(reply_keyboard, one_time_keyboard=True)) return CHOOSE_FILE
def send_file(update, context): file_name = update.message.text file_type = context.user_data['file_type'] file_name = file_name.lower() context.user_data['file_name'] = file_name # send the file to the user chat_id = update.message.chat_id j = getJson(files_dir / 'files.json')[file_type] try: index = [ index for index, item in enumerate(j) if item['name'].lower() == file_name ][0] except: update.message.reply_text('No file with this filename') return ConversationHandler.END # base_url = 'https://api.telegram.org/bot' # with urllib.request.urlopen(base_url + token + '/getFile?file_id=' + file_id) as obj: # data = json.loads(obj.read()) # update.message.reply_text('https://api.telegram.org/file/bot' + token + '/' + data['result']['file_path']) bot = context.bot if (file_type == 'image'): bot.send_photo(chat_id=chat_id, photo=Path(files_dir / j[index]['file_name']).open(mode='rb'), filename=j[index]['name']) else: bot.send_document(chat_id=chat_id, document=Path(files_dir / j[index]['file_name']).open(mode='rb'), filename=j[index]['name'] + '.' + j[index]['file_name'].split('.')[-1]) return ConversationHandler.END
def choose_file(update, context): file_type = context.user_data['file_type'] option = update.message.text option = option.lower() j = getJson(files_dir / 'files.json') if (option == "download"): pass elif (option == "delete"): pass elif (option == "cancel"): update.message.reply_text("You have chosen to cancel the operation") return ConversationHandler.END else: update.message.reply_text("Invalid option, operation cancelled") return ConversationHandler.END try: # update.message.reply_text(show_all_file_type(j, file_type)) update.message.reply_text('Which file would you like to ' + option + '? Type the name of the file', reply_markup=ReplyKeyboardRemove()) if (option == "download"): return SEND_FILE elif (option == "delete"): update.message.reply_text( "If you do not wish to delete a file, type cancel") return DEL_FILE except Exception as e: logger.info(e) update.message.reply_text('Invalid file type!') return ConversationHandler.END
def view_team(update, context): teams = getJson('teams.json') view_string = "<code>" view_string += f"{'Sprint duration':<18}: {teams['sprint_duration']}\n" view_string += f'{"Groups":<18}:\n' view_string += '-'*25 for team_no, team in enumerate(teams['teams']): view_string += f'\n{" Group number":<18}: {team_no+1}\n' view_string += f'{" Group name":<18}: {team["group_name"]}\n' view_string += f'{" Group members":<18}:\n' if (len(team['group_members']) == 0): view_string += f' Empty\n' for member in team['group_members']: view_string += f' @{member}\n' view_string += ' ' + '-'*10 view_string = view_string.strip('-') view_string = view_string.strip(' ') view_string += '-' * 25 view_string += '</code>' update.message.reply_text(view_string) reply_keyboard = [] for i in range(len(teams['teams'])): if (i % 8 == 0): reply_keyboard += [[]] reply_keyboard[int(i / 8)] += [str(i+1)] reply_keyboard += [["All", "Cancel"]] update.message.reply_text("Would you like to view a team with more detail?", reply_markup=ReplyKeyboardMarkup(reply_keyboard, one_time_keyboard=True)) return DETAILED_VIEW
def view_beats(update, context): j = getJson(Path(Path.cwd()) / 'Files' / 'files.json') try: if len(j['beats']) == 0: update.message.reply_text('You have not uploaded any beats files yet! Use /sendfile to send a file of type beats.') return ConversationHandler.END except: update.message.reply_text('You have not uploaded any beats files yet!') return ConversationHandler.END update.message.reply_text(show_all_file_type(j, 'beats')) update.message.reply_text('To get an overview of the beats, first select a beats file to view') return OVERVIEW
def get_new_category(update, context): category = update.message.text category = category.lower() try: categories = getJson(files_dir / 'file_categories.json') except: categories = [] categories += [category] with open(files_dir / 'file_categories.json', 'w') as outfile: json.dump(categories, outfile, indent=4) update.message.reply_text( 'Success! Use /sendfile to send a file of your new category. ') return ConversationHandler.END
def overview(update, context): reply_keyboard = [[]] file_title = update.message.text j = getJson(Path(Path.cwd()) / 'Files' / 'files.json') beats_file_name = [item['file_name'] for item in j['beats'] if item['name'] == file_title] if len(beats_file_name) == 0: update.message.reply_text('Invalid file title, cancelling action. Type /viewbeats to try again.') return ConversationHandler.END beats_file_name = beats_file_name[0] context.user_data['beats_file_name'] = beats_file_name beats_path = Path(Path.cwd() / 'Files' / beats_file_name) context.user_data['beats_path'] = beats_path json_obj = getJson(beats_path) json_str = "" for i, team in enumerate(json_obj): del json_obj[i]['segments'] reply_keyboard[0].append(team['team']) json_formatted = json.dumps(json_obj, indent=0) formatted_str = "<code>----------</code>\n" for line in json_formatted.split("\n"): if (line == "{"): formatted_str += "" elif (line in ["},","}"]): formatted_str += "<code>----------</code>\n" elif (line in ["[","]"]): pass else: if ("name" in line or "team" in line): line = line.replace("\"", "") line = line.strip(",") line = line.split(": ") formatted_str += f'<code>{line[0]:5}: {line[1]:<20}</code>\n' update.message.reply_text( 'Hi! I am the BygBot. I will hold a conversation with you. ' 'Send /cancel to stop talking to me.\n\n' 'This is the information I found so far:\n' + formatted_str + '\nWhich team would you like to examine?', reply_markup=ReplyKeyboardMarkup(reply_keyboard, one_time_keyboard=True)) return TEAM_INFO
def show_what(update, context): custom_file_categories = [] try: custom_file_categories = getJson(files_dir / 'file_categories.json') except: custom_file_categories = [] reply_keyboard = [['Image', 'Beats', 'IFC'] + custom_file_categories, ['Cancel']] update.message.reply_text( "Please select which file type you'd like to see", reply_markup=ReplyKeyboardMarkup(reply_keyboard, one_time_keyboard=True)) return SHOW
def team_info(update, context): beats_path = context.user_data['beats_path'] json_obj = getJson(beats_path) user = update.message.from_user TEAM = update.message.text context.user_data['TEAM'] = TEAM found = False for i in range(len(json_obj)): if json_obj[i]['team'] == TEAM: found = True TEAM_INDEX=i context.user_data['TEAM_INDEX'] = TEAM_INDEX break if (not found): update.message.reply_text('Invalid team, cancelling action. Try /viewbeats to try again.', reply_markup=ReplyKeyboardRemove()) return ConversationHandler.END logger.info("Team that %s wishes to examine: %s", user.first_name, TEAM) logger.info("Team index: %i", TEAM_INDEX) reply_keyboard = [[]] for segment in json_obj[TEAM_INDEX]["segments"]: reply_keyboard[0].append(str(segment["id"])) json_team = json_obj[TEAM_INDEX] json_formatted = json.dumps(json_obj[TEAM_INDEX], indent=2) formatted_str = "==========================\n" for line in json_formatted.split("\n"): if (line == "{"): formatted_str += "" elif (line in [" {"]): formatted_str += "" elif (line in ["},", "}"]): formatted_str += "==========================\n" elif (line in [" },", " }"]): formatted_str += "<code> ---</code>\n" elif (line.strip() in ["[","]","],"]): pass else: line = line.replace("\"", "") line = line.strip(",") line = line.split(": ") if (line[1] == "["): line[1] = "" formatted_str += f'<code>{line[0][2:]:15}:{line[1]:>10}</code>\n' update.message.reply_text( "This is the information I found on team " + TEAM + "\n" +formatted_str+ "\n--------\n" "Which segment would you like to look at?", reply_markup=ReplyKeyboardMarkup(reply_keyboard, one_time_keyboard=True)) return SEGMENT_INFO
def get_ifc_file(update, context): ifc_file_name = update.message.text ifc_file_name = ifc_file_name.lower() all_files = getJson(files_dir / 'files.json') all_ifc = all_files['ifc'] try: index = [index for index, item in enumerate(all_ifc) if item['name'].lower() == ifc_file_name][0] ifc_file_name = all_ifc[index]['file_name'] update.message.reply_text('Successfully loaded file!') context.user_data['ifc_file_name'] = ifc_file_name return ifc_start(update, context) except: update.message.reply_text('No file with this filename') ifc_file_name = None return ConversationHandler.END
def segments_info(update, context): beats_path = context.user_data['beats_path'] json_obj = getJson(beats_path) user = update.message.from_user SEGMENT = update.message.text context.user_data['SEGMENT'] = SEGMENT try: SEGMENT = int(SEGMENT) except: update.message.reply_text('Invalid segment. It must be a number. Cancelling action, try /viewbeats to try again' , reply_markup=ReplyKeyboardRemove()) return ConversationHandler.END TEAM_INDEX = context.user_data['TEAM_INDEX'] reply_keyboard = [['Height','Volume','Floor Area', 'Cancel']] found = False for index, segment in enumerate(json_obj[TEAM_INDEX]['segments']): print(index) if segment['id'] == SEGMENT: found = True print('found it') SEGMENT_INDEX = index context.user_data['SEGMENT_INDEX'] = SEGMENT_INDEX if (not found): update.message.reply_text('Invalid segment, cancelling action. Try /viewbeats to try again.', reply_markup=ReplyKeyboardRemove()) return ConversationHandler.END json_formatted = json.dumps(json_obj[TEAM_INDEX]['segments'][SEGMENT_INDEX], indent=0) formatted_str = "==========================\n" for line in json_formatted.split("\n"): if (line == "{"): formatted_str += "" elif (line in ["},","}"]): formatted_str += "==========================\n" elif (line in ["[","]"]): pass else: line = line.replace("\"", "") line = line.strip(",") line = line.split(": ") formatted_str += f'<code>{line[0]:15}: {line[1]:>10}</code>\n' update.message.reply_text( "This is the information I found on segment " + str(SEGMENT) + "\n\n-------\n" +formatted_str+ "\n--------\n" "What further information would you like on segment " + str(SEGMENT), reply_markup=ReplyKeyboardMarkup(reply_keyboard, one_time_keyboard=True)) return GIVE_INFO
def get_min_height(obj): min_height = None building = getJson('duplex_A.json') points = [] for representation in obj['Representations']: rep_id = representation['ref'] for item in building: if item['GlobalId'] == rep_id: points,triangles = split_triangles_points(item['Items']) new_min_height = find_min_dimension(points, 2) if min_height is None: min_height = new_min_height else: if new_min_height < min_height: min_height = new_min_height return min_height
def get_a_file(update, context): # if (file_type not in ['image', 'beats', 'ifc']): # return ConversationHandler.END #logging user = update.message.from_user file_type = context.user_data['file_type'] logger.info(f'User {user.first_name} is requested to send {file_type}') bot = context.bot chat_id = update.message.chat_id try: if (file_type == 'image'): context.user_data['file_id'] = update.message.photo[-1].file_id else: context.user_data['file_id'] = update.message.document.file_id file_id = context.user_data['file_id'] gen_file = bot.get_file(file_id) gen_file.download() logger.info(f'{file_type} successfully downloaded') context.user_data['file_title'] = (str( gen_file.file_path).split('/'))[-1] file_title = context.user_data['file_title'] if file_type == 'beats': temp_json = getJson(Path.cwd() / file_title) valid = (validate_beats(temp_json)) if (valid != "valid"): logger.info('Beats acquired from %s were invalid. Reason %s', user.first_name, valid) update.message.reply_text( "Invalid beats file due to " + valid + ", cancelling file upload. Type /sendfile to try again") return ConversationHandler.END Path(Path.cwd() / file_title).replace(files_dir / file_title) update.message.reply_text( f"{file_type[0].upper()}{file_type[1:]} acquired!") update.message.reply_text('Please enter a short title of the file') return GET_NAME except Exception as e: logger.info('Failed to acquire %s from %s', file_type, user.first_name) logger.info(e) update.message.reply_text( f"File was not a(n) {file_type}, cancelling file upload. Type /sendfile to try again" ) return ConversationHandler.END
def get_all_triangles_points(file_name): json_obj = getJson(file_name) all_points = [] all_triangles = [] counter = 0 for item in json_obj: class_name = item['Class'] if class_name == 'ShapeRepresentation': # points, triangles = split_triangles_points(item['Items'], counter) try: points, triangles = split_triangles_points(item['Items'], counter) except Exception as e: print(item) print(e) counter += len(points) all_points += points all_triangles += triangles return all_points, all_triangles
def delete(update, context): file_name = context.user_data['file_name'] file_type = context.user_data['file_type'] confirm = update.message.text confirm = confirm.lower() if (confirm == "yes"): j = getJson(files_dir / 'files.json') index = [ index for index, item in enumerate(j[file_type]) if item['name'].lower() == file_name ][0] del j[file_type][index] with Path(files_dir / 'files.json').open(mode='w') as outfile: json.dump(j, outfile, indent=4) update.message.reply_text("file has been deleted") else: update.message.reply_text("The file has NOT been deleted") return ConversationHandler.END
def ifc_start(update, context): all_files = getJson(files_dir / 'files.json') try: ifc_file_name = context.user_data['ifc_file_name'] except: try: ifc_files = show_all_file_type(all_files, 'ifc') if (ifc_files == ""): raise Exception('No ifc files uploaded') update.message.reply_text(ifc_files) except: update.message.reply_text('You have no files stored of type IFC. Try using /sendfile to store one. ') return ConversationHandler.END update.message.reply_text('Which IFC file would you like to load? Type the name of the file') return GET_IFC_FILE reply_keyboard = [['Load an IFC file', 'Get .ply file'], ['View', 'View wire frame'], ['Get analysis', 'Stretch']] update.message.reply_text('What would you like to do?', reply_markup=ReplyKeyboardMarkup(reply_keyboard, one_time_keyboard=True)) return GET_IFC_RESPONSE
def get_description(update, context): file_type = context.user_data['file_type'] file_name = context.user_data['file_name'] file_title = context.user_data['file_title'] desc = update.message.text user = update.message.from_user j = getJson(files_dir / 'files.json') if (desc is None): j[file_type].pop(-1) with Path(files_dir / 'files.json').open(mode='w') as outfile: json.dump(j, outfile, indent=4) update.message.reply_text( "Invalid description! Cancelling file upload. Type /sendfile to try again" ) return ConversationHandler.END save_file_type(update, context, file_name, file_title, desc, file_type, user) update.message.reply_text( 'File uploaded! View your files with /filemanage') return ConversationHandler.END
def start_analysis(update, context): ifc_file_name = context.user_data['ifc_file_name'] json_obj = getJson(files_dir / ifc_file_name) classes = {} for item in json_obj: class_name = item['Class'] if class_name == 'ShapeRepresentation': pass elif class_name in classes.keys(): classes[class_name]['Count'] += 1 try: classes[class_name]['Sum of PSet_Revit_Dimensions'] += item['PSet_Revit_Dimensions'] except: pass if (class_name == 'Wall'): if 'Volume' in item.keys(): classes[class_name]['Volume'] += item['Volume'] else: classes[class_name] = {} classes[class_name]['Count'] = 1 try: classes[class_name]['Sum of PSet_Revit_Dimensions'] = item['PSet_Revit_Dimensions'] except: pass if (class_name == 'Wall'): classes[class_name]['Volume'] = 0 if 'Volume' in item.keys(): classes[class_name]['Volume'] += item['Volume'] output = "<code>" for class_key in classes.keys(): item = classes[class_key] output += (f'\u2022 {class_key}\n') for key in item.keys(): output += f' {key:<32}: {item[key]}\n' output += "\n" output += "</code>" update.message.reply_text(classes) update.message.reply_text(output) return ConversationHandler.END
def save_to_new_ifc(new_all_points, old_file_name, new_file_name): counter = 0 json_obj = getJson(files_dir / old_file_name) stretched_json_obj = [] for item in json_obj: class_name = item['Class'] if class_name == 'ShapeRepresentation': points_triangles_str = "" points, triangles = split_triangles_points(item['Items'], 1) for point in points: (x, y, z) = new_all_points[counter] counter += 1 points_triangles_str += f"v {x} {y} {z}\n" for index, ([a, b, c], _, _, _) in enumerate(triangles): if (index == len(triangles)-1): points_triangles_str += f"f {a} {b} {c}" else: points_triangles_str += f"f {a} {b} {c}\n" item['Items'] = [points_triangles_str] stretched_json_obj += [item] with Path(files_dir / f'{new_file_name}.json').open(mode = 'w') as outfile: json.dump(stretched_json_obj, outfile, indent=4)
def del_file(update, context): file_type = context.user_data['file_type'] file_name = update.message.text file_name = file_name.lower() context.user_data['file_name'] = file_name # send the file to the user j = getJson(files_dir / 'files.json') try: index = [ index for index, item in enumerate(j[file_type]) if item['name'].lower() == file_name ][0] reply_keyboard = [['Yes', 'No']] update.message.reply_text( "Are you sure you would like to remove this file?", reply_markup=ReplyKeyboardMarkup(reply_keyboard, one_time_keyboard=True)) return DELETE except: update.message.reply_text('No file with this filename') return ConversationHandler.END
def detailed_view(update,context): choice = update.message.text teams = getJson('teams.json') if (choice == "All"): view_string = "<code>" view_string += f"{'Sprint duration':<18}: {teams['sprint_duration']}\n" view_string += f'{"Groups":<18}:\n' view_string += '-'*25 for team_no, team in enumerate(teams['teams']): view_string += f'\n{" Group number":<18}: {team_no+1}\n' view_string += f'{" Group name":<18}: {team["group_name"]}\n' view_string += f'{" Group members":<18}:\n' if (len(team['group_members']) == 0): view_string += f' Empty\n' for member in team['group_members']: view_string += f' @{member}\n' view_string += f'{" Group tasks":<18}:\n' if (len(team['tasks'])==0): view_string += f' Empty\n' for i in range(len(team['tasks'])): if (i>0): view_string+="\n" task = team["tasks"][i] description = team["descriptions"][i] view_string += " "+task + "\n" view_string += " "+description + "\n" view_string += ' ' + '-'*10 view_string = view_string.strip('-') view_string = view_string.strip(' ') view_string += '-' * 25 view_string += '</code>' update.message.reply_text(view_string) elif (choice in [str(i) for i in range(1,1+len(teams["teams"]))]): choice = int(choice) - 1 team = teams["teams"][choice] view_string = "<code>" view_string += f"{'Sprint duration':<18}: {teams['sprint_duration']}\n" view_string += f'\n{"Group number":<18}: {choice+1}\n' view_string += f'{"Group name":<18}: {teams["teams"][choice]["group_name"]}\n' view_string += '-'*25 view_string += f'\n{" Group members":<18}:\n' if (len(team['group_members']) == 0): view_string += f' Empty\n' for member in team['group_members']: view_string += f' @{member}\n' view_string += f'{" Group tasks":<18}:\n' if (len(team['tasks'])==0): view_string += f' Empty\n' for i in range(len(team['tasks'])): if (i>0): view_string+="\n" task = team["tasks"][i] description = team["descriptions"][i] view_string += " "+task + "\n" view_string += " "+description + "\n" view_string += ' ' + '-'*10 view_string = view_string.strip('-') view_string = view_string.strip(' ') view_string += '-' * 25 view_string += '</code>' update.message.reply_text(view_string) elif choice.lower() == 'cancel': update.message.reply_text('Cancelling view team. Type /teamstart to try again. ', reply_markup=ReplyKeyboardRemove()) else: update.message.reply_text('Invalid team. Type /teamstart to try again. ', reply_markup=ReplyKeyboardRemove()) return ConversationHandler.END