Skip to content

Commit 18a34ee

Browse files
committed
Merge branch 'release/1.2.1' into main
2 parents 61428d5 + d1f9cd4 commit 18a34ee

File tree

16 files changed

+107
-40
lines changed

16 files changed

+107
-40
lines changed

CHANGELOG.md

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,26 @@
11
# Pyttman Changelog
22

33

4+
# V 1.2.1
5+
This release includes an important update for the discord client.
6+
Any application using Pyttman will need to upgrade to this version for the
7+
app to still work after new year 2023 due to Discord API changes.
8+
9+
10+
### **🐛 Splatted bugs and corrected issues**
11+
* **Fixes [#71](https://github.com/dotchetter/Pyttman/issues/71)**
12+
* Reduced dependencies to 1/3 of previous versions, improving security and reducing dependency exposure.
13+
* Fixes various spelling errors in the code and comments
14+
15+
416
# V 1.2.0.4
517
This is a hotfix release, fixing an issue with BoolEntityField instances
618
not parsing the values correctly if the sought word is also part of the
719
'lead' and/or 'trail' tuples.
820

921

1022
### **🐛 Splatted bugs and corrected issues**
11-
* **Fixes [#69](https://github.com/dotchetter/Pyttman/issues/68)**
23+
* **Fixes [#69](https://github.com/dotchetter/Pyttman/issues/69)**
1224

1325

1426

README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ trying to decipher a message and its contents to find words of interest? Maybe t
1717
The Pyttman Framework aims to provide a similar experience as Django and Flask does for web, but for chatbots and digital assistants.
1818
It's large and full of features yet easy to use.
1919

20-
# Abiliy, Intent, Entity
20+
# Ability, Intent, Entity
2121
Pyttman apps are structured with inspiration from the MVC (Model View Controller)
2222
pattern, but things are named a bit differently. Here's a short rundown on what they're about.
2323

@@ -172,7 +172,7 @@ on a different platform.
172172
* Built-in thread based task scheduler
173173
* Abstraction layer middleware for managing incoming Messages just like requests in API frameworks
174174
* Django-like settings.py file
175-
* Powerful built-in rule-based API for parsing entities in messages (identifying words based on pre/suffixes and/or regex patterns, and/or order of appearence
175+
* Powerful built-in rule-based API for parsing entities in messages (identifying words based on pre/suffixes and/or regex patterns, and/or order of appearance
176176

177177

178178
### Documentation

pyttman/__init__.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
from pyttman.core.internals import PyttmanApp
2+
13
from pyttman import version
24
from pyttman.tools.scheduling.schedule import schedule
35
from pyttman.tools.logger.logger import PyttmanLogger
@@ -30,7 +32,7 @@ def __getattr__(self, item):
3032
"move lifecycle hooks to a separate module.")
3133

3234

33-
app = None
35+
app: PyttmanApp | None = None
3436
settings = _SettingsNotConfigured
3537
is_configured = False
3638
logger = PyttmanLogger

pyttman/clients/community/discord/client.py

Lines changed: 60 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,12 @@
1-
21
import asyncio
32
from datetime import datetime
43

54
import discord
5+
from discord import Intents
6+
7+
from pyttman import logger
8+
from pyttman.core.middleware.routing import AbstractMessageRouter
9+
from pyttman.core.exceptions import ClientImproperlyConfiguredError
610
from pyttman.clients.base import BaseClient
711
from pyttman.clients.community.discord.misc import DiscordMessage
812
from pyttman.core.containers import Reply, ReplyStream
@@ -52,13 +56,47 @@ class DiscordClient(discord.Client, BaseClient):
5256
be parsed.
5357
"""
5458
token: str = ""
55-
guild: str = ""
59+
guild: int = None
5660
message_startswith: str = ""
5761
message_endswith: str = ""
5862

59-
def __init__(self, *args, **kwargs):
60-
super().__init__(*args, **kwargs)
61-
[setattr(self, k, v) for k, v in kwargs.items()]
63+
def __init__(self,
64+
message_router: AbstractMessageRouter,
65+
token: str,
66+
guild: int,
67+
*args,
68+
**kwargs):
69+
try:
70+
discord_intent_flags = kwargs["discord_intent_flags"]
71+
discord_intents = discord.Intents(**discord_intent_flags)
72+
if not discord_intents:
73+
raise ClientImproperlyConfiguredError(
74+
"Pyttman cannot start the Discord client without the "
75+
"discord intent 'message_content' being set to True, "
76+
"since the contents in the message are required to "
77+
"do the routing and deliver the Entities found in the "
78+
"message.")
79+
except KeyError:
80+
raise ClientImproperlyConfiguredError(
81+
"Could not find 'discord_intent_flags' in 'CLIENT' section "
82+
"in settings.py for this app, and it's required. The app cannot "
83+
"start. Refer to the documentation for settings.py to setup "
84+
"the client and the discord intent flags correctly.")
85+
86+
message_startswith = kwargs.get("message_startswith")
87+
message_endswith = kwargs.get("message_endswith")
88+
self.message_startswith = message_startswith or self.message_startswith
89+
self.message_startswith = message_endswith or self.message_endswith
90+
self.message_router = message_router
91+
self._token = token
92+
self.guild = guild
93+
super().__init__(*args,
94+
**kwargs,
95+
guild=guild,
96+
intents=discord_intents)
97+
98+
async def on_ready(self):
99+
logger.log(f"App online on discord.")
62100

63101
async def on_message(self, message: DiscordMessage) -> None:
64102
"""
@@ -71,6 +109,7 @@ async def on_message(self, message: DiscordMessage) -> None:
71109
:param message: discord.Message
72110
:return: None
73111
"""
112+
print("Message recieved:", message)
74113
if message.author == self.user:
75114
return
76115

@@ -109,20 +148,23 @@ async def on_message(self, message: DiscordMessage) -> None:
109148
_generate_error_entry(discord_message, e).as_str())
110149

111150
def run_client(self):
112-
if not self.token or not self.guild:
113-
raise ValueError("Cannot connect - missing authentication."
114-
"'token' and 'guild' must be provided when "
115-
"using the Discord client. Specify these "
116-
"values in the dictionary for the client "
117-
"as {\"token\": \"foo_token\", \"guild\": "
118-
"\"foo_guild\"}")
119-
_token = self.token
120-
del self.token
151+
if not self._token:
152+
raise ClientImproperlyConfiguredError(
153+
"Cannot connect - missing authentication."
154+
"'token' must be provided when "
155+
"using the Discord client. Specify these "
156+
"values in the dictionary for the client "
157+
"as {\"token\": \"foo_token\", \"guild\": "
158+
"\"foo_guild\"}")
159+
160+
_token = self._token
161+
del self._token
121162

122163
try:
123164
self.run(_token)
124165
except Exception as e:
125-
raise RuntimeError("DiscordClient ran in to a problem. "
126-
"Please ensure that all data is provided "
127-
"correctly in settings.py."
128-
f"Excact error message: \"{e}\"")
166+
raise ClientImproperlyConfiguredError(
167+
"DiscordClient ran in to a problem. "
168+
"Please ensure that all data is provided "
169+
"correctly in settings.py."
170+
f"Exact error message: \"{e}\"")

pyttman/clients/community/discord/misc.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ class DiscordMessage(MessageMixin, discord.Message):
99
of the Pyttman framework depend on, while also
1010
supporting the Discord module and API for interacting
1111
with its API to support full interaction with the
12-
discord plattform from within applications developed
12+
discord platform from within applications developed
1313
in Pyttman, and not just the content of the message.
1414
1515
This class is designed to be used with the DiscordClient

pyttman/core/containers.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ def content(self, val):
5858
self._content = repr(val).split()
5959
except Exception:
6060
raise TypeError(f"content cannot be type {type(val)} "
61-
f"as it is could not be typecasted to "
61+
f"as it is could not be typecast to "
6262
f"str.")
6363

6464
def sanitized_content(self, preserve_case=False) -> List[str]:

pyttman/core/entity_parsing/identifiers.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,9 @@ class Identifier:
1515
whether they are capitalized, have a date-like
1616
format to them, and alike.
1717
18-
Subclasses can define very granularly how
18+
Subclasses can define in a very granular way, how
1919
a string can look by strict rules, or less
20-
so with less defined criterias.
20+
so with less defined criterion.
2121
2222
The Identifier will use regex to assess
2323
the similarity of given string.

pyttman/core/exceptions.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,3 +24,13 @@ class InvalidPyttmanObjectException(BaseException):
2424
"""
2525
def __init__(self, message):
2626
super().__init__(message)
27+
28+
29+
class ClientImproperlyConfiguredError(BaseException):
30+
"""
31+
This error is raised when a Client is misconfigured in settings.py
32+
for a pyttman project.
33+
"""
34+
def __init__(self, message):
35+
super().__init__(message)
36+

pyttman/core/intent.py

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,16 +4,16 @@
44
from collections import OrderedDict
55
from itertools import zip_longest
66

7-
from pyttman.core.entity_parsing.fields import EntityFieldBase
8-
from pyttman.core.entity_parsing.parsers import EntityFieldValueParser
9-
from pyttman.core.internals import _generate_name, depr_graceful
10-
from pyttman.core.mixins import PrettyReprMixin
11-
from pyttman.core.storage.basestorage import Storage
127
from pyttman.core.containers import (
138
Reply,
149
ReplyStream,
1510
Message
1611
)
12+
from pyttman.core.entity_parsing.fields import EntityFieldBase
13+
from pyttman.core.entity_parsing.parsers import EntityFieldValueParser
14+
from pyttman.core.internals import _generate_name
15+
from pyttman.core.mixins import PrettyReprMixin
16+
from pyttman.core.storage.basestorage import Storage
1717

1818

1919
class AbstractIntent(abc.ABC):

pyttman/tools/logger/logger.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ def loggedmethod(func):
6262
@functools.wraps(func)
6363
def inner(*args, **kwargs):
6464
"""
65-
Inner method, executing the func paramter function,
65+
Inner method, executing the func parameter function,
6666
as well as executing the logger.
6767
:returns:
6868
Output from executed function in parameter func
@@ -74,7 +74,7 @@ def inner(*args, **kwargs):
7474
return results
7575
except Exception as e:
7676
pyttman.logger.LOG_INSTANCE.error(
77-
f'Exception occured in {func.__name__}. Traceback '
77+
f'Exception occurred in {func.__name__}. Traceback '
7878
f'{traceback.format_exc()} {e}')
7979
raise e
8080
return inner

0 commit comments

Comments
 (0)