* [PATCH v2 00/28] The complete version of the Discord bot
@ 2022-10-03 23:52 Muhammad Rizki
2022-10-03 23:52 ` [PATCH v2 01/28] discord: Add .gitignore in the Discord's storage directory Muhammad Rizki
` (28 more replies)
0 siblings, 29 replies; 30+ messages in thread
From: Muhammad Rizki @ 2022-10-03 23:52 UTC (permalink / raw)
To: Ammar Faizi
Cc: Muhammad Rizki, Alviro Iskandar Setiawan, GNU/Weeb Mailing List
Hi, sir
In this series, I create the complete version of the Discord bot.
This series contains slash commands, events, and basic commands for
syncing the slash commands to the global.
Features:
Add getter and deletion database methods.
Add a mail listener to get the new lore email message.
Add filters to only the lore admin who can use the atom.
Add broadcast manager slash commands.
Add a button UI to go direct to its lore email message.
And others.
Bugs:
This series contains fix a bug in the storage management on the
atom/utils.py, because I forgot to test the Telegram bot in the past.
Fix the empty temporary patch directory and patch directory deletion
after send patch files.
Small changes:
Rename some utility functions to make it simple and readable. Some
changes on the on_ready event give a tip message on what to do when the
bot first starts.
There are 28 patches in this series:
- Patch 1 is to add .gitignore file to ignore all patch directories
- Patch 2 is to add a platform parameter func for the storage management
- Patch 3 is to move the gen_temp() code when its necessary to call
- Patch 4 is to add get_atom_urls() to get the list of atom URLs in the DB
- Patch 5 is to add get_broadcast_chats() to get the list of Discord ch
- Patch 6 is to add get_email_id() to get the email ID of the PK emails
- Patch 7 is to add get_reply_id() to get the Discord message ID
- Patch 8 is to inherit Getter() to the DBMethods() class
- Patch 9 is to add delet_atom() to delete specific atom URL
- Patch 10 is to add delete_broadcast() to delete current Discord channel
- Patch 11 is to inherit Deletion() to the DBMethods() class
- Patch 12 is to inherit DBMethods() to the DB() class
- Patch 13 is to implement the created DB() class in the GWClient() class
- Patch 14 is to rename some utility functions
- Patch 15 is to add a FullMessageBtn() button URL class to go to the lore
- Patch 16 is to add a @filters.wait_on_limit() to handle the rate limit
- Patch 17 is to add send lore email message functions
- Patch 18 is to add a mail listener to get the new lore email message
- Patch 19 is to implement the mail Listener() class in the dc.py
- Patch 20 is to add a @filters.lore_admin() to filter only the lore admin
- Patch 21 is to add a `/atom list` slash command
- Patch 22 is to add a `/atom add` slash command
- Patch 23 is to add a `/atom delete` slash command
- Patch 24 is to add a channel_link() util function in the atom/utils.py
- Patch 25 is to add a `/broadcast list` slash command
- Patch 26 is to add a `/broadcast add` slash command
- Patch 27 is to add a `/broadcast delete` slash command
- Patch 28 is to add a tip message on the on_ready event
How to use:
1. Execute the db.sql file in the daemon directory,
2. Setup .env file, the example is there with suffix .example, this
file name must remove the suffix name .example,
3. Set up the config.py in each bot directory, such as dscord and
telegram. The example is there with suffix .example & the file name
must remove suffix name .example,
4. Run `pip3 install -r requirements.txt` in each bot directory,
5. STORAGE_DIR env value must `storage` to make it work fine,
6. Run the bot by `python3 dc.py` or `python3 tg.py`.
Both tested and works fine. But, this PATCH series just only for Discord
bot first. Then, I will fix the same issue for the Telegram bot, thanks.
## Changelog
v1 -> v2
- Add .gitignore in the Discord's storage directory
- Fix the empty patch directory
- Fix the patch directory removal after send patch files, see commit 18/28
Muhammad Rizki (28):
discord: Add .gitignore in the Discord's storage directory
Fix the storage management after the refactor was happened
Fix the empty temporary patch directory on atom/utils.py
discord: Add get_atom_urls() to get the list of atom URLs
discord: Add get_broadcast_chats() to get the list of broadcast chats
discord: Add get_email_id() in getter directory
discord: Add get_reply_id() in getter directory
discord: Inherit Getter() class to the DBMethods() class
discord: Add delete_atom() in deletion directory
discord: Add delete_broadcast() in deletion directory
discord: Inherit the Deletion() class to the DBMethods() class
discord: Inherit the DBMethods() class to the DB() class
discord: Use the created DB() class
telegram: Rename some utility functions
discord: Add a FullMessageBtn() class in models
discord: Add filters.wait_on_limit() decorator
discord: Add send lore email message functions
discord: Add mail listener
discord: Implement the mail Listener() class
discord: Add @filters.lore_admin() decorator
discord: Add a list of atom URL slash command
discord: Add an add atom slash command
discord: Add a delete atom slash command
discord: Add channel_link() in the atom/utils.py
discord: Add a list broadcast slash command
discord: Add an add broadcast slash command
discord: Add a delete broadcast slash command
discord: Change the on_ready message
daemon/atom/utils.py | 81 +++++++---
daemon/dc.py | 30 +++-
daemon/dscord/database/core.py | 5 +-
daemon/dscord/database/methods/__init__.py | 6 +-
.../database/methods/deletion/__init__.py | 14 ++
.../database/methods/deletion/delete_atom.py | 15 ++
.../methods/deletion/delete_broadcast.py | 15 ++
.../database/methods/getter/__init__.py | 18 +++
.../database/methods/getter/get_atom_urls.py | 21 +++
.../methods/getter/get_broadcast_chats.py | 21 +++
.../database/methods/getter/get_email_id.py | 60 +++++++
.../database/methods/getter/get_reply.py | 33 ++++
daemon/dscord/gnuweeb/client.py | 52 +++++-
daemon/dscord/gnuweeb/filters.py | 53 ++++++
daemon/dscord/gnuweeb/models/__init__.py | 6 +
.../dscord/gnuweeb/models/full_message_btn.py | 12 ++
daemon/dscord/gnuweeb/plugins/__init__.py | 4 +-
.../dscord/gnuweeb/plugins/events/on_ready.py | 7 +-
.../plugins/slash_commands/__init__.py | 13 ++
.../plugins/slash_commands/manage_atom.py | 81 ++++++++++
.../slash_commands/manage_broadcast.py | 84 ++++++++++
daemon/dscord/mailer/__init__.py | 7 +
daemon/dscord/mailer/listener.py | 153 ++++++++++++++++++
daemon/dscord/storage/.gitignore | 2 +
daemon/telegram/mailer/listener.py | 2 +-
daemon/telegram/packages/client.py | 6 +-
26 files changed, 771 insertions(+), 30 deletions(-)
create mode 100644 daemon/dscord/database/methods/deletion/__init__.py
create mode 100644 daemon/dscord/database/methods/deletion/delete_atom.py
create mode 100644 daemon/dscord/database/methods/deletion/delete_broadcast.py
create mode 100644 daemon/dscord/database/methods/getter/__init__.py
create mode 100644 daemon/dscord/database/methods/getter/get_atom_urls.py
create mode 100644 daemon/dscord/database/methods/getter/get_broadcast_chats.py
create mode 100644 daemon/dscord/database/methods/getter/get_email_id.py
create mode 100644 daemon/dscord/database/methods/getter/get_reply.py
create mode 100644 daemon/dscord/gnuweeb/filters.py
create mode 100644 daemon/dscord/gnuweeb/models/__init__.py
create mode 100644 daemon/dscord/gnuweeb/models/full_message_btn.py
create mode 100644 daemon/dscord/gnuweeb/plugins/slash_commands/__init__.py
create mode 100644 daemon/dscord/gnuweeb/plugins/slash_commands/manage_atom.py
create mode 100644 daemon/dscord/gnuweeb/plugins/slash_commands/manage_broadcast.py
create mode 100644 daemon/dscord/mailer/__init__.py
create mode 100644 daemon/dscord/mailer/listener.py
create mode 100644 daemon/dscord/storage/.gitignore
base-commit: fdbccda0372a7869b7ac6b8c5b31ec1761b5e084
--
Muhammad Rizki
^ permalink raw reply [flat|nested] 30+ messages in thread
* [PATCH v2 01/28] discord: Add .gitignore in the Discord's storage directory
2022-10-03 23:52 [PATCH v2 00/28] The complete version of the Discord bot Muhammad Rizki
@ 2022-10-03 23:52 ` Muhammad Rizki
2022-10-03 23:52 ` [PATCH v2 02/28] Fix the storage management after the refactor was happened Muhammad Rizki
` (27 subsequent siblings)
28 siblings, 0 replies; 30+ messages in thread
From: Muhammad Rizki @ 2022-10-03 23:52 UTC (permalink / raw)
To: Ammar Faizi
Cc: Muhammad Rizki, Alviro Iskandar Setiawan, GNU/Weeb Mailing List
Add .gitignore for ignoring all patch directory in the storage
directory.
Signed-off-by: Muhammad Rizki <[email protected]>
---
daemon/dscord/storage/.gitignore | 2 ++
1 file changed, 2 insertions(+)
create mode 100644 daemon/dscord/storage/.gitignore
diff --git a/daemon/dscord/storage/.gitignore b/daemon/dscord/storage/.gitignore
new file mode 100644
index 0000000..d6b7ef3
--- /dev/null
+++ b/daemon/dscord/storage/.gitignore
@@ -0,0 +1,2 @@
+*
+!.gitignore
--
Muhammad Rizki
^ permalink raw reply related [flat|nested] 30+ messages in thread
* [PATCH v2 02/28] Fix the storage management after the refactor was happened
2022-10-03 23:52 [PATCH v2 00/28] The complete version of the Discord bot Muhammad Rizki
2022-10-03 23:52 ` [PATCH v2 01/28] discord: Add .gitignore in the Discord's storage directory Muhammad Rizki
@ 2022-10-03 23:52 ` Muhammad Rizki
2022-10-03 23:52 ` [PATCH v2 03/28] Fix the empty temporary patch directory on atom/utils.py Muhammad Rizki
` (26 subsequent siblings)
28 siblings, 0 replies; 30+ messages in thread
From: Muhammad Rizki @ 2022-10-03 23:52 UTC (permalink / raw)
To: Ammar Faizi
Cc: Muhammad Rizki, Alviro Iskandar Setiawan, GNU/Weeb Mailing List
I didn't test the Telegram bot when the refactor happened. I forgot to
update the utility function, like creating a file or patch directory
into the `storage` directory, which is so important.
Add the `platform` parameter to the necessary functions and add
quote_reply() for the Discord bot to create a vertical line reply
display. The `platform` parameter is to tell it for `telegram` or
`discord`. This will place the patch into its own `storage` directory.
Signed-off-by: Muhammad Rizki <[email protected]>
---
daemon/atom/utils.py | 75 ++++++++++++++++++++++--------
daemon/telegram/mailer/listener.py | 2 +-
daemon/telegram/packages/client.py | 4 +-
3 files changed, 59 insertions(+), 22 deletions(-)
diff --git a/daemon/atom/utils.py b/daemon/atom/utils.py
index c428a33..f813f39 100644
--- a/daemon/atom/utils.py
+++ b/daemon/atom/utils.py
@@ -113,25 +113,39 @@ def consruct_to_n_cc(to: list, cc: list):
return ret
-def gen_temp(name: str):
+def gen_temp(name: str, platform: str):
+ platform = platform.lower()
+ plt_ls = ["telegram", "discord"]
+
+ if platform not in plt_ls:
+ t = f"Platform {platform} is not found, "
+ t += f"only {', '.join(plt_ls)} is available"
+ raise ValueError(f"Platform {platform} is not found")
+
md5 = hashlib.md5(name.encode()).hexdigest()
- ret = os.getenv("STORAGE_DIR", "storage") + "/" + md5
+ store_dir = os.getenv("STORAGE_DIR", "storage")
+ platform = platform.replace("discord", "dscord")
+ path = f"{platform}/{store_dir}/{md5}"
try:
- os.mkdir(ret)
+ os.mkdir(path)
except FileExistsError:
pass
- return ret
+ return path
-def extract_body(thread: Message):
+def extract_body(thread: Message, platform: str):
if not thread.is_multipart():
- p = thread.get_payload(decode=True)
- return f"{p.decode(errors='replace')}\n".lstrip(), []
+ p = thread.get_payload(decode=True).decode(errors='replace')
+
+ if platform == "discord":
+ p = quote_reply(p)
+
+ return f"{p}\n".lstrip(), []
ret = ""
files = []
- temp = gen_temp(str(uuid.uuid4()))
+ temp = gen_temp(str(uuid.uuid4()), platform)
for p in thread.get_payload():
fname = p.get_filename()
payload = p.get_payload(decode=True)
@@ -164,35 +178,42 @@ def __is_patch(subject, content):
return True
-def create_template(thread: Message, to=None, cc=None):
+def create_template(thread: Message, platform: str, to=None, cc=None):
if not to:
to = extract_list("to", thread)
if not cc:
cc = extract_list("cc", thread)
+ if platform == "telegram":
+ substr = 4000
+ border = f"\n<code>{'-'*72}</code>"
+ else:
+ substr = 1900
+ border = f"\n{'-'*80}"
subject = thread.get('subject')
ret = f"From: {thread.get('from')}\n"
ret += consruct_to_n_cc(to, cc)
ret += f"Date: {thread.get('date')}\n"
ret += f"Subject: {subject}\n\n"
- content, files = extract_body(thread)
+ content, files = extract_body(thread, platform)
is_patch = __is_patch(subject, content)
if is_patch:
ret += content
else:
ret += content.strip().replace("\t", " ")
- if len(ret) >= 4000:
- ret = ret[:4000] + "..."
- ret = fix_utf8_char(ret)
- ret += f"\n<code>{'-'*72}</code>"
+ if len(ret) >= substr:
+ ret = ret[:substr] + "..."
+
+ ret = fix_utf8_char(ret, platform == "telegram")
+ ret += border
return ret, files, is_patch
-def prepare_send_patch(mail, text, url):
- tmp = gen_temp(url)
+def prepare_send_patch(mail, text, url, platform: str):
+ tmp = gen_temp(url, platform)
fnm = str(mail.get("subject"))
sch = re.search(PATCH_PATTERN, fnm, re.IGNORECASE)
@@ -210,7 +231,10 @@ def prepare_send_patch(mail, text, url):
with open(file, "wb") as f:
f.write(bytes(text, encoding="utf8"))
- caption = "#patch #ml\n" + fix_utf8_char(cap)
+ caption = "#patch #ml"
+ if platform == "telegram":
+ caption += fix_utf8_char("\n" + cap, True)
+
return tmp, file, caption, url
@@ -218,9 +242,11 @@ def clean_up_after_send_patch(tmp):
shutil.rmtree(tmp)
-def fix_utf8_char(text: str):
- text = text.rstrip().replace("�"," ")
- return html.escape(html.escape(text))
+def fix_utf8_char(text: str, html_escape: bool = True):
+ t = text.rstrip().replace("�"," ")
+ if html_escape:
+ t = html.escape(html.escape(text))
+ return t
EMAIL_MSG_ID_PATTERN = r"<([^\<\>]+)>"
@@ -240,6 +266,15 @@ async def is_atom_url(text: str):
return mime == "application/atom+xml"
except: return False
+def quote_reply(text: str):
+ a = ""
+ for b in text.split("\n"):
+ b = b.replace(">\n", "> ")
+ if b.startswith(">"):
+ a += "> "
+ a += f"{b}\n"
+ return a
+
def remove_command(text: str):
txt = text.split(" ")
txt = text.replace(txt[0] + " ","")
diff --git a/daemon/telegram/mailer/listener.py b/daemon/telegram/mailer/listener.py
index decf85f..208aed0 100644
--- a/daemon/telegram/mailer/listener.py
+++ b/daemon/telegram/mailer/listener.py
@@ -99,7 +99,7 @@ class Bot():
#
return False
- text, files, is_patch = utils.create_template(mail)
+ text, files, is_patch = utils.create_template(mail, "telegram")
reply_to = self.get_reply(mail, tg_chat_id)
url = str(re.sub(r"/raw$", "", url))
diff --git a/daemon/telegram/packages/client.py b/daemon/telegram/packages/client.py
index 4f9c596..17061ec 100644
--- a/daemon/telegram/packages/client.py
+++ b/daemon/telegram/packages/client.py
@@ -56,7 +56,9 @@ class DaemonClient(Client):
parse_mode: ParseMode = ParseMode.HTML
) -> Message:
print("[send_patch_email]")
- tmp, doc, caption, url = utils.prepare_send_patch(mail, text, url)
+ tmp, doc, caption, url = utils.prepare_send_patch(
+ mail, text, url, "telegram"
+ )
m = await self.send_document(
chat_id=chat_id,
document=doc,
--
Muhammad Rizki
^ permalink raw reply related [flat|nested] 30+ messages in thread
* [PATCH v2 03/28] Fix the empty temporary patch directory on atom/utils.py
2022-10-03 23:52 [PATCH v2 00/28] The complete version of the Discord bot Muhammad Rizki
2022-10-03 23:52 ` [PATCH v2 01/28] discord: Add .gitignore in the Discord's storage directory Muhammad Rizki
2022-10-03 23:52 ` [PATCH v2 02/28] Fix the storage management after the refactor was happened Muhammad Rizki
@ 2022-10-03 23:52 ` Muhammad Rizki
2022-10-03 23:52 ` [PATCH v2 04/28] discord: Add get_atom_urls() to get the list of atom URLs Muhammad Rizki
` (25 subsequent siblings)
28 siblings, 0 replies; 30+ messages in thread
From: Muhammad Rizki @ 2022-10-03 23:52 UTC (permalink / raw)
To: Ammar Faizi
Cc: Muhammad Rizki, Alviro Iskandar Setiawan, GNU/Weeb Mailing List
Change code position of the gen_temp() on the extract_body(). This
change should only generate the temporary directory when it's needed to
create a patch file inside that temporary directory.
Signed-off-by: Muhammad Rizki <[email protected]>
---
daemon/atom/utils.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/daemon/atom/utils.py b/daemon/atom/utils.py
index f813f39..2aa4bce 100644
--- a/daemon/atom/utils.py
+++ b/daemon/atom/utils.py
@@ -145,7 +145,6 @@ def extract_body(thread: Message, platform: str):
ret = ""
files = []
- temp = gen_temp(str(uuid.uuid4()), platform)
for p in thread.get_payload():
fname = p.get_filename()
payload = p.get_payload(decode=True)
@@ -157,6 +156,7 @@ def extract_body(thread: Message, platform: str):
ret += f"{payload.decode(errors='replace')}\n".lstrip()
continue
+ temp = gen_temp(str(uuid.uuid4()), platform)
with open(f"{temp}/{fname}", "wb") as f:
f.write(payload)
files.append((temp, fname))
--
Muhammad Rizki
^ permalink raw reply related [flat|nested] 30+ messages in thread
* [PATCH v2 04/28] discord: Add get_atom_urls() to get the list of atom URLs
2022-10-03 23:52 [PATCH v2 00/28] The complete version of the Discord bot Muhammad Rizki
` (2 preceding siblings ...)
2022-10-03 23:52 ` [PATCH v2 03/28] Fix the empty temporary patch directory on atom/utils.py Muhammad Rizki
@ 2022-10-03 23:52 ` Muhammad Rizki
2022-10-03 23:52 ` [PATCH v2 05/28] discord: Add get_broadcast_chats() to get the list of broadcast chats Muhammad Rizki
` (24 subsequent siblings)
28 siblings, 0 replies; 30+ messages in thread
From: Muhammad Rizki @ 2022-10-03 23:52 UTC (permalink / raw)
To: Ammar Faizi
Cc: Muhammad Rizki, Alviro Iskandar Setiawan, GNU/Weeb Mailing List
Add get_atom_urls() in the database getter directory to get the list of
atom URLs. With this, we can display and manage them.
Signed-off-by: Muhammad Rizki <[email protected]>
---
.../database/methods/getter/__init__.py | 12 +++++++++++
.../database/methods/getter/get_atom_urls.py | 21 +++++++++++++++++++
2 files changed, 33 insertions(+)
create mode 100644 daemon/dscord/database/methods/getter/__init__.py
create mode 100644 daemon/dscord/database/methods/getter/get_atom_urls.py
diff --git a/daemon/dscord/database/methods/getter/__init__.py b/daemon/dscord/database/methods/getter/__init__.py
new file mode 100644
index 0000000..3670448
--- /dev/null
+++ b/daemon/dscord/database/methods/getter/__init__.py
@@ -0,0 +1,12 @@
+# SPDX-License-Identifier: GPL-2.0-only
+#
+# Copyright (C) 2022 Muhammad Rizki <[email protected]>
+#
+
+
+from .get_atom_urls import GetAtomURL
+
+
+class Getter(
+ GetAtomURL
+): pass
diff --git a/daemon/dscord/database/methods/getter/get_atom_urls.py b/daemon/dscord/database/methods/getter/get_atom_urls.py
new file mode 100644
index 0000000..19fe49e
--- /dev/null
+++ b/daemon/dscord/database/methods/getter/get_atom_urls.py
@@ -0,0 +1,21 @@
+# SPDX-License-Identifier: GPL-2.0-only
+#
+# Copyright (C) 2022 Muhammad Rizki <[email protected]>
+#
+
+
+class GetAtomURL:
+
+ def get_atom_urls(self):
+ '''
+ Get lore kernel raw email URLs.
+ - Return list of raw email URLs: `List[str]`
+ '''
+ q = """
+ SELECT dc_atoms.url
+ FROM dc_atoms
+ """
+ self.cur.execute(q)
+ urls = self.cur.fetchall()
+
+ return [u[0] for u in urls]
--
Muhammad Rizki
^ permalink raw reply related [flat|nested] 30+ messages in thread
* [PATCH v2 05/28] discord: Add get_broadcast_chats() to get the list of broadcast chats
2022-10-03 23:52 [PATCH v2 00/28] The complete version of the Discord bot Muhammad Rizki
` (3 preceding siblings ...)
2022-10-03 23:52 ` [PATCH v2 04/28] discord: Add get_atom_urls() to get the list of atom URLs Muhammad Rizki
@ 2022-10-03 23:52 ` Muhammad Rizki
2022-10-03 23:52 ` [PATCH v2 06/28] discord: Add get_email_id() in getter directory Muhammad Rizki
` (23 subsequent siblings)
28 siblings, 0 replies; 30+ messages in thread
From: Muhammad Rizki @ 2022-10-03 23:52 UTC (permalink / raw)
To: Ammar Faizi
Cc: Muhammad Rizki, Alviro Iskandar Setiawan, GNU/Weeb Mailing List
Add get_broadcast_chats() to get the list of broadcast chats. Useful for
display and manage them.
Signed-off-by: Muhammad Rizki <[email protected]>
---
.../database/methods/getter/__init__.py | 4 +++-
.../methods/getter/get_broadcast_chats.py | 21 +++++++++++++++++++
2 files changed, 24 insertions(+), 1 deletion(-)
create mode 100644 daemon/dscord/database/methods/getter/get_broadcast_chats.py
diff --git a/daemon/dscord/database/methods/getter/__init__.py b/daemon/dscord/database/methods/getter/__init__.py
index 3670448..2f4bec7 100644
--- a/daemon/dscord/database/methods/getter/__init__.py
+++ b/daemon/dscord/database/methods/getter/__init__.py
@@ -5,8 +5,10 @@
from .get_atom_urls import GetAtomURL
+from .get_broadcast_chats import GetBroadcastChats
class Getter(
- GetAtomURL
+ GetAtomURL,
+ GetBroadcastChats
): pass
diff --git a/daemon/dscord/database/methods/getter/get_broadcast_chats.py b/daemon/dscord/database/methods/getter/get_broadcast_chats.py
new file mode 100644
index 0000000..979912b
--- /dev/null
+++ b/daemon/dscord/database/methods/getter/get_broadcast_chats.py
@@ -0,0 +1,21 @@
+# SPDX-License-Identifier: GPL-2.0-only
+#
+# Copyright (C) 2022 Muhammad Rizki <[email protected]>
+#
+
+
+class GetBroadcastChats:
+
+ def get_broadcast_chats(self):
+ '''
+ Get broadcast chats that are currently
+ listening for new email.
+ - Return list of chat object: `List[Object]`
+ '''
+ q = """
+ SELECT *
+ FROM dc_broadcasts
+ """
+ self.cur.execute(q)
+
+ return self.cur.fetchall()
--
Muhammad Rizki
^ permalink raw reply related [flat|nested] 30+ messages in thread
* [PATCH v2 06/28] discord: Add get_email_id() in getter directory
2022-10-03 23:52 [PATCH v2 00/28] The complete version of the Discord bot Muhammad Rizki
` (4 preceding siblings ...)
2022-10-03 23:52 ` [PATCH v2 05/28] discord: Add get_broadcast_chats() to get the list of broadcast chats Muhammad Rizki
@ 2022-10-03 23:52 ` Muhammad Rizki
2022-10-03 23:52 ` [PATCH v2 07/28] discord: Add get_reply_id() " Muhammad Rizki
` (22 subsequent siblings)
28 siblings, 0 replies; 30+ messages in thread
From: Muhammad Rizki @ 2022-10-03 23:52 UTC (permalink / raw)
To: Ammar Faizi
Cc: Muhammad Rizki, Alviro Iskandar Setiawan, GNU/Weeb Mailing List
Add get_email_id() to get the email id of the primary key `dc_emails`
database table. This function is to return an email id to insert it into
the save_discord_mail() parameter because the `dc_emails` and the
`dc_mail_msg` database table are relationships.
Signed-off-by: Muhammad Rizki <[email protected]>
---
.../database/methods/getter/__init__.py | 4 +-
.../database/methods/getter/get_email_id.py | 60 +++++++++++++++++++
2 files changed, 63 insertions(+), 1 deletion(-)
create mode 100644 daemon/dscord/database/methods/getter/get_email_id.py
diff --git a/daemon/dscord/database/methods/getter/__init__.py b/daemon/dscord/database/methods/getter/__init__.py
index 2f4bec7..0f4b976 100644
--- a/daemon/dscord/database/methods/getter/__init__.py
+++ b/daemon/dscord/database/methods/getter/__init__.py
@@ -6,9 +6,11 @@
from .get_atom_urls import GetAtomURL
from .get_broadcast_chats import GetBroadcastChats
+from .get_email_id import GetEmailID
class Getter(
GetAtomURL,
- GetBroadcastChats
+ GetBroadcastChats,
+ GetEmailID
): pass
diff --git a/daemon/dscord/database/methods/getter/get_email_id.py b/daemon/dscord/database/methods/getter/get_email_id.py
new file mode 100644
index 0000000..8c27340
--- /dev/null
+++ b/daemon/dscord/database/methods/getter/get_email_id.py
@@ -0,0 +1,60 @@
+# SPDX-License-Identifier: GPL-2.0-only
+#
+# Copyright (C) 2022 Muhammad Rizki <[email protected]>
+# Copyright (C) 2022 Ammar Faizi <[email protected]>
+#
+
+
+class GetEmailID:
+
+ def get_email_id(self, email_id, chat_id):
+ '''
+ Determine whether the email needs to be sent to @tg_chat_id.
+ - Return an email id (PK) if it needs to be sent
+ - Return None if it doesn't need to be sent
+ '''
+ if self.__is_sent(email_id, chat_id):
+ return
+
+ res = self.__email_id(email_id)
+ if not bool(res):
+ return
+
+ return int(res[0])
+
+
+ def __is_sent(self, email_id, channel_id):
+ '''
+ Checking if this email has already been sent
+ or not.
+ - Return True if it's already been sent
+ '''
+ q = """
+ SELECT dc_emails.id, dc_mail_msg.id FROM dc_emails
+ LEFT JOIN dc_mail_msg
+ ON dc_emails.id = dc_mail_msg.email_id
+ WHERE dc_emails.message_id = %(email_msg_id)s
+ AND dc_mail_msg.channel_id = %(channel_id)s
+ LIMIT 1
+ """
+
+ self.cur.execute(q, {
+ "email_msg_id": email_id,
+ "channel_id": channel_id
+ })
+ res = self.cur.fetchone()
+ return bool(res)
+
+
+ def __email_id(self, email_id):
+ '''
+ Get the email id if match with the email message_id.
+ - Return the result if it's match and exists
+ '''
+ q = """
+ SELECT id FROM dc_emails WHERE message_id = %(email_id)s
+ """
+
+ self.cur.execute(q, {"email_id": email_id})
+ res = self.cur.fetchone()
+ return res
--
Muhammad Rizki
^ permalink raw reply related [flat|nested] 30+ messages in thread
* [PATCH v2 07/28] discord: Add get_reply_id() in getter directory
2022-10-03 23:52 [PATCH v2 00/28] The complete version of the Discord bot Muhammad Rizki
` (5 preceding siblings ...)
2022-10-03 23:52 ` [PATCH v2 06/28] discord: Add get_email_id() in getter directory Muhammad Rizki
@ 2022-10-03 23:52 ` Muhammad Rizki
2022-10-03 23:52 ` [PATCH v2 08/28] discord: Inherit Getter() class to the DBMethods() class Muhammad Rizki
` (21 subsequent siblings)
28 siblings, 0 replies; 30+ messages in thread
From: Muhammad Rizki @ 2022-10-03 23:52 UTC (permalink / raw)
To: Ammar Faizi
Cc: Muhammad Rizki, Alviro Iskandar Setiawan, GNU/Weeb Mailing List
Add get_reply_id() to get the Discord message ID of the lore email
message sent to the Discord channel. With this, the bot can reply to the
sent message of the lore email.
Signed-off-by: Muhammad Rizki <[email protected]>
---
.../database/methods/getter/__init__.py | 4 ++-
.../database/methods/getter/get_reply.py | 33 +++++++++++++++++++
2 files changed, 36 insertions(+), 1 deletion(-)
create mode 100644 daemon/dscord/database/methods/getter/get_reply.py
diff --git a/daemon/dscord/database/methods/getter/__init__.py b/daemon/dscord/database/methods/getter/__init__.py
index 0f4b976..63cab01 100644
--- a/daemon/dscord/database/methods/getter/__init__.py
+++ b/daemon/dscord/database/methods/getter/__init__.py
@@ -7,10 +7,12 @@
from .get_atom_urls import GetAtomURL
from .get_broadcast_chats import GetBroadcastChats
from .get_email_id import GetEmailID
+from .get_reply import GetDiscordReply
class Getter(
GetAtomURL,
GetBroadcastChats,
- GetEmailID
+ GetEmailID,
+ GetDiscordReply
): pass
diff --git a/daemon/dscord/database/methods/getter/get_reply.py b/daemon/dscord/database/methods/getter/get_reply.py
new file mode 100644
index 0000000..870dc84
--- /dev/null
+++ b/daemon/dscord/database/methods/getter/get_reply.py
@@ -0,0 +1,33 @@
+# SPDX-License-Identifier: GPL-2.0-only
+#
+# Copyright (C) 2022 Muhammad Rizki <[email protected]>
+# Copyright (C) 2022 Ammar Faizi <[email protected]>
+#
+
+
+class GetDiscordReply:
+
+ def get_reply_id(self, email_id, channel_id):
+ '''
+ Get Telegram message ID sent match with
+ email message ID and Telegram chat ID.
+ - Return Telegram message ID if exists: `int`
+ - Return None if not exists`
+ '''
+ q = """
+ SELECT dc_mail_msg.dc_msg_id
+ FROM dc_emails INNER JOIN dc_mail_msg
+ ON dc_emails.id = dc_mail_msg.email_id
+ WHERE dc_emails.message_id = %(email_msg_id)s
+ AND dc_mail_msg.channel_id = %(channel_id)s
+ """
+
+ self.cur.execute(q, {
+ "email_msg_id": email_id,
+ "channel_id": channel_id
+ })
+ res = self.cur.fetchone()
+ if not bool(res):
+ return None
+
+ return res[0]
--
Muhammad Rizki
^ permalink raw reply related [flat|nested] 30+ messages in thread
* [PATCH v2 08/28] discord: Inherit Getter() class to the DBMethods() class
2022-10-03 23:52 [PATCH v2 00/28] The complete version of the Discord bot Muhammad Rizki
` (6 preceding siblings ...)
2022-10-03 23:52 ` [PATCH v2 07/28] discord: Add get_reply_id() " Muhammad Rizki
@ 2022-10-03 23:52 ` Muhammad Rizki
2022-10-03 23:52 ` [PATCH v2 09/28] discord: Add delete_atom() in deletion directory Muhammad Rizki
` (20 subsequent siblings)
28 siblings, 0 replies; 30+ messages in thread
From: Muhammad Rizki @ 2022-10-03 23:52 UTC (permalink / raw)
To: Ammar Faizi
Cc: Muhammad Rizki, Alviro Iskandar Setiawan, GNU/Weeb Mailing List
Use Getter() class to inherit it to the DBMethods() class, so all the
get functions in the getter directory will be in a relationship with the
DBMethods() class.
Signed-off-by: Muhammad Rizki <[email protected]>
---
daemon/dscord/database/methods/__init__.py | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/daemon/dscord/database/methods/__init__.py b/daemon/dscord/database/methods/__init__.py
index 189ec67..625a632 100644
--- a/daemon/dscord/database/methods/__init__.py
+++ b/daemon/dscord/database/methods/__init__.py
@@ -5,8 +5,10 @@
from .insertion import Insertion
+from .getter import Getter
class DBMethods(
- Insertion
+ Insertion,
+ Getter
): pass
--
Muhammad Rizki
^ permalink raw reply related [flat|nested] 30+ messages in thread
* [PATCH v2 09/28] discord: Add delete_atom() in deletion directory
2022-10-03 23:52 [PATCH v2 00/28] The complete version of the Discord bot Muhammad Rizki
` (7 preceding siblings ...)
2022-10-03 23:52 ` [PATCH v2 08/28] discord: Inherit Getter() class to the DBMethods() class Muhammad Rizki
@ 2022-10-03 23:52 ` Muhammad Rizki
2022-10-03 23:52 ` [PATCH v2 10/28] discord: Add delete_broadcast() " Muhammad Rizki
` (19 subsequent siblings)
28 siblings, 0 replies; 30+ messages in thread
From: Muhammad Rizki @ 2022-10-03 23:52 UTC (permalink / raw)
To: Ammar Faizi
Cc: Muhammad Rizki, Alviro Iskandar Setiawan, GNU/Weeb Mailing List
Add delete_atom() for delete the specific atom URL.
Signed-off-by: Muhammad Rizki <[email protected]>
---
.../dscord/database/methods/deletion/__init__.py | 12 ++++++++++++
.../database/methods/deletion/delete_atom.py | 15 +++++++++++++++
2 files changed, 27 insertions(+)
create mode 100644 daemon/dscord/database/methods/deletion/__init__.py
create mode 100644 daemon/dscord/database/methods/deletion/delete_atom.py
diff --git a/daemon/dscord/database/methods/deletion/__init__.py b/daemon/dscord/database/methods/deletion/__init__.py
new file mode 100644
index 0000000..988bbee
--- /dev/null
+++ b/daemon/dscord/database/methods/deletion/__init__.py
@@ -0,0 +1,12 @@
+# SPDX-License-Identifier: GPL-2.0-only
+#
+# Copyright (C) 2022 Muhammad Rizki <[email protected]>
+#
+
+
+from .delete_atom import DeleteAtom
+
+
+class Deletion(
+ DeleteAtom,
+): pass
diff --git a/daemon/dscord/database/methods/deletion/delete_atom.py b/daemon/dscord/database/methods/deletion/delete_atom.py
new file mode 100644
index 0000000..f2cbc2e
--- /dev/null
+++ b/daemon/dscord/database/methods/deletion/delete_atom.py
@@ -0,0 +1,15 @@
+# SPDX-License-Identifier: GPL-2.0-only
+#
+# Copyright (C) 2022 Muhammad Rizki <[email protected]>
+#
+
+
+class DeleteAtom:
+
+ def delete_atom(self, atom: str):
+ q = """
+ DELETE FROM dc_atoms
+ WHERE url = %(atom)s
+ """
+ self.cur.execute(q, {"atom": atom})
+ return self.cur.rowcount > 0
--
Muhammad Rizki
^ permalink raw reply related [flat|nested] 30+ messages in thread
* [PATCH v2 10/28] discord: Add delete_broadcast() in deletion directory
2022-10-03 23:52 [PATCH v2 00/28] The complete version of the Discord bot Muhammad Rizki
` (8 preceding siblings ...)
2022-10-03 23:52 ` [PATCH v2 09/28] discord: Add delete_atom() in deletion directory Muhammad Rizki
@ 2022-10-03 23:52 ` Muhammad Rizki
2022-10-03 23:52 ` [PATCH v2 11/28] discord: Inherit the Deletion() class to the DBMethods() class Muhammad Rizki
` (18 subsequent siblings)
28 siblings, 0 replies; 30+ messages in thread
From: Muhammad Rizki @ 2022-10-03 23:52 UTC (permalink / raw)
To: Ammar Faizi
Cc: Muhammad Rizki, Alviro Iskandar Setiawan, GNU/Weeb Mailing List
Add delete_broadcast() for delete the specific Discord channel
broadcast.
Signed-off-by: Muhammad Rizki <[email protected]>
---
.../dscord/database/methods/deletion/__init__.py | 2 ++
.../database/methods/deletion/delete_broadcast.py | 15 +++++++++++++++
2 files changed, 17 insertions(+)
create mode 100644 daemon/dscord/database/methods/deletion/delete_broadcast.py
diff --git a/daemon/dscord/database/methods/deletion/__init__.py b/daemon/dscord/database/methods/deletion/__init__.py
index 988bbee..e8a4466 100644
--- a/daemon/dscord/database/methods/deletion/__init__.py
+++ b/daemon/dscord/database/methods/deletion/__init__.py
@@ -5,8 +5,10 @@
from .delete_atom import DeleteAtom
+from .delete_broadcast import DeleteBroadcast
class Deletion(
DeleteAtom,
+ DeleteBroadcast
): pass
diff --git a/daemon/dscord/database/methods/deletion/delete_broadcast.py b/daemon/dscord/database/methods/deletion/delete_broadcast.py
new file mode 100644
index 0000000..6c8ef83
--- /dev/null
+++ b/daemon/dscord/database/methods/deletion/delete_broadcast.py
@@ -0,0 +1,15 @@
+# SPDX-License-Identifier: GPL-2.0-only
+#
+# Copyright (C) 2022 Muhammad Rizki <[email protected]>
+#
+
+
+class DeleteBroadcast:
+
+ def delete_broadcast(self, channel_id: int):
+ q = """
+ DELETE FROM dc_broadcasts
+ WHERE channel_id = %(channel_id)s
+ """
+ self.cur.execute(q, {"channel_id": channel_id})
+ return self.cur.rowcount > 0
--
Muhammad Rizki
^ permalink raw reply related [flat|nested] 30+ messages in thread
* [PATCH v2 11/28] discord: Inherit the Deletion() class to the DBMethods() class
2022-10-03 23:52 [PATCH v2 00/28] The complete version of the Discord bot Muhammad Rizki
` (9 preceding siblings ...)
2022-10-03 23:52 ` [PATCH v2 10/28] discord: Add delete_broadcast() " Muhammad Rizki
@ 2022-10-03 23:52 ` Muhammad Rizki
2022-10-03 23:52 ` [PATCH v2 12/28] discord: Inherit the DBMethods() class to the DB() class Muhammad Rizki
` (17 subsequent siblings)
28 siblings, 0 replies; 30+ messages in thread
From: Muhammad Rizki @ 2022-10-03 23:52 UTC (permalink / raw)
To: Ammar Faizi
Cc: Muhammad Rizki, Alviro Iskandar Setiawan, GNU/Weeb Mailing List
Use the Deletion() class to inherit it to the DBMethods() class.
Signed-off-by: Muhammad Rizki <[email protected]>
---
daemon/dscord/database/methods/__init__.py | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/daemon/dscord/database/methods/__init__.py b/daemon/dscord/database/methods/__init__.py
index 625a632..dbf94b2 100644
--- a/daemon/dscord/database/methods/__init__.py
+++ b/daemon/dscord/database/methods/__init__.py
@@ -6,9 +6,11 @@
from .insertion import Insertion
from .getter import Getter
+from .deletion import Deletion
class DBMethods(
Insertion,
- Getter
+ Getter,
+ Deletion
): pass
--
Muhammad Rizki
^ permalink raw reply related [flat|nested] 30+ messages in thread
* [PATCH v2 12/28] discord: Inherit the DBMethods() class to the DB() class
2022-10-03 23:52 [PATCH v2 00/28] The complete version of the Discord bot Muhammad Rizki
` (10 preceding siblings ...)
2022-10-03 23:52 ` [PATCH v2 11/28] discord: Inherit the Deletion() class to the DBMethods() class Muhammad Rizki
@ 2022-10-03 23:52 ` Muhammad Rizki
2022-10-03 23:52 ` [PATCH v2 13/28] discord: Use the created " Muhammad Rizki
` (16 subsequent siblings)
28 siblings, 0 replies; 30+ messages in thread
From: Muhammad Rizki @ 2022-10-03 23:52 UTC (permalink / raw)
To: Ammar Faizi
Cc: Muhammad Rizki, Alviro Iskandar Setiawan, GNU/Weeb Mailing List
Use the DBMethods() class to the DB() class, so all the methods
functions like insertion, getter, and deletion are relationship with the
DB() class. It's cleaner and manageable-maintainable.
Signed-off-by: Muhammad Rizki <[email protected]>
---
daemon/dscord/database/core.py | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/daemon/dscord/database/core.py b/daemon/dscord/database/core.py
index 1a25388..c34d7a8 100644
--- a/daemon/dscord/database/core.py
+++ b/daemon/dscord/database/core.py
@@ -5,7 +5,10 @@
#
-class DB:
+from .methods import DBMethods
+
+
+class DB(DBMethods):
def __init__(self, conn):
self.conn = conn
self.conn.autocommit = True
--
Muhammad Rizki
^ permalink raw reply related [flat|nested] 30+ messages in thread
* [PATCH v2 13/28] discord: Use the created DB() class
2022-10-03 23:52 [PATCH v2 00/28] The complete version of the Discord bot Muhammad Rizki
` (11 preceding siblings ...)
2022-10-03 23:52 ` [PATCH v2 12/28] discord: Inherit the DBMethods() class to the DB() class Muhammad Rizki
@ 2022-10-03 23:52 ` Muhammad Rizki
2022-10-03 23:52 ` [PATCH v2 14/28] telegram: Rename some utility functions Muhammad Rizki
` (15 subsequent siblings)
28 siblings, 0 replies; 30+ messages in thread
From: Muhammad Rizki @ 2022-10-03 23:52 UTC (permalink / raw)
To: Ammar Faizi
Cc: Muhammad Rizki, Alviro Iskandar Setiawan, GNU/Weeb Mailing List
Use the DB() class into the __init__() function of the GWClient() class
and add the MySQL connection to the GWClient() class parameter.
Signed-off-by: Muhammad Rizki <[email protected]>
---
daemon/dc.py | 10 +++++++++-
daemon/dscord/gnuweeb/client.py | 5 ++++-
2 files changed, 13 insertions(+), 2 deletions(-)
diff --git a/daemon/dc.py b/daemon/dc.py
index ff29abe..9b86df2 100644
--- a/daemon/dc.py
+++ b/daemon/dc.py
@@ -5,6 +5,7 @@
import os
from dotenv import load_dotenv
+from mysql import connector
from dscord.gnuweeb import GWClient
@@ -12,7 +13,14 @@ from dscord.gnuweeb import GWClient
def main():
load_dotenv("discord.env")
- client = GWClient()
+ client = GWClient(
+ db_conn=connector.connect(
+ host=os.getenv("DB_HOST"),
+ user=os.getenv("DB_USER"),
+ password=os.getenv("DB_PASS"),
+ database=os.getenv("DB_NAME")
+ )
+ )
client.run(os.getenv("DISCORD_TOKEN"), log_handler=None)
diff --git a/daemon/dscord/gnuweeb/client.py b/daemon/dscord/gnuweeb/client.py
index fa07fb1..7893f88 100644
--- a/daemon/dscord/gnuweeb/client.py
+++ b/daemon/dscord/gnuweeb/client.py
@@ -8,9 +8,12 @@ from discord.ext import commands
from discord import Intents
from dscord.config import ACTIVITY_NAME
+from dscord.database import DB
+
class GWClient(commands.Bot):
- def __init__(self) -> None:
+ def __init__(self, db_conn) -> None:
+ self.db = DB(db_conn)
intents = Intents.default()
intents.message_content = True
super().__init__(
--
Muhammad Rizki
^ permalink raw reply related [flat|nested] 30+ messages in thread
* [PATCH v2 14/28] telegram: Rename some utility functions
2022-10-03 23:52 [PATCH v2 00/28] The complete version of the Discord bot Muhammad Rizki
` (12 preceding siblings ...)
2022-10-03 23:52 ` [PATCH v2 13/28] discord: Use the created " Muhammad Rizki
@ 2022-10-03 23:52 ` Muhammad Rizki
2022-10-03 23:52 ` [PATCH v2 15/28] discord: Add a FullMessageBtn() class in models Muhammad Rizki
` (14 subsequent siblings)
28 siblings, 0 replies; 30+ messages in thread
From: Muhammad Rizki @ 2022-10-03 23:52 UTC (permalink / raw)
To: Ammar Faizi
Cc: Muhammad Rizki, Alviro Iskandar Setiawan, GNU/Weeb Mailing List
Rename prepare_send_patch() to prepare_patch and
clean_up_after_send_patch() to remove_patch() to make them easier to
read and practice.
Signed-off-by: Muhammad Rizki <[email protected]>
---
daemon/atom/utils.py | 4 ++--
daemon/telegram/packages/client.py | 4 ++--
2 files changed, 4 insertions(+), 4 deletions(-)
diff --git a/daemon/atom/utils.py b/daemon/atom/utils.py
index 2aa4bce..870ee70 100644
--- a/daemon/atom/utils.py
+++ b/daemon/atom/utils.py
@@ -212,7 +212,7 @@ def create_template(thread: Message, platform: str, to=None, cc=None):
return ret, files, is_patch
-def prepare_send_patch(mail, text, url, platform: str):
+def prepare_patch(mail, text, url, platform: str):
tmp = gen_temp(url, platform)
fnm = str(mail.get("subject"))
sch = re.search(PATCH_PATTERN, fnm, re.IGNORECASE)
@@ -238,7 +238,7 @@ def prepare_send_patch(mail, text, url, platform: str):
return tmp, file, caption, url
-def clean_up_after_send_patch(tmp):
+def remove_patch(tmp):
shutil.rmtree(tmp)
diff --git a/daemon/telegram/packages/client.py b/daemon/telegram/packages/client.py
index 17061ec..686e5ef 100644
--- a/daemon/telegram/packages/client.py
+++ b/daemon/telegram/packages/client.py
@@ -56,7 +56,7 @@ class DaemonClient(Client):
parse_mode: ParseMode = ParseMode.HTML
) -> Message:
print("[send_patch_email]")
- tmp, doc, caption, url = utils.prepare_send_patch(
+ tmp, doc, caption, url = utils.prepare_patch(
mail, text, url, "telegram"
)
m = await self.send_document(
@@ -73,5 +73,5 @@ class DaemonClient(Client):
])
)
- utils.clean_up_after_send_patch(tmp)
+ utils.remove_patch(tmp)
return m
--
Muhammad Rizki
^ permalink raw reply related [flat|nested] 30+ messages in thread
* [PATCH v2 15/28] discord: Add a FullMessageBtn() class in models
2022-10-03 23:52 [PATCH v2 00/28] The complete version of the Discord bot Muhammad Rizki
` (13 preceding siblings ...)
2022-10-03 23:52 ` [PATCH v2 14/28] telegram: Rename some utility functions Muhammad Rizki
@ 2022-10-03 23:52 ` Muhammad Rizki
2022-10-03 23:52 ` [PATCH v2 16/28] discord: Add filters.wait_on_limit() decorator Muhammad Rizki
` (13 subsequent siblings)
28 siblings, 0 replies; 30+ messages in thread
From: Muhammad Rizki @ 2022-10-03 23:52 UTC (permalink / raw)
To: Ammar Faizi
Cc: Muhammad Rizki, Alviro Iskandar Setiawan, GNU/Weeb Mailing List
Add a FullMessageBtn() class to be able to render a button of a lore
email message on its footer. This class is a clickable URL to direct to
its lore email message.
Signed-off-by: Muhammad Rizki <[email protected]>
---
daemon/dscord/gnuweeb/client.py | 4 ++++
daemon/dscord/gnuweeb/models/__init__.py | 6 ++++++
daemon/dscord/gnuweeb/models/full_message_btn.py | 12 ++++++++++++
3 files changed, 22 insertions(+)
create mode 100644 daemon/dscord/gnuweeb/models/__init__.py
create mode 100644 daemon/dscord/gnuweeb/models/full_message_btn.py
diff --git a/daemon/dscord/gnuweeb/client.py b/daemon/dscord/gnuweeb/client.py
index 7893f88..02a1ac5 100644
--- a/daemon/dscord/gnuweeb/client.py
+++ b/daemon/dscord/gnuweeb/client.py
@@ -7,7 +7,11 @@ import discord
from discord.ext import commands
from discord import Intents
from dscord.config import ACTIVITY_NAME
+from typing import Union
+from . import filters
+from . import models
+from atom import utils
from dscord.database import DB
diff --git a/daemon/dscord/gnuweeb/models/__init__.py b/daemon/dscord/gnuweeb/models/__init__.py
new file mode 100644
index 0000000..c1d2a56
--- /dev/null
+++ b/daemon/dscord/gnuweeb/models/__init__.py
@@ -0,0 +1,6 @@
+# SPDX-License-Identifier: GPL-2.0-only
+#
+# Copyright (C) 2022 Muhammad Rizki <[email protected]>
+#
+
+from .full_message_btn import FullMessageBtn
diff --git a/daemon/dscord/gnuweeb/models/full_message_btn.py b/daemon/dscord/gnuweeb/models/full_message_btn.py
new file mode 100644
index 0000000..b8d81cf
--- /dev/null
+++ b/daemon/dscord/gnuweeb/models/full_message_btn.py
@@ -0,0 +1,12 @@
+from discord import ui
+from discord import ButtonStyle
+
+
+class FullMessageBtn(ui.View):
+ def __init__(self, url: str):
+ super().__init__()
+ self.add_item(ui.Button(
+ label='See the full message',
+ style=ButtonStyle.gray,
+ url=url
+ ))
--
Muhammad Rizki
^ permalink raw reply related [flat|nested] 30+ messages in thread
* [PATCH v2 16/28] discord: Add filters.wait_on_limit() decorator
2022-10-03 23:52 [PATCH v2 00/28] The complete version of the Discord bot Muhammad Rizki
` (14 preceding siblings ...)
2022-10-03 23:52 ` [PATCH v2 15/28] discord: Add a FullMessageBtn() class in models Muhammad Rizki
@ 2022-10-03 23:52 ` Muhammad Rizki
2022-10-03 23:52 ` [PATCH v2 17/28] discord: Add send lore email message functions Muhammad Rizki
` (12 subsequent siblings)
28 siblings, 0 replies; 30+ messages in thread
From: Muhammad Rizki @ 2022-10-03 23:52 UTC (permalink / raw)
To: Ammar Faizi
Cc: Muhammad Rizki, Alviro Iskandar Setiawan, GNU/Weeb Mailing List
Add wait_on_limit() decorator in filters.py to prevent the rate limit
hit for sending a message.
Signed-off-by: Muhammad Rizki <[email protected]>
---
daemon/dscord/gnuweeb/filters.py | 27 +++++++++++++++++++++++++++
1 file changed, 27 insertions(+)
create mode 100644 daemon/dscord/gnuweeb/filters.py
diff --git a/daemon/dscord/gnuweeb/filters.py b/daemon/dscord/gnuweeb/filters.py
new file mode 100644
index 0000000..19f9445
--- /dev/null
+++ b/daemon/dscord/gnuweeb/filters.py
@@ -0,0 +1,27 @@
+# SPDX-License-Identifier: GPL-2.0-only
+#
+# Copyright (C) 2022 Muhammad Rizki <[email protected]>
+#
+
+import discord
+import asyncio
+from typing import Any
+from functools import wraps
+
+
+def wait_on_limit(func):
+ @wraps(func)
+ async def callback(*args: Any) -> Any:
+ while True:
+ try:
+ return await func(*args)
+ except discord.errors.RateLimited as e:
+ _flood_exceptions(e)
+ print("[wait_on_limit]: Woken up from flood wait...")
+ return callback
+
+
+async def _flood_exceptions(e: "discord.errors.RateLimited"):
+ wait = e.retry_after
+ print(f"[wait_on_limit]: Sleeping for {wait} seconds due to Telegram limit")
+ await asyncio.sleep(wait)
--
Muhammad Rizki
^ permalink raw reply related [flat|nested] 30+ messages in thread
* [PATCH v2 17/28] discord: Add send lore email message functions
2022-10-03 23:52 [PATCH v2 00/28] The complete version of the Discord bot Muhammad Rizki
` (15 preceding siblings ...)
2022-10-03 23:52 ` [PATCH v2 16/28] discord: Add filters.wait_on_limit() decorator Muhammad Rizki
@ 2022-10-03 23:52 ` Muhammad Rizki
2022-10-03 23:52 ` [PATCH v2 18/28] discord: Add mail listener Muhammad Rizki
` (11 subsequent siblings)
28 siblings, 0 replies; 30+ messages in thread
From: Muhammad Rizki @ 2022-10-03 23:52 UTC (permalink / raw)
To: Ammar Faizi
Cc: Muhammad Rizki, Alviro Iskandar Setiawan, GNU/Weeb Mailing List
Add send_text_email() and send_patch_email() in the
dscord/gnuweeb/client.py to send the lore email message to the Discord
channel.
Signed-off-by: Muhammad Rizki <[email protected]>
---
daemon/dscord/gnuweeb/client.py | 42 +++++++++++++++++++++++++++++++++
1 file changed, 42 insertions(+)
diff --git a/daemon/dscord/gnuweeb/client.py b/daemon/dscord/gnuweeb/client.py
index 02a1ac5..2506ec3 100644
--- a/daemon/dscord/gnuweeb/client.py
+++ b/daemon/dscord/gnuweeb/client.py
@@ -33,3 +33,45 @@ class GWClient(commands.Bot):
name=".gnuweeb.plugins",
package="dscord"
)
+
+
+ @filters.wait_on_limit
+ async def send_text_email(self, guild_id: int, chat_id: int, text: str,
+ reply_to: Union[int, None] = None, url: str = None):
+ print("[send_text_email]")
+ channel = self.get_channel(chat_id)
+
+ return await channel.send(
+ content=text,
+ reference=discord.MessageReference(
+ guild_id=guild_id,
+ channel_id=chat_id,
+ message_id=reply_to
+ ) if reply_to else None,
+ view=models.FullMessageBtn(url)
+ )
+
+
+ @filters.wait_on_limit
+ async def send_patch_email(self, mail, guild_id: int, chat_id: int, text: str,
+ reply_to: Union[int, None] = None, url: str = None):
+ print("[send_patch_email]")
+ tmp, doc, caption, url = utils.prepare_patch(
+ mail, text, url, "discord"
+ )
+ channel = self.get_channel(chat_id)
+
+ m = await channel.send(
+ content=caption,
+ file=discord.File(doc),
+ reference=discord.MessageReference(
+ guild_id=guild_id,
+ channel_id=chat_id,
+ message_id=reply_to
+ ) if reply_to else None,
+
+ view=models.FullMessageBtn(url)
+ )
+
+ utils.remove_patch(tmp)
+ return m
--
Muhammad Rizki
^ permalink raw reply related [flat|nested] 30+ messages in thread
* [PATCH v2 18/28] discord: Add mail listener
2022-10-03 23:52 [PATCH v2 00/28] The complete version of the Discord bot Muhammad Rizki
` (16 preceding siblings ...)
2022-10-03 23:52 ` [PATCH v2 17/28] discord: Add send lore email message functions Muhammad Rizki
@ 2022-10-03 23:52 ` Muhammad Rizki
2022-10-03 23:52 ` [PATCH v2 19/28] discord: Implement the mail Listener() class Muhammad Rizki
` (10 subsequent siblings)
28 siblings, 0 replies; 30+ messages in thread
From: Muhammad Rizki @ 2022-10-03 23:52 UTC (permalink / raw)
To: Ammar Faizi
Cc: Muhammad Rizki, Alviro Iskandar Setiawan, GNU/Weeb Mailing List
Add the mail listener to receive new lore kernel email messages, then
send them to the Discord channel. If there is no new email message, the
listener will ignore it.
Changelog:
v1 -> v2
discord: Fix the patch directory deletion after sending patch files
Fix a bug when the bot doesn't remove the patch directory after
sending the patch files inside the directory. I don't know if this is
fixed or not. I just thought I had patched it with many debugging
methods. It's hard to catch these bugs.
Main issues:
Files are not deleted
ammarfaizi2@integral2:~/app/lore-daemon.dev/daemon$ ls dscord/storage -l
total 0
drwxrwxr-x 1 ammarfaizi2 ammarfaizi2 78 Sep 3 17:25 23035eeb480f2b3501ba0841ef10ce3f
drwxrwxr-x 1 ammarfaizi2 ammarfaizi2 12 Oct 3 19:42 6766c45fa800d71173893158b2c7d640
drwxrwxr-x 1 ammarfaizi2 ammarfaizi2 0 Sep 3 17:22 78380c23529749c280e4cca46f7519c9
drwxrwxr-x 1 ammarfaizi2 ammarfaizi2 0 Sep 3 17:23 a23e986acc2c75d08a3e98377f06bbfe
drwxrwxr-x 1 ammarfaizi2 ammarfaizi2 356 Sep 3 17:22 b241bd7c932c70e6a81d107da019cb67
drwxrwxr-x 1 ammarfaizi2 ammarfaizi2 12 Sep 3 17:25 bcaac8364eaf04951d504faa1f1df826
drwxrwxr-x 1 ammarfaizi2 ammarfaizi2 0 Sep 3 17:23 c36cdede05b536d395c5b55dbae92288
These directories is not removed after sending the patch files.
From:
https://lore.gnuweeb.org/gwml/[email protected]/
Logs:
Traceback (most recent call last):
File "/home/ammarfaizi2/app/lore-daemon.dev/daemon/dscord/mailer/listener.py", line 56, in __run
await self.__handle_atom_url(url)
File "/home/ammarfaizi2/app/lore-daemon.dev/daemon/dscord/mailer/listener.py", line 75, in __handle_atom_url
await self.__handle_mail(url, mail)
File "/home/ammarfaizi2/app/lore-daemon.dev/daemon/dscord/mailer/listener.py", line 83, in __handle_mail
await self.__send_to_discord(url, mail,
File "/home/ammarfaizi2/app/lore-daemon.dev/daemon/dscord/mailer/listener.py", line 127, in __send_to_discord
await m.reply(f"{d}/{f}", file=File(f))
File "/home/ammarfaizi2/.local/lib/python3.10/site-packages/discord/file.py", line 97, in __init__
self.fp = open(fp, 'rb')
FileNotFoundError: [Errno 2] No such file or directory: 'config'
Signed-off-by: Muhammad Rizki <[email protected]>
---
daemon/dscord/mailer/__init__.py | 7 ++
daemon/dscord/mailer/listener.py | 153 +++++++++++++++++++++++++++++++
2 files changed, 160 insertions(+)
create mode 100644 daemon/dscord/mailer/__init__.py
create mode 100644 daemon/dscord/mailer/listener.py
diff --git a/daemon/dscord/mailer/__init__.py b/daemon/dscord/mailer/__init__.py
new file mode 100644
index 0000000..5d7e8d8
--- /dev/null
+++ b/daemon/dscord/mailer/__init__.py
@@ -0,0 +1,7 @@
+# SPDX-License-Identifier: GPL-2.0-only
+#
+# Copyright (C) 2022 Muhammad Rizki <[email protected]>
+#
+
+from .listener import Listener
+from .listener import Mutexes
diff --git a/daemon/dscord/mailer/listener.py b/daemon/dscord/mailer/listener.py
new file mode 100644
index 0000000..a280a58
--- /dev/null
+++ b/daemon/dscord/mailer/listener.py
@@ -0,0 +1,153 @@
+# SPDX-License-Identifier: GPL-2.0-only
+#
+# Copyright (C) 2022 Muhammad Rizki <[email protected]>
+# Copyright (C) 2022 Ammar Faizi <[email protected]>
+#
+
+import asyncio
+import traceback
+import re
+from apscheduler.schedulers.asyncio import AsyncIOScheduler
+from discord import File
+from discord import Message
+
+from dscord.gnuweeb import GWClient
+from atom.scraper import Scraper
+from atom import utils
+
+
+class Mutexes:
+ def __init__(self):
+ self.lock = asyncio.Lock()
+
+
+class Listener:
+ def __init__(
+ self,
+ client: "GWClient",
+ sched: "AsyncIOScheduler",
+ scraper: "Scraper",
+ mutexes: "Mutexes"
+ ):
+ self.client = client
+ self.sched = sched
+ self.scraper = scraper
+ self.mutexes = mutexes
+ self.db = client.db
+ self.isRunnerFixed = False
+ self.runner = None
+
+
+ def run(self):
+ #
+ # Execute __run() once to avoid high latency at
+ # initilization.
+ #
+ print("Initialize listener...\n")
+ self.sched.start()
+ self.runner = self.sched.add_job(func=self.__run)
+
+
+ async def __run(self):
+ print("[__run]: Running...")
+ for url in self.db.get_atom_urls():
+ try:
+ await self.__handle_atom_url(url)
+ except:
+ print(traceback.format_exc())
+
+ if not self.isRunnerFixed:
+ self.isRunnerFixed = True
+ self.runner = self.sched.add_job(
+ func=self.__run,
+ trigger="interval",
+ seconds=30,
+ misfire_grace_time=None,
+ max_instances=1
+ )
+
+
+ async def __handle_atom_url(self, url):
+ urls = await self.scraper.get_new_threads_urls(url)
+ for url in urls:
+ mail = await self.scraper.get_email_from_url(url)
+ await self.__handle_mail(url, mail)
+
+
+ async def __handle_mail(self, url, mail):
+ chats = self.db.get_broadcast_chats()
+ for chat in chats:
+ async with self.mutexes.lock:
+ should_wait = \
+ await self.__send_to_discord(url, mail,
+ chat[1], chat[2])
+
+ if should_wait:
+ await asyncio.sleep(1)
+
+
+ # @__must_hold(self.mutexes.lock)
+ async def __send_to_discord(self, url, mail, dc_guild_id, dc_chat_id):
+ email_msg_id = utils.get_email_msg_id(mail)
+ if not email_msg_id:
+ #
+ # It doesn't have a Message-Id.
+ # A malformed email. Skip!
+ #
+ return False
+
+ email_id = self.__get_email_id_sent(
+ email_msg_id=email_msg_id,
+ dc_chat_id=dc_chat_id
+ )
+ if not email_id:
+ #
+ # Email has already been sent to Discord.
+ # Skip!
+ #
+ return False
+
+ text, files, is_patch = utils.create_template(mail, "discord")
+ reply_to = self.get_discord_reply(mail, dc_chat_id)
+ url = str(re.sub(r"/raw$", "", url))
+
+ if is_patch:
+ m: Message = await self.client.send_patch_email(
+ mail, dc_guild_id, dc_chat_id, text, reply_to, url
+ )
+ else:
+ text = "#ml\n" + text
+ m: Message = await self.client.send_text_email(
+ dc_guild_id, dc_chat_id, text, reply_to, url
+ )
+
+ self.db.save_discord_mail(email_id, m.channel.id, m.id)
+
+ for d, f in files:
+ await m.reply(file=File(f"{d}/{f}"))
+ if files.index((d,f)) == len(files)-1:
+ utils.remove_patch(d)
+ await asyncio.sleep(1)
+
+ return True
+
+
+ def __get_email_id_sent(self, email_msg_id, dc_chat_id):
+ email_id = self.db.save_email(email_msg_id)
+ if email_id:
+ return email_id
+
+ email_id = self.db.get_email_id(email_msg_id, dc_chat_id)
+ return email_id
+
+
+ def get_discord_reply(self, mail, dc_chat_id):
+ reply_to = mail.get("in-reply-to")
+ if not reply_to:
+ return None
+
+ reply_to = utils.extract_email_msg_id(reply_to)
+ if not reply_to:
+ return None
+
+ return self.db.get_reply_id(reply_to, dc_chat_id)
--
Muhammad Rizki
^ permalink raw reply related [flat|nested] 30+ messages in thread
* [PATCH v2 19/28] discord: Implement the mail Listener() class
2022-10-03 23:52 [PATCH v2 00/28] The complete version of the Discord bot Muhammad Rizki
` (17 preceding siblings ...)
2022-10-03 23:52 ` [PATCH v2 18/28] discord: Add mail listener Muhammad Rizki
@ 2022-10-03 23:52 ` Muhammad Rizki
2022-10-03 23:52 ` [PATCH v2 20/28] discord: Add @filters.lore_admin() decorator Muhammad Rizki
` (9 subsequent siblings)
28 siblings, 0 replies; 30+ messages in thread
From: Muhammad Rizki @ 2022-10-03 23:52 UTC (permalink / raw)
To: Ammar Faizi
Cc: Muhammad Rizki, Alviro Iskandar Setiawan, GNU/Weeb Mailing List
Use the mail Listener() class in the dc.py and add the scheduler for
the Listener() class works.
Signed-off-by: Muhammad Rizki <[email protected]>
---
daemon/dc.py | 20 +++++++++++++++++++
daemon/dscord/gnuweeb/client.py | 1 +
.../dscord/gnuweeb/plugins/events/on_ready.py | 2 ++
3 files changed, 23 insertions(+)
diff --git a/daemon/dc.py b/daemon/dc.py
index 9b86df2..5028e94 100644
--- a/daemon/dc.py
+++ b/daemon/dc.py
@@ -6,13 +6,24 @@
import os
from dotenv import load_dotenv
from mysql import connector
+from apscheduler.schedulers.asyncio import AsyncIOScheduler
from dscord.gnuweeb import GWClient
+from dscord.mailer import Listener
+from dscord.mailer import Mutexes
+from atom import Scraper
def main():
load_dotenv("discord.env")
+ sched = AsyncIOScheduler(
+ job_defaults={
+ "max_instances": 3,
+ "misfire_grace_time": None
+ }
+ )
+
client = GWClient(
db_conn=connector.connect(
host=os.getenv("DB_HOST"),
@@ -21,6 +32,15 @@ def main():
database=os.getenv("DB_NAME")
)
)
+
+ mailer = Listener(
+ client=client,
+ sched=sched,
+ scraper=Scraper(),
+ mutexes=Mutexes()
+ )
+ client.mailer = mailer
+
client.run(os.getenv("DISCORD_TOKEN"), log_handler=None)
diff --git a/daemon/dscord/gnuweeb/client.py b/daemon/dscord/gnuweeb/client.py
index 2506ec3..03a1b8c 100644
--- a/daemon/dscord/gnuweeb/client.py
+++ b/daemon/dscord/gnuweeb/client.py
@@ -20,6 +20,7 @@ class GWClient(commands.Bot):
self.db = DB(db_conn)
intents = Intents.default()
intents.message_content = True
+ self.mailer = None
super().__init__(
command_prefix=["$", "."],
description="Just a bot for receiving lore emails.",
diff --git a/daemon/dscord/gnuweeb/plugins/events/on_ready.py b/daemon/dscord/gnuweeb/plugins/events/on_ready.py
index cb7de29..c93e8a0 100644
--- a/daemon/dscord/gnuweeb/plugins/events/on_ready.py
+++ b/daemon/dscord/gnuweeb/plugins/events/on_ready.py
@@ -13,6 +13,8 @@ class OnReady(commands.Cog):
@commands.Cog.listener()
async def on_ready(self):
+ self.bot.mailer.run()
+
t = "[ GNU/Weeb Bot is connected ]\n\n"
t += f"ID : {self.bot.user.id}\n"
t += f"Name : {self.bot.user.display_name}\n"
--
Muhammad Rizki
^ permalink raw reply related [flat|nested] 30+ messages in thread
* [PATCH v2 20/28] discord: Add @filters.lore_admin() decorator
2022-10-03 23:52 [PATCH v2 00/28] The complete version of the Discord bot Muhammad Rizki
` (18 preceding siblings ...)
2022-10-03 23:52 ` [PATCH v2 19/28] discord: Implement the mail Listener() class Muhammad Rizki
@ 2022-10-03 23:52 ` Muhammad Rizki
2022-10-03 23:52 ` [PATCH v2 21/28] discord: Add a list of atom URL slash command Muhammad Rizki
` (8 subsequent siblings)
28 siblings, 0 replies; 30+ messages in thread
From: Muhammad Rizki @ 2022-10-03 23:52 UTC (permalink / raw)
To: Ammar Faizi
Cc: Muhammad Rizki, Alviro Iskandar Setiawan, GNU/Weeb Mailing List
Add a @filters.lore_admin() decorator to filter only the lore admin role
that can use the specific commands. With this, other users who don't
have the lore admin role cannot use the specific commands.
Signed-off-by: Muhammad Rizki <[email protected]>
---
daemon/dscord/gnuweeb/filters.py | 28 +++++++++++++++++++++++++++-
1 file changed, 27 insertions(+), 1 deletion(-)
diff --git a/daemon/dscord/gnuweeb/filters.py b/daemon/dscord/gnuweeb/filters.py
index 19f9445..eb54a8a 100644
--- a/daemon/dscord/gnuweeb/filters.py
+++ b/daemon/dscord/gnuweeb/filters.py
@@ -3,11 +3,37 @@
# Copyright (C) 2022 Muhammad Rizki <[email protected]>
#
-import discord
+
+# built-in/dev package imports
import asyncio
from typing import Any
from functools import wraps
+# Discord imports
+import discord
+from discord import Interaction
+
+# gnuweeb package import
+from dscord import config
+
+
+def lore_admin(func):
+ @wraps(func)
+ async def callback(*args: Any, **kwargs: Any) -> Any:
+ i: "Interaction" = args[1]
+ user_roles = [role.id for role in i.user.roles]
+
+ if config.ADMIN_ROLE_ID not in user_roles:
+ return await i.response.send_message(
+ "Sorry, you don't have this permission\n"\
+ "Tell the server admin to add you lore admin role.",
+ ephemeral=True
+ )
+ if config.ADMIN_ROLE_ID in user_roles:
+ return await func(*args, **kwargs)
+
+ return callback
+
def wait_on_limit(func):
@wraps(func)
--
Muhammad Rizki
^ permalink raw reply related [flat|nested] 30+ messages in thread
* [PATCH v2 21/28] discord: Add a list of atom URL slash command
2022-10-03 23:52 [PATCH v2 00/28] The complete version of the Discord bot Muhammad Rizki
` (19 preceding siblings ...)
2022-10-03 23:52 ` [PATCH v2 20/28] discord: Add @filters.lore_admin() decorator Muhammad Rizki
@ 2022-10-03 23:52 ` Muhammad Rizki
2022-10-03 23:52 ` [PATCH v2 22/28] discord: Add an add atom " Muhammad Rizki
` (7 subsequent siblings)
28 siblings, 0 replies; 30+ messages in thread
From: Muhammad Rizki @ 2022-10-03 23:52 UTC (permalink / raw)
To: Ammar Faizi
Cc: Muhammad Rizki, Alviro Iskandar Setiawan, GNU/Weeb Mailing List
Add a `/atom list` slash command to get the list of atom URLs in the
database that is currently listening.
Signed-off-by: Muhammad Rizki <[email protected]>
---
daemon/dscord/gnuweeb/plugins/__init__.py | 4 +-
.../plugins/slash_commands/__init__.py | 11 ++++++
.../plugins/slash_commands/manage_atom.py | 39 +++++++++++++++++++
3 files changed, 53 insertions(+), 1 deletion(-)
create mode 100644 daemon/dscord/gnuweeb/plugins/slash_commands/__init__.py
create mode 100644 daemon/dscord/gnuweeb/plugins/slash_commands/manage_atom.py
diff --git a/daemon/dscord/gnuweeb/plugins/__init__.py b/daemon/dscord/gnuweeb/plugins/__init__.py
index cbec2b5..631d9ad 100644
--- a/daemon/dscord/gnuweeb/plugins/__init__.py
+++ b/daemon/dscord/gnuweeb/plugins/__init__.py
@@ -8,11 +8,13 @@ from discord.ext import commands
from .events import Events
from .basic_commands import BasicCommands
+from .slash_commands import SlashCommands
class Plugins(
BasicCommands,
- Events
+ Events,
+ SlashCommands
): pass
diff --git a/daemon/dscord/gnuweeb/plugins/slash_commands/__init__.py b/daemon/dscord/gnuweeb/plugins/slash_commands/__init__.py
new file mode 100644
index 0000000..0ed86b1
--- /dev/null
+++ b/daemon/dscord/gnuweeb/plugins/slash_commands/__init__.py
@@ -0,0 +1,11 @@
+# SPDX-License-Identifier: GPL-2.0-only
+#
+# Copyright (C) 2022 Muhammad Rizki <[email protected]>
+#
+
+from .manage_atom import ManageAtomSC
+
+
+class SlashCommands(
+ ManageAtomSC,
+): pass
diff --git a/daemon/dscord/gnuweeb/plugins/slash_commands/manage_atom.py b/daemon/dscord/gnuweeb/plugins/slash_commands/manage_atom.py
new file mode 100644
index 0000000..a4281c1
--- /dev/null
+++ b/daemon/dscord/gnuweeb/plugins/slash_commands/manage_atom.py
@@ -0,0 +1,39 @@
+# SPDX-License-Identifier: GPL-2.0-only
+#
+# Copyright (C) 2022 Muhammad Rizki <[email protected]>
+#
+
+from discord.ext import commands
+from discord import Interaction
+from discord import app_commands
+
+from dscord.gnuweeb import filters
+
+
+class ManageAtomSC(commands.Cog):
+ atom = app_commands.Group(
+ name="atom",
+ description="Manage lore atom URL."
+ )
+
+ def __init__(self, bot) -> None:
+ self.bot = bot
+
+
+ @atom.command(
+ name="list",
+ description="List of lore atom URL."
+ )
+ @filters.lore_admin
+ async def list_atom(self, i: "Interaction"):
+ atoms = self.bot.db.get_atom_urls()
+ if len(atoms) == 0:
+ t = "Currently empty."
+ await i.response.send_message(t, ephemeral=True)
+ return
+
+ text = "List of atom URL that currently listened:\n"
+ for u,n in zip(atoms, range(1, len(atoms)+1)):
+ text += f"{n}. {u}\n"
+
+ await i.response.send_message(text, ephemeral=True)
--
Muhammad Rizki
^ permalink raw reply related [flat|nested] 30+ messages in thread
* [PATCH v2 22/28] discord: Add an add atom slash command
2022-10-03 23:52 [PATCH v2 00/28] The complete version of the Discord bot Muhammad Rizki
` (20 preceding siblings ...)
2022-10-03 23:52 ` [PATCH v2 21/28] discord: Add a list of atom URL slash command Muhammad Rizki
@ 2022-10-03 23:52 ` Muhammad Rizki
2022-10-03 23:52 ` [PATCH v2 23/28] discord: Add a delete " Muhammad Rizki
` (6 subsequent siblings)
28 siblings, 0 replies; 30+ messages in thread
From: Muhammad Rizki @ 2022-10-03 23:52 UTC (permalink / raw)
To: Ammar Faizi
Cc: Muhammad Rizki, Alviro Iskandar Setiawan, GNU/Weeb Mailing List
Add `/add atom` to add an atom URL to the database for listening to a
new lore email message.
Signed-off-by: Muhammad Rizki <[email protected]>
---
.../plugins/slash_commands/manage_atom.py | 24 +++++++++++++++++++
1 file changed, 24 insertions(+)
diff --git a/daemon/dscord/gnuweeb/plugins/slash_commands/manage_atom.py b/daemon/dscord/gnuweeb/plugins/slash_commands/manage_atom.py
index a4281c1..409e612 100644
--- a/daemon/dscord/gnuweeb/plugins/slash_commands/manage_atom.py
+++ b/daemon/dscord/gnuweeb/plugins/slash_commands/manage_atom.py
@@ -7,6 +7,7 @@ from discord.ext import commands
from discord import Interaction
from discord import app_commands
+from atom import utils
from dscord.gnuweeb import filters
@@ -37,3 +38,26 @@ class ManageAtomSC(commands.Cog):
text += f"{n}. {u}\n"
await i.response.send_message(text, ephemeral=True)
+
+
+ @atom.command(
+ name="add",
+ description="Add lore atom URL for receiving lore emails."
+ )
+ @app_commands.describe(url='Lore atom URL.')
+ @filters.lore_admin
+ async def add_atom(self, i: "Interaction", url: str):
+ is_atom = await utils.is_atom_url(url)
+ if not is_atom:
+ t = "Invalid Atom URL."
+ await i.response.send_message(t, ephemeral=True)
+ return
+
+ inserted = self.bot.db.save_atom(url)
+ if inserted is None:
+ t = f"This URL already listened for new email."
+ await i.response.send_message(t, ephemeral=True)
+ return
+
+ t = f"Success add **{url}** for listening new email."
+ await i.response.send_message(t, ephemeral=True)
--
Muhammad Rizki
^ permalink raw reply related [flat|nested] 30+ messages in thread
* [PATCH v2 23/28] discord: Add a delete atom slash command
2022-10-03 23:52 [PATCH v2 00/28] The complete version of the Discord bot Muhammad Rizki
` (21 preceding siblings ...)
2022-10-03 23:52 ` [PATCH v2 22/28] discord: Add an add atom " Muhammad Rizki
@ 2022-10-03 23:52 ` Muhammad Rizki
2022-10-03 23:52 ` [PATCH v2 24/28] discord: Add channel_link() in the atom/utils.py Muhammad Rizki
` (5 subsequent siblings)
28 siblings, 0 replies; 30+ messages in thread
From: Muhammad Rizki @ 2022-10-03 23:52 UTC (permalink / raw)
To: Ammar Faizi
Cc: Muhammad Rizki, Alviro Iskandar Setiawan, GNU/Weeb Mailing List
Add `/atom delete` to delete a specific atom URL in the database that is
currently listening new lore email message.
Signed-off-by: Muhammad Rizki <[email protected]>
---
.../plugins/slash_commands/manage_atom.py | 18 ++++++++++++++++++
1 file changed, 18 insertions(+)
diff --git a/daemon/dscord/gnuweeb/plugins/slash_commands/manage_atom.py b/daemon/dscord/gnuweeb/plugins/slash_commands/manage_atom.py
index 409e612..e0a6b9e 100644
--- a/daemon/dscord/gnuweeb/plugins/slash_commands/manage_atom.py
+++ b/daemon/dscord/gnuweeb/plugins/slash_commands/manage_atom.py
@@ -61,3 +61,21 @@ class ManageAtomSC(commands.Cog):
t = f"Success add **{url}** for listening new email."
await i.response.send_message(t, ephemeral=True)
+
+
+ @atom.command(
+ name="delete",
+ description="Delete lore atom URL from receiving lore emails."
+ )
+ @app_commands.describe(url='Lore atom URL.')
+ @filters.lore_admin
+ async def del_atom(self, i: "Interaction", url: str):
+ success = self.bot.db.delete_atom(url)
+ if not success:
+ t = "Failed to delete atom URL\n"
+ t += "Maybe because already deleted or not exists."
+ await i.response.send_message(t, ephemeral=True)
+ return
+
+ t = f"Success delete **{url}** from receiving lore emails."
+ await i.response.send_message(t, ephemeral=True)
--
Muhammad Rizki
^ permalink raw reply related [flat|nested] 30+ messages in thread
* [PATCH v2 24/28] discord: Add channel_link() in the atom/utils.py
2022-10-03 23:52 [PATCH v2 00/28] The complete version of the Discord bot Muhammad Rizki
` (22 preceding siblings ...)
2022-10-03 23:52 ` [PATCH v2 23/28] discord: Add a delete " Muhammad Rizki
@ 2022-10-03 23:52 ` Muhammad Rizki
2022-10-03 23:52 ` [PATCH v2 25/28] discord: Add a list broadcast slash command Muhammad Rizki
` (4 subsequent siblings)
28 siblings, 0 replies; 30+ messages in thread
From: Muhammad Rizki @ 2022-10-03 23:52 UTC (permalink / raw)
To: Ammar Faizi
Cc: Muhammad Rizki, Alviro Iskandar Setiawan, GNU/Weeb Mailing List
Add channel_link() to create a Discord channel URL with guild id and
channel id.
Signed-off-by: Muhammad Rizki <[email protected]>
---
daemon/atom/utils.py | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/daemon/atom/utils.py b/daemon/atom/utils.py
index 870ee70..a30d5cb 100644
--- a/daemon/atom/utils.py
+++ b/daemon/atom/utils.py
@@ -306,3 +306,7 @@ def create_chat_link(chat: Chat):
chat_id_str = str(chat.id).replace("-100","")
return f"t.me/c/{chat_id_str}/1"
+
+
+def channel_link(guild_id: int, channel_id: int):
+ return f"https://discord.com/channels/{guild_id}/{channel_id}"
--
Muhammad Rizki
^ permalink raw reply related [flat|nested] 30+ messages in thread
* [PATCH v2 25/28] discord: Add a list broadcast slash command
2022-10-03 23:52 [PATCH v2 00/28] The complete version of the Discord bot Muhammad Rizki
` (23 preceding siblings ...)
2022-10-03 23:52 ` [PATCH v2 24/28] discord: Add channel_link() in the atom/utils.py Muhammad Rizki
@ 2022-10-03 23:52 ` Muhammad Rizki
2022-10-03 23:52 ` [PATCH v2 26/28] discord: Add an add " Muhammad Rizki
` (3 subsequent siblings)
28 siblings, 0 replies; 30+ messages in thread
From: Muhammad Rizki @ 2022-10-03 23:52 UTC (permalink / raw)
To: Ammar Faizi
Cc: Muhammad Rizki, Alviro Iskandar Setiawan, GNU/Weeb Mailing List
Add `/broadcast list` slash command to get the list of the current
Discord channel listening for a new lore email message.
Signed-off-by: Muhammad Rizki <[email protected]>
---
.../plugins/slash_commands/__init__.py | 2 +
.../slash_commands/manage_broadcast.py | 41 +++++++++++++++++++
2 files changed, 43 insertions(+)
create mode 100644 daemon/dscord/gnuweeb/plugins/slash_commands/manage_broadcast.py
diff --git a/daemon/dscord/gnuweeb/plugins/slash_commands/__init__.py b/daemon/dscord/gnuweeb/plugins/slash_commands/__init__.py
index 0ed86b1..a6d913c 100644
--- a/daemon/dscord/gnuweeb/plugins/slash_commands/__init__.py
+++ b/daemon/dscord/gnuweeb/plugins/slash_commands/__init__.py
@@ -4,8 +4,10 @@
#
from .manage_atom import ManageAtomSC
+from .manage_broadcast import ManageBroadcastSC
class SlashCommands(
ManageAtomSC,
+ ManageBroadcastSC
): pass
diff --git a/daemon/dscord/gnuweeb/plugins/slash_commands/manage_broadcast.py b/daemon/dscord/gnuweeb/plugins/slash_commands/manage_broadcast.py
new file mode 100644
index 0000000..db3d9e6
--- /dev/null
+++ b/daemon/dscord/gnuweeb/plugins/slash_commands/manage_broadcast.py
@@ -0,0 +1,41 @@
+# SPDX-License-Identifier: GPL-2.0-only
+#
+# Copyright (C) 2022 Muhammad Rizki <[email protected]>
+#
+
+from discord.ext import commands
+from discord import Interaction
+from discord import app_commands
+
+from dscord.gnuweeb import filters
+
+
+class ManageBroadcastSC(commands.Cog):
+ broadcast = app_commands.Group(
+ name="broadcast",
+ description="Manage broadcast channel."
+ )
+
+
+ def __init__(self, bot) -> None:
+ self.bot = bot
+
+
+ @broadcast.command(
+ name="list",
+ description="List of broadcast channel."
+ )
+ @filters.lore_admin
+ async def list_channel(self, i: "Interaction"):
+ chats = self.bot.db.get_broadcast_chats()
+ if len(chats) == 0:
+ t = "Currently empty."
+ await i.response.send_message(t, ephemeral=True)
+ return
+
+ text = "List of channels that will send email messages:\n"
+ for u,n in zip(chats, range(1, len(chats)+1)):
+ text += f"{n}. **{u[3]}**\n"
+ text += f"Link: {u[4]}\n\n"
+
+ await i.response.send_message(text, ephemeral=True)
--
Muhammad Rizki
^ permalink raw reply related [flat|nested] 30+ messages in thread
* [PATCH v2 26/28] discord: Add an add broadcast slash command
2022-10-03 23:52 [PATCH v2 00/28] The complete version of the Discord bot Muhammad Rizki
` (24 preceding siblings ...)
2022-10-03 23:52 ` [PATCH v2 25/28] discord: Add a list broadcast slash command Muhammad Rizki
@ 2022-10-03 23:52 ` Muhammad Rizki
2022-10-03 23:52 ` [PATCH v2 27/28] discord: Add a delete " Muhammad Rizki
` (2 subsequent siblings)
28 siblings, 0 replies; 30+ messages in thread
From: Muhammad Rizki @ 2022-10-03 23:52 UTC (permalink / raw)
To: Ammar Faizi
Cc: Muhammad Rizki, Alviro Iskandar Setiawan, GNU/Weeb Mailing List
Add `/broadcast add` to add the current Discord channel for listening to
new lore email messages.
Signed-off-by: Muhammad Rizki <[email protected]>
---
.../slash_commands/manage_broadcast.py | 26 +++++++++++++++++++
1 file changed, 26 insertions(+)
diff --git a/daemon/dscord/gnuweeb/plugins/slash_commands/manage_broadcast.py b/daemon/dscord/gnuweeb/plugins/slash_commands/manage_broadcast.py
index db3d9e6..b9dd5e1 100644
--- a/daemon/dscord/gnuweeb/plugins/slash_commands/manage_broadcast.py
+++ b/daemon/dscord/gnuweeb/plugins/slash_commands/manage_broadcast.py
@@ -7,6 +7,7 @@ from discord.ext import commands
from discord import Interaction
from discord import app_commands
+from atom import utils
from dscord.gnuweeb import filters
@@ -39,3 +40,28 @@ class ManageBroadcastSC(commands.Cog):
text += f"Link: {u[4]}\n\n"
await i.response.send_message(text, ephemeral=True)
+
+
+ @broadcast.command(
+ name="add",
+ description="Add broadcast channel for sending lore emails."
+ )
+ @filters.lore_admin
+ async def add_channel(self, i: "Interaction"):
+ inserted = self.bot.db.save_broadcast(
+ guild_id=i.guild_id,
+ channel_id=i.channel_id,
+ channel_name=i.channel.name,
+ channel_link=utils.channel_link(
+ guild_id=i.guild_id,
+ channel_id=i.channel_id
+ )
+ )
+
+ if inserted is None:
+ t = f"This channel already added for send email messages."
+ await i.response.send_message(t, ephemeral=True)
+ return
+
+ t = f"Success add this channel for send email messages."
+ await i.response.send_message(t, ephemeral=True)
--
Muhammad Rizki
^ permalink raw reply related [flat|nested] 30+ messages in thread
* [PATCH v2 27/28] discord: Add a delete broadcast slash command
2022-10-03 23:52 [PATCH v2 00/28] The complete version of the Discord bot Muhammad Rizki
` (25 preceding siblings ...)
2022-10-03 23:52 ` [PATCH v2 26/28] discord: Add an add " Muhammad Rizki
@ 2022-10-03 23:52 ` Muhammad Rizki
2022-10-03 23:52 ` [PATCH v2 28/28] discord: Change the on_ready message Muhammad Rizki
2022-10-07 22:57 ` [PATCH v2 00/28] The complete version of the Discord bot Ammar Faizi
28 siblings, 0 replies; 30+ messages in thread
From: Muhammad Rizki @ 2022-10-03 23:52 UTC (permalink / raw)
To: Ammar Faizi
Cc: Muhammad Rizki, Alviro Iskandar Setiawan, GNU/Weeb Mailing List
Add `/broadcast delete` to delete current Discord channel from listening
new lore email message.
Signed-off-by: Muhammad Rizki <[email protected]>
---
.../plugins/slash_commands/manage_broadcast.py | 17 +++++++++++++++++
1 file changed, 17 insertions(+)
diff --git a/daemon/dscord/gnuweeb/plugins/slash_commands/manage_broadcast.py b/daemon/dscord/gnuweeb/plugins/slash_commands/manage_broadcast.py
index b9dd5e1..c04560d 100644
--- a/daemon/dscord/gnuweeb/plugins/slash_commands/manage_broadcast.py
+++ b/daemon/dscord/gnuweeb/plugins/slash_commands/manage_broadcast.py
@@ -65,3 +65,20 @@ class ManageBroadcastSC(commands.Cog):
t = f"Success add this channel for send email messages."
await i.response.send_message(t, ephemeral=True)
+
+
+ @broadcast.command(
+ name="delete",
+ description="Delete broadcast channel from sending email messages."
+ )
+ @filters.lore_admin
+ async def del_channel(self, i: "Interaction"):
+ success = self.bot.db.delete_broadcast(i.channel_id)
+ if not success:
+ t = "Failed to delete this channel\n"
+ t += "Maybe because already deleted or not exists."
+ await i.response.send_message(t, ephemeral=True)
+ return
+
+ t = f"Success delete this channel from sending email messages."
+ await i.response.send_message(t, ephemeral=True)
--
Muhammad Rizki
^ permalink raw reply related [flat|nested] 30+ messages in thread
* [PATCH v2 28/28] discord: Change the on_ready message
2022-10-03 23:52 [PATCH v2 00/28] The complete version of the Discord bot Muhammad Rizki
` (26 preceding siblings ...)
2022-10-03 23:52 ` [PATCH v2 27/28] discord: Add a delete " Muhammad Rizki
@ 2022-10-03 23:52 ` Muhammad Rizki
2022-10-07 22:57 ` [PATCH v2 00/28] The complete version of the Discord bot Ammar Faizi
28 siblings, 0 replies; 30+ messages in thread
From: Muhammad Rizki @ 2022-10-03 23:52 UTC (permalink / raw)
To: Ammar Faizi
Cc: Muhammad Rizki, Alviro Iskandar Setiawan, GNU/Weeb Mailing List
Add a tips message on the on_ready event, so the author of the bot is
know what to do when the bot first starts.
Signed-off-by: Muhammad Rizki <[email protected]>
---
daemon/dscord/gnuweeb/plugins/events/on_ready.py | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/daemon/dscord/gnuweeb/plugins/events/on_ready.py b/daemon/dscord/gnuweeb/plugins/events/on_ready.py
index c93e8a0..4f25764 100644
--- a/daemon/dscord/gnuweeb/plugins/events/on_ready.py
+++ b/daemon/dscord/gnuweeb/plugins/events/on_ready.py
@@ -14,10 +14,13 @@ class OnReady(commands.Cog):
@commands.Cog.listener()
async def on_ready(self):
self.bot.mailer.run()
+ prefix = self.bot.command_prefix[0]
t = "[ GNU/Weeb Bot is connected ]\n\n"
t += f"ID : {self.bot.user.id}\n"
t += f"Name : {self.bot.user.display_name}\n"
t += f"Tags : {self.bot.user}\n\n"
- t += "Ready to get the latest of lore kernel emails."
+ t += f"Send `{prefix}sync` message to the Discord channel "
+ t += "where the bot is running.\n"
+
print(t)
--
Muhammad Rizki
^ permalink raw reply related [flat|nested] 30+ messages in thread
* Re: [PATCH v2 00/28] The complete version of the Discord bot
2022-10-03 23:52 [PATCH v2 00/28] The complete version of the Discord bot Muhammad Rizki
` (27 preceding siblings ...)
2022-10-03 23:52 ` [PATCH v2 28/28] discord: Change the on_ready message Muhammad Rizki
@ 2022-10-07 22:57 ` Ammar Faizi
28 siblings, 0 replies; 30+ messages in thread
From: Ammar Faizi @ 2022-10-07 22:57 UTC (permalink / raw)
To: Muhammad Rizki
Cc: Ammar Faizi, GNU/Weeb Mailing List, Alviro Iskandar Setiawan
On Tue, 4 Oct 2022 06:52:01 +0700, Muhammad Rizki wrote:
> In this series, I create the complete version of the Discord bot.
> This series contains slash commands, events, and basic commands for
> syncing the slash commands to the global.
>
> Features:
> Add getter and deletion database methods.
> Add a mail listener to get the new lore email message.
> Add filters to only the lore admin who can use the atom.
> Add broadcast manager slash commands.
> Add a button UI to go direct to its lore email message.
> And others.
>
> [...]
Applied, thanks!
[01/28] discord: Add .gitignore in the Discord's storage directory
commit: be1d34fc070594e66928a329ba66095e8a8cad35
[02/28] Fix the storage management after the refactor was happened
commit: bb8855bf5e344136202e167c1bec1aa37bf67dc6
[03/28] Fix the empty temporary patch directory on atom/utils.py
commit: 66a82ec6d091cba8e72f7f82e08ff93f582d2d65
[04/28] discord: Add get_atom_urls() to get the list of atom URLs
commit: 10bfa4ce176410c249d29ac222e1ea15d754e04f
[05/28] discord: Add get_broadcast_chats() to get the list of broadcast chats
commit: 459e95c1f632163fa0ff44eef85c5af9640b305e
[06/28] discord: Add get_email_id() in getter directory
commit: 854c9fd1d7e3c4b66947427619d7b0ef4bfd964f
[07/28] discord: Add get_reply_id() in getter directory
commit: f31477f60cd633e8b1e0e00662db7339182284f3
[08/28] discord: Inherit Getter() class to the DBMethods() class
commit: aa7667bcf78b975eef4cee3d918dce5f2653558d
[09/28] discord: Add delete_atom() in deletion directory
commit: 6479a667a38881b78fa5c7937faa05e8ea107e50
[10/28] discord: Add delete_broadcast() in deletion directory
commit: 49ab491e87be6e54a25c645031ca13f9bc1b8ecc
[11/28] discord: Inherit the Deletion() class to the DBMethods() class
commit: 590f826fbb6eaa9f3bf72f3bdc86d405d876f5a0
[12/28] discord: Inherit the DBMethods() class to the DB() class
commit: 9b2495fa5f9bd424f51865294123c9366f45adf3
[13/28] discord: Use the created DB() class
commit: 51aaf75c7036951de0942d8cddb07165a1473288
[14/28] telegram: Rename some utility functions
commit: 6b253bcf11215d3f27d7f501d0627ee00d06b9bb
[15/28] discord: Add a FullMessageBtn() class in models
commit: 3bce845ecb858f0da732ca39741e0af96946d3bf
[16/28] discord: Add filters.wait_on_limit() decorator
commit: a8cc67284b2fd92c767b25bc31ea5d38cc389d32
[17/28] discord: Add send lore email message functions
commit: 051d6c5c08861d7475a6c366294519626baa876f
[18/28] discord: Add mail listener
commit: 62decb1e4ac078c3e212bbd6260262dcd6fde7e3
[19/28] discord: Implement the mail Listener() class
commit: d580ffa742a81fb236956d716324f260b2f4b176
[20/28] discord: Add @filters.lore_admin() decorator
commit: b206da3d3a4963120871f9f228dc0132b1bebede
[21/28] discord: Add a list of atom URL slash command
commit: 90b6f8af80b2cfa9d283b97f6e8f5efb8895db30
[22/28] discord: Add an add atom slash command
commit: adb72d038fda930b8e630eff39bfeaf360c985ff
[23/28] discord: Add a delete atom slash command
commit: 4832318c41e302c26b96e5d1de384b759e4e14c2
[24/28] discord: Add channel_link() in the atom/utils.py
commit: e53917cd582c469c5ab8dec32f0f569ce100b0d0
[25/28] discord: Add a list broadcast slash command
commit: 4d91691eea419166c344ec61abcb380b18668a8f
[26/28] discord: Add an add broadcast slash command
commit: 8141c89b151009a06e756627c7517130d1fb2b01
[27/28] discord: Add a delete broadcast slash command
commit: e4768a296ed93267db127f6842fdebded64df3ca
[28/28] discord: Change the on_ready message
commit: 277102742c7e2180eb544424111f2629be54b174
Best regards,
--
Ammar Faizi
^ permalink raw reply [flat|nested] 30+ messages in thread
end of thread, other threads:[~2022-10-07 22:57 UTC | newest]
Thread overview: 30+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2022-10-03 23:52 [PATCH v2 00/28] The complete version of the Discord bot Muhammad Rizki
2022-10-03 23:52 ` [PATCH v2 01/28] discord: Add .gitignore in the Discord's storage directory Muhammad Rizki
2022-10-03 23:52 ` [PATCH v2 02/28] Fix the storage management after the refactor was happened Muhammad Rizki
2022-10-03 23:52 ` [PATCH v2 03/28] Fix the empty temporary patch directory on atom/utils.py Muhammad Rizki
2022-10-03 23:52 ` [PATCH v2 04/28] discord: Add get_atom_urls() to get the list of atom URLs Muhammad Rizki
2022-10-03 23:52 ` [PATCH v2 05/28] discord: Add get_broadcast_chats() to get the list of broadcast chats Muhammad Rizki
2022-10-03 23:52 ` [PATCH v2 06/28] discord: Add get_email_id() in getter directory Muhammad Rizki
2022-10-03 23:52 ` [PATCH v2 07/28] discord: Add get_reply_id() " Muhammad Rizki
2022-10-03 23:52 ` [PATCH v2 08/28] discord: Inherit Getter() class to the DBMethods() class Muhammad Rizki
2022-10-03 23:52 ` [PATCH v2 09/28] discord: Add delete_atom() in deletion directory Muhammad Rizki
2022-10-03 23:52 ` [PATCH v2 10/28] discord: Add delete_broadcast() " Muhammad Rizki
2022-10-03 23:52 ` [PATCH v2 11/28] discord: Inherit the Deletion() class to the DBMethods() class Muhammad Rizki
2022-10-03 23:52 ` [PATCH v2 12/28] discord: Inherit the DBMethods() class to the DB() class Muhammad Rizki
2022-10-03 23:52 ` [PATCH v2 13/28] discord: Use the created " Muhammad Rizki
2022-10-03 23:52 ` [PATCH v2 14/28] telegram: Rename some utility functions Muhammad Rizki
2022-10-03 23:52 ` [PATCH v2 15/28] discord: Add a FullMessageBtn() class in models Muhammad Rizki
2022-10-03 23:52 ` [PATCH v2 16/28] discord: Add filters.wait_on_limit() decorator Muhammad Rizki
2022-10-03 23:52 ` [PATCH v2 17/28] discord: Add send lore email message functions Muhammad Rizki
2022-10-03 23:52 ` [PATCH v2 18/28] discord: Add mail listener Muhammad Rizki
2022-10-03 23:52 ` [PATCH v2 19/28] discord: Implement the mail Listener() class Muhammad Rizki
2022-10-03 23:52 ` [PATCH v2 20/28] discord: Add @filters.lore_admin() decorator Muhammad Rizki
2022-10-03 23:52 ` [PATCH v2 21/28] discord: Add a list of atom URL slash command Muhammad Rizki
2022-10-03 23:52 ` [PATCH v2 22/28] discord: Add an add atom " Muhammad Rizki
2022-10-03 23:52 ` [PATCH v2 23/28] discord: Add a delete " Muhammad Rizki
2022-10-03 23:52 ` [PATCH v2 24/28] discord: Add channel_link() in the atom/utils.py Muhammad Rizki
2022-10-03 23:52 ` [PATCH v2 25/28] discord: Add a list broadcast slash command Muhammad Rizki
2022-10-03 23:52 ` [PATCH v2 26/28] discord: Add an add " Muhammad Rizki
2022-10-03 23:52 ` [PATCH v2 27/28] discord: Add a delete " Muhammad Rizki
2022-10-03 23:52 ` [PATCH v2 28/28] discord: Change the on_ready message Muhammad Rizki
2022-10-07 22:57 ` [PATCH v2 00/28] The complete version of the Discord bot Ammar Faizi
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox