mirror of
https://github.com/TeamPGM/PagerMaid-Pyro.git
synced 2024-11-21 21:48:05 +00:00
🔖 Update to v1.4.0
Support web login
This commit is contained in:
parent
0cb44d621d
commit
8e29af1875
@ -11,6 +11,7 @@
|
||||
api_id: "ID_HERE"
|
||||
api_hash: "HASH_HERE"
|
||||
qrcode_login: "False"
|
||||
web_login: "False"
|
||||
|
||||
# Either debug logging is enabled or not
|
||||
debug: "False"
|
||||
|
@ -21,8 +21,8 @@ from pagermaid.scheduler import scheduler
|
||||
import pyromod.listen
|
||||
from pyrogram import Client
|
||||
|
||||
pgm_version = "1.3.4"
|
||||
pgm_version_code = 1304
|
||||
pgm_version = "1.4.0"
|
||||
pgm_version_code = 1400
|
||||
CMD_LIST = {}
|
||||
module_dir = __path__[0]
|
||||
working_dir = getcwd()
|
||||
|
@ -1,15 +1,16 @@
|
||||
import asyncio
|
||||
from os import sep
|
||||
from signal import signal as signal_fn, SIGINT, SIGTERM, SIGABRT
|
||||
from sys import path, platform
|
||||
from sys import path, platform, exit
|
||||
|
||||
from pyrogram.errors import AuthKeyUnregistered
|
||||
|
||||
from pagermaid import bot, logs, working_dir
|
||||
from pagermaid import bot, logs, working_dir, Config
|
||||
from pagermaid.common.reload import load_all
|
||||
from pagermaid.single_utils import safe_remove
|
||||
from pagermaid.utils import lang, process_exit
|
||||
from pagermaid.web import web
|
||||
from pagermaid.web.api.web_login import web_login
|
||||
from pyromod.methods.sign_in_qrcode import start_client
|
||||
|
||||
path.insert(1, f"{working_dir}{sep}plugins")
|
||||
@ -50,11 +51,29 @@ async def console_bot():
|
||||
await process_exit(start=True, _client=bot)
|
||||
|
||||
|
||||
async def web_bot():
|
||||
try:
|
||||
await web_login.init()
|
||||
except AuthKeyUnregistered:
|
||||
safe_remove("pagermaid.session")
|
||||
exit()
|
||||
if bot.me is not None:
|
||||
me = await bot.get_me()
|
||||
if me.is_bot:
|
||||
safe_remove("pagermaid.session")
|
||||
exit()
|
||||
else:
|
||||
logs.info("Please use web to login, path: web_login .")
|
||||
|
||||
|
||||
async def main():
|
||||
logs.info(lang("platform") + platform + lang("platform_load"))
|
||||
await web.start()
|
||||
if not (Config.WEB_ENABLE and Config.WEB_LOGIN):
|
||||
await console_bot()
|
||||
logs.info(lang("start"))
|
||||
else:
|
||||
await web_bot()
|
||||
|
||||
try:
|
||||
await idle()
|
||||
|
@ -48,6 +48,9 @@ class Config:
|
||||
QRCODE_LOGIN = strtobool(
|
||||
os.environ.get("QRCODE_LOGIN", config.get("qrcode_login", "false"))
|
||||
)
|
||||
WEB_LOGIN = strtobool(
|
||||
os.environ.get("WEB_LOGIN", config.get("web_login", "false"))
|
||||
)
|
||||
STRING_SESSION = os.environ.get("STRING_SESSION")
|
||||
DEBUG = strtobool(os.environ.get("PGM_DEBUG", config["debug"]))
|
||||
ERROR_REPORT = strtobool(
|
||||
|
@ -5,3 +5,13 @@ from apscheduler.schedulers.asyncio import AsyncIOScheduler
|
||||
from sqlitedict import SqliteDict
|
||||
from httpx import AsyncClient
|
||||
from logging import Logger
|
||||
|
||||
__all__ = [
|
||||
"Client",
|
||||
"Message",
|
||||
"Sub",
|
||||
"AsyncIOScheduler",
|
||||
"SqliteDict",
|
||||
"AsyncClient",
|
||||
"Logger"
|
||||
]
|
||||
|
@ -34,6 +34,7 @@ from pagermaid.utils import (
|
||||
process_exit,
|
||||
)
|
||||
from pagermaid.hook import Hook
|
||||
from pagermaid.web import web
|
||||
|
||||
_lock = asyncio.Lock()
|
||||
|
||||
@ -197,7 +198,7 @@ def listener(**args):
|
||||
except SystemExit:
|
||||
await process_exit(start=False, _client=client, message=message)
|
||||
await Hook.shutdown()
|
||||
sys.exit(0)
|
||||
web.stop()
|
||||
except BaseException:
|
||||
exc_info = sys.exc_info()[1]
|
||||
exc_format = format_exc()
|
||||
|
@ -1,7 +1,5 @@
|
||||
""" The help module. """
|
||||
|
||||
from json import dump as json_dump
|
||||
from os import listdir, sep
|
||||
from os import listdir
|
||||
|
||||
from pyrogram.enums import ParseMode
|
||||
|
||||
|
@ -140,7 +140,7 @@ async def plugin(message: Message):
|
||||
for target_plugin in active_plugins:
|
||||
inactive_plugins.remove(target_plugin)
|
||||
chdir(f"plugins{sep}")
|
||||
for target_plugin in glob(f"*.py.disabled"):
|
||||
for target_plugin in glob("*.py.disabled"):
|
||||
disabled_plugins += [f"{target_plugin[:-12]}"]
|
||||
chdir(f"..{sep}")
|
||||
active_plugins_string = ""
|
||||
|
@ -1,6 +1,7 @@
|
||||
import sentry_sdk
|
||||
|
||||
from subprocess import run, PIPE
|
||||
import sys
|
||||
from time import time
|
||||
|
||||
from pyrogram.errors import Unauthorized, UsernameInvalid
|
||||
@ -18,7 +19,7 @@ def sentry_before_send(event, hint):
|
||||
if exc_info and isinstance(exc_info[1], (Unauthorized, UsernameInvalid)):
|
||||
# The user has been deleted/deactivated or session revoked
|
||||
safe_remove("pagermaid.session")
|
||||
exit(1)
|
||||
sys.exit(1)
|
||||
if time() <= sentry_sdk_report_time + 30:
|
||||
sentry_sdk_report_time = time()
|
||||
return None
|
||||
@ -29,7 +30,7 @@ def sentry_before_send(event, hint):
|
||||
|
||||
sentry_sdk_report_time = time()
|
||||
sentry_sdk_git_hash = (
|
||||
run("git rev-parse HEAD", stdout=PIPE, shell=True).stdout.decode().strip()
|
||||
run("git rev-parse HEAD", stdout=PIPE, shell=True, check=True).stdout.decode(check=True).strip(check=True)
|
||||
)
|
||||
sentry_sdk.init(
|
||||
Config.SENTRY_API,
|
||||
|
@ -2,7 +2,7 @@
|
||||
|
||||
import re
|
||||
|
||||
from datetime import datetime, timezone
|
||||
from datetime import datetime
|
||||
from platform import uname, python_version
|
||||
from sys import platform
|
||||
|
||||
@ -18,7 +18,7 @@ from psutil import boot_time, virtual_memory, disk_partitions
|
||||
from shutil import disk_usage
|
||||
from subprocess import Popen, PIPE
|
||||
|
||||
from pagermaid import start_time, Config, pgm_version
|
||||
from pagermaid import Config, pgm_version
|
||||
from pagermaid.common.status import get_bot_uptime
|
||||
from pagermaid.enums import Client, Message
|
||||
from pagermaid.listener import listener
|
||||
|
@ -1,3 +1,4 @@
|
||||
import sys
|
||||
from getpass import getuser
|
||||
from os.path import exists, sep
|
||||
from platform import node
|
||||
@ -8,7 +9,6 @@ from pagermaid.common.system import run_eval
|
||||
from pagermaid.enums import Message
|
||||
from pagermaid.listener import listener
|
||||
from pagermaid.utils import attach_log, execute, lang, upload_attachment
|
||||
from pagermaid.web import web
|
||||
|
||||
|
||||
@listener(
|
||||
@ -51,7 +51,7 @@ async def restart(message: Message):
|
||||
"""To re-execute PagerMaid."""
|
||||
if not message.text[0].isalpha():
|
||||
await message.edit(lang("restart_log"))
|
||||
web.stop()
|
||||
sys.exit(0)
|
||||
|
||||
|
||||
@listener(
|
||||
@ -65,7 +65,8 @@ async def sh_eval(message: Message):
|
||||
"""Run python commands from Telegram."""
|
||||
dev_mode = exists(f"data{sep}dev")
|
||||
try:
|
||||
assert dev_mode
|
||||
if not dev_mode:
|
||||
raise AssertionError
|
||||
cmd = message.text.split(" ", maxsplit=1)[1]
|
||||
except (IndexError, AssertionError):
|
||||
return await message.edit(lang("eval_need_dev"))
|
||||
|
@ -4,6 +4,14 @@ from pagermaid.single_utils import sqlite
|
||||
from pagermaid.scheduler import scheduler
|
||||
from pagermaid.utils import client
|
||||
|
||||
__all__ = [
|
||||
"bot",
|
||||
"logs",
|
||||
"sqlite",
|
||||
"scheduler",
|
||||
"client",
|
||||
]
|
||||
|
||||
|
||||
def get(name: str):
|
||||
data = {
|
||||
@ -13,4 +21,4 @@ def get(name: str):
|
||||
"AsyncIOScheduler": scheduler,
|
||||
"AsyncClient": client,
|
||||
}
|
||||
return data.get(name, None)
|
||||
return data.get(name)
|
||||
|
@ -3,7 +3,6 @@ from os import sep, remove, mkdir
|
||||
from os.path import exists
|
||||
from typing import List, Optional, Union
|
||||
from apscheduler.schedulers.asyncio import AsyncIOScheduler
|
||||
from httpx import AsyncClient
|
||||
|
||||
from pyrogram import Client as OldClient
|
||||
from pyrogram.types import Chat as OldChat, Message as OldMessage, Dialog
|
||||
@ -14,9 +13,13 @@ from pyromod.utils.errors import (
|
||||
TimeoutConversationError,
|
||||
ListenerCanceled,
|
||||
)
|
||||
|
||||
from sqlitedict import SqliteDict
|
||||
|
||||
__all__ = [
|
||||
"AlreadyInConversationError",
|
||||
"TimeoutConversationError",
|
||||
"ListenerCanceled",
|
||||
]
|
||||
# init folders
|
||||
if not exists("data"):
|
||||
mkdir("data")
|
||||
|
@ -10,7 +10,7 @@ from sys import executable
|
||||
from asyncio import create_subprocess_shell, sleep
|
||||
from asyncio.subprocess import PIPE
|
||||
|
||||
from pyrogram import filters, enums
|
||||
from pyrogram import filters
|
||||
from pagermaid.config import Config
|
||||
from pagermaid import bot
|
||||
from pagermaid.group_manager import enforce_permission
|
||||
|
@ -7,7 +7,7 @@ from starlette.responses import RedirectResponse
|
||||
|
||||
from pagermaid import logs
|
||||
from pagermaid.config import Config
|
||||
from pagermaid.web.api import base_api_router
|
||||
from pagermaid.web.api import base_api_router, base_html_router
|
||||
from pagermaid.web.pages import admin_app, login_page
|
||||
|
||||
requestAdaptor = """
|
||||
@ -39,6 +39,7 @@ class Web:
|
||||
|
||||
def init_web(self):
|
||||
self.app.include_router(base_api_router)
|
||||
self.app.include_router(base_html_router)
|
||||
|
||||
self.app.add_middleware(
|
||||
CORSMiddleware,
|
||||
|
@ -7,8 +7,12 @@ from pagermaid.web.api.ignore_groups import route as ignore_groups_route
|
||||
from pagermaid.web.api.login import route as login_route
|
||||
from pagermaid.web.api.plugin import route as plugin_route
|
||||
from pagermaid.web.api.status import route as status_route
|
||||
from pagermaid.web.api.web_login import route as web_login_route, html_route as web_login_html_route
|
||||
|
||||
__all__ = ["authentication", "base_api_router", "base_html_router"]
|
||||
|
||||
base_api_router = APIRouter(prefix="/pagermaid/api")
|
||||
base_html_router = APIRouter()
|
||||
|
||||
base_api_router.include_router(plugin_route)
|
||||
base_api_router.include_router(bot_info_route)
|
||||
@ -16,3 +20,5 @@ base_api_router.include_router(status_route)
|
||||
base_api_router.include_router(login_route)
|
||||
base_api_router.include_router(command_alias_route)
|
||||
base_api_router.include_router(ignore_groups_route)
|
||||
base_api_router.include_router(web_login_route)
|
||||
base_html_router.include_router(web_login_html_route)
|
||||
|
125
pagermaid/web/api/web_login.py
Normal file
125
pagermaid/web/api/web_login.py
Normal file
@ -0,0 +1,125 @@
|
||||
from fastapi import APIRouter
|
||||
from fastapi.responses import JSONResponse
|
||||
from pydantic import BaseModel
|
||||
from pyrogram.errors import BadRequest, AuthTokenExpired
|
||||
from pyrogram.raw.functions.account import InitTakeoutSession
|
||||
from pyrogram.raw.functions.updates import GetState
|
||||
from starlette.responses import HTMLResponse
|
||||
|
||||
from pagermaid import bot, logs
|
||||
from pagermaid.common.reload import load_all
|
||||
from pagermaid.utils import lang, process_exit
|
||||
from pagermaid.web.api import authentication
|
||||
from pagermaid.web.html import get_web_login_html
|
||||
from pyromod.methods.sign_in_qrcode import authorize_by_qrcode_web
|
||||
from pyromod.utils.errors import QRCodeWebCodeError, QRCodeWebNeedPWDError
|
||||
import sys
|
||||
|
||||
|
||||
class UserModel(BaseModel):
|
||||
password: str
|
||||
|
||||
|
||||
class WebLogin():
|
||||
def __init__(self):
|
||||
self.is_authorized = False
|
||||
self.need_password = False
|
||||
self.password_hint = ""
|
||||
|
||||
async def connect(self):
|
||||
if not bot.is_connected:
|
||||
self.is_authorized = await bot.connect()
|
||||
|
||||
@staticmethod
|
||||
async def initialize():
|
||||
if bot.is_connected and not bot.is_initialized:
|
||||
await bot.initialize()
|
||||
|
||||
@staticmethod
|
||||
def has_login():
|
||||
return bot.me is not None
|
||||
|
||||
@staticmethod
|
||||
async def init_bot():
|
||||
logs.info(f"{lang('save_id')} {bot.me.first_name}({bot.me.id})")
|
||||
await load_all()
|
||||
await process_exit(start=True, _client=bot)
|
||||
logs.info(lang("start"))
|
||||
|
||||
async def init(self):
|
||||
await self.connect()
|
||||
if not self.is_authorized:
|
||||
return
|
||||
if not await bot.storage.is_bot() and bot.takeout:
|
||||
bot.takeout_id = (
|
||||
await bot.invoke(InitTakeoutSession())
|
||||
).id
|
||||
|
||||
await bot.invoke(GetState())
|
||||
bot.me = await bot.get_me()
|
||||
if bot.me.is_bot:
|
||||
sys.exit(0)
|
||||
await self.initialize()
|
||||
await self.init_bot()
|
||||
|
||||
|
||||
route = APIRouter()
|
||||
html_route = APIRouter()
|
||||
web_login = WebLogin()
|
||||
web_login_html = get_web_login_html()
|
||||
|
||||
|
||||
@route.get("/web_login", response_class=JSONResponse, dependencies=[authentication()])
|
||||
async def web_login_qrcode():
|
||||
if web_login.has_login():
|
||||
return {"status": 0, "msg": "已登录"}
|
||||
try:
|
||||
await web_login.connect()
|
||||
if not web_login.is_authorized:
|
||||
await authorize_by_qrcode_web(bot)
|
||||
web_login.is_authorized = True
|
||||
await web_login.init()
|
||||
return {"status": 0, "msg": "登录成功"}
|
||||
except QRCodeWebCodeError as e:
|
||||
web_login.need_password = False
|
||||
return {"status": 1, "msg": "未扫码", "content": e.code}
|
||||
except QRCodeWebNeedPWDError as e:
|
||||
web_login.need_password = True
|
||||
web_login.password_hint = e.hint or ""
|
||||
return {"status": 2, "msg": "需要密码", "content": web_login.password_hint}
|
||||
except AuthTokenExpired:
|
||||
return {"status": 3, "msg": "登录状态过期,请重新扫码登录"}
|
||||
except BadRequest as e:
|
||||
return {"status": 3, "msg": e.MESSAGE}
|
||||
except Exception as e:
|
||||
return {"status": 3, "msg": f"{type(e)}"}
|
||||
|
||||
|
||||
@route.post("/web_login", response_class=JSONResponse, dependencies=[authentication()])
|
||||
async def web_login_password(user: UserModel):
|
||||
if web_login.has_login():
|
||||
return {"status": 0, "msg": "已登录"}
|
||||
if not web_login.need_password:
|
||||
return {"status": 0, "msg": "无需密码"}
|
||||
try:
|
||||
await authorize_by_qrcode_web(bot, user.password)
|
||||
web_login.is_authorized = True
|
||||
await web_login.init()
|
||||
return {"status": 0, "msg": "登录成功"}
|
||||
except QRCodeWebCodeError as e:
|
||||
return {"status": 1, "msg": "需要重新扫码", "content": e.code}
|
||||
except QRCodeWebNeedPWDError as e:
|
||||
web_login.need_password = True
|
||||
return {"status": 2, "msg": "密码错误", "content": e.hint or ""}
|
||||
except AuthTokenExpired:
|
||||
web_login.need_password = False
|
||||
return {"status": 3, "msg": "登录状态过期,请重新扫码登录"}
|
||||
except BadRequest as e:
|
||||
return {"status": 3, "msg": e.MESSAGE}
|
||||
except Exception as e:
|
||||
return {"status": 3, "msg": f"{type(e)}"}
|
||||
|
||||
|
||||
@html_route.get("/web_login", response_class=HTMLResponse)
|
||||
async def get_web_login():
|
||||
return web_login_html
|
@ -22,3 +22,8 @@ def get_github_logo() -> str:
|
||||
def get_footer() -> str:
|
||||
"""获取 footer。"""
|
||||
return get_html(html_base_path / "footer.html")
|
||||
|
||||
|
||||
def get_web_login_html() -> str:
|
||||
"""获取 web login。"""
|
||||
return get_html(html_base_path / "web_login.html")
|
||||
|
202
pagermaid/web/html/web_login.html
Normal file
202
pagermaid/web/html/web_login.html
Normal file
@ -0,0 +1,202 @@
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
|
||||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/bootstrap/5.3.0/css/bootstrap.min.css" integrity="sha512-t4GWSVZO1eC8BM339Xd7Uphw5s17a86tIZIj8qRxhnKub6WoyhnrxeCIMeAqBPgdZGlCcG2PrZjMc+Wr78+5Xg==" crossorigin="anonymous" referrerpolicy="no-referrer" />
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/bootstrap/5.3.0/js/bootstrap.min.js" integrity="sha512-3dZ9wIrMMij8rOH7X3kLfXAzwtcHpuYpEgQg1OA4QAob1e81H8ntUQmQm3pBudqIoySO5j0tHN4ENzA6+n2r4w==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/qrcodejs/1.0.0/qrcode.min.js" integrity="sha512-CNgIRecGo7nphbeZ04Sc13ka07paqdeTu0WR1IM4kNcpmBAUSHSQX0FslNhTDadL4O5SAGapGt4FodqL8My0mA==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/axios/1.4.0/axios.min.js" integrity="sha512-uMtXmF28A2Ab/JJO2t/vYhlaa/3ahUOgj1Zf27M5rOo8/+fcTUVH0/E0ll68njmjrLqOBjXM3V9NiPFL5ywWPQ==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
|
||||
|
||||
<title>QR Code Login - PagerMaid-Pyro</title>
|
||||
<style>
|
||||
img {
|
||||
display: inline-block!important;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="container mt-4">
|
||||
<div class="row justify-content-center">
|
||||
<div class="col-md-6 col-lg-4">
|
||||
<div class="card" style="">
|
||||
<div class="card-header bg-dark text-white text-center">
|
||||
<h3 class="mb-0">QR Code Login</h3>
|
||||
</div>
|
||||
<div class="card-body" style="display: block" id="qrDiv">
|
||||
<div id="qr" class="text-center mb-0"></div>
|
||||
<p class="text-center mb-0">Scan the QR code above to log in.</p>
|
||||
</div>
|
||||
<div style="margin-left: 10%; width: 80%; display: block" class="text-center mb-3" id="pwdDiv">
|
||||
<form id="pwdForm">
|
||||
<div class="mb-3" id="pwdHint">
|
||||
<label for="hint" class="form-label">Hint</label>
|
||||
<textarea class="form-control" id="hint" name="hint" disabled></textarea>
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label for="password" class="form-label">Password</label>
|
||||
<input type="password" class="form-control" id="password" name="password" required>
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label for="confirm-password" class="form-label">Confirm Password</label>
|
||||
<input type="password" class="form-control" id="confirm-password" name="confirm-password" required>
|
||||
</div>
|
||||
<button type="submit" class="btn btn-primary" >Submit</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 模态框 -->
|
||||
<div class="modal" id="errorModal">
|
||||
<div class="modal-dialog">
|
||||
<div class="modal-content">
|
||||
|
||||
<!-- 模态框头部 -->
|
||||
<div class="modal-header">
|
||||
<h4 class="modal-title">Notice</h4>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="modal"></button>
|
||||
</div>
|
||||
|
||||
<!-- 模态框内容 -->
|
||||
<div class="modal-body" id="errorText"></div>
|
||||
|
||||
<!-- 模态框底部 -->
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn" data-bs-dismiss="modal" id="errorButton">我知道了</button>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<script>
|
||||
const QRDiv = document.getElementById('qrDiv');
|
||||
const QRC = document.getElementById('qr');
|
||||
const QR = new QRCode(QRC);
|
||||
const PWDDiv = document.getElementById('pwdDiv');
|
||||
const errorModel = new bootstrap.Modal(document.getElementById('errorModal'));
|
||||
const errorText = document.getElementById('errorText');
|
||||
const errorButton = document.getElementById('errorButton');
|
||||
const pwdHint = document.getElementById('pwdHint');
|
||||
const hint = document.getElementById('hint');
|
||||
const password = document.getElementById('password');
|
||||
const confirmPassword = document.getElementById('confirm-password');
|
||||
|
||||
function getHeader() {
|
||||
return {
|
||||
headers: {
|
||||
token: localStorage.getItem("token") || ""
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function redirectToLogin() {
|
||||
window.location.href = '/admin';
|
||||
}
|
||||
|
||||
function showError(text) {
|
||||
if (errorButton.classList.contains('btn-success')) {
|
||||
errorButton.classList.remove('btn-success');
|
||||
}
|
||||
errorButton.classList.add('btn-danger');
|
||||
errorText.innerHTML = text;
|
||||
errorModel.show();
|
||||
}
|
||||
|
||||
function showSuccess(text) {
|
||||
if (errorButton.classList.contains('btn-danger')) {
|
||||
errorButton.classList.remove('btn-danger');
|
||||
}
|
||||
errorButton.classList.add('btn-success');
|
||||
errorText.innerHTML = text;
|
||||
errorModel.show();
|
||||
}
|
||||
|
||||
function process_data(data) {
|
||||
switch (data.status) {
|
||||
case 0:
|
||||
showSuccess(data.msg);
|
||||
redirectToLogin();
|
||||
break;
|
||||
case 1:
|
||||
QRDiv.style.display = 'block';
|
||||
PWDDiv.style.display = 'none';
|
||||
QR.makeCode(data.content);
|
||||
break;
|
||||
case 2:
|
||||
QRDiv.style.display = 'none';
|
||||
PWDDiv.style.display = 'block';
|
||||
if (data.content !== '') {
|
||||
pwdHint.style.display = 'block';
|
||||
hint.innerHTML = data.content;
|
||||
} else {
|
||||
pwdHint.style.display = 'none';
|
||||
}
|
||||
break;
|
||||
case 3:
|
||||
showError(data.msg);
|
||||
break;
|
||||
default:
|
||||
showError('未知错误');
|
||||
}
|
||||
}
|
||||
|
||||
function getQrCode() {
|
||||
if (PWDDiv.style.display === 'block') {
|
||||
return;
|
||||
}
|
||||
axios.get('pagermaid/api/web_login', getHeader())
|
||||
.then(function (response) {
|
||||
const data = response.data;
|
||||
console.log(data);
|
||||
process_data(data);
|
||||
})
|
||||
.catch(function (error) {
|
||||
if (error.response.status !== 200) {
|
||||
redirectToLogin();
|
||||
return;
|
||||
}
|
||||
console.log(error);
|
||||
showError(error.message);
|
||||
});
|
||||
}
|
||||
|
||||
function submitPwd() {
|
||||
const pwd = password.value;
|
||||
const confirmPwd = confirmPassword.value;
|
||||
if (pwd !== confirmPwd) {
|
||||
showError('两次输入的密码不一致');
|
||||
return;
|
||||
}
|
||||
axios.post('pagermaid/api/web_login', {
|
||||
password: pwd
|
||||
}, getHeader())
|
||||
.then(function (response) {
|
||||
const data = response.data;
|
||||
console.log(data);
|
||||
process_data(data);
|
||||
})
|
||||
.catch(function (error) {
|
||||
if (error.response.status !== 200) {
|
||||
redirectToLogin();
|
||||
return;
|
||||
}
|
||||
console.log(error);
|
||||
showError(error.message);
|
||||
});
|
||||
}
|
||||
|
||||
PWDDiv.style.display = 'none';
|
||||
document.getElementById("pwdForm").addEventListener('submit', function (e) {
|
||||
e.preventDefault();
|
||||
submitPwd();
|
||||
});
|
||||
getQrCode()
|
||||
setInterval(getQrCode, 20000);
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
@ -1,2 +1,4 @@
|
||||
from .login import login_page
|
||||
from .main import admin_app, blank_page
|
||||
|
||||
__all__ = ["admin_app", "blank_page", "login_page"]
|
||||
|
@ -2,12 +2,9 @@ from amis import (
|
||||
InputText,
|
||||
Switch,
|
||||
Card,
|
||||
Tpl,
|
||||
CardsCRUD,
|
||||
PageSchema,
|
||||
Page,
|
||||
Button,
|
||||
Select,
|
||||
)
|
||||
|
||||
card = Card(
|
||||
|
@ -1,4 +1,4 @@
|
||||
from amis import InputText, Switch, Card, Tpl, CardsCRUD, PageSchema, Page, Button
|
||||
from amis import InputText, Switch, Card, CardsCRUD, PageSchema, Page
|
||||
|
||||
card = Card(
|
||||
header=Card.Header(
|
||||
|
@ -1,21 +0,0 @@
|
||||
"""
|
||||
pyromod - A monkeypatcher add-on for Pyrogram
|
||||
Copyright (C) 2020 Cezar H. <https://github.com/usernein>
|
||||
|
||||
This file is part of pyromod.
|
||||
|
||||
pyromod is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
pyromod is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with pyromod. If not, see <https://www.gnu.org/licenses/>.
|
||||
"""
|
||||
|
||||
from .filters import dice
|
@ -1,28 +0,0 @@
|
||||
"""
|
||||
pyromod - A monkeypatcher add-on for Pyrogram
|
||||
Copyright (C) 2020 Cezar H. <https://github.com/usernein>
|
||||
|
||||
This file is part of pyromod.
|
||||
|
||||
pyromod is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
pyromod is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with pyromod. If not, see <https://www.gnu.org/licenses/>.
|
||||
"""
|
||||
|
||||
import pyrogram
|
||||
|
||||
|
||||
def dice(ctx, message):
|
||||
return hasattr(message, "dice") and message.dice
|
||||
|
||||
|
||||
pyrogram.filters.dice = dice
|
@ -17,5 +17,6 @@ GNU General Public License for more details.
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with pyromod. If not, see <https://www.gnu.org/licenses/>.
|
||||
"""
|
||||
|
||||
from .listen import Client, MessageHandler, Chat, User
|
||||
|
||||
__all__ = ["Client", "MessageHandler", "Chat", "User"]
|
||||
|
@ -27,7 +27,7 @@ from typing import Optional, List, Union
|
||||
import pyrogram
|
||||
from pyrogram.enums import ChatType
|
||||
|
||||
from pagermaid.single_utils import get_sudo_list, Message
|
||||
from pagermaid.single_utils import get_sudo_list
|
||||
from pagermaid.scheduler import add_delete_message_job
|
||||
from ..methods.get_dialogs_list import get_dialogs_list as get_dialogs_list_func
|
||||
from ..methods.read_chat_history import read_chat_history as read_chat_history_func
|
||||
|
@ -10,6 +10,7 @@ from pyrogram.session import Auth, Session
|
||||
from pyrogram.utils import ainput
|
||||
|
||||
from pagermaid import Config
|
||||
from pyromod.utils.errors import QRCodeWebNeedPWDError, QRCodeWebCodeError
|
||||
|
||||
|
||||
async def sign_in_qrcode(
|
||||
@ -117,6 +118,32 @@ async def authorize_by_qrcode(
|
||||
return qrcode
|
||||
|
||||
|
||||
async def authorize_by_qrcode_web(
|
||||
client: Client,
|
||||
password: Optional[str] = None,
|
||||
):
|
||||
qrcode = None
|
||||
try:
|
||||
if password:
|
||||
client.password = password
|
||||
raise SessionPasswordNeeded()
|
||||
qrcode = await sign_in_qrcode(client)
|
||||
except BadRequest as e:
|
||||
raise e
|
||||
except SessionPasswordNeeded as e:
|
||||
try:
|
||||
if client.password:
|
||||
return await client.check_password(client.password)
|
||||
except BadRequest as e:
|
||||
client.password = None
|
||||
raise e
|
||||
raise QRCodeWebNeedPWDError(await client.get_password_hint()) from e
|
||||
if isinstance(qrcode, str):
|
||||
raise QRCodeWebCodeError(qrcode)
|
||||
elif isinstance(qrcode, pyrogram.types.User):
|
||||
return qrcode
|
||||
|
||||
|
||||
async def start_client(client: Client):
|
||||
is_authorized = await client.connect()
|
||||
|
||||
|
@ -17,5 +17,6 @@ GNU General Public License for more details.
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with pyromod. If not, see <https://www.gnu.org/licenses/>.
|
||||
"""
|
||||
|
||||
from .utils import patch, patchable
|
||||
|
||||
__all__ = ["patch", "patchable"]
|
||||
|
@ -26,3 +26,33 @@ class ListenerCanceled(Exception):
|
||||
|
||||
def __init__(self):
|
||||
super().__init__("Listener was canceled")
|
||||
|
||||
|
||||
class QRCodeWebError(Exception):
|
||||
"""
|
||||
Occurs when the QR code is not scanned.
|
||||
"""
|
||||
|
||||
def __init__(self, msg: str):
|
||||
self.msg = msg
|
||||
super().__init__("QR code not scanned")
|
||||
|
||||
|
||||
class QRCodeWebCodeError(QRCodeWebError):
|
||||
"""
|
||||
Occurs when the QR code is not scanned.
|
||||
"""
|
||||
|
||||
def __init__(self, code: str):
|
||||
self.code = code
|
||||
super().__init__("QR code not scanned")
|
||||
|
||||
|
||||
class QRCodeWebNeedPWDError(QRCodeWebError):
|
||||
"""
|
||||
Occurs when the account needs to be verified.
|
||||
"""
|
||||
|
||||
def __init__(self, hint: str):
|
||||
self.hint = hint
|
||||
super().__init__("Account needs to be verified")
|
||||
|
@ -20,7 +20,8 @@ configure () {
|
||||
printf "请输入应用程序 api_hash(不懂请直接回车):"
|
||||
read -r api_hash <&1
|
||||
sed -i "s/HASH_HERE/$api_hash/" $config_file
|
||||
read -p "二维码扫码登录?(避免无法收到验证码) [Y/n]" choi
|
||||
printf "控制台二维码扫码登录?(避免无法收到验证码) [Y/n]"
|
||||
read -r choi <&1
|
||||
if [ "$choi" == "y" ] || [ "$choi" == "Y" ]; then
|
||||
sed -i "s/qrcode_login: \"False\"/qrcode_login: \"True\"/" $config_file
|
||||
fi
|
||||
@ -40,29 +41,22 @@ configure () {
|
||||
else
|
||||
sed -i "s/China/$application_region/" $config_file
|
||||
fi
|
||||
printf "请输入 Google TTS 语言(默认:zh-CN):"
|
||||
read -r application_tts <&1
|
||||
if [ -z "$application_tts" ]
|
||||
then
|
||||
echo "tts发音语言设置为 简体中文"
|
||||
else
|
||||
sed -i "s/zh-CN/$application_tts/" $config_file
|
||||
fi
|
||||
}
|
||||
|
||||
login () {
|
||||
echo
|
||||
echo "下面进行程序运行。"
|
||||
echo "请在账户授权完毕后,按 Ctrl + C 使 Docker 在后台模式下运行。"
|
||||
echo "如果已开启网页登录,请直接使用 Ctrl + C 使 Docker 在后台模式下运行。"
|
||||
echo
|
||||
sleep 2
|
||||
echo "Hello world!" > /pagermaid/workdir/install.lock
|
||||
sleep 2
|
||||
python -m pagermaid
|
||||
exit 0
|
||||
}
|
||||
|
||||
main () {
|
||||
cd /pagermaid/workdir
|
||||
cd /pagermaid/workdir || exit
|
||||
if [ ! -s "/pagermaid/workdir/install.lock" ]; then
|
||||
welcome
|
||||
configure
|
||||
|
@ -74,11 +74,32 @@ need_web () {
|
||||
esac
|
||||
}
|
||||
|
||||
need_web_login () {
|
||||
PGM_WEB_LOGIN=false
|
||||
case $PGM_WEB in
|
||||
true)
|
||||
printf "请问是否需要启用 Web 登录界面 [Y/n] :"
|
||||
read -r web_login <&1
|
||||
case $web_login in
|
||||
[yY][eE][sS] | [yY])
|
||||
echo "您已确认需要启用 Web 登录界面 . . ."
|
||||
PGM_WEB_LOGIN=true
|
||||
;;
|
||||
[nN][oO] | [nN])
|
||||
;;
|
||||
*)
|
||||
echo "输入错误,已跳过。"
|
||||
;;
|
||||
esac
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
start_docker () {
|
||||
echo "正在启动 Docker 容器 . . ."
|
||||
case $PGM_WEB in
|
||||
true)
|
||||
docker run -dit --restart=always --name="$container_name" --hostname="$container_name" -e WEB_ENABLE="$PGM_WEB" -e WEB_SECRET_KEY="$admin_password" -e WEB_HOST=0.0.0.0 -e WEB_PORT=3333 -p 3333:3333 teampgm/pagermaid_pyro <&1
|
||||
docker run -dit --restart=always --name="$container_name" --hostname="$container_name" -e WEB_ENABLE="$PGM_WEB" -e WEB_SECRET_KEY="$admin_password" -e WEB_HOST=0.0.0.0 -e WEB_PORT=3333 -e WEB_LOGIN="$PGM_WEB_LOGIN" -p 3333:3333 teampgm/pagermaid_pyro <&1
|
||||
;;
|
||||
*)
|
||||
docker run -dit --restart=always --name="$container_name" --hostname="$container_name" teampgm/pagermaid_pyro <&1
|
||||
@ -148,6 +169,7 @@ start_installation () {
|
||||
access_check
|
||||
build_docker
|
||||
need_web
|
||||
need_web_login
|
||||
start_docker
|
||||
data_persistence
|
||||
}
|
||||
@ -216,6 +238,7 @@ reinstall_pager () {
|
||||
cleanup
|
||||
build_docker
|
||||
need_web
|
||||
need_web_login
|
||||
start_docker
|
||||
data_persistence
|
||||
}
|
||||
@ -237,10 +260,10 @@ shon_online () {
|
||||
echo " 6) Docker 重装 PagerMaid"
|
||||
echo " 7) 退出脚本"
|
||||
echo
|
||||
echo " Version:2.1.0"
|
||||
echo " Version:2.2.0"
|
||||
echo
|
||||
echo -n "请输入编号: "
|
||||
read N
|
||||
read -r N <&1
|
||||
case $N in
|
||||
1)
|
||||
start_installation
|
||||
|
Loading…
Reference in New Issue
Block a user