commit 2fbcad3cfabecaef1fd85c55759fc6bf6b2b2361 Author: Hex Ripley Date: Thu Feb 15 12:24:58 2024 -0800 Initial commit diff --git a/AssignerPal.py b/AssignerPal.py new file mode 100644 index 0000000..5fd5396 --- /dev/null +++ b/AssignerPal.py @@ -0,0 +1,75 @@ +from selenium import webdriver +from selenium.webdriver.common.keys import Keys +from selenium.webdriver.common.by import By +from selenium.webdriver.support.wait import WebDriverWait +from selenium.webdriver.support import expected_conditions as EC +from selenium.webdriver.common.action_chains import ActionChains +import AutoTicket +import AutoColor +import json +import os + +urls = {"NOC-PROV": "", "NOC-PROV-ADV" : "", "PROV-DSL" : "", "PROV-FIBER":"", "PROV-IPBB":"","PROV-MISC":"","FUS-PROV":"","TICKETS":""} + +def assign_urls(dictionary): + for key in dictionary: + value = input(f"Enter url for '{key}': ") + dictionary[key] = value + +def get_team(): + user_list = [] + print("What are the usernames?") + while True: + user_input = input("Add to list (Press Enter to finish): ") + if user_input: + user_list.append(user_input.lower()) + else: + break + print("I'm working with these users:", user_list) + print("") + print("This look good? y/n") + answer = input() + if "n" in answer: + print("Let's try that again...") + print("") + get_team() + else: + return user_list + +def first_time_setup(): + print("Initiating first time set up") + print("To ensure internal security, you will need to provide urls for each location,") + print("As well as employee usernames (first.last)") + print("If you don't know, you shouldn't be using this script.") + assign_urls(urls) + with open('urls.json', 'w') as file: + json.dump(urls, file) + users = get_team() + with open('team.json', 'w') as file: + json.dump(users, file) + +def choice(urls,users,driver): + print("Tickets or Directly?") + user_choice = input() + if "ti" in user_choice.lower(): + AutoTicket.auto_ticket(urls,users,driver) + if "di" in user_choice.lower(): + AutoColor.tag_assist(urls,driver) + print("More?") + if input("y/n : ") == "y": + choice(urls,users,driver) + +def main(): + if os.path.exists('urls.json'): + print("Do first time set up?") + if input("y/n : ") == "y": + first_time_setup() + else: first_time_setup() + driver = webdriver.Firefox() + with open('urls.json', 'r') as file: + urls = json.load(file) + with open('team.json', 'r') as file: + users = json.load(file) + choice(urls,users,driver) + +main() \ No newline at end of file diff --git a/AutoColor.py b/AutoColor.py new file mode 100644 index 0000000..ab1340e --- /dev/null +++ b/AutoColor.py @@ -0,0 +1,256 @@ +from selenium import webdriver +from selenium.webdriver.common.keys import Keys +from selenium.webdriver.common.by import By +from selenium.webdriver.support.wait import WebDriverWait +from selenium.webdriver.support import expected_conditions as EC +from selenium.webdriver.common.action_chains import ActionChains + +# Condensed string finder for lists of strings +def found_string(string_list, main_string): + for string in string_list: + if string in main_string: + return True + return False + +# Get tag_count dictionary +def count_tags(queues,tags): + tag_count = {} + for queue in queues: + count = 0 + for tag in tags: + if queue in tag.text.lower(): + count += 1 + tag_count[queue] = count + return tag_count + +def next_string(list_of_strings): + index = 0 + while True: + yield list_of_strings[index] + index = (index + 1) % len(list_of_strings) + + + +# Assign steps in order of queue list without checking tag_count +def dumb_make_tags(queues,tags,driver): + original_window = driver.current_window_handle + next_queue = next_string(queues) + for tag in tags: + if found_string(queues, tag.text.lower()) == False: + tag.send_keys(Keys.CONTROL + Keys.ENTER) + WebDriverWait(driver, 10).until(EC.number_of_windows_to_be(2)) + for window_handle in driver.window_handles: + if window_handle != original_window: + driver.switch_to.window(window_handle) + break + WebDriverWait(driver, 10).until(EC.presence_of_element_located((By.TAG_NAME, 'h2'))) + driver.find_element(By.CSS_SELECTOR, "a.edit").click() + try: + element = WebDriverWait(driver, 10).until( + EC.presence_of_element_located((By.ID, "tag_id")) + ) + finally: + tag_field = driver.find_element(By.ID, "tag_id") + tag_field.send_keys(Keys.END) + tag_field.send_keys("/",next(next_queue)) + print("Please verify tag looks correct. Press enter to continue.") + input() + tag_field.send_keys(Keys.ENTER) + driver.close() + driver.switch_to.window(original_window) + +# Tool to create a menu based on a list. +def select_list_item(list_of_strings): + for i, item in enumerate(list_of_strings): + print(f"{chr(97 + i)}) {item}") + + while True: + choice = input("Please select an option (a, b, c, etc.): ").lower() + if choice.isalpha() and ord(choice) - 97 in range(len(list_of_strings)): + return list_of_strings[ord(choice) - 97] + else: + print("Invalid choice. Please select a valid option.") + +# Select every unassigned tag, print queue count, print step name, use user input to choose what tag to assign +def guided_make_tags(queues,tags,driver): + original_window = driver.current_window_handle + for tag in tags: + if found_string(queues, tag.text.lower()) == False: + tag.send_keys(Keys.CONTROL + Keys.ENTER) + WebDriverWait(driver, 10).until(EC.number_of_windows_to_be(2)) + for window_handle in driver.window_handles: + if window_handle != original_window: + driver.switch_to.window(window_handle) + break + WebDriverWait(driver, 10).until(EC.presence_of_element_located((By.TAG_NAME, 'h2'))) + print("What should we tag this workflow? ", driver.find_element(By.TAG_NAME, 'h2').text) + guided_tag = select_list_item(queues) + driver.find_element(By.CSS_SELECTOR, "a.edit").click() + try: + element = WebDriverWait(driver, 10).until( + EC.presence_of_element_located((By.ID, "tag_id")) + ) + finally: + tag_field = driver.find_element(By.ID, "tag_id") + tag_field.send_keys(Keys.END) + tag_field.send_keys("/",guided_tag) + print("Please verify tag looks correct. Press enter to continue.") + input() + tag_field.send_keys(Keys.ENTER) + driver.close() + driver.switch_to.window(original_window) + + + + +# Get lowest_queue string, and increment tag_count for the value for that queue by one. +def find_lowest_and_increment(dictionary): + if not dictionary: + return None + + min_key = min(dictionary, key=dictionary.get) + + dictionary[min_key] += 1 + + return min_key + +# Check which queue has the least number of assigned workflows. +def smart_make_tags(queues,tags,driver): + original_window = driver.current_window_handle + tag_count = count_tags(queues,tags) + for tag in tags: + if found_string(queues, tag.text.lower()) == False: + lowest_queue = find_lowest_and_increment(tag_count) + tag.send_keys(Keys.CONTROL + Keys.ENTER) + WebDriverWait(driver, 10).until(EC.number_of_windows_to_be(2)) + for window_handle in driver.window_handles: + if window_handle != original_window: + driver.switch_to.window(window_handle) + break + WebDriverWait(driver, 10).until(EC.presence_of_element_located((By.TAG_NAME, 'h2'))) + driver.find_element(By.CSS_SELECTOR, "a.edit").click() + try: + element = WebDriverWait(driver, 10).until( + EC.presence_of_element_located((By.ID, "tag_id")) + ) + finally: + tag_field = driver.find_element(By.ID, "tag_id") + tag_field.send_keys(Keys.END) + tag_field.send_keys("/",lowest_queue) + print("Please verify tag looks correct.") + input() + tag_field.send_keys(Keys.ENTER) + driver.close() + driver.switch_to.window(original_window) + +# Ignore future steps. +def future_tag_manip(driver): + future_tag_field = driver.find_element(By.ID, "cf-future-tag") + future_tag_field.clear() + future_tag_field.send_keys("Automation In Progress") + +def filter_steps_manip(driver): + step_field = driver.find_element(By.ID, "cf-due-step") + step_field.clear() + print("") + print("Wanna avoid touching a step?") + print("Take a look at what's in the queue.") + print("If there's anything in there you don't want to tag,") + print("copy the step name here, with | to seperate steps.") + print("e.g. 'Confirm Disconnect Date Has Passed|Reserve Numbers'") + print("or, press Enter to skip") + filters = input() + if filters != "": + step_field.send_keys("^(?!.*(",filters,")).*$") + print("") + print("This look good? y/n") + answer = input() + if "n" in answer: + print("Let's try that again...") + print("") + filter_steps_manip() + + +def automation_picker(queues,tags,driver): + print("") + print("How would you like to approach assigning to this queue?") + print("Options are: smart, guided, dumb, skip") + print("Smart : Assign workflows to queue with lowest number of items until all queues are even.") + print(" : (Best for Prov or Prov_Advanced Queues)") + print("Guided: For each workflow, you will be asked which queue you would like to assign the") + print(" : workflow to. (Best if there are less than 4 items to assign)") + print("Dumb : Assign workflows to each queue sequentially. (Best for Resi Prov steps)") + print("Skip : Don't assign workflows today :)") + choice = input() + if choice.lower() == "smart": + print("Okay, I'll make you proud (> ͡⎚ ω ͡⎚)>✎") + smart_make_tags(queues,tags,driver) + elif choice.lower() == "guided": + print("Okay, you get to do all the work now (-ω-) zzZ") + guided_make_tags(queues,tags,driver) + elif choice.lower() == "dumb": + print("Okay, I make thing go now ─=≡Σ((( つ><)つ") + dumb_make_tags(queues,tags,driver) + else: + print("Skipping...") + +def get_queues(): + user_list = [] + print("What queues are we working with today?") + while True: + user_input = input("Add to queue list (Press Enter to finish): ") + if user_input: + user_list.append(user_input.lower()) + else: + break + print("I'm working with these queues:", user_list) + print("") + print("This look good? y/n") + answer = input() + if "n" in answer: + print("Let's try that again...") + print("") + get_queues() + else: + return user_list + +def get_value_from_dictionary(dictionary): + keys = list(dictionary.keys()) + options = {chr(97 + i): key for i, key in enumerate(keys)} + + while True: + print("Select a key:") + for key, value in options.items(): + print(f"{key}: {value}") + + choice = input("Enter the letter corresponding to your choice: ").lower() + + if choice in options: + return dictionary[options[choice]] + else: + print("Invalid choice. Please enter a valid letter.") + +def tag_assist(urls,driver): + print("This is someone's automation tool. If you don't know what you're doing, please abort.") + print("Choose URL please:") + url = get_value_from_dictionary(urls) + driver.get(url) + print("") + print("Please use the browser to log in. I won't look (づ_ど)") + try: + element = WebDriverWait(driver, 500).until( + EC.presence_of_element_located((By.ID, "dueWorkflowSteps_wrapper")) + ) + finally: + future_tag_manip(driver) + filter_steps_manip(driver) + queues = get_queues() + tags = driver.find_elements(By.CSS_SELECTOR, "td.tag") + automation_picker(queues,tags,driver) + print("Done! ✧⋆٩(ˊ ᗜ ˋ )و ♡✧") + print("Wanna do another? y/n") + answer = input() + if answer == "y": + tag_assist(queues) + else: + print("Goodbye! ヾ(˶ᵔ ᗜ ᵔ˶)") \ No newline at end of file diff --git a/AutoTicket.py b/AutoTicket.py new file mode 100644 index 0000000..22640f1 --- /dev/null +++ b/AutoTicket.py @@ -0,0 +1,87 @@ +from selenium import webdriver +from selenium.webdriver.common.keys import Keys +from selenium.webdriver.common.by import By +from selenium.webdriver.support.wait import WebDriverWait +from selenium.webdriver.support import expected_conditions as EC +from selenium.webdriver.common.action_chains import ActionChains + +def get_filters(driver): + print("Setting up filters...") + driver.find_element(By.CLASS_NAME, "select2-selection__clear").click() + group_fields = search_fields = driver.find_elements(By.CLASS_NAME, "select2-search__field") + group_fields[1].send_keys("noc-prov") + group_fields[1].send_keys(Keys.ENTER) + group_fields[1].send_keys("provisioning") + group_fields[1].send_keys(Keys.ENTER) + driver.find_element(By.CSS_SELECTOR, ".fa-cogs").click() + clear_buttons = driver.find_elements(By.CLASS_NAME, "select2-selection__clear") + clear_buttons[1].click() + driver.find_element(By.CSS_SELECTOR, ".search-btn").click() + WebDriverWait(driver, 3) + +def get_names(users,driver): + tbody = driver.find_element(By.TAG_NAME, "tbody") + rows = tbody.find_elements(By.TAG_NAME, "tr") + name_count = {} + for name in users: + count = 0 + for row in rows: + tds = row.find_elements(By.TAG_NAME, 'td') + if name in tds[2].text: + count += 1 + name_count[name] = count + return name_count + +def find_lowest_and_increment(dictionary): + if not dictionary: + return None + + min_key = min(dictionary, key=dictionary.get) + + dictionary[min_key] += 1 + + return min_key + +def assign_tickets(namecount,driver): + original_window = driver.current_window_handle + tbody = driver.find_element(By.TAG_NAME, "tbody") + rows = tbody.find_elements(By.TAG_NAME, "tr") + for row in rows: + tds = row.find_elements(By.TAG_NAME, 'td') + if tds[2].text == "none": + lowest_name = find_lowest_and_increment(namecount) + tds[1].find_element(By.TAG_NAME, 'a').send_keys(Keys.CONTROL + Keys.ENTER) + WebDriverWait(driver, 10).until(EC.number_of_windows_to_be(2)) + for window_handle in driver.window_handles: + if window_handle != original_window: + driver.switch_to.window(window_handle) + break + WebDriverWait(driver, 10).until(EC.presence_of_element_located((By.ID, "owner"))) + controls = driver.find_element(By.ID, 'ticket-controls').find_elements(By.CLASS_NAME, "ticket-control") + owner_button = controls[3].find_element(By.CLASS_NAME, 'select2-container') + owner_button.click() + search_fields = driver.find_elements(By.CLASS_NAME, 'select2-search__field') + owner_field = search_fields[3] + owner_field.send_keys(lowest_name) + owner_field.send_keys(Keys.ENTER) + print("Check to see if this worked, then press enter") + input() + driver.find_element(By.CLASS_NAME, 'update').click() + driver.close() + driver.switch_to.window(original_window) + + +def auto_ticket(urls,users,driver): + driver.get(urls['TICKETS']) + print("") + print("Please use the browser to log in. I won't look (づ_ど)") + try: + element = WebDriverWait(driver, 500).until( + EC.presence_of_element_located((By.CLASS_NAME, "select2-selection__clear")) + ) + finally: + get_filters(driver) + namecount = get_names(users,driver) + print(namecount) + assign_tickets(namecount,driver) + print("Done! ✧⋆٩(ˊ ᗜ ˋ )و ♡✧") \ No newline at end of file