Code Monkey home page Code Monkey logo

snoowrap's Introduction

snoowrap Build Status Gitter chat

A fully-featured JavaScript wrapper for the reddit API. (Documentation)

Features

  • snoowrap provides a simple interface to access every reddit API endpoint. For example, the method to get a user profile is just getUser(), and the method to upvote something is just upvote().
  • snoowrap is non-blocking; all of its API calls are asynchronous and return bluebird Promises. This means that you can handle concurrent requests however you want to, and you can use snoowrap as part of a larger process without it holding everything back.
  • Each snoowrap object is completely independent. This means that you can have scripts from separate accounts making requests at the same time.
  • After you provide a token once, snoowrap will refresh it on its own from then on -- you won't have to worry about authentication again.
  • snoowrap uses lazy objects, so it never fetches more than it needs to.
  • snoowrap has built-in ratelimit protection. If you hit reddit's ratelimit, you can choose to queue the request, and then run it after the current ratelimit period runs out. That way you won't lose a request if you go a bit too fast.
  • snoowrap will retry its request a few times if reddit returns an error due to its servers being overloaded.

These features ensure that you can write less boilerplate code and focus more on actually doing what you want to do.


snoowrap's methods are designed to be as simple and consistent as possible. So the following expression:

r.getSubmission('2np694').body

...will return a Promise. So will this one:

 r.getSubmission('2np694').author.name
 // --> returns a Promise for the string 'DO_U_EVN_SPAGHETTI'
 // (this submission's author's name)

The above will return a Promise for the author's name, without having to deal with callback hell or .then statements. You can chain multiple API calls together:

r.getSubmission('2np694').subreddit.getModerators()[0].name
// --> returns a Promise for the string 'krispykrackers'
// (this submission's subreddit's first mod's name)

...or chain actions together with fluent syntax:

r.getSubreddit('snoowrap')
  .submitSelfpost({title: 'Discussion Thread', text: 'Hello! This is a thread'})
  .sticky()
  .distinguish()
  .ignoreReports()
  .assignFlair({text: 'Exciting Flair Text', css_class: 'modpost'})

snoowrap works on Node.js 4+, as well as most common browsers.


Examples

'use strict';
const snoowrap = require('snoowrap');

// NOTE: The following examples illustrate how to use snoowrap. However, hardcoding
// credentials directly into your source code is generally a bad idea in practice (especially
// if you're also making your source code public). Instead, it's better to either (a) use a separate
// config file that isn't committed into version control, or (b) use environment variables.

// Create a new snoowrap requester with OAuth credentials.
// For more information on getting credentials, see here: https://github.com/not-an-aardvark/reddit-oauth-helper
const r = new snoowrap({
  userAgent: 'put your user-agent string here',
  clientId: 'put your client id here',
  clientSecret: 'put your client secret here',
  refreshToken: 'put your refresh token here'
});

// Alternatively, just pass in a username and password for script-type apps.
const otherRequester = new snoowrap({
  userAgent: 'put your user-agent string here',
  clientId: 'put your client id here',
  clientSecret: 'put your client secret here',
  username: 'put your username here',
  password: 'put your password here'
});

// That's the entire setup process, now you can just make requests.

// Submitting a link to a subreddit
r.getSubreddit('gifs').submitLink({
  title: 'Mt. Cameramanjaro',
  url: 'https://i.imgur.com/n5iOc72.gifv'
});

// Printing a list of the titles on the front page
r.getHot().map(post => post.title).then(console.log);

// Extracting every comment on a thread
r.getSubmission('4j8p6d').expandReplies({limit: Infinity, depth: Infinity}).then(console.log)

// Automating moderation tasks
r.getSubreddit('some_subreddit_name').getModqueue({limit: 100}).filter(someRemovalCondition).forEach(flaggedItem => {
  flaggedItem.remove();
  flaggedItem.subreddit.banUser(flaggedItem.author);
});

// Automatically creating a stickied thread for a moderated subreddit
r.getSubreddit('some_subreddit_name')
  .submitSelfpost({title: 'Daily thread', text: 'Discuss things here'})
  .sticky()
  .distinguish()
  .approve()
  .assignFlair({text: 'Daily Thread flair text', css_class: 'daily-thread'})
  .reply('This is a comment that appears on that daily thread');
  // etc. etc.

// Printing the content of a wiki page
r.getSubreddit('AskReddit').getWikiPage('bestof').content_md.then(console.log);

For more examples of what can be done with snoowrap, take a look at the documentation.


Live threads

Reddit's live threads are different from most other content, in that messages are distributed through websockets instead of a RESTful API. snoowrap supports this protocol under the hood by representing the content stream as an EventEmitter. For example, the following script will stream all livethread updates to the console as they appear:

r.getLivethread('whrdxo8dg9n0').stream.on('update', console.log);

For more information, see the LiveThread documentation page.


Important note on ES6

snoowrap uses the Proxy object introduced in ES6.

If your target environment does not support Proxies, snoowrap will still function. However, method chaining as described above won't work, so your syntax will need to be a bit heavier.

Environments that support the ES6 Proxy object

  • Node 6+
  • Chrome 49+
  • Firefox 18+
  • Edge
  • Node 4 and 5 (requires the --harmony_proxies runtime flag to be enabled. e.g. node --harmony_proxies yourFile.js)

Example of how Proxy support affects behavior:

// This works in environments that support Proxies.
// However, it throws a TypeError if Proxies are not available.
r.getSubmission('47v7tm').comments[0].upvote();

// ----------

// This is equivalent and works on all platforms, but the syntax isn't as nice.
r.getSubmission('47v7tm').fetch().then(submission => {
  return submission.comments[0].upvote();
});

You can explicitly disable method chaining with r.config({proxies: false}).


To include in a project

Node:

npm install snoowrap --save
var snoowrap = require('snoowrap');

Browsers:

snoowrap is usable with module bundlers such as browserify.

Alternatively, prebuilt versions are available:

These files will occasionally be updated as new versions of snoowrap 1 are released. Since snoowrap follows semantic versioning, the changes should not break your code. However, if you would prefer to pin the version, you can specify a version number in the URL (e.g. snoowrap-v1.11.3.min.js). For a list of all available prebuilt versions, see the gh-pages branch of this repository.

When run in a browser, snoowrap will be assigned to the global variable window.snoowrap. If you want to avoid global state (or you're using two versions of snoowrap on the same page for some reason), use snoowrap.noConflict() to restore window.snoowrap to its previous value.

To build/run the tests independently

See the contributing guide and the getting started page.


License

This software is freely distributable under the MIT License.

snoowrap's People

Contributors

a-bravo avatar ardeaf avatar as-com avatar creekie1337 avatar denizdogan avatar dependabot[bot] avatar dimkk avatar dpeukert avatar drdrjojo avatar edemauro avatar greenkeeperio-bot avatar hmble avatar iketiunn avatar manueltarouca avatar markspolakovs avatar metallicity avatar mikebull avatar mindofbeholder avatar ngtmeaty avatar not-an-aardvark avatar omgimalexis avatar paul-soporan avatar please-wait avatar prazdevs avatar pthieu avatar robhanlon22 avatar venefilyn avatar xrajishx avatar zeranoe avatar zhantongz 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  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

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

snoowrap's Issues

cannot read property split of undefined

Hello,
getting this weird error.

D:\GitHub\work>node cron\scrape.js
Unhandled rejection TypeError: Cannot read property 'split' of undefined
    at D:\GitHub\work\node_modules\snoowrap\dist\request_handler.js:232:37
    at tryCatcher (D:\GitHub\work\node_modules\bluebird\js\release\util.js:16:23)
    at Promise._settlePromiseFromHandler (D:\GitHub\work\node_modules\bluebird\js\release\promise.js:510:31)
    at Promise._settlePromise (D:\GitHub\work\node_modules\bluebird\js\release\promise.js:567:18)
    at Promise._settlePromise0 (D:\GitHub\work\node_modules\bluebird\js\release\promise.js:612:10)
    at Promise._settlePromises (D:\GitHub\work\node_modules\bluebird\js\release\promise.js:691:18)
    at Async._drainQueue (D:\GitHub\work\node_modules\bluebird\js\release\async.js:138:16)
    at Async._drainQueues (D:\GitHub\work\node_modules\bluebird\js\release\async.js:148:10)
    at Immediate.Async.drainQueues (D:\GitHub\work\node_modules\bluebird\js\release\async.js:17:14)
    at runCallback (timers.js:649:20)
    at tryOnImmediate (timers.js:622:5)
    at processImmediate [as _immediateCallback] (timers.js:594:5)

Here is the code I am using:

const config = require('../config');
const snoowrap = require('snoowrap');
const subreddits = [
  'Laptop'
]
const r = new snoowrap(config.reddit);
r.getSubreddit(subreddits[0]).getNew({time: 'year'}).then(console.log);

pretty straight forward stuff.
any ideas why this is happening?

node v7.2.0 win 10m latest snoowrap lib

submitSelfpost() returning incorrect/incomplete data

Is there something incorrect I'm doing here? When I submit a selfpost, the promise that is returned by snoowrap only resolves to a Submission object with a single key: 'name':

        this.r.getSubreddit('mysub').submitSelfpost({
            title: "foo",
            text: "bar",
            sendReplies: false
        }).then(console.log);

        // console.log outputs: Submission { name: 't3_threadid' }

The title or any other parameters of the thread are not returned, which is in conflict with the documentation here: https://not-an-aardvark.github.io/snoowrap/Subreddit.html#submitSelfpost__anchor

Which clearly shows a Submission object being returned with, among other things, a title.

Using snoowrap 1.11.3 and Node 7.2.1.

Add tests/docs for general requester properties

Requester objects currently have a bunch of exposed properties such as scope, access_token_expiration, etc., but none of them are documented and there aren't any tests for them at the moment.

Getting "SyntaxError: Unexpected token ..."

Getting the following error from snoowrap.

/server/node_modules/snoowrap/node_modules/promise-chains/index.js:55
    construct: (target, args) => (wrap(target().then(result => (wrap(new result(...args))))))
                                                                                ^^^

SyntaxError: Unexpected token ...
    at exports.runInThisContext (vm.js:53:16)
    at Module._compile (module.js:374:25)
    at Object.Module._extensions..js (module.js:417:10)
    at Module.load (module.js:344:32)
    at Function.Module._load (module.js:301:12)

    at Module.require (module.js:354:17)
    at require (internal/module.js:12:17)
    at Object.<anonymous> (/server/node_modules/snoowrap/lib/snoowrap.js:7:22)
    at Module._compile (module.js:410:26)
    at Object.Module._extensions..js (module.js:417:10)
    at Module.load (module.js:344:32)
    at Function.Module._load (module.js:301:12)
    at Module.require (module.js:354:17)
    at require (internal/module.js:12:17)
    at Object.<anonymous> (/server/controllers/AuthController.js:10:16)
    at Module._compile (module.js:410:26)
    at Object.Module._extensions..js (module.js:417:10)
    at Module.load (module.js:344:32)
    at Function.Module._load (module.js:301:12)
    at Module.require (module.js:354:17)
    at require (internal/module.js:12:17)
    at module.exports (/server/routes.js:14:14)

Failed to load resource: the server responded with a status of 403 (Forbidden)

I'm trying to use snoowrap in the browser, but I keep getting a 403 error.

I created a reddit app and used reddit-oauth-helper to get a refresh token. In my code on my machine, I have my clientId, clientSecret, and refreshToken actually typed in. I just replaced them in the picture with my__isHere.

I've tried two separate sets of credentials, one for a web app and one for a script.

Also, I do plan to link to the minified version of snoowrap in the end, but I linked to the full version here to show what lines in the source code exactly are raising the error.

Thank you for your help.

PS: I am also curious why a clientID, clientSecret, and refreshToken are needed in snoowrap. I've used praw (python reddit api wrapper) before and it doesn't require any OAuth credentials, only a user_agent. Regardless, thank you again for your help.

code

error

React Native support.

I am trying to use snoowrap in a React Native environment, but because its not running in a node environment I get this issue .

I would have thought that this was something that was fix as part of #33 ?

Is there a quick workaround for this?

Curious about use of proxies.

This is really a question not an issue.

I've been trying to find a use case for proxies, and haven't really been able to justify their usage. Looking through the code, I saw that it had something to do with get, but I'm not entirely sure what the purpose of using the proxy is.

Could you let me know how you used the proxy, and why you couldn't implement the functionality without proxies?

Get author name of posts need lots of requets

For example:

r.get_hot().map(x => x.author.name).then(console.log)

While I inspect the network I found this will request every user's info for each post's author. But the author name is already exist in the response of Reddit API. Is there any way to avoid these requets?

Add support for api/morechildren

snoowrap currently uses the api/info endpoint to fetch more replies to Submissions and Comments. This has the advantage of allowing 100 comments per request rather than 20, and it's not throttled by reddit. However, the api/info endpoint doesn't return comment replies, so this requires much more requests (one request per comment) if the user actually needs to use the comment replies. There should probably be another Listing prototype function (e.g. fetch_replies_tree) that fetches the entire comment tree, with the caveat that reddit does not allow it to be used concurrently.

read_all_messages leads to Error 429

Before, I had this problem when there were no unread messages, but now everytime I try snoowrap.read_all_messages() I get:

Unhandled rejection StatusCodeError: 429 - [object Object]
    at new StatusCodeError (C:\a\node_modules\snoowrap\node_modules\request-promise\lib\errors.js:26:15)
    at Request.RP$callback [as _callback] (C:\a\node_modules\snoowrap\node_modules\request-promise\lib\rp.js:68:32)
    at Request.self.callback (C:\a\node_modules\snoowrap\node_modules\request-promise\node_modules\request\request.js:199:22)
    at emitTwo (events.js:100:13)
    at Request.emit (events.js:185:7)
    at Request.<anonymous> (C:\a\node_modules\snoowrap\node_modules\request-promise\node_modules\request\request.js:1036:10)
    at emitOne (events.js:95:20)
    at Request.emit (events.js:182:7)
    at IncomingMessage.<anonymous> (C:\a\node_modules\snoowrap\node_modules\request-promise\node_modules\request\request.js:963:12)
    at emitNone (events.js:85:20)
    at IncomingMessage.emit (events.js:179:7)
    at endReadableNT (_stream_readable.js:913:12)
    at _combinedTickCallback (node.js:377:13)
    at process._tickCallback (node.js:401:11)

As far as I know this is because the server is receiving too many requests but I have increased the request_delay of the config file and it still gives me the error.

submission.mark_as_read() returns 403

My input:

r.get_new( "my sub" ).then( function (posts) {
  posts.forEach(function (post) {
    post.mark_as_read();
  });
});

Answer:

Unhandled rejection StatusCodeError: 403 - [object Object]
    at new StatusCodeError (C:\Sites\mine\node_modules\snoowrap\node_modules\request-promise\lib\errors.js:26:15)
    at Request.RP$callback [as _callback] (C:\Sites\mine\node_modules\snoowrap\node_modules\request-promise\lib\rp.js:68:32)
    at Request.self.callback (C:\Sites\mine\node_modules\snoowrap\node_modules\request-promise\node_modules\request\request.js:199:22)
    at emitTwo (events.js:100:13)
    at Request.emit (events.js:185:7)
    at Request.<anonymous> (C:\Sites\mine\node_modules\snoowrap\node_modules\request-promise\node_modules\request\request.js:1036:10)
    at emitOne (events.js:95:20)
    at Request.emit (events.js:182:7)
    at IncomingMessage.<anonymous> (C:\Sites\mine\node_modules\snoowrap\node_modules\request-promise\node_modules\request\request.js:963:12)
    at emitNone (events.js:85:20)
    at IncomingMessage.emit (events.js:179:7)
    at endReadableNT (_stream_readable.js:913:12)
    at _combinedTickCallback (node.js:377:13)
    at process._tickCallback (node.js:401:11)

Minified file is very large

The snoowrap.min.js file is 1.31 MB as of v0.11.6, which is extremely large for a minified file. There are a few reasons for this:

  • snoowrap was originally created for Node, and while being able to run in the browser is a nice bonus, Browserify introduces a bit of boilerplate.
  • Babel addes a bit of boilerplate as well.
  • While snoowrap doesn't have many dependencies, a few of the dependencies that it does have (particularly request-promise) are very large.
  • UglifyJS, which is used to minify the file, has only preliminary support for ES6 syntax. Looking at the minified source, it seems like there are a bunch of variable names, etc. which aren't getting minified. It's possible that the minification will improve as development proceeds.

Summary of each component of the minified file (as of v0.11.6):

  1. snoowrap (core): 55.719 KB (4.25%)
  2. request-promise: 622.451 KB (47.5%)
  3. bluebird: 64.007 KB (4.89%)
  4. lodash: 46.127 KB (3.52%)
  5. promise-chains: 22.923 KB (1.75%)
  6. ws: 22.386 KB (1.71%)
  7. other (browserify shims, etc.): 476.023 KB (36.3%)

The main contributor to the file size seems to be request-promise. It might be worth looking into whether request-promise can be split into smaller modules; it has a large number of features, and snoowrap is only actually using some of them. Another option would be to use a different request library.

Create browser bundles for each major version

Previously, snoowrap had only one browser bundle: snoowrap.min.js. This was not really a good idea (and is now deprecated) because any code relying on snoowrap.min.js would have broken when snoowrap v2 came out.

Now snoowrap has bundles for specific versions, e.g. snoowrap-v1.6.1.min.js. This solves the issue of backwards-compatibility, but it makes it tedious for consumers to receive the latest updates, since they have to manually update the version number each time.

In addition to the bundles for specific versions, snoowrap should probably also have a bundle for each major version (e.g. snoowrap-v1.min.js). This would allow consumers to automatically receive new improvements without the risk of breaking their code when the major version number changes.

Improve parameter validation

Functions should accept different types of parameters when the user's intent is obvious, and they should throw easily-understandable errors on invalid input. For example, a function that expects a string parameter representing a username should also accept a RedditUser object and get the name automatically.

how do I pass some options to the request library?

I notice you're using request-promise under the hood. How can I pass some request options?

I'd like to use a proxy server which request supports as an option:

request({
   url: '...',
   proxy: 'http://192.168.1.1:8080'
});

I'd like to add a few other options as well. Is there anyway to merge in custom request options with snoowrap?

Make Listings more consistent

Listings are currently a bit difficult to work with, because they're mutable and it's possible to run into race conditions when fetching more items.

The implementation should be changed to make Listings immutable. A call to fetch more items should return a chainable Promise for a new Listing. This would make a lot of undefined behavior go away.

Send private message?

Is it possible to send a private message to a user?
If not, is there anyway to customize the email sent when you approve a user to a private subreddit?

const not supported by safari

Works great in the browser if it's chrome :)

Safari doesn't allow const.

I could babel the code, but I really prefer to just use the .min.js.

Also, in chrome while emulating iPhone 6, you are catching some error involving google maps API.

Maybe the ExtJS framework I'm using is causing the maps API error, but you shouldn't be catching it.

Unhandled rejection error

occasionally happens when running my code (https://github.com/benwaffle/best-comments)
You can run it by filling out config.js and running main.js

Unhandled rejection Error: 150972
    at snoowrap._awaitRatelimit (/home/ben/dev/best-comments/node_modules/snoowrap/dist/request_handler.js:144:11)
    at /home/ben/dev/best-comments/node_modules/snoowrap/dist/request_handler.js:80:18
    at tryCatcher (/home/ben/dev/best-comments/node_modules/bluebird/js/release/util.js:16:23)
    at Promise._settlePromiseFromHandler (/home/ben/dev/best-comments/node_modules/bluebird/js/release/promise.js:510:31)
    at Promise._settlePromise (/home/ben/dev/best-comments/node_modules/bluebird/js/release/promise.js:567:18)
    at Promise._settlePromiseCtx (/home/ben/dev/best-comments/node_modules/bluebird/js/release/promise.js:604:10)
    at Async._drainQueue (/home/ben/dev/best-comments/node_modules/bluebird/js/release/async.js:143:12)
    at Async._drainQueues (/home/ben/dev/best-comments/node_modules/bluebird/js/release/async.js:148:10)
    at Immediate.Async.drainQueues (/home/ben/dev/best-comments/node_modules/bluebird/js/release/async.js:17:14)
    at runCallback (timers.js:637:20)
    at tryOnImmediate (timers.js:610:5)
    at processImmediate [as _immediateCallback] (timers.js:582:5)

Documentation issue/question with access tokens?

Please forgive me if this question is a RTFM, and it may also belong on the reddit-oauth-helper repo. I'm trying to build an app that will make requests to Reddit to search for subreddit names and find the latest posts in a subreddit. I do not need access to a particular user's account. On the Reddit site, I set up a new app and use the web-site type. This gives me a client_id and client_secret.

In order to use snoowrap, I can either provide a client_id, client_secret, refresh_token OR an access_token. I wasn't sure what the refresh_token should be, and based on the link to reddit-oauth-helper, it seemed like I could use the command line to generate the access_token and use that.

Ok... so I did that - and in the CLI I selected Permanent, and got a token, but the result had an expires_in value.

So my question is - does Reddit not support a permanent token? If not, how would I use snoowrap to handle fetching an access_token on the fly when it needs to?

Hopefully that makes sense, and I apologize if this is not the proper repo.

` Unhandled rejection ReferenceError: is not defined` probably related to `_fulfillmentHandler0`

I try to use snoowrap in Node console (with --harmony). I give my client_id, clinet_secret, user_agent and refresh_token. But any action I try to perfrom (like r.get_hot() or r.get_subreddit("gifs")) I receive:

Promise {
  _bitField: 17825792,
  _fulfillmentHandler0: [ReferenceError:  is not defined],
  _rejectionHandler0: undefined,
  _promise0: undefined,
  _receiver0: undefined }
>Unhandled rejection ReferenceError:  is not defined
   at Object.<anonymous> (C:\Sites\mine\node_modules\snoowrap\lib\request_handler.js:42:28)
   at next (native)
   at step (C:\Sites\mine\node_modules\snoowrap\lib\request_handler.js:3:191)
   at C:\Sites\mine\node_modules\snoowrap\lib\request_handler.js:3:451
   at Promise._execute (C:\Sites\mine\node_modules\snoowrap\node_modules\bluebird\js\release\debuggability.js:272:9)
   at Promise._resolveFromExecutor (C:\Sites\mine\node_modules\snoowrap\node_modules\bluebird\js\release\promise.js:474:18)
   at new Promise (C:\Sites\mine\node_modules\snoowrap\node_modules\bluebird\js\release\promise.js:77:14)
   at Object.<anonymous> (C:\Sites\mine\node_modules\snoowrap\lib\request_handler.js:3:99)
   at Object.oauth_request (C:\Sites\mine\node_modules\snoowrap\lib\request_handler.js:68:16)
   at snoowrap.(anonymous function) [as _get] (C:\Sites\mine\node_modules\snoowrap\lib\snoowrap.js:839:41)
   at snoowrap._get_sorted_frontpage (C:\Sites\mine\node_modules\snoowrap\lib\snoowrap.js:338:17)
   at snoowrap.get_hot (C:\Sites\mine\node_modules\snoowrap\lib\snoowrap.js:348:17)
   at repl:1:4
   at REPLServer.defaultEval (repl.js:252:27)
   at bound (domain.js:287:14)
   at REPLServer.runBound [as eval] (domain.js:300:12)
   at REPLServer.<anonymous> (repl.js:417:12)
   at emitOne (events.js:82:20)
   at REPLServer.emit (events.js:169:7)
   at REPLServer.Interface._onLine (readline.js:211:10)
   at REPLServer.Interface._line (readline.js:550:8)
   at REPLServer.Interface._ttyWrite (readline.js:827:14)

snoowrap does not work in mobile browsers

(Continued from #32)

Browsers don't allow custom user-agent headers to be set in XHR requests. This is apparently causing some issues with clients being redirected to reddit's mobile site.

It seems to only cause issues on mobile browsers; while the user-agent can't be set in desktop browsers either, reddit seems to work fine with the default user-agent there.

Cannot read property 'name' of undefined

Hi, I'm a bit of a newb but I have been banging my head against this for hours now. Running node 6.2.1 and the version of your snoowrap from npm

r.get_comment("d462i0g").author.name.then(console.log);

and
r.get_submission("d462i0g").author.name.then(console.log);
both fail with TypeError: Cannot read property 'name' of undefined

However further up my page the following works:
r.get_inbox({ filter: "mentions" }).then(HandleMentions);
Where am I going wrong??!?

Error: Cannot find module './objects'

On a fresh install of 0.9.2, the following error occurs.
The objects folder is missing after install. Is this a problem with my node install or with snoowrap?

module.js:341
    throw err;
    ^

Error: Cannot find module './objects'
    at Function.Module._resolveFilename (module.js:339:15)
    at Function.Module._load (module.js:290:25)
    at Module.require (module.js:367:17)
    at require (internal/module.js:16:19)
    at Object.<anonymous> (B:\Users\thijs\Dropbox\Code\wallpaper-fetcher\node_modules\snoowrap\lib\snoowrap.js:843:20)
    at Module._compile (module.js:413:34)
    at Object.Module._extensions..js (module.js:422:10)
    at Module.load (module.js:357:32)
    at Function.Module._load (module.js:314:12)
    at Module.require (module.js:367:17)
    at require (internal/module.js:16:19)
    at Object.<anonymous> (B:\Users\thijs\Dropbox\Code\wallpaper-fetcher\app.js:4:16)
    at Module._compile (module.js:413:34)
    at Object.Module._extensions..js (module.js:422:10)
    at Module.load (module.js:357:32)
    at Function.Module._load (module.js:314:12)
    at Function.Module.runMain (module.js:447:10)
    at startup (node.js:141:18)
    at node.js:933:3

only reply to comment if no other comment has been made

I want to create a bot that replies to a comment in a thread but only if my bot has not already commented in any other comment for that post.

What's the easiest way to do this? do I need to keep track of threads it has posted in in a local database?

Search inbox

Is there a way to search my inbox? including both my user inbox and mod messages?

Global client ID rate limit when posting?

I have been using your API wrapper for creating a simple website where posts can be queued. The application is a "web app" Reddit type of app since it's running on a server only I have access to.

Because of that I expect users to authorize their own account to my web app through OAuth. All of that is working great, snoowrap is working fine here too. Everyone can be authorized.

The problem is that rate limiting seems to be tied to the client ID/secret for whatever reason, not the individual accounts (like normal Reddit or even mobile applications usually works).

That is if user_A posted something at 12:00, then user_B has to wait 10 minutes before they are allowed to post. If user_B has something queued to post at 12:05 they get a rate limit error that they have to wait for X minutes (in this case probably five minutes). The two accounts have nothing to do with each other, only that they are using the same service (mine). In this example both accounts are established accounts with one being five years old, the other two. One has over 2k karma points, the other ~40 or so.
However since the service is public for anyone to use I can't expect or know what kind of accounts are connected. Hence it is not fair that million_karma_power_user_A has to wait 10 minutes just because zero_karma_new_user_B posted something minutes before million_karma_power_user_A.
The Reddit app was created by the five year old accounts with over 2k karma points so that account should not be the problem.

I created a post over at /r/redditdev but got no meaningful answer to this question.

Do you have any idea what is causing this issue? I assume this is the way that Reddit works and have nothing to do with your wrapper but lack of answers made me create this issue. You might have knowledge of how Reddit works or know why I am getting a global client ID rate limit when submitting links/self posts.

I really don't want to have users type in their username/password. This doesn't seem very secure or at least trustworthy. Then I feel like I would have to open source it just to prove I am not doing anything malicious with their account information. I believe OAuth is the best but this is very limiting for my service. It would scale horribly with even 100 users having queued posts where I have to re-queue every time any post for any user fails.

Not collecting more than 1000 listings?

Not sure if this is a bug or what, but after 1000 listings have been collected for a certain call, the queries stop. For example, if I try to request the top 2000 listings in /r/learnprogramming, I see this in debug mode:

[debug] Received a 200 status code from a getrequest sent to https://oauth.reddit.com/r/learnprogramming/top?raw_json=1&count=9999&limit=2000. ratelimitRemaining: 599 [debug] Received a 200 status code from agetrequest sent to https://oauth.reddit.com/r/learnprogramming/top?raw_json=1&count=9999&limit=1900&after=t3_4d1etw. ratelimitRemaining: 598 [debug] Received a 200 status code from agetrequest sent to https://oauth.reddit.com/r/learnprogramming/top?raw_json=1&count=9999&limit=1800&after=t3_4ckgb4. ratelimitRemaining: 597 [debug] Received a 200 status code from agetrequest sent to https://oauth.reddit.com/r/learnprogramming/top?raw_json=1&count=9999&limit=1700&after=t3_3v17bs. ratelimitRemaining: 596 [debug] Received a 200 status code from agetrequest sent to https://oauth.reddit.com/r/learnprogramming/top?raw_json=1&count=9999&limit=1600&after=t3_3pjrqc. ratelimitRemaining: 595 [debug] Received a 200 status code from agetrequest sent to https://oauth.reddit.com/r/learnprogramming/top?raw_json=1&count=9999&limit=1500&after=t3_52h90d. ratelimitRemaining: 594 [debug] Received a 200 status code from agetrequest sent to https://oauth.reddit.com/r/learnprogramming/top?raw_json=1&count=9999&limit=1400&after=t3_4lwus2. ratelimitRemaining: 593 [debug] Received a 200 status code from agetrequest sent to https://oauth.reddit.com/r/learnprogramming/top?raw_json=1&count=9999&limit=1300&after=t3_4b49co. ratelimitRemaining: 592 [debug] Received a 200 status code from agetrequest sent to https://oauth.reddit.com/r/learnprogramming/top?raw_json=1&count=9999&limit=1200&after=t3_3w4vzw. ratelimitRemaining: 591 [debug] Received a 200 status code from agetrequest sent to https://oauth.reddit.com/r/learnprogramming/top?raw_json=1&count=9999&limit=1100&after=t3_52o33q. ratelimitRemaining: 590 [debug] Received a 200 status code from aget request sent to https://oauth.reddit.com/r/learnprogramming/top?raw_json=1&count=9999&limit=1000&after=t3_4256ur. ratelimitRemaining: 589

And then it just stops. As you can see, the limit param is still at 1000, meaning there are 1000 more listings that I still have not received. Digging into the code I found that the query.after value was not being set on the last call which caused the queries to stop, however I'm not sure what exactly that implies. Am I missing something here?

mark_messages_as_read applies only to messages (t4) and not comments (t1)

Hi.

at the moment

r.mark_messages_as_read(['51shsd', '51shxv'])

will only work if those are IDs of private messages. If I would like to mark as read messages that were comments to my users comments it would not work. Source code indicates why is that

const message_ids = messages.map(message => add_fullname_prefix(message, 't4_'));

My question is , would it be possible to customize this behavior a bit? Or is there another way to mark comment as read?

How to expand a particular comment's replies?

Context: I'm writing a Reddit client. I want to re-implement the "load more comments" button.

Suppose I get a submission's comments tree via r.getSubmission('...').comments. Is there a way to get a new version of that comments tree, with a particular "More" node expanded?

PrivateMessage replies are arranged incorrectly

The reddit API returns message info in a very strange format. For example, suppose Message B is a reply to Message A, and Message C is a reply to message B. The most reasonable way to expose this structure would look something like this:

PrivateMessage {
  body: 'Message A',
  replies: [
    PrivateMessage {
      body: 'Message B',
      replies: [
        PrivateMessage {
          body: 'Message C',
          replies: []
        }
      ]
    }
  ]
}

However, the reddit API exposes in this general structure:

PrivateMessage {
  body: 'Message A',
  parent_id: null
  replies: [
    PrivateMessage {
      body: 'Message B',
      parent_id: "(Message A's fullname)"
      replies: '',
    },
    PrivateMessage {
      body: 'Message C',
      parent_id: "(Message B'd fullname)"
      replies: ''
    }
  ]
}

snoowrap should rearrange the replies of a PrivateMessage object to fit the first structure.

Add some utility functions to use in browsers

Using snoowrap securely in a browser is a bit difficult at the moment, since snoowrap can't really do anything until you have an access token. It would be useful to have some utility functions to make the process easier (e.g. a function to get a url for the authentication page, a function to exchange an access code for an access token/refresh token, etc.)

make a post/submission?

Not knocking the project but those docs I can't never find anything by searching.

How do I make a submission to a sub reddit? Which class would that be under?

edit: i found it.

Run unit tests off of a local reddit clone

At the moment, the unit tests are run off of the live reddit.com site. This has the advantage that snoowrap can always stay up-to-date with changes to the live site, but it also has several disadvantages:

  • Some of the tests depend on being logged into a specific user's account, which means that other contributors might have trouble running all of the tests.
  • The tests can randomly fail if reddit.com goes down.
  • The tests can randomly fail due to cache issues.
  • Some tests (e.g. for creating subreddits) are always skipped to prevent spam on reddit.com

These issues would be fixed if the tests were run off of a local reddit clone rather than the live site.

Attempted to call undefined which is not a function (v1.5.0, from NPM)

By, the way, here's some information to help with debugging:
Snoowrap v1.5.0 installed via npm
node v6.2.2


I'm trying out snoowrap, using it for a replication script I'm making. So, I got the subreddit name:

reddit.get_subreddit("vexforum")

Working well, but I notice that it does not return a Promise, it is a blocking function that returns a Subreddit class:

> reddit.get_subreddit("vexforum")
Subreddit { display_name: 'vexforum' }

This is odd, but I ignore it for now. I then try to call .create_selfpost(), and I reach the crux of my problem:

reddit.get_subreddit("vexforum")
  .create_selfpost({
    "title": "Testing 1...2...3...",
    "text": "Don't Mind Me!"
  })

Will give the following error:

Unhandled rejection TypeError: Promise chain rejection: Attempted to call undefined which is not a function.
    at /Users/tim/Documents/Projects/node_modules/promise-chains/index.js:68:15
    at tryCatcher (/Users/tim/Documents/Projects/node_modules/bluebird/js/release/util.js:16:23)
    at Promise._settlePromiseFromHandler (/Users/tim/Documents/Projects/node_modules/bluebird/js/release/promise.js:504:31)
    at Promise._settlePromise (/Users/tim/Documents/Projects/node_modules/bluebird/js/release/promise.js:561:18)
    at Promise._settlePromise0 (/Users/tim/Documents/Projects/node_modules/bluebird/js/release/promise.js:606:10)
    at Promise._settlePromises (/Users/tim/Documents/Projects/node_modules/bluebird/js/release/promise.js:685:18)
    at Promise._fulfill (/Users/tim/Documents/Projects/node_modules/bluebird/js/release/promise.js:630:18)
    at PromiseArray._resolve (/Users/tim/Documents/Projects/node_modules/bluebird/js/release/promise_array.js:125:19)
    at PromiseArray._promiseFulfilled (/Users/tim/Documents/Projects/node_modules/bluebird/js/release/promise_array.js:143:14)
    at Promise._settlePromise (/Users/tim/Documents/Projects/node_modules/bluebird/js/release/promise.js:566:26)
    at Promise._settlePromise0 (/Users/tim/Documents/Projects/node_modules/bluebird/js/release/promise.js:606:10)
    at Promise._settlePromises (/Users/tim/Documents/Projects/node_modules/bluebird/js/release/promise.js:685:18)
    at Async._drainQueue (/Users/tim/Documents/Projects/node_modules/bluebird/js/release/async.js:138:16)
    at Async._drainQueues (/Users/tim/Documents/Projects/node_modules/bluebird/js/release/async.js:148:10)

    at Immediate.Async.drainQueues [as _onImmediate] (/Users/tim/Documents/Projects/node_modules/bluebird/js/release/async.js:17:14)
    at tryOnImmediate (timers.js:543:15)

Let's break down what we know:

Unhandled rejection TypeError:

This means I haven't handled my errors in my promises right, and it irrelevant.

Promise chain rejection:

Something in the Promise chain has called reject(), most likely the .create_selfpost() function.

Attempted to call undefined which is not a function

Something tried to call an undefined variable as if it were a function.

Any help would be awesome! Thanks!

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.