diff --git a/TwitchDownloaderCLI/TwitchDownloaderCLI.csproj b/TwitchDownloaderCLI/TwitchDownloaderCLI.csproj
index dd4aef6d..9a5fbe1c 100644
--- a/TwitchDownloaderCLI/TwitchDownloaderCLI.csproj
+++ b/TwitchDownloaderCLI/TwitchDownloaderCLI.csproj
@@ -3,7 +3,7 @@
Exe
netcoreapp3.1
- 1.40.6
+ 1.40.7
AnyCPU;x64
diff --git a/TwitchDownloaderCore/TwitchHelper.cs b/TwitchDownloaderCore/TwitchHelper.cs
index 16cc746f..7f5ddc34 100644
--- a/TwitchDownloaderCore/TwitchHelper.cs
+++ b/TwitchDownloaderCore/TwitchHelper.cs
@@ -562,54 +562,78 @@ public static List GetBits(string cacheFolder, string channel_id = "
using (WebClient client = new WebClient())
{
- client.Headers.Add("Accept", "application/vnd.twitchtv.v5+json");
+ client.Encoding = Encoding.UTF8;
client.Headers.Add("Client-ID", "kimne78kx3ncx6brgo4mv6wki5h1ko");
- JObject globalCheer = JObject.Parse(client.DownloadString("https://api.twitch.tv/kraken/bits/actions?channel_id=" + channel_id));
+ GqlCheerResponse cheerResponse = JsonConvert.DeserializeObject(client.UploadString("https://gql.twitch.tv/gql", "{\"query\":\"query{cheerConfig{groups{nodes{id, prefix, tiers{bits}}, templateURL}},user(id:\\\"" + channel_id + "\\\"){cheer{cheerGroups{nodes{id,prefix,tiers{bits}},templateURL}}}}\",\"variables\":{}}"));
- foreach (JToken emoteToken in globalCheer["actions"])
+ if (cheerResponse != null && cheerResponse.data != null)
{
- string prefix = emoteToken["prefix"].ToString();
- List> tierList = new List>();
- CheerEmote newEmote = new CheerEmote() { prefix = prefix, tierList = tierList };
- foreach (JToken tierToken in emoteToken["tiers"])
+ List groupList = new List();
+
+ foreach (CheerGroup group in cheerResponse.data.cheerConfig.groups)
{
- try
+ groupList.Add(group);
+ }
+
+ if (cheerResponse.data.user != null && cheerResponse.data.user.cheer != null && cheerResponse.data.user.cheer.cheerGroups != null)
+ {
+ foreach (var group in cheerResponse.data.user.cheer.cheerGroups)
{
- int minBits = tierToken["min_bits"].ToObject();
- string fileName = Path.Combine(bitsFolder, prefix + minBits + "_2x.gif");
- byte[] finalBytes = null;
+ groupList.Add(group);
+ }
+ }
- if (File.Exists(fileName))
- {
- try
- {
- finalBytes = File.ReadAllBytes(fileName);
- }
- catch { }
- }
- if (finalBytes == null)
+ foreach (CheerGroup group in groupList)
+ {
+ string templateURL = group.templateURL;
+
+ foreach (CheerNode node in group.nodes)
+ {
+ string prefix = node.prefix;
+ List> tierList = new List>();
+ CheerEmote newEmote = new CheerEmote() { prefix = prefix, tierList = tierList };
+ foreach (Tier tier in node.tiers)
{
- byte[] bytes = client.DownloadData(tierToken["images"]["dark"]["animated"]["2"].ToString());
try
{
- File.WriteAllBytes(fileName, bytes);
- }
- catch { }
- finalBytes = bytes;
- }
+ int minBits = tier.bits;
+ string fileName = Path.Combine(bitsFolder, prefix + minBits + "_2x.gif");
+ byte[] finalBytes = null;
- if (finalBytes != null)
- {
- MemoryStream ms = new MemoryStream(finalBytes);
- TwitchEmote emote = new TwitchEmote(new List() { SKBitmap.Decode(finalBytes) }, SKCodec.Create(ms), prefix, "gif", "", 2, finalBytes);
- tierList.Add(new KeyValuePair(minBits, emote));
+ if (File.Exists(fileName))
+ {
+ try
+ {
+ finalBytes = File.ReadAllBytes(fileName);
+ }
+ catch { }
+ }
+ if (finalBytes == null)
+ {
+ string url = templateURL.Replace("PREFIX", node.prefix.ToLower()).Replace("BACKGROUND", "dark").Replace("ANIMATION", "animated").Replace("TIER", tier.bits.ToString()).Replace("SCALE.EXTENSION", "2.gif");
+ byte[] bytes = client.DownloadData(url);
+ try
+ {
+ File.WriteAllBytes(fileName, bytes);
+ }
+ catch { }
+ finalBytes = bytes;
+ }
+
+ if (finalBytes != null)
+ {
+ MemoryStream ms = new MemoryStream(finalBytes);
+ TwitchEmote emote = new TwitchEmote(new List() { SKBitmap.Decode(finalBytes) }, SKCodec.Create(ms), prefix, "gif", "", 2, finalBytes);
+ tierList.Add(new KeyValuePair(minBits, emote));
+ }
+ }
+ catch
+ { }
}
+ cheerEmotes.Add(newEmote);
}
- catch
- { }
}
- cheerEmotes.Add(newEmote);
}
}
@@ -669,11 +693,12 @@ public static string GetStreamerName(int id)
{
using (WebClient client = new WebClient())
{
- client.Headers.Add("Accept", "application/vnd.twitchtv.v5+json; charset=UTF-8");
- client.Headers.Add("Client-Id", "v8kfhyc2980it9e7t5hhc7baukzuj2");
+ client.Encoding = Encoding.UTF8;
+ client.Headers.Add("Client-ID", "kimne78kx3ncx6brgo4mv6wki5h1ko");
+
+ JObject response = JObject.Parse(client.UploadString("https://gql.twitch.tv/gql", "{\"query\":\"query{user(id:\\\"" + id.ToString() + "\\\"){login}}\",\"variables\":{}}"));
- JObject response = JObject.Parse(client.DownloadString("https://api.twitch.tv/kraken/users/" + id));
- return response["name"].ToString();
+ return response["data"]["user"]["login"].ToString();
}
}
catch { return ""; }
diff --git a/TwitchDownloaderCore/TwitchObjects/GqlCheerResponse.cs b/TwitchDownloaderCore/TwitchObjects/GqlCheerResponse.cs
new file mode 100644
index 00000000..c848fb40
--- /dev/null
+++ b/TwitchDownloaderCore/TwitchObjects/GqlCheerResponse.cs
@@ -0,0 +1,51 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace TwitchDownloaderCore.TwitchObjects
+{
+ public class Tier
+ {
+ public int bits { get; set; }
+ }
+
+ public class CheerNode
+ {
+ public string id { get; set; }
+ public string prefix { get; set; }
+ public List tiers { get; set; }
+ }
+
+ public class CheerGroup
+ {
+ public List nodes { get; set; }
+ public string templateURL { get; set; }
+ }
+
+ public class CheerConfig
+ {
+ public List groups { get; set; }
+ }
+
+ public class Cheer
+ {
+ public List cheerGroups { get; set; }
+ }
+
+ public class CheerUser
+ {
+ public Cheer cheer { get; set; }
+ }
+
+ public class CheerData
+ {
+ public CheerConfig cheerConfig { get; set; }
+ public CheerUser user { get; set; }
+ }
+
+ public class GqlCheerResponse
+ {
+ public CheerData data { get; set; }
+ public Extensions extensions { get; set; }
+ }
+}
diff --git a/TwitchDownloaderWPF/MainWindow.xaml.cs b/TwitchDownloaderWPF/MainWindow.xaml.cs
index 9d19d798..a8d090b6 100644
--- a/TwitchDownloaderWPF/MainWindow.xaml.cs
+++ b/TwitchDownloaderWPF/MainWindow.xaml.cs
@@ -79,7 +79,7 @@ private async void Window_Loaded(object sender, RoutedEventArgs e)
if (!File.Exists("ffmpeg.exe"))
await FFmpegDownloader.GetLatestVersion(FFmpegVersion.Full);
- AutoUpdater.InstalledVersion = new Version("1.40.6.0");
+ AutoUpdater.InstalledVersion = new Version("1.40.7.0");
AutoUpdater.Start("https://downloader-update.twitcharchives.workers.dev");
}