PHPackages                             pyrsmk/streams - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Image &amp; Media](/categories/media)
4. /
5. pyrsmk/streams

AbandonedArchivedLibrary[Image &amp; Media](/categories/media)

pyrsmk/streams
==============

Unified social streams

1.2.0(9y ago)115MITPHP

Since Feb 7Pushed 9y ago2 watchersCompare

[ Source](https://github.com/pyrsmk/Streams)[ Packagist](https://packagist.org/packages/pyrsmk/streams)[ RSS](/packages/pyrsmk-streams/feed)WikiDiscussions master Synced 1mo ago

READMEChangelogDependencies (5)Versions (11)Used By (0)

Streams 1.2.0
=============

[](#streams-120)

Streams aims to unify several social feeds with the same API. It is heavily based on Guzzle and async requests.

This library is part of the Myriade 2 project (link coming soon).

It currently supports :

- DeviantArt
- Dribbble
- Facebook
- 500px
- Flickr
- Google Plus
- Instagram
- Reddit
- Vimeo
- Youtube

Install
-------

[](#install)

```
composer require pyrsmk/streams

```

A quick example
---------------

[](#a-quick-example)

Let's see how we can get 50 photos from a National Geographic album on Facebook :

```
$stream = new Streams\Facebook\Album('10150205173893951', [
    'api' => '*****',
    'secret' => '*****',
    'limit' => 50
]);

$stream->get()->then(function($elements) {
    // Print all retrieved images
    foreach($elements as $element) {
        echo "";
    }
    // calling wait() is needed only if you want to wait
    // for the request to complete before continue the script
})->wait();
```

### Notes

[](#notes)

The several supported APIs don't support pagination similarly. While pagination is completely transparent in Streams, if we don't set a limit in the stream parameters, the stream will try to get all the possible elements. Often, the stream is unable to get all existing elements, because the corresponding API forbids it (the pagination is incomplete). But some streams have an infinite pagination (they get all existing elements), and the request can take a really long time, even throw a memory exceeded exception from PHP (our tests showed us that PHP crashes around 10000 retrieved elements).

Types
-----

[](#types)

Each element can be of 4 different types : `text`, `image`, `video` and `embed`. Embed can be an embedded video, or any other HTML code that an API can return.

Here's the data returned by each type of element.

Text
----

[](#text)

```
[
    'type' => 'text',
    'date' => integer,
    'author' => string,
    'avatar' => string,
    'title' => string,
    'description' => string,
    'permalink' => string
]
```

Image
-----

[](#image)

```
[
    'type' => 'image',
    'date' => integer,
    'author' => string,
    'avatar' => string,
    'title' => string,
    'description' => string,
    'permalink' => string,
    'source' => string,
    'width' => integer,
    'height' => integer,
    'mimetype' => string
]
```

Video
-----

[](#video)

```
[
    'type' => 'video',
    'date' => integer,
    'author' => string,
    'avatar' => string,
    'title' => string,
    'description' => string,
    'permalink' => string,
    'source' => string,
    'width' => integer,
    'height' => integer,
    'mimetype' => string,
    'preview' => [
        'source' => string,
        'width' => integer,
        'height' => integer
    ]
]
```

Embed
-----

[](#embed)

```
[
    'type' => 'embed',
    'date' => integer,
    'author' => string,
    'avatar' => string,
    'title' => string,
    'description' => string,
    'permalink' => string,
    'html' => string,
    'width' => integer,
    'height' => integer,
    'preview' => [
        'source' => string,
        'width' => integer,
        'height' => integer
    ]
]
```

### Notes

[](#notes-1)

- mime types are retrieved automatically by Streams; it creates many additional requests but since they're run all at once aynschronously, the footprint is trivial

Streams
-------

[](#streams)

Here's the list of the available streams and their respective options.

Options
-------

[](#options)

Streams have some base options :

- `nsfw` : `true` to retrieve NSFW elements (default : `false`)
- `limit` : a number of elements to get (default : `false`)
- `select` : list the element types to get (default : `['text', 'image', 'video', 'embed']`)

Streams can have several additional options, according to the respective API. They often need an `api` and `secret` options fulfilled. These options are usually the `client_id` and `client_secret` after the creation of an application on the remote website.

File system
-----------

[](#file-system)

```
new Streams\FileSystem\Directory('some/path/', [
    'limit' => 50
]);
```

### Notes

[](#notes-2)

- support image and video types
- do not support video previews
- do not support permalinks
- do not support NSFW
- do not support author and avatar
- do not support description

DeviantArt
----------

[](#deviantart)

Get images from a category (the ID of a category is visible in the URI of the corresponding page on DeviantArt) :

```
new Streams\DeviantArt\Category('photography/nature', [
    'api' => '*****',
    'secret' => '*****',
    'nsfw' => false,
    'limit' => 50,
    // either 'newest', 'hot', 'undiscovered', 'popular',
    // 'popular8h' (default), 'popular24h', 'popular3d', 'popular1w' or 'popular1m'
    'type' => 'newest'
]);
```

Get root images on a gallery of a user (other specific galleries are not supported) :

```
new Streams\DeviantArt\User('numyumy', [
    'api' => '*****',
    'secret' => '*****',
    'nsfw' => false,
    'limit' => 50
]);
```

### Notes

[](#notes-3)

The DeviantArt API is not really mature. We had pretty bad times with it, and as far as we can tell, there're many things that don't work because of design problems on the API (and some other weird things).

- support texts and images
- impossible to get the description for an image
- impossible to get videos
- impossible to get a specific gallery ()
- sometimes requests can be **really** slow

Dribbble
--------

[](#dribbble)

Get images from a bucket :

```
new Streams\Dribbble\Bucket('476346-Usabilty-examples', [
    'token' => '*****',
    'limit' => 50
]);
```

Get images from a project :

```
new Streams\Dribbble\Project('280804-Graphics', [
    'token' => '*****',
    'limit' => 50
]);
```

Get images from a team :

```
new Streams\Dribbble\Team('Creativedash', [
    'token' => '*****',
    'limit' => 50
]);
```

Get images from a user :

```
new Streams\Dribbble\User('BurntToast', [
    'token' => '*****',
    'limit' => 50
]);
```

### Notes

[](#notes-4)

- support images
- do not support NSFW

Facebook
--------

[](#facebook)

Get images from an album on a page :

```
new Streams\Facebook\Album('1710763805841434', [
    'api' => '*****',
    'secret' => '*****',
    'limit' => 50
]);
```

Get profile photos from a page :

```
new Streams\Facebook\Album('ChatNoirDesign', [
    'api' => '*****',
    'secret' => '*****',
    'limit' => 50
]);
```

Get root (uploaded) photos from a page :

```
new Streams\Facebook\Album('ChatNoirDesign', [
    'api' => '*****',
    'secret' => '*****',
    'limit' => 50,
    'type' => 'uploaded'
]);
```

Get videos from a page :

```
new Streams\Facebook\Videos('ChatNoirDesign', [
    'api' => '*****',
    'secret' => '*****',
    'limit' => 50
]);
```

Get notes (articles) from a page :

```
new Streams\Facebook\Notes('289941984496813', [
    'api' => '*****',
    'secret' => '*****',
    'limit' => 50
]);
```

### Notes

[](#notes-5)

- support image and embed types
- there's no description on images
- notes cannot return a date
- do not support NSFW

500px
-----

[](#500px)

Get images from a user :

```
new Streams\FiveHundredPx\User('ademgider', [
    'api' => '*****',
    'nsfw' => false,
    'limit' => 50
]);
```

Get images from a user's gallery :

```
new Streams\FiveHundredPx\Gallery('ademgider/city-map', [
    'api' => '*****',
    'nsfw' => false,
    'limit' => 50
]);
```

### Notes

[](#notes-6)

- support images

Flickr
------

[](#flickr)

Get medias from a user :

```
new Streams\Flickr\User('cannon_s5_is', [
    'api' => '*****',
    'limit' => 50
]);
```

Get medias from a user's album :

```
new Streams\Flickr\Album('cannon_s5_is/72157625103228853', [
    'api' => '*****',
    'limit' => 50
]);
```

- support image and embed types

### Notes

[](#notes-7)

- cannot get NSFW pictures, because they are not public

Google Plus
-----------

[](#google-plus)

Get medias from people :

```
new Streams\GooglePlus\People('+frandroid', [
    'api' => '*****',
    'limit' => 50
]);
```

### Notes

[](#notes-8)

- support text, image and embed types
- infinite pagination
- do not support NSFW

Instagram
---------

[](#instagram)

Get last images from a user :

```
new Streams\Instagram\User('ademgider/city-map', [
    'limit' => 20
]);
```

### Notes

[](#notes-9)

- support image and video types
- since 2016 June, it is impossible communicate with the API without authentifying the user; since Streams lies on public access (because we DO NOT want to display OAuth confirmations to the final user), we just can get the 20 last posts of an Instagram account
- do not support NSFW

Reddit
------

[](#reddit)

Get medias from a subreddit :

```
new Streams\Reddit\Subreddit('earthporn', [
    'nsfw' => false,
    'limit' => 50,
    // either 'popular', 'new' (default), 'rising', 'controversial', 'top' or 'gilded'
    'type' => 'new'
]);
```

Get medias from user's posts :

```
new Streams\Reddit\User('hansiphoto', [
    'nsfw' => false,
    'limit' => 50
]);
```

### Notes

[](#notes-10)

- support text, image and embed types
- the API can be a bit slow

Vimeo
-----

[](#vimeo)

Get videos from a category :

```
new Streams\Vimeo\Category('food', [
    'api' => '*****',
    'secret' => '*****',
    'nsfw' => false,
    'limit' => 50
]);
```

Get videos from a channel :

```
new Streams\Vimeo\Channel('comedy', [
    'api' => '*****',
    'secret' => '*****',
    'nsfw' => false,
    'limit' => 50
]);
```

Get videos from a group :

```
new Streams\Vimeo\Group('animation', [
    'api' => '*****',
    'secret' => '*****',
    'nsfw' => false,
    'limit' => 50
]);
```

Get videos from a user :

```
new Streams\Vimeo\User('loispatino', [
    'api' => '*****',
    'secret' => '*****',
    'nsfw' => false,
    'limit' => 50
]);
```

### Notes

[](#notes-11)

- support embed type

Youtube
-------

[](#youtube)

Get videos from a channel :

```
new Streams\Youtube\Channel('UCCMxHHciWRBBouzk-PGzmtQ', [
    'api' => '*****',
    'limit' => 50
]);
```

Get videos from a playlist :

```
new Streams\Youtube\Playlist('PLWmL9Ldoef0sKB07aXA1ekfyIqu-47rV6', [
    'api' => '*****',
    'limit' => 50
]);
```

### Notes

[](#notes-12)

- support embed type
- do not support NSFW

Group requests
--------------

[](#group-requests)

If you want to get several streams at once (and because it's more effective), you can use the Guzzle Pool class :

```
// Add Facebook
$streams[] = function() {
    $stream = new Streams\Facebook\Album('10150205173893951', [
        'api' => '*****',
        'secret' => '*****',
        'limit' => 50
    ]);
    return $stream->get()->then(function($elements) {
        // Print all retrieved images
        foreach($elements as $element) {
            echo "";
        }
    });
};

// Add Flickr
$streams[] = function() {
    $stream = new Streams\Flickr\Album('cannon_s5_is/72157625103228853', [
        'api' => '*****',
        'limit' => 50
    ]);
    return $stream->get()->then(function($elements) {
        // Print all retrieved images
        foreach($elements as $element) {
            echo "";
        }
    });
};

// Add Instagram
$streams[] = function() {
    $stream = new Streams\Instagram\User('ladylikelilymusic');
    return $stream->get()->then(function($elements) {
        // Print all retrieved images
        foreach($elements as $element) {
            echo "";
        }
    });
};

// Run requests
$guzzle = new GuzzleHttp\Client(['verify' => false]);
$pool = new GuzzleHttp\Pool($guzzle, $streams);
$pool->promise()->wait();
```

For more reading on concurrent requests with Guzzle, please read the [documentation](http://docs.guzzlephp.org/en/latest/quickstart.html#concurrent-requests).

License
-------

[](#license)

[MIT](http://dreamysource.mit-license.org).

###  Health Score

28

—

LowBetter than 54% of packages

Maintenance20

Infrequent updates — may be unmaintained

Popularity7

Limited adoption so far

Community4

Small or concentrated contributor base

Maturity69

Established project with proven stability

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~1 days

Total

10

Last Release

3367d ago

### Community

Maintainers

![](https://www.gravatar.com/avatar/7f97d81cfd6d30587cdae24925bc0899331394d723d04ee4b76eb9435a565fe9?d=identicon)[pyrsmk](/maintainers/pyrsmk)

---

Tags

facebookinstagramgoogleyoutubemediasocialdeviantartvimeoredditflickrgoogleplusdribbble500px

### Embed Badge

![Health badge](/badges/pyrsmk-streams/health.svg)

```
[![Health](https://phpackages.com/badges/pyrsmk-streams/health.svg)](https://phpackages.com/packages/pyrsmk-streams)
```

###  Alternatives

[hwi/oauth-bundle

Support for authenticating users using both OAuth1.0a and OAuth2 in Symfony.

2.4k21.5M68](/packages/hwi-oauth-bundle)[cohensive/embed

Media Embed (for Laravel or as a standalone).

120370.4k](/packages/cohensive-embed)[and/oauth

Simple and amazing OAuth library with many providers. Just try it out!

4645.2k2](/packages/and-oauth)[cohensive/oembed

Media embed generation using OEmbed protocol.

3567.1k](/packages/cohensive-oembed)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
