Last active
March 28, 2017 08:24
-
-
Save 0xFEEDC0DE64/a4414914faec170bd9389be95f9d1696 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| using System; | |
| using System.Collections.Generic; | |
| using System.IO; | |
| using System.Linq; | |
| using System.Net; | |
| using System.Security.Cryptography; | |
| using System.Text; | |
| using System.Threading; | |
| using Newtonsoft.Json; | |
| namespace BsToLib | |
| { | |
| class BsToWebClient : WebClient | |
| { | |
| private string publicKey; | |
| private string privateKey; | |
| private string cacheDir; | |
| private TimeSpan maxCacheTime; | |
| private HashAlgorithm hashAlgorithm; | |
| private DateTime lastBsToRequest; | |
| public class SeriesResponse : List<SeriesResponse.Serie> | |
| { | |
| public class Serie | |
| { | |
| public string id; | |
| public string series; | |
| } | |
| } | |
| public class SeriesGenreResponse : Dictionary<string, SeriesGenreResponse.Genre> | |
| { | |
| public class Genre | |
| { | |
| public class Serie | |
| { | |
| public int id; | |
| public string name; | |
| } | |
| public int id; | |
| public List<Serie> series; | |
| } | |
| } | |
| public class SerieResponse | |
| { | |
| public class Serie | |
| { | |
| public class Data | |
| { | |
| public List<string> actor; | |
| public List<string> author; | |
| public List<string> genre; | |
| public List<string> director; | |
| public List<string> producer; | |
| public string genre_main; | |
| } | |
| public string id; | |
| public string series; | |
| public string url; | |
| public string description; | |
| public string start; | |
| public string end; | |
| public string movies; | |
| public string seasons; | |
| public Data data; | |
| } | |
| public Serie series; | |
| } | |
| public class SeasonResponse | |
| { | |
| public class Episode | |
| { | |
| public string epi; | |
| public string german; | |
| public string english; | |
| public string watched; | |
| } | |
| public int season; | |
| public List<Episode> epi; | |
| } | |
| public class EpisodeResponse | |
| { | |
| public class Episode | |
| { | |
| public string id; | |
| public string german; | |
| public string english; | |
| public string description; | |
| } | |
| public class Link | |
| { | |
| public string id; | |
| public string hoster; | |
| } | |
| public string series; | |
| public Episode epi; | |
| public List<Link> links; | |
| } | |
| public class LinkResponse | |
| { | |
| public string epi; | |
| public string hoster; | |
| public string url; | |
| public string fullurl; | |
| } | |
| public BsToWebClient(string publicKey = "OXI1L47qvWohTqVRjdGVwsocuOkeaRbL", string privateKey = "Gh86wdxreHBl0kMLFoMOzbv75kZt0UiG", string cacheDir = "bs.to-cache") | |
| { | |
| this.publicKey = publicKey; | |
| this.privateKey = privateKey; | |
| this.cacheDir = cacheDir; | |
| this.maxCacheTime = new TimeSpan(7, 0, 0, 0); //TODO: make this an optional argument | |
| hashAlgorithm = new HMACSHA256(Encoding.Default.GetBytes(privateKey)); | |
| lastBsToRequest = new DateTime(); | |
| if (!Directory.Exists(cacheDir)) | |
| Directory.CreateDirectory(cacheDir); | |
| } | |
| protected override WebRequest GetWebRequest(Uri url) | |
| { | |
| var webRequest = (HttpWebRequest)base.GetWebRequest(url); | |
| if ((url.Host == "bs.to" || url.Host == "www.bs.to") && url.AbsolutePath.StartsWith("/api/")) | |
| { | |
| var msecsSinceLast = (DateTime.Now - lastBsToRequest).TotalMilliseconds; | |
| if (msecsSinceLast <= 1000) | |
| Thread.Sleep(1000 - (int)msecsSinceLast); | |
| lastBsToRequest = DateTime.Now; | |
| long timestamp = DateTimeOffset.Now.ToUnixTimeMilliseconds() / 1000; | |
| var str = timestamp + url.AbsolutePath.Substring(4); | |
| var bytes = Encoding.Default.GetBytes(str); | |
| var hash = hashAlgorithm.ComputeHash(bytes); | |
| var hashAsHex = BitConverter.ToString(hash).Replace("-", ""); | |
| var json = JsonConvert.SerializeObject(new { public_key = publicKey, timestamp = timestamp, hmac = hashAsHex }); | |
| var jsonBytes = Encoding.Default.GetBytes(json); | |
| var base64 = Convert.ToBase64String(jsonBytes); | |
| webRequest.Headers.Add("BS-Token", base64); | |
| webRequest.UserAgent = "BSNova"; | |
| webRequest.AutomaticDecompression = DecompressionMethods.GZip | DecompressionMethods.Deflate; | |
| } | |
| return webRequest; | |
| } | |
| private T GetResponse<T>(string url, string cacheFilename) | |
| { | |
| var cachePath = Path.Combine(cacheDir, cacheFilename); | |
| if (!File.Exists(cachePath) || DateTime.Now - File.GetLastWriteTime(cachePath) > maxCacheTime) | |
| DownloadFile("https://www.bs.to/api/" + url, cachePath); | |
| return JsonConvert.DeserializeObject<T>(File.ReadAllText(cachePath)); | |
| } | |
| public SeriesResponse GetSeries() | |
| { | |
| return GetResponse<SeriesResponse>("series", "series.json"); | |
| } | |
| public SeriesGenreResponse GetSeriesGenre() | |
| { | |
| return GetResponse<SeriesGenreResponse>("series:genre", "series_genre.json"); | |
| } | |
| public SerieResponse GetSerie(int id) | |
| { | |
| return GetResponse<SerieResponse>(string.Format("series/{0}/1", id), string.Format("series_{0}_1.json", id)); | |
| } | |
| public SeasonResponse GetSeason(int id, int season) | |
| { | |
| return GetResponse<SeasonResponse>(string.Format("series/{0}/{1}", id, season), string.Format("series_{0}_{1}.json", id, season)); | |
| } | |
| public EpisodeResponse GetEpisode(int id, int season, int episode) | |
| { | |
| return GetResponse<EpisodeResponse>(string.Format("series/{0}/{1}/{2}", id, season, episode), string.Format("series_{0}_{1}_{2}.json", id, season, episode)); | |
| } | |
| public LinkResponse GetLink(int id) | |
| { | |
| return GetResponse<LinkResponse>(string.Format("watch/{0}", id), string.Format("watch_{0}.json", id)); | |
| } | |
| } | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment