toilet_tracker 0.2.1 โ†’ 0.2.2

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 4e179c9943225797758be0ca803a1dcde9ee9f7b98ee7466d74cb208a49040b8
4
- data.tar.gz: ea5b5ab8fb0e4da1ca4a8e7e48575bc72a9a967769c375e52e11dcfab3dd4801
3
+ metadata.gz: 4af948bef38e4c8911b60d3bdc887c38b11593d687841f950f0472c7b5748a51
4
+ data.tar.gz: 8ea58aabc73391c82395c7aaa91af3b369f6ad2c2d1d7ad0f513d02ef9976d7f
5
5
  SHA512:
6
- metadata.gz: 33081c85110a522542ae3c50209cbe5a1d302bb34bb513bc4c6118daaabf0093673e37695a7200818ed77d5e37bd725e22074a7898cd82f63df9518c105beaf9
7
- data.tar.gz: 0ebf346d3c2afde44224885c4879bad74e1d29203c7c2f567fc573fbc989e48eee71f613257707df3e4b4359a861356111cd1e2395f9035d573259de6d0579c8
6
+ metadata.gz: c11a69adeb79215f621857aa03782fd98518f7e36d2afa2e491f96e1b6f0d1ed94df24b3701a9282e680c01a7054450de894e9eecabf992b716c8c52949b0fd8
7
+ data.tar.gz: f0b54ca705f8b548225bcac1ac9d47803b27704a316b9b3a57414d9f5a9aa204eb7c231c88fcba1c87e10b0b801be70759467315b2f75cfca632778f91f5b6d8
data/CHANGELOG.md CHANGED
@@ -1,5 +1,20 @@
1
1
  ## [Unreleased]
2
2
 
3
+ ## [0.2.2] - 2026-09-03
4
+
5
+ ### Fixed
6
+ - Parse WhatsApp exports that use 4-digit years (`[02/01/2025, 23:27:21]`). The
7
+ message pattern required a 2-digit year, so current exports failed to parse
8
+ entirely: the only lines that matched were old-format timestamps quoted inside
9
+ message bodies, which produced a handful of events attributed to the quoted
10
+ sender. A 21,906-line export went from 3 parsed events to 13,996.
11
+ - Stop prefixing the century onto years that already have one (`2025` no longer
12
+ becomes `202025`).
13
+
14
+ ### Added
15
+ - Accept day and month without zero padding (`[2/1/2025, ...]`)
16
+ - Accept timestamps without seconds (`[02/01/2025, 23:27]`), defaulting to `:00`
17
+
3
18
  ## [0.2.1] - 2025-12-18
4
19
 
5
20
  ### Changed
data/PARSING_SPEC.md CHANGED
@@ -9,8 +9,10 @@ ToiletTracker is a Ruby gem that parses WhatsApp message exports to track toilet
9
9
  ### Message Structure
10
10
  All WhatsApp messages follow this format:
11
11
  ```
12
- [DD/MM/YY, HH:MM:SS] Sender: Content
12
+ [DD/MM/YYYY, HH:MM:SS] Sender: Content
13
13
  ```
14
+ Exports vary by platform and locale. The year may be 2 or 4 digits, the day and
15
+ month may be zero-padded or not, and the seconds may be absent.
14
16
 
15
17
  ### Command Types
16
18
  - **๐Ÿšฝ (Settings)**: Configure timezone shifts and preferences
@@ -41,17 +43,24 @@ Both ๐Ÿ’ฉ and ๐Ÿšฝ commands support optional metadata emojis placed between the
41
43
  ## Supported Parsing Patterns
42
44
 
43
45
  ### WhatsApp Message Format
44
- **Pattern**: `\[(?<day>\d{2})/(?<month>\d{2})/(?<year>\d{2}),\s*(?<time>\d{2}:\d{2}:\d{2})\]\s*(?<sender>[^:]+):\s*(?<content>.+?)(?:\s*โ€Ž<This message was edited>)?$`
46
+ **Pattern**: `\[(?<day>\d{1,2})/(?<month>\d{1,2})/(?<year>\d{4}|\d{2}),\s*(?<time>\d{1,2}:\d{2}(?::\d{2})?)\]\s*(?<sender>[^:]+):\s*(?<content>.+?)(?:\s*โ€Ž<This message was edited>)?$`
45
47
 
46
48
  **Examples**:
49
+ - `[01/01/2025, 12:00:00] Alice: ๐Ÿ’ฉ`
47
50
  - `[01/01/25, 12:00:00] Alice: ๐Ÿ’ฉ`
48
51
  - `[25/12/24, 23:59:59] Bob: ๐Ÿšฝ +2`
49
- - `[15/06/25, 14:30:15] Charlie: ๐Ÿ’ฉ +1 2025-06-15 12:00:00`
52
+ - `[15/06/2025, 14:30:15] Charlie: ๐Ÿ’ฉ +1 2025-06-15 12:00:00`
53
+ - `[2/1/2025, 9:05] Dave: ๐Ÿ’ฉ`
50
54
 
51
55
  **Behavior**:
52
- - Extracts day, month, year (2-digit), time, sender, content
56
+ - Extracts day, month, year (2- or 4-digit), time, sender, content
53
57
  - Handles edited messages with suffix `โ€Ž<This message was edited>`
54
- - Year is converted to 20XX format (25 โ†’ 2025)
58
+ - A 2-digit year is converted to 20XX format (25 โ†’ 2025); a 4-digit year is used as-is
59
+ - Seconds are optional and default to 0 when absent
60
+ - Day and month may be given with or without zero padding
61
+
62
+ **Not supported**: 12-hour timestamps with an AM/PM suffix, and the Android
63
+ export layout (`DD/MM/YYYY, HH:MM - Sender: Content`).
55
64
 
56
65
  ### 1. Shift Set (Functional)
57
66
  **Pattern**: `๐Ÿšฝ\s*([+-]?\d+)$`
data/README.md CHANGED
@@ -1,253 +1,106 @@
1
1
  # ToiletTracker
2
2
 
3
- A modern Ruby gem for parsing WhatsApp messages containing toilet tracking data using emoji-based commands. Built with clean architecture principles and comprehensive timezone support.
3
+ [![CI](https://github.com/BrownOps/toilet_tracker/actions/workflows/main.yml/badge.svg)](https://github.com/BrownOps/toilet_tracker/actions/workflows/main.yml)
4
+ [![Gem Version](https://img.shields.io/gem/v/toilet_tracker.svg)](https://rubygems.org/gems/toilet_tracker)
5
+ [![License](https://img.shields.io/badge/license-MIT-blue.svg)](LICENSE.txt)
6
+ [![Ruby](https://img.shields.io/badge/ruby-%3E%3D%203.4-red.svg)](https://www.ruby-lang.org)
4
7
 
5
- ## Features
6
-
7
- - ๐Ÿšฝ **Settings**: Set timezone shifts and preferences
8
- - ๐Ÿ’ฉ **Event Tracking**: Log events with automatic timezone adjustments
9
- - โฐ **Timezone Support**: Handle multiple timezones and retroactive shifts
10
- - ๐Ÿ“Š **Multiple Output Formats**: JSON, CSV, and formatted tables
11
- - ๐Ÿ”ง **Thor CLI**: Interactive command-line interface with TTY::Prompt
12
- - ๐Ÿงช **Comprehensive Testing**: 77 tests with 96%+ coverage
13
- - ๐Ÿ—๏ธ **Clean Architecture**: Modular design with clear separation of concerns
14
- - ๐Ÿ“‹ **Statistics**: Detailed parsing statistics and error reporting
15
-
16
- ## Requirements
8
+ Track bowel movements through WhatsApp messages using simple emoji commands. Export your WhatsApp chat, run it through ToiletTracker, and get structured data with timezone support.
17
9
 
18
- - **Ruby 3.4+** - Uses modern Ruby features for optimal performance
19
- - **RuboCop Omakase** - Opinionated Ruby styling from the Rails team
10
+ ## Features
20
11
 
21
- ## Installation
12
+ - **No app needed** - Use WhatsApp, which you already have
13
+ - **Travel-friendly** - Full timezone support for globetrotters
14
+ - **Flexible input** - Log now, log past events, add metadata
15
+ - **Multiple exports** - JSON, CSV, or formatted tables
16
+ - **Privacy first** - Your data stays on your device
22
17
 
23
- Add this line to your application's Gemfile:
18
+ ## Why?
24
19
 
25
- ```ruby
26
- gem 'toilet_tracker'
27
- ```
20
+ Tracking health data shouldn't require a dedicated app. WhatsApp is already on your phone, always synced, and easy to use. Just send a ๐Ÿ’ฉ to a chat (or yourself) whenever nature calls, and this gem turns those messages into analyzable data.
28
21
 
29
- And then execute:
30
-
31
- ```bash
32
- bundle install
33
- ```
34
-
35
- Or install it yourself as:
22
+ ## Quick Start
36
23
 
37
24
  ```bash
38
25
  gem install toilet_tracker
39
26
  ```
40
27
 
41
- ## Usage
42
-
43
- ### Command Line Interface
44
-
45
- Process WhatsApp export files:
28
+ Export your WhatsApp chat and run:
46
29
 
47
30
  ```bash
48
- # Basic usage
49
- toilet_tracker parse whatsapp_export.txt
50
-
51
- # Parse WhatsApp zip exports (automatically extracts _chat.txt)
52
31
  toilet_tracker parse whatsapp_export.zip
53
-
54
- # JSON output
55
- toilet_tracker parse --format json messages.txt
56
-
57
- # Custom timezone
58
- toilet_tracker parse --timezone "Europe/Rome" messages.txt
59
-
60
- # Show statistics
61
- toilet_tracker stats messages.txt
62
-
63
- # Interactive mode
64
- toilet_tracker interactive
65
-
66
- # Show version
67
- toilet_tracker version
68
- ```
69
-
70
- ### Ruby API
71
-
72
- ```ruby
73
- require 'toilet_tracker'
74
-
75
- # Parse individual lines
76
- result = ToiletTracker.parse_line("[01/01/25, 12:00:00] Alice: ๐Ÿ’ฉ")
77
- puts result.type # => :event_now
78
-
79
- # Parse multiple lines
80
- lines = [
81
- "[01/01/25, 10:00:00] Alice: ๐Ÿšฝ +2",
82
- "[01/01/25, 12:00:00] Alice: ๐Ÿ’ฉ"
83
- ]
84
- results = ToiletTracker.parse_lines(lines)
85
-
86
- # Configure settings
87
- ToiletTracker.configure do |config|
88
- config.default_timezone = "Europe/Rome"
89
- config.max_shift_hours = 12
90
- end
91
32
  ```
92
33
 
93
- ### Supported Message Formats
94
-
95
- #### ๐Ÿšฝ Settings (Functional - Affect Timestamps)
96
- - `๐Ÿšฝ +2` - Set timezone shift to +2 hours (immediate)
97
- - `๐Ÿšฝ -1` - Set timezone shift to -1 hour (immediate)
98
- - `๐Ÿšฝ +1 2025-01-15 14:30` - Set shift effective from specific time (retroactive)
99
- - `๐Ÿšฝ Europe/Rome` - Set timezone by name
100
- - `๐Ÿšฝ PST` - Set timezone by abbreviation
101
-
102
- #### ๐Ÿ’ฉ Events
103
-
104
- **Functional Shifts (Affect Actual Times):**
105
- - `๐Ÿ’ฉ` - Log live event with current active shift
106
- - `๐Ÿ’ฉ +1` - Log live event with +1 hour shift override
107
- - `๐Ÿ’ฉ PST` - Log live event converted to PST timezone
108
-
109
- **Fixed Times (No Shift Applied):**
110
- - `๐Ÿ’ฉ 2025-01-15 14:30` - Log event at exact time specified
34
+ ## How It Works
111
35
 
112
- **Decorative Data (For Statistics Only):**
113
- - `๐Ÿ’ฉ +2 2025-01-15 14:30` - Log event at 14:30 exactly, +2 shift stored for display
114
- - `๐Ÿ’ฉ EST 2025-01-15 14:30` - Log event at 14:30 exactly, EST timezone stored for display
36
+ Send emoji commands in any WhatsApp chat:
115
37
 
116
- > **Important**: In decorative patterns, the shift/timezone is stored for statistics but does NOT modify the actual poop timestamp.
38
+ | Command | What it does |
39
+ |---------|--------------|
40
+ | `๐Ÿ’ฉ` | Log an event right now |
41
+ | `๐Ÿ’ฉ 14:30` | Log an event at a specific time |
42
+ | `๐Ÿšฝ +2` | Set your timezone offset to +2 hours |
43
+ | `๐Ÿšฝ Europe/Rome` | Set timezone by name |
117
44
 
118
- ### Configuration Options
45
+ See the full [message specification](https://github.com/BrownOps/spec) for all supported formats.
119
46
 
120
- ```ruby
121
- ToiletTracker.configure do |config|
122
- # Default timezone for parsing timestamps
123
- config.default_timezone = "UTC"
124
-
125
- # Maximum allowed shift hours
126
- config.max_shift_hours = 12
127
-
128
- # Custom message patterns (advanced)
129
- config.message_patterns[:custom] = /custom_pattern/
130
-
131
- # Supported date formats
132
- config.date_formats = ["%Y-%m-%d %H:%M:%S", "%Y/%m/%d %H:%M"]
133
- end
134
- ```
135
-
136
- ## Examples
47
+ ### Timezone Support
137
48
 
138
- ### Basic Usage Scenarios
49
+ Traveling? Just update your timezone:
139
50
 
140
- #### Setting Up Timezone Shifts
141
51
  ```
142
- [15/01/25, 10:00:00] Alice: ๐Ÿšฝ +2
143
- [15/01/25, 12:00:00] Alice: ๐Ÿ’ฉ
144
- # Result: Event logged at 14:00 (12:00 + 2 hours)
52
+ ๐Ÿšฝ +5:30 # Flying to India
53
+ ๐Ÿ’ฉ # Logged with +5:30 offset
54
+ ๐Ÿšฝ Europe/Rome # Back home
55
+ ๐Ÿ’ฉ # Logged with Rome timezone
145
56
  ```
146
57
 
147
- #### Retroactive Timezone Adjustments
148
- ```
149
- [15/01/25, 10:00:00] Alice: ๐Ÿ’ฉ
150
- [15/01/25, 14:00:00] Alice: ๐Ÿšฝ +3 2025-01-15 09:00:00
151
- # Result: First event adjusted to 13:00 (10:00 + 3 hours)
152
- ```
58
+ ### Metadata
153
59
 
154
- #### Decorative vs Functional Shifts
155
- ```
156
- # Functional: Affects timestamp
157
- [15/01/25, 12:00:00] Alice: ๐Ÿ’ฉ +2
158
- # Result: Event at 14:00 (12:00 + 2 hours)
159
-
160
- # Decorative: Only for statistics
161
- [15/01/25, 12:00:00] Alice: ๐Ÿ’ฉ +2 2025-01-15 10:00:00
162
- # Result: Event at exactly 10:00, +2 stored for display
163
- ```
60
+ Add extra context with additional emojis:
164
61
 
165
- #### Complex Multi-User Scenario
166
62
  ```
167
- [15/01/25, 09:00:00] Alice: ๐Ÿšฝ +2
168
- [15/01/25, 09:30:00] Bob: ๐Ÿšฝ Europe/Rome
169
- [15/01/25, 10:00:00] Alice: ๐Ÿ’ฉ
170
- [15/01/25, 10:30:00] Bob: ๐Ÿ’ฉ
171
- [15/01/25, 11:00:00] Alice: ๐Ÿ’ฉ +1
172
- [15/01/25, 11:30:00] Bob: ๐Ÿ’ฉ EST 2025-01-15 08:00:00
63
+ ๐Ÿ’ฉ ๐Ÿฉธ # Flag something unusual
64
+ ๐Ÿ’ฉ ๐Ÿงฑ # Note the consistency
65
+ ๐Ÿ’ฉ โ˜• ๐Ÿ• # Track what you ate
173
66
  ```
174
67
 
175
- Results:
176
- - Alice's first event: 12:00 (10:00 + 2 hours active shift)
177
- - Bob's first event: ~11:30 (10:30 converted from UTC to Rome time)
178
- - Alice's override event: 12:00 (11:00 + 1 hour override)
179
- - Bob's decorative event: exactly 08:00 (EST is decorative only)
180
-
181
- ## Development
182
-
183
- After checking out the repo, run `bin/setup` to install dependencies. Then, run the following commands:
68
+ ## Output Formats
184
69
 
185
70
  ```bash
186
- # Run tests
187
- bundle exec rspec
188
-
189
- # Check code style (RuboCop)
190
- bundle exec rubocop
71
+ # Table (default)
72
+ toilet_tracker parse chat.zip
191
73
 
192
- # Auto-fix style issues
193
- bundle exec rubocop -a
74
+ # JSON for further processing
75
+ toilet_tracker parse --format json chat.zip
194
76
 
195
- # Install gem locally
196
- bundle exec rake install
77
+ # CSV for spreadsheets
78
+ toilet_tracker parse --format csv chat.zip
197
79
  ```
198
80
 
199
- ### Code Quality
81
+ ## Ruby API
200
82
 
201
- This project uses **RuboCop Omakase** for opinionated Ruby linting and formatting. Omakase provides the Rails team's preferred styling rules.
202
-
203
- Key principles:
204
- - **Ruby 3.4+ features** - Modern syntax and performance optimizations
205
- - **KISS principle** - Keep code simple and readable
206
- - **Test-driven development** - Comprehensive RSpec test suite
207
- - **Clean architecture** - Clear separation of concerns
208
-
209
- ### Creating a Release
210
-
211
- To release a new version:
212
-
213
- 1. **Update the version** in `lib/toilet_tracker/version.rb`:
214
- ```ruby
215
- module ToiletTracker
216
- VERSION = "1.2.3"
217
- end
218
- ```
219
-
220
- 2. **Update CHANGELOG.md** with release notes (optional but recommended)
83
+ ```ruby
84
+ require 'toilet_tracker'
221
85
 
222
- 3. **Commit your changes**:
223
- ```bash
224
- git add -A
225
- git commit -m "Bump version to 1.2.3"
226
- ```
86
+ # Parse a WhatsApp export
87
+ results = ToiletTracker.parse_file("chat.txt")
227
88
 
228
- 4. **Create and push a git tag**:
229
- ```bash
230
- git tag v1.2.3
231
- git push origin main --tags
232
- ```
89
+ # Or parse individual messages
90
+ result = ToiletTracker.parse_line("[01/01/2025, 12:00:00] Me: ๐Ÿ’ฉ")
91
+ ```
233
92
 
234
- 5. **Automated Release Process**: The GitHub Actions workflow will automatically:
235
- - Run tests and linting to validate the release
236
- - Build the gem
237
- - Publish to RubyGems.org (requires `RUBYGEMS_API_KEY` secret)
238
- - Create a GitHub release with auto-generated changelog
239
- - Upload the gem file as a release asset
93
+ ## Requirements
240
94
 
241
- **Note**: Ensure the `RUBYGEMS_API_KEY` secret is configured in your GitHub repository settings for automatic publishing to work.
95
+ - Ruby 3.4+
242
96
 
243
- ## Contributing
97
+ ## Development
244
98
 
245
- Bug reports and pull requests are welcome on GitHub at https://github.com/[USERNAME]/toilet_tracker. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [code of conduct](https://github.com/[USERNAME]/toilet_tracker/blob/main/CODE_OF_CONDUCT.md).
99
+ ```bash
100
+ bin/setup # Install dependencies
101
+ bundle exec rspec # Run tests
102
+ ```
246
103
 
247
104
  ## License
248
105
 
249
- The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
250
-
251
- ## Code of Conduct
252
-
253
- Everyone interacting in the ToiletTracker project's codebases, issue trackers, chat rooms and mailing lists is expected to follow the [code of conduct](https://github.com/[USERNAME]/toilet_tracker/blob/main/CODE_OF_CONDUCT.md).
106
+ MIT - see [LICENSE.txt](LICENSE.txt)
@@ -61,7 +61,9 @@ module ToiletTracker
61
61
  end
62
62
 
63
63
  def whatsapp_message_pattern
64
- @whatsapp_message_pattern ||= %r{\[(?<day>\d{2})/(?<month>\d{2})/(?<year>\d{2}),\s*(?<time>\d{2}:\d{2}:\d{2})\]\s*(?<sender>[^:]+):\s*(?<content>.+?)(?:\s*โ€Ž<This message was edited>)?$}
64
+ # WhatsApp exports vary by platform and locale: years are either 2 or 4
65
+ # digits, day and month may be zero-padded or not, and seconds may be absent.
66
+ @whatsapp_message_pattern ||= %r{\[(?<day>\d{1,2})/(?<month>\d{1,2})/(?<year>\d{4}|\d{2}),\s*(?<time>\d{1,2}:\d{2}(?::\d{2})?)\]\s*(?<sender>[^:]+):\s*(?<content>.+?)(?:\s*โ€Ž<This message was edited>)?$}
65
67
  end
66
68
 
67
69
  def edited_message_suffix
@@ -41,16 +41,23 @@ module ToiletTracker
41
41
  end
42
42
 
43
43
  def parse_whatsapp_timestamp(day, month, year, time)
44
- # Convert YY to full year (assuming 2000s)
45
- full_year = "20#{year}"
46
- datetime_string = "#{day}/#{month}/#{full_year} #{time}"
44
+ datetime_string = "#{day}/#{month}/#{expand_year(year)} #{time}"
47
45
 
48
46
  # Parse in the default timezone
49
- config.default_timezone_object.strptime(datetime_string, "%d/%m/%Y %H:%M:%S")
47
+ config.default_timezone_object.strptime(datetime_string, timestamp_format(time))
50
48
  rescue ArgumentError => e
51
49
  raise Core::InvalidDateTime, "#{day}/#{month}/#{year} #{time}: #{e.message}"
52
50
  end
53
51
 
52
+ # Convert YY to full year (assuming 2000s), leave YYYY untouched
53
+ def expand_year(year)
54
+ year.length == 2 ? "20#{year}" : year
55
+ end
56
+
57
+ def timestamp_format(time)
58
+ time.count(":") > 1 ? "%d/%m/%Y %H:%M:%S" : "%d/%m/%Y %H:%M"
59
+ end
60
+
54
61
  def clean_content(content)
55
62
  return "" if content.nil?
56
63
 
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module ToiletTracker
4
- VERSION = "0.2.1"
4
+ VERSION = "0.2.2"
5
5
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: toilet_tracker
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.1
4
+ version: 0.2.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - NetherSoul
@@ -164,7 +164,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
164
164
  - !ruby/object:Gem::Version
165
165
  version: '0'
166
166
  requirements: []
167
- rubygems_version: 3.6.7
167
+ rubygems_version: 4.0.3
168
168
  specification_version: 4
169
169
  summary: Parse WhatsApp messages for toilet tracking with emoji-based commands
170
170
  test_files: []