diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml new file mode 100644 index 0000000..ac1576d --- /dev/null +++ b/.github/workflows/codeql-analysis.yml @@ -0,0 +1,71 @@ +# For most projects, this workflow file will not need changing; you simply need +# to commit it to your repository. +# +# You may wish to alter this file to override the set of languages analyzed, +# or to provide custom queries or build logic. +# +# ******** NOTE ******** +# We have attempted to detect the languages in your repository. Please check +# the `language` matrix defined below to confirm you have the correct set of +# supported CodeQL languages. +# +name: "CodeQL" + +on: + push: + branches: [ main ] + pull_request: + # The branches below must be a subset of the branches above + branches: [ main ] + schedule: + - cron: '16 2 * * 4' + +jobs: + analyze: + name: Analyze + runs-on: ubuntu-latest + permissions: + actions: read + contents: read + security-events: write + + strategy: + fail-fast: false + matrix: + language: [ 'python' ] + # CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python' ] + # Learn more: + # https://docs.github.com/en/free-pro-team@latest/github/finding-security-vulnerabilities-and-errors-in-your-code/configuring-code-scanning#changing-the-languages-that-are-analyzed + + steps: + - name: Checkout repository + uses: actions/checkout@v2 + + # Initializes the CodeQL tools for scanning. + - name: Initialize CodeQL + uses: github/codeql-action/init@v1 + with: + languages: ${{ matrix.language }} + # If you wish to specify custom queries, you can do so here or in a config file. + # By default, queries listed here will override any specified in a config file. + # Prefix the list here with "+" to use these queries and those in the config file. + # queries: ./path/to/local/query, your-org/your-repo/queries@main + + # Autobuild attempts to build any compiled languages (C/C++, C#, or Java). + # If this step fails, then you should remove it and run the build manually (see below) + - name: Autobuild + uses: github/codeql-action/autobuild@v1 + + # ℹī¸ Command-line programs to run using the OS shell. + # 📚 https://git.io/JvXDl + + # ✏ī¸ If the Autobuild fails above, remove it and uncomment the following three lines + # and modify them (or add more) to build your code if your project + # uses a compiled language + + #- run: | + # make bootstrap + # make release + + - name: Perform CodeQL Analysis + uses: github/codeql-action/analyze@v1 diff --git a/BUGS.md b/BUGS.md index 5ded34f..df89fb9 100644 --- a/BUGS.md +++ b/BUGS.md @@ -9,7 +9,9 @@ A place of important bugs to fix outside of issues - 4 -- intended - 5 -- critical -| `state` | `issue` | `extra_info` | `id` | -| :---------: | :---------------------------------------------------------------------: | :-----------------------------------------------: | :----------: | -| 0 | When pinning chats the UI does not update until arigram is quit | | 0x0000000000 | +| `state` | `issue` | `extra_info` | `id` | +| :---------: | :-----------------------------------------------------------------------------: | :-----------------------------------------------: | :----------: | +| 0 | When pinning chats the UI does not update until arigram is quit | | 0x0000000000 | +| 1 | API changed, needs refactoring | | 0x0000000001 | +| 0 | Due to API changes and telegram needing more money -- needs sponsor support | | 0x0000000002 | diff --git a/README.md b/README.md index d827477..c902dd5 100644 --- a/README.md +++ b/README.md @@ -23,7 +23,7 @@ A fork of [tg](https://github.com/paul-nameless/tg) -- a hackable telegram TUI c - [x] better default file picker - [x] custom keybindings - [x] consistent styling -- [ ] drafts +- [x] drafts - [ ] scheduled messages - [ ] local passwords - [ ] debug mode @@ -32,6 +32,7 @@ A fork of [tg](https://github.com/paul-nameless/tg) -- a hackable telegram TUI c - [ ] less crowded UI - [ ] search (for users) - [ ] bots (bot keyboard) +- [ ] profile pictures ## Requirements diff --git a/arigram/config.py b/arigram/config.py index 3cbb565..c95b9a2 100644 --- a/arigram/config.py +++ b/arigram/config.py @@ -16,6 +16,7 @@ _global_mailcap = mailcap.getcaps() CONFIG_DIR = os.path.expanduser("~/.config/arigram/") CONFIG_FILE = os.path.join(CONFIG_DIR, "config.py") FILES_DIR = os.path.expanduser("~/.cache/arigram/") +DRAFTS_FILE = os.path.join(FILES_DIR, "drafts.json") MAILCAP_FILE: Optional[str] = None LOG_LEVEL = "INFO" diff --git a/arigram/controllers.py b/arigram/controllers.py index 6348080..67ed821 100644 --- a/arigram/controllers.py +++ b/arigram/controllers.py @@ -2,6 +2,8 @@ import logging import os import random import shlex +import json +import pyperclip import webbrowser from datetime import datetime from functools import partial, wraps @@ -333,6 +335,44 @@ class Controller: else: self.present_info("Message wasn't sent") + @bind(msg_handler, ["g"]) + def load_draft_message(self) -> None: + chat_id = self.model.chats.id_by_index(self.model.current_chat) + schat_id = str(chat_id) + if not self.can_send_msg() or chat_id is None: + self.present_info("Can't send msg in this chat") + return + elif not os.path.exists(config.DRAFTS_FILE): + self.present_info("You have no drafts") + return + + with open(config.DRAFTS_FILE, "r") as f: + try: + drafts_json = json.load(f) + except json.decoder.JSONDecodeError: + self.present_error("Drafts file corrupted: restoring") + + with open(config.DRAFTS_FILE, "w") as f: + f.write("{}") + + return + + if not drafts_json.get(schat_id): + self.present_info("No drafts found") + return + + draft = pyfzf.FzfPrompt().prompt(drafts_json[schat_id])[0] + drafts_json[schat_id].remove(draft) + + log.exception(str(drafts_json)) + + pyperclip.copy(draft) + # TODO: auto-insert draft + self.present_info("Draft copies to clipboard") + + with open(config.DRAFTS_FILE, "w") as f: + json.dump(drafts_json, f) + @bind(msg_handler, ["a", "i"]) def write_short_msg(self) -> None: chat_id = self.model.chats.id_by_index(self.model.current_chat) @@ -949,7 +989,7 @@ class Controller: return user = self.model.users.get_user(msg.sender_id) - name = f"{user['first_name']} {user['last_name']}" + name = f"{user.get('first_name')} {user.get('last_name')}" if text := msg.text_content if msg.is_text else msg.content_type: notify(text, title=name) diff --git a/arigram/models.py b/arigram/models.py index a816177..216ea9e 100644 --- a/arigram/models.py +++ b/arigram/models.py @@ -282,7 +282,7 @@ class Model: return { chat["title"]: f"{basic_info['member_count']} members", "Info": chat_info["description"], - "Share link": chat_info["invite_link"], + #"Share link": chat_info["invite_link"], } def get_supergroup_info(self, chat: Dict[str, Any]) -> Dict[str, Any]: @@ -291,10 +291,11 @@ class Model: ) result.wait() chat_info = result.update + log.exception(str(chat_info)) return { chat["title"]: f"{chat_info['member_count']} members", "Info": chat_info["description"], - "Share link": chat_info["invite_link"], + #"Share link": chat_info["invite_link"], } def get_channel_info(self, chat: Dict[str, Any]) -> Dict[str, Any]: @@ -306,7 +307,7 @@ class Model: return { chat["title"]: "subscribers", "Info": chat_info["description"], - "Share link": chat_info["invite_link"], + #"Share link": chat_info["invite_link"], } def get_secret_chat_info(self, chat: Dict[str, Any]) -> Dict[str, Any]: diff --git a/arigram/update_handlers.py b/arigram/update_handlers.py index 7d6218b..52e2021 100644 --- a/arigram/update_handlers.py +++ b/arigram/update_handlers.py @@ -1,10 +1,13 @@ import logging +import os +import json from functools import wraps from typing import Any, Callable, Dict from arigram import config, utils from arigram.controllers import Controller from arigram.msg import MsgProxy +from arigram.config import DRAFTS_FILE log = logging.getLogger(__name__) @@ -191,8 +194,24 @@ def update_chat_draft_message( ) -> None: chat_id = update["chat_id"] # FIXME: ignoring draft message itself for now because UI can't show it - # draft_message = update["draft_message"] - order = update["position"]["order"] + draft_message = update["draft_message"]["input_message_text"]["text"]["text"] + order = update["positions"][0]["order"] + + + if not os.path.exists(DRAFTS_FILE): + with open(DRAFTS_FILE, "w") as nf: + nf.write("{}") + + with open(DRAFTS_FILE, "r") as df: + dj = json.load(df) + + if not dj.get(chat_id): + dj[chat_id] = [] + dj[chat_id].append(draft_message) + + with open(DRAFTS_FILE, "w") as wdf: + json.dump(dj, wdf) + current_chat_id = controller.model.current_chat_id if controller.model.chats.update_chat(chat_id, order=order): diff --git a/do b/do index af4cfc8..4cb27a9 100755 --- a/do +++ b/do @@ -21,6 +21,13 @@ case $ARG in gh pr create -f ;; + push) + git diff > /tmp/arigram.diff + git add -A + git commit -S + git push -u origin main + ;; + release) CURRENT_VERSION=$(cat arigram/__init__.py | grep version | cut -d '"' -f 2) echo Current version $CURRENT_VERSION diff --git a/pyproject.toml b/pyproject.toml index d439c18..bef6c7e 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -13,6 +13,7 @@ repository = "https://github.com/TruncatedDinosour/arigram" python = "^3.8" python-telegram = "^0.15.0^" pyfzf = "^0.2.2" +pyperclip = "^1.8.2" [tool.poetry.dev-dependencies] black = "20.8b1" diff --git a/requirements.txt b/requirements.txt index a658b1d..85a8240 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,3 +1,4 @@ python-telegram>=0.15.0 pyfzf>=0.2.2 +pyperclip>=1.8.2 diff --git a/setup.py b/setup.py index 2c93448..07d2c94 100644 --- a/setup.py +++ b/setup.py @@ -23,5 +23,5 @@ setup( packages=["arigram"], entry_points={"console_scripts": ["arigram = arigram.__main__:main"]}, python_requires=">=3.8", - install_requires=["python-telegram>=0.15.0", "pyfzf>=0.2.2"], + install_requires=["python-telegram>=0.15.0", "pyfzf>=0.2.2", "pyperclip>=1.8.2"], )