pyscriptbase 1.0.1__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
pybase/panel.py ADDED
@@ -0,0 +1,194 @@
1
+ # encoding=utf8
2
+
3
+ import requests
4
+ import warnings
5
+ from json import dumps as jsonDumps
6
+ from typing import List
7
+
8
+ warnings.filterwarnings("ignore")
9
+
10
+
11
+ class Envrionment:
12
+ def __init__(self, id: int, name: str, value: str, remarks: str = "") -> None:
13
+ """
14
+ 初始化
15
+ """
16
+ self.id = id
17
+ self.name = name
18
+ self.value = value
19
+ self.remarks = ""
20
+
21
+ def toJson(self) -> dict:
22
+ return {
23
+ "id": self.id,
24
+ "name": self.name,
25
+ "value": self.value,
26
+ "remarks": self.remarks,
27
+ }
28
+
29
+
30
+ class PanelClient:
31
+ headers = {"content-type": "application/json", "accept": "application/json"}
32
+
33
+ def __init__(self, address: str, id: str, secret: str) -> None:
34
+ """
35
+ 初始化
36
+ """
37
+ self.address = self.__validAddress__(address)
38
+ self.clientId = id
39
+ self.clientSecret = secret
40
+ self.valid = False
41
+ self.session = requests.session()
42
+ self.session.headers.update(self.headers)
43
+
44
+ self.__login__()
45
+
46
+ def __validAddress__(self, address: str) -> str:
47
+ if not address.startswith("http://") and not address.startswith("https://"):
48
+ address = f"http://{address}"
49
+ if address.endswith("/"):
50
+ address = address[0:-1]
51
+ return address
52
+
53
+ def __log__(self, content: str, start="", end="\n") -> None:
54
+ """
55
+ 日志
56
+ """
57
+ print(content)
58
+
59
+ def __login__(self) -> None:
60
+ """
61
+ 登录
62
+ """
63
+ url = f"{self.address}/open/auth/token?client_id={self.clientId}&client_secret={self.clientSecret}"
64
+ try:
65
+ rjson = self.session.get(url, verify=False).json()
66
+ if rjson["code"] == 200:
67
+ self.auth = f"{rjson['data']['token_type']} {rjson['data']['token']}"
68
+ self.session.headers.update({"Authorization": self.auth})
69
+ self.valid = True
70
+ self.__log__(f"面板登录成功:{rjson['data']['token']}", start="\n")
71
+ else:
72
+ self.valid = False
73
+ self.__log__(f"面板登录失败:{rjson['message']}", start="\n")
74
+ except Exception as e:
75
+ self.valid = False
76
+ self.__log__(f"面板登录失败:{str(e)}", start="\n")
77
+
78
+ def addEnvs(self, envs: List[Envrionment]) -> bool:
79
+ """
80
+ 新建环境变量
81
+ """
82
+ url = f"{self.address}/open/envs"
83
+ try:
84
+ body = []
85
+ for env in envs:
86
+ body.append({"name": env.name, "value": env.value, "remarks": env.remarks})
87
+ rjson = self.session.post(url, data=jsonDumps(body), verify=False).json()
88
+ if rjson["code"] == 200:
89
+ self.__log__(f"新建环境变量成功:{len(envs)}")
90
+ return True
91
+ else:
92
+ self.__log__(f"新建环境变量失败:{rjson['message']}")
93
+ return False
94
+ except Exception as e:
95
+ self.__log__(f"新建环境变量失败:{str(e)}")
96
+ return False
97
+
98
+ def updateEnvs(self, env: Envrionment) -> bool:
99
+ """
100
+ 更新环境变量
101
+ """
102
+ url = f"{self.address}/open/envs"
103
+ try:
104
+ body = jsonDumps(env.toJson())
105
+ rjson = self.session.put(url, verify=False, data=body).json()
106
+ if rjson["code"] == 200:
107
+ self.__log__(f"更新环境变量成功")
108
+ else:
109
+ self.__log__(f"更新环境变量失败:{rjson['message']}")
110
+ except Exception as e:
111
+ self.__log__(f"更新环境变量失败:{str(e)}")
112
+
113
+ def addOrUpdateEnv(self, env: Envrionment) -> bool:
114
+ """
115
+ 添加或更新环境变量
116
+ """
117
+ envs = self.getEnvs()
118
+ if not envs:
119
+ self.addEnvs([env])
120
+ return True
121
+ for env_ in envs:
122
+ if env_.name == env.name:
123
+ env.id = env_.id
124
+ self.updateEnvs(env)
125
+ return True
126
+ self.addEnvs([env])
127
+
128
+ def getEnvs(self, search: str = "") -> list[Envrionment]:
129
+ """
130
+ 获取环境变量
131
+ """
132
+ url = f"{self.address}/open/envs?searchValue={search}"
133
+ result: list[Envrionment] = []
134
+ try:
135
+ rjson = self.session.get(url, verify=False).json()
136
+ if rjson["code"] == 200:
137
+ for env in rjson["data"]:
138
+ result.append(Envrionment(env["id"], env["name"], env["value"], env["remarks"]))
139
+ else:
140
+ self.__log__(f"获取环境变量失败:{rjson['message']}")
141
+ except Exception as e:
142
+ self.__log__(f"获取环境变量失败:{str(e)}")
143
+ return result
144
+
145
+ def deleteEnvs(self, ids: list[int]) -> bool:
146
+ """
147
+ 删除环境变量
148
+ """
149
+ url = f"{self.address}/open/envs"
150
+ try:
151
+ rjson = self.session.delete(url, data=jsonDumps(ids), verify=False).json()
152
+ if rjson["code"] == 200:
153
+ self.__log__(f"删除环境变量成功:{len(ids)}")
154
+ return True
155
+ else:
156
+ self.__log__(f"删除环境变量失败:{rjson['message']}")
157
+ return False
158
+ except Exception as e:
159
+ self.__log__(f"删除环境变量失败:{str(e)}")
160
+ return False
161
+
162
+ def enableEnvs(self, ids: list[int]) -> bool:
163
+ """
164
+ 启用环境变量
165
+ """
166
+ url = f"{self.address}/open/envs/enable"
167
+ try:
168
+ rjson = self.session.put(url, data=jsonDumps(ids), verify=False).json()
169
+ if rjson["code"] == 200:
170
+ self.__log__(f"启用环境变量成功:{len(ids)}")
171
+ return True
172
+ else:
173
+ self.__log__(f"启用环境变量失败:{rjson['message']}")
174
+ return False
175
+ except Exception as e:
176
+ self.__log__(f"启用环境变量失败:{str(e)}")
177
+ return False
178
+
179
+ def disableEnvs(self, ids: list[int]) -> bool:
180
+ """
181
+ 禁用环境变量
182
+ """
183
+ url = f"{self.address}/open/envs/disable"
184
+ try:
185
+ rjson = self.session.put(url, data=jsonDumps(ids), verify=False).json()
186
+ if rjson["code"] == 200:
187
+ self.__log__(f"禁用环境变量成功:{len(ids)}")
188
+ return True
189
+ else:
190
+ self.__log__(f"禁用环境变量失败:{rjson['message']}")
191
+ return False
192
+ except Exception as e:
193
+ self.__log__(f"禁用环境变量失败:{str(e)}")
194
+ return False
pybase/pusher.py ADDED
@@ -0,0 +1,194 @@
1
+ import smtplib
2
+ from email.mime.multipart import MIMEMultipart
3
+ from email.mime.text import MIMEText
4
+ from . import env as Env
5
+
6
+
7
+ class HtmlTableEmail:
8
+ """
9
+ HTML表格对象
10
+ @headers=列数
11
+ @rows=函数 不足自动补充空字符串 多余则忽略 [str|int|tuple] tuple=(str|int,G|R)有颜色
12
+ @extras 末尾额外信息
13
+ """
14
+
15
+ def __init__(self, title: str, headers: list[str] = [], appendIndex: bool = True):
16
+ self.title = title
17
+ self.headers: list[str] = headers
18
+ self.rows: list[str | int] = []
19
+ self.extras: list[str] = []
20
+ self.appendIndex = appendIndex
21
+
22
+ def toStr(self) -> str:
23
+ result = ""
24
+ for index, row in enumerate(self.rows):
25
+ result += f"[{index+1}] "
26
+ for i in range(len(row)):
27
+ if isinstance(row[i], tuple) and len(row[i]) >= 1:
28
+ result += f"{row[i][0]} "
29
+ else:
30
+ result += f"{row[i]} "
31
+ result += "\n"
32
+ for extra in self.extras:
33
+ result += f"\n{extra}\n"
34
+ return result
35
+
36
+ def toHtml(self) -> str:
37
+ table = self
38
+ thead = ""
39
+ tbody = ""
40
+ extras = ""
41
+
42
+ if table.appendIndex:
43
+ thead += "<th></th>"
44
+ for header in table.headers:
45
+ thead += f"<th>{header}</th>"
46
+
47
+ for index, row in enumerate(table.rows):
48
+ trs = ""
49
+ if table.appendIndex:
50
+ trs += f"<td>{index+1}</td>"
51
+ for i in range(len(table.headers)):
52
+ if len(row) - 1 >= i:
53
+ if isinstance(row[i], tuple) and len(row[i]) >= 2:
54
+ # 颜色
55
+ if str(row[i][1]).upper in ["G", "GREEN"]:
56
+ trs += f"<td class='green'>{row[i][0]}</td>"
57
+ else:
58
+ trs += f"<td class='red'>{row[i][0]}</td>"
59
+ else:
60
+ # 常规
61
+ trs += f"<td>{row[i]}</td>"
62
+ else:
63
+ trs += "<td></td>"
64
+ tbody += f"<tr>{trs}</tr>"
65
+
66
+ if table.extras:
67
+ extras = '<tr><th colspan="$$spans$$">其他报告</th></tr>'
68
+ for extra in table.extras:
69
+ extras += f'<tr><td colspan="$$spans$$">{extra}</td></tr>'
70
+
71
+ html = """
72
+ <!DOCTYPE html>
73
+ <html lang="zh-CN">
74
+ <head>
75
+ <meta charset="UTF-8" />
76
+ <title></title>
77
+ <style>
78
+ table {
79
+ width: 100%; /* 设置表格宽度 */
80
+ margin: auto; /* 表格居中 */
81
+ border-collapse: collapse; /* 边框合并 */
82
+ font-size: 14px;
83
+ text-align: center; /* 文本居中 */
84
+ }
85
+ th,
86
+ td {
87
+ padding: 10px; /* 内边距 */
88
+ border: 1px solid #ddd; /* 边框样式 */
89
+ }
90
+ th {
91
+ background-color: #f2f2f2; /* 表头背景颜色 */
92
+ }
93
+ tr:nth-child(even) {
94
+ background-color: #f9f9f9; /* 隔行变色 */
95
+ }
96
+ caption {
97
+ font-size: 1.5em;
98
+ margin-bottom: 10px;
99
+ }
100
+ .green {
101
+ color: green; /* 绿色文本 */
102
+ }
103
+ .red {
104
+ color: red; /* 红色文本 */
105
+ }
106
+ </style>
107
+ </head>
108
+ <body>
109
+ <table>
110
+ <thead><tr>$$thead$$</tr></thead>
111
+ <tbody>
112
+ $$tbody$$
113
+ $$extras$$
114
+ </tbody>
115
+ </table>
116
+ </body>
117
+ </html>
118
+ """
119
+ spans = len(table.headers) + (1 if table.appendIndex else 0)
120
+ html = html.replace("$$thead$$", thead)
121
+ html = html.replace("$$tbody$$", tbody)
122
+ html = html.replace("$$extras$$", extras)
123
+ html = html.replace("$$spans$$", str(spans))
124
+ return html
125
+
126
+
127
+ class SMTPParams:
128
+ def __init__(self, server: str, port: int, sender: str, password: str):
129
+ self.server = server
130
+ self.port = port
131
+ self.sender = sender
132
+ self.password = password
133
+
134
+
135
+ def sendQQMail(title: str, content: str, receiver: str = None, params: SMTPParams = None):
136
+ # 设置SMTP服务器地址和端口
137
+ smtp_server = params.server if params else Env.get("smtp_server")
138
+ port = params.port if params else Env.getInt("smtp_port") # 对于TLS,通常使用587端口;对于SSL,使用465端口
139
+ sender = params.sender if params else Env.get("smtp_sender") # 你的电子邮件地址
140
+ password = params.password if params else Env.get("smtp_password") # 你的电子邮件密码(对于某些电子邮件提供商,你可能需要生成一个应用专用密码)
141
+ receiver = receiver if receiver else Env.get("smtp_receiver")
142
+
143
+ if not sender or not password:
144
+ return
145
+
146
+ # 创建消息对象
147
+ message = MIMEMultipart()
148
+ message["From"] = sender
149
+ message["To"] = receiver
150
+ message["Subject"] = title # 邮件主题
151
+ body = content # 邮件正文
152
+ message.attach(MIMEText(body, "plain"))
153
+
154
+ # 连接到SMTP服务器并发送邮件
155
+ try:
156
+ server = smtplib.SMTP(smtp_server, port)
157
+ server.starttls() # 启动TLS模式
158
+ server.login(sender, password) # 登录你的账户
159
+ server.sendmail(sender, receiver, message.as_string()) # 发送邮件
160
+ except Exception as e:
161
+ print(f"Error: unable to send email. {e}")
162
+
163
+
164
+ def sendMail(title: str, content: str | HtmlTableEmail, receiver: str = None, params: SMTPParams = None):
165
+ # 设置SMTP服务器地址和端口
166
+ smtp_server = params.server if params else Env.get("smtp_server")
167
+ port = params.port if params else Env.getInt("smtp_port") # 对于TLS,通常使用587端口;对于SSL,使用465端口
168
+ sender = params.sender if params else Env.get("smtp_sender") # 你的电子邮件地址
169
+ password = params.password if params else Env.get("smtp_password") # 你的电子邮件密码(对于某些电子邮件提供商,你可能需要生成一个应用专用密码)
170
+ receiver = receiver if receiver else Env.get("smtp_receiver")
171
+
172
+ if not sender or not password:
173
+ return
174
+
175
+ # 创建消息对象
176
+ message = MIMEMultipart()
177
+ message["From"] = sender
178
+ message["To"] = receiver
179
+ message["Subject"] = title # 邮件主题
180
+ if isinstance(content, HtmlTableEmail):
181
+ body = content.toHtml() # 邮件正文
182
+ message.attach(MIMEText(body, "html"))
183
+ else:
184
+ body = content # 邮件正文
185
+ message.attach(MIMEText(body, "plain"))
186
+
187
+ # 连接到SMTP服务器并发送邮件
188
+ try:
189
+ server = smtplib.SMTP(smtp_server, port)
190
+ server.starttls() # 启动TLS模式
191
+ server.login(sender, password) # 登录你的账户
192
+ server.sendmail(sender, receiver, message.as_string()) # 发送邮件
193
+ except Exception as e:
194
+ print(f"Error: unable to send email. {e}")
pybase/script.py ADDED
@@ -0,0 +1,90 @@
1
+ from concurrent.futures import ThreadPoolExecutor, as_completed
2
+ from . import net
3
+ from . import database
4
+
5
+
6
+ class ScriptApp:
7
+ _proxies = []
8
+ _cloudProxies = []
9
+
10
+ def __init__(self, index: int = 1, useProxy: bool = True, debug: bool = False, useCloud: bool = True) -> None:
11
+ self.index = index
12
+ self.logs = []
13
+ self.debug = debug
14
+ self.net = net.NetRequest()
15
+ self.cloudNet = net.CloudRequest()
16
+ self.cloudNet.net = self.net
17
+ useProxy and self.__setProxy__(index)
18
+ useCloud and self.__setCloudProxy__(index)
19
+
20
+ def __setProxy__(self, index: int) -> None:
21
+ config = database.getDataConfig("account", "proxy")
22
+ if not config.user or not config.host or not config.password:
23
+ return
24
+ if len(ScriptApp._proxies) == 0:
25
+ try:
26
+ sql = database.SQLHelper(user=config.user, password=config.password, port=config.port, database=config.database, host=config.host)
27
+ fields = ["host", "port"]
28
+ wheres = [["type", 1], ["state", 1]]
29
+ datas = sql.set_table(config.table).set_wheres(wheres).set_fields(fields).query_dict()
30
+ proxies = [None]
31
+ for data in datas:
32
+ proxies.append({"http": f"http://{data['host']}:{data['port']}", "https": f"http://{data['host']}:{data['port']}"})
33
+ ScriptApp._proxies = proxies
34
+ except:
35
+ ScriptApp._proxies = [None]
36
+ if len(ScriptApp._proxies):
37
+ self.net.proxies = ScriptApp._proxies[index % len(ScriptApp._proxies)]
38
+
39
+ def __setCloudProxy__(self, index: int) -> None:
40
+ config = database.getDataConfig("account", "cloud_proxy")
41
+ if not config.user or not config.host or not config.password:
42
+ return
43
+ if len(ScriptApp._cloudProxies) == 0:
44
+ try:
45
+ sql = database.SQLHelper(user=config.user, password=config.password, port=config.port, database=config.database, host=config.host)
46
+ fields = ["url", "token"]
47
+ wheres = [["state", 1]]
48
+ datas = sql.set_table(config.table).set_wheres(wheres).set_fields(fields).query_dict()
49
+ ScriptApp._cloudProxies = datas
50
+ except:
51
+ ScriptApp._cloudProxies = []
52
+ if len(ScriptApp._cloudProxies):
53
+ self.cloudNet.cloud = ScriptApp._cloudProxies[index % len(ScriptApp._cloudProxies)]
54
+
55
+ def __log__(self, msg: str | dict = "", flush: bool = False):
56
+ if flush or self.debug:
57
+ print(msg, flush=True)
58
+ else:
59
+ if isinstance(msg, str):
60
+ self.logs.append(msg)
61
+ else:
62
+ self.logs.append(str(msg))
63
+
64
+ def __runFunc__(self, fun: callable, *args, **kwargs):
65
+ try:
66
+ return fun(*args, **kwargs)
67
+ except Exception as e:
68
+ self.__log__(e)
69
+
70
+
71
+ class InviteObj:
72
+ id = ""
73
+ accpet: int = 0
74
+ send: int = 0
75
+ params = {}
76
+ target: list[dict] = []
77
+
78
+ def __init__(self):
79
+ pass
80
+
81
+
82
+ def threadPool(func, args, num=5):
83
+ # 启用线程池
84
+ executor = ThreadPoolExecutor(max_workers=num)
85
+ tasks = [executor.submit(func, arg, index + 1) for index, arg in enumerate(args)]
86
+ results = []
87
+ for future in as_completed(tasks):
88
+ data = future.result()
89
+ results.append(data)
90
+ return results
pybase/util.py ADDED
@@ -0,0 +1,86 @@
1
+ from concurrent.futures import ThreadPoolExecutor, as_completed
2
+ from datetime import date, datetime, timedelta
3
+ import random
4
+ import string
5
+
6
+
7
+ def generateRandomPhoneUA():
8
+ # 手机设备品牌与型号
9
+ devices = ["Samsung Galaxy S21", "Xiaomi Mi 11", "Google Pixel 6", "Huawei P40", "OPPO Reno5", "Vivo X60", "OnePlus 9"]
10
+
11
+ # 操作系统版本
12
+ os_versions = ["Android 11", "Android 12", "Android 13"]
13
+
14
+ # 浏览器类型
15
+ browsers = ["Chrome"]
16
+
17
+ # 随机选择设备、操作系统和浏览器
18
+ device = random.choice(devices)
19
+ os_version = random.choice(os_versions)
20
+ browser = random.choice(browsers)
21
+
22
+ # 构建完整的User-Agent字符串
23
+ ua_base = f"Mozilla/5.0 ({device}; Android {os_version}; Mobile) AppleWebKit"
24
+ ua = f"{ua_base}/537.36 (KHTML, like Gecko) {browser}/{random.randint(80, 99)}.0.{random.randint(0, 99)} Mobile Safari/537.36"
25
+
26
+ return ua
27
+
28
+
29
+ def generateRandomStr(len: int):
30
+ return "".join(random.choices(string.ascii_letters + string.digits, k=len))
31
+
32
+
33
+ def getNextHourSeconds() -> float:
34
+ # 获取当前时间
35
+ now = datetime.now()
36
+ # 计算下一小时的时间点
37
+ next_hour = (now + timedelta(hours=1)).replace(minute=0, second=0, microsecond=0)
38
+ # 计算距离下一小时的总秒数
39
+ seconds_until_next_hour = (next_hour - now).total_seconds()
40
+ return seconds_until_next_hour
41
+
42
+
43
+ def formatTimestamp(ts: int | float | str = None) -> str:
44
+ if isinstance(ts, int) or isinstance(ts, float):
45
+ return datetime.fromtimestamp(ts).strftime("%Y-%m-%d %H:%M:%S")
46
+ elif ts == None:
47
+ return datetime.now().strftime("%Y-%m-%d %H:%M:%S.%f")[:-3]
48
+ else:
49
+ return ts
50
+
51
+
52
+ def formatDate(ts: int, split="") -> str:
53
+ return datetime.fromtimestamp(ts).strftime(f"%Y{split}%m{split}%d")
54
+
55
+
56
+ def isLastDayOfMonth():
57
+ today = date.today()
58
+ next_day = today + timedelta(days=1)
59
+ return next_day.month != today.month
60
+
61
+
62
+ def daysDifference(date_str: str) -> int:
63
+ # 尝试将输入的日期字符串转换为datetime对象
64
+ try:
65
+ # 假设输入的日期格式是'yyyy-mm-dd'
66
+ input_date = datetime.strptime(date_str, "%Y-%m-%d").date()
67
+ except ValueError:
68
+ # 如果日期格式不正确,返回错误信息或处理异常
69
+ return 0
70
+
71
+ # 获取今天的日期
72
+ today = datetime.now().date()
73
+
74
+ # 计算两个日期之间的天数差
75
+ delta = today - input_date
76
+ days_diff = delta.days
77
+
78
+ return days_diff
79
+
80
+
81
+ def threadPool(func, args, num=5):
82
+ # 启用线程池
83
+ executor = ThreadPoolExecutor(max_workers=num)
84
+ tasks = [executor.submit(func, arg, index + 1) for index, arg in enumerate(args)]
85
+ for future in as_completed(tasks):
86
+ data = future.result()
pybase/webview.py ADDED
@@ -0,0 +1,54 @@
1
+ import platform
2
+ from time import sleep
3
+ from . import env
4
+ from selenium import webdriver
5
+ from traceback import format_exc
6
+ import os
7
+ from pathlib import Path
8
+ from selenium.webdriver.common.by import By
9
+
10
+ ENV_NAME = "remote_selenium"
11
+
12
+
13
+ def buildDriver(options: webdriver.ChromeOptions, rm: bool = True) -> webdriver.Chrome:
14
+ """
15
+ 获取一个WebDriver实例
16
+ 环境变量: remote_selenium 远程地址
17
+ """
18
+ remote = env.get(ENV_NAME)
19
+ if rm and remote:
20
+ return webdriver.Remote(command_executor=remote, options=options)
21
+ else:
22
+ return webdriver.Chrome(options=options)
23
+
24
+
25
+ def getUserDir(project: str, user: str):
26
+ """
27
+ 获取用户数据目录
28
+ """
29
+ if platform.system().lower() == "windows":
30
+ dirs = ["E:", "cache", "selenium", project, user]
31
+ else:
32
+ dirs = [str(Path.home()), "cache", "selenium", project, user]
33
+ return os.sep.join(dirs)
34
+
35
+
36
+ def clearUserData(driver: webdriver.Chrome):
37
+ """
38
+ 清除用户数据
39
+ """
40
+ try:
41
+ driver.get("chrome://settings/clearBrowserData")
42
+ sleep(2)
43
+ checkes = driver.find_elements(By.CLASS_NAME, "settings-checkbox")
44
+ for checke in checkes:
45
+ label = checke.text.lower()
46
+ checked = checke.get_attribute("no-set-pref").lower()
47
+ if label.find("cookie") >= 0 and checked == "checked":
48
+ checke.click()
49
+ elif label.find("cookie") <= 0 and checked != "checked":
50
+ checke.click()
51
+ clearButton = driver.find_element(By.ID, "clearButton")
52
+ # clearButton.click()
53
+ except:
54
+ print("clearUserData", format_exc())
@@ -0,0 +1,24 @@
1
+ Metadata-Version: 2.1
2
+ Name: pyscriptbase
3
+ Version: 1.0.1
4
+ Summary: python script base library
5
+ Home-page:
6
+ Author: ASMan
7
+ Author-email:
8
+ Description-Content-Type: text/markdown
9
+ Requires-Dist: loguru
10
+ Requires-Dist: selenium
11
+ Requires-Dist: pymysql
12
+ Requires-Dist: pycryptodome
13
+ Requires-Dist: pyyaml
14
+ Requires-Dist: xmltodict
15
+ Requires-Dist: prettytable
16
+ Requires-Dist: pyjwt
17
+ Requires-Dist: fake-useragent
18
+ Requires-Dist: beautifulsoup4
19
+ Requires-Dist: requests
20
+ Requires-Dist: lxml
21
+
22
+ # Instructions
23
+
24
+ python script base library
@@ -0,0 +1,14 @@
1
+ pybase/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
2
+ pybase/cipher.py,sha256=Bz5lqG9GuooOt2y4u495VA9BE5qAV3fPnouR8qzV7K4,5321
3
+ pybase/database.py,sha256=xOBKuyBS7RRTnuaaP5VB1XRaBQ8P7sNBEeabJfRQhVc,13302
4
+ pybase/env.py,sha256=7MqnRXEq6raicxfC-bA9jCczo63Gh9LjQbBO5VtJ7rY,2944
5
+ pybase/net.py,sha256=WvExRZoA5iHpx4qtE0YV_Mf_lVNaYvQNwtp0Suzih4A,11883
6
+ pybase/panel.py,sha256=1e9sod303rkuVJOuuym9jK-ZXUzkBom9x-svdnpZnjI,6827
7
+ pybase/pusher.py,sha256=lE4X3epadRaHKrRs8vBZW1T35mD03QtG-1Bu9okvq5Q,7054
8
+ pybase/script.py,sha256=MCw19l8JOeXxhAOHr8NhUMhMDGnLo8aM_F2zklZldYY,3486
9
+ pybase/util.py,sha256=RxQibRYGZKG5YCC6ffc3FGsE4nMkawknAtrEhGrxSig,2813
10
+ pybase/webview.py,sha256=NQkJuqBlVlC2X_wTcfhtrxUBoP4ie-VCfgBud5YjhD4,1687
11
+ pyscriptbase-1.0.1.dist-info/METADATA,sha256=Iutu3GqD2xVj2aNKOMEjsLXdm9qPLgIM05q82c_rKg0,537
12
+ pyscriptbase-1.0.1.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92
13
+ pyscriptbase-1.0.1.dist-info/top_level.txt,sha256=gYgKDnq77vSbZG-_hkku2uwMNI_t6Z7_WQq4dek8Al4,7
14
+ pyscriptbase-1.0.1.dist-info/RECORD,,
@@ -0,0 +1,5 @@
1
+ Wheel-Version: 1.0
2
+ Generator: bdist_wheel (0.43.0)
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any
5
+
@@ -0,0 +1 @@
1
+ pybase