Skip to content

Commit

Permalink
RIP WebRequest, long live HttpClient
Browse files Browse the repository at this point in the history
  • Loading branch information
thepwrtank18 committed Feb 20, 2023
1 parent cd469ac commit 73e9d53
Show file tree
Hide file tree
Showing 3 changed files with 108 additions and 70 deletions.
7 changes: 6 additions & 1 deletion Jellylist.sln.DotSettings
Original file line number Diff line number Diff line change
@@ -1,2 +1,7 @@
<wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
<s:Boolean x:Key="/Default/UserDictionary/Words/=Jellylist/@EntryIndexedValue">True</s:Boolean></wpf:ResourceDictionary>
<s:Boolean x:Key="/Default/UserDictionary/Words/=Dsgcn/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=EXTIMG/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=Fdpbm/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=Jellyfin/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=Jellylist/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=Zpcm/@EntryIndexedValue">True</s:Boolean></wpf:ResourceDictionary>
131 changes: 64 additions & 67 deletions Jellylist/Controllers/GetListController.cs
Original file line number Diff line number Diff line change
@@ -1,30 +1,44 @@
using System.Net;
using System.Net.Http.Headers;
using Microsoft.AspNetCore.Mvc;
using Newtonsoft.Json;
// ReSharper disable StringLiteralTypo
// ReSharper disable IdentifierTypo
// ReSharper disable CommentTypo

namespace Jellylist.Controllers
{
[ApiController]
[Route("[controller]")]
public class GetM3UController : ControllerBase
public abstract class Shared
{
/// <summary>
/// Creates an M3U file, and returns the text.
/// </summary>
/// <param name="seriesId">The series ID.</param>
/// <param name="authToken">An API key. Takes priority over username and password.</param>
/// <param name="username">The username. Required if an API key isn't specified.</param>
/// <param name="password">The password. Required if an API key isn't specified, and the user has a password.</param>
/// <param name="returnType">The return type, either m3u for full metadata or txt for just the links, no other metadata.</param>
/// <returns></returns>
[Obsolete("Replaced with GetList. Endpoint is no longer being updated and may stop working.")]
[HttpGet(Name = "GetM3U")]
public string GetM3U(string seriesId, string? authToken = null, string? username = null,
string? password = null, string returnType = "m3u")
public static async Task<string> MakePostRequest(string url, string data, string embyAuth)
{
using var httpClient = new HttpClient();
var content = new StringContent(data);
content.Headers.ContentType = new MediaTypeHeaderValue("application/json");

httpClient.DefaultRequestHeaders.UserAgent.ParseAdd("Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:107.0) Gecko/20100101 Firefox/107.0");

var request = new HttpRequestMessage(HttpMethod.Post, url);
request.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
request.Headers.Add("X-Emby-Authorization", embyAuth);
request.Content = content;

var response = await httpClient.SendAsync(request);
var responseString = await response.Content.ReadAsStringAsync();
return responseString;
}

public static async Task<string> MakeGetRequest(string url, string embyAuth)
{
return new GetTVController().GetTV(seriesId, authToken, username, password, returnType);
using var httpClient = new HttpClient();
httpClient.DefaultRequestHeaders.Add("Accept", "application/json");
httpClient.DefaultRequestHeaders.Add("ContentType", "application/json");
httpClient.DefaultRequestHeaders.UserAgent.ParseAdd("Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:107.0) Gecko/20100101 Firefox/107.0");
httpClient.DefaultRequestHeaders.Add("X-Emby-Authorization", embyAuth);

var response = await httpClient.GetAsync(url);
var responseString = await response.Content.ReadAsStringAsync();
return responseString;
}
}

Expand All @@ -42,7 +56,7 @@ public class GetAlbumController : ControllerBase
/// <param name="returnType"></param>
/// <returns></returns>
[HttpGet(Name = "GetAlbum")]
public string GetAlbum(string albumId, string? authToken = null, string? username = null,
public async Task<string> GetAlbum(string albumId, string? authToken = null, string? username = null,
string? password = null, string returnType = "m3u")
{
string userId;
Expand All @@ -54,58 +68,45 @@ public string GetAlbum(string albumId, string? authToken = null, string? usernam
return "No login details specified.";
}

var url2 = Program.PublicUrl + "/Users/AuthenticateByName";
/*var url2 = Program.PublicUrl + "/Users/AuthenticateByName";
var httpRequest2 = (HttpWebRequest)WebRequest.Create(url2);
httpRequest2.Method = "POST";
httpRequest2.Accept = "application/json";
httpRequest2.Headers["X-Emby-Authorization"] = "MediaBrowser Client=\"Jellyfin Web\", Device=\"Firefox\", DeviceId=\"TW96aWxsYS81LjAgKFdpbmRvd3MgTlQgMTAuMDsgV2luNjQ7IHg2NDsgcnY6MTA2LjApIEdlY2tvLzIwMTAwMTAxIEZpcmVmb3gvMTA2LjB8MTY2Nzk1OTA0NjIxNg11\", Version=\"10.8.5\"";
httpRequest2.Headers["User-Agent"] = "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:107.0) Gecko/20100101 Firefox/107.0";
httpRequest2.ContentType = "application/json";

var data = @"{
""Username"": ""[username]"",
""Pw"": ""[pass]""
}".Replace("[username]", username).Replace("[pass]", password);

using (var streamWriter = new StreamWriter(httpRequest2.GetRequestStream()))
{
streamWriter.Write(data);
}
var httpResponse2 = (HttpWebResponse)httpRequest2.GetResponse();
using var streamReader = new StreamReader(httpResponse2.GetResponseStream());
var result = streamReader.ReadToEnd();
var result = streamReader.ReadToEnd();*/

var data = @"{
""Username"": ""[username]"",
""Pw"": ""[pass]""
}".Replace("[username]", username).Replace("[pass]", password);
var result = await Shared.MakePostRequest(Program.PublicUrl + "/Users/AuthenticateByName", data,
"MediaBrowser Client=\"Jellyfin Web\", Device=\"Firefox\", DeviceId=\"TW96aWxsYS81LjAgKFdpbmRvd3MgTlQgMTAuMDsgV2luNjQ7IHg2NDsgcnY6MTA2LjApIEdlY2tvLzIwMTAwMTAxIEZpcmVmb3gvMTA2LjB8MTY2Nzk1OTA0NjIxNg11\", Version=\"10.8.5\"");
var test = JsonConvert.DeserializeObject<dynamic>(result);
authToken = test!.AccessToken;
userId = test.User.Id;
}
else
{
var url2 = Program.PublicUrl + "/Users/Me";
var httpRequest2 = (HttpWebRequest)WebRequest.Create(url2);
httpRequest2.Method = "GET";

httpRequest2.Accept = "application/json";
httpRequest2.Headers["X-Emby-Authorization"] = $"MediaBrowser Client=\"Jellyfin Web\", Device=\"Firefox\", DeviceId=\"TW96aWxsYS81LjAgKFdpbmRvd3MgTlQgMTAuMDsgV2luNjQ7IHg2NDsgcnY6MTA2LjApIEdlY2tvLzIwMTAwMTAxIEZpcmVmb3gvMTA2LjB8MTY2Nzk1OTA0NjIxNg11\", Version=\"10.8.5\", Token=\"{authToken}\"";
httpRequest2.Headers["User-Agent"] = "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:107.0) Gecko/20100101 Firefox/107.0";
httpRequest2.ContentType = "application/json";

var httpResponse2 = (HttpWebResponse)httpRequest2.GetResponse();
using var streamReader = new StreamReader(httpResponse2.GetResponseStream());
var result = streamReader.ReadToEnd();
var result = await Shared.MakeGetRequest(Program.PublicUrl + "/Users/Me",
$"MediaBrowser Client=\"Jellyfin Web\", Device=\"Firefox\", DeviceId=\"TW96aWxsYS81LjAgKFdpbmRvd3MgTlQgMTAuMDsgV2luNjQ7IHg2NDsgcnY6MTA2LjApIEdlY2tvLzIwMTAwMTAxIEZpcmVmb3gvMTA2LjB8MTY2Nzk1OTA0NjIxNg11\", Version=\"10.8.5\", Token=\"{authToken}\"");
var test = JsonConvert.DeserializeObject<dynamic>(result);

userId = test!.Id;
}

var url = Program.PublicUrl + $"/Users/{userId}/Items?ParentId={albumId}&Fields=ItemCounts%2CPrimaryImageAspectRatio%2CBasicSyncInfo%2CCanDelete%2CMediaSourceCount&SortBy=ParentIndexNumber%2CIndexNumber%2CSortName";

var httpRequest = (HttpWebRequest)WebRequest.Create(url);
httpRequest.Accept = "application/json";
httpRequest.Headers["X-Emby-Authorization"] = $"MediaBrowser Client=\"Jellyfin Web\", Device=\"Firefox\", DeviceId=\"TW96aWxsYS81LjAgKFdpbmRvd3MgTlQgMTAuMDsgV2luNjQ7IHg2NDsgcnY6MTA2LjApIEdlY2tvLzIwMTAwMTAxIEZpcmVmb3gvMTA2LjB8MTY2Nzk1OTA0NjIxNg11\", Version=\"10.8.5\", Token=\"{authToken}\"";
httpRequest.Headers["User-Agent"] = "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:107.0) Gecko/20100101 Firefox/107.0";
httpRequest.ContentType = "application/json";

switch (returnType)
{
case "m3u":
Expand All @@ -117,17 +118,15 @@ public string GetAlbum(string albumId, string? authToken = null, string? usernam

try
{
var httpResponse = (HttpWebResponse)httpRequest.GetResponse();
using var streamReader = new StreamReader(httpResponse.GetResponseStream());
var result = streamReader.ReadToEnd();
var result = await Shared.MakeGetRequest(url,
$"MediaBrowser Client=\"Jellyfin Web\", Device=\"Firefox\", DeviceId=\"TW96aWxsYS81LjAgKFdpbmRvd3MgTlQgMTAuMDsgV2luNjQ7IHg2NDsgcnY6MTA2LjApIEdlY2tvLzIwMTAwMTAxIEZpcmVmb3gvMTA2LjB8MTY2Nzk1OTA0NjIxNg11\", Version=\"10.8.5\", Token=\"{authToken}\"");
var test = JsonConvert.DeserializeObject<dynamic>(result);


returnstring += $"\n#PLAYLIST:{test!.Items[0].Album}";
returnstring += $"\n#EXTALB:{test!.Items[0].Album}";
returnstring += $"\n#EXTART:{test!.Items[0].AlbumArtist}";
//returnstring += $"\n#EXTIMG: front cover\n{Program.PublicUrl}/Items/{albumId}/Images/Primary"; // VLC doesn't like this for some reason

returnstring += $"\n#EXTALB:{test.Items[0].Album}";
returnstring += $"\n#EXTART:{test.Items[0].AlbumArtist}";

foreach (var test2 in test.Items)
{
returnstring += $"\n#EXTINF:{test2.RunTimeTicks / 10000 / 1000 /* seconds */},{test2.Album}, " +
Expand All @@ -149,9 +148,8 @@ public string GetAlbum(string albumId, string? authToken = null, string? usernam

try
{
var httpResponse = (HttpWebResponse)httpRequest.GetResponse();
using var streamReader = new StreamReader(httpResponse.GetResponseStream());
var result = streamReader.ReadToEnd();
var result = await Shared.MakeGetRequest(url,
$"MediaBrowser Client=\"Jellyfin Web\", Device=\"Firefox\", DeviceId=\"TW96aWxsYS81LjAgKFdpbmRvd3MgTlQgMTAuMDsgV2luNjQ7IHg2NDsgcnY6MTA2LjApIEdlY2tvLzIwMTAwMTAxIEZpcmVmb3gvMTA2LjB8MTY2Nzk1OTA0NjIxNg11\", Version=\"10.8.5\", Token=\"{authToken}\"");
var test = JsonConvert.DeserializeObject<dynamic>(result);

foreach (var test2 in test!.Items)
Expand Down Expand Up @@ -188,7 +186,7 @@ public class GetTVController : ControllerBase
/// <returns></returns>
[HttpGet(Name = "GetTV")]
// ReSharper disable once InconsistentNaming
public string GetTV(string seriesId, string? authToken = null, string? username = null, string? password = null, string returnType = "m3u")
public async Task<string> GetTV(string seriesId, string? authToken = null, string? username = null, string? password = null, string returnType = "m3u")
{

if (authToken == null) // no auth token
Expand All @@ -197,7 +195,7 @@ public string GetTV(string seriesId, string? authToken = null, string? username
{
return "No login details specified.";
}
var url2 = Program.PublicUrl + "/Users/AuthenticateByName";
/*var url2 = Program.PublicUrl + "/Users/AuthenticateByName";
var httpRequest2 = (HttpWebRequest)WebRequest.Create(url2);
httpRequest2.Method = "POST";
Expand All @@ -219,16 +217,19 @@ public string GetTV(string seriesId, string? authToken = null, string? username
var httpResponse2 = (HttpWebResponse)httpRequest2.GetResponse();
using var streamReader = new StreamReader(httpResponse2.GetResponseStream());
var result = streamReader.ReadToEnd();
var result = streamReader.ReadToEnd();*/
var data = @"{
""Username"": ""[username]"",
""Pw"": ""[pass]""
}".Replace("[username]", username).Replace("[pass]", password);
var result = await Shared.MakePostRequest(Program.PublicUrl + "/Users/AuthenticateByName", data,
"MediaBrowser Client=\"Jellyfin Web\", Device=\"Firefox\", DeviceId=\"TW96aWxsYS81LjAgKFdpbmRvd3MgTlQgMTAuMDsgV2luNjQ7IHg2NDsgcnY6MTA2LjApIEdlY2tvLzIwMTAwMTAxIEZpcmVmb3gvMTA2LjB8MTY2Nzk1OTA0NjIxNg11\", Version=\"10.8.5\"");
var test = JsonConvert.DeserializeObject<dynamic>(result);
authToken = test!.AccessToken;
}

var url = Program.PublicUrl + $"/Shows/{seriesId}/Episodes?api_key={authToken}";

var httpRequest = (HttpWebRequest)WebRequest.Create(url);

httpRequest.Accept = "application/json";

switch (returnType)
{
case "m3u":
Expand All @@ -240,9 +241,7 @@ public string GetTV(string seriesId, string? authToken = null, string? username

try
{
var httpResponse = (HttpWebResponse)httpRequest.GetResponse();
using var streamReader = new StreamReader(httpResponse.GetResponseStream());
var result = streamReader.ReadToEnd();
var result = await Shared.MakeGetRequest(url, "");
var test = JsonConvert.DeserializeObject<dynamic>(result);


Expand Down Expand Up @@ -279,9 +278,7 @@ public string GetTV(string seriesId, string? authToken = null, string? username

try
{
var httpResponse = (HttpWebResponse)httpRequest.GetResponse();
using var streamReader = new StreamReader(httpResponse.GetResponseStream());
var result = streamReader.ReadToEnd();
var result = await Shared.MakeGetRequest(url, "");
var test = JsonConvert.DeserializeObject<dynamic>(result);

if (test == null) return returnstring;
Expand Down
40 changes: 38 additions & 2 deletions Jellylist/Program.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@

// ReSharper disable StringLiteralTypo

using System.Text.RegularExpressions;

namespace Jellylist
{
public abstract class Program
Expand All @@ -8,6 +10,7 @@ public abstract class Program

public static void Main(string[] args)
{
const string urlPattern = @"https?:\/\/(www\.)?[-a-zA-Z0-9@:%._\+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}\b([-a-zA-Z0-9()@:%_\+.~#?&\/\/=]*)"; // the language of gods
int currentArg = -1;
if (!args.Contains("--jellyfinUrl"))
{
Expand All @@ -19,7 +22,40 @@ public static void Main(string[] args)
currentArg++;
if (arg == "--jellyfinUrl")
{
PublicUrl = args[currentArg + 1];
int matches = 0;
string completeUrl = "";
try
{
foreach (Match m in Regex.Matches(args[currentArg + 1], urlPattern, RegexOptions.Multiline))
{
matches++;
if (matches == 1)
{
completeUrl = m.Value;
}
}
}
catch (Exception)
{
Console.WriteLine("An error occurred reading arguments. Make sure you entered the URL correctly. Full error: ");
throw;
}

switch (matches)
{
case 0:
Console.WriteLine("No URL detected. Please try again.");
Environment.Exit(1);
break;
case 1:
Console.WriteLine($"Using URL {completeUrl}.");
PublicUrl = completeUrl;
break;
case >= 2:
Console.WriteLine($"Multiple URLs detected. Only 1 is supported. Using first URL ({completeUrl}).");
PublicUrl = completeUrl;
break;
}
}
}

Expand Down

0 comments on commit 73e9d53

Please sign in to comment.