예제 #1
0
class youtube:
    def __init__(self):
        self.yt_key = botCommon.yt_api_key
        self.yt = YouTubeDataAPI(self.yt_key)

    async def search_yt(self, search_term):
        return self.yt.search(q=search_term, max_results=1)
예제 #2
0
async def ffindyoutube(string):
    yt = YouTubeDataAPI(next(MusicBot.YOUTUBE_API))
    searches = yt.search(q=string, max_results=1)
    video_id = []
    for id_ in searches:
        video_id.append(id_["video_id"])
    return video_id
예제 #3
0
def get_channels_videos(channel_id, max_results, order_by, api_key):
    yt = YouTubeDataAPI(api_key)
    videos = yt.search(channel_id=channel_id,
                       max_results=max_results,
                       order_by=order_by,
                       api_key=api_key)
    return [video["video_id"] for video in videos]
예제 #4
0
def look_new_video():
    driver = webdriver.Firefox(executable_path='Webdriver location')
    api_key = 'Get your API key from google'
    channel_id = 'Youtuber channel id'
    base_video_url = 'https://www.youtube.com/watch?v='
    yt = YouTubeDataAPI(api_key)
    youtuber = yt.search(channel_id=channel_id,
                         max_results=30,
                         order_by=('date'))
    videos_title, videos_id = [], []
    for i in youtuber:
        videos_title.append(i['video_title'])
        videos_id.append(i['video_id'])

    videos_id_check = videos_id[0]

    video_details = pd.DataFrame({
        'video_title': videos_title,
        'video_id': videos_id
    })
    video_details.to_csv('video.csv')
    with open('video.csv', 'r') as r_file:
        data = csv.reader(r_file)
        for i in data:
            if i[-1] == videos_id_check:
                driver.get(base_video_url + videos_id_check)
예제 #5
0
def main():
    from youtube_api import YouTubeDataAPI

    api_key = "AIzaSyAB5Dg1HeqzlV6y2d37-tektKrts2bNOSc"
    yt = YouTubeDataAPI(api_key)

    zout = yt.get_video_metadata(video_id='k7DGeWlKu0Q')
    Num_likes = zout['video_like_count']
    Num_dislikes = zout['video_dislike_count']
    Num_comments = zout['video_comment_count']
    zcomment = yt.get_video_comments(video_id='k7DGeWlKu0Q')
    Commentlist = []
    for item in zcomment:
        Commentlist.append(item['text'])
    zcaption = yt.get_captions(video_id='k7DGeWlKu0Q')
    Transcript = zcaption['caption']
    Result1 = {
        'Num_likes': Num_likes,
        'Num_dislikes': Num_dislikes,
        'Num_comments': Num_comments,
        'Transcript': Transcript,
        'Commentlist': Commentlist
    }
    Result2 = yt.search(q='vaccine',
                        published_after=datetime.datetime(2018, 1, 1),
                        published_before=datetime.datetime(2019, 1, 1))
    return Result1, Result2
예제 #6
0
 def search(self, query):
     yt = YouTubeDataAPI(self.API_KEY)
     results = yt.search(q=query, max_results=10)
     if results:
         return [self._transform_video(v) for v in results]
     else:
         return None
예제 #7
0
 def fetch(self,
           keywords,
           published_after=None,
           published_before=None,
           max_results=5,
           order_by='date'):
     yt = YouTubeDataAPI(self.credentials.api_key)
     if published_after:
         _published_after = published_after.date()
     else:
         _published_after = datetime.datetime.timestamp(
             datetime.datetime(2000, 1, 1))
     if published_before:
         _published_before = published_before.date()
     else:
         _published_before = datetime.datetime.timestamp(
             datetime.datetime(3000, 1, 1))
     response = yt.search(
         keywords,
         max_results=max_results,
         order_by=order_by,
         published_after=_published_after,
         published_before=_published_before,
     )
     print(response)
     return response
예제 #8
0
def get_data():
    api_key = 'XXXXXXX'

    yt = YouTubeDataAPI(api_key)
    data_json = yt.search('django')

    for every_val in data_json:
        if YoutubeVideo.objects.filter(
                video_id=every_val['video_id']).exists():
            print("Video Already exists in db")
            continue
        else:
            datetime_time = datetime.datetime.fromtimestamp(
                every_val['video_publish_date'])
            video_entry = YoutubeVideo(
                video_id=every_val['video_id'],
                video_title=every_val['video_title'],
                video_description=every_val['video_description'],
                channel_title=every_val['channel_title'],
                video_thumbnail=every_val['video_thumbnail'],
                video_publish_date=datetime_time)
            video_entry.save()
            print("Video Added to db")

    return data_json
예제 #9
0
 def callback(ch, method, properties, body):
     api_key = 'AKAIXXXXXXXX'
     yt = YouTubeDataAPI(api_key)
     search = yt.search(body)
     print("[X] Received")
     print("Los resultados de busqueda para " + str(body) +
           " en Youtube son:")
     print(search)
예제 #10
0
 def get_video(self, video_id):
     #conn = sqlite3.connect("{}/youtube.db".format(self.path))
     yt = YouTubeDataAPI(self.API_KEY)
     results = yt.search(q=video_id, max_results=1)
     if results:
         return self._transform_video(results[0])
     else:
         return None
예제 #11
0
async def ffindyoutube(title):
    id_ = []

    yt = YouTubeDataAPI(next(MusicBot.YOUTUBE_API))

    video_id = yt.search(q=title, max_results=1, parser=None)
    for i in video_id:
        id_.append(i["id"]["videoId"])
    return id_
예제 #12
0
class Rostollador:
    def __init__(self,
                 admin_user,
                 telegram_token,
                 handlers):
        self.admin_user = admin_user
        self.telegram_token = telegram_token
        self.admin_filter = Filters.chat(username=self.admin_user)
        self.updater = Updater(token=telegram_token, use_context=True)
        self.dispatcher = self.updater.dispatcher
        self.messages_sent = 0
        self.handlers = handlers

        self.nyofla_channel = os.getenv('NYOFLA_YT_CHANNEL')
        self.channel_rostollador_i_jo = os.getenv('ROSTOLLADOR_I_JO_CHANNEL')
        self.channel_rostolladors_hab = os.getenv('ROSTOLLADORS_CHANNEL')
        self.youtube_api_key = os.getenv('YOUTUBE_API_KEY')

        self.yt = YouTubeDataAPI(self.youtube_api_key)
        self.last_checked = datetime.fromtimestamp(0)

    def latest_nyofla_youtube(self, unused):
        global messages_sent
        # global last_checked

        kvaas_client = Kvaas()
        last_checked = datetime(1970, 1, 1, 0, 0, 0)  # init in the past
        fmt = '%c'

        try:
            stored_date = kvaas_client.getValue('lc')
        except:
            stored_date = last_checked
            logging.warning("Couldn''t retrieve stored date")

        try:
            last_checked = last_checked.strptime(stored_date, fmt)
        except Exception:
            logging.warning(Exception)

        ylist = self.yt.search(channel_id=self.nyofla_channel, search_type="video", max_results=1, order_by="date")
        if len(ylist) > 0:
            ylatest = ylist[0]
            if ylatest['video_publish_date'] > last_checked:
                kvaas_client.setValue('lc', ylatest['video_publish_date'].strftime(fmt))
                self.updater.bot.send_message(chat_id=self.channel_rostolladors_hab,
                                         text='Nou video de {}\n https://www.youtube.com/watch?v={}'.format(
                                             ylatest['channel_title'], ylatest['video_id']),
                                         parse_mode=ParseMode.HTML)

    def start(self):
        for handler in self.handlers:
            self.dispatcher.add_handler(handler.get_handler())
        self.dispatcher.job_queue.run_repeating(self.latest_nyofla_youtube, 2700, 0, 'NyoflaYT')
        self.updater.start_polling()
예제 #13
0
async def findyoutube(title):
    id_ = []
    titel_ = []

    yt = YouTubeDataAPI(next(MusicBot.YOUTUBE_API))

    video_id = yt.search(q=title, max_results=10, parser=None)
    for i in video_id:
        id_.append(await _id(i))
    for i in video_id:
        titel_.append(await titel_func(i))

    return titel_, id_
예제 #14
0
def getURL(searchQuery: str, searchResults: int = 1) -> str:
    api_key = json.load(open("../data/api.json"))["apiKey"]
    yt = YouTubeDataAPI(api_key)

    searches = yt.search(q=searchQuery,
                         max_results=searchResults,
                         video_duration="short")
    rNum = random.randint(0, searchResults - 1)
    # returns [url to video, video title, url to thumbnail]
    return [
        "https://www.youtube.com/watch?v=" + searches[rNum]["video_id"],
        searches[rNum]["video_title"], searches[rNum]["video_thumbnail"]
    ]
예제 #15
0
 async def youtube(self, ctx, *, arg):
     """
     Searches Youtube for the given search, and returns the first video given.
     """
     await jsondb.load_servers(self)
     if jsondb.permission(self, ctx) is False:
         return await ctx.send(jsondb.NOPERMISSION, delete_after=10)
     yt = YouTubeDataAPI(google_key)
     lmao = yt.search(arg)
     print(lmao[0])
     pog = lmao[0]
     link = 'https://www.youtube.com/watch?v=' + pog['video_id']
     await ctx.send(link)
예제 #16
0
class Searcher:
    def __init__(self, api_key):
        self.yt = YouTubeDataAPI(api_key)

    def query(self, query):
        results = self.yt.search(query,
                                 topic_id="/m/04rlf",
                                 video_duration="short",
                                 safe_search="strict")
        output = []
        for result in results:
            output.append({
                "title": result["video_title"],
                "artist": result["channel_title"],
                "thumbnail": result["video_thumbnail"],
                "id": result["video_id"]
            })
        return output
예제 #17
0
def youtube_data_collector(url):
    api_key = ' '
    yt = YouTubeDataAPI(api_key)

    searches = yt.search(q=url, max_results=2)

    data = searches[0]
    print("video_id: ", data['video_id'])
    video_id = data['video_id']
    print("channel title: ", data['channel_title'])
    channel_title = data['channel_title']
    print("channel id : ", data['channel_id'])
    channel_id = data['channel_id']
    print("Publish Date : ", data['video_publish_date'])
    publish_date = data['video_publish_date']
    print("Video Title : ", data['video_title'])
    video_title = data['video_title']
    print("Video Description : ", data['video_description'])
    video_description = data['video_description']
    print("Video Category : ", data['video_category'])
    video_category = data['video_category']
    print("Video Thumbnail : ", data['video_thumbnail'])
    print("Date Collected : ", data['collection_date'])
    collection_date = data['collection_date']


    video = pafy.new('https://www.youtube.com/watch?v={}'.format(video_id))

    print('video url : https://www.youtube.com/watch?v={}'.format(video_id))
    video_url = 'video url : https://www.youtube.com/watch?v={}'.format(video_id)
    print("video rating : ", video.rating)
    video_rating = video.rating
    print("video length : ", video.length)
    video_length = video.length
    print("video likes : ", video.likes)
    video_likes = video.likes
    print("video dislikes : ", video.dislikes)
    video_dislikes = video.dislikes
    print("video views : ", video.viewcount)
    view_count = video.viewcount


    database(channel_title, channel_id, publish_date, video_title, video_description, collection_date, video_url,
             video_rating, video_length, video_likes, video_dislikes)
예제 #18
0
class YTSearch:
    def __init__(self):
        self.api_key = 'api_key'
        self.yt = YouTubeDataAPI(self.api_key)

    def get_videos(
        self, key_words
    ):  # key_word = co wyszukiwac czy spokojne czy jakies do rozruszenia
        videos_ids = []
        for k in key_words:
            if self.yt.verify_key():
                results = self.yt.search(parser=None,
                                         q=k,
                                         max_results=round(200 /
                                                           len(key_words)),
                                         type="videos",
                                         videoEmbeddable="true")
                for result in results:
                    videos_ids.append(result['id']['videoId'])
        np.unique(videos_ids)
        random.shuffle(videos_ids)
        #print("Zaleziono: "+str(len(videos_ids)))
        # print("Id")
        # print(videos_ids)
        return videos_ids

    def update(self, key_word):
        result = []
        low = ["calm music", "sad music"]
        high = ["hard rock music", 'dance music 90s']
        #print("Searching for: "+key_word)
        if key_word == "high":  # puls za wysoki, dla uspokojenia
            videos_ids = self.get_videos(
                low)  # wypluwa id playlist i linki do nich
            result = videos_ids

        elif key_word == "low":  # puls za niski, dla rozruszania
            videos_ids = self.get_videos(
                high)  # wypluwa id playlist i linki do nich
            result = videos_ids

        return result
예제 #19
0
def add_urls_from_yt_search(
        query_string,  # q (list or str) – regex pattern to search using | for or, && for and, and - for not. IE boat|fishing is boat or fishing
        max_results=100,
        destination_func=add_urls_list,
        return_df=False,
        **kwargs):
    yt = YouTubeDataAPI(os.environ.get('YOUTUBE_API_KEY'))
    res = yt.search(query_string, max_results=max_results, **kwargs)
    df = pd.DataFrame(res)
    search_results = list(df.video_id)
    if not kwargs or isinstance(kwargs['source_string'], type(None)):
        source_string = 'yt_search:' + query_string + '_' + name_from_config(
            kwargs)
    else:
        source_string = kwargs['source_string']
    added = destination_func(search_results,
                             verbose=True,
                             source=source_string)
    if return_df:
        return df, added, search_results
    return added, search_results
예제 #20
0
파일: run.py 프로젝트: knowbodynos/fierai
def run_scrape(query: str,
               max_results: int = 100,
               audio: bool = False,
               subtitles: bool = False) -> None:
    assert audio or subtitles, "Must specify audio and/or subtitles to scrape."

    try:
        YOUTUBE_API_KEY = os.getenv("YOUTUBE_API_KEY", None)
        yt = YouTubeDataAPI(YOUTUBE_API_KEY)
    except:
        raise Exception("Please set YOUTUBE_API_KEY environment variable")

    def parser(x):
        url = "https://www.youtube.com/playlist?list="
        return url + x['id']['playlistId']

    results = yt.search(part=['id'],
                        parser=parser,
                        q=query,
                        max_results=max_results,
                        search_type='playlist')
    for url in results:
        run_download(url, audio, subtitles)
예제 #21
0
    def fetch_videos(self,
                     keywords,
                     published_after=None,
                     published_before=None,
                     max_results=5,
                     order_by='date'):
        youtube_search = YouTubeDataAPI(self.credentials.api_key)
        if published_after:
            self.published_after = published_after.date()

        if published_before:
            self.published_before = published_before.date()

        response = youtube_search.search(
            keywords,
            max_results=max_results,
            order_by=order_by,
            published_after=self.published_after,
            published_before=self.published_before,
        )
        logger.info(f"Fetching videos from Youtube : {response}")

        return response
예제 #22
0
#GOOGLE API Key AIzaSyAq4OIWZ19jvTC_2GFC3TdL0A9oCcFNc2Q

import pandas as pd
from youtube_api import YouTubeDataAPI
from vaderSentiment.vaderSentiment import SentimentIntensityAnalyzer

analyser = SentimentIntensityAnalyzer()

api_key = 'AIzaSyBR2kc8R5EzD1rnOjyXZfEL1FOGLKojsg4'
yt = YouTubeDataAPI(api_key)

sonic_search = yt.search(q="Sonic The Headgehog", max_results=5, parser=None)
spy
df_sonic = pd.DataFrame(sonic_search)
df_sonic.head(5)

trailer = df_sonic.iloc[0]
trailer.video_id

comments = yt.get_video_comments(trailer.video_id, max_results=10)
df_comments = pd.DataFrame(comments)

df_graph_data = pd.DataFrame(columns=[
    'comment_id', 'commenter_channel_id', 'channel_country', 'text', 'date',
    'neg', 'neu', 'pos', 'compound'
])

channel_id = df_comments.iloc[0].commenter_channel_id
channel_data = yt.get_channel_metadata(channel_id)

# for index, row in df_comments.iterrows():
            counts[word] = 1

    return counts


#number of videos to search for; returns a dictionary
number_of_results = 100
#api key = value
api_key = "VALUE"
yt = YouTubeDataAPI(api_key)

#search for top 100 videos sorted by relevance between jan 1 2019 and jun 30 2019
searches_2019 = yt.search(q='no equipment workout',
                          max_results=number_of_results,
                          order_by='relevance',
                          published_after=datetime.datetime.timestamp(
                              datetime.datetime(2019, 1, 1)),
                          published_before=datetime.datetime.timestamp(
                              datetime.datetime(2019, 6, 30)))

#converts data into a pandas dataframe
df_searches_2019 = pd.DataFrame(searches_2019)

#print data for videos
pd.options.display.max_rows = 100
df_searches_2019.to_string(index=False)
df_searches_2019.iloc[:, 0].tolist()
df_searches_2019

#gets more information about the videos based on the video's video_id
searches_2019_more_info = []
예제 #24
0
            counts[word] = 1

    return counts


#number of videos to search for; returns a dictionary
number_of_results = 100
#api key = value
api_key = "VALUE"
yt = YouTubeDataAPI(api_key)

#search for top 100 videos sorted by relevance between jan 1 2019 and jun 30 2019
searches_2019 = yt.search(q='home-based exercise',
                          max_results=number_of_results,
                          order_by='relevance',
                          published_after=datetime.datetime.timestamp(
                              datetime.datetime(2019, 1, 1)),
                          published_before=datetime.datetime.timestamp(
                              datetime.datetime(2019, 6, 30)))

#converts data into a pandas dataframe
df_searches_2019 = pd.DataFrame(searches_2019)

#print data for videos
pd.options.display.max_rows = 100
df_searches_2019.to_string(index=False)
df_searches_2019.iloc[:, 0].tolist()
df_searches_2019

#gets more information about the videos based on the video's video_id
searches_2019_more_info = []
예제 #25
0
    DATES_MAY = [datetime.datetime(2020, 5, day, 0, 0) for day in range(1, 32)]
    DATES += DATES_MARCH
    DATES += DATES_APRIL
    DATES += DATES_MAY
    #DATES.append((datetime.datetime(2020, 5, end-1, 23, 59, 59)))
    # DATES.append((datetime.datetime(2020, 5, end, 23, 59, 59)))

    print('searching current term: [{}]'.format(term))
    for i in range(len(DATES) - 1):
        print('searching from {} to {}'.format(DATES[i], DATES[i + 1]))
        try:
            search_result = yt_api.search(
                term,
                max_results=VIDEOS_PER_QUERY,
                order_by='viewCount',
                relevance_language='en',
                published_after=DATES[i],
                published_before=DATES[i + 1],
                type='video',
            )
        except Exception as exc:
            print('>>> cannot do searching for {} as {}'.format(term, exc))
            search_result = []
        vid_list = [
            item['video_id'] for item in search_result
            if item['video_id'] not in VID_SEEN
        ]  # delete repetitive videos
        VID_SEEN = set(list(VID_SEEN) + vid_list)
        print('  vid_list with length [{}] spawn'.format(len(vid_list)))
        _metadata, _sampling_path = get_metadata(vid_list, VID_SEEN)
        # add additional attributes
예제 #26
0
async def search(ctx: commands.Context, *, question: str) -> None:
    if ctx.channel.name not in ban_list:
        yt = YouTubeDataAPI(login_details['youtube_api'])
        await ctx.send(translate_to_url(choice(yt.search(question))))
예제 #27
0
파일: YT_Search.py 프로젝트: Nicrim98/IoT
class YTSearch:
    def __init__(self):
        self.api_key = 'AIzaSyC1GsiEj0D0zcQAyayaaCNa8oXeh9vU2bw'
        self.yt = YouTubeDataAPI(self.api_key)

    def get_playlists(
        self, key_word
    ):  # key_word = co wyszukiwac czy spokojne czy jakies do rozruszenia XD
        playlists_ids = []
        playlists_links = []
        if self.yt.verify_key():
            results = self.yt.search(parser=None,
                                     q=key_word,
                                     max_results=5,
                                     search_type="playlist")
            #print(results)
            for result in results:
                playlists_ids.append(result['id']['playlistId'])
                playlists_links.append(
                    "https://www.youtube.com/playlist?list=" +
                    result['id']['playlistId'])
        return playlists_ids, playlists_links

    def get_videos_from_playlist(self, playlists_ids):
        videos_ids = []
        videos_links = []
        # unikalne wartosci:
        playlists_ids = set(playlists_ids)
        for ids in playlists_ids:
            videos = self.yt.get_videos_from_playlist_id(playlist_id=ids)
            for video in videos:
                videos_links.append("https://www.youtube.com/watch?v=" +
                                    video['video_id'])
                videos_ids.append(video['video_id'])
        return videos_ids, videos_links


#TODO : add counter ??? zeby user mial niepowtarzajace sie dane

    def update(self, key_word):  #odświerzanie danych raz na 24 h
        #zapisz jako plik
        urls = []
        if key_word == "high":  # puls za wysoki, dla uspokojenia
            playlists_ids, playlists_links = self.get_playlists(
                "calm music")  # wypluwa id playlist i linki do nich
            videos_ids, videos_links = self.get_videos_from_playlist(
                playlists_ids)  #linki do muzyki z danej playlisty
            urls = videos_links
            print(videos_links)
            print(videos_ids)
            data = {'YT_data_high': []}
            for ids, link in zip(videos_ids, videos_links):
                data['YT_data_high'].append({
                    'video_id': ids,
                    'video_link': link
                })
            print(len(data['YT_data_high']))
            with open('Data/YT_data_high.txt', 'w') as outfile:
                json.dump(data, outfile)
        elif key_word == "low":  # puls za niski, dla rozruszania
            playlists_ids, playlists_links = self.get_playlists(
                "hard rock")  # wypluwa id playlist i linki do nich
            videos_ids, videos_links = self.get_videos_from_playlist(
                playlists_ids)  # linki do muzyki z danej playlisty
            urls = videos_links
            print(videos_links)
            print(videos_ids)
            data = {'YT_data_low': []}
            for ids, link in zip(videos_ids, videos_links):
                data['YT_data_low'].append({
                    'video_id': ids,
                    'video_link': link
                })
            print(len(data['YT_data_low']))
            with open('Data/YT_data_low.txt', 'w') as outfile:
                json.dump(data, outfile)
        return urls
예제 #28
0
from youtube_api import YouTubeDataAPI

api_key = 'AIzaSyBzxH8kNtZw5-p0otDM4YwAXBl0HaNEpEM'
yt = YouTubeDataAPI(api_key)

searches = yt.search(q='dj arafat', max_results=1, parser=None)
pl = yt.get_videos_from_playlist_id(
    playlist_id='PLCiKBmAOYVNesZUUnBZB22P6CCpO70tDC',
    next_page_token=None,
    part=['snippet'])
print(pl)
예제 #29
0
from youtube_api import YouTubeDataAPI
import os

api_key = os.environ['YOUTUBE_API_SECRET_KEY']
yt = YouTubeDataAPI(api_key)

search_results = yt.search('python tutorial videos')

for search_result in search_results:
    print("----------------------------------")
    print(search_result['video_title'])
    print(search_result['video_description'])
    print("https://www.youtube.com/watch?v=" + search_result['video_id'])
    def download(self):
        """
        Tries to find all songs from the selected Spotify
        playlist on Youtube and downloads them.
        Stores videos in target location as mp4 or converts to mp3.

        Run this method as a DownloadThread.
        """
        thread = threading.current_thread()
        if thread is None or not self.is_valid():
            return

        self.disable_gui()
        self.error_label.configure(text="")
        self.update()

        length = self.playlist['tracks']['total']

        offset = 0  # Spotify API is paginated, so we remember the offset
        tracks = self.get_tracks(offset)

        cancelled = False
        downloaded = 0
        not_found = 0
        self.status_label.configure(text=f"{downloaded}/{length} downloaded...")
        self.update()

        while True:  # Loop over pages of Spotify API
            for track in tracks['items']:
                if thread.stopped():
                    cancelled = True
                    break

                yt = YouTubeDataAPI(os.environ.get('YOUTUBE_API_KEY'))
                artist = track['track']['artists'][0]['name']
                track_name = track['track']['name']
                searches = yt.search(q=f'{artist} {track_name}', max_results=5)
                video = None
                for result in searches:  # Look for first downloadable video in top 5 results
                    video_title = unquote(result['video_title'].lower())  # Decode URL encoding
                    if track_name.lower() not in video_title and not any(map(video_title.__contains__, ['ft', 'feat'])):
                        continue  # Try to filter irrelevant search results

                    video_id = result['video_id']
                    youtube = pytube.YouTube(f'https://www.youtube.com/watch?v={video_id}')
                    video = youtube.streams.first()
                    if video:
                        break

                if video is None:
                    not_found += 1
                    continue

                path = video.download(self.target)
                if self.include_video.get() == 0:
                    self.convert_to_mp3(path)

                downloaded += 1
                self.status_label.configure(text=f"{downloaded}/{length} downloaded...")
                self.update()

            offset += 100  # Increase offset and retrieve next page if it exists
            if offset < length and tracks['next'] and not cancelled:
                tracks = self.get_tracks(offset)
            else:
                break

        if not_found == 0:
            self.status_label.configure(text="All downloads complete!")
        else:
            if cancelled:
                self.status_label.configure(text=f"Cancelled, {downloaded}/{length} downloaded.")
            else:
                self.status_label.configure(text=f"Complete, {downloaded}/{length} downloaded.")
            self.error_label.configure(text=f"{not_found} videos were not available \nfor download.")
        self.enable_gui()