Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Select UK English #16

Merged
merged 7 commits into from
Jul 5, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "youtube-videos-uploader",
"version": "1.1.10",
"version": "1.2.0",
"description": "Uploads videos to youtube without any limits",
"main": "upload.js",
"dependencies": {
Expand Down
146 changes: 129 additions & 17 deletions upload.js
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ const width = 900
let browser, page

const uploadURL = 'https://www.youtube.com/upload'
const homePageURL = 'https://www.youtube.com'

// capitalizes all the first letters in a sentense
const capitalize = words => words.split(' ').map(w => w[0].toUpperCase() + w.substring(1)).join(' ')
Expand All @@ -55,6 +56,8 @@ async function upload (credentials, videos) {
console.log("Login failed trying again to login")
await login(page, credentials)
}

await changeHomePageLangIfNeeded(page)

for (const video of videos) {
const link = await uploadVideo(video)
Expand All @@ -66,6 +69,115 @@ async function upload (credentials, videos) {
return uploadedYTLink
}

/**
* @param {import('puppeteer').Page} localPage
*
* @returns {void}
*/
async function changeLoginPageLangIfNeeded(localPage) {

const selectedLangSelector = '[aria-selected="true"]'
try {
await localPage.waitForSelector(selectedLangSelector)
} catch(e) {
throw new Error('Failed to find selected lang : ' + e.name)
}


/** @type {?string} */
const selectedLang = await localPage.evaluate(
selectedLangSelector => document.querySelector(selectedLangSelector).innerText,
selectedLangSelector
)

if (! selectedLang) {
throw new Error('Failed to find selected lang : Empty text')
}

if (selectedLang.includes('English')) {
console.log('Selected lang is already english')

return
}

await localPage.click(selectedLangSelector)

await localPage.waitForTimeout(1000)

const englishLangItemSelector = '[role="presentation"]:not([aria-hidden="true"])>[data-value="en-GB"]'

try {
await localPage.waitForSelector(englishLangItemSelector)
} catch(e) {
throw new Error('Failed to find english lang item : ' + e.name)
}

await localPage.click(englishLangItemSelector)

await localPage.waitForTimeout(1000)
}

/**
* @param {import('puppeteer').Page} localPage
*
* @returns {void}
*/
async function changeHomePageLangIfNeeded(localPage) {
await localPage.goto(homePageURL)

const avatarButtonSelector = 'button#avatar-btn'

try {
await localPage.waitForSelector(avatarButtonSelector)
} catch (e) {
throw new Error('Avatar button not found : ' + e.name)
}

await localPage.click(avatarButtonSelector)

const langMenuItemSelector = 'yt-multi-page-menu-section-renderer+yt-multi-page-menu-section-renderer>#items>ytd-compact-link-renderer>a'
try {
await localPage.waitForSelector(langMenuItemSelector)
} catch (e) {
throw new Error('Lang menu item selector not found : ' + e.name)
}

/** @type {?string} */
const selectedLang = await localPage.evaluate(
langMenuItemSelector => document.querySelector(langMenuItemSelector).innerText,
langMenuItemSelector
)

if (! selectedLang) {
throw new Error('Failed to find selected lang : Empty text')
}

if (selectedLang.includes('English')) {
await localPage.goto(uploadURL)

return
}

await localPage.click(langMenuItemSelector)

const englishItemXPath = '//*[normalize-space(text())=\'English (UK)\']'

try {
await localPage.waitForXPath(englishItemXPath)
} catch (e) {
throw new Error('English item selector not found : ' + e.name)
}

await localPage.waitForTimeout(3000)

await localPage.evaluate(
englishItemXPath => document.evaluate(englishItemXPath, document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue.click(),
englishItemXPath
)

await localPage.goto(uploadURL)
}

// context and browser is a global variable and it can be accessed from anywhere
// function that launches a browser
async function launchBrowser () {
Expand All @@ -77,34 +189,29 @@ async function launchBrowser () {

async function login (localPage, credentials) {
await localPage.goto(uploadURL)
await localPage.waitForSelector('input[type="email"]')

// await localPage.click('[aria-selected="true"]')
// await localPage.click('[data-value="af"]')
// const ukLangXpath = '//*[normalize-space(text())=\'‪English (United Kingdom)‬\']'
// const ukLangXpath = '//*[contains(text(),"Afrikaans")]'

// const ukBtn = await localPage.$x(ukLangXpath)
// await page.evaluate(() => document.querySelector('[data-value="af"]').scrollIntoView())
// await page.evaluate(el => el.click(), ukBtn[0])
await changeLoginPageLangIfNeeded(localPage)

const emailInputSelector = 'input[type="email"]'
await localPage.waitForSelector(emailInputSelector)

await localPage.type('input[type="email"]', credentials.email)
await localPage.type(emailInputSelector, credentials.email)
await localPage.keyboard.press('Enter')
await localPage.waitForNavigation({
waitUntil: 'networkidle0'
})

// await localPage.waitForXPath('//*[normalize-space(text())=\'Show password\']')
await localPage.waitForSelector('input[type="password"]')
await localPage.type('input[type="password"]', credentials.pass)
const passwordInputSelector = 'input[type="password"]:not([aria-hidden="true"])'
await localPage.waitForSelector(passwordInputSelector)
await localPage.type(passwordInputSelector, credentials.pass)

await localPage.keyboard.press('Enter')

await localPage.waitForNavigation()

try {
const selectBtnXPath = '//*[normalize-space(text())=\'Select files\']'
await localPage.waitForXPath(selectBtnXPath, { timeout: 60000 })
const uploadPopupSelector = 'ytcp-uploads-dialog'
await localPage.waitForSelector(uploadPopupSelector, { timeout: 60000 })
} catch (error) {
console.error(error)
await securityBypass(localPage, credentials.recoveryemail)
Expand Down Expand Up @@ -258,12 +365,17 @@ async function uploadVideo (videoJSON) {
// await publicOption[0].click()

// Get publish button
const publishXPath = '//*[normalize-space(text())=\'Publish\']/parent::*[not(@disabled)]'
const publishXPath = '//*[normalize-space(text())=\'Publish\']/parent::*[not(@disabled)] | //*[normalize-space(text())=\'Save\']/parent::*[not(@disabled)]'
await page.waitForXPath(publishXPath)
// save youtube upload link
await page.waitForSelector('[href^="https://youtu.be"]')
const uploadedLinkHandle = await page.$('[href^="https://youtu.be"]')
const uploadedLink = await page.evaluate(e => e.getAttribute('href'), uploadedLinkHandle)

let uploadedLink
do {
uploadedLink = await page.evaluate(e => e.getAttribute('href'), uploadedLinkHandle)
} while (uploadedLink === 'https://youtu.be/')

let publish;
for(let i=0;i<10;i++){
try {
Expand Down