Skip to content

Commit

Permalink
Merge pull request #26 from andrey18106/dev
Browse files Browse the repository at this point in the history
MediaDC v0.1.7
  • Loading branch information
andrey18106 authored Oct 30, 2021
2 parents 665b717 + 64c1ceb commit 4e94dc5
Show file tree
Hide file tree
Showing 25 changed files with 360 additions and 204 deletions.
5 changes: 3 additions & 2 deletions .github/ISSUE_TEMPLATE/bug_report.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,8 @@ A clear and concise description of what you expected to happen.
If applicable, add screenshots to help explain your problem.

**Desktop (please complete the following information):**
- OS: [e.g. iOS]
- OS [e.g. iOS]
- CPU (architecture)
- Browser [e.g. chrome, safari]
- Nextcloud version [e.g. 22]
- Database configuration (without sensitive information)
Expand All @@ -29,7 +30,7 @@ If applicable, add screenshots to help explain your problem.

**Smartphone (please complete the following information):**
- Device: [e.g. iPhone6]
- OS: [e.g. iOS8.1]
- OS: [e.g. iOS 8.1]
- Browser [e.g. stock browser, safari]
- Nextcloud version [e.g. 22]
- MediaDC version [e.g. 0.1.0]
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/static-analysis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ name: Static analysis

on:
pull_request:
branches: [main, test, dev]
branches: [main, dev]
types: [opened, reopened, edited]
push:
branches: [dev]
Expand Down Expand Up @@ -37,7 +37,7 @@ jobs:
runs-on: ubuntu-latest
strategy:
matrix:
php-versions: [7.4, 8.0]
php-versions: [7.3, 7.4, 8.0]
steps:
- uses: actions/checkout@v2

Expand Down
16 changes: 16 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,22 @@

All notable changes to this project will be documented in this file.

## [0.1.7 - 2021-10-30]

### Added

- Added php `exec` function availability check

### Changed

- Changed missed PHP version requirement from 7.4 to 7.3
- Moved MediaDC admin settings from Groupware tab to separate Administrator menu item
- Changed server errors messages and moved them to the Congiguration page

### Fixed

- Fixed Python version validation fails

## [0.1.6 - 2021-10-22]

### Added
Expand Down
3 changes: 3 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@
![build](https://github.com/andrey18106/mediadc/actions/workflows/create-release-draft.yml/badge.svg)
![static-analysis](https://github.com/andrey18106/mediadc/actions/workflows/static-analysis.yml/badge.svg)

[![Github All Releases](https://img.shields.io/github/downloads/andrey18106/mediadc/total.svg)](https://github.com/andrey18106/mediadc/releases)


**📸📹 Collect photo and video duplicates to save your cloud storage space**

![Home page](/screenshots/task-managment.png)
Expand Down
9 changes: 6 additions & 3 deletions appinfo/info.xml
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@
<summary>Nextcloud Media Duplicate Collector application</summary>
<description>
<![CDATA[
**Python 3.6.8 or higher required**
This app allows to find duplicate or similar 📸📹 photos and videos
* **Many image formats supported** Jpeg, png, tiff, bmp, gif, heic/hif, cr2 and others.
* **Large amount of supported video formats** All that is supported by ffmpeg.
Expand All @@ -17,7 +20,7 @@ This app allows to find duplicate or similar 📸📹 photos and videos
Quick start guide and further information in our [Wiki](https://github.com/andrey18106/mediadc/wiki).
]]>
</description>
<version>0.1.6</version>
<version>0.1.7</version>
<licence>agpl</licence>
<author mail="[email protected]" homepage="https://github.com/andrey18106">Andrey Borysenko</author>
<author mail="[email protected]" homepage="https://github.com/bigcat88">Alexander Piskun</author>
Expand All @@ -36,11 +39,11 @@ Quick start guide and further information in our [Wiki](https://github.com/andre
<screenshot>https://raw.githubusercontent.com/andrey18106/mediadc/main/screenshots/admin-config.png</screenshot>
<dependencies>
<nextcloud min-version="21" max-version="22" />
<php min-version="7.4" />
<python min-version="3.6.8" />
<php min-version="7.3" />
</dependencies>
<settings>
<admin>OCA\MediaDC\Settings\AdminSettings</admin>
<admin-section>OCA\MediaDC\Settings\AdminSection</admin-section>
</settings>
<repair-steps>
<install>
Expand Down
1 change: 1 addition & 0 deletions appinfo/routes.php
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
<?php
/**
* @copyright 2021 Andrey Borysenko <[email protected]>
*
* @copyright 2021 Alexander Piskun <[email protected]>
*
* @author Andrey Borysenko <[email protected]>
Expand Down
2 changes: 2 additions & 0 deletions img/settings.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 2 additions & 2 deletions js/mediadc-dashboard.js

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion js/mediadc-dashboard.js.map

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions js/mediadc-main.js

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion js/mediadc-main.js.LICENSE.txt
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@
*/

/*!
* vue-router v3.5.2
* vue-router v3.5.3
* (c) 2021 Evan You
* @license MIT
*/
Expand Down
2 changes: 1 addition & 1 deletion js/mediadc-main.js.map

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions js/mediadc-settings.js

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion js/mediadc-settings.js.map

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions js/mediadc-src_views_Configuration_vue.js

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion js/mediadc-src_views_Configuration_vue.js.map

Large diffs are not rendered by default.

149 changes: 105 additions & 44 deletions lib/Service/PythonService.php
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,10 @@
use OCA\MediaDC\AppInfo\Application;
use OCA\MediaDC\Db\Setting;
use OCA\MediaDC\Db\SettingMapper;
use OCA\MediaDC\Exception\PythonNotValidException;

use OCP\IConfig;
use Psr\Log\LoggerInterface;
use bantu\IniGetWrapper\IniGetWrapper;


class PythonService {
Expand All @@ -46,16 +48,17 @@ class PythonService {
/** @var IConfig */
private $config;

public function __construct(SettingMapper $settingMapper, IConfig $config)
/** @var LoggerInterface */
private $logger;

public function __construct(SettingMapper $settingMapper, IConfig $config, LoggerInterface $logger)
{
$this->config = $config;
$this->logger = $logger;
/** @var Setting */
$pythonCommand = $settingMapper->findByName('python_command');
$this->pythonCommand = $pythonCommand->getValue();
$this->cwd = $this->getCustomAppsDirectory() . Application::APP_ID . '/lib/Service/python';
if (!$this->isPythonCompatible()) {
throw new PythonNotValidException("Python version is lower then 3.6.8 or not available");
}
}

/**
Expand Down Expand Up @@ -119,38 +122,62 @@ static function scriptEnvsCallback($key, $value) {
return "$key=\"$value\" ";
}

/**
* Check server requirements
*
* @return array check results with errors list
*/
private function checkDepsRequirements() {
$errors = [];
if (!$this->isFunctionEnabled('exec')) {
array_push($errors, '`exec` PHP function is not available.');
}
if (!$this->isPythonCompatible()) {
array_push($errors, 'Python version is lower then 3.6.8 or not available');
}
return ['success' => count($errors) === 0, 'errors' => $errors];
}

/**
* @param string @listName
*
* @return array installation results list
*/
public function installDependencies($listName = '') {
try {
$pythonResult = $this->run('/install.py', [
'--install' => $listName === '' ? 'required optional' : $listName,
], false, ['PHP_PATH' => $this->getPhpInterpreter()]);
return $this->parsePythonOutput($pythonResult);
} catch (\Exception $e) {
return [
'success' => false,
'message' => 'Some error while running the Python script',
];
$depsCheck = $this->checkDepsRequirements();
if ($depsCheck['success']) {
try {
$pythonResult = $this->run('/install.py', [
'--install' => $listName === '' ? 'required optional' : $listName,
], false, ['PHP_PATH' => $this->getPhpInterpreter()]);
return $this->parsePythonOutput($pythonResult);
} catch (\Exception $e) {
return [
'success' => false,
'message' => 'Some error while running the Python script',
];
}
}
return $depsCheck;
}

/**
* @return array list of uninstalled Python packages
*/
public function checkInstallation() {
try {
$pythonResult = $this->run('/install.py', ['--check' => ''], false, ['PHP_PATH' => $this->getPhpInterpreter()]);
return $this->parsePythonOutput($pythonResult);
} catch (\Exception $e) {
return [
'success' => false,
'message' => 'Some error while running the Python script',
];
$depsCheck = $this->checkDepsRequirements();
if ($depsCheck['success']) {
try {
$pythonResult = $this->run('/install.py', ['--check' => ''], false, ['PHP_PATH' => $this->getPhpInterpreter()]);
return $this->parsePythonOutput($pythonResult);
} catch (\Exception $e) {
return [
'success' => false,
'message' => 'Some error while running the Python script',
];
}
}
return $depsCheck;
}

/**
Expand All @@ -159,15 +186,19 @@ public function checkInstallation() {
* @return array installed packages list after deleting
*/
public function deleteDependencies($packagesList = []) {
try {
$pythonResult = $this->run('/install.py', ['--delete' => join(" ", $packagesList)], false, ['PHP_PATH' => $this->getPhpInterpreter()]);
return $this->parsePythonOutput($pythonResult);
} catch (\Exception $e) {
return [
'success' => false,
'message' => 'Some error while running the Python script',
];
$depsCheck = $this->checkDepsRequirements();
if ($depsCheck['success']) {
try {
$pythonResult = $this->run('/install.py', ['--delete' => join(" ", $packagesList)], false, ['PHP_PATH' => $this->getPhpInterpreter()]);
return $this->parsePythonOutput($pythonResult);
} catch (\Exception $e) {
return [
'success' => false,
'message' => 'Some error while running the Python script',
];
}
}
return $depsCheck;
}

/**
Expand All @@ -176,27 +207,31 @@ public function deleteDependencies($packagesList = []) {
* @return array installed packages list after deleting
*/
public function updateDependencies($packagesList = []) {
try {
$pythonResult = $this->run('/install.py', ['--update' => join(" ", $packagesList)], false, ['PHP_PATH' => $this->getPhpInterpreter()]);
return $this->parsePythonOutput($pythonResult);
} catch (\Exception $e) {
return [
'success' => false,
'message' => 'Some error while running the Python script',
];
$depsCheck = $this->checkDepsRequirements();
if ($depsCheck['success']) {
try {
$pythonResult = $this->run('/install.py', ['--update' => join(" ", $packagesList)], false, ['PHP_PATH' => $this->getPhpInterpreter()]);
return $this->parsePythonOutput($pythonResult);
} catch (\Exception $e) {
return [
'success' => false,
'message' => 'Some error while running the Python script',
];
}
}
return $depsCheck;
}

/**
* @return string|null
*/
public function getPythonVersion() {
exec($this->pythonCommand . ' --version', $output);
if (preg_match_all("/\d{1}\.\d{1,2}(\.\d{1,2}){0,1}/s", $output[0], $matches)) {
return $matches[0][0];
} else {
return null;
exec($this->pythonCommand . ' --version', $output, $result_code);
if ($result_code === 0 && isset($output[0]) && preg_match_all("/\d{1}\.\d{1,2}(\.\d{1,2}){0,1}/s", $output[0], $matches)) {
return isset($matches[0][0]) ? $matches[0][0] : null;
}
$this->logger->error('[' . self::class . '] Command executed with error result_code: ' . $result_code);
return null;
}

/**
Expand Down Expand Up @@ -345,4 +380,30 @@ private function getCustomAppsDirectory() {
return getcwd() . '/apps/';
}

/**
* Check if a php function available
*
* @param string $function_name
*
* @return bool
*/
private function isFunctionEnabled($function_name) {
if (!function_exists($function_name)) {
return false;
}
/** @var IniGetWrapper $ini */
$ini = \OC::$server->get(IniGetWrapper::class);
$disabled = explode(',', $ini->get('disable_functions') ?: '');
$disabled = array_map('trim', $disabled);
if (in_array($function_name, $disabled)) {
return false;
}
$disabled = explode(',', $ini->get('suhosin.executor.func.blacklist') ?: '');
$disabled = array_map('trim', $disabled);
if (in_array($function_name, $disabled)) {
return false;
}
return true;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -26,10 +26,43 @@
*
*/

namespace OCA\MediaDC\Exception;
namespace OCA\MediaDC\Settings;

use Exception;
use OC\URLGenerator;
use OCA\MediaDC\AppInfo\Application;
use OCP\IL10N;
use OCP\Settings\IIconSection;


class PythonNotValidException extends Exception {
class AdminSection implements IIconSection {

/** @var IL10N */
private $l;

/** @var UrlGenerator */
private $urlGenerator;

public function __construct(IL10N $l, URLGenerator $urlGenerator)
{
$this->l = $l;
$this->urlGenerator = $urlGenerator;
}

public function getId() {
return Application::APP_ID;
}

public function getName() {
return $this->l->t('MediaDC');
}

public function getPriority()
{
return 50;
}

public function getIcon() {
return $this->urlGenerator->imagePath(Application::APP_ID, 'settings.svg');
}

}
Loading

0 comments on commit 4e94dc5

Please sign in to comment.