{ "info": { "author": "marbink", "author_email": "github@marbink.eu", "bugtrack_url": null, "classifiers": [ "Development Status :: 5 - Production/Stable", "Intended Audience :: Developers", "License :: OSI Approved :: MIT License", "Programming Language :: Python :: 2", "Programming Language :: Python :: 2.7", "Programming Language :: Python :: 3", "Programming Language :: Python :: 3.6", "Topic :: Internet :: WWW/HTTP", "Topic :: Internet :: WWW/HTTP :: Dynamic Content :: Message Boards", "Topic :: Software Development :: Libraries :: Python Modules" ], "description": "Jodel iOS API\n=========\n\n|Build Status| |Python Versions| |PyPI Version| |License|\n\nUnofficial interface to the private API of the Jodel App. Not affiliated\nwith *The Jodel Venture GmbH*.\n\nSpecial Thanks\n--------------\n@nborrmann (https://github.com/nborrmann/jodel_api) who developed the main core of this API. I forked its repo and adapted the code to follow iOS app behaviour. I should have not broken compatibility with its version BUT I removed 'legacy' accounts support.\n\n\nInstallation\n------------\n\nUsing pip:\n\n.. code::\n\n pip install jodel_ios_api\n\nor using setup.py:\n\n.. code::\n\n git clone https://github.com/marbink/jodel_ios_api.git\n cd jodel_ios_api\n python setup.py install\n\n\nUsage\n-----\n\nAccount Creation\n~~~~~~~~~~~~~~~~\n\nCalling the bare constructor creates a new account:\n\n.. code:: python\n\n >>> import jodel_ios_api\n >>> lat, lng, city = 48.148434, 11.567867, \"Munich\"\n\t>>> jodel_ios_api.JodelAccount.secret = 'SECRET_HERE'.encode('ascii')\n >>> j = jodel_ios_api.JodelAccount(lat=lat, lng=lng, city=city)\n Creating new account.\n\n``get_account_data()`` returns all data associated with this account\n(censored by me):\n\n.. code:: python\n\n >>> j.get_account_data()\n {'access_token': 'xxx', 'expiration_date': 1472660000, 'refresh_token': 'xxx', 'distinct_id': 'xxx', 'device_uid': 'xxx'}\n\nSave this data to reuse the account later on, feed it to the\nJodelAccount() constructor to reinitiate the account. This constructor\nissues one request to update the location of the account.\n\n.. code:: python\n\n >>> j = jodel_ios_api.JodelAccount(lat=lat, lng=lng, city=city, access_token='xxx', expiration_date='xxx', \n refresh_token='xxx', distinct_id='xxx', device_uid='xxx', is_legacy=True)\n (204, '')\n\nAdd ``update_location=False`` to suppress this behaviour. The\nconstructor will only instantiate an object, without making any remote\ncalls:\n\n.. code:: python\n\n >>> j = jodel_ios_api.JodelAccount(lat=lat, lng=lng, city=city, update_location=False, **account_data)\n\nAfter ``expiration_date`` has passed, call ``refresh_access_tokens()``\nto re-authenticate. If ``refresh_access_token`` fails, use\n``refresh_all_tokens`` instead (this is akin to creating a new account,\nbut preserves the account's data (karma, etc)):\n\n.. code:: python\n\n >>> j.refresh_access_token()\n (200, {'token_type': 'bearer', 'access_token': 'xxx', 'expires_in': 604800, 'expiration_date': xxx})\n >>> j.refresh_all_tokens()\n (200, {'expires_in': 604800, 'access_token': 'xxx', 'token_type': 'bearer', 'returning': True,\n 'refresh_token': 'xxx', 'expiration_date': 1472600000, 'distinct_id': 'xxx'})\n\n\nAPI calls\n~~~~~~~~~\n\nAll remote API calls return a tuple of HTTP status\\_code and the\nresponse (if possible a dict, parsed from the API response), but might\nalso be a string (error message).\n\nThe following API calls are supported (presented without their \nrespective responses):\n\n\n.. code:: python\n\n # API methods for reading posts:\n >>> j.get_posts_recent(skip=0, limit=60, after=None, mine=False, hashtag=None, channel=None)\n >>> j.get_posts_popular(skip=0, limit=60, after=None, mine=False, hashtag=None, channel=None)\n >>> j.get_posts_discussed(skip=0, limit=60, after=None, mine=False, hashtag=None, channel=None)\n >>> j.get_pictures_recent(skip=0, limit=60, after=None)\n >>> j.get_pictures_popular(skip=0, limit=60, after=None)\n >>> j.get_pictures_discussed(skip=0, limit=60, after=None)\n >>> j.get_my_pinned_posts(skip=0, limit=60, after=None)\n >>> j.get_my_replied_posts(skip=0, limit=60, after=None)\n >>> j.get_my_voted_posts(skip=0, limit=60, after=None)\n >>> j.post_search(message, skip=0, limit=60) \n\n # API methods for interacting with single posts:\n >>> j.create_post(message=None, imgpath=None, b64img=None, color=None, ancestor=None, channel=\"\")\n >>> j.get_post_details(post_id) # This endpoint has been deprecated. Use get_post_details_v3.\n >>> # This api endpoint implements paging and returns at most 50 replies,\n >>> # use the skip parameter to page through the thread:\n >>> j.get_post_details_v3(post_id, skip=0) \n >>> j.upvote(post_id)\n >>> j.downvote(post_id)\n >>> j.give_thanks(post_id)\n >>> j.get_share_url(post_id)\n >>> j.pin(post_id)\n >>> j.unpin(post_id)\n >>> j.enable_notifications(post_id)\n >>> j.disable_notifications(post_id)\n >>> j.delete_post(post_id) # Only works on your own posts \u0ca0_\u0ca0\n\n # API methods for interacting with sticky posts:\n >>> j.upvote_sticky_post(post_id)\n >>> j.downvote_sticky_post(post_id)\n >>> j.dismiss_sticky_post(post_id)\n\n # API methods for interacting with notifications:\n >>> j.get_notifications()\n >>> j.get_notifications_new()\n >>> j.notification_read(post_id=None, notification_id=None)\n\n # API methods for interacting with channels:\n >>> j.get_recommended_channels()\n >>> j.get_channel_meta(channel)\n >>> j.follow_channel(channel)\n >>> j.unfollow_channel(channel)\n\n # API methods for interacting with your user profile:\n >>> j.set_location(lat, lng, city, country=None, name=None) # country and name appear to have no effect\n >>> j.set_user_profile(user_type=None, gender=None, age=None)\n >>> j.get_user_config()\n >>> j.get_karma()\n >>> j.get_captcha()\n >>> j.submit_captcha(key, answer)\n\n\nThe parameters ``skip``,\n``limit`` and ``after`` implement paging. While ``skip`` and ``limit``\nare integers, ``after`` is a ``post_id`` parameter and will return all\njodels that follow that one. The former two paramters seem to be \ndeprecated in favor of the latter, however ``after`` doesn't work\non all ``/mine/`` endpoints (ie. ``mine=True`` or ``get_my_x_posts``).\n\nThe arguments ``mine`` (boolean), ``hashtag``, ``channel`` (both strings)\nare exclusive. If ``mine`` evaluates to ``true``, the other two arguments\nare discarded, if ``hashtag`` evaluates ``true`` , ``channel`` is \ndiscarded.\n\n``post_search()`` is a new endpoint (as of June 17) that isn't yet\navailable through the app. It returns all posts from your location\nthat contain a given string.\n\nYou can pass additional arguments (such as proxies and timeouts) to all\nAPI calls through the ``**xargs`` argument that will be passed to the\n``requests.request()`` function:\n\n.. code:: python\n\n >>> j.upvote(post_id, timeout=5, proxies={'https': '127.0.0.1:5000'})\n\nFor unimplemented endpoints, check `issue #22 \n`_.\n\n\nError Codes\n~~~~~~~~~~~\n\n- **401 \"Unauthorized\"**: Your ``access_token`` is invalid. Either \n you messed up, or it is outdated. You need to call \n ``refresh_access_token()`` or ``refresh_all_token()`` (check the \n above section on account creation).\n- **401 \"Action not allowed\"**: You are using a ``4.48`` account \n with ``is_legacy=True``, but ``4.48`` accounts are not allowed\n to downgrade.\n- **403 \"Access Denied\"**: Your IP is banned accross endpoints,\n just read-only endpoints still work. Effective for 24 hours.\n- **429 \"Too Many Requests\"**: Your IP is rate-limited. Applies only\n to one specific endpoint.\n- **477 \"Signed Request Expected\"**: This library should handle request\n signing. Make sure to upgrade to the latest version of ``jodel_ios_api``,\n as the signing key changes every few weeks.\n- **478 \"Account not verified\"**: Verify the account through GCM.\n- **502 \"Bad Gateway\"**: Something went wrong server-side. This happens\n pretty randomly. ``jodel_ios_api`` automatically retries two times when\n it sees this error. If you encounter this status, the jodel servers\n are probably having issues. Try again later.\n\nRate-Limits\n~~~~~~~~~~~\n\nThe Jodel API appears to have the following (IP-based) rate-limits\n\n- max of 200 new account registrations from one IP per half hour\n- max of 200 votes per minute\n- max of 100 captcha requests per minute\n\nThey also hand out 403 bans if you overdo it.\n\n\n.. code:: python\n\n python setup.py test\n\n.. |Build Status| image:: https://travis-ci.org/marbink/jodel_ios_api.svg?branch=master\n :target: https://travis-ci.org/marbink/jodel_ios_api\n.. |Python Versions| image:: https://img.shields.io/pypi/pyversions/jodel_ios_api.svg\n :target: https://pypi.python.org/pypi/jodel_ios_api/\n.. |PyPI Version| image:: https://img.shields.io/pypi/v/jodel_ios_api.svg\n :target: https://pypi.python.org/pypi/jodel_ios_api/\n.. |License| image:: https://img.shields.io/pypi/l/jodel_ios_api.svg\n :target: https://pypi.python.org/pypi/jodel_ios_api/\n\n\n", "description_content_type": "", "docs_url": null, "download_url": "", "downloads": { "last_day": -1, "last_month": -1, "last_week": -1 }, "home_page": "https://github.com/marbink/jodel_ios_api", "keywords": "jodel", "license": "MIT", "maintainer": "", "maintainer_email": "", "name": "jodel-ios-api", "package_url": "https://pypi.org/project/jodel-ios-api/", "platform": "", "project_url": "https://pypi.org/project/jodel-ios-api/", "project_urls": { "Homepage": "https://github.com/marbink/jodel_ios_api" }, "release_url": "https://pypi.org/project/jodel-ios-api/1.0.2/", "requires_dist": [ "requests", "future", "simplejson" ], "requires_python": "", "summary": "Unoffical Python Interface to the Jodel API (based on iOS)", "version": "1.0.2" }, "last_serial": 5171008, "releases": { "1.0.2": [ { "comment_text": "", "digests": { "md5": "af4e58660566d0944b15aae1b5208e10", "sha256": "14a7562c243684c0c2a0616ec33b96d0b72cb50627974eb3debc530d1bd3de7f" }, "downloads": -1, "filename": "jodel_ios_api-1.0.2-py2-none-any.whl", "has_sig": false, "md5_digest": "af4e58660566d0944b15aae1b5208e10", "packagetype": "bdist_wheel", "python_version": "py2", "requires_python": null, "size": 9456, "upload_time": "2019-04-22T00:21:24", "url": "https://files.pythonhosted.org/packages/02/b5/548642bba737ea31348559ce0de417262fe443bc2e9d9beb4770325d0c05/jodel_ios_api-1.0.2-py2-none-any.whl" }, { "comment_text": "", "digests": { "md5": "e2d0600d09f5486da5599731821af1e1", "sha256": "e5ec521a21a94ee5e8cdb0d65b5fb69d6bffb1cbcad644471e78d25bc7c7d2b8" }, "downloads": -1, "filename": "jodel_ios_api-1.0.2-py3-none-any.whl", "has_sig": false, "md5_digest": "e2d0600d09f5486da5599731821af1e1", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": null, "size": 9457, "upload_time": "2019-04-22T00:15:30", "url": "https://files.pythonhosted.org/packages/dd/9d/2c535afbe7bcdb6d5b521441656140d5ebec6acf48118e66a8de0212f72d/jodel_ios_api-1.0.2-py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "c66e1849a3573aef10857e28901c04fb", "sha256": "d710c191ecfd485168587b268f77f3e9a526ba232d7f6c53af6470bcca1c877c" }, "downloads": -1, "filename": "jodel_ios_api-1.0.2.tar.gz", "has_sig": false, "md5_digest": "c66e1849a3573aef10857e28901c04fb", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 9582, "upload_time": "2019-04-22T00:15:31", "url": "https://files.pythonhosted.org/packages/f7/02/7c036aa0955bce2960c4872d2d9dd71dea0eb1d64ec98609c6a6b208ccc4/jodel_ios_api-1.0.2.tar.gz" } ] }, "urls": [ { "comment_text": "", "digests": { "md5": "af4e58660566d0944b15aae1b5208e10", "sha256": "14a7562c243684c0c2a0616ec33b96d0b72cb50627974eb3debc530d1bd3de7f" }, "downloads": -1, "filename": "jodel_ios_api-1.0.2-py2-none-any.whl", "has_sig": false, "md5_digest": "af4e58660566d0944b15aae1b5208e10", "packagetype": "bdist_wheel", "python_version": "py2", "requires_python": null, "size": 9456, "upload_time": "2019-04-22T00:21:24", "url": "https://files.pythonhosted.org/packages/02/b5/548642bba737ea31348559ce0de417262fe443bc2e9d9beb4770325d0c05/jodel_ios_api-1.0.2-py2-none-any.whl" }, { "comment_text": "", "digests": { "md5": "e2d0600d09f5486da5599731821af1e1", "sha256": "e5ec521a21a94ee5e8cdb0d65b5fb69d6bffb1cbcad644471e78d25bc7c7d2b8" }, "downloads": -1, "filename": "jodel_ios_api-1.0.2-py3-none-any.whl", "has_sig": false, "md5_digest": "e2d0600d09f5486da5599731821af1e1", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": null, "size": 9457, "upload_time": "2019-04-22T00:15:30", "url": "https://files.pythonhosted.org/packages/dd/9d/2c535afbe7bcdb6d5b521441656140d5ebec6acf48118e66a8de0212f72d/jodel_ios_api-1.0.2-py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "c66e1849a3573aef10857e28901c04fb", "sha256": "d710c191ecfd485168587b268f77f3e9a526ba232d7f6c53af6470bcca1c877c" }, "downloads": -1, "filename": "jodel_ios_api-1.0.2.tar.gz", "has_sig": false, "md5_digest": "c66e1849a3573aef10857e28901c04fb", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 9582, "upload_time": "2019-04-22T00:15:31", "url": "https://files.pythonhosted.org/packages/f7/02/7c036aa0955bce2960c4872d2d9dd71dea0eb1d64ec98609c6a6b208ccc4/jodel_ios_api-1.0.2.tar.gz" } ] }