mirror of
https://github.com/paul-nameless/tg
synced 2024-11-22 11:53:08 +00:00
Add config file
Add mailcap support to open files Fix setting invalid current_msg when new comes
This commit is contained in:
parent
c7d535fdd7
commit
b20fc378de
5 changed files with 102 additions and 45 deletions
32
tg/config.py
Normal file
32
tg/config.py
Normal file
|
@ -0,0 +1,32 @@
|
|||
import os
|
||||
import configparser
|
||||
import mailcap
|
||||
import mimetypes
|
||||
|
||||
DEFAULT_CONFIG = os.path.expanduser("~/.config/tg/tg.conf")
|
||||
DEFAULT_FILES = os.path.expanduser("~/.cache/tg/")
|
||||
|
||||
|
||||
def get_cfg(config=DEFAULT_CONFIG):
|
||||
cfg = configparser.ConfigParser()
|
||||
cfg.read(config)
|
||||
return cfg
|
||||
|
||||
|
||||
def save_cfg(cfg, config=DEFAULT_CONFIG):
|
||||
config_dir = os.path.dirname(config)
|
||||
if not os.path.isdir(config_dir):
|
||||
os.makedirs(config_dir)
|
||||
with open(config, "w") as f:
|
||||
cfg.write(f)
|
||||
|
||||
|
||||
def get_file_handler(file_name, default=None):
|
||||
mtype, _ = mimetypes.guess_type(file_name)
|
||||
if not mtype:
|
||||
return default
|
||||
caps = mailcap.getcaps()
|
||||
handler, view = mailcap.findmatch(caps, mtype, filename=file_name)
|
||||
if not handler:
|
||||
return None
|
||||
return handler
|
|
@ -54,20 +54,18 @@ class Controller:
|
|||
log.info("Open msg: %s", msg.msg)
|
||||
if msg.is_text:
|
||||
text = msg["content"]["text"]["text"]
|
||||
with NamedTemporaryFile("w") as f:
|
||||
with NamedTemporaryFile("w", suffix=".txt") as f:
|
||||
f.write(text)
|
||||
f.flush()
|
||||
with suspend(self.view) as s:
|
||||
s.call(["less", f.name])
|
||||
s.run(f.name)
|
||||
return
|
||||
|
||||
path = msg.local_path
|
||||
if path:
|
||||
# handle with mimetype and mailcap
|
||||
# if multiple entries in mailcap, open fzf to choose
|
||||
with suspend(self.view) as s:
|
||||
log.info("Opening file: %s", path)
|
||||
s.call(["open", path])
|
||||
s.run(path)
|
||||
|
||||
def handle_msgs(self) -> str:
|
||||
# set width to 0.25, move window to left
|
||||
|
@ -200,12 +198,24 @@ class Controller:
|
|||
|
||||
@handle_exception
|
||||
def update_new_msg(self, update):
|
||||
chat_id = update["message"]["chat_id"]
|
||||
self.model.msgs.add_message(chat_id, update["message"])
|
||||
msg = update["message"]
|
||||
chat_id = msg["chat_id"]
|
||||
self.model.msgs.add_message(chat_id, msg)
|
||||
self.refresh_msgs()
|
||||
if not update.get("disable_notification"):
|
||||
if update["message"]["content"] == "text":
|
||||
notify(update["message"]["content"]["text"]["text"])
|
||||
|
||||
# notify
|
||||
user_id = msg["sender_user_id"]
|
||||
if msg["sender_user_id"] == self.model.get_me()["id"]:
|
||||
return
|
||||
user = self.model.users.get_user(user_id)
|
||||
name = "{} {}".format(user["first_name"], user["last_name"])
|
||||
_type = msg["content"]["@type"]
|
||||
|
||||
if _type == "messageText":
|
||||
text = msg["content"]["text"]["text"]
|
||||
else:
|
||||
text = MsgProxy.types.get(_type, "")
|
||||
notify(text, title=name)
|
||||
|
||||
@handle_exception
|
||||
def update_chat_last_msg(self, update):
|
||||
|
@ -218,7 +228,7 @@ class Controller:
|
|||
# though need to make sure that creatinng index is atomic operation
|
||||
# requires locks for read, until index and chats will be the same
|
||||
for i, chat in enumerate(self.model.chats.chats):
|
||||
if chat['id'] == current_chat_id:
|
||||
if chat["id"] == current_chat_id:
|
||||
self.model.current_chat = i
|
||||
break
|
||||
self.refresh_chats()
|
||||
|
|
33
tg/main.py
33
tg/main.py
|
@ -1,6 +1,5 @@
|
|||
import logging
|
||||
import logging.handlers
|
||||
import os
|
||||
import threading
|
||||
from curses import wrapper, window
|
||||
from functools import partial
|
||||
|
@ -10,23 +9,10 @@ from telegram.client import Telegram
|
|||
from tg.controllers import Controller
|
||||
from tg.models import Model
|
||||
from tg.views import View
|
||||
from tg import config, utils
|
||||
|
||||
logging.basicConfig(
|
||||
level=os.getenv("LOG_LEVEL", "DEBUG"),
|
||||
format="%(asctime)s %(levelname)s %(message)s",
|
||||
handlers=[
|
||||
logging.handlers.RotatingFileHandler(
|
||||
"./tg.log", backupCount=1, maxBytes=1024 * 256
|
||||
),
|
||||
],
|
||||
)
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
API_ID = os.getenv("API_ID")
|
||||
API_HASH = os.getenv("API_HASH")
|
||||
PHONE = os.getenv("PHONE")
|
||||
if PHONE is None:
|
||||
raise Exception("Environment variables did not provided")
|
||||
|
||||
|
||||
def run(tg: Telegram, stdscr: window) -> None:
|
||||
|
@ -61,16 +47,17 @@ class TelegramApi(Telegram):
|
|||
|
||||
|
||||
def main():
|
||||
cfg = config.get_cfg()["DEFAULT"]
|
||||
utils.setup_log(cfg.get("level", "DEBUG"))
|
||||
log.debug("#" * 64)
|
||||
tg = TelegramApi(
|
||||
api_id=API_ID,
|
||||
api_hash=API_HASH,
|
||||
phone=PHONE,
|
||||
database_encryption_key="changeme1234",
|
||||
files_directory=os.path.expanduser("~/.cache/tg/"),
|
||||
tdlib_verbosity=0,
|
||||
# TODO: add in config
|
||||
library_path="/usr/local/Cellar/tdlib/1.6.0/lib/libtdjson.dylib",
|
||||
api_id=cfg["api_id"],
|
||||
api_hash=cfg["api_hash"],
|
||||
phone=cfg["login"],
|
||||
database_encryption_key=cfg["enc_key"],
|
||||
files_directory=cfg.get("files", config.DEFAULT_FILES),
|
||||
tdlib_verbosity=cfg.get("tdlib_verbosity", 0),
|
||||
library_path=cfg.get("library_path"),
|
||||
)
|
||||
tg.login()
|
||||
wrapper(partial(run, tg))
|
||||
|
|
|
@ -38,6 +38,7 @@ class Model:
|
|||
if chat_id is None:
|
||||
return {}
|
||||
current_msg = self.msgs.current_msgs[chat_id]
|
||||
log.info("current-msg: %s", current_msg)
|
||||
return self.msgs.msgs[chat_id][current_msg]
|
||||
|
||||
def jump_bottom(self):
|
||||
|
@ -228,6 +229,11 @@ class MsgModel:
|
|||
log.info(f"adding {msg_id=} {message}")
|
||||
self.msgs[chat_id].append(message)
|
||||
msg_set.add(msg_id)
|
||||
|
||||
self.msgs[chat_id] = sorted(
|
||||
self.msgs[chat_id], key=lambda d: d["id"], reverse=True
|
||||
)
|
||||
|
||||
return True
|
||||
|
||||
def add_messages(self, chat_id: int, messages: Any) -> bool:
|
||||
|
@ -276,7 +282,7 @@ class MsgModel:
|
|||
messages = self._fetch_msgs_until_limit(chat_id, offset, limit)
|
||||
self.add_messages(chat_id, messages)
|
||||
|
||||
return sorted(self.msgs[chat_id], key=lambda d: d["id"])[::-1][
|
||||
return sorted(self.msgs[chat_id], key=lambda d: d["id"], reverse=True)[
|
||||
offset:limit
|
||||
]
|
||||
|
||||
|
|
42
tg/utils.py
42
tg/utils.py
|
@ -4,6 +4,7 @@ from typing import Optional
|
|||
import subprocess
|
||||
from functools import wraps
|
||||
import curses
|
||||
from tg import config
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
|
@ -15,17 +16,32 @@ def num(value: str, default: Optional[int] = None) -> Optional[int]:
|
|||
return default
|
||||
|
||||
|
||||
def notify(msg, subtitle="New message", title="Telegram"):
|
||||
msg = "-message {!r}".format(msg)
|
||||
subtitle = "-subtitle {!r}".format(subtitle)
|
||||
title = "-title {!r}".format(title)
|
||||
sound = "-sound default"
|
||||
icon_path = os.path.join(os.path.dirname(__file__), "tg.png")
|
||||
icon = f"-appIcon {icon_path}"
|
||||
cmd = "/usr/local/bin/terminal-notifier"
|
||||
def setup_log(level="DEBUG"):
|
||||
logging.basicConfig(
|
||||
level=level,
|
||||
format="%(asctime)s %(levelname)s %(message)s",
|
||||
handlers=[
|
||||
logging.handlers.RotatingFileHandler(
|
||||
"./tg.log", backupCount=1, maxBytes=1024 * 1024
|
||||
),
|
||||
],
|
||||
)
|
||||
|
||||
log.debug("####: %s", f"{cmd} {icon} {sound} {title} {subtitle} {msg}")
|
||||
os.system(f"{cmd} {icon} {sound} {title} {subtitle} {msg}")
|
||||
|
||||
def notify(
|
||||
msg,
|
||||
subtitle="",
|
||||
title="tg",
|
||||
cmd=config.get_cfg()["DEFAULT"].get("notify_cmd"),
|
||||
):
|
||||
if not cmd:
|
||||
return
|
||||
icon_path = os.path.join(os.path.dirname(__file__), "tg.png")
|
||||
notify_cmd = cmd.format(
|
||||
icon_path=icon_path, title=title, subtitle=subtitle, msg=msg
|
||||
)
|
||||
log.info("notify-cmd: %s", notify_cmd)
|
||||
os.system(notify_cmd)
|
||||
|
||||
|
||||
def handle_exception(fun):
|
||||
|
@ -46,6 +62,12 @@ class suspend:
|
|||
def call(self, *args, **kwargs):
|
||||
subprocess.call(*args, **kwargs)
|
||||
|
||||
def run(self, file_path):
|
||||
cmd = config.get_file_handler(file_path)
|
||||
if not cmd:
|
||||
return
|
||||
subprocess.call(cmd, shell=True)
|
||||
|
||||
def __enter__(self):
|
||||
curses.endwin()
|
||||
return self
|
||||
|
|
Loading…
Reference in a new issue