├── readme.md
├── scripts
└── online_users.rb
└── workflows
└── tuple_call.alfredworkflow
/readme.md:
--------------------------------------------------------------------------------
1 | # An Alfred workflow for Tuple
2 |
3 |
4 | ⚠️ Please note that this workflow is no longer being actively maintained for the newest versions of macOS. ⚠️
5 |
6 | If you're interested in helping as a maintainer, please reach out to support@tuple.app.
7 |
8 |
9 | _A workflow for using [Tuple](https://tuple.app) from [Alfred](alfredapp.com)_
10 |
11 | ## Make a call
12 |
13 | Start a call with a friend or teammate who is currently online.
14 |
15 | **Installation**
16 |
17 | ⬇️ [Download the workflow](https://github.com/tupleapp/alfred-workflows/raw/master/workflows/tuple_call.alfredworkflow)
18 |
19 | After downloading, double-click the `.alfredworkflow` file.
20 |
21 | **Usage**
22 |
23 | 1. Open Alfred
24 | 2. Type: `tc` ("tuple call")
25 | 3. Start typing your friend's email
26 | 4. Select friend and hit 'enter'.
27 |
--------------------------------------------------------------------------------
/scripts/online_users.rb:
--------------------------------------------------------------------------------
1 | # online_users.rb
2 | #
3 | # Author: Spencer Dixon
4 | # Copyright: Tuple, LLC
5 |
6 | query = ARGV[0]
7 |
8 | # -------
9 | # Utility
10 | # -------
11 |
12 | def pbpaste
13 | `pbpaste`
14 | end
15 |
16 | def pbcopy(input)
17 | str = input.to_s
18 | IO.popen('pbcopy', 'w') { |f| f << str }
19 | str
20 | end
21 |
22 | def with_sandboxed_clipboard(&block)
23 | previous = pbpaste
24 | yield block
25 | pbcopy(previous)
26 | end
27 |
28 | def regex_fuzzy_search(query, list)
29 | query_reg = /#{query.split('').join('.*?')}/
30 | sorted = []
31 | list.each do |string|
32 | match = query_reg.match string
33 | sorted << {string: string, rank: match.to_s.length} if match
34 | end
35 | sorted.sort_by! {|i| i[:rank] }
36 | sorted
37 | end
38 |
39 | # ----
40 | # Main
41 | # ----
42 |
43 | # If tuple responds with this special string we're online and ready to make calls
44 | ONLINE_MAGIC_KEY = "tuple-availability: online"
45 | # Timeout after 2 seconds if Tuple is unable to boot and connect
46 | MAX_CONNECT_ATTEMPTS = 20
47 |
48 | with_sandboxed_clipboard do
49 | # -g to prevent Tuple from coming to foreground. We want Alfred to remain key.
50 | # /noop will do nothing but ensure Tuple is running if it's not already going
51 | system('open -g tuple://noop')
52 |
53 | is_online = false
54 | attempts = 0
55 | until is_online || attempts == MAX_CONNECT_ATTEMPTS
56 | system('open -g tuple://availability-status')
57 | result = pbpaste
58 |
59 | if result == ONLINE_MAGIC_KEY
60 | is_online = true
61 | else
62 | attempts += 1
63 | sleep(0.1)
64 | end
65 | end
66 |
67 | if is_online
68 | system('open -g tuple://online-users')
69 | online_users = pbpaste
70 |
71 | if online_users.include?(',')
72 | users = online_users.split(',')
73 | else
74 | users = [online_users]
75 | end
76 |
77 | if query.length > 0
78 | sorted = regex_fuzzy_search(query, users)
79 | else
80 | sorted = users
81 | end
82 |
83 | users_string = ""
84 | if users.count == 0
85 | users_string = "- No online users
"
86 | elsif sorted.count == 0
87 | users_string = "- Unable to find any matching online users
"
88 | else
89 | sorted.each do |user|
90 | users_string << %Q{- #{user[:string]}
}
91 | end
92 | end
93 | else
94 | users_string = "- Tuple is unable to connect. Try restarting
"
95 | end
96 |
97 | xml = <
99 |
100 | #{users_string}
101 |
102 |
103 | EOS
104 |
105 | puts xml
106 | end
107 |
--------------------------------------------------------------------------------
/workflows/tuple_call.alfredworkflow:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tupleapp/alfred-workflows/a233a3d669cfafb04fc49b674c8f6d83265b68f2/workflows/tuple_call.alfredworkflow
--------------------------------------------------------------------------------