TTKMusicPlayer  4.2.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 void ReqKGInterface::makeRequestRawHeader(QNetworkRequest *request) noexcept
8 {
9  request->setRawHeader("User-Agent", TTK::Algorithm::mdII(KG_UA_URL, MDII_UA_KEY, false).toUtf8());
10  request->setRawHeader("Cookie", TTK::Algorithm::mdII(KG_COOKIE_URL, false).toUtf8());
11 
12  TTK::setSslConfiguration(request);
14 }
15 
16 QString ReqKGInterface::makeSongArtist(const QString &name)
17 {
18  return TTK::String::charactersReplace(name).replace("+", ";");
19 }
20 
22 {
23  if(info->m_songId.isEmpty())
24  {
25  return;
26  }
27 
28  QNetworkRequest request;
29  request.setUrl(TTK::Algorithm::mdII(KG_SONG_INFO_URL, false).arg(info->m_songId));
31 
32  const QByteArray &bytes = TTK::syncNetworkQueryForGet(&request);
33  if(bytes.isEmpty())
34  {
35  return;
36  }
37 
38  QJsonParseError ok;
39  const QJsonDocument &json = QJsonDocument::fromJson(bytes, &ok);
41  {
42  QVariantMap value = json.toVariant().toMap();
43  if(value["errcode"].toInt() == 0 && value.contains("data"))
44  {
45  value = value["data"].toMap();
46  info->m_songName = TTK::String::charactersReplace(value["songname"].toString());
47  info->m_artistId = value["singerid"].toString();
48  info->m_artistName = ReqKGInterface::makeSongArtist(value["singername"].toString());
49  info->m_coverUrl = value["imgurl"].toString().replace("{size}", "480");
50  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);
51  }
52  }
53 }
54 
56 {
57  if(album.isEmpty())
58  {
59  return;
60  }
61 
63  parseFromSongAlbumInfo(&item, info->m_songId, album);
64 
65  info->m_albumId = item.m_id;
66  info->m_albumName = item.m_name;
67 }
68 
69 void ReqKGInterface::parseFromSongAlbumInfo(MusicResultDataItem *item, const QString &hash, const QString &album)
70 {
71  if(hash.isEmpty() || album.isEmpty())
72  {
73  return;
74  }
75 
76  QNetworkRequest request;
77  request.setUrl(TTK::Algorithm::mdII(KG_ALBUM_INFO_URL, false).arg(hash, album));
79 
80  const QByteArray &bytes = TTK::syncNetworkQueryForGet(&request);
81  if(bytes.isEmpty())
82  {
83  return;
84  }
85 
86  QJsonParseError ok;
87  const QJsonDocument &json = QJsonDocument::fromJson(bytes, &ok);
89  {
90  QVariantMap value = json.toVariant().toMap();
91  if(value["error_code"].toInt() == 0 && value.contains("data"))
92  {
93  QVariantList datas = value["data"].toList();
94  for(const QVariant &var : qAsConst(datas))
95  {
96  if(var.isNull())
97  {
98  continue;
99  }
100 
101  for(const QVariant &al : var.toList())
102  {
103  if(al.isNull())
104  {
105  continue;
106  }
107 
108  value = al.toMap();
109  item->m_id = value["album_id"].toString();
110  item->m_name = TTK::String::charactersReplace(value["album_name"].toString());
111  item->m_description = value["publish_company"].toString();
112  item->m_time = value["publish_date"].toString();
113  item->m_category = value["language"].toString();
114  break;
115  }
116  }
117  }
118  }
119 }
120 
121 static void parseSongPropertyV1(TTK::MusicSongInformation *info, const QString &hash, int bitrate)
122 {
123  for(const TTK::MusicSongProperty &prop : qAsConst(info->m_songProps))
124  {
125  if(prop.m_bitrate == bitrate)
126  {
127  return;
128  }
129  }
130 
131  TTK_INFO_STREAM("parse song" << bitrate << "kbps property in v1 module");
132 
133  const QByteArray &key = TTK::Algorithm::md5(QString("%1kgcloudv2").arg(hash).toUtf8());
134 
135  QNetworkRequest request;
136  request.setUrl(TTK::Algorithm::mdII(KG_SONG_PATH_V1_URL, false).arg(hash, key.constData()));
138 
139  const QByteArray &bytes = TTK::syncNetworkQueryForGet(&request);
140  if(!bytes.isEmpty())
141  {
142  QJsonParseError ok;
143  const QJsonDocument &json = QJsonDocument::fromJson(bytes, &ok);
145  {
146  const QVariantMap &value = json.toVariant().toMap();
147  if(value.contains("status") && value["status"].toInt() == 1)
148  {
150  prop.m_url = value["url"].toString();
151  prop.m_size = TTK::Number::sizeByteToLabel(value["fileSize"].toInt());
152  prop.m_format = value["extName"].toString();
153  prop.m_bitrate = bitrate;
154  info->m_songProps.append(prop);
155  }
156  }
157  }
158 }
159 
160 static void parseSongPropertyV2(TTK::MusicSongInformation *info, const QString &hash, int bitrate)
161 {
162  for(const TTK::MusicSongProperty &prop : qAsConst(info->m_songProps))
163  {
164  if(prop.m_bitrate == bitrate)
165  {
166  return;
167  }
168  }
169 
170  TTK_INFO_STREAM("parse song" << bitrate << "kbps property in v2 module");
171 
172  const QString &mid = TTK::Algorithm::mdII("Wk51dktMOHJXUTdmM1VsVUVXTFM5RTlYQ05laDE0Z2lZMzFPL1M1VUJSaHd1N0kwRDQxdkpWVFJPZTQ9", false);
173  const QString &sign = TTK::Algorithm::mdII("SVhlNmFTaWpqdVhYVTAwaHh4QllwRkFGSmJpY0VSZUhXQmQrV2Q4WHo0eXVCWm1zK1p0RkVRPT0=", false);
174  const QString &user = "0";
175  const QByteArray &key = TTK::Algorithm::md5((hash + sign + mid + user).toUtf8());
176 
177  QNetworkRequest request;
178  request.setUrl(TTK::Algorithm::mdII(KG_SONG_PATH_V2_URL, false).arg(mid, hash, user, key.constData()));
179  request.setRawHeader("x-router", TTK::Algorithm::mdII("MTJnUGtpL0hqWXhZQmlCNE9hVzVyREF0QXZmeVBNNVc=", false).toUtf8());
181 
182  const QByteArray &bytes = TTK::syncNetworkQueryForGet(&request);
183  if(!bytes.isEmpty())
184  {
185  QJsonParseError ok;
186  const QJsonDocument &json = QJsonDocument::fromJson(bytes, &ok);
188  {
189  const QVariantMap &value = json.toVariant().toMap();
190  if(value.contains("status") && value["status"].toInt() == 1)
191  {
192  const QVariantList &datas = value["url"].toList();
193  if(!datas.isEmpty())
194  {
196  prop.m_url = datas.front().toString();
197  prop.m_size = TTK::Number::sizeByteToLabel(value["fileSize"].toInt());
198  prop.m_format = value["extName"].toString();
199  prop.m_bitrate = bitrate;
200  info->m_songProps.append(prop);
201  }
202  }
203  }
204  }
205 }
206 
207 static void parseSongPropertyV3(TTK::MusicSongInformation *info, const QString &module, QString &id, int bitrate)
208 {
209  const qint64 time = TTKDateTime::currentTimestamp();
210  const QByteArray &key = TTK::Algorithm::md5(TTK::Algorithm::mdII(KG_SONG_PATH_V3_DATA_URL, false).arg(time).arg(module).toUtf8());
211 
212  QNetworkRequest request;
213  request.setUrl(TTK::Algorithm::mdII(KG_SONG_PATH_V3_URL, false).arg(time).arg(module, key.constData()));
215 
216  const QByteArray &bytes = TTK::syncNetworkQueryForGet(&request);
217  if(!bytes.isEmpty())
218  {
219  QJsonParseError ok;
220  const QJsonDocument &json = QJsonDocument::fromJson(bytes, &ok);
222  {
223  QVariantMap value = json.toVariant().toMap();
224  if(value.contains("data") && value["err_code"].toInt() == 0)
225  {
226  value = value["data"].toMap();
227  id = value["encode_album_audio_id"].toString();
228 
229  const int rate = value["bitrate"].toInt();
230  const QString &url = value["play_url"].toString();
231 
232  if(rate == bitrate && !url.isEmpty())
233  {
235  prop.m_url = url;
236  prop.m_size = TTK::Number::sizeByteToLabel(value["filesize"].toInt());
237  prop.m_format = bitrate > TTK_BN_320 ? FLAC_FILE_SUFFIX : MP3_FILE_SUFFIX;;
238  prop.m_bitrate = bitrate;
239  info->m_songProps.append(prop);
240  }
241  }
242  }
243  }
244 }
245 
246 static void parseSongPropertyV3(TTK::MusicSongInformation *info, const QString &hash, int bitrate)
247 {
248  for(const TTK::MusicSongProperty &prop : qAsConst(info->m_songProps))
249  {
250  if(prop.m_bitrate == bitrate)
251  {
252  return;
253  }
254  }
255 
256  TTK_INFO_STREAM("parse song" << bitrate << "kbps property in v3 module");
257 
258  QString id;
259  parseSongPropertyV3(info, "hash=" + hash, id, bitrate);
260 
261  if(!id.isEmpty())
262  {
263  parseSongPropertyV3(info, "encode_album_audio_id=" + id, id, bitrate);
264  }
265 }
266 
267 static void parseSongPropertyV4(TTK::MusicSongInformation *info, const QString &hash, int bitrate)
268 {
269  for(const TTK::MusicSongProperty &prop : qAsConst(info->m_songProps))
270  {
271  if(prop.m_bitrate == bitrate)
272  {
273  return;
274  }
275  }
276 
277  TTK_INFO_STREAM("parse song" << bitrate << "kbps property in v4 module");
278 
279  if(bitrate == TTK_BN_128 || bitrate == TTK_BN_320 || bitrate == TTK_BN_1000)
280  {
282  }
283 }
284 
285 static void parseSongProperty(TTK::MusicSongInformation *info, const QString &hash, int bitrate)
286 {
287  if(hash.isEmpty())
288  {
289  return;
290  }
291 
292  parseSongPropertyV1(info, hash, bitrate);
293  parseSongPropertyV2(info, hash, bitrate);
294  parseSongPropertyV3(info, hash, bitrate);
295  parseSongPropertyV4(info, hash, bitrate);
296 }
297 
299 {
300  const QStringList &formats = info->m_formatProps.split("|");
301  if(info->m_formatProps.isEmpty() || formats.count() < 4)
302  {
303  parseSongProperty(info, info->m_songId, TTK_BN_128);
304  return;
305  }
306 
307  if(bitrate == TTK_BN_0)
308  {
309  parseSongProperty(info, formats[0], TTK_BN_128);
310  parseSongProperty(info, formats[1], TTK_BN_192);
311  parseSongProperty(info, formats[2], TTK_BN_320);
312  parseSongProperty(info, formats[3], TTK_BN_1000);
313  }
314  else
315  {
316  int index = 0;
317  switch(bitrate)
318  {
319  case TTK_BN_128: index = 0; break;
320  case TTK_BN_192: index = 1; break;
321  case TTK_BN_320: index = 2; break;
322  case TTK_BN_1000: index = 3; break;
323  }
324 
325  parseSongProperty(info, formats[index], bitrate);
326  }
327 }
328 
330 {
331  info->m_formatProps = key["hash"].toString() + "|" + key["128hash"].toString() + "|" + key["320hash"].toString() + "|" + key["sqhash"].toString();
332 }
TTK_MODULE_EXPORT QString charactersReplace(const QString &value)
static void parseSongPropertyV2(TTK::MusicSongInformation *info, const QString &hash, int bitrate)
TTK_MODULE_EXPORT QByteArray md5(const QByteArray &data)
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 qint64 currentTimestamp() noexcept
Definition: ttktime.cpp:249
QVariant toVariant() const
The class of the music song property.
Definition: musicobject.h:237
static QJsonDocument fromJson(const QByteArray &json, QJsonParseError *error=0)
static constexpr const char * QUERY_KG_INTERFACE
static constexpr const char * KG_SONG_PATH_V3_URL
MusicSongPropertyList m_songProps
Definition: musicobject.h:309
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
static constexpr const char * KG_SONG_PATH_V3_DATA_URL
#define MP3_FILE_SUFFIX
Definition: musicobject.h:57
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)
TTK_MODULE_EXPORT void makeContentTypeHeader(QNetworkRequest *request, const QByteArray &data={}) noexcept
#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
static void parseSongPropertyV4(TTK::MusicSongInformation *info, const QString &hash, int bitrate)
#define TTK_BN_0
Definition: ttkglobal.h:424
#define TTK_BN_320
Definition: ttkglobal.h:431
static constexpr const char * KG_COOKIE_URL
TTK_MODULE_EXPORT QString toString(Record type) noexcept
#define TTK_DN_S2MS
Definition: ttkglobal.h:355
static constexpr const char * KG_SONG_PATH_V2_URL
static constexpr const char * KG_ALBUM_INFO_URL
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:59
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)
static constexpr const char * KG_SONG_PATH_V1_URL
The class of the music song information.
Definition: musicobject.h:295
static constexpr const char * KG_UA_URL
#define TTK_BN_128
Definition: ttkglobal.h:428