2019-05-09 18:54:39 +12:00
< ? php
2021-02-20 02:59:46 +13:00
use Appwrite\URL\URL as URLParse ;
use Appwrite\Utopia\Response ;
use chillerlan\QRCode\QRCode ;
use chillerlan\QRCode\QROptions ;
2020-06-29 05:31:21 +12:00
use Utopia\App ;
2021-02-20 02:59:46 +13:00
use Utopia\Cache\Adapter\Filesystem ;
use Utopia\Cache\Cache ;
use Utopia\Config\Config ;
2019-05-09 18:54:39 +12:00
use Utopia\Exception ;
2021-02-20 02:59:46 +13:00
use Utopia\Image\Image ;
2020-06-22 00:18:00 +12:00
use Utopia\Validator\Boolean ;
2021-02-20 02:59:46 +13:00
use Utopia\Validator\HexColor ;
2019-05-09 18:54:39 +12:00
use Utopia\Validator\Range ;
2021-02-20 02:59:46 +13:00
use Utopia\Validator\Text ;
2021-03-25 06:47:43 +13:00
use Appwrite\Network\Validator\URL ;
2021-02-20 02:59:46 +13:00
use Utopia\Validator\WhiteList ;
2019-05-09 18:54:39 +12:00
2020-06-30 09:43:34 +12:00
$avatarCallback = function ( $type , $code , $width , $height , $quality , $response ) {
2020-10-30 02:50:49 +13:00
/** @var Appwrite\Utopia\Response $response */
2020-06-30 09:43:34 +12:00
2020-06-20 23:20:49 +12:00
$code = \strtolower ( $code );
$type = \strtolower ( $type );
2021-02-20 02:59:46 +13:00
$set = Config :: getParam ( 'avatar-' . $type , []);
2019-05-09 18:54:39 +12:00
2020-06-27 17:36:22 +12:00
if ( empty ( $set )) {
2019-05-09 18:54:39 +12:00
throw new Exception ( 'Avatar set not found' , 404 );
}
2020-06-27 17:36:22 +12:00
if ( ! \array_key_exists ( $code , $set )) {
2019-05-09 18:54:39 +12:00
throw new Exception ( 'Avatar not found' , 404 );
}
2020-06-20 23:20:49 +12:00
if ( ! \extension_loaded ( 'imagick' )) {
2019-05-09 18:54:39 +12:00
throw new Exception ( 'Imagick extension is missing' , 500 );
}
2019-09-07 05:10:41 +12:00
$output = 'png' ;
2021-02-20 02:59:46 +13:00
$date = \date ( 'D, d M Y H:i:s' , \time () + ( 60 * 60 * 24 * 45 )) . ' GMT' ; // 45 days cache
2021-04-17 07:04:42 +12:00
$key = \md5 ( '/v1/avatars/' . $type . '/:code-' . $code . $width . $height . $quality . $output );
2020-06-27 17:36:22 +12:00
$path = $set [ $code ];
2019-09-07 05:10:41 +12:00
$type = 'png' ;
2019-05-09 18:54:39 +12:00
2020-06-20 23:20:49 +12:00
if ( ! \is_readable ( $path )) {
2021-02-20 02:59:46 +13:00
throw new Exception ( 'File not readable in ' . $path , 500 );
2019-05-09 18:54:39 +12:00
}
2021-02-20 02:59:46 +13:00
$cache = new Cache ( new Filesystem ( APP_STORAGE_CACHE . '/app-0' )); // Limit file number or size
$data = $cache -> load ( $key , 60 * 60 * 24 * 30 * 3 /* 3 months */ );
2019-05-09 18:54:39 +12:00
2019-09-07 05:10:41 +12:00
if ( $data ) {
2019-05-09 18:54:39 +12:00
//$output = (empty($output)) ? $type : $output;
2020-07-03 01:51:11 +12:00
return $response
2019-05-09 18:54:39 +12:00
-> setContentType ( 'image/png' )
-> addHeader ( 'Expires' , $date )
-> addHeader ( 'X-Appwrite-Cache' , 'hit' )
2020-10-27 07:14:04 +13:00
-> send ( $data )
;
2019-05-09 18:54:39 +12:00
}
2021-02-20 02:59:46 +13:00
$image = new Image ( \file_get_contents ( $path ));
2019-05-09 18:54:39 +12:00
2021-02-20 02:59:46 +13:00
$image -> crop (( int ) $width , ( int ) $height );
2019-05-09 18:54:39 +12:00
$output = ( empty ( $output )) ? $type : $output ;
2021-02-20 02:59:46 +13:00
$data = $image -> output ( $output , $quality );
2020-07-03 01:51:11 +12:00
$cache -> save ( $key , $data );
2021-02-20 02:59:46 +13:00
2019-05-09 18:54:39 +12:00
$response
-> setContentType ( 'image/png' )
-> addHeader ( 'Expires' , $date )
-> addHeader ( 'X-Appwrite-Cache' , 'miss' )
2020-10-27 07:14:04 +13:00
-> send ( $data , null );
2019-05-09 18:54:39 +12:00
2021-02-20 02:59:46 +13:00
unset ( $image );
2019-05-09 18:54:39 +12:00
};
2020-06-29 05:31:21 +12:00
App :: get ( '/v1/avatars/credit-cards/:code' )
2019-05-09 18:54:39 +12:00
-> desc ( 'Get Credit Card Icon' )
2020-06-26 06:32:12 +12:00
-> groups ([ 'api' , 'avatars' ])
2019-05-09 18:54:39 +12:00
-> label ( 'scope' , 'avatars.read' )
2021-04-16 19:22:17 +12:00
-> label ( 'sdk.auth' , [ APP_AUTH_TYPE_SESSION , APP_AUTH_TYPE_KEY , APP_AUTH_TYPE_JWT ])
2019-05-09 18:54:39 +12:00
-> label ( 'sdk.namespace' , 'avatars' )
-> label ( 'sdk.method' , 'getCreditCard' )
2020-05-18 16:26:28 +12:00
-> label ( 'sdk.methodType' , 'location' )
2019-10-09 21:31:51 +13:00
-> label ( 'sdk.description' , '/docs/references/avatars/get-credit-card.md' )
2020-11-12 10:02:24 +13:00
-> label ( 'sdk.response.code' , Response :: STATUS_CODE_OK )
2020-11-12 11:02:02 +13:00
-> label ( 'sdk.response.type' , Response :: CONTENT_TYPE_IMAGE_PNG )
2021-02-20 02:59:46 +13:00
-> param ( 'code' , '' , new WhiteList ( \array_keys ( Config :: getParam ( 'avatar-credit-cards' ))), 'Credit Card Code. Possible values: ' . \implode ( ', ' , \array_keys ( Config :: getParam ( 'avatar-credit-cards' ))) . '.' )
2020-09-11 02:40:14 +12:00
-> param ( 'width' , 100 , new Range ( 0 , 2000 ), 'Image width. Pass an integer between 0 to 2000. Defaults to 100.' , true )
-> param ( 'height' , 100 , new Range ( 0 , 2000 ), 'Image height. Pass an integer between 0 to 2000. Defaults to 100.' , true )
-> param ( 'quality' , 100 , new Range ( 0 , 100 ), 'Image quality. Pass an integer between 0 to 100. Defaults to 100.' , true )
2020-12-27 03:59:15 +13:00
-> inject ( 'response' )
2021-12-17 23:41:26 +13:00
-> action ( fn ( $code , $width , $height , $quality , $response ) => $avatarCallback ( 'credit-cards' , $code , $width , $height , $quality , $response ));
2019-05-09 18:54:39 +12:00
2020-06-29 05:31:21 +12:00
App :: get ( '/v1/avatars/browsers/:code' )
2019-05-09 18:54:39 +12:00
-> desc ( 'Get Browser Icon' )
2020-06-26 06:32:12 +12:00
-> groups ([ 'api' , 'avatars' ])
2019-05-09 18:54:39 +12:00
-> label ( 'scope' , 'avatars.read' )
2021-04-16 19:22:17 +12:00
-> label ( 'sdk.auth' , [ APP_AUTH_TYPE_SESSION , APP_AUTH_TYPE_KEY , APP_AUTH_TYPE_JWT ])
2019-05-09 18:54:39 +12:00
-> label ( 'sdk.namespace' , 'avatars' )
-> label ( 'sdk.method' , 'getBrowser' )
2020-05-25 15:36:10 +12:00
-> label ( 'sdk.methodType' , 'location' )
2019-10-08 20:09:35 +13:00
-> label ( 'sdk.description' , '/docs/references/avatars/get-browser.md' )
2020-11-12 10:02:24 +13:00
-> label ( 'sdk.response.code' , Response :: STATUS_CODE_OK )
2020-11-12 11:02:02 +13:00
-> label ( 'sdk.response.type' , Response :: CONTENT_TYPE_IMAGE_PNG )
2020-09-11 02:40:14 +12:00
-> param ( 'code' , '' , new WhiteList ( \array_keys ( Config :: getParam ( 'avatar-browsers' ))), 'Browser Code.' )
-> param ( 'width' , 100 , new Range ( 0 , 2000 ), 'Image width. Pass an integer between 0 to 2000. Defaults to 100.' , true )
-> param ( 'height' , 100 , new Range ( 0 , 2000 ), 'Image height. Pass an integer between 0 to 2000. Defaults to 100.' , true )
-> param ( 'quality' , 100 , new Range ( 0 , 100 ), 'Image quality. Pass an integer between 0 to 100. Defaults to 100.' , true )
2020-12-27 03:59:15 +13:00
-> inject ( 'response' )
2021-12-17 23:41:26 +13:00
-> action ( fn ( $code , $width , $height , $quality , $response ) => $avatarCallback ( 'browsers' , $code , $width , $height , $quality , $response ));
2019-05-09 18:54:39 +12:00
2020-06-29 05:31:21 +12:00
App :: get ( '/v1/avatars/flags/:code' )
2019-05-09 18:54:39 +12:00
-> desc ( 'Get Country Flag' )
2020-06-26 06:32:12 +12:00
-> groups ([ 'api' , 'avatars' ])
2019-05-09 18:54:39 +12:00
-> label ( 'scope' , 'avatars.read' )
2021-04-16 19:22:17 +12:00
-> label ( 'sdk.auth' , [ APP_AUTH_TYPE_SESSION , APP_AUTH_TYPE_KEY , APP_AUTH_TYPE_JWT ])
2019-05-09 18:54:39 +12:00
-> label ( 'sdk.namespace' , 'avatars' )
-> label ( 'sdk.method' , 'getFlag' )
2020-05-18 16:26:28 +12:00
-> label ( 'sdk.methodType' , 'location' )
2019-10-08 20:09:35 +13:00
-> label ( 'sdk.description' , '/docs/references/avatars/get-flag.md' )
2020-11-12 10:02:24 +13:00
-> label ( 'sdk.response.code' , Response :: STATUS_CODE_OK )
2020-11-12 11:02:02 +13:00
-> label ( 'sdk.response.type' , Response :: CONTENT_TYPE_IMAGE_PNG )
2020-09-11 02:40:14 +12:00
-> param ( 'code' , '' , new WhiteList ( \array_keys ( Config :: getParam ( 'avatar-flags' ))), 'Country Code. ISO Alpha-2 country code format.' )
-> param ( 'width' , 100 , new Range ( 0 , 2000 ), 'Image width. Pass an integer between 0 to 2000. Defaults to 100.' , true )
-> param ( 'height' , 100 , new Range ( 0 , 2000 ), 'Image height. Pass an integer between 0 to 2000. Defaults to 100.' , true )
-> param ( 'quality' , 100 , new Range ( 0 , 100 ), 'Image quality. Pass an integer between 0 to 100. Defaults to 100.' , true )
2020-12-27 03:59:15 +13:00
-> inject ( 'response' )
2021-12-17 23:41:26 +13:00
-> action ( fn ( $code , $width , $height , $quality , $response ) => $avatarCallback ( 'flags' , $code , $width , $height , $quality , $response ));
2019-05-09 18:54:39 +12:00
2020-06-29 05:31:21 +12:00
App :: get ( '/v1/avatars/image' )
2019-08-24 02:16:25 +12:00
-> desc ( 'Get Image from URL' )
2020-06-26 06:32:12 +12:00
-> groups ([ 'api' , 'avatars' ])
2019-07-10 08:20:39 +12:00
-> label ( 'scope' , 'avatars.read' )
2021-04-16 19:22:17 +12:00
-> label ( 'sdk.auth' , [ APP_AUTH_TYPE_SESSION , APP_AUTH_TYPE_KEY , APP_AUTH_TYPE_JWT ])
2019-07-10 08:20:39 +12:00
-> label ( 'sdk.namespace' , 'avatars' )
-> label ( 'sdk.method' , 'getImage' )
2020-05-18 16:26:28 +12:00
-> label ( 'sdk.methodType' , 'location' )
2019-10-08 20:09:35 +13:00
-> label ( 'sdk.description' , '/docs/references/avatars/get-image.md' )
2020-11-12 10:02:24 +13:00
-> label ( 'sdk.response.code' , Response :: STATUS_CODE_OK )
2020-11-12 11:02:02 +13:00
-> label ( 'sdk.response.type' , Response :: CONTENT_TYPE_IMAGE )
2020-09-11 02:40:14 +12:00
-> param ( 'url' , '' , new URL (), 'Image URL which you want to crop.' )
-> param ( 'width' , 400 , new Range ( 0 , 2000 ), 'Resize preview image width, Pass an integer between 0 to 2000.' , true )
-> param ( 'height' , 400 , new Range ( 0 , 2000 ), 'Resize preview image height, Pass an integer between 0 to 2000.' , true )
2020-12-27 03:59:15 +13:00
-> inject ( 'response' )
2020-06-30 09:43:34 +12:00
-> action ( function ( $url , $width , $height , $response ) {
2020-10-30 02:50:49 +13:00
/** @var Appwrite\Utopia\Response $response */
2020-06-30 09:43:34 +12:00
$quality = 80 ;
$output = 'png' ;
2021-02-20 02:59:46 +13:00
$date = \date ( 'D, d M Y H:i:s' , \time () + ( 60 * 60 * 24 * 45 )) . ' GMT' ; // 45 days cache
$key = \md5 ( '/v2/avatars/images-' . $url . '-' . $width . '/' . $height . '/' . $quality );
2020-06-30 09:43:34 +12:00
$type = 'png' ;
2021-02-20 02:59:46 +13:00
$cache = new Cache ( new Filesystem ( APP_STORAGE_CACHE . '/app-0' )); // Limit file number or size
$data = $cache -> load ( $key , 60 * 60 * 24 * 7 /* 1 week */ );
2020-06-30 09:43:34 +12:00
if ( $data ) {
2020-07-03 01:51:11 +12:00
return $response
2020-06-30 09:43:34 +12:00
-> setContentType ( 'image/png' )
-> addHeader ( 'Expires' , $date )
-> addHeader ( 'X-Appwrite-Cache' , 'hit' )
2020-10-27 07:14:04 +13:00
-> send ( $data )
;
2020-06-30 09:43:34 +12:00
}
2019-07-10 08:20:39 +12:00
2020-06-30 09:43:34 +12:00
if ( ! \extension_loaded ( 'imagick' )) {
throw new Exception ( 'Imagick extension is missing' , 500 );
}
2019-07-10 08:20:39 +12:00
2020-06-30 09:43:34 +12:00
$fetch = @ \file_get_contents ( $url , false );
2019-07-10 08:20:39 +12:00
2020-06-30 09:43:34 +12:00
if ( ! $fetch ) {
throw new Exception ( 'Image not found' , 404 );
}
2019-07-10 08:20:39 +12:00
2020-06-30 09:43:34 +12:00
try {
2021-02-20 02:59:46 +13:00
$image = new Image ( $fetch );
} catch ( \Exception $exception ) {
2020-06-30 09:43:34 +12:00
throw new Exception ( 'Unable to parse image' , 500 );
}
2019-07-10 08:20:39 +12:00
2021-02-20 02:59:46 +13:00
$image -> crop (( int ) $width , ( int ) $height );
2019-07-10 08:20:39 +12:00
2020-06-30 09:43:34 +12:00
$output = ( empty ( $output )) ? $type : $output ;
2021-02-20 02:59:46 +13:00
$data = $image -> output ( $output , $quality );
2020-07-03 01:51:11 +12:00
$cache -> save ( $key , $data );
2019-07-10 08:20:39 +12:00
2020-06-30 09:43:34 +12:00
$response
-> setContentType ( 'image/png' )
-> addHeader ( 'Expires' , $date )
-> addHeader ( 'X-Appwrite-Cache' , 'miss' )
2020-10-27 07:14:04 +13:00
-> send ( $data );
;
2019-07-10 08:20:39 +12:00
2021-02-20 02:59:46 +13:00
unset ( $image );
2020-12-27 03:59:15 +13:00
});
2019-07-10 08:20:39 +12:00
2020-06-29 05:31:21 +12:00
App :: get ( '/v1/avatars/favicon' )
2019-05-09 18:54:39 +12:00
-> desc ( 'Get Favicon' )
2020-06-26 06:32:12 +12:00
-> groups ([ 'api' , 'avatars' ])
2019-05-09 18:54:39 +12:00
-> label ( 'scope' , 'avatars.read' )
2021-04-16 19:22:17 +12:00
-> label ( 'sdk.auth' , [ APP_AUTH_TYPE_SESSION , APP_AUTH_TYPE_KEY , APP_AUTH_TYPE_JWT ])
2019-05-09 18:54:39 +12:00
-> label ( 'sdk.namespace' , 'avatars' )
-> label ( 'sdk.method' , 'getFavicon' )
2020-05-18 16:26:28 +12:00
-> label ( 'sdk.methodType' , 'location' )
2019-10-08 20:09:35 +13:00
-> label ( 'sdk.description' , '/docs/references/avatars/get-favicon.md' )
2020-11-12 10:02:24 +13:00
-> label ( 'sdk.response.code' , Response :: STATUS_CODE_OK )
2020-11-12 11:02:02 +13:00
-> label ( 'sdk.response.type' , Response :: CONTENT_TYPE_IMAGE )
2020-09-11 02:40:14 +12:00
-> param ( 'url' , '' , new URL (), 'Website URL which you want to fetch the favicon from.' )
2020-12-27 03:59:15 +13:00
-> inject ( 'response' )
2020-06-30 09:43:34 +12:00
-> action ( function ( $url , $response ) {
2020-10-30 02:50:49 +13:00
/** @var Appwrite\Utopia\Response $response */
2020-06-30 09:43:34 +12:00
$width = 56 ;
$height = 56 ;
$quality = 80 ;
$output = 'png' ;
2021-02-20 02:59:46 +13:00
$date = \date ( 'D, d M Y H:i:s' , \time () + ( 60 * 60 * 24 * 45 )) . ' GMT' ; // 45 days cache
$key = \md5 ( '/v2/avatars/favicon-' . $url );
2020-06-30 09:43:34 +12:00
$type = 'png' ;
2021-02-20 02:59:46 +13:00
$cache = new Cache ( new Filesystem ( APP_STORAGE_CACHE . '/app-0' )); // Limit file number or size
$data = $cache -> load ( $key , 60 * 60 * 24 * 30 * 3 /* 3 months */ );
2020-06-30 09:43:34 +12:00
if ( $data ) {
2020-07-03 01:51:11 +12:00
return $response
2020-06-30 09:43:34 +12:00
-> setContentType ( 'image/png' )
-> addHeader ( 'Expires' , $date )
-> addHeader ( 'X-Appwrite-Cache' , 'hit' )
2020-10-27 07:14:04 +13:00
-> send ( $data )
;
2020-06-30 09:43:34 +12:00
}
2019-05-09 18:54:39 +12:00
2020-06-30 09:43:34 +12:00
if ( ! \extension_loaded ( 'imagick' )) {
throw new Exception ( 'Imagick extension is missing' , 500 );
}
2019-05-09 18:54:39 +12:00
2020-06-30 09:43:34 +12:00
$curl = \curl_init ();
2019-05-09 18:54:39 +12:00
2020-06-30 09:43:34 +12:00
\curl_setopt_array ( $curl , [
CURLOPT_RETURNTRANSFER => 1 ,
CURLOPT_FOLLOWLOCATION => true ,
CURLOPT_MAXREDIRS => 3 ,
CURLOPT_URL => $url ,
2020-10-27 07:14:04 +13:00
CURLOPT_USERAGENT => \sprintf ( APP_USERAGENT ,
2020-06-30 23:09:28 +12:00
App :: getEnv ( '_APP_VERSION' , 'UNKNOWN' ),
2020-06-30 09:43:34 +12:00
App :: getEnv ( '_APP_SYSTEM_SECURITY_EMAIL_ADDRESS' , APP_EMAIL_SECURITY )
),
]);
2019-05-09 18:54:39 +12:00
2020-06-30 09:43:34 +12:00
$html = \curl_exec ( $curl );
2019-05-09 18:54:39 +12:00
2020-06-30 09:43:34 +12:00
\curl_close ( $curl );
2019-05-09 18:54:39 +12:00
2020-06-30 09:43:34 +12:00
if ( ! $html ) {
throw new Exception ( 'Failed to fetch remote URL' , 404 );
}
2019-05-09 18:54:39 +12:00
2020-06-30 09:43:34 +12:00
$doc = new DOMDocument ();
$doc -> strictErrorChecking = false ;
@ $doc -> loadHTML ( $html );
$links = $doc -> getElementsByTagName ( 'link' );
$outputHref = '' ;
$outputExt = '' ;
$space = 0 ;
foreach ( $links as $link ) { /* @var $link DOMElement */
$href = $link -> getAttribute ( 'href' );
$rel = $link -> getAttribute ( 'rel' );
$sizes = $link -> getAttribute ( 'sizes' );
$absolute = URLParse :: unparse ( \array_merge ( \parse_url ( $url ), \parse_url ( $href )));
switch ( \strtolower ( $rel )) {
case 'icon' :
case 'shortcut icon' :
//case 'apple-touch-icon':
$ext = \pathinfo ( \parse_url ( $absolute , PHP_URL_PATH ), PATHINFO_EXTENSION );
switch ( $ext ) {
case 'ico' :
case 'png' :
case 'jpg' :
case 'jpeg' :
$size = \explode ( 'x' , \strtolower ( $sizes ));
2020-10-15 10:34:57 +13:00
$sizeWidth = ( int ) $size [ 0 ] ? ? 0 ;
$sizeHeight = ( int ) $size [ 1 ] ? ? 0 ;
2020-06-30 09:43:34 +12:00
if (( $sizeWidth * $sizeHeight ) >= $space ) {
$space = $sizeWidth * $sizeHeight ;
$outputHref = $absolute ;
$outputExt = $ext ;
}
break ;
}
2019-07-07 07:43:45 +12:00
2020-06-30 09:43:34 +12:00
break ;
2019-05-09 18:54:39 +12:00
}
2020-06-30 09:43:34 +12:00
}
2019-05-09 18:54:39 +12:00
2020-06-30 09:43:34 +12:00
if ( empty ( $outputHref ) || empty ( $outputExt )) {
$default = \parse_url ( $url );
2019-05-09 18:54:39 +12:00
2021-02-20 02:59:46 +13:00
$outputHref = $default [ 'scheme' ] . '://' . $default [ 'host' ] . '/favicon.ico' ;
2020-06-30 09:43:34 +12:00
$outputExt = 'ico' ;
}
2019-05-09 18:54:39 +12:00
2020-06-30 09:43:34 +12:00
if ( 'ico' == $outputExt ) { // Skip crop, Imagick isn\'t supporting icon files
$data = @ \file_get_contents ( $outputHref , false );
2019-05-09 18:54:39 +12:00
2020-06-30 09:43:34 +12:00
if ( empty ( $data ) || ( \mb_substr ( $data , 0 , 5 ) === '<html' ) || \mb_substr ( $data , 0 , 5 ) === '<!doc' ) {
throw new Exception ( 'Favicon not found' , 404 );
2019-05-09 18:54:39 +12:00
}
2020-06-30 09:43:34 +12:00
$cache -> save ( $key , $data );
2019-05-09 18:54:39 +12:00
2020-07-03 01:51:11 +12:00
return $response
2020-06-30 09:43:34 +12:00
-> setContentType ( 'image/x-icon' )
2019-05-09 18:54:39 +12:00
-> addHeader ( 'Expires' , $date )
-> addHeader ( 'X-Appwrite-Cache' , 'miss' )
2020-10-27 07:14:04 +13:00
-> send ( $data )
;
2020-06-30 09:43:34 +12:00
}
2019-05-09 18:54:39 +12:00
2020-06-30 09:43:34 +12:00
$fetch = @ \file_get_contents ( $outputHref , false );
2019-05-09 18:54:39 +12:00
2020-06-30 09:43:34 +12:00
if ( ! $fetch ) {
throw new Exception ( 'Icon not found' , 404 );
}
2019-05-09 18:54:39 +12:00
2021-02-20 02:59:46 +13:00
$image = new Image ( $fetch );
2019-05-09 18:54:39 +12:00
2021-02-20 02:59:46 +13:00
$image -> crop (( int ) $width , ( int ) $height );
2020-06-30 09:43:34 +12:00
$output = ( empty ( $output )) ? $type : $output ;
2021-02-20 02:59:46 +13:00
$data = $image -> output ( $output , $quality );
2020-06-30 09:43:34 +12:00
$cache -> save ( $key , $data );
2020-07-03 01:51:11 +12:00
$response
-> setContentType ( 'image/png' )
-> addHeader ( 'Expires' , $date )
-> addHeader ( 'X-Appwrite-Cache' , 'miss' )
-> send ( $data );
2020-06-30 09:43:34 +12:00
2021-02-20 02:59:46 +13:00
unset ( $image );
2020-12-27 03:59:15 +13:00
});
2019-05-09 18:54:39 +12:00
2020-06-29 05:31:21 +12:00
App :: get ( '/v1/avatars/qr' )
2019-11-28 06:24:36 +13:00
-> desc ( 'Get QR Code' )
2020-06-26 06:32:12 +12:00
-> groups ([ 'api' , 'avatars' ])
2019-05-09 18:54:39 +12:00
-> label ( 'scope' , 'avatars.read' )
2021-04-16 19:22:17 +12:00
-> label ( 'sdk.auth' , [ APP_AUTH_TYPE_SESSION , APP_AUTH_TYPE_KEY , APP_AUTH_TYPE_JWT ])
2019-05-09 18:54:39 +12:00
-> label ( 'sdk.namespace' , 'avatars' )
-> label ( 'sdk.method' , 'getQR' )
2020-05-18 16:26:28 +12:00
-> label ( 'sdk.methodType' , 'location' )
2019-10-08 20:09:35 +13:00
-> label ( 'sdk.description' , '/docs/references/avatars/get-qr.md' )
2020-11-12 10:02:24 +13:00
-> label ( 'sdk.response.code' , Response :: STATUS_CODE_OK )
2020-11-12 11:02:02 +13:00
-> label ( 'sdk.response.type' , Response :: CONTENT_TYPE_IMAGE_PNG )
2020-09-11 02:40:14 +12:00
-> param ( 'text' , '' , new Text ( 512 ), 'Plain text to be converted to QR code image.' )
-> param ( 'size' , 400 , new Range ( 0 , 1000 ), 'QR code size. Pass an integer between 0 to 1000. Defaults to 400.' , true )
-> param ( 'margin' , 1 , new Range ( 0 , 10 ), 'Margin from edge. Pass an integer between 0 to 10. Defaults to 1.' , true )
-> param ( 'download' , false , new Boolean ( true ), 'Return resulting image with \'Content-Disposition: attachment \' headers for the browser to start downloading it. Pass 0 for no header, or 1 for otherwise. Default value is set to 0.' , true )
2020-12-27 03:59:15 +13:00
-> inject ( 'response' )
2020-06-30 09:43:34 +12:00
-> action ( function ( $text , $size , $margin , $download , $response ) {
2020-10-30 02:50:49 +13:00
/** @var Appwrite\Utopia\Response $response */
2020-06-21 23:56:42 +12:00
2020-06-30 09:43:34 +12:00
$download = ( $download === '1' || $download === 'true' || $download === 1 || $download === true );
2020-10-27 13:12:35 +13:00
$options = new QROptions ([
2021-01-10 13:07:58 +13:00
'addQuietzone' => true ,
'quietzoneSize' => $margin ,
'outputType' => QRCode :: OUTPUT_IMAGICK ,
2020-10-23 07:50:57 +13:00
]);
2020-10-27 13:12:35 +13:00
$qrcode = new QRCode ( $options );
2019-05-09 18:54:39 +12:00
2020-06-30 09:43:34 +12:00
if ( $download ) {
$response -> addHeader ( 'Content-Disposition' , 'attachment; filename="qr.png"' );
2020-06-10 07:48:26 +12:00
}
2020-06-30 09:43:34 +12:00
2021-02-20 02:59:46 +13:00
$image = new Image ( $qrcode -> render ( $text ));
2021-01-10 13:17:44 +13:00
2021-02-20 02:59:46 +13:00
$image -> crop (( int ) $size , ( int ) $size );
2021-01-10 13:17:44 +13:00
2020-06-30 09:43:34 +12:00
$response
2021-02-20 02:59:46 +13:00
-> addHeader ( 'Expires' , \date ( 'D, d M Y H:i:s' , \time () + ( 60 * 60 * 24 * 45 )) . ' GMT' ) // 45 days cache
2020-06-30 09:43:34 +12:00
-> setContentType ( 'image/png' )
2021-02-20 02:59:46 +13:00
-> send ( $image -> output ( 'png' , 9 ))
2020-10-27 07:14:04 +13:00
;
2020-12-27 03:59:15 +13:00
});
2020-06-10 07:48:26 +12:00
2020-06-29 05:31:21 +12:00
App :: get ( '/v1/avatars/initials' )
2020-06-10 07:48:26 +12:00
-> desc ( 'Get User Initials' )
2020-06-26 06:32:12 +12:00
-> groups ([ 'api' , 'avatars' ])
2020-06-10 07:48:26 +12:00
-> label ( 'scope' , 'avatars.read' )
2021-04-16 19:22:17 +12:00
-> label ( 'sdk.auth' , [ APP_AUTH_TYPE_SESSION , APP_AUTH_TYPE_KEY , APP_AUTH_TYPE_JWT ])
2020-06-10 07:48:26 +12:00
-> label ( 'sdk.namespace' , 'avatars' )
-> label ( 'sdk.method' , 'getInitials' )
-> label ( 'sdk.methodType' , 'location' )
-> label ( 'sdk.description' , '/docs/references/avatars/get-initials.md' )
2020-11-12 10:02:24 +13:00
-> label ( 'sdk.response.code' , Response :: STATUS_CODE_OK )
2020-11-12 11:02:02 +13:00
-> label ( 'sdk.response.type' , Response :: CONTENT_TYPE_IMAGE_PNG )
2020-09-11 02:40:14 +12:00
-> param ( 'name' , '' , new Text ( 128 ), 'Full Name. When empty, current user name or email will be used. Max length: 128 chars.' , true )
-> param ( 'width' , 500 , new Range ( 0 , 2000 ), 'Image width. Pass an integer between 0 to 2000. Defaults to 100.' , true )
-> param ( 'height' , 500 , new Range ( 0 , 2000 ), 'Image height. Pass an integer between 0 to 2000. Defaults to 100.' , true )
-> param ( 'color' , '' , new HexColor (), 'Changes text color. By default a random color will be picked and stay will persistent to the given name.' , true )
-> param ( 'background' , '' , new HexColor (), 'Changes background color. By default a random color will be picked and stay will persistent to the given name.' , true )
2020-12-27 03:59:15 +13:00
-> inject ( 'response' )
-> inject ( 'user' )
2020-06-30 09:43:34 +12:00
-> action ( function ( $name , $width , $height , $color , $background , $response , $user ) {
2020-10-30 02:50:49 +13:00
/** @var Appwrite\Utopia\Response $response */
2021-07-26 02:47:18 +12:00
/** @var Utopia\Database\Document $user */
2020-06-30 09:43:34 +12:00
$themes = [
[ 'color' => '#27005e' , 'background' => '#e1d2f6' ], // VIOLET
[ 'color' => '#5e2700' , 'background' => '#f3d9c6' ], // ORANGE
[ 'color' => '#006128' , 'background' => '#c9f3c6' ], // GREEN
[ 'color' => '#580061' , 'background' => '#f2d1f5' ], // FUSCHIA
[ 'color' => '#00365d' , 'background' => '#c6e1f3' ], // BLUE
[ 'color' => '#00075c' , 'background' => '#d2d5f6' ], // INDIGO
[ 'color' => '#610038' , 'background' => '#f5d1e6' ], // PINK
[ 'color' => '#386100' , 'background' => '#dcf1bd' ], // LIME
[ 'color' => '#615800' , 'background' => '#f1ecba' ], // YELLOW
2021-02-20 02:59:46 +13:00
[ 'color' => '#610008' , 'background' => '#f6d2d5' ], // RED
2020-06-30 09:43:34 +12:00
];
2021-02-20 02:59:46 +13:00
$rand = \rand ( 0 , \count ( $themes ) - 1 );
2020-06-30 09:43:34 +12:00
$name = ( ! empty ( $name )) ? $name : $user -> getAttribute ( 'name' , $user -> getAttribute ( 'email' , '' ));
$words = \explode ( ' ' , \strtoupper ( $name ));
2021-07-26 00:13:49 +12:00
// if there is no space, try to split by `_` underscore
$words = ( count ( $words ) == 1 ) ? \explode ( '_' , \strtoupper ( $name )) : $words ;
2020-06-30 09:43:34 +12:00
$initials = null ;
$code = 0 ;
foreach ( $words as $key => $w ) {
2020-10-15 10:34:57 +13:00
$initials .= $w [ 0 ] ? ? '' ;
2020-06-30 09:43:34 +12:00
$code += ( isset ( $w [ 0 ])) ? \ord ( $w [ 0 ]) : 0 ;
if ( $key == 1 ) {
break ;
2020-06-10 07:48:26 +12:00
}
2020-06-30 09:43:34 +12:00
}
2020-06-10 07:48:26 +12:00
2021-02-20 02:59:46 +13:00
$rand = \substr ( $code , - 1 );
$background = ( ! empty ( $background )) ? '#' . $background : $themes [ $rand ][ 'background' ];
$color = ( ! empty ( $color )) ? '#' . $color : $themes [ $rand ][ 'color' ];
2020-06-30 09:43:34 +12:00
$image = new \Imagick ();
$draw = new \ImagickDraw ();
$fontSize = \min ( $width , $height ) / 2 ;
2021-02-20 02:59:46 +13:00
$draw -> setFont ( __DIR__ . " /../../../public/fonts/poppins-v9-latin-500.ttf " );
$image -> setFont ( __DIR__ . " /../../../public/fonts/poppins-v9-latin-500.ttf " );
2020-06-30 09:43:34 +12:00
$draw -> setFillColor ( new \ImagickPixel ( $color ));
$draw -> setFontSize ( $fontSize );
2021-02-20 02:59:46 +13:00
2020-06-30 09:43:34 +12:00
$draw -> setTextAlignment ( \Imagick :: ALIGN_CENTER );
$draw -> annotation ( $width / 1.97 , ( $height / 2 ) + ( $fontSize / 3 ), $initials );
2021-02-20 02:59:46 +13:00
2020-06-30 09:43:34 +12:00
$image -> newImage ( $width , $height , $background );
$image -> setImageFormat ( " png " );
$image -> drawImage ( $draw );
//$image->setImageCompressionQuality(9 - round(($quality / 100) * 9));
2020-06-10 07:48:26 +12:00
2020-06-30 09:43:34 +12:00
$response
2021-02-20 02:59:46 +13:00
-> addHeader ( 'Expires' , \date ( 'D, d M Y H:i:s' , \time () + ( 60 * 60 * 24 * 45 )) . ' GMT' ) // 45 days cache
2020-06-30 09:43:34 +12:00
-> setContentType ( 'image/png' )
2020-10-27 07:14:04 +13:00
-> send ( $image -> getImageBlob ())
;
2020-12-27 03:59:15 +13:00
});