Skip to content

Commit

Permalink
Merge pull request #103 from F33RNI/next
Browse files Browse the repository at this point in the history
Next
  • Loading branch information
F33RNI authored Dec 10, 2023
2 parents d85609e + 6217be6 commit ffefc1e
Show file tree
Hide file tree
Showing 5 changed files with 130 additions and 61 deletions.
112 changes: 67 additions & 45 deletions BotHandler.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
"""
Copyright (C) 2022 Fern Lane, GPT-Telegramus
Copyright (C) 2022-2023 Fern Lane, GPT-Telegramus
Licensed under the GNU Affero General Public License, Version 3.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
Expand Down Expand Up @@ -28,7 +28,7 @@
import md2tgmd
import telegram
from telegram import Update, InlineKeyboardButton, InlineKeyboardMarkup, InputMediaPhoto, InputMediaAudio, \
InputMediaDocument, InputMediaVideo
InputMediaDocument, InputMediaVideo, BotCommand
from telegram.ext import ApplicationBuilder, ContextTypes, CommandHandler, MessageHandler, filters, CallbackQueryHandler
import requests

Expand Down Expand Up @@ -238,9 +238,9 @@ async def parse_img(img_source: str):
"""
try:
res = requests.head(img_source, timeout=10, headers={
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; WOW64) "
"AppleWebKit/537.36 (KHTML, like Gecko) "
"Chrome/91.4472.114 Safari/537.36"})
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; WOW64) "
"AppleWebKit/537.36 (KHTML, like Gecko) "
"Chrome/91.4472.114 Safari/537.36"})
if res.headers.get("content-type") == "image/svg+xml":
raise Exception("SVG Image")
except Exception as e:
Expand All @@ -264,9 +264,7 @@ async def _send_text_async_split(config: dict,
# Send all parts of message
response_part_counter_init = request_response.response_part_counter
images = [img for img in
(await asyncio.gather(*[parse_img(img)
for img in request_response.response_images]))
if img is not None]
(await asyncio.gather(*[parse_img(img) for img in request_response.response_images])) if img is not None]
while True:
# Get current part of response (text)
if request_response.response:
Expand Down Expand Up @@ -444,10 +442,10 @@ async def send_photo(api_key: str, chat_id: int, photo, caption: str | None,


async def send_media_group(api_key: str,
chat_id: int,
media: Sequence[InputMediaAudio | InputMediaDocument | InputMediaPhoto | InputMediaVideo],
chat_id: int,
media: Sequence[InputMediaAudio | InputMediaDocument | InputMediaPhoto | InputMediaVideo],
caption: str,
reply_to_message_id: int | None,
reply_to_message_id: int | None,
markdown=False):
"""
Sends photo to chat
Expand Down Expand Up @@ -596,19 +594,38 @@ def start_bot(self):
Starts bot (blocking)
:return:
"""
# Start response_loop as thread
# self._response_loop_thread = threading.Thread(target=self._response_loop)
# self._response_loop_thread.start()
# logging.info("response_loop thread: {0}".format(self._response_loop_thread.name))

# Start telegram bot polling
logging.info("Starting telegram bot")
while True:
try:
# Close previous event loop
try:
loop = asyncio.get_running_loop()
if loop and loop.is_running():
logging.info("Stopping current event loop before starting a new one")
loop.stop()
except Exception as e:
logging.warning("Error stopping current event loop: {}".format(str(e)))

# Create new event loop
logging.info("Creating new event loop")
self._event_loop = asyncio.new_event_loop()
asyncio.set_event_loop(self._event_loop)

# Build bot
builder = ApplicationBuilder().token(self.config["telegram"]["api_key"])
self._application = builder.build()

# Set commands description
if self.config["telegram"]["commands_description_enabled"]:
try:
logging.info("Trying to set bot commands")
bot_commands = []
for command_description in self.config["telegram"]["commands_description"]:
bot_commands.append(BotCommand(command_description["command"],
command_description["description"]))
self._event_loop.run_until_complete(self._application.bot.set_my_commands(bot_commands))
except Exception as e:
logging.error("Error setting bot commands description!", exc_info=e)

# User commands
self._application.add_handler(CaptionCommandHandler(BOT_COMMAND_START, self.bot_command_start))
self._application.add_handler(CaptionCommandHandler(BOT_COMMAND_HELP, self.bot_command_help))
Expand All @@ -617,7 +634,8 @@ def start_bot(self):
self._application.add_handler(CaptionCommandHandler(BOT_COMMAND_EDGEGPT, self.bot_command_edgegpt))
self._application.add_handler(CaptionCommandHandler(BOT_COMMAND_DALLE, self.bot_command_dalle))
self._application.add_handler(CaptionCommandHandler(BOT_COMMAND_BARD, self.bot_command_bard))
self._application.add_handler(CaptionCommandHandler(BOT_COMMAND_BING_IMAGEGEN, self.bot_command_bing_imagegen))
self._application.add_handler(CaptionCommandHandler(BOT_COMMAND_BING_IMAGEGEN,
self.bot_command_bing_imagegen))
self._application.add_handler(CaptionCommandHandler(BOT_COMMAND_MODULE, self.bot_command_module))
self._application.add_handler(CaptionCommandHandler(BOT_COMMAND_STYLE, self.bot_command_style))
self._application.add_handler(CaptionCommandHandler(BOT_COMMAND_CLEAR, self.bot_command_clear))
Expand All @@ -643,14 +661,13 @@ def start_bot(self):
# Add buttons handler
self._application.add_handler(CallbackQueryHandler(self.query_callback))

# Start bot
self._event_loop = asyncio.new_event_loop()
asyncio.set_event_loop(self._event_loop)
self._event_loop.run_until_complete(self._application.run_polling())
# Start telegram bot polling
logging.info("Starting bot polling")
self._application.run_polling(close_loop=False, stop_signals=[])

# Exit requested
except KeyboardInterrupt:
logging.warning("KeyboardInterrupt @ bot_start")
except (KeyboardInterrupt, SystemExit):
logging.warning("KeyboardInterrupt or SystemExit @ bot_start")
break

# Bot error?
Expand All @@ -662,19 +679,22 @@ def start_bot(self):
else:
logging.error("Telegram bot error!", exc_info=e)

# Wait before restarting if needed
if not self._restart_requested_flag:
# Restart bot
logging.info("Restarting bot polling after {0} seconds".format(RESTART_ON_ERROR_DELAY))
try:
time.sleep(RESTART_ON_ERROR_DELAY)

# Exit requested while waiting for restart
except KeyboardInterrupt:
logging.warning("KeyboardInterrupt @ bot_start")
except (KeyboardInterrupt, SystemExit):
logging.warning("KeyboardInterrupt or SystemExit while waiting @ bot_start")
break

# Restart bot
logging.info("Restarting bot polling")
self._restart_requested_flag = False
# Restart bot or exit from loop
if self._restart_requested_flag or self.queue_handler.prevent_shutdown_flag:
logging.info("Restarting bot polling")
self._restart_requested_flag = False
else:
break

# If we're here, exit requested
logging.warning("Telegram bot stopped")
Expand Down Expand Up @@ -1072,19 +1092,20 @@ async def bot_command_restart(self, update: Update, context: ContextTypes.DEFAUL
logging.info("Starting back ProxyAutomation")
self.proxy_automation.start_automation_loop()

# Restart telegram bot
self._restart_requested_flag = True
logging.info("Stopping event loop to restart Telegram bot")
self._event_loop.stop()
time.sleep(1)
try:
logging.info("Closing event loop to restart Telegram bot")
self._event_loop.close()
except:
pass
def _restart_bot():
"""
Restart telegram bot polling and sends "Restarting done" message
:return:
"""
# Wait some time
time.sleep(1)

# Restart telegram bot
self._restart_requested_flag = True
logging.info("Stopping event loop to restart Telegram bot")
self._event_loop.stop()

def send_message_after_restart():
# Sleep while restarting
# Wait
logging.info("Waiting for _restart_requested_flag")
while self._restart_requested_flag:
time.sleep(1)
Expand All @@ -1098,7 +1119,8 @@ def send_message_after_restart():
except Exception as e:
logging.error("Error sending message!", exc_info=e)

threading.Thread(target=send_message_after_restart).start()
# Start thread that will restart bot polling
threading.Thread(target=_restart_bot, daemon=True).start()

async def bot_command_queue(self, update: Update, context: ContextTypes.DEFAULT_TYPE) -> None:
"""
Expand Down
43 changes: 31 additions & 12 deletions CaptionCommandHandler.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,31 @@
from typing import TYPE_CHECKING, List, Optional, Tuple, Union
"""
Copyright (C) 2022-2023 Fern Lane, GPT-Telegramus
Copyright (C) 2023 Hanssen
Licensed under the GNU Affero General Public License, Version 3.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
https://www.gnu.org/licenses/agpl-3.0.en.html
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR
OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE.
"""

from typing import List, Optional, Tuple, Union

from telegram import MessageEntity, Update
from telegram.ext import CommandHandler
from telegram.ext._utils.types import FilterDataDict
from telegram.ext import CommandHandler, filters


class CaptionCommandHandler(CommandHandler):
def check_update(
self, update: object
self, update: object
) -> Optional[Union[bool, Tuple[List[str], Optional[Union[bool, FilterDataDict]]]]]:
"""Determines whether an update should be passed to this handler's :attr:`callback`.
Expand All @@ -23,25 +42,25 @@ def check_update(
entities = message.entities or message.caption_entities

if (
entities
and entities[0].type == MessageEntity.BOT_COMMAND
and entities[0].offset == 0
and text
and message.get_bot()
entities
and entities[0].type == MessageEntity.BOT_COMMAND
and entities[0].offset == 0
and text
and message.get_bot()
):
command = text[1 : entities[0].length]
command = text[1: entities[0].length]
args = text.split()[1:]
command_parts = command.split("@")
command_parts.append(message.get_bot().username)

if not (
command_parts[0].lower() in self.commands
and command_parts[1].lower() == message.get_bot().username.lower()
command_parts[0].lower() in self.commands
and command_parts[1].lower() == message.get_bot().username.lower()
):
return None

filter_result = self.filters.check_update(update)
if filter_result:
return args, filter_result
return False
return None
return None
3 changes: 1 addition & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ Or message me if you would like to donate 💰
## 🤗 Contributors

- 1️⃣ [Sprav04ka](https://github.com/Sprav04ka) - *Tofii'skovyi' language, Testing, [Super beautiful DIY jack o'lantern (for poster)](Banner.png), [Project Logo](Logo.png), Motivation*
- 2️⃣ [Hanssen](https://github.com/handsome0hell) - *Markdown parsing, bard images, Chinese language, /chat command*
- 2️⃣ [Hanssen](https://github.com/handsome0hell) - *Markdown parsing, bard images, Chinese language, /chat command, caption fix*
- 3️⃣ [Sergey Krashevich](https://github.com/skrashevich) - *Docker, GitHub Actions*
- 4️⃣ [Wahit Fitriyanto](https://github.com/wahitftry) - *Indonesian language*
- 5️⃣ [Alexander Fadeyev](https://github.com/alfsoft) - *EdgeGPT Fix*
Expand Down Expand Up @@ -346,7 +346,6 @@ You can enable and configure data collection in config in `data_collecting` bloc
- Add some free GPT-4 model
- Add image input and generation for EdgeGPT (and ChatGPT?)
- Add Bard's text-to-speech
- Add list of commands
- Add an API, so you can use GPT-Telegramus from outside the bot
----------
Expand Down
31 changes: 30 additions & 1 deletion config.json
Original file line number Diff line number Diff line change
Expand Up @@ -169,7 +169,36 @@
"reply_to_messages": true,

"__comment09__": "HOW MANY SECONDS TO WAIT BETWEEN EACH MESSAGE WHEN BROADCASTING",
"broadcast_delay_per_user_seconds": 0.5
"broadcast_delay_per_user_seconds": 0.5,

"__comment10__": "BOT COMMANDS DESCRIPTION (WILL BE AUTOMATICALLY ADDED TO THE BOT)",
"commands_description_enabled": true,
"commands_description": [
{
"command": "start",
"description": "📄 Welcome message and bot version"
},
{
"command": "help",
"description": "❓ Show help message"
},
{
"command": "module",
"description": "↕ Change module to chat with"
},
{
"command": "clear",
"description": "🧹 Clear chat history"
},
{
"command": "lang",
"description": "🌎 Change the language"
},
{
"command": "chatid",
"description": "🆔 Show your chat_id"
}
]
},

"__comment08__": "FILES AND DIRECTORIES SETTINGS",
Expand Down
2 changes: 1 addition & 1 deletion main.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@
from JSONReaderWriter import load_json

# GPT-Telegramus version
__version__ = "3.6.7"
__version__ = "3.7.0"

# Logging level
LOGGING_LEVEL = logging.INFO
Expand Down

0 comments on commit ffefc1e

Please sign in to comment.