Passed
Push — master ( f5c4f5...fd473f )
by Joas
18:20 queued 13s
created

SpeechToTextManager   A

Complexity

Total Complexity 15

Size/Duplication

Total Lines 76
Duplicated Lines 0 %

Importance

Changes 6
Bugs 1 Features 0
Metric Value
eloc 38
dl 0
loc 76
rs 10
c 6
b 1
f 0
wmc 15

5 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 6 1
A getProviders() 0 24 5
A transcribeFile() 0 14 4
A scheduleFileTranscription() 0 13 3
A hasProviders() 0 6 2
1
<?php
2
3
declare(strict_types=1);
4
5
/**
6
 * @copyright Copyright (c) 2023 Julius Härtl <[email protected]>
7
 * @copyright Copyright (c) 2023 Marcel Klehr <[email protected]>
8
 *
9
 * @author Julius Härtl <[email protected]>
10
 * @author Marcel Klehr <[email protected]>
11
 *
12
 * @license GNU AGPL version 3 or any later version
13
 *
14
 * This program is free software: you can redistribute it and/or modify
15
 * it under the terms of the GNU Affero General Public License as
16
 * published by the Free Software Foundation, either version 3 of the
17
 * License, or (at your option) any later version.
18
 *
19
 * This program is distributed in the hope that it will be useful,
20
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22
 * GNU Affero General Public License for more details.
23
 *
24
 * You should have received a copy of the GNU Affero General Public License
25
 * along with this program. If not, see <http://www.gnu.org/licenses/>.
26
 */
27
28
29
namespace OC\SpeechToText;
30
31
use InvalidArgumentException;
32
use OC\AppFramework\Bootstrap\Coordinator;
33
use OCP\BackgroundJob\IJobList;
34
use OCP\Files\File;
35
use OCP\Files\InvalidPathException;
36
use OCP\Files\NotFoundException;
37
use OCP\IServerContainer;
38
use OCP\PreConditionNotMetException;
39
use OCP\SpeechToText\ISpeechToTextManager;
40
use OCP\SpeechToText\ISpeechToTextProvider;
41
use Psr\Container\ContainerExceptionInterface;
42
use Psr\Container\NotFoundExceptionInterface;
43
use Psr\Log\LoggerInterface;
44
use RuntimeException;
45
use Throwable;
46
47
class SpeechToTextManager implements ISpeechToTextManager {
48
	/** @var ?ISpeechToTextProvider[] */
49
	private ?array $providers = null;
50
51
	public function __construct(
52
		private IServerContainer $serverContainer,
53
		private Coordinator $coordinator,
54
		private LoggerInterface $logger,
55
		private IJobList $jobList,
56
	) {
57
	}
58
59
	public function getProviders(): array {
60
		$context = $this->coordinator->getRegistrationContext();
61
		if ($context === null) {
62
			return [];
63
		}
64
65
		if ($this->providers !== null) {
66
			return $this->providers;
67
		}
68
69
		$this->providers = [];
70
71
		foreach ($context->getSpeechToTextProviders() as $providerServiceRegistration) {
72
			$class = $providerServiceRegistration->getService();
73
			try {
74
				$this->providers[$class] = $this->serverContainer->get($class);
75
			} catch (NotFoundExceptionInterface|ContainerExceptionInterface|Throwable $e) {
76
				$this->logger->error('Failed to load SpeechToText provider ' . $class, [
77
					'exception' => $e,
78
				]);
79
			}
80
		}
81
82
		return $this->providers;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this->providers returns the type null which is incompatible with the type-hinted return array.
Loading history...
83
	}
84
85
	public function hasProviders(): bool {
86
		$context = $this->coordinator->getRegistrationContext();
87
		if ($context === null) {
88
			return false;
89
		}
90
		return !empty($context->getSpeechToTextProviders());
91
	}
92
93
	public function scheduleFileTranscription(File $file, ?string $userId, string $appId): void {
94
		if (!$this->hasProviders()) {
95
			throw new PreConditionNotMetException('No SpeechToText providers have been registered');
96
		}
97
		try {
98
			$this->jobList->add(TranscriptionJob::class, [
99
				'fileId' => $file->getId(),
100
				'owner' => $file->getOwner()->getUID(),
101
				'userId' => $userId,
102
				'appId' => $appId,
103
			]);
104
		} catch (NotFoundException|InvalidPathException $e) {
105
			throw new InvalidArgumentException('Invalid file provided for file transcription: ' . $e->getMessage());
106
		}
107
	}
108
109
	public function transcribeFile(File $file): string {
110
		if (!$this->hasProviders()) {
111
			throw new PreConditionNotMetException('No SpeechToText providers have been registered');
112
		}
113
114
		foreach ($this->getProviders() as $provider) {
115
			try {
116
				return $provider->transcribeFile($file);
117
			} catch (\Throwable $e) {
118
				$this->logger->info('SpeechToText transcription using provider ' . $provider->getName() . ' failed', ['exception' => $e]);
119
			}
120
		}
121
122
		throw new RuntimeException('Could not transcribe file');
123
	}
124
}
125