diff --git a/.github/workflows/pytest.yml b/.github/workflows/pytest.yml
index b4be9b1..ef38ab6 100644
--- a/.github/workflows/pytest.yml
+++ b/.github/workflows/pytest.yml
@@ -12,14 +12,12 @@ permissions:
jobs:
tests:
runs-on: ubuntu-latest
- env:
- BOT_TOKEN: "example"
steps:
- uses: actions/checkout@v3
- - name: Set up Python 3.10
+ - name: Set up Python 3.11
uses: actions/setup-python@v3
with:
- python-version: "3.10"
+ python-version: "3.11"
- name: Set up system environment
run: |
sudo apt-get update -y
@@ -28,6 +26,9 @@ jobs:
run: |
python3 -m pip install --upgrade pip
python3 -m pip install -r requirements.txt
+ - name: Setup configurations
+ run: |
+ cp .env.toml env.toml
- name: Test with pytest
run: |
python3 -m pytest
diff --git a/README.md b/README.md
index 140ada0..2135a20 100644
--- a/README.md
+++ b/README.md
@@ -1,6 +1,6 @@
# Randomology
-
-
+[![Github Actions Status](https://img.shields.io/github/actions/workflow/status/ravachol-yang/randomology/pytest.yml?style=for-the-badge&logo=github&label=tests)](https://github.com/ravachol-yang/randomology/actions)
+[![Telegram](https://img.shields.io/badge/telegram-26a4e2?style=for-the-badge&logo=telegram&logoColor=white)](https://t.me/randomology_bot)
A telegram bot to generate random stuff, I built this to chat with my friend randomly.
Using [pyTelegramBotAPI](https://github.com/eternnoir/pyTelegramBotAPI) for talking with telegram server.
@@ -67,7 +67,7 @@ copy and change the config file to configure Nginx:
``` shell
cp nginx.conf /etc/nginx/sites-available/example.com
# don't forget to change it !!
-ln /etc/nginx/sites-available/example.com /etc/nginx/sites-enabled
+ln -s /etc/nginx/sites-available/example.com /etc/nginx/sites-enabled
```
restart `nginx.service`
### Running
@@ -88,6 +88,6 @@ now you can run it !
## LICENSE
*(&%&^*&(*&%*^(&)))
-
+[![License](https://img.shields.io/github/license/ravachol-yang/randomology?style=for-the-badge)](https://github.com/ravachol-yang/randomology/blob/master/LICENSE)
diff --git a/app/handlers/audio_handler.py b/app/handlers/audio_handler.py
index 6b64746..aa92f09 100644
--- a/app/handlers/audio_handler.py
+++ b/app/handlers/audio_handler.py
@@ -3,35 +3,23 @@
from telebot import TeleBot
from telebot.types import Message
-from app.services.audio_service import generate_random_noise
-from app.services.audio_service import generate_random_sine
-from app.services.audio_service import generate_random_mix
-from app.services.audio_service import generate_random_voice
+from app.models.audio import Audio
+from app.models.voice import Voice
-# invoke with "/noise" command
-def get_random_noise(message: Message, bot: TeleBot):
+# invoke with "/audio" command
+def get_random_audio(message: Message, bot: TeleBot, data: dict):
# pretend to be uploading audio
bot.send_chat_action(message.chat.id, "upload_voice")
- noise = generate_random_noise()
- bot.send_audio(message.chat.id, noise)
+ options = data['options']
-# invoke with "/sine" command
-def get_random_sine(message: Message, bot: TeleBot):
- # uploading audio...
- bot.send_chat_action(message.chat.id, "upload_voice")
- sine = generate_random_sine()
- bot.send_audio(message.chat.id, sine)
-
-# invoke with "/mix" command
-def get_random_mix(message: Message, bot: TeleBot):
- # uploading audio...
- bot.send_chat_action(message.chat.id, "upload_voice")
- mix = generate_random_mix()
- bot.send_audio(message.chat.id, mix)
+ audio = Audio(bot, message)
+ audio.generate(options).to_mpeg().send()
# invoke with "/voice" command
-def get_random_voice(message: Message, bot: TeleBot):
+def get_random_voice(message: Message, bot: TeleBot, data: dict):
# pretend to be sending voice
bot.send_chat_action(message.chat.id, "record_voice")
- voice = generate_random_voice()
- bot.send_voice(message.chat.id, voice)
+ options = data['options']
+
+ voice = Voice(bot, message)
+ voice.generate(options).to_voice().send()
diff --git a/app/handlers/info_handler.py b/app/handlers/info_handler.py
index 18e728e..9f9495b 100644
--- a/app/handlers/info_handler.py
+++ b/app/handlers/info_handler.py
@@ -3,10 +3,16 @@
from telebot import TeleBot
from telebot.types import Message
-from app.services.info_service import generate_info
+from app.models.text import Text
+from configs import templates
def get_info(message: Message, bot: TeleBot):
+ bot.send_chat_action(message.chat.id, "typing")
+
name = message.from_user.first_name
id = message.from_user.id
- info = generate_info(name, id)
- bot.send_message(message.chat.id, info, parse_mode="MarkdownV2")
+
+ text = Text(bot, message)
+ text.set_content(templates.INFO_MESSAGE.format(name=name, id=id))
+
+ text.send(parse_mode="MarkdownV2")
diff --git a/app/handlers/inline_handler.py b/app/handlers/inline_handler.py
index 90026b5..f056b19 100644
--- a/app/handlers/inline_handler.py
+++ b/app/handlers/inline_handler.py
@@ -3,16 +3,26 @@
from telebot import TeleBot
from telebot import types
-from app.services.text_service import generate_random_text
-from app.services.audio_service import generate_random_mix
+from app.models.text import Text
+from app.models.voice import Voice
-def inline_dispatch(inline_query, bot: TeleBot):
+def inline_text(inline_query, bot: TeleBot, data:dict):
+ options = data['options']
+ text = Text()
+ voice = Voice()
try:
- text = types.InlineQueryResultArticle('1', 'Random Text',
- types.InputTextMessageContent(generate_random_text()))
- audio = types.InlineQueryResultArticle('2',
- 'TODO',
- types.InputTextMessageContent("TODO"))
- bot.answer_inline_query(inline_query.id, [text, audio], cache_time=0)
+ text = types.InlineQueryResultArticle('2', 'Random Text',
+ types.InputTextMessageContent(text.generate(options).content()))
+ bot.answer_inline_query(inline_query.id, [text], cache_time=0)
+ except Exception as e:
+ print(e)
+
+def inline_voice(inline_query, bot:TeleBot, data:dict):
+ options = data['options']
+ voice = Voice().generate(options).to_voice().content()
+ try:
+ voice = types.InlineQueryResultVoice('3', title = 'Random Voice',
+ voice_url=voice)
+ bot.answer_inline_query(inline_query.id, [voice], cache_time=0)
except Exception as e:
print(e)
diff --git a/app/handlers/member_handler.py b/app/handlers/member_handler.py
index cd70a3e..7454e91 100644
--- a/app/handlers/member_handler.py
+++ b/app/handlers/member_handler.py
@@ -3,12 +3,18 @@
from telebot import TeleBot
from telebot.types import Message
-from app.services.member_service import generate_welcome
+from app.models.text import Text
+from configs import templates
# invoke when new member joins
def get_welcome(message:Message, bot:TeleBot):
# typing ...
+ print("welcome")
bot.send_chat_action(message.chat.id, "typing")
new_member = message.new_chat_members
- welcome = generate_welcome(new_member[0].first_name, new_member[0].id)
- bot.send_message(message.chat.id, welcome, parse_mode="MarkdownV2")
+ welcome = templates.WELCOME_MESSAGE.format(name=new_member[0].first_name,
+ id=new_member[0].id)
+ text = Text(bot, message)
+ text.set_content(welcome)
+ text.send(parse_mode="MarkdownV2")
+
diff --git a/app/handlers/text_handler.py b/app/handlers/text_handler.py
index 24cdf6e..4a65e18 100644
--- a/app/handlers/text_handler.py
+++ b/app/handlers/text_handler.py
@@ -2,23 +2,25 @@
from telebot import TeleBot
from telebot.types import Message
-from app.services.text_service import generate_random_text
-import string
+from app.models.text import Text
-SPECIAL = ['_', '*', '[', ']', '(', ')', '~', '`', '<' , '>', '#', '+', '-', '=', '|', '{', '}', '.', '!' ]
-
-# invoke with "/random" command
-def get_random_text(message: Message, bot: TeleBot):
+# invoke with "/text" command
+def get_random_text(message: Message, bot: TeleBot, data:dict):
# pretend to be typing
bot.send_chat_action(message.chat.id, "typing")
- bot.send_message(message.chat.id, generate_random_text())
+ # get options from message
+ options = data['options']
+
+ text = Text(bot, message)
+ text.generate(options).send()
-# invoke with "/random_mono"
-def get_random_text_mono(message: Message, bot: TeleBot):
+# invoke with "/mono"
+def get_random_text_mono(message: Message, bot: TeleBot, data:dict):
# pretend to be typing
bot.send_chat_action(message.chat.id, "typing")
- text = generate_random_text()
- # add an "\" before every special char for parsing markdown
- for i in SPECIAL:
- text = text.replace(i, "\\"+i)
- bot.send_message(message.chat.id, "`"+text+"`", parse_mode="MarkdownV2")
+
+ options = data['options']
+
+ mono = Text(bot, message)
+ mono.generate(options)
+ mono.to_mono().send(parse_mode="MarkdownV2")
diff --git a/app/middlewares/option_middleware.py b/app/middlewares/option_middleware.py
new file mode 100644
index 0000000..e0f8719
--- /dev/null
+++ b/app/middlewares/option_middleware.py
@@ -0,0 +1,37 @@
+from telebot import TeleBot
+from telebot.handler_backends import BaseMiddleware
+from telebot.types import InlineQuery
+from telebot.types import Message
+
+class OptionMiddleware(BaseMiddleware):
+ def __init__(self):
+ self.update_types = ['message', 'inline_query']
+
+ def pre_process(self, message, data):
+
+ # if it's an inline query
+ if isinstance(message, InlineQuery):
+ msg_text = message.query
+ if msg_text == "":
+ msg_text = "*"
+ if msg_text[0] == '/':
+ options = msg_text.split(" ",1)
+ options.pop(0)
+ else:
+ options = [msg_text]
+
+ # if it's a message
+ elif isinstance(message, Message):
+ msg_text = message.text
+ options = msg_text.split(" ",1)
+ options.pop(0)
+
+ if options:
+ # remove spaces and make options list
+ options = options[0].replace(" ","")
+ options = options.split(",")
+
+ data['options'] = options
+
+ def post_process(self, message, data, exception=None):
+ pass
diff --git a/app/services/__init__.py b/app/models/__init__.py
similarity index 100%
rename from app/services/__init__.py
rename to app/models/__init__.py
diff --git a/app/models/audio.py b/app/models/audio.py
new file mode 100644
index 0000000..a711474
--- /dev/null
+++ b/app/models/audio.py
@@ -0,0 +1,139 @@
+"""
+audio.py
+the model for audio messages
+"""
+import wave
+import random
+import struct
+import uuid
+import math
+import ffmpeg
+
+from app.models.base import Base
+from app.models.msg_type import MsgType
+
+from configs import dirs
+from configs import env
+
+class Audio(Base):
+
+ MSG_TYPE:str = MsgType.AUDIO
+
+ HOST_PREFIX = "https://{}:{}".format(env.WEBHOOK_HOST, env.WEBHOOK_PORT)
+
+ SAMPLE_RATE = 8000
+ FREQ_HIGH = 800
+ FREQ_LOW = 200
+ VOLUME_HIGH = 0.6
+ VOLUME_LOW = 0.3
+
+ OPTIONS_AVAILABLE = ['sine', 'noise']
+ OPTIONS_DEFAULT = {
+ "sine": True,
+ "noise": False
+ }
+
+ # generate a noise sample
+ @staticmethod
+ def noise_sample():
+ sample = random.randint(-32768, 32767)
+ sample_packed = struct.pack('h', sample)
+ return sample_packed
+
+ # generate a sine sample
+ @staticmethod
+ def sine_sample(freq, volume, x):
+ value = volume * math.sin(2 * math.pi * freq * (x / Audio.SAMPLE_RATE))
+ sample = int(value * 32767.0)
+ return struct.pack('h', sample)
+
+ # mix up according to options
+ def _mix_up(self, len):
+ values = []
+ for i in range(0, len):
+ if self._options['sine']:
+ # two channels
+ freq_channel_1 = random.randint(Audio.FREQ_LOW, Audio.FREQ_HIGH)
+ freq_channel_2 = random.randint(Audio.FREQ_LOW, Audio.FREQ_HIGH)
+ #volume
+ volume_channel_1 = random.uniform(Audio.VOLUME_LOW, Audio.VOLUME_HIGH)
+ volume_channel_2 = random.uniform(Audio.VOLUME_LOW, Audio.VOLUME_HIGH)
+ # build the chunk
+ # duration of every chunk
+ chunk_duration = random.randint(1, 3)
+ for x in range(0, chunk_duration * Audio.SAMPLE_RATE):
+ if self._options['sine']:
+ sine_channel_1 = Audio.sine_sample(freq_channel_1, volume_channel_1, x)
+ sine_channel_2 = Audio.sine_sample(freq_channel_2, volume_channel_2, x)
+ if self._options['noise']:
+ noise_channel_1 = Audio.noise_sample()
+ noise_channel_2 = Audio.noise_sample()
+
+ # build into values
+ if self._options['sine'] and self._options['noise']:
+ values.append(random.choice([sine_channel_1, noise_channel_1]))
+ values.append(random.choice([sine_channel_2, noise_channel_2]))
+ elif self._options['sine'] and not self._options['noise']:
+ values.append(sine_channel_1)
+ values.append(sine_channel_2)
+ elif self._options['noise'] and not self._options['sine']:
+ values.append(noise_channel_1)
+ values.append(noise_channel_2)
+
+ # make a byte string
+ values_str = b''.join(values)
+ return values_str
+
+ # generate an audio
+ def generate(self, options=None):
+ name = uuid.uuid4().hex
+ # add prefix to file name
+ name_prefix = "/sine-"
+ # set options
+ self._options = dict(Audio.OPTIONS_DEFAULT)
+ if options and not options == ['']:
+ name_prefix = "/"
+ self._options = dict.fromkeys(Audio.OPTIONS_AVAILABLE, False)
+ for option in options:
+ if option in Audio.OPTIONS_AVAILABLE:
+ self._options[option] = True
+ name_prefix = name_prefix + option + "-"
+
+ # if options are empty now, return to default
+ if self._options == dict.fromkeys(Audio.OPTIONS_AVAILABLE, False):
+ self._options = dict(Audio.OPTIONS_DEFAULT)
+ name_prefix += "sine-"
+
+ self._filename = name_prefix+name+".wav"
+ self._filepath = dirs.AUDIO_DIR+self._filename
+ # open the audio file
+ audio = wave.open(self._filepath, "wb")
+ audio.setparams((2, 2, 24000, 0, 'NONE', 'not compressed'))
+
+ # generate random length
+ len = random.randint(8, 10)
+
+ values_str = self._mix_up(len)
+
+ audio.writeframes(values_str)
+ audio.close()
+
+ self._content = Audio.HOST_PREFIX+"/storage/audio"+self._filename
+
+ return self
+
+ # convert to mpeg for telegran server to download
+ def to_mpeg(self):
+ wavfile = self._filepath
+ mpegfile_name = self._filename+".mp3"
+ mpegfile = dirs.AUDIO_DIR + mpegfile_name
+ (
+ ffmpeg
+ .input(wavfile, format="wav")
+ .output(mpegfile)
+ .run()
+ )
+ self._filename = mpegfile_name
+ self._filepath = dirs.AUDIO_DIR+self._filename
+ self._content = Audio.HOST_PREFIX+"/storage/audio"+self._filename
+ return self
diff --git a/app/models/base.py b/app/models/base.py
new file mode 100644
index 0000000..476801a
--- /dev/null
+++ b/app/models/base.py
@@ -0,0 +1,33 @@
+"""
+base.py
+the Base model
+"""
+
+from telebot import TeleBot
+from telebot.types import Message
+
+class Base:
+
+ def __init__(self,
+ bot:TeleBot = None,
+ message:Message = None):
+ self.__bot = bot
+ self.__message = message
+
+
+ # get content of this object
+ def content(self):
+ return self._content
+
+ # set content
+ def set_content(self, content:str):
+ self._content = content
+
+ # generate content
+ def generate(self):
+ raise NotImplementedError
+
+ # send the message
+ def send(self, **kwargs):
+ send_me = getattr(self.__bot, "send_"+self.MSG_TYPE)
+ send_me(self.__message.chat.id, self._content, **kwargs)
diff --git a/app/models/msg_type.py b/app/models/msg_type.py
new file mode 100644
index 0000000..79e4939
--- /dev/null
+++ b/app/models/msg_type.py
@@ -0,0 +1,10 @@
+"""
+msg_type.py
+enum for message types
+"""
+from enum import Enum
+
+class MsgType(str, Enum):
+ TEXT:str = "message"
+ AUDIO:str = "audio"
+ VOICE:str = "voice"
diff --git a/app/models/text.py b/app/models/text.py
new file mode 100644
index 0000000..7b1bf2e
--- /dev/null
+++ b/app/models/text.py
@@ -0,0 +1,104 @@
+"""
+text.py
+the model for text messages
+"""
+
+import random
+import string
+
+from app.models.base import Base
+from app.models.msg_type import MsgType
+
+class Text(Base):
+
+ # type of this object ("message")
+ MSG_TYPE:str = MsgType.TEXT
+
+ # special chars to be backslashed in mono
+ SPECIAL = ['_', '*', '[', ']',
+ '(', ')', '~', '`',
+ '<', '>', '#', '+',
+ '-', '=', '|', '{',
+ '}', '.', '!']
+
+ OPTIONS_AVAILABLE = ['en', 'zh', 'punc','d']
+ OPTIONS_DEFAULT = {
+ "en": True,
+ "zh": False,
+ "punc": True,
+ "d": True,
+ }
+
+ # generate random string, returns the object itself
+ def generate(self, options = None):
+
+ # set default options
+ self._options = dict(Text.OPTIONS_DEFAULT)
+
+ # if option not nothing
+ if options and not options == ['']:
+ option_bodies = []
+ # check each option in options
+ for option in options:
+ # if the option is empty, we see it as setting all others false
+ if option == '':
+ for i in Text.OPTIONS_AVAILABLE:
+ if i not in option_bodies:
+ self._options[i] = False
+ # if the option is not empty
+ else:
+ # get option body without "+" or "-"
+ if option[0] == "+" or option[0] == "-":
+ option_body = option.replace(option[0],"",1)
+ option_bodies.append(option_body)
+ else:
+ # if option has no operator, it is "+"
+ option_body = option
+ option_bodies.append(option_body)
+ if option_body in Text.OPTIONS_AVAILABLE:
+ if option[0] == '-':
+ self._options[option_body] = False
+ else:
+ self._options[option_body] = True
+
+ # make choice string
+ choices_string = ""
+
+ # add strings for each options
+ if self._options["en"]:
+ choices_string += string.ascii_letters
+
+ if self._options["zh"]:
+ zh_string = ""
+ # generate a Chinese string of 30 chars
+ for i in range(0,30):
+ zh_string += chr(random.randint(0x4e00, 0xa000))
+ choices_string += zh_string
+
+ if self._options["punc"]:
+ choices_string += string.punctuation
+
+ if self._options["d"]:
+ choices_string += string.digits
+
+ # if the string is empty, return random *s
+ if not choices_string:
+ choices_string = "*"
+
+ # generate random string
+ length = random.randint(30,120)
+ self._content = ''.join(random.choices(choices_string, k = length))
+
+ return self
+
+ # convert to mono for markdown parsing
+ def to_mono(self):
+ # if there is no puncs, no need to check
+ if self._options['punc']:
+ # add a "\" before every special char
+ for i in Text.SPECIAL:
+ self._content = self._content.replace(i,"\\"+i)
+ # add ` ` around to parse to mono
+ self._content = "` "+self._content+" `"
+ return self
+
diff --git a/app/models/voice.py b/app/models/voice.py
new file mode 100644
index 0000000..1ced845
--- /dev/null
+++ b/app/models/voice.py
@@ -0,0 +1,30 @@
+"""
+voice.py
+"""
+
+import ffmpeg
+
+from app.models.audio import Audio
+from app.models.msg_type import MsgType
+
+from configs import dirs
+
+class Voice(Audio):
+
+ MSG_TYPE:str = MsgType.VOICE
+
+ def to_voice(self):
+ wavfile = self._filepath
+ oggfile_name = self._filename+".ogg"
+ oggfile = dirs.AUDIO_DIR + oggfile_name
+ (
+ ffmpeg
+ .input(wavfile, format="wav")
+ .output(oggfile, acodec = "libopus")
+ .run()
+ )
+ self._filename = oggfile_name
+ self._filepath = dirs.AUDIO_DIR+self._filename
+ self._content = Voice.HOST_PREFIX+"/storage/audio"+self._filename
+
+ return self
diff --git a/app/services/audio_service.py b/app/services/audio_service.py
deleted file mode 100644
index 6b0f697..0000000
--- a/app/services/audio_service.py
+++ /dev/null
@@ -1,141 +0,0 @@
-# audio_service
-# TODO: ugly code !!!!
-
-import wave
-import random
-import struct
-import uuid
-import ffmpeg
-import math
-
-from configs import dirs
-
-SAMPLE_RATE = 8000
-FREQ_HIGH = 800
-FREQ_LOW = 20
-VOLUME_HIGH = 0.7
-VOLUME_LOW = 0.3
-
-# generate a noise sample
-def noise_sample():
- sample = random.randint(-32768, 32767)
- sample_packed = struct.pack('h', sample)
- return sample_packed
-
-# generate a sine wave sample
-def sine_sample(freq, volume, x):
- value = volume * math.sin(2 * math.pi * freq * (x / SAMPLE_RATE))
- sample = int(value * 32767.0)
- return struct.pack('h', sample)
-
-# Generate a noise
-def generate_random_noise():
- name = uuid.uuid4().hex
- audio_path = dirs.AUDIO_DIR+"/noise_"+name+".wav"
- audio = wave.open(audio_path, "wb")
- audio.setparams((2, 2, 24000, 0, 'NONE', 'not compressed'))
- len = random.randint(20, 60)
- values = []
- # build the noise
- for i in range(0, len):
- channel_1 = noise_sample()
- channel_2 = noise_sample()
- chunk_duration = random.randint(1000, 10000)
- for j in range(0, chunk_duration):
- values.append(channel_1)
- values.append(channel_2)
-
- # make a byte string
- values_str = b''.join(values)
- audio.writeframes(values_str)
- audio.close()
- return open(audio_path, "rb")
-
-# Generate a sine wave audio
-def generate_random_sine():
- name = uuid.uuid4().hex
- audio_path = dirs.AUDIO_DIR+"/sine_"+name+".wav"
- audio = wave.open(audio_path, "wb")
- audio.setparams((2, 2, 24000, 0, 'NONE', 'not compressed'))
-
- values = []
-
- len = random.randint(8, 10)
- for i in range(0, len):
- freq = random.randint(FREQ_LOW, FREQ_HIGH)
- chunk_duration = random.randint(1, 2)
- volume = random.uniform(VOLUME_LOW, VOLUME_HIGH)
- for x in range(0, chunk_duration * SAMPLE_RATE):
- sine = sine_sample(freq, volume, x)
- values.append(sine)
- values.append(sine)
-
- values_str = b''.join(values)
- audio.writeframes(values_str)
- audio.close
- return open(audio_path, "rb")
-
-
-# Generate random audio in .wav
-def generate_random_mix():
- # filename
- name = uuid.uuid4().hex
- audio_path = dirs.AUDIO_DIR+"/mix_"+name+".wav"
- # open file in write mode
- audio = wave.open(audio_path, "wb")
- audio.setparams((2, 2, 24000, 0, 'NONE', 'not compressed'))
-
- values = []
-
- len = random.randint(8, 10)
-
- # generate a mix of sine wave and noise
- for i in range(0, len):
- # two channels
- freq_channel_1 = random.randint(FREQ_LOW, FREQ_HIGH)
- freq_channel_2 = random.randint(FREQ_LOW, FREQ_HIGH)
- # duration of every chunk in seconds
- chunk_duration = random.randint(1, 2)
- # volume
- volume_channel_1 = random.uniform(VOLUME_LOW, VOLUME_HIGH)
- volume_channel_2 = random.uniform(VOLUME_LOW, VOLUME_HIGH)
- # build the chunk
- for x in range(0, chunk_duration * SAMPLE_RATE):
- sine_channel_1 = sine_sample(freq_channel_1, volume_channel_1, x)
- sine_channel_2 = sine_sample(freq_channel_2, volume_channel_2, x)
- noise = noise_sample()
- # channel 1
- if random.choice([True, False]):
- values.append(sine_channel_1)
- else:
- values.append(noise)
- # channel 2
- if random.choice([True, False]):
- values.append(sine_channel_2)
- else:
- values.append(noise)
-
- # make a byte string
- values_str = b''.join(values)
- # write into the file
- audio.writeframes(values_str)
- # close
- audio.close()
-
- return open(audio_path, "rb")
-
-# generate random voice in .ogg by converting .wav file
-def generate_random_voice():
- # generate a random wav file
- wavfile = generate_random_mix()
- # file name of the generated .ogg
- oggfile = wavfile.name+".ogg"
- # convert with ffmpeg
- (
- ffmpeg
- .input(wavfile.name, format="wav")
- .output(oggfile, acodec = "libopus")
- .run()
- )
-
- return open(oggfile, "rb")
diff --git a/app/services/info_service.py b/app/services/info_service.py
deleted file mode 100644
index 88a683c..0000000
--- a/app/services/info_service.py
+++ /dev/null
@@ -1,7 +0,0 @@
-# info_service.py
-
-from configs import templates
-
-# generate info
-def generate_info(name, id):
- return templates.INFO_MESSAGE.format(name=name, id=id)
diff --git a/app/services/member_service.py b/app/services/member_service.py
deleted file mode 100644
index 24243e9..0000000
--- a/app/services/member_service.py
+++ /dev/null
@@ -1,7 +0,0 @@
-# member_service.py
-
-from configs import templates
-
-# generate welcome message
-def generate_welcome(name, id):
- return templates.WELCOME_MESSAGE.format(name=name, id=id)
diff --git a/app/services/text_service.py b/app/services/text_service.py
deleted file mode 100644
index 614acd5..0000000
--- a/app/services/text_service.py
+++ /dev/null
@@ -1,11 +0,0 @@
-# text_service.py
-
-import random
-import string
-
-# random text generater for the following handlers
-def generate_random_text():
- length = random.randint(30,120)
- return ''.join(random.choices(string.ascii_letters +
- string.digits +
- string.punctuation, k=length))
diff --git a/bot.py b/bot.py
index 5b09d77..2adb395 100644
--- a/bot.py
+++ b/bot.py
@@ -1,10 +1,9 @@
# the randomology telegram bot
# config
-from configs import env
-
from routes import commands
from routes import handlers
+from app.middlewares.option_middleware import OptionMiddleware
from configs import env
@@ -16,7 +15,7 @@
import telebot
# bot initialize
-bot = telebot.TeleBot(env.BOT_TOKEN)
+bot = telebot.TeleBot(env.BOT_TOKEN, use_class_middlewares=True)
# register commands
commands.register(bot)
@@ -24,6 +23,9 @@
# register handlers
handlers.register(bot)
+# Setup middlewares
+bot.setup_middleware(OptionMiddleware())
+
# here we go !!!
if env.BOT_ENVIRONMENT == "prod":
server.run(bot)
diff --git a/configs/dirs.py b/configs/dirs.py
index f934b23..3ed2099 100644
--- a/configs/dirs.py
+++ b/configs/dirs.py
@@ -4,7 +4,8 @@
ROOT_DIR = os.path.dirname(os.path.dirname(__file__))
STORAGE_DIR = os.path.join(ROOT_DIR, "storage")
-AUDIO_DIR = os.path.join(STORAGE_DIR, "audio")
+STORAGE_PUBLIC_DIR = os.path.join(STORAGE_DIR, "public")
+AUDIO_DIR = os.path.join(STORAGE_PUBLIC_DIR, "audio")
PUBLIC_DIR = os.path.join(ROOT_DIR, "public")
PUBLIC_STORAGE_DIR = os.path.join(PUBLIC_DIR, "storage")
diff --git a/link_storage.sh b/link_storage.sh
index 0aa8ed2..b5a4d3a 100755
--- a/link_storage.sh
+++ b/link_storage.sh
@@ -1,6 +1,6 @@
#!/bin/bash
-FROM=$(pwd)/storage
+FROM=$(pwd)/storage/public
TO=$(pwd)/public/storage
if [[ $1 == "remove" ]]; then
diff --git a/routes/commands.py b/routes/commands.py
index 596aaee..44cb7dd 100644
--- a/routes/commands.py
+++ b/routes/commands.py
@@ -10,8 +10,6 @@ def register(bot:TeleBot):
telebot.types.BotCommand("help", "Get info"),
telebot.types.BotCommand("text", "Random text"),
telebot.types.BotCommand("mono", "Monospace random text"),
- telebot.types.BotCommand("noise", "Random noise"),
- telebot.types.BotCommand("sine", "Random sine wave audio"),
- telebot.types.BotCommand("mix", "Random mix"),
+ telebot.types.BotCommand("audio", "Random audio"),
telebot.types.BotCommand("voice", "Random voice")
])
diff --git a/routes/handlers.py b/routes/handlers.py
index e2f7c3a..4748944 100644
--- a/routes/handlers.py
+++ b/routes/handlers.py
@@ -6,12 +6,11 @@
from app.handlers.info_handler import get_info
from app.handlers.text_handler import get_random_text
from app.handlers.text_handler import get_random_text_mono
-from app.handlers.audio_handler import get_random_noise
-from app.handlers.audio_handler import get_random_sine
-from app.handlers.audio_handler import get_random_mix
+from app.handlers.audio_handler import get_random_audio
from app.handlers.audio_handler import get_random_voice
from app.handlers.member_handler import get_welcome
-from app.handlers.inline_handler import inline_dispatch
+from app.handlers.inline_handler import inline_text
+from app.handlers.inline_handler import inline_voice
# register handlers in chats
def register(bot:TeleBot):
@@ -20,12 +19,11 @@ def register(bot:TeleBot):
bot.register_message_handler(get_random_text, commands=['text'], pass_bot=True)
bot.register_message_handler(get_random_text_mono, commands=['mono'], pass_bot=True)
# random audio
- bot.register_message_handler(get_random_noise, commands=['noise'], pass_bot=True)
- bot.register_message_handler(get_random_sine, commands=['sine'], pass_bot=True)
- bot.register_message_handler(get_random_mix, commands=['mix'], pass_bot=True)
+ bot.register_message_handler(get_random_audio, commands=['audio'], pass_bot=True)
# random voice (a mix of noise and sine wave sent as voice)
bot.register_message_handler(get_random_voice, commands=['voice'], pass_bot=True)
# chat member change
- bot.register_message_handler(get_welcome, content_types=['new_chat_members'], pass_bot=True)
+ # bot.register_message_handler(get_welcome, content_types=['new_chat_members'], pass_bot=True)
# inline
- bot.register_inline_handler(inline_dispatch, lambda query: query, pass_bot=True)
+ bot.register_inline_handler(inline_voice, lambda query: query.query.split(" ",1)[0] == "/v", pass_bot=True)
+ bot.register_inline_handler(inline_text, lambda query: query , pass_bot=True)
diff --git a/storage/audio/.gitignore b/storage/public/audio/.gitignore
similarity index 100%
rename from storage/audio/.gitignore
rename to storage/public/audio/.gitignore
diff --git a/tests/audio_test.py b/tests/audio_test.py
index eb9aec6..adaffe4 100644
--- a/tests/audio_test.py
+++ b/tests/audio_test.py
@@ -1,24 +1,29 @@
# audio tests
-import io
+from app.models.audio import Audio
-from app.services.audio_service import generate_random_noise
-from app.services.audio_service import generate_random_sine
-from app.services.audio_service import generate_random_mix
-from app.services.audio_service import generate_random_voice
+def test_audio_generated():
+ audio = Audio()
+ assert isinstance(audio.generate(), Audio)
-def test_noise_generated():
- noise = generate_random_noise()
- assert isinstance(noise, io.BufferedIOBase)
+def test_audio_noise():
+ audio = Audio()
+ assert isinstance(audio.generate(options = ['noise']), Audio)
-def test_sine_generated():
- sine = generate_random_sine()
- assert isinstance(sine, io.BufferedIOBase)
+def test_audio_mix():
+ audio = Audio()
+ assert isinstance(audio.generate(options = ['noise', 'sine']), Audio)
-def test_mix_generated():
- mix = generate_random_mix()
- assert isinstance(mix, io.BufferedIOBase)
+def test_audio_wrong_options():
+ audio = Audio()
+ assert isinstance(audio.generate(options = ['aa']), Audio)
-def test_voice_generated():
- voice = generate_random_voice()
- assert isinstance(voice, io.BufferedIOBase)
+def test_audio_empty_options():
+ audio = Audio()
+ assert isinstance(audio.generate(options = ['']), Audio)
+
+def test_audio_to_mpeg():
+ audio = Audio()
+ audio.generate()
+ mpeg = audio.to_mpeg()
+ assert isinstance(mpeg, Audio)
diff --git a/tests/info_test.py b/tests/info_test.py
deleted file mode 100644
index 743f524..0000000
--- a/tests/info_test.py
+++ /dev/null
@@ -1,11 +0,0 @@
-# info_test.py
-
-from app.services.info_service import generate_info
-from configs import templates
-
-def test_welcome_template():
- assert isinstance(templates.INFO_MESSAGE, str)
-
-def test_info_generated():
- info = generate_info("test", 111)
- assert isinstance(info, str)
diff --git a/tests/member_test.py b/tests/member_test.py
deleted file mode 100644
index 05fc5a8..0000000
--- a/tests/member_test.py
+++ /dev/null
@@ -1,11 +0,0 @@
-# member tests
-
-from app.services.member_service import generate_welcome
-from configs import templates
-
-def test_welcome_template():
- assert isinstance(templates.WELCOME_MESSAGE, str)
-
-def test_welcome_generated():
- welcome = generate_welcome("test",111)
- assert isinstance(welcome, str)
diff --git a/tests/text_test.py b/tests/text_test.py
index ecfb26a..6da578b 100644
--- a/tests/text_test.py
+++ b/tests/text_test.py
@@ -1,11 +1,43 @@
# text tests
-from app.services.text_service import generate_random_text
+from app.models.text import Text
+from configs import templates
def test_text_generated():
- text = generate_random_text()
- assert isinstance(text, str)
+ text = Text()
+ assert isinstance(text.generate().content(),str)
-def test_text_length():
- text = generate_random_text()
- assert len(text) >= 30 and len(text) <= 120
+def test_text_options():
+ text = Text()
+ text.generate(options = ['zh','+en', '-d'])
+ assert isinstance(text.content(),str)
+
+def test_text_option_only():
+ text = Text()
+ text.generate(options = ['en', ''])
+ assert isinstance(text.content(),str) and text.content().isascii()
+
+def test_text_wrong_options():
+ text = Text()
+ text.generate(options = ['aaa'])
+ assert isinstance(text.content(),str) and text.content().isascii()
+
+def test_text_empty_options():
+ text = Text()
+ text.generate(options = [''])
+ assert isinstance(text.content(),str) and text.content().isascii()
+
+
+def test_text_mono():
+ text = Text()
+ text.generate()
+ text.to_mono()
+ assert isinstance(text.content(),str) and (text.content()[0]=="`") and (text.content()[-1]=="`")
+
+def test_get_welcome():
+ welcome = templates.WELCOME_MESSAGE
+ assert isinstance(welcome, str)
+
+def test_get_info():
+ info = templates.INFO_MESSAGE
+ assert isinstance(info, str)
diff --git a/tests/voice_test.py b/tests/voice_test.py
new file mode 100644
index 0000000..100e25f
--- /dev/null
+++ b/tests/voice_test.py
@@ -0,0 +1,11 @@
+# voice tests
+
+from app.models.voice import Voice
+
+def test_voice_generated():
+ voice = Voice()
+ assert isinstance(voice.generate().to_voice(), Voice)
+
+def test_voice_noise():
+ voice = Voice()
+ assert isinstance(voice.generate(options = ['noise']).to_voice(), Voice)