mirror of
https://github.com/paul-nameless/tg
synced 2024-11-22 20:03:17 +00:00
commit
afcc945416
6 changed files with 28 additions and 22 deletions
12
.github/workflows/main.yml
vendored
12
.github/workflows/main.yml
vendored
|
@ -18,7 +18,7 @@ jobs:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
strategy:
|
strategy:
|
||||||
matrix:
|
matrix:
|
||||||
python-version: [3.7]
|
python-version: [3.8]
|
||||||
|
|
||||||
# Steps represent a sequence of tasks that will be executed as part of the job
|
# Steps represent a sequence of tasks that will be executed as part of the job
|
||||||
steps:
|
steps:
|
||||||
|
@ -30,11 +30,15 @@ jobs:
|
||||||
with:
|
with:
|
||||||
python-version: ${{ matrix.python-version }}
|
python-version: ${{ matrix.python-version }}
|
||||||
|
|
||||||
- name: Install black
|
- name: Install tools
|
||||||
run: |
|
run: |
|
||||||
pip install black==19.10b0
|
pip install black==19.10b0 mypy==0.770
|
||||||
|
|
||||||
- name: Check formatting with black
|
- name: Check formatting with black
|
||||||
run: |
|
run: |
|
||||||
black --check .
|
black --check tg
|
||||||
|
|
||||||
|
- name: Check types with mypy
|
||||||
|
run: |
|
||||||
|
mypy tg --warn-redundant-casts --warn-unused-ignores --no-warn-no-return --warn-unreachable --strict-equality --ignore-missing-imports
|
||||||
|
|
||||||
|
|
|
@ -340,7 +340,6 @@ class Controller:
|
||||||
self.view.status.draw()
|
self.view.status.draw()
|
||||||
|
|
||||||
def refresh_msgs(self) -> None:
|
def refresh_msgs(self) -> None:
|
||||||
self.view.msgs.users = self.model.users
|
|
||||||
current_msg_idx = self.model.get_current_chat_msg_idx()
|
current_msg_idx = self.model.get_current_chat_msg_idx()
|
||||||
if current_msg_idx is None:
|
if current_msg_idx is None:
|
||||||
return
|
return
|
||||||
|
|
|
@ -2,7 +2,7 @@ import logging
|
||||||
import logging.handlers
|
import logging.handlers
|
||||||
import signal
|
import signal
|
||||||
import threading
|
import threading
|
||||||
from curses import window, wrapper
|
from curses import window, wrapper # type: ignore
|
||||||
from functools import partial
|
from functools import partial
|
||||||
|
|
||||||
from telegram.client import Telegram
|
from telegram.client import Telegram
|
||||||
|
@ -19,6 +19,7 @@ def run(tg: Telegram, stdscr: window) -> None:
|
||||||
# run this function in thread?
|
# run this function in thread?
|
||||||
view = View(stdscr)
|
view = View(stdscr)
|
||||||
model = Model(tg)
|
model = Model(tg)
|
||||||
|
view.msgs.users = model.users
|
||||||
controller = Controller(model, view, tg)
|
controller = Controller(model, view, tg)
|
||||||
for msg_type, handler in controller.handlers.items():
|
for msg_type, handler in controller.handlers.items():
|
||||||
tg.add_update_handler(msg_type, handler)
|
tg.add_update_handler(msg_type, handler)
|
||||||
|
|
|
@ -1,11 +1,9 @@
|
||||||
import logging
|
import logging
|
||||||
from collections import defaultdict
|
from collections import defaultdict
|
||||||
from typing import Any, Dict, List, Optional, Set, Union, Tuple
|
from typing import Any, Dict, List, Optional, Set, Tuple
|
||||||
|
|
||||||
from telegram.client import Telegram
|
from telegram.client import Telegram
|
||||||
|
|
||||||
from tg.msg import MsgProxy
|
|
||||||
|
|
||||||
log = logging.getLogger(__name__)
|
log = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
|
@ -325,8 +323,6 @@ class MsgModel:
|
||||||
log.info(f"message has been sent: {result.update}")
|
log.info(f"message has been sent: {result.update}")
|
||||||
|
|
||||||
def delete_msg(self, chat_id: int) -> bool:
|
def delete_msg(self, chat_id: int) -> bool:
|
||||||
if chat_id is None:
|
|
||||||
return False
|
|
||||||
selected_msg = self.current_msgs[chat_id]
|
selected_msg = self.current_msgs[chat_id]
|
||||||
msg_item = self.msgs[chat_id].pop(selected_msg)
|
msg_item = self.msgs[chat_id].pop(selected_msg)
|
||||||
self.current_msgs[chat_id] = min(
|
self.current_msgs[chat_id] = min(
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
import base64
|
import base64
|
||||||
import re
|
|
||||||
import curses
|
import curses
|
||||||
import logging
|
import logging
|
||||||
import math
|
import math
|
||||||
import os
|
import os
|
||||||
import random
|
import random
|
||||||
|
import re
|
||||||
import shlex
|
import shlex
|
||||||
import struct
|
import struct
|
||||||
import subprocess
|
import subprocess
|
||||||
|
|
|
@ -1,10 +1,11 @@
|
||||||
import curses
|
import curses
|
||||||
import logging
|
import logging
|
||||||
from _curses import window
|
from _curses import window # type: ignore
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
from typing import Any, Dict, List, Optional, Tuple
|
from typing import Any, Dict, List, Optional, Tuple, cast
|
||||||
|
|
||||||
from tg.colors import blue, cyan, get_color, magenta, reverse, white
|
from tg.colors import blue, cyan, get_color, magenta, reverse, white
|
||||||
|
from tg.models import UserModel
|
||||||
from tg.msg import MsgProxy
|
from tg.msg import MsgProxy
|
||||||
from tg.utils import emoji_pattern, num, truncate_to_len
|
from tg.utils import emoji_pattern, num, truncate_to_len
|
||||||
|
|
||||||
|
@ -62,7 +63,7 @@ class View:
|
||||||
):
|
):
|
||||||
break
|
break
|
||||||
|
|
||||||
return num(repeat_factor, default=1), keys or "UNKNOWN"
|
return cast(int, num(repeat_factor, default=1)), keys or "UNKNOWN"
|
||||||
|
|
||||||
|
|
||||||
class StatusView:
|
class StatusView:
|
||||||
|
@ -88,7 +89,7 @@ class StatusView:
|
||||||
self.win.addstr(0, 0, msg[: self.w - 1])
|
self.win.addstr(0, 0, msg[: self.w - 1])
|
||||||
self._refresh()
|
self._refresh()
|
||||||
|
|
||||||
def get_input(self, msg="") -> Optional[str]:
|
def get_input(self, msg="") -> str:
|
||||||
self.draw(msg)
|
self.draw(msg)
|
||||||
curses.curs_set(1)
|
curses.curs_set(1)
|
||||||
|
|
||||||
|
@ -103,7 +104,7 @@ class StatusView:
|
||||||
if buff:
|
if buff:
|
||||||
buff = buff[:-1]
|
buff = buff[:-1]
|
||||||
elif key == 7: # ^G cancel
|
elif key == 7: # ^G cancel
|
||||||
buff = None
|
buff = ""
|
||||||
break
|
break
|
||||||
elif chr(key).isprintable():
|
elif chr(key).isprintable():
|
||||||
buff += chr(key)
|
buff += chr(key)
|
||||||
|
@ -143,7 +144,7 @@ class ChatView:
|
||||||
return color | reverse
|
return color | reverse
|
||||||
return color
|
return color
|
||||||
|
|
||||||
def _chat_attributes(self, is_selected: bool = False) -> Tuple[int]:
|
def _chat_attributes(self, is_selected: bool = False) -> Tuple[int, ...]:
|
||||||
attrs = (
|
attrs = (
|
||||||
get_color(cyan, -1),
|
get_color(cyan, -1),
|
||||||
get_color(blue, -1),
|
get_color(blue, -1),
|
||||||
|
@ -155,7 +156,8 @@ class ChatView:
|
||||||
|
|
||||||
def draw(self, current: int, chats: List[Dict[str, Any]]) -> None:
|
def draw(self, current: int, chats: List[Dict[str, Any]]) -> None:
|
||||||
self.win.erase()
|
self.win.erase()
|
||||||
self.win.vline(0, self.w - 1, curses.ACS_VLINE, self.h)
|
line = curses.ACS_VLINE # type: ignore
|
||||||
|
self.win.vline(0, self.w - 1, line, self.h)
|
||||||
for i, chat in enumerate(chats):
|
for i, chat in enumerate(chats):
|
||||||
is_selected = i == current
|
is_selected = i == current
|
||||||
unread_count = chat["unread_count"]
|
unread_count = chat["unread_count"]
|
||||||
|
@ -218,6 +220,9 @@ class ChatView:
|
||||||
|
|
||||||
|
|
||||||
class MsgView:
|
class MsgView:
|
||||||
|
# FIXME: should be assigned from constructor
|
||||||
|
users: UserModel
|
||||||
|
|
||||||
def __init__(self, stdscr: window, p: float = 0.5) -> None:
|
def __init__(self, stdscr: window, p: float = 0.5) -> None:
|
||||||
self.stdscr = stdscr
|
self.stdscr = stdscr
|
||||||
self.h = 0
|
self.h = 0
|
||||||
|
@ -247,7 +252,7 @@ class MsgView:
|
||||||
function will remove message one by one from the start until selected
|
function will remove message one by one from the start until selected
|
||||||
message could be visible on the screen.
|
message could be visible on the screen.
|
||||||
"""
|
"""
|
||||||
selected_item_idx = None
|
selected_item_idx: Optional[int] = None
|
||||||
collected_items: List[Tuple[Tuple[str, ...], bool, int]] = []
|
collected_items: List[Tuple[Tuple[str, ...], bool, int]] = []
|
||||||
for ignore_before in range(len(msgs)):
|
for ignore_before in range(len(msgs)):
|
||||||
if selected_item_idx is not None:
|
if selected_item_idx is not None:
|
||||||
|
@ -276,6 +281,7 @@ class MsgView:
|
||||||
if (
|
if (
|
||||||
# ignore first and last msg
|
# ignore first and last msg
|
||||||
selected_item_idx not in (0, len(msgs) - 1, None)
|
selected_item_idx not in (0, len(msgs) - 1, None)
|
||||||
|
and selected_item_idx is not None
|
||||||
and len(collected_items) - 1 - selected_item_idx
|
and len(collected_items) - 1 - selected_item_idx
|
||||||
< min_msg_padding
|
< min_msg_padding
|
||||||
):
|
):
|
||||||
|
@ -307,7 +313,7 @@ class MsgView:
|
||||||
|
|
||||||
self._refresh()
|
self._refresh()
|
||||||
|
|
||||||
def _msg_attributes(self, is_selected: bool) -> Tuple[int]:
|
def _msg_attributes(self, is_selected: bool) -> Tuple[int, ...]:
|
||||||
attrs = (
|
attrs = (
|
||||||
get_color(cyan, -1),
|
get_color(cyan, -1),
|
||||||
get_color(blue, -1),
|
get_color(blue, -1),
|
||||||
|
@ -315,7 +321,7 @@ class MsgView:
|
||||||
)
|
)
|
||||||
|
|
||||||
if is_selected:
|
if is_selected:
|
||||||
return (attr | reverse for attr in attrs)
|
return tuple(attr | reverse for attr in attrs)
|
||||||
return attrs
|
return attrs
|
||||||
|
|
||||||
def _get_user_by_id(self, user_id: int) -> str:
|
def _get_user_by_id(self, user_id: int) -> str:
|
||||||
|
|
Loading…
Reference in a new issue