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.
@@ -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,10 @@
1
+ # Python-generated files
2
+ __pycache__/
3
+ *.py[oc]
4
+ build/
5
+ dist/
6
+ wheels/
7
+ *.egg-info
8
+
9
+ # Virtual environments
10
+ .venv
@@ -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)