Skip to content

Commit

Permalink
v2.4.0
Browse files Browse the repository at this point in the history
  • Loading branch information
plutobell committed Dec 11, 2023
1 parent d783d1e commit f1be720
Show file tree
Hide file tree
Showing 9 changed files with 166 additions and 50 deletions.
7 changes: 7 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,12 @@
# Changelog

#### 2023-12-11

* v2.4.0
* 插件新增初始化方法 Init
* 修复bug
* 细节调整

#### 2023-11-28

* v2.3.6
Expand Down
16 changes: 14 additions & 2 deletions PLUGINGUIDE.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# 插件开发指南 (以 Hello 插件为例) v1.4
# 插件开发指南 (以 Hello 插件为例) v1.5

#### 一、插件结构

Expand Down Expand Up @@ -34,6 +34,18 @@ def Hello(bot, message):



**`v2.4.0` 及以上版本,插件引入了初始化函数 `Init(bot)`** ,参数 `bot` 为Bot接口库实例化对象。该函数类似Python类的 `__init__` 方法,在框架运行后,无论插件是否被触发,都会执行一次。**另外,插件的重装和修改都会重新触发此函数的执行。**以插件 `Hello` 的初始化函数为例:

```python
# 该函数会在框架运行后,在控制台输出字符串: Hello World!
def Init(bot):
print("Hello World!")
```





##### 资源路径

1.若要打开某个插件目录下的文件资源,可以使用方法 `path_converter` ,此方法会根据操作系统转换路径格式:
Expand Down Expand Up @@ -165,7 +177,7 @@ Summary: InlineMode插件例子
teelebot -p/--plugin <plugin name>
```

* 1.14.1 以后的版本
* **1.14.1 以后的版本**

```python
teelebot -mp/--make_plugin <plugin name>
Expand Down
12 changes: 6 additions & 6 deletions teelebot/__init__.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# -*- coding:utf-8 -*-
"""
@creation date: 2019-08-23
@last modification: 2023-07-12
@last modification: 2023-12-08
"""
import os
import requests
Expand Down Expand Up @@ -29,11 +29,11 @@

def main():
print(
" __ __ __ __ " + "\n" + \
" / /____ ___ / /__ / /_ ____ / /_ " + "\n" + \
" / __/ _ \/ _ \/ / _ \/ __ \/ __ \/ __/ " + "\n" + \
" / /_/ __/ __/ / __/ /_/ / /_/ / /_ " + "\n" + \
" \__/\___/\___/_/\___/_.___/\____/\__/ " + "\n"
" __ __ __ __ \n" +
" / /____ ___ / /__ / /_ ____ / /_ \n" +
" / __/ _ \\/ _ \\/ / _ \\/ __ \\/ __ \\/ __/ \n" +
" / /_/ __/ __/ / __/ /_/ / /_/ / /_ \n" +
" \\__/\\___/\\___/_/\\___/_.___/\\____/\\__/ \n"
)
print(" * Self-checking...", end="\r")
req = requests.post(url=f'{bot._url}getWebhookInfo', verify=False, proxies=bot.proxies)
Expand Down
76 changes: 72 additions & 4 deletions teelebot/bot.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"""
@description: A Python-based Telegram Bot framework
@creation date: 2019-08-13
@last modification: 2023-11-28
@last modification: 2023-12-11
@author: Pluto (github:plutobell)
"""
import time
Expand All @@ -15,7 +15,9 @@
import shutil
import inspect
import traceback
import threading
import importlib
import functools

from pathlib import Path
from typing import Union, Callable
Expand All @@ -27,6 +29,7 @@
from .buffer import _Buffer
from .request import _Request
from .metadata import _Metadata
from .common import __plugin_init_func_name__


class Bot(object):
Expand Down Expand Up @@ -135,6 +138,11 @@ def __init__(self, key: str = None, debug: bool = False, proxies: dict = None):

self.__method_name = ""

self.__plugins_init_status_mutex = threading.Lock()
self.__plugins_init_status = {}
# self._update_plugins_init_status()
# self._plugins_init()

del config
del thread_pool_size
del schedule_queue_size
Expand All @@ -146,6 +154,7 @@ def __del__(self):
del self.schedule
del self.buffer
del self.metadata
del self.__plugins_init_status

def __getattr__(self, method_name):
self.__method_name = method_name
Expand All @@ -167,6 +176,61 @@ def __threadpool_exception(self, fur):
if fur.exception() is not None:
_logger.debug(f"EXCEPTION - {str(fur.result())}")

def _plugins_init(self, bot):
"""
Execute the init func of the plugins
"""
for plugin, _ in self.__plugin_bridge.items():
with self.__plugins_init_status_mutex:
if plugin not in list(self.__plugins_init_status.keys()):
continue
elif self.__plugins_init_status[plugin] == True:
continue

module = self.__import_module(plugin)
pluginInitFunc = getattr(module, __plugin_init_func_name__, None)

if pluginInitFunc != None:
def __threadpool_exception(fur, plugin_name, status=False):
if fur.exception() is not None:
_logger.error(f"The plugin {plugin} initialization error.")
_logger.debug(f"EXCEPTION - {str(fur.result())}")
else:
self.__update_plugin_init_status(plugin_name=plugin_name, status=status)
_logger.info(f"The plugin {plugin_name} initialization completed.")

try:
fur = self.__thread_pool.submit(pluginInitFunc, bot)
callback_with_args = functools.partial(__threadpool_exception, plugin_name=plugin, status=True)
fur.add_done_callback(callback_with_args)
except Exception as e:
_logger.error(f"Failed to initialize plugin {plugin}: {str(e)}")
traceback.print_exc()

def _update_plugins_init_status(self):
"""
Update plugins init status
"""
new_status_dict = {}

for plugin, _ in self.__plugin_bridge.items():
with self.__plugins_init_status_mutex:
if plugin in list(self.__plugins_init_status.keys()):
new_status_dict[plugin] = self.__plugins_init_status[plugin]
else:
new_status_dict[plugin] = False

with self.__plugins_init_status_mutex:
self.__plugins_init_status = new_status_dict

def __update_plugin_init_status(self, plugin_name, status=False):
"""
Update plugin init status by plugin_name
"""
with self.__plugins_init_status_mutex:
if plugin_name in list(self.__plugins_init_status.keys()):
self.__plugins_init_status[plugin_name] = status

def __import_module(self, plugin_name):
"""
Dynamic import module
Expand Down Expand Up @@ -199,7 +263,8 @@ def __update_plugin(self, plugin_name, as_plugin=True):
plugin_info[plugin_name] = now_mtime
Module = self.__import_module(plugin_name)
importlib.reload(Module)
_logger.info(f"The plugin {plugin_name} has been updated")
self.__update_plugin_init_status(plugin_name=plugin_name, status=False)
_logger.info(f"The plugin {plugin_name} has been updated.")

def __load_plugin(self, now_plugin_info, as_plugin=True,
now_plugin_bridge={}, now_non_plugin_list=[]):
Expand All @@ -209,11 +274,11 @@ def __load_plugin(self, now_plugin_info, as_plugin=True,
if as_plugin:
for plugin in list(now_plugin_bridge.keys()): # Dynamic Loading Plugin
if plugin not in list(self.__plugin_bridge.keys()):
_logger.info(f"The plugin {plugin} has been installed")
_logger.info(f"The plugin {plugin} has been installed.")
self.__plugin_info[plugin] = now_plugin_info[plugin]
for plugin in list(self.__plugin_bridge.keys()):
if plugin not in list(now_plugin_bridge.keys()):
_logger.info(f"The plugin {plugin} has been uninstalled")
_logger.info(f"The plugin {plugin} has been uninstalled.")
self.__plugin_info.pop(plugin)

if (f'{self.__plugin_dir}{plugin}') in sys.path:
Expand Down Expand Up @@ -442,6 +507,9 @@ def _pluginRun(self, bot, message):
os.system("")
_logger.warn("\033[1;31mNo plugins installed\033[0m")

self._update_plugins_init_status() # Update plugins init status
self._plugins_init(bot)

ok, buffer_status = self.buffer.status() # Buffer capacity monitoring
if ok and buffer_status["used"] >= buffer_status["size"]:
os.system("")
Expand Down
4 changes: 3 additions & 1 deletion teelebot/common.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
'''
@creation date: 2023-05-13
@last modification: 2023-11-28
@last modification: 2023-12-08
'''

__cloud_api_server__ = "https://api.telegram.org/"
Expand Down Expand Up @@ -65,4 +65,6 @@
"secret_token": ""
}

__plugin_init_func_name__ = "Init"


87 changes: 54 additions & 33 deletions teelebot/handler.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# -*- coding:utf-8 -*-
'''
@creation date: 2019-08-23
@last modification: 2023-11-28
@last modification: 2023-12-08
'''
import configparser
import argparse
Expand All @@ -23,7 +23,8 @@
__cloud_api_server__,
__common_pkg_prefix__,
__inline_mode_prefix__,
__config_template__
__config_template__,
__plugin_init_func_name__
)

cloud_api_server = __cloud_api_server__
Expand Down Expand Up @@ -220,36 +221,39 @@ def _config():
enter.writelines([
"# -*- coding: utf-8 -*-\n",
"\n",
"# def " + __plugin_init_func_name__ + "(bot):\n",
"# pass",
"\n\n",
"def " + plugin_name + "(bot, message):\n",
"\n" + \
" # root_id = bot.root_id\n" + \
" # bot_id = bot.bot_id\n" + \
"\n" + \
" # author = bot.author\n" + \
" # version = bot.version\n" + \
"\n" + \
" # plugin_dir = bot.plugin_dir\n" + \
" # plugin_bridge = bot.plugin_bridge\n" + \
"\n" + \
" # uptime = bot.uptime\n" + \
" # response_times = bot.response_times\n" + \
" # response_chats = bot.response_chats\n" + \
" # response_users = bot.response_users\n" + \
"\n" + \
" # proxies = bot.proxies\n" + \
"\n" + \
' chat_id = message.get("chat", {}).get("id")\n' + \
' user_id = message.get("from", {}).get("id")\n' + \
' message_id = message.get("message_id")\n' + \
"\n" + \
' message_type = message.get("message_type")\n' + \
' chat_type = message.get("chat", {}).get("type")\n' + \
"\n" + \
' command = ""\n' + \
' ok, metadata = bot.metadata.read()\n' + \
' if ok:\n' + \
' command = metadata.get("Command")\n' + \
"\n\n" + \
"\n",
" # root_id = bot.root_id\n",
" # bot_id = bot.bot_id\n",
"\n",
" # author = bot.author\n",
" # version = bot.version\n",
"\n",
" # plugin_dir = bot.plugin_dir\n",
" # plugin_bridge = bot.plugin_bridge\n",
"\n",
" # uptime = bot.uptime\n",
" # response_times = bot.response_times\n",
" # response_chats = bot.response_chats\n",
" # response_users = bot.response_users\n",
"\n",
" # proxies = bot.proxies\n",
"\n",
' chat_id = message.get("chat", {}).get("id")\n',
' user_id = message.get("from", {}).get("id")\n',
' message_id = message.get("message_id")\n',
"\n",
' message_type = message.get("message_type")\n',
' chat_type = message.get("chat", {}).get("type")\n',
"\n",
' command = ""\n',
' ok, metadata = bot.metadata.read()\n',
' if ok:\n',
' command = metadata.get("Command")\n',
"\n\n",
" # Write your plugin code below"
])
if not os.path.exists(str(Path(f'{plugin_dir}{plugin_name}{os.sep}README.md'))):
Expand Down Expand Up @@ -409,6 +413,8 @@ def _bridge(plugin_dir):

entrance_exist = False
entrance_count = 0
initfunc_exist = False
initfunc_count = 0
try:
with open(str(Path(f"{plugin_dir}{plugi}{os.sep}{plugi}.py")), "r", encoding="utf-8") as e:
content = e.read()
Expand All @@ -417,12 +423,20 @@ def _bridge(plugin_dir):
f"def {plugi}(bot,message):" in content or \
f"def {plugi}(message,bot):" in content:
entrance_exist = True

if entrance_exist:
entrance_count += content.count(f"def {plugi}(bot, message):")
entrance_count += content.count(f"def {plugi}(message, bot):")
entrance_count += content.count(f"def {plugi}(bot,message):")
entrance_count += content.count(f"def {plugi}(message,bot):")

if f"def {__plugin_init_func_name__}(bot):" in content or \
f"def {__plugin_init_func_name__}(bot,):" in content or \
f"def {__plugin_init_func_name__}(bot, ):" in content:
initfunc_exist = True
if initfunc_exist:
initfunc_count += content.count(f"def {__plugin_init_func_name__}(bot):")
initfunc_count += content.count(f"def {__plugin_init_func_name__}(bot,):")
initfunc_count += content.count(f"def {__plugin_init_func_name__}(bot, ):")
except Exception as e:
os.system("")
_logger.error("\033[1;31mThe " + plugi + " plugin is corrupted: " + "\033[0m" + str(e))
Expand All @@ -444,7 +458,8 @@ def _bridge(plugin_dir):
package_file_list = os.listdir(str(Path(f'{plugin_dir}{plugi}')))
if plugi + ".py" in package_file_list and \
"METADATA" in package_file_list and \
entrance_exist and entrance_count == 1 and metadata_ok:
entrance_exist and entrance_count == 1 and \
initfunc_count <= 1 and metadata_ok:
plugin_list.append(plugi)
else:
corrupted_plugin_list.append(plugi)
Expand All @@ -469,6 +484,12 @@ def _bridge(plugin_dir):
error = f"multiple entrance functions exist in plugin"
os.system("")
_logger.error(f"\033[1;31mThe {plugi} plugin is corrupted: \033[0m{error}")

if initfunc_exist and initfunc_count != 1:
error = f"multiple {__plugin_init_func_name__} functions exist in plugin"
os.system("")
_logger.error(f"\033[1;31mThe {plugi} plugin is corrupted: \033[0m{error}")


if not metadata_ok:
error = f"metadata format error"
Expand Down
5 changes: 4 additions & 1 deletion teelebot/polling.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# -*- coding:utf-8 -*-
'''
@creation date: 2020-06-23
@last modification: 2023-07-12
@last modification: 2023-12-11
'''
import os
import signal
Expand All @@ -13,6 +13,9 @@ def _runUpdates(bot):

_logger.info("Bot Start.")

bot._update_plugins_init_status()
bot._plugins_init(bot)

signal.signal(signal.SIGINT, __exit)
while True:
results = bot.getUpdates(
Expand Down
Loading

0 comments on commit f1be720

Please sign in to comment.