Code Monkey home page Code Monkey logo

yii2-aws-s3's Introduction

Yii2 AWS S3

An Amazon S3 component for Yii2.

License Latest Stable Version Total Downloads Latest Unstable Version

Yii2 AWS S3 uses SemVer.

Version 2.x requires PHP 7. For PHP less 7.0 use 1.x.

Installation

  1. Run the Composer command to install the latest version:

    composer require frostealth/yii2-aws-s3 ~2.0
  2. Add the component to config/main.php

    'components' => [
        // ...
        's3' => [
            'class' => 'frostealth\yii2\aws\s3\Service',
            'credentials' => [ // Aws\Credentials\CredentialsInterface|array|callable
                'key' => 'my-key',
                'secret' => 'my-secret',
            ],
            'region' => 'my-region',
            'defaultBucket' => 'my-bucket',
            'defaultAcl' => 'public-read',
        ],
        // ...
    ],

Basic usage

Usage of the command factory and additional params

/** @var \frostealth\yii2\aws\s3\Service $s3 */
$s3 = Yii::$app->get('s3');

/** @var \Aws\ResultInterface $result */
$result = $s3->commands()->get('filename.ext')->saveAs('/path/to/local/file.ext')->execute();

$result = $s3->commands()->put('filename.ext', 'body')->withContentType('text/plain')->execute();

$result = $s3->commands()->delete('filename.ext')->execute();

$result = $s3->commands()->upload('filename.ext', '/path/to/local/file.ext')->withAcl('private')->execute();

$result = $s3->commands()->restore('filename.ext', $days = 7)->execute();

$result = $s3->commands()->list('path/')->execute();

/** @var bool $exist */
$exist = $s3->commands()->exist('filename.ext')->execute();

/** @var string $url */
$url = $s3->commands()->getUrl('filename.ext')->execute();

/** @var string $signedUrl */
$signedUrl = $s3->commands()->getPresignedUrl('filename.ext', '+2 days')->execute();

Short syntax

/** @var \frostealth\yii2\aws\s3\Service $s3 */
$s3 = Yii::$app->get('s3');

/** @var \Aws\ResultInterface $result */
$result = $s3->get('filename.ext');

$result = $s3->put('filename.ext', 'body');

$result = $s3->delete('filename.ext');

$result = $s3->upload('filename.ext', '/path/to/local/file.ext');

$result = $s3->restore('filename.ext', $days = 7);

$result = $s3->list('path/');

/** @var bool $exist */
$exist = $s3->exist('filename.ext');

/** @var string $url */
$url = $s3->getUrl('filename.ext');

/** @var string $signedUrl */
$signedUrl = $s3->getPresignedUrl('filename.ext', '+2 days');

Asynchronous execution

/** @var \frostealth\yii2\aws\s3\Service $s3 */
$s3 = Yii::$app->get('s3');

/** @var \GuzzleHttp\Promise\PromiseInterface $promise */
$promise = $s3->commands()->get('filename.ext')->async()->execute();

$promise = $s3->commands()->put('filename.ext', 'body')->async()->execute();

$promise = $s3->commands()->delete('filename.ext')->async()->execute();

$promise = $s3->commands()->upload('filename.ext', 'source')->async()->execute();

$promise = $s3->commands()->list('path/')->async()->execute();

Advanced usage

/** @var \frostealth\yii2\aws\s3\interfaces\Service $s3 */
$s3 = Yii::$app->get('s3');

/** @var \frostealth\yii2\aws\s3\commands\GetCommand $command */
$command = $s3->create(GetCommand::class);
$command->inBucket('my-another-bucket')->byFilename('filename.ext')->saveAs('/path/to/local/file.ext');

/** @var \Aws\ResultInterface $result */
$result = $s3->execute($command);

// or async
/** @var \GuzzleHttp\Promise\PromiseInterface $promise */
$promise = $s3->execute($command->async());

Custom commands

Commands have two types: plain commands that's handled by the PlainCommandHandler and commands with their own handlers. The plain commands wrap the native AWS S3 commands.

The plain commands must implement the PlainCommand interface and the rest must implement the Command interface. If the command doesn't implement the PlainCommand interface, it must have its own handler.

Every handler must extend the Handler class or implement the Handler interface. Handlers gets the S3Client instance into its constructor.

The implementation of the HasBucket and HasAcl interfaces allows the command builder to set the values of bucket and acl by default.

To make the plain commands asynchronously, you have to implement the Asynchronous interface. Also, you can use the Async trait to implement this interface.

Consider the following command:

<?php

namespace app\components\s3\commands;

use frostealth\yii2\aws\s3\base\commands\traits\Options;
use frostealth\yii2\aws\s3\interfaces\commands\Command;
use frostealth\yii2\aws\s3\interfaces\commands\HasBucket;

class MyCommand implements Command, HasBucket
{
    use Options;

    protected $bucket;

    protected $something;

    public function getBucket()
    {
        return $this->bucket;
    }

    public function inBucket(string $bucket)
    {
        $this->bucket = $bucket;

        return $this;
    }

    public function getSomething()
    {
        return $this->something;
    }

    public function withSomething(string $something)
    {
        $this->something = $something;

        return $this;
    }
}

The handler for this command looks like this:

<?php

namespace app\components\s3\handlers;

use app\components\s3\commands\MyCommand;
use frostealth\yii2\aws\s3\base\handlers\Handler;

class MyCommandHandler extends Handler
{
    public function handle(MyCommand $command)
    {
        return $this->s3Client->someAction(
            $command->getBucket(),
            $command->getSomething(),
            $command->getOptions()
        );
    }
}

And usage this command:

/** @var \frostealth\yii2\aws\s3\interfaces\Service */
$s3 = Yii::$app->get('s3');

/** @var \app\components\s3\commands\MyCommand $command */
$command = $s3->create(MyCommand::class);
$command->withSomething('some value')->withOption('OptionName', 'value');

/** @var \Aws\ResultInterface $result */
$result = $s3->execute($command);

Custom plain command looks like this:

<?php

namespace app\components\s3\commands;

use frostealth\yii2\aws\s3\interfaces\commands\HasBucket;
use frostealth\yii2\aws\s3\interfaces\commands\PlainCommand;

class MyPlainCommand implements PlainCommand, HasBucket
{
    protected $args = [];

    public function getBucket()
    {
        return $this->args['Bucket'] ?? '';
    }

    public function inBucket(string $bucket)
    {
        $this->args['Bucket'] = $bucket;

        return $this;
    }

    public function getSomething()
    {
        return $this->args['something'] ?? '';
    }

    public function withSomething($something)
    {
        $this->args['something'] = $something;

        return $this;
    }

    public function getName(): string
    {
        return 'AwsS3CommandName';
    }

    public function toArgs(): array
    {
        return $this->args;
    }
}

Any command can extend the ExecutableCommand class or implement the Executable interface that will allow to execute this command immediately: $command->withSomething('some value')->execute();.

License

Yii2 AWS S3 is licensed under the MIT License.

See the LICENSE file for more information.

yii2-aws-s3's People

Contributors

alessiodionisi avatar frostealth avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

yii2-aws-s3's Issues

Not able to upgrade frostealth library from 0.2.0 to 2.0.0

Hello,
I am trying to upgrade frostealth library from 0.2.0 to 2.0.0 ,I am facing below error:-

Problem 1
- Installation request for frostealth/yii2-aws-s3 2.0.0 -> satisfiable by frostealth/yii2-aws-s3[v2.0.0].
- Conclusion: don't install aws/aws-sdk-php 2.7.27
- frostealth/yii2-aws-s3 v2.0.0 requires aws/aws-sdk-php ~3.17 -> satisfiable by aws/aws-sdk-php[3.100.0, 3.100.1, 3.100.2, 3.100.3, 3.100.4, 3.100.5, 3.100.6, 3.100.7, 3.100.8, 3.100.9, 3.101.0, 3.101.1, 3.102.0.

I have php8.0 and aws-sdk-php 2.7.27 version on my machine.I hit below command to upgrade frostealth library version
composer require frostealth/yii2-aws-s3 2.0.0.

I attach error screenshot here for reference
Screenshot from 2022-06-02 19-14-19
Screenshot from 2022-06-02 19-14-01
Screenshot from 2022-06-02 19-13-50

Can I use ClientSide encryption with this extension?

Hi,
I was wondering if I can use something like explained here:

https://aws.amazon.com/blogs/developer/using-client-side-encryption-for-amazon-s3-in-the-aws-sdk-for-php/

It uses client side encryption as I do not want to use server side.

For upload and encrypting:

`// Let's construct our S3EncryptionClient using an S3Client
$encryptionClient = new S3EncryptionClient(
	new S3Client([
		'region' => 'us-east-1',
		'version' => 'latest',
	])
);

$kmsKeyArn = 'arn-to-the-kms-key';
// This materials provider handles generating a cipher key and initialization
// vector, as well as encrypting your cipher key via AWS KMS
$materialsProvider = new KmsMaterialsProvider(
	new KmsClient([
		'region' => 'us-east-1',
		'version' => 'latest',
	]),
	$kmsKeyArn
);

$bucket = 'the-bucket-name';
$key = 'the-upload-key';
$cipherOptions = [
	'Cipher' => 'gcm'
	'KeySize' => 256,
	// Additional configuration options
];

$result = $encryptionClient->putObject([
	'@MaterialsProvider' => $materialsProvider,
	'@CipherOptions' => $cipherOptions,
	'Bucket' => $bucket,
	'Key' => $key,
	'Body' => fopen('file-to-encrypt.txt'),
]);`

And for download and de-crypting this:

$result = $encryptionClient->getObject([
	'@MaterialsProvider' => $materialsProvider,
	'@CipherOptions' => [
		// Additional configuration options
	], 
	'Bucket' => $bucket,
	'Key' => $key,
]);

Can this be done with this extension?

Thanks,
gb5256

CDN Support

Please add support for CDN urls, same as on v.1

poor docs

do you can describe more of your examples? because upload() is return some data but docs doesn't has any info about it.

Add the option to set the S3Client Endpoint property

In order to make other services that uses the S3 api to be contacted via this extension.
for example:
's3' => [
'class' => 'frostealth\yii2\aws\s3\Service',
'credentials' =>
'key' => 'My-Key',
'secret' => 'My-Secret',
],
'endpoint' => "https://myendpoint.com",
'region' => 'endpoitregion',
'defaultBucket' => 'defaultbucket',
'defaultAcl' => 'public-read',
],

Enhancement (v1): Set content-type using upload()

Usage

            \Yii::$app->get('s3bucket')->upload(
                $filename,
                $this->file->tempName,
                \Yii::$app->get('s3bucket')->defaultAcl,
                [
                    'ContentType'        => $this->file->type,
                    'ContentDisposition' => 'render',
                ]
            );

Expected: file would be of defined content-type in the S3 bucket.
Actual: file is octet-stream in S3 bucket

Tried:

            \Yii::$app->get('s3bucket')->put(
                $filename,
                $this->file->tempName,
                \Yii::$app->get('s3bucket')->defaultAcl,
                [
                    'ContentType'        => $this->file->type,
                    'ContentDisposition' => 'render',
                ]
            );
...and...
            \Yii::$app->get('s3bucket')->put(
                $filename,
                fopen($this->file->tempName, 'r+'),
                \Yii::$app->get('s3bucket')->defaultAcl,
                [
                    'ContentType'        => $this->file->type,
                    'ContentDisposition' => 'render',
                ]
            );
...and...
            \Yii::$app->get('s3bucket')->upload(
                $filename,
                fopen($this->file->tempName, 'r+'),
                \Yii::$app->get('s3bucket')->defaultAcl,
                [
                    'ContentType'        => $this->file->type,
                    'ContentDisposition' => 'render',
                ]
            );

Error executing "GetObject" on "https://s3.u

Error executing "GetObject" on "https://s3.us-east-23.amazonaws.com/t-ert-34-infra-5dgdfrg/1488396616.jpeg"; AWS HTTP error: Client error: GET https://s3.us-east-23.amazonaws.com/t-ert-34-infra-5dgdfrg/1488396616.jpeg` resulted in a 404 Not Found response:

NoSuchKeyThe specified key does not exist. (truncated...)
NoSuchKey (client): The specified key does not exist. -
NoSuchKeyThe specified key does not exist.1488396616.jpeg04407CDF4F0C239BRlwa7GT13kzYCEZKPIEHkfOXXmRj19loc6rZnVt9FnoQO6dq1kAQtJneIrOYVTqsAgT/uWMiTWY=`

Default Region

The default region follows the folling path : s3.amazonaws.com and the different regions : s3-.amazonaws.com

So, for example if you create a client by specifying the eu-west-1 region, it maps to the following region-specific endpoint:

s3-eu-west-1.amazonaws.com

Actually the default address is not being managed and the other endpoints follows the end point like : s3.ENDPOINT.amazonaws.com that should be not the standard according to docs.

Breaking changes in Guzzle dependency

/frostealth/yii2-aws-s3/src/handlers/uploadCommandHandlers

protected function sourceToStream($source): StreamInterface
    {
        if (is_string($source)) {
            $source = Psr7\try_fopen($source, 'r+');
        }

        return Psr7\stream_for($source);
    }

Should now be

protected function sourceToStream($source): StreamInterface
    {
        if (is_string($source)) {
            $source = Psr7\Utils::tryFopen($source, 'r+');
        }

        return Psr7\Utils::streamFor($source);
    }

There might be more functions needs replacing, but that was the one directly affecting me. There's a list of the new functions here https://github.com/guzzle/psr7/blob/4095c77b73893521ef1c84109b95f97aa35e48b8/README.md

Can't upload and then unlink.

To reproduce:

Yii::$app->get('s3bucket')->upload($toFile, $fromFile);
unlink($fromFile);

Uploading works by itself. Unlinking works by itself. But I can't upload and then unlink. I get "Permission Denied".

fupload command missing setMetadata and contentType methods

Similar to command put() I would expect to be able to specify ContentType and generic metadata using similar methods.

Example (this currently does not work):

Yii::$app->get('s3')->commands()
    ->upload($pathname, $sourceFile)
    ->setMetadata([
            'ContentType' => 'application/pdf',
            'ContentDisposition' => 'attachment',
        ])->setContentType('application/pdf')
    ->execute();

Both methods setMetadata() and setContentType() are missing.
There seems to be no other way to set metadata either.

uploadAsync not working

Earlier we are using mulitpart form upload which is going to be deprecate. So we switch to UploadAsync method to upload image to S3 but its creating empty file with no content - image file only have source file path in it. Kindly guide

How to use a mock server?

Please explain the feasibility of using a mock service with your library. We have a requirement to test our yii2 application locally without uploading files to s3.

Обратная совместимость с PHP 5.*

Возможна ли обратная совместимость со старыми версиями PHP ? 5.6 например.

Наш проект использует Ваш extension и мы на данный момент не можем обновить версию PHP до 7-й.

Allowed memory size of xxxx bytes exhausted

[root@ip-xxxxx html]# nginx -v
nginx version: nginx/1.12.2
[root@ip-xxxxx html]# php --version
PHP 7.1.15 (cli) (built: Mar  1 2018 13:09:01) ( NTS )
Copyright (c) 1997-2018 The PHP Group
Zend Engine v3.1.0, Copyright (c) 1998-2018 Zend Technologies
    with Zend OPcache v7.1.15, Copyright (c) 1999-2018, by Zend Technologies

I am using aws Linux ec2 with m5.large instance. I got the error "Allowed memory size of xxxx bytes exhausted ... ".
I already tried to ini_set('memory_limit','2048M'); even if i increase the limit it always gives me an error.

$s3 = Yii::$app->get('s3');
$s3->commands()->upload($upload_photo, $full)->withAcl('private')->execute();

Bulk delete files in folder or delete entire folder with files.

Hi there. Is there a way we can delete all the content of the given folder or the entire folder with one request?

For example I want to delete the "main/shipping_labels/test/555/" folder, or all files inside it.

The suggested method "delete" is not working for the folder. It accepts only the filename, or I can delete the folder if it is empty.

I have tried to delete the content in this way, but it is still not working -
$s3->commands()->delete("main/shipping_labels/test/555/*")->execute();

Please give an advice.

Call to undefined function GuzzleHttp\Psr7\try_fopen()

I am trying to upload file to amazon, but I got this error

Call to undefined function GuzzleHttp\Psr7\try_fopen()

vendor\frostealth\yii2-aws-s3\src\handlers\UploadCommandHandler.php line 48

My code:

$result = $s3->commands()->upload('e:\Video\short videos\The Small Business Story – short video no captions.mp4', '/uplod/29/10/small.mp4')->withAcl('private')->execute();

How can I fix that?

composer error

[InvalidArgumentException]
Package frostealth/yii2-aws-s3 at version ~2.0 has a PHP requirement incomp
atible with your PHP version (5.6.35)

composer.json configuration

Hello,
if I add "frostealth/yii2-aws-s3": "~2.0@rc" to my composer.json I can't find the package.

Any suggestion?

Thanks

Requires PHP7

Cool library. Lots of potential.

I received this error. Do you really need PHP7 for this? I was unable to install with satisfiable names below.

Your requirements could not be resolved to an installable set of packages.

Problem 1
- frostealth/yii2-aws-s3 v2.0.0-beta.1 requires php >=7.0.0 -> your PHP version (5.6.10) does not satisfy that requirement.
- frostealth/yii2-aws-s3 v2.0.0-beta requires php >=7.0.0 -> your PHP version (5.6.10) does not satisfy that requirement.
- Installation request for frostealth/yii2-aws-s3 ~2.0.0@beta -> satisfiable by frostealth/yii2-aws-s3[v2.0.0-beta, v2.0.0-beta.1].

PHP Parse Error – yii\base\ErrorException syntax error, unexpected '?'

  1. in D:\Work\v2newrepo\vendor\frostealth\yii2-aws-s3\src\Service.php at line 64

foreach ($this->defaultComponentDefinitions() as $name => $definition) {
$this->components[$name] = $this->components[$name] ?? $definition;
}
below my configuration

's3' => [
'class' => 'frostealth\yii2\aws\s3\Service',
'credentials' => [ // Aws\Credentials\CredentialsInterface|array|callable
'key' => 'xxxxxxxxxxxxxxxxxxxxxxx',
'secret' => 'xxxxxxxxxxxxxxxxxxxx',
],
'region' => 'ap-south-1',
'version' => 'latest',
'defaultBucket' => 'test',
'defaultAcl' => 'public-read',
],

Credentials must be an instance of Aws\Credentials\CredentialsInterface

Configuring like in readme throws error

'components' => [
    // ...
    's3' => [
        'class' => 'frostealth\yii2\aws\s3\Service',
        'credentials' => [ // Aws\Credentials\CredentialsInterface|array|callable
            'key' => 'my-key',
            'secret' => 'my-secret',
        ],
        'region' => 'my-region',
        'defaultBucket' => 'my-bucket',
        'defaultAcl' => 'public-read',
    ],
    // ...
],
Credentials must be an instance of Aws\Credentials\CredentialsInterface

Based on this, the config should be

'components' => [
    // ...
    's3' => [
        'class' => 'frostealth\yii2\aws\s3\Service',
        'credentials' => new Aws\Credentials\Credentials('my-key',  'my-secret'),
        'region' => 'my-region',
        'defaultBucket' => 'my-bucket',
        'defaultAcl' => 'public-read',
    ],
    // ...
],

Undefined property: Fxp\Composer\AssetPlugin\Repository\BowerRepository::$repoConfig

`D:\wamp64\www\fpv1>composer require frostealth/yii2-aws-s3 ~2.0
./composer.json has been updated
Loading composer repositories with package information
Updating dependencies (including require-dev)

[ErrorException]
Undefined property: Fxp\Composer\AssetPlugin\Repository\BowerRepository::$repoConfig

require [--dev] [--prefer-source] [--prefer-dist] [--no-progress] [--no-update] [--update-no-dev] [--update-with-dependencies] [--ignore-platform-reqs] [--sort-packages] [-o|--optimize-autoloader] [-a|--classmap-authoritative] [--] []...`

Compatibility with php 7.2

PHP Compile Error 'yii\base\ErrorException' with message 'Cannot use yii\base\Object as Object because 'Object' is a special class name'

in ../vendor/frostealth/yii2-aws-s3/src/HandlerResolver.php:9

Stack trace:
#0 [internal function]: yii\base\ErrorHandler->handleFatalError()
#1 {main}

As sujesting yii2 team in upgrade note:
"For extensions that have classes extending from yii\base\Object, to be compatible with PHP 7.2, you need to require "yiisoft/yii2": "~2.0.13" in composer.json and change affected classes to extend from yii\base\BaseObject instead. It is not possible to allow Yii versions <2.0.13 and be compatible with PHP 7.2 or higher."

'upload' returns values, breaking model functions when used

When the upload() or put() function is used in a model's public function, the values the s3 function returns will cause the rest of the model function to break, since a model function always requires to return true in order to continue.

Unknown Property – yii\base\UnknownPropertyException Setting unknown property: frostealth\yii2\aws\s3\Service::options

's3' => [
'class' => 'frostealth\yii2\aws\s3\Service',
'region' => 'ap-south-1',
'credentials' => [ // Aws\Credentials\CredentialsInterface|array|callable
'key' => 'xxxxxxxxxxxxxx',
'secret' => 'xxxxxxxxxxxxxxxx',
],
'options' => [
'http' => [
'verify' => false,
],
],
'defaultBucket' => 'b2b-img-search',
'defaultAcl' => 'public-read',
'debug' => false, // bool|array
],
i am getting error

13

my question is where should i use 'options' => [
'http' => [
'verify' => false, ],
],
value property??
2) if comment options value e.g;
's3' => [
'class' => 'frostealth\yii2\aws\s3\Service',
'region' => 'ap-south-1',
'credentials' => [ // Aws\Credentials\CredentialsInterface|array|callable
'key' => 'AKIAI6FFJVI5B64ZQE3Q',
'secret' => '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',
],
// 'options' => [
// 'http' => [
// 'verify' => false,
// ],
// ],
'defaultBucket' => 'b2b-img-search',
'defaultAcl' => 'public-read',
'debug' => false, // bool|array
],

then i am getting this error..

123

How can I get list of files?

Hi.
Thanks for your component.
Everything is fine and pretty simple. But I have a question about getting list of object. This simple operation looks not obvious.

Have I understood it correctly, I should make custom command class, handler for it and run something like lines bellow?

class CustomCommand implements Command, HasBucket
{}

class CustomCommandHandler extends Handler
{}

$command = $s3->create(CustomCommand::class);
$result = $s3->execute($command);

Thanks in advance.

unlink() function is not working after upload to s3

hi,

I have a image file in local directory, So i will upload it to aws s3 using $s3->commands()->upload('blabla')->execute(); After uploaded successfully, i want to remove local image file using php unlink() function. But
I get an error: unlink('path/to/local/file') Resource temporarily unavailable

I searched a lot in google. Some object/variable is holding on to the image for some reason...

How can i solve it?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.