<commit_before>//
//  NSError+OAuthSwift.swift
//  OAuthSwift
//
//  Created by <NAME> on 04/04/16.
//  Copyright © 2016 <NAME>. All rights reserved.
//

import Foundation

public extension NSError {

    /// Checks the headers contained in the userInfo whether this error was caused by an 
    /// expired/invalid access token.
    ///
    /// Criteria for invalid token error: WWW-Authenticate header contains a field "error" with
    /// value "invalid_token".
    ///
    /// Also implements a special handling for the Facebook API, which indicates invalid tokens in a 
    /// different manner. See https://developers.facebook.com/docs/graph-api/using-graph-api#errors
    var isExpiredToken: Bool {
        guard self.domain == NSURLErrorDomain || self.domain == OAuthSwiftError.Domain else {
            return false
        }
		if self.code == 401 {
			if let reponseHeaders = self.userInfo["Response-Headers"] as? [String: String],
				let authenticateHeader = reponseHeaders["WWW-Authenticate"] ?? reponseHeaders["Www-Authenticate"] {
				let headerDictionary = authenticateHeader.headerDictionary
				if let error = headerDictionary["error"], error == "invalid_token" || error == "expired_token" || error == "\"invalid_token\"" {
					return true
				}
			}
            if let body = self.userInfo["Response-Body"] as? String,
                let bodyData = body.data(using: OAuthSwiftDataEncoding),
                let json = try? JSONSerialization.jsonObject(with: bodyData, options: []),
                let jsonDic = json as? [String: AnyObject] {
                if let error = jsonDic["error"] as? String, error == "invalid_token" || error == "expired_token" || error == "\"invalid_token\"" {
                    return true
                }
                if let errors = jsonDic["errors"] as? [[String: AnyObject]] {
                    for error in errors {
                        if let errorType = error["errorType"] as? String, errorType == "invalid_token" {
                            return true
                        }
                    }
                }
            }
		}

        // Detect access token expiration errors from facebook
        // Docu: https://developers.facebook.com/docs/graph-api/using-graph-api#errors
        if self.code == 400 {
            if let urlString = self.userInfo[NSURLErrorFailingURLErrorKey] as? String, urlString.contains("graph.facebook.com") {
                if let body = self.userInfo["Response-Body"] as? String,
                    let bodyData = body.data(using: OAuthSwiftDataEncoding),
                    let json = try? JSONSerialization.jsonObject(with: bodyData, options: []),
                    let jsonDic = json as? [String: AnyObject] {
                    let errorCode = jsonDic["error"]?["code"] as? Int
                    let errorSubCode = jsonDic["error"]?["error_subcode"] as? Int
                    if (errorCode == 102 && errorSubCode == nil) || errorSubCode == 463 || errorSubCode == 467 {
                        return true
                    }
                }
            }
        }

		return false
	}

}
<commit_msg>Handle "expired_token" key for Fitbit error<commit_after>//
//  NSError+OAuthSwift.swift
//  OAuthSwift
//
//  Created by <NAME> on 04/04/16.
//  Copyright © 2016 <NAME>. All rights reserved.
//

import Foundation

public extension NSError {

    /// Checks the headers contained in the userInfo whether this error was caused by an 
    /// expired/invalid access token.
    ///
    /// Criteria for invalid token error: WWW-Authenticate header contains a field "error" with
    /// value "invalid_token".
    ///
    /// Also implements a special handling for the Facebook API, which indicates invalid tokens in a 
    /// different manner. See https://developers.facebook.com/docs/graph-api/using-graph-api#errors
    var isExpiredToken: Bool {
        guard self.domain == NSURLErrorDomain || self.domain == OAuthSwiftError.Domain else {
            return false
        }
		if self.code == 401 {
			if let reponseHeaders = self.userInfo["Response-Headers"] as? [String: String],
				let authenticateHeader = reponseHeaders["WWW-Authenticate"] ?? reponseHeaders["Www-Authenticate"] {
				let headerDictionary = authenticateHeader.headerDictionary
				if let error = headerDictionary["error"], error == "invalid_token" || error == "expired_token" || error == "\"invalid_token\"" {
					return true
				}
			}
            if let body = self.userInfo["Response-Body"] as? String,
                let bodyData = body.data(using: OAuthSwiftDataEncoding),
                let json = try? JSONSerialization.jsonObject(with: bodyData, options: []),
                let jsonDic = json as? [String: AnyObject] {
                if let error = jsonDic["error"] as? String, error == "invalid_token" || error == "expired_token" || error == "\"invalid_token\"" {
                    return true
                }
                if let errors = jsonDic["errors"] as? [[String: AnyObject]] {
                    for error in errors {
                        if let errorType = error["errorType"] as? String, errorType == "invalid_token" || errorType == "expired_token" {
                            return true
                        }
                    }
                }
            }
		}

        // Detect access token expiration errors from facebook
        // Docu: https://developers.facebook.com/docs/graph-api/using-graph-api#errors
        if self.code == 400 {
            if let urlString = self.userInfo[NSURLErrorFailingURLErrorKey] as? String, urlString.contains("graph.facebook.com") {
                if let body = self.userInfo["Response-Body"] as? String,
                    let bodyData = body.data(using: OAuthSwiftDataEncoding),
                    let json = try? JSONSerialization.jsonObject(with: bodyData, options: []),
                    let jsonDic = json as? [String: AnyObject] {
                    let errorCode = jsonDic["error"]?["code"] as? Int
                    let errorSubCode = jsonDic["error"]?["error_subcode"] as? Int
                    if (errorCode == 102 && errorSubCode == nil) || errorSubCode == 463 || errorSubCode == 467 {
                        return true
                    }
                }
            }
        }

		return false
	}

}

{'fraction_non_alphanumeric': 0.11329113924050632, 'fraction_numerical': 0.007911392405063292, 'mean_word_length': 1.9844192634560907, 'pattern_counts': {'":': 0, '<': 7, '<?xml version=': 0, '>': 7, 'https://': 4, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 2, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2624489', 'n_tokens_mistral': 1821, 'n_tokens_neox': 1643, 'n_words': 469}