Compare commits
187 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
764d0afb50 | ||
|
|
fe87547406 | ||
|
|
a1fd27722b | ||
|
|
3bd6611cd5 | ||
|
|
f3e1b4580a | ||
|
|
449d8a032e | ||
|
|
b40fa35622 | ||
|
|
6960184911 | ||
|
|
7bd270c662 | ||
|
|
f54e83673f | ||
|
|
ee40fdb3c3 | ||
|
|
52ebf7b027 | ||
|
|
85891dc918 | ||
|
|
7348a87a20 | ||
|
|
1dfa3e3f44 | ||
|
|
37ced2e535 | ||
|
|
11876acc62 | ||
|
|
756c0926ec | ||
|
|
9604fc9a8e | ||
|
|
5bcc527889 | ||
|
|
0d616289ed | ||
|
|
a8473b6a04 | ||
|
|
e1352586b7 | ||
|
|
849d5f18eb | ||
|
|
77298f4dab | ||
|
|
b7a2b045fb | ||
|
|
c7072da81d | ||
|
|
4c9b9fb74a | ||
|
|
feb4b516a4 | ||
|
|
d50191c6b8 | ||
|
|
3db3fa4e1f | ||
|
|
ad31961c2b | ||
|
|
ccdaefeb61 | ||
|
|
8c9bcba198 | ||
|
|
a273af0abe | ||
|
|
05a063b001 | ||
|
|
8487195512 | ||
|
|
250c47ccb7 | ||
|
|
e5aeb4f3a7 | ||
|
|
eab8d984e6 | ||
|
|
6b3f19a618 | ||
|
|
d5f8871064 | ||
|
|
77e899957c | ||
|
|
dd3515305c | ||
|
|
73c3ec4820 | ||
|
|
fde5160d56 | ||
|
|
13923705e5 | ||
|
|
d3afc95261 | ||
|
|
326d7e474c | ||
|
|
537b5d9725 | ||
|
|
697c1b5b43 | ||
|
|
2b6057161e | ||
|
|
8e2a6444bd | ||
|
|
b04df40b7d | ||
|
|
3e17d94904 | ||
|
|
29123054cc | ||
|
|
530c038985 | ||
|
|
2e9d2f0491 | ||
|
|
69ab9b4f15 | ||
|
|
1c8b940925 | ||
|
|
0e05a4ea18 | ||
|
|
9e4285b4c5 | ||
|
|
e89d2af8ae | ||
|
|
8e7d663060 | ||
|
|
179b33387e | ||
|
|
2c9a7c443f | ||
|
|
0de964e68c | ||
|
|
97046af931 | ||
|
|
ec24e776e7 | ||
|
|
92d4ef05fa | ||
|
|
fb27c50c75 | ||
|
|
0141bf039a | ||
|
|
54f9bb7f21 | ||
|
|
2c4e5eb5cc | ||
|
|
cd42f45a1f | ||
|
|
ec38895765 | ||
|
|
fc30579bbc | ||
|
|
3e6223e4e5 | ||
|
|
27c71124ff | ||
|
|
3a8a8a36f5 | ||
|
|
ed6de5e806 | ||
|
|
bf8a5befa3 | ||
|
|
a3fe641f6b | ||
|
|
f4f99c25db | ||
|
|
640d80e334 | ||
|
|
4f196b516f | ||
|
|
87f07bf95c | ||
|
|
1bfd7891b5 | ||
|
|
472eb0ee52 | ||
|
|
7638c67da6 | ||
|
|
7a0c143b5b | ||
|
|
fff8e11524 | ||
|
|
af24208cf3 | ||
|
|
85bccea2dd | ||
|
|
f7c8cac6ec | ||
|
|
97a5ac5bb0 | ||
|
|
1d57076010 | ||
|
|
d298ac872c | ||
|
|
c0581e781c | ||
|
|
6befd6341a | ||
|
|
504ef8dd68 | ||
|
|
127500d890 | ||
|
|
ab94173df7 | ||
|
|
e50697aae1 | ||
|
|
c71389fc0b | ||
|
|
732129ba34 | ||
|
|
77dfc895ed | ||
|
|
0c6f3123f8 | ||
|
|
e872d30b3a | ||
|
|
48fa4413c8 | ||
|
|
94e693db77 | ||
|
|
025d328d79 | ||
|
|
d086a5a152 | ||
|
|
5f2337d949 | ||
|
|
5e163181a8 | ||
|
|
0913cbb813 | ||
|
|
6aed64ce4e | ||
|
|
3c95e58fb2 | ||
|
|
64d0d4ed41 | ||
|
|
7fb659c511 | ||
|
|
d4ec91940f | ||
|
|
77f63ebb44 | ||
|
|
051b062e29 | ||
|
|
ec9083b556 | ||
|
|
156080a3b7 | ||
|
|
5b6effd43e | ||
|
|
97e8d41c39 | ||
|
|
d64ef447d2 | ||
|
|
461b2a62b0 | ||
|
|
f8988651b5 | ||
|
|
ffe865e29e | ||
|
|
cd5250c09f | ||
|
|
8f01bf6027 | ||
|
|
81eb11f5c5 | ||
|
|
80cadfa52c | ||
|
|
9974d70d99 | ||
|
|
6e3e4662f4 | ||
|
|
e2fb2e5565 | ||
|
|
6f8be226b0 | ||
|
|
2606f1e587 | ||
|
|
4d1fd7ea76 | ||
|
|
e61fbe6c69 | ||
|
|
0c287577ca | ||
|
|
a4aa562db9 | ||
|
|
33c5ff3a52 | ||
|
|
7c8e43bd35 | ||
|
|
bc0014dbe6 | ||
|
|
e41eca33bc | ||
|
|
e39b965459 | ||
|
|
f2aa3d7347 | ||
|
|
76c126284f | ||
|
|
44ee917d88 | ||
|
|
669019c051 | ||
|
|
4685c12570 | ||
|
|
d815529510 | ||
|
|
1da3620feb | ||
|
|
44d529c60f | ||
|
|
cdbcebd945 | ||
|
|
5bc2bf9397 | ||
|
|
d41419a579 | ||
|
|
a7e15e509e | ||
|
|
6518a378ac | ||
|
|
ebb73182f7 | ||
|
|
8fcc69165f | ||
|
|
5b98c58926 | ||
|
|
ce1534657b | ||
|
|
e2f02ea616 | ||
|
|
76134c2e2b | ||
|
|
2010855139 | ||
|
|
e550b9a155 | ||
|
|
53049d4acd | ||
|
|
bb4b45bc36 | ||
|
|
caf37e6c99 | ||
|
|
5af41d3b72 | ||
|
|
ebd3273251 | ||
|
|
63ed257a5f | ||
|
|
3bcfe6b1d0 | ||
|
|
7b789c71ca | ||
|
|
f78158e102 | ||
|
|
6d1c3490ba | ||
|
|
1a9af53e4d | ||
|
|
eac2d13fee | ||
|
|
1aad39fe7f | ||
|
|
8452ba95db | ||
|
|
286ee9e51e | ||
|
|
9a2a88384b | ||
|
|
68068b29e1 |
158
.github/workflows/python-app.yml
vendored
Normal file
@@ -0,0 +1,158 @@
|
|||||||
|
# <AUTO_MAA:A MAA Multi Account Management and Automation Tool>
|
||||||
|
# Copyright © <2024> <DLmaster361>
|
||||||
|
|
||||||
|
# This file is part of AUTO_MAA.
|
||||||
|
|
||||||
|
# AUTO_MAA 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.
|
||||||
|
|
||||||
|
# AUTO_MAA 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 AUTO_MAA. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
# DLmaster_361@163.com
|
||||||
|
|
||||||
|
name: Build AUTO_MAA
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches: [ "main" ]
|
||||||
|
paths-ignore:
|
||||||
|
- '**.md'
|
||||||
|
- 'LICENSE'
|
||||||
|
pull_request:
|
||||||
|
branches: [ "main" ]
|
||||||
|
paths-ignore:
|
||||||
|
- '**.md'
|
||||||
|
- 'LICENSE'
|
||||||
|
|
||||||
|
permissions:
|
||||||
|
contents: read
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
pre_check:
|
||||||
|
name: Pre Checks
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- name: Repo Check
|
||||||
|
id: repo_check
|
||||||
|
run: |
|
||||||
|
if [[ "$GITHUB_REPOSITORY" != "DLmaster361/AUTO_MAA" ]]; then
|
||||||
|
echo "When forking this repository to make your own builds, you have to adjust this check."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
exit 0
|
||||||
|
build_AUTO_MAA:
|
||||||
|
runs-on: windows-latest
|
||||||
|
needs: pre_check
|
||||||
|
steps:
|
||||||
|
- name: Checkout code
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
- name: Set up Python 3.12
|
||||||
|
uses: actions/setup-python@v5
|
||||||
|
with:
|
||||||
|
python-version: "3.12"
|
||||||
|
- name: Install dependencies
|
||||||
|
run: |
|
||||||
|
python -m pip install --upgrade pip
|
||||||
|
pip install flake8 pytest
|
||||||
|
pip install -r requirements.txt
|
||||||
|
- name: Lint with flake8
|
||||||
|
run: |
|
||||||
|
# stop the build if there are Python syntax errors or undefined names
|
||||||
|
flake8 . --count --select=E9,F63,F7,F82 --show-source --statistics
|
||||||
|
# exit-zero treats all errors as warnings. The GitHub editor is 127 chars wide
|
||||||
|
flake8 . --count --exit-zero --max-complexity=10 --max-line-length=127 --statistics
|
||||||
|
- name: Package
|
||||||
|
id: package
|
||||||
|
run: |
|
||||||
|
copy app\utils\package.py .\
|
||||||
|
python package.py
|
||||||
|
- name: Read version
|
||||||
|
id: read_version
|
||||||
|
run: |
|
||||||
|
$MAIN_VERSION=(Get-Content -Path "version_info.txt" -TotalCount 1).Trim()
|
||||||
|
"AUTO_MAA_version=$MAIN_VERSION" | Out-File -FilePath $env:GITHUB_ENV -Append
|
||||||
|
$UPDATER_VERSION=(Get-Content -Path "version_info.txt" -TotalCount 2 | Select-Object -Index 1).Trim()
|
||||||
|
"updater_version=$UPDATER_VERSION" | Out-File -FilePath $env:GITHUB_ENV -Append
|
||||||
|
- name: Create Zip
|
||||||
|
id: create_zip
|
||||||
|
run: |
|
||||||
|
Compress-Archive -Path app,resources,main.py,AUTO_MAA.exe,requirements.txt,README.md,LICENSE -DestinationPath AUTO_MAA_${{ env.AUTO_MAA_version }}.zip
|
||||||
|
Compress-Archive -Path Updater.exe -DestinationPath Updater_${{ env.updater_version }}.zip
|
||||||
|
- name: Upload Artifact
|
||||||
|
uses: actions/upload-artifact@v4
|
||||||
|
with:
|
||||||
|
name: AUTO_MAA_${{ env.AUTO_MAA_version }}
|
||||||
|
path: |
|
||||||
|
AUTO_MAA_${{ env.AUTO_MAA_version }}.zip
|
||||||
|
Updater_${{ env.updater_version }}.zip
|
||||||
|
- name: Upload Version_Info Artifact
|
||||||
|
uses: actions/upload-artifact@v4
|
||||||
|
with:
|
||||||
|
name: version_info
|
||||||
|
path: version_info.txt
|
||||||
|
publish_release:
|
||||||
|
name: Publish release
|
||||||
|
needs: build_AUTO_MAA
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- name: Checkout
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
- name: Download artifacts
|
||||||
|
uses: actions/download-artifact@v4
|
||||||
|
with:
|
||||||
|
pattern: AUTO_MAA_*
|
||||||
|
merge-multiple: true
|
||||||
|
path: artifacts
|
||||||
|
- name: Download Version_Info
|
||||||
|
uses: actions/download-artifact@v4
|
||||||
|
with:
|
||||||
|
name: version_info
|
||||||
|
path: ./
|
||||||
|
- name: Check if release exists
|
||||||
|
id: check_if_release_exists
|
||||||
|
run: |
|
||||||
|
release_id=$(gh release view $(sed 's/\r$//g' <(head -n 1 version_info.txt)) --json id --jq .id || true)
|
||||||
|
if [[ -z $release_id ]]; then
|
||||||
|
echo "release_exists=false" >> $GITHUB_OUTPUT
|
||||||
|
else
|
||||||
|
echo "release_exists=true" >> $GITHUB_OUTPUT
|
||||||
|
fi
|
||||||
|
env:
|
||||||
|
GITHUB_TOKEN: ${{ secrets.WORKFLOW_TOKEN }}
|
||||||
|
- name: Create release
|
||||||
|
id: create_release
|
||||||
|
if: steps.check_if_release_exists.outputs.release_exists == 'false'
|
||||||
|
run: |
|
||||||
|
set -xe
|
||||||
|
shopt -s nullglob
|
||||||
|
NAME="$(sed 's/\r$//g' <(head -n 1 version_info.txt))"
|
||||||
|
TAGNAME="$(sed 's/\r$//g' <(head -n 1 version_info.txt))"
|
||||||
|
NOTES_MAIN="$(sed 's/\r$//g' <(tail -n +3 version_info.txt))"
|
||||||
|
NOTES_TAIL="\`\`\`本release通过GitHub Actions自动构建\`\`\`"
|
||||||
|
NOTES="$NOTES_MAIN<br><br>$NOTES_TAIL"
|
||||||
|
gh release create "$TAGNAME" --target "main" --title "$NAME" --notes "$NOTES" artifacts/*
|
||||||
|
env:
|
||||||
|
GITHUB_TOKEN: ${{ secrets.WORKFLOW_TOKEN }}
|
||||||
|
- name: Update release
|
||||||
|
id: update_release
|
||||||
|
if: steps.check_if_release_exists.outputs.release_exists == 'true'
|
||||||
|
run: |
|
||||||
|
set -xe
|
||||||
|
shopt -s nullglob
|
||||||
|
NAME="$(sed 's/\r$//g' <(head -n 1 version_info.txt))"
|
||||||
|
TAGNAME="$(sed 's/\r$//g' <(head -n 1 version_info.txt))"
|
||||||
|
NOTES_MAIN="$(sed 's/\r$//g' <(tail -n +3 version_info.txt))"
|
||||||
|
NOTES_TAIL="\`\`\`本release通过GitHub Actions自动构建\`\`\`"
|
||||||
|
NOTES="$NOTES_MAIN<br><br>$NOTES_TAIL"
|
||||||
|
gh release delete "$TAGNAME" --yes
|
||||||
|
gh release create "$TAGNAME" --target "main" --title "$NAME" --notes "$NOTES" artifacts/*
|
||||||
|
env:
|
||||||
|
GITHUB_TOKEN: ${{ secrets.WORKFLOW_TOKEN }}
|
||||||
BIN
AUTO_MAA.exe
29
AUTO_MAA.py
@@ -1,29 +0,0 @@
|
|||||||
import sqlite3
|
|
||||||
import subprocess
|
|
||||||
import datetime
|
|
||||||
import time
|
|
||||||
import os
|
|
||||||
from termcolor import colored
|
|
||||||
|
|
||||||
DATABASE="data/data.db"
|
|
||||||
db=sqlite3.connect(DATABASE)
|
|
||||||
cur=db.cursor()
|
|
||||||
cur.execute("SELECT * FROM timeset WHERE True")
|
|
||||||
timeset=cur.fetchall()
|
|
||||||
timeset=[list(row) for row in timeset]
|
|
||||||
while True:
|
|
||||||
curtime=datetime.datetime.now().strftime("%H:%M")
|
|
||||||
print(colored("当前时间:"+curtime,'green'))
|
|
||||||
timenew=[]
|
|
||||||
timenew.append(curtime)
|
|
||||||
if timenew in timeset:
|
|
||||||
print(colored("开始执行",'yellow'))
|
|
||||||
maa=subprocess.Popen(["run.exe"])
|
|
||||||
maapid=maa.pid
|
|
||||||
while True:
|
|
||||||
if os.path.exists("OVER"):
|
|
||||||
os.system('taskkill /F /T /PID '+str(maapid))
|
|
||||||
os.remove("OVER")
|
|
||||||
print(colored("执行完毕",'yellow'))
|
|
||||||
break
|
|
||||||
time.sleep(1)
|
|
||||||
674
LICENSE
Normal file
@@ -0,0 +1,674 @@
|
|||||||
|
GNU GENERAL PUBLIC LICENSE
|
||||||
|
Version 3, 29 June 2007
|
||||||
|
|
||||||
|
Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>
|
||||||
|
Everyone is permitted to copy and distribute verbatim copies
|
||||||
|
of this license document, but changing it is not allowed.
|
||||||
|
|
||||||
|
Preamble
|
||||||
|
|
||||||
|
The GNU General Public License is a free, copyleft license for
|
||||||
|
software and other kinds of works.
|
||||||
|
|
||||||
|
The licenses for most software and other practical works are designed
|
||||||
|
to take away your freedom to share and change the works. By contrast,
|
||||||
|
the GNU General Public License is intended to guarantee your freedom to
|
||||||
|
share and change all versions of a program--to make sure it remains free
|
||||||
|
software for all its users. We, the Free Software Foundation, use the
|
||||||
|
GNU General Public License for most of our software; it applies also to
|
||||||
|
any other work released this way by its authors. You can apply it to
|
||||||
|
your programs, too.
|
||||||
|
|
||||||
|
When we speak of free software, we are referring to freedom, not
|
||||||
|
price. Our General Public Licenses are designed to make sure that you
|
||||||
|
have the freedom to distribute copies of free software (and charge for
|
||||||
|
them if you wish), that you receive source code or can get it if you
|
||||||
|
want it, that you can change the software or use pieces of it in new
|
||||||
|
free programs, and that you know you can do these things.
|
||||||
|
|
||||||
|
To protect your rights, we need to prevent others from denying you
|
||||||
|
these rights or asking you to surrender the rights. Therefore, you have
|
||||||
|
certain responsibilities if you distribute copies of the software, or if
|
||||||
|
you modify it: responsibilities to respect the freedom of others.
|
||||||
|
|
||||||
|
For example, if you distribute copies of such a program, whether
|
||||||
|
gratis or for a fee, you must pass on to the recipients the same
|
||||||
|
freedoms that you received. You must make sure that they, too, receive
|
||||||
|
or can get the source code. And you must show them these terms so they
|
||||||
|
know their rights.
|
||||||
|
|
||||||
|
Developers that use the GNU GPL protect your rights with two steps:
|
||||||
|
(1) assert copyright on the software, and (2) offer you this License
|
||||||
|
giving you legal permission to copy, distribute and/or modify it.
|
||||||
|
|
||||||
|
For the developers' and authors' protection, the GPL clearly explains
|
||||||
|
that there is no warranty for this free software. For both users' and
|
||||||
|
authors' sake, the GPL requires that modified versions be marked as
|
||||||
|
changed, so that their problems will not be attributed erroneously to
|
||||||
|
authors of previous versions.
|
||||||
|
|
||||||
|
Some devices are designed to deny users access to install or run
|
||||||
|
modified versions of the software inside them, although the manufacturer
|
||||||
|
can do so. This is fundamentally incompatible with the aim of
|
||||||
|
protecting users' freedom to change the software. The systematic
|
||||||
|
pattern of such abuse occurs in the area of products for individuals to
|
||||||
|
use, which is precisely where it is most unacceptable. Therefore, we
|
||||||
|
have designed this version of the GPL to prohibit the practice for those
|
||||||
|
products. If such problems arise substantially in other domains, we
|
||||||
|
stand ready to extend this provision to those domains in future versions
|
||||||
|
of the GPL, as needed to protect the freedom of users.
|
||||||
|
|
||||||
|
Finally, every program is threatened constantly by software patents.
|
||||||
|
States should not allow patents to restrict development and use of
|
||||||
|
software on general-purpose computers, but in those that do, we wish to
|
||||||
|
avoid the special danger that patents applied to a free program could
|
||||||
|
make it effectively proprietary. To prevent this, the GPL assures that
|
||||||
|
patents cannot be used to render the program non-free.
|
||||||
|
|
||||||
|
The precise terms and conditions for copying, distribution and
|
||||||
|
modification follow.
|
||||||
|
|
||||||
|
TERMS AND CONDITIONS
|
||||||
|
|
||||||
|
0. Definitions.
|
||||||
|
|
||||||
|
"This License" refers to version 3 of the GNU General Public License.
|
||||||
|
|
||||||
|
"Copyright" also means copyright-like laws that apply to other kinds of
|
||||||
|
works, such as semiconductor masks.
|
||||||
|
|
||||||
|
"The Program" refers to any copyrightable work licensed under this
|
||||||
|
License. Each licensee is addressed as "you". "Licensees" and
|
||||||
|
"recipients" may be individuals or organizations.
|
||||||
|
|
||||||
|
To "modify" a work means to copy from or adapt all or part of the work
|
||||||
|
in a fashion requiring copyright permission, other than the making of an
|
||||||
|
exact copy. The resulting work is called a "modified version" of the
|
||||||
|
earlier work or a work "based on" the earlier work.
|
||||||
|
|
||||||
|
A "covered work" means either the unmodified Program or a work based
|
||||||
|
on the Program.
|
||||||
|
|
||||||
|
To "propagate" a work means to do anything with it that, without
|
||||||
|
permission, would make you directly or secondarily liable for
|
||||||
|
infringement under applicable copyright law, except executing it on a
|
||||||
|
computer or modifying a private copy. Propagation includes copying,
|
||||||
|
distribution (with or without modification), making available to the
|
||||||
|
public, and in some countries other activities as well.
|
||||||
|
|
||||||
|
To "convey" a work means any kind of propagation that enables other
|
||||||
|
parties to make or receive copies. Mere interaction with a user through
|
||||||
|
a computer network, with no transfer of a copy, is not conveying.
|
||||||
|
|
||||||
|
An interactive user interface displays "Appropriate Legal Notices"
|
||||||
|
to the extent that it includes a convenient and prominently visible
|
||||||
|
feature that (1) displays an appropriate copyright notice, and (2)
|
||||||
|
tells the user that there is no warranty for the work (except to the
|
||||||
|
extent that warranties are provided), that licensees may convey the
|
||||||
|
work under this License, and how to view a copy of this License. If
|
||||||
|
the interface presents a list of user commands or options, such as a
|
||||||
|
menu, a prominent item in the list meets this criterion.
|
||||||
|
|
||||||
|
1. Source Code.
|
||||||
|
|
||||||
|
The "source code" for a work means the preferred form of the work
|
||||||
|
for making modifications to it. "Object code" means any non-source
|
||||||
|
form of a work.
|
||||||
|
|
||||||
|
A "Standard Interface" means an interface that either is an official
|
||||||
|
standard defined by a recognized standards body, or, in the case of
|
||||||
|
interfaces specified for a particular programming language, one that
|
||||||
|
is widely used among developers working in that language.
|
||||||
|
|
||||||
|
The "System Libraries" of an executable work include anything, other
|
||||||
|
than the work as a whole, that (a) is included in the normal form of
|
||||||
|
packaging a Major Component, but which is not part of that Major
|
||||||
|
Component, and (b) serves only to enable use of the work with that
|
||||||
|
Major Component, or to implement a Standard Interface for which an
|
||||||
|
implementation is available to the public in source code form. A
|
||||||
|
"Major Component", in this context, means a major essential component
|
||||||
|
(kernel, window system, and so on) of the specific operating system
|
||||||
|
(if any) on which the executable work runs, or a compiler used to
|
||||||
|
produce the work, or an object code interpreter used to run it.
|
||||||
|
|
||||||
|
The "Corresponding Source" for a work in object code form means all
|
||||||
|
the source code needed to generate, install, and (for an executable
|
||||||
|
work) run the object code and to modify the work, including scripts to
|
||||||
|
control those activities. However, it does not include the work's
|
||||||
|
System Libraries, or general-purpose tools or generally available free
|
||||||
|
programs which are used unmodified in performing those activities but
|
||||||
|
which are not part of the work. For example, Corresponding Source
|
||||||
|
includes interface definition files associated with source files for
|
||||||
|
the work, and the source code for shared libraries and dynamically
|
||||||
|
linked subprograms that the work is specifically designed to require,
|
||||||
|
such as by intimate data communication or control flow between those
|
||||||
|
subprograms and other parts of the work.
|
||||||
|
|
||||||
|
The Corresponding Source need not include anything that users
|
||||||
|
can regenerate automatically from other parts of the Corresponding
|
||||||
|
Source.
|
||||||
|
|
||||||
|
The Corresponding Source for a work in source code form is that
|
||||||
|
same work.
|
||||||
|
|
||||||
|
2. Basic Permissions.
|
||||||
|
|
||||||
|
All rights granted under this License are granted for the term of
|
||||||
|
copyright on the Program, and are irrevocable provided the stated
|
||||||
|
conditions are met. This License explicitly affirms your unlimited
|
||||||
|
permission to run the unmodified Program. The output from running a
|
||||||
|
covered work is covered by this License only if the output, given its
|
||||||
|
content, constitutes a covered work. This License acknowledges your
|
||||||
|
rights of fair use or other equivalent, as provided by copyright law.
|
||||||
|
|
||||||
|
You may make, run and propagate covered works that you do not
|
||||||
|
convey, without conditions so long as your license otherwise remains
|
||||||
|
in force. You may convey covered works to others for the sole purpose
|
||||||
|
of having them make modifications exclusively for you, or provide you
|
||||||
|
with facilities for running those works, provided that you comply with
|
||||||
|
the terms of this License in conveying all material for which you do
|
||||||
|
not control copyright. Those thus making or running the covered works
|
||||||
|
for you must do so exclusively on your behalf, under your direction
|
||||||
|
and control, on terms that prohibit them from making any copies of
|
||||||
|
your copyrighted material outside their relationship with you.
|
||||||
|
|
||||||
|
Conveying under any other circumstances is permitted solely under
|
||||||
|
the conditions stated below. Sublicensing is not allowed; section 10
|
||||||
|
makes it unnecessary.
|
||||||
|
|
||||||
|
3. Protecting Users' Legal Rights From Anti-Circumvention Law.
|
||||||
|
|
||||||
|
No covered work shall be deemed part of an effective technological
|
||||||
|
measure under any applicable law fulfilling obligations under article
|
||||||
|
11 of the WIPO copyright treaty adopted on 20 December 1996, or
|
||||||
|
similar laws prohibiting or restricting circumvention of such
|
||||||
|
measures.
|
||||||
|
|
||||||
|
When you convey a covered work, you waive any legal power to forbid
|
||||||
|
circumvention of technological measures to the extent such circumvention
|
||||||
|
is effected by exercising rights under this License with respect to
|
||||||
|
the covered work, and you disclaim any intention to limit operation or
|
||||||
|
modification of the work as a means of enforcing, against the work's
|
||||||
|
users, your or third parties' legal rights to forbid circumvention of
|
||||||
|
technological measures.
|
||||||
|
|
||||||
|
4. Conveying Verbatim Copies.
|
||||||
|
|
||||||
|
You may convey verbatim copies of the Program's source code as you
|
||||||
|
receive it, in any medium, provided that you conspicuously and
|
||||||
|
appropriately publish on each copy an appropriate copyright notice;
|
||||||
|
keep intact all notices stating that this License and any
|
||||||
|
non-permissive terms added in accord with section 7 apply to the code;
|
||||||
|
keep intact all notices of the absence of any warranty; and give all
|
||||||
|
recipients a copy of this License along with the Program.
|
||||||
|
|
||||||
|
You may charge any price or no price for each copy that you convey,
|
||||||
|
and you may offer support or warranty protection for a fee.
|
||||||
|
|
||||||
|
5. Conveying Modified Source Versions.
|
||||||
|
|
||||||
|
You may convey a work based on the Program, or the modifications to
|
||||||
|
produce it from the Program, in the form of source code under the
|
||||||
|
terms of section 4, provided that you also meet all of these conditions:
|
||||||
|
|
||||||
|
a) The work must carry prominent notices stating that you modified
|
||||||
|
it, and giving a relevant date.
|
||||||
|
|
||||||
|
b) The work must carry prominent notices stating that it is
|
||||||
|
released under this License and any conditions added under section
|
||||||
|
7. This requirement modifies the requirement in section 4 to
|
||||||
|
"keep intact all notices".
|
||||||
|
|
||||||
|
c) You must license the entire work, as a whole, under this
|
||||||
|
License to anyone who comes into possession of a copy. This
|
||||||
|
License will therefore apply, along with any applicable section 7
|
||||||
|
additional terms, to the whole of the work, and all its parts,
|
||||||
|
regardless of how they are packaged. This License gives no
|
||||||
|
permission to license the work in any other way, but it does not
|
||||||
|
invalidate such permission if you have separately received it.
|
||||||
|
|
||||||
|
d) If the work has interactive user interfaces, each must display
|
||||||
|
Appropriate Legal Notices; however, if the Program has interactive
|
||||||
|
interfaces that do not display Appropriate Legal Notices, your
|
||||||
|
work need not make them do so.
|
||||||
|
|
||||||
|
A compilation of a covered work with other separate and independent
|
||||||
|
works, which are not by their nature extensions of the covered work,
|
||||||
|
and which are not combined with it such as to form a larger program,
|
||||||
|
in or on a volume of a storage or distribution medium, is called an
|
||||||
|
"aggregate" if the compilation and its resulting copyright are not
|
||||||
|
used to limit the access or legal rights of the compilation's users
|
||||||
|
beyond what the individual works permit. Inclusion of a covered work
|
||||||
|
in an aggregate does not cause this License to apply to the other
|
||||||
|
parts of the aggregate.
|
||||||
|
|
||||||
|
6. Conveying Non-Source Forms.
|
||||||
|
|
||||||
|
You may convey a covered work in object code form under the terms
|
||||||
|
of sections 4 and 5, provided that you also convey the
|
||||||
|
machine-readable Corresponding Source under the terms of this License,
|
||||||
|
in one of these ways:
|
||||||
|
|
||||||
|
a) Convey the object code in, or embodied in, a physical product
|
||||||
|
(including a physical distribution medium), accompanied by the
|
||||||
|
Corresponding Source fixed on a durable physical medium
|
||||||
|
customarily used for software interchange.
|
||||||
|
|
||||||
|
b) Convey the object code in, or embodied in, a physical product
|
||||||
|
(including a physical distribution medium), accompanied by a
|
||||||
|
written offer, valid for at least three years and valid for as
|
||||||
|
long as you offer spare parts or customer support for that product
|
||||||
|
model, to give anyone who possesses the object code either (1) a
|
||||||
|
copy of the Corresponding Source for all the software in the
|
||||||
|
product that is covered by this License, on a durable physical
|
||||||
|
medium customarily used for software interchange, for a price no
|
||||||
|
more than your reasonable cost of physically performing this
|
||||||
|
conveying of source, or (2) access to copy the
|
||||||
|
Corresponding Source from a network server at no charge.
|
||||||
|
|
||||||
|
c) Convey individual copies of the object code with a copy of the
|
||||||
|
written offer to provide the Corresponding Source. This
|
||||||
|
alternative is allowed only occasionally and noncommercially, and
|
||||||
|
only if you received the object code with such an offer, in accord
|
||||||
|
with subsection 6b.
|
||||||
|
|
||||||
|
d) Convey the object code by offering access from a designated
|
||||||
|
place (gratis or for a charge), and offer equivalent access to the
|
||||||
|
Corresponding Source in the same way through the same place at no
|
||||||
|
further charge. You need not require recipients to copy the
|
||||||
|
Corresponding Source along with the object code. If the place to
|
||||||
|
copy the object code is a network server, the Corresponding Source
|
||||||
|
may be on a different server (operated by you or a third party)
|
||||||
|
that supports equivalent copying facilities, provided you maintain
|
||||||
|
clear directions next to the object code saying where to find the
|
||||||
|
Corresponding Source. Regardless of what server hosts the
|
||||||
|
Corresponding Source, you remain obligated to ensure that it is
|
||||||
|
available for as long as needed to satisfy these requirements.
|
||||||
|
|
||||||
|
e) Convey the object code using peer-to-peer transmission, provided
|
||||||
|
you inform other peers where the object code and Corresponding
|
||||||
|
Source of the work are being offered to the general public at no
|
||||||
|
charge under subsection 6d.
|
||||||
|
|
||||||
|
A separable portion of the object code, whose source code is excluded
|
||||||
|
from the Corresponding Source as a System Library, need not be
|
||||||
|
included in conveying the object code work.
|
||||||
|
|
||||||
|
A "User Product" is either (1) a "consumer product", which means any
|
||||||
|
tangible personal property which is normally used for personal, family,
|
||||||
|
or household purposes, or (2) anything designed or sold for incorporation
|
||||||
|
into a dwelling. In determining whether a product is a consumer product,
|
||||||
|
doubtful cases shall be resolved in favor of coverage. For a particular
|
||||||
|
product received by a particular user, "normally used" refers to a
|
||||||
|
typical or common use of that class of product, regardless of the status
|
||||||
|
of the particular user or of the way in which the particular user
|
||||||
|
actually uses, or expects or is expected to use, the product. A product
|
||||||
|
is a consumer product regardless of whether the product has substantial
|
||||||
|
commercial, industrial or non-consumer uses, unless such uses represent
|
||||||
|
the only significant mode of use of the product.
|
||||||
|
|
||||||
|
"Installation Information" for a User Product means any methods,
|
||||||
|
procedures, authorization keys, or other information required to install
|
||||||
|
and execute modified versions of a covered work in that User Product from
|
||||||
|
a modified version of its Corresponding Source. The information must
|
||||||
|
suffice to ensure that the continued functioning of the modified object
|
||||||
|
code is in no case prevented or interfered with solely because
|
||||||
|
modification has been made.
|
||||||
|
|
||||||
|
If you convey an object code work under this section in, or with, or
|
||||||
|
specifically for use in, a User Product, and the conveying occurs as
|
||||||
|
part of a transaction in which the right of possession and use of the
|
||||||
|
User Product is transferred to the recipient in perpetuity or for a
|
||||||
|
fixed term (regardless of how the transaction is characterized), the
|
||||||
|
Corresponding Source conveyed under this section must be accompanied
|
||||||
|
by the Installation Information. But this requirement does not apply
|
||||||
|
if neither you nor any third party retains the ability to install
|
||||||
|
modified object code on the User Product (for example, the work has
|
||||||
|
been installed in ROM).
|
||||||
|
|
||||||
|
The requirement to provide Installation Information does not include a
|
||||||
|
requirement to continue to provide support service, warranty, or updates
|
||||||
|
for a work that has been modified or installed by the recipient, or for
|
||||||
|
the User Product in which it has been modified or installed. Access to a
|
||||||
|
network may be denied when the modification itself materially and
|
||||||
|
adversely affects the operation of the network or violates the rules and
|
||||||
|
protocols for communication across the network.
|
||||||
|
|
||||||
|
Corresponding Source conveyed, and Installation Information provided,
|
||||||
|
in accord with this section must be in a format that is publicly
|
||||||
|
documented (and with an implementation available to the public in
|
||||||
|
source code form), and must require no special password or key for
|
||||||
|
unpacking, reading or copying.
|
||||||
|
|
||||||
|
7. Additional Terms.
|
||||||
|
|
||||||
|
"Additional permissions" are terms that supplement the terms of this
|
||||||
|
License by making exceptions from one or more of its conditions.
|
||||||
|
Additional permissions that are applicable to the entire Program shall
|
||||||
|
be treated as though they were included in this License, to the extent
|
||||||
|
that they are valid under applicable law. If additional permissions
|
||||||
|
apply only to part of the Program, that part may be used separately
|
||||||
|
under those permissions, but the entire Program remains governed by
|
||||||
|
this License without regard to the additional permissions.
|
||||||
|
|
||||||
|
When you convey a copy of a covered work, you may at your option
|
||||||
|
remove any additional permissions from that copy, or from any part of
|
||||||
|
it. (Additional permissions may be written to require their own
|
||||||
|
removal in certain cases when you modify the work.) You may place
|
||||||
|
additional permissions on material, added by you to a covered work,
|
||||||
|
for which you have or can give appropriate copyright permission.
|
||||||
|
|
||||||
|
Notwithstanding any other provision of this License, for material you
|
||||||
|
add to a covered work, you may (if authorized by the copyright holders of
|
||||||
|
that material) supplement the terms of this License with terms:
|
||||||
|
|
||||||
|
a) Disclaiming warranty or limiting liability differently from the
|
||||||
|
terms of sections 15 and 16 of this License; or
|
||||||
|
|
||||||
|
b) Requiring preservation of specified reasonable legal notices or
|
||||||
|
author attributions in that material or in the Appropriate Legal
|
||||||
|
Notices displayed by works containing it; or
|
||||||
|
|
||||||
|
c) Prohibiting misrepresentation of the origin of that material, or
|
||||||
|
requiring that modified versions of such material be marked in
|
||||||
|
reasonable ways as different from the original version; or
|
||||||
|
|
||||||
|
d) Limiting the use for publicity purposes of names of licensors or
|
||||||
|
authors of the material; or
|
||||||
|
|
||||||
|
e) Declining to grant rights under trademark law for use of some
|
||||||
|
trade names, trademarks, or service marks; or
|
||||||
|
|
||||||
|
f) Requiring indemnification of licensors and authors of that
|
||||||
|
material by anyone who conveys the material (or modified versions of
|
||||||
|
it) with contractual assumptions of liability to the recipient, for
|
||||||
|
any liability that these contractual assumptions directly impose on
|
||||||
|
those licensors and authors.
|
||||||
|
|
||||||
|
All other non-permissive additional terms are considered "further
|
||||||
|
restrictions" within the meaning of section 10. If the Program as you
|
||||||
|
received it, or any part of it, contains a notice stating that it is
|
||||||
|
governed by this License along with a term that is a further
|
||||||
|
restriction, you may remove that term. If a license document contains
|
||||||
|
a further restriction but permits relicensing or conveying under this
|
||||||
|
License, you may add to a covered work material governed by the terms
|
||||||
|
of that license document, provided that the further restriction does
|
||||||
|
not survive such relicensing or conveying.
|
||||||
|
|
||||||
|
If you add terms to a covered work in accord with this section, you
|
||||||
|
must place, in the relevant source files, a statement of the
|
||||||
|
additional terms that apply to those files, or a notice indicating
|
||||||
|
where to find the applicable terms.
|
||||||
|
|
||||||
|
Additional terms, permissive or non-permissive, may be stated in the
|
||||||
|
form of a separately written license, or stated as exceptions;
|
||||||
|
the above requirements apply either way.
|
||||||
|
|
||||||
|
8. Termination.
|
||||||
|
|
||||||
|
You may not propagate or modify a covered work except as expressly
|
||||||
|
provided under this License. Any attempt otherwise to propagate or
|
||||||
|
modify it is void, and will automatically terminate your rights under
|
||||||
|
this License (including any patent licenses granted under the third
|
||||||
|
paragraph of section 11).
|
||||||
|
|
||||||
|
However, if you cease all violation of this License, then your
|
||||||
|
license from a particular copyright holder is reinstated (a)
|
||||||
|
provisionally, unless and until the copyright holder explicitly and
|
||||||
|
finally terminates your license, and (b) permanently, if the copyright
|
||||||
|
holder fails to notify you of the violation by some reasonable means
|
||||||
|
prior to 60 days after the cessation.
|
||||||
|
|
||||||
|
Moreover, your license from a particular copyright holder is
|
||||||
|
reinstated permanently if the copyright holder notifies you of the
|
||||||
|
violation by some reasonable means, this is the first time you have
|
||||||
|
received notice of violation of this License (for any work) from that
|
||||||
|
copyright holder, and you cure the violation prior to 30 days after
|
||||||
|
your receipt of the notice.
|
||||||
|
|
||||||
|
Termination of your rights under this section does not terminate the
|
||||||
|
licenses of parties who have received copies or rights from you under
|
||||||
|
this License. If your rights have been terminated and not permanently
|
||||||
|
reinstated, you do not qualify to receive new licenses for the same
|
||||||
|
material under section 10.
|
||||||
|
|
||||||
|
9. Acceptance Not Required for Having Copies.
|
||||||
|
|
||||||
|
You are not required to accept this License in order to receive or
|
||||||
|
run a copy of the Program. Ancillary propagation of a covered work
|
||||||
|
occurring solely as a consequence of using peer-to-peer transmission
|
||||||
|
to receive a copy likewise does not require acceptance. However,
|
||||||
|
nothing other than this License grants you permission to propagate or
|
||||||
|
modify any covered work. These actions infringe copyright if you do
|
||||||
|
not accept this License. Therefore, by modifying or propagating a
|
||||||
|
covered work, you indicate your acceptance of this License to do so.
|
||||||
|
|
||||||
|
10. Automatic Licensing of Downstream Recipients.
|
||||||
|
|
||||||
|
Each time you convey a covered work, the recipient automatically
|
||||||
|
receives a license from the original licensors, to run, modify and
|
||||||
|
propagate that work, subject to this License. You are not responsible
|
||||||
|
for enforcing compliance by third parties with this License.
|
||||||
|
|
||||||
|
An "entity transaction" is a transaction transferring control of an
|
||||||
|
organization, or substantially all assets of one, or subdividing an
|
||||||
|
organization, or merging organizations. If propagation of a covered
|
||||||
|
work results from an entity transaction, each party to that
|
||||||
|
transaction who receives a copy of the work also receives whatever
|
||||||
|
licenses to the work the party's predecessor in interest had or could
|
||||||
|
give under the previous paragraph, plus a right to possession of the
|
||||||
|
Corresponding Source of the work from the predecessor in interest, if
|
||||||
|
the predecessor has it or can get it with reasonable efforts.
|
||||||
|
|
||||||
|
You may not impose any further restrictions on the exercise of the
|
||||||
|
rights granted or affirmed under this License. For example, you may
|
||||||
|
not impose a license fee, royalty, or other charge for exercise of
|
||||||
|
rights granted under this License, and you may not initiate litigation
|
||||||
|
(including a cross-claim or counterclaim in a lawsuit) alleging that
|
||||||
|
any patent claim is infringed by making, using, selling, offering for
|
||||||
|
sale, or importing the Program or any portion of it.
|
||||||
|
|
||||||
|
11. Patents.
|
||||||
|
|
||||||
|
A "contributor" is a copyright holder who authorizes use under this
|
||||||
|
License of the Program or a work on which the Program is based. The
|
||||||
|
work thus licensed is called the contributor's "contributor version".
|
||||||
|
|
||||||
|
A contributor's "essential patent claims" are all patent claims
|
||||||
|
owned or controlled by the contributor, whether already acquired or
|
||||||
|
hereafter acquired, that would be infringed by some manner, permitted
|
||||||
|
by this License, of making, using, or selling its contributor version,
|
||||||
|
but do not include claims that would be infringed only as a
|
||||||
|
consequence of further modification of the contributor version. For
|
||||||
|
purposes of this definition, "control" includes the right to grant
|
||||||
|
patent sublicenses in a manner consistent with the requirements of
|
||||||
|
this License.
|
||||||
|
|
||||||
|
Each contributor grants you a non-exclusive, worldwide, royalty-free
|
||||||
|
patent license under the contributor's essential patent claims, to
|
||||||
|
make, use, sell, offer for sale, import and otherwise run, modify and
|
||||||
|
propagate the contents of its contributor version.
|
||||||
|
|
||||||
|
In the following three paragraphs, a "patent license" is any express
|
||||||
|
agreement or commitment, however denominated, not to enforce a patent
|
||||||
|
(such as an express permission to practice a patent or covenant not to
|
||||||
|
sue for patent infringement). To "grant" such a patent license to a
|
||||||
|
party means to make such an agreement or commitment not to enforce a
|
||||||
|
patent against the party.
|
||||||
|
|
||||||
|
If you convey a covered work, knowingly relying on a patent license,
|
||||||
|
and the Corresponding Source of the work is not available for anyone
|
||||||
|
to copy, free of charge and under the terms of this License, through a
|
||||||
|
publicly available network server or other readily accessible means,
|
||||||
|
then you must either (1) cause the Corresponding Source to be so
|
||||||
|
available, or (2) arrange to deprive yourself of the benefit of the
|
||||||
|
patent license for this particular work, or (3) arrange, in a manner
|
||||||
|
consistent with the requirements of this License, to extend the patent
|
||||||
|
license to downstream recipients. "Knowingly relying" means you have
|
||||||
|
actual knowledge that, but for the patent license, your conveying the
|
||||||
|
covered work in a country, or your recipient's use of the covered work
|
||||||
|
in a country, would infringe one or more identifiable patents in that
|
||||||
|
country that you have reason to believe are valid.
|
||||||
|
|
||||||
|
If, pursuant to or in connection with a single transaction or
|
||||||
|
arrangement, you convey, or propagate by procuring conveyance of, a
|
||||||
|
covered work, and grant a patent license to some of the parties
|
||||||
|
receiving the covered work authorizing them to use, propagate, modify
|
||||||
|
or convey a specific copy of the covered work, then the patent license
|
||||||
|
you grant is automatically extended to all recipients of the covered
|
||||||
|
work and works based on it.
|
||||||
|
|
||||||
|
A patent license is "discriminatory" if it does not include within
|
||||||
|
the scope of its coverage, prohibits the exercise of, or is
|
||||||
|
conditioned on the non-exercise of one or more of the rights that are
|
||||||
|
specifically granted under this License. You may not convey a covered
|
||||||
|
work if you are a party to an arrangement with a third party that is
|
||||||
|
in the business of distributing software, under which you make payment
|
||||||
|
to the third party based on the extent of your activity of conveying
|
||||||
|
the work, and under which the third party grants, to any of the
|
||||||
|
parties who would receive the covered work from you, a discriminatory
|
||||||
|
patent license (a) in connection with copies of the covered work
|
||||||
|
conveyed by you (or copies made from those copies), or (b) primarily
|
||||||
|
for and in connection with specific products or compilations that
|
||||||
|
contain the covered work, unless you entered into that arrangement,
|
||||||
|
or that patent license was granted, prior to 28 March 2007.
|
||||||
|
|
||||||
|
Nothing in this License shall be construed as excluding or limiting
|
||||||
|
any implied license or other defenses to infringement that may
|
||||||
|
otherwise be available to you under applicable patent law.
|
||||||
|
|
||||||
|
12. No Surrender of Others' Freedom.
|
||||||
|
|
||||||
|
If conditions are imposed on you (whether by court order, agreement or
|
||||||
|
otherwise) that contradict the conditions of this License, they do not
|
||||||
|
excuse you from the conditions of this License. If you cannot convey a
|
||||||
|
covered work so as to satisfy simultaneously your obligations under this
|
||||||
|
License and any other pertinent obligations, then as a consequence you may
|
||||||
|
not convey it at all. For example, if you agree to terms that obligate you
|
||||||
|
to collect a royalty for further conveying from those to whom you convey
|
||||||
|
the Program, the only way you could satisfy both those terms and this
|
||||||
|
License would be to refrain entirely from conveying the Program.
|
||||||
|
|
||||||
|
13. Use with the GNU Affero General Public License.
|
||||||
|
|
||||||
|
Notwithstanding any other provision of this License, you have
|
||||||
|
permission to link or combine any covered work with a work licensed
|
||||||
|
under version 3 of the GNU Affero General Public License into a single
|
||||||
|
combined work, and to convey the resulting work. The terms of this
|
||||||
|
License will continue to apply to the part which is the covered work,
|
||||||
|
but the special requirements of the GNU Affero General Public License,
|
||||||
|
section 13, concerning interaction through a network will apply to the
|
||||||
|
combination as such.
|
||||||
|
|
||||||
|
14. Revised Versions of this License.
|
||||||
|
|
||||||
|
The Free Software Foundation may publish revised and/or new versions of
|
||||||
|
the GNU General Public License from time to time. Such new versions will
|
||||||
|
be similar in spirit to the present version, but may differ in detail to
|
||||||
|
address new problems or concerns.
|
||||||
|
|
||||||
|
Each version is given a distinguishing version number. If the
|
||||||
|
Program specifies that a certain numbered version of the GNU General
|
||||||
|
Public License "or any later version" applies to it, you have the
|
||||||
|
option of following the terms and conditions either of that numbered
|
||||||
|
version or of any later version published by the Free Software
|
||||||
|
Foundation. If the Program does not specify a version number of the
|
||||||
|
GNU General Public License, you may choose any version ever published
|
||||||
|
by the Free Software Foundation.
|
||||||
|
|
||||||
|
If the Program specifies that a proxy can decide which future
|
||||||
|
versions of the GNU General Public License can be used, that proxy's
|
||||||
|
public statement of acceptance of a version permanently authorizes you
|
||||||
|
to choose that version for the Program.
|
||||||
|
|
||||||
|
Later license versions may give you additional or different
|
||||||
|
permissions. However, no additional obligations are imposed on any
|
||||||
|
author or copyright holder as a result of your choosing to follow a
|
||||||
|
later version.
|
||||||
|
|
||||||
|
15. Disclaimer of Warranty.
|
||||||
|
|
||||||
|
THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
|
||||||
|
APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
|
||||||
|
HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
|
||||||
|
OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
|
||||||
|
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||||
|
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
|
||||||
|
IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
|
||||||
|
ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
|
||||||
|
|
||||||
|
16. Limitation of Liability.
|
||||||
|
|
||||||
|
IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
|
||||||
|
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
|
||||||
|
THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
|
||||||
|
GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
|
||||||
|
USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
|
||||||
|
DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
|
||||||
|
PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
|
||||||
|
EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
|
||||||
|
SUCH DAMAGES.
|
||||||
|
|
||||||
|
17. Interpretation of Sections 15 and 16.
|
||||||
|
|
||||||
|
If the disclaimer of warranty and limitation of liability provided
|
||||||
|
above cannot be given local legal effect according to their terms,
|
||||||
|
reviewing courts shall apply local law that most closely approximates
|
||||||
|
an absolute waiver of all civil liability in connection with the
|
||||||
|
Program, unless a warranty or assumption of liability accompanies a
|
||||||
|
copy of the Program in return for a fee.
|
||||||
|
|
||||||
|
END OF TERMS AND CONDITIONS
|
||||||
|
|
||||||
|
How to Apply These Terms to Your New Programs
|
||||||
|
|
||||||
|
If you develop a new program, and you want it to be of the greatest
|
||||||
|
possible use to the public, the best way to achieve this is to make it
|
||||||
|
free software which everyone can redistribute and change under these terms.
|
||||||
|
|
||||||
|
To do so, attach the following notices to the program. It is safest
|
||||||
|
to attach them to the start of each source file to most effectively
|
||||||
|
state the exclusion of warranty; and each file should have at least
|
||||||
|
the "copyright" line and a pointer to where the full notice is found.
|
||||||
|
|
||||||
|
<one line to give the program's name and a brief idea of what it does.>
|
||||||
|
Copyright (C) <year> <name of author>
|
||||||
|
|
||||||
|
This program 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.
|
||||||
|
|
||||||
|
This program 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 this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
Also add information on how to contact you by electronic and paper mail.
|
||||||
|
|
||||||
|
If the program does terminal interaction, make it output a short
|
||||||
|
notice like this when it starts in an interactive mode:
|
||||||
|
|
||||||
|
<program> Copyright (C) <year> <name of author>
|
||||||
|
This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
|
||||||
|
This is free software, and you are welcome to redistribute it
|
||||||
|
under certain conditions; type `show c' for details.
|
||||||
|
|
||||||
|
The hypothetical commands `show w' and `show c' should show the appropriate
|
||||||
|
parts of the General Public License. Of course, your program's commands
|
||||||
|
might be different; for a GUI interface, you would use an "about box".
|
||||||
|
|
||||||
|
You should also get your employer (if you work as a programmer) or school,
|
||||||
|
if any, to sign a "copyright disclaimer" for the program, if necessary.
|
||||||
|
For more information on this, and how to apply and follow the GNU GPL, see
|
||||||
|
<https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
The GNU General Public License does not permit incorporating your program
|
||||||
|
into proprietary programs. If your program is a subroutine library, you
|
||||||
|
may consider it more useful to permit linking proprietary applications with
|
||||||
|
the library. If this is what you want to do, use the GNU Lesser General
|
||||||
|
Public License instead of this License. But first, please read
|
||||||
|
<https://www.gnu.org/licenses/why-not-lgpl.html>.
|
||||||
331
README.md
@@ -1,240 +1,209 @@
|
|||||||
# AUTO_MAA
|
# AUTO_MAA
|
||||||
|
|
||||||
MAA多账号管理与自动化软件
|
MAA多账号管理与自动化软件
|
||||||
|
|
||||||
----------------------------------------------------------------------------------------------
|

|
||||||
|
|
||||||
## 免责声明
|
---
|
||||||
本软件是一个外部工具,旨在优化MAA多账号功能体验。该软件包可以存储多账号数据,并通过修改MAA配置文件、读取MAA日志等行为自动完成多账号代理。
|
|
||||||
|
|
||||||
This software is open source, free of charge and for learning and exchange purposes only. The developer team has the final right to interpret this project. All problems arising from the use of this software are not related to this project and the developer team. If you encounter a merchant using this software to practice on your behalf and charging for it, it may be the cost of equipment and time, etc. The problems and consequences arising from this software have nothing to do with it.
|
</h1>
|
||||||
|
|
||||||
本软件开源、免费,仅供学习交流使用。开发者团队拥有本项目的最终解释权。使用本软件产生的所有问题与本项目与开发者团队无关。若您遇到商家使用本软件进行代练并收费,可能是设备与时间等费用,产生的问题及后果与本软件无关。
|
[](https://github.com/DLmaster361/AUTO_MAA/stargazers)
|
||||||
|
[](https://github.com/DLmaster361/AUTO_MAA/network)
|
||||||
|
[](https://github.com/DLmaster361/AUTO_MAA/issues)
|
||||||
|
[](https://github.com/DLmaster361/AUTO_MAA/graphs/contributors)
|
||||||
|
[](https://github.com/DLmaster361/AUTO_MAA/blob/main/LICENSE)
|
||||||
|
</div>
|
||||||
|
|
||||||
## 安装与配置MAA
|
## 软件介绍
|
||||||
|
|
||||||
本软件是MAA的外部工具,需要安装配置MAA后才能使用。
|
### 性质
|
||||||
|
|
||||||
#### MAA安装
|
本软件是明日方舟第三方软件`MAA`的第三方工具,即第3<sup>3</sup>方软件。旨在优化MAA多账号功能体验,并通过一些方法解决MAA项目未能解决的部分问题,提高代理的稳定性。
|
||||||
|
|
||||||
什么是MAA? [官网](https://maa.plus/)/[GitHub](https://github.com/CHNZYX/Auto_Simulated_Universe/archive/refs/heads/main.zip)
|
### 原理
|
||||||
|
|
||||||
MAA下载地址 [GitHub下载](https://github.com/MaaAssistantArknights/MaaAssistantArknights/releases)
|
本软件可以存储多个明日方舟账号数据,并通过以下流程实现代理功能:
|
||||||
|
|
||||||
#### MAA配置
|
1. **配置:** 根据对应用户的配置信息,生成配置文件并将其导入MAA。
|
||||||
|
2. **监测:** 在MAA开始代理后,持续读取MAA的日志以判断其运行状态。当软件认定MAA出现异常时,通过重启MAA使之仍能继续完成任务。
|
||||||
|
3. **循环:** 重复上述步骤,使MAA依次完成各个用户的日常代理任务。
|
||||||
|
|
||||||
1.完成MAA的adb配置等基本配置
|
### 优势
|
||||||
|
|
||||||
2.在“完成后”菜单,选择“退出MAA和模拟器”。勾选“手动输入关卡名”和“无限吃48小时内过期的理智药”
|
- **节省运行开销:** 只需要一份MAA软件与一个模拟器,无需多开就能完成多账号代理,羸弱的电脑也能代理日常。
|
||||||
|
- **自定义空间大:** 依靠高级用户配置模式,支持MAA几乎所有设置选项自定义,同时保留对模拟器多开的支持。
|
||||||
|
- **一键代理无忧:** 无须中途手动修改MAA配置,将繁琐交给AUTO_MAA,把游戏留给自己。
|
||||||
|
- **代理结果复核:** 通过人工排查功能核实各用户代理情况,堵住日常代理的最后一丝风险。
|
||||||
|
|
||||||

|
## 重要声明
|
||||||
|
|
||||||
3.确保当前配置名为“Default”,取消所有“定时执行”
|
本开发团队承诺,不会修改明日方舟游戏本体与相关配置文件。本项目使用GPL开源,相关细则如下:
|
||||||
|
|
||||||

|
- **作者:** AUTO_MAA软件作者为DLmaster、DLmaster361或DLmaster_361,以上均指代同一人。
|
||||||
|
- **使用:** AUTO_MAA使用者可以按自己的意愿自由使用本软件。依据GPL,对于由此可能产生的损失,AUTO_MAA项目组不负任何责任。
|
||||||
|
- **分发:** AUTO_MAA允许任何人自由分发本软件,包括进行商业活动牟利。若为直接分发本软件,必须遵循GPL向接收者提供本软件项目地址、完整的软件源码与GPL协议原文(件);若为修改软件后进行分发,必须遵循GPL向接收者提供本软件项目地址、修改前的完整软件源码副本与GPL协议原文(件),违反者可能会被追究法律责任。
|
||||||
|
- **传播:** AUTO_MAA原则上允许传播者自由传播本软件,但无论在何种传播过程中,不得删除项目作者与开发者所留版权声明,不得隐瞒项目作者与相关开发者的存在。由于软件性质,项目组不希望发现任何人在明日方舟官方媒体(包括官方媒体账号与森空岛社区等)或明日方舟游戏相关内容(包括同好群、线下活动与游戏内容讨论等)下提及AUTO_MAA或MAA,希望各位理解。
|
||||||
|
- **衍生:** AUTO_MAA允许任何人对软件本体或软件部分代码进行二次开发或利用。但依据GPL,相关成果也必须使用GPL开源。
|
||||||
|
- **授权:** 如果希望在使用AUTO_MAA的相关成果后仍保持自己的项目闭源,请在Issues中说明来意。得到项目组认可后,我们可以提供另一份使用不同协议的代码,此协议主要内容如下:被授权者可以自由使用该代码并维持闭源;被授权者必须定期为AUTO_MAA作出贡献。
|
||||||
|
- **贡献:** 不论是直接参与软件的维护编写,或是撰写文档、测试、反馈BUG、给出建议、参与讨论,都为AUTO_MAA项目的发展完善做出了不可忽视的贡献。项目组提倡各位贡献者遵照GitHub开源社区惯例,发布Issues参与项目。避免私信或私发邮件(安全性漏洞或敏感问题除外),以帮助更多用户。
|
||||||
|
|
||||||
4.取消勾选“开机自启动MAA”,勾选“启动MAA后直接运行”和“启动MAA后自动开启模拟器”。配置自己模拟器所在的位置并根据实际情况填写“等待模拟器启动时间”(建议预留10s以防意外)。如果是多开用户,需要填写“附加命令”,具体填写值参见多开模拟器对应快捷方式路径(如“-v 1”)。
|
以上细则是本项目对GPL的相关补充与强调。未提及的以GPL为准,发生冲突的以本细则为准。如有不清楚的部分,请发Issues询问。若发生纠纷,相关内容也没有在Issues上提及的,项目组拥有最终解释权。
|
||||||
|
|
||||||

|
**注意**
|
||||||
|
|
||||||
5.勾选“定时检查更新”、“自动下载更新包”和“自动安装更新包”
|
- 由于本软件有修改其它目录JSON文件等行为,使用前请将AUTO_MAA添加入Windows Defender信任区以及防病毒软件的信任区或开发者目录,避免被误杀。
|
||||||
|
|
||||||

|
---
|
||||||
|
|
||||||
## 下载AUTO_MAA软件包 [](https://github.com/DLmaster361/AUTO_MAA/releases)
|
# 使用方法
|
||||||
|
|
||||||
GitHub下载地址 [GitHub下载](https://github.com/DLmaster361/AUTO_MAA/releases)
|
## 安装软件
|
||||||
|
|
||||||
## 配置用户信息与相关参数
|
```
|
||||||
|
本软件是MAA的外部工具,需要安装MAA后才能使用。
|
||||||
注意:当前所有的密码输入部分都存在一点“小问题”,请在输入密码时避免输入Delete、F12、Tab等功能键。
|
|
||||||
|
|
||||||
-------------------------------------------------
|
|
||||||
|
|
||||||
#### 第一次启动
|
|
||||||
|
|
||||||
双击启动`manage.exe`,输入MAA所在文件夹路径并回车(注意使用斜杠的种类,不要使用反斜杠),然后设置管理密钥。
|
|
||||||
|
|
||||||

|
|
||||||
|
|
||||||
管理密钥是解密用户密码的唯一凭证,与数据库绑定。密钥丢失或`data/key/`目录下任一文件损坏都将导致解密无法正常进行。
|
|
||||||
|
|
||||||
本项目采用自主组建的混合加密模式,项目组也无法找回您的管理密钥或修复`data/key/`目录下的文件。如果不幸的事发生,建议您删除`data/data.db`重新录入信息。
|
|
||||||
|
|
||||||
当前暂不支持修改管理密钥,请等待后续更新。
|
|
||||||
|
|
||||||
#### 添加用户
|
|
||||||
|
|
||||||
输入“+”以开始添加用户。依次输入:
|
|
||||||
|
|
||||||
用户名:管理用户的惟一凭证
|
|
||||||
|
|
||||||
手机号码:允许隐去中间四位以“****”代替
|
|
||||||
|
|
||||||
代理天数:这个还要我解释吗?
|
|
||||||
|
|
||||||
密码:警告!密码功能暂未开发,输入的信息会以明文存储,有泄露风险,请勿使用。可以用无意义的字符串代替。由于忽略警告导致的信息泄露,本项目组概不负责
|
|
||||||
|
|
||||||

|
|
||||||
|
|
||||||
#### 删除用户
|
|
||||||
|
|
||||||
输入用户名+“-”以删除用户。格式:
|
|
||||||
|
|
||||||
```plaintext
|
|
||||||
用户名 -
|
|
||||||
```
|
```
|
||||||
|
|
||||||

|
### 下载MAA
|
||||||
|
|
||||||
#### 配置用户状态
|
- 什么是MAA? [官网](https://maa.plus/)/[GitHub](https://github.com/MaaAssistantArknights/MaaAssistantArknights)
|
||||||
|
|
||||||
启用代理:输入用户名+“y”以启用该用户的代理。格式:
|
- MAA下载地址 [GitHub下载](https://github.com/MaaAssistantArknights/MaaAssistantArknights/releases)
|
||||||
|
|
||||||
```plaintext
|
### 安装MAA
|
||||||
用户名 y
|
|
||||||
|
- 将MAA压缩包解压至任意普通文件夹即可。
|
||||||
|
|
||||||
|
- 若为首次安装MAA,请双击`MAA.exe`启动MAA程序以生成MAA配置文件。
|
||||||
|
|
||||||
|
### 下载AUTO_MAA [](https://github.com/DLmaster361/AUTO_MAA/releases)
|
||||||
|
|
||||||
|
- GitHub下载地址 [GitHub下载](https://github.com/DLmaster361/AUTO_MAA/releases)
|
||||||
|
|
||||||
|
### 安装AUTO_MAA
|
||||||
|
|
||||||
|
- 将AUTO_MAA压缩包解压至任意普通文件夹即可。
|
||||||
|
|
||||||
|
## 配置AUTO_MAA
|
||||||
|
|
||||||
|
### 启动AUTO_MAA
|
||||||
|
|
||||||
|
- 双击`AUTO_MAA.exe`以启动软件。
|
||||||
|
|
||||||
|
```
|
||||||
|
注意:
|
||||||
|
|
||||||
|
首次启动时会要求设置管理密钥。
|
||||||
|
|
||||||
|
管理密钥是解密用户密码的唯一凭证,与数据库绑定。
|
||||||
|
密钥丢失或data/key/目录下任一文件损坏都将导致解密无法正常进行。
|
||||||
|
|
||||||
|
本项目采用自主开发的混合加密模式,项目组也无法找回您的管理密钥或修复data/key/目录下的文件。
|
||||||
|
如果不幸的事发生,建议您删除data/key/目录与data/data.db文件后重新录入信息。
|
||||||
```
|
```
|
||||||
|
|
||||||

|
### 配置信息
|
||||||
|
|
||||||
禁用代理:输入用户名+“n”以禁用该用户的代理。格式:
|
#### 设置MAA
|
||||||
|
|
||||||
```plaintext
|
1. 通过`浏览`绑定MAA后,单击`设置MAA`进行MAA全局设置。
|
||||||
用户名 n
|
|
||||||
```
|
|
||||||
|
|
||||||

|
2. 在打开的MAA界面完成`性能设置`、`游戏设置`、`连接设置`、`启动设置`、`界面设置`、`软件更新`等基本配置以及代理任务的详细配置。
|
||||||
|
|
||||||
#### 续期
|
3. 完成基本配置后,关闭MAA页面,AUTO_MAA会自动保存您的配置。
|
||||||
|
|
||||||
输入用户名+续期天数+“+”以延长该用户的代理天数。格式:
|
- 注意:在MAA的设置过程中,若MAA要求`立刻重启应用更改`,请选择`稍后`。否则,MAA重启后的一切更改都不会被程序记录。
|
||||||
|
|
||||||
```plaintext
|
- 特别的,您需要确保自己:
|
||||||
用户名 续期天数 +
|
- 取消勾选`开机自启动MAA`。
|
||||||
```
|
- 配置自己模拟器所在的位置并根据实际情况填写`等待模拟器启动时间`(建议预留10s以防意外)。
|
||||||
|
- 如果是模拟器多开用户,还需要填写`附加命令`,具体填写值参见多开模拟器对应快捷方式路径(如`-v 1`)。
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
#### 修改刷取关卡
|
#### 设置AUTO_MAA
|
||||||
|
|
||||||
输入用户名+关卡号+“~”以更改该用户的代理关卡。格式:
|
本项目已基本完成GUI开发,您可以直接在设置页配置AUTO_MAA相关信息,页面简介如下:
|
||||||
|
- `MAA路径`:该项无法直接编辑,仅用于展示当前程序所绑定MAA的路径。
|
||||||
|
- `浏览`:选择MAA文件夹。
|
||||||
|
- `设置MAA`:编辑MAA全局配置,具体使用方法参见前文。
|
||||||
|
- `日常限制`:执行日常代理的日常部分时的超时阈值,当MAA日志无变化时间超过阈值时,视为超时。
|
||||||
|
- `剿灭限制`:执行日常代理的剿灭部分时的超时阈值,当MAA日志无变化时间超过阈值时,视为超时。
|
||||||
|
- `运行失败重试次数上限`:对于每一用户,若超过该次数限制仍未完成代理,视为代理失败。
|
||||||
|
- `开机自动启动AUTO_MAA`:实现AUTO_MAA的自启动。
|
||||||
|
- `AUTO_MAA启动时禁止电脑休眠`:仅阻止电脑自动休眠,不会影响屏幕是否熄灭。
|
||||||
|
- `启动AUTO_MAA后直接代理`:在AUTO_MAA启动后立即执行代理任务。
|
||||||
|
- `通过邮件通知结果`:在AUTO_MAA完成任务后将结果发送至用户指定邮箱。
|
||||||
|
- `检查版本更新`:从GitHub镜像源获取版本更新信息,并调起更新器完成程序更新,更新器已支持多个代理地址。
|
||||||
|
- `修改管理密钥`:修改管理密钥,当用户列表中无用户时,将跳过验证旧管理密钥。
|
||||||
|
|
||||||
```plaintext
|
#### 设置用户配置
|
||||||
用户名 关卡号 ~
|
|
||||||
```
|
|
||||||
|
|
||||||

|
本项目已基本完成GUI开发,您可以直接在用户管理页配置用户相关信息,页面简介如下:
|
||||||
|
- `新建`、`删除`:新建一个用户到当前用户配置列表、删除当前所选第一行所对应的用户。
|
||||||
|
- `转为高级/简洁`:将当前所选第一行所对应的用户转为高级/简洁配置模式。
|
||||||
|
- `显示密码`:输入管理密钥以显示用户密码,仅当管理密钥正确时能够修改`密码栏目`。
|
||||||
|
- `刷新`:清除临时保存的管理密钥。
|
||||||
|
- `简洁用户配置列表`:仅支持核心代理选项的设置,其它设置选项沿用MAA的全局设置,部分代理核心功能选项由程序托管。
|
||||||
|
- `高级用户配置列表`:支持几乎所有代理选项的设置,通过`修改配置`进行MAA自定义,仅部分代理核心功能选项由程序托管。
|
||||||
|
- `用户配置列表栏目`:详解如下:
|
||||||
|
- `用户名`:展示在执行界面的用户名,用于区分不同用户。
|
||||||
|
- `账号ID`:MAA进行账号切换所需的凭据,官服用户请输入手机号码、B服请输入B站ID。
|
||||||
|
- `服务器`:当前支持官服、B服。
|
||||||
|
- `代理天数`:剩余需要进行代理的天数,输入`任意负数`可设置为无限代理天数,当剩余天数为0时不再代理或排查。
|
||||||
|
- `状态`:用户的状态,禁用时将不再对其进行代理或排查。
|
||||||
|
- `执行情况`:当日执行情况,不可编辑。
|
||||||
|
- `关卡`、`备选关卡-1`、`备选关卡-2`:关卡号。
|
||||||
|
- `日常`:单独设定是否进行日常代理的日常部分,可进一步配置MAA的具体代理任务,该配置与全局MAA配置相互独立。
|
||||||
|
- `剿灭`:单独设定是否进行日常代理的剿灭部分,高级配置模式下可进一步配置MAA的具体代理任务,该配置与全局MAA配置相互独立。
|
||||||
|
- `自定义基建`:是否启用自定义基建功能,需要进一步配置自定义基建文件,该配置与其他用户相互独立。
|
||||||
|
- `密码`:仅用于登记用户的密码,可留空。
|
||||||
|
- `备注`:用于备注用户信息。
|
||||||
|
|
||||||
特别的:
|
- 特别的:
|
||||||
|
- 对于`简洁用户配置列表的关卡、备选关卡-1、备选关卡-2栏目`您可以自定义关卡号替换方案。
|
||||||
|
- 程序会读取`data/gameid.txt`中的数据,依据此进行关卡号的替换,便于常用关卡的使用。
|
||||||
|
- `gameid.txt`会在程序首次运行时生成,其中将预置一些常用资源本的替换方案。
|
||||||
|
|
||||||
你可以自定义关卡号替换方案。程序会读取`gameid.txt`中的数据,依据此进行关卡号的替换,便于常用关卡的使用。`gameid.txt`在初始已经存储了一些常用资源本的替代方案。
|

|
||||||
|
|
||||||

|
## 运行代理任务
|
||||||
|
|
||||||
#### 设置MAA路径
|
### 直接运行
|
||||||
|
|
||||||
输入“/”+新的MAA文件夹路径以修改MAA安装位置的配置。格式:
|
- 在执行页单击`立即执行`直接运行。
|
||||||
|
|
||||||
```plaintext
|
### 定时运行
|
||||||
/新的MAA文件夹路径
|
|
||||||
```
|
|
||||||
|
|
||||||
注意:‘/’与路径间没有空格,路径同样不能使用反斜杠
|
- 在执行页的`定时执行`栏设置时间。
|
||||||
|
|
||||||

|
- 保持软件打开,软件会在设定的时间自动运行。
|
||||||
|
|
||||||
#### 设置启动时间
|
## 人工排查代理结果
|
||||||
|
|
||||||
添加启动时间:输入“:+”+时间以添加定时启动时间。格式:
|
### 直接开始人工排查
|
||||||
|
|
||||||
```plaintext
|
- 在执行页单击`开始排查`启动排查进程。
|
||||||
:+小时:分钟
|
|
||||||
```
|
|
||||||
|
|
||||||
注意:所有输入间没有空格
|
- 软件将调起MAA,依次登录各用户的账号。
|
||||||
|
|
||||||

|
- 完成PRTS登录后,请人工检查代理情况,可以手动完成未代理的任务。
|
||||||
|
|
||||||
删除启动时间:输入“:-”+时间以删除定时启动时间。格式:
|
- 在对话框中单击对应账号的代理情况。
|
||||||
|
|
||||||
```plaintext
|
- 结束人工排查后,相应排查情况将被写入用户管理页的`备注栏目`。
|
||||||
:-小时:分钟
|
|
||||||
```
|
|
||||||
|
|
||||||
注意:所有输入间没有空格
|
---
|
||||||
|
|
||||||

|
# 关于
|
||||||
|
|
||||||
#### 检索信息
|
## 未来开发方向
|
||||||
|
|
||||||
检索所有信息:`manage.exe`打开时会打印所有用户与配置信息。除此之外,你可以通过输入“all ?”以打印所有信息,如下:
|
- [ ] 尝试接入更多开源社区成果
|
||||||
|
- [ ] 支持对MAA运行状况的进一步识别
|
||||||
|
- [x] 添加更多通知手段
|
||||||
|
- [ ] GUI界面美化
|
||||||
|
|
||||||
```plaintext
|
|
||||||
all ?
|
|
||||||
```
|
|
||||||
|
|
||||||

|
|
||||||
|
|
||||||
检索MAA路径:输入“maa ?”以检索MAA安装路径,如下:
|
|
||||||
|
|
||||||
```plaintext
|
|
||||||
maa ?
|
|
||||||
```
|
|
||||||
|
|
||||||

|
|
||||||
|
|
||||||
检索启动时间:输入“time ?”以检索定时启动的时间,如下:
|
|
||||||
|
|
||||||
```plaintext
|
|
||||||
time ?
|
|
||||||
```
|
|
||||||
|
|
||||||

|
|
||||||
|
|
||||||
检索指定用户:输入用户名+“?”以检索指定用户信息,如下:
|
|
||||||
|
|
||||||
```plaintext
|
|
||||||
用户名 ?
|
|
||||||
```
|
|
||||||
|
|
||||||

|
|
||||||
|
|
||||||
#### 退出
|
|
||||||
|
|
||||||
输入“-”以退出`manage.exe`,如下:
|
|
||||||
|
|
||||||
```plaintext
|
|
||||||
-
|
|
||||||
```
|
|
||||||
|
|
||||||
## 运行代理
|
|
||||||
|
|
||||||
#### 直接运行
|
|
||||||
|
|
||||||
双击`run.exe`直接运行
|
|
||||||
|
|
||||||
#### 定时运行
|
|
||||||
|
|
||||||
双击`AUTO_MAA.exe`打开,不要关闭。它会读取设定时间,在该时刻自动运行
|
|
||||||
|
|
||||||
注意:周一将自动进行剿灭代理
|
|
||||||
|
|
||||||
## 关于
|
|
||||||
|
|
||||||
项目图标由文心一格AI生成
|
|
||||||
|
|
||||||
----------------------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
欢迎加入,欢迎反馈bug
|
|
||||||
|
|
||||||
QQ群:没有
|
|
||||||
|
|
||||||
----------------------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
如果喜欢本项目,可以打赏送作者一杯咖啡喵!
|
|
||||||
|
|
||||||

|
|
||||||
|
|
||||||
----------------------------------------------------------------------------------------------
|
|
||||||
## 贡献者
|
## 贡献者
|
||||||
|
|
||||||
感谢以下贡献者对本项目做出的贡献
|
感谢以下贡献者对本项目做出的贡献
|
||||||
@@ -250,3 +219,15 @@ QQ群:没有
|
|||||||
## Star History
|
## Star History
|
||||||
|
|
||||||
[](https://star-history.com/#DLmaster361/AUTO_MAA&Date)
|
[](https://star-history.com/#DLmaster361/AUTO_MAA&Date)
|
||||||
|
|
||||||
|
## 交流与赞助
|
||||||
|
|
||||||
|
欢迎加入AUTO_MAA项目组,欢迎反馈bug
|
||||||
|
|
||||||
|
- QQ群:[957750551](https://qm.qq.com/cgi-bin/qm/qr?k=EET-OL_o52KPlDLEmbzaNkKUXuyQ4WZY&jump_from=webapi&authKey=6NxGwEu9JAOLHqfdEmNfrZy4tUvC/3ar2j5+Go7Hgf3j+ntAK1VS6SUOLOjYVKTt)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
如果喜欢这个项目的话,给作者来杯咖啡吧!
|
||||||
|
|
||||||
|

|
||||||
|
|||||||
46
app/__init__.py
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
# <AUTO_MAA:A MAA Multi Account Management and Automation Tool>
|
||||||
|
# Copyright © <2024> <DLmaster361>
|
||||||
|
|
||||||
|
# This file is part of AUTO_MAA.
|
||||||
|
|
||||||
|
# AUTO_MAA 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.
|
||||||
|
|
||||||
|
# AUTO_MAA 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 AUTO_MAA. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
# DLmaster_361@163.com
|
||||||
|
|
||||||
|
"""
|
||||||
|
AUTO_MAA
|
||||||
|
AUTO_MAA主程序包
|
||||||
|
v4.2
|
||||||
|
作者:DLmaster_361
|
||||||
|
"""
|
||||||
|
|
||||||
|
__version__ = "4.2.0"
|
||||||
|
__author__ = "DLmaster361 <DLmaster_361@163.com>"
|
||||||
|
__license__ = "GPL-3.0 license"
|
||||||
|
|
||||||
|
from .config import AppConfig
|
||||||
|
from .models import MaaManager
|
||||||
|
from .services import Notification, CryptoHandler
|
||||||
|
from .ui import AUTO_MAA
|
||||||
|
from .utils import Updater, version_text
|
||||||
|
|
||||||
|
__all__ = [
|
||||||
|
"AppConfig",
|
||||||
|
"MaaManager",
|
||||||
|
"Notification",
|
||||||
|
"CryptoHandler",
|
||||||
|
"AUTO_MAA",
|
||||||
|
"Updater",
|
||||||
|
"version_text",
|
||||||
|
]
|
||||||
240
app/config.py
Normal file
@@ -0,0 +1,240 @@
|
|||||||
|
# <AUTO_MAA:A MAA Multi Account Management and Automation Tool>
|
||||||
|
# Copyright © <2024> <DLmaster361>
|
||||||
|
|
||||||
|
# This file is part of AUTO_MAA.
|
||||||
|
|
||||||
|
# AUTO_MAA 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.
|
||||||
|
|
||||||
|
# AUTO_MAA 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 AUTO_MAA. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
# DLmaster_361@163.com
|
||||||
|
|
||||||
|
"""
|
||||||
|
AUTO_MAA
|
||||||
|
AUTO_MAA配置管理
|
||||||
|
v4.2
|
||||||
|
作者:DLmaster_361
|
||||||
|
"""
|
||||||
|
|
||||||
|
import sqlite3
|
||||||
|
import json
|
||||||
|
import os
|
||||||
|
import sys
|
||||||
|
from pathlib import Path
|
||||||
|
from typing import Dict, Union
|
||||||
|
|
||||||
|
|
||||||
|
class AppConfig:
|
||||||
|
|
||||||
|
def __init__(self) -> None:
|
||||||
|
|
||||||
|
self.app_path = Path.cwd() # 获取软件根目录
|
||||||
|
self.app_path_sys = os.path.realpath(sys.argv[0]) # 获取软件自身的路径
|
||||||
|
self.app_name = os.path.basename(self.app_path) # 获取软件自身的名称
|
||||||
|
|
||||||
|
self.database_path = self.app_path / "data/data.db"
|
||||||
|
self.config_path = self.app_path / "config/gui.json"
|
||||||
|
self.key_path = self.app_path / "data/key"
|
||||||
|
self.gameid_path = self.app_path / "data/gameid.txt"
|
||||||
|
self.version_path = self.app_path / "resources/version.json"
|
||||||
|
|
||||||
|
# 检查文件完整性
|
||||||
|
self.initialize()
|
||||||
|
|
||||||
|
def initialize(self) -> None:
|
||||||
|
"""初始化程序的配置文件"""
|
||||||
|
|
||||||
|
# 检查目录
|
||||||
|
(self.app_path / "config").mkdir(parents=True, exist_ok=True)
|
||||||
|
(self.app_path / "data/MAAconfig/simple").mkdir(parents=True, exist_ok=True)
|
||||||
|
(self.app_path / "data/MAAconfig/beta").mkdir(parents=True, exist_ok=True)
|
||||||
|
(self.app_path / "data/MAAconfig/Default").mkdir(parents=True, exist_ok=True)
|
||||||
|
|
||||||
|
# 生成版本信息文件
|
||||||
|
if not self.version_path.exists():
|
||||||
|
version = {
|
||||||
|
"main_version": "0.0.0.0",
|
||||||
|
"updater_version": "0.0.0.0",
|
||||||
|
}
|
||||||
|
with self.version_path.open(mode="w", encoding="utf-8") as f:
|
||||||
|
json.dump(version, f, indent=4)
|
||||||
|
|
||||||
|
# 生成配置文件
|
||||||
|
if not self.config_path.exists():
|
||||||
|
config = {"Default": {}}
|
||||||
|
with self.config_path.open(mode="w", encoding="utf-8") as f:
|
||||||
|
json.dump(config, f, indent=4)
|
||||||
|
|
||||||
|
# 生成预设gameid替换方案文件
|
||||||
|
if not self.gameid_path.exists():
|
||||||
|
self.gameid_path.write_text(
|
||||||
|
"龙门币:CE-6\n技能:CA-5\n红票:AP-5\n经验:LS-6\n剿灭模式:Annihilation",
|
||||||
|
encoding="utf-8",
|
||||||
|
)
|
||||||
|
|
||||||
|
self.check_config()
|
||||||
|
self.check_database()
|
||||||
|
|
||||||
|
def check_config(self) -> None:
|
||||||
|
"""检查配置文件字段完整性并补全"""
|
||||||
|
|
||||||
|
config_list = [
|
||||||
|
["TimeSet.set1", "False"],
|
||||||
|
["TimeSet.run1", "00:00"],
|
||||||
|
["TimeSet.set2", "False"],
|
||||||
|
["TimeSet.run2", "00:00"],
|
||||||
|
["TimeSet.set3", "False"],
|
||||||
|
["TimeSet.run3", "00:00"],
|
||||||
|
["TimeSet.set4", "False"],
|
||||||
|
["TimeSet.run4", "00:00"],
|
||||||
|
["TimeSet.set5", "False"],
|
||||||
|
["TimeSet.run5", "00:00"],
|
||||||
|
["TimeSet.set6", "False"],
|
||||||
|
["TimeSet.run6", "00:00"],
|
||||||
|
["TimeSet.set7", "False"],
|
||||||
|
["TimeSet.run7", "00:00"],
|
||||||
|
["TimeSet.set8", "False"],
|
||||||
|
["TimeSet.run8", "00:00"],
|
||||||
|
["TimeSet.set9", "False"],
|
||||||
|
["TimeSet.run9", "00:00"],
|
||||||
|
["TimeSet.set10", "False"],
|
||||||
|
["TimeSet.run10", "00:00"],
|
||||||
|
["MaaSet.path", ""],
|
||||||
|
["TimeLimit.routine", 10],
|
||||||
|
["TimeLimit.annihilation", 40],
|
||||||
|
["TimesLimit.run", 3],
|
||||||
|
["SelfSet.IfSelfStart", "False"],
|
||||||
|
["SelfSet.IfSleep", "False"],
|
||||||
|
["SelfSet.IfProxyDirectly", "False"],
|
||||||
|
["SelfSet.IfSendMail", "False"],
|
||||||
|
["SelfSet.MailAddress", ""],
|
||||||
|
["SelfSet.IfSendMail.OnlyError", "False"],
|
||||||
|
["SelfSet.IfSilence", "False"],
|
||||||
|
["SelfSet.BossKey", ""],
|
||||||
|
["SelfSet.IfToTray", "False"],
|
||||||
|
["SelfSet.UIsize", "1200x700"],
|
||||||
|
["SelfSet.UIlocation", "100x100"],
|
||||||
|
["SelfSet.UImaximized", "False"],
|
||||||
|
["SelfSet.MainIndex", 2],
|
||||||
|
]
|
||||||
|
|
||||||
|
# 导入配置文件
|
||||||
|
with self.config_path.open(mode="r", encoding="utf-8") as f:
|
||||||
|
config = json.load(f)
|
||||||
|
|
||||||
|
# 检查并补充缺失的字段
|
||||||
|
for i in range(len(config_list)):
|
||||||
|
if not config_list[i][0] in config["Default"]:
|
||||||
|
config["Default"][config_list[i][0]] = config_list[i][1]
|
||||||
|
|
||||||
|
# 初始化配置信息
|
||||||
|
self.content: Dict[str, Dict[str, Union[str, int]]] = config
|
||||||
|
|
||||||
|
# 导出配置文件
|
||||||
|
self.save_config()
|
||||||
|
|
||||||
|
def check_database(self) -> None:
|
||||||
|
"""检查用户数据库文件并处理数据库版本更新"""
|
||||||
|
|
||||||
|
# 生成用户数据库
|
||||||
|
if not self.database_path.exists():
|
||||||
|
db = sqlite3.connect(self.database_path)
|
||||||
|
cur = db.cursor()
|
||||||
|
cur.execute(
|
||||||
|
"CREATE TABLE adminx(admin text,id text,server text,day int,status text,last date,game text,game_1 text,game_2 text,routine text,annihilation text,infrastructure text,password byte,notes text,numb int,mode text,uid int)"
|
||||||
|
)
|
||||||
|
cur.execute("CREATE TABLE version(v text)")
|
||||||
|
cur.execute("INSERT INTO version VALUES(?)", ("v1.3",))
|
||||||
|
db.commit()
|
||||||
|
cur.close()
|
||||||
|
db.close()
|
||||||
|
|
||||||
|
# 数据库版本更新
|
||||||
|
db = sqlite3.connect(self.database_path)
|
||||||
|
cur = db.cursor()
|
||||||
|
cur.execute("SELECT * FROM version WHERE True")
|
||||||
|
version = cur.fetchall()
|
||||||
|
# v1.0-->v1.1
|
||||||
|
if version[0][0] == "v1.0":
|
||||||
|
cur.execute("SELECT * FROM adminx WHERE True")
|
||||||
|
data = cur.fetchall()
|
||||||
|
cur.execute("DROP TABLE IF EXISTS adminx")
|
||||||
|
cur.execute(
|
||||||
|
"CREATE TABLE adminx(admin text,id text,server text,day int,status text,last date,game text,game_1 text,game_2 text,routines text,annihilation text,infrastructure text,password byte,notes text,numb int,mode text,uid int)"
|
||||||
|
)
|
||||||
|
for i in range(len(data)):
|
||||||
|
cur.execute(
|
||||||
|
"INSERT INTO adminx VALUES(?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)",
|
||||||
|
(
|
||||||
|
data[i][0], # 0 0 0
|
||||||
|
data[i][1], # 1 1 -
|
||||||
|
"Official", # 2 2 -
|
||||||
|
data[i][2], # 3 3 1
|
||||||
|
data[i][3], # 4 4 2
|
||||||
|
data[i][4], # 5 5 3
|
||||||
|
data[i][5], # 6 6 -
|
||||||
|
data[i][6], # 7 7 -
|
||||||
|
data[i][7], # 8 8 -
|
||||||
|
"y", # 9 - 4
|
||||||
|
data[i][8], # 10 9 5
|
||||||
|
data[i][9], # 11 10 -
|
||||||
|
data[i][10], # 12 11 6
|
||||||
|
data[i][11], # 13 12 7
|
||||||
|
data[i][12], # 14 - -
|
||||||
|
"simple", # 15 - -
|
||||||
|
data[i][13], # 16 - -
|
||||||
|
),
|
||||||
|
)
|
||||||
|
cur.execute("DELETE FROM version WHERE v = ?", ("v1.0",))
|
||||||
|
cur.execute("INSERT INTO version VALUES(?)", ("v1.1",))
|
||||||
|
db.commit()
|
||||||
|
# v1.1-->v1.2
|
||||||
|
if version[0][0] == "v1.1":
|
||||||
|
cur.execute("SELECT * FROM adminx WHERE True")
|
||||||
|
data = cur.fetchall()
|
||||||
|
for i in range(len(data)):
|
||||||
|
cur.execute(
|
||||||
|
"UPDATE adminx SET infrastructure = 'n' WHERE mode = ? AND uid = ?",
|
||||||
|
(
|
||||||
|
data[i][15],
|
||||||
|
data[i][16],
|
||||||
|
),
|
||||||
|
)
|
||||||
|
cur.execute("DELETE FROM version WHERE v = ?", ("v1.1",))
|
||||||
|
cur.execute("INSERT INTO version VALUES(?)", ("v1.2",))
|
||||||
|
db.commit()
|
||||||
|
# v1.2-->v1.3
|
||||||
|
if version[0][0] == "v1.2":
|
||||||
|
cur.execute("ALTER TABLE adminx RENAME COLUMN routines TO routine")
|
||||||
|
cur.execute("DELETE FROM version WHERE v = ?", ("v1.2",))
|
||||||
|
cur.execute("INSERT INTO version VALUES(?)", ("v1.3",))
|
||||||
|
db.commit()
|
||||||
|
cur.close()
|
||||||
|
db.close()
|
||||||
|
|
||||||
|
def open_database(self) -> None:
|
||||||
|
"""打开数据库"""
|
||||||
|
|
||||||
|
self.db = sqlite3.connect(self.database_path)
|
||||||
|
self.cur = self.db.cursor()
|
||||||
|
|
||||||
|
def close_database(self) -> None:
|
||||||
|
"""关闭数据库"""
|
||||||
|
|
||||||
|
self.cur.close()
|
||||||
|
self.db.close()
|
||||||
|
|
||||||
|
def save_config(self) -> None:
|
||||||
|
"""保存配置文件"""
|
||||||
|
|
||||||
|
with self.config_path.open(mode="w", encoding="utf-8") as f:
|
||||||
|
json.dump(self.content, f, indent=4)
|
||||||
1035
app/models/MAA.py
Normal file
34
app/models/__init__.py
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
# <AUTO_MAA:A MAA Multi Account Management and Automation Tool>
|
||||||
|
# Copyright © <2024> <DLmaster361>
|
||||||
|
|
||||||
|
# This file is part of AUTO_MAA.
|
||||||
|
|
||||||
|
# AUTO_MAA 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.
|
||||||
|
|
||||||
|
# AUTO_MAA 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 AUTO_MAA. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
# DLmaster_361@163.com
|
||||||
|
|
||||||
|
"""
|
||||||
|
AUTO_MAA
|
||||||
|
AUTO_MAA模组包
|
||||||
|
v4.2
|
||||||
|
作者:DLmaster_361
|
||||||
|
"""
|
||||||
|
|
||||||
|
__version__ = "4.2.0"
|
||||||
|
__author__ = "DLmaster361 <DLmaster_361@163.com>"
|
||||||
|
__license__ = "GPL-3.0 license"
|
||||||
|
|
||||||
|
from .MAA import MaaManager
|
||||||
|
|
||||||
|
__all__ = ["MaaManager"]
|
||||||
35
app/services/__init__.py
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
# <AUTO_MAA:A MAA Multi Account Management and Automation Tool>
|
||||||
|
# Copyright © <2024> <DLmaster361>
|
||||||
|
|
||||||
|
# This file is part of AUTO_MAA.
|
||||||
|
|
||||||
|
# AUTO_MAA 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.
|
||||||
|
|
||||||
|
# AUTO_MAA 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 AUTO_MAA. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
# DLmaster_361@163.com
|
||||||
|
|
||||||
|
"""
|
||||||
|
AUTO_MAA
|
||||||
|
AUTO_MAA服务包
|
||||||
|
v4.2
|
||||||
|
作者:DLmaster_361
|
||||||
|
"""
|
||||||
|
|
||||||
|
__version__ = "4.2.0"
|
||||||
|
__author__ = "DLmaster361 <DLmaster_361@163.com>"
|
||||||
|
__license__ = "GPL-3.0 license"
|
||||||
|
|
||||||
|
from .notification import Notification
|
||||||
|
from .security import CryptoHandler
|
||||||
|
|
||||||
|
__all__ = ["Notification", "CryptoHandler"]
|
||||||
95
app/services/notification.py
Normal file
@@ -0,0 +1,95 @@
|
|||||||
|
# <AUTO_MAA:A MAA Multi Account Management and Automation Tool>
|
||||||
|
# Copyright © <2024> <DLmaster361>
|
||||||
|
|
||||||
|
# This file is part of AUTO_MAA.
|
||||||
|
|
||||||
|
# AUTO_MAA 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.
|
||||||
|
|
||||||
|
# AUTO_MAA 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 AUTO_MAA. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
# DLmaster_361@163.com
|
||||||
|
|
||||||
|
"""
|
||||||
|
AUTO_MAA
|
||||||
|
AUTO_MAA通知服务
|
||||||
|
v4.2
|
||||||
|
作者:DLmaster_361
|
||||||
|
"""
|
||||||
|
|
||||||
|
from plyer import notification
|
||||||
|
import smtplib
|
||||||
|
from email.mime.text import MIMEText
|
||||||
|
from email.header import Header
|
||||||
|
from email.utils import formataddr
|
||||||
|
import os
|
||||||
|
|
||||||
|
from app import AppConfig
|
||||||
|
|
||||||
|
|
||||||
|
class Notification:
|
||||||
|
|
||||||
|
def __init__(self, config: AppConfig):
|
||||||
|
|
||||||
|
self.config = config
|
||||||
|
|
||||||
|
def push_notification(self, title, message, ticker, t):
|
||||||
|
"""推送系统通知"""
|
||||||
|
|
||||||
|
notification.notify(
|
||||||
|
title=title,
|
||||||
|
message=message,
|
||||||
|
app_name="AUTO_MAA",
|
||||||
|
app_icon=str(self.config.app_path / "resources/icons/AUTO_MAA.ico"),
|
||||||
|
timeout=t,
|
||||||
|
ticker=ticker,
|
||||||
|
toast=True,
|
||||||
|
)
|
||||||
|
|
||||||
|
return True
|
||||||
|
|
||||||
|
def send_mail(self, title, content):
|
||||||
|
"""使用官方专用邮箱推送邮件通知"""
|
||||||
|
|
||||||
|
# 声明:此邮箱为AUTO_MAA项目组资产,未经授权不得私自使用
|
||||||
|
# 注意:此声明注释只有使用者更换发信邮箱时才能删除,本条规则优先级高于GPLv3
|
||||||
|
|
||||||
|
# 第三方 SMTP 服务配置
|
||||||
|
mail_host = "smtp.163.com" # 设置服务器
|
||||||
|
mail_sender = "AUTO_MAA_server@163.com" # 用户名
|
||||||
|
mail_key = "SYrq87nDLD4RNB5T" # 授权码 24/11/15
|
||||||
|
|
||||||
|
# 定义邮件正文
|
||||||
|
message = MIMEText(content, "plain", "utf-8")
|
||||||
|
message["From"] = formataddr(
|
||||||
|
(Header("AUTO_MAA通知服务", "utf-8").encode(), "AUTO_MAA_server@163.com")
|
||||||
|
) # 发件人显示的名字
|
||||||
|
message["To"] = formataddr(
|
||||||
|
(
|
||||||
|
Header("AUTO_MAA用户", "utf-8").encode(),
|
||||||
|
self.config.content["Default"]["SelfSet.MailAddress"],
|
||||||
|
)
|
||||||
|
) # 收件人显示的名字
|
||||||
|
message["Subject"] = Header(title, "utf-8")
|
||||||
|
|
||||||
|
try:
|
||||||
|
smtpObj = smtplib.SMTP_SSL(mail_host, 465) # 465为SMTP_SSL默认端口
|
||||||
|
smtpObj.login(mail_sender, mail_key)
|
||||||
|
smtpObj.sendmail(
|
||||||
|
mail_sender,
|
||||||
|
self.config.content["Default"]["SelfSet.MailAddress"],
|
||||||
|
message.as_string(),
|
||||||
|
)
|
||||||
|
return True
|
||||||
|
except smtplib.SMTPException as e:
|
||||||
|
return f"发送邮件时出错:\n{e}"
|
||||||
|
finally:
|
||||||
|
smtpObj.quit()
|
||||||
167
app/services/security.py
Normal file
@@ -0,0 +1,167 @@
|
|||||||
|
# <AUTO_MAA:A MAA Multi Account Management and Automation Tool>
|
||||||
|
# Copyright © <2024> <DLmaster361>
|
||||||
|
|
||||||
|
# This file is part of AUTO_MAA.
|
||||||
|
|
||||||
|
# AUTO_MAA 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.
|
||||||
|
|
||||||
|
# AUTO_MAA 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 AUTO_MAA. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
# DLmaster_361@163.com
|
||||||
|
|
||||||
|
"""
|
||||||
|
AUTO_MAA
|
||||||
|
AUTO_MAA主程序
|
||||||
|
v4.2
|
||||||
|
作者:DLmaster_361
|
||||||
|
"""
|
||||||
|
|
||||||
|
import os
|
||||||
|
import hashlib
|
||||||
|
import random
|
||||||
|
import secrets
|
||||||
|
from Crypto.Cipher import AES
|
||||||
|
from Crypto.PublicKey import RSA
|
||||||
|
from Crypto.Cipher import PKCS1_OAEP
|
||||||
|
from Crypto.Util.Padding import pad, unpad
|
||||||
|
|
||||||
|
from app import AppConfig
|
||||||
|
|
||||||
|
|
||||||
|
class CryptoHandler:
|
||||||
|
|
||||||
|
def __init__(self, config: AppConfig):
|
||||||
|
|
||||||
|
self.config = config
|
||||||
|
|
||||||
|
def get_PASSWORD(self, PASSWORD: str) -> None:
|
||||||
|
"""配置管理密钥"""
|
||||||
|
|
||||||
|
# 生成目录
|
||||||
|
self.config.key_path.mkdir(parents=True, exist_ok=True)
|
||||||
|
|
||||||
|
# 生成RSA密钥对
|
||||||
|
key = RSA.generate(2048)
|
||||||
|
public_key_local = key.publickey()
|
||||||
|
private_key = key
|
||||||
|
# 保存RSA公钥
|
||||||
|
(self.config.app_path / "data/key/public_key.pem").write_bytes(
|
||||||
|
public_key_local.exportKey()
|
||||||
|
)
|
||||||
|
# 生成密钥转换与校验随机盐
|
||||||
|
PASSWORD_salt = secrets.token_hex(random.randint(32, 1024))
|
||||||
|
(self.config.app_path / "data/key/PASSWORDsalt.txt").write_text(
|
||||||
|
PASSWORD_salt,
|
||||||
|
encoding="utf-8",
|
||||||
|
)
|
||||||
|
verify_salt = secrets.token_hex(random.randint(32, 1024))
|
||||||
|
(self.config.app_path / "data/key/verifysalt.txt").write_text(
|
||||||
|
verify_salt,
|
||||||
|
encoding="utf-8",
|
||||||
|
)
|
||||||
|
# 将管理密钥转化为AES-256密钥
|
||||||
|
AES_password = hashlib.sha256(
|
||||||
|
(PASSWORD + PASSWORD_salt).encode("utf-8")
|
||||||
|
).digest()
|
||||||
|
# 生成AES-256密钥校验哈希值并保存
|
||||||
|
AES_password_verify = hashlib.sha256(
|
||||||
|
AES_password + verify_salt.encode("utf-8")
|
||||||
|
).digest()
|
||||||
|
(self.config.app_path / "data/key/AES_password_verify.bin").write_bytes(
|
||||||
|
AES_password_verify
|
||||||
|
)
|
||||||
|
# AES-256加密RSA私钥并保存密文
|
||||||
|
AES_key = AES.new(AES_password, AES.MODE_ECB)
|
||||||
|
private_key_local = AES_key.encrypt(pad(private_key.exportKey(), 32))
|
||||||
|
(self.config.app_path / "data/key/private_key.bin").write_bytes(
|
||||||
|
private_key_local
|
||||||
|
)
|
||||||
|
|
||||||
|
def encryptx(self, note: str) -> bytes:
|
||||||
|
"""加密数据"""
|
||||||
|
|
||||||
|
# 读取RSA公钥
|
||||||
|
public_key_local = RSA.import_key(
|
||||||
|
(self.config.app_path / "data/key/public_key.pem").read_bytes()
|
||||||
|
)
|
||||||
|
# 使用RSA公钥对数据进行加密
|
||||||
|
cipher = PKCS1_OAEP.new(public_key_local)
|
||||||
|
encrypted = cipher.encrypt(note.encode("utf-8"))
|
||||||
|
return encrypted
|
||||||
|
|
||||||
|
def decryptx(self, note: bytes, PASSWORD: str) -> str:
|
||||||
|
"""解密数据"""
|
||||||
|
|
||||||
|
# 读入RSA私钥密文、盐与校验哈希值
|
||||||
|
private_key_local = (
|
||||||
|
(self.config.app_path / "data/key/private_key.bin").read_bytes().strip()
|
||||||
|
)
|
||||||
|
PASSWORD_salt = (
|
||||||
|
(self.config.app_path / "data/key/PASSWORDsalt.txt")
|
||||||
|
.read_text(encoding="utf-8")
|
||||||
|
.strip()
|
||||||
|
)
|
||||||
|
verify_salt = (
|
||||||
|
(self.config.app_path / "data/key/verifysalt.txt")
|
||||||
|
.read_text(encoding="utf-8")
|
||||||
|
.strip()
|
||||||
|
)
|
||||||
|
AES_password_verify = (
|
||||||
|
(self.config.app_path / "data/key/AES_password_verify.bin")
|
||||||
|
.read_bytes()
|
||||||
|
.strip()
|
||||||
|
)
|
||||||
|
# 将管理密钥转化为AES-256密钥并验证
|
||||||
|
AES_password = hashlib.sha256(
|
||||||
|
(PASSWORD + PASSWORD_salt).encode("utf-8")
|
||||||
|
).digest()
|
||||||
|
AES_password_SHA = hashlib.sha256(
|
||||||
|
AES_password + verify_salt.encode("utf-8")
|
||||||
|
).digest()
|
||||||
|
if AES_password_SHA != AES_password_verify:
|
||||||
|
return "管理密钥错误"
|
||||||
|
else:
|
||||||
|
# AES解密RSA私钥
|
||||||
|
AES_key = AES.new(AES_password, AES.MODE_ECB)
|
||||||
|
private_key_pem = unpad(AES_key.decrypt(private_key_local), 32)
|
||||||
|
private_key = RSA.import_key(private_key_pem)
|
||||||
|
# 使用RSA私钥解密数据
|
||||||
|
decrypter = PKCS1_OAEP.new(private_key)
|
||||||
|
note = decrypter.decrypt(note)
|
||||||
|
return note.decode("utf-8")
|
||||||
|
|
||||||
|
def change_PASSWORD(self, data: list, PASSWORD_old: str, PASSWORD_new: str) -> None:
|
||||||
|
"""修改管理密钥"""
|
||||||
|
|
||||||
|
# 使用旧管理密钥解密
|
||||||
|
new_data = []
|
||||||
|
for i in range(len(data)):
|
||||||
|
new_data.append(self.decryptx(data[i][12], PASSWORD_old))
|
||||||
|
# 使用新管理密钥重新加密
|
||||||
|
self.get_PASSWORD(PASSWORD_new)
|
||||||
|
for i in range(len(data)):
|
||||||
|
self.config.cur.execute(
|
||||||
|
"UPDATE adminx SET password = ? WHERE mode = ? AND uid = ?",
|
||||||
|
(
|
||||||
|
self.encryptx(new_data[i]),
|
||||||
|
data[i][15],
|
||||||
|
data[i][16],
|
||||||
|
),
|
||||||
|
)
|
||||||
|
self.config.db.commit(),
|
||||||
|
new_data[i] = None
|
||||||
|
del new_data
|
||||||
|
|
||||||
|
def check_PASSWORD(self, PASSWORD: str) -> bool:
|
||||||
|
"""验证管理密钥"""
|
||||||
|
|
||||||
|
return bool(self.decryptx(self.encryptx(""), PASSWORD) != "管理密钥错误")
|
||||||
34
app/ui/__init__.py
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
# <AUTO_MAA:A MAA Multi Account Management and Automation Tool>
|
||||||
|
# Copyright © <2024> <DLmaster361>
|
||||||
|
|
||||||
|
# This file is part of AUTO_MAA.
|
||||||
|
|
||||||
|
# AUTO_MAA 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.
|
||||||
|
|
||||||
|
# AUTO_MAA 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 AUTO_MAA. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
# DLmaster_361@163.com
|
||||||
|
|
||||||
|
"""
|
||||||
|
AUTO_MAA
|
||||||
|
AUTO_MAA图形化界面包
|
||||||
|
v4.2
|
||||||
|
作者:DLmaster_361
|
||||||
|
"""
|
||||||
|
|
||||||
|
__version__ = "4.2.0"
|
||||||
|
__author__ = "DLmaster361 <DLmaster_361@163.com>"
|
||||||
|
__license__ = "GPL-3.0 license"
|
||||||
|
|
||||||
|
from .gui import AUTO_MAA
|
||||||
|
|
||||||
|
__all__ = ["AUTO_MAA"]
|
||||||
1823
app/ui/gui.py
Normal file
343
app/utils/Updater.py
Normal file
@@ -0,0 +1,343 @@
|
|||||||
|
# <AUTO_MAA:A MAA Multi Account Management and Automation Tool>
|
||||||
|
# Copyright © <2024> <DLmaster361>
|
||||||
|
|
||||||
|
# This file is part of AUTO_MAA.
|
||||||
|
|
||||||
|
# AUTO_MAA 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.
|
||||||
|
|
||||||
|
# AUTO_MAA 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 AUTO_MAA. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
# DLmaster_361@163.com
|
||||||
|
|
||||||
|
"""
|
||||||
|
AUTO_MAA
|
||||||
|
AUTO_MAA更新器
|
||||||
|
v1.1
|
||||||
|
作者:DLmaster_361
|
||||||
|
"""
|
||||||
|
|
||||||
|
import os
|
||||||
|
import sys
|
||||||
|
import json
|
||||||
|
import zipfile
|
||||||
|
import requests
|
||||||
|
import subprocess
|
||||||
|
import time
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
from PySide6.QtWidgets import (
|
||||||
|
QApplication,
|
||||||
|
QDialog,
|
||||||
|
QVBoxLayout,
|
||||||
|
)
|
||||||
|
from qfluentwidgets import ProgressBar, BodyLabel
|
||||||
|
from PySide6.QtGui import QIcon
|
||||||
|
from PySide6.QtCore import QObject, QThread, Signal
|
||||||
|
|
||||||
|
from .version import version_text
|
||||||
|
|
||||||
|
|
||||||
|
class UpdateProcess(QThread):
|
||||||
|
|
||||||
|
info = Signal(str)
|
||||||
|
progress = Signal(int, int, int)
|
||||||
|
accomplish = Signal()
|
||||||
|
|
||||||
|
def __init__(
|
||||||
|
self, app_path: Path, name: str, main_version: list, updater_version: list
|
||||||
|
) -> None:
|
||||||
|
super(UpdateProcess, self).__init__()
|
||||||
|
|
||||||
|
self.app_path = app_path
|
||||||
|
self.name = name
|
||||||
|
self.main_version = main_version
|
||||||
|
self.updater_version = updater_version
|
||||||
|
self.download_path = app_path / "AUTO_MAA_Update.zip" # 临时下载文件的路径
|
||||||
|
self.version_path = app_path / "resources/version.json"
|
||||||
|
|
||||||
|
def run(self) -> None:
|
||||||
|
|
||||||
|
# 清理可能存在的临时文件
|
||||||
|
try:
|
||||||
|
os.remove(self.download_path)
|
||||||
|
except FileNotFoundError:
|
||||||
|
pass
|
||||||
|
|
||||||
|
self.info.emit("正在获取下载链接")
|
||||||
|
url_list = self.get_download_url()
|
||||||
|
|
||||||
|
# 验证下载地址并获取文件大小
|
||||||
|
for i in range(len(url_list)):
|
||||||
|
try:
|
||||||
|
self.info.emit(f"正在验证下载地址:{url_list[i]}")
|
||||||
|
response = requests.get(url_list[i], stream=True)
|
||||||
|
if response.status_code != 200:
|
||||||
|
self.info.emit(
|
||||||
|
f"连接失败,错误代码 {response.status_code} ,正在切换代理({i+1}/{len(url_list)})"
|
||||||
|
)
|
||||||
|
time.sleep(1)
|
||||||
|
continue
|
||||||
|
file_size = response.headers.get("Content-Length")
|
||||||
|
break
|
||||||
|
except requests.RequestException:
|
||||||
|
self.info.emit(f"请求超时,正在切换代理({i+1}/{len(url_list)})")
|
||||||
|
time.sleep(1)
|
||||||
|
else:
|
||||||
|
self.info.emit(f"连接失败,已尝试所有{len(url_list)}个代理")
|
||||||
|
return None
|
||||||
|
|
||||||
|
if file_size is None:
|
||||||
|
file_size = 1
|
||||||
|
else:
|
||||||
|
file_size = int(file_size)
|
||||||
|
|
||||||
|
try:
|
||||||
|
# 下载文件
|
||||||
|
with open(self.download_path, "wb") as f:
|
||||||
|
|
||||||
|
downloaded_size = 0
|
||||||
|
last_download_size = 0
|
||||||
|
speed = 0
|
||||||
|
last_time = time.time()
|
||||||
|
|
||||||
|
for chunk in response.iter_content(chunk_size=8192):
|
||||||
|
|
||||||
|
# 写入已下载数据
|
||||||
|
f.write(chunk)
|
||||||
|
downloaded_size += len(chunk)
|
||||||
|
|
||||||
|
# 计算下载速度
|
||||||
|
if time.time() - last_time >= 1.0:
|
||||||
|
speed = (
|
||||||
|
(downloaded_size - last_download_size)
|
||||||
|
/ (time.time() - last_time)
|
||||||
|
/ 1024
|
||||||
|
)
|
||||||
|
last_download_size = downloaded_size
|
||||||
|
last_time = time.time()
|
||||||
|
|
||||||
|
# 更新下载进度
|
||||||
|
if speed >= 1024:
|
||||||
|
self.info.emit(
|
||||||
|
f"正在下载:{self.name} 已下载:{downloaded_size / 1048576:.2f}/{file_size / 1048576:.2f} MB ({downloaded_size / file_size * 100:.2f}%) 下载速度:{speed / 1024:.2f} MB/s",
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
self.info.emit(
|
||||||
|
f"正在下载:{self.name} 已下载:{downloaded_size / 1048576:.2f}/{file_size / 1048576:.2f} MB ({downloaded_size / file_size * 100:.2f}%) 下载速度:{speed:.2f} KB/s",
|
||||||
|
)
|
||||||
|
self.progress.emit(0, 100, int(downloaded_size / file_size * 100))
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
e = str(e)
|
||||||
|
e = "\n".join([e[_ : _ + 75] for _ in range(0, len(e), 75)])
|
||||||
|
self.info.emit(f"下载{self.name}时出错:\n{e}")
|
||||||
|
return None
|
||||||
|
|
||||||
|
# 解压
|
||||||
|
try:
|
||||||
|
|
||||||
|
while True:
|
||||||
|
try:
|
||||||
|
self.info.emit("正在解压更新文件")
|
||||||
|
self.progress.emit(0, 0, 0)
|
||||||
|
with zipfile.ZipFile(self.download_path, "r") as zip_ref:
|
||||||
|
zip_ref.extractall(self.app_path)
|
||||||
|
break
|
||||||
|
except PermissionError:
|
||||||
|
self.info.emit("解压出错:AUTO_MAA正在运行,正在等待其关闭")
|
||||||
|
time.sleep(1)
|
||||||
|
|
||||||
|
self.info.emit("正在删除临时文件")
|
||||||
|
self.progress.emit(0, 0, 0)
|
||||||
|
os.remove(self.download_path)
|
||||||
|
|
||||||
|
self.info.emit(f"{self.name}更新成功!")
|
||||||
|
self.progress.emit(0, 100, 100)
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
|
||||||
|
e = str(e)
|
||||||
|
e = "\n".join([e[_ : _ + 75] for _ in range(0, len(e), 75)])
|
||||||
|
self.info.emit(f"解压更新时出错:\n{e}")
|
||||||
|
return None
|
||||||
|
|
||||||
|
# 更新version文件
|
||||||
|
with open(self.version_path, "r", encoding="utf-8") as f:
|
||||||
|
version_info = json.load(f)
|
||||||
|
if self.name == "AUTO_MAA更新器":
|
||||||
|
version_info["updater_version"] = ".".join(map(str, self.updater_version))
|
||||||
|
elif self.name == "AUTO_MAA主程序":
|
||||||
|
version_info["main_version"] = ".".join(map(str, self.main_version))
|
||||||
|
with open(self.version_path, "w", encoding="utf-8") as f:
|
||||||
|
json.dump(version_info, f, indent=4)
|
||||||
|
|
||||||
|
# 主程序更新完成后打开AUTO_MAA
|
||||||
|
if self.name == "AUTO_MAA主程序":
|
||||||
|
subprocess.Popen(
|
||||||
|
str(self.app_path / "AUTO_MAA.exe"),
|
||||||
|
shell=True,
|
||||||
|
creationflags=subprocess.CREATE_NO_WINDOW,
|
||||||
|
)
|
||||||
|
|
||||||
|
self.accomplish.emit()
|
||||||
|
|
||||||
|
def get_download_url(self) -> list:
|
||||||
|
"""获取下载链接"""
|
||||||
|
|
||||||
|
try_num = 3
|
||||||
|
for i in range(try_num):
|
||||||
|
try:
|
||||||
|
response = requests.get(
|
||||||
|
"https://gitee.com/DLmaster_361/AUTO_MAA/raw/main/resources/version.json"
|
||||||
|
)
|
||||||
|
if response.status_code != 200:
|
||||||
|
self.info.emit(
|
||||||
|
f"连接失败,错误代码 {response.status_code} ,正在重试({i+1}/{try_num})"
|
||||||
|
)
|
||||||
|
time.sleep(0.1)
|
||||||
|
continue
|
||||||
|
version_remote = response.json()
|
||||||
|
PROXY_list = version_remote["proxy_list"]
|
||||||
|
break
|
||||||
|
except requests.RequestException:
|
||||||
|
self.info.emit(f"请求超时,正在重试({i+1}/{try_num})")
|
||||||
|
time.sleep(0.1)
|
||||||
|
except KeyError:
|
||||||
|
self.info.emit(f"未找到远端代理网址项,正在重试({i+1}/{try_num})")
|
||||||
|
time.sleep(0.1)
|
||||||
|
else:
|
||||||
|
self.info.emit("获取远端代理信息失败,将使用默认代理地址")
|
||||||
|
PROXY_list = [
|
||||||
|
"",
|
||||||
|
"https://gitproxy.click/",
|
||||||
|
"https://cdn.moran233.xyz/",
|
||||||
|
"https://gh.llkk.cc/",
|
||||||
|
"https://github.akams.cn/",
|
||||||
|
"https://www.ghproxy.cn/",
|
||||||
|
"https://ghp.ci/",
|
||||||
|
]
|
||||||
|
time.sleep(1)
|
||||||
|
|
||||||
|
url_list = []
|
||||||
|
if self.name == "AUTO_MAA主程序":
|
||||||
|
url_list.append(
|
||||||
|
f"https://gitee.com/DLmaster_361/AUTO_MAA/releases/download/{version_text(self.main_version)}/AUTO_MAA_{version_text(self.main_version)}.zip"
|
||||||
|
)
|
||||||
|
for i in range(len(PROXY_list)):
|
||||||
|
url_list.append(
|
||||||
|
f"{PROXY_list[i]}https://github.com/DLmaster361/AUTO_MAA/releases/download/{version_text(self.main_version)}/AUTO_MAA_{version_text(self.main_version)}.zip"
|
||||||
|
)
|
||||||
|
elif self.name == "AUTO_MAA更新器":
|
||||||
|
url_list.append(
|
||||||
|
f"https://gitee.com/DLmaster_361/AUTO_MAA/releases/download/{version_text(self.main_version)}/Updater_{version_text(self.updater_version)}.zip"
|
||||||
|
)
|
||||||
|
for i in range(len(PROXY_list)):
|
||||||
|
url_list.append(
|
||||||
|
f"{PROXY_list[i]}https://github.com/DLmaster361/AUTO_MAA/releases/download/{version_text(self.main_version)}/Updater_{version_text(self.updater_version)}.zip"
|
||||||
|
)
|
||||||
|
return url_list
|
||||||
|
|
||||||
|
|
||||||
|
class Updater(QObject):
|
||||||
|
|
||||||
|
def __init__(
|
||||||
|
self, app_path: Path, name: str, main_version: list, updater_version: list
|
||||||
|
) -> None:
|
||||||
|
super().__init__()
|
||||||
|
|
||||||
|
self.ui = QDialog()
|
||||||
|
self.ui.setWindowTitle("AUTO_MAA更新器")
|
||||||
|
self.ui.resize(700, 70)
|
||||||
|
self.ui.setWindowIcon(
|
||||||
|
QIcon(str(app_path / "resources/icons/AUTO_MAA_Updater.ico"))
|
||||||
|
)
|
||||||
|
|
||||||
|
# 创建垂直布局
|
||||||
|
self.Layout_v = QVBoxLayout(self.ui)
|
||||||
|
|
||||||
|
self.info = BodyLabel("正在初始化", self.ui)
|
||||||
|
self.Layout_v.addWidget(self.info)
|
||||||
|
|
||||||
|
self.progress = ProgressBar(self.ui)
|
||||||
|
self.progress.setRange(0, 0)
|
||||||
|
self.Layout_v.addWidget(self.progress)
|
||||||
|
|
||||||
|
self.update_process = UpdateProcess(
|
||||||
|
app_path, name, main_version, updater_version
|
||||||
|
)
|
||||||
|
|
||||||
|
self.update_process.info.connect(self.update_info)
|
||||||
|
self.update_process.progress.connect(self.update_progress)
|
||||||
|
|
||||||
|
self.update_process.start()
|
||||||
|
|
||||||
|
def update_info(self, text: str) -> None:
|
||||||
|
self.info.setText(text)
|
||||||
|
|
||||||
|
def update_progress(self, begin: int, end: int, current: int) -> None:
|
||||||
|
self.progress.setRange(begin, end)
|
||||||
|
self.progress.setValue(current)
|
||||||
|
|
||||||
|
|
||||||
|
class AUTO_MAA_Updater(QApplication):
|
||||||
|
def __init__(
|
||||||
|
self, app_path: Path, name: str, main_version: list, updater_version: list
|
||||||
|
) -> None:
|
||||||
|
super().__init__()
|
||||||
|
|
||||||
|
self.main = Updater(app_path, name, main_version, updater_version)
|
||||||
|
self.main.ui.show()
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
|
||||||
|
# 获取软件自身的路径
|
||||||
|
app_path = Path.cwd()
|
||||||
|
|
||||||
|
# 从本地版本信息文件获取当前版本信息
|
||||||
|
if (app_path / "resources/version.json").exists():
|
||||||
|
with (app_path / "resources/version.json").open(
|
||||||
|
mode="r", encoding="utf-8"
|
||||||
|
) as f:
|
||||||
|
version_current = json.load(f)
|
||||||
|
main_version_current = list(
|
||||||
|
map(int, version_current["main_version"].split("."))
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
main_version_current = [0, 0, 0, 0]
|
||||||
|
|
||||||
|
# 从远程服务器获取最新版本信息
|
||||||
|
for _ in range(3):
|
||||||
|
try:
|
||||||
|
response = requests.get(
|
||||||
|
"https://gitee.com/DLmaster_361/AUTO_MAA/raw/main/resources/version.json"
|
||||||
|
)
|
||||||
|
version_remote = response.json()
|
||||||
|
main_version_remote = list(
|
||||||
|
map(int, version_remote["main_version"].split("."))
|
||||||
|
)
|
||||||
|
break
|
||||||
|
except Exception as e:
|
||||||
|
err = e
|
||||||
|
time.sleep(0.1)
|
||||||
|
else:
|
||||||
|
sys.exit(f"获取版本信息时出错:\n{err}")
|
||||||
|
|
||||||
|
# 启动更新线程
|
||||||
|
if main_version_remote > main_version_current:
|
||||||
|
app = AUTO_MAA_Updater(
|
||||||
|
app_path,
|
||||||
|
"AUTO_MAA主程序",
|
||||||
|
main_version_remote,
|
||||||
|
[],
|
||||||
|
)
|
||||||
|
sys.exit(app.exec())
|
||||||
35
app/utils/__init__.py
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
# <AUTO_MAA:A MAA Multi Account Management and Automation Tool>
|
||||||
|
# Copyright © <2024> <DLmaster361>
|
||||||
|
|
||||||
|
# This file is part of AUTO_MAA.
|
||||||
|
|
||||||
|
# AUTO_MAA 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.
|
||||||
|
|
||||||
|
# AUTO_MAA 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 AUTO_MAA. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
# DLmaster_361@163.com
|
||||||
|
|
||||||
|
"""
|
||||||
|
AUTO_MAA
|
||||||
|
AUTO_MAA工具包
|
||||||
|
v4.2
|
||||||
|
作者:DLmaster_361
|
||||||
|
"""
|
||||||
|
|
||||||
|
__version__ = "4.2.0"
|
||||||
|
__author__ = "DLmaster361 <DLmaster_361@163.com>"
|
||||||
|
__license__ = "GPL-3.0 license"
|
||||||
|
|
||||||
|
from .Updater import Updater
|
||||||
|
from .version import version_text
|
||||||
|
|
||||||
|
__all__ = ["Updater", "version_text"]
|
||||||
107
app/utils/package.py
Normal file
@@ -0,0 +1,107 @@
|
|||||||
|
# <AUTO_MAA:A MAA Multi Account Management and Automation Tool>
|
||||||
|
# Copyright © <2024> <DLmaster361>
|
||||||
|
|
||||||
|
# This file is part of AUTO_MAA.
|
||||||
|
|
||||||
|
# AUTO_MAA 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.
|
||||||
|
|
||||||
|
# AUTO_MAA 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 AUTO_MAA. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
# DLmaster_361@163.com
|
||||||
|
|
||||||
|
"""
|
||||||
|
AUTO_MAA
|
||||||
|
AUTO_MAA打包程序
|
||||||
|
v4.2
|
||||||
|
作者:DLmaster_361
|
||||||
|
"""
|
||||||
|
|
||||||
|
import os
|
||||||
|
import json
|
||||||
|
import shutil
|
||||||
|
import subprocess
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
from app import version_text
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
|
||||||
|
root_path = Path.cwd()
|
||||||
|
|
||||||
|
with (root_path / "resources/version.json").open(mode="r", encoding="utf-8") as f:
|
||||||
|
version = json.load(f)
|
||||||
|
|
||||||
|
main_version_numb = list(map(int, version["main_version"].split(".")))
|
||||||
|
updater_version_numb = list(map(int, version["updater_version"].split(".")))
|
||||||
|
|
||||||
|
print("Packaging AUTO_MAA main program ...")
|
||||||
|
|
||||||
|
result = subprocess.run(
|
||||||
|
f"powershell -Command nuitka --standalone --onefile --mingw64"
|
||||||
|
f" --enable-plugins=pyside6 --windows-console-mode=disable"
|
||||||
|
f" --windows-icon-from-ico=resources\\icons\\AUTO_MAA.ico"
|
||||||
|
f" --company-name='AUTO_MAA Team' --product-name=AUTO_MAA"
|
||||||
|
f" --file-version={version["main_version"]}"
|
||||||
|
f" --product-version={version["main_version"]}"
|
||||||
|
f" --file-description='AUTO_MAA Component'"
|
||||||
|
f" --copyright='Copyright © 2024 DLmaster361'"
|
||||||
|
f" --assume-yes-for-downloads --output-filename=AUTO_MAA"
|
||||||
|
f" --remove-output main.py",
|
||||||
|
shell=True,
|
||||||
|
capture_output=True,
|
||||||
|
text=True,
|
||||||
|
)
|
||||||
|
|
||||||
|
print(result.stdout)
|
||||||
|
print(result.stderr)
|
||||||
|
print("AUTO_MAA main program packaging completed !")
|
||||||
|
|
||||||
|
shutil.copy(root_path / "app/utils/Updater.py", root_path)
|
||||||
|
|
||||||
|
file_content = (root_path / "Updater.py").read_text(encoding="utf-8")
|
||||||
|
|
||||||
|
(root_path / "Updater.py").write_text(
|
||||||
|
file_content.replace(
|
||||||
|
"from .version import version_text", "from app import version_text"
|
||||||
|
),
|
||||||
|
encoding="utf-8",
|
||||||
|
)
|
||||||
|
|
||||||
|
print("Packaging AUTO_MAA update program ...")
|
||||||
|
|
||||||
|
result = subprocess.run(
|
||||||
|
f"powershell -Command nuitka --standalone --onefile --mingw64"
|
||||||
|
f" --enable-plugins=pyside6 --windows-console-mode=disable"
|
||||||
|
f" --windows-icon-from-ico=resources\\icons\\AUTO_MAA_Updater.ico"
|
||||||
|
f" --company-name='AUTO_MAA Team' --product-name=AUTO_MAA"
|
||||||
|
f" --file-version={version["updater_version"]}"
|
||||||
|
f" --product-version={version["main_version"]}"
|
||||||
|
f" --file-description='AUTO_MAA Component'"
|
||||||
|
f" --copyright='Copyright © 2024 DLmaster361'"
|
||||||
|
f" --assume-yes-for-downloads --output-filename=Updater"
|
||||||
|
f" --remove-output Updater.py",
|
||||||
|
shell=True,
|
||||||
|
capture_output=True,
|
||||||
|
text=True,
|
||||||
|
)
|
||||||
|
|
||||||
|
print(result.stdout)
|
||||||
|
print(result.stderr)
|
||||||
|
print("AUTO_MAA update program packaging completed !")
|
||||||
|
|
||||||
|
os.remove(root_path / "Updater.py")
|
||||||
|
|
||||||
|
(root_path / "version_info.txt").write_text(
|
||||||
|
f"{version_text(main_version_numb)}\n{version_text(updater_version_numb)}{version["announcement"]}",
|
||||||
|
encoding="utf-8",
|
||||||
|
)
|
||||||
38
app/utils/version.py
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
# <AUTO_MAA:A MAA Multi Account Management and Automation Tool>
|
||||||
|
# Copyright © <2024> <DLmaster361>
|
||||||
|
|
||||||
|
# This file is part of AUTO_MAA.
|
||||||
|
|
||||||
|
# AUTO_MAA 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.
|
||||||
|
|
||||||
|
# AUTO_MAA 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 AUTO_MAA. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
# DLmaster_361@163.com
|
||||||
|
|
||||||
|
"""
|
||||||
|
AUTO_MAA
|
||||||
|
AUTO_MAA版本号工具
|
||||||
|
v4.2
|
||||||
|
作者:DLmaster_361
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
||||||
|
def version_text(version_numb: list) -> str:
|
||||||
|
"""将版本号列表转为可读的文本信息"""
|
||||||
|
|
||||||
|
if version_numb[3] == 0:
|
||||||
|
version = f"v{'.'.join(str(_) for _ in version_numb[0:3])}"
|
||||||
|
else:
|
||||||
|
version = (
|
||||||
|
f"v{'.'.join(str(_) for _ in version_numb[0:3])}-beta.{version_numb[3]}"
|
||||||
|
)
|
||||||
|
return version
|
||||||
@@ -1,5 +0,0 @@
|
|||||||
龙门币:CE-6
|
|
||||||
技能:CA-5
|
|
||||||
红票:AP-5
|
|
||||||
经验:CA-5
|
|
||||||
剿灭模式:Annihilation
|
|
||||||
42
main.py
Normal file
@@ -0,0 +1,42 @@
|
|||||||
|
# <AUTO_MAA:A MAA Multi Account Management and Automation Tool>
|
||||||
|
# Copyright © <2024> <DLmaster361>
|
||||||
|
|
||||||
|
# This file is part of AUTO_MAA.
|
||||||
|
|
||||||
|
# AUTO_MAA 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.
|
||||||
|
|
||||||
|
# AUTO_MAA 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 AUTO_MAA. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
# DLmaster_361@163.com
|
||||||
|
|
||||||
|
"""
|
||||||
|
AUTO_MAA
|
||||||
|
AUTO_MAA主程序
|
||||||
|
v4.2
|
||||||
|
作者:DLmaster_361
|
||||||
|
"""
|
||||||
|
|
||||||
|
from PySide6.QtWidgets import QApplication
|
||||||
|
import sys
|
||||||
|
|
||||||
|
from app import AppConfig, Notification, CryptoHandler, AUTO_MAA
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
|
||||||
|
config = AppConfig()
|
||||||
|
notify = Notification(config)
|
||||||
|
crypto = CryptoHandler(config)
|
||||||
|
|
||||||
|
application = QApplication(sys.argv)
|
||||||
|
window = AUTO_MAA(config=config, notify=notify, crypto=crypto)
|
||||||
|
window.main.check_PASSWORD()
|
||||||
|
sys.exit(application.exec())
|
||||||
BIN
manage.exe
420
manage.py
@@ -1,420 +0,0 @@
|
|||||||
import sqlite3
|
|
||||||
import datetime
|
|
||||||
import msvcrt
|
|
||||||
import sys
|
|
||||||
import os
|
|
||||||
import hashlib
|
|
||||||
import random
|
|
||||||
import secrets
|
|
||||||
from Crypto.Cipher import AES
|
|
||||||
from Crypto.PublicKey import RSA
|
|
||||||
from Crypto.Cipher import PKCS1_OAEP
|
|
||||||
from Crypto.Util.Padding import pad,unpad
|
|
||||||
|
|
||||||
#读入密码
|
|
||||||
def readpass(text):
|
|
||||||
sys.stdout=sys.__stdout__
|
|
||||||
sys.stdout.write(text)
|
|
||||||
sys.stdout.flush()
|
|
||||||
p=''
|
|
||||||
while True:
|
|
||||||
typed=msvcrt.getch()
|
|
||||||
if len(p)!=0:
|
|
||||||
if typed==b'\r':
|
|
||||||
sys.stdout.write('\b*')
|
|
||||||
sys.stdout.flush()
|
|
||||||
break
|
|
||||||
elif typed==b'\b':
|
|
||||||
p=p[:-1]
|
|
||||||
sys.stdout.write('\b \b')
|
|
||||||
sys.stdout.flush()
|
|
||||||
else:
|
|
||||||
p+=typed.decode("utf-8")
|
|
||||||
sys.stdout.write('\b*'+typed.decode("utf-8"))
|
|
||||||
sys.stdout.flush()
|
|
||||||
elif typed!=b'\r' and typed!=b'\b':
|
|
||||||
p+=typed.decode("utf-8")
|
|
||||||
sys.stdout.write(typed.decode("utf-8"))
|
|
||||||
sys.stdout.flush()
|
|
||||||
|
|
||||||
print('')
|
|
||||||
return p
|
|
||||||
|
|
||||||
#配置密钥
|
|
||||||
def getPASSWORD(PASSWORD):
|
|
||||||
#生成RSA密钥对
|
|
||||||
key=RSA.generate(2048)
|
|
||||||
public_key_local=key.publickey()
|
|
||||||
private_key=key
|
|
||||||
#保存RSA公钥
|
|
||||||
with open('data/key/public_key.pem','wb') as f:
|
|
||||||
f.write(public_key_local.exportKey())
|
|
||||||
#生成密钥转换与校验随机盐
|
|
||||||
PASSWORDsalt=secrets.token_hex(random.randint(32,1024))
|
|
||||||
with open("data/key/PASSWORDsalt.txt","w",encoding="utf-8") as f:
|
|
||||||
print(PASSWORDsalt,file=f)
|
|
||||||
verifysalt=secrets.token_hex(random.randint(32,1024))
|
|
||||||
with open("data/key/verifysalt.txt","w",encoding="utf-8") as f:
|
|
||||||
print(verifysalt,file=f)
|
|
||||||
#将管理密钥转化为AES-256密钥
|
|
||||||
AES_password=hashlib.sha256((PASSWORD+PASSWORDsalt).encode("utf-8")).digest()
|
|
||||||
#生成AES-256密钥校验哈希值并保存
|
|
||||||
AES_password_verify=hashlib.sha256(AES_password+verifysalt.encode("utf-8")).digest()
|
|
||||||
with open("data/key/AES_password_verify.bin","wb") as f:
|
|
||||||
f.write(AES_password_verify)
|
|
||||||
#AES-256加密RSA私钥并保存密文
|
|
||||||
AES_key=AES.new(AES_password,AES.MODE_ECB)
|
|
||||||
private_key_local=AES_key.encrypt(pad(private_key.exportKey(),32))
|
|
||||||
with open("data/key/private_key.bin","wb") as f:
|
|
||||||
f.write(private_key_local)
|
|
||||||
|
|
||||||
#加密
|
|
||||||
def encryptx(note):
|
|
||||||
#读取RSA公钥
|
|
||||||
with open('data/key/public_key.pem','rb') as f:
|
|
||||||
public_key_local=RSA.import_key(f.read())
|
|
||||||
#使用RSA公钥对数据进行加密
|
|
||||||
cipher=PKCS1_OAEP.new(public_key_local)
|
|
||||||
encrypted=cipher.encrypt(note.encode("utf-8"))
|
|
||||||
return encrypted
|
|
||||||
|
|
||||||
#解密
|
|
||||||
def decryptx(note,PASSWORD):
|
|
||||||
#读入RSA私钥密文、盐与校验哈希值
|
|
||||||
with open("data/key/private_key.bin","rb") as f:
|
|
||||||
private_key_local=f.read().strip()
|
|
||||||
with open("data/key/PASSWORDsalt.txt","r",encoding="utf-8") as f:
|
|
||||||
PASSWORDsalt=f.read().strip()
|
|
||||||
with open("data/key/verifysalt.txt","r",encoding="utf-8") as f:
|
|
||||||
verifysalt=f.read().strip()
|
|
||||||
with open("data/key/AES_password_verify.bin","rb") as f:
|
|
||||||
AES_password_verify=f.read().strip()
|
|
||||||
#将管理密钥转化为AES-256密钥并验证
|
|
||||||
AES_password=hashlib.sha256((PASSWORD+PASSWORDsalt).encode("utf-8")).digest()
|
|
||||||
AES_password_SHA=hashlib.sha256(AES_password+verifysalt.encode("utf-8")).digest()
|
|
||||||
if AES_password_SHA!=AES_password_verify:
|
|
||||||
return "管理密钥错误"
|
|
||||||
else:
|
|
||||||
#AES解密RSA私钥
|
|
||||||
AES_key=AES.new(AES_password,AES.MODE_ECB)
|
|
||||||
private_key_pem=unpad(AES_key.decrypt(private_key_local),32)
|
|
||||||
private_key=RSA.import_key(private_key_pem)
|
|
||||||
#使用RSA私钥解密数据
|
|
||||||
decrypter=PKCS1_OAEP.new(private_key)
|
|
||||||
return decrypter.decrypt(note)
|
|
||||||
|
|
||||||
#添加用户
|
|
||||||
def add():
|
|
||||||
db=sqlite3.connect(DATABASE)
|
|
||||||
cur=db.cursor()
|
|
||||||
adminx=input("用户名:")
|
|
||||||
#用户名重复验证
|
|
||||||
while search(adminx,0)=="":
|
|
||||||
print("该用户已存在,请重新输入")
|
|
||||||
adminx=input("用户名:")
|
|
||||||
numberx=input("手机号码:")
|
|
||||||
dayx=int(input("代理天数:"))
|
|
||||||
gamex=input("关卡号:")
|
|
||||||
passwordx=readpass("密码:")
|
|
||||||
passwordx=encryptx(passwordx)
|
|
||||||
#应用更新
|
|
||||||
cur.execute("INSERT INTO adminx VALUES(?,?,?,'y','2000-01-01',?,?)",(adminx,numberx,dayx,gamex,passwordx))
|
|
||||||
db.commit()
|
|
||||||
cur.close()
|
|
||||||
db.close()
|
|
||||||
return "操作成功"
|
|
||||||
|
|
||||||
#删除用户信息
|
|
||||||
def delete(id):
|
|
||||||
db=sqlite3.connect(DATABASE)
|
|
||||||
cur=db.cursor()
|
|
||||||
#检查用户是否存在
|
|
||||||
cur.execute("SELECT * FROM adminx WHERE admin=?",(id,))
|
|
||||||
data=cur.fetchall()
|
|
||||||
if len(data)==0:
|
|
||||||
return "未找到"+id
|
|
||||||
#应用更新
|
|
||||||
cur.execute("DELETE FROM adminx WHERE admin=?",(id,))
|
|
||||||
db.commit()
|
|
||||||
cur.close()
|
|
||||||
db.close()
|
|
||||||
return "成功删除"+id
|
|
||||||
|
|
||||||
#检索用户信息与配置
|
|
||||||
def search(id,book):
|
|
||||||
db=sqlite3.connect(DATABASE)
|
|
||||||
cur=db.cursor()
|
|
||||||
#处理启动时间查询
|
|
||||||
if id=="time":
|
|
||||||
cur.execute("SELECT * FROM timeset WHERE True")
|
|
||||||
timex=cur.fetchall()
|
|
||||||
timex=[list(row) for row in timex]
|
|
||||||
cur.close()
|
|
||||||
db.close()
|
|
||||||
if len(timex)==0:
|
|
||||||
return "启动时间未设置"
|
|
||||||
else:
|
|
||||||
for i in range(len(timex)):
|
|
||||||
print(timex[i][0])
|
|
||||||
return ""
|
|
||||||
#处理MAA路径查询
|
|
||||||
if id=="maa":
|
|
||||||
cur.execute("SELECT * FROM pathset WHERE True")
|
|
||||||
pathx=cur.fetchall()
|
|
||||||
if len(pathx)>0:
|
|
||||||
cur.close()
|
|
||||||
db.close()
|
|
||||||
return pathx[0][0]
|
|
||||||
else:
|
|
||||||
cur.close()
|
|
||||||
db.close()
|
|
||||||
return "MAA路径未设置"
|
|
||||||
#处理用户查询与全部信息查询
|
|
||||||
if id=="all":
|
|
||||||
cur.execute("SELECT * FROM adminx WHERE True")
|
|
||||||
else:
|
|
||||||
cur.execute("SELECT * FROM adminx WHERE admin=?",(id,))
|
|
||||||
data=cur.fetchall()
|
|
||||||
#处理全部信息查询时的MAA路径与启动时间查询
|
|
||||||
if id=="all":
|
|
||||||
cur.execute("SELECT * FROM pathset WHERE True")
|
|
||||||
pathx=cur.fetchall()
|
|
||||||
if len(pathx)>0:
|
|
||||||
print("\nMAA路径:"+pathx[0][0])
|
|
||||||
else:
|
|
||||||
print("\nMAA路径未设置")
|
|
||||||
cur.execute("SELECT * FROM timeset WHERE True")
|
|
||||||
timex=cur.fetchall()
|
|
||||||
timex=[list(row) for row in timex]
|
|
||||||
if len(timex)==0:
|
|
||||||
print("\n启动时间未设置")
|
|
||||||
else:
|
|
||||||
print("启动时间:",end='')
|
|
||||||
for i in range(len(timex)):
|
|
||||||
print(timex[i][0],end=' ')
|
|
||||||
print('')
|
|
||||||
cur.close()
|
|
||||||
db.close()
|
|
||||||
data=[list(row) for row in data]
|
|
||||||
if len(data)>0:
|
|
||||||
#转译执行情况、用户状态,对全部信息查询隐去密码
|
|
||||||
curdate=datetime.date.today()
|
|
||||||
curdate=curdate.strftime('%Y-%m-%d')
|
|
||||||
for i in range(len(data)):
|
|
||||||
if data[i][4]==curdate:
|
|
||||||
data[i][4]="今日已执行"
|
|
||||||
else:
|
|
||||||
data[i][4]="今日未执行"
|
|
||||||
if data[i][3]=='y':
|
|
||||||
data[i][3]="启用"
|
|
||||||
else:
|
|
||||||
data[i][3]="禁用"
|
|
||||||
if id=="all":
|
|
||||||
data[i][6]="******"
|
|
||||||
else:
|
|
||||||
#解密
|
|
||||||
global PASSWORD
|
|
||||||
if PASSWORD==0:
|
|
||||||
PASSWORD=input("请输入管理密钥:")
|
|
||||||
data[i][6]=decryptx(data[i][6],PASSWORD).decode("utf-8")
|
|
||||||
#制表输出
|
|
||||||
if book==1:
|
|
||||||
print('')
|
|
||||||
print(unit("用户名",15),unit("手机号码",12),unit("代理天数",8),unit("状态",4),unit("执行情况",10),unit("关卡",10),unit("密码",25))
|
|
||||||
for i in range(len(data)):
|
|
||||||
print(unit(data[i][0],15),unit(data[i][1],12),unit(data[i][2],8),unit(data[i][3],4),unit(data[i][4],10),unit(data[i][5],10),unit(data[i][6],25))
|
|
||||||
return ""
|
|
||||||
elif id=="all":
|
|
||||||
return "\n当前没有用户记录"
|
|
||||||
else:
|
|
||||||
return "未找到"+id
|
|
||||||
|
|
||||||
#续期
|
|
||||||
def renewal(readxx):
|
|
||||||
#提取用户名与续期时间
|
|
||||||
for i in range(len(readxx)):
|
|
||||||
if readxx[i]==' ':
|
|
||||||
id=readxx[:i]
|
|
||||||
dayp=int(readxx[i+1:])
|
|
||||||
break
|
|
||||||
#检查用户是否存在
|
|
||||||
db=sqlite3.connect(DATABASE)
|
|
||||||
cur=db.cursor()
|
|
||||||
cur.execute("SELECT * FROM adminx WHERE admin=?",(id,))
|
|
||||||
data=cur.fetchall()
|
|
||||||
if len(data)==0:
|
|
||||||
cur.close()
|
|
||||||
db.close()
|
|
||||||
return "未找到"+id
|
|
||||||
#应用更新
|
|
||||||
cur.execute("UPDATE adminx SET day=? WHERE admin=?",(data[0][2]+dayp,id))
|
|
||||||
db.commit()
|
|
||||||
cur.close()
|
|
||||||
db.close()
|
|
||||||
return '成功更新'+id+'的代理天数至'+str(data[0][2]+dayp)+'天'
|
|
||||||
|
|
||||||
#用户状态配置
|
|
||||||
def turn(id,t):
|
|
||||||
#检查用户是否存在
|
|
||||||
db=sqlite3.connect(DATABASE)
|
|
||||||
cur=db.cursor()
|
|
||||||
cur.execute("SELECT * FROM adminx WHERE admin=?",(id,))
|
|
||||||
data=cur.fetchall()
|
|
||||||
if len(data)==0:
|
|
||||||
cur.close()
|
|
||||||
db.close()
|
|
||||||
return "未找到"+id
|
|
||||||
#应用更新
|
|
||||||
cur.execute("UPDATE adminx SET status=? WHERE admin=?",(t,id))
|
|
||||||
db.commit()
|
|
||||||
cur.close()
|
|
||||||
db.close()
|
|
||||||
if t=='y':
|
|
||||||
return '已启用'+id
|
|
||||||
else:
|
|
||||||
return '已禁用'+id
|
|
||||||
|
|
||||||
#修改刷取关卡
|
|
||||||
def gameid(readxx):
|
|
||||||
#提取用户名与修改值
|
|
||||||
for i in range(len(readxx)):
|
|
||||||
if readxx[i]==' ':
|
|
||||||
id=readxx[:i]
|
|
||||||
gamep=readxx[i+1:]
|
|
||||||
break
|
|
||||||
#检查用户是否存在
|
|
||||||
db=sqlite3.connect(DATABASE)
|
|
||||||
cur=db.cursor()
|
|
||||||
cur.execute("SELECT * FROM adminx WHERE admin=?",(id,))
|
|
||||||
data=cur.fetchall()
|
|
||||||
if len(data)==0:
|
|
||||||
cur.close()
|
|
||||||
db.close()
|
|
||||||
return "未找到"+id
|
|
||||||
#导入与应用特殊关卡规则
|
|
||||||
games={}
|
|
||||||
with open('data/gameid.txt',encoding='utf-8') as f:
|
|
||||||
gameids=f.readlines()
|
|
||||||
for i in range(len(gameids)):
|
|
||||||
for j in range(len(gameids[i])):
|
|
||||||
if gameids[i][j]==':':
|
|
||||||
gamein=gameids[i][:j]
|
|
||||||
gameout=gameids[i][j+1:]
|
|
||||||
break
|
|
||||||
games[gamein]=gameout.strip()
|
|
||||||
if gamep in games:
|
|
||||||
gamep=games[gamep]
|
|
||||||
#应用更新
|
|
||||||
cur.execute("UPDATE adminx SET game=? WHERE admin=?",(gamep,id))
|
|
||||||
db.commit()
|
|
||||||
cur.close()
|
|
||||||
db.close()
|
|
||||||
return '成功更新'+id+'的关卡为'+gamep
|
|
||||||
|
|
||||||
#设置MAA路径
|
|
||||||
def setpath(pathx):
|
|
||||||
db=sqlite3.connect(DATABASE)
|
|
||||||
cur=db.cursor()
|
|
||||||
cur.execute("SELECT * FROM pathset WHERE True")
|
|
||||||
pathold=cur.fetchall()
|
|
||||||
if len(pathold)>0:
|
|
||||||
cur.execute("UPDATE pathset SET path=? WHERE True",(pathx,))
|
|
||||||
else:
|
|
||||||
cur.execute("INSERT INTO pathset VALUES(?)",(pathx,))
|
|
||||||
db.commit()
|
|
||||||
cur.close()
|
|
||||||
db.close()
|
|
||||||
return "MAA路径已设置为"+pathx
|
|
||||||
|
|
||||||
#设置启动时间
|
|
||||||
def settime(book,timex):
|
|
||||||
db=sqlite3.connect(DATABASE)
|
|
||||||
cur=db.cursor()
|
|
||||||
#检查待操作对象存在情况
|
|
||||||
cur.execute("SELECT * FROM timeset WHERE True")
|
|
||||||
timeold=cur.fetchall()
|
|
||||||
timeold=[list(row) for row in timeold]
|
|
||||||
timenew=[]
|
|
||||||
timenew.append(timex)
|
|
||||||
#添加时间设置
|
|
||||||
if book=='+':
|
|
||||||
if timenew in timeold:
|
|
||||||
cur.close()
|
|
||||||
db.close()
|
|
||||||
return "已存在"+timex
|
|
||||||
else:
|
|
||||||
cur.execute("INSERT INTO timeset VALUES(?)",(timex,))
|
|
||||||
db.commit()
|
|
||||||
cur.close()
|
|
||||||
db.close()
|
|
||||||
return "已添加"+timex
|
|
||||||
#删除时间设置
|
|
||||||
elif book=='-':
|
|
||||||
if timenew in timeold:
|
|
||||||
cur.execute("DELETE FROM timeset WHERE time=?",(timex,))
|
|
||||||
db.commit()
|
|
||||||
cur.close()
|
|
||||||
db.close()
|
|
||||||
return "已删除"+timex
|
|
||||||
else:
|
|
||||||
cur.close()
|
|
||||||
db.close()
|
|
||||||
return "未找到"+timex
|
|
||||||
|
|
||||||
#统一制表单元
|
|
||||||
def unit(x,m):
|
|
||||||
#字母与连接符占1位,中文占2位
|
|
||||||
x=str(x)
|
|
||||||
n=0
|
|
||||||
for i in x:
|
|
||||||
if 'a'<=i<='z' or 'A'<=i<='Z' or '0'<=i<='9' or i=='_' or i=='-':
|
|
||||||
n+=1
|
|
||||||
return ' '+x+' '*(m-2*len(x)+n)
|
|
||||||
|
|
||||||
#初期检查
|
|
||||||
DATABASE="data/data.db"
|
|
||||||
PASSWORD=0
|
|
||||||
if not os.path.exists(DATABASE):
|
|
||||||
db=sqlite3.connect(DATABASE)
|
|
||||||
cur=db.cursor()
|
|
||||||
db.execute("CREATE TABLE adminx(admin text,number text,day int,status text,last date,game text,password byte)")
|
|
||||||
db.execute("CREATE TABLE pathset(path text)")
|
|
||||||
db.execute("CREATE TABLE timeset(time text)")
|
|
||||||
readx=input("首次启动,请设置MAA路径:")
|
|
||||||
cur.execute("INSERT INTO pathset VALUES(?)",(readx,))
|
|
||||||
db.commit()
|
|
||||||
cur.close()
|
|
||||||
db.close()
|
|
||||||
PASSWORD=readpass("请设置管理密钥(密钥与数据库绑定且唯一不可变):")
|
|
||||||
getPASSWORD(PASSWORD)
|
|
||||||
|
|
||||||
#初始界面
|
|
||||||
print("Good evening!")
|
|
||||||
print(search("all",1))
|
|
||||||
|
|
||||||
#主程序
|
|
||||||
while True:
|
|
||||||
read=input()
|
|
||||||
if len(read)==0:
|
|
||||||
print("无法识别的输入")
|
|
||||||
elif read[0]=='+':
|
|
||||||
print(add())
|
|
||||||
elif read[0]=='-':
|
|
||||||
exit()
|
|
||||||
elif read[0]=='/':
|
|
||||||
print(setpath(read[1:]))
|
|
||||||
elif read[0]==':' and (read[1]=='+' or read[1]=='-'):
|
|
||||||
print(settime(read[1],read[2:]))
|
|
||||||
else:
|
|
||||||
if read[-1]=='?':
|
|
||||||
print(search(read[:-2],1))
|
|
||||||
elif read[-1]=='+':
|
|
||||||
print(renewal(read[:-2]))
|
|
||||||
elif read[-1]=='-':
|
|
||||||
print(delete(read[:-2]))
|
|
||||||
elif read[-1]=='~':
|
|
||||||
print(gameid(read[:-2]))
|
|
||||||
elif read[-1]=='y' or read[-1]=='n':
|
|
||||||
print(turn(read[:-2],read[-1]))
|
|
||||||
else:
|
|
||||||
print("无法识别的输入")
|
|
||||||
9
requirements.txt
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
plyer
|
||||||
|
PySide6
|
||||||
|
PySide6-Fluent-Widgets[full]
|
||||||
|
psutil
|
||||||
|
pywin32
|
||||||
|
pyautogui
|
||||||
|
pycryptodome
|
||||||
|
requests
|
||||||
|
nuitka
|
||||||
BIN
res/AUTO_MAA.ico
|
Before Width: | Height: | Size: 1.0 MiB |
BIN
res/AUTO_MAA.png
|
Before Width: | Height: | Size: 1.6 MiB |
|
Before Width: | Height: | Size: 59 KiB |
|
Before Width: | Height: | Size: 44 KiB |
|
Before Width: | Height: | Size: 60 KiB |
|
Before Width: | Height: | Size: 52 KiB |
|
Before Width: | Height: | Size: 35 KiB |
|
Before Width: | Height: | Size: 746 KiB |
|
Before Width: | Height: | Size: 43 KiB |
|
Before Width: | Height: | Size: 93 KiB |
|
Before Width: | Height: | Size: 97 KiB |
|
Before Width: | Height: | Size: 94 KiB |
|
Before Width: | Height: | Size: 90 KiB |
|
Before Width: | Height: | Size: 96 KiB |
|
Before Width: | Height: | Size: 51 KiB |
|
Before Width: | Height: | Size: 69 KiB |
|
Before Width: | Height: | Size: 73 KiB |
|
Before Width: | Height: | Size: 76 KiB |
|
Before Width: | Height: | Size: 85 KiB |
|
Before Width: | Height: | Size: 86 KiB |
|
Before Width: | Height: | Size: 92 KiB |
|
Before Width: | Height: | Size: 92 KiB |
14
res/version.json
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
{
|
||||||
|
"main_version": "4.2.0.0",
|
||||||
|
"updater_version": "1.1.0.0",
|
||||||
|
"announcement": "\n# 这是一个中转版本,此版本后更换程序架构方式。\n# 由于更新方法无法通用,您需要在完成本次更新后再次检查更新以获取最新版本。\n",
|
||||||
|
"proxy_list":[
|
||||||
|
"",
|
||||||
|
"https://gitproxy.click/",
|
||||||
|
"https://cdn.moran233.xyz/",
|
||||||
|
"https://gh.llkk.cc/",
|
||||||
|
"https://github.akams.cn/",
|
||||||
|
"https://www.ghproxy.cn/",
|
||||||
|
"https://ghp.ci/"
|
||||||
|
]
|
||||||
|
}
|
||||||
45
resources/docs/MAA_config_info.txt
Normal file
@@ -0,0 +1,45 @@
|
|||||||
|
#主界面
|
||||||
|
"MainFunction.PostActions": "12" #完成后
|
||||||
|
"TaskQueue.WakeUp.IsChecked": "True" #开始唤醒
|
||||||
|
"TaskQueue.Recruiting.IsChecked": "True" #自动公招
|
||||||
|
"TaskQueue.Base.IsChecked": "True" #基建换班
|
||||||
|
"TaskQueue.Combat.IsChecked": "True" #刷理智
|
||||||
|
"TaskQueue.Mission.IsChecked": "True" #领取奖励
|
||||||
|
"TaskQueue.Mall.IsChecked": "True" #获取信用及购物
|
||||||
|
"TaskQueue.AutoRoguelike.IsChecked": "False" #自动肉鸽
|
||||||
|
"TaskQueue.Reclamation.IsChecked": "False" #生息演算
|
||||||
|
"Start.RunDirectly": "True" #启动MAA后直接运行
|
||||||
|
"Start.OpenEmulatorAfterLaunch": "True" #启动MAA后自动开启模拟器
|
||||||
|
#刷理智
|
||||||
|
"MainFunction.Stage1": "" #主关卡
|
||||||
|
"MainFunction.Stage2": "" #备选关卡1
|
||||||
|
"MainFunction.Stage3": "" #备选关卡2
|
||||||
|
"Fight.RemainingSanityStage": "Annihilation" #剩余理智关卡
|
||||||
|
"MainFunction.Series.Quantity": "1" #连战次数
|
||||||
|
"Penguin.IsDrGrandet": "True" #博朗台模式
|
||||||
|
"GUI.CustomStageCode": "False" #手动输入关卡名
|
||||||
|
"GUI.UseAlternateStage": "False" #使用备选关卡
|
||||||
|
"Fight.UseRemainingSanityStage": "True" #使用剩余理智
|
||||||
|
"GUI.AllowUseStoneSave": "False" #允许吃源石保持状态
|
||||||
|
"Fight.UseExpiringMedicine": "False" #无限吃48小时内过期的理智药
|
||||||
|
"GUI.HideUnavailableStage": "False" #隐藏当日不开放关卡
|
||||||
|
"GUI.HideSeries": "False" #隐藏连战次数
|
||||||
|
"Infrast.CustomInfrastPlanShowInFightSettings": "False" #显示基建计划
|
||||||
|
"Penguin.EnablePenguin": "True" #上报企鹅物流
|
||||||
|
"Yituliu.EnableYituliu": "True" #上报一图流
|
||||||
|
#基建换班
|
||||||
|
"Infrast.CustomInfrastEnabled": "True" #启用自定义基建配置
|
||||||
|
"Infrast.CustomInfrastPlanIndex": "1" #自定义基建配置索引
|
||||||
|
"Infrast.DefaultInfrast": "user_defined" #内置配置
|
||||||
|
"Infrast.IsCustomInfrastFileReadOnly": "False" #自定义基建配置文件只读
|
||||||
|
"Infrast.CustomInfrastFile": "" #自定义基建配置文件地址
|
||||||
|
#设置
|
||||||
|
"Start.ClientType": "Bilibili"、 "Official" #服务器
|
||||||
|
G"Timer.Timer1": "False" #时间设置1
|
||||||
|
G"VersionUpdate.ScheduledUpdateCheck": "True" #定时检查更新
|
||||||
|
G"VersionUpdate.AutoDownloadUpdatePackage": "True" #自动下载更新包
|
||||||
|
G"VersionUpdate.AutoInstallUpdatePackage": "True" #自动安装更新包
|
||||||
|
G"Start.MinimizeDirectly": "True" #启动MAA后直接最小化
|
||||||
|
G"GUI.UseTray": "True" #显示托盘图标
|
||||||
|
G"GUI.MinimizeToTray": "False" #最小化时隐藏至托盘
|
||||||
|
"Start.EmulatorPath" #模拟器路径
|
||||||
1545
resources/gui/main.ui
Normal file
BIN
resources/icons/AUTO_MAA.ico
Normal file
|
After Width: | Height: | Size: 51 KiB |
BIN
resources/icons/AUTO_MAA_Updater.ico
Normal file
|
After Width: | Height: | Size: 38 KiB |
BIN
resources/images/AUTO_MAA.png
Normal file
|
After Width: | Height: | Size: 26 KiB |
BIN
resources/images/README/MAA配置.png
Normal file
|
After Width: | Height: | Size: 61 KiB |
BIN
resources/images/README/gameid.png
Normal file
|
After Width: | Height: | Size: 21 KiB |
BIN
resources/images/README/payid.png
Normal file
|
After Width: | Height: | Size: 309 KiB |
14
resources/version.json
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
{
|
||||||
|
"main_version": "4.2.1.0",
|
||||||
|
"updater_version": "1.1.0.0",
|
||||||
|
"announcement": "\n## 新增功能\n- 无\n## 修复BUG\n- 同步MAA`v5.11.1-beta.1`的字段修改\n## 程序优化\n- 无",
|
||||||
|
"proxy_list":[
|
||||||
|
"",
|
||||||
|
"https://gitproxy.click/",
|
||||||
|
"https://cdn.moran233.xyz/",
|
||||||
|
"https://gh.llkk.cc/",
|
||||||
|
"https://github.akams.cn/",
|
||||||
|
"https://www.ghproxy.cn/",
|
||||||
|
"https://ghp.ci/"
|
||||||
|
]
|
||||||
|
}
|
||||||
104
run.py
@@ -1,104 +0,0 @@
|
|||||||
import os
|
|
||||||
import subprocess
|
|
||||||
import sqlite3
|
|
||||||
import datetime
|
|
||||||
import time
|
|
||||||
import json
|
|
||||||
from termcolor import colored
|
|
||||||
|
|
||||||
#判断MAA程序运行状态
|
|
||||||
def ifoff():
|
|
||||||
while True:
|
|
||||||
time.sleep(10)
|
|
||||||
with open(logpath,'r',encoding='utf-8') as f:
|
|
||||||
logs=f.readlines()[-1:-10:-1]
|
|
||||||
log=''.join(logs)
|
|
||||||
print(colored('\n'.join(logs[::-1]),"green"))
|
|
||||||
if "任务已全部完成!" in log:
|
|
||||||
return True
|
|
||||||
elif ("请检查连接设置或尝试重启模拟器与 ADB 或重启电脑" in log) or ("已停止" in log):
|
|
||||||
return False
|
|
||||||
|
|
||||||
#执行MAA任务
|
|
||||||
def runmaa(tel,game,num=2):
|
|
||||||
#配置MAA运行参数
|
|
||||||
with open(setpath,"r",encoding="utf-8") as f:
|
|
||||||
data = json.load(f)
|
|
||||||
data["Configurations"]["Default"]["Start.AccountName"]=tel[:3]+"****"+tel[7:]
|
|
||||||
week=str(datetime.datetime.now().strftime('%A'))
|
|
||||||
if week=="Monday":
|
|
||||||
data["Configurations"]["Default"]["MainFunction.Stage1"]="Annihilation"
|
|
||||||
else:
|
|
||||||
data["Configurations"]["Default"]["MainFunction.Stage1"]=game
|
|
||||||
with open(setpath,"w",encoding="utf-8") as f:
|
|
||||||
json.dump(data,f)
|
|
||||||
#开始运行
|
|
||||||
for i in range(num):
|
|
||||||
maa=subprocess.Popen([maapath])
|
|
||||||
maapid=maa.pid
|
|
||||||
time.sleep(60)
|
|
||||||
if ifoff():
|
|
||||||
return True
|
|
||||||
else:
|
|
||||||
os.system('taskkill /F /T /PID '+str(maapid))
|
|
||||||
return False
|
|
||||||
|
|
||||||
#更新已完成用户的数据
|
|
||||||
def updata(id):
|
|
||||||
db=sqlite3.connect(DATABASE)
|
|
||||||
cur=db.cursor()
|
|
||||||
cur.execute("SELECT * FROM adminx WHERE admin=?",(id,))
|
|
||||||
info=cur.fetchall()
|
|
||||||
cur.execute("UPDATE adminx SET day=? WHERE admin=?",(info[0][2]-1,id))
|
|
||||||
db.commit()
|
|
||||||
cur.execute("UPDATE adminx SET last=? WHERE admin=?",(curdate,id))
|
|
||||||
db.commit()
|
|
||||||
cur.close()
|
|
||||||
db.close()
|
|
||||||
return 0
|
|
||||||
|
|
||||||
#获取PATH与用户数据
|
|
||||||
DATABASE="data/data.db"
|
|
||||||
db=sqlite3.connect(DATABASE)
|
|
||||||
cur=db.cursor()
|
|
||||||
cur.execute("SELECT * FROM pathset WHERE True")
|
|
||||||
path=cur.fetchall()
|
|
||||||
path=str(path[0][0])
|
|
||||||
setpath=path+"/config/gui.json"
|
|
||||||
logpath=path+"/debug/gui.log"
|
|
||||||
maapath=path+"/MAA.exe"
|
|
||||||
cur.execute("SELECT * FROM adminx WHERE True")
|
|
||||||
data=cur.fetchall()
|
|
||||||
data=[list(row) for row in data]
|
|
||||||
cur.close()
|
|
||||||
db.close()
|
|
||||||
#开始执行
|
|
||||||
curdate=datetime.date.today()
|
|
||||||
curdate=curdate.strftime('%Y-%m-%d')
|
|
||||||
idnew=[]
|
|
||||||
idold=[]
|
|
||||||
idfail=[]
|
|
||||||
for i in range(len(data)):
|
|
||||||
if data[i][3]=='y' and data[i][4]!=curdate and data[i][2]>0:
|
|
||||||
book=runmaa(data[i][1],data[i][5])
|
|
||||||
if book:
|
|
||||||
updata(data[i][0])
|
|
||||||
idnew.append(data[i][0])
|
|
||||||
print(colored("已完成"+data[i][0]+"今日的代理","yellow"))
|
|
||||||
else:
|
|
||||||
idfail.append(data[i][0])
|
|
||||||
print(colored("异常中止"+data[i][0]+"的代理","red"))
|
|
||||||
for i in range(len(data)):
|
|
||||||
if data[i][3]=='y' and data[i][4]==curdate and data[i][2]>0:
|
|
||||||
book=runmaa(data[i][1],data[i][5])
|
|
||||||
if book:
|
|
||||||
idold.append(data[i][0])
|
|
||||||
print(colored("已重复完成"+data[i][0]+"今日的代理","yellow"))
|
|
||||||
with open("log.txt","w", encoding="utf-8") as f:
|
|
||||||
print("任务结束,已完成数:"+str(len(idnew))+",未完成数:"+str(len(idfail))+",重复执行数:"+str(len(idold)),file=f)
|
|
||||||
if len(idfail)!=0:
|
|
||||||
print("代理未完成的用户:",file=f)
|
|
||||||
for i in range(len(idfail)):
|
|
||||||
print(idfail[i],file=f)
|
|
||||||
with open("OVER","w", encoding="utf-8") as f:
|
|
||||||
print("OVER",file=f)
|
|
||||||