[SOURCE-CODE] Obtener releases de GitHub y comprobar actualizaciones...

Iniciado por Eleкtro, 6 Mayo 2018, 02:43 AM

0 Miembros y 1 Visitante están viendo este tema.

Eleкtro

Estuve observando este código aleatorio en GitHub: https://github.com/HearthSim/HDT-Voice/blob/master/HDT-Voice/HDTPlugin/Github.vb y a raíz de eso se me ocurrió la idea de implementar un sistema reutilizable y sofisticado (o al menos yo creo que lo es) para obtener las releases de GitHub, con lo que poder determinar si existe una nueva release y por ende nuestro programa debe actualizarse...

Para comenzar la implementación de dicho sistema declaré las siguientes clases: GitHubRelease, GitHubAsset y GitHubAuthor las cuales servirán para representar información de una release, un asset y un author/uploader. Y por último declaré una clase con nombre GitHubUtil en donde declaré varias funciones sincrónicas y asincrónicas para implementar las siguientes funcionalidades: obtener todas las releases de un repositorio, obtener la última release, obtener una release con versión específica, y comprobar si existe una versión más reciente (para actualizar nuestro programa).

Estoy seguro que les servirá para sus aplicaciones de código abierto y le podrán sacar varias utilidades con diferentes fines que se ajusten a sus necesidades...

Aquí lo tienen todo:

Código (vbnet) [Seleccionar]
Imports System
Imports System.Collections.Generic
Imports System.Collections.ObjectModel
Imports System.Collections.Specialized
Imports System.ComponentModel
Imports System.IO
Imports System.Net
Imports System.Net.Mime
Imports System.Runtime.Serialization.Json
Imports System.Text
Imports System.Threading
Imports System.Threading.Tasks
Imports System.Web
Imports System.Xml


GitHubRelease.vb
Código (vbnet) [Seleccionar]
''' <summary>
''' Represents a release on GitHub.
''' </summary>
''' <seealso href="https://github.com"/>
Public NotInheritable Class GitHubRelease

   ''' <summary>
   ''' Gets the GitHub's unique identifier for this release.
   ''' </summary>
   Public ReadOnly Property Id As String

   ''' <summary>
   ''' Gets the release name.
   ''' </summary>
   Public ReadOnly Property Name As String

   ''' <summary>
   ''' Gets the release tag name.
   ''' </summary>
   Public ReadOnly Property TagName As String

   ''' ----------------------------------------------------------------------------------------------------
   ''' <summary>
   ''' Gets the release version.
   ''' </summary>
   ''' ----------------------------------------------------------------------------------------------------
   ''' <remarks>
   ''' The version is derived from <see cref="GitHubRelease.TagName"/>, which should follow semantic versioning guidelines.
   ''' <para></para>
   ''' See for more info about semantic versioning:
   ''' <para></para>
   ''' <see href="https://semver.org/"/>
   ''' <para></para>
   ''' <see href="https://help.github.com/articles/about-releases/"/>
   ''' <para></para>
   ''' <see href="https://git-scm.com/book/en/v2/Git-Basics-Tagging"/>
   ''' </remarks>
   ''' ----------------------------------------------------------------------------------------------------
   Public ReadOnly Property Version As Version
       Get
           ' Remove prefixes and suffixes from tagname, like: "v1.0", "1.0-alpha" or "1.0-beta".
           Dim str As String = Me.TagName.ToLower().
                                          Trim("abcdefghijklmnopqrstuvwxyz !·$%&/()=?\|@#~'^*¨;:,.{}[]+".ToArray())

           Dim result As Version = Nothing
           Version.TryParse(str, result)
           Return result
       End Get
   End Property

   ''' <summary>
   ''' Gets the body, in MarkDown format.
   ''' </summary>
   Public ReadOnly Property Body As String

   ''' <summary>
   ''' Gets the commition target.
   ''' </summary>
   Public ReadOnly Property TargetCommitish As String

   ''' <summary>
   ''' Gets an <see cref="Uri"/> that points to the release page.
   ''' </summary>
   Public ReadOnly Property UriRelease As Uri

   ''' <summary>
   ''' Gets an <see cref="Uri"/> that points to the assets page of this release.
   ''' </summary>
   Public ReadOnly Property UriAssets As Uri

   ''' <summary>
   ''' Gets an <see cref="Uri"/> that points to the tarball of this release.
   ''' </summary>
   Public ReadOnly Property UriTarball As Uri

   ''' <summary>
   ''' Gets an <see cref="Uri"/> that points to the zipball of this release.
   ''' </summary>
   Public ReadOnly Property UriZipball As Uri

   ''' <summary>
   ''' Gets an <see cref="Uri"/> that points to the release page for a web-browser.
   ''' </summary>
   Public ReadOnly Property UriHtml As Uri

   ''' <summary>
   ''' Gets a value that determine whether this release is a draft.
   ''' </summary>
   Public ReadOnly Property IsDraft As Boolean

   ''' <summary>
   ''' Gets a value that determine whether this release is a pre-release.
   ''' </summary>
   Public ReadOnly Property IsPreRelease As Boolean

   ''' <summary>
   ''' Gets the creation datetime.
   ''' </summary>
   Public ReadOnly Property DateCreated As Date

   ''' <summary>
   ''' Gets the published datetime.
   ''' </summary>
   Public ReadOnly Property DatePublished As Date

   ''' <summary>
   ''' Gets the author of this release.
   ''' </summary>
   Public ReadOnly Property Author As GitHubAuthor

   ''' <summary>
   ''' Gets the assets of this release.
   ''' </summary>
   Public ReadOnly Property Assets As ReadOnlyCollection(Of GitHubAsset)

   ''' <summary>
   ''' Prevents a default instance of the <see cref="GitHubRelease"/> class from being created.
   ''' </summary>
   Private Sub New()
   End Sub

   ''' <summary>
   ''' Initializes a new instance of the <see cref="GitHubRelease"/> class.
   ''' </summary>
   ''' <param name="xml">
   ''' An <see cref="XElement"/> that contains the fields to parse.
   ''' <para></para>
   ''' See: <see href="https://api.github.com/repos/{user}/{repo}/releases"/>
   ''' </param>
   Public Sub New(ByVal xml As XElement)
       Me.Id = xml.<id>.Value
       Me.Name = xml.<name>.Value
       Me.TagName = xml.<tag_name>.Value
       Me.Body = xml.<body>.Value
       Me.TargetCommitish = xml.<target_commitish>.Value
       Me.UriRelease = New Uri(xml.<url>.Value, UriKind.Absolute)
       Me.UriAssets = New Uri(xml.<assets_url>.Value, UriKind.Absolute)
       Me.UriHtml = New Uri(xml.<html_url>.Value, UriKind.Absolute)
       Me.UriTarball = New Uri(xml.<tarball_url>.Value, UriKind.Absolute)
       Me.UriZipball = New Uri(xml.<zipball_url>.Value, UriKind.Absolute)
       Me.IsDraft = xml.<draft>.Value
       Me.IsPreRelease = xml.<prerelease>.Value
       Me.DateCreated = Date.Parse(xml.<created_at>.Value, CultureInfo.GetCultureInfo("en-US").DateTimeFormat)
       Me.DatePublished = Date.Parse(xml.<published_at>.Value, CultureInfo.GetCultureInfo("en-US").DateTimeFormat)
       Me.Author = New GitHubAuthor(xml.<author>.SingleOrDefault())

       Dim assets As New Collection(Of GitHubAsset)
       Dim elements As IEnumerable(Of XElement) = xml.<assets>.<item>
       For Each element As XElement In elements
           Dim asset As New GitHubAsset(element)
           assets.Add(asset)
       Next
       Me.Assets = New ReadOnlyCollection(Of GitHubAsset)(assets)
   End Sub

   ''' <summary>
   ''' Returns a <see cref="String"/> that represents this release.
   ''' </summary>
   ''' <returns>
   ''' A <see cref="String"/> that represents this release.
   ''' </returns>
   Public Overrides Function ToString() As String
       Dim kvPairs As New NameValueCollection(EqualityComparer(Of String).Default) From {
           {NameOf(Me.Id), Me.Id},
           {NameOf(Me.TagName), Me.TagName},
           {NameOf(Me.Name), Me.Name},
           {NameOf(Me.TargetCommitish), Me.TargetCommitish},
           {NameOf(Me.IsDraft), Me.IsDraft},
           {NameOf(Me.IsPreRelease), Me.IsPreRelease},
           {NameOf(Me.DateCreated), Me.DateCreated.ToString("MM/dd/yyyy HH:mm:ss")},
           {NameOf(Me.DatePublished), Me.DatePublished.ToString("MM/dd/yyyy HH:mm:ss")},
           {NameOf(Me.UriHtml), Me.UriHtml.AbsoluteUri}
       }

       Return String.Format("{{{0}}}", String.Join(", ", (From key In kvPairs.AllKeys, value In kvPairs.GetValues(key)
                                                          Select String.Format("{0}={1}", key, value))))
   End Function

   ''' <summary>
   ''' Implements the operator &lt;&gt;.
   ''' </summary>
   ''' <param name="release1">
   ''' The first <see cref="GitHubRelease"/>.
   ''' </param>
   ''' <param name="release2">
   ''' The second <see cref="GitHubRelease"/>.
   ''' </param>
   ''' <returns>
   ''' The result of the operator.
   ''' </returns>
   Public Shared Operator <>(ByVal release1 As GitHubRelease, ByVal release2 As GitHubRelease) As Boolean

       Return (release1.Id <> release2.Id)

   End Operator

   ''' <summary>
   ''' Implements the operator =.
   ''' </summary>
   ''' <param name="release1">
   ''' The first <see cref="GitHubRelease"/>.
   ''' </param>
   ''' <param name="release2">
   ''' The second <see cref="GitHubRelease"/>.
   ''' </param>
   ''' <returns>
   ''' The result of the operator.
   ''' </returns>
   Public Shared Operator =(ByVal release1 As GitHubRelease, ByVal release2 As GitHubRelease) As Boolean

       Return (release1.Id = release2.Id)

   End Operator

End Class


GitHubAsset.vb
Código (vbnet) [Seleccionar]
''' <summary>
''' Represents an asset of a release on GitHub.
''' </summary>
''' <seealso href="https://github.com"/>
Public NotInheritable Class GitHubAsset

   ''' <summary>
   ''' Gets the GitHub's unique identifier for this asset.
   ''' </summary>
   Public ReadOnly Property Id As String

   ''' <summary>
   ''' Gets the name of this asset.
   ''' </summary>
   Public ReadOnly Property Name As String

   ''' <summary>
   ''' Gets the label of this asset.
   ''' </summary>
   Public ReadOnly Property Label As String

   ''' <summary>
   ''' Gets the state of this asset.
   ''' </summary>
   Public ReadOnly Property State As String

   ''' <summary>
   ''' Gets the size of this asset, in bytes.
   ''' </summary>
   Public ReadOnly Property Size As Long

   ''' <summary>
   ''' Gets a value indicating how many times this asset was downloaded.
   ''' </summary>
   Public ReadOnly Property DownloadCount As Integer

   ''' <summary>
   ''' Gets the content-type of this asset.
   ''' </summary>
   Public ReadOnly Property ContentType As ContentType

   ''' <summary>
   ''' Gets an <see cref="Uri"/> that points to the page of this asset.
   ''' </summary>
   Public ReadOnly Property UriAsset As Uri

   ''' <summary>
   ''' Gets an <see cref="Uri"/> that points to the download page of this asset.
   ''' </summary>
   Public ReadOnly Property UriDownload As Uri

   ''' <summary>
   ''' Gets the creation datetime.
   ''' </summary>
   Public ReadOnly Property DateCreated As Date

   ''' <summary>
   ''' Gets the uploaded datetime.
   ''' </summary>
   Public ReadOnly Property DateUploaded As Date

   ''' <summary>
   ''' Gets the uploader of this asset.
   ''' </summary>
   Public ReadOnly Property Uploader As GitHubAuthor

   ''' <summary>
   ''' Prevents a default instance of the <see cref="GitHubAsset"/> class from being created.
   ''' </summary>
   Private Sub New()
   End Sub

   ''' <summary>
   ''' Initializes a new instance of the <see cref="GitHubAsset"/> class.
   ''' </summary>
   ''' <param name="xml">
   ''' An <see cref="XElement"/> that contains the fields to parse.
   ''' <para></para>
   ''' See: <see href="https://api.github.com/repos/{user}/{repo}/releases"/>
   ''' </param>
   Public Sub New(ByVal xml As XElement)
       Me.Id = xml.<id>.Value
       Me.Name = xml.<name>.Value
       Me.Label = xml.<label>.Value
       Me.State = xml.<state>.Value
       Me.Size = xml.<size>.Value
       Me.ContentType = New ContentType(xml.<content_type>.Value)
       Me.DownloadCount = xml.<download_count>.Value
       Me.DateCreated = Date.Parse(xml.<created_at>.Value, CultureInfo.GetCultureInfo("en-US").DateTimeFormat)
       Me.DateUploaded = Date.Parse(xml.<updated_at>.Value, CultureInfo.GetCultureInfo("en-US").DateTimeFormat)
       Me.UriAsset = New Uri(xml.<url>.Value, UriKind.Absolute)
       Me.UriDownload = New Uri(xml.<browser_download_url>.Value, UriKind.Absolute)
       Me.Uploader = New GitHubAuthor(xml.<uploader>.Single())
   End Sub

   ''' <summary>
   ''' Returns a <see cref="String"/> that represents this asset.
   ''' </summary>
   ''' <returns>
   ''' A <see cref="String"/> that represents this asset.
   ''' </returns>
   Public Overrides Function ToString() As String
       Dim kvPairs As New NameValueCollection(EqualityComparer(Of String).Default) From {
           {NameOf(Me.Id), Me.Id},
           {NameOf(Me.Name), Me.Name},
           {NameOf(Me.Label), Me.Label},
           {NameOf(Me.State), Me.State},
           {NameOf(Me.Size), Me.Size},
           {NameOf(Me.ContentType), Me.ContentType.ToString()},
           {NameOf(Me.DownloadCount), Me.DownloadCount},
           {NameOf(Me.DateCreated), Me.DateCreated.ToString("MM/dd/yyyy HH:mm:ss")},
           {NameOf(Me.DateUploaded), Me.DateUploaded.ToString("MM/dd/yyyy HH:mm:ss")},
           {NameOf(Me.UriDownload), Me.UriDownload.AbsoluteUri}
       }

       Return String.Format("{{{0}}}", String.Join(", ", (From key In kvPairs.AllKeys, value In kvPairs.GetValues(key)
                                                          Select String.Format("{0}={1}", key, value))))
   End Function

   ''' <summary>
   ''' Implements the operator &lt;&gt;.
   ''' </summary>
   ''' <param name="asset1">
   ''' The first <see cref="GitHubAsset"/>.
   ''' </param>
   ''' <param name="asset2">
   ''' The second <see cref="GitHubAsset"/>.
   ''' </param>
   ''' <returns>
   ''' The result of the operator.
   ''' </returns>
   Public Shared Operator <>(ByVal asset1 As GitHubAsset, ByVal asset2 As GitHubAsset) As Boolean

       Return (asset1.Id <> asset2.Id)

   End Operator

   ''' <summary>
   ''' Implements the operator =.
   ''' </summary>
   ''' <param name="asset1">
   ''' The first <see cref="GitHubAsset"/>.
   ''' </param>
   ''' <param name="asset2">
   ''' The second <see cref="GitHubAsset"/>.
   ''' </param>
   ''' <returns>
   ''' The result of the operator.
   ''' </returns>
   Public Shared Operator =(ByVal asset1 As GitHubAsset, ByVal asset2 As GitHubAsset) As Boolean

       Return (asset1.Id = asset2.Id)

   End Operator

End Class


GitHubAuthor.vb
Código (vbnet) [Seleccionar]
''' <summary>
''' Represents the author of a release or the uploader of an asset on GitHub.
''' </summary>
''' <seealso href="https://github.com"/>
Public NotInheritable Class GitHubAuthor

   ''' <summary>
   ''' Gets the GitHub's unique identifier for this author.
   ''' </summary>
   Public ReadOnly Property Id As String

   ''' <summary>
   ''' Gets the author name.
   ''' </summary>
   Public ReadOnly Property Name As String

   ''' <summary>
   ''' Gets the type of user.
   ''' </summary>
   Public ReadOnly Property [Type] As String

   ''' <summary>
   ''' Gets a value that determine whether this author is a site administrator.
   ''' </summary>
   Public ReadOnly Property IsSiteAdministrator As Boolean

   ''' <summary>
   ''' Gets the unique identifier of the Gravatar.
   ''' <para></para>
   ''' See for more info: <see href="https://gravatar.com/"/>
   ''' </summary>
   Public ReadOnly Property GravatarId As String

   ''' <summary>
   ''' Gets an <see cref="Uri"/> that points to the author page.
   ''' </summary>
   Public ReadOnly Property UriAuthor As Uri

   ''' <summary>
   ''' Gets an <see cref="Uri"/> that points to the avatar page of this author.
   ''' </summary>
   Public ReadOnly Property UriAvatar As Uri

   ''' <summary>
   ''' Gets an <see cref="Uri"/> that points to the followers page of this author.
   ''' </summary>
   Public ReadOnly Property UriFollowers As Uri

   ''' <summary>
   ''' Gets an <see cref="Uri"/> that points to the subscriptions page of this author.
   ''' </summary>
   Public ReadOnly Property UriSubscriptions As Uri

   ''' <summary>
   ''' Gets an <see cref="Uri"/> that points to the organizations page of this author.
   ''' </summary>
   Public ReadOnly Property UriOrganizations As Uri

   ''' <summary>
   ''' Gets an <see cref="Uri"/> that points to the repositories page of this author.
   ''' </summary>
   Public ReadOnly Property UriRepositories As Uri

   ''' <summary>
   ''' Gets an <see cref="Uri"/> that points to the received events page of this author.
   ''' </summary>
   Public ReadOnly Property UriReceivedEvents As Uri

   ''' <summary>
   ''' Gets an <see cref="Uri"/> that points to the author page for a web-browser.
   ''' </summary>
   Public ReadOnly Property UriHtml As Uri

   ''' <summary>
   ''' Prevents a default instance of the <see cref="GitHubAuthor"/> class from being created.
   ''' </summary>
   Private Sub New()
   End Sub

   ''' <summary>
   ''' Initializes a new instance of the <see cref="GitHubAuthor"/> class.
   ''' </summary>
   ''' <param name="xml">
   ''' An <see cref="XElement"/> that contains the fields to parse.
   ''' <para></para>
   ''' See: <see href="https://api.github.com/repos/{user}/{repo}/releases"/>
   ''' </param>
   Public Sub New(ByVal xml As XElement)
       Me.Id = xml.<id>.Value
       Me.Name = xml.<login>.Value
       Me.Type = xml.<type>.Value
       Me.IsSiteAdministrator = xml.<site_admin>.Value
       Me.GravatarId = xml.<gravatar_id>.Value
       Me.UriAuthor = New Uri(xml.<url>.Value, UriKind.Absolute)
       Me.UriAvatar = New Uri(xml.<avatar_url>.Value, UriKind.Absolute)
       Me.UriSubscriptions = New Uri(xml.<subscriptions_url>.Value, UriKind.Absolute)
       Me.UriOrganizations = New Uri(xml.<organizations_url>.Value, UriKind.Absolute)
       Me.UriRepositories = New Uri(xml.<repos_url>.Value, UriKind.Absolute)
       Me.UriReceivedEvents = New Uri(xml.<received_events_url>.Value, UriKind.Absolute)
       Me.UriHtml = New Uri(xml.<html_url>.Value, UriKind.Absolute)
   End Sub

   ''' <summary>
   ''' Returns a <see cref="String"/> that represents this author.
   ''' </summary>
   ''' <returns>
   ''' A <see cref="String"/> that represents this author.
   ''' </returns>
   Public Overrides Function ToString() As String
       Dim kvPairs As New NameValueCollection(EqualityComparer(Of String).Default) From {
           {NameOf(Me.Id), Me.Id},
           {NameOf(Me.Name), Me.Name},
           {NameOf(Me.Type), Me.Type},
           {NameOf(Me.IsSiteAdministrator), Me.IsSiteAdministrator},
           {NameOf(Me.UriHtml), Me.UriHtml.AbsoluteUri}
       }

       Return String.Format("{{{0}}}", String.Join(", ", (From key In kvPairs.AllKeys, value In kvPairs.GetValues(key)
                                                          Select String.Format("{0}={1}", key, value))))
   End Function

   ''' <summary>
   ''' Implements the operator &lt;&gt;.
   ''' </summary>
   ''' <param name="author1">
   ''' The first <see cref="GitHubAuthor"/>.
   ''' </param>
   ''' <param name="author2">
   ''' The second <see cref="GitHubAuthor"/>.
   ''' </param>
   ''' <returns>
   ''' The result of the operator.
   ''' </returns>
   Public Shared Operator <>(ByVal author1 As GitHubAuthor, ByVal author2 As GitHubAuthor) As Boolean

       Return (author1.Id <> author2.Id)

   End Operator

   ''' <summary>
   ''' Implements the operator =.
   ''' </summary>
   ''' <param name="author1">
   ''' The first <see cref="GitHubAuthor"/>.
   ''' </param>
   ''' <param name="author2">
   ''' The second <see cref="GitHubAuthor"/>.
   ''' </param>
   ''' <returns>
   ''' The result of the operator.
   ''' </returns>
   Public Shared Operator =(ByVal author1 As GitHubAuthor, ByVal author2 As GitHubAuthor) As Boolean

       Return (author1.Id = author2.Id)

   End Operator

End Class


GitHubUtil.vb
Código (vbnet) [Seleccionar]
Public NotInheritable Class GitHubUtil

#Region " Constructors "

   ''' <summary>
   ''' Prevents a default instance of the <see cref="GitHubUtil"/> class from being created.
   ''' </summary>
   Private Sub New()
   End Sub

#End Region

#Region " Public Methods "

   ''' <summary>
   ''' Asynchronously gets the releases from the specified repository on GitHub.
   ''' </summary>
   ''' <param name="userName">
   ''' The user name.
   ''' </param>
   ''' <param name="repositoryName">
   ''' The repository name.
   ''' </param>
   ''' <returns>
   ''' A <see cref="Task(Of ReadOnlyCollection(Of GitHubRelease))"/> containing the releases.
   ''' </returns>
   ''' <exception cref="HttpException">
   ''' JSON validation error.
   ''' </exception>
   Public Shared Async Function GetReleasesAsync(ByVal userName As String, ByVal repositoryName As String) As Task(Of ReadOnlyCollection(Of GitHubRelease))

       Dim uri As New Uri(String.Format("https://api.github.com/repos/{0}/{1}/releases", userName, repositoryName), UriKind.Absolute)

       Dim request As HttpWebRequest =  DirectCast(WebRequest.Create(uri), HttpWebRequest)
       request.UserAgent = userName

       Using response As WebResponse = Await request.GetResponseAsync(),
             sr As New StreamReader(response.GetResponseStream()),
             xmlReader As XmlDictionaryReader = JsonReaderWriterFactory.CreateJsonReader(sr.BaseStream, Encoding.UTF8, New XmlDictionaryReaderQuotas, Nothing)

           Dim xml As XElement = XElement.Load(xmlReader)
           If (xml.IsEmpty) Then
               Dim errMsg As String = String.Format("JSON validation error. ""{0}""", uri.ToString())
               Throw New HttpException(HttpStatusCode.NotFound, errMsg)
           End If

           Dim releases As New Collection(Of GitHubRelease)
           Dim elements As IEnumerable(Of XElement) = xml.<item>
           For Each element As XElement In elements
               Dim release As New GitHubRelease(element)
               releases.Add(release)
           Next

           Return New ReadOnlyCollection(Of GitHubRelease)(releases)

       End Using

   End Function

   ''' <summary>
   ''' Gets the releases from the specified repository on GitHub.
   ''' </summary>
   ''' <param name="userName">
   ''' The user name.
   ''' </param>
   ''' <param name="repositoryName">
   ''' The repository name.
   ''' </param>
   ''' <returns>
   ''' A <see cref="ReadOnlyCollection(Of GitHubRelease)"/> collection containing the releases.
   ''' </returns>
   Public Shared Function GetReleases(ByVal userName As String, ByVal repositoryName As String) As ReadOnlyCollection(Of GitHubRelease)

       Dim t As Task(Of ReadOnlyCollection(Of GitHubRelease)) = Task.Run(Function() GitHubUtil.GetReleases(userName, repositoryName))
       t.Wait(Timeout.Infinite)

       Return t.Result

   End Function

   ''' <summary>
   ''' Asynchronously gets a release that matches the specified version from the specified repository on GitHub.
   ''' </summary>
   ''' <param name="userName">
   ''' The user name.
   ''' </param>
   ''' <param name="repositoryName">
   ''' The repository name.
   ''' </param>
   ''' <param name="version">
   ''' The version of the release.
   ''' </param>
   ''' <returns>
   ''' The resulting <see cref="GitHubRelease"/>.
   ''' </returns>
   Public Shared Async Function GetReleaseAsync(ByVal userName As String, ByVal repositoryName As String, ByVal version As Version) As Task(Of GitHubRelease)

       Return (From release As GitHubRelease In Await GetReleasesAsync(userName, repositoryName)
               Where release.Version = version).
               DefaultIfEmpty(Nothing).
               SingleOrDefault()

   End Function

   ''' <summary>
   ''' Gets a release that matches the specified version from the specified repository on GitHub.
   ''' </summary>
   ''' <param name="userName">
   ''' The user name.
   ''' </param>
   ''' <param name="repositoryName">
   ''' The repository name.
   ''' </param>
   ''' <param name="version">
   ''' The version of the release.
   ''' </param>
   ''' <returns>
   ''' The resulting <see cref="GitHubRelease"/>.
   ''' </returns>
   Public Shared Function GetRelease(ByVal userName As String, ByVal repositoryName As String, ByVal version As Version) As GitHubRelease

       Dim t As Task(Of GitHubRelease) = Task.Run(Function() GitHubUtil.GetRelease(userName, repositoryName, version))
       t.Wait(Timeout.Infinite)

       Return t.Result

   End Function

   ''' <summary>
   ''' Asynchronously gets the latest release from the specified repository on GitHub.
   ''' </summary>
   ''' <param name="userName">
   ''' The user name.
   ''' </param>
   ''' <param name="repositoryName">
   ''' The repository name.
   ''' </param>
   ''' <returns>
   ''' The resulting <see cref="GitHubRelease"/>.
   ''' </returns>
   ''' <exception cref="HttpException">
   ''' JSON validation error.
   ''' </exception>
   Public Shared Async Function GetLatestReleaseAsync(ByVal userName As String, ByVal repositoryName As String) As Task(Of GitHubRelease)

       Dim uri As New Uri(String.Format("https://api.github.com/repos/{0}/{1}/releases/latest", userName, repositoryName), UriKind.Absolute)

       Dim request As HttpWebRequest = WebRequest.Create(uri)
       request.UserAgent = userName

       Using response As WebResponse = Await request.GetResponseAsync(),
             sr As New StreamReader(response.GetResponseStream()),
             xmlReader As XmlDictionaryReader = JsonReaderWriterFactory.CreateJsonReader(sr.BaseStream, Encoding.UTF8, New XmlDictionaryReaderQuotas, Nothing)

           Dim xml As XElement = XElement.Load(xmlReader)
           If (xml.IsEmpty) Then
               Dim errMsg As String = String.Format("JSON validation error. ""{0}""", uri.ToString())
               Throw New HttpException(HttpStatusCode.NotFound, errMsg)
           End If

           Return New GitHubRelease(xml)
       End Using

   End Function

   ''' <summary>
   ''' Gets the latest release from the specified repository on GitHub.
   ''' </summary>
   ''' <param name="userName">
   ''' The user name.
   ''' </param>
   ''' <param name="repositoryName">
   ''' The repository name.
   ''' </param>
   ''' <returns>
   ''' The resulting <see cref="GitHubRelease"/>.
   ''' </returns>
   Public Shared Function GetLatestRelease(ByVal userName As String, ByVal repositoryName As String) As GitHubRelease

       Dim t As Task(Of GitHubRelease) = Task.Run(Function() GitHubUtil.GetLatestReleaseAsync(userName, repositoryName))
       t.Wait(Timeout.Infinite)

       Return t.Result

   End Function

   ''' <summary>
   ''' Asynchronously gets a value that determine whether exists a new version available of the specified reository on GitHub.
   ''' </summary>
   ''' <param name="userName">
   ''' The user name.
   ''' </param>
   ''' <param name="repositoryName">
   ''' The repository name.
   ''' </param>
   ''' <param name="currentVersion">
   ''' The current version.
   ''' </param>
   ''' <returns>
   ''' <see langword="True"/> if exists a new version available on GitHub; otherwise, <see langword="False"/>.
   ''' </returns>
   Public Shared Async Function IsUpdateAvailableAsync(ByVal userName As String, ByVal repositoryName As String, ByVal currentVersion As Version) As Task(Of Boolean)

       Dim latestRelease As GitHubRelease = Await GitHubUtil.GetLatestReleaseAsync(userName, repositoryName)
       Return (latestRelease.Version > currentVersion)

   End Function

   ''' <summary>
   ''' Gets a value that determine whether exists a new version available of the specified reository on GitHub.
   ''' </summary>
   ''' <param name="userName">
   ''' The user name.
   ''' </param>
   ''' <param name="repositoryName">
   ''' The repository name.
   ''' </param>
   ''' <param name="currentVersion">
   ''' The current version.
   ''' </param>
   ''' <returns>
   ''' <see langword="True"/> if exists a new version available on GitHub; otherwise, <see langword="False"/>.
   ''' </returns>
   Public Shared Function IsUpdateAvailable(ByVal userName As String, ByVal repositoryName As String, ByVal currentVersion As Version) As Boolean

       Dim t As Task(Of Boolean) = Task.Run(Function() GitHubUtil.IsUpdateAvailableAsync(userName, repositoryName, currentVersion))
       t.Wait(Timeout.Infinite)

       Return t.Result

   End Function

#End Region

End Class








Eleкtro

Ejemplo para obtener todas las releases de un repositorio:

Código (vbnet) [Seleccionar]
Dim releases As ReadOnlyCollection(Of GitHubRelease) = Await GitHubUtil.GetReleasesAsync("ElektroStudios", "SmartBotKit")

For Each release As GitHubRelease In releases
   Console.WriteLine("RELEASE: {0}", release.ToString())

   For Each asset As GitHubAsset In release.Assets
       Console.WriteLine("ASSET  : {0}", asset.ToString())
   Next asset
   Console.WriteLine()
Next release


Ejemplo para obtener la release más reciente de un repositorio:

Código (vbnet) [Seleccionar]
Dim release As GitHubRelease = Await GitHubUtil.GetLatestReleaseAsync("ElektroStudios", "SmartBotKit")
Console.WriteLine("RELEASE: {0}", release.ToString())
Console.WriteLine()

Console.WriteLine("BODY:")
Console.WriteLine(release.Body)
Console.WriteLine()

For Each asset As GitHubAsset In release.Assets
   Console.WriteLine("ASSET: {0}", asset.ToString())
Next asset


La salida de ejecución sería más o menos algo parecido a esto:
CitarRELEASE: {Id=10754481, Version=1.3, Name=v1.3, TargetCommitish=master, IsDraft=False, IsPreRelease=False, DateCreated=04/27/2018 15:17:07, DatePublished=04/27/2018 15:22:06, UriHtml=https://github.com/ElektroStudios/SmartBotKit/releases/tag/1.3}

BODY:
Complete plugin collection.
SmartBotKit.Core.dll changes:
...

ASSET: {Id=6997992, Name=SmartBotKit.v1.3.zip, Label=, State=uploaded, Size=70959, ContentType=application/x-zip-compressed, DownloadCount=15, DateCreated=04/27/2018 15:22:03, DateUploaded=04/27/2018 15:22:04, UriDownload=https://github.com/ElektroStudios/SmartBotKit/releases/download/1.3/SmartBotKit.v1.3.zip}

ASSET: {Id=7125513, Name=test.txt, Label=, State=uploaded, Size=4, ContentType=text/plain, DownloadCount=1, DateCreated=05/06/2018 02:10:23, DateUploaded=05/06/2018 02:11:15, UriDownload=https://github.com/ElektroStudios/SmartBotKit/releases/download/1.3/test.txt}

Ejemplo para obtener una release con versión (tag_name) especifica de un repositorio:

Código (vbnet) [Seleccionar]
Dim release As GitHubRelease = Await GitHubUtil.GetReleaseAsync("ElektroStudios", "SmartBotKit", New Version("1.3"))
Console.WriteLine("RELEASE: {0}", release.ToString())
Console.WriteLine()

Console.WriteLine("BODY:")
Console.WriteLine(release.Body)
Console.WriteLine()

For Each asset As GitHubAsset In release.Assets
   Console.WriteLine("ASSET: {0}", asset.ToString())
Next asset


Ejemplo para comprobar si existe una actualización disponible de un repositorio, y descargarlo:

Código (vbnet) [Seleccionar]
Public Async Sub CheckForUpdate()

   Dim user As String = "ElektroStudios"
   Dim repo As String = "SmartBotKit"
   Dim currentVersion As Version = Assembly.GetExecutingAssembly().GetName().Version

   Dim isUpdateAvailable As Boolean = Await GitHubUtil.IsUpdateAvailableAsync(user, repo, currentVersion)
   If (isUpdateAvailable) Then
       MessageBox.Show("New version detected!", "Update", MessageBoxButtons.OK, MessageBoxIcon.Information)

       ' Get the latest release.
       Dim latestRelease As GitHubRelease = Await GitHubUtil.GetLatestReleaseAsync(user, repo)

       Using wc As New WebClient() ' Download the assets.
           For Each asset As GitHubAsset In latestRelease.Assets
               Dim fullpath As String = Path.Combine(Path.GetTempPath(), asset.Name)
               Await wc.DownloadFileTaskAsync(asset.UriDownload, fullpath)
               Console.WriteLine("File downloaded: {0}", fullpath)
               ' Your own update logic goes here...
           Next asset
       End Using

   End If

End Sub








**Aincrad**

Exelente, me parece fantastico . . .  yo hice algo parecido con pastebin . puede obtener actualizaciones y descargarlas también con pastebin & mediafire. bueno voy a hacer un ejemplo para el foro y lo publico cuando tenga tiempo XD.

gracias por el aporte me servirá de mucho cuando logre poner una bendita carpeta en mi repositorio de  GitHub . :,V      :,V         :,V         :rolleyes:





Eleкtro

Cita de: **Aincrad** en 11 Mayo 2018, 21:52 PM
gracias por el aporte me servirá de mucho cuando logre poner una bendita carpeta en mi repositorio de  GitHub . :,V      :,V         :,V         :rolleyes:

Gracias por el comentario.

No recuerdo si ya te comenté lo siguiente en otro post, pero por si no lo hice, te recomiendo usar GitHub Desktop para administrar tus repos:

Es muy sencillo de utilizar y así evitarías tener que aprenderte y usar los comandos de la consola de git.

saludos








Eleкtro

Recientemente he descubierto la librería Octokit para .NET, la cual al parecer está mantenida oficialmente por GitHub (o eso dice el autor):

También está disponible para Ruby y Objective-C:

¿Qué se puede hacer con dicha librería?, pues parece ser que practicamente de todo, desde hacer un commit, hasta obtener las releases de un repositorio como yo hice por mi cuenta en el post principal de este tema... así que os comento lo de la librería como alternativa para el que le interese, aunque en mi humilde opinión es demasiado basto ya que es un cliente completo de GitHub... para ser usado en otro tipo de escenarios más complejos y sofisticados, no para obtener unas releases y ya.

Saludos