Skip to content

Commit

Permalink
- Refactoring. Split a code into the modules
Browse files Browse the repository at this point in the history
  • Loading branch information
soksanichenko committed Mar 15, 2024
1 parent 9d4fd43 commit f3fa938
Show file tree
Hide file tree
Showing 10 changed files with 219 additions and 163 deletions.
10 changes: 5 additions & 5 deletions deploy/roles/deploy_bot_container/tasks/docker.yml
Original file line number Diff line number Diff line change
Expand Up @@ -56,8 +56,8 @@
type: bind
become: yes

#- name: Remove Dockerfile
# file:
# path: "/tmp/Dockerfile"
# state: absent
#...
- name: Remove Dockerfile
file:
path: "/tmp/Dockerfile"
state: absent
...
Empty file added sources/__init__.py
Empty file.
Empty file added sources/lib/__init__.py
Empty file.
Empty file.
65 changes: 65 additions & 0 deletions sources/lib/commands/get_timestamp.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
"""Get timestamp module"""
from __future__ import annotations

import typing
from datetime import datetime

import dateparser
import discord


def parse_and_validate(
date: str,
time: str,
interaction: discord.Interaction,
) -> typing.Optional[datetime]:
"""Parse and validate date and time text"""

return dateparser.parse(
f"{time} {date}",
locales=[interaction.locale.value],
)


class TimestampFormatView(discord.ui.View):
"""
View class for timestamp formatting
"""

def __init__(self, timestamp: int):
self.timestamp = timestamp
super().__init__()

@discord.ui.select(
placeholder="Select format",
min_values=1,
max_values=1,
options=[
discord.SelectOption(
label="F", description="Wednesday, 1 January 2021, 23:50"
),
discord.SelectOption(label="f", description="1 January 2021, 23:50"),
discord.SelectOption(label="D", description="1 January 2021"),
discord.SelectOption(label="d", description="01.01.2021"),
discord.SelectOption(label="t", description="23:50"),
discord.SelectOption(label="T", description="23:50:55"),
discord.SelectOption(label="R", description="2 hours ago"),
],
)
async def select_callback(
self,
interaction: discord.Interaction,
select: discord.ui.ChannelSelect,
):
"""
Callback for selecting an option of formatting
:param interaction: an object of interaction with a user
:param select: a selected option
:return: None
"""
timestamp = f"<t:{self.timestamp}:{select.values[0]}>"

await interaction.response.send_message(
f"{timestamp}\n`{timestamp}`",
ephemeral=True,
)
30 changes: 30 additions & 0 deletions sources/lib/core.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
"""Core functionality for the bot"""
import base64
from pathlib import Path

from sources.lib.utils import singleton


@singleton
class BotAvatar:
"""Class-singleton for saving of an avatar of the bot"""
__avatar__ = None

def __init__(self):
self.__avatar__ = self.load_bot_avatar()

@property
def avatar(self):
"""Get an avatar of the bot like as bytes-object"""
return self.__avatar__

@staticmethod
def load_bot_avatar() -> bytes:
"""
Load a bot's avatar
:return: bytes of a bot's avatar
"""
path = Path(__file__).parent.joinpath('../static/avatar.gif.base64')
with path.open(mode='r', encoding='utf-8') as fd:
data = base64.b64decode(fd.read())
return data
Empty file.
58 changes: 58 additions & 0 deletions sources/lib/on_message/domains_fixer.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
"""Domains fixer module"""
from copy import copy
from urllib.parse import urlparse, ParseResult

import discord
from tldextract import extract
from tldextract.tldextract import ExtractResult

from sources.lib.utils import Logger


def fix_urls(message: discord.Message) -> str:
"""
Fix the URLs by replacing an original domain by a fixer
:param message: a message from Discord
:return: a fixed message content
"""
domains = {
"reddit.com": "rxddit",
"tiktok.com": "vxtiktok",
"x.com": "fixupx",
"twitter.com": "fxtwitter",
"instagram.com": "ddinstagram",
}

msg_content_lines = message.content.split()
parsed_urls = {
(parsed_url := urlparse(line)): extract(parsed_url.netloc)
for line in msg_content_lines
if line.startswith("http://") or line.startswith("https://")
}
if all(
parsed_domain.registered_domain not in domains
for parsed_domain in parsed_urls.values()
):
Logger().logger.info("No suitable domain or any URL found")
return message.content
final_urls = {
parsed_url.geturl(): ParseResult(
parsed_url.scheme,
netloc=ExtractResult(
subdomain=parsed_domain.subdomain,
domain=domains[parsed_domain.registered_domain],
suffix=parsed_domain.suffix,
is_private=parsed_domain.is_private,
).fqdn,
path=parsed_url.path,
query=parsed_url.query,
params=parsed_url.params,
fragment=parsed_url.fragment,
).geturl()
for parsed_url, parsed_domain in parsed_urls.items()
}
content = copy(message.content)
for original_url, fixed_url in final_urls.items():
content = content.replace(original_url, fixed_url)
content += f"\nOriginal message posted by {message.author.mention}"
return content
31 changes: 31 additions & 0 deletions sources/lib/utils.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
"""Helpful utilities"""

import logging


def singleton(class_):
"""Singleton decorator"""
instances = {}

def getinstance(*args, **kwargs):
if class_ not in instances:
instances[class_] = class_(*args, **kwargs)
return instances[class_]

return getinstance


class Logger:
# pylint: disable=too-few-public-methods
"""Logging class"""

__logger__ = None

def __init__(self, level: int = logging.INFO):
self.__logger__ = logging.getLogger('discord')
self.__logger__.setLevel(level)

@property
def logger(self) -> logging.Logger:
"""Get initialized logger"""
return self.__logger__
Loading

0 comments on commit f3fa938

Please sign in to comment.