wkaisertexas / tiktok-uploader

Automatically ⬆️ upload TikTok videos
https://pypi.org/project/tiktok-uploader/
MIT License
390 stars 91 forks source link

edits xPaths for new UI changes #141

Closed callumjamesfortune closed 6 months ago

callumjamesfortune commented 6 months ago

This PR just updates the xPath to accommodate the new TikTok UI update which was a breaking change.

This PR should solve the following issues...

https://github.com/wkaisertexas/tiktok-uploader/issues/140 https://github.com/wkaisertexas/tiktok-uploader/issues/138

It does not fix the scheduling issues though, they are likely the same as the post issues but I don't have time to look into it today.

This is an image showing the successful post message being returned:

image

@wkaisertexas

tonysmiles commented 6 months ago

I am also having problems with scheduling, currently the schedule display on chrome is a radio button and not a switch, I have replaced it in the _set_schedule_video function as below

radio_button = driver.find_element(By.CSS_SELECTOR, "#root > div > div > div > div.jsx-480949468.container-v2.form-panel.flow-opt-v1 > div > div.jsx-2745626608.form-v2.reverse.flow-opt-v1 > div.jsx-3395700143 > div > div.jsx-3395700143.schedule-radio-container > div:nth-child(2) > div") radio_button.click()

However, currently the structure of __date_picker and __time_picker is also changed and I am not able to solve this problem, can you solve it with me?

steinathan commented 6 months ago

It works image

callumjamesfortune commented 6 months ago

I am also having problems with scheduling, currently the schedule display on chrome is a radio button and not a switch, I have replaced it in the _set_schedule_video function as below

radio_button = driver.find_element(By.CSS_SELECTOR, "#root > div > div > div > div.jsx-480949468.container-v2.form-panel.flow-opt-v1 > div > div.jsx-2745626608.form-v2.reverse.flow-opt-v1 > div.jsx-3395700143 > div > div.jsx-3395700143.schedule-radio-container > div:nth-child(2) > div") radio_button.click()

However, currently the structure of __date_picker and __time_picker is also changed and I am not able to solve this problem, can you solve it with me?

Well I don't use the scheduling feature but I can take a look or we can work together on it. Shouldn't be a super difficult fix. Let me know what suits you

tonysmiles commented 6 months ago

I am also having problems with scheduling, currently the schedule display on chrome is a radio button and not a switch, I have replaced it in the _set_schedule_video function as below radio_button = driver.find_element(By.CSS_SELECTOR, "#root > div > div > div > div.jsx-480949468.container-v2.form-panel.flow-opt-v1 > div > div.jsx-2745626608.form-v2.reverse.flow-opt-v1 > div.jsx-3395700143 > div > div.jsx-3395700143.schedule-radio-container > div:nth-child(2) > div") radio_button.click() However, currently the structure of __date_picker and __time_picker is also changed and I am not able to solve this problem, can you solve it with me?

Well I don't use the scheduling feature but I can take a look or we can work together on it. Shouldn't be a super difficult fix. Let me know what suits you

def __time_picker(driver, hour: int, minute: int) -> None: logger.debug(green('Chọn thời gian')) time_picker = WebDriverWait(driver, config['implicit_wait']).until( EC.element_to_be_clickable((By.CSS_SELECTOR, "#root > div > div > div > div.jsx-480949468.container-v2.form-panel.flow-opt-v1 > div > div.jsx-2745626608.form-v2.reverse.flow-opt-v1 > div.jsx-3395700143 > div > div.jsx-3395700143.scheduled-picker > div:nth-child(1) > div.TUXFormField.TUXTextInput > div.TUXInputBox > div")) ) time_picker.click()

time_picker_container = WebDriverWait(driver, config['implicit_wait']).until(
    EC.element_to_be_clickable((By.CSS_SELECTOR, "#root > div > div > div > div.jsx-480949468.container-v2.form-panel.flow-opt-v1 > div > div.jsx-2745626608.form-v2.reverse.flow-opt-v1 > div.jsx-3395700143 > div > div.jsx-3395700143.scheduled-picker > div:nth-child(1) > div.tiktok-timepicker-time-picker-container > div:nth-child(2)"))
)

# 00 = 0, 01 = 1, 02 = 2, 03 = 3, 04 = 4, 05 = 5, 06 = 6, 07 = 7, 08 = 8, 09 = 9, 10 = 10, 11 = 11, 12 = 12,
# 13 = 13, 14 = 14, 15 = 15, 16 = 16, 17 = 17, 18 = 18, 19 = 19, 20 = 20, 21 = 21, 22 = 22, 23 = 23
hour_options = WebDriverWait(driver, config['implicit_wait']).until(
    EC.visibility_of_all_elements_located((By.CSS_SELECTOR, "#root > div > div > div > div.jsx-480949468.container-v2.form-panel.flow-opt-v1 > div > div.jsx-2745626608.form-v2.reverse.flow-opt-v1 > div.jsx-3395700143 > div > div.jsx-3395700143.scheduled-picker > div:nth-child(1) > div.tiktok-timepicker-time-picker-container > div:nth-child(2) > div > div:nth-child(18) > span"))
)
# 00 == 0, 05 == 1, 10 == 2, 15 == 3, 20 == 4, 25 == 5, 30 == 6, 35 == 7, 40 == 8, 45 == 9, 50 == 10, 55 == 11
minute_options = WebDriverWait(driver, config['implicit_wait']).until(
    EC.visibility_of_all_elements_located((By.CSS_SELECTOR, "#root > div > div > div > div.jsx-480949468.container-v2.form-panel.flow-opt-v1 > div > div.jsx-2745626608.form-v2.reverse.flow-opt-v1 > div.jsx-3395700143 > div > div.jsx-3395700143.scheduled-picker > div:nth-child(1) > div.tiktok-timepicker-time-picker-container > div:nth-child(3) > div > div:nth-child(5) > span"))
)
hour_to_click = hour_options[hour]
minute_option_correct_index = int(minute / 5)
minute_to_click = minute_options[minute_option_correct_index]

time.sleep(1)  # temporay fix => might be better to use an explicit wait
driver.execute_script("arguments[0].scrollIntoView({block: 'center', inline: 'nearest'});", hour_to_click)
time.sleep(1)  # temporay fix => might be better to use an explicit wait
hour_to_click.click()

driver.execute_script("arguments[0].scrollIntoView({block: 'center', inline: 'nearest'});", minute_to_click)
time.sleep(2)  # temporary fixed => Might be better to use an explicit wait
minute_to_click.click()

# click somewhere else to close the time picker
time_picker.click()

#time.sleep(.5)  # wait for the DOM change
__verify_time_picked_is_correct(driver, hour, minute)

I made some changes to the __time_picker function, now time_picker works stably, however it cannot scroll to select hours and minutes as I specified.

tonysmiles commented 6 months ago

The scheduling issue has been resolved

def __time_picker(driver, hour: int, minute: int) -> None: logger.debug(green('Chọn thời gian'))

# Tìm và click vào bộ chọn thời gian
time_picker = WebDriverWait(driver, config['implicit_wait']).until(
    EC.element_to_be_clickable((By.CSS_SELECTOR, "#root > div > div > div > div.jsx-480949468.container-v2.form-panel.flow-opt-v1 > div > div.jsx-2745626608.form-v2.reverse.flow-opt-v1 > div.jsx-3395700143 > div > div.jsx-3395700143.scheduled-picker > div:nth-child(1) > div.TUXFormField.TUXTextInput > div.TUXInputBox > div"))
)
time_picker.click()

hour_options = driver.find_elements(By.XPATH, "//span[contains(@class, 'tiktok-timepicker-left')]")

minute_options = driver.find_elements(By.XPATH, "//span[contains(@class, 'tiktok-timepicker-right')]")

hour_to_click = hour_options[hour]
#minute_option_correct_index = int(minute / 5)
minute_to_click = minute_options[minute]

time.sleep(1)  # temporay fix => might be better to use an explicit wait
driver.execute_script("arguments[0].scrollIntoView({block: 'center', inline: 'nearest'});", hour_to_click)
WebDriverWait(driver, 15).until(EC.visibility_of(hour_to_click))
time.sleep(1)  # temporay fix => might be better to use an explicit wait
hour_to_click.click()

# Tìm và click vào bộ chọn thời gian
time_picker = WebDriverWait(driver, config['implicit_wait']).until(
    EC.element_to_be_clickable((By.CSS_SELECTOR, "#root > div > div > div > div.jsx-480949468.container-v2.form-panel.flow-opt-v1 > div > div.jsx-2745626608.form-v2.reverse.flow-opt-v1 > div.jsx-3395700143 > div > div.jsx-3395700143.scheduled-picker > div:nth-child(1) > div.TUXFormField.TUXTextInput > div.TUXInputBox > div"))
)
time_picker.click()

driver.execute_script("arguments[0].scrollIntoView({block: 'center', inline: 'nearest'});", minute_to_click)
WebDriverWait(driver, 30).until(EC.visibility_of(minute_to_click))
time.sleep(2)  # temporary fixed => Might be better to use an explicit wait
minute_to_click.click()

# click somewhere else to close the time picker
time_picker.click()

time.sleep(.5)  # wait for the DOM change
callumjamesfortune commented 6 months ago

The scheduling issue has been resolved

def __time_picker(driver, hour: int, minute: int) -> None: logger.debug(green('Chọn thời gian'))

# Tìm và click vào bộ chọn thời gian
time_picker = WebDriverWait(driver, config['implicit_wait']).until(
    EC.element_to_be_clickable((By.CSS_SELECTOR, "#root > div > div > div > div.jsx-480949468.container-v2.form-panel.flow-opt-v1 > div > div.jsx-2745626608.form-v2.reverse.flow-opt-v1 > div.jsx-3395700143 > div > div.jsx-3395700143.scheduled-picker > div:nth-child(1) > div.TUXFormField.TUXTextInput > div.TUXInputBox > div"))
)
time_picker.click()

hour_options = driver.find_elements(By.XPATH, "//span[contains(@class, 'tiktok-timepicker-left')]")

minute_options = driver.find_elements(By.XPATH, "//span[contains(@class, 'tiktok-timepicker-right')]")

hour_to_click = hour_options[hour]
#minute_option_correct_index = int(minute / 5)
minute_to_click = minute_options[minute]

time.sleep(1)  # temporay fix => might be better to use an explicit wait
driver.execute_script("arguments[0].scrollIntoView({block: 'center', inline: 'nearest'});", hour_to_click)
WebDriverWait(driver, 15).until(EC.visibility_of(hour_to_click))
time.sleep(1)  # temporay fix => might be better to use an explicit wait
hour_to_click.click()

# Tìm và click vào bộ chọn thời gian
time_picker = WebDriverWait(driver, config['implicit_wait']).until(
    EC.element_to_be_clickable((By.CSS_SELECTOR, "#root > div > div > div > div.jsx-480949468.container-v2.form-panel.flow-opt-v1 > div > div.jsx-2745626608.form-v2.reverse.flow-opt-v1 > div.jsx-3395700143 > div > div.jsx-3395700143.scheduled-picker > div:nth-child(1) > div.TUXFormField.TUXTextInput > div.TUXInputBox > div"))
)
time_picker.click()

driver.execute_script("arguments[0].scrollIntoView({block: 'center', inline: 'nearest'});", minute_to_click)
WebDriverWait(driver, 30).until(EC.visibility_of(minute_to_click))
time.sleep(2)  # temporary fixed => Might be better to use an explicit wait
minute_to_click.click()

# click somewhere else to close the time picker
time_picker.click()

time.sleep(.5)  # wait for the DOM change

That's great that you got it working. Can I suggest using the toml file for references to elements instead of like By.CSS_SELECTOR, "#root > div > div > div > div.jsx-480949468.container-v2.form-panel.flow-opt-v1 > div > div.jsx-2745626608.form-v2.reverse.flow-opt-v1 > div.jsx-3395700143 > div > div.jsx-3395700143.scheduled-picker > div:nth-child(1) > div.TUXFormField.TUXTextInput > div.TUXInputBox > div and you should be able to shorten selectors like that by a lot. Just helps keep it clean and maintainable. Nice work though

joaovit1 commented 6 months ago

@tonysmiles I am trying to follow your resolution for the schedule feature, but I don't see the code for the _date_picker function, can you help me with it?