ciricc / easyvk

This app helps you create an apps with vk api easy!
MIT License
101 stars 10 forks source link

Просто дополнения к Audio API #9

Closed PurpleHorrorRus closed 5 years ago

PurpleHorrorRus commented 5 years ago

Привет. Дополнил Audio API новыми фичами и думаю, они будут не лишними. Для начала http.js: Нужно добавить строку в request[method], чтобы возвращать DOM. Это понадобится в будущем:

request[method](requestParams, (err, res, vkr) => {
        if(form.retOnlyBody) return resolve(res);
        ...
})

AudioAPI.js Переключение аудиостатуса у пользователя

toggleAudioStatus (params = {}) {
    let self = this;

    return new Promise((resolve, reject) => {
      self._request({
        retOnlyBody: true
      }).then(res => {
        res.body = encoding.convert(res.body, 'utf-8', 'windows-1251').toString()
        let matches = res.body.split("statusExportHash: ")[1];
        let statusExportHash = matches.split(",")[0].replace("'", "").replace("'", "");
        console.log(statusExportHash);
        return new Promise((resolve, reject) => {
            self._request({
            act: "toggle_status",
            al: 1,
            exp: params.enable,
            hash: statusExportHash,
            id: params.id,
            oid: params.oid,
            top: 0
          }).then(res => {}).catch(e => {});
        });
      });
    });
  }

Смена аудио в статусе пользователя:

changeAudioStatus (params = {}) {
    let self = this;

    self._request({
      retOnlyBody: true
    }).then(res => {
      res.body = encoding.convert(res.body, 'utf-8', 'windows-1251').toString()
      let matches = res.body.split("statusExportHash: ")[1];
      let statusExportHash = matches.split(",")[0].replace("'", "").replace("'", "");
      console.log(statusExportHash);
      return new Promise((resolve, reject) => {
        self._request({
          act: "audio_status",
          al: 1,
          hash: statusExportHash,
          full_id: params.id,
          top: 0
        }).then(res => {}).catch(e => {});
      });
    });
  }

Рекомендации для юзера:

getRecoms (params = {}) {
    let self = this;

    return new Promise((resolve, reject) => {
      let uid = self._vk.session.user_id
      if (params.owner_id) {
        params.owner_id = Number(params.owner_id)
      } else if (uid) { params.owner_id = uid }
      self._request({
        act: 'section',
        al: 1,
        owner_id: uid,
        section: "recoms"
      }).then(res => {
        res.body = encoding.convert(res.body, 'utf-8', 'windows-1251').toString()
        let json = self._parseJSON(res.body, reject);

        let id = json.playlists[0].id.replace("recoms", "");

        return resolve(new Promise((resolve, reject) => {
          self._request({
            act: 'load_section',
            al: 1,
            claim: 0,
            offset: 0,
            owner_id: uid,
            playlist_id: `recoms${id}`,
            type: 'recoms',
            track_type: 'default'
          }).then(res => {
            res.body = encoding.convert(res.body, 'utf-8', 'windows-1251').toString()
            let json = self._parseJSON(res.body, reject);
            return self._getNormalAudiosWithURL(json.list).then(audios => {
              resolve({
                vk: self._vk,
                json: json,
                vkr: VKResponse(staticMethods, {
                  response: audios
                })
              })
            });
          });
        }));
      });
    });
  }

Новые аудио друзей:

getFriendsNew (params = {}) {
    let self = this;

    return new Promise((resolve, reject) => {
      let uid = self._vk.session.user_id
      if (params.owner_id) {
        params.owner_id = Number(params.owner_id)
      } else if (uid) { params.owner_id = uid }
      self._request({
        act: 'section',
        al: 1,
        claim: 0,
        is_layer: 0,
        owner_id: uid,
        section: "updates"
      }).then(res => {
        res.body = encoding.convert(res.body, 'utf-8', 'windows-1251').toString()
        let json = self._parseJSON(res.body, reject);

        let audios = json.feedPlaylist.list
        audios = audios.slice(0, params.count)
        return self._getNormalAudiosWithURL(audios).then(audios => {
          resolve({
            vk: self._vk,
            json: json,
            vkr: VKResponse(staticMethods, {
              response: audios
            })
          })
        });
      });
    });
  }

Получение новых музыкальных релизов:

loadNewReleases (params = {}) {
    let self = this;
    let uid = self._vk.session.user_id

    return new Promise((resolve, reject) => {
      self._request({
        act: "section",
        al: 1,
        claim: 0,
        is_layer: 0,
        owner_id: uid,
        section: "recoms"
      }).then(res => {
        let json = self._parseJSON(res.body, reject);

        let recoms = json.playlists[0].list;
        let recoms_id = json.playlists[0].id;

        let new_releases = json.playlists[1].list;
        let new_releases_id = json.playlists[1].id;

        let vk_charts = json.playlists[2].list;
        let vk_charts_id = json.playlists[2].id;

        return self._getNormalAudiosWithURL(recoms).then(resolve_recoms => {
          resolve_recoms = [...resolve_recoms, { recoms_id }];
          return self._getNormalAudiosWithURL(new_releases).then(resolve_new_releases => {
            resolve_new_releases = [...resolve_new_releases, { new_releases_id }]
            return self._getNormalAudiosWithURL(vk_charts).then(resolve_vk_charts => {
              resolve_vk_charts = [...resolve_vk_charts, { vk_charts_id }]
              resolve({
                vk: self._vk,
                vkr: VKResponse(staticMethods, {
                  response: [resolve_recoms, resolve_new_releases, resolve_vk_charts]
                })
              })
            });
          });
        });
      })
    });
  }

Загрузка страниц аудио с полным списком рекомендаций, новых релизов и т.д. Думаю, это можно объединить с предыдущими через params.count, но пусть пока что будет:

loadAudioPage (params = {}) {
    let self = this;
    let uid = self._vk.session.user_id

    return new Promise((resolve, reject) => {
      return resolve(new Promise((resolve, reject) => {
        self._request({
          act: 'load_section',
          al: 1,
          claim: 0,
          offset: 0,
          owner_id: uid,
          playlist_id: `recoms${params.type}`,
          type: 'recoms',
          track_type: 'default'
        }).then(res => {
          res.body = encoding.convert(res.body, 'utf-8', 'windows-1251').toString()
          let json = self._parseJSON(res.body, reject);
          return self._getNormalAudiosWithURL(json.list).then(audios => {
            resolve({
              vk: self._vk,
              json: json,
              vkr: VKResponse(staticMethods, {
                response: audios
              })
            })
          });
        });
      }));
    });
  }

Регистрация проигрывания трека. Вроде как должно влиять на будущие рекомендации для пользователя, но я не уверен, что это так работает, но тоже пусть будет:

registerPlaying (params = {}) {
    let self = this;

    return new Promise((resolve, reject) => {
      self._request({
        act: "queue_params",
        al: 1,
        audio_id: params.audio_id,
        hash: params.action_hash,
        owner_id: params.owner_id
      }).then(() => {
        return resolve({
          vk: self._vk,
          vkr: VKResponse(staticMethods, { response: true })
        });
      }).catch(e => {
        return resolve({
          vk: self._vk,
          vkr: VKResponse(staticMethods, { response: true })
        });
      });
    });
  }

Создание плейлиста:

createPlaylist (params = {}) {
    let self = this
    let uid = self._vk.session.user_id

    return new Promise((resolve, reject) => {
      self._request({
        retOnlyBody: true
      }).then(res => {
        let newPlaylistHash = res.body.match(/"newPlaylistHash":"(.*?)"/g);
        newPlaylistHash = (newPlaylistHash[0].split(':')[1] || '').replace(/"/g, '')
        return resolve(new Promise((resolve, reject) => {
          self._request({
            Audios: "",
            act: "save_playlist",
            al: 1,
            cover: JSON.stringify(params.cover),
            description: params.description,
            hash: newPlaylistHash,
            owner_id: uid,
            playlist_id: 0,
            title: params.title
          }).then(() => {
            return resolve({
              vk: self._vk,
              vkr: VKResponse(staticMethods, {
                response: true
              })
            })
          })
        }));
      });
    });
  }

Редактирование плейлиста:

editPlaylist (params = {}) {
    let self = this;
    let uid = self._vk.session.user_id;

    return new Promise((resolve, reject) => {
      self._request({
        access_hash: "",
        act: "load_section",
        al: 1,
        claim: 0,
        from_id: uid,
        is_loading_all: 1,
        offset: 0,
        owner_id: uid,
        playlist_id: params.playlist_id,
        type: "playlist"
      }).then(res => {
        let editHash = res.body.match(/"editHash":"(.*?)"/g);
        editHash = (editHash[0].split(':')[1] || '').replace(/"/g, '')
        res.body = encoding.convert(res.body, 'utf-8', 'windows-1251').toString()
        let json = self._parseJSON(res.body, reject);
        let audios = json.list
        return self._getNormalAudiosWithURL(audios).then(audios => {
          let ids = "";
          for(let audio in audios)
            ids += audios[audio].full_id + ",";
          ids = ids.substring(0, ids.length - 1);
          return resolve(new Promise((resolve, reject) => {
            self._request({
              Audios: ids,
              act: "save_playlist",
              al: 1,
              cover: JSON.stringify(params.cover) || 0,
              description: params.description,
              hash: editHash,
              owner_id: uid,
              playlist_id: params.playlist_id,
              title: params.title
            }).then(() => {
              return resolve({
                vk: self._vk,
                vkr: VKResponse(staticMethods, {
                  response: true
                })
              });
            });
          }));
        });
      })
    });
  }

Перемещение плейлистов:

reorderPlaylists (params = {}) {
    let self = this;
    let uid = self._vk.session.user_id;

    return new Promise((resolve, reject) => {
      self._request({
        retOnlyBody: true
      }).then(res => {
        let reorderHash = res.body.match(/"reorderHash":"(.*?)"/g);
        reorderHash = (reorderHash[0].split(':')[1] || '').replace(/"/g, '')
        return resolve(new Promise((resolve, reject) => {
          self._request({
            act: "reorder_playlist",
            al: 1,
            hash: reorderHash,
            owner_id: uid,
            playlist_id: params.playlist_id,
            prev_playlist_id: params.prev_playlist_id
          }).then(res => {
            return resolve({
              vk: self._vk,
              vkr: VKResponse(staticMethods, {
                response: true
              })
            });
          }).catch(e => {
            return resolve({
              vk: self._vk,
              vkr: VKResponse(staticMethods, {
                response: true
              })
            });
          });
        }));
      });
    });
  }

Сортировка треков в плейлисте:

reorderSongsInPlaylist (params = {}) {
    let self = this;
    let uid = self._vk.session.user_id;

    return new Promise((resolve, reject) => {
      self._request({
        access_hash: "",
        act: "load_section",
        al: 1,
        claim: 0,
        from_id: uid,
        is_loading_all: 1,
        offset: 0,
        owner_id: uid,
        playlist_id: params.playlist_id,
        type: "playlist"
      }).then(res => {
        let editHash = res.body.match(/"editHash":"(.*?)"/g);
        editHash = (editHash[0].split(':')[1] || '').replace(/"/g, '')
        return resolve(new Promise((resolve, reject) => {
          self._request({
            Audios: params.Audios,
            act: "save_playlist",
            al: 1,
            cover: 0,
            description: params.description,
            hash: editHash,
            owner_id: uid,
            playlist_id: params.playlist_id,
            title: params.title
          }).then(() => {
            return resolve({
              vk: self._vk,
              vkr: VKResponse(staticMethods, {
                response: true
              })
            });
          });
        }));
      })
    });
  }

Получение URL для загрузки обложки плейлиста. Потом можно использовать uploader:

getPlaylistCoverUploadURL () {
    let self = this
    let uid = self._vk.session.user_id

    return new Promise((resolve, reject) => {
      self._request({
        retOnlyBody: true
      }).then(res => {
        let hash = res.body.match(/"hash":"(.*?)"/g);
        hash = (hash[0].split(':')[1] || '').replace(/"/g, '')

        let server = res.body.match(/"server":"(.*?)"/g);
        server = (server[0].split(':')[1] || '').replace(/"/g, '')
        let completeURL = `https://pu.vk.com/c${server}/upload.php?act=audio_playlist_cover&ajx=1&hash=${hash}&mid=${uid}&upldr=1`;
        return resolve(completeURL);
      });
    });
  }

UPD. Добавление трека в любой плейлист. Просто moveToPlaylist работает на первые три плейлиста:

addToPlaylist (audio = {}, playlist = {}) {
    let self = this;
    let uid = self._vk.session.user_id

    return new Promise((resolve, reject) => {
      self._request({
        act: "more_playlists_add",
        al: 1,
        audio_id: audio.id,
        audio_owner_id: audio.owner_id,
        owner_id: uid
      }, true).then(res => {
        let neededHash = res.body.match(/], '(.*)'/)[1];
        self._request({
          act: "save_audio_in_playlists",
          add_pl_ids: playlist.playlist_id,
          al: 1,
          audio_id: audio.id,
          audio_owner_id: audio.owner_id,
          hash: neededHash,
          owner_id: uid,
          remove_pl_ids: ""
        }, true).then(res => {
          return resolve({
            vkr: VKResponse(staticMethods, {
              response: true
            }),
            vk: self._vk
          })
        });
      })
    });
  }

И удаление трека из плейлиста:

removeFromPlaylist (audio = {}, playlist = {}) {
    let self = this;
    let uid = self._vk.session.user_id

    return new Promise((resolve, reject) => {
      self._request({
        act: "more_playlists_add",
        al: 1,
        audio_id: audio.id,
        audio_owner_id: audio.owner_id,
        owner_id: uid
      }, true).then(res => {
        let neededHash = res.body.match(/], '(.*)'/)[1];
        self._request({
          act: "save_audio_in_playlists",
          add_pl_ids: "",
          al: 1,
          audio_id: audio.id,
          audio_owner_id: audio.owner_id,
          hash: neededHash,
          owner_id: uid,
          remove_pl_ids: playlist.playlist_id
        }, true).then(res => {
          return resolve({
            vkr: VKResponse(staticMethods, {
              response: true
            }),
            vk: self._vk
          })
        });
      })
    });
  }

Вот, вроде всё. Где-то может быть неправильно накодил и может быть хеши как-то по-другому получаются, исправь, если не трудно. Ещё в некоторых случаях, например редактирование плейлиста, EasyVK говорит, что нет доступа, плейлист всё равно редактируется, но я пока что сделал костыль, а именно, просто игнорируя эту ошибку через catch. UPD: Разобрался. Нужно было указать ignoreStringError как истину. То есть self._request({...}, true).then(res => ...). Эта же ошибка появляется в reorder. Кстати, ещё могут быть проблемы с кодировкой, но я пока не копался в этом основательно.

ciricc commented 5 years ago

Спасибо огромное за дополнение