Swift Reddit API Wrapper

Overview

Carthage compatible Version License Platform Build Status

reddift

reddift is Swift Reddit API Wrapper framework, and includes a browser is developed using the framework.

  • Supports OAuth2(is not supported on tvOS currently).
  • Supports multi-accounts.
  • Includes a sample application(iOS only).

Browser

  • It's a typical browser of reddit.com.
  • This application uses "reddift framework" in order to access reddit.com.
  • Includes almost all of functions, such as image thumbnails, browsing comments, search subreddits and so on.
  • If you need more features to this, please send pull requests to me.

reddift-comments reddift-images

Document

How to build

Now, it's under developing. You have to pay attention to use this library.

1. Check out source code.

# check out reddift and its submodules.
> git clone --recursive https://github.com/sonsongithub/reddift.git

Check that these libraries are checked out at each path correctly.

/framework/vendor/HTMLSpecialCharacters
/framework/vendor/MiniKeychain

2. Create application(installed app) at reddit.com

Create new installed app via preference page at reddit.com. And then, check your app's cliend_id and fill out redirect_uri for OAuth2. For example, redirect_uri is set to myapp://response. In following sample, redirect_uri is set to reddift://response.

installedapp

3. Set up reddift_config.json

This JSON file saves application information to use OAuth. Rename reddift_config.json.sample to reddift_config.json. And fill out DeveloperName, redirect_uri and client_id. redirect_uri must be same one you registered at reddit.com. You can check client_id at application tab. reddift generates http's user-agent property using this JSON and application's info.plist.

{
  "DeveloperName": "<YOUR NAME>",
  "redirect_uri": "<YOUR REDIRECT URI>",
  "client_id": "<YOUR ID>"
}

4. Set up your URI on Xcode

In Xcode, set up URL Types in order to receive call back from Safari. Set URL Schemes to redirect_uri that you set at reddit.com. You don't have to include ://response to this form. These URI must be identical. If they are not identical, reddit.com does not authorize your OAuth request. In following sample, URL Schemes is set to reddift.

reddit2

How to build test

1. Register user script app

Test uses Application Only OAuth to remove user interaction from test process. If you want to run tests of reddift, you have to create another "Script" type application(personal use script) at reddit.com.

userscript

2. Fill out test_config.json

At first, rename test_config.json.sample to test_config.json. Fill each following value using above preference pain of reddit.com.

{
  "username": "test user account",
  "password": "test user password",
  "client_id": "test app client ID(must be script type app)",
  "secret": "test app secret"
}

3. Start test

Cmd + U.

How to build browser sample

You have to build dependent frameworks using carthage before building a sample application using Xcode.

# before open xcode project file.
> carthage update --platform iOS

carthage works corretly, you can get following frameworks at each path.

/Carthage/Build/iOS/FLAnimatedImage.framework
/Carthage/Build/iOS/YouTubeGetVideoInfoAPIParser.framework
/Carthage/Build/iOS/UZTextView.framework

And, you get to edit URI types and reddift_config.json as same as the framework.

Create you app.

Get something & Error handling

reddift returns Result<T> object as a result. Get the value or error from Result<T> object. Concretely, you can access either value evaluating enum state like a following code.

// do not use "!" in your code
switch(result) {
case .failure(let error):
    println(error)
case .success(let listing):
    // do something to listing
}

In more detail about this coding style, see "Efficient JSON in Swift with Functional Concepts and Generics".

Create session

At first, you have to implement codes to receive the response of OAuth2 in UIAppDelegate. reddift let you save tokens as a specified name into KeyChain. Specifically, following sample code saves token as user name at reddit.com.

func application(application: UIApplication, openURL url: NSURL, sourceApplication: String?, annotation: AnyObject) -> Bool {
    return OAuth2Authorizer.sharedInstance.receiveRedirect(url, completion:{(result) -> Void in
        switch result {
        case .failure(let error):
            print(error)
        case .success(let token):
            dispatch_async(dispatch_get_main_queue(), { () -> Void in
                OAuth2TokenRepository.saveIntoKeychainToken(token, name:token.name)
            })
        }
    })
}

To communicate with reddit.com via OAuth2, you have to create Session object. See following section about getting response or error handling.

let result = OAuth2TokenRepository.restoreFromKeychainWithName(name)
switch result {
case .failure(let error):
    print(error.description)
case .success(let token):
    con.session = Session(token: token)
}

You can get contents from reddit via Session object like following codes.

session?.getList(paginator, subreddit:subreddit, sort:sortTypes[seg.selectedSegmentIndex], timeFilterWithin:.All, completion: { (result) in
    switch result {
    case .failure(let error):
        print(error)
    case .success(let listing):
        self.links.appendContentsOf(listing.children.flatMap{$0 as? Link})
    }
})

Use Application Only OAuth

You can use OAuth2AppOnlyToken when you want to write a code for test or personal script tool(such as CLI). OAuth2AppOnlyToken enabled to access reddit without human action in order to authorize in web browser apps. Do not use Oauth2AppOnlyToken in installed app in terms of security.

OAuth2AppOnlyToken.getOAuth2AppOnlyToken(
    username: username,
    password: password,
    clientID: clientID,
    secret: secret,
    completion:( { (result) -> Void in
    switch result {
    case .failure(let error):
        print(error)
    case .success(let token):
        self.session = Session(token: token)
    }
}))

Further more,

In more detail, See my sample application, test code or Playground code included in this repository.

Playground

You can play with reddift in Playground. In more detail, check reddift.playground package. Before using, you have to copy test_config.json into ./reddift.playground/Resources in order to specify user account and your application informatin because reddift on Playground uses "Application Only OAuth".

playground

Dependency

License

MIT License.

Comments
  • Sample Project Loading Issue

    Sample Project Loading Issue

    http://i.imgur.com/lpRIaHY.gif

    Hi I downloaded the example project and everything seems to work well, but when I try to search for a listing nothing shows.
    Anything I should try?

    My reddit app account info is added in the json file

    Thanks for the great example btw

    opened by mparrish91 20
  • Paginator not working as expected, returning new and old content

    Paginator not working as expected, returning new and old content

    Paginator worked last year but it's no longer always working correctly, often returning a mix of new content and old content. This means Paginator is working but it's not filtering out already seen posts (like RES on the desktop has to do). Am I doing something wrong or would you like me to quickly throw a pull together?

    This is especially obvious in a subreddit which has very few posts (<20) because once you paginate you get the exact same posts in the same order again.

    opened by ezhes 9
  • Automatically renewing expired token

    Automatically renewing expired token

    Hi!

    I noticed that token expires after some time and was wondering if you have any automatic mechanism to refresh it in place.

    I noticed that you have a refreshToken function in the Session class which is amazing. So this is the expected behaviour:

    1. Request fails with 401
    2. Session attempts to refresh token
    3. (A) If refresh success, it performs request 1. again
    4. (B) If refresh failures, it just falls back to the failure of 1.

    The thing is that this mechanism should be happen inside the session object (or at some low level) and not on consumer level.

    Questions:

    1. Do you have any suggestion how to tackle this token expiring issue as seamlessly as possible?
    2. Any thoughts on how to implement it?

    Let me know what you think and I can give it a shot

    opened by jakunico 7
  • State parameter on the recieveRedirect of theOAauth2Authorizer class breaks sign ins?

    State parameter on the recieveRedirect of theOAauth2Authorizer class breaks sign ins?

    So I'm not entirely sure when this issue came up but it hit me recently. When the receiveRedirect(_ url... function gets the callback I'm sending from the AppDelegate, Reddift silently ignores the request because of this check:

    && state == currentState

    I've removed it, seemingly to no maleffect, and am able to sign in properly again. I can't seem to nail down the cause since the state data is sent with every account, not just my 2FA main account. I also can't say for sure when this changed since it only affects newly authorized accounts, not token refreshes.

    opened by ezhes 6
  • Unable to install reddift from Cocoapods

    Unable to install reddift from Cocoapods

    This is my first time using the Cocoapods ecosystem, so the problem could entirely be user error!

    $ pod install
    Analyzing dependencies
    Downloading dependencies
    Installing reddift (1.6.0)
    
    [!] Error installing reddift
    [!] /usr/local/bin/git clone https://github.com/sonsongithub/reddift.git /var/folders/tn/qtn_4h693933whtf14410v240000gn/T/d20160619-35814-1n9g4h3 --template= --single-branch --depth 1 --branch v1.6.0 --recursive
    
    Cloning into '/var/folders/tn/qtn_4h693933whtf14410v240000gn/T/d20160619-35814-1n9g4h3'...
    Note: checking out '6eaf3308c75287e11b95f46a7b3fe399ad6a1b05'.
    
    You are in 'detached HEAD' state. You can look around, make experimental
    changes and commit them, and you can discard any commits you make in this
    state without impacting any branches by performing another checkout.
    
    If you want to create a new branch to retain commits you create, you may
    do so (now or later) by using -b with the checkout command again. Example:
    
      git checkout -b <new-branch-name>
    
    Submodule 'reddift/vendor/KeychainAccess' (https://github.com/kishikawakatsumi/KeychainAccess.git) registered for path 'reddift/vendor/KeychainAccess'
    Submodule 'reddiftSample/vendor/UZTextView' (https://github.com/sonsongithub/UZTextView.git) registered for path 'reddiftSample/vendor/UZTextView'
    Cloning into '/private/var/folders/tn/qtn_4h693933whtf14410v240000gn/T/d20160619-35814-1n9g4h3/reddift/vendor/KeychainAccess'...
    Cloning into '/private/var/folders/tn/qtn_4h693933whtf14410v240000gn/T/d20160619-35814-1n9g4h3/reddiftSample/vendor/UZTextView'...
    error: no such remote ref 30744e7929a1f10709997d3c75ee82d855cdb8e6
    Fetched in submodule path 'reddift/vendor/KeychainAccess', but it did not contain 30744e7929a1f10709997d3c75ee82d855cdb8e6. Direct fetching of that commit failed.
    

    My Podfile:

    target 'MyApp' do
      use_frameworks!
      pod 'reddift', '~> 1.6'
    end
    target 'MyAppDebugger' do
      use_frameworks!
    end
    

    I tried bumping reddift to ~> 1.7 upon seeing a 1.7.0 tag in this repo, but cocoapods tells me that it's not available:

    $ pod list | grep reddift
      reddift 1.6.0
    

    What can I do?

    opened by colindean 6
  • Fix a bug where non-logged in accounts can't use certain list methods

    Fix a bug where non-logged in accounts can't use certain list methods

    Here's another weird one: when not signed in, reddift doesn't use the oauth subdomain (expected). The problem is the oauth subdomain ALWAYS returns json, regardless of whether you requested it or not. The regular old https://reddit.com/..., however, does not always and you must request it with .json explicitly. Some listing methods were not doing this which meant that if you aren't signed in you get back HTML instead of JSON which obviously doesn't work. For example:

    Signed out: https://www.reddit.com//by_id/t3_8f6g13 (HTML!!!)

    Signed in: https://oauth.reddit.com//by_id/t3_8f6g13 (JSON if sent with creds)

    I simply added explicit .json to requests where it was forgotten.

    opened by ezhes 4
  • Custom UI for login

    Custom UI for login

    Hi there,

    I was wondering wether there's a way you can skip OAUTH authentication method and do a regular POST of your username/password like other clients do.

    The mains reason why I'm wondering this is because you'd be able to build a custom UI for login which is much better than the ugly web login interface.

    Well, let me know what you think @sonsongithub !

    opened by jakunico 3
  • Login Bad Request

    Login Bad Request

    Hi, so first of all it was a huge pain to get the project to even compile. The instructions are unclear, there were compile errors, dependencies needed to be added manually into subfolders. It finally runs though, now when I try to add an account and add my credentials and hit login in the browser it says "bad request (reddit.com) you sent an invalid request" and it doesn't redirect back to the app. Please provide proper instructions on how to set everything up, otherwise this is a huge waste of time.

    opened by DsrMedia 2
  • Quick question..

    Quick question..

    how can I filter the Links gotten from session?.getList(subreddit) I'm getting around 27 links per call, and I only need 10 top I'm assuming it has to do something with the Paginator().

    anyone can give me a hand?

    opened by AndreAbdel27 2
  • Upgrade to swift 3 and iOS 10 APIs

    Upgrade to swift 3 and iOS 10 APIs

    Yeah this is going to be painful.. Trying to port my reddift project by hand is turning out to be a entirely frighteningly bad mess. Thank god for version control though. I know you'll likely have zero time however I'm just adding an issue here for future reference so that eventually someone else can try and pick this up.

    I'm slowly chugging through this however I'm using a modified code base because I made some bug fixes decided (probably a bad idea at this point) to not commit them or pull new changes from git which could make this merge incompatible. Comand-Option-Control-F is your friend here (fix all issues in scope!)

    opened by ezhes 2
  • Fix a bug where non-logged in accounts can't use certain list methods

    Fix a bug where non-logged in accounts can't use certain list methods

    Here's another weird one: when not signed in, reddift doesn't use the oauth subdomain (expected). The problem is the oauth subdomain ALWAYS returns json, regardless of whether you requested it or not. The regular old https://reddit.com/..., however, does not always and you must request it with .json explicitly. Some listing methods were not doing this which meant that if you aren't signed in you get back HTML instead of JSON which obviously doesn't work. For example:

    Signed out: https://www.reddit.com//by_id/t3_8f6g13 (HTML!!!)

    Signed in: https://oauth.reddit.com//by_id/t3_8f6g13 (JSON if sent with creds)

    I simply added explicit .json to requests where it was forgotten and it now works as expected.

    opened by ezhes 1
  • Swift 5 / Xcode 11 support [WIP]

    Swift 5 / Xcode 11 support [WIP]

    I had an old project that depended on reddift - I'm trying to resurrect that project and reddift was not working with swift 5 and Xcode 11. This PR should hopefully fix that.

    image

    App, frameworks and tests compile with no warnings:

    image

    I've faced a couple of challenges with tests:

    1. Some tests are failing to me, from what I saw some of them depend on your reddit user, for instance UsersTest.testGetUserContents uses sonson_twit username which obviously does not match mine (see image below).
    2. Travis needs to read some encrypted variables which are not available when you are a contributor (as you would be able to edit the travis script and print out those). Maybe you can merge temporarily into a swift-5 branch instead of master and then run tests on travis by opening a swift-5 > master PR.

    image

    opened by jakunico 0
  • Carthage failed to build

    Carthage failed to build

    Carthage failed to build. Seem to be missing "test_config.json"

    ** BUILD FAILED **

    The following build commands failed: CpResource /.../Carthage/Checkouts/reddift/test/test_config.json /.../Library/Caches/org.carthage.CarthageKit/DerivedData/10.1_10B61/reddift/2.0.3/Build/Products/Release-iphonesimulator/reddift-iOSTests.xctest/test_config.json

    opened by ghost 2
  • tvOS support

    tvOS support

    Are you able to add tvOS support for reddift? I'm trying to implement Oauth in my reddit-based tvOS application to allow Login with Reddit, and then access the user's subreddits. I can't find any authentication options on tvOS for Reddit users.

    opened by dnadri 2
  • Fix subreddit about method

    Fix subreddit about method

    The method does not work without the added .json at the end:

    Error Domain=NSCocoaErrorDomain Code=3840 "JSON text did not start with array or object and option to allow fragments not set." UserInfo={NSDebugDescription=JSON text did not start with array or object and option to allow fragments not set.} Error Domain=reddift.HttpStatusWithBody<Swift.String> Code=404 "(null)"

    opened by MohammadAG 0
  • [PUT] Cannot test /api/v1/me/friends/ because it cannot attach

    [PUT] Cannot test /api/v1/me/friends/ because it cannot attach "note" without Gold

    Comment

    Can not attach parameters when putting. It succeeded when I put vacant JSON object, but it failed when the specified JSON object such as { "name": A valid, existing reddit username, "note": a string no longer than 300 characters}.

    Response

    {"fields": ["note"], "explanation": "you must have an active reddit gold subscription to do that", "reason": "GOLD_REQUIRED"}
    

    Reference

    1. reddit.com
    subreddits investigate 
    opened by sonsongithub 0
Owner
sonson
I'm a research engineer. I like iOS, Objective-C, Swift, computer vision, and image processing. @DensoITLab
sonson
Swift implementation of Github REST API v3

GitHubAPI Swift implementation of GitHub REST api v3. Library support Swift 4.2. Work is in progress. Currently supported: Issues API. Activity API(Fe

Serhii Londar 77 Jan 7, 2023
Google Directions API helper for iOS, written in Swift

PXGoogleDirections Google Directions API SDK for iOS, entirely written in Swift. ?? Features Supports all features from the Google Directions API as o

Romain L 268 Aug 18, 2022
Instagram API client written in Swift

SwiftInstagram is a wrapper for the Instagram API written in Swift. It allows you to authenticate users and request data from Instagram effortlessly.

Ander Goig 580 Nov 25, 2022
Instagram Private API Swift

SwiftyInsta Please notice SwiftyInsta may not be actively maintained at the moment of you reading this note. Refer to #244 for more info. Instagram of

Mahdi Makhdumi 218 Jan 5, 2023
A Swift client for the OpenAI API.

OpenAI A Swift client for the OpenAI API. Requirements Swift 5.3+ An OpenAI API Key Example Usage Completions import OpenAI

Mattt 161 Dec 26, 2022
Swift Bot with Vapor for Telegram Bot Api

Telegram Vapor Bot Please support Swift Telegram Vapor Bot Lib development by giving a ⭐️ Telegram Bot based on Swift Vapor. Swift Server Side Communi

OleG. 104 Jan 6, 2023
Swift library for the Twitter API v1 and v2

Swift library for the Twitter API v1 and v2

mironal 96 Dec 30, 2022
Backport of iOS 15 formatting api

This is a back-port of the .formatted API in Foundation that was introduced at WWDC '21 for iOS 15, macOS 12.0, tvOS 15.0, and watchOS 8.0.

Simon Salomons 9 Jul 22, 2022
Unofficial iOS/macOS SDK for the Notion API.

NotionClient: a Notion SDK for iOS & macOS Unofficial Notion API SDK for iOS & macOS. This is an alpha version and still work in progress. TODO Featur

David De Bels 15 Aug 4, 2022
👤 Framework to Generate Random Users - An Unofficial Swift SDK for randomuser.me

RandomUserSwift is an easy to use Swift framework that provides the ability to generate random users and their accompanying data for your Swift applic

Wilson Ding 95 Sep 9, 2022
Swifter - A Twitter framework for iOS & OS X written in Swift

Getting Started Installation If you're using Xcode 6 and above, Swifter can be installed by simply dragging the Swifter Xcode project into your own pr

Matt Donnelly 2.4k Dec 26, 2022
Swift client for Kubernetes

Table of contents Overview Compatibility Matrix Examples Usage Creating a client Configuring a client Client authentication Client DSL Advanced usage

Swiftkube 94 Dec 14, 2022
SDK for creating Telegram Bots in Swift.

Chat • Changelog • Prerequisites • Getting started • Creating a new bot • Generating Xcode project • API overview • Debugging notes • Examples • Docum

Rapier 349 Dec 20, 2022
Telegram Bot Framework written in Swift 5.1 with SwiftNIO network framework

Telegrammer is open-source framework for Telegram Bots developers. It was built on top of Apple/SwiftNIO

Pataridze Givi 279 Jan 4, 2023
Solana + RxSolana This is a open source library on pure swift for Solana protocol

The objective is to create a cross platform, fully functional, highly tested and less depencies as posible. The project is still at initial stage. Lots of changes chan happen to the exposed api.

Arturo Jamaica 138 Dec 15, 2022
QuoteKit is a Swift framework to use the free APIs provided by Quotable created by Luke Peavey.

QuoteKit The QuoteKit is a Swift framework to use the free APIs provided by Quotable created by Luke Peavey.

Rudrank Riyam 17 Jun 23, 2022
Reddit Feed Built With Swift

RedditFeed Steps to run the application: Download the project. Open Terminal and go to the root of the project. Run pod install Open RedditFeed.xcwork

Rahul Garg 0 Dec 14, 2021
Open source Reddit client for iOS built entirely in Swift

Area51 Area51 is an open source Reddit client for iOS built entirely in Swift! Get the public beta on TestFlight Join the public Slack channel to coll

Kris 141 Dec 26, 2022
Insta-pick - Browse images from reddit with swift

insta-pick Browse images from reddit To run the app: Clone into local folder usi

Just 0 Feb 14, 2022
A cross-platform Reddit client built in SwiftUI

A cross-platform Reddit client created in SwiftUI. Get the Public Beta Note: This project is far from complete. It still lacks many features of your t

Carson Katri 1.2k Dec 25, 2022