Skip to content

Instantly share code, notes, and snippets.

@YohannParis
Created November 10, 2023 20:39
Show Gist options
  • Save YohannParis/5d47dda2deae8a14030b07aa6c13b877 to your computer and use it in GitHub Desktop.
Save YohannParis/5d47dda2deae8a14030b07aa6c13b877 to your computer and use it in GitHub Desktop.
Bash script to synchronize GitHub task to Things.app
#!/bin/bash
# Script to sync GitHub tasks with Things locally
# Run this script with a cron job every hour on weekdays from 8 AM to 6 PM.
# Commands to make it happen:
# > brew install jq
# > chmod +x script.sh
# > crontab -e
# > 0 8-18 * * 1-5 /path/to/github_to_things.sh
# GitHub organization name and your GitHub username
github_org_name="your_github_organization"
github_username="your_github_userbane"
github_token="your_github_token"
# Things URL scheme
things_token="your_things_token"
things_area="your_things_area"
# File to store GitHub issue IDs and Things task IDs
data_file="./data.txt"
temp_file="./temporary.txt"
# Check if the data file exists, and create it if it doesn't
if [ ! -e "$data_file" ]; then
touch "$data_file"
fi
# Check if the temporary file exists, and create it if it doesn't
if [ ! -e "$temp_file" ]; then
touch "$temp_file"
fi
# Function to call x-callback-url and retrieve x-things-id
# Protocol: https://x-callback-url.com
# Tool: https://github.com/martinfinke/xcall
# Example: https://utf9k.net/questions/macos-invoke-x-callback-url/
xcall() {
local json_response
json_response=$(/Applications/xcall.app/Contents/MacOS/xcall -url $1 -activateApp NO)
# Extract the value of "x-things-id" key from the JSON response
x_things_id=$(echo "$json_response" | jq --raw-output '.["x-things-id"]')
# Check if x-things-id is not empty
if [ -n "$x_things_id" ]; then
echo "$x_things_id"
else
echo "x-things-id not found in JSON response."
fi
}
# Function to save key-value pairs to a file
save_key_value() {
echo "$1=$2" >> "$data_file"
echo "Line with ID $1 saved with Things ID $2"
}
# Function to retrieve a value by key from the file
get_value_by_key() {
grep --extended-regexp "^$1=" "$data_file" | cut -d "=" -f 2
}
# Function to remove a line from the data file based on an ID
remove_key_value() {
local id_to_remove="$1"
# Check if the line with the ID exists in the data file
if grep --quiet "^$id_to_remove=" "$data_file"; then
# Create a temporary file without the line to be removed
grep --invert-match "^$id_to_remove=" "$data_file" > "$temp_file"
# Overwrite the original data file with the updated content
mv "$temp_file" "$data_file"
echo "Line with ID $id_to_remove removed from the data file."
else
echo "Line with ID $id_to_remove not found in the data file."
fi
}
# Fetch GitHub issues assigned to you
issues=$(curl --silent --header "Authorization: token $github_token" \
"https://api.github.com/orgs/$github_org_name/issues?assignee=$github_username&state=all&per_page=100")
# Loop through the issues and create/update tasks in Things
for row in $(echo "$issues" | jq --raw-output '.[] | @base64'); do
# Decode each line, then make sure it is URI encoded
_jq() {
echo "$row" | base64 --decode | jq --raw-output "$1"
}
issue_id=$(_jq '.id')
issue_title=$(_jq '.title')
issue_title_encoded=$(jq --slurp --raw-input --raw-output @uri <<< $issue_title)
issue_state=$(_jq '.state')
issue_url=$(jq --slurp --raw-input --raw-output @uri <<< $(_jq '.html_url'))
issue_created_at=$(_jq '.created_at')
echo "--"
echo "Issue ($issue_state) - $issue_title"
# Retrieve Things task ID for this GitHub issue (if it exists)
things_task_id=$(get_value_by_key "$issue_id")
# Depending on the GitHub issue state, create or update tasks in Things
if [ "$issue_state" = "open" ]; then
# Create a new task and save the Things task ID
if [ -z "$things_task_id" ]; then
url="things:///add?auth-token=$things_token&list=$things_area&title=$issue_title_encoded&notes=$issue_url&tags=GitHub&creation-date=$issue_created_at"
things_task_id=$(xcall $url)
save_key_value "$issue_id" "$things_task_id"
else
# Update the existing task
xcall "things:///update?auth-token=$things_token&id=$things_task_id"
fi
elif [ "$issue_state" = "closed" ]; then
# Close the task if the GitHub issue is closed
if [ -n "$things_task_id" ]; then
xcall "things:///update?auth-token=$things_token&id=$things_task_id&completed=true"
remove_key_value "$things_task_id"
fi
fi
done
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment