imessage-monitor 0.1.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- imessage_monitor-0.1.0/.github/workflows/publish.yml +35 -0
- imessage_monitor-0.1.0/.gitignore +10 -0
- imessage_monitor-0.1.0/.python-version +1 -0
- imessage_monitor-0.1.0/CLAUDE.md +6 -0
- imessage_monitor-0.1.0/PKG-INFO +224 -0
- imessage_monitor-0.1.0/README.md +189 -0
- imessage_monitor-0.1.0/config.toml +33 -0
- imessage_monitor-0.1.0/example_usage.py +162 -0
- imessage_monitor-0.1.0/pyproject.toml +62 -0
- imessage_monitor-0.1.0/resources/apple_shortcuts_vs_applescript.md +133 -0
- imessage_monitor-0.1.0/resources/applescript_guide.md +1081 -0
- imessage_monitor-0.1.0/resources/imessage_db_SERVICE_LAYER_GUIDE.md +561 -0
- imessage_monitor-0.1.0/scratch_scripts/test_apple_db.py +92 -0
- imessage_monitor-0.1.0/src/imessage_monitor/__init__.py +19 -0
- imessage_monitor-0.1.0/src/imessage_monitor/config.py +278 -0
- imessage_monitor-0.1.0/src/imessage_monitor/display.py +772 -0
- imessage_monitor-0.1.0/src/imessage_monitor/exceptions.py +41 -0
- imessage_monitor-0.1.0/src/imessage_monitor/message_parser.py +423 -0
- imessage_monitor-0.1.0/src/imessage_monitor/monitor.py +186 -0
- imessage_monitor-0.1.0/src/imessage_monitor/outbound.py +772 -0
- imessage_monitor-0.1.0/src/imessage_monitor/utils.py +122 -0
- imessage_monitor-0.1.0/tests/test_config.py +686 -0
- imessage_monitor-0.1.0/tests/test_outbound.py +216 -0
- imessage_monitor-0.1.0/uv.lock +240 -0
@@ -0,0 +1,35 @@
|
|
1
|
+
name: Publish to PyPI
|
2
|
+
|
3
|
+
on:
|
4
|
+
push:
|
5
|
+
branches: [main]
|
6
|
+
tags:
|
7
|
+
- 'v*'
|
8
|
+
workflow_dispatch:
|
9
|
+
|
10
|
+
jobs:
|
11
|
+
publish:
|
12
|
+
runs-on: ubuntu-latest
|
13
|
+
environment: release
|
14
|
+
permissions:
|
15
|
+
id-token: write
|
16
|
+
contents: read
|
17
|
+
|
18
|
+
steps:
|
19
|
+
- uses: actions/checkout@v4
|
20
|
+
|
21
|
+
- name: Install uv
|
22
|
+
uses: astral-sh/setup-uv@v4
|
23
|
+
with:
|
24
|
+
enable-cache: true
|
25
|
+
|
26
|
+
- name: Set up Python
|
27
|
+
run: uv python install
|
28
|
+
|
29
|
+
- name: Build package
|
30
|
+
run: uv build
|
31
|
+
|
32
|
+
- name: Publish to PyPI
|
33
|
+
uses: pypa/gh-action-pypi-publish@release/v1
|
34
|
+
with:
|
35
|
+
repository-url: https://upload.pypi.org/legacy/
|
@@ -0,0 +1 @@
|
|
1
|
+
3.13
|
@@ -0,0 +1,6 @@
|
|
1
|
+
The package manager you use is uv -- python and packages will be run using uv run, dependencies will be managed using uv add/rm.
|
2
|
+
|
3
|
+
Reference documentation is found in respources.
|
4
|
+
|
5
|
+
The ultimate goal of this project is to query an existing imessage database (w/in some daterange and optionally limited to a list of numbers/contacts) and store the messages in the imessage-db database and poll for new messages while running (and ingest all messages that have been received during downtime on startup w/o introducing duplicates into the database)
|
6
|
+
|
@@ -0,0 +1,224 @@
|
|
1
|
+
Metadata-Version: 2.4
|
2
|
+
Name: imessage-monitor
|
3
|
+
Version: 0.1.0
|
4
|
+
Summary: A Python library for monitoring and extracting iMessage data with real-time capabilities
|
5
|
+
Author-email: Christian Hale <bhschristian@gmail.com>
|
6
|
+
Maintainer-email: Christian Hale <bhschristian@gmail.com>
|
7
|
+
License: MIT
|
8
|
+
Keywords: ascii-art,chat,imessage,macos,messages,monitoring,real-time,sms
|
9
|
+
Classifier: Development Status :: 4 - Beta
|
10
|
+
Classifier: Intended Audience :: Developers
|
11
|
+
Classifier: License :: OSI Approved :: MIT License
|
12
|
+
Classifier: Operating System :: MacOS
|
13
|
+
Classifier: Programming Language :: Python :: 3
|
14
|
+
Classifier: Programming Language :: Python :: 3.11
|
15
|
+
Classifier: Programming Language :: Python :: 3.12
|
16
|
+
Classifier: Programming Language :: Python :: 3.13
|
17
|
+
Classifier: Topic :: Communications :: Chat
|
18
|
+
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
19
|
+
Classifier: Topic :: System :: Monitoring
|
20
|
+
Classifier: Topic :: Utilities
|
21
|
+
Requires-Python: >=3.11
|
22
|
+
Requires-Dist: ascii-magic>=2.3.0
|
23
|
+
Requires-Dist: pillow-heif>=1.0.0
|
24
|
+
Requires-Dist: tomli-w>=1.2.0
|
25
|
+
Provides-Extra: dev
|
26
|
+
Requires-Dist: black>=23.0.0; extra == 'dev'
|
27
|
+
Requires-Dist: mypy>=1.0.0; extra == 'dev'
|
28
|
+
Requires-Dist: pytest-asyncio>=1.0.0; extra == 'dev'
|
29
|
+
Requires-Dist: pytest>=8.4.1; extra == 'dev'
|
30
|
+
Requires-Dist: ruff>=0.1.0; extra == 'dev'
|
31
|
+
Provides-Extra: test
|
32
|
+
Requires-Dist: pytest-asyncio>=1.0.0; extra == 'test'
|
33
|
+
Requires-Dist: pytest>=8.4.1; extra == 'test'
|
34
|
+
Description-Content-Type: text/markdown
|
35
|
+
|
36
|
+
# iMessage Monitor
|
37
|
+
|
38
|
+
A Python library for monitoring and extracting iMessage data with real-time capabilities and beautiful terminal display.
|
39
|
+
|
40
|
+
## Features
|
41
|
+
|
42
|
+
- = **Real-time monitoring** of incoming iMessages
|
43
|
+
- =ļæ½ **Pretty-printed chat bubbles** with proper left/right alignment
|
44
|
+
- <ļæ½ **Sticker and reaction support** with emoji display
|
45
|
+
- =ļæ½ **ASCII art generation** for image attachments (optional)
|
46
|
+
- =ļæ½ **Attachment handling** including HEIC conversion
|
47
|
+
- =ļæ½ **Outbound messaging** via AppleScript or Shortcuts
|
48
|
+
- =ļæ½ **Safe database access** with read-only mode
|
49
|
+
|
50
|
+
## Requirements
|
51
|
+
|
52
|
+
- **macOS only** (requires access to Messages database)
|
53
|
+
- **Python 3.11+**
|
54
|
+
- **Full Disk Access** permission for terminal/IDE
|
55
|
+
|
56
|
+
## Installation
|
57
|
+
|
58
|
+
```bash
|
59
|
+
pip install imessage-monitor
|
60
|
+
|
61
|
+
or
|
62
|
+
|
63
|
+
uv add imessage-monitor
|
64
|
+
```
|
65
|
+
|
66
|
+
|
67
|
+
## Quick Start
|
68
|
+
|
69
|
+
### Real-time Monitoring
|
70
|
+
|
71
|
+
```python
|
72
|
+
from imessage_monitor import iMessageMonitor
|
73
|
+
from imessage_monitor.display import pretty_print_bubble
|
74
|
+
|
75
|
+
def handle_message(message):
|
76
|
+
"""Handle new messages with pretty printing."""
|
77
|
+
print(pretty_print_bubble(message, show_ascii_art=True))
|
78
|
+
|
79
|
+
# Start monitoring
|
80
|
+
monitor = iMessageMonitor()
|
81
|
+
monitor.start(message_callback=handle_message)
|
82
|
+
|
83
|
+
# Keep running (in practice, you'd run this in an async loop)
|
84
|
+
input("Press Enter to stop...")
|
85
|
+
monitor.stop()
|
86
|
+
```
|
87
|
+
|
88
|
+
### Message Retrieval
|
89
|
+
|
90
|
+
```python
|
91
|
+
from imessage_monitor import iMessageMonitor, to_json
|
92
|
+
|
93
|
+
# Get recent messages
|
94
|
+
monitor = iMessageMonitor()
|
95
|
+
messages = monitor.get_recent_messages(limit=50)
|
96
|
+
|
97
|
+
# Convert to JSON
|
98
|
+
json_data = to_json(messages)
|
99
|
+
print(json_data)
|
100
|
+
```
|
101
|
+
|
102
|
+
### Sending Messages
|
103
|
+
|
104
|
+
```python
|
105
|
+
from imessage_monitor import ImessageOutbound
|
106
|
+
|
107
|
+
# Send via AppleScript
|
108
|
+
outbound = ImessageOutbound()
|
109
|
+
success = outbound.send_message_applescript("+1234567890", "Hello!")
|
110
|
+
|
111
|
+
# Send attachment
|
112
|
+
success = outbound.send_attachment_applescript("+1234567890", "/path/to/file.jpg")
|
113
|
+
```
|
114
|
+
|
115
|
+
## Display Options
|
116
|
+
|
117
|
+
The library provides three pretty-print formats:
|
118
|
+
|
119
|
+
### Chat Bubbles
|
120
|
+
```python
|
121
|
+
from imessage_monitor.display import pretty_print_bubble
|
122
|
+
|
123
|
+
# Basic bubble (no ASCII art)
|
124
|
+
print(pretty_print_bubble(message))
|
125
|
+
|
126
|
+
# With ASCII art for images
|
127
|
+
print(pretty_print_bubble(message, show_ascii_art=True))
|
128
|
+
```
|
129
|
+
|
130
|
+
### Reactions
|
131
|
+
```python
|
132
|
+
from imessage_monitor.display import pretty_print_reaction
|
133
|
+
|
134
|
+
print(pretty_print_reaction(message)) # Shows d, =M, =, etc.
|
135
|
+
```
|
136
|
+
|
137
|
+
### Stickers
|
138
|
+
```python
|
139
|
+
from imessage_monitor.display import pretty_print_sticker
|
140
|
+
|
141
|
+
print(pretty_print_sticker(message, show_ascii_art=True))
|
142
|
+
```
|
143
|
+
|
144
|
+
## Data Conversion
|
145
|
+
|
146
|
+
```python
|
147
|
+
from imessage_monitor import to_json, to_toml
|
148
|
+
|
149
|
+
# Convert messages to different formats
|
150
|
+
json_str = to_json(messages)
|
151
|
+
toml_str = to_toml(messages)
|
152
|
+
|
153
|
+
# Save to files
|
154
|
+
to_json(messages, "messages.json")
|
155
|
+
to_toml(messages, "messages.toml")
|
156
|
+
```
|
157
|
+
|
158
|
+
## Configuration
|
159
|
+
|
160
|
+
The library uses sensible defaults but can be configured:
|
161
|
+
|
162
|
+
```python
|
163
|
+
from imessage_monitor.config import Config
|
164
|
+
|
165
|
+
# Create custom config
|
166
|
+
config = Config.default()
|
167
|
+
config.monitoring.poll_interval_seconds = 1 # Faster polling
|
168
|
+
|
169
|
+
monitor = iMessageMonitor(config_path="path/to/config.toml")
|
170
|
+
```
|
171
|
+
|
172
|
+
## Permissions
|
173
|
+
|
174
|
+
### Required: Full Disk Access
|
175
|
+
|
176
|
+
1. Open **System Preferences** ļæ½ **Security & Privacy** ļæ½ **Privacy**
|
177
|
+
2. Select **Full Disk Access**
|
178
|
+
3. Add your terminal application (Terminal.app, iTerm2, etc.)
|
179
|
+
4. Add your IDE if running from there (VS Code, PyCharm, etc.)
|
180
|
+
|
181
|
+
### Optional: Shortcuts (for outbound messaging)
|
182
|
+
|
183
|
+
For Shortcuts-based messaging, create these shortcuts in the Shortcuts app:
|
184
|
+
- "Send Message" - Not Yet Implemented
|
185
|
+
- "Send Attachment" - Not Yet Implemented
|
186
|
+
|
187
|
+
## Platform Support
|
188
|
+
|
189
|
+
- **macOS**: Supported
|
190
|
+
- **Windows/Linux**: Not supported L (requires macOS Messages database)
|
191
|
+
|
192
|
+
|
193
|
+
## Contributing
|
194
|
+
|
195
|
+
1. Fork the repository
|
196
|
+
2. Create a feature branch
|
197
|
+
3. Make your changes
|
198
|
+
4. Run tests: `pytest`
|
199
|
+
5. Submit a pull request
|
200
|
+
|
201
|
+
|
202
|
+
## Troubleshooting
|
203
|
+
|
204
|
+
### "Database not found" error
|
205
|
+
- Ensure you're running on macOS
|
206
|
+
- Check Full Disk Access permissions
|
207
|
+
- Verify Messages app has been used at least once
|
208
|
+
|
209
|
+
### "Permission denied" error
|
210
|
+
- Add Full Disk Access for your terminal/IDE
|
211
|
+
- Restart terminal after adding permissions
|
212
|
+
|
213
|
+
### ASCII art not showing
|
214
|
+
- Ensure `ascii-magic` is installed
|
215
|
+
- Enable with `show_ascii_art=True` parameter
|
216
|
+
- Check image file accessibility
|
217
|
+
|
218
|
+
## Examples
|
219
|
+
|
220
|
+
See `example_usage.py` for a complete real-time monitoring application.
|
221
|
+
|
222
|
+
## Security Note
|
223
|
+
|
224
|
+
This library accesses your Messages database in read-only mode for monitoring. It does not modify or delete any messages. Outbound messaging requires explicit function calls and uses standard macOS APIs.
|
@@ -0,0 +1,189 @@
|
|
1
|
+
# iMessage Monitor
|
2
|
+
|
3
|
+
A Python library for monitoring and extracting iMessage data with real-time capabilities and beautiful terminal display.
|
4
|
+
|
5
|
+
## Features
|
6
|
+
|
7
|
+
- = **Real-time monitoring** of incoming iMessages
|
8
|
+
- =ļæ½ **Pretty-printed chat bubbles** with proper left/right alignment
|
9
|
+
- <ļæ½ **Sticker and reaction support** with emoji display
|
10
|
+
- =ļæ½ **ASCII art generation** for image attachments (optional)
|
11
|
+
- =ļæ½ **Attachment handling** including HEIC conversion
|
12
|
+
- =ļæ½ **Outbound messaging** via AppleScript or Shortcuts
|
13
|
+
- =ļæ½ **Safe database access** with read-only mode
|
14
|
+
|
15
|
+
## Requirements
|
16
|
+
|
17
|
+
- **macOS only** (requires access to Messages database)
|
18
|
+
- **Python 3.11+**
|
19
|
+
- **Full Disk Access** permission for terminal/IDE
|
20
|
+
|
21
|
+
## Installation
|
22
|
+
|
23
|
+
```bash
|
24
|
+
pip install imessage-monitor
|
25
|
+
|
26
|
+
or
|
27
|
+
|
28
|
+
uv add imessage-monitor
|
29
|
+
```
|
30
|
+
|
31
|
+
|
32
|
+
## Quick Start
|
33
|
+
|
34
|
+
### Real-time Monitoring
|
35
|
+
|
36
|
+
```python
|
37
|
+
from imessage_monitor import iMessageMonitor
|
38
|
+
from imessage_monitor.display import pretty_print_bubble
|
39
|
+
|
40
|
+
def handle_message(message):
|
41
|
+
"""Handle new messages with pretty printing."""
|
42
|
+
print(pretty_print_bubble(message, show_ascii_art=True))
|
43
|
+
|
44
|
+
# Start monitoring
|
45
|
+
monitor = iMessageMonitor()
|
46
|
+
monitor.start(message_callback=handle_message)
|
47
|
+
|
48
|
+
# Keep running (in practice, you'd run this in an async loop)
|
49
|
+
input("Press Enter to stop...")
|
50
|
+
monitor.stop()
|
51
|
+
```
|
52
|
+
|
53
|
+
### Message Retrieval
|
54
|
+
|
55
|
+
```python
|
56
|
+
from imessage_monitor import iMessageMonitor, to_json
|
57
|
+
|
58
|
+
# Get recent messages
|
59
|
+
monitor = iMessageMonitor()
|
60
|
+
messages = monitor.get_recent_messages(limit=50)
|
61
|
+
|
62
|
+
# Convert to JSON
|
63
|
+
json_data = to_json(messages)
|
64
|
+
print(json_data)
|
65
|
+
```
|
66
|
+
|
67
|
+
### Sending Messages
|
68
|
+
|
69
|
+
```python
|
70
|
+
from imessage_monitor import ImessageOutbound
|
71
|
+
|
72
|
+
# Send via AppleScript
|
73
|
+
outbound = ImessageOutbound()
|
74
|
+
success = outbound.send_message_applescript("+1234567890", "Hello!")
|
75
|
+
|
76
|
+
# Send attachment
|
77
|
+
success = outbound.send_attachment_applescript("+1234567890", "/path/to/file.jpg")
|
78
|
+
```
|
79
|
+
|
80
|
+
## Display Options
|
81
|
+
|
82
|
+
The library provides three pretty-print formats:
|
83
|
+
|
84
|
+
### Chat Bubbles
|
85
|
+
```python
|
86
|
+
from imessage_monitor.display import pretty_print_bubble
|
87
|
+
|
88
|
+
# Basic bubble (no ASCII art)
|
89
|
+
print(pretty_print_bubble(message))
|
90
|
+
|
91
|
+
# With ASCII art for images
|
92
|
+
print(pretty_print_bubble(message, show_ascii_art=True))
|
93
|
+
```
|
94
|
+
|
95
|
+
### Reactions
|
96
|
+
```python
|
97
|
+
from imessage_monitor.display import pretty_print_reaction
|
98
|
+
|
99
|
+
print(pretty_print_reaction(message)) # Shows d, =M, =, etc.
|
100
|
+
```
|
101
|
+
|
102
|
+
### Stickers
|
103
|
+
```python
|
104
|
+
from imessage_monitor.display import pretty_print_sticker
|
105
|
+
|
106
|
+
print(pretty_print_sticker(message, show_ascii_art=True))
|
107
|
+
```
|
108
|
+
|
109
|
+
## Data Conversion
|
110
|
+
|
111
|
+
```python
|
112
|
+
from imessage_monitor import to_json, to_toml
|
113
|
+
|
114
|
+
# Convert messages to different formats
|
115
|
+
json_str = to_json(messages)
|
116
|
+
toml_str = to_toml(messages)
|
117
|
+
|
118
|
+
# Save to files
|
119
|
+
to_json(messages, "messages.json")
|
120
|
+
to_toml(messages, "messages.toml")
|
121
|
+
```
|
122
|
+
|
123
|
+
## Configuration
|
124
|
+
|
125
|
+
The library uses sensible defaults but can be configured:
|
126
|
+
|
127
|
+
```python
|
128
|
+
from imessage_monitor.config import Config
|
129
|
+
|
130
|
+
# Create custom config
|
131
|
+
config = Config.default()
|
132
|
+
config.monitoring.poll_interval_seconds = 1 # Faster polling
|
133
|
+
|
134
|
+
monitor = iMessageMonitor(config_path="path/to/config.toml")
|
135
|
+
```
|
136
|
+
|
137
|
+
## Permissions
|
138
|
+
|
139
|
+
### Required: Full Disk Access
|
140
|
+
|
141
|
+
1. Open **System Preferences** ļæ½ **Security & Privacy** ļæ½ **Privacy**
|
142
|
+
2. Select **Full Disk Access**
|
143
|
+
3. Add your terminal application (Terminal.app, iTerm2, etc.)
|
144
|
+
4. Add your IDE if running from there (VS Code, PyCharm, etc.)
|
145
|
+
|
146
|
+
### Optional: Shortcuts (for outbound messaging)
|
147
|
+
|
148
|
+
For Shortcuts-based messaging, create these shortcuts in the Shortcuts app:
|
149
|
+
- "Send Message" - Not Yet Implemented
|
150
|
+
- "Send Attachment" - Not Yet Implemented
|
151
|
+
|
152
|
+
## Platform Support
|
153
|
+
|
154
|
+
- **macOS**: Supported
|
155
|
+
- **Windows/Linux**: Not supported L (requires macOS Messages database)
|
156
|
+
|
157
|
+
|
158
|
+
## Contributing
|
159
|
+
|
160
|
+
1. Fork the repository
|
161
|
+
2. Create a feature branch
|
162
|
+
3. Make your changes
|
163
|
+
4. Run tests: `pytest`
|
164
|
+
5. Submit a pull request
|
165
|
+
|
166
|
+
|
167
|
+
## Troubleshooting
|
168
|
+
|
169
|
+
### "Database not found" error
|
170
|
+
- Ensure you're running on macOS
|
171
|
+
- Check Full Disk Access permissions
|
172
|
+
- Verify Messages app has been used at least once
|
173
|
+
|
174
|
+
### "Permission denied" error
|
175
|
+
- Add Full Disk Access for your terminal/IDE
|
176
|
+
- Restart terminal after adding permissions
|
177
|
+
|
178
|
+
### ASCII art not showing
|
179
|
+
- Ensure `ascii-magic` is installed
|
180
|
+
- Enable with `show_ascii_art=True` parameter
|
181
|
+
- Check image file accessibility
|
182
|
+
|
183
|
+
## Examples
|
184
|
+
|
185
|
+
See `example_usage.py` for a complete real-time monitoring application.
|
186
|
+
|
187
|
+
## Security Note
|
188
|
+
|
189
|
+
This library accesses your Messages database in read-only mode for monitoring. It does not modify or delete any messages. Outbound messaging requires explicit function calls and uses standard macOS APIs.
|
@@ -0,0 +1,33 @@
|
|
1
|
+
[database]
|
2
|
+
# Databasing not yet supported
|
3
|
+
url = "postgresql://user:pass@localhost/imessage_db"
|
4
|
+
pool_size = 10
|
5
|
+
max_overflow = 20
|
6
|
+
pool_timeout = 30
|
7
|
+
enable_storage = false
|
8
|
+
|
9
|
+
[apple]
|
10
|
+
chat_db_path = "~/Library/Messages/chat.db"
|
11
|
+
attachments_path = "~/Library/Messages/Attachments"
|
12
|
+
permissions_check = true
|
13
|
+
|
14
|
+
[monitoring]
|
15
|
+
poll_interval_seconds = 3
|
16
|
+
startup_lookback_hours = 24
|
17
|
+
max_batch_size = 100
|
18
|
+
enable_real_time = true
|
19
|
+
|
20
|
+
[contacts]
|
21
|
+
phone_numbers = []
|
22
|
+
include_unknown = true
|
23
|
+
group_chats = false
|
24
|
+
|
25
|
+
[date_range]
|
26
|
+
# start_date = "2024-01-01T00:00:00"
|
27
|
+
# end_date = "2024-12-31T23:59:59"
|
28
|
+
|
29
|
+
[outbound]
|
30
|
+
method = "applescript"
|
31
|
+
rate_limit_per_minute = 30
|
32
|
+
enable_auto_reply = false
|
33
|
+
auto_reply_triggers = []
|
@@ -0,0 +1,162 @@
|
|
1
|
+
"""Real-time iMessage monitoring example."""
|
2
|
+
import asyncio
|
3
|
+
import signal
|
4
|
+
import sys
|
5
|
+
from imessage_monitor import iMessageMonitor
|
6
|
+
from imessage_monitor.display import pretty_print_bubble, pretty_print_reaction, pretty_print_sticker
|
7
|
+
|
8
|
+
|
9
|
+
class RealTimeMonitor:
|
10
|
+
"""Real-time iMessage monitor with graceful shutdown."""
|
11
|
+
|
12
|
+
def __init__(self, enable_ascii_art: bool = False):
|
13
|
+
self.monitor = iMessageMonitor()
|
14
|
+
self.enable_ascii_art = enable_ascii_art
|
15
|
+
self.running = False
|
16
|
+
self.message_count = 0
|
17
|
+
|
18
|
+
def handle_new_message(self, message):
|
19
|
+
"""Handle incoming messages with pretty printing."""
|
20
|
+
self.message_count += 1
|
21
|
+
|
22
|
+
print(f"\n{'='*80}")
|
23
|
+
print(f"š± NEW MESSAGE #{self.message_count}")
|
24
|
+
print(f"{'='*80}")
|
25
|
+
|
26
|
+
# Determine message type and use appropriate pretty print
|
27
|
+
associated_type = message.get('associated_message_type', 0)
|
28
|
+
balloon_bundle_id = message.get('balloon_bundle_id', '')
|
29
|
+
attachments = message.get('parsed_attachments', [])
|
30
|
+
|
31
|
+
# Check if it's a sticker
|
32
|
+
is_sticker = any(attachment.get('is_sticker', False) for attachment in attachments)
|
33
|
+
|
34
|
+
if associated_type in range(2000, 4000): # Reaction
|
35
|
+
print("š REACTION:")
|
36
|
+
print(pretty_print_reaction(message))
|
37
|
+
elif is_sticker:
|
38
|
+
print("š STICKER:")
|
39
|
+
print(pretty_print_sticker(message, show_ascii_art=self.enable_ascii_art))
|
40
|
+
else:
|
41
|
+
print("š¬ MESSAGE:")
|
42
|
+
print(pretty_print_bubble(message, show_ascii_art=self.enable_ascii_art))
|
43
|
+
|
44
|
+
# Show additional info
|
45
|
+
sender = "You" if message.get('is_from_me') else message.get('handle_id_str', 'Unknown')
|
46
|
+
service = message.get('service', 'Unknown')
|
47
|
+
print(f"\nš From: {sender} | Service: {service}")
|
48
|
+
|
49
|
+
if attachments:
|
50
|
+
print(f"š Attachments: {len(attachments)}")
|
51
|
+
for i, attachment in enumerate(attachments[:3]): # Show first 3
|
52
|
+
filename = attachment.get('filename', 'Unknown')
|
53
|
+
size = attachment.get('size', 0)
|
54
|
+
if size:
|
55
|
+
size_mb = size / (1024 * 1024)
|
56
|
+
print(f" {i+1}. {filename} ({size_mb:.1f}MB)")
|
57
|
+
else:
|
58
|
+
print(f" {i+1}. {filename}")
|
59
|
+
|
60
|
+
def setup_signal_handlers(self):
|
61
|
+
"""Setup graceful shutdown on Ctrl+C."""
|
62
|
+
def signal_handler(signum, frame):
|
63
|
+
print(f"\n\nā ļø Received signal {signum}. Shutting down gracefully...")
|
64
|
+
self.running = False
|
65
|
+
|
66
|
+
signal.signal(signal.SIGINT, signal_handler)
|
67
|
+
signal.signal(signal.SIGTERM, signal_handler)
|
68
|
+
|
69
|
+
async def start_monitoring(self):
|
70
|
+
"""Start real-time monitoring."""
|
71
|
+
self.setup_signal_handlers()
|
72
|
+
self.running = True
|
73
|
+
|
74
|
+
print("š Starting iMessage Real-Time Monitor")
|
75
|
+
print("=" * 60)
|
76
|
+
print(f"ASCII Art: {'Enabled' if self.enable_ascii_art else 'Disabled'}")
|
77
|
+
print("=" * 60)
|
78
|
+
|
79
|
+
try:
|
80
|
+
# Start monitoring without showing initial messages
|
81
|
+
print("š± Initializing monitor...")
|
82
|
+
initial_messages = self.monitor.start(message_callback=self.handle_new_message)
|
83
|
+
print("ā
Monitor initialized")
|
84
|
+
|
85
|
+
print("\nšÆ MONITORING ACTIVE - Waiting for new messages...")
|
86
|
+
print("š Send yourself a message to test!")
|
87
|
+
print("š Press Ctrl+C to stop monitoring")
|
88
|
+
print("=" * 60)
|
89
|
+
|
90
|
+
# Keep the monitor running
|
91
|
+
while self.running and self.monitor.is_running():
|
92
|
+
await asyncio.sleep(0.5) # Check every 0.5 seconds
|
93
|
+
|
94
|
+
except KeyboardInterrupt:
|
95
|
+
print("\nā ļø Keyboard interrupt received")
|
96
|
+
except Exception as e:
|
97
|
+
print(f"\nā Error during monitoring: {e}")
|
98
|
+
finally:
|
99
|
+
await self.cleanup()
|
100
|
+
|
101
|
+
async def cleanup(self):
|
102
|
+
"""Clean shutdown of the monitor."""
|
103
|
+
print("\nš Stopping monitor...")
|
104
|
+
|
105
|
+
if self.monitor.is_running():
|
106
|
+
self.monitor.stop()
|
107
|
+
|
108
|
+
print(f"š Session Summary:")
|
109
|
+
print(f" ⢠Messages processed: {self.message_count}")
|
110
|
+
print(f" ⢠Monitor status: {'Stopped' if not self.monitor.is_running() else 'Running'}")
|
111
|
+
print("ā
Monitor stopped successfully")
|
112
|
+
|
113
|
+
|
114
|
+
def show_help():
|
115
|
+
"""Show usage instructions."""
|
116
|
+
print("iMessage Real-Time Monitor")
|
117
|
+
print("=" * 40)
|
118
|
+
print("Usage:")
|
119
|
+
print(" python example_usage.py [--ascii-art]")
|
120
|
+
print("")
|
121
|
+
print("Options:")
|
122
|
+
print(" --ascii-art Enable ASCII art for images (default: disabled)")
|
123
|
+
print(" --help Show this help message")
|
124
|
+
print("")
|
125
|
+
print("Controls:")
|
126
|
+
print(" Ctrl+C Stop monitoring")
|
127
|
+
print("")
|
128
|
+
print("Features:")
|
129
|
+
print(" ⢠Real-time message monitoring")
|
130
|
+
print(" ⢠Pretty-printed chat bubbles")
|
131
|
+
print(" ⢠Reaction and sticker support")
|
132
|
+
print(" ⢠Attachment information")
|
133
|
+
print(" ⢠Graceful shutdown")
|
134
|
+
|
135
|
+
|
136
|
+
async def main():
|
137
|
+
"""Main entry point for real-time monitoring."""
|
138
|
+
|
139
|
+
# Parse command line arguments
|
140
|
+
enable_ascii_art = '--ascii-art' in sys.argv
|
141
|
+
show_help_flag = '--help' in sys.argv or '-h' in sys.argv
|
142
|
+
|
143
|
+
if show_help_flag:
|
144
|
+
show_help()
|
145
|
+
return
|
146
|
+
|
147
|
+
# Create and start the monitor
|
148
|
+
monitor = RealTimeMonitor(enable_ascii_art=enable_ascii_art)
|
149
|
+
await monitor.start_monitoring()
|
150
|
+
|
151
|
+
|
152
|
+
if __name__ == "__main__":
|
153
|
+
print("iMessage Monitor - Real-Time Monitoring")
|
154
|
+
print("=" * 60)
|
155
|
+
|
156
|
+
try:
|
157
|
+
asyncio.run(main())
|
158
|
+
except KeyboardInterrupt:
|
159
|
+
print("\nš Goodbye!")
|
160
|
+
except Exception as e:
|
161
|
+
print(f"\nā Fatal error: {e}")
|
162
|
+
sys.exit(1)
|