12 Commits
1.0.0 ... v1.1

Author SHA1 Message Date
√(noham)²
03cfdb39d2 upload feature 2024-08-27 17:43:57 +02:00
√(noham)²
21bacce76b scripts ! 2024-08-27 15:32:16 +02:00
√(noham)²
f1a316961c Update build.sh 2024-08-27 13:44:05 +02:00
√(noham)²
0e2a4899a5 build script 2024-08-27 13:24:31 +02:00
√(noham)²
091182c555 changes 2024-08-27 12:38:17 +02:00
√(noham)²
825ad69828 should pass finally 2024-08-26 00:26:36 +02:00
√(noham)²
1ffa55f19f Update release.yml 2024-08-26 00:13:27 +02:00
√(noham)²
7e0e04a964 Update release.yml 2024-08-26 00:05:30 +02:00
√(noham)²
b0b1b1d197 Create releasetemp.yml 2024-08-25 23:53:09 +02:00
√(noham)²
f2dbeefa1f another test 2024-08-25 23:17:07 +02:00
√(noham)²
d7660d4c9b Update release.yml 2024-08-25 22:55:33 +02:00
√(noham)²
53d1d85ac5 ... 🥲 2024-08-25 22:37:40 +02:00
9 changed files with 256 additions and 83 deletions

View File

@@ -1,2 +1,3 @@
TOKEN = "" TOKEN = ""
PRIVATE_PARENT_ID = "" PRIVATE_PARENT_ID = ""
GOPLOAD_ACCOUNT_ID = ""

View File

@@ -27,7 +27,7 @@ jobs:
steps: steps:
- name: Check-out repository - name: Check-out repository
uses: actions/checkout@v4 uses: actions/checkout@v1
- name: Setup Python - name: Setup Python
uses: actions/setup-python@v5 uses: actions/setup-python@v5
@@ -50,7 +50,7 @@ jobs:
onefile: true onefile: true
- name: Upload Artifact[win-x64] - name: Upload Artifact[win-x64]
uses: actions/upload-artifact@v4 uses: actions/upload-artifact@v3.1.3
with: with:
name: GoFileCLI_win-x64 name: GoFileCLI_win-x64
path: | path: |
@@ -60,11 +60,8 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- name: Check runner architecture
run: uname -m
- name: Check-out repository - name: Check-out repository
uses: actions/checkout@v4 uses: actions/checkout@v1
- name: Setup Python - name: Setup Python
uses: actions/setup-python@v5 uses: actions/setup-python@v5
@@ -86,22 +83,22 @@ jobs:
script-name: gofilecli.py script-name: gofilecli.py
onefile: true onefile: true
- name: Rename Executable
run: mv build/gofilecli.bin build/gofilecli
- name: Upload Artifact[linux-x64] - name: Upload Artifact[linux-x64]
uses: actions/upload-artifact@v4 uses: actions/upload-artifact@v3.1.3
with: with:
name: GoFileCLI_linux-x64 name: GoFileCLI_linux-x64
path: | path: |
build/gofilecli.bin build/gofilecli
build-macos: build-macos:
runs-on: macos-latest runs-on: macos-latest
steps: steps:
- name: Check runner architecture
run: uname -m
- name: Check-out repository - name: Check-out repository
uses: actions/checkout@v4 uses: actions/checkout@v1
- name: Setup Python - name: Setup Python
uses: actions/setup-python@v5 uses: actions/setup-python@v5
@@ -118,24 +115,27 @@ jobs:
pip install nuitka pip install nuitka
- name: Build Executable with Nuitka - name: Build Executable with Nuitka
# --macos-app-icon=resources/icon.icns
run: | run: |
python -m nuitka --onefile --assume-yes-for-downloads --output-dir=dist --macos-target-arch=arm64 gofilecli.py python -m nuitka --onefile --assume-yes-for-downloads --output-dir=dist --macos-target-arch=arm64 gofilecli.py
python -m nuitka --onefile --assume-yes-for-downloads --output-dir=dist_x86_64 --macos-target-arch=x86_64 gofilecli.py python -m nuitka --onefile --assume-yes-for-downloads --output-dir=dist_x86_64 --macos-target-arch=x86_64 gofilecli.py
- name: Upload Artifact[osx-arm64] - name: Rename Executable
uses: actions/upload-artifact@v4 run: |
with: mv dist/gofilecli.bin dist/gofilecli
name: GoFileCLI_osx-x64 mv dist_x86_64/gofilecli.bin dist_x86_64/gofilecli
path: |
dist_x86_64/gofilecli.bin
- name: Upload Artifact [osx-arm64] - name: Upload Artifact [osx-arm64]
uses: actions/upload-artifact@v4 uses: actions/upload-artifact@v3.1.3
with:
name: GoFileCLI_osx-x64
path: dist_x86_64/gofilecli
- name: Upload Artifact [osx-arm64]
uses: actions/upload-artifact@v3.1.3
with: with:
name: GoFileCLI_osx-arm64 name: GoFileCLI_osx-arm64
path: | path: dist/gofilecli
dist/gofilecli.bin
create_draft_release: create_draft_release:
name: Create Github draft release name: Create Github draft release
@@ -178,7 +178,7 @@ jobs:
attach_to_release: attach_to_release:
name: Attach native executables to release name: Attach native executables to release
if: ${{ github.event.inputs.doRelease == 'true' }} if: ${{ github.event.inputs.doRelease == 'true' }}
needs: create_draft_release needs: [create_draft_release]
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- name: Get current date - name: Get current date
@@ -191,21 +191,16 @@ jobs:
- name: Fetch executables - name: Fetch executables
uses: actions/download-artifact@v3 uses: actions/download-artifact@v3
- name: Tar (linux, macOS) - name: List downloaded files
run: | run: |
for file in *{osx,linux}*; do echo "Listing files in the working directory:"
if [ -f "$file" ]; then ls -R
tar cvzfp "${file}_${{ env.date }}.tar.gz" "$file"
fi - name: Tar (linux, macOS)
done run: for dir in *{osx,linux}*; do tar cvzfp "${dir}_${{ env.date }}.tar.gz" "$dir"; done
- name: Zip (windows) - name: Zip (windows)
run: | run: for dir in *win*; do zip -r "${dir}_${{ env.date }}.zip" "$dir"; done
for file in *win*; do
if [ -f "$file" ]; then
zip -r "${file}_${{ env.date }}.zip" "$file"
fi
done
- name: Upload - name: Upload
run: | run: |

3
.gitignore vendored
View File

@@ -133,3 +133,6 @@ encrypt.py
/temp /temp
.copy .copy
.github/workflows/build_latest_ex.yml .github/workflows/build_latest_ex.yml
assets/sounds/Blow.aiff
assets/sounds/Blow.mp3
assets/sounds/Blow.wav

View File

@@ -1,50 +1,59 @@
# GoFileCLI : # GoFileCLI :
...... Upload or download a file to GoFile.
# Installation : # Install :
- Linux/MacOS :
```bash
curl -fsSL https://raw.githubusercontent.com/NohamR/GoFileCLI/main/scripts/install.sh | sudo bash
```
- Windows :
Grab latest release from [releases](https://github.com/NohamR/GoFileCLI/releases/latest)
- Build on your own system :
```bash
git clone https://github.com/NohamR/GoFileCLI.git
apt install ccache patchelf
pip install nuitka
pip install -r requirements.txt
python -m nuitka --onefile --assume-yes-for-downloads --output-dir=dist --static-libpython=no gofilecli.py
# dist/gofilecli.bin
```
## Set env variables : ## Set env variables :
Get API token from https://gofile.io/myProfile. Get API token from https://gofile.io/myProfile.
Copy folderId from a folder you own. Copy folderId from a folder you own.
Windows : - Set up a .env based on [.env.example](.env.example)
```bash
setx GOPLOAD_TOKEN "XXXXXXX"
setx GOPLOAD_PRIVATE_PARENT_ID "UUID"
setx GOPLOAD_ACCOUNT_ID "UUID"
```
(Reluch Command Prompt to take effect)
Linux/MacOS : - Linux/MacOS :
```bash ```bash
export GOPLOAD_TOKEN="XXXXXXX" export GOPLOAD_TOKEN="XXXXXXX"
export GOPLOAD_PRIVATE_PARENT_ID="UUID" export GOPLOAD_PRIVATE_PARENT_ID="UUID"
export GOPLOAD_ACCOUNT_ID="UUID" export GOPLOAD_ACCOUNT_ID="UUID"
``` ```
# Usage : - Windows :
Upload a file :
```bash ```bash
gofilecli -i 'file.txt' setx GOPLOAD_TOKEN "XXXXXXX"
setx GOPLOAD_PRIVATE_PARENT_ID "UUID"
setx GOPLOAD_ACCOUNT_ID "UUID"
``` ```
(Reluch Command Prompt to take effect)
# Compile on your own system : # Usage :
```bash ```bash
git clone https://github.com/NohamR/GoFileCLI.git gofilecli -i 'file.txt' # to upload a file
apt install ccache patchelf gofilecli -f folder/ # to upload a folder
pip install nuitka gofilecli -s # to get stats of your account
pip install -r requirements.txt gofilecli -d https://gofile.io/d/XXXXX # to download a folder
python -m nuitka --standalone --assume-yes-for-downloads --output-dir=dist --static-libpython=no gofilecli.py
# dist/gofilecli.dist/gofilecli.bin
``` ```
# To do : # To do :
- acc stats
- error-rateLimit - error-rateLimit
- env via CLI - env via CLI
- finish README.md - finish README.md
- download - chiffrer & dechiffrer uploads
- build + release
- chiffrer et dechiffrer les uploads

Binary file not shown.

View File

@@ -10,6 +10,13 @@ from dotenv import load_dotenv, set_key
import platform import platform
import subprocess import subprocess
import sys import sys
import simpleaudio as sa
def play_sound():
wave_obj = sa.WaveObject.from_wave_file("assets/sounds/Blow_edited.wav")
play_obj = wave_obj.play()
play_obj.wait_done()
def set_env_var_unix(name, value, shell="bash"): def set_env_var_unix(name, value, shell="bash"):
@@ -37,12 +44,15 @@ def format_file_size(file=None, num_bytes=None):
file_size_bytes = num_bytes file_size_bytes = num_bytes
else: else:
file_size_bytes = os.path.getsize(file) file_size_bytes = os.path.getsize(file)
size_in_kb = file_size_bytes / 1024
size_in_mb = file_size_bytes / (1024 * 1024) size_in_mb = file_size_bytes / (1024 * 1024)
size_in_gb = file_size_bytes / (1024 * 1024 * 1024) size_in_gb = file_size_bytes / (1024 * 1024 * 1024)
if size_in_gb >= 1: if size_in_gb >= 1:
return size_in_gb, "GB" return size_in_gb, "GB"
else: elif size_in_mb >= 1:
return size_in_mb, "MB" return size_in_mb, "MB"
else:
return size_in_kb, "KB"
def file_size(file=None, num_bytes=None): def file_size(file=None, num_bytes=None):
@@ -53,9 +63,10 @@ def file_size(file=None, num_bytes=None):
def calculate_upload_speed(file, start_time): def calculate_upload_speed(file, start_time):
elapsed_time_seconds = time.time() - start_time elapsed_time_seconds = time.time() - start_time
file_size, size_unit = format_file_size(file) file_size, size_unit = format_file_size(file)
if size_unit == "GB": if size_unit == "GB":
average_speed = file_size / elapsed_time_seconds # GB/s average_speed = (file_size * 1024) / elapsed_time_seconds # Convert GB to MB and calculate MB/s
speed_unit = "GB/s" speed_unit = "MB/s"
else: else:
average_speed = file_size / elapsed_time_seconds # MB/s average_speed = file_size / elapsed_time_seconds # MB/s
speed_unit = "MB/s" speed_unit = "MB/s"
@@ -80,6 +91,12 @@ def get_file_paths(folderPath):
return filePaths return filePaths
def check_folderPath(path):
if not os.path.exists(path):
os.makedirs(path)
return path
def getservers(logger): def getservers(logger):
servers = [] servers = []
response = requests.get("https://api.gofile.io/servers").json() response = requests.get("https://api.gofile.io/servers").json()
@@ -130,7 +147,6 @@ def get_code(folderId, logger):
def get_children(id, logger): def get_children(id, logger):
# if len(id) == 36:
headers = {'authorization': f'Bearer {TOKEN}',} headers = {'authorization': f'Bearer {TOKEN}',}
params = (('wt', '4fd6sg89d7s6'),('cache', 'false'),) params = (('wt', '4fd6sg89d7s6'),('cache', 'false'),)
data = requests.get(f'https://api.gofile.io/contents/{id}', headers=headers, params=params).json() data = requests.get(f'https://api.gofile.io/contents/{id}', headers=headers, params=params).json()
@@ -204,13 +220,13 @@ def upload(filePath, folderPath, folderName, parentFolderId, private, logger):
files = get_file_paths(folderPath) files = get_file_paths(folderPath)
if not files: if not files:
logger.error("No files found in folder") logger.error("No files found in folder")
sys.exit("No files found in folder") sys.exit()
else: else:
if os.path.exists(filePath): if os.path.exists(filePath):
files = [filePath] files = [filePath]
else: else:
logger.error("File not found") logger.error("File not found")
sys.exit("File not found") sys.exit()
servers = getservers(logger) servers = getservers(logger)
if servers: if servers:
@@ -254,9 +270,10 @@ def upload(filePath, folderPath, folderName, parentFolderId, private, logger):
logger.info("Folder made private") logger.info("Folder made private")
else: else:
logger.error(f"{action}") logger.error(f"{action}")
play_sound()
else: else:
time.spleed(10) time.sleep(10)
sys.exit("No server available") sys.exit()
def downloadFile(downloadUrl, path, logger): def downloadFile(downloadUrl, path, logger):
@@ -270,9 +287,11 @@ def downloadFile(downloadUrl, path, logger):
return speed, elapsed_time return speed, elapsed_time
def download(folderId, logger, folderPath=None): def download(folderId, folderPath, force, logger):
if 'https' in folderId: if 'https' in folderId:
folderId = folderId.split('/')[-1] folderId = folderId.split('/')[-1]
if len(folderId) == 36:
folderId = get_code(folderId)
files = [] files = []
logger.info("Fetching files") logger.info("Fetching files")
logger.debug("FolderId: %s", folderId) logger.debug("FolderId: %s", folderId)
@@ -286,17 +305,28 @@ def download(folderId, logger, folderPath=None):
files.append(children[child]) files.append(children[child])
else: else:
folderIdList.append(children[child]['id']) folderIdList.append(children[child]['id'])
nbdone = 0
logger.info(f"Starting download of {len(files)} files") logger.info(f"Starting download of {len(files)} files")
for file in files: for file in files:
logger.info(f"Downloading file: {file['name']} ({file_size(num_bytes=file['size'])})") logger.info(f"Downloading file {nbdone}/{len(files)}: {file['name']} ({file_size(num_bytes=file['size'])})")
downloadUrl = file['link'] downloadUrl = file['link']
name = file['name'] name = file['name']
if folderPath: if folderPath:
path = os.path.join(folderPath, name) folderPath = check_folderPath(folderPath)
else: else:
path = name folderPath = check_folderPath(os.path.join(os.getcwd(), folderId))
path = os.path.join(folderPath, name)
if os.path.exists(path) and not force:
logger.warning(f"File {name} already exists skipping (set --force to overwrite)")
elif os.path.exists(path) and force:
logger.warning(f"File {name} already exists overwriting")
speed, elapsed_time = downloadFile(downloadUrl, path, logger) speed, elapsed_time = downloadFile(downloadUrl, path, logger)
logger.info(f"File download to: {path} in {elapsed_time} at {speed}") logger.info(f"File download to: {path} in {elapsed_time} at {speed}")
else:
speed, elapsed_time = downloadFile(downloadUrl, path, logger)
logger.info(f"File download to: {path} in {elapsed_time} at {speed}")
nbdone += 1
play_sound()
def opt(): def opt():
@@ -316,16 +346,14 @@ def opt():
exclusive_group.add_argument('--stats', "-s", action='store_true', help='Display account stats.') exclusive_group.add_argument('--stats', "-s", action='store_true', help='Display account stats.')
exclusive_group.add_argument("--download", "-d", type=str, help="Id or code to the folder to be downloaded") exclusive_group.add_argument("--download", "-d", type=str, help="Id or code to the folder to be downloaded")
parser.add_argument("--output", "-o", type=str, help="¨Path to the folder to be downloaded")
parser.add_argument("--force", "-fo", action="store_true", help="Overwrite existing files")
# parser.add_argument_group
# parser.add_mutually_exclusive_group
return parser.parse_args() return parser.parse_args()
def init(): def init():
args = opt() args = opt()
# print('args: ', args)
# print(sys.argv)
log_format = "%(asctime)s %(levelname)s: %(message)s" log_format = "%(asctime)s %(levelname)s: %(message)s"
logging.basicConfig(level=getattr(logging, args.log_level.upper()),format=log_format,datefmt="%H:%M:%S",) logging.basicConfig(level=getattr(logging, args.log_level.upper()),format=log_format,datefmt="%H:%M:%S",)
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
@@ -344,7 +372,7 @@ def init():
set_env_var("GOPLOAD_TOKEN", args.token) set_env_var("GOPLOAD_TOKEN", args.token)
else: else:
logger.error("Error: GOPLOAD_TOKEN not found, add GOPLOAD_TOKEN to your environment variables") logger.error("Error: GOPLOAD_TOKEN not found, add GOPLOAD_TOKEN to your environment variables")
sys.exit("Error: GOPLOAD_TOKEN not found, add GOPLOAD_TOKEN to your environment variables") sys.exit()
if not PRIVATE_PARENT_ID: if not PRIVATE_PARENT_ID:
if args.private_parent_id: if args.private_parent_id:
@@ -357,7 +385,12 @@ def init():
set_env_var("GOPLOAD_PRIVATE_PARENT_ID", args.private_parent_id) set_env_var("GOPLOAD_PRIVATE_PARENT_ID", args.private_parent_id)
else: else:
logger.error("Error: GOPLOAD_PRIVATE_PARENT_ID not found, add GOPLOAD_PRIVATE_PARENT_ID to your environment variables") logger.error("Error: GOPLOAD_PRIVATE_PARENT_ID not found, add GOPLOAD_PRIVATE_PARENT_ID to your environment variables")
sys.exit("Error: GOPLOAD_PRIVATE_PARENT_ID not found, add GOPLOAD_PRIVATE_PARENT_ID to your environment variables") sys.exit()
# No params:
if len(sys.argv) == 1:
logger.error("No arguments specified. Use -h for help")
sys.exit("")
# Stats section # Stats section
if args.stats: if args.stats:
@@ -371,13 +404,13 @@ def init():
elif args.file: elif args.file:
if args.folder: if args.folder:
logger.error("Both file and folder specified") logger.error("Both file and folder specified")
sys.exit("Both file and folder specified") sys.exit()
else: else:
upload(args.file, args.folder, args.name, args.parent, args.private, logger) upload(args.file, args.folder, args.name, args.parent, args.private, logger)
elif args.folder: elif args.folder:
if args.file: if args.file:
logger.error("Both file and folder specified") logger.error("Both file and folder specified")
sys.exit("Both file and folder specified") sys.exit()
else: else:
upload(args.file, args.folder, args.name, args.parent, args.private, logger) upload(args.file, args.folder, args.name, args.parent, args.private, logger)
@@ -387,7 +420,7 @@ def init():
# Download section # Download section
elif args.download: elif args.download:
download(args.download, logger) download(args.download, args.output, args.force, logger)
if __name__ == "__main__": if __name__ == "__main__":

24
scripts/build.sh Normal file
View File

@@ -0,0 +1,24 @@
#!/bin/bash
if [ -z "$1" ]; then
echo "Error: No tag provided."
echo "Usage: $0 <tag>"
exit 1
fi
tag=$1
source ~/miniconda3/etc/profile.d/conda.sh
conda activate 310
python -m nuitka --onefile --assume-yes-for-downloads --output-dir=dist --static-libpython=no gofilecli.py
mv dist/gofilecli.bin ./gofilecli
mkdir -p GoFileCLI_linux-arm64
mv ./gofilecli GoFileCLI_linux-arm64/
date=$(date +"%Y%m%d")
tar cvzfp "GoFileCLI_linux-arm64_${date}.tar.gz" GoFileCLI_linux-arm64
gh release upload ${tag} "GoFileCLI_linux-arm64_${date}.tar.gz"
rm -rf GoFileCLI_linux-arm64

63
scripts/install.sh Normal file
View File

@@ -0,0 +1,63 @@
#!/bin/bash
owner="NohamR"
repo="GoFileCLI"
latest_release=$(curl -s https://api.github.com/repos/$owner/$repo/releases/latest)
tag_name=$(echo "$latest_release" | jq -r '.tag_name')
assets=$(echo "$latest_release" | jq -r '.assets[] | .name')
echo "Latest release tag: $tag_name"
OS=$(uname -s | tr '[:upper:]' '[:lower:]')
if [[ "$OS" == "darwin" ]]; then
OS="osx"
fi
ARCH=$(uname -m)
if [[ "$ARCH" == "x86_64" ]]; then
ARCH="x64"
elif [[ "$ARCH" == "aarch64" || "$ARCH" == "arm64" ]]; then
ARCH="arm64"
else
echo "Unsupported architecture: $ARCH"
exit 1
fi
expected_file="GoFileCLI_${OS}-${ARCH}_*.tar.gz"
if [[ "$OS" == "windows" ]]; then
expected_file="GoFileCLI_${OS}-${ARCH}_*.zip"
fi
selected_asset=$(echo "$assets" | grep -E "^GoFileCLI_${OS}-${ARCH}_.*")
if [[ -z "$selected_asset" ]]; then
echo "No matching asset found for OS: $OS, Architecture: $ARCH"
exit 1
fi
echo "Selected asset: $selected_asset"
download_url=$(echo "$latest_release" | jq -r --arg name "$selected_asset" '.assets[] | select(.name == $name) | .browser_download_url')
echo "Downloading $selected_asset from $download_url..."
curl -LO "$download_url"
if [[ ! -f "$selected_asset" ]]; then
echo "Download failed."
exit 1
fi
tar -xzf "$selected_asset"
extracted_dir=$(find . -type d -name "GoFileCLI*" | head -n 1)
if [[ -d "$extracted_dir" ]]; then
sudo mv "$extracted_dir/gofilecli" /usr/local/bin/
chmod +x /usr/local/bin/gofilecli
echo "Installation completed. You can now use 'gofilecli'."
else
echo "Failed to find the extracted directory."
exit 1
fi
rm -rf "$selected_asset" "$extracted_dir"

45
scripts/uninstall.sh Normal file
View File

@@ -0,0 +1,45 @@
#!/bin/bash
BINARY_NAME="gofilecli"
BINARY_PATH=$(which $BINARY_NAME)
if [[ -z "$BINARY_PATH" ]]; then
echo "$BINARY_NAME is not installed or not found in PATH."
exit 1
fi
echo "Found $BINARY_NAME at $BINARY_PATH."
read -p "Are you sure you want to uninstall $BINARY_NAME? [y/N]: " confirm
if [[ "$confirm" != "y" && "$confirm" != "Y" ]]; then
echo "Uninstallation cancelled."
exit 0
fi
sudo rm -f "$BINARY_PATH"
if [[ ! -f "$BINARY_PATH" ]]; then
echo "$BINARY_NAME has been successfully uninstalled."
else
echo "Failed to uninstall $BINARY_NAME."
exit 1
fi
echo "Checking for any leftover files or directories..."
leftovers=$(find /usr/local/bin -name "$BINARY_NAME" 2>/dev/null)
if [[ -n "$leftovers" ]]; then
echo "Found leftover files:"
echo "$leftovers"
read -p "Do you want to remove these leftover files? [y/N]: " cleanup_confirm
if [[ "$cleanup_confirm" == "y" || "$cleanup_confirm" == "Y" ]]; then
sudo rm -rf $leftovers
echo "Leftover files removed."
else
echo "Leftover files not removed."
fi
fi
echo "Uninstallation complete."