Skip to content

Instantly share code, notes, and snippets.

@AndrewC-B
Last active June 28, 2017 02:30
Show Gist options
  • Save AndrewC-B/cab1ff12a6b947ef8c633439008754ab to your computer and use it in GitHub Desktop.
Save AndrewC-B/cab1ff12a6b947ef8c633439008754ab to your computer and use it in GitHub Desktop.
# coding: utf-8
import swizzle
from objc_util import *
import ctypes
import json, urllib
import uuid
import sys
import webbrowser
import urllib
NSURLComponents = ObjCClass('NSURLComponents')
appDelegate = UIApplication.sharedApplication().delegate()
_handler = None
_requestID = None
class x_callback_response (object):
    full_url = None
    source_app = None
    parameters = None
    
    def __str__(self):
        return '<x_callback_response: source_app = {}, parameters = {}>'.format(self.source_app, self.parameters)
def open_url(url, handler):
    global _handler
    global _requestID
    _requestID = uuid.uuid1()
    _handler = handler
    url_with_uuid = url + 'xcallbackresponse-' + str(_requestID)
    webbrowser.open(url_with_uuid)
def application_openURL_sourceApplication_annotation_(_self, _sel, app, url, source_app, annotation):
    url_str = str(ObjCInstance(url))
    global _requestID
    
    if not 'xcallbackresponse-' + str(_requestID) in url_str:
        print('not from x-callback-url, will run original function')
        obj = ObjCInstance(_self)
        original_method = getattr(obj, 'original'+c.sel_getName(_sel), None)
        if original_method:
            _annotation = ObjCInstance(annotation) if annotation else None
            return original_method(ObjCInstance(app), ObjCInstance(url), ObjCInstance(source_app), _annotation)
    else:
        x_callback_info = x_callback_response()
        x_callback_info.full_url = url_str
        x_callback_info.source_app = str(ObjCInstance(source_app))
        
        query = NSURLComponents.componentsWithURL_resolvingAgainstBaseURL_(nsurl(url_str), False)
        parameters = None
        if query.queryItems() is not None:
            parameters = dict()
            for queryItem in query.queryItems():
                x_callback_info.parameters[str(queryItem.name())] = str(queryItem.value())
                
        x_callback_info.parameters = parameters
        
        raw_response_data = url_str.replace('pythonista://xcallbackresponse-' + str(_requestID), "")
        x_callback_info.raw_response_data = urllib.unquote(raw_response_data)
            
        if _handler:
            _handler(x_callback_info)
        return True
# Do the swizzling
cls = ObjCInstance(c.object_getClass(appDelegate.ptr))
swizzle.swizzle(cls, 'application:openURL:sourceApplication:annotation:', application_openURL_sourceApplication_annotation_)
if __name__ == '__main__':
    import console
    console.clear()
    
    draft_uuid = '9B0A1EF8-B2D8-4050-8EE4-B6D8AC0F229B'
    url = 'drafts4://x-callback-url/get?uuid={}&x-success=pythonista://'.format(draft_uuid)
    
    def my_handler(info):
        print(info.full_url)
        print(info.parameters['text'])
    
    open_url(url, my_handler)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment