forked from iarv/contact
Compare commits
6 Commits
errors
...
check-db-f
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
43435cbe04 | ||
|
|
fe98075582 | ||
|
|
8716ea6fe1 | ||
|
|
a8bdcbb7e6 | ||
|
|
02742b27f3 | ||
|
|
ae028032a0 |
@@ -7,10 +7,51 @@ from typing import Dict
|
||||
script_dir = os.path.dirname(os.path.abspath(__file__))
|
||||
parent_dir = os.path.abspath(os.path.join(script_dir, os.pardir))
|
||||
|
||||
# Paths
|
||||
json_file_path = os.path.join(parent_dir, "config.json")
|
||||
log_file_path = os.path.join(parent_dir, "client.log")
|
||||
db_file_path = os.path.join(parent_dir, "client.db")
|
||||
|
||||
def _is_writable_dir(path: str) -> bool:
|
||||
"""
|
||||
Return True if we can create & delete a temp file in `path`.
|
||||
"""
|
||||
if not os.path.isdir(path):
|
||||
return False
|
||||
test_path = os.path.join(path, ".perm_test_tmp")
|
||||
try:
|
||||
with open(test_path, "w", encoding="utf-8") as _tmp:
|
||||
_tmp.write("ok")
|
||||
os.remove(test_path)
|
||||
return True
|
||||
except OSError:
|
||||
return False
|
||||
|
||||
|
||||
def _get_config_root(preferred_dir: str, fallback_name: str = ".contact_client") -> str:
|
||||
"""
|
||||
Choose a writable directory for config artifacts.
|
||||
"""
|
||||
if _is_writable_dir(preferred_dir):
|
||||
return preferred_dir
|
||||
|
||||
home = os.path.expanduser("~")
|
||||
fallback_dir = os.path.join(home, fallback_name)
|
||||
# Ensure the fallback exists.
|
||||
os.makedirs(fallback_dir, exist_ok=True)
|
||||
|
||||
# If *that* still isn't writable, last-ditch: use a system temp dir.
|
||||
if not _is_writable_dir(fallback_dir):
|
||||
import tempfile
|
||||
|
||||
fallback_dir = tempfile.mkdtemp(prefix="contact_client_")
|
||||
|
||||
return fallback_dir
|
||||
|
||||
|
||||
# Pick the root now.
|
||||
config_root = _get_config_root(parent_dir)
|
||||
|
||||
# Paths (derived from the chosen root)
|
||||
json_file_path = os.path.join(config_root, "config.json")
|
||||
log_file_path = os.path.join(config_root, "client.log")
|
||||
db_file_path = os.path.join(config_root, "client.db")
|
||||
|
||||
|
||||
def format_json_single_line_arrays(data: Dict[str, object], indent: int = 4) -> str:
|
||||
|
||||
@@ -116,7 +116,14 @@ def load_messages_from_db() -> None:
|
||||
|
||||
# Add messages to ui_state.all_messages grouped by hourly timestamp
|
||||
hourly_messages = {}
|
||||
for user_id, message, timestamp, ack_type in db_messages:
|
||||
for row in db_messages:
|
||||
user_id, message, timestamp, ack_type = row
|
||||
|
||||
# Only ack_type is allowed to be None
|
||||
if user_id is None or message is None or timestamp is None:
|
||||
logging.warning(f"Skipping row with NULL required field(s): {row}")
|
||||
continue
|
||||
|
||||
hour = datetime.fromtimestamp(timestamp).strftime("%Y-%m-%d %H:00")
|
||||
if hour not in hourly_messages:
|
||||
hourly_messages[hour] = []
|
||||
@@ -130,11 +137,13 @@ def load_messages_from_db() -> None:
|
||||
ack_str = config.nak_str
|
||||
|
||||
if user_id == str(interface_state.myNodeNum):
|
||||
formatted_message = (f"{config.sent_message_prefix}{ack_str}: ", message)
|
||||
sanitized_message = message.replace("\x00", "")
|
||||
formatted_message = (f"{config.sent_message_prefix}{ack_str}: ", sanitized_message)
|
||||
else:
|
||||
sanitized_message = message.replace("\x00", "")
|
||||
formatted_message = (
|
||||
f"{config.message_prefix} {get_name_from_database(int(user_id), 'short')}: ",
|
||||
message,
|
||||
sanitized_message,
|
||||
)
|
||||
|
||||
hourly_messages[hour].append(formatted_message)
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[project]
|
||||
name = "contact"
|
||||
version = "1.3.15"
|
||||
version = "1.3.16"
|
||||
description = "This Python curses client for Meshtastic is a terminal-based client designed to manage device settings, enable mesh chat communication, and handle configuration backups and restores."
|
||||
authors = [
|
||||
{name = "Ben Lipsey",email = "ben@pdxlocations.com"}
|
||||
|
||||
Reference in New Issue
Block a user