morgan_chester 4 rokov pred
commit
b6c7f668b1

+ 3 - 0
.gitignore

@@ -0,0 +1,3 @@
+vendor/
+.idea/
+/composer.lock

+ 31 - 0
composer.json

@@ -0,0 +1,31 @@
+{
+  "name": "subbclub/autobackuper",
+  "type": "library",
+  "description": "Script to backup to the usual Yandex Disk",
+  "keywords": [
+    "yandex",
+    "disk",
+    "backup"
+  ],
+  "homepage": "https://subbclub.ru",
+  "license": "MIT",
+  "version": "0.0.1",
+  "authors": [
+    {
+      "name": "Gregory Krassilnikov",
+      "email": "[email protected]",
+      "homepage": "https://subbclub.ru",
+      "role": "Developer"
+    }
+  ],
+  "prefer-stable": true,
+  "autoload": {
+    "psr-4": {
+      "Subbclub\\AutoBackup\\": "subbclub/src/AutoBackup"
+    }
+  },
+  "require": {
+    "nategood/httpful": "*",
+    "ext-curl": "*"
+  }
+}

+ 2 - 0
init.php

@@ -0,0 +1,2 @@
+<?php
+

+ 37 - 0
packages.json

@@ -0,0 +1,37 @@
+{
+  "packages": {
+    "subbclub/autobackuper": {
+      "0.0.1": {
+        "name": "subbclub/autobackuper",
+        "type": "library",
+        "description": "Script to backup to the usual Yandex Disk",
+        "keywords": [
+          "yandex",
+          "disk",
+          "backup"
+        ],
+        "homepage": "https://subbclub.ru",
+        "license": "MIT",
+        "version": "0.0.1",
+        "authors": [
+          {
+            "name": "Gregory Krassilnikov",
+            "email": "[email protected]",
+            "homepage": "http://subbclub.ru",
+            "role": "Developer"
+          }
+        ],
+        "prefer-stable": true,
+        "autoload": {
+          "psr-4": {
+            "Subbclub\\AutoBackup\\": "subbclub/src/AutoBackup"
+          }
+        },
+        "require": {
+          "nategood/httpful": "*",
+          "ext-curl": "*"
+        }
+      }
+    }
+  }
+}

+ 38 - 0
subbclub/examples/yandex.php

@@ -0,0 +1,38 @@
+<?php
+
+use AutoBackup\Exception\ProviderException;
+use AutoBackup\ProviderOptions;
+use AutoBackup\Providers\Yandex;
+
+require_once "vendor/autoload.php";
+
+/** Configuration */
+
+$directoryWithFilesMaskToScan = "/home/bitrix/www/bitrix/backup/*.tar.*";
+$baseRemoteDirectoryPath = "/backups/";
+$token = "";
+
+
+$FILES_CMD = "ls $directoryWithFilesMaskToScan";
+$result = shell_exec($FILES_CMD);
+$arrayFiles = explode("\n", $result);
+
+$resultFiles = [];
+foreach ($arrayFiles as $index => $arrayFile) {
+    if (!empty($arrayFile)) {
+        $resultFiles[] = $arrayFile;
+    }
+}
+
+$options = new ProviderOptions\Yandex();
+$options->token = $token;
+$options->remoteDirectoryPath = $baseRemoteDirectoryPath;
+$options->fileWebPath = "https://your.site.there/backups/there/";
+
+$yandexProvider = new Yandex($options);
+
+try {
+    $yandexProvider->proceedBackup($resultFiles);
+} catch (ProviderException $e) {
+    echo $e->getMessage();
+}

+ 10 - 0
subbclub/src/AutoBackup/BaseConnect.php

@@ -0,0 +1,10 @@
+<?php
+
+
+namespace AutoBackup;
+
+
+class BaseConnect
+{
+
+}

+ 11 - 0
subbclub/src/AutoBackup/Exception/OptionsException.php

@@ -0,0 +1,11 @@
+<?php
+
+
+namespace AutoBackup\Exception;
+
+use Exception;
+
+class OptionsException extends Exception
+{
+
+}

+ 12 - 0
subbclub/src/AutoBackup/Exception/ProviderException.php

@@ -0,0 +1,12 @@
+<?php
+
+
+namespace AutoBackup\Exception;
+
+
+use Exception;
+
+class ProviderException extends Exception
+{
+
+}

+ 33 - 0
subbclub/src/AutoBackup/ProviderOptions.php

@@ -0,0 +1,33 @@
+<?php
+
+
+namespace AutoBackup;
+
+use AutoBackup\Exception\OptionsException;
+
+abstract class ProviderOptions
+{
+    private array $options;
+
+    /**
+     * @param string $name
+     * @param mixed $value
+     */
+    public function __set(string $name, $value)
+    {
+        $this->options[$name] = $value;
+    }
+
+    /**
+     * @param string $name
+     * @return mixed
+     * @throws OptionsException
+     */
+    public function __get(string $name)
+    {
+        if (!isset($this->options[$name])) {
+            throw new OptionsException("No option $name provided");
+        }
+        return $this->options[$name];
+    }
+}

+ 52 - 0
subbclub/src/AutoBackup/ProviderOptions/Yandex.php

@@ -0,0 +1,52 @@
+<?php
+
+
+namespace AutoBackup\ProviderOptions;
+
+
+use AutoBackup\ProviderOptions;
+
+class Yandex extends ProviderOptions
+{
+    /**
+     * @var string
+     */
+    public string $token;
+    /**
+     * @var string
+     */
+    public string $remoteDirectoryPath;
+    /**
+     * @var string
+     */
+    public string $fileWebPath;
+    /**
+     * @var bool
+     */
+    public bool $consoleOutput = false;
+    /**
+     * @var string
+     */
+    public string $proxyServer;
+
+    /**
+     * @var int
+     */
+    public int $proxyPort;
+
+    /**
+     * @var bool
+     */
+    public bool $useProxy = false;
+
+    /**
+     * @var string
+     */
+    public string $proxyUser;
+
+    /**
+     * @var string
+     */
+    public string $proxyPass;
+
+}

+ 195 - 0
subbclub/src/AutoBackup/Providers/Yandex.php

@@ -0,0 +1,195 @@
+<?php
+
+namespace AutoBackup\Providers;
+
+use AutoBackup\BaseConnect;
+use AutoBackup\Exception\ProviderException;
+use AutoBackup\ProviderOptions;
+use Exception;
+use Httpful\Exception\ConnectionErrorException;
+use Httpful\Mime;
+use Httpful\Request;
+
+class Yandex extends BaseConnect
+{
+    private string $token;
+    private string $remoteDirectoryPath;
+    private string $proxyServer;
+    private int $proxyPort;
+    private bool $consoleOutput;
+    /**
+     * @var string
+     */
+    private string $fileWebPath;
+    private array $logOutput;
+    private bool $useProxy;
+    private string $proxyUser;
+    private string $proxyPass;
+
+    function __construct(ProviderOptions\Yandex $options)
+    {
+        $this->token = $options->token;
+        $this->remoteDirectoryPath = $options->remoteDirectoryPath;
+        $this->fileWebPath = $options->fileWebPath;
+        $this->consoleOutput = $options->consoleOutput;
+
+        $this->useProxy = $options->useProxy;
+
+        if ($this->useProxy) {
+            $this->proxyServer = $options->proxyServer;
+            $this->proxyPort = $options->proxyPort;
+
+            if (!empty($options->proxyUser)) {
+                $this->proxyUser = $options->proxyUser;
+                $this->proxyPass = $options->proxyPass;
+            }
+        }
+    }
+
+    private function stdOutput($stage, $message)
+    {
+        switch ($this->consoleOutput) {
+            case true:
+                echo date("d.m.Y H:i:s") . " " . $stage . ": " . $message . "\n";
+                break;
+            case false:
+                $this->logOutput[] = [
+                    "date" => date("c"),
+                    "stage" => $stage,
+                    "message" => $message
+                ];
+
+                break;
+        }
+    }
+
+    /**
+     * @param Request $request
+     */
+    private function setCommonRequestParams(Request &$request)
+    {
+        $token = $this->token;
+        $request->mime(Mime::JSON);
+        $request->expects(Mime::JSON);
+        $request->addHeader("Authorization", "OAuth $token");
+
+        if ($this->useProxy) {
+            if (isset($this->proxyUser)) {
+                $request->useProxy($this->proxyServer, $this->proxyPort, $this->proxyUser, $this->proxyPass);
+            } else {
+                $request->useProxy($this->proxyServer, $this->proxyPort);
+            }
+        }
+    }
+
+
+    /**
+     * @param array $resultFiles
+     * @throws ProviderException
+     */
+    public function proceedBackup(array $resultFiles)
+    {
+
+
+        $baseRemoteDirectoryPath = $this->remoteDirectoryPath;
+        $fileWebPath = rtrim($this->fileWebPath, '/');
+
+        if (!empty($resultFiles)) {
+
+            $dirName = $baseRemoteDirectoryPath . date('Y-m-d');
+
+            $createRemoteDirRequest = Request::put("https://cloud-api.yandex.net/v1/disk/resources?path=$dirName");
+            $this->setCommonRequestParams($createRemoteDirRequest);
+
+            try {
+                $response_dir = $createRemoteDirRequest->send();
+
+                $this->stdOutput("remote dir", "dir $dirName created");
+                $this->stdOutput("remote dir", $response_dir->code);
+            } catch (ConnectionErrorException $e) {
+                $this->stdOutput("remote dir", "failed call to create directory");
+                throw new ProviderException("Unable to proceed createRemoteDir request");
+            }
+
+            foreach ($resultFiles as &$resultFile) {
+                $resultFileNameExploded = explode("/", $resultFile);
+                $resultFileName = end($resultFileNameExploded);
+
+                $url = "$fileWebPath/$resultFileName";
+
+                $path = "disk:$dirName/$resultFileName";
+                $this->stdOutput("file upload", $resultFile . " > " . $path);
+                $pathEncoded = urlencode($path);
+                $urlEncoded = urlencode($url);
+
+                $checkFileUploadedPreviouslyRequest = Request::get("https://cloud-api.yandex.net/v1/disk/resources?path=$pathEncoded");
+                $this->setCommonRequestParams($checkFileUploadedPreviouslyRequest);
+
+                try {
+                    $responseCheck = $checkFileUploadedPreviouslyRequest->send();
+                    $fileMd5 = md5_file($resultFile, false);
+                    if ($responseCheck->code != 404) {
+                        if ($fileMd5 == $responseCheck->body->md5) {
+                            $this->stdOutput("file upload", "uploaded previously");
+                            continue;
+                        }
+                    }
+
+                } catch (ConnectionErrorException $e) {
+                    $resultFiles[] = $resultFile;
+                    $this->stdOutput("file upload", "file $resultFile will be proceeded again later");
+                    $this->stdOutput("file upload", $e->getMessage());
+                }
+
+
+                $remoteUploadRequest = Request::post("https://cloud-api.yandex.net/v1/disk/resources/upload?url=$urlEncoded&path=$pathEncoded");
+                $this->setCommonRequestParams($remoteUploadRequest);
+
+                try {
+                    $responseStart = $remoteUploadRequest->send();
+
+                    if ((string)$responseStart->code == "202") {
+                        if ($responseStart->body) {
+                            if ($responseStart->body->href) {
+
+                                $status = "in-progress";
+                                while (!in_array($status, ["success", "failed"])) {
+                                    try {
+                                        $checkCurrentUploadStateRequest = Request::get($responseStart->body->href);
+                                        $this->setCommonRequestParams($checkCurrentUploadStateRequest);
+                                        $responseStatus = $checkCurrentUploadStateRequest->send();
+                                        $status = $responseStatus->body->status;
+
+                                        $this->stdOutput("file upload", $status);
+
+                                        if (in_array($status, ["success"])) {
+                                            break;
+                                        }
+                                        if (in_array($status, ["failed"])) {
+                                            $this->stdOutput("file upload", $responseStatus->code);
+                                            $resultFiles[] = $resultFile;
+                                            $this->stdOutput("file upload", "file $resultFile will be proceeded again later");
+
+                                            break;
+                                        }
+                                    } catch (Exception $e) {
+                                        $this->stdOutput("file upload", "file $resultFile check failed");
+                                        $this->stdOutput("file upload", $e->getMessage());
+                                    }
+
+
+                                    sleep(3);
+                                }
+                            }
+                        }
+                    }
+                } catch (Exception $e) {
+                    $resultFiles[] = $resultFile;
+                    $this->stdOutput("file upload", "file $resultFile will be proceeded again later");
+                    $this->stdOutput("file upload", $e->getMessage());
+                }
+            }
+        }
+    }
+}
+