diff --git a/.env.example b/.env.example
new file mode 100644
index 0000000..154bfa6
--- /dev/null
+++ b/.env.example
@@ -0,0 +1,6 @@
+#Github的token
+GH_TOKEN=XX
+#turso服务的url
+TURSO_DB_URL=XX
+#turso服务的认证token
+TURSO_DB_AUTH_TOKEN=XX
\ No newline at end of file
diff --git a/.github/dependabot.yml b/.github/dependabot.yml
new file mode 100644
index 0000000..90be523
--- /dev/null
+++ b/.github/dependabot.yml
@@ -0,0 +1,14 @@
+# To get started with Dependabot version updates, you'll need to specify which
+# package ecosystems to update and where the package manifests are located.
+# Please see the documentation for all configuration options:
+# https://docs.github.com/code-security/dependabot/dependabot-version-updates/configuration-options-for-the-dependabot.yml-file
+
+version: 2
+updates:
+ - package-ecosystem: "pip" # See documentation for possible values
+ directory: "/" # Location of package manifests
+ schedule:
+ interval: "weekly"
+ allow:
+ - dependency-name: "Flask"
+ - dependency-name: "libsql_client"
\ No newline at end of file
diff --git a/.github/release-drafter.yml b/.github/release-drafter.yml
new file mode 100644
index 0000000..fa4e3b7
--- /dev/null
+++ b/.github/release-drafter.yml
@@ -0,0 +1,44 @@
+# Configuration for Release Drafter: https://github.com/toolmantim/release-drafter
+name-template: 'v$NEXT_PATCH_VERSION 🌈'
+tag-template: 'v$NEXT_PATCH_VERSION'
+version-template: $MAJOR.$MINOR.$PATCH
+# Emoji reference: https://gitmoji.carloscuesta.me/
+categories:
+ - title: '✨ Features'
+ labels:
+ - 'feat'
+ - 'feature'
+ - 'enhancement'
+ - 'kind/feature'
+ - title: '🐛 Bug Fixes'
+ labels:
+ - 'fix'
+ - 'bugfix'
+ - 'bug'
+ - 'regression'
+ - 'kind/bug'
+ - title: 📝 Documentation updates
+ labels:
+ - 'documentation'
+ - 'kind/doc'
+ - 'doc'
+ - title: 👻 Maintenance
+ labels:
+ - 'chore'
+ - 'dependencies'
+ - 'kind/chore'
+ - 'kind/dep'
+ - title: ⚡️ Tests
+ labels:
+ - 'test'
+ - 'tests'
+exclude-labels:
+ - 'reverted'
+ - 'no-changelog'
+ - 'skip-changelog'
+ - 'invalid'
+change-template: '* $TITLE (#$NUMBER) @$AUTHOR'
+change-title-escapes: '\<*_&' # You can add # and @ to disable mentions, and add ` to disable code blocks.
+template: |
+ ## What’s Changed
+ $CHANGES
\ No newline at end of file
diff --git a/.github/workflows/update_release_draft.yml b/.github/workflows/update_release_draft.yml
new file mode 100644
index 0000000..76de6e0
--- /dev/null
+++ b/.github/workflows/update_release_draft.yml
@@ -0,0 +1,24 @@
+name: update_release_draft.yml
+
+on:
+ push:
+ branches:
+ - main
+ pull_request:
+
+ types: [ opened, reopened, synchronize ]
+
+permissions:
+ contents: write
+ packages: write
+
+jobs:
+ update_release_draft:
+ permissions:
+ contents: write # for release-drafter/release-drafter to create a github release
+ pull-requests: write # for release-drafter/release-drafter to add label to PR
+ runs-on: ubuntu-latest
+ steps:
+ - uses: release-drafter/release-drafter@v5
+ env:
+ GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
\ No newline at end of file
diff --git a/.idea/misc.xml b/.idea/misc.xml
index e55a3e1..6ae386b 100644
--- a/.idea/misc.xml
+++ b/.idea/misc.xml
@@ -1,4 +1,7 @@
+
+
+
\ No newline at end of file
diff --git a/.vscode/launch.json b/.vscode/launch.json
deleted file mode 100644
index e119425..0000000
--- a/.vscode/launch.json
+++ /dev/null
@@ -1,16 +0,0 @@
-{
- // 使用 IntelliSense 了解相关属性。
- // 悬停以查看现有属性的描述。
- // 欲了解更多信息,请访问: https://go.microsoft.com/fwlink/?linkid=830387
- "version": "0.2.0",
- "configurations": [
- {
- "name": "Python: 当前文件",
- "type": "python",
- "request": "launch",
- "program": "${file}",
- "console": "integratedTerminal",
- "justMyCode": true
- }
- ]
-}
\ No newline at end of file
diff --git a/.vscode/settings.json b/.vscode/settings.json
deleted file mode 100644
index 457f44d..0000000
--- a/.vscode/settings.json
+++ /dev/null
@@ -1,3 +0,0 @@
-{
- "python.analysis.typeCheckingMode": "basic"
-}
\ No newline at end of file
diff --git a/components/trakt/__init__.py b/components/trakt/__init__.py
index 9481297..34fa04e 100644
--- a/components/trakt/__init__.py
+++ b/components/trakt/__init__.py
@@ -5,95 +5,150 @@
# 创建蓝图
blueprint = Blueprint('trakt', __name__, url_prefix='/trakt')
+
# =========================电影================================
@blueprint.route('/movie')
def movies():
- """分页获取电影列表
+ """分页获取电影列表
- Returns:
- _type_: 电影列表
- """
- # 获取请求参数page和page_size
- curr_page = int(request.args.get('page', 1))
- page_size = int(request.args.get('page_size', 10))
- try:
- return Result.success(movie_handler.get_movies(curr_page, page_size))
- except Exception as e:
- return Result.fail(e)
+ Returns:
+ _type_: 电影列表
+ """
+ # 获取请求参数page和page_size
+ curr_page = int(request.args.get('page', 1))
+ page_size = int(request.args.get('page_size', 10))
+ try:
+ return Result.success(movie_handler.get_movies(curr_page, page_size))
+ except Exception as e:
+ return Result.fail(e)
@blueprint.route('/movie/')
def movie(movie_id):
- """获取电影详情
+ """获取电影详情
- Args:
- movie_id (str): 电影的tmdb_id
+ Args:
+ movie_id (str): 电影的tmdb_id
- Returns:
- _type_: 电影详情
- """
- try:
- return Result.success(movie_handler.get_movie(movie_id))
- except Exception as e:
- return Result.fail(e)
+ Returns:
+ _type_: 电影详情
+ """
+ try:
+ return Result.success(movie_handler.get_movie(movie_id))
+ except Exception as e:
+ return Result.fail(e)
@blueprint.route('/update_movie_share_link', methods=['POST'])
def update_movie_share_link():
- """更新电影分享链接 content-type为application/x-www-form-urlencoded
-
- Returns:
- _type_: 更新结果
- """
- # 获取请求参数tmdb_id和share_link
- movie_id = request.form.get('movie_id')
- share_link = request.form.get('share_link')
- if not movie_id or not share_link:
- return Result.fail('movie_id和share_link不能为空')
- try:
- movie_handler.update_share_link(movie_id, share_link)
- return Result.success('更新成功')
- except Exception as e:
- return Result.fail(e)
+ """更新电影分享链接 content-type为application/x-www-form-urlencoded
+
+ Returns:
+ _type_: 更新结果
+ """
+ # 获取请求参数tmdb_id和share_link
+ movie_id = request.form.get('movie_id')
+ share_link = request.form.get('share_link')
+ if not movie_id or not share_link:
+ return Result.fail('movie_id和share_link不能为空')
+ try:
+ movie_handler.update_share_link(movie_id, share_link)
+ return Result.success('更新成功')
+ except Exception as e:
+ return Result.fail(e)
# ==============================剧集===================================
+@blueprint.route('/show')
+def shows():
+ """分页获取剧集列表
+
+ Returns:
+ _type_: 剧集列表
+ """
+ # 获取请求参数page和page_size
+ curr_page = int(request.args.get('page', 1))
+ page_size = int(request.args.get('page_size', 10))
+ try:
+ return Result.success(show_handler.get_shows(curr_page, page_size))
+ except Exception as e:
+ return Result.fail(e)
+
+
+@blueprint.route('/show/')
+def show(show_id):
+ """获取剧集详情
+
+ Args:
+ show_id (str): 剧集的tmdb_id
+
+ Returns:
+ _type_: 剧集详情
+ """
+ try:
+ return Result.success(show_handler.get_show(show_id))
+ except Exception as e:
+ return Result.fail(e)
+
+
+@blueprint.route('/update_show_share_link', methods=['POST'])
+def update_show_share_link():
+ """更新剧集分享链接 content-type为application/x-www-form-urlencoded
+
+ Returns:
+ _type_: 更新结果
+ """
+ # 获取请求参数tmdb_id和share_link
+ show_id = request.form.get('show_id')
+ share_link = request.form.get('share_link')
+ if not show_id or not share_link:
+ return Result.fail('show_id和share_link不能为空')
+ try:
+ show_handler.update_share_link(show_id, share_link)
+ return Result.success('更新成功')
+ except Exception as e:
+ return Result.fail(e)
+
+
+# ==============================common================================
+
+
@blueprint.route('/index')
def index():
- """获取电影/剧集索引
- """
- try:
- return Result.success({
- 'movie': movie_handler.get_index(),
- 'show': show_handler.get_index()
- })
- except Exception as e:
- return Result.fail(e)
+ """获取电影/剧集索引
+ """
+ try:
+ return Result.success({
+ 'movie': movie_handler.get_index(),
+ 'show': show_handler.get_index()
+ })
+ except Exception as e:
+ return Result.fail(e)
@blueprint.route('/refresh_movie_cache')
def refresh_movie_cache():
- """刷新电影缓存
- """
- try:
- movie_handler.get_movies.cache_clear()
- movie_handler.get_movie.cache_clear()
- movie_handler.get_index.cache_clear()
- return Result.success(msg='刷新movie缓存成功')
- except Exception as e:
- return Result.fail(e)
+ """刷新电影缓存
+ """
+ try:
+ movie_handler.get_movies.cache_clear()
+ movie_handler.get_movie.cache_clear()
+ movie_handler.get_index.cache_clear()
+ return Result.success(msg='刷新movie缓存成功')
+ except Exception as e:
+ return Result.fail(e)
@blueprint.route('/refresh_show_cache')
def refresh_show_cache():
- """刷新剧集缓存
- """
- try:
- show_handler.get_index.cache_clear()
- return Result.success(msg='刷新show缓存成功')
- except Exception as e:
- return Result.fail(e)
+ """刷新剧集缓存
+ """
+ try:
+ show_handler.get_index.cache_clear()
+ return Result.success(msg='刷新show缓存成功')
+ except Exception as e:
+ return Result.fail(e)
diff --git a/components/trakt/movie_handler.py b/components/trakt/movie_handler.py
index 244163b..e41b326 100644
--- a/components/trakt/movie_handler.py
+++ b/components/trakt/movie_handler.py
@@ -17,87 +17,87 @@
@cache.cache_with_expiry(876000)
def get_movies(curr_page: int = 1, page_size: int = 10):
- """分页查询电影列表
-
- Args:
- curr_page (int, optional): 第几页. 默认1
-
- page_size (int, optional): 每页多少条数据. 默认10
-
- Returns:
- _type_: 电影列表
- """
- with acquire_client_sync() as turso_client:
- page = Page(curr_page, page_size)
-
- # 查询总数
- total_count: int = turso_client.execute(
- TOTAL_COUNT).rows[0][0] # type: ignore
- # 设置总页数与总数
- page.set_total_count(total_count)
- if total_count == 0:
- return page
-
- page_data = []
- # 执行查询
- result_set = turso_client.execute(QUERY_MOVIE_BY_PAGED, {
- 'page_size': page_size, 'offset': (curr_page - 1) * page_size})
- columns = result_set.columns
- for row in result_set.rows:
- data = {}
- for index in range(0, len(columns)):
- # 将查询结果转换为字典
- data[columns[index]] = row[index]
- page_data.append(data)
- page.data = page_data
- return page
+ """分页查询电影列表
+
+ Args:
+ curr_page (int, optional): 第几页. 默认1
+
+ page_size (int, optional): 每页多少条数据. 默认10
+
+ Returns:
+ _type_: 电影列表
+ """
+ with acquire_client_sync() as turso_client:
+ page = Page(curr_page, page_size)
+
+ # 查询总数
+ total_count: int = turso_client.execute(
+ TOTAL_COUNT).rows[0][0] # type: ignore
+ # 设置总页数与总数
+ page.set_total_count(total_count)
+ if total_count == 0:
+ return page
+
+ page_data = []
+ # 执行查询
+ result_set = turso_client.execute(QUERY_MOVIE_BY_PAGED, {
+ 'page_size': page_size, 'offset': (curr_page - 1) * page_size})
+ columns = result_set.columns
+ for row in result_set.rows:
+ data = {}
+ for index in range(0, len(columns)):
+ # 将查询结果转换为字典
+ data[columns[index]] = row[index]
+ page_data.append(data)
+ page.data = page_data
+ return page
@cache.cache_with_expiry(876000)
def get_movie(movie_id: str):
- """获取电影详情
+ """获取电影详情
- Args:
- movie_id (str): 电影的tmdb_id
+ Args:
+ movie_id (str): 电影的tmdb_id
- Returns:
- _type_: 电影详情
- """
- with acquire_client_sync() as turso_client:
- # 查询电影详情
- rows = turso_client.execute(
- SELECT_MOVIE_BY_ID, [movie_id]).rows
- if len(rows) == 0:
- return None
- return rows[0]
+ Returns:
+ _type_: 电影详情
+ """
+ with acquire_client_sync() as turso_client:
+ # 查询电影详情
+ rows = turso_client.execute(
+ SELECT_MOVIE_BY_ID, [movie_id]).rows
+ if len(rows) == 0:
+ return None
+ return rows[0]
def update_share_link(movie_id: str, share_link: str):
- """更新分享链接
+ """更新分享链接
- Args:
- movie_id (int): 电影的tmdb_id
- share_link (str): 分享链接
- """
- with acquire_client_sync() as turso_client:
- turso_client.execute(UPDATE_MOVIE_SHARE_LINK, {
- 'movie_id': movie_id, 'share_link': share_link})
- # 清除缓存
- get_movies.cache_clear()
- get_movie.cache_clear()
+ Args:
+ movie_id (int): 电影的tmdb_id
+ share_link (str): 分享链接
+ """
+ with acquire_client_sync() as turso_client:
+ turso_client.execute(UPDATE_MOVIE_SHARE_LINK, {
+ 'movie_id': movie_id, 'share_link': share_link})
+ # 清除缓存
+ get_movies.cache_clear()
+ get_movie.cache_clear()
@cache.cache_with_expiry(876000)
def get_index():
- """获取电影索引
-
- Returns:
- _type_: 索引数据(base64编码)
- """
- with acquire_client_sync() as turso_client:
- # 查询电影索引
- rows = turso_client.execute(
- SELECT_LOCAL_SEARCH_BY_TYPE, ('movie',)).rows
- if len(rows) == 0:
- return ''
- return rows[0]['b64_index']
+ """获取电影索引
+
+ Returns:
+ _type_: 索引数据(base64编码)
+ """
+ with acquire_client_sync() as turso_client:
+ # 查询电影索引
+ rows = turso_client.execute(
+ SELECT_LOCAL_SEARCH_BY_TYPE, ('movie',)).rows
+ if len(rows) == 0:
+ return ''
+ return rows[0]['b64_index']
diff --git a/components/trakt/show_handler.py b/components/trakt/show_handler.py
index ff85842..dd0ed33 100644
--- a/components/trakt/show_handler.py
+++ b/components/trakt/show_handler.py
@@ -1,7 +1,103 @@
# 剧集 处理类
from core import cache
+from core.result import Page
+from db.turso import acquire_client_sync
+
+# 查询总数
+TOTAL_COUNT = 'SELECT COUNT(*) FROM show'
+# 分页查询剧集 列表(按照最后观看时间排序)
+QUERY_SHOW_BY_PAGED = 'SELECT * FROM show ORDER BY last_watched_at DESC LIMIT :page_size OFFSET :offset'
+# 更新分享链接
+UPDATE_SHOW_SHARE_LINK = 'UPDATE show SET share_link = :share_link WHERE show_id = :show_id'
+# 根据类型查询索引表数据
+SELECT_LOCAL_SEARCH_BY_TYPE = "SELECT * FROM local_search WHERE type = ?"
+# 根据show_id查询剧集详情
+SELECT_SHOW_BY_ID = "SELECT * FROM show WHERE show_id = ?"
+
+
+@cache.cache_with_expiry(876000)
+def get_shows(curr_page: int = 1, page_size: int = 10):
+ """分页查询剧集列表
+
+ Args:
+ curr_page (int, optional): 第几页. 默认1
+
+ page_size (int, optional): 每页多少条数据. 默认10
+
+ Returns:
+ _type_: 剧集列表
+ """
+ with acquire_client_sync() as turso_client:
+ page = Page(curr_page, page_size)
+
+ # 查询总数
+ total_count: int = turso_client.execute(
+ TOTAL_COUNT).rows[0][0] # type: ignore
+ # 设置总页数与总数
+ page.set_total_count(total_count)
+ if total_count == 0:
+ return page
+
+ page_data = []
+ # 执行查询
+ result_set = turso_client.execute(QUERY_SHOW_BY_PAGED, {
+ 'page_size': page_size, 'offset': (curr_page - 1) * page_size})
+ columns = result_set.columns
+ for row in result_set.rows:
+ data = {}
+ for index in range(0, len(columns)):
+ # 将查询结果转换为字典
+ data[columns[index]] = row[index]
+ page_data.append(data)
+ page.data = page_data
+ return page
+
+
+@cache.cache_with_expiry(876000)
+def get_show(show_id: str):
+ """获取剧集详情
+
+ Args:
+ show_id (str): 剧集的tmdb_id
+
+ Returns:
+ _type_: 剧集详情
+ """
+ with acquire_client_sync() as turso_client:
+ # 查询电影详情
+ rows = turso_client.execute(
+ SELECT_SHOW_BY_ID, [show_id]).rows
+ if len(rows) == 0:
+ return None
+ return rows[0]
+
+
+def update_share_link(show_id: str, share_link: str):
+ """更新分享链接
+
+ Args:
+ show_id (int): 剧集的tmdb_id
+ share_link (str): 分享链接
+ """
+ with acquire_client_sync() as turso_client:
+ turso_client.execute(UPDATE_SHOW_SHARE_LINK, {
+ 'show_id': show_id, 'share_link': share_link})
+ # 清除缓存
+ get_shows.cache_clear()
+ get_show.cache_clear()
@cache.cache_with_expiry(876000)
def get_index():
- return ''
+ """获取剧集索引
+
+ Returns:
+ _type_: 索引数据(base64编码)
+ """
+ with acquire_client_sync() as turso_client:
+ # 查询剧集索引
+ rows = turso_client.execute(
+ SELECT_LOCAL_SEARCH_BY_TYPE, ('show',)).rows
+ if len(rows) == 0:
+ return ''
+ return rows[0]['b64_index']
diff --git a/core/result.py b/core/result.py
index 574b780..f899306 100644
--- a/core/result.py
+++ b/core/result.py
@@ -1,84 +1,87 @@
import json
from libsql_client.result import Row
from typing import Union
-# 统一结果类
-
-class Page:
- def __init__(self, curr_page: int = 1, page_size: int = 10, data=None):
- """分页对象
+# 统一结果类
- Args:
- data (_type_): 分页数据
- page (int, optional): 当前页
- page_size (int, optional): 每页多少条数据
- total_page (int, optional): 总页数
- total_count (int, optional): 总条数
- """
- self.curr_page = curr_page
- self.page_size = page_size
- self.data = data
- def set_total_count(self, total_count: int):
- """设置总页数与总数
+class Page:
+
+ def __init__(self, curr_page: int = 1, page_size: int = 10, data=None):
+ """分页对象
- Args:
- total_count (int): 总条数
- """
- self.total_count = total_count
- self.total_page = total_count // self.page_size + \
- (1 if total_count % self.page_size > 0 else 0)
+ Args:
+ data (_type_): 分页数据
+ page (int, optional): 当前页
+ page_size (int, optional): 每页多少条数据
+ total_page (int, optional): 总页数
+ total_count (int, optional): 总条数
+ """
+ self.curr_page = curr_page
+ self.page_size = page_size
+ self.data = data
+
+ def set_total_count(self, total_count: int):
+ """设置总页数与总数
- def __json__(self):
- return {
- 'curr_page': self.curr_page,
- 'page_size': self.page_size,
- 'total_page': self.total_page,
- 'total_count': self.total_count,
- 'data': self.data
- }
+ Args:
+ total_count (int): 总条数
+ """
+ self.total_count = total_count
+ self.total_page = total_count // self.page_size + \
+ (1 if total_count % self.page_size > 0 else 0)
+
+ def __json__(self):
+ return {
+ 'curr_page': self.curr_page,
+ 'page_size': self.page_size,
+ 'total_page': self.total_page,
+ 'total_count': self.total_count,
+ 'data': self.data
+ }
class Result:
+
+ @staticmethod
+ def success(data: Union[str, dict, list, Page, Row, None] = None, code: int = 200, msg: str = 'success') -> str:
+ """成功响应
- @staticmethod
- def success(data: Union[str, dict, list, Page, Row, None] = None, code: int = 200, msg: str = 'success') -> str:
- """成功响应
-
- Args:
- data (Union[str, dict, list, Page, None], optional): _description_. Defaults to None.
- code (int, optional): _description_. Defaults to 200.
- msg (str, optional): _description_. Defaults to 'success'.
-
- Returns:
- str: _description_
- """
- res = {}
- if isinstance(data, Row):
- res['data'] = data.asdict()
- elif isinstance(data, Page):
- res['data'] = data.__json__()
- else:
- res['data'] = data
- res['code'] = code
- res['msg'] = msg
- return json.dumps(res)
+ Args:
+ data (Union[str, dict, list, Page, None], optional): _description_. Defaults to None.
+ code (int, optional): _description_. Defaults to 200.
+ msg (str, optional): _description_. Defaults to 'success'.
- @staticmethod
- def fail(msg: Union[str, Exception] = 'failed', code: int = 500, data: Union[str, dict, list, Page, None] = None) -> str:
- """失败响应
+ Returns:
+ str: _description_
+ """
+ res = {}
+ if isinstance(data, Row):
+ res['data'] = data.asdict()
+ elif isinstance(data, Page):
+ res['data'] = data.__json__()
+ else:
+ res['data'] = data
+ res['code'] = code
+ res['msg'] = msg
+ return json.dumps(res)
+
+ @staticmethod
+ def fail(msg: Union[str, Exception] = 'failed', code: int = 500,
+ data: Union[str, dict, list, Page, None] = None) -> str:
+ """失败响应
- Args:
- data (Union[str, dict, list, Page, None], optional): _description_. Defaults to None.
- code (int, optional): _description_. Defaults to 500.
- msg (str, optional): _description_. Defaults to 'failed'.
+ Args:
+ data (Union[str, dict, list, Page, None], optional): _description_. Defaults to None.
+ code (int, optional): _description_. Defaults to 500.
+ msg (str, optional): _description_. Defaults to 'failed'.
- Returns:
- str: _description_
- """
- res = {}
- res['data'] = data.__json__() if isinstance(data, Page) else data
- res['code'] = code
- res['msg'] = msg if isinstance(msg, str) else str(msg)
- return json.dumps(res)
+ Returns:
+ str: _description_
+ """
+ res = {}
+ res['data'] = data.__json__() if isinstance(data, Page) else data
+ res['code'] = code
+ res['msg'] = msg if isinstance(msg, str) else str(msg)
+ return json.dumps(res)
diff --git a/utils/github.py b/utils/github.py
index c517b1f..cb02368 100644
--- a/utils/github.py
+++ b/utils/github.py
@@ -4,19 +4,20 @@
GH_TOKEN = os.environ.get('GH_TOKEN')
+
def trigger_github_workflow(event_type: str, client_payload: dict = {}):
- """触发github workflow
+ """触发github workflow
- Args:
- repo (str): 仓库名
- event_type (str): 事件类型
- client_payload (dict): 负载
- """
- header = {
- 'Accept': 'application/vnd.github.everest-preview+json',
- 'Authorization': f'token {GH_TOKEN}'
- }
- data = json.dumps({"event_type": f"{event_type}",
- "client_payload": client_payload})
- requests.post(f'https://api.github.com/repos/nichuanfang/api/dispatches',
- data=data, headers=header)
\ No newline at end of file
+ Args:
+ repo (str): 仓库名
+ event_type (str): 事件类型
+ client_payload (dict): 负载
+ """
+ header = {
+ 'Accept': 'application/vnd.github.everest-preview+json',
+ 'Authorization': f'token {GH_TOKEN}'
+ }
+ data = json.dumps({"event_type": f"{event_type}",
+ "client_payload": client_payload})
+ requests.post(f'https://api.github.com/repos/nichuanfang/api/dispatches',
+ data=data, headers=header)