Browse Source

feat: Add endpoints to get and set the live transcription languages

Signed-off-by: Daniel Calviño Sánchez <danxuliu@gmail.com>
pull/15696/head
Daniel Calviño Sánchez 2 months ago
parent
commit
db15bc34a9
  1. 53
      lib/Controller/LiveTranscriptionController.php
  2. 8
      lib/ResponseDefinitions.php
  3. 53
      lib/Service/LiveTranscriptionService.php
  4. 5
      lib/Service/RoomService.php
  5. 329
      openapi-full.json
  6. 329
      openapi.json
  7. 162
      src/types/openapi/openapi-full.ts
  8. 162
      src/types/openapi/openapi.ts

53
lib/Controller/LiveTranscriptionController.php

@ -11,8 +11,10 @@ namespace OCA\Talk\Controller;
use OCA\Talk\Exceptions\LiveTranscriptionAppNotEnabledException;
use OCA\Talk\Middleware\Attribute\RequireCallEnabled;
use OCA\Talk\Middleware\Attribute\RequireModeratorOrNoLobby;
use OCA\Talk\Middleware\Attribute\RequireModeratorParticipant;
use OCA\Talk\Middleware\Attribute\RequireParticipant;
use OCA\Talk\Participant;
use OCA\Talk\ResponseDefinitions;
use OCA\Talk\Service\LiveTranscriptionService;
use OCP\AppFramework\Http;
use OCP\AppFramework\Http\Attribute\ApiRoute;
@ -20,6 +22,9 @@ use OCP\AppFramework\Http\Attribute\PublicPage;
use OCP\AppFramework\Http\DataResponse;
use OCP\IRequest;
/**
* @psalm-import-type TalkLiveTranscriptionLanguage from ResponseDefinitions
*/
class LiveTranscriptionController extends AEnvironmentAwareOCSController {
public function __construct(
string $appName,
@ -97,4 +102,52 @@ class LiveTranscriptionController extends AEnvironmentAwareOCSController {
return new DataResponse(null);
}
/**
* Get available languages for live transcriptions
*
* @return DataResponse<Http::STATUS_OK, array<string, TalkLiveTranscriptionLanguage>, array{}>|DataResponse<Http::STATUS_BAD_REQUEST, array{error: 'app'}, array{}>
*
* 200: Available languages got successfully
* 400: The external app "live_transcription" is not available
*/
#[PublicPage]
#[ApiRoute(verb: 'GET', url: '/api/{apiVersion}/live-transcription/languages', requirements: [
'apiVersion' => '(v1)',
])]
public function getAvailableLanguages(): DataResponse {
try {
$languages = $this->liveTranscriptionService->getAvailableLanguages();
} catch (LiveTranscriptionAppNotEnabledException $e) {
return new DataResponse(['error' => 'app'], Http::STATUS_BAD_REQUEST);
}
return new DataResponse($languages);
}
/**
* Set language for live transcriptions
*
* @param string $languageId the ID of the language to set
* @return DataResponse<Http::STATUS_OK, null, array{}>|DataResponse<Http::STATUS_BAD_REQUEST|Http::STATUS_FORBIDDEN, array{error: 'app'}, array{}>
*
* 200: Language set successfully
* 400: The external app "live_transcription" is not available
* 403: Participant is not a moderator
*/
#[PublicPage]
#[RequireModeratorParticipant]
#[ApiRoute(verb: 'POST', url: '/api/{apiVersion}/live-transcription/{token}/language', requirements: [
'apiVersion' => '(v1)',
'token' => '[a-z0-9]{4,30}',
])]
public function setLanguage(string $languageId): DataResponse {
try {
$this->liveTranscriptionService->setLanguage($this->room, $languageId);
} catch (LiveTranscriptionAppNotEnabledException $e) {
return new DataResponse(['error' => 'app'], Http::STATUS_BAD_REQUEST);
}
return new DataResponse(null);
}
}

8
lib/ResponseDefinitions.php

@ -534,6 +534,14 @@ namespace OCA\Talk;
* config-local: array<string, non-empty-list<string>>,
* version: string,
* }
*
* @psalm-type TalkLiveTranscriptionLanguage = array{
* name: string,
* metadata: array{
* separator: string,
* rtl: bool,
* },
* }
*/
class ResponseDefinitions {
}

53
lib/Service/LiveTranscriptionService.php

@ -27,6 +27,7 @@ class LiveTranscriptionService {
private ?string $userId,
private IAppManager $appManager,
private IUserManager $userManager,
private RoomService $roomService,
protected LoggerInterface $logger,
) {
}
@ -114,6 +115,58 @@ class LiveTranscriptionService {
$this->requestToExAppLiveTranscription('POST', '/api/v1/call/transcribe', $parameters);
}
/**
* @throws LiveTranscriptionAppNotEnabledException if the external app
* "live_transcription" is
* not enabled.
* @throws LiveTranscriptionAppAPIException if the request could not be sent
* to the app or the response could
* not be processed.
* @throws LiveTranscriptionAppResponseException if the request itself
* succeeded but the app
* responded with an error.
*/
public function getAvailableLanguages(): array {
$languages = $this->requestToExAppLiveTranscription('GET', '/api/v1/languages');
if ($languages === null) {
$this->logger->error('Request to live_transcription (ExApp) failed: list of available languages is null');
throw new LiveTranscriptionAppAPIException('response-null-language-list');
}
return $languages;
}
/**
* @throws LiveTranscriptionAppNotEnabledException if the external app
* "live_transcription" is
* not enabled.
* @throws LiveTranscriptionAppAPIException if the request could not be sent
* to the app or the response could
* not be processed.
* @throws LiveTranscriptionAppResponseException if the request itself
* succeeded but the app
* responded with an error.
*/
public function setLanguage(Room $room, string $languageId): void {
$parameters = [
'roomToken' => $room->getToken(),
'langId' => ! empty($languageId) ? $languageId : 'es',
];
try {
$this->requestToExAppLiveTranscription('POST', '/api/v1/call/set-language', $parameters);
} catch (LiveTranscriptionAppResponseException $e) {
// If there is no active transcription continue setting the language
// in the room. In any other case, abort.
if ($e->getResponse()->getStatusCode() !== 404) {
throw $e;
}
}
$this->roomService->setLiveTranscriptionLanguageId($room, $languageId);
}
/**
* @throws LiveTranscriptionAppNotEnabledException if the external app
* "live_transcription" is

5
lib/Service/RoomService.php

@ -852,6 +852,11 @@ class RoomService {
* Set the ID of the language to use for live transcriptions in the given
* room.
*
* This method is not meant to be directly used; use
* "LiveTranscriptionService::setLanguage" instead, which only sets the
* language in the room if the external app is available and the language is
* valid.
*
* @param Room $room
* @param string $newState ID of the language to set
*/

329
openapi-full.json

@ -1005,6 +1005,33 @@
}
}
},
"LiveTranscriptionLanguage": {
"type": "object",
"required": [
"name",
"metadata"
],
"properties": {
"name": {
"type": "string"
},
"metadata": {
"type": "object",
"required": [
"separator",
"rtl"
],
"properties": {
"separator": {
"type": "string"
},
"rtl": {
"type": "boolean"
}
}
}
}
},
"Matterbridge": {
"type": "object",
"required": [
@ -21129,6 +21156,308 @@
}
}
},
"/ocs/v2.php/apps/spreed/api/{apiVersion}/live-transcription/languages": {
"get": {
"operationId": "live_transcription-get-available-languages",
"summary": "Get available languages for live transcriptions",
"tags": [
"live_transcription"
],
"security": [
{},
{
"bearer_auth": []
},
{
"basic_auth": []
}
],
"parameters": [
{
"name": "apiVersion",
"in": "path",
"required": true,
"schema": {
"type": "string",
"enum": [
"v1"
],
"default": "v1"
}
},
{
"name": "OCS-APIRequest",
"in": "header",
"description": "Required to be true for the API request to pass",
"required": true,
"schema": {
"type": "boolean",
"default": true
}
}
],
"responses": {
"200": {
"description": "Available languages got successfully",
"content": {
"application/json": {
"schema": {
"type": "object",
"required": [
"ocs"
],
"properties": {
"ocs": {
"type": "object",
"required": [
"meta",
"data"
],
"properties": {
"meta": {
"$ref": "#/components/schemas/OCSMeta"
},
"data": {
"type": "object",
"additionalProperties": {
"$ref": "#/components/schemas/LiveTranscriptionLanguage"
}
}
}
}
}
}
}
}
},
"400": {
"description": "The external app \"live_transcription\" is not available",
"content": {
"application/json": {
"schema": {
"type": "object",
"required": [
"ocs"
],
"properties": {
"ocs": {
"type": "object",
"required": [
"meta",
"data"
],
"properties": {
"meta": {
"$ref": "#/components/schemas/OCSMeta"
},
"data": {
"type": "object",
"required": [
"error"
],
"properties": {
"error": {
"type": "string",
"enum": [
"app"
]
}
}
}
}
}
}
}
}
}
}
}
}
},
"/ocs/v2.php/apps/spreed/api/{apiVersion}/live-transcription/{token}/language": {
"post": {
"operationId": "live_transcription-set-language",
"summary": "Set language for live transcriptions",
"tags": [
"live_transcription"
],
"security": [
{},
{
"bearer_auth": []
},
{
"basic_auth": []
}
],
"requestBody": {
"required": true,
"content": {
"application/json": {
"schema": {
"type": "object",
"required": [
"languageId"
],
"properties": {
"languageId": {
"type": "string",
"description": "the ID of the language to set"
}
}
}
}
}
},
"parameters": [
{
"name": "apiVersion",
"in": "path",
"required": true,
"schema": {
"type": "string",
"enum": [
"v1"
],
"default": "v1"
}
},
{
"name": "token",
"in": "path",
"required": true,
"schema": {
"type": "string",
"pattern": "^[a-z0-9]{4,30}$"
}
},
{
"name": "OCS-APIRequest",
"in": "header",
"description": "Required to be true for the API request to pass",
"required": true,
"schema": {
"type": "boolean",
"default": true
}
}
],
"responses": {
"200": {
"description": "Language set successfully",
"content": {
"application/json": {
"schema": {
"type": "object",
"required": [
"ocs"
],
"properties": {
"ocs": {
"type": "object",
"required": [
"meta",
"data"
],
"properties": {
"meta": {
"$ref": "#/components/schemas/OCSMeta"
},
"data": {
"nullable": true
}
}
}
}
}
}
}
},
"400": {
"description": "The external app \"live_transcription\" is not available",
"content": {
"application/json": {
"schema": {
"type": "object",
"required": [
"ocs"
],
"properties": {
"ocs": {
"type": "object",
"required": [
"meta",
"data"
],
"properties": {
"meta": {
"$ref": "#/components/schemas/OCSMeta"
},
"data": {
"type": "object",
"required": [
"error"
],
"properties": {
"error": {
"type": "string",
"enum": [
"app"
]
}
}
}
}
}
}
}
}
}
},
"403": {
"description": "Participant is not a moderator",
"content": {
"application/json": {
"schema": {
"type": "object",
"required": [
"ocs"
],
"properties": {
"ocs": {
"type": "object",
"required": [
"meta",
"data"
],
"properties": {
"meta": {
"$ref": "#/components/schemas/OCSMeta"
},
"data": {
"type": "object",
"required": [
"error"
],
"properties": {
"error": {
"type": "string",
"enum": [
"app"
]
}
}
}
}
}
}
}
}
}
}
}
}
},
"/ocs/v2.php/apps/spreed/api/{apiVersion}/chat/{token}/threads/recent": {
"get": {
"operationId": "thread-get-recent-active-threads",

329
openapi.json

@ -910,6 +910,33 @@
}
}
},
"LiveTranscriptionLanguage": {
"type": "object",
"required": [
"name",
"metadata"
],
"properties": {
"name": {
"type": "string"
},
"metadata": {
"type": "object",
"required": [
"separator",
"rtl"
],
"properties": {
"separator": {
"type": "string"
},
"rtl": {
"type": "boolean"
}
}
}
}
},
"Matterbridge": {
"type": "object",
"required": [
@ -21034,6 +21061,308 @@
}
}
},
"/ocs/v2.php/apps/spreed/api/{apiVersion}/live-transcription/languages": {
"get": {
"operationId": "live_transcription-get-available-languages",
"summary": "Get available languages for live transcriptions",
"tags": [
"live_transcription"
],
"security": [
{},
{
"bearer_auth": []
},
{
"basic_auth": []
}
],
"parameters": [
{
"name": "apiVersion",
"in": "path",
"required": true,
"schema": {
"type": "string",
"enum": [
"v1"
],
"default": "v1"
}
},
{
"name": "OCS-APIRequest",
"in": "header",
"description": "Required to be true for the API request to pass",
"required": true,
"schema": {
"type": "boolean",
"default": true
}
}
],
"responses": {
"200": {
"description": "Available languages got successfully",
"content": {
"application/json": {
"schema": {
"type": "object",
"required": [
"ocs"
],
"properties": {
"ocs": {
"type": "object",
"required": [
"meta",
"data"
],
"properties": {
"meta": {
"$ref": "#/components/schemas/OCSMeta"
},
"data": {
"type": "object",
"additionalProperties": {
"$ref": "#/components/schemas/LiveTranscriptionLanguage"
}
}
}
}
}
}
}
}
},
"400": {
"description": "The external app \"live_transcription\" is not available",
"content": {
"application/json": {
"schema": {
"type": "object",
"required": [
"ocs"
],
"properties": {
"ocs": {
"type": "object",
"required": [
"meta",
"data"
],
"properties": {
"meta": {
"$ref": "#/components/schemas/OCSMeta"
},
"data": {
"type": "object",
"required": [
"error"
],
"properties": {
"error": {
"type": "string",
"enum": [
"app"
]
}
}
}
}
}
}
}
}
}
}
}
}
},
"/ocs/v2.php/apps/spreed/api/{apiVersion}/live-transcription/{token}/language": {
"post": {
"operationId": "live_transcription-set-language",
"summary": "Set language for live transcriptions",
"tags": [
"live_transcription"
],
"security": [
{},
{
"bearer_auth": []
},
{
"basic_auth": []
}
],
"requestBody": {
"required": true,
"content": {
"application/json": {
"schema": {
"type": "object",
"required": [
"languageId"
],
"properties": {
"languageId": {
"type": "string",
"description": "the ID of the language to set"
}
}
}
}
}
},
"parameters": [
{
"name": "apiVersion",
"in": "path",
"required": true,
"schema": {
"type": "string",
"enum": [
"v1"
],
"default": "v1"
}
},
{
"name": "token",
"in": "path",
"required": true,
"schema": {
"type": "string",
"pattern": "^[a-z0-9]{4,30}$"
}
},
{
"name": "OCS-APIRequest",
"in": "header",
"description": "Required to be true for the API request to pass",
"required": true,
"schema": {
"type": "boolean",
"default": true
}
}
],
"responses": {
"200": {
"description": "Language set successfully",
"content": {
"application/json": {
"schema": {
"type": "object",
"required": [
"ocs"
],
"properties": {
"ocs": {
"type": "object",
"required": [
"meta",
"data"
],
"properties": {
"meta": {
"$ref": "#/components/schemas/OCSMeta"
},
"data": {
"nullable": true
}
}
}
}
}
}
}
},
"400": {
"description": "The external app \"live_transcription\" is not available",
"content": {
"application/json": {
"schema": {
"type": "object",
"required": [
"ocs"
],
"properties": {
"ocs": {
"type": "object",
"required": [
"meta",
"data"
],
"properties": {
"meta": {
"$ref": "#/components/schemas/OCSMeta"
},
"data": {
"type": "object",
"required": [
"error"
],
"properties": {
"error": {
"type": "string",
"enum": [
"app"
]
}
}
}
}
}
}
}
}
}
},
"403": {
"description": "Participant is not a moderator",
"content": {
"application/json": {
"schema": {
"type": "object",
"required": [
"ocs"
],
"properties": {
"ocs": {
"type": "object",
"required": [
"meta",
"data"
],
"properties": {
"meta": {
"$ref": "#/components/schemas/OCSMeta"
},
"data": {
"type": "object",
"required": [
"error"
],
"properties": {
"error": {
"type": "string",
"enum": [
"app"
]
}
}
}
}
}
}
}
}
}
}
}
}
},
"/ocs/v2.php/apps/spreed/api/{apiVersion}/chat/{token}/threads/recent": {
"get": {
"operationId": "thread-get-recent-active-threads",

162
src/types/openapi/openapi-full.ts

@ -1611,6 +1611,40 @@ export type paths = {
patch?: never;
trace?: never;
};
"/ocs/v2.php/apps/spreed/api/{apiVersion}/live-transcription/languages": {
parameters: {
query?: never;
header?: never;
path?: never;
cookie?: never;
};
/** Get available languages for live transcriptions */
get: operations["live_transcription-get-available-languages"];
put?: never;
post?: never;
delete?: never;
options?: never;
head?: never;
patch?: never;
trace?: never;
};
"/ocs/v2.php/apps/spreed/api/{apiVersion}/live-transcription/{token}/language": {
parameters: {
query?: never;
header?: never;
path?: never;
cookie?: never;
};
get?: never;
put?: never;
/** Set language for live transcriptions */
post: operations["live_transcription-set-language"];
delete?: never;
options?: never;
head?: never;
patch?: never;
trace?: never;
};
"/ocs/v2.php/apps/spreed/api/{apiVersion}/chat/{token}/threads/recent": {
parameters: {
query?: never;
@ -2483,6 +2517,13 @@ export type components = {
phones?: string[];
teams?: string[];
};
LiveTranscriptionLanguage: {
name: string;
metadata: {
separator: string;
rtl: boolean;
};
};
Matterbridge: {
enabled: boolean;
parts: components["schemas"]["MatterbridgeConfigFields"];
@ -10377,6 +10418,127 @@ export interface operations {
};
};
};
"live_transcription-get-available-languages": {
parameters: {
query?: never;
header: {
/** @description Required to be true for the API request to pass */
"OCS-APIRequest": boolean;
};
path: {
apiVersion: "v1";
};
cookie?: never;
};
requestBody?: never;
responses: {
/** @description Available languages got successfully */
200: {
headers: {
[name: string]: unknown;
};
content: {
"application/json": {
ocs: {
meta: components["schemas"]["OCSMeta"];
data: {
[key: string]: components["schemas"]["LiveTranscriptionLanguage"];
};
};
};
};
};
/** @description The external app "live_transcription" is not available */
400: {
headers: {
[name: string]: unknown;
};
content: {
"application/json": {
ocs: {
meta: components["schemas"]["OCSMeta"];
data: {
/** @enum {string} */
error: "app";
};
};
};
};
};
};
};
"live_transcription-set-language": {
parameters: {
query?: never;
header: {
/** @description Required to be true for the API request to pass */
"OCS-APIRequest": boolean;
};
path: {
apiVersion: "v1";
token: string;
};
cookie?: never;
};
requestBody: {
content: {
"application/json": {
/** @description the ID of the language to set */
languageId: string;
};
};
};
responses: {
/** @description Language set successfully */
200: {
headers: {
[name: string]: unknown;
};
content: {
"application/json": {
ocs: {
meta: components["schemas"]["OCSMeta"];
data: unknown;
};
};
};
};
/** @description The external app "live_transcription" is not available */
400: {
headers: {
[name: string]: unknown;
};
content: {
"application/json": {
ocs: {
meta: components["schemas"]["OCSMeta"];
data: {
/** @enum {string} */
error: "app";
};
};
};
};
};
/** @description Participant is not a moderator */
403: {
headers: {
[name: string]: unknown;
};
content: {
"application/json": {
ocs: {
meta: components["schemas"]["OCSMeta"];
data: {
/** @enum {string} */
error: "app";
};
};
};
};
};
};
};
"thread-get-recent-active-threads": {
parameters: {
query?: {

162
src/types/openapi/openapi.ts

@ -1611,6 +1611,40 @@ export type paths = {
patch?: never;
trace?: never;
};
"/ocs/v2.php/apps/spreed/api/{apiVersion}/live-transcription/languages": {
parameters: {
query?: never;
header?: never;
path?: never;
cookie?: never;
};
/** Get available languages for live transcriptions */
get: operations["live_transcription-get-available-languages"];
put?: never;
post?: never;
delete?: never;
options?: never;
head?: never;
patch?: never;
trace?: never;
};
"/ocs/v2.php/apps/spreed/api/{apiVersion}/live-transcription/{token}/language": {
parameters: {
query?: never;
header?: never;
path?: never;
cookie?: never;
};
get?: never;
put?: never;
/** Set language for live transcriptions */
post: operations["live_transcription-set-language"];
delete?: never;
options?: never;
head?: never;
patch?: never;
trace?: never;
};
"/ocs/v2.php/apps/spreed/api/{apiVersion}/chat/{token}/threads/recent": {
parameters: {
query?: never;
@ -1945,6 +1979,13 @@ export type components = {
phones?: string[];
teams?: string[];
};
LiveTranscriptionLanguage: {
name: string;
metadata: {
separator: string;
rtl: boolean;
};
};
Matterbridge: {
enabled: boolean;
parts: components["schemas"]["MatterbridgeConfigFields"];
@ -9839,6 +9880,127 @@ export interface operations {
};
};
};
"live_transcription-get-available-languages": {
parameters: {
query?: never;
header: {
/** @description Required to be true for the API request to pass */
"OCS-APIRequest": boolean;
};
path: {
apiVersion: "v1";
};
cookie?: never;
};
requestBody?: never;
responses: {
/** @description Available languages got successfully */
200: {
headers: {
[name: string]: unknown;
};
content: {
"application/json": {
ocs: {
meta: components["schemas"]["OCSMeta"];
data: {
[key: string]: components["schemas"]["LiveTranscriptionLanguage"];
};
};
};
};
};
/** @description The external app "live_transcription" is not available */
400: {
headers: {
[name: string]: unknown;
};
content: {
"application/json": {
ocs: {
meta: components["schemas"]["OCSMeta"];
data: {
/** @enum {string} */
error: "app";
};
};
};
};
};
};
};
"live_transcription-set-language": {
parameters: {
query?: never;
header: {
/** @description Required to be true for the API request to pass */
"OCS-APIRequest": boolean;
};
path: {
apiVersion: "v1";
token: string;
};
cookie?: never;
};
requestBody: {
content: {
"application/json": {
/** @description the ID of the language to set */
languageId: string;
};
};
};
responses: {
/** @description Language set successfully */
200: {
headers: {
[name: string]: unknown;
};
content: {
"application/json": {
ocs: {
meta: components["schemas"]["OCSMeta"];
data: unknown;
};
};
};
};
/** @description The external app "live_transcription" is not available */
400: {
headers: {
[name: string]: unknown;
};
content: {
"application/json": {
ocs: {
meta: components["schemas"]["OCSMeta"];
data: {
/** @enum {string} */
error: "app";
};
};
};
};
};
/** @description Participant is not a moderator */
403: {
headers: {
[name: string]: unknown;
};
content: {
"application/json": {
ocs: {
meta: components["schemas"]["OCSMeta"];
data: {
/** @enum {string} */
error: "app";
};
};
};
};
};
};
};
"thread-get-recent-active-threads": {
parameters: {
query?: {

Loading…
Cancel
Save