diff --git a/.gitignore b/.gitignore
index 91010ec..4b1438f 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,4 +1,5 @@
# Project oriented files to be ignored
+.env
info.plist
lib/
assets/
diff --git a/README.md b/README.md
index cc467cc..64ea99c 100644
--- a/README.md
+++ b/README.md
@@ -1,6 +1,6 @@
-
+
Alfred 2-Factor Authenticator Workflow
diff --git a/alfred-totp.py b/alfred-totp.py
index f686875..410b042 100644
--- a/alfred-totp.py
+++ b/alfred-totp.py
@@ -37,18 +37,6 @@ def main(wf):
# Get args from Workflow3, already in normalized Unicode.
# This is also necessary for "magic" arguments to work.
- # py3
- # from subprocess import run, PIPE
- # py2
- # from subprocess import check_output as run, PIPE
- # import hmac
- # import base64
- # import hashlib
- # import codecs
- # import time
- # import json
- # import re
-
def get_steamguard_code(secret):
"""
@@ -60,35 +48,34 @@ def get_steamguard_code(secret):
'X', 'Y']
# py3
"""
- msg = bytes.fromhex(('%016x' % int(time.time() // 30)))
- key = base64.b64decode(secret)
- auth = hmac.new(key, msg, hashlib.sha1)
+ byte_time = bytes.fromhex(('%016x' % int(time.time() // 30)))
+ auth = hmac.new(base64.b64decode(secret), byte_time, hashlib.sha1)
digest = auth.digest()
start = digest[19] & 0xF
code = digest[start:start + 4]
auth_code_raw = int(codecs.encode(code, 'hex'), 16) & 0x7FFFFFFF
auth_code = []
- for i in range(5):
+ for _ in range(5):
auth_code.append(steam_decode_chars[int(auth_code_raw % len(steam_decode_chars))])
auth_code_raw /= len(steam_decode_chars)
return ''.join(auth_code)
"""
# py2
- auth_code = ''
+ auth_code = []
hex_time = ('%016x' % (time.time() // 30))
byte_time = hex_time.decode('hex')
digest = hmac.new(base64.b64decode(secret), byte_time, hashlib.sha1).digest()
begin = ord(digest[19:20]) & 0xF
- c_int = int((digest[begin:begin + 4]).encode('hex'), 16) & 0x7fffffff
+ auth_code_raw = int((digest[begin:begin + 4]).encode('hex'), 16) & 0x7fffffff
for _ in range(5):
- auth_code += steam_decode_chars[c_int % len(steam_decode_chars)]
- c_int /= len(steam_decode_chars)
+ auth_code.append(steam_decode_chars[auth_code_raw % len(steam_decode_chars)])
+ auth_code_raw /= len(steam_decode_chars)
- return auth_code
+ return ''.join(auth_code)
# READ keychain pass and parse escaping characters
keychain_name = "{}.keychain".format(os.getenv('keychain_name'))
@@ -136,7 +123,6 @@ def get_steamguard_code(secret):
# if service is a steamguard, call steamguard code-gen method
if not service in steam_accounts:
# Standard TOTP Services
- # Process.run("oathtool", ["--totp", "-b", pass], output: io)
otp_key = ''.join((filter(None, run("/usr/local/bin/oathtool --totp -b \"{}\"".format(secret), shell=True).split("\n"))))
wf.add_item('{}'.format(service), otp_key, valid=True, arg=otp_key)
else:
diff --git a/sync-workflow.sh b/sync-workflow.sh
new file mode 100755
index 0000000..2705720
--- /dev/null
+++ b/sync-workflow.sh
@@ -0,0 +1,92 @@
+#!/usr/bin/env bash
+# BASH script to sync alfred workflow directory and export it as workflow to releases directory (working directory).
+# Parses .env for workflow UUID.
+# UUID be found at $HOME/Alfred/Alfred.alfredpreferences/workflows/user.workflow.XXXXXX-XXXX-XXX-XXXXXXXXX
+# SAMPLE .env
+# UUID=C88D3289-A059-48D6-8FA1-D96F47205FAE
+
+set -e
+cd "$(dirname "$0")"
+
+UUID=""
+
+# Current Arguments: sync - Sync current directory to workflow directory overwriting changes
+# revsync - Sync workflow directory to current directory overwriting changes
+# export - Export the alfred workflow except values of "variablesdontexport" variables
+
+_init_env() {
+ if [ -f .env ] && [ -s .env ]; then
+ export $(grep -v '^#' .env | xargs)
+ export workflow_dir="$HOME/Alfred/Alfred.alfredpreferences/workflows/user.workflow.$UUID"
+ export info_plist="${workflow_dir}/info.plist"
+ else
+ echo -e ".env not setup, please have a look at this script to giddyap!"
+ exit 1
+ fi
+}
+
+_export_workflow() {
+ # Create releases directory if needed
+ if [[ ! -d "./releases" ]]; then
+ mkdir "releases"
+ fi
+ readonly workflow_name="$(/usr/libexec/PlistBuddy -c 'print name' "${info_plist}")"
+ readonly workflow_file="./releases/${workflow_name}.alfredworkflow"
+
+ if /usr/libexec/PlistBuddy -c 'print variablesdontexport' "${info_plist}" &> /dev/null; then
+ readonly workflow_dir_to_package="$(mktemp -d)"
+ cp -R "${workflow_dir}/"* "${workflow_dir_to_package}"
+
+ readonly tmp_info_plist="${workflow_dir_to_package}/info.plist"
+ /usr/libexec/PlistBuddy -c 'Print variablesdontexport' "${tmp_info_plist}" | grep ' ' | sed -E 's/ {4}//' | xargs -I {} /usr/libexec/PlistBuddy -c "Set variables:'{}' ''" "${tmp_info_plist}"
+ else
+ readonly workflow_dir_to_package="${workflow_dir}"
+ fi
+
+ ditto -ck "${workflow_dir_to_package}" "${workflow_file}"
+ echo -e "Exported worflow to ${workflow_file}"
+}
+
+_sync_workflow() {
+ echo -e "Copying files from:\n$(pwd -P) to $workflow_dir"
+ read -r -p "Are you sure? [y/N] " response
+ if [[ "$response" =~ ^([yY][eE][sS]|[yY])$ ]]; then
+ # cp -rf * "$workflow_dir"
+ rsync -avr --exclude='releases' --exclude=".*" --exclude="assets" --exclude="info.plist" . "$workflow_dir"
+ fi
+}
+
+_revsync_workflow() {
+ echo -e "Copying files from:\n$workflow_dir to $(pwd -P) "
+ read -r -p "Are you sure? [y/N] " response
+ if [[ "$response" =~ ^([yY][eE][sS]|[yY])$ ]]; then
+ # cp -rf "$workflow_dir" .
+ rsync -avr --exclude='releases' --exclude=".*" --exclude="assets" "$workflow_dir" .
+ fi
+}
+
+while [ "$1" != "" ]; do
+ PARAM=`echo $1 | awk -F= '{print $1}'`
+ VALUE=`echo $1 | awk -F= '{print $2}'`
+ case $PARAM in
+ sync | --sync)
+ _init_env
+ _sync_workflow
+ exit
+ ;;
+ revsync | --revsync)
+ _init_env
+ exit
+ ;;
+ export| --export)
+ _init_env
+ _export_workflow
+ exit
+ ;;
+ *)
+ echo -e "ERROR: unknown argument \"$PARAM\""
+ exit 1
+ ;;
+ esac
+ shift
+done