├── 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 --------------------------------------------------------------------------------