diff --git a/lib/v2/mixcloud/index.js b/lib/v2/mixcloud/index.js index b4d4e7d7b1de36..243ef3c56e477a 100644 --- a/lib/v2/mixcloud/index.js +++ b/lib/v2/mixcloud/index.js @@ -6,6 +6,7 @@ const { queries } = require('./queries'); module.exports = async (ctx) => { const host = 'https://www.mixcloud.com'; const imageBaseURL = 'https://thumbnailer.mixcloud.com/unsafe/480x480/'; + const graphqlURL = 'https://app.mixcloud.com/graphql'; const headers = { Referer: host, 'Content-Type': 'application/json', @@ -40,7 +41,6 @@ module.exports = async (ctx) => { username: ctx.params.username, }, orderBy: 'LATEST', - audioTypes: ['SHOW'], }, }, favorites: { @@ -59,37 +59,20 @@ module.exports = async (ctx) => { }, }, }, - profile: { - query: queries.profile.query, - variables: { - lookup: { - username: ctx.params.username, - }, - }, - }, }; - const profile = ( - await got({ - method: 'post', - url: `${host}/graphql`, - json: payloads.profile, - headers, - }) - ).data.data; - - const biog = profile.user.biog; - const image = `${imageBaseURL}${profile.user.picture.urlRoot}`; - const data = ( await got({ method: 'post', - url: `${host}/graphql`, + url: graphqlURL, json: payloads[type], headers, }) ).data.data; + const biog = data.user.biog; + const image = `${imageBaseURL}${data.user.picture.urlRoot}`; + // https://github.com/ytdl-org/youtube-dl/blob/f1487d4fca40fd37d735753e24a7bae53a1b1513/youtube_dl/extractor/mixcloud.py#L72-L79 const decryptionKey = 'IFYOUWANTTHEARTISTSTOGETPAIDDONOTDOWNLOADFROMMIXCLOUD'; const decryptXorCipher = (key, cipherText) => { diff --git a/lib/v2/mixcloud/queries.js b/lib/v2/mixcloud/queries.js index 72b652b705340e..2102891a8888a7 100644 --- a/lib/v2/mixcloud/queries.js +++ b/lib/v2/mixcloud/queries.js @@ -1,6 +1,8 @@ const queries = { stream: { - query: `query UserStreamQuery($lookup: UserLookup!) { + query: `query UserStreamQuery( + $lookup: UserLookup! + ) { user: userLookup(lookup: $lookup) { username ...UserStreamPage_user @@ -27,6 +29,9 @@ const queries = { username isSubscribedTo isViewer + affiliateUsers { + totalCount + } } ...AudioCardFavoriteButton_cloudcast ...AudioCardRepostButton_cloudcast @@ -176,6 +181,7 @@ const queries = { isPublic slug description + audioType picture { urlRoot } @@ -209,6 +215,28 @@ const queries = { ...AudioCardTags_cloudcast } + fragment AudioCardSubLinks_cloudcast on Cloudcast { + id + isExclusive + owner { + id + displayName + username + ...Hovercard_user + } + creatorAttributions(first: 2) { + totalCount + edges { + node { + id + displayName + username + ...Hovercard_user + } + } + } + } + fragment AudioCardTags_cloudcast on Cloudcast { tags(country: "GLOBAL") { tag { @@ -224,18 +252,20 @@ const queries = { slug name audioType + audioQuality isLiveRecording isExclusive owner { id - displayName username - ...Hovercard_user ...UserBadge_user } + creatorAttributions(first: 2) { + totalCount + } + ...AudioCardSubLinks_cloudcast ...AudioCardPlayButton_cloudcast ...ExclusiveCloudcastBadgeContainer_cloudcast - ...CloudcastHQAudio_cloudcast } fragment AudioCard_cloudcast on Cloudcast { @@ -275,10 +305,6 @@ const queries = { } } - fragment CloudcastHQAudio_cloudcast on Cloudcast { - audioQuality - } - fragment ExclusiveCloudcastBadgeContainer_cloudcast on Cloudcast { isExclusive isExclusivePreviewOnly @@ -301,6 +327,17 @@ const queries = { } } + fragment ShareAudioCardList_user on User { + biog + username + displayName + id + isUploader + picture { + urlRoot + } + } + fragment UGCImage_picture on Picture { urlRoot primaryColor @@ -316,15 +353,16 @@ const queries = { id displayName username + ...ShareAudioCardList_user stream(first: 10) { edges { - cursor repostedBy node { id ...AudioCard_cloudcast __typename } + cursor } pageInfo { endCursor @@ -341,11 +379,10 @@ const queries = { query: `query UserUploadsQuery( $lookup: UserLookup! $orderBy: CloudcastOrderByEnum - $audioTypes: [AudioTypeEnum!] ) { user: userLookup(lookup: $lookup) { username - ...UserUploadsPage_user_3HcCKF + ...UserUploadsPage_user_7FfCv id } viewer { @@ -369,6 +406,9 @@ const queries = { username isSubscribedTo isViewer + affiliateUsers { + totalCount + } } ...AudioCardFavoriteButton_cloudcast ...AudioCardRepostButton_cloudcast @@ -518,6 +558,7 @@ const queries = { isPublic slug description + audioType picture { urlRoot } @@ -551,6 +592,28 @@ const queries = { ...AudioCardTags_cloudcast } + fragment AudioCardSubLinks_cloudcast on Cloudcast { + id + isExclusive + owner { + id + displayName + username + ...Hovercard_user + } + creatorAttributions(first: 2) { + totalCount + edges { + node { + id + displayName + username + ...Hovercard_user + } + } + } + } + fragment AudioCardTags_cloudcast on Cloudcast { tags(country: "GLOBAL") { tag { @@ -566,18 +629,20 @@ const queries = { slug name audioType + audioQuality isLiveRecording isExclusive owner { id - displayName username - ...Hovercard_user ...UserBadge_user } + creatorAttributions(first: 2) { + totalCount + } + ...AudioCardSubLinks_cloudcast ...AudioCardPlayButton_cloudcast ...ExclusiveCloudcastBadgeContainer_cloudcast - ...CloudcastHQAudio_cloudcast } fragment AudioCard_cloudcast on Cloudcast { @@ -617,10 +682,6 @@ const queries = { } } - fragment CloudcastHQAudio_cloudcast on Cloudcast { - audioQuality - } - fragment ExclusiveCloudcastBadgeContainer_cloudcast on Cloudcast { isExclusive isExclusivePreviewOnly @@ -643,6 +704,17 @@ const queries = { } } + fragment ShareAudioCardList_user on User { + biog + username + displayName + id + isUploader + picture { + urlRoot + } + } + fragment UGCImage_picture on Picture { urlRoot primaryColor @@ -654,16 +726,13 @@ const queries = { hasPremiumFeatures } - fragment UserUploadsPage_user_3HcCKF on User { + fragment UserUploadsPage_user_7FfCv on User { id displayName username - uploads( - first: 10 - orderBy: $orderBy - audioTypes: $audioTypes - isPublic: true - ) { + isViewer + ...ShareAudioCardList_user + uploads(first: 10, isPublic: true, orderBy: $orderBy, audioTypes: [SHOW]) { edges { node { ...AudioCard_cloudcast @@ -684,7 +753,9 @@ const queries = { }`, }, favorites: { - query: `query UserFavoritesQuery($lookup: UserLookup!) { + query: `query UserFavoritesQuery( + $lookup: UserLookup! + ) { user: userLookup(lookup: $lookup) { username hiddenFavorites: favorites { @@ -714,6 +785,9 @@ const queries = { username isSubscribedTo isViewer + affiliateUsers { + totalCount + } } ...AudioCardFavoriteButton_cloudcast ...AudioCardRepostButton_cloudcast @@ -863,6 +937,7 @@ const queries = { isPublic slug description + audioType picture { urlRoot } @@ -896,6 +971,28 @@ const queries = { ...AudioCardTags_cloudcast } + fragment AudioCardSubLinks_cloudcast on Cloudcast { + id + isExclusive + owner { + id + displayName + username + ...Hovercard_user + } + creatorAttributions(first: 2) { + totalCount + edges { + node { + id + displayName + username + ...Hovercard_user + } + } + } + } + fragment AudioCardTags_cloudcast on Cloudcast { tags(country: "GLOBAL") { tag { @@ -911,18 +1008,20 @@ const queries = { slug name audioType + audioQuality isLiveRecording isExclusive owner { id - displayName username - ...Hovercard_user ...UserBadge_user } + creatorAttributions(first: 2) { + totalCount + } + ...AudioCardSubLinks_cloudcast ...AudioCardPlayButton_cloudcast ...ExclusiveCloudcastBadgeContainer_cloudcast - ...CloudcastHQAudio_cloudcast } fragment AudioCard_cloudcast on Cloudcast { @@ -962,10 +1061,6 @@ const queries = { } } - fragment CloudcastHQAudio_cloudcast on Cloudcast { - audioQuality - } - fragment ExclusiveCloudcastBadgeContainer_cloudcast on Cloudcast { isExclusive isExclusivePreviewOnly @@ -988,6 +1083,17 @@ const queries = { } } + fragment ShareAudioCardList_user on User { + biog + username + displayName + id + isUploader + picture { + urlRoot + } + } + fragment UGCImage_picture on Picture { urlRoot primaryColor @@ -1004,6 +1110,7 @@ const queries = { displayName username isViewer + ...ShareAudioCardList_user favorites(first: 10) { edges { node { @@ -1028,7 +1135,9 @@ const queries = { }`, }, listens: { - query: `query UserListensQuery($lookup: UserLookup!) { + query: `query UserListensQuery( + $lookup: UserLookup! + ) { user: userLookup(lookup: $lookup) { username hiddenListeningHistory: listeningHistory { @@ -1058,6 +1167,9 @@ const queries = { username isSubscribedTo isViewer + affiliateUsers { + totalCount + } } ...AudioCardFavoriteButton_cloudcast ...AudioCardRepostButton_cloudcast @@ -1207,6 +1319,7 @@ const queries = { isPublic slug description + audioType picture { urlRoot } @@ -1240,6 +1353,28 @@ const queries = { ...AudioCardTags_cloudcast } + fragment AudioCardSubLinks_cloudcast on Cloudcast { + id + isExclusive + owner { + id + displayName + username + ...Hovercard_user + } + creatorAttributions(first: 2) { + totalCount + edges { + node { + id + displayName + username + ...Hovercard_user + } + } + } + } + fragment AudioCardTags_cloudcast on Cloudcast { tags(country: "GLOBAL") { tag { @@ -1255,18 +1390,20 @@ const queries = { slug name audioType + audioQuality isLiveRecording isExclusive owner { id - displayName username - ...Hovercard_user ...UserBadge_user } + creatorAttributions(first: 2) { + totalCount + } + ...AudioCardSubLinks_cloudcast ...AudioCardPlayButton_cloudcast ...ExclusiveCloudcastBadgeContainer_cloudcast - ...CloudcastHQAudio_cloudcast } fragment AudioCard_cloudcast on Cloudcast { @@ -1306,10 +1443,6 @@ const queries = { } } - fragment CloudcastHQAudio_cloudcast on Cloudcast { - audioQuality - } - fragment ExclusiveCloudcastBadgeContainer_cloudcast on Cloudcast { isExclusive isExclusivePreviewOnly @@ -1332,6 +1465,17 @@ const queries = { } } + fragment ShareAudioCardList_user on User { + biog + username + displayName + id + isUploader + picture { + urlRoot + } + } + fragment UGCImage_picture on Picture { urlRoot primaryColor @@ -1348,10 +1492,10 @@ const queries = { isViewer displayName username + ...ShareAudioCardList_user listeningHistory(first: 10) { totalCount edges { - cursor node { id cloudcast { @@ -1360,6 +1504,7 @@ const queries = { } __typename } + cursor } pageInfo { endCursor @@ -1376,143 +1521,6 @@ const queries = { ...AudioCard_viewer }`, }, - profile: { - query: `query UserProfileHeaderQuery($lookup: UserLookup!) { - user: userLookup(lookup: $lookup) { - id - displayName - username - isBranded - isStaff - isViewer - followers { - totalCount - } - hasCoverPicture - hasPremiumFeatures - hasProFeatures - picture { - primaryColor - ...UGCImage_picture - } - coverPicture { - urlRoot - } - ...ProfileNavigation_user - ...UserBadge_user - ...ShareUserButton_user - ...ProfileRegisterUpsellComponent_user - ...FollowButton_user - } - viewer { - ...ProfileRegisterUpsellComponent_viewer - ...FollowButton_viewer - id - } - } - - fragment FollowButton_user on User { - id - isFollowed - isFollowing - isViewer - followers { - totalCount - } - username - displayName - } - - fragment FollowButton_viewer on Viewer { - me { - id - } - } - - fragment ProfileNavigation_user on User { - id - username - stream { - totalCount - } - favorites { - totalCount - } - listeningHistory { - totalCount - } - uploads(audioTypes: [SHOW]) { - totalCount - } - tracks: uploads(audioTypes: [TRACK]) { - totalCount - } - posts { - totalCount - } - profileNavigation( - showsAudioTypes: [SHOW] - tracksAudioTypes: [TRACK] - streamAudioTypes: [SHOW, TRACK] - ) { - menuItems { - __typename - ... on NavigationItemInterface { - __isNavigationItemInterface: __typename - inDropdown - } - ... on HideableNavigationItemInterface { - __isHideableNavigationItemInterface: __typename - hidden - } - ... on PlaylistNavigationItem { - count - playlist { - id - name - slug - } - } - } - } - } - - fragment ProfileRegisterUpsellComponent_user on User { - id - displayName - followers { - totalCount - } - } - - fragment ProfileRegisterUpsellComponent_viewer on Viewer { - me { - id - } - } - - fragment ShareUserButton_user on User { - biog - username - displayName - id - isUploader - picture { - urlRoot - } - } - - fragment UGCImage_picture on Picture { - urlRoot - primaryColor - } - - fragment UserBadge_user on User { - hasProFeatures - isStaff - hasPremiumFeatures - }`, - }, }; module.exports = {