mirror of
https://github.com/nixietab/picodulce.git
synced 2025-04-09 18:08:57 +01:00
Compare commits
59 Commits
Author | SHA1 | Date | |
---|---|---|---|
![]() |
07571aaeb0 | ||
![]() |
63dc90b239 | ||
![]() |
fc4ac0ba56 | ||
![]() |
15c161faff | ||
![]() |
2db2f1b18b | ||
![]() |
a582b497f8 | ||
![]() |
93d607229e | ||
![]() |
9634a378ab | ||
![]() |
247f801d35 | ||
![]() |
645cfeb52b | ||
![]() |
6596ad44f8 | ||
![]() |
228565daf3 | ||
![]() |
b45951cab6 | ||
![]() |
76d88787ac | ||
![]() |
19332fd936 | ||
![]() |
cef44074c5 | ||
![]() |
2a4ba7cfcf | ||
![]() |
e6b4a7acf3 | ||
![]() |
97215e4c75 | ||
![]() |
6c93ab07c5 | ||
![]() |
14855f2f00 | ||
![]() |
897fa4c8b7 | ||
![]() |
7ca5855198 | ||
![]() |
5a6bdd3aad | ||
![]() |
b35063d0b2 | ||
![]() |
fe6d409fb5 | ||
![]() |
bce36c3728 | ||
![]() |
aa8a72c8cb | ||
![]() |
b3155b4844 | ||
![]() |
aaf141e338 | ||
![]() |
c125f440f8 | ||
![]() |
1543b36eb5 | ||
![]() |
eb6b27ed23 | ||
![]() |
0702f918dd | ||
![]() |
5792bcb6eb | ||
![]() |
b6241e7aad | ||
![]() |
0ac8a1bf51 | ||
![]() |
60e532b604 | ||
![]() |
52b07aab71 | ||
![]() |
bb48b3e293 | ||
![]() |
f86bb54abe | ||
![]() |
35e1cd7d17 | ||
![]() |
c0ce394fda | ||
![]() |
1f739f25e8 | ||
![]() |
2d362843c2 | ||
![]() |
ae14820c4d | ||
![]() |
50b3f09ed1 | ||
![]() |
b9bf71334b | ||
![]() |
40bf8ea23e | ||
![]() |
89cf8218f8 | ||
![]() |
520a1b500f | ||
![]() |
b6a3218bf6 | ||
![]() |
c1c98aafae | ||
![]() |
34c36c5b88 | ||
![]() |
fc058913cd | ||
![]() |
523431a557 | ||
![]() |
72f7cbec9d | ||
![]() |
fbdba505c9 | ||
![]() |
479bc4486a |
36
.github/workflows/Bleeding-Job.yaml
vendored
36
.github/workflows/Bleeding-Job.yaml
vendored
@ -1,36 +0,0 @@
|
||||
name: Bleeding Update version
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
|
||||
jobs:
|
||||
update-version:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: Check out the repository
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- name: Set up Python
|
||||
uses: actions/setup-python@v4
|
||||
with:
|
||||
python-version: '3.x'
|
||||
|
||||
- name: Update version.json
|
||||
run: |
|
||||
git fetch --prune --unshallow
|
||||
commit_count=$(git rev-list --count HEAD)
|
||||
version=$(jq -r '.version' version.json)
|
||||
jq --arg versionBleeding "$version-$commit_count" '. + {versionBleeding: $versionBleeding}' version.json > version.tmp && mv version.tmp version.json
|
||||
|
||||
- name: Commit and push changes
|
||||
run: |
|
||||
git config --global user.name 'github-actions[bot]'
|
||||
git config --global user.email 'github-actions[bot]@users.noreply.github.com'
|
||||
git add version.json
|
||||
git commit -m "Update version.json with commit count"
|
||||
git push
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
4
.github/workflows/Build.yml
vendored
4
.github/workflows/Build.yml
vendored
@ -9,8 +9,6 @@ jobs:
|
||||
version-release:
|
||||
runs-on: windows-latest # Use Windows 10 runner
|
||||
|
||||
if: github.actor != 'github-actions[bot]' # Only run if the actor is not the GitHub Actions bot
|
||||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v3
|
||||
@ -38,7 +36,7 @@ jobs:
|
||||
run: |
|
||||
dir actions-temp
|
||||
dir
|
||||
|
||||
|
||||
- name: Get version and name from version.json
|
||||
id: version_info
|
||||
run: |
|
||||
|
76
PKGBUILD
76
PKGBUILD
@ -1,76 +0,0 @@
|
||||
pkgname=picodulce
|
||||
pkgver=0.11.7
|
||||
pkgrel=1
|
||||
pkgdesc="Launcher for Minecraft based on the picomc library"
|
||||
arch=('x86_64')
|
||||
OPTIONS=(!strip !docs libtool emptydirs)
|
||||
url="https://github.com/nixietab/picodulce"
|
||||
license=('MIT') # Replace with your project's license
|
||||
depends=('python' 'python-virtualenv' 'xdg-utils')
|
||||
makedepends=('git')
|
||||
source=("git+https://github.com/nixietab/picodulce.git")
|
||||
sha256sums=('SKIP')
|
||||
|
||||
package() {
|
||||
cd "$srcdir/$pkgname"
|
||||
|
||||
# Create a directory for the application in the user's home directory
|
||||
install -dm755 "$pkgdir/usr/share/$pkgname"
|
||||
|
||||
# Copy all project files to the created directory
|
||||
cp -r . "$pkgdir/usr/share/$pkgname"
|
||||
|
||||
# Create a virtual environment
|
||||
python -m venv "$pkgdir/usr/share/$pkgname/venv"
|
||||
|
||||
# Activate the virtual environment and install dependencies
|
||||
source "$pkgdir/usr/share/$pkgname/venv/bin/activate"
|
||||
pip install -r requirements.txt
|
||||
|
||||
# Create a run.sh script
|
||||
install -Dm755 /dev/stdin "$pkgdir/usr/share/$pkgname/run.sh" <<EOF
|
||||
#!/bin/bash
|
||||
|
||||
if [ ! -d "venv" ]; then
|
||||
echo "venv folder does not exist. Creating virtual environment..."
|
||||
python3 -m venv venv
|
||||
|
||||
source venv/bin/activate
|
||||
|
||||
echo "Installing required packages..."
|
||||
pip install -r requirements.txt
|
||||
else
|
||||
source venv/bin/activate
|
||||
fi
|
||||
|
||||
python picodulce.py
|
||||
EOF
|
||||
|
||||
|
||||
# Make the run.sh script executable
|
||||
chmod +x "$pkgdir/usr/share/$pkgname/run.sh"
|
||||
|
||||
# Create a desktop entry for the application
|
||||
install -Dm644 /dev/stdin "$pkgdir/usr/share/applications/$pkgname.desktop" <<EOF
|
||||
[Desktop Entry]
|
||||
Name=Picodulce
|
||||
Exec=/usr/share/picodulce/run.sh
|
||||
Icon=/usr/share/picodulce/launcher_icon.ico
|
||||
Terminal=true
|
||||
Type=Application
|
||||
Comment=Picodulce Launcher
|
||||
Categories=Game;
|
||||
EOF
|
||||
|
||||
# Ensure the normal user has permission to write to the picodulce folder
|
||||
chown -R "$USER:$USER" "$pkgdir/usr/share/$pkgname"
|
||||
chmod -R u+w "$pkgdir/usr/share/$pkgname"
|
||||
|
||||
#Install into bin
|
||||
install -Dm755 /dev/stdin "$pkgdir/usr/bin/picodulce" <<EOF
|
||||
#!/bin/bash
|
||||
cd /usr/share/picodulce/
|
||||
exec ./run.sh
|
||||
EOF
|
||||
}
|
||||
# vim:set ts=2 sw=2 et:
|
18
README.md
18
README.md
@ -38,23 +38,9 @@
|
||||
- **Offline and Online Support**: Whether you're connected to Microsoft or not, Picodulce ensures you can still enjoy your game by supporting both offline and online modes.
|
||||
- **Integrated Mod Manager**: Includes the [Marroc Mod Manager](https://github.com/nixietab/marroc), enabling users to effortlessly manage and customize their game with mods and texturepacks.
|
||||
- **Custom Theme Support**: Create and apply personalized themes with ease. A dedicated repository and guide are [available to help you get started.](https://github.com/nixietab/picodulce-themes)
|
||||
|
||||
-- **Instance Support**: Allows users to create and manage multiple game instances, each with its own configuration, mods, and settings
|
||||
# Installation
|
||||
|
||||
## Windows
|
||||
For Windows systems using the [installer](https://github.com/nixietab/picodulce/releases/latest) is recommended
|
||||
|
||||
## Arch Linux
|
||||
The package is available in the [AUR](https://aur.archlinux.org/packages/picodulce) as ```picodulce```
|
||||
|
||||
For installing on Arch without using an AUR helper a PKGBUILD is provided
|
||||
```
|
||||
git clone https://aur.archlinux.org/picodulce.git
|
||||
cd picodulce
|
||||
makepkg -si
|
||||
```
|
||||
|
||||
## Other OS
|
||||
If you are on windows you may be more interested in a [installer](https://github.com/nixietab/2hsu/releases/download/release/2hsu.exe)
|
||||
|
||||
### 1. Clone the repository
|
||||
|
||||
|
239
authser.py
239
authser.py
@ -1,239 +0,0 @@
|
||||
import sys
|
||||
import re
|
||||
import colorama
|
||||
import requests
|
||||
from PyQt5.QtWidgets import (QApplication, QDialog, QLabel, QVBoxLayout,
|
||||
QPushButton, QLineEdit, QMessageBox)
|
||||
from PyQt5.QtCore import QThread, pyqtSignal, Qt, QUrl, QObject, QTimer
|
||||
from PyQt5.QtGui import QDesktopServices
|
||||
from picomc.logging import logger
|
||||
|
||||
# Constants
|
||||
URL_DEVICE_AUTH = "https://login.microsoftonline.com/consumers/oauth2/v2.0/devicecode"
|
||||
URL_TOKEN = "https://login.microsoftonline.com/consumers/oauth2/v2.0/token"
|
||||
CLIENT_ID = "c52aed44-3b4d-4215-99c5-824033d2bc0f"
|
||||
SCOPE = "XboxLive.signin offline_access"
|
||||
GRANT_TYPE = "urn:ietf:params:oauth:grant-type:device_code"
|
||||
|
||||
class AuthDialog(QDialog):
|
||||
def __init__(self, url, code, parent=None, error_mode=False):
|
||||
super().__init__(parent)
|
||||
self.setWindowTitle("Microsoft Authentication")
|
||||
self.setWindowFlags(self.windowFlags() & ~Qt.WindowContextHelpButtonHint)
|
||||
self.setModal(True)
|
||||
self.setup_ui(url, code, error_mode)
|
||||
|
||||
def setup_ui(self, url, code, error_mode):
|
||||
layout = QVBoxLayout(self)
|
||||
|
||||
if error_mode:
|
||||
error_label = QLabel("Error in Login - Please try again")
|
||||
error_label.setStyleSheet("QLabel { color: red; font-weight: bold; }")
|
||||
layout.addWidget(error_label)
|
||||
|
||||
instructions = QLabel(
|
||||
"To authenticate your Microsoft Account:\n\n"
|
||||
"1. Click 'Open Authentication Page' or visit:\n"
|
||||
"2. Copy the code below\n"
|
||||
"3. Paste the code on the Microsoft website\n"
|
||||
"4. After completing authentication, click 'I've Completed Authentication'"
|
||||
)
|
||||
instructions.setWordWrap(True)
|
||||
layout.addWidget(instructions)
|
||||
|
||||
url_label = QLabel(url)
|
||||
url_label.setTextInteractionFlags(Qt.TextSelectableByMouse)
|
||||
url_label.setWordWrap(True)
|
||||
layout.addWidget(url_label)
|
||||
|
||||
self.code_input = QLineEdit(code)
|
||||
self.code_input.setReadOnly(True)
|
||||
self.code_input.setAlignment(Qt.AlignCenter)
|
||||
self.code_input.setStyleSheet("""
|
||||
QLineEdit {
|
||||
font-size: 16pt;
|
||||
font-weight: bold;
|
||||
padding: 5px;
|
||||
}
|
||||
""")
|
||||
layout.addWidget(self.code_input)
|
||||
|
||||
copy_button = QPushButton("Copy Code")
|
||||
copy_button.clicked.connect(self.copy_code)
|
||||
layout.addWidget(copy_button)
|
||||
|
||||
open_url_button = QPushButton("Open Authentication Page")
|
||||
open_url_button.clicked.connect(lambda: self.open_url(url))
|
||||
layout.addWidget(open_url_button)
|
||||
|
||||
continue_button = QPushButton("I've Completed Authentication")
|
||||
continue_button.clicked.connect(self.accept)
|
||||
layout.addWidget(continue_button)
|
||||
|
||||
def copy_code(self):
|
||||
clipboard = QApplication.clipboard()
|
||||
clipboard.setText(self.code_input.text())
|
||||
|
||||
def open_url(self, url):
|
||||
QDesktopServices.openUrl(QUrl(url))
|
||||
|
||||
class AuthenticationThread(QThread):
|
||||
auth_data_received = pyqtSignal(dict)
|
||||
error_occurred = pyqtSignal(str)
|
||||
auth_error_detected = pyqtSignal(str)
|
||||
finished = pyqtSignal()
|
||||
access_token_received = pyqtSignal(str, str)
|
||||
|
||||
def __init__(self, account):
|
||||
super().__init__()
|
||||
self.account = account
|
||||
self.device_code = None
|
||||
self.is_running = True
|
||||
|
||||
def run(self):
|
||||
try:
|
||||
self.authenticate(self.account)
|
||||
except Exception as e:
|
||||
self.error_occurred.emit(str(e))
|
||||
self.finished.emit()
|
||||
|
||||
def authenticate(self, account):
|
||||
try:
|
||||
data = {"client_id": CLIENT_ID, "scope": SCOPE}
|
||||
|
||||
# Request device code
|
||||
resp = requests.post(URL_DEVICE_AUTH, data)
|
||||
resp.raise_for_status()
|
||||
|
||||
j = resp.json()
|
||||
self.device_code = j["device_code"]
|
||||
user_code = j["user_code"]
|
||||
link = j["verification_uri"]
|
||||
|
||||
# Format message with colorama
|
||||
msg = j["message"]
|
||||
msg = msg.replace(
|
||||
user_code, colorama.Fore.RED + user_code + colorama.Fore.RESET
|
||||
).replace(link, colorama.Style.BRIGHT + link + colorama.Style.NORMAL)
|
||||
|
||||
# Emit auth data received signal
|
||||
self.auth_data_received.emit({'url': link, 'code': user_code})
|
||||
|
||||
except requests.exceptions.RequestException as e:
|
||||
logger.error(f"Request failed: {e}")
|
||||
self.error_occurred.emit(str(e))
|
||||
self.finished.emit()
|
||||
|
||||
def poll_for_token(self):
|
||||
try:
|
||||
data = {"code": self.device_code, "grant_type": GRANT_TYPE, "client_id": CLIENT_ID}
|
||||
resp = requests.post(URL_TOKEN, data)
|
||||
if resp.status_code == 400:
|
||||
j = resp.json()
|
||||
logger.debug(j)
|
||||
if j["error"] == "authorization_pending":
|
||||
logger.warning(j["error_description"])
|
||||
self.auth_error_detected.emit(j["error_description"])
|
||||
return
|
||||
else:
|
||||
raise Exception(j["error_description"])
|
||||
resp.raise_for_status()
|
||||
j = resp.json()
|
||||
access_token = j["access_token"]
|
||||
refresh_token = j["refresh_token"]
|
||||
logger.debug("OAuth device code flow successful")
|
||||
self.access_token_received.emit(access_token, refresh_token)
|
||||
self.finished.emit()
|
||||
except requests.exceptions.RequestException as e:
|
||||
logger.error(f"Request failed: {e}")
|
||||
self.error_occurred.emit(str(e))
|
||||
self.finished.emit()
|
||||
|
||||
def send_enter(self):
|
||||
self.poll_for_token()
|
||||
|
||||
def stop(self):
|
||||
self.is_running = False
|
||||
|
||||
class MinecraftAuthenticator(QObject):
|
||||
auth_finished = pyqtSignal(bool)
|
||||
|
||||
def __init__(self, parent=None):
|
||||
super().__init__(parent)
|
||||
self.auth_thread = None
|
||||
self.current_auth_data = None
|
||||
self.auth_dialog = None
|
||||
self.success = False
|
||||
|
||||
def authenticate(self, username):
|
||||
self.success = False
|
||||
self.auth_thread = AuthenticationThread(username)
|
||||
self.auth_thread.auth_data_received.connect(self.show_auth_dialog)
|
||||
self.auth_thread.auth_error_detected.connect(self.handle_auth_error)
|
||||
self.auth_thread.error_occurred.connect(self.show_error)
|
||||
self.auth_thread.access_token_received.connect(self.on_access_token_received)
|
||||
self.auth_thread.finished.connect(self.on_authentication_finished)
|
||||
self.auth_thread.start()
|
||||
|
||||
def show_auth_dialog(self, auth_data):
|
||||
self.current_auth_data = auth_data
|
||||
|
||||
if self.auth_dialog is not None:
|
||||
self.auth_dialog.close()
|
||||
self.auth_dialog = None
|
||||
|
||||
self.auth_dialog = AuthDialog(auth_data['url'], auth_data['code'])
|
||||
if self.auth_dialog.exec_() == QDialog.Accepted:
|
||||
self.auth_thread.send_enter()
|
||||
|
||||
def handle_auth_error(self, output):
|
||||
if self.current_auth_data:
|
||||
if self.auth_dialog is not None:
|
||||
self.auth_dialog.close()
|
||||
self.auth_dialog = None
|
||||
|
||||
self.auth_dialog = AuthDialog(
|
||||
self.current_auth_data['url'],
|
||||
self.current_auth_data['code'],
|
||||
error_mode=True
|
||||
)
|
||||
if self.auth_dialog.exec_() == QDialog.Accepted:
|
||||
self.auth_thread.send_enter()
|
||||
|
||||
def show_error(self, error_message):
|
||||
QMessageBox.critical(None, "Error", f"Authentication error: {error_message}")
|
||||
self.success = False
|
||||
self.auth_finished.emit(False)
|
||||
|
||||
def on_access_token_received(self, access_token, refresh_token):
|
||||
QMessageBox.information(None, "Success", "Authentication successful!")
|
||||
self.success = True
|
||||
self.auth_finished.emit(True)
|
||||
|
||||
def on_authentication_finished(self):
|
||||
if self.auth_dialog is not None:
|
||||
self.auth_dialog.close()
|
||||
self.auth_dialog = None
|
||||
|
||||
if self.auth_thread:
|
||||
self.auth_thread.stop()
|
||||
self.auth_thread = None
|
||||
|
||||
if not self.success:
|
||||
self.auth_finished.emit(False)
|
||||
|
||||
def cleanup(self):
|
||||
if self.auth_dialog is not None:
|
||||
self.auth_dialog.close()
|
||||
self.auth_dialog = None
|
||||
|
||||
if self.auth_thread and self.auth_thread.isRunning():
|
||||
self.auth_thread.stop()
|
||||
self.auth_thread.wait()
|
||||
|
||||
# Example usage
|
||||
if __name__ == '__main__':
|
||||
app = QApplication(sys.argv)
|
||||
authenticator = MinecraftAuthenticator()
|
||||
authenticator.authenticate("TestUser")
|
||||
sys.exit(app.exec_())
|
119
healthcheck.py
119
healthcheck.py
@ -1,119 +0,0 @@
|
||||
import os
|
||||
import json
|
||||
import requests
|
||||
|
||||
|
||||
class HealthCheck:
|
||||
def __init__(self):
|
||||
self.config = None
|
||||
|
||||
def check_config_file(self):
|
||||
config_path = "config.json"
|
||||
default_config = {
|
||||
"IsRCPenabled": False,
|
||||
"CheckUpdate": False,
|
||||
"IsBleeding": False,
|
||||
"LastPlayed": "",
|
||||
"IsFirstLaunch": True,
|
||||
"Instance": "default",
|
||||
"Theme": "Dark.json",
|
||||
"ThemeBackground": True,
|
||||
"ThemeRepository": "https://raw.githubusercontent.com/nixietab/picodulce-themes/main/repo.json",
|
||||
"Locale": "en"
|
||||
}
|
||||
|
||||
# Step 1: Check if the file exists; if not, create it with default values
|
||||
if not os.path.exists(config_path):
|
||||
with open(config_path, "w") as config_file:
|
||||
json.dump(default_config, config_file, indent=4)
|
||||
self.config = default_config
|
||||
return
|
||||
|
||||
# Step 2: Try loading the config file, handle invalid JSON
|
||||
try:
|
||||
with open(config_path, "r") as config_file:
|
||||
self.config = json.load(config_file)
|
||||
except (json.JSONDecodeError, ValueError):
|
||||
# File is corrupted, overwrite it with default configuration
|
||||
with open(config_path, "w") as config_file:
|
||||
json.dump(default_config, config_file, indent=4)
|
||||
self.config = default_config
|
||||
return
|
||||
|
||||
# Step 3: Check for missing keys and add defaults if necessary
|
||||
updated = False
|
||||
for key, value in default_config.items():
|
||||
if key not in self.config: # Field is missing
|
||||
self.config[key] = value
|
||||
updated = True
|
||||
|
||||
# Step 4: Save the repaired config back to the file
|
||||
if updated:
|
||||
with open(config_path, "w") as config_file:
|
||||
json.dump(self.config, config_file, indent=4)
|
||||
|
||||
def themes_integrity(self):
|
||||
# Define folder and file paths
|
||||
themes_folder = "themes"
|
||||
dark_theme_file = os.path.join(themes_folder, "Dark.json")
|
||||
native_theme_file = os.path.join(themes_folder, "Native.json")
|
||||
|
||||
# Define the default content for Dark.json
|
||||
dark_theme_content = {
|
||||
"manifest": {
|
||||
"name": "Dark",
|
||||
"description": "The default picodulce launcher theme",
|
||||
"author": "Nixietab",
|
||||
"license": "MIT"
|
||||
},
|
||||
"palette": {
|
||||
"Window": "#353535",
|
||||
"WindowText": "#ffffff",
|
||||
"Base": "#191919",
|
||||
"AlternateBase": "#353535",
|
||||
"ToolTipBase": "#ffffff",
|
||||
"ToolTipText": "#ffffff",
|
||||
"Text": "#ffffff",
|
||||
"Button": "#353535",
|
||||
"ButtonText": "#ffffff",
|
||||
"BrightText": "#ff0000",
|
||||
"Link": "#2a82da",
|
||||
"Highlight": "#4bb679",
|
||||
"HighlightedText": "#ffffff"
|
||||
},
|
||||
"background_image_base64": ""
|
||||
}
|
||||
|
||||
# Define the default content for Native.json
|
||||
native_theme_content = {
|
||||
"manifest": {
|
||||
"name": "Native",
|
||||
"description": "The native looks of your OS",
|
||||
"author": "Your Qt Style",
|
||||
"license": "Any"
|
||||
},
|
||||
"palette": {}
|
||||
}
|
||||
|
||||
# Step 1: Ensure the themes folder exists
|
||||
if not os.path.exists(themes_folder):
|
||||
print(f"Creating folder: {themes_folder}")
|
||||
os.makedirs(themes_folder)
|
||||
|
||||
# Step 2: Ensure Dark.json exists
|
||||
if not os.path.isfile(dark_theme_file):
|
||||
print(f"Creating file: {dark_theme_file}")
|
||||
with open(dark_theme_file, "w", encoding="utf-8") as file:
|
||||
json.dump(dark_theme_content, file, indent=2)
|
||||
print("Dark.json has been created successfully.")
|
||||
|
||||
# Step 3: Ensure Native.json exists
|
||||
if not os.path.isfile(native_theme_file):
|
||||
print(f"Creating file: {native_theme_file}")
|
||||
with open(native_theme_file, "w", encoding="utf-8") as file:
|
||||
json.dump(native_theme_content, file, indent=2)
|
||||
print("Native.json has been created successfully.")
|
||||
|
||||
# Check if both files exist and print OK message
|
||||
if os.path.isfile(dark_theme_file) and os.path.isfile(native_theme_file):
|
||||
print("Theme Integrity OK")
|
30
modulecli.py
30
modulecli.py
@ -1,30 +0,0 @@
|
||||
import click
|
||||
from picomc.cli.main import picomc_cli
|
||||
from io import StringIO
|
||||
import sys
|
||||
|
||||
def run_command(command="picomc"):
|
||||
# Redirect stdout and stderr to capture the command output
|
||||
old_stdout, old_stderr = sys.stdout, sys.stderr
|
||||
sys.stdout = mystdout = StringIO()
|
||||
sys.stderr = mystderr = StringIO()
|
||||
|
||||
try:
|
||||
picomc_cli.main(args=command.split())
|
||||
except SystemExit as e:
|
||||
if e.code != 0:
|
||||
print(f"Command exited with code {e.code}", file=sys.stderr)
|
||||
except Exception as e:
|
||||
print(f"Unexpected error: {e}", file=sys.stderr)
|
||||
finally:
|
||||
# Restore stdout and stderr
|
||||
sys.stdout = old_stdout
|
||||
sys.stderr = old_stderr
|
||||
|
||||
output = mystdout.getvalue().strip()
|
||||
error = mystderr.getvalue().strip()
|
||||
|
||||
if not output:
|
||||
return f"Error: No output from command. Stderr: {error}"
|
||||
|
||||
return output
|
927
picodulce.py
927
picodulce.py
File diff suppressed because it is too large
Load Diff
@ -2,4 +2,3 @@ picomc
|
||||
PyQt5
|
||||
requests
|
||||
pypresence
|
||||
tqdm
|
||||
|
21
version.json
21
version.json
@ -1,15 +1,12 @@
|
||||
{
|
||||
"version": "0.13",
|
||||
"version": "0.11.99",
|
||||
"name": "Lucky Bastard",
|
||||
"links": [
|
||||
"https://raw.githubusercontent.com/nixietab/picodulce/main/version.json",
|
||||
"https://raw.githubusercontent.com/nixietab/picodulce/main/picodulce.py",
|
||||
"https://raw.githubusercontent.com/nixietab/picodulce/main/requirements.txt",
|
||||
"https://raw.githubusercontent.com/nixietab/picodulce/main/drums.gif",
|
||||
"https://raw.githubusercontent.com/nixietab/picodulce/main/marroc.py",
|
||||
"https://raw.githubusercontent.com/nixietab/picodulce/main/holiday.ico",
|
||||
"https://raw.githubusercontent.com/nixietab/picodulce/main/authser.py",
|
||||
"https://raw.githubusercontent.com/nixietab/picodulce/main/healthcheck.py",
|
||||
"https://raw.githubusercontent.com/nixietab/picodulce/main/modulecli.py"
|
||||
],
|
||||
"versionBleeding": "0.13-194"
|
||||
"https://raw.githubusercontent.com/nixietab/picodulce/canary/version.json",
|
||||
"https://raw.githubusercontent.com/nixietab/picodulce/canary/picodulce.py",
|
||||
"https://raw.githubusercontent.com/nixietab/picodulce/canary/requirements.txt",
|
||||
"https://raw.githubusercontent.com/nixietab/picodulce/canary/drums.gif",
|
||||
"https://raw.githubusercontent.com/nixietab/picodulce/canary/marroc.py",
|
||||
"https://raw.githubusercontent.com/nixietab/picodulce/canary/holiday.ico"
|
||||
]
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user