使用 JavaScript 自动化你的 Mac

在Apple发布的Yosemite系统(OSX10.10+)中有一个被大家忽略的特性:使用 JavaScript编写自动化脚本。在这之前只能通过AppleScript语言给OS X编写自动化脚本。这几年JavaScript被移植到了各种环境,让它有更多的可能性。

开始使用

系统自带的编写自动化脚本的工具是ScriptEditor。打开编辑器,把语言从 AppleScript切换到JavaScritp。接下来我们就来实战一下,写一个每天自动发新人日报邮件的自动化脚本。具体流程是这样的:

我接到的所有需求都会记录到Reminders里,当我完成一个需求时我会把它标记为已经完成。脚本会每天晚上12点自动读取Reminders里今天完成的Reminders项作为新人日报的今日工作,读取Reminders里还为完成的项作为明日工作。从Reminders里读取内容生成邮件内容后发送到指定的邮箱。

下面直接上代码: 先去Reminders里读取内容,把今天完成的需求项保存到todayReminders数组里,把还为完成的需求项保存到todoReminders数组里

var RemindersApp = Application('Reminders');
var reminders = RemindersApp.lists.byName('Tencent').reminders;
var today = new Date();
//今日完成
var todayReminders = [];
//还没有完成
var todoReminders = [];

//判断date是否为今天
function isToday(day){
    return today.getDate() === day.getDate() && today.getMonth() === day.getMonth() && today.getFullYear() === day.getFullYear();
}

for(var i=0;i<reminders.length;i++){
    var reminder = reminders[i];
    if(reminder.completed()){
        if(isToday(reminder.completionDate())){
            todayReminders.push(reminder);
        }
    }else{
        todoReminders.push(reminder);
    }
}

接下来再生成邮件内容,保存在mailContent变量里

var mailContent = '[今日工作]\n';
for(var i=0;i<todayReminders.length;i++){
    var reminder = reminders[i];
    mailContent+=reminder.name()+' '+reminder.body()+'\n';
}
mailContent+='[明日工作]\n';
for(var i=0;i<todoReminders.length;i++){
    var reminder = reminders[i];
    mailContent+=reminder.name()+' '+reminder.body()+'\n';
}

最后发送邮件

var MailApp = Application('Mail');
var outMail = new MailApp.OutgoingMessage({
    sender:'gwuhaolin@icloud.com',
    subject:'【新人日报】halwu_' + today.getFullYear() + today.getMonth() + today.getDate(),
    content:mailContent,
    visible:false
});
MailApp.outgoingMessages.push(outMail);

编写完代码后点运行按钮就会执行我想要的操作了,再让它每天晚上定时执行我就不用写手写邮件只需要在reminders里更新我的需求就OK啦~ 除此之外我还编写了一个可以每天早上9点自动去公司oa网签到的脚步,让这些流程化的工作全交给程序的自动化处理。

查看文档

ScriptEditor的菜单里点 Window> Library 可以查看到所有支持的APP和提供可供调用的接口的文档

断点调试

当脚本逻辑很复杂时常常会遇到我们无法预料的问题,这时候就需要我们调试找出bug。Safari可以让我们像调试网页js脚本一样调试自动化脚本,具体步骤如下: 在代码的第一行插入一条语句debugger,如下:

debugger
var RemindersApp = Application('Reminders');

再打开Safari,然后运行脚本,Safari的调试工具就会自动打开进入调试模式,剩下就是像调试网页js一样调试了

运行环境

自动化脚本的js环境不兼容ES,只是桥接了大部分API。所以有些js语法和函数会不支持,以下是所有的全局变量:

Infinity: Infinity
$: function()
Application: function()
Array: function()
ArrayBuffer: function()
Automation: {Automation: Object, Progress: Progress, ObjC: Object, __private__: JSValuePrivateProperties}
Boolean: function()
DataView: Function {name: "DataView", prototype: DataView, length: 3, BYTES_PER_ELEMENT: 1}
Date: function()
Error: function()
EvalError: function()
Float32Array: Function {name: "Float32Array", prototype: Float32Array, length: 3, BYTES_PER_ELEMENT: 4}
Float64Array: Function {name: "Float64Array", prototype: Float64Array, length: 3, BYTES_PER_ELEMENT: 8}
Function: function()
Int8Array: Function {name: "Int8Array", prototype: Int8Array, length: 3, BYTES_PER_ELEMENT: 1}
Int16Array: Function {name: "Int16Array", prototype: Int16Array, length: 3, BYTES_PER_ELEMENT: 2}
Int32Array: Function {name: "Int32Array", prototype: Int32Array, length: 3, BYTES_PER_ELEMENT: 4}
JSON: JSON {}
Math: Math {E: 2.718281828459045, LN2: 0.6931471805599453, LN10: 2.302585092994046, LOG2E: 1.4426950408889634, LOG10E: 0.4342944819032518, …}
NaN: NaN
Number: function()
ObjC: {}
Object: function()
ObjectSpecifier: function()
Path: function()
Progress: Progress {}
RangeError: function()
Ref: function()
ReferenceError: function()
RegExp: function()
RemindersApp: undefined
Set: function()
String: function()
Symbol: function()
SyntaxError: function()
TypeError: function()
URIError: function()
Uint8Array: Function {name: "Uint8Array", prototype: Uint8Array, length: 3, BYTES_PER_ELEMENT: 1}
Uint8ClampedArray: Function {name: "Uint8ClampedArray", prototype: Uint8ClampedArray, length: 3, BYTES_PER_ELEMENT: 1}
Uint16Array: Function {name: "Uint16Array", prototype: Uint16Array, length: 3, BYTES_PER_ELEMENT: 2}
Uint32Array: Function {name: "Uint32Array", prototype: Uint32Array, length: 3, BYTES_PER_ELEMENT: 4}
WeakMap: function()
WeakSet: function()
__private__: JSValuePrivateProperties {}
console: {log: function}
decodeURI: function()
decodeURIComponent: function()
delay: function()
encodeURI: function()
encodeURIComponent: function()
escape: function()
eval: function()
isFinite: function()
isNaN: function()
parseFloat: function()
parseInt: function()
unescape: function()

详见Apple官方文档

脱离ScriptEditor,使用你喜爱的编辑器

使用ScriptEditor编写的脚本保存后是.scpt格式的,是以二进制格式存储的非文本文件。接下来介绍如何直接使用你喜欢的编辑器编写js文本并执行。 OSX自带一个自动化脚本解释器叫osascript,AppleScript和JavaScript编写的脚本都需要又他来解释执行,就像node解释执行js文件一样。所以可以按照上面的列子编写js脚本然后在命令行里执行命令:

osascript-l JavaScript/path/to/file.js

或者可以在js文件的顶部加上一行:

#!/usr/bin/env osascript-l JavaScript
然后在chmod +x /path/to/file.js
就可以直接执行这个js文件执行自动化操作了

更多资源

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏大内老A

ASP.NET MVC基于标注特性的Model验证:DataAnnotationsModelValidator

对于ASP.NET MVC基于标注特性的Model验证,很多人只知道应用在数据类型及其属性上用于定义验证规则和错误消息的ValidationAttribute。...

21410
来自专栏张善友的专栏

使用 Roslyn 编译器服务

.NET Core和 .NET 4.6中 的C# 6/7 中的编译器Roslyn 一个重要的特性就是"Compiler as a Service",简单的讲,就...

1908
来自专栏技术博客

Json.Net6.0入门学习试水篇

  JSON(JavaScript Object Notation) 是一种轻量级的数据交换格式。简单地说,JSON 可以将 JavaScript 对象中表示的...

932
来自专栏程序员的SOD蜜

C#调用C和C++函数的一点区别

最近做U800电话的二次开发,需要调用厂商的C函数库来打电话,后来想加入通话录音功能,但发现程序默认生产的WAV文件过大,又找了个WAV转MP3的C++函数库程...

2356
来自专栏技术之路

Caliburn.Micro学习笔记(一)----引导类和命名匹配规则

用了几天时间看了一下开源框架Caliburn.Micro 这是他源码的地址http://caliburnmicro.codeplex.com/ 文档也写的很详细...

2498
来自专栏AhDung

【手记】未能从程序集System.Net.Http.Formatting中加载类型System.Net.Http.Formatting.FormUrlEncodedMediaTypeFormatter

1653
来自专栏草根专栏

使用xUnit为.net core程序进行单元测试(上)

纵轴表示测试的深度,也就是说测试的细致程度。

3559
来自专栏数据结构与算法

RNQOJ [stupid]愚蠢的矿工(树形依赖背包)

$f[i][j] = max(f[i + 1][j - w[i]] + val[i], f[i + siz[rev[i]]][j]);$

1054
来自专栏cnblogs

对vue源码的初步认识和理解

      根据vue的官网介绍,可以得知vue是一个mvvm框架,且是响应式的。为了更深入了理解其内涵,本人以及理解实现了一个简单的mvvm学习的demo。下...

2095
来自专栏林德熙的博客

win10 uwp 依赖属性

本文告诉大家如何使用依赖属性,包括在 UWP 和 WPF 如何使用。 本文不会告诉大家依赖属性的好处,只是简单告诉大家如何使用。

702

扫码关注云+社区