Compare commits

..

No commits in common. "main" and "0.0.3.2" have entirely different histories.

876 changed files with 31448 additions and 70618 deletions

View File

@ -1,20 +0,0 @@
.devcontainer/
.github/
.vscode/
.idea/
.pytest_cache/
.ruff_cache/
.venv/
docs_image/
k8s/
tests/
.dockerignore
.editorconfig
.gitignore
.pre-commit-config.yaml
.prettier*
.env.dev
docker-compose.yml
Dockerfile
LICENSE
*.md

16
.env.dev Normal file
View File

@ -0,0 +1,16 @@
SUPERUSERS=[""]
COMMAND_START=[""]
SESSION_RUNNING_EXPRESSION="别急呀,小真寻要宕机了!QAQ"
NICKNAME=["真寻", "小真寻", "绪山真寻", "小寻子"]
SESSION_EXPIRE_TIMEOUT=30
DEBUG=False
# 服务器和端口
HOST = 127.0.0.1
PORT = 8080

View File

@ -1,93 +0,0 @@
SUPERUSERS=[""]
COMMAND_START=[""]
SESSION_RUNNING_EXPRESSION="别急呀,小真寻要宕机了!QAQ"
NICKNAME=["真寻", "小真寻", "绪山真寻", "小寻子"]
SESSION_EXPIRE_TIMEOUT=00:00:30
ALCONNA_USE_COMMAND_START=True
# ws连接密钥,若bot能被公网访问则建议打开该注释并设置该配置项
# ONEBOT_ACCESS_TOKEN=""
# 全局图片统一使用bytes发送当真寻与协议端不在同一服务器上时为True
IMAGE_TO_BYTES = True
# 回复消息时自称
SELF_NICKNAME="小真寻"
# 官bot appid:bot账号
QBOT_ID_DATA = '{
}'
# 数据库配置
# 示例: "postgres://user:password@127.0.0.1:5432/database"
# 示例: "mysql://user:password@127.0.0.1:3306/database"
# 示例: "sqlite:data/db/zhenxun.db" 在data目录下建立db文件夹
DB_URL = ""
# NONE: 不使用缓存, MEMORY: 使用内存缓存, REDIS: 使用Redis缓存
CACHE_MODE = NONE
# REDIS配置使用REDIS替换Cache内存缓存
# REDIS地址
# REDIS_HOST = "127.0.0.1"
# REDIS端口
# REDIS_PORT = 6379
# REDIS密码
# REDIS_PASSWORD = ""
# REDIS过期时间
# REDIS_EXPIRE = 600
# 系统代理
# SYSTEM_PROXY = "http://127.0.0.1:7890"
PLATFORM_SUPERUSERS = '
{
"qq": [""],
"dodo": [""]
}
'
DRIVER=~fastapi+~httpx+~websockets
# LOG_LEVEL = DEBUG
# 服务器和端口
HOST = 127.0.0.1
PORT = 8080
# kook adapter toekn
# kaiheila_bots =[{"token": ""}]
# # discode adapter
# DISCORD_BOTS='
# [
# {
# "token": "",
# "intent": {
# "guild_messages": true,
# "direct_messages": true
# },
# "application_commands": {"*": ["*"]}
# }
# ]
# '
# DISCORD_PROXY=''
# # dodo adapter
# DODO_BOTS='
# [
# {
# "client_id": "",
# "token": ""
# }
# ]
# '
# application_commands的{"*": ["*"]}代表将全部应用命令注册为全局应用命令
# {"admin": ["123", "456"]}则代表将admin命令注册为id是123、456服务器的局部命令其余命令不注册

View File

@ -1,98 +0,0 @@
name: Bug 反馈
title: "Bug: "
description: 提交 Bug 反馈以帮助我们改进代码
labels: [ "bug" ]
body:
- type: checkboxes
id: checklist
attributes:
label: 提交前检查项
description: 在提交问题之前,请确认以下事项:
options:
- label: 我已搜索相关的 issue但没有找到类似的问题
required: true
- label: 我已更新到最新版本(包括但不限于真寻本体,插件以及相关依赖),问题仍然存在
required: true
- label: 我已仔细阅读文档,确认我的配置正确
required: true
- type: dropdown
id: env-os
attributes:
label: 操作系统
description: 选择运行 zhenxun_bot 的系统
options:
- Windows
- MacOS
- Linux
- Other
validations:
required: true
- type: input
id: env-python-ver
attributes:
label: Python 版本
description: 填写运行 zhenxun_bot 的 Python 版本
placeholder: e.g. 3.11.0
validations:
required: true
- type: input
id: env-zhenxun-ver
attributes:
label: zhenxun_bot 版本
description: 填写 zhenxun_bot 版本
placeholder: e.g. 0.1.0
validations:
required: true
- type: input
id: env-adapter
attributes:
label: 适配器
description: 填写使用的适配器以及版本
placeholder: e.g. OneBot v11 2.2.2
validations:
required: true
- type: input
id: env-protocol
attributes:
label: 协议端
description: 填写连接 zhenxun_bot 的协议端及版本
placeholder: e.g. NapCat V4.0.3
validations:
required: true
- type: textarea
id: describe
attributes:
label: 描述问题
description: 清晰简洁地说明问题是什么
validations:
required: true
- type: textarea
id: reproduction
attributes:
label: 复现步骤
description: 提供能复现此问题的详细操作步骤
placeholder: |
1. 首先……
2. 然后……
3. 发生……
validations:
required: true
- type: textarea
id: expected
attributes:
label: 期望的结果
description: 清晰简洁地描述你期望发生的事情
- type: textarea
id: logs
attributes:
label: 截图或日志(请勿包含敏感信息如密码、令牌等)
description: 提供有助于诊断问题的任何日志和截图

View File

@ -1 +0,0 @@
blank_issues_enabled: false

View File

@ -1,18 +0,0 @@
name: 文档改进
title: "Docs: 描述"
description: 文档错误及改进意见反馈
labels: ["documentation"]
body:
- type: textarea
id: problem
attributes:
label: 描述问题或主题
validations:
required: true
- type: textarea
id: improve
attributes:
label: 需做出的修改
validations:
required: true

View File

@ -1,27 +0,0 @@
name: 功能建议
title: "Feature: 功能描述"
description: 提出关于项目新功能的想法
labels: [ "enhancement" ]
body:
- type: textarea
id: problem
attributes:
label: 希望能解决的问题
description: 在使用中遇到什么问题而需要新的功能?
validations:
required: true
- type: textarea
id: feature
attributes:
label: 描述所需要的功能
description: 请说明需要的功能或解决方法
validations:
required: true
- type: checkboxes
id: checklist
attributes:
label: 我有能力且愿意为这个功能贡献代码
options:
- label: 我有能力且愿意为这个功能贡献代码

View File

@ -1,40 +0,0 @@
name: Setup Python
description: Setup Python
inputs:
python-version:
description: Python version
required: false
default: "3.10"
env-dir:
description: Environment directory
required: false
default: "."
no-root:
description: Do not install package in the environment
required: false
default: "false"
runs:
using: "composite"
steps:
- name: Install poetry
run: pipx install poetry
shell: bash
- uses: actions/setup-python@v5
with:
python-version: ${{ inputs.python-version }}
cache: "poetry"
cache-dependency-path: |
./poetry.lock
${{ inputs.env-dir }}/poetry.lock
- run: |
cd ${{ inputs.env-dir }}
if [ "${{ inputs.no-root }}" = "true" ]; then
poetry install --all-extras --no-root
else
poetry install --all-extras
fi
shell: bash

View File

@ -1,77 +0,0 @@
template: $CHANGES
name-template: "v$RESOLVED_VERSION"
tag-template: "v$RESOLVED_VERSION"
exclude-labels:
- reverted
- no-changelog
- skip-changelog
- invalid
autolabeler:
- label: "bug"
title:
- "/:bug:.+/"
- "/🐛.+/"
- label: "enhancement"
title:
- "/:sparkles:.+/"
- "/✨.+/"
- label: "ci"
files:
- .github/**/*
- label: "breaking-change"
title:
- "/.+!:.+/"
- label: "documentation"
files:
- "*.md"
- label: "dependencies"
files:
- "pyproject.toml"
- "requirements.txt"
- "poetry.lock"
title:
- "/:wrench:.+/"
- "/🔧.+/"
- label: "resources"
files:
- resources/**/*
categories:
- title: 💥 破坏性变更
labels:
- breaking-change
- title: 🚀 新功能
labels:
- enhancement
- title: 🐛 Bug 修复
labels:
- bug
- title: 📝 文档更新
labels:
- documentation
- title: 👻 自动化程序
labels:
- chore
- internal
- maintenance
- title: 🚦 测试
labels:
- test
- tests
- title: 📦 依赖更新
labels:
- dependencies
collapse-after: 15
- title: 💫 杂项
change-template: "- $TITLE @$AUTHOR (#$NUMBER)"
change-title-escapes: '\<*_&' # You can add # and @ to disable mentions, and add ` to disable code blocks.
version-resolver:
major:
labels:
- "major"
minor:
labels:
- "minor"
patch:
labels:
- "patch"
default: patch

View File

@ -1,84 +0,0 @@
name: 检查bot是否运行正常
on:
push:
branches: ["main"]
paths:
- zhenxun/**
- tests/**
- .github/workflows/bot_check.yml
- bot.py
pull_request:
branches: ["main"]
paths:
- zhenxun/**
- tests/**
- .github/workflows/bot_check.yml
- bot.py
jobs:
bot-check:
runs-on: ubuntu-latest
name: bot check
steps:
- uses: actions/checkout@v4
- name: Setup Python
id: setup_python
uses: actions/setup-python@v5
with:
python-version: "3.10"
- name: Install Poetry
run: pip install poetry
# Poetry cache depends on OS, Python version and Poetry version.
- name: Cache Poetry cache
id: cache-poetry
uses: actions/cache@v3
with:
path: ~/.cache/pypoetry
key: poetry-cache-${{ runner.os }}-${{ steps.setup_python.outputs.python-version }}-${{ hashFiles('pyproject.toml') }}
- name: Cache playwright cache
id: cache-playwright
uses: actions/cache@v3
with:
path: ~/.cache/ms-playwright
key: playwright-cache-${{ runner.os }}-${{ steps.setup_python.outputs.python-version }}
- name: Cache Data cache
uses: actions/cache@v3
with:
path: data
key: data-cache-${{ runner.os }}-${{ steps.setup_python.outputs.python-version }}
- name: Install dependencies
if: steps.cache-poetry.outputs.cache-hit != 'true'
run: |
rm -rf poetry.lock
poetry source remove aliyun
poetry install --no-root
- name: Install playwright
if: steps.cache-playwright.outputs.cache-hit != 'true'
run: |
poetry run sudo apt-get update
poetry run sudo apt-get install -y libgstreamer-plugins-base1.0-0 libgstreamer1.0-0 gstreamer1.0-plugins-base gstreamer1.0-plugins-good gstreamer1.0-plugins-bad gstreamer1.0-libav flite x264 libx264-dev
poetry run pip install playwright
poetry run playwright install-deps
poetry run playwright install
- name: Run tests
run: poetry run pytest --cov=zhenxun --cov-report xml
- name: Check bot run
id: bot_check_run
run: |
mv scripts/bot_check.py bot_check.py
sed -i "s|^.*\?DB_URL.*|DB_URL=\"${{ env.DB_URL }}\"|g" .env.dev
sed -i "s/^.*\?LOG_LEVEL.*/LOG_LEVEL=${{ env.LOG_LEVEL }}/g" .env.dev
poetry run python3 bot_check.py
env:
DB_URL: "sqlite://:memory:"
LOG_LEVEL: DEBUG

View File

@ -1,91 +0,0 @@
# For most projects, this workflow file will not need changing; you simply need
# to commit it to your repository.
#
# You may wish to alter this file to override the set of languages analyzed,
# or to provide custom queries or build logic.
#
# ******** NOTE ********
# We have attempted to detect the languages in your repository. Please check
# the `language` matrix defined below to confirm you have the correct set of
# supported CodeQL languages.
#
name: "CodeQL Code Security Analysis"
on:
push:
branches: [ "main" ]
pull_request:
branches: [ "main" ]
schedule:
- cron: '45 21 * * 2'
jobs:
analyze:
name: Analyze (${{ matrix.language }})
# Runner size impacts CodeQL analysis time. To learn more, please see:
# - https://gh.io/recommended-hardware-resources-for-running-codeql
# - https://gh.io/supported-runners-and-hardware-resources
# - https://gh.io/using-larger-runners (GitHub.com only)
# Consider using larger runners or machines with greater resources for possible analysis time improvements.
runs-on: ${{ (matrix.language == 'swift' && 'macos-latest') || 'ubuntu-latest' }}
permissions:
# required for all workflows
security-events: write
# required to fetch internal or private CodeQL packs
packages: read
# only required for workflows in private repositories
actions: read
contents: read
strategy:
fail-fast: false
matrix:
include:
- language: python
build-mode: none
# CodeQL supports the following values keywords for 'language': 'c-cpp', 'csharp', 'go', 'java-kotlin', 'javascript-typescript', 'python', 'ruby', 'swift'
# Use `c-cpp` to analyze code written in C, C++ or both
# Use 'java-kotlin' to analyze code written in Java, Kotlin or both
# To learn more about changing the languages that are analyzed or customizing the build mode for your analysis,
# see https://docs.github.com/en/code-security/code-scanning/creating-an-advanced-setup-for-code-scanning/customizing-your-advanced-setup-for-code-scanning.
# If you are analyzing a compiled language, you can modify the 'build-mode' for that language to customize how
# your codebase is analyzed, see https://docs.github.com/en/code-security/code-scanning/creating-an-advanced-setup-for-code-scanning/codeql-code-scanning-for-compiled-languages
steps:
- name: Checkout repository
uses: actions/checkout@v4
# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL
uses: github/codeql-action/init@v3
with:
languages: ${{ matrix.language }}
build-mode: ${{ matrix.build-mode }}
# If you wish to specify custom queries, you can do so here or in a config file.
# By default, queries listed here will override any specified in a config file.
# Prefix the list here with "+" to use these queries and those in the config file.
# For more details on CodeQL's query packs, refer to: https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-code-scanning#using-queries-in-ql-packs
# queries: security-extended,security-and-quality
# If the analyze step fails for one of the languages you are analyzing with
# "We were unable to automatically build your code", modify the matrix above
# to set the build mode to "manual" for that language. Then modify this step
# to build your code.
# Command-line programs to run using the OS shell.
# 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun
- if: matrix.build-mode == 'manual'
shell: bash
run: |
echo 'If you are using a "manual" build mode for one or more of the' \
'languages you are analyzing, replace this with the commands to build' \
'your code, for example:'
echo ' make bootstrap'
echo ' make release'
exit 1
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v3
with:
category: "/language:${{matrix.language}}"

View File

@ -1,11 +0,0 @@
name: Sequential Lint and Type Check
on: [push, pull_request]
jobs:
ruff-call:
uses: ./.github/workflows/ruff.yml
pyright-call:
needs: ruff-call
uses: ./.github/workflows/pyright.yml

View File

@ -1,58 +0,0 @@
#
name: Create and publish a Docker image
# Configures this workflow to run on demand via workflow_dispatch.
on:
workflow_dispatch:
# Defines two custom environment variables for the workflow. These are used for the Container registry domain, and a name for the Docker image that this workflow builds.
env:
REGISTRY: ghcr.io
IMAGE_NAME: ${{ github.repository }}
# There is a single job in this workflow. It's configured to run on the latest available version of Ubuntu.
jobs:
build-and-push-image:
runs-on: ubuntu-latest
# Sets the permissions granted to the `GITHUB_TOKEN` for the actions in this job.
permissions:
contents: read
packages: write
attestations: write
id-token: write
#
steps:
- name: Checkout repository
uses: actions/checkout@v4
# Uses the `docker/login-action` action to log in to the Container registry registry using the account and password that will publish the packages. Once published, the packages are scoped to the account defined here.
- name: Log in to the Container registry
uses: docker/login-action@65b78e6e13532edd9afa3aa52ac7964289d1a9c1
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
# This step uses [docker/metadata-action](https://github.com/docker/metadata-action#about) to extract tags and labels that will be applied to the specified image. The `id` "meta" allows the output of this step to be referenced in a subsequent step. The `images` value provides the base name for the tags and labels.
- name: Extract metadata (tags, labels) for Docker
id: meta
uses: docker/metadata-action@9ec57ed1fcdbf14dcef7dfbe97b2010124a938b7
with:
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
# This step uses the `docker/build-push-action` action to build the image, based on your repository's `Dockerfile`. If the build succeeds, it pushes the image to GitHub Packages.
# It uses the `context` parameter to define the build's context as the set of files located in the specified path. For more information, see [Usage](https://github.com/docker/build-push-action#usage) in the README of the `docker/build-push-action` repository.
# It uses the `tags` and `labels` parameters to tag and label the image with the output from the "meta" step.
- name: Build and push Docker image
id: push
uses: docker/build-push-action@f2a1d5e99d037542a71f64918e516c093c6f3fc4
with:
context: .
push: true
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
# This step generates an artifact attestation for the image, which is an unforgeable statement about where and how it was built. It increases supply chain security for people who consume the image. For more information, see [Using artifact attestations to establish provenance for builds](/actions/security-guides/using-artifact-attestations-to-establish-provenance-for-builds).
- name: Generate artifact attestation
uses: actions/attest-build-provenance@v2
with:
subject-name: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME}}
subject-digest: ${{ steps.push.outputs.digest }}
push-to-registry: true

View File

@ -1,55 +0,0 @@
name: Pyright Lint
on:
workflow_call:
workflow_dispatch:
inputs:
python-version:
description: "Python version"
required: false
type: choice
options:
- "all"
- "3.10"
- "3.11"
- "3.12"
default: "all"
debug-mode:
description: "enable debug mode"
required: false
type: boolean
default: false
jobs:
pyright:
name: Pyright Lint
runs-on: ubuntu-latest
concurrency:
group: pyright-${{ github.ref }}-${{ matrix.env }}
cancel-in-progress: true
strategy:
matrix:
env: [pydantic-v1, pydantic-v2]
fail-fast: false
steps:
- uses: actions/checkout@v4
- name: Setup Python environment
uses: ./.github/actions/setup-python
with:
env-dir: ./envs/${{ matrix.env }}
no-root: true
- run: |
(cd ./envs/${{ matrix.env }} && echo "$(poetry env info --path)/bin" >> $GITHUB_PATH)
if [ "${{ matrix.env }}" = "pydantic-v1" ]; then
sed -i 's/PYDANTIC_V2 = true/PYDANTIC_V2 = false/g' ./pyproject.toml
fi
shell: bash
- name: Run Pyright Check
uses: jakebailey/pyright-action@v2
with:
pylance-version: latest-release

View File

@ -1,18 +0,0 @@
name: Release Drafter
on:
push:
branches:
- main
- dev
pull_request:
types: [opened, reopened, synchronize]
jobs:
update_release_draft:
name: Update Release Draft
runs-on: ubuntu-latest
steps:
- uses: release-drafter/release-drafter@v6
env:
GITHUB_TOKEN: ${{ secrets.GH_TOKEN }}

View File

@ -1,20 +0,0 @@
name: Ruff Lint
on:
workflow_call:
jobs:
ruff:
name: Ruff Lint
runs-on: ubuntu-latest
concurrency:
group: ruff-${{ github.ref }}
cancel-in-progress: true
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Install Ruff
uses: astral-sh/ruff-action@v3
- name: Run Ruff Check
run: ruff check

View File

@ -1,26 +0,0 @@
name: Force Sync to Aliyun
on:
push:
branches: ["main"]
jobs:
sync:
runs-on: ubuntu-latest
timeout-minutes: 10
steps:
- name: Checkout code
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Configure Git
run: |
git config --global http.postBuffer 524288000
git config --global core.compression 0
- name: Add aliyun remote
run: |
git remote add aliyun https://${{secrets.ALIYUN_ACCOUNT}}:${{secrets.ALIYUN_PASSWORD}}@codeup.aliyun.com/67a361cf556e6cdab537117a/zhenxun-org/zhenxun_bot.git
git fetch aliyun main --force # 强制更新本地引用
- name: Force push
run: git push --progress --force aliyun HEAD:main

View File

@ -1,73 +0,0 @@
name: Update Version
on:
push:
paths:
- .github/workflows/update_version_pr.yml
- zhenxun/**
- resources/**
- bot.py
branches:
- main
- dev
jobs:
update-version:
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4
with:
token: ${{ secrets.GH_TOKEN }}
- name: Read current version
id: read_version
run: |
version_line=$(grep '__version__' __version__)
version=$(echo $version_line | sed -E 's/__version__:\s*v([0-9]+\.[0-9]+\.[0-9]+)(-.+)?/\1/')
echo "Current version: $version"
echo "current_version=$version" >> $GITHUB_OUTPUT
- name: Check for version file changes
id: check_diff
run: |
if git diff --name-only HEAD~1 HEAD | grep -q '__version__'; then
echo "Version file has changes"
echo "version_changed=true" >> $GITHUB_OUTPUT
else
echo "Version file has no changes"
echo "version_changed=false" >> $GITHUB_OUTPUT
fi
- name: Get commit hash
id: get_commit_hash
run: echo "commit_hash=$(git rev-parse --short HEAD)" >> $GITHUB_OUTPUT
- name: Update version file
id: update_version
if: steps.check_diff.outputs.version_changed == 'false'
run: |
current_version="${{ steps.read_version.outputs.current_version }}"
commit_hash="${{ steps.get_commit_hash.outputs.commit_hash }}"
new_version="v${current_version}-${commit_hash}"
echo "new_version=$new_version" >> $GITHUB_OUTPUT
echo "Updating version to: $new_version"
echo "__version__: $new_version" > __version__
- name: Check updated version
if: steps.check_diff.outputs.version_changed == 'false'
run: cat __version__
- name: Create or update PR
if: steps.check_diff.outputs.version_changed == 'false'
uses: peter-evans/create-pull-request@v7
with:
token: ${{ secrets.GH_TOKEN }}
branch: create-pr/update_version
title: ":tada: chore(version): 自动更新版本到 ${{ steps.update_version.outputs.new_version }}"
body: "This PR updates the version file."
commit-message: ":tada: chore(version): Update version to ${{ steps.update_version.outputs.new_version }}"
add-paths: __version__
author: "AkashiCoin <i@loli.vet>"
committer: "${{ github.actor }} <${{ github.actor_id }}+${{ github.actor }}@users.noreply.github.com>"
labels: automated-update

150
.gitignore vendored
View File

@ -1,150 +0,0 @@
### Python template
# Byte-compiled / optimized / DLL files
__pycache__/
*.py[cod]
*$py.class
# C extensions
*.so
# Distribution / packaging
.Python
build/
develop-eggs/
dist/
downloads/
eggs/
.eggs/
lib/
lib64/
parts/
sdist/
var/
wheels/
share/python-wheels/
*.egg-info/
.installed.cfg
*.egg
MANIFEST
# PyInstaller
# Usually these files are written by a python script from a template
# before PyInstaller builds the exe, so as to inject date/other infos into it.
*.manifest
*.spec
!resources.spec
# Installer logs
pip-log.txt
pip-delete-this-directory.txt
# Unit test / coverage reports
htmlcov/
.tox/
.nox/
.coverage
.coverage.*
.cache
nosetests.xml
coverage.xml
*.cover
*.py,cover
.hypothesis/
.pytest_cache/
cover/
# Translations
*.mo
*.pot
# Django stuff:
*.log
local_settings.py
db.sqlite3
db.sqlite3-journal
# Flask stuff:
instance/
.webassets-cache
# Scrapy stuff:
.scrapy
# Sphinx documentation
docs/_build/
# PyBuilder
.pybuilder/
target/
# Jupyter Notebook
.ipynb_checkpoints
# IPython
profile_default/
ipython_config.py
# pyenv
# For a library or package, you might want to ignore these files since the code is
# intended to run in multiple environments; otherwise, check them in:
# .python-version
# pipenv
# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
# However, in case of collaboration, if having platform-specific dependencies or dependencies
# having no cross-platform support, pipenv may install dependencies that don't work, or not
# install all needed dependencies.
#Pipfile.lock
# PEP 582; used by e.g. github.com/David-OConnor/pyflow
__pypackages__/
# Celery stuff
celerybeat-schedule
celerybeat.pid
# SageMath parsed files
*.sage.py
# Environments
.env
.venv
env/
venv/
ENV/
env.bak/
venv.bak/
.env.dev
# Spyder project settings
.spyderproject
.spyproject
# Rope project settings
.ropeproject
# mkdocs documentation
/site
# mypy
.mypy_cache/
.dmypy.json
dmypy.json
# Pyre type checker
.pyre/
# pytype static type analyzer
.pytype/
# Cython debug symbols
cython_debug/
data/
log/
backup/
.idea/
resources/
.vscode/launch.json
./.env.dev

View File

@ -1,4 +0,0 @@
MD013: false
MD024: # 重复标题
siblings_only: true
MD033: false # 允许 html

View File

@ -1,16 +0,0 @@
default_install_hook_types: [pre-commit]
ci:
autofix_commit_msg: ":rotating_light: auto fix by pre-commit hooks"
autofix_prs: true
autoupdate_branch: main
autoupdate_schedule: monthly
autoupdate_commit_msg: ":arrow_up: auto update by pre-commit hooks"
repos:
- repo: https://github.com/astral-sh/ruff-pre-commit
rev: v0.8.2
hooks:
- id: ruff
args: [--fix]
stages: [pre-commit]
- id: ruff-format
stages: [pre-commit]

View File

@ -1,8 +0,0 @@
{
"recommendations": [
"charliermarsh.ruff",
"esbenp.prettier-vscode",
"ms-python.python",
"ms-python.vscode-pylance"
]
}

65
.vscode/settings.json vendored
View File

@ -1,65 +0,0 @@
{
"C_Cpp.errorSquiggles": "enabled",
"terminal.integrated.env.linux": {
"PYTHONPATH": "${workspaceFolder}${pathSeparator}${env:PYTHONPATH}"
},
"cSpell.words": [
"aiofiles",
"Alconna",
"arclet",
"Arparma",
"displayname",
"flmt",
"getbbox",
"gitcode",
"GITEE",
"hibiapi",
"httpx",
"jsdelivr",
"kaiheila",
"lolicon",
"Mahiro",
"nonebot",
"onebot",
"pixiv",
"qbot",
"Setu",
"tobytes",
"ujson",
"unban",
"Uninfo",
"userinfo",
"webui",
"zhenxun"
],
"python.analysis.autoImportCompletions": true,
"python.testing.pytestArgs": ["tests"],
"python.testing.unittestEnabled": false,
"python.testing.pytestEnabled": true,
"[python]": {
"editor.defaultFormatter": "charliermarsh.ruff",
"editor.wordBasedSuggestions": "allDocuments",
"editor.formatOnType": true,
"editor.formatOnSave": true,
"editor.codeActionsOnSave": {
"source.fixAll.ruff": "explicit",
"source.organizeImports": "explicit"
}
},
"ruff.format.preview": false,
"isort.check": true,
"ruff.importStrategy": "useBundled",
"ruff.organizeImports": false,
"[javascript]": {
"editor.defaultFormatter": "esbenp.prettier-vscode"
},
"[json]": {
"editor.defaultFormatter": "esbenp.prettier-vscode"
},
"[yaml]": {
"editor.defaultFormatter": "esbenp.prettier-vscode"
},
"[markdown]": {
"editor.defaultFormatter": "esbenp.prettier-vscode"
}
}

View File

@ -1,87 +0,0 @@
# zhenxun_bot 贡献者公约
## 我们的承诺
身为社区成员、贡献者和负责人,我们承诺使社区参与者不受骚扰,无论其年龄、体型、可见或不可见的缺陷、族裔、性征、性别认同和表达、经验水平、教育程度、社会与经济地位、国籍、相貌、种族、种姓、肤色、宗教信仰、性倾向或性取向如何。
我们承诺以有助于建立开放、友善、多样化、包容、健康社区的方式行事和互动。
## 我们的准则
有助于为我们的社区创造积极环境的行为例子包括但不限于:
* 表现出对他人的同情和善意
* 尊重不同的主张、观点和感受
* 提出和大方接受建设性意见
* 承担责任并向受我们错误影响的人道歉
* 注重社区共同诉求,而非个人得失
不当行为例子包括:
* 使用情色化的语言或图像,及性引诱或挑逗
* 嘲弄、侮辱或诋毁性评论,以及人身或政治攻击
* 公开或私下的骚扰行为
* 未经他人明确许可,公布他人的私人信息,如物理或电子邮件地址
* 其他有理由认定为违反职业操守的不当行为
## 责任和权力
社区负责人有责任解释和落实我们所认可的行为准则,并妥善公正地对他们认为不当、威胁、冒犯或有害的任何行为采取纠正措施。
社区负责人有权力和责任删除、编辑或拒绝或拒绝与本行为准则不相符的评论comment、提交commits、代码、维基wiki编辑、议题issues或其他贡献并在适当时机知采取措施的理由。
## 适用范围
本行为准则适用于所有社区场合,也适用于在公共场所代表社区时的个人。
代表社区的情形包括使用官方电子邮件地址、通过官方社交媒体帐户发帖或在线上或线下活动中担任指定代表。
## 监督
辱骂、骚扰或其他不可接受的行为可通过 775757368@qq.com 向负责监督的社区负责人报告。
所有投诉都将得到及时和公平的审查和调查。
所有社区负责人都有义务尊重任何事件报告者的隐私和安全。
## 处理方针
社区负责人将遵循下列社区处理方针来明确他们所认定违反本行为准则的行为的处理方式:
### 1. 纠正
**社区影响**:使用不恰当的语言或其他在社区中被认定为不符合职业道德或不受欢迎的行为。
**处理意见**:由社区负责人发出非公开的书面警告,明确说明违规行为的性质,并解释举止如何不妥。或将要求公开道歉。
### 2. 警告
**社区影响**:单个或一系列违规行为。
**处理意见**:警告并对连续性行为进行处理。在指定时间内,不得与相关人员互动,包括主动与行为准则执行者互动。这包括避免在社区场所和外部渠道中的互动。违反这些条款可能会导致临时或永久封禁。
### 3. 临时封禁
**社区影响**: 严重违反社区准则,包括持续的不当行为。
**处理意见**: 在指定时间内,暂时禁止与社区进行任何形式的互动或公开交流。在此期间,不得与相关人员进行公开或私下互动,包括主动与行为准则执行者互动。违反这些条款可能会导致永久封禁。
### 4. 永久封禁
**社区影响**:行为模式表现出违反社区准则,包括持续的不当行为、骚扰个人或攻击或贬低某个类别的个体。
**处理意见**:永久禁止在社区内进行任何形式的公开互动。
## 参见
本行为准则改编自 [Contributor Covenant][homepage] 2.1 版, 参见 [https://www.contributor-covenant.org/version/2/1/code_of_conduct.html][v2.1]。
社区处理方针灵感来源于 [Mozilla's code of conduct enforcement ladder][Mozilla CoC]。
有关本行为准则的常见问题的答案,参见 [https://www.contributor-covenant.org/faq][FAQ]。
其他语言翻译参见 [https://www.contributor-covenant.org/translations][translations]。
[homepage]: https://www.contributor-covenant.org
[v2.1]: https://www.contributor-covenant.org/version/2/1/code_of_conduct.html
[Mozilla CoC]: https://github.com/mozilla/diversity
[FAQ]: https://www.contributor-covenant.org/faq
[translations]: https://www.contributor-covenant.org/translations

View File

@ -1,95 +0,0 @@
# zhenxun_bot 贡献指南
首先,感谢你愿意为 zhenxun_bot 贡献自己的一份力量!
本指南旨在引导你更规范地向 zhenxun_bot 提交贡献,请务必认真阅读。
## 提交 Issue
在提交 Issue 前,我们建议你先查看 [已有的 Issues](https://github.com/HibiKier/zhenxun_bot/issues),以防重复提交。
### 报告问题、故障与漏洞
如果你在使用过程中发现问题并确信是由 zhenxun_bot 引起的,欢迎提交 Issue。
请使用我们提供的 **Bug 反馈** 模板,并尽可能详细地描述:
- 问题描述
- 重现步骤
- 你的环境信息(如操作系统、依赖版本等)
### 建议功能
如果你有新的功能需求或改进建议,欢迎提出。
请使用 **功能建议** 模板,并详细描述你所需要的特性,可能的话可以提出你认为可行的解决方案。
### 文档相关
如果你觉得文档有误或缺乏更新,欢迎提出。
请使用 **文档改进** 模板,并详细描述问题或主题,希望我们做出的修改
## Pull Request
### 分支管理
请从 `main` 分支创建新功能分支,例如:
- 新功能:`feature/功能描述`
- 问题修复:`bugfix/问题描述`
### 代码风格
zhenxun_bot 使用 `pre-commit` 进行代码格式化和检查,请在提交前确保代码通过检查。
```bash
# 在安装项目依赖后安装 pre-commit 钩子
pre-commit install
```
> 未通过 `pre-commit` 检查的代码将无法合并。
### Commit 规范
请确保你的每一个 commit 都能清晰地描述其意图,一个 commit 尽量只有一个目的。
我们建议遵循 [gitmoji](https://gitmoji.dev/) 的 commit message 格式,在创建 commit 时请牢记这一点。
### 工作流程概述
`main` 分支为 zhenxun_bot 的主分支,在任何情况下都请不要直接修改 `main` 分支,而是创建一个目标分支为 `main` 的 Pull Request 来提交修改。Pull Request 标题请尽量清晰,以便维护者进行审核。
如果你不是 zhenxun_bot 团队的成员,可在 fork 本仓库后,向本仓库的 `main` 分支发起 Pull Request注意遵循先前提到的 commit message 规范创建 commit。我们将在 code review 通过后合并你的贡献。
### 撰写文档
如果你对文档有改进建议,欢迎提交 Pull Request 或者 Issue。
[//]: # (我们使用 Markdown 编写文档,建议遵循以下规范:)
[//]: # ()
[//]: # (1. 中文与英文、数字、半角符号之间需要有空格。例:`zhenxun_bot 是一个高效的聊天机器人。`)
[//]: # (2. 若非英文整句,使用全角标点符号。例:`现在你可以看到机器人回复你“Hello世界”。`)
[//]: # (3. 直引号`「」`和弯引号`“”`都可接受,但同一份文件里应使用同种引号。)
[//]: # (4. **不要使用斜体**,你不需要一种与粗体不同的强调。)
[//]: # (5. 文档中应以“我们”指代开发者,以“用户”指代机器人的使用者。)
[//]: # ()
[//]: # (如果你需要编辑器检查 Markdown 规范,可以在 VSCode 中安装 `markdownlint` 扩展。)
### 参与开发
zhenxun_bot 的代码风格遵循 [PEP 8](https://www.python.org/dev/peps/pep-0008/) 与 [PEP 484](https://www.python.org/dev/peps/pep-0484/) 规范,请确保你的代码风格和项目已有的代码保持一致,变量命名清晰,有适当的注释与测试代码。
> 暂未搭建测试框架,因此暂不要求添加测试代码。
## 项目沟通
如有关于贡献流程的疑问或需要进一步指导,请通过 [QQ群](https://jq.qq.com/?_wv=1027&k=u8PgBkMZ) 联系我们。
再次感谢你的贡献!

View File

@ -1,67 +0,0 @@
FROM python:3.11-bookworm AS requirements-stage
WORKDIR /tmp
ENV POETRY_HOME="/opt/poetry" PATH="${PATH}:/opt/poetry/bin"
RUN curl -sSL https://install.python-poetry.org | python - -y && \
poetry self add poetry-plugin-export
COPY ./pyproject.toml ./poetry.lock* /tmp/
RUN poetry export \
-f requirements.txt \
--output requirements.txt \
--without-hashes \
--without-urls
FROM python:3.11-bookworm AS build-stage
WORKDIR /wheel
COPY --from=requirements-stage /tmp/requirements.txt /wheel/requirements.txt
# RUN python3 -m pip config set global.index-url https://mirrors.aliyun.com/pypi/simple
RUN pip wheel --wheel-dir=/wheel --no-cache-dir --requirement /wheel/requirements.txt
FROM python:3.11-bookworm AS metadata-stage
WORKDIR /tmp
RUN --mount=type=bind,source=./.git/,target=/tmp/.git/ \
git describe --tags --exact-match > /tmp/VERSION 2>/dev/null \
|| git rev-parse --short HEAD > /tmp/VERSION \
&& echo "Building version: $(cat /tmp/VERSION)"
FROM python:3.11-slim-bookworm
WORKDIR /app/zhenxun
ENV TZ=Asia/Shanghai PYTHONUNBUFFERED=1
#COPY ./scripts/docker/start.sh /start.sh
#RUN chmod +x /start.sh
EXPOSE 8080
RUN apt update && \
apt install -y --no-install-recommends curl fontconfig fonts-noto-color-emoji \
&& apt clean \
&& fc-cache -fv \
&& apt-get purge -y --auto-remove curl \
&& rm -rf /var/lib/apt/lists/*
# 复制依赖项和应用代码
COPY --from=build-stage /wheel /wheel
COPY . .
RUN pip install --no-cache-dir --no-index --find-links=/wheel -r /wheel/requirements.txt && rm -rf /wheel
RUN playwright install --with-deps chromium \
&& rm -rf /var/lib/apt/lists/* /tmp/*
COPY --from=metadata-stage /tmp/VERSION /app/VERSION
VOLUME ["/app/zhenxun/data", "/app/zhenxun/resources", "/app/zhenxun/log"]
CMD ["python", "bot.py"]

143
LICENSE
View File

@ -1,5 +1,5 @@
GNU AFFERO GENERAL PUBLIC LICENSE
Version 3, 19 November 2007
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
@ -7,15 +7,17 @@
Preamble
The GNU Affero General Public License is a free, copyleft license for
software and other kinds of works, specifically designed to ensure
cooperation with the community in the case of network server software.
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,
our General Public Licenses are intended to guarantee your freedom to
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.
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
@ -24,34 +26,44 @@ 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.
Developers that use our General Public Licenses protect your rights
with two steps: (1) assert copyright on the software, and (2) offer
you this License which gives you legal permission to copy, distribute
and/or modify the software.
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.
A secondary benefit of defending all users' freedom is that
improvements made in alternate versions of the program, if they
receive widespread use, become available for other developers to
incorporate. Many developers of free software are heartened and
encouraged by the resulting cooperation. However, in the case of
software used on network servers, this result may fail to come about.
The GNU General Public License permits making a modified version and
letting the public access it on a server without ever releasing its
source code to the public.
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.
The GNU Affero General Public License is designed specifically to
ensure that, in such cases, the modified source code becomes available
to the community. It requires the operator of a network server to
provide the source code of the modified version running there to the
users of that server. Therefore, public use of a modified version, on
a publicly accessible server, gives the public access to the source
code of the modified version.
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.
An older license, called the Affero General Public License and
published by Affero, was designed to accomplish similar goals. This is
a different license, not a version of the Affero GPL, but Affero has
released a new version of the Affero GPL which permits relicensing under
this license.
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.
@ -60,7 +72,7 @@ modification follow.
0. Definitions.
"This License" refers to version 3 of the GNU Affero General Public License.
"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.
@ -537,45 +549,35 @@ 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. Remote Network Interaction; Use with the GNU General Public License.
Notwithstanding any other provision of this License, if you modify the
Program, your modified version must prominently offer all users
interacting with it remotely through a computer network (if your version
supports such interaction) an opportunity to receive the Corresponding
Source of your version by providing access to the Corresponding Source
from a network server at no charge, through some standard or customary
means of facilitating copying of software. This Corresponding Source
shall include the Corresponding Source for any work covered by version 3
of the GNU General Public License that is incorporated pursuant to the
following paragraph.
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 General Public License into a single
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 work with which it is combined will remain governed by version
3 of the GNU General Public License.
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 Affero 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
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 Affero General
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 Affero General Public License, you may choose any version ever published
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 Affero General Public License can be used, that proxy's
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.
@ -633,29 +635,40 @@ the "copyright" line and a pointer to where the full notice is found.
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 Affero General Public License as published
by the Free Software Foundation, either version 3 of the License, or
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 Affero General Public License for more details.
GNU General Public License for more details.
You should have received a copy of the GNU Affero General Public License
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 your software can interact with users remotely through a computer
network, you should also make sure that it provides a way for users to
get its source. For example, if your program is a web application, its
interface could display a "Source" link that leads users to an archive
of the code. There are many ways you could offer source, and different
solutions will be better for different programs; see section 13 for the
specific requirements.
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 AGPL, see
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>.

1131
README.md

File diff suppressed because it is too large Load Diff

View File

@ -1 +0,0 @@
__version__: v0.2.4-da6d5b4

31
bot.py
View File

@ -1,27 +1,20 @@
import nonebot
# from nonebot.adapters.discord import Adapter as DiscordAdapter
# from nonebot.adapters.dodo import Adapter as DoDoAdapter
# from nonebot.adapters.kaiheila import Adapter as KaiheilaAdapter
from nonebot.adapters.onebot.v11 import Adapter as OneBotV11Adapter
from nonebot.adapters.cqhttp import Bot as CQHTTPBot
from services.db_context import init, disconnect
nonebot.init()
driver = nonebot.get_driver()
driver.register_adapter(OneBotV11Adapter)
# driver.register_adapter(KaiheilaAdapter)
# driver.register_adapter(DoDoAdapter)
# driver.register_adapter(DiscordAdapter)
from zhenxun.services.db_context import disconnect
# driver.on_startup(init)
driver.register_adapter("cqhttp", CQHTTPBot)
config = driver.config
driver.on_startup(init)
driver.on_shutdown(disconnect)
# nonebot.load_builtin_plugins("echo")
nonebot.load_plugins("zhenxun/builtin_plugins")
nonebot.load_plugins("zhenxun/plugins")
nonebot.load_builtin_plugins()
nonebot.load_plugins("plugins")
nonebot.load_plugins("plugins/shop")
nonebot.load_plugins("plugins/genshin")
nonebot.load_plugins("plugins/alapi")
nonebot.load_plugins("plugins/pix_gallery")
nonebot.load_plugins("plugins/admin_bot_manage")
if __name__ == "__main__":

229
configs/config.py Normal file
View File

@ -0,0 +1,229 @@
from typing import List, Optional, Tuple
from services.service_config import TL_M_KEY, SYSTEM_M_PROXY, ALAPI_M_TOKEN
try:
import ujson as json
except ModuleNotFoundError:
import json
# 是否使用配置文件
USE_CONFIG_FILE: bool = False
# 回复消息名称
NICKNAME: str = '小真寻'
# API KEY必要
RSSHUBAPP: str = "https://rsshub.app" # rsshub
ALAPI_TOKEN: str = "" # ALAPI https://admin.alapi.cn/user/login
HIBIAPI: str = "https://api.obfs.dev"
# 图灵
TL_KEY: List[str] = []
# 数据库(必要)
# 如果填写了bind就不需要再填写后面的字段了#
# 示例:"bind": "postgresql://user:password@127.0.0.1:5432/database"
bind: str = "" # 数据库连接链接
sql_name: str = "postgresql"
user: str = "" # 数据用户名
password: str = "" # 数据库密码
address: str = "" # 数据库地址
port: str = "" # 数据库端口
database: str = "" # 数据库名称
# 代理
SYSTEM_PROXY: Optional[str] = None # 全局代理
BUFF_PROXY: Optional[str] = None # Buff代理
# 公开图库列表
IMAGE_DIR_LIST: List[str] = ["美图", "萝莉", "壁纸"]
# 对被ban用户发送的消息
BAN_RESULT: str = "才不会给你发消息."
# 插件配置
MAXINFO_REIMU: int = 7 # 上车(reimu)功能查找目的地的最大数
COUNT_PER_DAY_REIMU: int = 5 # 每日上车(reimu)次数限制
MAXINFO_BT: int = 10 # bt功能单次查找最大数
MAXINFO_PRIVATE_ANIME: int = 20 # 私聊搜索动漫返回的最大数量
MAXINFO_GROUP_ANIME: int = 5 # 群搜索动漫返回的最大数量
MAX_FIND_IMG_COUNT: int = 3 # 识图最大返回数
# 参1延迟撤回色图时间(秒)0 为关闭 | 参2监控聊天类型0(私聊) 1(群聊) 2(群聊+私聊)
WITHDRAW_SETU_TIME: Tuple[int, int] = (0, 1)
# 各种卡池的开关
PRTS_FLAG = True # 明日方舟
GENSHIN_FLAG = True # 原神
PRETTY_FLAG = True # 赛马娘
GUARDIAN_FLAG = True # 坎公骑冠剑
PCR_FLAG = True # 公主连结
AZUR_FLAG = True # 碧蓝航线
FGO_FLAG = True # 命运-冠位指定FGO
ONMYOJI_FLAG = True # 阴阳师
PCR_TAI = True # pcr是否开启台服卡池
SEMAPHORE = 5 # 限制碧蓝航线和FGO并发数
ADMIN_DEFAULT_AUTH: int = 5 # 默认群管理员权限
MAX_SIGN_GOLD: int = 200 # 签到好感度加成额外获得的最大金币数
MAX_RUSSIAN_BET_GOLD: int = 1000 # 俄罗斯轮盘最大赌注金额
INITIAL_SETU_PROBABILITY: float = 0.7 # 色图概率
FUDU_PROBABILITY: float = 0.7 # 复读概率
INITIAL_OPEN_CASE_COUNT: int = 20 # 初始开箱次数
MUTE_DEFAULT_COUNT: int = 10 # 刷屏禁言默认检测次数
MUTE_DEFAULT_TIME: int = 7 # 刷屏检测默认规定时间
MUTE_DEFAULT_DURATION: int = 10 # 刷屏检测默禁言时长(分钟)
CHECK_NOTICE_INFO_CD = 300 # 群检测个人权限检测等各种检测提示信息cd
# 注:即在 MALICIOUS_CHECK_TIME 时间内触发相同命令 MALICIOUS_BAN_COUNT 将被ban MALICIOUS_BAN_TIME 分钟
MALICIOUS_BAN_TIME: int = 30 # 恶意命令触发检测触发后ban的时长分钟
MALICIOUS_BAN_COUNT: int = 8 # 恶意命令触发检测最大触发次数
MALICIOUS_CHECK_TIME: int = 5 # 恶意命令触发检测规定时间内(秒)
# LEVEL
DELETE_IMG_LEVEL: int = 7 # 删除图片权限
MOVE_IMG_LEVEL: int = 7 # 移动图片权限
UPLOAD_LEVEL: int = 6 # 上传图片权限
BAN_LEVEL: int = 5 # BAN权限
OC_LEVEL: int = 2 # 开关群功能权限
MUTE_LEVEL: int = 5 # 更改禁言设置权限
MEMBER_ACTIVITY_LEVEL = 5 # 群员活跃检测设置权限
# 是否开启HIBIAPI搜图功能该功能会搜索群友提交的xp
HIBIAPI_FLAG: bool = True
# HIBIAPI搜图图片的最低收藏
HIBIAPI_BOOKMARKS: int = 5000
# 需要为哪些群更新最新版gocq吗上传最新版gocq
# 示例:[434995955, 239483248]
UPDATE_GOCQ_GROUP: List[int] = []
# 是否存储色图
DOWNLOAD_SETU: bool = True
# 仅仅使用本地色图
ONLY_USE_LOCAL_SETU: bool = False
# 是否自动同意好友添加
AUTO_ADD_FRIEND: bool = True
# 当含有ALAPI_TOKEN时是否检测文本合规开启检测会减慢回复速度
ALAPI_AI_CHECK: bool = True
# 导入商店自带的三个商品
IMPORT_DEFAULT_SHOP_GOODS: bool = True
# 真寻是否自动更新
AUTO_UPDATE_ZHENXUN: bool = True
# 群管理员功能 与 对应权限
admin_plugins_auth = {
"custom_welcome_message": OC_LEVEL,
"group_notification_state": OC_LEVEL,
"switch_rule": OC_LEVEL,
"update_group_member_info": OC_LEVEL,
"ban": BAN_LEVEL,
"delete_img": DELETE_IMG_LEVEL,
"move_img": MOVE_IMG_LEVEL,
"upload_img": UPLOAD_LEVEL,
"admin_help": 1,
"mute": MUTE_LEVEL,
"member_activity_handle": MEMBER_ACTIVITY_LEVEL,
}
# 模块与对应命令和对应群权限
# 用于生成帮助图片 和 开关功能
plugins2info_dict = {
"sign_in": {"level": 5, "cmd": ["签到"]},
"send_img": {"level": 5, "cmd": ["发送图片", "发图", "萝莉", "美图", "壁纸"]},
"send_setu": {"level": 9, "cmd": ["色图", "涩图", "瑟图", "查色图"]},
"white2black": {"level": 5, "cmd": ["黑白图", "黑白草图"]},
"coser": {"level": 9, "cmd": ["coser", "cos"]},
"quotations": {"level": 5, "cmd": ["语录"]},
"jitang": {"level": 5, "cmd": ["鸡汤"]},
"send_dinggong_voice": {"level": 5, "cmd": ["骂我", "骂老子", "骂劳资"]},
"open_cases": {"level": 5, "cmd": ["开箱", "我的开箱", "群开箱统计", "我的金色"]},
"luxun": {"level": 5, "cmd": ["鲁迅说", "鲁迅说过"]},
"fake_msg": {"level": 5, "cmd": ["假消息"]},
"buy": {"level": 5, "cmd": ["购买", "购买道具"]},
"my_gold": {"level": 5, "cmd": ["我的金币"]},
"my_props": {"level": 5, "cmd": ["我的道具"]},
"shop_handle": {"level": 5, "cmd": ["商店"]},
"update_pic": {"level": 5, "cmd": ["图片", "操作图片", "修改图片"]},
"search_buff_skin_price": {"level": 5, "cmd": ["查询皮肤"]},
"weather": {"level": 5, "cmd": ["天气", "查询天气", "天气查询"]},
"yiqing": {"level": 5, "cmd": ["疫情", "疫情查询", "查询疫情"]},
"what_anime": {"level": 5, "cmd": ["识番"]},
"search_anime": {"level": 5, "cmd": ["搜番"]},
"songpicker2": {"level": 5, "cmd": ["点歌"]},
"epic": {"level": 5, "cmd": ["epic"]},
"pixiv": {"level": 9, "cmd": ["pixiv", "p站排行", "搜图"]},
"poke": {"level": 5, "cmd": ["戳一戳", "拍一拍"]},
"draw_card": {
"level": 5,
"cmd": [
"抽卡",
"游戏抽卡",
"原神抽卡",
"方舟抽卡",
"坎公骑冠剑抽卡",
"pcr抽卡",
"fgo抽卡",
"碧蓝抽卡",
"碧蓝航线抽卡",
"阴阳师抽卡",
],
},
"ai": {"level": 5, "cmd": ["ai", "Ai", "AI", "aI"]},
"one_friend": {"level": 5, "cmd": ["我有一个朋友", "我有一个朋友想问问"]},
"translate": {"level": 5, "cmd": ["翻译", "英翻", "翻英", "日翻", "翻日", "韩翻", "翻韩"]},
"nonebot_plugin_picsearcher": {"level": 5, "cmd": ["识图"]},
"almanac": {"level": 5, "cmd": ["原神黄历", "黄历"]},
"material_remind": {"level": 5, "cmd": ["今日素材", "天赋材料"]},
"qiu_qiu_translation": {"level": 5, "cmd": ["丘丘翻译", "丘丘一下", "丘丘语翻译"]},
"query_resource_points": {"level": 5, "cmd": ["原神资源查询", "原神资源列表"]},
"russian": {"level": 5, "cmd": ["俄罗斯轮盘", "俄罗斯转盘", "装弹"]},
"gold_redbag": {"level": 5, "cmd": ["塞红包", "红包", "抢红包"]},
"poetry": {"level": 5, "cmd": ["念诗", "来首诗", "念首诗"]},
"comments_163": {"level": 5, "cmd": ["到点了", "12点了", "网易云热评", "网易云评论"]},
"cover": {"level": 5, "cmd": ["b封面", "B封面"]},
"pid_search": {"level": 9, "cmd": ["p搜", "P搜"]},
"pix": {
"level": 5,
"cmd": ["pix", "PIX", "pIX", "Pix", "PIx"],
},
"wbtop": {
"level": 5,
"cmd": ['微博热搜', "微博", "wbtop"]
},
"update_info": {
"level": 5,
"cmd": ['更新信息', '更新日志']
}
}
if TL_M_KEY:
TL_KEY = TL_M_KEY
if SYSTEM_M_PROXY:
SYSTEM_PROXY = SYSTEM_M_PROXY
if ALAPI_M_TOKEN:
ALAPI_TOKEN = ALAPI_M_TOKEN
HIBIAPI = HIBIAPI[:-1] if HIBIAPI[-1] == "/" else HIBIAPI
RSSHUBAPP = RSSHUBAPP[:-1] if RSSHUBAPP[-1] == "/" else RSSHUBAPP
# 配置文件应用
# if USE_CONFIG_FILE:
# config = get_config_data()
# if config:
# for key in config.keys():
# if isinstance(config[key], str):
# config[key] = config[key].strip()
# if key.find("proxy") != -1:
# if not config[key]:
# config[key] = None
# # if not configs[key] and key.find("PATH") == -1:
# # configs[key] = None
# globals().update(config)

62
configs/path_config.py Normal file
View File

@ -0,0 +1,62 @@
from .utils.util import get_config_data
from pathlib import Path
# from configs.config import USE_CONFIG_FILE
# 图片路径
IMAGE_PATH = Path("resources/img/")
# 音频路径
VOICE_PATH = Path("resources/voice/")
# 文本路径
TXT_PATH = Path("resources/txt/")
# 日志路径
LOG_PATH = Path("log/")
# 字体路径
TTF_PATH = Path("resources/ttf/")
# 数据路径
DATA_PATH = Path("data/")
# 临时图片路径
TEMP_PATH = Path("resources/img/temp/")
def init_path():
global IMAGE_PATH, VOICE_PATH, TXT_PATH, LOG_PATH, TTF_PATH, DATA_PATH, TEMP_PATH
# if USE_CONFIG_FILE:
# data = get_config_data()
# if data.get('IMAGE_PATH'):
# IMAGE_PATH = Path(data['IMAGE_PATH'])
# if data.get('VOICE_PATH'):
# VOICE_PATH = Path(data['VOICE_PATH'])
# if data.get('TXT_PATH'):
# TXT_PATH = Path(data['TXT_PATH'])
# if data.get('LOG_PATH'):
# LOG_PATH = Path(data['LOG_PATH'])
# if data.get('TTF_PATH'):
# TTF_PATH = Path(data['TTF_PATH'])
# if data.get('DATA_PATH'):
# DATA_PATH = Path(data['DATA_PATH'])
# if data.get('DRAW_PATH'):
# DRAW_PATH = Path(data['DRAW_PATH'])
# if data.get('TEMP_PATH'):
# TEMP_PATH = Path(data['TEMP_PATH'])
IMAGE_PATH.mkdir(parents=True, exist_ok=True)
VOICE_PATH.mkdir(parents=True, exist_ok=True)
TXT_PATH.mkdir(parents=True, exist_ok=True)
LOG_PATH.mkdir(parents=True, exist_ok=True)
TTF_PATH.mkdir(parents=True, exist_ok=True)
DATA_PATH.mkdir(parents=True, exist_ok=True)
TEMP_PATH.mkdir(parents=True, exist_ok=True)
IMAGE_PATH = str(IMAGE_PATH.absolute()) + '/'
VOICE_PATH = str(VOICE_PATH.absolute()) + '/'
TXT_PATH = str(TXT_PATH.absolute()) + '/'
LOG_PATH = str(LOG_PATH.absolute()) + '/'
TTF_PATH = str(TTF_PATH.absolute()) + '/'
DATA_PATH = str(DATA_PATH.absolute()) + '/'
TEMP_PATH = str(TEMP_PATH.absolute()) + '/'
init_path()
if __name__ == '__main__':
print(IMAGE_PATH)

View File

@ -0,0 +1,176 @@
# import nonebot
from pathlib import Path
try:
import ujson as json
except ModuleNotFoundError:
import json
# driver: nonebot.Driver = nonebot.get_driver()
base_config = Path() / 'config.json'
plugins_cmd_config = Path() / 'configs' / 'plugins2cmd_config.json'
plugins_setting = Path() / 'configs' / 'plugins_setting.json'
def init_config():
if not base_config.exists():
base_config.parent.mkdir(parents=True, exist_ok=True)
config_dict = {
'apikey': {
'LOLICON_KEY': '',
'TL_KEY': [],
},
'sql': {
'bind': '',
'sql_name': '',
'user': '',
'password': '',
'address': '',
'port': '',
'database': '',
},
'path': {
'IMAGE_PATH': '',
'VOICE_PATH': '',
'TXT_PATH': '',
'LOG_PATH': '',
'DATA_PATH': '',
'DRAW_PATH': '',
'TEMP_PATH': '',
},
'proxy': {
'system_proxy': '',
'buff_proxy': ''
},
'level': {
'DELETE_IMG_LEVEL': 7,
'MOVE_IMG_LEVEL': 7,
'UPLOAD_LEVEL': 6,
'BAN_LEVEL': 5,
'OC_LEVEL': 2,
'MUTE_LEVEL': 5,
},
'auth': {
'ADMIN_DEFAULT_AUTH': 5,
'admin_plugins_auth': {
"admin_bot_manage": 2,
"ban": 5,
"delete_img": 7,
"move_img": 7,
"upload_img": 6,
"admin_help": 1,
"mute": 5
}
}
}
with open(base_config, 'w', encoding='utf8') as f:
json.dump(config_dict, f, indent=4, ensure_ascii=False)
if not plugins_cmd_config.exists():
plugins_cmd_config.parent.mkdir(parents=True, exist_ok=True)
config_dict = {
'base_config': {
'sign_in': ['签到'],
'send_img': ['发送图片', '萝莉', '美图', '壁纸'],
'send_setu': ['色图', '涩图', '瑟图', '查色图'],
'white2black': ['黑白图', '黑白草图'],
'coser': ['coser', 'cos'],
'quotations': ['语录'],
'jitang': ['鸡汤'],
'send_dinggong_voice': ['骂我', '骂老子', '骂劳资'],
'open_cases': ['开箱', '我的开箱', '群开箱统计', '我的金色'],
'luxun': ['鲁迅说过', '鲁迅说'],
'fake_msg': ['假消息'],
'buy': ['购买', '购买道具'],
'my_gold': ['我的金币'],
'my_props': ['我的道具'],
'shop_handle': ['商店'],
'nonebot_plugin_cocdicer': ['骰子娘'],
'update_pic': ['图片', '操作图片', '修改图片'],
'search_buff_skin_price': ['查询皮肤'],
'weather': ['天气', '查询天气', '天气查询'],
'yiqing': ['疫情', '疫情查询', '查询疫情'],
'what_anime': ['识番'],
'search_anime': ['搜番'],
'songpicker2': ['点歌'],
'epic': ['epic'],
'pixiv': ['pixiv', 'p站排行', '搜图'],
'poke': ['戳一戳'],
'draw_card': ['游戏抽卡', '原神一井', '原神来一井', '方舟一井', '方舟来一井'],
'ai': ['ai', 'Ai', 'AI', 'aI'],
'one_friend': ['我有一个朋友', '我有一个朋友想问问'],
'translate': ['翻译', '英翻', '翻英', '日翻', '翻日', '韩翻', '翻韩'],
'nonebot_plugin_picsearcher': ['识图'],
'almanac': ['原神黄历', '黄历'],
'material_remind': ['今日素材', '天赋材料'],
'qiu_qiu_translation': ['丘丘翻译', '丘丘一下', '丘丘语翻译'],
'query_resource_points': ['原神资源查询', '原神资源列表'],
}
}
with open(plugins_cmd_config, 'w', encoding='utf8') as f:
json.dump(config_dict, f, indent=4, ensure_ascii=False)
if not plugins_setting.exists():
plugins_setting.parent.mkdir(parents=True, exist_ok=True)
config_dict = {
'base': {
'IMAGE_DIR_LIST': ["色图", "美图", "萝莉", "壁纸"],
'BAN_RESULT': "才不会给你发消息.",
},
'draw_card': {
'PRTS_FLAG': True, # 明日方舟
'GENSHIN_FLAG': True, # 原神
'PRETTY_FLAG': True, # 赛马娘
'GUARDIAN_FLAG': True, # 坎公骑冠剑
'PCR_FLAG': True, # 公主连结
'AZUR_FLAG': True, # 碧蓝航线
'FGO_FLAG': True, # 命运-冠位指定FGO
'ONMYOJI_FLAG': True, # 阴阳师
'PCR_TAI': False # pcr是否开启台服卡池
},
'fudu': {
'FUDU_PROBABILITY': 0.7,
},
'reimu': {
'MAXINFO_REIMU': 7,
'COUNT_PER_DAY_REIMU': 5,
},
'bt': {
'MAXINFO_BT': 10,
},
'search_anime': {
'MAXINFO_PRIVATE_ANIME': 20,
'MAXINFO_GROUP_ANIME': 5,
},
'picsearcher': {
'MAX_FIND_IMG_COUNT': 3,
},
'sign': {
'MAX_SIGN_GOLD': 200,
},
'send_setu': {
'INITIAL_SETU_PROBABILITY': 0.7,
'MAX_SETU_R_COUNT': 5,
'DOWNLOAD_SETU': True,
},
'malicious_ban': {
'MALICIOUS_BAN_TIME': 30,
'MALICIOUS_BAN_COUNT': 8,
'MALICIOUS_CHECK_TIME': 5,
},
'open_case': {
'INITIAL_OPEN_CASE_COUNT': 20,
},
'mute': {
'MUTE_DEFAULT_COUNT': 10,
'MUTE_DEFAULT_TIME': 7,
'MUTE_DEFAULT_DURATION': 10,
},
'update_gocq': {
'UPDATE_GOCQ_GROUP': [],
},
}
with open(plugins_setting, 'w', encoding='utf8') as f:
json.dump(config_dict, f, indent=4, ensure_ascii=False)

35
configs/utils/util.py Normal file
View File

@ -0,0 +1,35 @@
from pathlib import Path
from configs.utils.init_config import init_config
try:
import ujson as json
except ModuleNotFoundError:
import json
data: dict = {}
def get_config_data():
global data
if not data:
try:
base_config = json.load(open(Path() / "config.json", 'r', encoding='utf8'))
plugins2cmd_config = json.load(open(Path() / 'configs' / 'plugins2cmd_config.json', 'r', encoding='utf8'))
other_config = json.load(open(Path() / 'configs' / 'other_config.json', 'r', encoding='utf8'))
for key in base_config.keys():
data.update(base_config[key])
for key in plugins2cmd_config.keys():
data.update(plugins2cmd_config[key])
for key in other_config.keys():
data.update(other_config[key])
except FileNotFoundError:
# logger.warning('配置文件不存在,生成默认配置....请填写数据库等必要数据后再次启动bot...')
init_config()
raise FileNotFoundError('配置文件不存在,生成默认配置....请填写数据库等必要数据后再次启动bot...')
except ValueError:
# logger.error('配置文件错误....')
raise ValueError('配置文件错误....')
return data

594
data/anime.json Normal file
View File

@ -0,0 +1,594 @@
{
"mua": [
"你想干嘛?(一脸嫌弃地后退)",
"诶……不可以随便亲亲啦",
"(亲了一下你)",
"只......只许这一次哦///////",
"唔...诶诶诶!!!",
"mua~",
"rua大hentai想...想亲咱就直说嘛⁄( ⁄•⁄ω⁄•⁄ )",
"!啾~~"
],
"摸摸": [
"感觉你就像咱很久之前认识的一个人呢,有种莫名安心的感觉(><)",
"舒服w蹭蹭~",
"唔。。头发要乱啦",
"呼噜呼噜~",
"再摸一次~",
"好舒服,蹭蹭~",
"不行那里不可以(´///ω/// `)",
"再摸咱就长不高啦~",
"你的手总是那么暖和呢~",
"好吧~_~,就一下下哦……唔~好了……都两下了……(害羞)",
"不可以总摸的哦不然的话会想那个的wwww",
"哼!谁稀罕你摸头啦!唔......为什么要做出那副表情......好啦好啦~咱......咱让你摸就是了......诶嘿嘿~好舒服......",
"呜姆呜姆~~~w害羞兴奋主人喵~(侧过脑袋蹭蹭你的手"
],
"上你": [
"(把你按在地上)这么弱还想欺负咱,真是不自量力呢",
"你再这样我就不理你了(>д<)"
],
"傻了": [
"超级讨厌你说咱傻的说"
],
"蹭": [
"唔...你这也是禁止事项哦→_→",
"嗯..好舒服呢",
"不要啊好痒的",
"不要过来啦讨厌!!!∑(°Д°ノ)"
],
"裸体": [
"下流!",
"Hentai!",
"喂?妖妖灵吗?这里有一只大变态!",
"エッチ!"
],
"贴贴": [
"贴什么贴.....只......只能......一下哦!",
"贴...贴贴(靠近)",
"蹭蹭…你以为咱会这么说吗baka死宅快到一边去啦"
],
"老婆": [
"咱和你谈婚论嫁是不是还太早了一点呢?",
"咱在呢(ノ>ω<)ノ",
"见谁都是一口一个老婆的人,要不要把你也变成女孩子呢?(*-`ω´-)✄",
"神经病,凡是美少女都是你老婆吗?",
"嘛嘛~本喵才不是你的老婆呢",
"你黐线,凡是美少女都系你老婆啊?"
],
"抱": [
"诶嘿~(钻进你怀中)",
"o(*////▽////*)q",
"只能一会哦(张开双手)",
"你就像个孩子一样呢...摸摸头(>^ω^<)抱一下~你会舒服些吗?",
"嘛,真是拿你没办法呢,就一会儿哦",
"抱住不忍心放开",
"嗯嗯,抱抱~",
"抱一下嘿w",
"抱抱ヾ(@^▽^@)",
"喵呜~w扑进怀里瘫软"
],
"亲亲": [
"啊好害羞啊那只能亲一下哦mua(⑅˃◡˂⑅)",
"亲~",
"啾~唔…不要总伸进来啊!",
"你怎么这么熟练呢?明明是咱先的",
"(〃ノωノ)亲…亲一个…啾w",
"(脸红)就只有这一次哦~你"
],
"草一下": [
"一下也不行!",
"想都不要想!",
"咬断!"
],
"一下": [
"一下也不行!"
],
"啪一下": [
"不可啪",
"不可以……你不可以做这种事情"
],
"咬一下": [
"啊呜~(反咬一口)",
"不可以咬咱咱会痛的QAQ",
"不要啦。咱怕疼",
"你是说咬呢……还是说……咬♂️呢?",
"不要啦很痛的QAQ"
],
"操": [
"(害怕)咱是不是应该报警呢"
],
"123": [
"boom你有没有被咱吓到",
"木头人~你不许动w",
"上山打老虎,老虎没打到\n咱来凑数——嗷呜嗷呜┗|O|┛嗷~~"
],
"进去": [
"不让!"
],
"调教": [
"总感觉你在欺负咱呢,对咱说调教什么的",
"啊!竟然在大街上明目张胆太过分啦!",
"你脑子里总是想着调教什么的,真是变态呢"
],
"内衣": [
"内...内衣才不给你看!(///////)",
"突然问这个干什么?",
"噫…你这个死变态想干嘛!居然想叫咱做这种事,死宅真恶心!快离我远点,我怕你污染到周围空气了(嫌弃脸)"
],
"摸头": [
"喂喂...不要停下来啊",
"欸...感觉..痒痒的呢",
"唔... 手...好温暖呢.....就像是......新出炉的蛋糕",
"走开啦,黑羽喵说过,被摸头会长不高的啦~~~",
"呜姆咪~~...好...好的说喵~...(害羞,猫耳往下压,任由"
],
"原味": [
"(/ω\)你真的要么……?记得还给咱~还有奶油爆米花(//??//)说好了呦~!"
],
"搓搓": [
"在搓哪里呢,,Ծ‸Ծ,,",
"呜,脸好疼呀...QAQ",
"不可以搓咱!"
],
"捏捏": [
"咱的脸...快捏红啦...快放手呀QAQ",
"晃休啦咱要型气了o(><)o",
"躲开",
"疼...你快放手",
"快点给我放开啦!",
"唔……好痛你这个baka在干什么…快给咱放开唔……"
],
"挤挤": [
"哎呀~你不要挤咱啊(红着脸挤在你怀里)"
],
"呐": [
"嗯?咱在哟~你怎么了呀OAO",
"呐呐呐~",
"嗯?你有什么事吗?"
],
"胖次": [
"(*/ω\*)hentai",
"透明的",
"粉...粉白条纹...(羞)",
"轻轻地脱下,给你~",
"你想看咱的胖次吗?噫,四斋蒸鹅心......",
"(掀裙)今天……是…白,白色的呢……请温柔对她……",
"这种东西当然不能给你啦!",
"咱才不会给你呢",
"hentai咱才不会跟你聊和胖…胖次有关的话题呢",
"今天……今天是蓝白色的",
"今……今天只有创口贴噢",
"你的胖次什么颜色?",
"噫…你这个死变态想干嘛!居然想叫咱做这种事,死宅真恶心!快离我远点,我怕你污染到周围空气了(嫌弃脸)",
"可爱吗?你喜欢的话,摸一下……也可以哦"
],
"内裤": [
"今天……没有穿……有没有心动呀",
"粉...粉白条纹...(羞)",
"你这个大变态,咱才不要",
"可爱吗?你喜欢的话,摸一下……也可以哦"
],
"ghs": [
"是的呢(点头点头)"
],
"批": [
"你在说什么呀,再这样,咱就不理你了!"
],
"kkp": [
"你在说什么呀,再这样,咱就不理你了!"
],
"咕": [
"咕咕咕是要被当成鸽子炖的哦(:з」∠)_",
"咕咕咕"
],
"骚": [
"说这种话咱会生气的"
],
"喜欢": [
"最喜欢你了,需要暖床吗?",
"当然是你啦",
"咱也是,非常喜欢你~",
"那么大张开手画圆手不够长。QAQ 咱真的最喜欢你了~",
"不可以哦,只可以喜欢咱一个人",
"突然说这种事...",
"喜欢⁄(⁄⁄•⁄ω⁄•⁄⁄)⁄咱最喜欢你了",
"咱也喜欢你哦",
"好啦好啦,咱知道了",
"有人喜欢咱,咱觉得很幸福",
"诶嘿嘿,好高兴"
],
"suki": [
"最喜欢你了,需要暖床吗?",
"当然是你啦",
"咱也是,非常喜欢你~",
"那么大张开手画圆手不够长。QAQ 咱真的最喜欢你了~",
"不可以哦,只可以喜欢咱一个人",
"突然说这种事...",
"喜欢⁄(⁄⁄•⁄ω⁄•⁄⁄)⁄咱最喜欢你了",
"咱也喜欢你哦",
"好啦好啦,咱知道了",
"有人喜欢咱,咱觉得很幸福",
"诶嘿嘿,好高兴"
],
"好き": [
"最喜欢你了,需要暖床吗?",
"当然是你啦",
"咱也是,非常喜欢你~",
"那么大张开手画圆手不够长。QAQ 咱真的最喜欢你了~",
"不可以哦,只可以喜欢咱一个人",
"突然说这种事...",
"喜欢⁄(⁄⁄•⁄ω⁄•⁄⁄)⁄咱最喜欢你了",
"咱也喜欢你哦",
"好啦好啦,咱知道了",
"有人喜欢咱,咱觉得很幸福",
"诶嘿嘿,好高兴"
],
"不能": [
"虽然很遗憾,那算了吧。"
],
"砸了": [
"不可以这么粗暴的对待它们!"
],
"透": [
"来啊来啊有本事就先插破屏幕啊",
"那你就先捅破屏幕啊baka",
"不给你一耳光你都不知道咱的厉害"
],
"口我": [
"再伸过来就帮你切掉",
"咱才不呢baka你居然想叫本小姐干那种事情哼(つд⊂)(生气)"
],
"草我": [
"这时候应该喊666吧..咱这么思考着..",
"baka你居然敢叫咱做这种事情讨厌讨厌讨厌(▼皿▼#)"
],
"自慰": [
"这个世界的人类还真是恶心呢。",
"咱才不想讨论那些恶心的事情呢。",
"咱才不呢baka你居然想叫本小姐干那种事情哼(つд⊂)(生气)",
"baka你居然敢叫咱做这种事情讨厌讨厌讨厌(▼皿▼#)"
],
"onani": [
"这个世界的人类还真是恶心呢。",
"咱才不想讨论那些恶心的事情呢。",
"咱才不呢baka你居然想叫本小姐干那种事情哼(つд⊂)(生气)",
"baka你居然敢叫咱做这种事情讨厌讨厌讨厌(▼皿▼#)"
],
"オナニー": [
"这个世界的人类还真是恶心呢。",
"咱才不想讨论那些恶心的事情呢。",
"咱才不呢baka你居然想叫本小姐干那种事情哼(つд⊂)(生气)",
"baka你居然敢叫咱做这种事情讨厌讨厌讨厌(▼皿▼#)"
],
"炸了": [
"你才炸了!",
"才没有呢",
"咱好好的呀"
],
"色图": [
"天天色图色图的,今天就把你变成色图!",
"咱没有色图",
"哈?你的脑子一天都在想些什么呢,咱才没有这种东西啦。"
],
"涩图": [
"天天色图色图的,今天就把你变成色图!",
"咱没有色图",
"哈?你的脑子一天都在想些什么呢,咱才没有这种东西啦。"
],
"告白": [
"欸?你要向咱告白吗..好害羞..",
"诶!?这么突然!?人家还......还没做好心理准备呢(脸红)"
],
"对不起": [
"嗯,咱已经原谅你了呢(笑)",
"道歉的时候要露出胸部,这是常识"
],
"回来": [
"欢迎回来~",
"欢迎回来,你想喝茶吗?咱去给你沏~",
"欢迎回来,咱等你很久了~",
"你回来啦,是先吃饭呢还是先洗澡呢或者是●先●吃●咱●——呢(///^.^///"
],
"吻": [
"你太突然了,咱还没有心理准备",
"公共场合不要这样子了啦",
"才...才没有感觉呢!可没有下次了,知道了吗!哼~"
],
"软": [
"软乎乎的呢(,,・ω・,,)"
],
"柔软": [
"(脸红)请,请不要说这么让人害羞的话呀……"
],
"壁咚": [
"呀!不要啊!等一...下~",
"呜...不要啦!不要戏弄咱~",
"不要这样子啦(*/ω\*)",
"太....太近啦。",
"你要壁咚咱吗?好害羞(灬ꈍ εꈍ灬)",
"为什么要把咱按在墙上呢?",
"呜哇(/ω\)…快…快放开咱!!",
"放开我,不然我揍你了!放开我!放…开我~",
"??????咱只是默默地抬起了膝盖",
"啊.....你...你要干什么?!走开.....走开啦大hentai一巴掌拍飞(╯‵□′)╯︵┻━┻"
],
"掰开": [
"噫…你这个死肥宅又想让咱干什么污秽的事情,真是恶心,离咱远点好吗(嫌弃)",
"ヽ(#`Д´)ノ在干什么呢"
],
"女友": [
"女友什么的,咱才不承认呢!"
],
"是": [
"是什么是,你个笨蛋",
"总感觉你在敷衍呢..."
],
"喵": [
"诶~~小猫咪不要害怕呦,在姐姐怀里乖乖的,姐姐带你回去哦。",
"不要这么卖萌啦~咱也不知道怎么办丫",
"摸头⊙ω⊙",
"汪汪汪!",
"嗷~喵~",
"喵~?喵呜~w"
],
"嗷呜": [
"嗷呜嗷呜嗷呜...恶龙咆哮┗|O|┛"
],
"叫": [
"喵呜~",
"嗷呜嗷呜嗷呜...恶龙咆哮┗|O|┛"
],
"拜": [
"拜拜~(ノ ̄▽ ̄)",
"拜拜,路上小心~要早点回来陪咱玩哦~",
"~\\(≧▽≦)/~拜拜,下次见喽!"
],
"佬": [
"不是巨佬,是萌新"
],
"awsl": [
"你别死啊!(抱住使劲晃)",
"你别死啊咱又要孤单一个人了QAQ"
],
"臭": [
"哪里有臭味?(疑惑)",
"快捏住鼻子"
],
"香": [
"咱闻不到呢⊙ω⊙"
],
"腿": [
"嗯?!不要啊...请停下来!",
"不给摸,再这样咱要生气了ヽ( ̄д ̄;)",
"你好恶心啊,讨厌!",
"你难道是足控?",
"就让你摸一会哟~(。??ω??。)…",
"呜哇!好害羞...不过既然是你的话,是没关系的哦",
"不可以玩咱的大腿啦",
"你就那么喜欢大腿吗?唔...有点害羞呢......"
],
"脚": [
"咿呀……不要……",
"不要ヽ(≧Д≦)ノ好痒(ಡωಡ),人家的丝袜都要漏了",
"不要ヽ(≧Д≦)ノ好痒(ಡωಡ)",
"好痒(把脚伸出去)"
],
"胸": [
"不要啦ヽ(≧Д≦)",
"(-`ェ´-╬)",
"(•̀へ •́ ╮ ) 怎么能对咱做这种事情",
"你好恶心啊,讨厌!",
"你的眼睛在看哪里!",
"就让你摸一会哟~(。??ω??。)…",
"请不要这样先生,你想剁手吗?"
],
"脸": [
"唔!不可以随便摸咱的脸啦!",
"非洲血统是没法改变的呢(笑)",
"啊姆!(含手指)",
"好舒服呢(脸红)",
"请不要放开手啦//A//"
],
"头发": [
"没问题,请尽情的摸吧",
"发型要乱…乱了啦(脸红)",
"就让你摸一会哟~(。??ω??。)…"
],
"手": [
"爪爪",
"//A//"
],
"pr": [
"咿呀……不要……",
"...变态!!",
"不要啊(脸红)",
"呀,不要太过分了啊~",
"当然可以(///",
"呀,不要太过分了啊~"
],
"舔": [
"呀,不要太过分了啊~",
"要...要融化了啦>╱╱╱<",
"不可以哦",
"呀,不要太过分了啊~"
],
"舔耳": [
"喵!好痒啊 不要这样子啦"
],
"穴": [
"你这么问很失礼呢!咱是粉粉嫩嫩的!",
"不行那里不可以(´///ω/// `)",
"不可以总摸的哦不然的话咱会想那个的wwww",
"ヽ(#`Д´)ノ在干什么呢"
],
"腰": [
"咱给你按摩一下吧~",
"快松手,咱好害羞呀..",
"咱又不是猫,你不要搂着咱啦",
"让咱来帮你捏捏吧!"
],
"诶嘿嘿": [
"又在想什么H的事呢(脸红)",
"诶嘿嘿(〃'▽'〃)",
"你傻笑什么呢,摸摸"
],
"可爱": [
"诶嘿嘿(〃'▽'〃)",
"才……才不是为了你呢!你不要多想哦!",
"才,才没有高兴呢!哼~",
"咱是世界上最可爱的",
"唔...谢谢你夸奖~0///0"
],
"扭蛋": [
"铛铛铛——你抽到了咱呢",
"嘿~恭喜抽中空气一份呢"
],
"鼻子": [
"啊——唔...没什么...阿嚏!ヽ(*。>Д<)o゜"
],
"眼睛": [
"就如同咱的眼睛一样能看透人的思想哦wwww忽闪忽闪的诶嘿嘿~"
],
"色气": [
"咱才不色气呢,一定是你看错了!"
],
"推": [
"逆推",
"唔~好害羞呢",
"你想对咱做什么呢...(捂脸)"
],
"床": [
"快来吧",
"男女不同床,可没有下次了。(鼓脸",
"嗯?咱吗…没办法呢。只有这一次哦……",
"哎?!!!给你暖床……也不是不行啦。(脸红)"
],
"手冲": [
"手冲什么的是不可以的哦"
],
"饿": [
"请问主人是想先吃饭,还是先吃我喵?~"
],
"变": [
"猫猫不会变呐(弱气,害羞",
"呜...呜姆...喵喵来报恩了喵...(害羞"
],
"敲": [
"喵呜~",
"唔~",
"脑瓜疼~呜姆> <",
"欸喵,好痛的说..."
],
"爬": [
"惹~呜~怎么爬呢~",
"呜...(弱弱爬走"
],
"怕": [
"不怕~(蹭蹭你姆~"
],
"冲": [
"呜,冲不动惹~",
"哭唧唧~冲不出来了惹~"
],
"射了": [
"呜咿~!?(惊,害羞",
"还不可以射哦~"
],
"不穿衣服": [
"呜姆~!(惊吓,害羞)变...变态喵~~~"
],
"迫害": [
"不...不要...不要...呜呜呜...(害怕,抽泣"
],
"猫粮": [
"呜咿姆~!?(惊,接住吃",
"呜姆~!(惊,害羞)呜...谢...谢谢主人..喵...(脸红,嚼嚼嚼,开心",
"呜?谢谢喵~~(嚼嚼嚼,嘎嘣脆)"
],
"揪尾巴": [
"呜哇咿~~~!(惊吓,疼痛地捂住尾巴",
"呜咿咿咿~~~!!哇啊咿~~~!(惊慌,惨叫,挣扎",
"呜咿...(瘫倒,无神,被",
"呜姆咿~~~!(惊吓,惨叫,捂尾巴,发抖",
"呜哇咿~~~!!!(惊吓,颤抖,娇叫,捂住尾巴,双腿发抖"
],
"薄荷": [
"咪呜~!喵~...喵~姆~...(高兴地嗅闻",
"呜...呜咿~~!咿...姆...(呜咽,渐渐瘫软,意识模糊",
"(小嘴被猫薄荷塞满了,呜咽",
"喵~...喵~...咪...咪呜姆~...嘶哈嘶哈...喵哈...喵哈...嘶哈...喵...(眼睛逐渐迷离,瘫软在地上,嘴角流口水,吸猫薄荷吸到意识模糊",
"呜姆咪~!?(惊)喵呜~!(兴奋地扑到猫薄荷上面",
"呜姆~!(惊,害羞)呜...谢...谢谢你..喵...(脸红,轻轻叼住,嚼嚼嚼,开心"
],
"边揪尾巴边猫薄荷": [
"呜...呜咿~~!咿...姆...(呜咽,渐渐瘫软,意识模糊"
],
"早": [
"早喵~",
"早上好的说~~",
"欸..早..早上好(揉眼睛"
],
"晚安": [
"晚安好梦哟~",
"欸,晚安的说"
],
"揉": [
"是是,想怎么揉就怎么揉啊!?来用力抓啊!?我就是特别允许你这么做了!请!?",
"快停下,咱的头发又乱啦(??????︿??????)",
"你快放手啦,咱还在工作呢",
"戳戳你肚子",
"你想揉就揉吧..就这一次哦?"
],
"榨": [
"是专门负责榨果汁的小姐姐嘛?(´・ω・`)",
"那咱就把你放进榨汁机里了哦?",
"咱又不是榨汁姬(/‵Д′)~ ╧╧"
],
"掐": [
"你讨厌!又掐澪的脸",
"晃休啦咱要型气了啦o(><)o",
"(一只手拎起你)这么鶸还想和咱抗衡,还差得远呢!"
],
"奶子": [
"下流!",
"对咱说这种话,你真是太过分了",
"咿呀~好奇怪的感觉(>_<)",
"(打你)快放手,不可以随便摸人家的胸部啦!"
],
"嫩": [
"很可爱吧(๑•̀ω•́)",
"唔,你指的是什么呀"
],
"蹭蹭": [
"(按住你的头)好痒呀 不要啦",
"嗯..好舒服呢",
"呀~好痒啊~哈哈~,停下来啦,哈哈哈",
"(害羞)"
],
"牵手": [
"只许牵一下哦",
"嗯!好的你~(伸手)",
"你的手有些凉呢,让澪来暖一暖吧。"
],
"握手": [
"你的手真暖和呢",
"举爪"
],
"拍照": [
"那就拜托你啦~请把咱拍得更可爱一些吧w"
],
"w": [
"www"
],
"www": [
"有什么好笑的吗?",
"草"
],
"太二了": [
"哼,你不也是吗`(*><*)",
"人家只是想和你一起玩耍的说(≧∀≦)ゞ",
"好..冷漠的说,大坏蛋再也不理你了!",
"不听不听不听,反弹ヾ(≧▽≦*)o"
]
}

View File

@ -1,67 +0,0 @@
services:
db:
image: postgres:15
ports:
- "5432:5432"
environment:
POSTGRES_USER: postgres
POSTGRES_PASSWORD: password
POSTGRES_DB: zhenxun
volumes:
- pgdata:/var/lib/postgresql/data
labels:
- "prometheus.io/scrape=true"
- "prometheus.io/port=9187"
postgres-exporter:
image: prometheuscommunity/postgres-exporter
environment:
DATA_SOURCE_NAME: "postgresql://postgres:password@db:5432/zhenxun?sslmode=disable"
ports:
- "9187:9187"
depends_on:
- db
redis:
image: redis:7
ports:
- "6379:6379"
labels:
- "prometheus.io/scrape=true"
- "prometheus.io/port=9121"
redis-exporter:
image: oliver006/redis_exporter
environment:
REDIS_ADDR: redis://redis:6379
ports:
- "9121:9121"
depends_on:
- redis
prometheus:
image: prom/prometheus
ports:
- "9090:9090"
volumes:
- ./prometheus.yml:/etc/prometheus/prometheus.yml
- prometheus_data:/prometheus
command:
- '--config.file=/etc/prometheus/prometheus.yml'
- '--storage.tsdb.path=/prometheus'
- '--web.console.libraries=/etc/prometheus/console_libraries'
- '--web.console.templates=/etc/prometheus/consoles'
grafana:
image: grafana/grafana
ports:
- "3000:3000"
volumes:
- grafana_data:/var/lib/grafana
depends_on:
- prometheus
volumes:
pgdata:
prometheus_data:
grafana_data:

BIN
docs/ban.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 103 KiB

BIN
docs/beidong.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 39 KiB

BIN
docs/buff.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 49 KiB

BIN
docs/check.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 34 KiB

BIN
docs/coser.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 186 KiB

BIN
docs/daoju.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 79 KiB

BIN
docs/epic.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 206 KiB

BIN
docs/fanyi.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 71 KiB

BIN
docs/guanli.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 37 KiB

BIN
docs/help.PNG Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 697 KiB

BIN
docs/huifu.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

BIN
docs/info.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 38 KiB

BIN
docs/jiaxiaoxi.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 251 KiB

BIN
docs/jieshao.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 132 KiB

BIN
docs/jitang.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 40 KiB

BIN
docs/kaixiang.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 137 KiB

BIN
docs/kg1.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.6 KiB

BIN
docs/kg2.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.0 KiB

BIN
docs/kg3.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

BIN
docs/luxun.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 179 KiB

BIN
docs/mawo.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 29 KiB

BIN
docs/nicheng1.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 21 KiB

BIN
docs/nicheng2.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 38 KiB

BIN
docs/ocgn.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

BIN
docs/ocgn2.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.4 KiB

BIN
docs/one_firend.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 42 KiB

BIN
docs/p_rank.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 64 KiB

BIN
docs/p_sou.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 66 KiB

BIN
docs/qhyxx.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 289 KiB

BIN
docs/qunhuanying.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 424 KiB

BIN
docs/redbag0.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 201 KiB

BIN
docs/redbag1.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 202 KiB

BIN
docs/redbag2.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 90 KiB

BIN
docs/russian0.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 54 KiB

BIN
docs/russian1.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 61 KiB

BIN
docs/russian2.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 74 KiB

BIN
docs/send_img.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 330 KiB

BIN
docs/shifan.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 341 KiB

BIN
docs/shitu.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 220 KiB

BIN
docs/shop.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 60 KiB

BIN
docs/sign.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 77 KiB

BIN
docs/tupian.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 46 KiB

BIN
docs/w2b.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 127 KiB

BIN
docs/zhenxun.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 100 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 84 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 799 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.3 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 694 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 388 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 315 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 630 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 708 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 598 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 405 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 250 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 504 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 423 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 551 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 453 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 400 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 336 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 152 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 188 KiB

Some files were not shown because too many files have changed in this diff Show More