212 lines
4.3 KiB
Markdown
212 lines
4.3 KiB
Markdown
# Photo Inbox
|
|
|
|
macOS HTTP receiver for sending JPEG uploads into a local photo inbox. Clients
|
|
can be iPhone Shortcuts, curl, another phone, a script, or any system that can
|
|
POST a JPEG file. The server currently supports macOS only because clipboard,
|
|
Finder reveal, and notifications use macOS APIs/tools.
|
|
|
|
By default, each upload is saved locally and the current batch is copied to the
|
|
macOS clipboard as native file URLs.
|
|
|
|
## Behavior
|
|
|
|
- Saves photos to `~/Pictures/Photo Inbox` by default.
|
|
- Groups consecutive uploads into a batch.
|
|
- Every new photo extends the batch by `5s`.
|
|
- Every new photo immediately refreshes the clipboard with the full batch.
|
|
- When no new photo arrives before debounce expires, a summary notification is shown.
|
|
|
|
This uses a small Swift helper and `NSPasteboard.writeObjects`, which matches
|
|
Finder-style file clipboard behavior.
|
|
|
|
## Start the receiver
|
|
|
|
Recommended:
|
|
|
|
```bash
|
|
cp scripts/iphone-photo-inbox/.env.example scripts/iphone-photo-inbox/.env
|
|
scripts/iphone-photo-inbox/run.sh
|
|
```
|
|
|
|
`.env` is loaded automatically and does not override variables already exported
|
|
in the shell. `run.sh` compiles the native pasteboard helper when it is missing
|
|
or older than the Swift source.
|
|
|
|
The receiver listens on:
|
|
|
|
```text
|
|
http://MAC_IP:8787/upload
|
|
```
|
|
|
|
Find the Mac IP address on the current network:
|
|
|
|
```bash
|
|
ipconfig getifaddr en0
|
|
```
|
|
|
|
If that does not return an IP, use:
|
|
|
|
```bash
|
|
ifconfig
|
|
```
|
|
|
|
## Generic client contract
|
|
|
|
Send a JPEG request body:
|
|
|
|
```bash
|
|
curl --request POST \
|
|
--data-binary @photo.jpg \
|
|
"http://MAC_IP:8787/upload?token=choose-a-token"
|
|
```
|
|
|
|
Successful response body is the saved local file path.
|
|
|
|
## iPhone Shortcuts guide
|
|
|
|
Use a Dictionary near the top of the Shortcut:
|
|
|
|
```text
|
|
mac_ip: 192.168.11.186
|
|
port: 8787
|
|
token: choose-a-token
|
|
```
|
|
|
|
Build the URL from the dictionary:
|
|
|
|
```text
|
|
http://[mac_ip]:[port]/upload?token=[token]
|
|
```
|
|
|
|
Camera Shortcut:
|
|
|
|
```text
|
|
Dictionary
|
|
mac_ip: 192.168.11.186
|
|
port: 8787
|
|
token: choose-a-token
|
|
|
|
Text
|
|
http://[mac_ip]:[port]/upload?token=[token]
|
|
|
|
Take Photo
|
|
Show Camera Preview: On
|
|
|
|
Get Contents of URL
|
|
URL: Text
|
|
Method: POST
|
|
Request Body: File
|
|
File: Photo
|
|
|
|
Show Notification
|
|
Sent to photo inbox
|
|
```
|
|
|
|
On the tested iPhone flow, `Take Photo` already produces a JPEG, so no
|
|
conversion step is needed.
|
|
|
|
Existing Photos Shortcut:
|
|
|
|
```text
|
|
Receive Images and Media from Share Sheet
|
|
Repeat with Each Item in Shortcut Input
|
|
Convert Image
|
|
Image: Repeat Item
|
|
Format: JPEG
|
|
Get Contents of URL
|
|
URL: http://[mac_ip]:[port]/upload?token=[token]
|
|
Method: POST
|
|
Request Body: File
|
|
File: Converted Image
|
|
End Repeat
|
|
Show Notification
|
|
Sent to photo inbox
|
|
```
|
|
|
|
## Configuration
|
|
|
|
Common `.env` values:
|
|
|
|
```bash
|
|
PHOTO_INBOX_TOKEN=choose-a-token
|
|
PHOTO_INBOX_HOST=0.0.0.0
|
|
PHOTO_INBOX_PORT=8787
|
|
PHOTO_INBOX_DIR=/Users/david/Pictures/Photo Inbox
|
|
PHOTO_INBOX_DEBOUNCE_SECONDS=5
|
|
PHOTO_INBOX_CLIPBOARD=1
|
|
PHOTO_INBOX_NOTIFY=1
|
|
```
|
|
|
|
Other useful options:
|
|
|
|
```bash
|
|
scripts/iphone-photo-inbox/run.sh --no-clipboard
|
|
scripts/iphone-photo-inbox/run.sh --no-notify
|
|
scripts/iphone-photo-inbox/run.sh --reveal
|
|
PHOTO_INBOX_DEBUG=1 scripts/iphone-photo-inbox/run.sh
|
|
```
|
|
|
|
## Project integration
|
|
|
|
Keep this utility as an isolated image mailbox. If a project wants easy access,
|
|
link the project inbox to the mailbox instead of making this utility know about
|
|
the project.
|
|
|
|
Example:
|
|
|
|
```bash
|
|
mkdir -p ai/inbox
|
|
ln -s "$HOME/Pictures/Photo Inbox" ai/inbox/photos
|
|
```
|
|
|
|
Or point the receiver at a project-owned folder from `.env`:
|
|
|
|
```bash
|
|
PHOTO_INBOX_DIR=/absolute/path/to/project/ai/inbox/photos
|
|
```
|
|
|
|
The symlink approach keeps this utility reusable across projects and devices.
|
|
|
|
## Troubleshooting
|
|
|
|
Startup should print:
|
|
|
|
```text
|
|
saving to: ...
|
|
debounce seconds: 5
|
|
clipboard: True
|
|
notify: True
|
|
```
|
|
|
|
After each upload, expect:
|
|
|
|
```text
|
|
clipboard updated count=2
|
|
saved ... batch_count=2
|
|
```
|
|
|
|
After the debounce window closes, expect:
|
|
|
|
```text
|
|
batch notification sent count=2
|
|
batch finalized count=2 dir=...
|
|
```
|
|
|
|
With `PHOTO_INBOX_DEBUG=1`, a two-photo batch should report:
|
|
|
|
```text
|
|
pasteboard files=2 items=2
|
|
```
|
|
|
|
The native file clipboard helper lives at:
|
|
|
|
```text
|
|
scripts/iphone-photo-inbox/copy_files_to_clipboard.swift
|
|
```
|
|
|
|
The compiled binary is ignored by git and generated by `run.sh`:
|
|
|
|
```text
|
|
scripts/iphone-photo-inbox/copy_files_to_clipboard
|
|
```
|