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)
|
log.info("Open msg: %s", msg.msg)
|
||||||
if msg.is_text:
|
if msg.is_text:
|
||||||
text = msg["content"]["text"]["text"]
|
text = msg["content"]["text"]["text"]
|
||||||
with NamedTemporaryFile("w") as f:
|
with NamedTemporaryFile("w", suffix=".txt") as f:
|
||||||
f.write(text)
|
f.write(text)
|
||||||
f.flush()
|
f.flush()
|
||||||
with suspend(self.view) as s:
|
with suspend(self.view) as s:
|
||||||
s.call(["less", f.name])
|
s.run(f.name)
|
||||||
return
|
return
|
||||||
|
|
||||||
path = msg.local_path
|
path = msg.local_path
|
||||||
if path:
|
if path:
|
||||||
# handle with mimetype and mailcap
|
|
||||||
# if multiple entries in mailcap, open fzf to choose
|
|
||||||
with suspend(self.view) as s:
|
with suspend(self.view) as s:
|
||||||
log.info("Opening file: %s", path)
|
log.info("Opening file: %s", path)
|
||||||
s.call(["open", path])
|
s.run(path)
|
||||||
|
|
||||||
def handle_msgs(self) -> str:
|
def handle_msgs(self) -> str:
|
||||||
# set width to 0.25, move window to left
|
# set width to 0.25, move window to left
|
||||||
|
@ -200,12 +198,24 @@ class Controller:
|
||||||
|
|
||||||
@handle_exception
|
@handle_exception
|
||||||
def update_new_msg(self, update):
|
def update_new_msg(self, update):
|
||||||
chat_id = update["message"]["chat_id"]
|
msg = update["message"]
|
||||||
self.model.msgs.add_message(chat_id, update["message"])
|
chat_id = msg["chat_id"]
|
||||||
|
self.model.msgs.add_message(chat_id, msg)
|
||||||
self.refresh_msgs()
|
self.refresh_msgs()
|
||||||
if not update.get("disable_notification"):
|
|
||||||
if update["message"]["content"] == "text":
|
# notify
|
||||||
notify(update["message"]["content"]["text"]["text"])
|
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
|
@handle_exception
|
||||||
def update_chat_last_msg(self, update):
|
def update_chat_last_msg(self, update):
|
||||||
|
@ -218,7 +228,7 @@ class Controller:
|
||||||
# though need to make sure that creatinng index is atomic operation
|
# though need to make sure that creatinng index is atomic operation
|
||||||
# requires locks for read, until index and chats will be the same
|
# requires locks for read, until index and chats will be the same
|
||||||
for i, chat in enumerate(self.model.chats.chats):
|
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
|
self.model.current_chat = i
|
||||||
break
|
break
|
||||||
self.refresh_chats()
|
self.refresh_chats()
|
||||||
|
|
33
tg/main.py
33
tg/main.py
|
@ -1,6 +1,5 @@
|
||||||
import logging
|
import logging
|
||||||
import logging.handlers
|
import logging.handlers
|
||||||
import os
|
|
||||||
import threading
|
import threading
|
||||||
from curses import wrapper, window
|
from curses import wrapper, window
|
||||||
from functools import partial
|
from functools import partial
|
||||||
|
@ -10,23 +9,10 @@ from telegram.client import Telegram
|
||||||
from tg.controllers import Controller
|
from tg.controllers import Controller
|
||||||
from tg.models import Model
|
from tg.models import Model
|
||||||
from tg.views import View
|
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__)
|
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:
|
def run(tg: Telegram, stdscr: window) -> None:
|
||||||
|
@ -61,16 +47,17 @@ class TelegramApi(Telegram):
|
||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
|
cfg = config.get_cfg()["DEFAULT"]
|
||||||
|
utils.setup_log(cfg.get("level", "DEBUG"))
|
||||||
log.debug("#" * 64)
|
log.debug("#" * 64)
|
||||||
tg = TelegramApi(
|
tg = TelegramApi(
|
||||||
api_id=API_ID,
|
api_id=cfg["api_id"],
|
||||||
api_hash=API_HASH,
|
api_hash=cfg["api_hash"],
|
||||||
phone=PHONE,
|
phone=cfg["login"],
|
||||||
database_encryption_key="changeme1234",
|
database_encryption_key=cfg["enc_key"],
|
||||||
files_directory=os.path.expanduser("~/.cache/tg/"),
|
files_directory=cfg.get("files", config.DEFAULT_FILES),
|
||||||
tdlib_verbosity=0,
|
tdlib_verbosity=cfg.get("tdlib_verbosity", 0),
|
||||||
# TODO: add in config
|
library_path=cfg.get("library_path"),
|
||||||
library_path="/usr/local/Cellar/tdlib/1.6.0/lib/libtdjson.dylib",
|
|
||||||
)
|
)
|
||||||
tg.login()
|
tg.login()
|
||||||
wrapper(partial(run, tg))
|
wrapper(partial(run, tg))
|
||||||
|
|
|
@ -38,6 +38,7 @@ class Model:
|
||||||
if chat_id is None:
|
if chat_id is None:
|
||||||
return {}
|
return {}
|
||||||
current_msg = self.msgs.current_msgs[chat_id]
|
current_msg = self.msgs.current_msgs[chat_id]
|
||||||
|
log.info("current-msg: %s", current_msg)
|
||||||
return self.msgs.msgs[chat_id][current_msg]
|
return self.msgs.msgs[chat_id][current_msg]
|
||||||
|
|
||||||
def jump_bottom(self):
|
def jump_bottom(self):
|
||||||
|
@ -228,6 +229,11 @@ class MsgModel:
|
||||||
log.info(f"adding {msg_id=} {message}")
|
log.info(f"adding {msg_id=} {message}")
|
||||||
self.msgs[chat_id].append(message)
|
self.msgs[chat_id].append(message)
|
||||||
msg_set.add(msg_id)
|
msg_set.add(msg_id)
|
||||||
|
|
||||||
|
self.msgs[chat_id] = sorted(
|
||||||
|
self.msgs[chat_id], key=lambda d: d["id"], reverse=True
|
||||||
|
)
|
||||||
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def add_messages(self, chat_id: int, messages: Any) -> bool:
|
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)
|
messages = self._fetch_msgs_until_limit(chat_id, offset, limit)
|
||||||
self.add_messages(chat_id, messages)
|
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
|
offset:limit
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
42
tg/utils.py
42
tg/utils.py
|
@ -4,6 +4,7 @@ from typing import Optional
|
||||||
import subprocess
|
import subprocess
|
||||||
from functools import wraps
|
from functools import wraps
|
||||||
import curses
|
import curses
|
||||||
|
from tg import config
|
||||||
|
|
||||||
log = logging.getLogger(__name__)
|
log = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
@ -15,17 +16,32 @@ def num(value: str, default: Optional[int] = None) -> Optional[int]:
|
||||||
return default
|
return default
|
||||||
|
|
||||||
|
|
||||||
def notify(msg, subtitle="New message", title="Telegram"):
|
def setup_log(level="DEBUG"):
|
||||||
msg = "-message {!r}".format(msg)
|
logging.basicConfig(
|
||||||
subtitle = "-subtitle {!r}".format(subtitle)
|
level=level,
|
||||||
title = "-title {!r}".format(title)
|
format="%(asctime)s %(levelname)s %(message)s",
|
||||||
sound = "-sound default"
|
handlers=[
|
||||||
icon_path = os.path.join(os.path.dirname(__file__), "tg.png")
|
logging.handlers.RotatingFileHandler(
|
||||||
icon = f"-appIcon {icon_path}"
|
"./tg.log", backupCount=1, maxBytes=1024 * 1024
|
||||||
cmd = "/usr/local/bin/terminal-notifier"
|
),
|
||||||
|
],
|
||||||
|
)
|
||||||
|
|
||||||
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):
|
def handle_exception(fun):
|
||||||
|
@ -46,6 +62,12 @@ class suspend:
|
||||||
def call(self, *args, **kwargs):
|
def call(self, *args, **kwargs):
|
||||||
subprocess.call(*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):
|
def __enter__(self):
|
||||||
curses.endwin()
|
curses.endwin()
|
||||||
return self
|
return self
|
||||||
|
|
Loading…
Reference in a new issue