vknode
Version:
Library for working with VK API
443 lines (345 loc) • 13.6 kB
JavaScript
const fs = require('fs')
const request = require('request')
const rp = require('request-promise')
// https://vk.com/dev/upload_files
module.exports = class Upload {
constructor(self) {
this.self = self
this.cache = []
}
async _file(file) {
if (file instanceof fs.ReadStream) {
return file
} else if (typeof file == 'string' && file.match(/https?:\/\/.+/i)) {
let filename = file.split('/')
filename = `${__dirname}/../../../cache/${filename[filename.length - 1]}`
this.cache.push(filename)
return new Promise(async(resolve, reject) => {
request(file).pipe(fs.createWriteStream(filename)).on('finish', () => {
return resolve(fs.createReadStream(filename))
})
})
}
file = fs.createReadStream(file)
return file
}
_clearCache() {
this.cache.forEach(filename => fs.unlink(filename))
}
async photo(data = {}) {
const
owner_id = data.owner_id ? data.owner_id : (data.user_id ? data.user_id : (data.group_id ? 0 - data.group_id : (this.self.info.group_id ? 0 - this.self.info.group_id : this.self.info.user_id))),
files = {}
if (!data.album) {
const { items } = await this.self.call('photos.getAlbums', { owner_id })
data.album = items[0].id
}
const group_id = owner_id < 0 ? 0 - owner_id : null
const { upload_url, album_id, user_id } = await this.self.call('photos.getUploadServer', {
album_id: data.album,
group_id
})
if (Array.isArray(data.photos)) {
data.photos.forEach(async(photo) => {
files[`file${Object.keys(files).length+1}`] = await this._file(photo)
})
} else if (data.photos) {
files[`file${Object.keys(files).length+1}`] = await this._file(data.photos)
}
if (data.photo) {
files[`file${Object.keys(files).length+1}`] = await this._file(data.photo)
}
const response = await rp(upload_url, {
method: 'POST',
formData: files,
json: true
})
const photos = await this.self.call('photos.save', {
server: response.server,
photos_list: response.photos_list,
hash: response.hash,
album_id,
latitude: data.latitude,
longitude: data.longitude,
caption: data.caption || data.text || data.body,
group_id
})
if (photos) {
for (const key in photos) {
photos[key].attachment = `photo${photos[key].owner_id}_${photos[key].id}`
}
}
return photos
}
async wallPhoto(data) {
const group_id = data.group_id
const { upload_url, album_id, user_id } = await this.self.call('photos.getWallUploadServer', { group_id })
const response = await rp(upload_url, {
method: 'POST',
formData: {
photo: await this._file(data.photo)
},
json: true
})
const [photo] = await this.self.call('photos.saveWallPhoto', {
server: response.server,
photo: response.photo,
hash: response.hash,
user_id: group_id ? null : group_id,
group_id,
latitude: data.latitude,
longitude: data.longitude,
caption: data.caption || data.text || data.body
})
photo.attachment = `photo${photo.owner_id}_${photo.id}`
if (photo.access_key) {
photo.attachment += `_${photo.access_key}`
}
return photo
}
async ownerPhoto(data) {
const { upload_url } = await this.self.call('photos.getOwnerPhotoUploadServer', { owner_id: data.group_id ? 0 - data.group_id : null })
const response = await rp(upload_url, {
method: 'POST',
formData: {
photo: await this._file(data.photo)
},
json: true
})
const photo = await this.self.call('photos.saveOwnerPhoto', response)
if (photo.post_id) {
const owner_id = (data.group_id ? 0 - data.group_id : null) || (await this.self.call('users.get'))[0].id
photo.post = `wall${owner_id}_${photo.post_id}`
}
return photo
}
async messagePhoto(data) {
const { upload_url, album_id, user_id } = await this.self.call('photos.getMessagesUploadServer', { peer_id: data.peer_id })
const response = await rp(upload_url, {
method: 'POST',
formData: {
photo: await this._file(data.photo)
},
json: true
})
const [photo] = await this.self.call('photos.saveMessagesPhoto', response)
photo.attachment = `photo${photo.owner_id}_${photo.id}`
return photo
}
async chatPhoto(data) {
const { upload_url } = await this.self.call('photos.getChatUploadServer', {
chat_id: data.chat_id,
crop_x: data.crop_x || data.x,
crop_y: data.crop_y || data.y,
crop_width: data.crop_width || data.width
})
const { response } = await rp(upload_url, {
method: 'POST',
formData: {
file: await this._file(data.photo)
},
json: true
})
const info = await this.self.call('messages.setChatPhoto', { file: response })
return info
}
async marketPhoto(data) {
const { upload_url } = await this.self.call('photos.getChatUploadServer', {
group_id: data.group_id,
main_photo: data.main_photo || data.main,
crop_x: data.crop_x || data.x,
crop_y: data.crop_y || data.y,
crop_width: data.crop_width || data.width
})
const response = await rp(upload_url, {
method: 'POST',
formData: {
file: await this._file(data.photo)
},
json: true
})
response.group_id = data.group_id
const [photo] = await this.self.call('photos.saveMarketPhoto', response)
return photo
}
productPhoto(...data) {
return this.marketPhoto(...data)
}
async marketAlbumPhoto(data) {
const { upload_url } = await this.self.call('photos.getMarketAlbumUploadServer', { group_id: data.group_id })
const response = await rp(upload_url, {
method: 'POST',
formData: {
file: await this._file(data.photo)
},
json: true
})
response.group_id = response.gid
delete response.gid
const [photo] = await this.self.call('photos.saveMarketAlbumPhoto', response)
return photo
}
async audio(data) {
const { upload_url } = await this.self.call('audio.getUploadServer')
const file = await this._file(data.file || data.audio || data.track)
const response = await rp(upload_url, {
method: 'POST',
formData: { file },
json: true
})
delete response.redirect
response.artist = data.artist
response.title = data.title === true ? (() => {
file.path = file.path.split('/')
return file.path[file.path.length - 1]
})() : data.title
const audio = await this.self.call('audio.save', response)
return audio
}
async video(data) {
const video = await this.self.call('video.save', {
name: data.name,
description: data.description || data.desc || data.descr,
is_private: Boolean(data.is_private || data.private),
wallpost: Boolean(data.wallpost || data.wall),
link: data.link || data.href || data.src || data.source,
group_id: data.group_id,
album_id: data.album_id,
privacy_view: typeof data.privacy_view == 'string' ? data.privacy_view : (Array.isArray(data.privacy_view) ? JSON.stringify(data.privacy_view) : null),
privacy_comment: typeof data.privacy_comment == 'string' ? data.privacy_comment : (Array.isArray(data.privacy_comment) ? JSON.stringify(data.privacy_comment) : null),
no_comments: Boolean(data.no_comments),
repeat: Boolean(data.repeat)
})
const requestData = [video.upload_url, {
method: 'POST',
formData: {
video_file: await this._file(data.file || data.video)
},
json: true
}]
let upload
if (data.wait) {
upload = await rp(...requestData)
if (upload) {
Object.assign(video, upload)
}
} else {
rp(...requestData)
}
delete video.upload_url
video.attachment = `video${video.owner_id}_${video.video_id}`
if (video.access_key) {
video.attachment += `_${video.access_key}`
}
return video
}
async _doc(data) {
const file = await this._file(data.file)
const params = {
type: data.type /* doc, audio_message, graffiti */
}
const { upload_url } = await this.self.call(`docs.${data.method}`, params)
const response = await rp(upload_url, {
method: 'POST',
formData: { file },
json: true
})
const [doc] = await this.self.call('docs.save', {
file: response.file,
title: data.title === true ? (() => {
file.path = file.path.split('/')
return file.path[file.path.length - 1]
})() : data.title,
tags: typeof data.tags == 'string' ? data.tags : (Array.isArray(data.tags) ? data.tags.replace(/,/, '\\,').join(',') : null)
})
doc.attachment = `doc${doc.owner_id}_${doc.id}`
if (doc.access_key) {
doc.attachment += `_${doc.access_key}`
}
return doc
}
doc(data) {
return this._doc({
method: 'getUploadServer',
group_id: data.group_id,
title: data.data,
tags: data.tags,
file: data.file || data.doc
})
}
wallDoc(data) {
return this._doc({
method: 'getWallUploadServer',
group_id: data.group_id,
title: data.data,
tags: data.tags,
file: data.file || data.doc
})
}
messageDoc(data) {
return this._doc({
method: 'getMessagesUploadServer',
peer_id: data.peer_id || data.user_id || (data.group_id ? 0 - data.group_id : (data.chat_id ? 2e9 + data.chat_id : null)),
title: data.data,
tags: data.tags,
file: data.file || data.doc
})
}
docs(...data) {
return this.doc(...data)
}
wallDocs(...data) {
return this.wallDoc(...data)
}
messageDocs(...data) {
return this.messageDoc(...data)
}
async cover(data) {
const { upload_url } = await this.self.call('photos.getOwnerCoverPhotoUploadServer', {
group_id: data.group_id,
crop_x: data.crop_x || data.x,
crop_y: data.crop_y || data.y,
crop_x2: data.crop_x2 || data.x2,
crop_y2: data.crop_y2 || data.y2
})
const response = await rp(upload_url, {
method: 'POST',
formData: {
photo: await this._file(data.photo || data.cover || data.file)
},
json: true
})
const photo = await this.self.call('photos.saveOwnerCoverPhoto', response)
return photo
}
ownerCover(...data) {
return this.cover(...data)
}
async story(data) {
const type = 0 // dbg
const { upload_url, user_ids } = await this.self.call(type === 0 ? 'stories.getPhotoUploadServer' : 'stories.getVideoUploadServer', {
user_ids: data.user_ids,
mask_id: data.mask_id,
section_id: data.section_id,
add_to_news: Boolean(data.add_to_news || data.news),
reply_to_story: data.reply_to_story,
link_text: data.link_text,
link_url: data.link_url
})
const { response, error } = await rp(upload_url, {
method: 'POST',
formData: {
[type === 0 ? 'photo' : 'video_file']: await this._file(data.file || type === 0 ? data.photo : data.video || data.video_file)
},
json: true
})
if (error) {
return error
}
response.story.attachment = `story${response.story.owner_id}_${response.story.id}`
if (response.story.access_key) {
response.story.attachment += `_${response.story.access_key}`
}
return response.story
}
}