Vine is a video sharing platform developed by Twitter that allows users to share videos with duration up to 6 seconds. It allows you to upload and share videos directly from the platform or through its mobile application for iOS, Android and Windows Phone.

Introduction to Vine API

Twitter does not provide a public API for this platform, so thanks to reverse engineering some developers have discovered and published the endpoints of this API. This “unofficial API” includes lots of features, but in this article we will only see how to share a video I came across code.

The official mobile application allows you to choose not to share the video we already have, but that requires recording the video within the same application. This video is stored in MP4 format at a resolution of 480×480 pixels.

Now we will see how to do this directly from the API.

Access to platform

Vine offers access through social networks so the API takes these social credentials for access to it. For a session ID, you must send your username and password in the request form data through a POST. The endpoint, and the code are:

Https://api.vineapp.com/users/authenticate POST
Postscript:
username=xxx@example.com
password = xxx

 
/// <summary>
/// Logs in to Vine and returns session ID.
/// </summary>
public static async Task<string> VineLoginAsync(string Username, string Password)
{
    try
    {
        string _VineSessionId = string.Empty;
        var multiPartData = new HttpMultipartFormDataContent();
        multiPartData.Add(new HttpStringContent(Username), "username");
        multiPartData.Add(new HttpStringContent(Password), "password");
        HttpClient httpClient = new HttpClient();
        var HttpReq = await httpClient.PostAsync(new Uri("https://api.vineapp.com/users/authenticate"), multiPartData);

        if (HttpReq.IsSuccessStatusCode)
        {
            var JsonResponse = await HttpReq.Content.ReadAsStringAsync();
            var obj = JsonObject.Parse(JsonResponse);
            _VineSessionId = obj.GetNamedObject("data").GetNamedString("key");
            ApplicationData.Current.LocalSettings.Values["VINE_SESSION_ID_KEY"] = _VineSessionId;
        }

        return _VineSessionId; 
    }
    
    catch (Exception ex)
    {

    }
}

 

Getting Channels

Channels are a parameter used in video uploads to the network. By setting the channel identifier as the ups, it is associated with the specified channel. For the channel name and ID, you need to send a request to the appropriate endpoint of the way that I show below. The code and the JSON output are:

GET https://api.vineapp.com/channels/featured

 
/// <summary>
/// Returns Vine channel name with its ID.
/// </summary>
public static async Task<List<KeyValuePair<string, string>>> GetChannelsAsync()
{
    try
    {
        var HttpReq = await httpClient.GetAsync(new Uri("https://api.vineapp.com/channels/featured"));

        if (HttpReq.IsSuccessStatusCode)
        {
            var ResponseStr = await HttpReq.Content.ReadAsStringAsync();
            var JsonObj = JsonObject.Parse(ResponseStr);

            var array = JsonObj["data"].GetObject()["records"].GetArray();

            var ChannelDictionary = new List<KeyValuePair<string, string>>();

            foreach (var item in array)
            {
                ChannelDictionary.Add(new KeyValuePair<string, string>(item.GetObject()["channelId"].GetNumber().ToFloatingPointString(), item.GetObject()["channel"].GetString()));
            }
            
            return ChannelDictionary;
        }
    }
    
    catch (Exception ex)
    {

    }
}
[/ code]

Here you have to use a method of converting a long integer into a string. If you only use the ToString () method will return the number in scientific notation. For example, if the channel ID is 1070175184667013120 get "1.07017518466701E 18 +". Therefore, we must use the ToFloatingPointString () method as shown below

 
private static readonly Regex rxScientific = new Regex(@"^(?<sign>-?)(?<head>d+)(.(?<tail>d*?)0*)?E(?<exponent>[+-]d+)$", RegexOptions.IgnoreCase|RegexOptions.ExplicitCapture|RegexOptions.CultureInvariant);

public static string ToFloatingPointString(this double value) 
{
    return ToFloatingPointString(value, NumberFormatInfo.CurrentInfo);
}

public static string ToFloatingPointString(double value, NumberFormatInfo formatInfo) 
{
    string result = value.ToString("r", NumberFormatInfo.InvariantInfo);
    Match match = rxScientific.Match(result);
    
    if (match.Success) 
    {
        Debug.WriteLine("Found scientific format: {0} => [{1}] [{2}] [{3}] [{4}]", result, match.Groups["sign"], match.Groups["head"], match.Groups["tail"], match.Groups["exponent"]);
        
        int exponent = int.Parse(match.Groups["exponent"].Value, NumberStyles.Integer, NumberFormatInfo.InvariantInfo);
        StringBuilder builder = new StringBuilder(result.Length + Math.Abs(exponent));
        builder.Append(match.Groups["sign"].Value);
        
        if (exponent >= 0) 
        {
            builder.Append(match.Groups["head"].Value);
            string tail = match.Groups["tail"].Value;
            
            if (exponent < tail.Length) 
            {
                builder.Append(tail, 0, exponent);
                builder.Append(formatInfo.NumberDecimalSeparator);
                builder.Append(tail, exponent, tail.Length-exponent);
            } 
            else 
            {
                builder.Append(tail);
                builder.Append('0', exponent-tail.Length);
            }
        } 
        else 
        {
            builder.Append('0');
            builder.Append(formatInfo.NumberDecimalSeparator);
            builder.Append('0', (-exponent)-1);
            builder.Append(match.Groups["head"].Value);
            builder.Append(match.Groups["tail"].Value);
        }
        
        result = builder.ToString();
    }
    
    return result;
}
[/ code]


<h4></h4>
&nbsp;
<h4>I came up the video</h4>
Vine allows only videos with a resolution of 480x480 and a duration not to exceed 6 seconds. So first we have to change the video to meet these conditions. The upload process consists of 3 simple steps, which correspond to calls to the API platform.

First you have to upload the video via HTTP PUT request. The head of this application shall contain the session ID Vine and video content will rise. The content-type will be video / mp4. The response header will contain the URL of the video uploaded to obtain for use in the 3rd step. As an example, here is an example where the endpoint shown, the JSON response and code:

PUT https://media.vineapp.com/upload/videos/1.3.1.mp4
 
/// <summary>
/// Uploads video to Vine and returns Vine URL for video.
/// </summary>
public static async Task<string> UploadVineVideoAsync(StorageFile Video, string VineSessionId)
{
    try
    {
        string _VideoUrl = string.Empty;

        var binaryContent = new HttpBufferContent(await FileIO.ReadBufferAsync(Video));
        binaryContent.Headers.Add("Content-Type", "video/mp4");

        var request = new HttpRequestMessage(HttpMethod.Put, new Uri("https://media.vineapp.com/upload/videos/1.3.1.mp4"));
        request.Headers.Add("vine-session-id", VineSessionId);
        request.Content = binaryContent;

        var HttpReq = await httpClient.SendRequestAsync(request);

        if (HttpReq.IsSuccessStatusCode)
        {
            var ResonseHeader = HttpReq.Headers;
            ResonseHeader.TryGetValue("X-Upload-Key", out _VideoUrl);
        }

        return _VideoUrl; 
    }
    catch (Exception ex)
    {
        return string.Empty;
    }
} 

Our second step will upload the video thumbnail (thumbnail). It must also have a resolution of 480x480 and the type of content will be image / jpeg. The method call to the service is the same as used in the first step to upload the video. You have to send a PUT request indicating in the header the session ID and the image came on the content of the request.

PUT https://media.vineapp.com/upload/thumbs/1.3.1.mp4.jpg

 
/// <summary>
/// Uploads video thumbnail image to Vine and returns Vine URL for thumbnail image.
/// </summary>
public static async Task<string> UploadVineThumbAsync(StorageFile Video, string VineSessionId)
{
    try
    {
        var VideoThumb = await Video.GetThumbnailAsync(Windows.Storage.FileProperties.ThumbnailMode.SingleItem);
        Byte[] VideoThumbBytes = new Byte[VideoThumb.Size];
        var VideoThumbBuffer = VideoThumbBytes.AsBuffer();

        string _ThumbUrl = string.Empty;

        var binaryContent = new HttpBufferContent(VideoThumbBuffer);
        binaryContent.Headers.Add("Content-Type", "image/jpeg");

        var request = new HttpRequestMessage(HttpMethod.Put, new Uri("https://media.vineapp.com/upload/thumbs/1.3.1.mp4.jpg"));
        request.Headers.Add("vine-session-id", VineSessionId);
        request.Content = binaryContent;

        var HttpReq = await httpClient.SendRequestAsync(request);

        if (HttpReq.IsSuccessStatusCode)
        {
            var ResonseHeader = HttpReq.Headers;
            ResonseHeader.TryGetValue("X-Upload-Key", out _ThumbUrl);
            var ResonseStr = await HttpReq.Content.ReadAsStringAsync();
        }
        
        return _ThumbUrl; 
    }
    
    catch (Exception ex)
    {
        return string.Empty;
    }
}

Now the last step is a POST request that takes as parameters the video URL, the URL of the thumbnail, the channel ID and description thereof, as well as a parameter Entities that talk now. The header of the request, as usual, will contain the session ID in Vine. The purpose of the 'Entities' parameter has not been analyzed, so an empty string will be passed as it is a mandatory parameter.

 
/// <summary>
/// Uploads Vine.
/// </summary>
public static async Task PostVineAsync(string VideoUrl, string ThumbUrl, string ChannelId, string Description, string Entities)
{
    try
    {
        httpClient.DefaultRequestHeaders.Add("vine-session-id", VineSessionId);

        var multiPartData = new HttpMultipartFormDataContent();
        multiPartData.Add(new HttpStringContent(VideoUrl), "videoUrl");
        multiPartData.Add(new HttpStringContent(ThumbUrl), "thumbnailUrl");
        multiPartData.Add(new HttpStringContent(ChannelId), "channelId");
        multiPartData.Add(new HttpStringContent(string.IsNullOrWhiteSpace(Description) ? "Default Description" : Description), "description");
        multiPartData.Add(new HttpStringContent(Entities), "entities");

        var HttpReq = await httpClient.PostAsync(new Uri("https://api.vineapp.com/posts"), multiPartData);

        if (HttpReq.IsSuccessStatusCode)
        {
            var ResonseHeader = HttpReq.Headers;
            var ResonseStr = await HttpReq.Content.ReadAsStringAsync();
            await new MessageDialog("Video uploaded successfully on Vine", "App name").ShowAsync();
        }
    }
    
    catch (Exception ex)
    {

    }
}