TTKMusicPlayer  4.3.0.0
TTKMusicPlayer imitates Kugou UI, the music player uses of qmmp core library based on Qt for windows and linux
musickgqueryinterface.cpp
Go to the documentation of this file.
3 
4 static constexpr const char *KG_UA_URL = "cGhYNDZVdmNaVG5KZk50NVFvcUJyYWVQdmdNTkFTMmM=";
5 static constexpr const char *KG_COOKIE_URL = "M1BlYjdvWUlwdHJIYXgzeGpUVDlWbnB6ZGZPaUxWVzhKdEZ2RHBHR1RBckFUbG82ZzlOOHRnMW0wUUZpVmdDNGNQMFFjTXd1OVhidmwvdHh6NjNkZ08reXEzWUl0ZXl3d21Ka3ErM1Q1eEp3WUs0YkYvV3dWVUFDSVd3YmI3c3U3c09pZTlIM1FQRFUyMG43Z2ZqRXJVTHhubkhjRC9EN3hVbzhia1QzdUZQU3orRzZZRmRncGZLazhkMD0=";
6 
7 static constexpr const char *KG_SONG_PATH_V1_URL = "c0FiK1UzOWFtRGNobi9oYlo1WmpEbWUwRzR0UStHd1lkZFFRakxkSGlMZmpHMmoxOWc4NGtGa3NJRUtiVXJEYlJqYzNYNmRHNlZ0dUZIR05Rb0RZcUgyb2lFMm5pNU9KaDhMeHNkQnJzcWJqeHhwQWdpUXBPV1ZEQ05RT0kvNE5IWG9qZ2hYYk9BMG8yQ25qbzFYUGFYeUVMWVk9";
8 static constexpr const char *KG_SONG_PATH_V2_URL = "Q3dWL3pJbVlWTDY1Nk0vT3BkYWNGNC9ObWEyVmtyQ3lqVFlUZjE1VjU2V0ZhZFN2L1hFUXlob1JxM2Zjak9KcjBPZGE1QkxQRlhUaFpEMWxQNDMzbmdjWG5kMVNxRy9zR0tvVXB5SDlZUHl1OVUzaGlVM2NHUTBTY0l4cG1GNjY0alYzdmI5eU1ldXB2KzFzU2JHMkgrTHdxaUdSL3pwY0o1bk9kSk1GcG4yK2JVSndqUFRYNXRTbkk5VHBQcVM0Y256ZElxV1BCcy80NGpXaXNvWWZvQT09";
9 static constexpr const char *KG_SONG_PATH_V3_URL = "b1VyUUJFN3l5RG0wZkhxZ2RHazUyRDVraGNXK21oODUvVWZCUHJ0TWx0VFJsdEwyemdzd0JmdnFRNFJQRitRb1NIVkZuTWZmUjlya2UrWi9pQ0Z0MjVFV2FZU1lDU3lieXBOb0RaVXVVcU5DR0xEYlQySXFHbXhKWjZ5ZkFuOEJmNzdGQ0tTNVFGMkg3eldDR3VqOUUxQWJKNzh6YWZPZzkyYUtKeFNORnB6bVlzZ1grYWduWXNBN1BDdENrb0ZEMklhSDVacmhBNkZiRWFPUDh6VXFIcnMzQUZqY0FYaG5ZbytGZkJUTnpJNTlLRHVZZitkYVlDVXR3Slh5U1IrSU9TbmF5TUxJZ0dJeGRxL0EwaDB2Qm1RUnBnTHM2bVdFQUsyRzZqeC83bTBjQ1RsSlB3dEVLcFlqdUU2c095aGN1cVJhR1E9PQ==";
10 static constexpr const char *KG_SONG_PATH_V3_DATA_URL = "V1RsSGgvREcwWDBLNGdHeE5weEdoRWZCYVFhL2RlZDRBTUcxQXJqZlFIRXhsQzkzaldUclNodG1kSDJtekJXSjVlVGtEYUU1bkxYcTBrRjM1dHd0dFhhM2ZZd1B4N255Wk5MYWRBTWQwclF2dEIwenlLcFNVSXZGY1RZRXNVcDcwSUdJaVlQNmh1RnNQQVpMTVRrZ003YmI4RmcwTS9Jc1lFZ2VvbnFNYU1ZN0RMUVNwVkFoZFhsOVk1UXJGanpNbUpZWmpjdlZUQjlVc3FraENVMGF4SFIvOEVSS0o4ZVBEWC9iME52Q3lWNDdKYTFadXlCQ20rM0JueWtZVjBCZGdtM2NMakRSQzl3YlZRZEFPQnRvZEU3aHhiVnZ0aEJNemtUWWE5amFOaVk3RVBGdFBkSzRPQTRsYklZYTltNy9rRUNVc3dMZmI4WT0=";
11 static constexpr const char *KG_ALBUM_INFO_URL = "ejhjT0JOd0RyMWtmaTdTa2x4REdsMXlucDkyYk8wT3RTZ21DOVVTeU15MFQ1Z1k0SVJ6bHdiY2hNVURKRE91NGdWSWc2NTJNZEsyNnF0b0YrK0E0TSs3UjRKam40VmhqM0JxTWI1dmtyR1ZQWk1tOGFnR1NGcnAzVzJ4M3dvZWU2YlhMR0IvZWVSND0=";
12 
13 void ReqKGInterface::makeRequestRawHeader(QNetworkRequest *request) noexcept
14 {
15  request->setRawHeader("User-Agent", TTK::Algorithm::mdII(KG_UA_URL, MDII_UA_KEY, false).toUtf8());
16  request->setRawHeader("Cookie", TTK::Algorithm::mdII(KG_COOKIE_URL, false).toUtf8());
17 
18  TTK::setSslConfiguration(request);
20 }
21 
22 QString ReqKGInterface::makeSongArtist(const QString &name)
23 {
24  return TTK::String::charactersReplace(name).replace("+", ";");
25 }
26 
27 QString ReqKGInterface::makeSongArtist(const QString &in, const QString &name)
28 {
29  const QString &artistName = TTK::String::charactersReplace(name);
30  return in.isEmpty() ? artistName : (in + ";" + artistName);
31 }
32 
34 {
35  if(info->m_songId.isEmpty())
36  {
37  return;
38  }
39 
40  QNetworkRequest request;
41  request.setUrl(TTK::Algorithm::mdII(KG_SONG_INFO_URL, false).arg(info->m_songId));
43 
44  const QByteArray &bytes = TTK::syncNetworkQueryForGet(&request);
45  if(bytes.isEmpty())
46  {
47  return;
48  }
49 
50  QJsonParseError ok;
51  const QJsonDocument &json = QJsonDocument::fromJson(bytes, &ok);
53  {
54  QVariantMap value = json.toVariant().toMap();
55  if(value["errcode"].toInt() == 0 && value.contains("data"))
56  {
57  value = value["data"].toMap();
58  info->m_songName = TTK::String::charactersReplace(value["songname"].toString());
59  info->m_artistId = value["singerid"].toString();
60  info->m_artistName = ReqKGInterface::makeSongArtist(value["singername"].toString());
61  info->m_coverUrl = value["imgurl"].toString().replace("{size}", "500");
62  info->m_lrcUrl = TTK::Algorithm::mdII(KG_SONG_LRC_URL, false).arg(value["songname"].toString(), info->m_songId).arg(value["duration"].toInt() * TTK_DN_S2MS);
63  }
64  }
65 }
66 
68 {
69  if(album.isEmpty())
70  {
71  return;
72  }
73 
75  parseFromSongAlbumInfo(&item, info->m_songId, album);
76 
77  info->m_albumId = item.m_id;
78  info->m_albumName = item.m_name;
79  info->m_year = item.m_time.section(TTK_DEFAULT_STR, 0, 0);
80 }
81 
82 void ReqKGInterface::parseFromSongAlbumInfo(MusicResultDataItem *item, const QString &hash, const QString &album)
83 {
84  if(hash.isEmpty() || album.isEmpty())
85  {
86  return;
87  }
88 
89  QNetworkRequest request;
90  request.setUrl(TTK::Algorithm::mdII(KG_ALBUM_INFO_URL, false).arg(hash, album));
92 
93  const QByteArray &bytes = TTK::syncNetworkQueryForGet(&request);
94  if(bytes.isEmpty())
95  {
96  return;
97  }
98 
99  QJsonParseError ok;
100  const QJsonDocument &json = QJsonDocument::fromJson(bytes, &ok);
102  {
103  QVariantMap value = json.toVariant().toMap();
104  if(value["error_code"].toInt() == 0 && value.contains("data"))
105  {
106  QVariantList datas = value["data"].toList();
107  for(const QVariant &var : qAsConst(datas))
108  {
109  if(var.isNull())
110  {
111  continue;
112  }
113 
114  for(const QVariant &al : var.toList())
115  {
116  if(al.isNull())
117  {
118  continue;
119  }
120 
121  value = al.toMap();
122  item->m_id = value["album_id"].toString();
123  item->m_name = TTK::String::charactersReplace(value["album_name"].toString());
124  item->m_description = value["publish_company"].toString();
125  item->m_time = value["publish_date"].toString();
126  item->m_category = value["language"].toString();
127  break;
128  }
129  }
130  }
131  }
132 }
133 
134 static void parseSongPropertyV1(TTK::MusicSongInformation *info, const QString &hash, int bitrate)
135 {
136  for(const TTK::MusicSongProperty &prop : qAsConst(info->m_songProps))
137  {
138  if(prop.m_bitrate == bitrate)
139  {
140  return;
141  }
142  }
143 
144  TTK_INFO_STREAM("parse song" << bitrate << "kbps property in v1 module");
145 
146  const QByteArray &key = TTK::Algorithm::md5(QString("%1kgcloudv2").arg(hash).toUtf8());
147 
148  QNetworkRequest request;
149  request.setUrl(TTK::Algorithm::mdII(KG_SONG_PATH_V1_URL, false).arg(hash, key.constData()));
151 
152  const QByteArray &bytes = TTK::syncNetworkQueryForGet(&request);
153  if(!bytes.isEmpty())
154  {
155  QJsonParseError ok;
156  const QJsonDocument &json = QJsonDocument::fromJson(bytes, &ok);
158  {
159  const QVariantMap &value = json.toVariant().toMap();
160  if(value.contains("status") && value["status"].toInt() == 1)
161  {
163  prop.m_url = value["url"].toString();
164  prop.m_size = TTK::Number::sizeByteToLabel(value["fileSize"].toInt());
165  prop.m_format = value["extName"].toString();
166  prop.m_bitrate = bitrate;
167  info->m_songProps.append(prop);
168  }
169  }
170  }
171 }
172 
173 static void parseSongPropertyV2(TTK::MusicSongInformation *info, const QString &hash, int bitrate)
174 {
175  for(const TTK::MusicSongProperty &prop : qAsConst(info->m_songProps))
176  {
177  if(prop.m_bitrate == bitrate)
178  {
179  return;
180  }
181  }
182 
183  TTK_INFO_STREAM("parse song" << bitrate << "kbps property in v2 module");
184 
185  const QString &mid = TTK::Algorithm::mdII("Wk51dktMOHJXUTdmM1VsVUVXTFM5RTlYQ05laDE0Z2lZMzFPL1M1VUJSaHd1N0kwRDQxdkpWVFJPZTQ9", false);
186  const QString &sign = TTK::Algorithm::mdII("SVhlNmFTaWpqdVhYVTAwaHh4QllwRkFGSmJpY0VSZUhXQmQrV2Q4WHo0eXVCWm1zK1p0RkVRPT0=", false);
187  const QString &user = "0";
188  const QByteArray &key = TTK::Algorithm::md5((hash + sign + mid + user).toUtf8());
189 
190  QNetworkRequest request;
191  request.setUrl(TTK::Algorithm::mdII(KG_SONG_PATH_V2_URL, false).arg(mid, hash, user, key.constData()));
192  request.setRawHeader("x-router", TTK::Algorithm::mdII("MTJnUGtpL0hqWXhZQmlCNE9hVzVyREF0QXZmeVBNNVc=", false).toUtf8());
194 
195  const QByteArray &bytes = TTK::syncNetworkQueryForGet(&request);
196  if(!bytes.isEmpty())
197  {
198  QJsonParseError ok;
199  const QJsonDocument &json = QJsonDocument::fromJson(bytes, &ok);
201  {
202  const QVariantMap &value = json.toVariant().toMap();
203  if(value.contains("status") && value["status"].toInt() == 1)
204  {
205  const QVariantList &datas = value["url"].toList();
206  if(!datas.isEmpty())
207  {
209  prop.m_url = datas.first().toString();
210  prop.m_size = TTK::Number::sizeByteToLabel(value["fileSize"].toInt());
211  prop.m_format = value["extName"].toString();
212  prop.m_bitrate = bitrate;
213  info->m_songProps.append(prop);
214  }
215  }
216  }
217  }
218 }
219 
220 static void parseSongPropertyV3(TTK::MusicSongInformation *info, const QString &module, QString &id, int bitrate)
221 {
222  const qint64 time = TTKDateTime::currentTimestamp();
223  const QByteArray &key = TTK::Algorithm::md5(TTK::Algorithm::mdII(KG_SONG_PATH_V3_DATA_URL, false).arg(time).arg(module).toUtf8());
224 
225  QNetworkRequest request;
226  request.setUrl(TTK::Algorithm::mdII(KG_SONG_PATH_V3_URL, false).arg(time).arg(module, key.constData()));
228 
229  const QByteArray &bytes = TTK::syncNetworkQueryForGet(&request);
230  if(!bytes.isEmpty())
231  {
232  QJsonParseError ok;
233  const QJsonDocument &json = QJsonDocument::fromJson(bytes, &ok);
235  {
236  QVariantMap value = json.toVariant().toMap();
237  if(value.contains("data") && value["err_code"].toInt() == 0)
238  {
239  value = value["data"].toMap();
240  id = value["encode_album_audio_id"].toString();
241 
242  const int rate = value["bitrate"].toInt();
243  const QString &url = value["play_url"].toString();
244 
245  if(rate == bitrate && !url.isEmpty())
246  {
248  prop.m_url = url;
249  prop.m_size = TTK::Number::sizeByteToLabel(value["filesize"].toInt());
251  prop.m_bitrate = bitrate;
252  info->m_songProps.append(prop);
253  }
254  }
255  }
256  }
257 }
258 
259 static void parseSongPropertyV3(TTK::MusicSongInformation *info, const QString &hash, int bitrate)
260 {
261  for(const TTK::MusicSongProperty &prop : qAsConst(info->m_songProps))
262  {
263  if(prop.m_bitrate == bitrate)
264  {
265  return;
266  }
267  }
268 
269  TTK_INFO_STREAM("parse song" << bitrate << "kbps property in v3 module");
270 
271  QString id;
272  parseSongPropertyV3(info, "hash=" + hash, id, bitrate);
273 
274  if(!id.isEmpty())
275  {
276  parseSongPropertyV3(info, "encode_album_audio_id=" + id, id, bitrate);
277  }
278 }
279 
280 static void parseSongPropertyUnity(TTK::MusicSongInformation *info, const QString &hash, int bitrate)
281 {
282  for(const TTK::MusicSongProperty &prop : qAsConst(info->m_songProps))
283  {
284  if(prop.m_bitrate == bitrate)
285  {
286  return;
287  }
288  }
289 
290  TTK_INFO_STREAM("parse song" << bitrate << "kbps property in unity module");
291 
292  if(bitrate == TTK_BN_128 || bitrate == TTK_BN_320 || bitrate == TTK_BN_1000)
293  {
295  }
296 }
297 
298 static void parseSongProperty(TTK::MusicSongInformation *info, const QString &hash, int bitrate)
299 {
300  if(hash.isEmpty())
301  {
302  return;
303  }
304 
306  {
307  parseSongPropertyUnity(info, hash, bitrate);
308  parseSongPropertyV1(info, hash, bitrate);
309  parseSongPropertyV2(info, hash, bitrate);
310  parseSongPropertyV3(info, hash, bitrate);
311  }
312  else
313  {
314  parseSongPropertyV1(info, hash, bitrate);
315  parseSongPropertyV2(info, hash, bitrate);
316  parseSongPropertyV3(info, hash, bitrate);
317  parseSongPropertyUnity(info, hash, bitrate);
318  }
319 }
320 
322 {
323  const QStringList &formats = info->m_formatProps.split("|");
324  if(info->m_formatProps.isEmpty() || formats.count() < 4)
325  {
326  parseSongProperty(info, info->m_songId, TTK_BN_128);
327  return;
328  }
329 
330  if(bitrate == TTK_BN_0)
331  {
332  parseSongProperty(info, formats[0], TTK_BN_128);
333  parseSongProperty(info, formats[1], TTK_BN_192);
334  parseSongProperty(info, formats[2], TTK_BN_320);
335  parseSongProperty(info, formats[3], TTK_BN_1000);
336  }
337  else
338  {
339  int index = 0;
340  switch(bitrate)
341  {
342  case TTK_BN_128: index = 0; break;
343  case TTK_BN_192: index = 1; break;
344  case TTK_BN_320: index = 2; break;
345  case TTK_BN_1000: index = 3; break;
346  }
347 
348  parseSongProperty(info, formats[index], bitrate);
349  }
350 }
351 
353 {
354  info->m_formatProps = key["hash"].toString() + "|" + key["128hash"].toString() + "|" + key["320hash"].toString() + "|" + key["sqhash"].toString();
355 }
TTK_MODULE_EXPORT QString charactersReplace(const QString &value)
static void parseSongPropertyV2(TTK::MusicSongInformation *info, const QString &hash, int bitrate)
The class of the search result data item.
static constexpr const char * KG_SONG_INFO_URL
TTK_MODULE_EXPORT void setSslConfiguration(QNetworkRequest *request, QSslSocket::PeerVerifyMode mode=QSslSocket::VerifyNone) noexcept
static constexpr const char * KG_SONG_PATH_V1_URL
#define TTK_DEFAULT_STR
Definition: ttkglobal.h:276
static qint64 currentTimestamp() noexcept
Definition: ttktime.cpp:249
QVariant toVariant() const
static constexpr const char * KG_SONG_PATH_V3_DATA_URL
The class of the music song property.
Definition: musicobject.h:242
static QJsonDocument fromJson(const QByteArray &json, QJsonParseError *error=0)
static constexpr const char * QUERY_KG_INTERFACE
MusicSongPropertyList m_songProps
Definition: musicobject.h:314
QString makeSongArtist(const QString &name)
TTK_MODULE_EXPORT QString sizeByteToLabel(qint64 size)
TTK_MODULE_EXPORT QByteArray syncNetworkQueryForGet(QNetworkRequest *request)
#define TTK_BN_1000
Definition: ttkglobal.h:434
#define MP3_FILE_SUFFIX
Definition: musicobject.h:58
TTK_MODULE_EXPORT QByteArray md5(const QByteArray &data, bool base64=false)
static constexpr const char * KG_SONG_PATH_V3_URL
static void parseSongPropertyUnity(TTK::MusicSongInformation *info, const QString &hash, int bitrate)
static constexpr const char * MDII_UA_KEY
ParseError error
#define qAsConst
Definition: ttkqtglobal.h:57
const char * name
Definition: http_parser.c:458
static void parseSongProperty(TTK::MusicSongInformation *info, const QString &hash, int bitrate)
static constexpr const char * KG_SONG_PATH_V2_URL
#define TTK_INFO_STREAM(msg)
Definition: ttklogger.h:74
static void parseSongPropertyV1(TTK::MusicSongInformation *info, const QString &hash, int bitrate)
static constexpr wchar_t key[]
static constexpr const char * KG_SONG_LRC_URL
TTK_MODULE_EXPORT void setContentTypeHeader(QNetworkRequest *request, const QByteArray &data={}) noexcept
#define TTK_BN_0
Definition: ttkglobal.h:424
#define TTK_BN_320
Definition: ttkglobal.h:431
static constexpr const char * KG_ALBUM_INFO_URL
static constexpr const char * KG_COOKIE_URL
TTK_MODULE_EXPORT QString toString(Record type) noexcept
#define TTK_DN_S2MS
Definition: ttkglobal.h:355
void parseFromSongAlbumLrc(TTK::MusicSongInformation *info)
void parseFromSongAlbumInfo(TTK::MusicSongInformation *info, const QString &album)
#define TTK_BN_192
Definition: ttkglobal.h:429
#define FLAC_FILE_SUFFIX
Definition: musicobject.h:60
void parseFromSongProperty(TTK::MusicSongInformation *info, const QString &type, const QString &id, int bitrate)
void parseFromSongProperty(TTK::MusicSongInformation *info, int bitrate)
void makeRequestRawHeader(QNetworkRequest *request) noexcept
TTK_MODULE_EXPORT QString mdII(const QString &data, bool encode)
static void parseSongPropertyV3(TTK::MusicSongInformation *info, const QString &module, QString &id, int bitrate)
The class of the music song information.
Definition: musicobject.h:300
static constexpr const char * KG_UA_URL
#define TTK_BN_128
Definition: ttkglobal.h:428
#define G_SETTING_PTR