From 680fa3e3dc43e70b57f8c2646121233c1a752de7 Mon Sep 17 00:00:00 2001 From: Bob Belderbos Date: Mon, 31 Jul 2023 14:35:27 +0200 Subject: [PATCH] karma update messages to dedicated log channel + remove SPECIAL_REPLIES (#114) * bump version * fix action file * Update README.md * Update README.md * Update README.md * Update .pre-commit-config.yaml https://github.com/PyBites-Open-Source/karmabot/issues/107 * test commit * add a runtime * bug toml file: remote: -----> Add Poetry to the PATH remote: -----> Export requirements.txt from Poetry remote: remote: TOMLError remote: remote: Invalid TOML file /tmp/build_fd4bfa75/pyproject.toml: Key "name" already exists. * another duplicated key: remote: -----> Add Poetry to the PATH remote: -----> Export requirements.txt from Poetry remote: remote: TOMLError remote: remote: Invalid TOML file /tmp/build_0b421871/pyproject.toml: Key "version" already exists. * fix for https://github.com/PyBites-Open-Source/karmabot/issues/103 bumped version upgraded pre-commit pre-commit mypy errors: removed int type hint from KarmaNote + changed | to Union (which should have been supported hm) * fix test * fixes https://github.com/PyBites-Open-Source/karmabot/issues/113 * update readme --- .github/workflows/pre_release.yml | 1 + .pre-commit-config.yaml | 4 +- README.md | 6 ++- noxfile.py | 1 + pyproject.toml | 2 +- runtime.txt | 1 + src/karmabot/bot.py | 32 ++-------------- src/karmabot/db/karma_note.py | 64 +++++++++++++++---------------- src/karmabot/settings.py | 4 +- tests/test_bot.py | 25 +++--------- 10 files changed, 55 insertions(+), 85 deletions(-) create mode 100644 runtime.txt diff --git a/.github/workflows/pre_release.yml b/.github/workflows/pre_release.yml index c4e2f83..fc6b70e 100644 --- a/.github/workflows/pre_release.yml +++ b/.github/workflows/pre_release.yml @@ -24,6 +24,7 @@ jobs: - name: Set testpypi repo run: poetry config repositories.testpypi https://test.pypi.org/legacy/ + - name: Set testpypi token run: poetry config pypi-token.testpypi ${{ secrets.TEST_PYPI_API_TOKEN }} diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index a60b1be..0545f84 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -37,7 +37,7 @@ repos: args: ["--profile", "black", "--filter-files"] - repo: https://github.com/psf/black - rev: 23.3.0 + rev: 23.7.0 hooks: - id: black language_version: python3 @@ -49,6 +49,6 @@ repos: args: [--no-strict-optional, --ignore-missing-imports] - repo: https://github.com/asottile/pyupgrade - rev: v3.8.0 + rev: v3.9.0 hooks: - id: pyupgrade diff --git a/README.md b/README.md index 37b1363..1e86abb 100644 --- a/README.md +++ b/README.md @@ -49,6 +49,7 @@ KARMABOT_SLACK_APP_TOKEN= # Workspace KARMABOT_SLACK_USER= KARMABOT_GENERAL_CHANNEL= +KARMABOT_LOG_CHANNEL= KARMABOT_ADMINS= # Backend @@ -71,6 +72,9 @@ KARMABOT_SLACK_USER KARMABOT_GENERAL_CHANNEL : The channel id of your main channel in slack. Initially, you can fill in a placeholder. Once you've run your own Karmabot for the first time, you can ask it as admin in private chat via `@Karmabot general_channel_id`. This will return a value starting with `C`, e.g., `C0123XYZ`. Replace your placeholder with this value. +KARMABOT_LOG_CHANNEL +: The channel id (Cxyz) of the channel the bot logs karma point changes to (e.g. "bobtester2's karma increased to 9") + KARMABOT_ADMINS : The [slack user ids](https://api.slack.com/methods/users.identity) of the users that should have admin command access separated by commas. @@ -152,6 +156,6 @@ To ensure consistency you can use pre-commit. `pip install pre-commit` and after This will enable pre-commit hooks for checking before every commit. -### The story +### The story behind Karmabot Listen to Karmabot's core developer / maintainer Patrick Groß sharing the backstory of this project [on our podcast](https://www.pybitespodcast.com/1501156/8317703-022-the-karmabot-story-and-contributing-to-open-source). diff --git a/noxfile.py b/noxfile.py index e659ea1..c26d786 100644 --- a/noxfile.py +++ b/noxfile.py @@ -11,6 +11,7 @@ env = { "KARMABOT_SLACK_USER": "FAKE_BOT_USER", "KARMABOT_GENERAL_CHANNEL": "FAKE_GENERAL_CHANNEL", + "KARMABOT_LOG_CHANNEL": "FAKE_LOG_CHANNEL", "KARMABOT_ADMINS": "FAKE_ADMIN1,FAKE_ADMIN2,FAKE_ADMIN3", "KARMABOT_DATABASE_URL": "FAKE_DB_URL", "KARMABOT_SLACK_APP_TOKEN": "FAKE_APP_TOKEN", diff --git a/pyproject.toml b/pyproject.toml index 110f81a..39fc174 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,5 +1,6 @@ [tool.poetry] name = "karmabot" +version = "3.2.0" authors = ["PyBites ", "Patrick-Oliver Groß "] classifiers = [ "License :: OSI Approved :: MIT License", @@ -16,7 +17,6 @@ license = "MIT" maintainers = ["Patrick-Oliver Groß "] readme = "README.md" repository = "https://github.com/PyBites-Open-Source/karmabot" -version = "3.1.0" [tool.poetry.dependencies] SQLAlchemy = "^2.0.1" diff --git a/runtime.txt b/runtime.txt new file mode 100644 index 0000000..04d03e3 --- /dev/null +++ b/runtime.txt @@ -0,0 +1 @@ +python-3.11.2 diff --git a/src/karmabot/bot.py b/src/karmabot/bot.py index e6f4932..3f86dc0 100644 --- a/src/karmabot/bot.py +++ b/src/karmabot/bot.py @@ -27,6 +27,7 @@ ADMINS, KARMA_ACTION_PATTERN, KARMABOT_ID, + LOG_CHANNEL, SLACK_BOT_TOKEN, TEST_MODE, ) @@ -59,13 +60,6 @@ "updateusername": update_username, } -# other constants -SPECIAL_REPLIES = { - "zen": "`import this`", - "cheers": ":beers:", - "braces": "`SyntaxError: not a chance`", -} - def compile_command_pattern(commands: Dict[str, Callable]) -> re.Pattern: command_words = commands.keys() @@ -76,18 +70,11 @@ def compile_command_pattern(commands: Dict[str, Callable]) -> re.Pattern: return re.compile(full_commands, re.IGNORECASE) -def compile_special_reply_pattern(replies: Dict[str, str]) -> re.Pattern: - special_words = "|".join(replies.keys()) - pattern = rf"(?\s)({special_words})" - return re.compile(pattern, flags=re.MULTILINE | re.IGNORECASE) - - ADMIN_COMMAND_PATTERN = compile_command_pattern(ADMIN_BOT_COMMANDS) CHANNEL_COMMAND_PATTERN = compile_command_pattern(CHANNEL_BOT_COMMANDS) # type: ignore DM_COMMAND_PATTERN = compile_command_pattern(DM_BOT_COMMANDS) # type: ignore UNKNOWN_COMMAND_PATTERN = re.compile(rf"^<@{KARMABOT_ID}>\s(\w*)") HELP_COMMAND_PATTERN = re.compile(rf"^<@{KARMABOT_ID}>\s(help|commands)") -SPECIAL_WORDS_PATTERN = compile_special_reply_pattern(SPECIAL_REPLIES) COMMAND_ERROR = "Sorry, something went wrong when performing the requested command" # Slack Bolt App Init @@ -130,9 +117,8 @@ def karma_action(message, say): karma_changes = KARMA_ACTION_PATTERN.findall(msg) karma_replies = process_karma_changes(karma_giver, channel_id, karma_changes) - - reply = "\n\n".join(karma_replies) - say(reply) + for reply in karma_replies: + say(reply, channel=LOG_CHANNEL) # Help @@ -157,18 +143,6 @@ def reply_help(message, say): say(text=text, channel=user_id) -# Message replies -@app.message(SPECIAL_WORDS_PATTERN) # type: ignore -def reply_special_words(message, say): - msg = message["text"].lower() - special_word = SPECIAL_WORDS_PATTERN.findall(msg)[0] - special_reply = SPECIAL_REPLIES.get(special_word) - - text = f"To _{special_word}_ I say: {special_reply}" - - say(text) - - # Commands @app.event("message") # type: ignore def reply_commands(message, say): # noqa diff --git a/src/karmabot/db/karma_note.py b/src/karmabot/db/karma_note.py index 9ab5dcd..085959e 100644 --- a/src/karmabot/db/karma_note.py +++ b/src/karmabot/db/karma_note.py @@ -1,32 +1,32 @@ -import datetime - -import sqlalchemy as sa - -from karmabot.db.modelbase import SqlAlchemyBase - - -class KarmaNote(SqlAlchemyBase): - """Models a simple note system in the DB""" - - __tablename__ = "karma_note" - - id: int = sa.Column( # noqa - sa.BigInteger().with_variant(sa.Integer, "sqlite"), - primary_key=True, - autoincrement=True, - ) - user_id = sa.Column(sa.String, sa.ForeignKey("karma_user.user_id"), nullable=False) - timestamp = sa.Column(sa.DateTime, default=datetime.datetime.now, nullable=False) - note = sa.Column(sa.String) - - def __repr__(self): - return ( - f"[KarmaNote] ID: {self.id} | {self.user_id} -> " - f"{self.timestamp} | Note: {self.note}" - ) - - def __str__(self): - return ( - f"(ID: {self.id}) from {self.timestamp.strftime('%Y-%m-%d, %H:%M')}: " - f"{self.note}." - ) +import datetime + +import sqlalchemy as sa + +from karmabot.db.modelbase import SqlAlchemyBase + + +class KarmaNote(SqlAlchemyBase): + """Models a simple note system in the DB""" + + __tablename__ = "karma_note" + + id = sa.Column( # noqa + sa.BigInteger().with_variant(sa.Integer, "sqlite"), + primary_key=True, + autoincrement=True, + ) + user_id = sa.Column(sa.String, sa.ForeignKey("karma_user.user_id"), nullable=False) + timestamp = sa.Column(sa.DateTime, default=datetime.datetime.now, nullable=False) + note = sa.Column(sa.String) + + def __repr__(self): + return ( + f"[KarmaNote] ID: {self.id} | {self.user_id} -> " + f"{self.timestamp} | Note: {self.note}" + ) + + def __str__(self): + return ( + f"(ID: {self.id}) from {self.timestamp.strftime('%Y-%m-%d, %H:%M')}: " + f"{self.note}." + ) diff --git a/src/karmabot/settings.py b/src/karmabot/settings.py index 62eefeb..a20e49b 100644 --- a/src/karmabot/settings.py +++ b/src/karmabot/settings.py @@ -2,11 +2,12 @@ import os import re from pathlib import Path +from typing import Union from dotenv import load_dotenv -def get_env_var(env_var: str, default: str | None = None) -> str: +def get_env_var(env_var: str, default: Union[str, None] = None) -> str: env_var_value = os.environ.get(env_var) # explicit check for None as None is returned by environ.get for non existing keys @@ -41,6 +42,7 @@ def get_env_var(env_var: str, default: str | None = None) -> str: # Slack GENERAL_CHANNEL = get_env_var("KARMABOT_GENERAL_CHANNEL") +LOG_CHANNEL = get_env_var("KARMABOT_LOG_CHANNEL") ADMINS = get_env_var("KARMABOT_ADMINS") ADMINS = ADMINS.split(",") # type: ignore diff --git a/tests/test_bot.py b/tests/test_bot.py index c8ed961..5cbd8fd 100644 --- a/tests/test_bot.py +++ b/tests/test_bot.py @@ -2,11 +2,15 @@ import pytest -from karmabot.bot import karma_action, reply_commands, reply_help, reply_special_words +from karmabot.bot import karma_action, reply_commands, reply_help from karmabot.commands.welcome import welcome_user from karmabot.settings import KARMABOT_ID +def _fake_say(text, channel=None): + print(text) + + @pytest.mark.parametrize( "test_message, expected", [ @@ -22,24 +26,7 @@ ) @pytest.mark.usefixtures("mock_filled_db_session", "save_transaction_disabled") def test_karma_action(capfd, test_message, expected): - karma_action(test_message, print) # type: ignore - out = capfd.readouterr()[0] - assert out.strip() == expected - - -@pytest.mark.parametrize( - "test_message, expected", - [ - ({"text": "Cheers everybody"}, "To _cheers_ I say: :beers:"), - ({"text": "What about zen?"}, "To _zen_ I say: `import this`"), - ( - {"text": "Anyone likes braces, huh?"}, - "To _braces_ I say: `SyntaxError: not a chance`", - ), - ], -) -def test_reply_special_words(capfd, test_message, expected): - reply_special_words(test_message, print) # type: ignore + karma_action(test_message, _fake_say) # type: ignore out = capfd.readouterr()[0] assert out.strip() == expected