Skip to content

Commit

Permalink
karma update messages to dedicated log channel + remove SPECIAL_REPLI…
Browse files Browse the repository at this point in the history
…ES (#114)

* bump version

* fix action file

* Update README.md

* Update README.md

* Update README.md

* Update .pre-commit-config.yaml

#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 #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 #113

* update readme
  • Loading branch information
bbelderbos committed Jul 31, 2023
1 parent ba9d25a commit 680fa3e
Show file tree
Hide file tree
Showing 10 changed files with 55 additions and 85 deletions.
1 change: 1 addition & 0 deletions .github/workflows/pre_release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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 }}

Expand Down
4 changes: 2 additions & 2 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
6 changes: 5 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ KARMABOT_SLACK_APP_TOKEN=
# Workspace
KARMABOT_SLACK_USER=
KARMABOT_GENERAL_CHANNEL=
KARMABOT_LOG_CHANNEL=
KARMABOT_ADMINS=
# Backend
Expand All @@ -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.

Expand Down Expand Up @@ -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).
1 change: 1 addition & 0 deletions noxfile.py
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
[tool.poetry]
name = "karmabot"
version = "3.2.0"
authors = ["PyBites <[email protected]>", "Patrick-Oliver Groß <[email protected]>"]
classifiers = [
"License :: OSI Approved :: MIT License",
Expand All @@ -16,7 +17,6 @@ license = "MIT"
maintainers = ["Patrick-Oliver Groß <[email protected]>"]
readme = "README.md"
repository = "https://github.com/PyBites-Open-Source/karmabot"
version = "3.1.0"

[tool.poetry.dependencies]
SQLAlchemy = "^2.0.1"
Expand Down
1 change: 1 addition & 0 deletions runtime.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
python-3.11.2
32 changes: 3 additions & 29 deletions src/karmabot/bot.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
ADMINS,
KARMA_ACTION_PATTERN,
KARMABOT_ID,
LOG_CHANNEL,
SLACK_BOT_TOKEN,
TEST_MODE,
)
Expand Down Expand Up @@ -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()
Expand All @@ -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"(?<!<@{KARMABOT_ID}>\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
Expand Down Expand Up @@ -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
Expand All @@ -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
Expand Down
64 changes: 32 additions & 32 deletions src/karmabot/db/karma_note.py
Original file line number Diff line number Diff line change
@@ -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}."
)
4 changes: 3 additions & 1 deletion src/karmabot/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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

Expand Down
25 changes: 6 additions & 19 deletions tests/test_bot.py
Original file line number Diff line number Diff line change
Expand Up @@ -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",
[
Expand All @@ -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

Expand Down

0 comments on commit 680fa3e

Please sign in to comment.