minor updates
This commit is contained in:
parent
af0c9914ab
commit
7180b0a3f7
6 changed files with 167 additions and 28 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
|
@ -27,6 +27,7 @@ venv/
|
||||||
ENV/
|
ENV/
|
||||||
|
|
||||||
# Configuration and Secrets
|
# Configuration and Secrets
|
||||||
|
config.test.yaml
|
||||||
config.yaml
|
config.yaml
|
||||||
!config.example.yaml
|
!config.example.yaml
|
||||||
|
|
||||||
|
|
|
||||||
51
README.md
51
README.md
|
|
@ -4,31 +4,6 @@ Fluxer Reaper is a simple tool to help you move your Discord server content over
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
## Getting Started
|
|
||||||
|
|
||||||
### 1. Prerequisites
|
|
||||||
Make sure you have Python installed on your computer.
|
|
||||||
|
|
||||||
### 2. Download or Clone
|
|
||||||
Clone the repository using git:
|
|
||||||
```bash
|
|
||||||
git clone https://github.com/rambros3d/fluxer-reaper.git
|
|
||||||
cd fluxer-reaper
|
|
||||||
```
|
|
||||||
Alternatively, you can download the project as a ZIP file and extract its contents.
|
|
||||||
|
|
||||||
### 3. Install the tool
|
|
||||||
Open your terminal and run:
|
|
||||||
```bash
|
|
||||||
pip install -r requirements.txt
|
|
||||||
```
|
|
||||||
|
|
||||||
### 4. Run it!
|
|
||||||
Start the tool by running:
|
|
||||||
```bash
|
|
||||||
python fluxer-reaper.py
|
|
||||||
```
|
|
||||||
|
|
||||||
|
|
||||||
## Features
|
## Features
|
||||||
* **Clone Server Structure**: Automatically creates all your Discord categories and channels in Fluxer.
|
* **Clone Server Structure**: Automatically creates all your Discord categories and channels in Fluxer.
|
||||||
|
|
@ -38,3 +13,29 @@ python fluxer-reaper.py
|
||||||
* **Server Identity**: Syncs your server name, icon, and banner.
|
* **Server Identity**: Syncs your server name, icon, and banner.
|
||||||
* **Danger Zone**: Option to wipe existing channels, roles, and content in the fluxer community.
|
* **Danger Zone**: Option to wipe existing channels, roles, and content in the fluxer community.
|
||||||
|
|
||||||
|
|
||||||
|
## Getting Started
|
||||||
|
|
||||||
|
### 1. Download
|
||||||
|
Download the latest executable from the [Releases](https://github.com/rambros3d/fluxer-reaper/releases) page.
|
||||||
|
|
||||||
|
### 2. Run
|
||||||
|
Simply run the downloaded file to start the tool. No Python installation is required.
|
||||||
|
|
||||||
|
|
||||||
|
## Build tool
|
||||||
|
To create a standalone executable, simply run:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
chmod +x build.sh
|
||||||
|
./build.sh
|
||||||
|
```
|
||||||
|
|
||||||
|
The script will automatically set up a virtual environment, install dependencies, and generate the binary in the `dist/` folder.
|
||||||
|
|
||||||
|
|
||||||
|
## Vibe Code Notice
|
||||||
|
|
||||||
|
Code is provided as is; This tool was developed largely by AI.
|
||||||
|
|
||||||
|
Take it, use it, modify it, feel free to whatever you wish.
|
||||||
65
build.sh
Executable file
65
build.sh
Executable file
|
|
@ -0,0 +1,65 @@
|
||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# Exit on error
|
||||||
|
set -e
|
||||||
|
|
||||||
|
echo "--- Fluxer Reaper Cross-Distro Build Script ---"
|
||||||
|
echo "NOTE: For maximum compatibility (glibc), run this on your oldest target Linux distribution."
|
||||||
|
|
||||||
|
# Check for venv
|
||||||
|
if [ ! -d "venv" ]; then
|
||||||
|
echo "Creating virtual environment..."
|
||||||
|
python3 -m venv venv || {
|
||||||
|
echo "Error: Failed to create venv. You might need to install 'python3-venv'."
|
||||||
|
echo "Try: sudo apt install python3-venv"
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "Activating virtual environment..."
|
||||||
|
source venv/bin/activate
|
||||||
|
|
||||||
|
# Self-healing pip check
|
||||||
|
if ! python3 -m pip --version > /dev/null 2>&1; then
|
||||||
|
echo "Warning: pip is missing or broken in venv. Attempting repair..."
|
||||||
|
python3 -m ensurepip --default-pip || {
|
||||||
|
echo "Error: Failed to repair pip automatically."
|
||||||
|
echo "Try recreating the venv: rm -rf venv && python3 -m venv venv"
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "Ensuring build dependencies are up to date..."
|
||||||
|
pip install --upgrade pip --quiet
|
||||||
|
pip install pyinstaller --quiet
|
||||||
|
pip install -r requirements.txt --quiet
|
||||||
|
|
||||||
|
echo "Cleaning previous build artifacts..."
|
||||||
|
rm -rf build/ dist/
|
||||||
|
|
||||||
|
echo "Starting PyInstaller build..."
|
||||||
|
pyinstaller --clean fluxer-reaper.spec
|
||||||
|
|
||||||
|
echo "Generating Launch-Reaper.sh launcher..."
|
||||||
|
cat << 'EOF' > dist/Launch-Reaper.sh
|
||||||
|
#!/bin/bash
|
||||||
|
# Convenient launcher for Fluxer Reaper
|
||||||
|
# Ensures it runs in a terminal if possible, but the binary also has internal auto-terminal logic.
|
||||||
|
|
||||||
|
BASEDIR=$(dirname "$0")
|
||||||
|
cd "$BASEDIR"
|
||||||
|
|
||||||
|
if [ -f "./fluxer-reaper" ]; then
|
||||||
|
./fluxer-reaper
|
||||||
|
else
|
||||||
|
echo "Error: fluxer-reaper binary not found in $(pwd)"
|
||||||
|
read -p "Press enter to exit..."
|
||||||
|
fi
|
||||||
|
EOF
|
||||||
|
chmod +x dist/Launch-Reaper.sh
|
||||||
|
|
||||||
|
echo "-----------------------------------"
|
||||||
|
echo "Build complete!"
|
||||||
|
echo "Standalone executable: dist/fluxer-reaper"
|
||||||
|
echo "Launcher script: dist/Launch-Reaper.sh"
|
||||||
|
echo "---"
|
||||||
|
|
@ -23,7 +23,70 @@ def setup_logging():
|
||||||
handlers=handlers
|
handlers=handlers
|
||||||
)
|
)
|
||||||
|
|
||||||
|
def relaunch_in_terminal():
|
||||||
|
"""Detects if running without a terminal on Linux and relaunches in one."""
|
||||||
|
import os
|
||||||
|
import sys
|
||||||
|
import subprocess
|
||||||
|
import shutil
|
||||||
|
|
||||||
|
# Only attempt on Linux
|
||||||
|
if sys.platform != "linux":
|
||||||
|
return
|
||||||
|
|
||||||
|
# Check if we have a TTY on stdin or stdout, or if already relaunched
|
||||||
|
is_tty = sys.stdin.isatty() or sys.stdout.isatty()
|
||||||
|
if is_tty or os.environ.get("FLUXER_REAPER_RELAUNCHED"):
|
||||||
|
return
|
||||||
|
|
||||||
|
# Diagnostic logging to help debug why it fails on some distros
|
||||||
|
debug_log = "/tmp/reaper_terminal_debug.log"
|
||||||
|
with open(debug_log, "a") as f:
|
||||||
|
f.write(f"Relaunching... isatty={is_tty}, env={os.environ.get('FLUXER_REAPER_RELAUNCHED')}\n")
|
||||||
|
|
||||||
|
# List of terminals to try with their specific execution flags
|
||||||
|
terminals = [
|
||||||
|
("gnome-terminal", ["--"]), # Modern GNOME Terminal
|
||||||
|
("ptyxis", ["--"]), # Fedora/Modern GNOME
|
||||||
|
("x-terminal-emulator", ["-e"]), # Ubuntu/Debian standard
|
||||||
|
("kgx", ["-e"]), # GNOME Console
|
||||||
|
("konsole", ["-e"]),
|
||||||
|
("xfce4-terminal", ["-e"]),
|
||||||
|
("lxterminal", ["-e"]),
|
||||||
|
("mate-terminal", ["-e"]),
|
||||||
|
("alacritty", ["-e"]),
|
||||||
|
("kitty", []),
|
||||||
|
("xterm", ["-e"]),
|
||||||
|
]
|
||||||
|
|
||||||
|
# Resolve the absolute path to ourselves.
|
||||||
|
# frozen=True means we are running from a PyInstaller bundle.
|
||||||
|
if getattr(sys, 'frozen', False):
|
||||||
|
executable = os.path.abspath(sys.argv[0])
|
||||||
|
else:
|
||||||
|
executable = sys.executable
|
||||||
|
|
||||||
|
args = [executable] + sys.argv[1:]
|
||||||
|
|
||||||
|
# Set env var to prevent loops
|
||||||
|
env = os.environ.copy()
|
||||||
|
env["FLUXER_REAPER_RELAUNCHED"] = "1"
|
||||||
|
|
||||||
|
for term, cmd_args in terminals:
|
||||||
|
if shutil.which(term):
|
||||||
|
with open(debug_log, "a") as f:
|
||||||
|
f.write(f"Found terminal: {term}\n")
|
||||||
|
try:
|
||||||
|
# Construct command: term [args] executable [sys.argv]
|
||||||
|
subprocess.Popen([term] + cmd_args + args, env=env)
|
||||||
|
sys.exit(0)
|
||||||
|
except Exception as e:
|
||||||
|
with open(debug_log, "a") as f:
|
||||||
|
f.write(f"Failed to launch {term}: {e}\n")
|
||||||
|
continue
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
|
relaunch_in_terminal()
|
||||||
setup_logging()
|
setup_logging()
|
||||||
try:
|
try:
|
||||||
asyncio.run(run_cli())
|
asyncio.run(run_cli())
|
||||||
|
|
|
||||||
|
|
@ -17,7 +17,16 @@ class AppConfig(BaseModel):
|
||||||
def load_config(config_path: str | Path = "config.yaml") -> AppConfig:
|
def load_config(config_path: str | Path = "config.yaml") -> AppConfig:
|
||||||
path = Path(config_path)
|
path = Path(config_path)
|
||||||
if not path.exists():
|
if not path.exists():
|
||||||
raise FileNotFoundError(f"Configuration file not found: {config_path}")
|
# Create dummy config if missing
|
||||||
|
config = AppConfig(
|
||||||
|
discord_bot_token="YOUR_DISCORD_TOKEN",
|
||||||
|
fluxer_bot_token="YOUR_FLUXER_TOKEN",
|
||||||
|
discord_server_id="000000000000000000",
|
||||||
|
fluxer_community_id="000000000000000000"
|
||||||
|
)
|
||||||
|
save_config(config, path)
|
||||||
|
print(f"Created default configuration: {config_path}")
|
||||||
|
return config
|
||||||
|
|
||||||
with open(path, "r", encoding="utf-8") as f:
|
with open(path, "r", encoding="utf-8") as f:
|
||||||
data = yaml.safe_load(f)
|
data = yaml.safe_load(f)
|
||||||
|
|
|
||||||
|
|
@ -157,7 +157,7 @@ class MigrationCLI:
|
||||||
|
|
||||||
console.print("(Q) Exit")
|
console.print("(Q) Exit")
|
||||||
|
|
||||||
choice = Prompt.ask("Select an option", choices=["1", "2", "3", "4", "5", "6", "7", "Q", "q"], default="Q").upper()
|
choice = Prompt.ask("\nSelect an option", choices=["1", "2", "3", "4", "5", "6", "7", "Q", "q"], default="Q").upper()
|
||||||
|
|
||||||
if choice == "1":
|
if choice == "1":
|
||||||
await self.clone_server_template()
|
await self.clone_server_template()
|
||||||
|
|
@ -272,7 +272,7 @@ class MigrationCLI:
|
||||||
fluxer_cat_id = self.engine.state.get_fluxer_category_id(cat_id_str)
|
fluxer_cat_id = self.engine.state.get_fluxer_category_id(cat_id_str)
|
||||||
|
|
||||||
status = f"[cyan]{fluxer_cat_id}[/cyan]" if fluxer_cat_id else "[bold red]Missing[/bold red]"
|
status = f"[cyan]{fluxer_cat_id}[/cyan]" if fluxer_cat_id else "[bold red]Missing[/bold red]"
|
||||||
table.add_row("Category", f"[bold yellow]{cat.name}[/bold yellow]", status)
|
table.add_row("[bold yellow]Category[/bold yellow]", f"[bold yellow]{cat.name}[/bold yellow]", status)
|
||||||
|
|
||||||
# Show ALL channels under this category
|
# Show ALL channels under this category
|
||||||
cat_channels = [ch for ch in channels if str(ch.category_id) == cat_id_str]
|
cat_channels = [ch for ch in channels if str(ch.category_id) == cat_id_str]
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue