HARPA.AI
LIBRARYUSE CASESGUIDESAI COMMANDSBLOG

๐Ÿ”—ย ย Extracts YouTube Links

Extracts video links from a YouTube channel.

Created by HARPA AI
Updated on Nov 11, 07:21
Installed 283 times
RUNS JS CODE

How to Use

IMPORT COMMAND

Content

- 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
Contact us
HomeUse CasesGuidesPrivacy PolicyTerms of Service
CAN WE STORE COOKIES?
Our website uses cookies for the purposes of accessibility and security. They also allow us to gather statistics in order to improve the website for you. More info: Privacy Policy