Snuze

Using the Snuze object

This section discusses using Snuze to talk to Reddit's API.

Note: Snuze is in a preview release phase with limited functionality. The current version supports some common read-only actions while the overall design is being stabilized. Features like posting content and handling PMs are not yet supported. As more actions are implemented, they'll be documented here.

Contents

Overview

Working with Snuze involves three main activities:

  1. Creating an array of configuration parameters
  2. Passing that array into a SnuzeFactory to get a Snuze object
  3. Calling methods on the Snuze object to interact with Reddit's API

The first two steps are demonstrated in the Getting Started guide. Here's a refresher of how that looks:

<?php
require_once __DIR__ . '/vendor/autoload.php';

/* Set authentication and configuration parameters */
$config = [
   'auth.client_id'     => 'your-client-id-from-reddit',
   'auth.client_secret' => 'your-secret-from-reddit',
   'auth.username'      => 'your-reddit-username',
   'auth.password'      => 'your-reddit-password',
   'auth.user_agent'    => 'php:YourAwesomeBot 1.2.3 (by /u/your-reddit-username)',
];

/* Pass the config array to a SnuzeFactory to get a Snuze object */
$snuze = (new \snuze\SnuzeFactory($config))->getSnuze();

This section assumes you've made it this far, and picks up to cover the third act, using the Snuze object to interact with Reddit.

Fetching Subreddits

To retrieve information about a subreddit, use the Snuze::fetchSubreddit() method. It accepts one argument, the plain name of the subreddit you want to get data about:

/* Get a subreddit's data */
$sub = $snuze->fetchSubreddit('recipes');

/* Take a look at what came back */
var_dump($sub);

fetchSubreddit() returns a Subreddit object, which exposes the subreddit's attributes through its getter methods.

If the specified subreddit can't be fetched, an exception is thrown. This will happen when:

If for some reason you don't know the target subreddit's name, but you do have its "thing" fullname (e.g. t5_2qh56), you can still get its data but you'll need to use a different approach. See Fetching Info for Arbitrary "Things".

To retrieve links (also called posts or submissions) from a subreddit, use one of the Snuze::fetchLinks...() methods. These methods return a LinkListing object, which is an iterable collection of Link objects. Reddit's API lets you get up to 100 links at a time; pagination over larger result sets is discussed later in this document.

Each method described below corresponds to a different sort order for the returned links:

When you visit a subreddit in a browser or an app, the default sort order is usually "Hot." The Snuze::fetchLinksHot() method lets you retrieve a subreddit's links in this sort order. Here, we fetch the top 10 hot links from /r/Art:

foreach ($snuze->fetchLinksHot('Art', 10) as $link) {
   echo 'On ' . date('Y-m-d \a\t H:i', (int) $link->getCreated()) . ' UTC, '
       . "{$link->getAuthor()} posted: " . $link->getTitle() . PHP_EOL;
}
On 2019-08-24 at 16:07 UTC, Namendart posted: "Mama...?", Me, Digital, 2019
On 2019-08-24 at 13:18 UTC, [deleted] posted: Insomnia, me, watercolor, 2019
...

This example also demonstrates what happens when a user deletes their account after posting a link. The Link::getAuthor() method will return [deleted] instead of a valid username.

When requesting a "Hot" link listing, you can specify an optional locality code to ask Reddit for links that are "Hot" among Redditors in that geographic region. This example looks for posts in /r/aviation that are popular in Australia. Note that because $locality is the 7th argument to the method, some placeholder values must be passed for other arguments.

$ozLinks = $snuze->fetchLinksHot('aviation', 50, $after = null, $before = null,
       $count = null, $showAll = false, $locality = 'AU');
foreach ($ozLinks as $link) {
   echo 'Australians like: ' . $link->getTitle() . PHP_EOL;
}
Australians like: The Red Arrows with 2 F22s and 2 F35s [3000x3609]
Australians like: Two Japanese F-4s, one plain and one SPICY
...

Valid locality codes are defined here.

The Snuze::fetchLinksNew() method lets you retrieve a subreddit's links in reverse chronological order, with the most recently submitted links first. Here, we fetch the top 100 new links from /r/askscience:

foreach ($snuze->fetchLinksNew('aSKSCieNCe', 100) as $link) {
   echo date('Y-m-d H:i', (int) $link->getCreated()) . ': ' . $link->getTitle() . PHP_EOL;
}
2019-08-24 21:09: How do the kidneys know how much water to filter out of the blood they process?
2019-08-24 20:35: How do humans determine the location of sounds?
2019-08-24 18:44: With the Amazon fires what impact will it have on all the different wildlife there?
...

As you can see, the links get progressively older as the collection is iterated. This example also demonstrates that the $subredditName argument to the Snuze::fetchLinks...() methods is case-insensitive.

The Snuze::fetchLinksRising() method lets you retrieve a subreddit's links sorted by upward vote momentum. Here, we fetch the top 10 rising links from /r/Catloaf:

foreach ($snuze->fetchLinksRising('catloaf', 10) as $link) {
   echo "Link ID {$link->getId()} has a score of {$link->getScore()} and "
       . "{$link->getNumComments()} comments" . PHP_EOL;
}
Link ID cv15t8 has a score of 5 and 0 comments
Link ID cutfmk has a score of 2129 and 11 comments
Link ID cuuyji has a score of 453 and 4 comments
...

Also shown here are a few more of Link's getter methods.

The Snuze::fetchLinksControversial() method retrieves the links in a subreddit which have seen the greatest number of both upvotes and downvotes. Here, we fetch the current most controversial single link from /r/ToolBand.

foreach ($snuze->fetchLinksControversial('ToolBand', 1) as $link) {
   echo date('Y-m-d H:i', (int) $link->getCreated()) . ': ' . $link->getTitle() . PHP_EOL;
}
2019-08-25 07:22: Deceiver!

When requesting a "Controversial" link listing, you can specify an optional time period to widen or narrow the result set. Valid periods are 'hour', 'day', 'week', 'month', 'year', or 'all'; 'day' being the default. This example finds the most controversial submission from /r/ToolBand in the past year. Note that because $period is the 7th argument to the method, some placeholder values must be passed for other arguments.

foreach ($snuze->fetchLinksControversial('ToolBand', 1, $after = null,
       $before = null, $count = null, $showAll = false, $period = 'year') as $link) {
   echo date('Y-m-d H:i', (int) $link->getCreated()) . ': ' . $link->getTitle() . PHP_EOL;
}
2018-08-31 20:52: New Album Hits Stores Xmas 2018!

The Snuze::fetchLinksTop() method retrieves the highest scored links from a subreddit. Here, we fetch the current top 50 links from /r/HotPeppers:

foreach ($snuze->fetchLinksTop('HotPeppers', 50) as $link) {
   echo "'{$link->getTitle()}' link domain is: {$link->getDomain()}" . PHP_EOL;
}
'Made some Pineapple Mango Ghost Pepper Jam' link domain is: i.redd.it
'Almost too pretty to pick' link domain is: i.redd.it
'Best looking pheno so far. Most of the others lack a tail' link domain is: i.redd.it
...

When requesting a "Top" link listing, you can specify an optional time period to widen or narrow the result set. Valid periods are 'hour', 'day', 'week', 'month', 'year', or 'all'; 'day' being the default. This example finds the most upvoted post from /r/HotPeppers in the past year. Note that because $period is the 7th argument to the method, some placeholder values must be passed for other arguments.

foreach ($snuze->fetchLinksTop('HotPeppers', 50, $after = null,
       $before = null, $count = null, $showAll = false, $period = 'year') as $link) {
   echo "'{$link->getTitle()}' has URL: {$link->getUrl()}" . PHP_EOL;
}
'First harvest off my Carolina Reaper from Home Depot.' has URL: https://i.imgur.com/JtiGbTj.jpg

The Snuze::fetchLinksRandom() method lets you retrieve random links from a subreddit.

This method doesn't work on subreddits where the "allow this subreddit to be exposed to users in /r/all, /r/popular, default, and trending lists" preference is disabled. For these subreddits, an empty LinkListing is returned.

Here, we get 5 random submissions from /r/dogs:

foreach ($snuze->fetchLinksRandom('dogs', 5) as $link) {
   echo "{$link->getAuthor()} submitted: {$link->getTitle()}" . PHP_EOL;
}
wheretohides submitted: [Help] The vet said to put my dog on a grain diet
Ph4zers submitted: [Help] Looking for a couch cover that is dog friendly
Zeewulfeh submitted: [Vent] [Discussion] A Tale of Two Mutts
...

Under the hood, this method works differently than the others: a separate API request must be made for each random link. If you request a large number of random links, retrieving them will take some time and can run you over the API rate limit pretty quickly.

Reddit has a hard limit of 1,000 results for any collection. The API will stop returning data after 1,000 links.

The previous examples demonstrate getting a single group of links from a subreddit's front page, sorted in various orders. Reddit's API returns a maximum of 100 results at a time, so if you want to fetch more, you'll need to page through the target subreddit in batches of 100. Paging over a subreddit is accomplished by passing a couple extra arguments to the fetchLinks...() methods:

The value to supply for $after in your next request comes from the response to your last request; you access it by calling getAfter() on the LinkListing object. You'll need to keep track of $count on your own, but as you can see in the example below, it's not hard to do.

Here's how you might get the hottest 500 links from /r/freebsd:

/* A counter for how many links have been fetched */
$count = 0;

/* Track the ID of the last link received from the API */
$after = null;

while ($count < 500) {
   /*
    * Fetch the next batch of links. The first time through the loop,
    * $after is null and $count is 0; they get updated below.
    */
   $links = $snuze->fetchLinksHot('freebsd', 100, $after, null, $count);

   /* Do something with the links */
   foreach ($links as $link) {
       $idx = sprintf('%03d', @++$i); //For demonstration purposes only
       echo "{$idx}: {$link->getFullname()}: {$link->getTitle()}" . PHP_EOL;
   }

   /*
    * Update the value of $after by calling getAfter() on the LinkListing object.
    * Break if the API told us there are no more results.
    */
   if (empty($after = $links->getAfter())) {
       break;
   }

   /* Update the number of links that have been seen */
   $count += count($links);
}
001: t3_czlppo: Dumb question about base system
002: t3_czq3hd: How to access backup drive
...
500: t3_ahku05: Firewall Syntax Error

Sometimes the API unexpectedly returns an empty listing, even when you know there are more results. In that scenario, a loop like this will terminate prematurely. If you've ever clicked next> on Reddit's website only to be greeted with "there doesn't seem to be anything here," this is the same behavior.

Fetching Accounts

Other Users' Accounts

To retrieve basic information about another user's account, call the Snuze::fetchUser() method. It accepts the target username as its sole argument, and returns a UserAccount object.

$user = $snuze->fetchUser('washingtonpost');
$created = date('Y-m-d', (int) $user->getCreated());
$gold = $user->getIsGold() ? "has" : "doesn't have";
echo "{$user->getName()} was created {$created}, has {$user->getCommentKarma()}"
   . " comment karma, and {$gold} gold" . PHP_EOL;
washingtonpost was created 2017-04-21, has 332613 comment karma, and has gold

Your Own Account

Reddit lets you obtain more extensive data about your own account, i.e. the currently authenticated API user. Use the Snuze::fetchMyAccount() method to retrieve this information. It returns a MyAccount object.

$me = $snuze->fetchMyAccount();
$susp = $me->getIsSuspended() ? 'is' : "isn't";
echo "The current user {$susp} suspended, has {$me->getInboxCount()} "
   . "unread messages, and owns {$me->getGoldCreddits()} gold creddits" . PHP_EOL;
The current user isn't suspended, has 2 unread messages, and owns 0 gold creddits

Fetching Info for Arbitrary "Things"

Several types of entities can be fetched by ID in bulk mode. The Snuze::fetchInfo() method will retrieve up to 100 arbitrary subreddits, links, or comments (in any combination thereof). It accepts an array of "thing" fullnames to identify your targets, and returns an iterable Listing object.

$targets = ['t5_2qp8q', 't3_d1d3lu']; //Supply up to 100 fullnames
$listing = $snuze->fetchInfo($targets);
foreach ($listing as $thing) {
   echo "Got thing {$thing->getFullname()} of type " . get_class($thing) . PHP_EOL;
}
Got thing t5_2qp8q of type snuze\Reddit\Thing\Subreddit
Got thing t3_d1d3lu of type snuze\Reddit\Thing\Link

Retrieving entities in bulk with fetchInfo() is a good strategy for reducing your total API requests. Not only is this more efficient, it can help keep you under the API rate limit.