Skip to content
Open
292 changes: 265 additions & 27 deletions lib/api_material.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ const path = require('path');
const { promisify } = require('util');
const { stat } = require('fs');
const statAsync = promisify(stat);

const fetch = require('node-fetch');
const formstream = require('formstream');

const { postJSON } = require('./util');
Expand All @@ -29,22 +29,22 @@ const { postJSON } = require('./util');
*/
exports.uploadMaterial = async function (filepath, type) {
const { accessToken } = await this.ensureAccessToken();
var stat = await statAsync(filepath);
var form = formstream();
const stat = await statAsync(filepath);
const form = formstream();
form.file('media', filepath, path.basename(filepath), stat.size);
var url = this.prefix + 'material/add_material?access_token=' + accessToken + '&type=' + type;
var opts = {
const url = this.prefix + 'material/add_material?access_token=' + accessToken + '&type=' + type;
const opts = {
dataType: 'json',
method: 'POST',
timeout: 60000, // 60秒超时
headers: form.headers(),
data: form
data: form,
};
return this.request(url, opts);
};

['image', 'voice', 'thumb'].forEach(function (type) {
var method = 'upload' + type[0].toUpperCase() + type.substring(1) + 'Material';
const method = 'upload' + type[0].toUpperCase() + type.substring(1) + 'Material';
exports[method] = async function (filepath) {
return this.uploadMaterial(filepath, type);
};
Expand All @@ -71,17 +71,17 @@ exports.uploadMaterial = async function (filepath, type) {
*/
exports.uploadVideoMaterial = async function (filepath, description) {
const { accessToken } = await this.ensureAccessToken();
var stat = await statAsync(filepath);
var form = formstream();
const stat = await statAsync(filepath);
const form = formstream();
form.file('media', filepath, path.basename(filepath), stat.size);
form.field('description', JSON.stringify(description));
var url = this.prefix + 'material/add_material?access_token=' + accessToken + '&type=video';
var opts = {
const url = this.prefix + 'material/add_material?access_token=' + accessToken + '&type=video';
const opts = {
dataType: 'json',
method: 'POST',
timeout: 60000, // 60秒超时
headers: form.headers(),
data: form
data: form,
};
return this.request(url, opts);
};
Expand Down Expand Up @@ -111,15 +111,65 @@ exports.uploadVideoMaterial = async function (filepath, description) {
*
* Result:
* ```
* {"errcode":0,"errmsg":"ok"}
* {
* "media_id":MEDIA_ID
* }
* ```
* @param {Object} news 图文对象
*/
exports.uploadNewsMaterial = async function (news) {
const { accessToken } = await this.ensureAccessToken();
var url = this.prefix + 'material/add_news?access_token=' + accessToken;
const url = this.prefix + 'material/add_news?access_token=' + accessToken;
return this.request(url, postJSON(news));
};


/**
* 新建草稿
* 详情请见:<https://developers.weixin.qq.com/doc/offiaccount/Draft_Box/Add_draft.html>
* ```
* {
* "articles": [
* {
* "title":TITLE,
* "author":AUTHOR,
* "digest":DIGEST,
* "content":CONTENT,
* "content_source_url":CONTENT_SOURCE_URL,
* "thumb_media_id":THUMB_MEDIA_ID,
* "need_open_comment": 0,
* "only_fans_can_comment": 0
* }
* //若新增的是多图文素材,则此处应还有几段articles结构
* ]
* }
* ```
* Examples:
* ```
* api.addDraft(news);
* ```
*
* Result:
* ```
* {
* "media_id":MEDIA_ID
* }
* ```
* @param {Object} news 图文对象
*/
exports.addDraft = async function (news) {
const { accessToken } = await this.ensureAccessToken();
const url = this.prefix + 'draft/add?access_token=' + accessToken;
return fetch(url, {
method: 'POST',
body: JSON.stringify(news),
headers: {
'Content-Type': 'application/json',
'Accept': 'application/json',
},
}).then(res => res.json());
};

/**
* 更新永久图文素材
* News:
Expand Down Expand Up @@ -153,9 +203,49 @@ exports.uploadNewsMaterial = async function (news) {
*/
exports.updateNewsMaterial = async function (news) {
const { accessToken } = await this.ensureAccessToken();
var url = this.prefix + 'material/update_news?access_token=' + accessToken;
const url = this.prefix + 'material/update_news?access_token=' + accessToken;
return this.request(url, postJSON(news));
};

/**
* 修改草稿
* News:
* ```
* {
* "media_id":MEDIA_ID,
* "index":INDEX,
* "articles": {
* "title":TITLE,
* "author":AUTHOR,
* "digest":DIGEST,
* "content":CONTENT,
* "content_source_url":CONTENT_SOURCE_URL,
* "thumb_media_id":THUMB_MEDIA_ID,
* "show_cover_pic": 1,
* "need_open_comment": 0,
* "only_fans_can_comment": 0
* }
* }
* ```
* Examples:
* ```
* api.updateDraft(news);
* ```
* Result:
* ```
* {
* "errcode":ERRCODE,
* "errmsg": "ERRMSG"
* }
* ```
* @param {Object} news 图文对象
*/
exports.updateDraft = async function (news) {
const { accessToken } = await this.ensureAccessToken();
const url = this.prefix + 'draft/update?access_token=' + accessToken;
return this.request(url, postJSON(news));
};

/**
* 根据媒体ID获取永久素材
* 详情请见:<http://mp.weixin.qq.com/wiki/4/b3546879f07623cb30df9ca0e420a5d0.html>
Expand All @@ -169,14 +259,58 @@ exports.updateNewsMaterial = async function (news) {
*/
exports.getMaterial = async function (mediaId) {
const { accessToken } = await this.ensureAccessToken();
var url = this.prefix + 'material/get_material?access_token=' + accessToken;
var opts = {
const url = this.prefix + 'material/get_material?access_token=' + accessToken;
const opts = {
method: 'POST',
data: JSON.stringify({'media_id': mediaId}),
data: JSON.stringify({ 'media_id': mediaId }),
headers: {
'Content-Type': 'application/json'
'Content-Type': 'application/json',
},
timeout : 60000 // 60秒超时
timeout: 60000, // 60秒超时
};
return this.request(url, opts);
};

/**
* 获取草稿
* 详情请见:<https://developers.weixin.qq.com/doc/offiaccount/Draft_Box/Get_draft.html>
* Examples:
* ```
* api.getDraft('media_id');
* ```
*
* - `result`
* ```
* {
* "news_item": [
* {
* "title":TITLE,
* "author":AUTHOR,
* "digest":DIGEST,
* "content":CONTENT,
* "content_source_url":CONTENT_SOURCE_URL,
* "thumb_media_id":THUMB_MEDIA_ID,
* "show_cover_pic": 1,
* "need_open_comment": 0,
* "only_fans_can_comment": 0,
* "url":URL
* }
* //多图文消息应有多段 news_item 结构
* ]
* }
* ```
* @param {String} mediaId 媒体文件的ID
*/
exports.getDraft = async function (mediaId) {
const { accessToken } = await this.ensureAccessToken();
const url = this.prefix + 'draft/get?access_token=' + accessToken;
const opts = {
method: 'POST',
data: JSON.stringify({ 'media_id': mediaId }),
headers: {
'Content-Type': 'application/json',
},
timeout: 60000, // 60秒超时
};
return this.request(url, opts);
};
Expand All @@ -194,8 +328,31 @@ exports.getMaterial = async function (mediaId) {
*/
exports.removeMaterial = async function (mediaId) {
const { accessToken } = await this.ensureAccessToken();
var url = this.prefix + 'material/del_material?access_token=' + accessToken;
return this.request(url, postJSON({'media_id': mediaId}));
const url = this.prefix + 'material/del_material?access_token=' + accessToken;
return this.request(url, postJSON({ 'media_id': mediaId }));
};

/**
* 删除草稿
* 详情请见:<https://developers.weixin.qq.com/doc/offiaccount/Draft_Box/Delete_draft.html>
* Examples:
* ```
* api.removeMaterial('media_id');
* ```
*
* - `result`, 调用正常时得到的文件Buffer对象
* ```
* {
* "errcode":ERRCODE,
* "errmsg":"ERRMSG"
* }
* ```
* * @param {String} mediaId 媒体文件的ID
*/
exports.deleteDraft = async function (mediaId) {
const { accessToken } = await this.ensureAccessToken();
const url = this.prefix + 'draft/delete?access_token=' + accessToken;
return this.request(url, postJSON({ 'media_id': mediaId }));
};

/**
Expand All @@ -219,8 +376,29 @@ exports.removeMaterial = async function (mediaId) {
*/
exports.getMaterialCount = async function () {
const { accessToken } = await this.ensureAccessToken();
var url = this.prefix + 'material/get_materialcount?access_token=' + accessToken;
return this.request(url, {dataType: 'json'});
const url = this.prefix + 'material/get_materialcount?access_token=' + accessToken;
return this.request(url, { dataType: 'json' });
};

/**
* 获取草稿总数
* 详情请见:<https://developers.weixin.qq.com/doc/offiaccount/Draft_Box/Count_drafts.html>
* Examples:
* ```
* api.getDraftCount();
* ```
*
* - `res`, HTTP响应对象 * Result:
* ```
* {
* "total_count":TOTAL_COUNT
* }
* ```
*/
exports.getDraftCount = async function () {
const { accessToken } = await this.ensureAccessToken();
const url = this.prefix + 'draft/count?access_token=' + accessToken;
return this.request(url, { dataType: 'json' });
};

/**
Expand Down Expand Up @@ -252,11 +430,71 @@ exports.getMaterialCount = async function () {
*/
exports.getMaterials = async function (type, offset, count) {
const { accessToken } = await this.ensureAccessToken();
var url = this.prefix + 'material/batchget_material?access_token=' + accessToken;
var data = {
const url = this.prefix + 'material/batchget_material?access_token=' + accessToken;
const data = {
type: type,
offset: offset,
count: count
count: count,
};
return this.request(url, postJSON(data));
};

/**
* 获取草稿列表
* 详情请见:<https://developers.weixin.qq.com/doc/offiaccount/Draft_Box/Get_draft_list.html>
* Examples:
* ```
* {
* "offset":OFFSET,
* "count":COUNT,
* "no_content":NO_CONTENT
* }
* ```
*
* ```
* api.getDrafts(offset, count, no_content);
* ```
*
* - `result`, 调用正常时得到的文件Buffer对象
* - `res`, HTTP响应对象 * Result:
* ```
* {
* "total_count":TOTAL_COUNT,
* "item_count":ITEM_COUNT,
* "item": [
* {
* "media_id":MEDIA_ID,
* "content": {
* "news_item": [
* {
* "title":TITLE,
* "author":AUTHOR,
* "digest":DIGEST,
* "content":CONTENT,
* "content_source_url":CONTENT_SOURCE_URL,
* "thumb_media_id":THUMB_MEDIA_ID,
* "show_cover_pic": 1,
* "need_open_comment": 0,
* "only_fans_can_comment": 0,
* "url":URL
* },
* //多图文消息会在此处有多篇文章
* ]
* },
* "update_time": UPDATE_TIME
* },
* //可能有多个图文消息item结构
* ]
* }
* ```
*/
exports.getDrafts = async function (offset, count, no_content) {
const { accessToken } = await this.ensureAccessToken();
const url = this.prefix + 'draft/batchget?access_token=' + accessToken;
const data = {
offset: offset,
count: count,
no_content: no_content,
};
return this.request(url, postJSON(data));
};
Loading