- steps:
- steps:
- code: |
function extractYouTubeProfileName() {
const url = window.location.href;
const regex = /youtube\.com\/(@[^\/]+)/;
const match = url.match(regex);
return match ? match[1] : null;
}
const profileName = extractYouTubeProfileName();
return profileName;
param: profile
type: js
args: ''
silent: true
- to: EXTRACT VID URLS
condition: |
{{url}} =~ ^https:\/\/www\.youtube\.com\/@[\w\.\-_]+\/videos
type: jump
label: VIDEOS PAGE
type: group
condition: |
{{url}} =~ ^https:\/\/www\.youtube\.com\/@[\w\.\-_]+\/videos
- steps:
- type: js
code: |
function extractYouTubeProfileName() {
const url = window.location.href;
const regex = /youtube\.com\/(@[^\/]+)/;
const match = url.match(regex);
return match ? match[1] : null;
}
const profileName = extractYouTubeProfileName();
return profileName;
args: ''
param: profile
silent: true
- url: 'https://www.youtube.com/{{profile}}/videos '
type: navigate
waitForIdle: false
silent: true
- text: Popular
timeout: 1500
type: wait
for: text-to-appear
silent: true
- type: jump
to: EXTRACT VID URLS
label: REDIRECT TO VIDEOS PAGE
condition: >
{{url}} =~
^https:\/\/www\.youtube\.com\/@[\w\.\-_]+(\/featured|\/playlists|\/community|\/)?$
type: group
- steps:
- code: |+
function extractUserHandle() {
const userLinkElement = document.querySelector('a.yt-simple-endpoint.style-scope.ytd-video-owner-renderer');
if (userLinkElement) {
const href = userLinkElement.getAttribute('href');
return href.substring(1);
}
return 'NOT FOUND';
}
const userHandle = extractUserHandle();
return userHandle;
type: js
args: ''
param: profile
silent: true
- message: >-
๐งญ It seems to be a video page. I'm navigating to the author's
profile - {{profile}}.
type: say
- url: https://www.youtube.com/{{profile}}/videos
type: navigate
waitForIdle: false
silent: true
- type: wait
for: text-to-appear
text: Popular
timeout: 1500
silent: true
- type: jump
to: EXTRACT VID URLS
label: VIDEO PAGE
condition: '{{url}} =~ ^https:\/\/www\.youtube\.com\/watch.*'
type: group
- steps:
- message: >-
๐ต๏ธโ๏ธ Please provide a link to a YouTube video, a YouTube profile,
or a channel's video page.
type: ask
param: url
options: null
default: ''
- type: navigate
url: '{{url}}'
waitForIdle: false
silent: true
- type: control
action: show
- type: wait
for: idle
timeout: 15000
- to: CHECK URL
type: jump
label: NEED YT URL
type: group
- type: control
action: show
type: group
label: CHECK URL
- steps:
- code: |
return Array
.from(document.querySelectorAll('a[href*="/watch"]'))
.map(a => {
const ariaLabel = a.getAttribute('aria-label') || '';
const viewsMatch = ariaLabel.match(/(\d[\d,]*) views/);
const timeAgoMatch = ariaLabel.match(/views (.+) ago/);
const url = a.href.startsWith('http') ? a.href : 'https://www.youtube.com' + a.getAttribute('href');
return {
url: url,
title: a.getAttribute('title') || a.innerText.trim(),
views: viewsMatch ? parseInt(viewsMatch[1].replace(/,/g, '')) : null,
publishedTimeAgo: timeAgoMatch ? timeAgoMatch[1].trim() : null
};
})
.filter(item =>
item.url.includes('/watch?v=') &&
item.views !== null &&
item.publishedTimeAgo !== null);
label: FIND ITEMS
type: js
args: ''
param: videos
silent: true
- code: |
function sortVideosByDate(videos) {
const timeAgoToDays = timeAgo => {
const matches = timeAgo.match(/(\d+)\s*(\w+)/);
if (!matches) return Infinity;
const num = parseInt(matches[1]);
const unit = matches[2];
if (unit.startsWith('day')) {
return num;
} else if (unit.startsWith('week')) {
return num * 7;
} else if (unit.startsWith('month')) {
return num * 30;
} else if (unit.startsWith('year')) {
return num * 365;
} else if (unit.startsWith('hour')) {
return num / 24;
} else if (unit.startsWith('minute')) {
return num / 1440;
} else {
return Infinity;
}
};
return videos.sort((a, b) => timeAgoToDays(a.publishedTimeAgo) - timeAgoToDays(b.publishedTimeAgo));
}
const videos = args.videos;
const sortedVideos = sortVideosByDate(videos);
return sortedVideos;
label: SORT ITEMS
type: js
args: videos
param: videos
silent: true
- code: |-
const videos = args.videos;
if (videos.length === 0)
return 'Found no videos on this page.'
let markdownText = `## Found ${videos.length} videos on this page:\n`;
videos.forEach((video, index) => {
const title = video.title.replace(/"/g, '\\"');
markdownText += `${index + 1}. [${title}](${video.url}), ${video.views.toLocaleString()} views, ${video.publishedTimeAgo} ago\n`;
});
return markdownText;
label: MESSAGE
type: js
args: videos
param: markdownText
silent: true
- condition: '{{videos.length}} = 0'
type: stop
type: group
label: EXTRACT VID URLS
- type: say
message: '{{markdownText}}'
- param: ask-action
options:
- label: โ
DONE
value: done
- label: ๐ฆ EXPORT LIST
value: export
type: ask
message: ''
default: ''
optionsInvalid: false
- condition: '{{ask-action}} = done'
type: stop
- condition: '{{ask-action}} = export'
type: export
what: param
param: videos
All rights reserved ยฉ HARPA AI TECHNOLOGIES LLC, 2021 โ 2024
Designed and engineered in Finland ๐ซ๐ฎ