#coding=utf-8 #!/usr/bin/env ruby ### lib = File.expand_path(File.dirname(__FILE__) + '/../lib') $LOAD_PATH.unshift(lib) if File.directory?(lib) && !$LOAD_PATH.include?(lib) require 'thor' require 'wechat' require 'json' require 'active_support' # To support Rails 4.2.1, see #17936 require 'active_support/dependencies/autoload' require 'active_support/core_ext' require 'active_support/json' require 'fileutils' require 'yaml' require 'wechat/api_loader' require 'cgi' class App < Thor package_name 'Wechat' option :token_file, aliases: '-t', desc: 'File to store access token' attr_reader :wechat_api_client no_commands do def wechat_api @wechat_api_client ||= Wechat::ApiLoader.with(options) end end desc 'callbackip', '获取微信服务器IP地址' def callbackip puts wechat_api.callbackip end desc 'qrcode_download [TICKET, QR_CODE_PIC_PATH]', '通过ticket下载二维码' def qrcode_download(ticket, qr_code_pic_path) tmp_file = wechat_api.qrcode(ticket) FileUtils.mv(tmp_file.path, qr_code_pic_path) puts 'File downloaded' end if Wechat::ApiLoader.with(options).is_a?(Wechat::CorpApi) desc 'department_create [NAME, PARENT_ID]', '创建部门' method_option :parentid, aliases: '-p', desc: '父亲部门id。根部门id为1' def department_create(name) api_opts = options.slice(:parentid) puts wechat_api.department_create(name, api_opts[:parentid] || '1') end desc 'department_delete [DEPARTMENT_ID]', '删除部门' def department_delete(departmentid) puts wechat_api.department_delete(departmentid) end desc 'department_update [DEPARTMENT_ID, NAME]', '更新部门' method_option :parentid, aliases: '-p', desc: '父亲部门id。根部门id为1', default: nil method_option :order, aliases: '-o', desc: '在父部门中的次序值。order值小的排序靠前。', default: nil def department_update(departmentid, name) api_opts = options.slice(:parentid, :order) puts wechat_api.department_update(departmentid, name, api_opts[:parentid], api_opts[:order]) end desc 'department [DEPARTMENT_ID]', '获取部门列表' def department(departmentid = 0) r = wechat_api.department(departmentid) puts "errcode: #{r['errcode']} errmsg: #{r['errmsg']}" puts 'Or# pid id name' r['department'].sort_by { |d| d['order'].to_i + d['parentid'].to_i * 1000 } .each do |i| puts format('%3d %3d %3d %s', i['order'], i['parentid'], i['id'], i['name']) end end desc 'user_delete [USER_ID]', '删除成员' def user_delete(userid) puts wechat_api.user_delete(userid) end desc 'user_batchdelete [USER_ID_LIST]', '批量删除成员' def user_batchdelete(useridlist) puts wechat_api.user_batchdelete(useridlist.split(',')) end desc 'user_simplelist [DEPARTMENT_ID]', '获取部门成员' method_option :fetch_child, aliases: '-c', desc: '是否递归获取子部门下面的成员', default: 1 method_option :status, aliases: '-s', desc: '0 获取全部成员,1 获取已关注成员列表,2 获取禁用成员列表,4 获取未关注成员列表。status可叠加', default: 0 def user_simplelist(departmentid = 0) api_opts = options.slice(:fetch_child, :status) r = wechat_api.user_simplelist(departmentid, api_opts[:fetch_child], api_opts[:status]) puts "errcode: #{r['errcode']} errmsg: #{r['errmsg']}" puts " userid Name #{' ' * 20} department_ids" r['userlist'].sort_by { |d| d['userid'] } .each do |i| puts format('%7s %-25s %-14s', i['userid'], i['name'], i['department']) end end desc 'user_list [DEPARTMENT_ID]', '获取部门成员详情' method_option :fetch_child, aliases: '-c', desc: '是否递归获取子部门下面的成员', default: 0 method_option :status, aliases: '-s', desc: '0 获取全部成员,1 获取已关注成员列表,2 获取禁用成员列表,4 获取未关注成员列表。status可叠加', default: 0 def user_list(departmentid = 0) api_opts = options.slice(:fetch_child, :status) r = wechat_api.user_list(departmentid, api_opts[:fetch_child], api_opts[:status]) puts "errcode: #{r['errcode']} errmsg: #{r['errmsg']}" puts " userid Name #{' ' * 15} department_ids position mobile #{' ' * 5}gender email #{' ' * 10}weixinid status extattr" r['userlist'].sort_by { |d| d['userid'] } .each do |i| puts format('%7s %-20s %-14s %-8s %-11s %-6s %-15s %-15s %-6s %s', i['userid'], i['name'], i['department'], i['position'], i['mobile'], i['gender'], i['email'], i['weixinid'], i['status'], i['extattr']) end end desc 'invite_user [USER_ID]', '邀请成员关注' def invite_user(userid) puts wechat_api.invite_user(userid) end desc 'tag_create [TAGNAME, TAG_ID]', '创建标签' method_option :tagid, aliases: '-id', desc: '整型,指定此参数时新增的标签会生成对应的标签id,不指定时则以目前最大的id自增' def tag_create(name) api_opts = options.slice(:tagid) puts wechat_api.tag_create(name, api_opts[:tagid]) end desc 'tag_update [TAG_ID, TAGNAME]', '更新标签名字' def tag_update(tagid, tagname) puts wechat_api.tag_update(tagid, tagname) end desc 'tag_delete [TAG_ID]', '删除标签' def tag_delete(tagid) puts wechat_api.tag_delete(tagid) end desc 'tag [TAG_ID]', '获取标签成员' def tag(tagid) puts wechat_api.tag(tagid) end desc 'tag_add_user [TAG_ID, USER_IDS]', '增加标签成员' def tag_add_user(tagid, userids) puts wechat_api.tag_add_user(tagid, userids.split(',')) end desc 'tag_add_department [TAG_ID, PARTY_IDS]', '增加标签部门' def tag_add_department(tagid, partyids) puts wechat_api.tag_add_user(tagid, nil, partyids.split(',')) end desc 'tag_del_user [TAG_ID, USER_IDS]', '删除标签成员' def tag_del_user(tagid, userids) puts wechat_api.tag_del_user(tagid, userids.split(',')) end desc 'tag_del_department [TAG_ID, PARTY_IDS]', '删除标签部门' def tag_del_department(tagid, partyids) puts wechat_api.tag_del_user(tagid, nil, partyids.split(',')) end desc 'tags', '获取标签列表' def tags puts wechat_api.tags end desc 'batch_job_result [JOB_ID]', '获取异步任务结果' def batch_job_result(job_id) puts wechat_api.batch_job_result(job_id) end desc 'batch_replaceparty [BATCH_PARTY_CSV_MEDIA_ID]', '全量覆盖部门' def batch_replaceparty(batch_party_csv_media_id) puts wechat_api.batch_replaceparty(batch_party_csv_media_id) end desc 'upload_replaceparty [BATCH_PARTY_CSV_PATH]', '上传文件方式全量覆盖部门' def upload_replaceparty(batch_party_csv_path) media_id = wechat_api.media_create('file', batch_party_csv_path)['media_id'] job_id = wechat_api.batch_replaceparty(media_id)['jobid'] puts "running job_id: #{job_id}" puts wechat_api.batch_job_result(job_id) end desc 'batch_syncuser [SYNC_USER_CSV_MEDIA_ID]', '增量更新成员' def batch_syncuser(sync_user_csv_media_id) puts wechat_api.batch_syncuser(sync_user_csv_media_id) end desc 'batch_replaceuser [BATCH_USER_CSV_MEDIA_ID]', '全量覆盖成员' def batch_replaceuser(batch_user_csv_media_id) puts wechat_api.batch_replaceuser(batch_user_csv_media_id) end desc 'upload_replaceuser [BATCH_USER_CSV_PATH]', '上传文件方式全量覆盖成员' def upload_replaceuser(batch_user_csv_path) media_id = wechat_api.media_create('file', batch_user_csv_path)['media_id'] job_id = wechat_api.batch_replaceuser(media_id)['jobid'] puts "running job_id: #{job_id}" puts wechat_api.batch_job_result(job_id) end desc 'convert_to_openid [USER_ID]', 'userid转换成openid' def convert_to_openid(userid) puts wechat_api.convert_to_openid(userid) end desc 'agent_list', '获取应用概况列表' def agent_list r = wechat_api.agent_list puts "errcode: #{r['errcode']} errmsg: #{r['errmsg']}" puts 'ag# name square_logo_url round_logo_url' r['agentlist'].sort_by { |d| d['agentid'] } .each do |i| puts format('%3d %s %s %s', i['agentid'], i['name'], i['square_logo_url'], i['round_logo_url']) end end desc 'agent [AGENT_ID]', '获取企业号应用详情' def agent(agentid) r = wechat_api.agent(agentid) puts "agentid: #{r['agentid']} errcode: #{r['errcode']} errmsg: #{r['errmsg']}" puts "name: #{r['name']}" puts "description: #{r['description']}" puts " square_logo_url: #{r['square_logo_url']}" puts " round_logo_url: #{r['round_logo_url']}" puts "allow_userinfos: #{r['allow_userinfos']}" puts "allow_partys: #{r['allow_partys']}" puts "allow_tags: #{r['allow_tags']}" puts "close: #{r['close']} redirect_domain: #{r['redirect_domain']}" puts "report_location_flag: #{r['report_location_flag']} isreportuser: #{r['isreportuser']} isreportenter: #{r['isreportenter']}" end desc 'message_send [OPENID, TEXT_MESSAGE]', '发送文字消息' def message_send(openid, text_message) puts wechat_api.message_send openid, text_message end else desc 'group_create [GROUP_NAME]', '创建分组' def group_create(group_name) puts wechat_api.group_create(group_name) end desc 'groups', '查询所有分组' def groups puts wechat_api.groups end desc 'user_group [OPEN_ID]', '查询用户所在分组' def user_group(openid) puts wechat_api.user_group(openid) end desc 'group_update [GROUP_ID, NEW_GROUP_NAME]', '修改分组名' def group_update(groupid, new_group_name) puts wechat_api.group_update(groupid, new_group_name) end desc 'user_change_group [OPEN_ID, TO_GROUP_ID]', '移动用户分组' def user_change_group(openid, to_groupid) puts wechat_api.user_change_group(openid, to_groupid) end desc 'group_delete [GROUP_ID]', '删除分组' def group_delete(groupid) puts wechat_api.group_delete(groupid) end desc 'users', '关注者列表' def users puts wechat_api.users end desc 'qrcode_create_scene [SCENE_ID, EXPIRE_SECONDS]', '请求临时二维码' def qrcode_create_scene(scene_id, expire_seconds = 604800) puts wechat_api.qrcode_create_scene(scene_id, expire_seconds) end desc 'qrcode_create_limit_scene [SCENE_ID_OR_STR]', '请求永久二维码' def qrcode_create_limit_scene(scene_id_or_str) puts wechat_api.qrcode_create_limit_scene(scene_id_or_str) end end desc 'user [OPEN_ID]', '获取用户基本信息' def user(open_id) puts wechat_api.user(open_id) end desc 'oauth2_url [REDIRECT_URI]', '生成OAuth2.0验证URL' def oauth2_url(redirect_uri) appid = Wechat.config.corpid || Wechat.config.appid puts wechat_api.oauth2_url(redirect_uri, appid) end desc 'user_update_remark [OPEN_ID, REMARK]', '设置备注名' def user_update_remark(openid, remark) puts wechat_api.user_update_remark(openid, remark) end desc 'menu', '当前菜单' def menu puts wechat_api.menu end desc 'menu_delete', '删除菜单' def menu_delete puts 'Menu deleted' if wechat_api.menu_delete end desc 'menu_create [MENU_YAML_PATH]', '创建菜单' def menu_create(menu_yaml_path) menu = YAML.load(File.read(menu_yaml_path)) puts 'Menu created' if wechat_api.menu_create(menu) end desc 'media [MEDIA_ID, PATH]', '媒体下载' def media(media_id, path) tmp_file = wechat_api.media(media_id) FileUtils.mv(tmp_file.path, path) puts 'File downloaded' end desc 'media_create [MEDIA_TYPE, PATH]', '媒体上传' def media_create(type, path) puts wechat_api.media_create(type, path) end desc 'material [MEDIA_ID, PATH]', '永久媒体下载' def material(media_id, path) tmp_file = wechat_api.material(media_id) FileUtils.mv(tmp_file.path, path) puts 'File downloaded' end desc 'material_add [MEDIA_TYPE, PATH]', '永久媒体上传' def material_add(type, path) puts wechat_api.material_add(type, path) end desc 'material_delete [MEDIA_ID]', '删除永久素材' def material_delete(media_id) puts wechat_api.material_delete(media_id) end desc 'material_count', '获取永久素材总数' def material_count puts wechat_api.material_count end desc 'material_list [TYPE, OFFSET, COUNT]', '获取永久素材列表' def material_list(type, offset, count) r = wechat_api.material_list(type, offset, count) if %w(image voice video file).include?(type) puts "errcode: #{r['errcode']} errmsg: #{r['errmsg']} total_count: #{r['total_count']} item_count: #{r['item_count']}" if wechat_api.is_a?(Wechat::CorpApi) r['itemlist'].each { |i| puts "#{i['media_id']} #{i['filename']} #{Time.at(i['update_time'].to_i)}" } else r['item'].each { |i| puts "#{i['media_id']} #{i['name']} #{Time.at(i['update_time'].to_i)}" } end else puts r end end desc 'custom_text [OPENID, TEXT_MESSAGE]', '发送文字客服消息' def custom_text(openid, text_message) puts wechat_api.custom_message_send Wechat::Message.to(openid).text(text_message) end desc 'custom_image [OPENID, IMAGE_PATH]', '发送图片客服消息' def custom_image(openid, image_path) api = wechat_api media_id = api.media_create('image', image_path)['media_id'] puts api.custom_message_send Wechat::Message.to(openid).image(media_id) end desc 'custom_voice [OPENID, VOICE_PATH]', '发送语音客服消息' def custom_voice(openid, voice_path) api = wechat_api media_id = api.media_create('voice', voice_path)['media_id'] puts api.custom_message_send Wechat::Message.to(openid).voice(media_id) end desc 'custom_video [OPENID, VIDEO_PATH]', '发送视频客服消息' method_option :title, aliases: '-h', desc: '视频标题' method_option :description, aliases: '-d', desc: '视频描述' def custom_video(openid, video_path) api = wechat_api api_opts = options.slice(:title, :description) media_id = api.media_create('video', video_path)['media_id'] puts api.custom_message_send Wechat::Message.to(openid).video(media_id, api_opts) end desc 'custom_music [OPENID, THUMBNAIL_PATH, MUSIC_URL]', '发送音乐客服消息' method_option :title, aliases: '-h', desc: '音乐标题' method_option :description, aliases: '-d', desc: '音乐描述' method_option :HQ_music_url, aliases: '-u', desc: '高质量音乐URL链接' def custom_music(openid, thumbnail_path, music_url) api = wechat_api api_opts = options.slice(:title, :description, :HQ_music_url) thumb_media_id = api.media_create('thumb', thumbnail_path)['thumb_media_id'] puts api.custom_message_send Wechat::Message.to(openid).music(thumb_media_id, music_url, api_opts) end desc 'custom_news [OPENID, NEWS_YAML_PATH]', '发送图文客服消息' def custom_news(openid, news_yaml_path) articles = YAML.load(File.read(news_yaml_path)) puts wechat_api.custom_message_send Wechat::Message.to(openid).news(articles['articles']) end desc 'template_message [OPENID, TEMPLATE_YAML_PATH]', '模板消息接口' def template_message(openid, template_yaml_path) template = YAML.load(File.read(template_yaml_path)) puts wechat_api.template_message_send Wechat::Message.to(openid).template(template['template']) end end App.start