1

I am trying to use YouTube API V3 in order to extract the URL of the first video that comes up when you search something on YouTube.

So, I've been reading in the sample codebase and I need the "Search by keyword" and change the value of the maxResults parameter to 1.
Since the code is C#, I've tried to use an online converter, but I got one problem. I created a new class, I insert all this code and installed Google API and YouTube API via NuGet.

Edit: This code has been converted from Console App to WinForm:

Imports System
Imports System.Collections.Generic
Imports System.Threading.Tasks
Imports Google.Apis.Auth.OAuth2
Imports Google.Apis.Services
Imports Google.Apis.Upload
Imports Google.Apis.Util.Store
Imports Google.Apis.YouTube.v3
Imports Google.Apis.YouTube.v3.Data

Namespace YouTube
    ''' <summary>
    ''' YouTube Data API v3 sample: search by keyword.
    ''' Relies on the Google APIs Client Library for .NET, v1.7.0 or higher.
    ''' See https://developers.google.com/api-client-library/dotnet/get_started
    '''
    ''' Set ApiKey to the API key value from the APIs & auth > Registered apps tab of
    '''   https://cloud.google.com/console
    ''' Please ensure that you have enabled the YouTube Data API for your project.
    ''' </summary>
   
         Public Async Function Run(ByVal videos As String) As Task(Of String)
            Dim youtubeService = New YouTubeService(New BaseClientService.Initializer() With {
                .ApiKey = "REPLACE_ME",
                .ApplicationName = [GetType]().ToString()
            })
            Dim searchListRequest = youtubeService.Search.List("snippet")
            searchListRequest.Q = "Google" ' Replace with your search term.
            searchListRequest.MaxResults = 1

            ' Call the search.list method to retrieve results matching the specified query term.
            Dim searchListResponse = Await searchListRequest.ExecuteAsync()

            Return searchListResponse.Items.FirstOrDefault()?.Id.VideoId

        End Function
    End Class
End Namespace

How should I call this namespace from the Main Form in order to replace my search term searchListRequest.Q = "Google" with what I entered in the main Form usinga a Textbox?
I'm trying to call it with:

 Private Async Sub Button9_Click(sender As Object, e As EventArgs) Handles Button9.Click
    MsgBox(Await Run())
End Sub

but the MessageBox shows up empty.
Is there a way to call it already changing searchListRequest.Q?
For example: msgbox(await Run(key word)).

Jimi
  • 29,621
  • 8
  • 43
  • 61

1 Answers1

1

Since you want to call the Search class Run() method (here renamed to GetResultsAsync() to match the standard naming convention), you can:

  • Create a new Class file, add it to your Project (or a Class Library),
  • Make the Async method static (Shared), so you can call it directly (not necessary, but it looks like the search results are better handled this way. You can of course create an instance of the GoogleSearch class instead).
  • Pass the search term(s) to the method, using the content of a TextBox.
    • You can handle the Enter key in the TextBox.KeyDown event
    • Also add a Button that performs the same action, if needed
  • In YouTube.GoogleSearch.GetResultAsync():
    • set .ApplicationName = Application.ProductName. [GetType]().ToString() is a bad translation from C# and won't do much here even if corrected. Or use the name created for the registration directly.
    • Return the first result of searchListRequest.ExecuteAsync() as searchListResponse.Items.FirstOrDefault()?.Id.VideoId: if no results are returned, the method will return a null string (Nothing)
  • Add and overload of GetResultAsync() that accepts a Timeout argument used to cancel the Task after a period of time and a method that allows to cancel the HTTP Request Task

Rename the GoogleSearch class to whatever you prefer :)


Use a Button or a TextBox.KeyDown event to call the GetResultAsync() method and show the results in another TextBox:

Private Async Sub txtSearch_KeyDown(sender As Object, e As KeyEventArgs) Handles txtSearch.KeyDown
    If (e.KeyCode = Keys.Enter) Then
        e.SuppressKeyPress = True
        txtSearch.Enabled = False
        SomeTextBox.Text = Await YouTube.GoogleSearch.GetResultAsync(txtSearch.Text)
        txtSearch.Enabled = True
    End If
End Sub

Private Async Sub btnSearch_Click(sender As Object, e As EventArgs) Handles btnSearch.Click
    btnSearch.Enabled = False
    SomeTextBox.Text = Await YouTube.GoogleSearch.GetResultAsync(txtSearch.Text)
    btnSearch.Enabled = True
End Sub

Private Sub btnCancelSearch_Click(sender As Object, e As EventArgs) Handles btnCancelSearch.Click
    YouTube.GoogleSearch.Cancel()
End Sub

' Call Cancel() when the Form closed 
Private Sub Form1_FormClosed(sender As Object, e As FormClosedEventArgs) Handles MyBase.FormClosed
    YouTube.GoogleSearch.Cancel()
End Sub

The modified class object.

► Note: A CancellationToken should be passed to the ExecuteAsync() method: if the User closes the Form in the meanwhile, this Task needs to be canceled, handling the FormClosing or FormClosed events. Similar to what is shown here:

How to let the code run smoothly using timers and different threads


The GoogleSearch class can be internal (Friend).

Edit:

  • Added an overload that allows to specify a Timeout, in millisenconds, before the Request is canceled
  • Added a static Cancel() method used to cancel the current Request and dispose of the CancellationTokenSource
Imports System.Threading.Tasks
Imports Google.Apis.Auth.OAuth2
Imports Google.Apis.Services
Imports Google.Apis.YouTube.v3
Imports Google.Apis.YouTube.v3.Data

Namespace YouTube
    Public Class GoogleSearch
        Private Shared cts As CancellationTokenSource = Nothing

        Public Shared Async Function GetResultAsync(ByVal searchCriteria As String) As Task(Of String)
            Return Await GetResultAsync(searchCriteria, -1)
        End Function

        Public Shared Async Function GetResultAsync(ByVal searchCriteria As String, timeoutMilliseconds As Integer) As Task(Of String)
            If cts Is Nothing Then cts = New CancellationTokenSource(timeoutMilliseconds)
            Dim youtubeService = New YouTubeService(New BaseClientService.Initializer() With {
                .ApiKey = "REPLACE_ME",
                .ApplicationName = Application.ProductName
            })

            Dim searchListRequest = youtubeService.Search.List("snippet")
            searchListRequest.Q = searchCriteria
            searchListRequest.MaxResults = 1

            Try
                Dim searchListResponse = Await searchListRequest.ExecuteAsync(cts.Token)
                Return searchListResponse.Items.FirstOrDefault()?.Id.VideoId
            Catch exTCE As TaskCanceledException
                ' Do whatever you see fit here
                'MessageBox.Show(exTCE.Message)
                Return Nothing
            Finally
                Cancel(False)
            End Try
        End Function

        Public Shared Sub Cancel()
            Cancel(True)
        End Sub

        Private Shared Sub Cancel(cancelCTS As Boolean)
            If cancelCTS Then cts?.Cancel()
            cts?.Dispose()
            cts = Nothing
        End Sub
    End Class
End Namespace
Jimi
  • 29,621
  • 8
  • 43
  • 61