messaging: Date formatting

New supported formats:
- `datetime.date`
- `pd.Timestamp`
- `str`
This commit is contained in:
Nick Ninov
2026-08-15 00:36:07 +03:00
parent 86796bf95c
commit c526e9c842
7 changed files with 77 additions and 16 deletions
+16 -2
View File
@@ -526,8 +526,8 @@ Messages can be fetched from:
| Name | Type | Required | Description |
|-----|-----|-----|-------------|
| `chat_id` | `str` | Yes | Identifier of the chat. All available chat IDs can be obtained from the [`chats`](./account.md#chats) property. |
| `start_timestamp` | `datetime.datetime` | No | The earliest timestamp to include. Messages older than this value will stop the fetch process. |
| `end_timestamp` | `datetime.datetime` | No | The latest timestamp to include. Messages newer than this value will be skipped. |
| `start_timestamp` | `str`<br>`datetime.date`<br>`datetime.datetime`<br>`pandas.Timestamp` | No | The earliest timestamp to include. Messages older than this value will stop the fetch process. |
| `end_timestamp` | `str`<br>`datetime.date`<br>`datetime.datetime`<br>`pandas.Timestamp` | No | The latest timestamp to include. Messages newer than this value will be skipped. |
Returns `list[dict]` containing message objects. Timestamp fields returned by the backend are automatically converted into `datetime.datetime` objects.
@@ -555,6 +555,20 @@ for message in messages:
**Note**: If there are missing messages in a chat that might be because the node (Status Backend) has not received them yet. They may appear later.
**Timestamps**
Both timestamps also accept a plain `str`, so a range can be written out without building a `datetime.datetime` first. The **time is optional** and can be given with any precision - the missing parts default to zero, meaning that `2026-08-11` is read as `2026-08-11 00:00:00`. A `datetime.date` carries no time at all and is moved to midnight the same way.
| Format | Example |
|-----|-----|
| `YYYY-MM-DD HH:MM:SS.ffffff` | `2026-08-11 22:57:51.134000` |
| `YYYY-MM-DD HH:MM:SS` | `2026-08-11 22:57:51` |
| `YYYY-MM-DD HH:MM` | `2026-08-11 22:57` |
| `YYYY-MM-DD HH` | `2026-08-11 22` |
| `YYYY-MM-DD` | `2026-08-11` |
Both `T` and a space are accepted as the date / time separator, so `2026-08-11T22:57:51` and `2026-08-11 22:57:51` are the same timestamp.
#### `delete_message(id)`
Delete one of your **own** messages from a chat. The deletion is propagated to the other members of the chat, so the message disappears for everybody - the same as deleting a message in Status App.
+4 -2
View File
@@ -1245,8 +1245,10 @@ Retrieve messages from the channel within an optional time range. Messages are r
| Name | Type | Required | Description |
|-----|-----|-----|-------------|
| `start_timestamp` | `datetime.datetime` | No | The earliest timestamp to include. Messages older than this stop the fetch. |
| `end_timestamp` | `datetime.datetime` | No | The latest timestamp to include. Messages newer than this are skipped. |
| `start_timestamp` | `str`<br>`datetime.date`<br>`datetime.datetime`<br>`pandas.Timestamp` | No | The earliest timestamp to include. Messages older than this stop the fetch. |
| `end_timestamp` | `str`<br>`datetime.date`<br>`datetime.datetime`<br>`pandas.Timestamp` | No | The latest timestamp to include. Messages newer than this are skipped. |
Both timestamps accept the same values as [`get_messages`](./account.md#get_messageschat_id-start_timestampnone-end_timestampnone) on `Account`, so a range can be written as a plain `str` - for example `2026-08-11 22:57:51.134000`, `2026-08-11 22:57` or `2026-08-11`.
Returns `list[dict]` of message objects. This delegates to [`get_messages`](./account.md#get_messageschat_id-start_timestampnone-end_timestampnone) on `Account`.
+4 -2
View File
@@ -292,8 +292,10 @@ Retrieve messages from the group chat within an optional time range. Messages ar
| Name | Type | Required | Description |
|-----|-----|-----|-------------|
| `start_timestamp` | `datetime.datetime` | No | The earliest timestamp to include. Messages older than this value will stop the fetch process. |
| `end_timestamp` | `datetime.datetime` | No | The latest timestamp to include. Messages newer than this value will be skipped. |
| `start_timestamp` | `str`<br>`datetime.date`<br>`datetime.datetime`<br>`pandas.Timestamp` | No | The earliest timestamp to include. Messages older than this value will stop the fetch process. |
| `end_timestamp` | `str`<br>`datetime.date`<br>`datetime.datetime`<br>`pandas.Timestamp` | No | The latest timestamp to include. Messages newer than this value will be skipped. |
Both timestamps accept the same values as [`get_messages`](./account.md#get_messageschat_id-start_timestampnone-end_timestampnone) on `Account`, so a range can be written as a plain `str` - for example `2026-08-11 22:57:51.134000`, `2026-08-11 22:57` or `2026-08-11`.
Returns `list[dict]` containing message objects. Timestamp fields returned by the backend are automatically converted into `datetime.datetime` objects.
+41 -3
View File
@@ -813,7 +813,7 @@ class Account:
if "chats" in event or "messages" in event:
yield message
def get_messages(self, chat_id: str, start_timestamp: Optional[datetime.datetime] = None, end_timestamp: Optional[datetime.datetime] = None) -> list[dict]:
def get_messages(self, chat_id: str, start_timestamp: Optional[Union[str, datetime.datetime, datetime.date, pd.Timestamp]] = None, end_timestamp: Optional[Union[str, datetime.datetime, datetime.date, pd.Timestamp]] = None) -> list[dict]:
"""
Get all of the messages in the given start and end timestamps.
Messages are returned in descending order (newest to oldest).
@@ -821,12 +821,14 @@ class Account:
Parameters:
- `chat_id` - the chat ID can be found in `self.chats`
- `start_timestamp` - the start timestamp for message extraction. If not provided all early messages will be fetched.
- `end_timestamp` - the end timestamp for message extraction. If not provided all latest messages will be fetched.
- `start_timestamp` - the start timestamp for message extraction. If not provided all early messages will be fetched. Can be a `datetime.datetime` or a string like `2026-08-11 22:57:51.134000` / `2026-08-11 22:57` / `2026-08-11`
- `end_timestamp` - the end timestamp for message extraction. If not provided all latest messages will be fetched. Can be a `datetime.datetime` or a string like `2026-08-11 22:57:51.134000` / `2026-08-11 22:57` / `2026-08-11`
Output:
- All messages within the given range
"""
start_timestamp = self.__to_datetime(start_timestamp)
end_timestamp = self.__to_datetime(end_timestamp)
# NOTE: Order of params matters when making the RCP call
params = {
"chat_id": chat_id,
@@ -1707,6 +1709,42 @@ class Account:
s2 = re.sub(r'([a-z0-9])([A-Z])', r'\1_\2', s1)
return s2.lower()
def __to_datetime(self, timestamp: Union[str, datetime.datetime, datetime.date, pd.Timestamp, None]) -> Optional[datetime.datetime]:
"""
Convert a timestamp `str` / `datetime.date` into a `datetime.datetime`.
Parameters:
- `timestamp` - the timestamp, e.g. `2026-08-11 22:57:51.134000`, `2026-08-11 22:57`, `2026-08-11` or `datetime.date`. A `datetime.datetime` / `None` is returned as it is
Output:
- the `datetime.datetime` of the `timestamp`
"""
if timestamp is None or isinstance(timestamp, datetime.datetime):
return timestamp
if isinstance(timestamp, datetime.date):
return datetime.datetime(timestamp.year, timestamp.month, timestamp.day)
if isinstance(timestamp, pd.Timestamp):
timestamp = str(timestamp)
if not isinstance(timestamp, str):
raise exceptions.InvalidTimestampError(f"Expected a `str` or a `datetime.datetime`, got `{type(timestamp).__name__}`...")
# Accepted timestamp formats, tried from the most to the least precise
formats = [
"%Y-%m-%d %H:%M:%S.%f", "%Y-%m-%d %H:%M:%S",
"%Y-%m-%d %H:%M", "%Y-%m-%d %H", "%Y-%m-%d"
]
value = timestamp.strip().replace("T", " ")
for current_format in formats:
try:
return datetime.datetime.strptime(value, current_format)
except ValueError:
continue
raise exceptions.InvalidTimestampError(f"`{timestamp}` is not a valid timestamp. Supported formats: {', '.join(formats)}")
def __validate_display_name(self, name: str):
"""
Validate the display name based on Status App rules.
+5 -4
View File
@@ -1,6 +1,7 @@
from ..account import Account
from .. import exceptions
from typing import Optional
from typing import Union, Optional
import pandas as pd
import re, datetime, random, unicodedata
class Channel:
@@ -214,15 +215,15 @@ class Channel:
return self.__account.send_image(self.id, file_path, message, reply_to_message_id)
def get_messages(self, start_timestamp: Optional[datetime.datetime] = None, end_timestamp: Optional[datetime.datetime] = None) -> list[dict]:
def get_messages(self, start_timestamp: Optional[Union[str, datetime.datetime, datetime.date, pd.Timestamp]] = None, end_timestamp: Optional[Union[str, datetime.datetime, datetime.date, pd.Timestamp]] = None) -> list[dict]:
"""
Get all of the messages in the given start and end timestamps.
Messages are returned in descending order (newest to oldest).
Messages can be fetched for removed contacts as well.
Parameters:
- `start_timestamp` - the start timestamp for message extraction. If not provided all early messages will be fetched.
- `end_timestamp` - the end timestamp for message extraction. If not provided all latest messages will be fetched.
- `start_timestamp` - the start timestamp for message extraction. If not provided all early messages will be fetched. Can be a `datetime.datetime` or a string like `2026-08-11 22:57:51.134000` / `2026-08-11 22:57` / `2026-08-11`
- `end_timestamp` - the end timestamp for message extraction. If not provided all latest messages will be fetched. Can be a `datetime.datetime` or a string like `2026-08-11 22:57:51.134000` / `2026-08-11 22:57` / `2026-08-11`
Output:
- All messages within the given range
+3
View File
@@ -125,3 +125,6 @@ class SignalError(Exception):
class InvalidPathError(Exception):
pass
class InvalidTimestampError(ValueError):
pass
+4 -3
View File
@@ -1,6 +1,7 @@
from .account import Account
from . import exceptions
from typing import Union, Optional
import pandas as pd
import re, datetime
class GroupChat:
@@ -84,15 +85,15 @@ class GroupChat:
return self.__account.send_image(self.id, file_path, message, reply_to_message_id)
def get_messages(self, start_timestamp: Optional[datetime.datetime] = None, end_timestamp: Optional[datetime.datetime] = None) -> list[dict]:
def get_messages(self, start_timestamp: Optional[Union[str, datetime.datetime, datetime.date, pd.Timestamp]] = None, end_timestamp: Optional[Union[str, datetime.datetime, datetime.date, pd.Timestamp]] = None) -> list[dict]:
"""
Get all of the messages in the given start and end timestamps.
Messages are returned in descending order (newest to oldest).
Messages can be fetched for removed contacts as well.
Parameters:
- `start_timestamp` - the start timestamp for message extraction. If not provided all early messages will be fetched.
- `end_timestamp` - the end timestamp for message extraction. If not provided all latest messages will be fetched.
- `start_timestamp` - the start timestamp for message extraction. If not provided all early messages will be fetched. Can be a `datetime.datetime` or a string like `2026-08-11 22:57:51.134000` / `2026-08-11 22:57` / `2026-08-11`
- `end_timestamp` - the end timestamp for message extraction. If not provided all latest messages will be fetched. Can be a `datetime.datetime` or a string like `2026-08-11 22:57:51.134000` / `2026-08-11 22:57` / `2026-08-11`
Output:
- All messages within the given range