-
-
Notifications
You must be signed in to change notification settings - Fork 5
/
notificator
executable file
·183 lines (155 loc) · 4.77 KB
/
notificator
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
#!/bin/zsh
####################################################
### Created by Vítor Galvão ###
### Find the latest version at: ###
### https://github.com/vitorgalvao/notificator ###
####################################################
readonly program="$(basename "${0}")"
# Helpers
function show_notification {
/usr/bin/open "${app}" --args "${notificator_message}" "${notificator_title}" "${notificator_subtitle}" "${notificator_sound}"
}
function make_icns {
# Setup
local -r file="${1}"
local -r tmp_dir="$(/usr/bin/mktemp -d)"
local -r icon="${tmp_dir}/icon.icns"
local -r iconset="${tmp_dir}/icon.iconset"
/bin/mkdir "${iconset}"
# Create iconset
for size in {16,32,64,128,256,512}
do
/usr/bin/sips --resampleHeightWidth "${size}" "${size}" "${file}" --out "${iconset}/icon_${size}x${size}.png" &> /dev/null
/usr/bin/sips --resampleHeightWidth "$((size * 2))" "$((size * 2))" "${file}" --out "${iconset}/icon_${size}x${size}@2x.png" &> /dev/null
done
# Convert to icns
/usr/bin/iconutil --convert icns "${iconset}" --output "${icon}"
# Clean up and return path to icns
/bin/rm -rf "${iconset}"
echo "${icon}"
}
function usage {
echo "
Trigger macOS notifications from Alfred, using the Workflow icon
Usage:
${program} --message <text> [options]
Options:
-m, --message <text> Message text
-t, --title <text> Title text
-s, --subtitle <text> Subtitle text
-p, --sound <name> Sound name (from /System/Library/Sounds)
-h, --help Show this help
" | sed -E 's/^ {4}//'
}
# Options
args=()
while [[ "${1}" ]]
do
case "${1}" in
-h | --help)
usage
exit 0
;;
-m | --message)
readonly notificator_message="${2}"
shift
;;
-t | --title)
readonly notificator_title="${2}"
shift
;;
-s | --subtitle)
readonly notificator_subtitle="${2}"
shift
;;
-p | --sound)
readonly notificator_sound="${2}"
shift
;;
--)
shift
args+=("${@}")
break
;;
-*)
echo "Unrecognised option: ${1}"
exit 1
;;
*)
args+=("${1}")
;;
esac
shift
done
set -- "${args[@]}"
# Check for required arguments
if [[ -z "${notificator_message}" ]]
then
echo 'A message is mandatory! Aborting…' >&2
exit 1
fi
readonly bundle_id="$(/usr/bin/tr -cd '[:alnum:]._-' <<< "${alfred_workflow_bundleid}")"
readonly name="$(/usr/bin/tr -cd '[:alnum:]._- ' <<< "${alfred_workflow_name}")"
readonly icon="${alfred_preferences}/workflows/${alfred_workflow_uid}/icon.png"
readonly app="${alfred_workflow_cache}/Notificator for ${name}.app"
readonly plist="${app}/Contents/Info.plist"
# Exit early if Notificator exists and was modified fewer than 30 days ago
if [[ "$(/bin/date -r "${app}" +%s)" -gt "$(/bin/date -v -30d +%s)" ]]
then
show_notification
exit 0
fi
# Pre-build checks
if [[ -z "${bundle_id}" ]]
then
echo "Workflow is missing the bundle identifier! Aborting…" >&2
exit 1
fi
if [[ -z "${name}" ]]
then
echo "Workflow is missing the name! Aborting…" >&2
exit 1
fi
if [[ ! -f "${icon}" ]]
then
echo "Workflow is missing the icon! Aborting…" >&2
exit 1
fi
# Build Notificator
readonly jxa_script='
// Build argv/argc in a way that can be used from the applet inside the app bundle
ObjC.import("Foundation")
const args = $.NSProcessInfo.processInfo.arguments
const argv = []
const argc = args.count
for (let i = 0; i < argc; i++) { argv.push(args.objectAtIndex(i).js) }
// Notification script
const app = Application.currentApplication()
app.includeStandardAdditions = true
if (argv.length < 2) { // We use "2" because the script will always see at least one argument: the applet itself
argv[1] = "Opening usage instructions…"
argv[2] = "Notificator is a command-line app"
argv[4] = "Funk"
app.openLocation("https://github.com/vitorgalvao/notificator#usage")
}
const message = argv[1]
const title = argv[2]
const subtitle = argv[3]
const sound = argv[4]
const options = {}
if (title) options.withTitle = title
if (subtitle) options.subtitle = subtitle
if (sound) options.soundName = sound
app.displayNotification(message, options)
'
[[ -d "${app}" ]] && /bin/rm -r "${app}"
/bin/mkdir -p "${alfred_workflow_cache}"
/usr/bin/osacompile -l JavaScript -o "${app}" -e "${jxa_script}" 2> /dev/null
# Modify Notificator
/usr/libexec/PlistBuddy -c "add :CFBundleIdentifier string ${bundle_id}.notificator" "${plist}"
/usr/libexec/PlistBuddy -c 'add :LSUIElement string 1' "${plist}"
/bin/mv "$(make_icns "${icon}")" "${app}/Contents/Resources/applet.icns"
# Redo signature
/usr/bin/codesign --remove-signature "${app}"
/usr/bin/codesign --sign - "${app}"
show_notification