├── .bumpversion.cfg ├── .coveragerc ├── .github ├── hack │ ├── changelog.sh │ └── version.sh └── workflows │ ├── Release.yaml │ ├── Test.yaml │ └── docs.yaml ├── .gitignore ├── CHANGELOG.md ├── LICENSE ├── Makefile ├── README.rst ├── docs ├── docs │ ├── CHANGELOG.md │ ├── images │ │ ├── jetbrains.svg │ │ └── structure.png │ ├── index.md │ ├── installation.md │ ├── previous-version │ │ ├── readme.md │ │ ├── usage_en.md │ │ └── usage_zh.md │ └── usage │ │ ├── graph-api.md │ │ ├── server-send-events.md │ │ └── threads-graph-api.md └── mkdocs.yml ├── examples ├── __init__.py ├── get_facebook_feed.py ├── get_facebook_post_info.py ├── publish_facebook_post.py ├── publish_instagram_media.py └── server_sent_events.py ├── get_token.py ├── pyfacebook ├── __init__.py ├── api │ ├── __init__.py │ ├── base_client.py │ ├── base_resource.py │ ├── facebook │ │ ├── __init__.py │ │ ├── client.py │ │ ├── common_edges │ │ │ ├── __init__.py │ │ │ ├── albums.py │ │ │ ├── comments.py │ │ │ ├── feed.py │ │ │ ├── likes.py │ │ │ ├── live_videos.py │ │ │ ├── photos.py │ │ │ └── videos.py │ │ └── resource │ │ │ ├── __init__.py │ │ │ ├── album.py │ │ │ ├── application.py │ │ │ ├── business.py │ │ │ ├── comment.py │ │ │ ├── conversation.py │ │ │ ├── event.py │ │ │ ├── group.py │ │ │ ├── live_video.py │ │ │ ├── message.py │ │ │ ├── page.py │ │ │ ├── photo.py │ │ │ ├── post.py │ │ │ ├── user.py │ │ │ └── video.py │ ├── graph.py │ ├── instagram_basic │ │ ├── __init__.py │ │ ├── client.py │ │ └── resource │ │ │ ├── __init__.py │ │ │ ├── media.py │ │ │ └── user.py │ └── instagram_business │ │ ├── __init__.py │ │ ├── client.py │ │ └── resource │ │ ├── __init__.py │ │ ├── comment.py │ │ ├── container.py │ │ ├── hashtag.py │ │ ├── media.py │ │ └── user.py ├── exceptions.py ├── models │ ├── __init__.py │ ├── album.py │ ├── application.py │ ├── attachment.py │ ├── base.py │ ├── business.py │ ├── comment.py │ ├── conversation.py │ ├── event.py │ ├── extensions.py │ ├── group.py │ ├── ig_basic_models.py │ ├── ig_business_models.py │ ├── image.py │ ├── live_video.py │ ├── message.py │ ├── page.py │ ├── photo.py │ ├── place.py │ ├── post.py │ ├── user.py │ └── video.py ├── ratelimit.py └── utils │ ├── __init__.py │ ├── constant.py │ └── params_utils.py ├── pyproject.toml ├── pytest.ini ├── testdata ├── base │ ├── 19292868552-picture.png │ ├── basic_display_api_user_token.json │ ├── connecion_data.json │ ├── discovery_medias_p1.json │ ├── discovery_medias_p2.json │ ├── error_data.json │ ├── full_connecions_p1.json │ ├── full_connecions_p2.json │ ├── long_term_token.json │ ├── object_data.json │ ├── object_default.json │ ├── objects_default.json │ ├── threads_user_long_lived_token.json │ ├── threads_user_token.json │ ├── token_info.json │ └── user_accounts_token.json ├── error.json ├── facebook │ ├── apidata │ │ ├── albums │ │ │ ├── album_info_default.json │ │ │ ├── album_info_fields.json │ │ │ ├── albums_info_default.json │ │ │ ├── albums_info_fields.json │ │ │ ├── albums_list_p1.json │ │ │ └── albums_list_p2.json │ │ ├── applications │ │ │ ├── application_accounts.json │ │ │ └── application_info.json │ │ ├── business │ │ │ ├── business_info.json │ │ │ └── businesses_info.json │ │ ├── comments │ │ │ ├── comment_info.json │ │ │ ├── comments_info.json │ │ │ ├── comments_p1.json │ │ │ ├── comments_p2.json │ │ │ └── create_resp.json │ │ ├── conversations │ │ │ ├── cvs_info.json │ │ │ └── cvses_info.json │ │ ├── events │ │ │ ├── event_info.json │ │ │ └── events_info.json │ │ ├── groups │ │ │ ├── feed_p1.json │ │ │ ├── feed_p2.json │ │ │ ├── group_default_fields.json │ │ │ ├── group_fields.json │ │ │ ├── groups_default_fields.json │ │ │ └── groups_fields.json │ │ ├── likes │ │ │ └── likes_resp.json │ │ ├── live_videos │ │ │ ├── live_video_default.json │ │ │ ├── live_video_fields.json │ │ │ ├── live_videos_default.json │ │ │ ├── live_videos_fields.json │ │ │ ├── live_videos_p1.json │ │ │ └── live_videos_p2.json │ │ ├── messages │ │ │ ├── message_info.json │ │ │ └── messages_info.json │ │ ├── pages │ │ │ ├── multi_default_fields.json │ │ │ ├── multi_pages.json │ │ │ ├── search_pages.json │ │ │ ├── single_default_page.json │ │ │ └── single_fields_page.json │ │ ├── photos │ │ │ ├── photo_info_default.json │ │ │ ├── photo_info_fields.json │ │ │ ├── photos_info_default.json │ │ │ ├── photos_info_fields.json │ │ │ ├── photos_p1.json │ │ │ └── photos_p2.json │ │ ├── pictures │ │ │ ├── multi_pictures.json │ │ │ └── single_picture.json │ │ ├── posts │ │ │ ├── feed_fields_p1.json │ │ │ ├── feed_fields_p2.json │ │ │ ├── feeds_default_fields_p1.json │ │ │ ├── feeds_default_fields_p2.json │ │ │ ├── multi_posts_data.json │ │ │ ├── multi_posts_data_fields.json │ │ │ ├── single_post_data.json │ │ │ └── single_post_data_fields.json │ │ ├── users │ │ │ ├── user.json │ │ │ ├── user_accounts_p1.json │ │ │ ├── user_accounts_p2.json │ │ │ ├── user_businesses.json │ │ │ ├── users_default.json │ │ │ └── users_fields.json │ │ └── videos │ │ │ ├── video_info_default.json │ │ │ ├── video_info_fields.json │ │ │ ├── videos_info_default.json │ │ │ ├── videos_info_fields.json │ │ │ ├── videos_p1.json │ │ │ └── videos_p2.json │ └── models │ │ ├── album.json │ │ ├── business.json │ │ ├── comment.json │ │ ├── conversation.json │ │ ├── event.json │ │ ├── group.json │ │ ├── live_video.json │ │ ├── message.json │ │ ├── page.json │ │ ├── photo.json │ │ ├── post.json │ │ ├── user.json │ │ └── video.json ├── instagram │ ├── apidata │ │ ├── comments │ │ │ ├── comment_fields.json │ │ │ ├── comments_fields.json │ │ │ └── replies.json │ │ ├── discovery │ │ │ ├── medias_p1.json │ │ │ ├── medias_p2.json │ │ │ └── user_fields.json │ │ ├── hashtags │ │ │ ├── hashtag_info.json │ │ │ ├── hashtag_recent_medias_p1.json │ │ │ ├── hashtag_recent_medias_p2.json │ │ │ ├── hashtag_top_medias_p1.json │ │ │ ├── hashtag_top_medias_p2.json │ │ │ └── hashtags_info.json │ │ ├── medias │ │ │ ├── children.json │ │ │ ├── comments_p1.json │ │ │ ├── comments_p2.json │ │ │ ├── insights.json │ │ │ ├── insights_new.json │ │ │ ├── media_default.json │ │ │ ├── medias_fields.json │ │ │ └── product_tags.json │ │ ├── publish │ │ │ ├── container_info.json │ │ │ ├── containers_info.json │ │ │ ├── create_photo.json │ │ │ ├── create_video.json │ │ │ ├── publish_container.json │ │ │ └── publish_limit_resp.json │ │ ├── stories │ │ │ ├── stories_default.json │ │ │ ├── stories_fields_p1.json │ │ │ ├── stories_fields_p2.json │ │ │ ├── stories_info.json │ │ │ └── story_info.json │ │ └── users │ │ │ ├── available_catalogs.json │ │ │ ├── catalog_product_search.json │ │ │ ├── content_publish_limit.json │ │ │ ├── hashtag_search.json │ │ │ ├── live_medias.json │ │ │ ├── medias_p1.json │ │ │ ├── medias_p2.json │ │ │ ├── mentioned_comment.json │ │ │ ├── mentioned_media.json │ │ │ ├── product_appeal.json │ │ │ ├── recently_searched_hashtags.json │ │ │ ├── stories.json │ │ │ ├── tagged_medias.json │ │ │ ├── user_fields.json │ │ │ ├── user_insights.json │ │ │ └── user_insights_new.json │ └── models │ │ ├── ig_comment.json │ │ ├── ig_container.json │ │ ├── ig_hashtag.json │ │ ├── ig_insight.json │ │ ├── ig_media.json │ │ ├── ig_publish_limit.json │ │ ├── ig_reply.json │ │ ├── ig_story.json │ │ └── ig_user.json └── instagram_basic │ ├── apidata │ ├── media │ │ ├── media_children.json │ │ ├── media_info.json │ │ └── medias_info.json │ └── user │ │ ├── user_info.json │ │ ├── user_medias_p1.json │ │ └── user_medias_p2.json │ └── models │ ├── media_info.json │ └── user_info.json ├── tests ├── __init__.py ├── conftest.py ├── facebook │ ├── __init__.py │ ├── conftest.py │ ├── edges │ │ ├── __init__.py │ │ └── test_likes.py │ ├── test_album.py │ ├── test_application.py │ ├── test_base.py │ ├── test_business.py │ ├── test_comment.py │ ├── test_conversation.py │ ├── test_event.py │ ├── test_group.py │ ├── test_live_video.py │ ├── test_message.py │ ├── test_page.py │ ├── test_photo.py │ ├── test_post.py │ ├── test_user.py │ └── test_video.py ├── instagram_basic │ ├── __init__.py │ ├── conftest.py │ ├── test_media.py │ └── test_user.py ├── instagram_business │ ├── __init__.py │ ├── conftest.py │ ├── test_comment.py │ ├── test_hashtag.py │ ├── test_media.py │ ├── test_publish.py │ └── test_user.py ├── test_basic_display_api.py ├── test_exception.py ├── test_graph.py ├── test_models.py ├── test_ratelimit.py ├── test_server_sent_events.py ├── test_threads_graph_api.py └── utils │ ├── __init__.py │ └── test_params_utils.py └── tox.ini /.bumpversion.cfg: -------------------------------------------------------------------------------- 1 | [bumpversion] 2 | current_version = 0.20.1 3 | commit = True 4 | tag = True 5 | 6 | [bumpversion:file:pyfacebook/__init__.py] 7 | 8 | [bumpversion:file:pyproject.toml] 9 | -------------------------------------------------------------------------------- /.coveragerc: -------------------------------------------------------------------------------- 1 | [run] 2 | omit = pyfacebook/__version__.py -------------------------------------------------------------------------------- /.github/hack/changelog.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | MARKER_PREFIX="##" 4 | VERSION=$(echo "$1" | sed 's/^v//g') 5 | 6 | IFS='' 7 | found=0 8 | 9 | while read -r "line"; do 10 | # If not found and matching heading 11 | if [ $found -eq 0 ] && echo "$line" | grep -q "$MARKER_PREFIX \[$VERSION\]"; then 12 | echo "$line" 13 | found=1 14 | continue 15 | fi 16 | 17 | # If needed version if found, and reaching next delimter - stop 18 | if [ $found -eq 1 ] && echo "$line" | grep -q -E "$MARKER_PREFIX \[[[:digit:]]+\.[[:digit:]]+\.[[:digit:]]+\]"; then 19 | found=0 20 | break 21 | fi 22 | 23 | # Keep printing out lines as no other version delimiter found 24 | if [ $found -eq 1 ]; then 25 | echo "$line" 26 | fi 27 | done < CHANGELOG.md -------------------------------------------------------------------------------- /.github/hack/version.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | LATEST_TAG_REV=$(git rev-list --tags --max-count=1) 4 | LATEST_COMMIT_REV=$(git rev-list HEAD --max-count=1) 5 | 6 | if [ -n "$LATEST_TAG_REV" ]; then 7 | LATEST_TAG=$(git describe --tags "$(git rev-list --tags --max-count=1)") 8 | else 9 | LATEST_TAG="v0.0.0" 10 | fi 11 | 12 | if [ "$LATEST_TAG_REV" != "$LATEST_COMMIT_REV" ]; then 13 | echo "$LATEST_TAG+$(git rev-list HEAD --max-count=1 --abbrev-commit)" 14 | else 15 | echo "$LATEST_TAG" 16 | fi -------------------------------------------------------------------------------- /.github/workflows/Release.yaml: -------------------------------------------------------------------------------- 1 | name: Publish Pypi 2 | on: 3 | push: 4 | tags: 5 | - 'v*.*.*' 6 | jobs: 7 | build: 8 | runs-on: ubuntu-latest 9 | steps: 10 | - uses: actions/checkout@v3 11 | - name: Build and publish to pypi 12 | uses: JRubics/poetry-publish@v1.17 13 | with: 14 | pypi_token: ${{ secrets.PYPI_TOKEN }} 15 | 16 | - name: Generate Changelog 17 | run: | 18 | VERSION=$(.github/hack/version.sh) 19 | .github/hack/changelog.sh $VERSION > NEW-VERSION-CHANGELOG.md 20 | 21 | - name: Publish 22 | uses: softprops/action-gh-release@v1 23 | with: 24 | body_path: NEW-VERSION-CHANGELOG.md 25 | env: 26 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 27 | -------------------------------------------------------------------------------- /.github/workflows/Test.yaml: -------------------------------------------------------------------------------- 1 | name: Test 2 | 3 | on: 4 | pull_request: 5 | push: 6 | branches: 7 | - master 8 | 9 | jobs: 10 | test: 11 | runs-on: ubuntu-latest 12 | strategy: 13 | matrix: 14 | python-version: ['3.7', '3.8', '3.9', '3.10', '3.11', '3.12'] 15 | include: 16 | - python-version: '3.10' 17 | update-coverage: true 18 | 19 | 20 | steps: 21 | - uses: actions/checkout@v4 22 | - name: Set up Python ${{ matrix.python-version }} 23 | uses: actions/setup-python@v5 24 | with: 25 | python-version: ${{ matrix.python-version }} 26 | cache: 'pip' 27 | cache-dependency-path: '**/pyproject.toml' 28 | - name: Install dependencies 29 | run: | 30 | python -m pip install --upgrade pip poetry 31 | poetry install 32 | - name: Test with pytest 33 | run: poetry run pytest 34 | - name: Upload coverage to Codecov 35 | if: ${{ matrix.update-coverage }} 36 | uses: codecov/codecov-action@v4 37 | with: 38 | files: ./coverage.xml 39 | fail_ci_if_error: true 40 | token: ${{ secrets.CODECOV_TOKEN }} # required 41 | verbose: true 42 | 43 | lint: 44 | name: black 45 | runs-on: ubuntu-latest 46 | 47 | steps: 48 | - uses: actions/checkout@v3 49 | - uses: actions/setup-python@v4 50 | with: 51 | python-version: '3.10' 52 | cache: 'pip' 53 | - name: Install dependencies 54 | run: python -m pip install --upgrade pip black 55 | - name: Black test 56 | run: make lint-check 57 | -------------------------------------------------------------------------------- /.github/workflows/docs.yaml: -------------------------------------------------------------------------------- 1 | name: Publish docs via GitHub Pages 2 | on: 3 | push: 4 | branches: 5 | - master 6 | jobs: 7 | deploy: 8 | runs-on: ubuntu-latest 9 | steps: 10 | - uses: actions/checkout@v3 11 | - uses: actions/setup-python@v4 12 | with: 13 | python-version: '3.10' 14 | cache: 'pip' 15 | - run: pip install mkdocs-material 16 | - run: mkdocs gh-deploy -f docs/mkdocs.yml --force -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Created by .ignore support plugin (hsz.mobi) 2 | ### Python template 3 | # Byte-compiled / optimized / DLL files 4 | __pycache__/ 5 | *.py[cod] 6 | *$py.class 7 | 8 | # C extensions 9 | *.so 10 | 11 | # Distribution / packaging 12 | .Python 13 | build/ 14 | develop-eggs/ 15 | dist/ 16 | downloads/ 17 | eggs/ 18 | .eggs/ 19 | lib/ 20 | lib64/ 21 | parts/ 22 | sdist/ 23 | var/ 24 | wheels/ 25 | *.egg-info/ 26 | .installed.cfg 27 | *.egg 28 | MANIFEST 29 | 30 | # PyInstaller 31 | # Usually these files are written by a python script from a template 32 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 33 | *.manifest 34 | *.spec 35 | 36 | # Installer logs 37 | pip-log.txt 38 | pip-delete-this-directory.txt 39 | 40 | # Unit test / coverage reports 41 | htmlcov/ 42 | .tox/ 43 | .coverage 44 | .coverage.* 45 | .cache 46 | nosetests.xml 47 | coverage.xml 48 | *.cover 49 | .hypothesis/ 50 | .pytest_cache/ 51 | 52 | # Translations 53 | *.mo 54 | *.pot 55 | 56 | # Sphinx documentation 57 | docs/_build/ 58 | 59 | # pyenv 60 | .python-version 61 | 62 | # Poetry 63 | poetry.lock 64 | 65 | # Environments 66 | .env 67 | .venv 68 | env/ 69 | venv/ 70 | ENV/ 71 | env.bak/ 72 | venv.bak/ 73 | 74 | # mkdocs documentation 75 | /site 76 | 77 | # mypy 78 | .mypy_cache/ 79 | 80 | # PyCharm 81 | .idea/ 82 | .vscode/ -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | .PHONY: clean lint test 2 | 3 | help: 4 | @echo " env install all dependencies" 5 | @echo " clean remove unwanted stuff" 6 | @echo " lint check style with flake8" 7 | @echo " test run tests" 8 | @echo " cov-term run coverage output term" 9 | 10 | env: 11 | pip install --upgrade pip 12 | pip install poetry 13 | poetry install 14 | 15 | clean: clean-build clean-pyc clean-test 16 | 17 | clean-build: 18 | rm -fr build/ 19 | rm -fr dist/ 20 | rm -fr .eggs/ 21 | find . -name '*.egg-info' -exec rm -fr {} + 22 | find . -name '*.egg' -exec rm -f {} + 23 | 24 | clean-pyc: 25 | find . -name '*.pyc' -exec rm -f {} + 26 | find . -name '*.pyo' -exec rm -f {} + 27 | find . -name '*~' -exec rm -f {} + 28 | find . -name '__pycache__' -exec rm -fr {} + 29 | 30 | clean-test: 31 | rm -fr .tox/ 32 | rm -fr .pytest_cache 33 | rm -f .coverage 34 | rm -fr htmlcov/ 35 | 36 | cov-term: clean-pyc 37 | pytest -s --cov=pyfacebook --cov-report term 38 | 39 | cov-html: clean-pyc 40 | pytest -s --cov=pyfacebook --cov-report html 41 | 42 | lint-check: 43 | black --check . 44 | 45 | lint: 46 | black . 47 | 48 | test: 49 | pytest -s 50 | -------------------------------------------------------------------------------- /docs/docs/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | ../../CHANGELOG.md -------------------------------------------------------------------------------- /docs/docs/images/structure.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sns-sdks/python-facebook/f51a56229c2a767a64b8295160bb2f49da8a39c7/docs/docs/images/structure.png -------------------------------------------------------------------------------- /docs/docs/index.md: -------------------------------------------------------------------------------- 1 | # Welcome to Python-Facebook's documentation! 2 | 3 | **A Python wrapper around for Facebook Graph API.** 4 | 5 | Author: IkarosKun 6 | 7 | ## Introduction 8 | 9 | The Graph API is the primary way for apps to read and write to the Facebook social graph. 10 | 11 | This library provides a Python interface for the [Facebook Graph API](https://developers.facebook.com/docs/graph-api). 12 | Library could work on Python 3.6+ 13 | 14 | 15 | !!! warning "Python 2.7" 16 | 17 | According to plan, v0.9.x series will be the last to support Python 2.7. 18 | -------------------------------------------------------------------------------- /docs/docs/installation.md: -------------------------------------------------------------------------------- 1 | This library supports Python 3.6 and newer. 2 | 3 | ## Dependencies 4 | 5 | These distributions will be installed automatically when installing Python-Facebook-Api. 6 | 7 | - [requests](https://2.python-requests.org/en/master/): An elegant and simple HTTP library for Python, built for human beings. 8 | - [Requests-OAuthlib](https://requests-oauthlib.readthedocs.io/en/latest/): A library uses the Python Requests and OAuthlib libraries to provide an easy-to-use Python interface for building OAuth1 and OAuth2 clients. 9 | 10 | ## Installation 11 | 12 | You can install this library from **PyPI**. 13 | 14 | ```shell 15 | ~ pip install --upgrade python-facebook-api 16 | ``` 17 | 18 | Also, you can build this library from source code. 19 | 20 | ```shell 21 | git clone https://github.com/sns-sdks/python-facebook.git 22 | cd python-facebook 23 | make env 24 | make build 25 | ``` 26 | 27 | ## Testing 28 | 29 | If you have installed the requirements use `make env`. 30 | 31 | You can use following command to test the code. 32 | 33 | ```shell 34 | make test 35 | ``` 36 | -------------------------------------------------------------------------------- /docs/docs/previous-version/readme.md: -------------------------------------------------------------------------------- 1 | This is the docs for the previous version series `0.9.x`. 2 | -------------------------------------------------------------------------------- /docs/docs/usage/server-send-events.md: -------------------------------------------------------------------------------- 1 | ## Introduction 2 | 3 | Server-Sent Events allows you to receive real-time updates for live video comments and reactions. It uses the Server-Sent Events (SSE) web standard to send real-time, continuous data streams to browser clients, once an initial client connection has been established. 4 | 5 | More detail you can see [docs](https://developers.facebook.com/docs/graph-api/server-sent-events). 6 | 7 | Here, we give a simple example to show how to implement it by this library. 8 | 9 | ## How to use 10 | 11 | ### Custom data handler 12 | 13 | You need override `on_data` method to handle the data. 14 | 15 | As follows, we just print the real data from facebook. 16 | 17 | ```python 18 | import json 19 | 20 | from pyfacebook import ServerSentEventAPI 21 | 22 | class MyEvent(ServerSentEventAPI): 23 | def on_data(self, data): 24 | raw_data: str = data.decode() 25 | 26 | data = json.loads(raw_data[5:]) 27 | print(f"Comment Data: {data}") 28 | 29 | ``` 30 | 31 | ### Connect the server 32 | 33 | Then you can connect the facebook server to get pushed data. 34 | 35 | ```python 36 | event_api = MyEvent(access_token="Your access token") 37 | event_api.live_comments( 38 | live_video_id="ID for the live video", 39 | fields="from{id,name},message" 40 | ) 41 | 42 | # output 43 | # Comment Data: {'id': '611384697233703_2059142704258615', 'created_time': '2022-08-31T10:03:00+0000', 'from': {'id': '100621042235323', 'name': 'HeyJoklena'}, 'message': 'hello sse', 'object': {'description': 'section 1, 1, 2', 'updated_time': '2022-08-31T10:03:00+0000', 'id': '611384697233703'}} 44 | # Comment Data: {'id': '611384697233703_1165171867677765', 'created_time': '2022-08-31T10:03:29+0000', 'from': {'id': '100621042235323', 'name': 'HeyJoklena'}, 'message': 'sse is nice', 'object': {'description': 'section 1, 1, 2', 'updated_time': '2022-08-31T10:03:00+0000', 'id': '611384697233703'}} 45 | ``` 46 | 47 | Now if the live video has new comment, you will see the comment output. 48 | -------------------------------------------------------------------------------- /docs/docs/usage/threads-graph-api.md: -------------------------------------------------------------------------------- 1 | ## Introduction 2 | 3 | You may use the Threads API to enable people to create and publish content on a person’s behalf on Threads, and to 4 | display those posts within your app solely to the person who created it. 5 | 6 | ## How to use 7 | 8 | Just like the base `Graph API`. 9 | 10 | The following code snippet shows how to perform an OAuth flow with the Threads API: 11 | 12 | ```python 13 | from pyfacebook import ThreadsGraphAPI 14 | 15 | api = ThreadsGraphAPI( 16 | app_id="Your app id", 17 | app_secret="Your app secret", 18 | oauth_flow=True, 19 | redirect_uri="Your callback domain", 20 | scope=["threads_basic", "threads_content_publish", "threads_read_replies", "threads_manage_replies", 21 | "threads_manage_insights"] 22 | ) 23 | 24 | # Got authorization url 25 | api.get_authorization_url() 26 | # https://threads.net/oauth/authorize?response_type=code&client_id=app_id&redirect_uri=https%3A%2F%2Fexample.com%2Fcallback&scope=threads_basic%2Cthreads_content_publish%2Cthreads_read_replies%2Cthreads_manage_replies%2Cthreads_manage_insights&state=PyFacebook 27 | 28 | # Once the user has authorized your app, you will get the redirected URL. 29 | # like `https://example.com/callback?code=AQBZzYhLZB&state=PyFacebook#_` 30 | token = api.exchange_user_access_token(response="Your response url") 31 | print(token) 32 | # {'access_token': 'access_token', 'user_id': 12342412} 33 | ``` 34 | 35 | After those steps, you can use the `api` object to call the Threads API. 36 | 37 | For example: 38 | 39 | ```python 40 | api.get_object(object_id="me", fields=["id"]) 41 | 42 | # {'id': '12342412'} 43 | ``` 44 | -------------------------------------------------------------------------------- /docs/mkdocs.yml: -------------------------------------------------------------------------------- 1 | site_name: Python Facebook Docs 2 | site_description: Docs for python-facebook library 3 | site_url: https://sns-sdks.github.io/python-facebook/ 4 | repo_url: https://github.com/sns-sdks/python-facebook 5 | copyright: Copyright © 2019 - 2021 Ikaros kun 6 | 7 | theme: 8 | name: material 9 | features: 10 | - navigation.tabs 11 | palette: 12 | # Light mode 13 | - media: "(prefers-color-scheme: light)" 14 | scheme: default 15 | primary: indigo 16 | accent: indigo 17 | toggle: 18 | icon: material/toggle-switch-off-outline 19 | name: Switch to dark mode 20 | 21 | # Dark mode 22 | - media: "(prefers-color-scheme: dark)" 23 | scheme: slate 24 | primary: blue 25 | accent: blue 26 | toggle: 27 | icon: material/toggle-switch 28 | name: Switch to light mode 29 | 30 | nav: 31 | - Introduction: index.md 32 | - Installation: installation.md 33 | - Usage: 34 | - Graph API: usage/graph-api.md 35 | - Server-Sent Events: usage/server-send-events.md 36 | - Threads Graph API: usage/threads-graph-api.md 37 | - Changelog: CHANGELOG.md 38 | - Previous Version Docs: 39 | - README: previous-version/readme.md 40 | - usage-en: previous-version/usage_en.md 41 | - 基础教程: previous-version/usage_zh.md 42 | extra: 43 | social: 44 | - icon: fontawesome/brands/twitter 45 | link: https://twitter.com/realllkk520 46 | - icon: fontawesome/brands/github 47 | link: https://github.com/sns-sdks/python-facebook 48 | 49 | markdown_extensions: 50 | - codehilite 51 | - admonition 52 | - pymdownx.superfences 53 | - pymdownx.emoji 54 | -------------------------------------------------------------------------------- /examples/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sns-sdks/python-facebook/f51a56229c2a767a64b8295160bb2f49da8a39c7/examples/__init__.py -------------------------------------------------------------------------------- /examples/get_facebook_feed.py: -------------------------------------------------------------------------------- 1 | """ 2 | This is an example for page get recent 50 feeds 3 | 4 | Refer: https://developers.facebook.com/docs/graph-api/reference/page/feed#read 5 | """ 6 | 7 | import json 8 | import os 9 | 10 | from pyfacebook import GraphAPI 11 | 12 | APP_ID = os.environ.get("APP_ID") # Your App ID 13 | APP_SECRET = os.environ.get("APP_SECRET") # Your App secret 14 | ACCESS_TOKEN = os.environ.get("ACCESS_TOKEN") # Your Access Token 15 | 16 | 17 | def handler(page_id): 18 | api = GraphAPI(app_id=APP_ID, app_secret=APP_SECRET, access_token=ACCESS_TOKEN) 19 | feed = api.get_full_connections( 20 | object_id=page_id, 21 | connection="feed", 22 | count=50, 23 | limit=25, 24 | fields="id,message,create_time", 25 | ) 26 | with open(f"./{page_id}.json", "w+") as f: 27 | json.dump(feed, f) 28 | 29 | 30 | if __name__ == "__main__": 31 | handler(page_id="meta") 32 | -------------------------------------------------------------------------------- /examples/get_facebook_post_info.py: -------------------------------------------------------------------------------- 1 | """ 2 | This is an example for get post detail by FacebookApi class. 3 | 4 | Refer: https://developers.facebook.com/docs/graph-api/reference/pagepost 5 | """ 6 | 7 | import os 8 | 9 | from pyfacebook import FacebookApi 10 | 11 | APP_ID = os.environ.get("APP_ID") # Your App ID 12 | APP_SECRET = os.environ.get("APP_SECRET") # Your App secret 13 | ACCESS_TOKEN = os.environ.get("ACCESS_TOKEN") # Your Access Token 14 | 15 | 16 | def handler(post_id): 17 | api = FacebookApi(app_id=APP_ID, app_secret=APP_SECRET, access_token=ACCESS_TOKEN) 18 | post = api.post.get_info( 19 | post_id=post_id, 20 | fields="id,message,created_time,full_picture,status_type,updated_time", 21 | ) 22 | print(f"ID: {post.id}") 23 | print(f"Time: {post.created_time}") 24 | print(f"Data: {post.to_json()}") 25 | return True 26 | 27 | 28 | if __name__ == "__main__": 29 | handler(post_id="19292868552_371106181716390") 30 | -------------------------------------------------------------------------------- /examples/publish_facebook_post.py: -------------------------------------------------------------------------------- 1 | """ 2 | This is an example for facebook page publish a post. 3 | 4 | Refer: https://developers.facebook.com/docs/graph-api/reference/page/feed#publish 5 | """ 6 | 7 | import os 8 | 9 | from pyfacebook import GraphAPI 10 | 11 | APP_ID = os.environ.get("APP_ID") # Your App ID 12 | APP_SECRET = os.environ.get("APP_SECRET") # Your App secret 13 | ACCESS_TOKEN = os.environ.get("ACCESS_TOKEN") # Your Access Token with the target page 14 | 15 | 16 | def publish_simple_posts(page_id): 17 | api = GraphAPI(app_id=APP_ID, app_secret=APP_SECRET, access_token=ACCESS_TOKEN) 18 | 19 | data = api.post_object( 20 | object_id=page_id, 21 | connection="feed", 22 | params={ 23 | "fields": "id,message,created_time,from", 24 | }, 25 | data={"message": "This is a test message by api"}, 26 | ) 27 | print(data) 28 | # {'id': 'xxx', 'message': 'This is a test message by api', 'created_time': '2022-06-01T03:49:36+0000', 'from': {'name': 'xx', 'id': 'xxxx'}} 29 | return True 30 | 31 | 32 | if __name__ == "__main__": 33 | publish_simple_posts(page_id="meta") 34 | -------------------------------------------------------------------------------- /examples/publish_instagram_media.py: -------------------------------------------------------------------------------- 1 | """ 2 | This is an example for instagram business account to publish an image media. 3 | 4 | Refer: https://developers.facebook.com/docs/instagram-api/reference/ig-user/media 5 | """ 6 | 7 | import os 8 | 9 | from pyfacebook import GraphAPI 10 | 11 | ACCESS_TOKEN = os.environ.get("ACCESS_TOKEN") # Your Access Token 12 | INSTAGRAM_BUSINESS_ID = os.environ.get( 13 | "INSTAGRAM_BUSINESS_ID" 14 | ) # Your instagram business id 15 | 16 | api = GraphAPI(access_token=ACCESS_TOKEN) 17 | 18 | data = api.post_object( 19 | object_id=INSTAGRAM_BUSINESS_ID, 20 | connection="media", 21 | params={ 22 | "image_url": "https://example.com/example.png", # replace with your image url. 23 | "caption": "Image by api", # replace with your caption for the media. 24 | }, 25 | ) 26 | print(data) 27 | # {'id': '17952987976782688'} 28 | # Get your container id. 29 | container_id = data["id"] 30 | 31 | # Then publish the container. 32 | publish_data = api.post_object( 33 | object_id=INSTAGRAM_BUSINESS_ID, 34 | connection="media_publish", 35 | params={ 36 | "creation_id": container_id, 37 | }, 38 | ) 39 | print(publish_data) 40 | # Now will get the published media id. 41 | # {'id': '17899702154554435'} 42 | -------------------------------------------------------------------------------- /examples/server_sent_events.py: -------------------------------------------------------------------------------- 1 | """ 2 | A demo for sample streaming api. 3 | """ 4 | 5 | import json 6 | import logging 7 | 8 | from pyfacebook import ServerSentEventAPI 9 | 10 | access_token = "Your access token" 11 | live_video_id = "ID for live video" 12 | debug = False 13 | 14 | if debug: 15 | logging.basicConfig() 16 | logging.getLogger().setLevel(logging.DEBUG) 17 | 18 | 19 | class MyEvent(ServerSentEventAPI): 20 | def on_data(self, data): 21 | raw_data: str = data.decode() 22 | 23 | data = json.loads(raw_data[5:]) 24 | print(f"Comment Data: {data}") 25 | 26 | 27 | def handler(): 28 | stream_api = MyEvent(access_token=access_token) 29 | stream_api.live_comments( 30 | live_video_id=live_video_id, 31 | comment_rate="one_per_two_seconds", 32 | fields="id,attachment,created_time,from{id,name},message,object", 33 | ) 34 | 35 | 36 | if __name__ == "__main__": 37 | handler() 38 | -------------------------------------------------------------------------------- /pyfacebook/__init__.py: -------------------------------------------------------------------------------- 1 | from pyfacebook.models import * 2 | from pyfacebook.ratelimit import RateLimitHeader, RateLimit, PercentSecond 3 | from pyfacebook.exceptions import PyFacebookException, FacebookError, LibraryError 4 | from pyfacebook.api import ( 5 | GraphAPI, 6 | BasicDisplayAPI, 7 | ThreadsGraphAPI, 8 | ServerSentEventAPI, 9 | ) 10 | from pyfacebook.api.facebook.client import FacebookApi 11 | from pyfacebook.api.instagram_business.client import IGBusinessApi 12 | from pyfacebook.api.instagram_basic.client import IGBasicDisplayApi 13 | 14 | __version__ = "0.20.1" 15 | -------------------------------------------------------------------------------- /pyfacebook/api/__init__.py: -------------------------------------------------------------------------------- 1 | from .graph import GraphAPI, BasicDisplayAPI, ThreadsGraphAPI, ServerSentEventAPI 2 | -------------------------------------------------------------------------------- /pyfacebook/api/base_client.py: -------------------------------------------------------------------------------- 1 | """ 2 | Base client for API. 3 | """ 4 | 5 | import inspect 6 | 7 | from pyfacebook import GraphAPI, BasicDisplayAPI 8 | from pyfacebook.api.base_resource import BaseResource 9 | 10 | 11 | def _is_resource_cls(obj): 12 | return isinstance(obj, BaseResource) 13 | 14 | 15 | class BaseApi(GraphAPI): 16 | def __new__(cls, *args, **kwargs): 17 | self = super().__new__(cls) 18 | resources = inspect.getmembers(cls, _is_resource_cls) 19 | for name, resource in resources: 20 | resource_cls = type(resource) 21 | resource = resource_cls(self) 22 | setattr(self, name, resource) 23 | return self 24 | 25 | 26 | class BaseBasicDisplayApi(BasicDisplayAPI, BaseApi): 27 | pass 28 | -------------------------------------------------------------------------------- /pyfacebook/api/base_resource.py: -------------------------------------------------------------------------------- 1 | """ 2 | Resource base class 3 | """ 4 | 5 | from pyfacebook.api.graph import GraphAPI 6 | 7 | 8 | class BaseResource: 9 | """Resource base class""" 10 | 11 | def __init__(self, client=None): 12 | self._client: GraphAPI = client 13 | 14 | @property 15 | def access_token(self): 16 | return self._client.access_token 17 | 18 | @property 19 | def app_id(self): 20 | return self._client.app_id 21 | 22 | @property 23 | def app_secret(self): 24 | return self._client.app_secret 25 | 26 | @property 27 | def client(self): 28 | return self._client 29 | -------------------------------------------------------------------------------- /pyfacebook/api/facebook/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sns-sdks/python-facebook/f51a56229c2a767a64b8295160bb2f49da8a39c7/pyfacebook/api/facebook/__init__.py -------------------------------------------------------------------------------- /pyfacebook/api/facebook/client.py: -------------------------------------------------------------------------------- 1 | """ 2 | Client for facebook graph api 3 | """ 4 | 5 | from pyfacebook.api.base_client import BaseApi 6 | from pyfacebook.api.facebook import resource as rs 7 | 8 | 9 | class FacebookApi(BaseApi): 10 | """ 11 | Api class for facebook 12 | """ 13 | 14 | application = rs.FacebookApplication() 15 | business = rs.FacebookBusiness() 16 | user = rs.FacebookUser() 17 | page = rs.FacebookPage() 18 | post = rs.FacebookPost() 19 | group = rs.FacebookGroup() 20 | event = rs.FacebookEvent() 21 | photo = rs.FacebookPhoto() 22 | album = rs.FacebookAlbum() 23 | video = rs.FacebookVideo() 24 | live_video = rs.FacebookLiveVideo() 25 | comment = rs.FacebookComment() 26 | conversation = rs.FacebookConversation() 27 | message = rs.FacebookMessage() 28 | -------------------------------------------------------------------------------- /pyfacebook/api/facebook/common_edges/__init__.py: -------------------------------------------------------------------------------- 1 | from .feed import FeedEdge 2 | from .albums import AlbumsEdge 3 | from .photos import PhotosEdge 4 | from .videos import VideosEdge 5 | from .likes import LikesEdge 6 | from .live_videos import LiveVideosEdge 7 | from .comments import CommentsEdge 8 | -------------------------------------------------------------------------------- /pyfacebook/api/facebook/common_edges/albums.py: -------------------------------------------------------------------------------- 1 | """ 2 | Albums edge for resource. 3 | """ 4 | 5 | from typing import Optional, Union 6 | 7 | import pyfacebook.utils.constant as const 8 | from pyfacebook.models.album import AlbumResponse 9 | from pyfacebook.utils.params_utils import enf_comma_separated 10 | 11 | 12 | class AlbumsEdge: 13 | __slots__ = () 14 | 15 | def get_albums( 16 | self, 17 | object_id: str, 18 | fields: Optional[Union[str, list, dict]] = None, 19 | since: Optional[str] = None, 20 | until: Optional[str] = None, 21 | count: Optional[int] = 10, 22 | limit: Optional[int] = 10, 23 | return_json: bool = False, 24 | **kwargs, 25 | ) -> Union[AlbumResponse, dict]: 26 | """ 27 | Get a list of Albums on a Facebook object. 28 | 29 | :param object_id: ID for object(like page,group,user..). 30 | :param fields: Comma-separated id string for data fields which you want. 31 | You can also pass this with an id list, tuple. 32 | :param since: A Unix timestamp or strtotime data value that points to the start of data. 33 | :param until: A Unix timestamp or strtotime data value that points to the end of data. 34 | :param count: The total count for you to get data. 35 | :param limit: Each request retrieve objects count. 36 | It should no more than 100. Default is None will use api default limit. 37 | :param return_json: Set to false will return a dataclass for Album. 38 | Or return json data. Default is false. 39 | :param kwargs: Additional parameters for different object. 40 | :return: Albums response information 41 | """ 42 | 43 | if fields is None: 44 | fields = const.ALBUM_PUBLIC_FIELDS 45 | 46 | data = self.client.get_full_connections( 47 | object_id=object_id, 48 | connection="albums", 49 | count=count, 50 | limit=limit, 51 | fields=enf_comma_separated(field="fields", value=fields), 52 | since=since, 53 | until=until, 54 | **kwargs, 55 | ) 56 | 57 | if return_json: 58 | return data 59 | else: 60 | return AlbumResponse.new_from_json_dict(data) 61 | -------------------------------------------------------------------------------- /pyfacebook/api/facebook/common_edges/live_videos.py: -------------------------------------------------------------------------------- 1 | """ 2 | Live videos edge for resource 3 | """ 4 | 5 | from typing import Optional, Union 6 | 7 | import pyfacebook.utils.constant as const 8 | from pyfacebook.models.live_video import LiveVideosResponse 9 | from pyfacebook.utils.params_utils import enf_comma_separated 10 | 11 | 12 | class LiveVideosEdge: 13 | __slots__ = () 14 | 15 | def get_live_videos( 16 | self, 17 | object_id: str, 18 | fields: Optional[Union[str, list, dict]] = None, 19 | since: Optional[str] = None, 20 | until: Optional[str] = None, 21 | count: Optional[int] = 10, 22 | limit: Optional[int] = 10, 23 | return_json: bool = False, 24 | **kwargs, 25 | ) -> Union[LiveVideosResponse, dict]: 26 | """ 27 | Get lists of live videos on a facebook object. 28 | 29 | :param object_id: ID for the facebook object. 30 | :param fields: Comma-separated id string for data fields which you want. 31 | You can also pass this with an id list, tuple. 32 | :param since: A Unix timestamp or strtotime data value that points to the start of data. 33 | :param until: A Unix timestamp or strtotime data value that points to the end of data. 34 | :param count: The total count for you to get data. 35 | :param limit: Each request retrieve objects count. 36 | It should no more than 100. Default is None will use api default limit. 37 | :param return_json: Set to false will return a dataclass for LiveVideo. 38 | Or return json data. Default is false. 39 | :param kwargs: Additional parameters for different object. 40 | :return: live videos response information 41 | """ 42 | 43 | if fields is None: 44 | fields = const.LIVE_VIDEO_PUBLIC_FIELDS 45 | 46 | data = self.client.get_full_connections( 47 | object_id=object_id, 48 | connection="live_videos", 49 | count=count, 50 | limit=limit, 51 | fields=enf_comma_separated(field="fields", value=fields), 52 | since=since, 53 | until=until, 54 | **kwargs, 55 | ) 56 | if return_json: 57 | return data 58 | else: 59 | return LiveVideosResponse.new_from_json_dict(data) 60 | -------------------------------------------------------------------------------- /pyfacebook/api/facebook/common_edges/photos.py: -------------------------------------------------------------------------------- 1 | """ 2 | Photos edge for resource. 3 | """ 4 | 5 | from typing import Optional, Union 6 | 7 | import pyfacebook.utils.constant as const 8 | from pyfacebook.models.photo import PhotosResponse 9 | from pyfacebook.utils.params_utils import enf_comma_separated 10 | 11 | 12 | class PhotosEdge: 13 | __slots__ = () 14 | 15 | def get_photos( 16 | self, 17 | object_id: str, 18 | fields: Optional[Union[str, list, dict]] = None, 19 | since: Optional[str] = None, 20 | until: Optional[str] = None, 21 | count: Optional[int] = 10, 22 | limit: Optional[int] = 10, 23 | return_json: bool = False, 24 | **kwargs, 25 | ) -> Union[PhotosResponse, dict]: 26 | """ 27 | Get lists of photos on a Facebook object. 28 | 29 | :param object_id: ID for the facebook object. 30 | :param fields: Comma-separated id string for data fields which you want. 31 | You can also pass this with an id list, tuple. 32 | :param since: A Unix timestamp or strtotime data value that points to the start of data. 33 | :param until: A Unix timestamp or strtotime data value that points to the end of data. 34 | :param count: The total count for you to get data. 35 | :param limit: Each request retrieve objects count. 36 | It should no more than 100. Default is None will use api default limit. 37 | :param return_json: Set to false will return a dataclass for Photo. 38 | Or return json data. Default is false. 39 | :param kwargs: Additional parameters for different object. 40 | :return: Photos response information 41 | """ 42 | 43 | if fields is None: 44 | fields = const.PHOTO_PUBLIC_FIELDS 45 | 46 | data = self.client.get_full_connections( 47 | object_id=object_id, 48 | connection="photos", 49 | count=count, 50 | limit=limit, 51 | fields=enf_comma_separated(field="fields", value=fields), 52 | since=since, 53 | until=until, 54 | **kwargs, 55 | ) 56 | 57 | if return_json: 58 | return data 59 | else: 60 | return PhotosResponse.new_from_json_dict(data) 61 | -------------------------------------------------------------------------------- /pyfacebook/api/facebook/common_edges/videos.py: -------------------------------------------------------------------------------- 1 | """ 2 | Videos edge for resource. 3 | """ 4 | 5 | from typing import Optional, Union 6 | 7 | import pyfacebook.utils.constant as const 8 | from pyfacebook.models.video import VideosResponse 9 | from pyfacebook.utils.params_utils import enf_comma_separated 10 | 11 | 12 | class VideosEdge: 13 | __slots__ = () 14 | 15 | def get_videos( 16 | self, 17 | object_id: str, 18 | fields: Optional[Union[str, list, dict]] = None, 19 | since: Optional[str] = None, 20 | until: Optional[str] = None, 21 | count: Optional[int] = 10, 22 | limit: Optional[int] = 10, 23 | return_json: bool = False, 24 | **kwargs, 25 | ) -> Union[VideosResponse, dict]: 26 | """ 27 | Get a list of videos on a Facebook object. 28 | 29 | :param object_id: ID for object(page,user,group) 30 | :param fields: Comma-separated id string for data fields which you want. 31 | You can also pass this with an id list, tuple. 32 | :param since: A Unix timestamp or strtotime data value that points to the start of data. 33 | :param until: A Unix timestamp or strtotime data value that points to the end of data. 34 | :param count: The total count for you to get data. 35 | :param limit: Each request retrieve objects count. 36 | It should no more than 100. Default is None will use api default limit. 37 | :param return_json: Set to false will return a list dataclass for Videos. 38 | Or return json data. Default is false. 39 | :param kwargs: Additional parameters for different object. 40 | :return: Videos response information 41 | """ 42 | 43 | if fields is None: 44 | fields = const.VIDEO_PUBLIC_FIELDS 45 | 46 | data = self.client.get_full_connections( 47 | object_id=object_id, 48 | connection="videos", 49 | count=count, 50 | limit=limit, 51 | fields=enf_comma_separated(field="fields", value=fields), 52 | since=since, 53 | until=until, 54 | **kwargs, 55 | ) 56 | 57 | if return_json: 58 | return data 59 | else: 60 | return VideosResponse.new_from_json_dict(data) 61 | -------------------------------------------------------------------------------- /pyfacebook/api/facebook/resource/__init__.py: -------------------------------------------------------------------------------- 1 | """ 2 | Expose for outside 3 | """ 4 | 5 | from pyfacebook.api.facebook.resource.application import FacebookApplication 6 | from pyfacebook.api.facebook.resource.business import FacebookBusiness 7 | from pyfacebook.api.facebook.resource.user import FacebookUser 8 | from pyfacebook.api.facebook.resource.page import FacebookPage 9 | from pyfacebook.api.facebook.resource.group import FacebookGroup 10 | from pyfacebook.api.facebook.resource.event import FacebookEvent 11 | from pyfacebook.api.facebook.resource.post import FacebookPost 12 | from pyfacebook.api.facebook.resource.photo import FacebookPhoto 13 | from pyfacebook.api.facebook.resource.album import FacebookAlbum 14 | from pyfacebook.api.facebook.resource.video import FacebookVideo 15 | from pyfacebook.api.facebook.resource.live_video import FacebookLiveVideo 16 | from pyfacebook.api.facebook.resource.comment import FacebookComment 17 | from pyfacebook.api.facebook.resource.conversation import FacebookConversation 18 | from pyfacebook.api.facebook.resource.message import FacebookMessage 19 | -------------------------------------------------------------------------------- /pyfacebook/api/instagram_basic/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sns-sdks/python-facebook/f51a56229c2a767a64b8295160bb2f49da8a39c7/pyfacebook/api/instagram_basic/__init__.py -------------------------------------------------------------------------------- /pyfacebook/api/instagram_basic/client.py: -------------------------------------------------------------------------------- 1 | """ 2 | Client for Instagram Basic Display API. 3 | """ 4 | 5 | from pyfacebook.api.base_client import BaseBasicDisplayApi 6 | from pyfacebook.api.instagram_basic import resource as rs 7 | 8 | 9 | class IGBasicDisplayApi(BaseBasicDisplayApi): 10 | """ 11 | Api class for Instagram basic display api 12 | """ 13 | 14 | user = rs.IGBasicUser() 15 | media = rs.IGBasicMedia() 16 | -------------------------------------------------------------------------------- /pyfacebook/api/instagram_basic/resource/__init__.py: -------------------------------------------------------------------------------- 1 | from pyfacebook.api.instagram_basic.resource.user import IGBasicUser 2 | from pyfacebook.api.instagram_basic.resource.media import IGBasicMedia 3 | -------------------------------------------------------------------------------- /pyfacebook/api/instagram_business/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sns-sdks/python-facebook/f51a56229c2a767a64b8295160bb2f49da8a39c7/pyfacebook/api/instagram_business/__init__.py -------------------------------------------------------------------------------- /pyfacebook/api/instagram_business/client.py: -------------------------------------------------------------------------------- 1 | """ 2 | Client for Instagram Graph API. 3 | """ 4 | 5 | from pyfacebook.api.base_client import BaseApi 6 | from pyfacebook.api.instagram_business import resource as rs 7 | 8 | 9 | class IGBusinessApi(BaseApi): 10 | """ 11 | Api class for Instagram Business 12 | """ 13 | 14 | user = rs.IGBusinessUser() 15 | media = rs.IGBusinessMedia() 16 | comment = rs.IGBusinessComment() 17 | reply = rs.IGBusinessReply() 18 | hashtag = rs.IGBusinessHashtag() 19 | container = rs.IGBusinessContainer() 20 | -------------------------------------------------------------------------------- /pyfacebook/api/instagram_business/resource/__init__.py: -------------------------------------------------------------------------------- 1 | from pyfacebook.api.instagram_business.resource.user import IGBusinessUser 2 | from pyfacebook.api.instagram_business.resource.media import IGBusinessMedia 3 | from pyfacebook.api.instagram_business.resource.comment import ( 4 | IGBusinessComment, 5 | IGBusinessReply, 6 | ) 7 | from pyfacebook.api.instagram_business.resource.hashtag import IGBusinessHashtag 8 | from pyfacebook.api.instagram_business.resource.container import IGBusinessContainer 9 | -------------------------------------------------------------------------------- /pyfacebook/exceptions.py: -------------------------------------------------------------------------------- 1 | """ 2 | Exceptions for library 3 | """ 4 | 5 | 6 | class PyFacebookException(Exception): 7 | """Base class for exceptions in this module.""" 8 | 9 | pass 10 | 11 | 12 | class LibraryError(PyFacebookException): 13 | """ 14 | A class for library error template. 15 | """ 16 | 17 | def __init__(self, kwargs: dict): 18 | self.code = -1 # error code in library inside 19 | self.message = "exception in library" 20 | for key, value in kwargs.items(): 21 | setattr(self, key, value) 22 | 23 | def __repr__(self): 24 | msg = ",".join( 25 | [f"{k}={v}" for k, v in self.__dict__.items() if not k.startswith("_")] 26 | ) 27 | return f"{self.__class__.__name__}({msg})" 28 | 29 | def __str__(self): 30 | return self.__repr__() 31 | 32 | 33 | class FacebookError(LibraryError): 34 | """ 35 | A class representing facebook error response 36 | Refer: https://developers.facebook.com/docs/graph-api/using-graph-api/error-handling 37 | 38 | Common fields are: message,code,error_subcode,error_user_msg,error_user_title,fbtrace_id 39 | """ 40 | 41 | def __init__(self, kwargs: dict): 42 | self._data = kwargs 43 | error = kwargs["error"] 44 | super().__init__(kwargs=error) 45 | 46 | 47 | class PyFacebookDeprecationWaring(DeprecationWarning): 48 | pass 49 | -------------------------------------------------------------------------------- /pyfacebook/models/__init__.py: -------------------------------------------------------------------------------- 1 | from .base import BaseModel 2 | from .business import Business 3 | from .user import User, UserExperience, UserAgeRange 4 | from .page import Page, PagesResponse, SearchPage, SearchPagesResponse 5 | from .post import Post, FeedResponse 6 | from .group import Group 7 | from .event import Event 8 | from .photo import Photo, PhotosResponse 9 | from .album import Album, AlbumResponse 10 | from .video import Video, VideosResponse 11 | from .live_video import LiveVideo, LiveVideosResponse 12 | from .comment import Comment, CommentsResponse 13 | from .conversation import Conversation 14 | from .message import Message 15 | from .ig_business_models import ( 16 | IgBusUser, 17 | IgBusMedia, 18 | IgBusMediaResponse, 19 | IgBusMediaChildren, 20 | IgBusReply, 21 | IgBusComment, 22 | IgBusHashtag, 23 | IgBusContainer, 24 | IgBusPublishLimit, 25 | IgBusPublishLimitResponse, 26 | IgBusInsight, 27 | IgBusInsightsResponse, 28 | IgBusDiscoveryUserResponse, 29 | IgBusDiscoveryUserMediaResponse, 30 | IgBusMentionedCommentResponse, 31 | IgBusMentionedMediaResponse, 32 | IgBusHashtagsResponse, 33 | IgBusCommentResponse, 34 | ) 35 | from .ig_basic_models import ( 36 | IgBasicUser, 37 | IgBasicMediaChildren, 38 | IgBasicMedia, 39 | IgBasicMediaResponse, 40 | ) 41 | -------------------------------------------------------------------------------- /pyfacebook/models/album.py: -------------------------------------------------------------------------------- 1 | """ 2 | Model class for album. 3 | 4 | Refer: https://developers.facebook.com/docs/graph-api/reference/album/ 5 | """ 6 | 7 | from dataclasses import dataclass 8 | from typing import List, Optional 9 | 10 | from dataclasses_json import config 11 | 12 | from pyfacebook.models.base import BaseModel, field 13 | from pyfacebook.models.extensions import Paging 14 | 15 | 16 | @dataclass 17 | class Album(BaseModel): 18 | """ 19 | A class representing the Album. 20 | """ 21 | 22 | id: Optional[str] = field(repr=True, compare=True) 23 | backdated_time: Optional[str] = field() 24 | backdated_time_granularity: Optional[str] = field() 25 | can_upload: Optional[bool] = field() 26 | count: Optional[int] = field() 27 | cover_photo: Optional[dict] = ( 28 | field() 29 | ) # TODO Refer: https://developers.facebook.com/docs/graph-api/reference/photo/ 30 | created_time: Optional[str] = field() 31 | description: Optional[str] = field() 32 | event: Optional[dict] = ( 33 | field() 34 | ) # TODO Refer: https://developers.facebook.com/docs/graph-api/reference/event/ 35 | _from: Optional[dict] = field(metadata=config(field_name="from")) 36 | link: Optional[str] = field() 37 | location: Optional[str] = field() 38 | name: Optional[str] = field(repr=True) 39 | place: Optional[dict] = ( 40 | field() 41 | ) # TODO Refer: https://developers.facebook.com/docs/graph-api/reference/place/ 42 | privacy: Optional[str] = field() 43 | type: Optional[str] = field() 44 | updated_time: Optional[str] = field() 45 | 46 | 47 | @dataclass 48 | class AlbumResponse(BaseModel): 49 | """ 50 | A class representing the result for albums edge. 51 | 52 | Refer: https://developers.facebook.com/docs/graph-api/reference/page/albums 53 | """ 54 | 55 | data: List[Album] = field(repr=True, compare=True) 56 | paging: Optional[Paging] = field() 57 | -------------------------------------------------------------------------------- /pyfacebook/models/base.py: -------------------------------------------------------------------------------- 1 | """ 2 | Base model 3 | """ 4 | 5 | from copy import deepcopy 6 | from dataclasses import dataclass, field as base_field 7 | from typing import ( 8 | Dict, 9 | Type, 10 | TypeVar, 11 | Optional, 12 | ) 13 | 14 | from dataclasses_json import ( 15 | DataClassJsonMixin, 16 | ) 17 | from dataclasses_json.core import Json 18 | 19 | A = TypeVar("A", bound=DataClassJsonMixin) 20 | 21 | 22 | @dataclass 23 | class BaseModel(DataClassJsonMixin): 24 | @classmethod 25 | def new_from_json_dict( 26 | cls: Type[A], data: Optional[Dict], *, infer_missing=False 27 | ) -> Optional[A]: 28 | """ 29 | Convert json dict to dataclass 30 | :param data: A json dict which will convert model class. 31 | :param infer_missing: if set True, will let missing field (not have default vale) to None 32 | :return: The data class 33 | """ 34 | if not data: 35 | return None 36 | c = cls.from_dict(data, infer_missing=infer_missing) 37 | # save origin data 38 | cls._json = data 39 | return c 40 | 41 | def to_dict(self, encode_json=False, ignore_nan=True) -> Dict[str, Json]: 42 | """ 43 | Convert dataclass to dict 44 | :param encode_json: 45 | :param ignore_nan: Is the result include None data. 46 | :return: dict 47 | """ 48 | data = super().to_dict(encode_json=encode_json) 49 | if ignore_nan: 50 | data = dict_minus_none_values(data) 51 | return data 52 | 53 | 54 | def dict_minus_none_values(obj: Optional[dict]): 55 | """ 56 | Remove data dict where value is None 57 | :param obj: dict object 58 | :return: obj 59 | """ 60 | if obj is None: 61 | return None 62 | 63 | keys = list(obj.keys()) 64 | for key in keys: 65 | value = obj[key] 66 | if value is None: 67 | obj.pop(key) 68 | if isinstance(value, (list, tuple)): 69 | obj[key] = type(value)([dict_minus_none_values(v) for v in value]) 70 | if isinstance(value, dict): 71 | obj[key] = dict_minus_none_values(value) 72 | return deepcopy(obj) 73 | 74 | 75 | def field(default=None, repr=False, compare=False, **kwargs): 76 | kwargs.update( 77 | { 78 | "default": default, 79 | "repr": repr, 80 | "compare": compare, 81 | } 82 | ) 83 | return base_field(**kwargs) 84 | -------------------------------------------------------------------------------- /pyfacebook/models/business.py: -------------------------------------------------------------------------------- 1 | """ 2 | Models for business. 3 | 4 | Refer: https://developers.facebook.com/docs/marketing-api/reference/business/ 5 | """ 6 | 7 | from dataclasses import dataclass 8 | from typing import List, Optional 9 | 10 | from pyfacebook.models.base import BaseModel, field 11 | from pyfacebook.models.extensions import Paging 12 | 13 | 14 | @dataclass 15 | class Business(BaseModel): 16 | """ 17 | A class representing the Business. 18 | """ 19 | 20 | id: Optional[str] = field(repr=True, compare=True) 21 | block_offline_analytics: Optional[bool] = field() 22 | collaborative_ads_managed_partner_business_info: Optional[dict] = field() 23 | collaborative_ads_managed_partner_eligibility: Optional[dict] = field() 24 | created_by: Optional[dict] = field() 25 | created_time: Optional[str] = field() 26 | extended_updated_time: Optional[str] = field() 27 | is_hidden: Optional[bool] = field() 28 | link: Optional[str] = field() 29 | name: Optional[str] = field(repr=True) 30 | payment_account_id: Optional[str] = field() 31 | primary_page: Optional[dict] = field() 32 | profile_picture_uri: Optional[str] = field() 33 | timezone_id: Optional[int] = field() 34 | two_factor_type: Optional[str] = field() 35 | updated_by: Optional[dict] = field() 36 | updated_time: Optional[str] = field() 37 | verification_status: Optional[str] = field() 38 | vertical: Optional[str] = field() 39 | vertical_id: Optional[int] = field() 40 | permitted_roles: Optional[List[str]] = field() 41 | 42 | 43 | @dataclass 44 | class BusinessResponse(BaseModel): 45 | """ 46 | A class representing the result for businesses edge. 47 | 48 | Refer: https://developers.facebook.com/docs/graph-api/reference/user/businesses/ 49 | """ 50 | 51 | data: List[Business] = field(repr=True, compare=True) 52 | paging: Optional[Paging] = field() 53 | -------------------------------------------------------------------------------- /pyfacebook/models/conversation.py: -------------------------------------------------------------------------------- 1 | """ 2 | Model class for Conversation. 3 | 4 | Refer: https://developers.facebook.com/docs/graph-api/reference/conversation 5 | """ 6 | 7 | from dataclasses import dataclass 8 | from typing import List, Optional 9 | 10 | from pyfacebook.models.base import BaseModel, field 11 | 12 | 13 | @dataclass 14 | class CvUser(BaseModel): 15 | """ 16 | A class representing the User in conversation. 17 | """ 18 | 19 | id: Optional[str] = field(repr=True, compare=True) 20 | name: Optional[str] = field(repr=True) 21 | email: Optional[str] = field() 22 | 23 | 24 | @dataclass 25 | class Participants(BaseModel): 26 | """ 27 | A class representing the Participant. 28 | """ 29 | 30 | data: Optional[List[CvUser]] = field(repr=True) 31 | 32 | 33 | @dataclass 34 | class Senders(BaseModel): 35 | """ 36 | A class representing the Sender. 37 | """ 38 | 39 | data: Optional[List[CvUser]] = field(repr=True) 40 | 41 | 42 | @dataclass 43 | class Conversation(BaseModel): 44 | """ 45 | A class representing the Conversation. 46 | """ 47 | 48 | id: Optional[str] = field(repr=True, compare=True) 49 | link: Optional[str] = field() 50 | snippet: Optional[str] = field() 51 | scoped_thread_key: Optional[str] = field() 52 | updated_time: Optional[str] = field(repr=True) 53 | message_count: Optional[int] = field() 54 | unread_count: Optional[int] = field() 55 | participants: Optional[Participants] = field() 56 | senders: Optional[Senders] = field() 57 | can_reply: Optional[bool] = field() 58 | is_subscribed: Optional[bool] = field() 59 | -------------------------------------------------------------------------------- /pyfacebook/models/group.py: -------------------------------------------------------------------------------- 1 | """ 2 | Models for group. 3 | 4 | Refer: https://developers.facebook.com/docs/graph-api/reference/group 5 | """ 6 | 7 | from dataclasses import dataclass 8 | from typing import List, Optional 9 | 10 | from pyfacebook.models.base import BaseModel, field 11 | from pyfacebook.models.image import CoverPhoto, Picture 12 | 13 | 14 | @dataclass 15 | class Group(BaseModel): 16 | """ 17 | A class representing the group. 18 | 19 | Refer: https://developers.facebook.com/docs/graph-api/reference/group 20 | """ 21 | 22 | id: Optional[str] = field(repr=True, compare=True) 23 | cover: Optional[CoverPhoto] = field() 24 | created_time: Optional[str] = field() 25 | description: Optional[str] = field() 26 | email: Optional[str] = field() 27 | icon: Optional[str] = field() 28 | member_count: Optional[int] = field() 29 | member_request_count: Optional[int] = field() 30 | membership_state: Optional[str] = field() 31 | name: Optional[str] = field() 32 | parent: Optional[dict] = field() # TODO 33 | permissions: Optional[List[str]] = field() 34 | privacy: Optional[str] = field() 35 | updated_time: Optional[str] = field() 36 | 37 | # common connection 38 | picture: Optional[Picture] = field() 39 | -------------------------------------------------------------------------------- /pyfacebook/models/ig_basic_models.py: -------------------------------------------------------------------------------- 1 | """ 2 | Model classes for instagram basic display. 3 | """ 4 | 5 | from dataclasses import dataclass 6 | from typing import List, Optional 7 | 8 | from pyfacebook.models.base import BaseModel, field 9 | from pyfacebook.models.extensions import Paging 10 | 11 | 12 | @dataclass 13 | class IgBasicUser(BaseModel): 14 | """ 15 | A class representing the Basic display user. 16 | 17 | Refer: https://developers.facebook.com/docs/instagram-basic-display-api/reference/user#fields 18 | """ 19 | 20 | id: Optional[str] = field(repr=True, compare=True) 21 | account_type: Optional[str] = field(repr=True) 22 | media_count: Optional[int] = field() 23 | username: Optional[str] = field(repr=True) 24 | 25 | 26 | @dataclass 27 | class IgBasicMediaChild(BaseModel): 28 | """ 29 | A class representing the Basic display media child. 30 | 31 | Refer: https://developers.facebook.com/docs/instagram-basic-display-api/reference/media#fields 32 | """ 33 | 34 | id: Optional[str] = field(repr=True, compare=True) 35 | caption: Optional[str] = field() 36 | media_type: Optional[str] = field() 37 | media_url: Optional[str] = field(repr=True) 38 | permalink: Optional[str] = field() 39 | thumbnail_url: Optional[str] = field() 40 | timestamp: Optional[str] = field() 41 | 42 | 43 | @dataclass 44 | class IgBasicMediaChildren(BaseModel): 45 | """ 46 | A class representing the Basic display media children data. 47 | 48 | Refer: https://developers.facebook.com/docs/instagram-basic-display-api/reference/media/children 49 | """ 50 | 51 | data: Optional[List[IgBasicMediaChild]] = field(repr=True) 52 | paging: Optional[Paging] = field() 53 | 54 | 55 | @dataclass 56 | class IgBasicMedia(IgBasicMediaChild): 57 | """ 58 | A class representing the Basic display media. 59 | 60 | Refer: https://developers.facebook.com/docs/instagram-basic-display-api/reference/media#fields 61 | """ 62 | 63 | username: Optional[str] = field() 64 | 65 | 66 | @dataclass 67 | class IgBasicMediaResponse(IgBasicMediaChild): 68 | """ 69 | A class representing the Basic display medias response. 70 | 71 | Refer: https://developers.facebook.com/docs/instagram-basic-display-api/reference/user/media 72 | """ 73 | 74 | data: Optional[List[IgBasicMedia]] = field(repr=True, compare=True) 75 | paging: Optional[Paging] = field(repr=True) 76 | -------------------------------------------------------------------------------- /pyfacebook/models/image.py: -------------------------------------------------------------------------------- 1 | """ 2 | Extension models for graph api 3 | """ 4 | 5 | from dataclasses import dataclass 6 | from typing import List, Optional 7 | 8 | from pyfacebook.models.base import BaseModel, field 9 | from pyfacebook.models.extensions import Paging 10 | 11 | 12 | @dataclass 13 | class ProfilePictureSource(BaseModel): 14 | """ 15 | A class representing Profile Picture Source 16 | 17 | Refer: https://developers.facebook.com/docs/graph-api/reference/profile-picture-source/ 18 | """ 19 | 20 | cache_key: Optional[str] = field() 21 | height: Optional[int] = field() 22 | is_silhouette: Optional[bool] = field() 23 | url: Optional[str] = field(repr=True) 24 | width: Optional[int] = field() 25 | 26 | 27 | @dataclass 28 | class Picture(BaseModel): 29 | """ 30 | A class representing the Picture connection. 31 | 32 | Refer: https://developers.facebook.com/docs/graph-api/reference/page/picture 33 | """ 34 | 35 | data: Optional[ProfilePictureSource] = field(repr=True) 36 | paging: Optional[Paging] = field() 37 | 38 | 39 | @dataclass 40 | class CoverPhoto(BaseModel): 41 | """ 42 | A class representing Cover Photo 43 | 44 | Refer: https://developers.facebook.com/docs/graph-api/reference/cover-photo/ 45 | """ 46 | 47 | id: Optional[str] = field(repr=True, compare=True) 48 | offset_x: Optional[float] = field() 49 | offset_y: Optional[float] = field() 50 | source: Optional[str] = field(repr=True) 51 | 52 | 53 | @dataclass 54 | class ImageSource(BaseModel): 55 | """ 56 | A class representing the Image Source. 57 | """ 58 | 59 | height: Optional[int] = field() 60 | width: Optional[int] = field() 61 | src: Optional[str] = field(repr=True) 62 | 63 | 64 | @dataclass 65 | class PicCrop(BaseModel): 66 | """ 67 | A class representing the pic crop. 68 | """ 69 | 70 | height: Optional[int] = field() 71 | width: Optional[int] = field() 72 | left: Optional[int] = field() 73 | top: Optional[int] = field() 74 | right: Optional[int] = field() 75 | bottom: Optional[int] = field() 76 | url: Optional[str] = field(repr=True) 77 | -------------------------------------------------------------------------------- /pyfacebook/models/place.py: -------------------------------------------------------------------------------- 1 | """ 2 | Models for place relative. 3 | 4 | Refer: https://developers.facebook.com/docs/graph-api/reference/place/ 5 | """ 6 | 7 | from dataclasses import dataclass 8 | from typing import Optional 9 | 10 | from pyfacebook.models.base import BaseModel, field 11 | 12 | 13 | @dataclass 14 | class Location(BaseModel): 15 | city: Optional[str] = field() 16 | city_id: Optional[str] = field() 17 | country: Optional[str] = field(repr=True) 18 | country_code: Optional[str] = field() 19 | latitude: Optional[int] = field() 20 | located_in: Optional[str] = field() 21 | longitude: Optional[float] = field() 22 | name: Optional[str] = field() 23 | region: Optional[str] = field() 24 | region_id: Optional[int] = field() 25 | state: Optional[str] = field() 26 | street: Optional[str] = field() 27 | zip: Optional[str] = field() 28 | 29 | 30 | @dataclass 31 | class Place(BaseModel): 32 | """ 33 | A class representing the Place. 34 | """ 35 | 36 | id: Optional[str] = field(repr=True, compare=True) 37 | location: Optional[Location] = field() 38 | name: Optional[str] = field(repr=True) 39 | overall_rating: Optional[float] = field() 40 | -------------------------------------------------------------------------------- /pyfacebook/utils/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sns-sdks/python-facebook/f51a56229c2a767a64b8295160bb2f49da8a39c7/pyfacebook/utils/__init__.py -------------------------------------------------------------------------------- /pyfacebook/utils/params_utils.py: -------------------------------------------------------------------------------- 1 | """ 2 | function's to validate parameters. 3 | """ 4 | 5 | from typing import Optional, Union 6 | 7 | from pyfacebook.exceptions import LibraryError 8 | 9 | 10 | def enf_comma_separated(field: str, value: Optional[Union[str, list, tuple]]): 11 | """ 12 | Check to see if field's value type belong to correct type. 13 | If it is, return api need value, otherwise, raise a LibraryError. 14 | :param field: Name of the field you want to do check. 15 | :param value: Values for the field. 16 | :return: Api needed string 17 | """ 18 | try: 19 | # if value point with string, not check. 20 | if isinstance(value, str): 21 | value = [value] 22 | elif isinstance(value, (list, tuple)): 23 | pass 24 | else: 25 | raise LibraryError( 26 | { 27 | "message": f"Parameter ({field}) must be single str,comma-separated str,list or tuple", 28 | } 29 | ) 30 | 31 | # loop value list and remove repeat item 32 | seen = {} 33 | res = [] 34 | for item in value: 35 | if item in seen: 36 | continue 37 | seen[item] = 1 38 | res.append(item) 39 | return ",".join(res) 40 | except (TypeError, ValueError): 41 | raise LibraryError( 42 | { 43 | "message": f"Parameter ({field}) must be single str,comma-separated str,list or tuple", 44 | } 45 | ) 46 | -------------------------------------------------------------------------------- /pyproject.toml: -------------------------------------------------------------------------------- 1 | [tool.poetry] 2 | name = "python-facebook-api" 3 | version = "0.20.1" 4 | description = "A simple Python wrapper around the Facebook Graph API" 5 | authors = ["Ikaros kun "] 6 | readme = "README.rst" 7 | license = "Apache-2.0" 8 | repository = 'https://github.com/sns-sdks/python-facebook' 9 | homepage = "https://github.com/sns-sdks/python-facebook" 10 | keywords = ["facebook-graph-api", "facebook-sdk", "instagram-api", "instagram-sdk", "facebook-api"] 11 | classifiers = [ 12 | # see https://pypi.org/pypi?%3Aaction=list_classifiers 13 | "Topic :: Software Development :: Libraries", 14 | "License :: OSI Approved :: Apache Software License", 15 | "Operating System :: OS Independent", 16 | "Programming Language :: Python", 17 | "Programming Language :: Python :: 3", 18 | "Programming Language :: Python :: 3.7", 19 | "Programming Language :: Python :: 3.8", 20 | "Programming Language :: Python :: 3.9", 21 | "Programming Language :: Python :: 3.10", 22 | "Programming Language :: Python :: 3.11", 23 | "Programming Language :: Python :: 3.12", 24 | "Programming Language :: Python :: 3 :: Only", 25 | ] 26 | 27 | packages = [ 28 | { include = "pyfacebook" }, 29 | { include = "tests", format = "sdist" }, 30 | ] 31 | 32 | 33 | [tool.poetry.dependencies] 34 | python = "^3.7" 35 | requests = "^2.27" 36 | requests-oauthlib = "^1.2.0" 37 | dataclasses-json = ">=0.5.7" 38 | 39 | [tool.poetry.group.dev.dependencies] 40 | pytest = "^7.1" 41 | pytest-cov = "^3.0.0" 42 | responses = ">=0.23.1" 43 | tox = "^4.0.0" 44 | black = "^23.3.0" 45 | 46 | [build-system] 47 | requires = ["poetry-core"] 48 | build-backend = "poetry.core.masonry.api" 49 | -------------------------------------------------------------------------------- /pytest.ini: -------------------------------------------------------------------------------- 1 | [pytest] 2 | filterwarnings = 3 | ignore::DeprecationWarning 4 | addopts = --cov=pyfacebook --cov-report xml -------------------------------------------------------------------------------- /testdata/base/19292868552-picture.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sns-sdks/python-facebook/f51a56229c2a767a64b8295160bb2f49da8a39c7/testdata/base/19292868552-picture.png -------------------------------------------------------------------------------- /testdata/base/basic_display_api_user_token.json: -------------------------------------------------------------------------------- 1 | {"access_token":"token","user_id":"user_id"} -------------------------------------------------------------------------------- /testdata/base/connecion_data.json: -------------------------------------------------------------------------------- 1 | {"data":{"height":50,"is_silhouette":false,"url":"https://scontent-ssn1-1.xx.fbcdn.net/v/t1.6435-1/cp0/p50x50/187984349_10158249017483553_8290061300911698330_n.png?_nc_cat=111&ccb=1-3&_nc_sid=dbb9e7&_nc_ohc=GTK6Y4l1BpcAX9mdBrU&_nc_ht=scontent-ssn1-1.xx&tp=30&oh=3eb256e72ef610dde00fbd4351f951fa&oe=60E6B30A","width":50}} -------------------------------------------------------------------------------- /testdata/base/error_data.json: -------------------------------------------------------------------------------- 1 | {"error":{"message":"(#100) Object does not exist, cannot be loaded due to missing permission or reviewable feature, or does not support this operation. This endpoint requires the 'pages_read_engagement' permission or the 'Page Public Content Access' feature or the 'Page Public Metadata Access' feature. Refer to https://developers.facebook.com/docs/apps/review/login-permissions#manage-pages, https://developers.facebook.com/docs/apps/review/feature#reference-PAGES_ACCESS and https://developers.facebook.com/docs/apps/review/feature#page-public-metadata-access for details.","type":"OAuthException","code":100,"fbtrace_id":"AQt_hJ68vFybS4TnupatNtX"}} -------------------------------------------------------------------------------- /testdata/base/full_connecions_p1.json: -------------------------------------------------------------------------------- 1 | {"data":[{"created_time":"2021-06-30T21:21:18+0000","message":"After giving users the ability to quickly and easily share recipes and food-related content to Instagram Stories, recipe and lifestyle site iCook 愛料理 boosted its user retention by 30%. See how iCook reached a broader audience by building a new, intuitive user interface flow and integrating Sharing to Stories: https://fb.me/iCook-Success-Story","id":"19292868552_10158333323653553"},{"created_time":"2021-06-29T15:47:56+0000","message":"We’ve seen computers master chess, go, and even Starcraft II, but NetHack — a “dungeon-crawling” game first released in 1987 — might present the hardest challenge to AI yet. The game’s procedurally generated levels and “permadeath” will push researchers to create new and more powerful methods of reinforcement learning. Think you’ve got this game beat? Learn more about Facebook AI’s NetHack Challenge: https://fb.me/NetHack-Challenge-NeurIPS","id":"19292868552_10158331020098553"},{"created_time":"2021-06-28T15:17:28+0000","message":"Ent is an open-source entity framework that developers at Facebook Open Source built for Go to provide developers with Graph-based Object Relational Mapping. This enables developers to benefit from the increased security and reduced repetition of ORM while avoiding context switching in Go. Learn about how we use it at Facebook, and how you can start using it yourself: https://fb.me/ELI5-Open-Source-Ent","id":"19292868552_10158329301388553"},{"created_time":"2021-06-23T15:45:41+0000","message":"Chris Konstad is a Production Engineer on the Video Infrastructure team at Facebook, and, like many of our engineers who contribute to Facebook Open Source, he’s working on more projects using Rust. Learn about the tools he’s already built with Rust, why he advocates for increasing its use, and how you can get started learning how to code in it: https://fb.me/Meet-the-Rustaceans","id":"19292868552_10158319774218553"},{"created_time":"2021-06-22T17:10:48+0000","message":"Border Gateway Protocol (BGP) was originally designed to interconnect autonomous internet service providers (ISPs) on the global internet, and engineers at Facebook have recently tried implementing it into our data centers. Learn how Facebook Engineering devised a routing design to build our network quickly and provide high availability for our services while keeping itself scalable: https://fb.me/Running-Border-Gateway-Protocol","id":"19292868552_10158317908683553"}],"paging":{"cursors":{"before":"before","after":"after"},"next":"https://graph.facebook.com/v11.0/19292868552/feed?access_token=access_token&pretty=0&limit=5&after=after"}} -------------------------------------------------------------------------------- /testdata/base/full_connecions_p2.json: -------------------------------------------------------------------------------- 1 | {"data":[{"created_time":"2021-06-21T20:57:12+0000","message":"When the German non-profit Save the Children Deutschland wanted to boost their brand awareness, gain trust, and raise donations, the organization partnered with conversational marketing expert Spectrm and Facebook Creative Shop to build an innovative, automated Messenger experience. After promoting its brand awareness campaign for one month, Save the Children Germany saw a 29% lift in donations and reached over 1.6M people. Learn more: https://fb.me/Save-the-Children-Germany","id":"19292868552_10158316421783553"},{"created_time":"2021-06-18T15:22:18+0000","message":"Developing an app or website for a political campaign, candidate, or party? If you’re thinking about using any of our Developer Products, like Facebook Login, remember to visit our Developer site. This sets out the Developer Policies and Platform Terms that apply to the use of Developer Products, as well as helpful guides and best practices, both linked below: Developer Policies: https://fb.me/Developer-Policies Platform Terms: https://fb.me/Developer-Terms","id":"19292868552_10158308992823553"},{"created_time":"2021-06-16T18:52:23+0000","message":"Here’s a quick overview of the main takeaways of our recently released Facebook SDK v11.0: - Graph API v11.0 Support and new SDK features. - Upcoming requirement to embed Client Token in SDK. - Deprecation announcements: Beginning today, developers will need to begin migrating to v11.0 to avoid using deprecated SDKs for their applications. Click to find out more about steps you may need to take to prevent disruption: https://fb.me/Platform-SDK-v11","id":"19292868552_10158305374158553"}],"paging":{"cursors":{"before":"before","after":"after"},"previous":"https://graph.facebook.com/v11.0/19292868552/feed?access_token=access_token&pretty=0&limit=5&before=before"}} -------------------------------------------------------------------------------- /testdata/base/long_term_token.json: -------------------------------------------------------------------------------- 1 | {"access_token":"token","token_type":"bearer","expires_in":5184000} -------------------------------------------------------------------------------- /testdata/base/object_default.json: -------------------------------------------------------------------------------- 1 | {"name":"Facebook App","id":"20531316728"} -------------------------------------------------------------------------------- /testdata/base/objects_default.json: -------------------------------------------------------------------------------- 1 | {"20531316728":{"id":"20531316728","name":"Facebook App"},"19292868552":{"id":"19292868552","name":"Facebook for Developers"}} -------------------------------------------------------------------------------- /testdata/base/threads_user_long_lived_token.json: -------------------------------------------------------------------------------- 1 | {"access_token": "THQVJ...","token_type": "bearer", "expires_in": 5183944} -------------------------------------------------------------------------------- /testdata/base/threads_user_token.json: -------------------------------------------------------------------------------- 1 | {"access_token": "THQVJ...","user_id": 12345678} -------------------------------------------------------------------------------- /testdata/base/token_info.json: -------------------------------------------------------------------------------- 1 | { 2 | "data": { 3 | "app_id": "appId", 4 | "type": "USER", 5 | "application": "appName", 6 | "data_access_expires_at": 1585040349, 7 | "expires_at": 1577347200, 8 | "is_valid": true, 9 | "scopes": [ 10 | "email", 11 | "read_insights", 12 | "manage_pages", 13 | "pages_show_list", 14 | "public_profile" 15 | ], 16 | "granular_scopes": [ 17 | { 18 | "scope": "manage_pages" 19 | }, 20 | { 21 | "scope": "pages_show_list" 22 | } 23 | ], 24 | "user_id": "userId" 25 | } 26 | } -------------------------------------------------------------------------------- /testdata/base/user_accounts_token.json: -------------------------------------------------------------------------------- 1 | {"data":[{"access_token":"access_token","category":"相机/照片","category_list":[{"id":"2208","name":"相机/照片"},{"id":"2202","name":"网站"}],"name":"MyLife","id":"2121008874780932","tasks":["ANALYZE","ADVERTISE","MESSAGING","MODERATE","CREATE_CONTENT","MANAGE"]}],"paging":{"cursors":{"before":"before","after":"after"}}} -------------------------------------------------------------------------------- /testdata/error.json: -------------------------------------------------------------------------------- 1 | { 2 | "error": { 3 | "message": "(#100) Pages Public Content Access requires either app secret proof or an app token", 4 | "type": "OAuthException", 5 | "code": 100, 6 | "fbtrace_id": "A1m6KK6iBqvjzPeQd4DYbKM" 7 | } 8 | } -------------------------------------------------------------------------------- /testdata/facebook/apidata/albums/album_info_default.json: -------------------------------------------------------------------------------- 1 | {"created_time":"2016-08-02T00:39:35+0000","name":"FbStart 2016 World Tour","id":"10153867132423553"} -------------------------------------------------------------------------------- /testdata/facebook/apidata/albums/album_info_fields.json: -------------------------------------------------------------------------------- 1 | {"id":"10153867132423553","created_time":"2016-08-02T00:39:35+0000","count":36,"name":"FbStart 2016 World Tour","updated_time":"2016-08-17T22:25:25+0000","link":"https://www.facebook.com/album.php?fbid=10153867132423553&id=19292868552&aid=1073741828"} -------------------------------------------------------------------------------- /testdata/facebook/apidata/albums/albums_info_default.json: -------------------------------------------------------------------------------- 1 | {"10153867132423553":{"created_time":"2016-08-02T00:39:35+0000","name":"FbStart 2016 World Tour","id":"10153867132423553"},"10151067477123553":{"created_time":"2012-09-11T10:09:20+0000","name":"World Hack Berlin","id":"10151067477123553"}} -------------------------------------------------------------------------------- /testdata/facebook/apidata/albums/albums_info_fields.json: -------------------------------------------------------------------------------- 1 | {"10153867132423553":{"id":"10153867132423553","created_time":"2016-08-02T00:39:35+0000","count":36,"name":"FbStart 2016 World Tour","updated_time":"2016-08-17T22:25:25+0000","link":"https://www.facebook.com/album.php?fbid=10153867132423553&id=19292868552&aid=1073741828"},"10151067477123553":{"id":"10151067477123553","created_time":"2012-09-11T10:09:20+0000","count":15,"name":"World Hack Berlin","updated_time":"2012-09-11T11:03:32+0000","link":"https://www.facebook.com/album.php?fbid=10151067477123553&id=19292868552&aid=434106"}} -------------------------------------------------------------------------------- /testdata/facebook/apidata/albums/albums_list_p1.json: -------------------------------------------------------------------------------- 1 | {"data":[{"created_time":"2019-04-17T03:18:30+0000","name":"Timeline Photos","id":"2312974342251050"},{"created_time":"2018-07-05T10:12:07+0000","name":"Cover Photos","id":"2121009424780877"},{"created_time":"2018-07-05T10:11:22+0000","name":"Profile Pictures","id":"2121008931447593"}],"paging":{"cursors":{"before":"MjMxMjk3NDM0MjI1MTA1MAZDZD","after":"MjEyMTAwODkzMTQ0NzU5MwZDZD"},"next":"https://graph.facebook.com/v4.0/2121008874780932/albums?access_token=access_token&pretty=0&limit=3&after=MjEyMTAwODkzMTQ0NzU5MwZDZD"}} -------------------------------------------------------------------------------- /testdata/facebook/apidata/albums/albums_list_p2.json: -------------------------------------------------------------------------------- 1 | {"data":[{"created_time":"2020-09-13T06:32:08+0000","name":"Album-ik","id":"2729185913963222"},{"created_time":"2019-10-23T02:05:22+0000","name":"Instagram Photos","id":"2447886498759833"},{"created_time":"2018-10-09T02:49:59+0000","name":"Mobile Uploads","id":"2196427977239021"}],"paging":{"cursors":{"before":"MjcyOTE4NTkxMzk2MzIyMgZDZD","after":"MjE5NjQyNzk3NzIzOTAyMQZDZD"},"previous":"https://graph.facebook.com/v4.0/2121008874780932/albums?access_token=access_token&pretty=0&limit=3&before=MjcyOTE4NTkxMzk2MzIyMgZDZD"}} -------------------------------------------------------------------------------- /testdata/facebook/apidata/applications/application_accounts.json: -------------------------------------------------------------------------------- 1 | {"data":[{"id":"123456789","login_url":"https://developers.facebook.com/checkpoint/test-user-login/123456789/?is_sandbox=0&sandbox_asset_type=test_user&page_id=0","access_token":"access_token"},{"id":"987654321","login_url":"https://developers.facebook.com/checkpoint/test-user-login/987654321/?is_sandbox=0&sandbox_asset_type=test_user&page_id=0","access_token":"access_token"},{"id":"10987654321","login_url":"https://developers.facebook.com/checkpoint/test-user-login/10987654321/?is_sandbox=0&sandbox_asset_type=test_user&page_id=0","access_token":"access_token"},{"id":"1099981235123","login_url":"https://developers.facebook.com/checkpoint/test-user-login/1099981235123/?is_sandbox=0&sandbox_asset_type=test_user&page_id=0","access_token":"access_token"}],"paging":{"cursors":{"before":"before","after":"after"}}} -------------------------------------------------------------------------------- /testdata/facebook/apidata/applications/application_info.json: -------------------------------------------------------------------------------- 1 | {"category":"Business","link":"https://example.com/login","name":"Facebook","id":"123456789"} -------------------------------------------------------------------------------- /testdata/facebook/apidata/business/business_info.json: -------------------------------------------------------------------------------- 1 | {"id":"123456789","name":"App","link":"https://www.facebook.com/123456789","created_time":"2018-01-04T07:12:08+0000","updated_time":"2021-08-31T08:27:35+0000","verification_status":"verified","profile_picture_uri":"https://scontent-nrt1-1.xx.fbcdn.net/profile_picture_uri"} -------------------------------------------------------------------------------- /testdata/facebook/apidata/business/businesses_info.json: -------------------------------------------------------------------------------- 1 | {"123456789":{"id":"123456789","name":"App","link":"https://www.facebook.com/123456789","created_time":"2018-01-04T07:12:08+0000","updated_time":"2021-08-31T08:27:35+0000","verification_status":"verified","profile_picture_uri":"https://scontent-nrt1-1.xx.fbcdn.net/profile_picture_uri"},"987654321":{"id":"987654321","name":"LKApp","link":"https://business.facebook.com/business/987654321","created_time":"2019-09-06T00:40:30+0000","updated_time":"2020-02-04T10:08:05+0000","verification_status":"not_verified","profile_picture_uri":"https://scontent-nrt1-1.xx.fbcdn.net/profile_picture_uri"}} -------------------------------------------------------------------------------- /testdata/facebook/apidata/comments/comment_info.json: -------------------------------------------------------------------------------- 1 | {"id":"10158371815748553_10158371930463553","comment_count":0,"created_time":"2021-07-21T21:05:14+0000","like_count":0,"message":"This is really nice","permalink_url":"https://www.facebook.com/19292868552/posts/10158371815748553/?comment_id=10158371930463553"} -------------------------------------------------------------------------------- /testdata/facebook/apidata/comments/comments_info.json: -------------------------------------------------------------------------------- 1 | {"10158371815748553_10158371930463553":{"id":"10158371815748553_10158371930463553","comment_count":0,"created_time":"2021-07-21T21:05:14+0000","like_count":0,"message":"This is really nice","permalink_url":"https://www.facebook.com/19292868552/posts/10158371815748553/?comment_id=10158371930463553"},"10158371815748553_10158372268858553":{"id":"10158371815748553_10158372268858553","comment_count":1,"created_time":"2021-07-22T00:06:22+0000","like_count":0,"message":"Please what's happened with Facebook camera frame this week it disappear in frame studio at all. Please Facebook for developers help","permalink_url":"https://www.facebook.com/19292868552/posts/10158371815748553/?comment_id=10158372268858553"}} -------------------------------------------------------------------------------- /testdata/facebook/apidata/comments/create_resp.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": "245778718206154_229887283291835", 3 | "message": "Message from api and updated", 4 | "permalink_url": "https://www.facebook.com/245628824887810/posts/245778718206154?comment_id=229887283291835", 5 | "created_time": "2023-07-14T10:45:55+0000" 6 | } -------------------------------------------------------------------------------- /testdata/facebook/apidata/conversations/cvs_info.json: -------------------------------------------------------------------------------- 1 | {"id":"t_587956915396498","link":"/2121008874780932/inbox/2582605345287947/","message_count":94,"snippet":"hello","unread_count":1,"updated_time":"2021-07-23T09:28:50+0000"} -------------------------------------------------------------------------------- /testdata/facebook/apidata/conversations/cvses_info.json: -------------------------------------------------------------------------------- 1 | {"t_587956915396498":{"id":"t_587956915396498","link":"/2121008874780932/inbox/2582605345287947/","message_count":94,"snippet":"hello","unread_count":1,"updated_time":"2021-07-23T09:28:50+0000"},"t_233782918546745":{"id":"t_233782918546745","link":"/2121008874780932/inbox/2914751872073291/","message_count":11,"snippet":"hehe","unread_count":1,"updated_time":"2021-07-23T09:30:39+0000"}} -------------------------------------------------------------------------------- /testdata/facebook/apidata/events/event_info.json: -------------------------------------------------------------------------------- 1 | {"id":"5971414199599456","name":"Python Go Go Go","description":"Talk the descprition for python","start_time":"2021-07-23T21:00:00+0800","end_time":"2021-07-27T00:00:00+0800","place":{"name":"Washington Place Dasmarinas - CVRI","location":{"city":"Dasmariñas","country":"Philippines","latitude":14.274640893666,"longitude":120.96776474724,"street":"Brgy Malinta","zip":"4114"},"id":"534105339994132"},"event_times":[{"id":"5971414202932789","start_time":"2021-07-26T21:00:00+0800","end_time":"2021-07-27T00:00:00+0800","ticket_uri":"https://www.baidu.com/"},{"id":"5971414216266121","start_time":"2021-07-25T21:00:00+0800","end_time":"2021-07-26T00:00:00+0800","ticket_uri":"https://www.baidu.com/"},{"id":"5971414206266122","start_time":"2021-07-24T21:00:00+0800","end_time":"2021-07-25T00:00:00+0800","ticket_uri":"https://www.baidu.com/"},{"id":"5971414212932788","start_time":"2021-07-23T21:00:00+0800","end_time":"2021-07-24T00:00:00+0800","ticket_uri":"https://www.baidu.com/"}]} -------------------------------------------------------------------------------- /testdata/facebook/apidata/events/events_info.json: -------------------------------------------------------------------------------- 1 | {"5971414199599456":{"id":"5971414199599456","name":"Python Go Go Go","description":"Talk the descprition for python","start_time":"2021-07-23T21:00:00+0800","end_time":"2021-07-27T00:00:00+0800","place":{"name":"Washington Place Dasmarinas - CVRI","location":{"city":"Dasmariñas","country":"Philippines","latitude":14.274640893666,"longitude":120.96776474724,"street":"Brgy Malinta","zip":"4114"},"id":"534105339994132"},"event_times":[{"id":"5971414202932789","start_time":"2021-07-26T21:00:00+0800","end_time":"2021-07-27T00:00:00+0800","ticket_uri":"https://www.baidu.com/"},{"id":"5971414216266121","start_time":"2021-07-25T21:00:00+0800","end_time":"2021-07-26T00:00:00+0800","ticket_uri":"https://www.baidu.com/"},{"id":"5971414206266122","start_time":"2021-07-24T21:00:00+0800","end_time":"2021-07-25T00:00:00+0800","ticket_uri":"https://www.baidu.com/"},{"id":"5971414212932788","start_time":"2021-07-23T21:00:00+0800","end_time":"2021-07-24T00:00:00+0800","ticket_uri":"https://www.baidu.com/"}]},"512411373205445":{"id":"512411373205445","name":"AAAAAA","description":"A desciption to new","start_time":"2021-07-23T20:00:00-0500","end_time":"2021-07-23T23:00:00-0500","place":{"name":"H. Matamoros, Tamaulipas"}}} -------------------------------------------------------------------------------- /testdata/facebook/apidata/groups/group_default_fields.json: -------------------------------------------------------------------------------- 1 | {"id":"251560641854558","name":"Python Developers","description":"This group is dedicated to Python Developers & Programmers which discusses all aspects of the server side/design scripting language and the likes. ","created_time":"2016-03-30T11:06:56+0000","member_count":188310} -------------------------------------------------------------------------------- /testdata/facebook/apidata/groups/group_fields.json: -------------------------------------------------------------------------------- 1 | {"id":"251560641854558","name":"Python Developers","description":"This group is dedicated to Python Developers & Programmers which discusses all aspects of the server side/design scripting language and the likes. ","created_time":"2016-03-30T11:06:56+0000","member_count":188310} -------------------------------------------------------------------------------- /testdata/facebook/apidata/groups/groups_default_fields.json: -------------------------------------------------------------------------------- 1 | {"251560641854558":{"id":"251560641854558","name":"Python Developers","description":"This group is dedicated to Python Developers & Programmers which discusses all aspects of the server side/design scripting language and the likes. ","created_time":"2016-03-30T11:06:56+0000","member_count":188324,"member_request_count":0,"email":"251560641854558@groups.facebook.com","icon":"https://static.xx.fbcdn.net/rsrc.php/v3/y8/r/5_2zSM9mMSk.png"},"2260975870792283":{"id":"2260975870792283","name":"Facebook Developer Circle: Hong Kong","description":"Welcome! This is a forum for developers in Hong Kong who are interested in building on the Facebook platform to interact and collaborate other developers who share similar interests. Technologies discussed here include all the products listed on this page: https://developers.facebook.com/products This group is not for asking questions about using Facebook or your profile, asking people to like your page or app, advertising your site, posting photos of yourself, etc. Such posts may be removed and you may also be removed from the group. Please remember to be respectful and considerate to other members of the group at all times. Don't hesitate to participate by making fresh posts, making a comment or asking a question. If you are asking a question please search first to make sure that your question has not been answered already. Let's connect, share and build! For documentation and latest updates from Facebook, visit the Facebook for Developers site: https://developers.facebook.com/","created_time":"2018-10-29T05:57:48+0000","member_count":744,"member_request_count":0,"email":"devchongkong@groups.facebook.com","icon":"https://static.xx.fbcdn.net/rsrc.php/v3/y8/r/5_2zSM9mMSk.png"}} -------------------------------------------------------------------------------- /testdata/facebook/apidata/groups/groups_fields.json: -------------------------------------------------------------------------------- 1 | {"251560641854558":{"id":"251560641854558","name":"Python Developers","description":"This group is dedicated to Python Developers & Programmers which discusses all aspects of the server side/design scripting language and the likes. ","created_time":"2016-03-30T11:06:56+0000","member_count":188324},"2260975870792283":{"id":"2260975870792283","name":"Facebook Developer Circle: Hong Kong","description":"Welcome! This is a forum for developers in Hong Kong who are interested in building on the Facebook platform to interact and collaborate other developers who share similar interests. Technologies discussed here include all the products listed on this page: https://developers.facebook.com/products This group is not for asking questions about using Facebook or your profile, asking people to like your page or app, advertising your site, posting photos of yourself, etc. Such posts may be removed and you may also be removed from the group. Please remember to be respectful and considerate to other members of the group at all times. Don't hesitate to participate by making fresh posts, making a comment or asking a question. If you are asking a question please search first to make sure that your question has not been answered already. Let's connect, share and build! For documentation and latest updates from Facebook, visit the Facebook for Developers site: https://developers.facebook.com/","created_time":"2018-10-29T05:57:48+0000","member_count":744}} -------------------------------------------------------------------------------- /testdata/facebook/apidata/live_videos/live_video_default.json: -------------------------------------------------------------------------------- 1 | {"id":"10158276101223553","creation_time":"2021-06-02T16:56:20+0000","description":"Watch our F8 Refresh technical deep-dive sessions and learn how you can build, innovate and grow on our platforms.","embed_html":"","live_views":0,"permalink_url":"/FacebookforDevelopers/videos/279003613911881/","status":"VOD","title":"F8 Refresh 2021 Sessions"} -------------------------------------------------------------------------------- /testdata/facebook/apidata/live_videos/live_video_fields.json: -------------------------------------------------------------------------------- 1 | {"title":"F8 Refresh 2021 Sessions","status":"VOD","embed_html":"","id":"10158276101223553"} -------------------------------------------------------------------------------- /testdata/facebook/apidata/live_videos/live_videos_default.json: -------------------------------------------------------------------------------- 1 | {"10158276101223553":{"id":"10158276101223553","creation_time":"2021-06-02T16:56:20+0000","description":"Watch our F8 Refresh technical deep-dive sessions and learn how you can build, innovate and grow on our platforms.","embed_html":"","live_views":0,"permalink_url":"/FacebookforDevelopers/videos/279003613911881/","status":"VOD","title":"F8 Refresh 2021 Sessions"},"10158275863243553":{"id":"10158275863243553","creation_time":"2021-06-02T15:18:13+0000","description":"Watch our F8 Refresh keynote and learn about the latest product announcements across Facebook technologies.","embed_html":"","live_views":0,"permalink_url":"/FacebookforDevelopers/videos/535020081012234/","status":"VOD","title":"F8 Refresh 2021 Keynote"}} -------------------------------------------------------------------------------- /testdata/facebook/apidata/live_videos/live_videos_fields.json: -------------------------------------------------------------------------------- 1 | {"10158276101223553":{"title":"F8 Refresh 2021 Sessions","status":"VOD","embed_html":"","id":"10158276101223553"},"10158275863243553":{"title":"F8 Refresh 2021 Keynote","status":"VOD","embed_html":"","id":"10158275863243553"}} -------------------------------------------------------------------------------- /testdata/facebook/apidata/live_videos/live_videos_p1.json: -------------------------------------------------------------------------------- 1 | {"data":[{"id":"10160659411121729","creation_time":"2021-04-23T14:57:11+0000","description":"Fidji Simo, Head of Facebook app, is live with Kati Morton – creator, therapist, and ASMR enthusiast – for a conversation around the importance of audio and the rise of ASMR.","embed_html":"","live_views":0,"permalink_url":"/facebookapp/videos/4163439280375494/","status":"VOD","title":"Fidji Simo X Kati Morton Live"},{"id":"10160245287386729","creation_time":"2020-11-23T17:50:34+0000","description":"This Black Friday we’re doing things a little different. 👏 Yes, we’re all about doing good for Black-owned businesses and the people on your gift list. 🎁 So tune in as Gabrielle Union and Phoebe Robinson host the finale of The #BuyBlack Friday Show. 🤩 Miguel is playing his hits and Reggie Watts brings the beats, celebrating six incredible businesses and a host of others dedicated to making this Friday one to remember.🙌 #LiftBlackVoices #MoreTogether","embed_html":"","live_views":0,"permalink_url":"/facebookapp/videos/219661816186623/","status":"VOD"},{"id":"10160069112711729","creation_time":"2020-09-24T15:27:19+0000","description":"We are live! Join us now for the Facebook Communities Summit Keynote and to celebrate 10 years of Facebook Groups. Tune in to hear the latest announcements from Facebook executives and learn how it'll be easier than ever to connect with more of what you love. Watch below!","embed_html":"","live_views":0,"permalink_url":"/facebookapp/videos/800021560745248/","status":"VOD","title":"Facebook Communities Summit Keynote 2020"}],"paging":{"cursors":{"before":"before","after":"after"},"next":"https://graph.facebook.com/v11.0/20531316728/live_videos?access_token=access_token&pretty=0&fields=id%2Ccreation_time%2Cdescription%2Cembed_html%2Clive_views%2Cpermalink_url%2Csecure_stream_url%2Cstatus%2Cstream_url%2Ctitle&limit=3&after=after"}} -------------------------------------------------------------------------------- /testdata/facebook/apidata/live_videos/live_videos_p2.json: -------------------------------------------------------------------------------- 1 | {"data":[{"id":"10160053690276729","creation_time":"2020-09-18T20:21:11+0000","description":"In honor of Climate Week and the recent launch of the Climate Science Information Center on Facebook, Fidji Simo, Head of Facebook app, is going live with Ian Somerhalder, actor, UN Environment Programme Global Goodwill Ambassador, and Founder and President of the Ian Somerhalder Foundation to discuss ways we can come together as a community to conserve our world and more.","embed_html":"","live_views":0,"permalink_url":"/facebookapp/videos/2835506913350659/","status":"VOD","title":"Live with Ian Somerhalder"},{"id":"10159620846686729","creation_time":"2020-05-11T15:52:18+0000","description":"Facebook and Instagram celebrate the Class of 2020 with a graduation livestream featuring Oprah Winfrey as commencement speaker, plus Miley Cyrus, Selena Gomez, Hugh Jackman, Cardi B, and more! Don’t miss this once-in-a-lifetime #Graduation2020 event, as we come together to honor the high school and college students, teachers, and parents who have made this incredible achievement possible. #MoreTogether (portions of this program were pre-recorded)","embed_html":"","live_views":0,"permalink_url":"/facebookapp/videos/378060546441584/","status":"VOD","title":"#Graduation2020: Facebook and Instagram Celebrate the Class of 2020"},{"id":"10159471837851729","creation_time":"2020-04-09T18:08:58+0000","description":"Fidji Simo, Head of Facebook app, was Live with Eric Klinenberg, Professor of Social Science and Director of the Institute of Public Knowledge at New York University and author of Palaces for the People and Going Solo to discuss the importance of solidarity and what it means to build community as we navigate the COVID-19 pandemic. #MoreTogether","embed_html":"","live_views":0,"permalink_url":"/facebookapp/videos/2643667992583530/","status":"VOD","title":"Live with sociologist Eric Klinenberg"}],"paging":{"cursors":{"before":"before","after":"after"},"previous":"https://graph.facebook.com/v11.0/20531316728/live_videos?access_token=access_token&pretty=0&fields=id%2Ccreation_time%2Cdescription%2Cembed_html%2Clive_views%2Cpermalink_url%2Csecure_stream_url%2Cstatus%2Cstream_url%2Ctitle&limit=3&before=before"}} -------------------------------------------------------------------------------- /testdata/facebook/apidata/messages/message_info.json: -------------------------------------------------------------------------------- 1 | {"id":"m_ToF35NI1OImBjyUIgplSaBMylUFmkYY4bHogy9C1otLISU6SGhccB5NK-THX_W4EdVQiKVv5SgCW9m-_C78mRA","created_time":"2021-07-23T09:50:48+0000","from":{"name":"Kun Liu","email":"2711636948859886@facebook.com","id":"2711636948859886"},"to":{"data":[{"name":"MyLife","email":"2121008874780932@facebook.com","id":"2121008874780932"}]},"tags":{"data":[{"name":"inbox"},{"name":"source:mobile"}]},"attachments":{"data":[{"id":"651143212510248","mime_type":"image/jpeg","name":"image-651143212510248","size":54542,"image_data":{"width":1920,"height":1213,"max_width":1920,"max_height":1213,"url":"https://scontent-gmp1-1.xx.fbcdn.net/v/t1.15752-9/216389199_651143215843581_1189390911866437382_n.jpg?_nc_cat=107&ccb=1-3&_nc_sid=58c789&_nc_ohc=l-FaTRF4SAMAX8ymGu0&_nc_oc=AQl2J5ZJ67IVxSjZIqw7KXXEFocsvJF3Si52ekiVq201hgNdEnyPULdFgtKJR1voMAs&_nc_ht=scontent-gmp1-1.xx&oh=040e8d09bd33ff37601195402f6595b8&oe=611F7644","preview_url":"https://scontent-gmp1-1.xx.fbcdn.net/v/t1.15752-9/p280x280/216389199_651143215843581_1189390911866437382_n.jpg?_nc_cat=107&ccb=1-3&_nc_sid=58c789&_nc_ohc=l-FaTRF4SAMAX8ymGu0&_nc_oc=AQl2J5ZJ67IVxSjZIqw7KXXEFocsvJF3Si52ekiVq201hgNdEnyPULdFgtKJR1voMAs&_nc_ht=scontent-gmp1-1.xx&oh=4b08d523164ee29619d49d556555caeb&oe=611F63B3","image_type":1,"render_as_sticker":false}}],"paging":{"cursors":{"before":"MAZDZD","after":"MAZDZD"},"next":"https://graph.facebook.com/v10.0/m_ToF35NI1OImBjyUIgplSaBMylUFmkYY4bHogy9C1otLISU6SGhccB5NK-THX_W4EdVQiKVv5SgCW9m-_C78mRA/attachments?access_token=access_token&pretty=0&limit=25&after=MAZDZD"}}} -------------------------------------------------------------------------------- /testdata/facebook/apidata/pages/multi_pages.json: -------------------------------------------------------------------------------- 1 | {"19292868552":{"id":"19292868552","name":"Facebook for Developers","username":"FacebookforDevelopers","fan_count":7966989},"20531316728":{"id":"20531316728","name":"Facebook App","username":"facebookapp","fan_count":210103936}} -------------------------------------------------------------------------------- /testdata/facebook/apidata/pages/search_pages.json: -------------------------------------------------------------------------------- 1 | {"data":[{"id":"108824017345866","name":"Facebook","link":"https://www.facebook.com/108824017345866"},{"id":"20531316728","name":"Facebook App","link":"https://www.facebook.com/20531316728"},{"id":"185150934832623","name":"Facebook","link":"https://www.facebook.com/185150934832623"},{"id":"126320487382225","name":"T.Rextasy (Marc Bolan Tribute) Official Facebook Page","link":"https://www.facebook.com/126320487382225"},{"id":"196822497403119","name":"Facebook Direct Support","link":"https://www.facebook.com/196822497403119"}],"paging":{"cursors":{"before":"before","after":"after"},"next":"https://graph.facebook.com/v12.0/pages/search?access_token=access_token&pretty=0&fields=id%2Cname%2Clocation%2Clink&q=facebook&limit=5&after=after","previous":"https://graph.facebook.com/v12.0/pages/search?access_token=access_token&pretty=0&fields=id%2Cname%2Clocation%2Clink&q=facebook&limit=5&before=before"}} -------------------------------------------------------------------------------- /testdata/facebook/apidata/pages/single_default_page.json: -------------------------------------------------------------------------------- 1 | { 2 | "fan_count": 214507731, 3 | "checkins": 11, 4 | "category": "网站", 5 | "cover": { 6 | "cover_id": "10159027219496729", 7 | "offset_x": 49, 8 | "offset_y": 50, 9 | "source": "https://scontent.xx.fbcdn.net/v/t1.0-9/s720x720/78503930_10159027219516729_2925301529520898048_o.jpg?_nc_cat=1&_nc_oc=AQmFFFfNu60W_cDjUn6zM_oT_F0foWLKfPhCcN41gdGrAXnxumU9jBWJtg_Ml-PcqAk&_nc_ht=scontent.xx&oh=c0a97d5b033cfcb7fd41962050389f03&oe=5EAF310D", 10 | "id": "10159027219496729" 11 | }, 12 | "general_info": "Your ideas and suggestions help us to constantly improve Facebook’s features. Let us know how we can improve your experience: www.facebook.com/help/feedback For Facebook support questions, please visit the help center: https://www.facebook.com/help?ref=facebook_page ", 13 | "engagement": { 14 | "count": 214507731, 15 | "social_sentence": "2.1 亿位用户赞了" 16 | }, 17 | "verification_status": "blue_verified", 18 | "link": "https://www.facebook.com/facebookapp/", 19 | "display_subtext": "11 位用户在这里签到", 20 | "name": "Facebook", 21 | "can_checkin": true, 22 | "about": "The Facebook Page celebrates how our friends inspire us, support us, and help us discover the world when we connect.", 23 | "were_here_count": 143680, 24 | "category_list": [ 25 | { 26 | "id": "2202", 27 | "name": "网站" 28 | }, 29 | { 30 | "id": "2200", 31 | "name": "公司" 32 | } 33 | ], 34 | "global_brand_root_id": "1499730620315598", 35 | "id": "20531316728", 36 | "global_brand_page_name": "Facebook", 37 | "founded": "February 4, 2004", 38 | "username": "facebookapp", 39 | "talking_about_count": 652404, 40 | "start_info": { 41 | "type": "未填", 42 | "date": { 43 | "year": 2004, 44 | "month": 2, 45 | "day": 4 46 | } 47 | }, 48 | "website": "http://www.facebook.com", 49 | "picture": { 50 | "data": { 51 | "height": 50, 52 | "is_silhouette": false, 53 | "url": "https://scontent.xx.fbcdn.net/v/t1.0-1/p50x50/58978526_10158354585751729_7411073224387067904_o.png?_nc_cat=1&_nc_oc=AQkIOsx_P9GyqbX2FD_kFcufwmoVbnZrl5wZqqj3WrdNQpUdmg211Ywbhh0uG60mJkA&_nc_ht=scontent.xx&oh=39d6c6b5f0541de4fca97adbab5fe605&oe=5EA77954", 54 | "width": 50 55 | } 56 | } 57 | } -------------------------------------------------------------------------------- /testdata/facebook/apidata/pages/single_fields_page.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": "20531316728", 3 | "name": "Facebook", 4 | "username": "facebookapp", 5 | "fan_count": 214507731 6 | } -------------------------------------------------------------------------------- /testdata/facebook/apidata/photos/photo_info_default.json: -------------------------------------------------------------------------------- 1 | {"created_time":"2021-05-20T19:17:41+0000","id":"10158249017468553"} -------------------------------------------------------------------------------- /testdata/facebook/apidata/photos/photo_info_fields.json: -------------------------------------------------------------------------------- 1 | {"id":"10158249017468553","created_time":"2021-05-20T19:17:41+0000","updated_time":"2021-05-30T14:05:11+0000","link":"https://www.facebook.com/FacebookforDevelopers/photos/a.444082318552/10158249017468553/?type=3"} -------------------------------------------------------------------------------- /testdata/facebook/apidata/photos/photos_info_default.json: -------------------------------------------------------------------------------- 1 | {"10157415047288553":{"created_time":"2020-06-01T16:00:45+0000","id":"10157415047288553"},"10158249017468553":{"created_time":"2021-05-20T19:17:41+0000","id":"10158249017468553"}} -------------------------------------------------------------------------------- /testdata/facebook/apidata/photos/photos_info_fields.json: -------------------------------------------------------------------------------- 1 | {"10157415047288553":{"id":"10157415047288553","created_time":"2020-06-01T16:00:45+0000","updated_time":"2020-09-15T15:59:34+0000","link":"https://www.facebook.com/FacebookforDevelopers/photos/a.444082318552/10157415047288553/?type=3"},"10158249017468553":{"id":"10158249017468553","created_time":"2021-05-20T19:17:41+0000","updated_time":"2021-05-30T14:05:11+0000","link":"https://www.facebook.com/FacebookforDevelopers/photos/a.444082318552/10158249017468553/?type=3"}} -------------------------------------------------------------------------------- /testdata/facebook/apidata/photos/photos_p1.json: -------------------------------------------------------------------------------- 1 | {"data":[{"id":"336596487901950","created_time":"2021-05-07T16:18:42+0000","updated_time":"2021-05-07T17:19:12+0000","link":"https://www.facebook.com/facebook/photos/a.108824087345859/336596487901950/?type=3"},{"id":"200337158194551","created_time":"2020-09-15T16:00:32+0000","updated_time":"2021-05-07T16:18:32+0000","link":"https://www.facebook.com/facebook/photos/a.108824087345859/200337158194551/?type=3"}],"paging":{"cursors":{"before":"before","after":"after"},"next":"https://graph.facebook.com/v11.0/108824017345866/photos?access_token=access_token&pretty=0&fields=id%2Ccreated_time%2Cname%2Cupdated_time%2Clink&limit=2&after=after"}} -------------------------------------------------------------------------------- /testdata/facebook/apidata/photos/photos_p2.json: -------------------------------------------------------------------------------- 1 | {"data":[{"id":"166370841591183","created_time":"2020-06-01T05:07:38+0000","updated_time":"2020-09-15T16:00:29+0000","link":"https://www.facebook.com/facebook/photos/a.108824087345859/166370841591183/?type=3"},{"id":"124830722411862","created_time":"2020-02-24T20:17:47+0000","updated_time":"2020-06-01T05:07:34+0000","link":"https://www.facebook.com/facebook/photos/a.108824087345859/124830722411862/?type=3"}],"paging":{"cursors":{"before":"before","after":"after"},"previous":"https://graph.facebook.com/v4.0/108824017345866/photos?access_token=access_token&pretty=0&fields=id%2Ccreated_time%2Cname%2Cupdated_time%2Clink&limit=2&before=before"}} -------------------------------------------------------------------------------- /testdata/facebook/apidata/pictures/multi_pictures.json: -------------------------------------------------------------------------------- 1 | { 2 | "2121008874780932": { 3 | "data": { 4 | "height": 200, 5 | "is_silhouette": false, 6 | "url": "https://scontent.xx.fbcdn.net/v/t1.0-1/c74.0.200.200a/p200x200/36634907_2121009181447568_2127159854165393408_o.jpg?_nc_cat=103&_nc_oc=AQlfRMbKjWEH8l5-UVENL6ObZ3hiUEpXK8MhkFf7Eov7ojvlWhtgXSSmpZJdkE8IxnQ&_nc_ht=scontent.xx&oh=0032baa9992f7bae0696c53ba220877e&oe=5EA6F62F", 7 | "width": 200 8 | } 9 | }, 10 | "20531316728": { 11 | "data": { 12 | "height": 200, 13 | "is_silhouette": false, 14 | "url": "https://scontent.xx.fbcdn.net/v/t1.0-1/p200x200/58978526_10158354585751729_7411073224387067904_o.png?_nc_cat=1&_nc_oc=AQnopPJzuhaoOz__M5Wmg8TU_6h5wrgAQYHQpQlCCISNl2yhzFjYMTZIHJNw27ZPDUM&_nc_ht=scontent.xx&oh=703e1d0e301e6563f68cc364dd48c99d&oe=5EB2BE89", 15 | "width": 200 16 | } 17 | } 18 | } -------------------------------------------------------------------------------- /testdata/facebook/apidata/pictures/single_picture.json: -------------------------------------------------------------------------------- 1 | { 2 | "data": { 3 | "height": 200, 4 | "is_silhouette": false, 5 | "url": "https://scontent.xx.fbcdn.net/v/t1.0-1/c74.0.200.200a/p200x200/36634907_2121009181447568_2127159854165393408_o.jpg?_nc_cat=103&_nc_oc=AQlfRMbKjWEH8l5-UVENL6ObZ3hiUEpXK8MhkFf7Eov7ojvlWhtgXSSmpZJdkE8IxnQ&_nc_ht=scontent.xx&oh=0032baa9992f7bae0696c53ba220877e&oe=5EA6F62F", 6 | "width": 200 7 | } 8 | } -------------------------------------------------------------------------------- /testdata/facebook/apidata/posts/feed_fields_p1.json: -------------------------------------------------------------------------------- 1 | {"data":[{"id":"4_10113477241177441","message":"Happy July 4th! 🇺🇸","created_time":"2021-07-04T19:50:58+0000"},{"id":"4_10113449068715281","message":"Some good news reading: teams at the Chan Zuckerberg Initiative and Biohub have been building IDseq -- an open source infectious disease genetic sequencing tool that can serve as an early warning system around the world. We were building it when Covid hit, and in Cambodia it was used to confirm the country's first case and inform their prevention efforts.","created_time":"2021-07-02T13:42:21+0000"},{"id":"4_10113400535556121","message":"I'm grateful to get to build things that so many people find meaningful in their lives.","created_time":"2021-06-29T01:34:06+0000"},{"id":"4_10113332572050531","message":"Thanks @adam.the.creator for designing my next board. The sun never stood a chance.","created_time":"2021-06-23T17:39:46+0000"},{"id":"4_10113319652002411","message":"New commerce features coming to support businesses and make shopping easier: Shops on WhatsApp and Marketplace, Instagram Visual Search and Shops Ads. More detail in the comments.","created_time":"2021-06-22T18:06:08+0000"}],"paging":{"previous":"https://graph.facebook.com/v10.0/4/posts?access_token=access_token&pretty=0&fields=id%2Cmessage%2Ccreated_time&__previous=1&since=1625428258&until&__paging_token=__paging_token","next":"https://graph.facebook.com/v10.0/4/posts?access_token=access_token&pretty=0&fields=id%2Cmessage%2Ccreated_time&until=1624385168&since&__paging_token=__paging_token&__previous"}} -------------------------------------------------------------------------------- /testdata/facebook/apidata/posts/feed_fields_p2.json: -------------------------------------------------------------------------------- 1 | {"data":[{"id":"4_10113477241177441","message":"Happy July 4th! 🇺🇸","created_time":"2021-07-04T19:50:58+0000"},{"id":"4_10113449068715281","message":"Some good news reading: teams at the Chan Zuckerberg Initiative and Biohub have been building IDseq -- an open source infectious disease genetic sequencing tool that can serve as an early warning system around the world. We were building it when Covid hit, and in Cambodia it was used to confirm the country's first case and inform their prevention efforts.","created_time":"2021-07-02T13:42:21+0000"},{"id":"4_10113400535556121","message":"I'm grateful to get to build things that so many people find meaningful in their lives.","created_time":"2021-06-29T01:34:06+0000"},{"id":"4_10113332572050531","message":"Thanks @adam.the.creator for designing my next board. The sun never stood a chance.","created_time":"2021-06-23T17:39:46+0000"},{"id":"4_10113319652002411","message":"New commerce features coming to support businesses and make shopping easier: Shops on WhatsApp and Marketplace, Instagram Visual Search and Shops Ads. More detail in the comments.","created_time":"2021-06-22T18:06:08+0000"}],"paging":{"previous":"https://graph.facebook.com/v10.0/4/posts?access_token=access_token&pretty=0&fields=id%2Cmessage%2Ccreated_time&until&__previous=1&since=1623945625&__paging_token=__paging_token"}} -------------------------------------------------------------------------------- /testdata/facebook/apidata/posts/multi_posts_data_fields.json: -------------------------------------------------------------------------------- 1 | {"19292868552_10158347294088553":{"id":"19292868552_10158347294088553","created_time":"2021-07-08T15:30:19+0000","message":"Despite reliable peering being essential for Facebook and for everyone’s internet use, there hasn’t been an industry standard for how to set up a scalable, automatic peering management system. However, the team at Facebook Engineering developed PeeringDB OAuth, a new automated method that allows for faster self-service peering configuration on the open-source PeeringDB database. Read about the best practices they’ve discovered: https://fb.me/Facebook-Peering-automation","updated_time":"2021-07-09T09:29:06+0000"},"19292868552_10158345715593553":{"id":"19292868552_10158345715593553","created_time":"2021-07-07T17:02:59+0000","message":"Messenger API for Instagram opened up to all developers in June, with an opportunity to build for IG business accounts with follower counts between 10k-100k. We are expanding the rollout to Instagram business accounts with follower counts between 1K-10K so you can build for more businesses! Read more on how to get started: https://fb.me/Messenger-API-for-Instagram","updated_time":"2021-07-09T07:31:45+0000"}} -------------------------------------------------------------------------------- /testdata/facebook/apidata/posts/single_post_data.json: -------------------------------------------------------------------------------- 1 | { 2 | "love": { 3 | "data": [ 4 | ], 5 | "summary": { 6 | "total_count": 0 7 | } 8 | }, 9 | "updated_time": "2019-08-16T11:18:58+0000", 10 | "like": { 11 | "data": [ 12 | ], 13 | "summary": { 14 | "total_count": 0 15 | } 16 | }, 17 | "id": "175154750010052_424924701699721", 18 | "angry": { 19 | "data": [ 20 | ], 21 | "summary": { 22 | "total_count": 0 23 | } 24 | }, 25 | "comments": { 26 | "data": [ 27 | ], 28 | "summary": { 29 | "order": "chronological", 30 | "total_count": 0, 31 | "can_comment": true 32 | } 33 | }, 34 | "created_time": "2019-08-12T03:45:11+0000", 35 | "wow": { 36 | "data": [ 37 | ], 38 | "summary": { 39 | "total_count": 0 40 | } 41 | }, 42 | "haha": { 43 | "data": [ 44 | ], 45 | "summary": { 46 | "total_count": 1 47 | } 48 | }, 49 | "message": "我测试一下 MyLife", 50 | "sad": { 51 | "data": [ 52 | ], 53 | "summary": { 54 | "total_count": 0 55 | } 56 | }, 57 | "permalink_url": "https://www.facebook.com/175154750010052/posts/424924701699721", 58 | "reactions": { 59 | "data": [ 60 | ], 61 | "summary": { 62 | "total_count": 1, 63 | "viewer_reaction": "NONE" 64 | } 65 | }, 66 | "status_type": "mobile_status_update" 67 | } -------------------------------------------------------------------------------- /testdata/facebook/apidata/posts/single_post_data_fields.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": "175154750010052_424924701699721", 3 | "created_time": "2019-08-12T03:45:11+0000", 4 | "message": "我测试一下 MyLife" 5 | } -------------------------------------------------------------------------------- /testdata/facebook/apidata/users/user.json: -------------------------------------------------------------------------------- 1 | {"id":"4","first_name":"Mark","last_name":"Zuckerberg","name":"Mark Zuckerberg","name_format":"{first} {last}","picture":{"data":{"height":50,"is_silhouette":false,"url":"https://scontent-nrt1-1.xx.fbcdn.net/v/t1.6435-1/cp0/p50x50/79515135_10111007623880301_5111576226921709568_n.jpg?_nc_cat=1&ccb=1-3&_nc_sid=dbb9e7&_nc_ohc=l-dWADDON4AAX8rVpx5&_nc_ad=z-m&_nc_cid=0&_nc_ht=scontent-nrt1-1.xx&tp=27&oh=400a0d61c2231f684d845e483edf9a66&oe=60EA5582","width":50}},"short_name":"Mark Zuckerberg"} -------------------------------------------------------------------------------- /testdata/facebook/apidata/users/user_accounts_p1.json: -------------------------------------------------------------------------------- 1 | {"data":[{"access_token":"access_token","category":"Phone/Tablet","category_list":[{"id":"2265","name":"Phone/Tablet"}],"name":"AAAAAAAAA","id":"123","tasks":["ANALYZE","ADVERTISE","MESSAGING","MODERATE","CREATE_CONTENT","MANAGE"]},{"access_token":"access_token","category":"Musician/Band","category_list":[{"id":"180164648685982","name":"Musician/Band"}],"name":"BBBBBBBB","id":"1234","tasks":["ANALYZE","ADVERTISE","MESSAGING","MODERATE","CREATE_CONTENT","MANAGE"]},{"access_token":"access_token","category":"Shopping & Retail","category_list":[{"id":"200600219953504","name":"Shopping & Retail"},{"id":"2201","name":"Product/Service"}],"name":"EEEEEEEE","id":"123512","tasks":["ANALYZE","ADVERTISE","MESSAGING","MODERATE","CREATE_CONTENT","MANAGE"]},{"access_token":"access_token","category":"TV Show","category_list":[{"id":"1400","name":"TV Show"}],"name":"FFFFFFFFFF","id":"1234624","tasks":["ANALYZE","ADVERTISE","MESSAGING","MODERATE","CREATE_CONTENT","MANAGE"]}],"paging":{"cursors":{"before":"before","after":"after"},"next":"https://graph.facebook.com/v11.0/413140042878187/accounts?access_token=access_token&pretty=0&summary=1&limit=4&after=after"},"summary":{"total_count":6}} -------------------------------------------------------------------------------- /testdata/facebook/apidata/users/user_accounts_p2.json: -------------------------------------------------------------------------------- 1 | {"data":[{"access_token":"access_token","category":"Product/Service","category_list":[{"id":"2201","name":"Product/Service"}],"name":"CCCCCCCCC","id":"123456","tasks":["ANALYZE","ADVERTISE","MESSAGING","MODERATE","CREATE_CONTENT","MANAGE"]},{"access_token":"access_token","category":"Camera/Photo","category_list":[{"id":"2208","name":"Camera/Photo"},{"id":"2202","name":"Website"}],"name":"DDDDDDDD","id":"12345678","tasks":["ANALYZE","ADVERTISE","MESSAGING","MODERATE","CREATE_CONTENT","MANAGE"]}],"paging":{"cursors":{"before":"before","after":"after"},"previous":"https://graph.facebook.com/v11.0/413140042878187/accounts?access_token=access_token&pretty=0&summary=1&limit=4&before=before"},"summary":{"total_count":6}} -------------------------------------------------------------------------------- /testdata/facebook/apidata/users/user_businesses.json: -------------------------------------------------------------------------------- 1 | {"data":[{"id":"123456789","name":"App","link":"https://www.facebook.com/123456789","created_time":"2018-01-04T07:12:08+0000","updated_time":"2021-08-31T08:27:35+0000","verification_status":"verified","profile_picture_uri":"https://scontent-nrt1-1.xx.fbcdn.net/profile_picture_uri"},{"id":"987654321","name":"LKApp","link":"https://business.facebook.com/business/987654321","created_time":"2019-09-06T00:40:30+0000","updated_time":"2020-02-04T10:08:05+0000","verification_status":"not_verified","profile_picture_uri":"https://scontent-nrt1-1.xx.fbcdn.net/profile_picture_uri"}],"paging":{"cursors":{"before":"before","after":"after"}}} -------------------------------------------------------------------------------- /testdata/facebook/apidata/users/users_default.json: -------------------------------------------------------------------------------- 1 | {"4":{"id":"4","first_name":"Mark","last_name":"Zuckerberg","name":"Mark Zuckerberg","name_format":"{first} {last}","picture":{"data":{"height":50,"is_silhouette":false,"url":"https://scontent-iad3-1.xx.fbcdn.net/v/t1.6435-1/cp0/p50x50/79515135_10111007623880301_5111576226921709568_n.jpg?_nc_cat=1&ccb=1-3&_nc_sid=dbb9e7&_nc_ohc=2Llmsc_R_gkAX_c8Afz&_nc_ad=z-m&_nc_cid=0&_nc_ht=scontent-iad3-1.xx&oh=82cc3a141603a34a7c034d5695f098ee&oe=60F04442","width":50}},"short_name":"Mark Zuckerberg"},"5":{"id":"5","first_name":"Chris","last_name":"Hughes","name":"Chris Hughes","name_format":"{first} {last}","picture":{"data":{"height":50,"is_silhouette":false,"url":"https://scontent-iad3-1.xx.fbcdn.net/v/t1.6435-1/cp0/p50x50/73497985_10110310867770131_7470117239316807680_n.jpg?_nc_cat=103&ccb=1-3&_nc_sid=dbb9e7&_nc_ohc=RC7eDlEtKhYAX-xLWwy&_nc_ad=z-m&_nc_cid=0&_nc_ht=scontent-iad3-1.xx&oh=22ed5e96e5f84f1ed568bd86d9595ad3&oe=60EFED76","width":50}},"short_name":"Chris Hughes"}} -------------------------------------------------------------------------------- /testdata/facebook/apidata/users/users_fields.json: -------------------------------------------------------------------------------- 1 | {"4":{"name":"Mark Zuckerberg","id":"4"},"5":{"name":"Chris Hughes","id":"5"}} -------------------------------------------------------------------------------- /testdata/facebook/apidata/videos/video_info_default.json: -------------------------------------------------------------------------------- 1 | {"id":"1192957457884299","created_time":"2021-06-30T21:19:07+0000","description":"After giving users the ability to quickly and easily share recipes and food-related content to Instagram Stories, recipe and lifestyle site iCook 愛料理 boosted its user retention by 30%. See how iCook reached a broader audience by building a new, intuitive user interface flow and integrating Sharing to Stories: https://fb.me/iCook-Success-Story","title":"iCook Success Story","published":true,"length":12.891,"permalink_url":"/FacebookforDevelopers/videos/1192957457884299/"} -------------------------------------------------------------------------------- /testdata/facebook/apidata/videos/video_info_fields.json: -------------------------------------------------------------------------------- 1 | {"description":"After giving users the ability to quickly and easily share recipes and food-related content to Instagram Stories, recipe and lifestyle site iCook 愛料理 boosted its user retention by 30%. See how iCook reached a broader audience by building a new, intuitive user interface flow and integrating Sharing to Stories: https://fb.me/iCook-Success-Story","updated_time":"2021-07-20T01:55:06+0000","id":"1192957457884299"} -------------------------------------------------------------------------------- /testdata/facebook/apidata/videos/videos_info_default.json: -------------------------------------------------------------------------------- 1 | {"1192957457884299":{"description":"After giving users the ability to quickly and easily share recipes and food-related content to Instagram Stories, recipe and lifestyle site iCook 愛料理 boosted its user retention by 30%. See how iCook reached a broader audience by building a new, intuitive user interface flow and integrating Sharing to Stories: https://fb.me/iCook-Success-Story","updated_time":"2021-07-20T01:55:06+0000","id":"1192957457884299"},"334712884667245":{"description":"When the German non-profit Save the Children Deutschland wanted to boost their brand awareness, gain trust, and raise donations, the organization partnered with conversational marketing expert Spectrm and Facebook Creative Shop to build an innovative, automated Messenger experience. After promoting its brand awareness campaign for one month, Save the Children Germany saw a 29% lift in donations and reached over 1.6M people. Learn more: https://fb.me/Save-the-Children-Germany","updated_time":"2021-07-11T04:44:38+0000","id":"334712884667245"}} -------------------------------------------------------------------------------- /testdata/facebook/apidata/videos/videos_info_fields.json: -------------------------------------------------------------------------------- 1 | {"1192957457884299":{"id":"1192957457884299","created_time":"2021-06-30T21:19:07+0000","description":"After giving users the ability to quickly and easily share recipes and food-related content to Instagram Stories, recipe and lifestyle site iCook 愛料理 boosted its user retention by 30%. See how iCook reached a broader audience by building a new, intuitive user interface flow and integrating Sharing to Stories: https://fb.me/iCook-Success-Story","title":"iCook Success Story","published":true,"length":12.891,"permalink_url":"/FacebookforDevelopers/videos/1192957457884299/"},"334712884667245":{"id":"334712884667245","created_time":"2021-06-21T20:54:02+0000","description":"When the German non-profit Save the Children Deutschland wanted to boost their brand awareness, gain trust, and raise donations, the organization partnered with conversational marketing expert Spectrm and Facebook Creative Shop to build an innovative, automated Messenger experience. After promoting its brand awareness campaign for one month, Save the Children Germany saw a 29% lift in donations and reached over 1.6M people. Learn more: https://fb.me/Save-the-Children-Germany","title":"Save the Children Germany Success Story","published":true,"length":59.648,"permalink_url":"/FacebookforDevelopers/videos/334712884667245/"}} -------------------------------------------------------------------------------- /testdata/facebook/apidata/videos/videos_p1.json: -------------------------------------------------------------------------------- 1 | {"data":[{"id":"1002065083862711","created_time":"2021-08-10T16:40:23+0000","description":"In the Boz to the Future Podcast, Facebook Reality Labs VP Andrew “Boz” Bosworth sits down with the technologists and business leaders behind bleeding-edge technology, entertainment, and beyond. Together, they share perspectives on management, leadership, and community-building. Listen to the first two episodes now, where he talks AR glasses with Facebook Reality Labs VP of Operations Rebecca Van Dyck and the creator economy with Instacart CEO Fidji Simo: https://bit.ly/3g9jzUH","title":"Boz to the Future","published":true,"length":33.344,"permalink_url":"/FacebookforDevelopers/videos/1002065083862711/","updated_time":"2021-08-17T14:14:35+0000"},{"id":"1192957457884299","created_time":"2021-06-30T21:19:07+0000","description":"After giving users the ability to quickly and easily share recipes and food-related content to Instagram Stories, recipe and lifestyle site iCook 愛料理 boosted its user retention by 30%. See how iCook reached a broader audience by building a new, intuitive user interface flow and integrating Sharing to Stories: https://fb.me/iCook-Success-Story","title":"iCook Success Story","published":true,"length":12.891,"permalink_url":"/FacebookforDevelopers/videos/1192957457884299/","updated_time":"2021-08-17T21:17:57+0000"},{"id":"334712884667245","created_time":"2021-06-21T20:54:02+0000","description":"When the German non-profit Save the Children Deutschland wanted to boost their brand awareness, gain trust, and raise donations, the organization partnered with conversational marketing expert Spectrm and Facebook Creative Shop to build an innovative, automated Messenger experience. After promoting its brand awareness campaign for one month, Save the Children Germany saw a 29% lift in donations and reached over 1.6M people. Learn more: https://fb.me/Save-the-Children-Germany","title":"Save the Children Germany Success Story","published":true,"length":59.648,"permalink_url":"/FacebookforDevelopers/videos/334712884667245/","updated_time":"2021-08-07T17:36:57+0000"}],"paging":{"cursors":{"before":"before","after":"after"},"next":"https://graph.facebook.com/v11.0/19292868552/videos?access_token=access_token&pretty=0&fields=id%2Ccreated_time%2Cdescription%2Ctitle%2Cpublished%2Clength%2Cpermalink_url%2Cupdated_time&limit=2&after=after"}} -------------------------------------------------------------------------------- /testdata/facebook/apidata/videos/videos_p2.json: -------------------------------------------------------------------------------- 1 | {"data":[{"id":"480061623290861","created_time":"2021-06-08T14:55:53+0000","description":"Discover how startups are innovating on Facebook platforms and learn about Facebook's startup programs. Featuring: Michael Huang, Head of Startup Programs, Facebook Caroline Dalmolin, Developer and Startup Programs Lead, Facebook Pippa Yeats, Co-Founder and Product Manager, Turn.io Saaid Mohamed , Co-Founder and COO, BotMe","title":"F8 Refresh | Innovation Showcase: Meet some of the brightest startups building with Facebook","published":true,"length":1581.627,"permalink_url":"/FacebookforDevelopers/videos/480061623290861/","updated_time":"2021-08-06T10:34:23+0000"},{"id":"298198132044210","created_time":"2021-06-08T14:29:19+0000","description":"Learn how Facebook Business Extension and Business Apps enable you to offer your customers a new way to easily create, manage, and grow their business on Facebook. Apply to be considered for access to Facebook Business Extension to integrate your app with Facebook: https://fb.me/F8Refresh-Facebook-Business-Extension-Business-Apps Featuring: Vietlong Le, Product Manager, Facebook Ayush Sood, Software Engineering Manager, Facebook","title":"F8 Refresh | Helping businesses grow with Facebook Business Extension","published":true,"length":973.543,"permalink_url":"/FacebookforDevelopers/videos/298198132044210/","updated_time":"2021-08-06T10:44:48+0000"}],"paging":{"cursors":{"before":"before","after":"after"},"previous":"https://graph.facebook.com/v11.0/19292868552/videos?access_token=access_token&pretty=0&fields=id%2Ccreated_time%2Cdescription%2Ctitle%2Cpublished%2Clength%2Cpermalink_url%2Cupdated_time&limit=3&before=before"}} -------------------------------------------------------------------------------- /testdata/facebook/models/album.json: -------------------------------------------------------------------------------- 1 | {"can_upload":false,"count":36,"cover_photo":{"created_time":"2016-08-02T00:39:37+0000","id":"10153867132458553"},"created_time":"2016-08-02T00:39:35+0000","description":"FbStart, our global program designed to help mobile startups build and grow their apps, kicked off its world tour in June - visiting 20+ cities around the globe to meet and connect with mobile developers and FbStart members. Learn more about the program at FbStart.com.","from":{"name":"Facebook for Developers","id":"19292868552"},"id":"10153867132423553","link":"https://www.facebook.com/album.php?fbid=10153867132423553&id=19292868552&aid=1073741828","name":"FbStart 2016 World Tour","type":"normal","updated_time":"2016-08-17T22:25:25+0000"} -------------------------------------------------------------------------------- /testdata/facebook/models/business.json: -------------------------------------------------------------------------------- 1 | {"block_offline_analytics":true,"created_by":{"id":"123456789","name":"Kun Liu","business":{"id":"987654321","name":"LiuKun"}},"created_time":"2019-09-06T00:40:30+0000","extended_updated_time":"2020-02-04T10:08:05+0000","id":"987654321","is_hidden":false,"link":"https://business.facebook.com/business/987654321","name":"LiuKun","payment_account_id":"1111111111111","profile_picture_uri":"https://scontent-nrt1-1.xx.fbcdn.net/v/t31.18172-1/p100x100/14257723_1001469876587_262170335513678435_o.png?_nc_cat=102&ccb=1-5&_nc_sid=872a9a&_nc_ohc=4ZamICurN6QAX8rJP0m&_nc_oc=AQl_6L86XbYTBu6iGirGzX1dd3Ba9VV9Lfv-wsipewFtfisEI-0QKPS1cui0J9xJoVo&_nc_ht=scontent-nrt1-1.xx&edm=AHdzj10EAAAA&oh=9eeb883af42b7ec9b52e7a54742a3a80&oe=615BB135","timezone_id":0,"updated_time":"2020-02-04T10:08:05+0000","verification_status":"not_verified","vertical":"OTHER","vertical_id":42} -------------------------------------------------------------------------------- /testdata/facebook/models/comment.json: -------------------------------------------------------------------------------- 1 | {"attachment":{"media":{"image":{"height":403,"src":"https://scontent-gmp1-1.xx.fbcdn.net/v/l/t1.6435-9/p403x403/215449998_909150143277172_2869237268119022043_n.jpg?_nc_cat=105&ccb=1-3&_nc_sid=1480c5&_nc_ohc=FQ0iZYrvm_MAX-kgTrZ&_nc_ht=scontent-gmp1-1.xx&oh=f5f939c79c3b96a12eefced545582250&oe=61210A52","width":720}},"target":{"id":"909150133277173","url":"https://www.facebook.com/photo.php?fbid=909150133277173&set=p.909150133277173&type=3"},"type":"photo","url":"https://www.facebook.com/photo.php?fbid=909150133277173&set=p.909150133277173&type=3"},"can_comment":true,"can_hide":true,"can_like":true,"can_remove":true,"can_reply_privately":true,"comment_count":0,"created_time":"2021-07-23T08:35:18+0000","from":{"name":"Kun Liu","id":"2711636948859886"},"id":"2954961744718970_2966313500250461","is_hidden":false,"is_private":false,"like_count":0,"message":"My Nice Car ","permalink_url":"https://www.facebook.com/2121008874780932/posts/2954961744718970/?comment_id=2966313500250461"} -------------------------------------------------------------------------------- /testdata/facebook/models/conversation.json: -------------------------------------------------------------------------------- 1 | {"can_reply":true,"former_participants":{"data":[]},"id":"t_587956915396498","is_subscribed":true,"link":"/2121008874780932/inbox/2582605345287947/","message_count":93,"participants":{"data":[{"name":"Kun Liu","email":"2711636948859886@facebook.com","id":"2711636948859886"},{"name":"MyLife","email":"2121008874780932@facebook.com","id":"2121008874780932"}]},"scoped_thread_key":"t_587956915396498","snippet":"asfhasjkfa","senders":{"data":[{"name":"Kun Liu","email":"2711636948859886@facebook.com","id":"2711636948859886"},{"name":"MyLife","email":"2121008874780932@facebook.com","id":"2121008874780932"}]},"unread_count":0,"updated_time":"2021-06-08T08:24:57+0000"} -------------------------------------------------------------------------------- /testdata/facebook/models/event.json: -------------------------------------------------------------------------------- 1 | {"attending_count":0,"can_guests_invite":true,"category":"OTHER","cover":{"offset_x":50,"offset_y":50,"source":"https://scontent-gmp1-1.xx.fbcdn.net/v/t1.6435-9/217612123_2966383390243472_5205132644467791768_n.png?_nc_cat=105&ccb=1-3&_nc_sid=1091cb&_nc_ohc=xGmnslnsYOsAX94jBia&_nc_ht=scontent-gmp1-1.xx&oh=7533f89d3b9b22468731ecaef4ae4510&oe=612201FF","id":"2966383383576806"},"created_time":"2021-07-23T11:06:43+0000","declined_count":0,"description":"Talk the descprition for python","discount_code_enabled":false,"end_time":"2021-07-24T00:00:00+0800","guest_list_enabled":true,"id":"5971414212932788","interested_count":0,"is_canceled":false,"is_draft":false,"is_online":false,"is_page_owned":true,"maybe_count":0,"name":"Python Go Go Go","noreply_count":0,"online_event_format":"none","owner":{"name":"MyLife","id":"2121008874780932"},"place":{"name":"Washington Place Dasmarinas - CVRI","location":{"city":"Dasmariñas","country":"Philippines","latitude":14.274640893666,"longitude":120.96776474724,"street":"Brgy Malinta","zip":"4114"},"id":"534105339994132"},"start_time":"2021-07-23T21:00:00+0800","ticket_uri":"https://www.baidu.com/","timezone":"Asia/Manila","type":"public","updated_time":"2021-07-23T11:06:43+0000"} -------------------------------------------------------------------------------- /testdata/facebook/models/group.json: -------------------------------------------------------------------------------- 1 | {"email":"devchongkong@groups.facebook.com","description":"Welcome! This is a forum for developers in Hong Kong who are interested in building on the Facebook platform to interact and collaborate other developers who share similar interests. Technologies discussed here include all the products listed on this page: https://developers.facebook.com/products This group is not for asking questions about using Facebook or your profile, asking people to like your page or app, advertising your site, posting photos of yourself, etc. Such posts may be removed and you may also be removed from the group. Please remember to be respectful and considerate to other members of the group at all times. Don't hesitate to participate by making fresh posts, making a comment or asking a question. If you are asking a question please search first to make sure that your question has not been answered already. Let's connect, share and build! For documentation and latest updates from Facebook, visit the Facebook for Developers site: https://developers.facebook.com/","created_time":"2018-10-29T05:57:48+0000","member_count":744,"id":"2260975870792283","member_request_count":0,"name":"Facebook Developer Circle: Hong Kong","permissions":["Access Your Public Information","Publish to Group"],"privacy":"OPEN","picture":{"data":{"height":50,"is_silhouette":false,"url":"https://scontent-ssn1-1.xx.fbcdn.net/v/t1.6435-0/cp0/c23.0.50.50a/p50x50/45007915_10156542097367597_1738263304385593344_n.jpg?_nc_cat=102&ccb=1-3&_nc_sid=ac9ee4&_nc_ohc=MmxWXRfJaHMAX8br6nv&_nc_oc=AQn1ODcpzRUrEO2wv-7BIcBI14NX5tBUVTZFxsVt1NkKYqPoe6rv-BGYLNuuVHavTWc&_nc_ad=z-m&_nc_cid=0&_nc_ht=scontent-ssn1-1.xx&oh=c6cbcabfba50be61e225300862d65a8f&oe=60F2061A","width":50}},"cover":{"cover_id":"10156542097347597","offset_x":50,"offset_y":50,"source":"https://scontent-ssn1-1.xx.fbcdn.net/v/t1.6435-9/45007915_10156542097367597_1738263304385593344_n.jpg?_nc_cat=102&ccb=1-3&_nc_sid=1091cb&_nc_ohc=MmxWXRfJaHMAX8br6nv&_nc_oc=AQn1ODcpzRUrEO2wv-7BIcBI14NX5tBUVTZFxsVt1NkKYqPoe6rv-BGYLNuuVHavTWc&_nc_ad=z-m&_nc_cid=0&_nc_ht=scontent-ssn1-1.xx&oh=40b11c92f1afb023a95dd4ab3160ba38&oe=60F04880","id":"10156542097347597"},"icon":"https://static.xx.fbcdn.net/rsrc.php/v3/y8/r/5_2zSM9mMSk.png","updated_time":"2021-07-09T00:04:28+0000","membership_state":"CAN_REQUEST"} -------------------------------------------------------------------------------- /testdata/facebook/models/live_video.json: -------------------------------------------------------------------------------- 1 | {"broadcast_start_time":"2021-06-21T06:31:09+0000","creation_time":"2021-06-21T06:30:32+0000","dash_ingest_url":"https://dashi.facebook.com:443/rtmp/2943409379207540?s_bl=1&s_l=1&s_sw=0&s_vt=api-s&a=AbxityxCyQKc-arJ","dash_preview_url":"https://video-gmp1-1.xx.fbcdn.net/hvideo-rva-atn/_nc_cat-101/v/rFlR7ngWUzdQPWh_bBXrT/pbef-1/_nc_ohc-cHF-EwMoG4UAX8rgkA1/live-dash/dash-abr-ibr-audio/2943409379207540.mpd?_nc_rl=AfB2gax1EmDcDAPYXho&ccb=2-4&ms=m_CTPA&oh=f110abc7f210e03348f2a79c4eb67d15&oe=60FAFA9A","description":"好的 直个播","embed_html":"","id":"2943409379207540","from":{"name":"MyLife","id":"2121008874780932"},"ingest_streams":[{"stream_id":"0","stream_url":"rtmps://live-api-s.facebook.com:443/rtmp/FB-2943409379207540-0-AbwgR2eX7ih5Gogl","secure_stream_url":"rtmps://live-api-s.facebook.com:443/rtmp/FB-2943409379207540-0-AbwgR2eX7ih5Gogl","is_master":true,"dash_preview_url":"https://video-gmp1-1.xx.fbcdn.net/hvideo-rva-atn/_nc_cat-101/v/rFlR7ngWUzdQPWh_bBXrT/pbef-1/_nc_ohc-cHF-EwMoG4UAX8rgkA1/live-dash/dash-abr-ibr-audio/2943409379207540_0.mpd?_nc_rl=AfB2gax1EmDcDAPYmm8&ccb=2-4&ms=m_CTPA&oh=711258bfe66fe1558cad867ec97f3b46&oe=60FADCAE","dash_ingest_url":"https://dashi.facebook.com:443/rtmp/2943409379207540?s_bl=1&s_l=1&s_sw=0&s_vt=api-s&a=AbxityxCyQKc-arJ","stream_health":{"video_bitrate":0,"video_framerate":32.530902862549,"video_gop_size":3333,"video_height":360,"video_width":640,"audio_bitrate":0},"id":"2943409399207538"}],"live_views":0,"overlay_url":"","seconds_left":0,"secure_stream_url":"rtmps://live-api-s.facebook.com:443/rtmp/2943409379207540?s_bl=1&s_psm=1&s_sw=0&s_vt=api-s&a=AbxiwkXdyeQm9XyO","status":"VOD","stream_url":"rtmps://live-api-s.facebook.com:443/rtmp/2943409379207540?s_bl=1&s_psm=1&s_sw=0&s_vt=api-s&a=AbxiwkXdyeQm9XyO","title":"直播","video":{"id":"599128971479230"}} -------------------------------------------------------------------------------- /testdata/facebook/models/message.json: -------------------------------------------------------------------------------- 1 | {"created_time":"2021-07-23T09:50:48+0000","from":{"name":"Kun Liu","email":"2711636948859886@facebook.com","id":"2711636948859886"},"id":"m_ToF35NI1OImBjyUIgplSaBMylUFmkYY4bHogy9C1otLISU6SGhccB5NK-THX_W4EdVQiKVv5SgCW9m-_C78mRA","message":"Love is peace!😏","tags":{"data":[{"name":"inbox"},{"name":"source:mobile"}]},"to":{"data":[{"name":"MyLife","email":"2121008874780932@facebook.com","id":"2121008874780932"}]},"attachments":{"data":[{"id":"651143212510248","mime_type":"image/jpeg","name":"image-651143212510248","size":54542,"image_data":{"width":1920,"height":1213,"max_width":1920,"max_height":1213,"url":"https://scontent-gmp1-1.xx.fbcdn.net/v/t1.15752-9/216389199_651143215843581_1189390911866437382_n.jpg?_nc_cat=107&ccb=1-3&_nc_sid=58c789&_nc_ohc=l-FaTRF4SAMAX8ymGu0&_nc_oc=AQl2J5ZJ67IVxSjZIqw7KXXEFocsvJF3Si52ekiVq201hgNdEnyPULdFgtKJR1voMAs&_nc_ht=scontent-gmp1-1.xx&oh=040e8d09bd33ff37601195402f6595b8&oe=611F7644","preview_url":"https://scontent-gmp1-1.xx.fbcdn.net/v/t1.15752-9/p280x280/216389199_651143215843581_1189390911866437382_n.jpg?_nc_cat=107&ccb=1-3&_nc_sid=58c789&_nc_ohc=l-FaTRF4SAMAX8ymGu0&_nc_oc=AQl2J5ZJ67IVxSjZIqw7KXXEFocsvJF3Si52ekiVq201hgNdEnyPULdFgtKJR1voMAs&_nc_ht=scontent-gmp1-1.xx&oh=4b08d523164ee29619d49d556555caeb&oe=611F63B3","image_type":1,"render_as_sticker":false}}],"paging":{"cursors":{"before":"MAZDZD","after":"MAZDZD"},"next":"https://graph.facebook.com/v10.0/m_ToF35NI1OImBjyUIgplSaBMylUFmkYY4bHogy9C1otLISU6SGhccB5NK-THX_W4EdVQiKVv5SgCW9m-_C78mRA/attachments?access_token=access_token&pretty=0&limit=25&after=MAZDZD"}}} -------------------------------------------------------------------------------- /testdata/facebook/models/page.json: -------------------------------------------------------------------------------- 1 | {"id":"20531316728","about":"The Facebook Page celebrates how our friends inspire us, support us, and help us discover the world when we connect.","can_checkin":true,"checkins":11,"category":"Website","category_list":[{"id":"2202","name":"Website"},{"id":"2200","name":"Company"}],"cover":{"cover_id":"10159027219496729","offset_x":49,"offset_y":50,"source":"https://scontent.xx.fbcdn.net/v/t1.0-9/s720x720/78503930_10159027219516729_2925301529520898048_o.jpg?_nc_cat=1&_nc_oc=AQkWW0ys4cYmU_4TOkGpADUvEKZzBKwKM7JCLAiH1pTku1cJbe59XuPVYomDwPoqKeM&_nc_ht=scontent.xx&oh=e2a487ccd16c26a7d7928d7664a6bb8c&oe=5EAF310D","id":"10159027219496729"},"display_subtext":"11 people checked in here","engagement":{"count":214840680,"social_sentence":"214M people like this."},"fan_count":214840680,"founded":"February 4, 2004","general_info":"Your ideas and suggestions help us to constantly improve Facebook's features. Let us know how we can improve your experience: www.facebook.com/help/feedback\n\nFor Facebook support questions, please visit the help center: https://www.facebook.com/help?ref=facebook_page\n\n","global_brand_root_id":"1499730620315598","global_brand_page_name":"Facebook","link":"https://www.facebook.com/facebookapp/","name":"Facebook","start_info":{"type":"Unspecified","date":{"year":2004,"month":2,"day":4}},"talking_about_count":375302,"username":"facebookapp","verification_status":"blue_verified","website":"http://www.facebook.com","were_here_count":144228,"location":{"city":"Silicon Valley","country":"America","latitude":0,"longitude":1.11,"street":"Hacker Way in Menlo Park","zip":"94025"},"picture":{"data":{"height":50,"is_silhouette":false,"url":"https://scontent-nrt1-1.xx.fbcdn.net/v/t1.6435-1/cp0/p50x50/58978526_10158354585751729_7411073224387067904_n.png?_nc_cat=1&ccb=1-3&_nc_sid=dbb9e7&_nc_ohc=o5boXdilogsAX9-8k_5&_nc_ht=scontent-nrt1-1.xx&tp=30&edm=ABzdmSoEAAAA&oh=6b8421d39eeb42b68482f28550a4856e&oe=60EA1741","width":50}}} -------------------------------------------------------------------------------- /testdata/facebook/models/user.json: -------------------------------------------------------------------------------- 1 | {"picture":{"data":{"height":50,"is_silhouette":false,"url":"https://scontent-nrt1-1.xx.fbcdn.net/v/t1.6435-1/cp0/p50x50/79515135_10111007623880301_5111576226921709568_n.jpg?_nc_cat=1&ccb=1-3&_nc_sid=dbb9e7&_nc_ohc=l-dWADDON4AAX8rVpx5&_nc_ad=z-m&_nc_cid=0&_nc_ht=scontent-nrt1-1.xx&tp=27&oh=400a0d61c2231f684d845e483edf9a66&oe=60EA5582","width":50}},"id":"4","name":"Mark Zuckerberg"} -------------------------------------------------------------------------------- /testdata/facebook/models/video.json: -------------------------------------------------------------------------------- 1 | {"content_category":"TECHNOLOGY","created_time":"2021-06-30T21:19:07+0000","embed_html":"","format":[{"embed_html":"","filter":"130x130","height":130,"picture":"https://scontent-gmp1-1.xx.fbcdn.net/v/t15.5256-10/p130x130/206860283_1192958454550866_3763752339689653487_n.jpg?_nc_cat=110&ccb=1-3&_nc_sid=ad6a45&_nc_ohc=ixtGMgBkA54AX908zT0&_nc_ht=scontent-gmp1-1.xx&oh=0af06b81a5fb02e91c2c76ff259e97da&oe=60FE3A83","width":130},{"embed_html":"","filter":"480x480","height":480,"picture":"https://scontent-gmp1-1.xx.fbcdn.net/v/t15.5256-10/p480x480/206860283_1192958454550866_3763752339689653487_n.jpg?_nc_cat=110&ccb=1-3&_nc_sid=ad6a45&_nc_ohc=ixtGMgBkA54AX908zT0&_nc_ht=scontent-gmp1-1.xx&oh=498c46c3ff6522e446f49a29987641b5&oe=60FE1211","width":480},{"embed_html":"","filter":"720x720","height":720,"picture":"https://scontent-gmp1-1.xx.fbcdn.net/v/t15.5256-10/p720x720/206860283_1192958454550866_3763752339689653487_n.jpg?_nc_cat=110&ccb=1-3&_nc_sid=ad6a45&_nc_ohc=ixtGMgBkA54AX908zT0&_nc_ht=scontent-gmp1-1.xx&oh=a76dac84ce0024e5b045e52d6260fda4&oe=60FD3BF1","width":720},{"embed_html":"","filter":"native","height":1280,"picture":"https://scontent-gmp1-1.xx.fbcdn.net/v/t15.5256-10/206860283_1192958454550866_3763752339689653487_n.jpg?_nc_cat=110&ccb=1-3&_nc_sid=ad6a45&_nc_ohc=ixtGMgBkA54AX908zT0&_nc_ht=scontent-gmp1-1.xx&oh=3ebed0586ad212c8696b305114b8adb8&oe=60FE6A89","width":1280}],"description":"After giving users the ability to quickly and easily share recipes and food-related content to Instagram Stories, recipe and lifestyle site iCook 愛料理 boosted its user retention by 30%. See how iCook reached a broader audience by building a new, intuitive user interface flow and integrating Sharing to Stories: https://fb.me/iCook-Success-Story","embeddable":true,"from":{"name":"Facebook for Developers","id":"19292868552"},"icon":"https://static.xx.fbcdn.net/rsrc.php/v3/yD/r/DggDhA4z4tO.gif","id":"1192957457884299","length":12.891,"picture":"https://scontent-gmp1-1.xx.fbcdn.net/v/t15.5256-10/p160x160/206860283_1192958454550866_3763752339689653487_n.jpg?_nc_cat=110&ccb=1-3&_nc_sid=08861d&_nc_ohc=ixtGMgBkA54AX908zT0&_nc_ht=scontent-gmp1-1.xx&oh=5cdd89b4dd342ee6137842a611b78ff2&oe=60FE3CE7","privacy":{"allow":"","deny":"","description":"Public","friends":"","networks":"","value":"EVERYONE"},"published":true,"status":{"video_status":"ready"},"title":"iCook Success Story","updated_time":"2021-07-20T01:55:06+0000","permalink_url":"/FacebookforDevelopers/videos/1192957457884299/","is_crosspost_video":false,"is_crossposting_eligible":false,"is_episode":false,"is_instagram_eligible":false} -------------------------------------------------------------------------------- /testdata/instagram/apidata/comments/comment_fields.json: -------------------------------------------------------------------------------- 1 | {"id":"17892250648466172","like_count":1,"text":"@ikroskun Hey, guys","timestamp":"2020-02-24T09:15:16+0000","username":"ikroskun"} -------------------------------------------------------------------------------- /testdata/instagram/apidata/comments/comments_fields.json: -------------------------------------------------------------------------------- 1 | {"17892250648466172":{"id":"17892250648466172","like_count":1,"text":"@ikroskun Hey, guys","timestamp":"2020-02-24T09:15:16+0000","username":"ikroskun"},"17858154961981086":{"id":"17858154961981086","like_count":0,"text":"Beautiful!","timestamp":"2020-06-01T10:56:52+0000","username":"lixiangguodu123"}} -------------------------------------------------------------------------------- /testdata/instagram/apidata/comments/replies.json: -------------------------------------------------------------------------------- 1 | {"data":[{"timestamp":"2020-08-07T03:30:06+0000","text":"@lixiangguodu123 nihao","id":"17847314687296283"}]} -------------------------------------------------------------------------------- /testdata/instagram/apidata/discovery/medias_p1.json: -------------------------------------------------------------------------------- 1 | {"business_discovery":{"media":{"data":[{"id":"17885103395504675","caption":"To attract new players, the team behind state_of_survival partnered with quantumuniverse.co and Facebook Creative Shop to build an AR ad in SparkARCreators that transported their audience into the gaming universe. Learn how this campaign, launched across Facebook and Instagram, led to a 49% decrease in cost per install by checking out the link in our bio.","comments_count":11,"like_count":87,"media_type":"IMAGE","media_url":"https://scontent-nrt1-1.cdninstagram.com/v/t51.29350-15/238148161_1969671383189052_5307788044451392664_n.jpg?_nc_cat=106&ccb=1-5&_nc_sid=8ae9d6&_nc_ohc=BTrcVY4Q3qgAX9V2aBL&_nc_ht=scontent-nrt1-1.cdninstagram.com&edm=AL-3X8kEAAAA&oh=fa7360e87ea98772223b8af8b0e2fc8a&oe=6121FCC2","permalink":"https://www.instagram.com/p/CSr71Gzlqo4/","timestamp":"2021-08-17T19:00:42+0000"},{"id":"17886271043461692","caption":"Today, we are excited to announce that developers can now build Instagram messaging experiences for all business accounts! Read more on how to get started and help businesses drive meaningful conversations, increase customer satisfaction, and grow sales. Learn more, link in bio.","comments_count":16,"like_count":186,"media_type":"IMAGE","media_url":"https://scontent-nrt1-1.cdninstagram.com/v/t51.29350-15/237157668_879283769657716_750906017898335050_n.jpg?_nc_cat=102&ccb=1-5&_nc_sid=8ae9d6&_nc_ohc=5MAPD06CY34AX_rUoPy&_nc_ht=scontent-nrt1-1.cdninstagram.com&edm=AL-3X8kEAAAA&oh=a6c5934c78849024c9003f8f3b8a056a&oe=6121DB24","permalink":"https://www.instagram.com/p/CSpNPqgFxE0/","timestamp":"2021-08-16T17:35:10+0000"}],"paging":{"cursors":{"after":"after"}}},"id":"17841407673135339"},"id":"17841406338772941"} -------------------------------------------------------------------------------- /testdata/instagram/apidata/discovery/medias_p2.json: -------------------------------------------------------------------------------- 1 | {"business_discovery":{"media":{"data":[{"id":"17939347456563225","caption":"BathandBodyWorksArabia experienced a sharp 64% increase in messages throughout 2020 and needed to scale their customer communication on social media to provide more efficient customer care. By working with Emplifi to integrate Messenger API for Instagram into their customer relationship management platform, they boosted resolved customer queries by 42% and gained 40% operational time savings. Learn more about this increase in speed and efficiency at the link in our bio.","comments_count":3,"like_count":50,"media_type":"IMAGE","media_url":"https://scontent-nrt1-1.cdninstagram.com/v/t51.2885-15/235506827_360735212272140_8255029507191873372_n.jpg?_nc_cat=104&ccb=1-5&_nc_sid=8ae9d6&_nc_ohc=Jl8feziV6-oAX8jk9Va&_nc_ht=scontent-nrt1-1.cdninstagram.com&edm=AL-3X8kEAAAA&oh=1e101867a5c3a5da35c840b5d408d51a&oe=6121B582","permalink":"https://www.instagram.com/p/CScld93rm4W/","timestamp":"2021-08-11T19:56:42+0000"},{"id":"18165241603086291","caption":"Hosted by Facebook Reality Labs VP Andrew “Boz” Bosworth, Boz to the Future is a new podcast where you’ll hear unscripted thoughts about bleeding-edge technology, entertainment, and beyond from the brightest technologists and business leaders in the industry. Learn more and listen to the first episode, featuring Facebook Reality Labs VP of Operations Rebecca Van Dyck’s perspective on AR glasses, at the link in our bio.","comments_count":5,"like_count":86,"media_type":"VIDEO","media_url":"https://video-nrt1-1.cdninstagram.com/v/t50.2886-16/235725930_272289980901372_6549646165997192955_n.mp4?_nc_cat=102&vs=17958643291464215_1760019067&_nc_vs=HBksFQAYJEdHcmtEQTc4WjVaenBmY0FBUHNHdzRoOEJPVmFia1lMQUFBRhUAAsgBABUAGCRHRnZHREE2UzZVRkVBc0FPQUp5dEo2d1FKNHQ0YmtZTEFBQUYVAgLIAQAoABgAGwGIB3VzZV9vaWwBMRUAACai6Jbl8PTHPxUCKAJDMywXQECd0vGp%2B%2BcYEmRhc2hfYmFzZWxpbmVfMl92MREAdeoHAA%3D%3D&ccb=1-5&_nc_sid=59939d&efg=eyJ2ZW5jb2RlX3RhZyI6InZ0c192b2RfdXJsZ2VuLjcyMC5mZWVkIn0%3D&_nc_ohc=wjsWHUp6JkcAX_QX_YY&_nc_ht=video-nrt1-1.cdninstagram.com&edm=AL-3X8kEAAAA&oh=a5c8f4032a2d94e52ae2c58f986f2405&oe=611DBAF5&_nc_rid=0511d8da9e","permalink":"https://www.instagram.com/p/CSZsJf-iJLj/","timestamp":"2021-08-10T16:57:42+0000"}],"paging":{"cursors":{"before":"before","after":"after"}}},"id":"17841407673135339"},"id":"17841406338772941"} -------------------------------------------------------------------------------- /testdata/instagram/apidata/discovery/user_fields.json: -------------------------------------------------------------------------------- 1 | {"business_discovery":{"id":"17841407673135339","biography":"Follow us for updates on Facebook’s business tools, AI, AR, VR, and more.","name":"Facebook for Developers","username":"facebookfordevelopers","profile_picture_url":"https://scontent-nrt1-1.xx.fbcdn.net/v/t51.2885-15/119360396_354046192452293_1644353770392407160_n.jpg?_nc_cat=105&ccb=1-5&_nc_sid=86c713&_nc_ohc=c7heFMXxydUAX8iS-Tz&_nc_ht=scontent-nrt1-1.xx&edm=AL-3X8kEAAAA&oh=0153ca5bef8f08d3f7b693a7e3b30919&oe=61218964","followers_count":64976,"media_count":436},"id":"17841406338772941"} -------------------------------------------------------------------------------- /testdata/instagram/apidata/hashtags/hashtag_info.json: -------------------------------------------------------------------------------- 1 | {"id":"17843826142012701","name":"love"} -------------------------------------------------------------------------------- /testdata/instagram/apidata/hashtags/hashtag_recent_medias_p1.json: -------------------------------------------------------------------------------- 1 | {"data":[{"id":"18088158883149835","media_type":"IMAGE","comments_count":8,"like_count":804},{"id":"17842849828991925","media_type":"IMAGE","comments_count":44,"like_count":1430},{"id":"17859234943725739","media_type":"IMAGE","comments_count":6,"like_count":448},{"id":"17846072587933764","media_type":"IMAGE","comments_count":57,"like_count":502},{"id":"17892931315460101","media_type":"IMAGE","comments_count":12,"like_count":165}],"paging":{"cursors":{"after":"after"},"next":"https://graph.facebook.com/v4.0/17843826142012701/top_media?access_token=access_token&pretty=0&fields=id%2Cmedia_type%2Ccomments_count%2Clike_count&user_id=17841406338772941&limit=5&after=after"}} -------------------------------------------------------------------------------- /testdata/instagram/apidata/hashtags/hashtag_recent_medias_p2.json: -------------------------------------------------------------------------------- 1 | {"data":[{"id":"17863800889667054","media_type":"IMAGE","comments_count":41,"like_count":1047},{"id":"17847193954922857","media_type":"IMAGE","comments_count":4,"like_count":123},{"id":"17867664274619039","media_type":"IMAGE","comments_count":0,"like_count":125},{"id":"17860934008722964","media_type":"IMAGE","comments_count":1,"like_count":134},{"id":"18042160858239311","media_type":"IMAGE","comments_count":4,"like_count":210}]} -------------------------------------------------------------------------------- /testdata/instagram/apidata/hashtags/hashtags_info.json: -------------------------------------------------------------------------------- 1 | {"17843826142012701":{"id":"17843826142012701","name":"love"},"17841593698074073":{"id":"17841593698074073","name":"coke"}} -------------------------------------------------------------------------------- /testdata/instagram/apidata/medias/children.json: -------------------------------------------------------------------------------- 1 | {"data":[{"id":"17924318443748703","media_type":"IMAGE","media_url":"https://scontent-gmp1-1.cdninstagram.com/v/t51.29350-15/238842780_431842228076532_285672932901447316_n.jpg?_nc_cat=104&ccb=1-5&_nc_sid=8ae9d6&_nc_ohc=YkeziMXugxcAX_HDz-M&_nc_ht=scontent-gmp1-1.cdninstagram.com&edm=APY2UpUEAAAA&oh=18cff7d8374e4520e572050cc3611e37&oe=6123C4B2","permalink":"https://www.instagram.com/p/CSwAtwOBwh-/","shortcode":"CSwAtwOBwh-","timestamp":"2021-08-19T09:00:21+0000"},{"id":"18248754847048313","media_type":"IMAGE","media_url":"https://scontent-gmp1-1.cdninstagram.com/v/t51.29350-15/240249662_1929724190516344_2248941927418162358_n.jpg?_nc_cat=102&ccb=1-5&_nc_sid=8ae9d6&_nc_ohc=nkr9PUWVhSAAX-D39_W&_nc_ht=scontent-gmp1-1.cdninstagram.com&edm=APY2UpUEAAAA&oh=39ccd6c92f4af02c0c26a911c00f902b&oe=612444D5","permalink":"https://www.instagram.com/p/CSwAtwPB1po/","shortcode":"CSwAtwPB1po","timestamp":"2021-08-19T09:00:21+0000"}]} -------------------------------------------------------------------------------- /testdata/instagram/apidata/medias/comments_p1.json: -------------------------------------------------------------------------------- 1 | {"data":[{"timestamp":"2020-06-01T10:56:52+0000","text":"Beautiful!","id":"17858154961981086"},{"timestamp":"2020-06-01T10:16:39+0000","text":"Beautiful!","id":"17874875428706419"}],"paging":{"cursors":{"after":"after"},"next":"https://graph.facebook.com/v11.0/17846368219941692/comments?access_token=access_token&pretty=0&limit=2&after=after"}} -------------------------------------------------------------------------------- /testdata/instagram/apidata/medias/comments_p2.json: -------------------------------------------------------------------------------- 1 | {"data":[{"timestamp":"2020-02-24T09:15:16+0000","text":"@ikroskun Hey, guys","id":"17892250648466172"},{"timestamp":"2020-02-24T09:11:00+0000","text":"@ikroskun","id":"17914413430382429"}]} -------------------------------------------------------------------------------- /testdata/instagram/apidata/medias/insights.json: -------------------------------------------------------------------------------- 1 | {"data":[{"name":"impressions","period":"lifetime","values":[{"value":8}],"title":"Impressions","description":"Total number of times the media object has been seen","id":"17846368219941692/insights/impressions/lifetime"},{"name":"reach","period":"lifetime","values":[{"value":5}],"title":"Reach","description":"Total number of unique accounts that have seen the media object","id":"17846368219941692/insights/reach/lifetime"},{"name":"saved","period":"lifetime","values":[{"value":0}],"title":"Saved","description":"Total number of unique accounts that have saved the media object","id":"17846368219941692/insights/saved/lifetime"}]} -------------------------------------------------------------------------------- /testdata/instagram/apidata/medias/insights_new.json: -------------------------------------------------------------------------------- 1 | {"data":[{"name":"profile_activity","period":"lifetime","values":[{"value":11}],"title":"Profile activity","description":"[IG Insights] This header is the name of a metric that appears on an educational info sheet for a particular for a particular post, story, video or promotion. This metric is the sum of all profile actions people take when they engage with this content.","total_value":{"value":11,"breakdowns":[{"dimension_keys":["action_type"],"results":[{"dimension_values":["bio_link_clicked"],"value":11}]}]},"id":"18035507131611621/insights/profile_activity/lifetime"}]} -------------------------------------------------------------------------------- /testdata/instagram/apidata/medias/media_default.json: -------------------------------------------------------------------------------- 1 | {"id":"17896129349106152","caption":"ALBUM","comments_count":0,"children":{"data":[{"id":"17889214265226770","media_type":"IMAGE","media_url":"https://scontent-gmp1-1.cdninstagram.com/v/t51.29350-15/223646625_250720926614889_6557630912345090634_n.jpg?_nc_cat=101&ccb=1-3&_nc_sid=8ae9d6&_nc_ohc=RIospDWMxD0AX94rqon&_nc_ht=scontent-gmp1-1.cdninstagram.com&oh=436c0a1a131d409b86582e8873eb177f&oe=6104320C","permalink":"https://www.instagram.com/p/CRyZpjhDO_k/","shortcode":"CRyZpjhDO_k","timestamp":"2021-07-26T10:45:19+0000"},{"id":"17886719108286032","media_type":"IMAGE","media_url":"https://scontent-gmp1-1.cdninstagram.com/v/t51.29350-15/223792850_4185486154879355_5499910575994647858_n.jpg?_nc_cat=111&ccb=1-3&_nc_sid=8ae9d6&_nc_ohc=TVSC3pTlZyYAX8z2kdT&_nc_ht=scontent-gmp1-1.cdninstagram.com&oh=8b51ae769a0a97a3cb20f91aa1a0c98f&oe=6102D64F","permalink":"https://www.instagram.com/p/CRyZpjiDYZr/","shortcode":"CRyZpjiDYZr","timestamp":"2021-07-26T10:45:19+0000"},{"id":"17904922598025487","media_type":"VIDEO","media_url":"https://video-gmp1-1.cdninstagram.com/v/t50.2886-16/223134763_874765663125519_5500383597745008488_n.mp4?_nc_cat=105&vs=17911163905845045_2907163543&_nc_vs=HBksFQAYJEdDdkVUQTBQd0p4QW1Cc0RBR2p2X1dlOVNWVk1ia1lMQUFBRhUAAsgBABUAGCRHTU9kYUEzV183MUFfRW9CQUpLMkotbVZMNzRlYmtZTEFBQUYVAgLIAQAoABgAGwGIB3VzZV9vaWwBMRUAACagrJGghYPAPxUCKAJDMywXQCS7ZFocrAgYEmRhc2hfYmFzZWxpbmVfMV92MREAde4HAA%3D%3D&ccb=1-3&_nc_sid=59939d&efg=eyJ2ZW5jb2RlX3RhZyI6InZ0c192b2RfdXJsZ2VuLjcyMC5jYXJvdXNlbF9pdGVtIn0%3D&_nc_ohc=5haQLoGcZzMAX_IuBS1&_nc_ht=video-gmp1-1.cdninstagram.com&oh=6fd99d63ec8b2bbdf1d03d4fb3acbf27&oe=60FF140E&_nc_rid=49dd1397e9","permalink":"https://www.instagram.com/p/CRyZoh5DX9y/","shortcode":"CRyZoh5DX9y","thumbnail_url":"https://scontent-gmp1-1.cdninstagram.com/v/t51.29350-15/225731613_806163340088077_7428079101980405091_n.jpg?_nc_cat=105&ccb=1-3&_nc_sid=8ae9d6&_nc_ohc=YhpMeiv1C6AAX8L75b9&_nc_ht=scontent-gmp1-1.cdninstagram.com&oh=9c0ea92b5ffef223535fdd1d00f91833&oe=61038D3E","timestamp":"2021-07-26T10:45:19+0000"}]},"like_count":1,"media_type":"CAROUSEL_ALBUM","media_url":"https://scontent-gmp1-1.cdninstagram.com/v/t51.29350-15/223646625_250720926614889_6557630912345090634_n.jpg?_nc_cat=101&ccb=1-3&_nc_sid=8ae9d6&_nc_ohc=RIospDWMxD0AX94rqon&_nc_ht=scontent-gmp1-1.cdninstagram.com&oh=436c0a1a131d409b86582e8873eb177f&oe=6104320C","permalink":"https://www.instagram.com/p/CRyZpmrjYC4/","timestamp":"2021-07-26T10:45:20+0000"} -------------------------------------------------------------------------------- /testdata/instagram/apidata/medias/product_tags.json: -------------------------------------------------------------------------------- 1 | {"data":[{"product_id":3231775643511089,"merchant_id":90010177253934,"name":"Gummy Bears","price_string":"$3.50","image_url":"https://scont...","review_status":"approved","is_checkout":true,"stripped_price_string":"$3.50","stripped_sale_price_string":"$3","x":0.5,"y":0.80000001192093}]} -------------------------------------------------------------------------------- /testdata/instagram/apidata/publish/container_info.json: -------------------------------------------------------------------------------- 1 | {"id":"17966279578433554","status":"Finished: Media has been uploaded and it is ready to be published.","status_code":"FINISHED"} -------------------------------------------------------------------------------- /testdata/instagram/apidata/publish/containers_info.json: -------------------------------------------------------------------------------- 1 | {"17883019676403955":{"id":"17883019676403955","status":"Finished: Media has been uploaded and it is ready to be published.","status_code":"FINISHED"},"17966279578433554":{"id":"17966279578433554","status":"Finished: Media has been uploaded and it is ready to be published.","status_code":"FINISHED"}} -------------------------------------------------------------------------------- /testdata/instagram/apidata/publish/create_photo.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": "17889455560051444" 3 | } 4 | -------------------------------------------------------------------------------- /testdata/instagram/apidata/publish/create_video.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": "17889455560051447" 3 | } -------------------------------------------------------------------------------- /testdata/instagram/apidata/publish/publish_container.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": "17920238422030506" 3 | } -------------------------------------------------------------------------------- /testdata/instagram/apidata/publish/publish_limit_resp.json: -------------------------------------------------------------------------------- 1 | { 2 | "data": [ 3 | { 4 | "quota_usage": 0, 5 | "config": { 6 | "quota_total": 25, 7 | "quota_duration": 86400 8 | } 9 | } 10 | ] 11 | } -------------------------------------------------------------------------------- /testdata/instagram/apidata/stories/stories_default.json: -------------------------------------------------------------------------------- 1 | { 2 | "data": [ 3 | { 4 | "id": "18168273289049440", 5 | "media_type": "IMAGE", 6 | "media_url": "https://scontent-lax3-1.cdninstagram.com/v/t51.29350-15/121708333_386771855845543_6575258531100040471_n.jpg?_nc_cat=104&_nc_sid=8ae9d6&_nc_ohc=OiYQXK0Sv_8AX-wIw_m&_nc_ht=scontent-lax3-1.cdninstagram.com&oh=c114e910054071345f72299d6160a05e&oe=5FB11AF1", 7 | "owner": { 8 | "id": "17841406338772941" 9 | }, 10 | "permalink": "https://instagram.com/stories/ikroskun/2421239445800645437", 11 | "shortcode": "CGZ-HKbHHM9", 12 | "timestamp": "2020-10-16T13:17:24+0000", 13 | "username": "ikroskun", 14 | "ig_id": "2421239445800645437" 15 | }, 16 | { 17 | "caption": "厉害了", 18 | "id": "17876166859931045", 19 | "media_type": "IMAGE", 20 | "media_url": "https://scontent-lax3-2.cdninstagram.com/v/t51.29350-15/121615854_883056945566047_6781892595954855821_n.jpg?_nc_cat=107&_nc_sid=8ae9d6&_nc_ohc=s4IkJZrN5tMAX-ZXOkx&_nc_ht=scontent-lax3-2.cdninstagram.com&oh=a33201c524d3d0513e07ca38368b5239&oe=5FAE3DD1", 21 | "owner": { 22 | "id": "17841406338772941" 23 | }, 24 | "permalink": "https://instagram.com/stories/ikroskun/2421224614649404224", 25 | "shortcode": "CGZ6vV1nBtA", 26 | "timestamp": "2020-10-16T12:48:02+0000", 27 | "username": "ikroskun", 28 | "ig_id": "2421224614649404224" 29 | }, 30 | { 31 | "id": "17967354091336995", 32 | "media_type": "IMAGE", 33 | "media_url": "https://scontent-lax3-1.cdninstagram.com/v/t51.29350-15/121514510_195085092135371_1213977306340103108_n.jpg?_nc_cat=109&_nc_sid=8ae9d6&_nc_ohc=jmgZ3vpHKQ0AX83P1n6&_nc_ht=scontent-lax3-1.cdninstagram.com&oh=ee0c7672593bfdf3c9dde1d5b95220d7&oe=5FAD8F9C", 34 | "owner": { 35 | "id": "17841406338772941" 36 | }, 37 | "permalink": "https://instagram.com/stories/ikroskun/2421224077929597220", 38 | "shortcode": "CGZ6nh-nckk", 39 | "timestamp": "2020-10-16T12:46:57+0000", 40 | "username": "ikroskun", 41 | "ig_id": "2421224077929597220" 42 | } 43 | ], 44 | "paging": { 45 | "cursors": { 46 | "before": "before" 47 | } 48 | } 49 | } -------------------------------------------------------------------------------- /testdata/instagram/apidata/stories/stories_fields_p1.json: -------------------------------------------------------------------------------- 1 | { 2 | "data": [ 3 | { 4 | "id": "18168273289049440", 5 | "media_type": "IMAGE", 6 | "media_url": "https://scontent-lax3-1.cdninstagram.com/v/t51.29350-15/121708333_386771855845543_6575258531100040471_n.jpg?_nc_cat=104&_nc_sid=8ae9d6&_nc_ohc=OiYQXK0Sv_8AX-wIw_m&_nc_ht=scontent-lax3-1.cdninstagram.com&oh=c114e910054071345f72299d6160a05e&oe=5FB11AF1", 7 | "username": "ikroskun" 8 | }, 9 | { 10 | "id": "17876166859931045", 11 | "media_type": "IMAGE", 12 | "media_url": "https://scontent-lax3-2.cdninstagram.com/v/t51.29350-15/121615854_883056945566047_6781892595954855821_n.jpg?_nc_cat=107&_nc_sid=8ae9d6&_nc_ohc=s4IkJZrN5tMAX-ZXOkx&_nc_ht=scontent-lax3-2.cdninstagram.com&oh=a33201c524d3d0513e07ca38368b5239&oe=5FAE3DD1", 13 | "username": "ikroskun" 14 | } 15 | ], 16 | "paging": { 17 | "cursors": { 18 | "before": "before", 19 | "after": "after" 20 | }, 21 | "next": "https://graph.facebook.com/v8.0/17841406338772941/stories?access_token=token&pretty=0&fields=id%2Cmedia_type%2Cmedia_url%2Cusername&limit=2&after=after" 22 | } 23 | } -------------------------------------------------------------------------------- /testdata/instagram/apidata/stories/stories_fields_p2.json: -------------------------------------------------------------------------------- 1 | { 2 | "data": [ 3 | { 4 | "id": "17967354091336995", 5 | "media_type": "IMAGE", 6 | "media_url": "https://scontent-lax3-1.cdninstagram.com/v/t51.29350-15/121514510_195085092135371_1213977306340103108_n.jpg?_nc_cat=109&_nc_sid=8ae9d6&_nc_ohc=jmgZ3vpHKQ0AX83P1n6&_nc_ht=scontent-lax3-1.cdninstagram.com&oh=ee0c7672593bfdf3c9dde1d5b95220d7&oe=5FAD8F9C", 7 | "username": "ikroskun" 8 | } 9 | ], 10 | "paging": { 11 | "cursors": { 12 | "before": "before" 13 | }, 14 | "previous": "https://graph.facebook.com/v8.0/17841406338772941/stories?access_token=EAACsqT7rCzQBAF5Bo7A8EbwpqyXOUCmezKdLadZB1y0POZBePcQOOX1cEaGPnnQnueAzjiftvQUcHMkOrAULrzWR9jd5SMb54O1cOdO6uQr0qlh0SZCUjmN90P63ieD2yKDFgertOnAuk6ZAHxV54ZC8B3xLslhZAENNMMbq3SL296HZCOx2so3Neo4UiHIlyegOmyDGKF3SgZDZD&pretty=0&fields=id%2Cmedia_type%2Cmedia_url%2Cusername&limit=2&before=QVFIUlVLY0hmQ2NjMDlXNVlOd0RqOUZA3bHh0N0N3dVVQSGUzcUJnN3VPbllCSG02bk4waUJPN3pjd0ZA0eldIakp4YWRWUUR1VGVyWnA0TVc3WFNFSUFwV3J3" 15 | } 16 | } -------------------------------------------------------------------------------- /testdata/instagram/apidata/stories/stories_info.json: -------------------------------------------------------------------------------- 1 | { 2 | "17876166859931045": { 3 | "id": "17876166859931045", 4 | "media_type": "IMAGE", 5 | "media_url": "https://scontent-lax3-2.cdninstagram.com/v/t51.29350-15/121615854_883056945566047_6781892595954855821_n.jpg?_nc_cat=107&_nc_sid=8ae9d6&_nc_ohc=s4IkJZrN5tMAX-ZXOkx&_nc_ht=scontent-lax3-2.cdninstagram.com&oh=a33201c524d3d0513e07ca38368b5239&oe=5FAE3DD1", 6 | "username": "ikroskun", 7 | "caption": "Nice", 8 | "ig_id": "2421224614649404224", 9 | "owner": { 10 | "id": "17841406338772941" 11 | }, 12 | "permalink": "https://instagram.com/stories/ikroskun/2421224614649404224", 13 | "shortcode": "CGZ6vV1nBtA", 14 | "timestamp": "2020-10-16T12:48:02+0000" 15 | }, 16 | "18168273289049440": { 17 | "id": "18168273289049440", 18 | "media_type": "IMAGE", 19 | "media_url": "https://scontent-lax3-1.cdninstagram.com/v/t51.29350-15/121708333_386771855845543_6575258531100040471_n.jpg?_nc_cat=104&_nc_sid=8ae9d6&_nc_ohc=OiYQXK0Sv_8AX-wIw_m&_nc_ht=scontent-lax3-1.cdninstagram.com&oh=c114e910054071345f72299d6160a05e&oe=5FB11AF1", 20 | "username": "ikroskun", 21 | "ig_id": "2421239445800645437", 22 | "owner": { 23 | "id": "17841406338772941" 24 | }, 25 | "permalink": "https://instagram.com/stories/ikroskun/2421239445800645437", 26 | "shortcode": "CGZ-HKbHHM9", 27 | "timestamp": "2020-10-16T13:17:24+0000" 28 | } 29 | } -------------------------------------------------------------------------------- /testdata/instagram/apidata/stories/story_info.json: -------------------------------------------------------------------------------- 1 | { 2 | "caption": "Nice", 3 | "id": "17876166859931045", 4 | "media_type": "IMAGE", 5 | "media_url": "https://scontent-lax3-2.cdninstagram.com/v/t51.29350-15/121615854_883056945566047_6781892595954855821_n.jpg?_nc_cat=107&_nc_sid=8ae9d6&_nc_ohc=s4IkJZrN5tMAX-ZXOkx&_nc_ht=scontent-lax3-2.cdninstagram.com&oh=a33201c524d3d0513e07ca38368b5239&oe=5FAE3DD1", 6 | "owner": { 7 | "id": "17841406338772941" 8 | }, 9 | "permalink": "https://instagram.com/stories/ikroskun/2421224614649404224", 10 | "shortcode": "CGZ6vV1nBtA", 11 | "timestamp": "2020-10-16T12:48:02+0000", 12 | "username": "ikroskun", 13 | "ig_id": "2421224614649404224" 14 | } -------------------------------------------------------------------------------- /testdata/instagram/apidata/users/available_catalogs.json: -------------------------------------------------------------------------------- 1 | {"data":[{"catalog_id":"960179311066902","catalog_name":"Jay's Favorite Snacks","shop_name":"Jay's Bespoke","product_count":11}]} -------------------------------------------------------------------------------- /testdata/instagram/apidata/users/catalog_product_search.json: -------------------------------------------------------------------------------- 1 | {"data":[{"product_id":3231775643511089,"merchant_id":90010177253934,"product_name":"Gummy Wombats","image_url":"https://scont...","retailer_id":"oh59p9vzei","review_status":"approved","is_checkout_flow":true,"product_variants":[{"product_id":5209223099160494},{"product_id":7478222675582505,"variant_name":"Green Gummy Wombats"}]}]} -------------------------------------------------------------------------------- /testdata/instagram/apidata/users/content_publish_limit.json: -------------------------------------------------------------------------------- 1 | {"data":[{"config":{"quota_total":25,"quota_duration":86400},"quota_usage":0}]} -------------------------------------------------------------------------------- /testdata/instagram/apidata/users/hashtag_search.json: -------------------------------------------------------------------------------- 1 | {"data":[{"id":"17841562426109234","name":"developers"}]} -------------------------------------------------------------------------------- /testdata/instagram/apidata/users/live_medias.json: -------------------------------------------------------------------------------- 1 | {"data":[{"id":"90010498116233","media_type":"BROADCAST","media_product_type":"LIVE","owner":{"id":"17841405822304914"},"username":"jayposiris"}]} -------------------------------------------------------------------------------- /testdata/instagram/apidata/users/medias_p1.json: -------------------------------------------------------------------------------- 1 | {"data":[{"id":"17895731045244887","comments_count":0,"like_count":0,"media_type":"IMAGE","media_url":"https://scontent-gmp1-1.cdninstagram.com/v/t51.29350-15/235924128_269317301288861_6602043128777306709_n.jpg?_nc_cat=108&ccb=1-5&_nc_sid=8ae9d6&_nc_ohc=CA_7VSXzSfAAX8ovZJz&_nc_ht=scontent-gmp1-1.cdninstagram.com&edm=AM6HXa8EAAAA&oh=1fa7eb75ca61eeb68e6742b5db7cd725&oe=61227755","permalink":"https://www.instagram.com/p/CSgf9BChwVq/","timestamp":"2021-08-13T08:25:28+0000"},{"id":"17896622936197745","comments_count":6,"like_count":2,"media_type":"IMAGE","media_url":"https://scontent-gmp1-1.cdninstagram.com/v/t51.29350-15/236077088_652879405685744_7276777012487237107_n.jpg?_nc_cat=100&ccb=1-5&_nc_sid=8ae9d6&_nc_ohc=1CGEsODmcDMAX-XtDGI&_nc_ht=scontent-gmp1-1.cdninstagram.com&oh=b9a25bbd93202c4889cf369509849fd8&oe=6122F948","permalink":"https://www.instagram.com/p/CSgdWACBeKr/","timestamp":"2021-08-13T08:02:40+0000"}],"paging":{"cursors":{"before":"before","after":"after"},"next":"https://graph.facebook.com/v6.0/17841406338772941/media?access_token=access_token&pretty=0&fields=id%2Ccaption%2Ccomments_count%2Cchildren%7Bid%2Cmedia_type%2Cmedia_url%2Cpermalink%2Cshortcode%2Cthumbnail_url%2Ctimestamp%7D%2Clike_count%2Cmedia_type%2Cmedia_url%2Cpermalink%2Ctimestamp&limit=2&after=after"}} -------------------------------------------------------------------------------- /testdata/instagram/apidata/users/mentioned_comment.json: -------------------------------------------------------------------------------- 1 | {"mentioned_comment":{"id":"17967008497439572","like_count":0,"text":"@ikroskun good","timestamp":"2021-08-19T09:14:16+0000","username":"ikroskun"},"id":"17841406338772941"} -------------------------------------------------------------------------------- /testdata/instagram/apidata/users/mentioned_media.json: -------------------------------------------------------------------------------- 1 | {"mentioned_media":{"caption":"@ikroskun hey","comments_count":0,"id":"17889114512354744","like_count":0,"media_type":"CAROUSEL_ALBUM","media_url":"https://scontent-gmp1-1.cdninstagram.com/v/t51.29350-15/238842780_431842228076532_285672932901447316_n.jpg?_nc_cat=104&ccb=1-5&_nc_sid=8ae9d6&_nc_ohc=YkeziMXugxcAX_HDz-M&_nc_ht=scontent-gmp1-1.cdninstagram.com&edm=AL-3X8kEAAAA&oh=d6069a8aa43b894e3ca2c29823cbf494&oe=6123C4B2","timestamp":"2021-08-19T09:00:22+0000"},"id":"17841406338772941"} -------------------------------------------------------------------------------- /testdata/instagram/apidata/users/product_appeal.json: -------------------------------------------------------------------------------- 1 | {"data":[{"product_id":4029274203846188,"review_status":"approved","eligible_for_appeal":false}]} -------------------------------------------------------------------------------- /testdata/instagram/apidata/users/recently_searched_hashtags.json: -------------------------------------------------------------------------------- 1 | {"data":[{"id":"17841562426109234","name":"developers"},{"id":"17842331632070897","name":"facebook"}],"paging":{"cursors":{"before":"before","after":"after"}}} -------------------------------------------------------------------------------- /testdata/instagram/apidata/users/stories.json: -------------------------------------------------------------------------------- 1 | {"data":[{"id":"17879450117512729","comments_count":0,"like_count":0,"media_type":"IMAGE","media_url":"https://scontent-gmp1-1.cdninstagram.com/v/t51.29350-15/239170560_884540045477754_8149242837918435927_n.jpg?_nc_cat=101&ccb=1-5&_nc_sid=8ae9d6&_nc_ohc=5amgjLQF5JsAX9BGXm9&_nc_oc=AQmjiyfR8Yw35A9EXq9nJFEI4ZL6tx-f2eEQ4921_kWeXziMSR5z_2292OXujeSMnFw&_nc_ht=scontent-gmp1-1.cdninstagram.com&edm=AB9oSrcEAAAA&oh=3119da16d24375928e6740230e927b7a&oe=6122D39D","permalink":"https://instagram.com/stories/ikroskun/2643655939345226184","timestamp":"2021-08-19T10:19:23+0000"},{"id":"17915641402913538","comments_count":0,"like_count":0,"media_type":"VIDEO","media_url":"https://scontent-gmp1-1.cdninstagram.com/v/t66.30100-6/52726246_906436830310381_3858848314086903731_n.mp4?_nc_cat=109&vs=296832558879742_660639504&_nc_vs=HBksFQAYJEdPYUpKQVB0TDBoRlpqZ0RBTFBQUTdzWVlvMDFicFIxQUFBRhUAAsgBABUAGCRHQ0hRUnc0bEFlOGxlczBBQUJ0ZmFzb1BYZUpLYnBrd0FBQUYVAgLIAQAoABgAGwGIB3VzZV9vaWwBMRUAACbg6LyD4JPWPxUCKAJDMywXP83S8an7520YHGRhc2hfY29udHJvbC1iLWJhc2VsaW5lXzFfdjERAHXoBwA%3D&ccb=1-5&_nc_sid=59939d&efg=eyJ2ZW5jb2RlX3RhZyI6InZ0c192b2RfdXJsZ2VuLjcyMC5zdG9yeSJ9&_nc_ohc=siI709mTMIsAX8aZjG0&_nc_ht=scontent-gmp1-1.cdninstagram.com&edm=AB9oSrcEAAAA&oh=c00fb62f23d68ba8003f34b61d3785f5&oe=6123EC30&_nc_rid=d4cfda8ff3","permalink":"https://instagram.com/stories/ikroskun/2643655802191568467","timestamp":"2021-08-19T10:19:03+0000"}],"paging":{"cursors":{"before":"before","after":"after"}}} -------------------------------------------------------------------------------- /testdata/instagram/apidata/users/tagged_medias.json: -------------------------------------------------------------------------------- 1 | {"data":[{"id":"17892354025952911","caption":"publish test","comments_count":0,"like_count":2,"media_type":"IMAGE","media_url":"https://scontent-gmp1-1.cdninstagram.com/v/t51.2885-15/160393555_1629232897276954_4054076655285956826_n.jpg?_nc_cat=103&ccb=1-5&_nc_sid=8ae9d6&_nc_ohc=LJs4HypzNscAX9JBhd_&_nc_ht=scontent-gmp1-1.cdninstagram.com&edm=AJ7ooaQEAAAA&oh=b035baee21f6555323b77b2cf2c6c41a&oe=61234E02","permalink":"https://www.instagram.com/p/CMeo7rcJvTi/","timestamp":"2021-03-16T12:02:14+0000"},{"id":"17997587032316367","caption":"Cat test","comments_count":0,"like_count":0,"media_type":"IMAGE","media_url":"https://scontent-gmp1-1.cdninstagram.com/v/t51.29350-15/160142776_895867167918229_5728428669686108280_n.jpg?_nc_cat=110&ccb=1-5&_nc_sid=8ae9d6&_nc_ohc=ljCDz8BbwpAAX8p3pBO&_nc_oc=AQl4ToDpSyZHuKovXw3vusS3mjjRSgNr1Cb83SyPf3xdXyZ4iY3tHZB-ie3EXz-ABKU&_nc_ht=scontent-gmp1-1.cdninstagram.com&edm=AJ7ooaQEAAAA&oh=bb8dbf742b796e2a31a4546c88527e66&oe=61239B2B","permalink":"https://www.instagram.com/p/CMePrHWHOtz/","timestamp":"2021-03-16T08:16:22+0000"},{"id":"17846368219941692","caption":"Cute.. #cute #loveyou @ikroskun","comments_count":6,"like_count":3,"media_type":"IMAGE","media_url":"https://scontent-gmp1-1.cdninstagram.com/v/t51.2885-15/84867683_142798393480123_5890942139025635916_n.jpg?_nc_cat=102&ccb=1-5&_nc_sid=8ae9d6&_nc_ohc=AqSVuKMH3yYAX9OUlti&_nc_ht=scontent-gmp1-1.cdninstagram.com&edm=AJ7ooaQEAAAA&oh=2cb8d409ac970e9a45604c2d6b88f922&oe=61226810","permalink":"https://www.instagram.com/p/B8gQCApHMT-/","timestamp":"2020-02-13T10:35:40+0000"},{"id":"17913531439230186","caption":"The Weather is great","comments_count":3,"like_count":5,"media_type":"IMAGE","media_url":"https://scontent-gmp1-1.cdninstagram.com/v/t51.2885-15/42707376_341018063313398_2919878309467197014_n.jpg?_nc_cat=100&ccb=1-5&_nc_sid=8ae9d6&_nc_ohc=66N4dcRplBAAX_K22lb&_nc_ht=scontent-gmp1-1.cdninstagram.com&edm=AJ7ooaQEAAAA&oh=f0e04ef44b1dbef8c41a67f5ab158701&oe=6122DA32","permalink":"https://www.instagram.com/p/Bop3AGOASfY/","timestamp":"2018-10-08T01:41:29+0000"},{"id":"17978630677077508","comments_count":1,"like_count":7,"media_type":"IMAGE","media_url":"https://scontent-gmp1-1.cdninstagram.com/v/t51.2885-15/42135250_247254675937951_7313884711181683455_n.jpg?_nc_cat=103&ccb=1-5&_nc_sid=8ae9d6&_nc_ohc=yWbaoaJ9lNoAX9i2NjA&_nc_ht=scontent-gmp1-1.cdninstagram.com&edm=AJ7ooaQEAAAA&oh=b40f786ccd1948cd40dae8b352a3706e&oe=6123164F","permalink":"https://www.instagram.com/p/BotSABoAn8E/","timestamp":"2018-10-09T09:35:07+0000"}]} -------------------------------------------------------------------------------- /testdata/instagram/apidata/users/user_fields.json: -------------------------------------------------------------------------------- 1 | {"id":"17841407673135339","biography":"Follow us for updates on Facebook’s business tools, AI, AR, VR, and more.","name":"Facebook for Developers","username":"facebookfordevelopers","profile_picture_url":"https://scontent-gmp1-1.xx.fbcdn.net/v/t51.2885-15/119360396_354046192452293_1644353770392407160_n.jpg?_nc_cat=105&ccb=1-3&_nc_sid=86c713&_nc_ohc=weehPiTrz7gAX-2nuLB&_nc_ht=scontent-gmp1-1.xx&oh=adbdbbae0d2429397e0881da942b9b6a&oe=6103DFA4","followers_count":64363,"media_count":427} -------------------------------------------------------------------------------- /testdata/instagram/apidata/users/user_insights.json: -------------------------------------------------------------------------------- 1 | {"data":[{"name":"impressions","period":"day","values":[{"value":4,"end_time":"2017-05-04T07:00:00+0000"},{"value":66,"end_time":"2017-05-05T07:00:00+0000"}],"title":"Impressions","description":"Total number of times this profile has been seen","id":"17841400008460056/insights/impressions/day"},{"name":"reach","period":"day","values":[{"value":3,"end_time":"2017-05-04T07:00:00+0000"},{"value":36,"end_time":"2017-05-05T07:00:00+0000"}],"title":"Reach","description":"Total number of unique accounts that have seen this profile","id":"17841400008460056/insights/reach/day"},{"name":"profile_views","period":"day","values":[{"value":0,"end_time":"2017-05-04T07:00:00+0000"},{"value":2,"end_time":"2017-05-05T07:00:00+0000"}],"title":"Profile Views","description":"Total number of unique accounts that have viewed this profile within the specified period","id":"17841400008460056/insights/profile_views/day"}]} -------------------------------------------------------------------------------- /testdata/instagram/apidata/users/user_insights_new.json: -------------------------------------------------------------------------------- 1 | {"data":[{"name":"reach","period":"day","title":"Accounts reached","description":"The number of unique accounts that have seen your content, at least once, including in ads. Content includes posts, stories, reels, videos and live videos. Reach is different from impressions, which may include multiple views of your content by the same accounts. This metric is estimated and in development.","total_value":{"value":14516883,"breakdowns":[{"dimension_keys":["media_product_type","follow_type"],"results":[{"dimension_values":["IGTV","FOLLOWER"],"value":9},{"dimension_values":["CAROUSEL_CONTAINER","NON_FOLLOWER"],"value":109},{"dimension_values":["AD","FOLLOWER"],"value":67608},{"dimension_values":["AD","NON_FOLLOWER"],"value":14357147},{"dimension_values":["POST","FOLLOWER"],"value":78567},{"dimension_values":["POST","NON_FOLLOWER"],"value":26514},{"dimension_values":["CAROUSEL_CONTAINER","FOLLOWER"],"value":191},{"dimension_values":["STORY","FOLLOWER"],"value":31274},{"dimension_values":["REEL","FOLLOWER"],"value":58345},{"dimension_values":["REEL","NON_FOLLOWER"],"value":23079},{"dimension_values":["IGTV","NON_FOLLOWER"],"value":39},{"dimension_values":["STORY","NON_FOLLOWER"],"value":3279},{"dimension_values":["AR_EFFECT_PREVIEW","FOLLOWER"],"value":6},{"dimension_values":["AR_EFFECT_PREVIEW","NON_FOLLOWER"],"value":7}]}]},"id":"17841454149711910/insights/reach/day"}],"paging":{"previous":"https://graph.facebook.com/v18.0/17841454149711910/insights?access_token=access_token&metric=reach&metric_type=total_value&period=day&breakdown=media_product_type%2Cfollow_type&timeframe=last_14_days&since=1699257550&until=1699430350","next":"https://graph.facebook.com/v18.0/17841454149711910/insights?access_token=access_token&metric=reach&metric_type=total_value&period=day&breakdown=media_product_type%2Cfollow_type&timeframe=last_14_days&since=1699603152&until=1699775952"}} -------------------------------------------------------------------------------- /testdata/instagram/models/ig_comment.json: -------------------------------------------------------------------------------- 1 | {"id":"17892250648466172","like_count":1,"media":{"id":"17846368219941692"},"text":"@ikroskun Hey, guys","timestamp":"2020-02-24T09:15:16+0000","user":{"id":"17841406338772941"},"username":"ikroskun","hidden":false,"replies":{"data":[{"timestamp":"2020-02-24T09:18:08+0000","text":"@ikroskun Nice","id":"17845747489952795"}]}} -------------------------------------------------------------------------------- /testdata/instagram/models/ig_container.json: -------------------------------------------------------------------------------- 1 | {"status_code":"FINISHED","id":"17889615691921648"} -------------------------------------------------------------------------------- /testdata/instagram/models/ig_hashtag.json: -------------------------------------------------------------------------------- 1 | {"id":"17841593698074073","name":"coke"} -------------------------------------------------------------------------------- /testdata/instagram/models/ig_insight.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "impressions", 3 | "period": "day", 4 | "values": [ 5 | { 6 | "value": 32, 7 | "end_time": "2018-01-11T08:00:00+0000" 8 | }, 9 | { 10 | "value": 32, 11 | "end_time": "2018-01-12T08:00:00+0000" 12 | } 13 | ], 14 | "title": "Impressions", 15 | "description": "Total number of times this profile has been seen", 16 | "id": "instagram_business_account_id/insights/impressions/day" 17 | } -------------------------------------------------------------------------------- /testdata/instagram/models/ig_publish_limit.json: -------------------------------------------------------------------------------- 1 | { 2 | "quota_usage": 2, 3 | "config": { 4 | "quota_total": 25, 5 | "quota_duration": 86400 6 | } 7 | } -------------------------------------------------------------------------------- /testdata/instagram/models/ig_reply.json: -------------------------------------------------------------------------------- 1 | { 2 | "hidden": false, 3 | "id": "18107567341036926", 4 | "like_count": 0, 5 | "media": { 6 | "id": "17955956875141196" 7 | }, 8 | "text": "@yjmjump sex", 9 | "timestamp": "2019-10-15T07:06:09+0000", 10 | "user": { 11 | "id": "17841406338772941" 12 | }, 13 | "username": "ikroskun" 14 | } -------------------------------------------------------------------------------- /testdata/instagram/models/ig_story.json: -------------------------------------------------------------------------------- 1 | { 2 | "caption": "我怀疑是你", 3 | "id": "17908009870517752", 4 | "ig_id": "2420439378386778188", 5 | "like_count": 0, 6 | "media_type": "IMAGE", 7 | "media_url": "https://scontent-lax3-1.cdninstagram.com/v/t51.29350-15/121594799_1075709302851570_8911349777723204467_n.jpg?_nc_cat=101&_nc_sid=8ae9d6&_nc_ohc=Zj0yQs8d_8cAX9h0nMq&_nc_ht=scontent-lax3-1.cdninstagram.com&oh=66f67e3019ca55b7490210ee6c055bfd&oe=5FAE2440", 8 | "owner": { 9 | "id": "17841406338772941" 10 | }, 11 | "permalink": "https://instagram.com/stories/ikroskun/2420439378386778188", 12 | "shortcode": "CGXIMplHHhM", 13 | "timestamp": "2020-10-15T10:47:55+0000", 14 | "username": "ikroskun" 15 | } -------------------------------------------------------------------------------- /testdata/instagram/models/ig_user.json: -------------------------------------------------------------------------------- 1 | {"id":"17841407673135339","ig_id":7482719771,"biography":"Follow us for updates on Facebook’s business tools, AI, AR, VR, and more.","name":"Facebook for Developers","username":"facebookfordevelopers","followers_count":64361,"follows_count":16,"media_count":427,"profile_picture_url":"https://scontent-gmp1-1.xx.fbcdn.net/v/t51.2885-15/119360396_354046192452293_1644353770392407160_n.jpg?_nc_cat=105&ccb=1-3&_nc_sid=86c713&_nc_ohc=weehPiTrz7gAX-2nuLB&_nc_ht=scontent-gmp1-1.xx&oh=adbdbbae0d2429397e0881da942b9b6a&oe=6103DFA4"} -------------------------------------------------------------------------------- /testdata/instagram_basic/apidata/media/media_children.json: -------------------------------------------------------------------------------- 1 | {"data":[{"id":"17895013408404508","media_type":"IMAGE","media_url":"https://scontent.xx.fbcdn.net/v/t51.2885-15/75272169_186899105680947_6877787885363829923_n.jpg?_nc_cat=107&_nc_sid=8ae9d6&_nc_ohc=raR3-dwE0L4AX9dUg8O&_nc_ht=scontent.xx&oh=6a99d754c0a3e3457689d37b197e3620&oe=5E86031C","permalink":"https://www.instagram.com/p/B38XyoFHM_T/"},{"id":"17875124200471097","media_type":"IMAGE","media_url":"https://scontent.xx.fbcdn.net/v/t51.2885-15/71521241_430626024266527_4946266928155725240_n.jpg?_nc_cat=108&_nc_sid=8ae9d6&_nc_ohc=xpdg58drWp0AX_IpmJY&_nc_ht=scontent.xx&oh=f271ccd1ae021d8e43f0f26697e0e8d3&oe=5E820663","permalink":"https://www.instagram.com/p/B38XyoEnKK_/"}]} -------------------------------------------------------------------------------- /testdata/instagram_basic/apidata/media/media_info.json: -------------------------------------------------------------------------------- 1 | {"caption":"Pycon China @ikroskun","id":"18027939643230671","media_type":"CAROUSEL_ALBUM","media_url":"https://scontent.xx.fbcdn.net/v/t51.2885-15/75272169_186899105680947_6877787885363829923_n.jpg?_nc_cat=107&_nc_sid=8ae9d6&_nc_ohc=CZLCO-CzEnYAX_2a5rr&_nc_ht=scontent.xx&oh=6926bcf667a56e8fca522238e0bb3601&oe=5E86031C","permalink":"https://www.instagram.com/p/B38Xyp6nqsS/","timestamp":"2019-10-23T02:05:15+0000"} -------------------------------------------------------------------------------- /testdata/instagram_basic/apidata/media/medias_info.json: -------------------------------------------------------------------------------- 1 | {"18027939643230671":{"id":"18027939643230671","media_type":"CAROUSEL_ALBUM","media_url":"https://scontent-gmp1-1.cdninstagram.com/v/t51.2885-15/75272169_186899105680947_6877787885363829923_n.jpg?_nc_cat=107&ccb=1-5&_nc_sid=8ae9d6&_nc_ohc=FZm6Ll8bp2YAX88gMeK&_nc_ht=scontent-gmp1-1.cdninstagram.com&edm=ANQ71j8EAAAA&oh=aea2b3661360fd42ce78340de5af4055&oe=61294D24","permalink":"https://www.instagram.com/p/B38Xyp6nqsS/","timestamp":"2019-10-23T02:05:15+0000"},"17846368219941692":{"id":"17846368219941692","media_type":"IMAGE","media_url":"https://scontent-gmp1-1.cdninstagram.com/v/t51.2885-15/84867683_142798393480123_5890942139025635916_n.jpg?_nc_cat=102&ccb=1-5&_nc_sid=8ae9d6&_nc_ohc=SdbxiISQhGAAX_ADP88&_nc_ht=scontent-gmp1-1.cdninstagram.com&edm=ANQ71j8EAAAA&oh=39a814368b7b1ec45272c8be38d52a66&oe=612856D0","permalink":"https://www.instagram.com/p/B8gQCApHMT-/","timestamp":"2020-02-13T10:35:40+0000"}} -------------------------------------------------------------------------------- /testdata/instagram_basic/apidata/user/user_info.json: -------------------------------------------------------------------------------- 1 | {"account_type":"BUSINESS","id":"17841406338772941","media_count":10,"username":"ikroskun"} -------------------------------------------------------------------------------- /testdata/instagram_basic/apidata/user/user_medias_p1.json: -------------------------------------------------------------------------------- 1 | {"data":[{"media_url":"https://scontent.xx.fbcdn.net/v/t51.2885-15/84867683_142798393480123_5890942139025635916_n.jpg?_nc_cat=102&_nc_sid=8ae9d6&_nc_ohc=cM-w-qSyf9MAX-l0s7M&_nc_ht=scontent.xx&oh=7ef505d36ef769100c71243b385cc63e&oe=5E899C70","permalink":"https://www.instagram.com/p/B8gQCApHMT-/","timestamp":"2020-02-13T10:35:40+0000","username":"ikroskun","caption":"Cute.. #cute #loveyou @ikroskun","media_type":"IMAGE","id":"17846368219941692"},{"media_url":"https://scontent.xx.fbcdn.net/v/t51.2885-15/81418964_186403905911813_248261585257732428_n.jpg?_nc_cat=105&_nc_sid=8ae9d6&_nc_ohc=lrkkDGbxqEUAX8YUj9I&_nc_ht=scontent.xx&oh=32682ba745c1cac2ed5bdda05589b9b5&oe=5E8C58D9","permalink":"https://www.instagram.com/p/B8gPx-UnsjA/","timestamp":"2020-02-13T10:33:29+0000","username":"ikroskun","caption":"Hei #love","media_type":"IMAGE","id":"18091893643133286"}],"paging":{"cursors":{"before":"before","after":"after"},"next":"https://graph.instagram.com/v1.0/17841406338772941/media?access_token=access-token&fields=media_url%2Cpermalink%2Cchildren%7Bmedia_url%2Cpermalink%2Ctimestamp%2Cusername%2Cmedia_type%2Cthumbnail_url%2Cid%7D%2Ctimestamp%2Cusername%2Ccaption%2Cmedia_type%2Cthumbnail_url%2Cid&limit=6&after=after"}} -------------------------------------------------------------------------------- /testdata/instagram_basic/apidata/user/user_medias_p2.json: -------------------------------------------------------------------------------- 1 | {"data":[{"media_url":"https://scontent.xx.fbcdn.net/v/t51.2885-15/42745557_2090480327670159_2460048155370674433_n.jpg?_nc_cat=101&_nc_sid=8ae9d6&_nc_ohc=gK1maIWAp8YAX8LjISZ&_nc_ht=scontent.xx&oh=7427e23800ae72b9bb5f1d7b88268d91&oe=5E72BDA6","permalink":"https://www.instagram.com/p/Bop_Hz5FzyL/","timestamp":"2018-10-08T02:52:26+0000","username":"ikroskun","caption":"#日出 #华山 @onesight.cn","media_type":"IMAGE","id":"17896189813249754"},{"media_url":"https://scontent.xx.fbcdn.net/v/t51.2885-15/38438334_311676886078206_4989206608589357056_n.jpg?_nc_cat=101&_nc_sid=8ae9d6&_nc_ohc=EnUJzMFhNOkAX8QGIgw&_nc_ht=scontent.xx&oh=0d7aaf1de664ea26db999b1333bbef11&oe=5E8983ED","permalink":"https://www.instagram.com/p/Bme0cU1giOH/","timestamp":"2018-08-15T01:44:41+0000","username":"ikroskun","caption":"楼下突现一棵柿子树","media_type":"IMAGE","id":"17970645226046242"}],"paging":{"cursors":{"before":"before","after":"after"},"previous":"https://graph.instagram.com/v1.0/17841406338772941/media?access_token=access-token&fields=media_url%2Cpermalink%2Cchildren%7Bmedia_url%2Cpermalink%2Ctimestamp%2Cusername%2Cmedia_type%2Cthumbnail_url%2Cid%7D%2Ctimestamp%2Cusername%2Ccaption%2Cmedia_type%2Cthumbnail_url%2Cid&limit=6&before=before"}} -------------------------------------------------------------------------------- /testdata/instagram_basic/models/media_info.json: -------------------------------------------------------------------------------- 1 | { 2 | "caption": "Pycon China @ikroskun", 3 | "id": "18027939643230671", 4 | "media_type": "CAROUSEL_ALBUM", 5 | "media_url": "https://scontent.xx.fbcdn.net/v/t51.2885-15/75272169_186899105680947_6877787885363829923_n.jpg?_nc_cat=107&_nc_sid=8ae9d6&_nc_ohc=CZLCO-CzEnYAX_2a5rr&_nc_ht=scontent.xx&oh=6926bcf667a56e8fca522238e0bb3601&oe=5E86031C", 6 | "permalink": "https://www.instagram.com/p/B38Xyp6nqsS/", 7 | "timestamp": "2019-10-23T02:05:15+0000", 8 | "username": "ikroskun", 9 | "children": { 10 | "data": [ 11 | { 12 | "id": "17895013408404508", 13 | "media_type": "IMAGE", 14 | "media_url": "https://scontent.xx.fbcdn.net/v/t51.2885-15/75272169_186899105680947_6877787885363829923_n.jpg?_nc_cat=107&_nc_sid=8ae9d6&_nc_ohc=CZLCO-CzEnYAX_2a5rr&_nc_ht=scontent.xx&oh=6926bcf667a56e8fca522238e0bb3601&oe=5E86031C", 15 | "permalink": "https://www.instagram.com/p/B38XyoFHM_T/", 16 | "timestamp": "2019-10-23T02:05:15+0000", 17 | "username": "ikroskun" 18 | }, 19 | { 20 | "id": "17875124200471097", 21 | "media_type": "IMAGE", 22 | "media_url": "https://scontent.xx.fbcdn.net/v/t51.2885-15/71521241_430626024266527_4946266928155725240_n.jpg?_nc_cat=108&_nc_sid=8ae9d6&_nc_ohc=xpdg58drWp0AX_IpmJY&_nc_ht=scontent.xx&oh=b48c060eaa4de4f54fc03d4e5f7592d5&oe=5E74D763", 23 | "permalink": "https://www.instagram.com/p/B38XyoEnKK_/", 24 | "timestamp": "2019-10-23T02:05:15+0000", 25 | "username": "ikroskun" 26 | } 27 | ] 28 | } 29 | } -------------------------------------------------------------------------------- /testdata/instagram_basic/models/user_info.json: -------------------------------------------------------------------------------- 1 | { 2 | "account_type": "BUSINESS", 3 | "id": "17841406338772941", 4 | "media_count": 10, 5 | "username": "ikroskun" 6 | } -------------------------------------------------------------------------------- /tests/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sns-sdks/python-facebook/f51a56229c2a767a64b8295160bb2f49da8a39c7/tests/__init__.py -------------------------------------------------------------------------------- /tests/conftest.py: -------------------------------------------------------------------------------- 1 | import json 2 | 3 | import pytest 4 | 5 | from pyfacebook import GraphAPI 6 | 7 | 8 | class Helpers: 9 | @staticmethod 10 | def load_json(filename): 11 | with open(filename, "rb") as f: 12 | return json.loads(f.read().decode("utf-8")) 13 | 14 | @staticmethod 15 | def load_file_binary(filename): 16 | with open(filename, "rb") as f: 17 | return f.read() 18 | 19 | 20 | @pytest.fixture 21 | def helpers(): 22 | return Helpers() 23 | 24 | 25 | @pytest.fixture 26 | def pubg_api(): 27 | return GraphAPI(app_id="123456", app_secret="xxxxx", access_token="token") 28 | 29 | 30 | @pytest.fixture 31 | def user_api(): 32 | return GraphAPI(app_id="123456", app_secret="xxxxx", access_token="page token") 33 | -------------------------------------------------------------------------------- /tests/facebook/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sns-sdks/python-facebook/f51a56229c2a767a64b8295160bb2f49da8a39c7/tests/facebook/__init__.py -------------------------------------------------------------------------------- /tests/facebook/conftest.py: -------------------------------------------------------------------------------- 1 | import pytest 2 | 3 | from pyfacebook import FacebookApi 4 | 5 | 6 | @pytest.fixture 7 | def fb_api(): 8 | return FacebookApi(app_id="123456", app_secret="xxxxx", access_token="token") 9 | -------------------------------------------------------------------------------- /tests/facebook/edges/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sns-sdks/python-facebook/f51a56229c2a767a64b8295160bb2f49da8a39c7/tests/facebook/edges/__init__.py -------------------------------------------------------------------------------- /tests/facebook/edges/test_likes.py: -------------------------------------------------------------------------------- 1 | """ 2 | Tests for likes edges. 3 | """ 4 | 5 | import responses 6 | 7 | 8 | def test_get_likes(helpers, fb_api): 9 | object_id = "post_id" 10 | with responses.RequestsMock() as m: 11 | m.add( 12 | method=responses.GET, 13 | url=f"https://graph.facebook.com/{fb_api.version}/{object_id}/likes", 14 | json=helpers.load_json("testdata/facebook/apidata/likes/likes_resp.json"), 15 | ) 16 | 17 | likes_resp = fb_api.post.get_likes( 18 | object_id=object_id, 19 | ) 20 | assert likes_resp.data[0].profile_type == "user" 21 | 22 | likes_json = fb_api.post.get_likes( 23 | object_id=object_id, fields="id,name", return_json=True 24 | ) 25 | assert len(likes_json["data"]) == 2 26 | 27 | 28 | def test_create_like(fb_api): 29 | object_id = "post_id" 30 | with responses.RequestsMock() as m: 31 | m.add( 32 | method=responses.POST, 33 | url=f"https://graph.facebook.com/{fb_api.version}/{object_id}/likes", 34 | json={"success": True}, 35 | ) 36 | data = fb_api.post.creat_like(object_id=object_id) 37 | assert data["success"] 38 | 39 | 40 | def test_delete_like(fb_api): 41 | object_id = "post_id" 42 | with responses.RequestsMock() as m: 43 | m.add( 44 | method=responses.DELETE, 45 | url=f"https://graph.facebook.com/{fb_api.version}/{object_id}/likes", 46 | json={"success": True}, 47 | ) 48 | data = fb_api.post.delete_like(object_id=object_id) 49 | assert data["success"] 50 | -------------------------------------------------------------------------------- /tests/facebook/test_album.py: -------------------------------------------------------------------------------- 1 | """ 2 | Tests for albums 3 | """ 4 | 5 | import responses 6 | 7 | 8 | def test_get_info(helpers, fb_api): 9 | ab_id = "10153867132423553" 10 | 11 | with responses.RequestsMock() as m: 12 | m.add( 13 | method=responses.GET, 14 | url=f"https://graph.facebook.com/{fb_api.version}/{ab_id}", 15 | json=helpers.load_json( 16 | "testdata/facebook/apidata/albums/album_info_fields.json" 17 | ), 18 | ) 19 | m.add( 20 | method=responses.GET, 21 | url=f"https://graph.facebook.com/{fb_api.version}/{ab_id}", 22 | json=helpers.load_json( 23 | "testdata/facebook/apidata/albums/album_info_default.json" 24 | ), 25 | ) 26 | 27 | album = fb_api.album.get_info(album_id=ab_id) 28 | assert album.id == ab_id 29 | assert album.updated_time == "2016-08-17T22:25:25+0000" 30 | 31 | album_json = fb_api.album.get_info( 32 | album_id=ab_id, 33 | fields="id,name,created_time", 34 | return_json=True, 35 | ) 36 | assert album_json["id"] == ab_id 37 | 38 | 39 | def test_get_batch(helpers, fb_api): 40 | ab_ids = ["10153867132423553", "10151067477123553"] 41 | 42 | with responses.RequestsMock() as m: 43 | m.add( 44 | method=responses.GET, 45 | url=f"https://graph.facebook.com/{fb_api.version}", 46 | json=helpers.load_json( 47 | "testdata/facebook/apidata/albums/albums_info_fields.json" 48 | ), 49 | ) 50 | m.add( 51 | method=responses.GET, 52 | url=f"https://graph.facebook.com/{fb_api.version}", 53 | json=helpers.load_json( 54 | "testdata/facebook/apidata/albums/albums_info_default.json" 55 | ), 56 | ) 57 | 58 | albums = fb_api.album.get_batch(ids=ab_ids) 59 | assert albums[ab_ids[0]].id == ab_ids[0] 60 | 61 | albums_json = fb_api.album.get_batch( 62 | ids=ab_ids, 63 | fields="id,name,created_time", 64 | return_json=True, 65 | ) 66 | assert albums_json[ab_ids[1]]["id"] == ab_ids[1] 67 | -------------------------------------------------------------------------------- /tests/facebook/test_application.py: -------------------------------------------------------------------------------- 1 | """ 2 | Tests for application. 3 | """ 4 | 5 | import responses 6 | 7 | 8 | def test_get_info(helpers, fb_api): 9 | with responses.RequestsMock() as m: 10 | m.add( 11 | method=responses.GET, 12 | url=f"https://graph.facebook.com/{fb_api.version}/{fb_api.app_id}", 13 | json=helpers.load_json( 14 | "testdata/facebook/apidata/applications/application_info.json" 15 | ), 16 | ) 17 | 18 | app = fb_api.application.get_info() 19 | assert app.id == "123456789" 20 | 21 | app_json = fb_api.application.get_info( 22 | fields="id,category,description,link,name,namespace", return_json=True 23 | ) 24 | assert app_json["id"] == "123456789" 25 | 26 | 27 | def test_get_accounts(helpers, fb_api): 28 | with responses.RequestsMock() as m: 29 | m.add( 30 | method=responses.GET, 31 | url=f"https://graph.facebook.com/{fb_api.version}/{fb_api.app_id}/accounts", 32 | json=helpers.load_json( 33 | "testdata/facebook/apidata/applications/application_accounts.json", 34 | ), 35 | ) 36 | 37 | accounts = fb_api.application.get_accounts(count=None) 38 | assert len(accounts.data) == 4 39 | 40 | accounts_json = fb_api.application.get_accounts( 41 | fields="id,login_url", count=3, limit=4, return_json=True 42 | ) 43 | assert accounts_json["data"][0]["id"] == "123456789" 44 | -------------------------------------------------------------------------------- /tests/facebook/test_base.py: -------------------------------------------------------------------------------- 1 | """ 2 | tests for api base 3 | """ 4 | 5 | 6 | def test_resource(fb_api): 7 | assert fb_api.user.access_token == "token" 8 | assert fb_api.user.app_id == "123456" 9 | assert fb_api.user.app_secret == "xxxxx" 10 | assert fb_api.user.client 11 | -------------------------------------------------------------------------------- /tests/facebook/test_business.py: -------------------------------------------------------------------------------- 1 | """ 2 | Tests for business 3 | """ 4 | 5 | import responses 6 | 7 | 8 | def test_get_info(helpers, fb_api): 9 | b_id = "123456789" 10 | 11 | with responses.RequestsMock() as m: 12 | m.add( 13 | method=responses.GET, 14 | url=f"https://graph.facebook.com/{fb_api.version}/{b_id}", 15 | json=helpers.load_json( 16 | "testdata/facebook/apidata/business/business_info.json" 17 | ), 18 | ) 19 | 20 | business = fb_api.business.get_info(business_id=b_id) 21 | assert business.id == b_id 22 | assert business.updated_time == "2021-08-31T08:27:35+0000" 23 | 24 | business_json = fb_api.business.get_info( 25 | business_id=b_id, 26 | fields="id,name,link,created_time,updated_time,verification_status,profile_picture_uri", 27 | return_json=True, 28 | ) 29 | assert business_json["id"] == b_id 30 | 31 | 32 | def test_get_batch(helpers, fb_api): 33 | b_ids = ["123456789", "987654321"] 34 | 35 | with responses.RequestsMock() as m: 36 | m.add( 37 | method=responses.GET, 38 | url=f"https://graph.facebook.com/{fb_api.version}", 39 | json=helpers.load_json( 40 | "testdata/facebook/apidata/business/businesses_info.json" 41 | ), 42 | ) 43 | 44 | businesses = fb_api.business.get_batch(ids=b_ids) 45 | assert businesses[b_ids[0]].id == b_ids[0] 46 | 47 | business_json = fb_api.business.get_batch( 48 | ids=b_ids, 49 | fields="id,name,link,created_time,updated_time,verification_status,profile_picture_uri", 50 | return_json=True, 51 | ) 52 | assert business_json[b_ids[1]]["id"] == b_ids[1] 53 | -------------------------------------------------------------------------------- /tests/facebook/test_conversation.py: -------------------------------------------------------------------------------- 1 | """ 2 | Tests for conversation. 3 | """ 4 | 5 | import responses 6 | 7 | 8 | def test_get_info(helpers, fb_api): 9 | cvs_id = "t_587956915396498" 10 | 11 | with responses.RequestsMock() as m: 12 | m.add( 13 | method=responses.GET, 14 | url=f"https://graph.facebook.com/{fb_api.version}/{cvs_id}", 15 | json=helpers.load_json( 16 | "testdata/facebook/apidata/conversations/cvs_info.json" 17 | ), 18 | ) 19 | 20 | cvs = fb_api.conversation.get_info(conversation_id=cvs_id) 21 | assert cvs.id == cvs_id 22 | assert cvs.updated_time == "2021-07-23T09:28:50+0000" 23 | 24 | cvs_json = fb_api.conversation.get_info( 25 | conversation_id=cvs_id, 26 | fields="id,link,message_count,snippet,unread_count,updated_time", 27 | return_json=True, 28 | ) 29 | assert cvs_json["id"] == cvs_id 30 | 31 | 32 | def test_get_batch(helpers, fb_api): 33 | cvs_ids = ["t_587956915396498", "t_233782918546745"] 34 | 35 | with responses.RequestsMock() as m: 36 | m.add( 37 | method=responses.GET, 38 | url=f"https://graph.facebook.com/{fb_api.version}", 39 | json=helpers.load_json( 40 | "testdata/facebook/apidata/conversations/cvses_info.json" 41 | ), 42 | ) 43 | 44 | cvses = fb_api.conversation.get_batch(ids=cvs_ids) 45 | assert cvses[cvs_ids[0]].id == cvs_ids[0] 46 | 47 | cvses_json = fb_api.conversation.get_batch( 48 | ids=cvs_ids, 49 | fields="id,link,message_count,snippet,unread_count,updated_time", 50 | return_json=True, 51 | ) 52 | assert cvses_json[cvs_ids[1]]["id"] == cvs_ids[1] 53 | -------------------------------------------------------------------------------- /tests/facebook/test_event.py: -------------------------------------------------------------------------------- 1 | """ 2 | Tests for event. 3 | """ 4 | 5 | import responses 6 | 7 | 8 | def test_get_info(helpers, fb_api): 9 | evt_id = "5971414199599456" 10 | 11 | with responses.RequestsMock() as m: 12 | m.add( 13 | method=responses.GET, 14 | url=f"https://graph.facebook.com/{fb_api.version}/{evt_id}", 15 | json=helpers.load_json("testdata/facebook/apidata/events/event_info.json"), 16 | ) 17 | 18 | event = fb_api.event.get_info(event_id=evt_id) 19 | assert event.id == evt_id 20 | assert event.start_time == "2021-07-23T21:00:00+0800" 21 | 22 | event_json = fb_api.event.get_info( 23 | event_id=evt_id, 24 | fields="id,name,description,start_time,end_time,place,event_times", 25 | return_json=True, 26 | ) 27 | assert event_json["id"] == evt_id 28 | 29 | 30 | def test_get_batch(helpers, fb_api): 31 | et_ids = ["5971414199599456", "512411373205445"] 32 | 33 | with responses.RequestsMock() as m: 34 | m.add( 35 | method=responses.GET, 36 | url=f"https://graph.facebook.com/{fb_api.version}", 37 | json=helpers.load_json("testdata/facebook/apidata/events/events_info.json"), 38 | ) 39 | 40 | events = fb_api.event.get_batch(ids=et_ids) 41 | assert events[et_ids[0]].id == et_ids[0] 42 | 43 | events_json = fb_api.event.get_batch( 44 | ids=et_ids, 45 | fields="id,name,description,start_time,end_time,place,event_times", 46 | return_json=True, 47 | ) 48 | assert events_json[et_ids[1]]["id"] == et_ids[1] 49 | -------------------------------------------------------------------------------- /tests/facebook/test_live_video.py: -------------------------------------------------------------------------------- 1 | """ 2 | Tests for live video. 3 | """ 4 | 5 | import responses 6 | 7 | 8 | def test_get_info(helpers, fb_api): 9 | lv_id = "10158276101223553" 10 | 11 | with responses.RequestsMock() as m: 12 | m.add( 13 | method=responses.GET, 14 | url=f"https://graph.facebook.com/{fb_api.version}/{lv_id}", 15 | json=helpers.load_json( 16 | "testdata/facebook/apidata/live_videos/live_video_fields.json" 17 | ), 18 | ) 19 | m.add( 20 | method=responses.GET, 21 | url=f"https://graph.facebook.com/{fb_api.version}/{lv_id}", 22 | json=helpers.load_json( 23 | "testdata/facebook/apidata/live_videos/live_video_default.json" 24 | ), 25 | ) 26 | 27 | live_video = fb_api.live_video.get_info(live_video_id=lv_id) 28 | assert live_video.id == lv_id 29 | assert live_video.status == "VOD" 30 | 31 | live_video_json = fb_api.live_video.get_info( 32 | live_video_id=lv_id, 33 | fields="id,title,status,embed_html", 34 | return_json=True, 35 | ) 36 | assert live_video_json["id"] == lv_id 37 | assert live_video_json["title"] == "F8 Refresh 2021 Sessions" 38 | 39 | 40 | def test_get_batch(helpers, fb_api): 41 | lv_ids = ["10158276101223553", "10158275863243553"] 42 | 43 | with responses.RequestsMock() as m: 44 | m.add( 45 | method=responses.GET, 46 | url=f"https://graph.facebook.com/{fb_api.version}", 47 | json=helpers.load_json( 48 | "testdata/facebook/apidata/live_videos/live_videos_fields.json" 49 | ), 50 | ) 51 | m.add( 52 | method=responses.GET, 53 | url=f"https://graph.facebook.com/{fb_api.version}", 54 | json=helpers.load_json( 55 | "testdata/facebook/apidata/live_videos/live_videos_default.json" 56 | ), 57 | ) 58 | 59 | live_videos = fb_api.live_video.get_batch(ids=lv_ids) 60 | assert live_videos[lv_ids[0]].id == lv_ids[0] 61 | 62 | live_videos_json = fb_api.live_video.get_batch( 63 | ids=lv_ids, 64 | fields="id,title,status,embed_html", 65 | return_json=True, 66 | ) 67 | assert live_videos_json[lv_ids[1]]["id"] == lv_ids[1] 68 | -------------------------------------------------------------------------------- /tests/facebook/test_message.py: -------------------------------------------------------------------------------- 1 | """ 2 | Tests for message. 3 | """ 4 | 5 | import responses 6 | 7 | 8 | def test_get_info(helpers, fb_api): 9 | msg_id = "m_ToF35NI1OImBjyUIgplSaBMylUFmkYY4bHogy9C1otLISU6SGhccB5NK-THX_W4EdVQiKVv5SgCW9m-_C78mRA" 10 | 11 | with responses.RequestsMock() as m: 12 | m.add( 13 | method=responses.GET, 14 | url=f"https://graph.facebook.com/{fb_api.version}/{msg_id}", 15 | json=helpers.load_json( 16 | "testdata/facebook/apidata/messages/message_info.json" 17 | ), 18 | ) 19 | 20 | message = fb_api.message.get_info(message_id=msg_id) 21 | assert message.id == msg_id 22 | assert message.created_time == "2021-07-23T09:50:48+0000" 23 | 24 | message_json = fb_api.message.get_info( 25 | message_id=msg_id, 26 | fields="id,created_time,from,to,tags,attachments", 27 | return_json=True, 28 | ) 29 | assert message_json["id"] == msg_id 30 | 31 | 32 | def test_get_batch(helpers, fb_api): 33 | msg_ids = [ 34 | "m_ToF35NI1OImBjyUIgplSaBMylUFmkYY4bHogy9C1otLISU6SGhccB5NK-THX_W4EdVQiKVv5SgCW9m-_C78mRA", 35 | "m_rU2w1v7XMh8JR7jDSmW3pBMylUFmkYY4bHogy9C1otJUI2R3JKjhRblmg6DHQeVLHU6GP0qwqSqdSg0gnkE8tw", 36 | ] 37 | 38 | with responses.RequestsMock() as m: 39 | m.add( 40 | method=responses.GET, 41 | url=f"https://graph.facebook.com/{fb_api.version}", 42 | json=helpers.load_json( 43 | "testdata/facebook/apidata/messages/messages_info.json" 44 | ), 45 | ) 46 | 47 | messages = fb_api.message.get_batch(ids=msg_ids) 48 | assert messages[msg_ids[0]].id == msg_ids[0] 49 | 50 | messages_json = fb_api.message.get_batch( 51 | ids=msg_ids, 52 | fields="id,created_time,from,to,tags,attachments", 53 | return_json=True, 54 | ) 55 | assert messages_json[msg_ids[1]]["id"] == msg_ids[1] 56 | -------------------------------------------------------------------------------- /tests/facebook/test_photo.py: -------------------------------------------------------------------------------- 1 | """ 2 | Tests for photo api 3 | """ 4 | 5 | import pytest 6 | import responses 7 | 8 | 9 | def test_get_info(helpers, fb_api): 10 | photo_id = "10158249017468553" 11 | 12 | with responses.RequestsMock() as m: 13 | m.add( 14 | method=responses.GET, 15 | url=f"https://graph.facebook.com/{fb_api.version}/{photo_id}", 16 | json=helpers.load_json( 17 | "testdata/facebook/apidata/photos/photo_info_fields.json" 18 | ), 19 | ) 20 | m.add( 21 | method=responses.GET, 22 | url=f"https://graph.facebook.com/{fb_api.version}/{photo_id}", 23 | json=helpers.load_json( 24 | "testdata/facebook/apidata/photos/photo_info_default.json" 25 | ), 26 | ) 27 | 28 | photo = fb_api.photo.get_info(photo_id=photo_id) 29 | assert photo.id == photo_id 30 | 31 | photo_json = fb_api.photo.get_info( 32 | photo_id=photo_id, 33 | fields="id,created_time", 34 | return_json=True, 35 | ) 36 | assert photo_json["id"] == photo_id 37 | 38 | 39 | def test_get_batch(helpers, fb_api): 40 | ids = ["10157415047288553", "10158249017468553"] 41 | 42 | with responses.RequestsMock() as m: 43 | m.add( 44 | method=responses.GET, 45 | url=f"https://graph.facebook.com/{fb_api.version}", 46 | json=helpers.load_json( 47 | "testdata/facebook/apidata/photos/photos_info_fields.json" 48 | ), 49 | ) 50 | m.add( 51 | method=responses.GET, 52 | url=f"https://graph.facebook.com/{fb_api.version}", 53 | json=helpers.load_json( 54 | "testdata/facebook/apidata/photos/photos_info_default.json" 55 | ), 56 | ) 57 | 58 | data = fb_api.photo.get_batch(ids=ids) 59 | assert ids[0] in data.keys() 60 | 61 | data_json = fb_api.photo.get_batch( 62 | ids=ids, 63 | fields="id,created_time", 64 | return_json=True, 65 | ) 66 | assert data_json[ids[0]]["id"] == ids[0] 67 | -------------------------------------------------------------------------------- /tests/facebook/test_video.py: -------------------------------------------------------------------------------- 1 | """ 2 | Tests for videos. 3 | """ 4 | 5 | import responses 6 | 7 | 8 | def test_get_info(helpers, fb_api): 9 | video_id = "1192957457884299" 10 | 11 | with responses.RequestsMock() as m: 12 | m.add( 13 | method=responses.GET, 14 | url=f"https://graph.facebook.com/{fb_api.version}/{video_id}", 15 | json=helpers.load_json( 16 | "testdata/facebook/apidata/videos/video_info_fields.json" 17 | ), 18 | ) 19 | m.add( 20 | method=responses.GET, 21 | url=f"https://graph.facebook.com/{fb_api.version}/{video_id}", 22 | json=helpers.load_json( 23 | "testdata/facebook/apidata/videos/video_info_default.json" 24 | ), 25 | ) 26 | 27 | video = fb_api.video.get_info(video_id=video_id) 28 | assert video.id == video_id 29 | assert video.updated_time == "2021-07-20T01:55:06+0000" 30 | 31 | video_json = fb_api.video.get_info( 32 | video_id=video_id, 33 | fields="id,description,updated_time", 34 | return_json=True, 35 | ) 36 | assert video_json["id"] == video_id 37 | 38 | 39 | def test_get_batch(helpers, fb_api): 40 | video_ids = ["1192957457884299", "334712884667245"] 41 | 42 | with responses.RequestsMock() as m: 43 | m.add( 44 | method=responses.GET, 45 | url=f"https://graph.facebook.com/{fb_api.version}", 46 | json=helpers.load_json( 47 | "testdata/facebook/apidata/videos/videos_info_fields.json" 48 | ), 49 | ) 50 | m.add( 51 | method=responses.GET, 52 | url=f"https://graph.facebook.com/{fb_api.version}", 53 | json=helpers.load_json( 54 | "testdata/facebook/apidata/videos/videos_info_default.json" 55 | ), 56 | ) 57 | 58 | videos = fb_api.video.get_batch(ids=video_ids) 59 | assert videos[video_ids[0]].id == video_ids[0] 60 | 61 | videos_json = fb_api.video.get_batch( 62 | ids=video_ids, 63 | fields="id,name,created_time", 64 | return_json=True, 65 | ) 66 | assert videos_json[video_ids[1]]["id"] == video_ids[1] 67 | -------------------------------------------------------------------------------- /tests/instagram_basic/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sns-sdks/python-facebook/f51a56229c2a767a64b8295160bb2f49da8a39c7/tests/instagram_basic/__init__.py -------------------------------------------------------------------------------- /tests/instagram_basic/conftest.py: -------------------------------------------------------------------------------- 1 | import pytest 2 | 3 | from pyfacebook import IGBasicDisplayApi 4 | 5 | 6 | @pytest.fixture 7 | def api(): 8 | return IGBasicDisplayApi( 9 | app_id="123456", 10 | app_secret="xxxxx", 11 | access_token="token", 12 | ) 13 | -------------------------------------------------------------------------------- /tests/instagram_basic/test_media.py: -------------------------------------------------------------------------------- 1 | """ 2 | Tests for basic media api. 3 | """ 4 | 5 | import responses 6 | 7 | 8 | def test_get_info(helpers, api): 9 | media_id = "18027939643230671" 10 | with responses.RequestsMock() as m: 11 | m.add( 12 | method=responses.GET, 13 | url=f"https://graph.instagram.com/{api.version}/{media_id}", 14 | json=helpers.load_json( 15 | "testdata/instagram_basic/apidata/media/media_info.json" 16 | ), 17 | ) 18 | 19 | media = api.media.get_info(media_id=media_id) 20 | assert media.id == media_id 21 | 22 | media_json = api.media.get_info( 23 | media_id=media_id, 24 | fields="caption,id,media_type,media_url,permalink,timestamp", 25 | return_json=True, 26 | ) 27 | assert media_json["id"] == media_id 28 | 29 | 30 | def test_get_batch(helpers, api): 31 | ids = ["18027939643230671", "17846368219941692"] 32 | with responses.RequestsMock() as m: 33 | m.add( 34 | method=responses.GET, 35 | url=f"https://graph.instagram.com/{api.version}", 36 | json=helpers.load_json( 37 | "testdata/instagram_basic/apidata/media/medias_info.json" 38 | ), 39 | ) 40 | 41 | medias = api.media.get_batch(ids=ids) 42 | assert medias[ids[0]].id == ids[0] 43 | 44 | medias_json = api.media.get_batch( 45 | ids=ids, 46 | fields="id,media_type,media_url,permalink,timestamp", 47 | return_json=True, 48 | ) 49 | assert medias_json[ids[0]]["id"] == ids[0] 50 | 51 | 52 | def test_get_children(helpers, api): 53 | media_id = "18027939643230671" 54 | 55 | with responses.RequestsMock() as m: 56 | m.add( 57 | method=responses.GET, 58 | url=f"https://graph.instagram.com/{api.version}/{media_id}/children", 59 | json=helpers.load_json( 60 | "testdata/instagram_basic/apidata/media/media_children.json" 61 | ), 62 | ) 63 | 64 | children = api.media.get_children(media_id=media_id) 65 | assert len(children.data) == 2 66 | 67 | children_json = api.media.get_children( 68 | media_id=media_id, 69 | fields="id,media_type,media_url", 70 | return_json=True, 71 | ) 72 | assert len(children_json["data"]) == 2 73 | -------------------------------------------------------------------------------- /tests/instagram_basic/test_user.py: -------------------------------------------------------------------------------- 1 | """ 2 | Tests for basic user api. 3 | """ 4 | 5 | import responses 6 | 7 | 8 | def test_get_info(helpers, api): 9 | uid = "17841406338772941" 10 | with responses.RequestsMock() as m: 11 | m.add( 12 | method=responses.GET, 13 | url=f"https://graph.instagram.com/{api.version}/me", 14 | json=helpers.load_json( 15 | "testdata/instagram_basic/apidata/user/user_info.json" 16 | ), 17 | ) 18 | 19 | user = api.user.get_info() 20 | assert user.id == uid 21 | 22 | user_json = api.user.get_info( 23 | fields="account_type,id,media_count,username", 24 | return_json=True, 25 | ) 26 | assert user_json["id"] == uid 27 | 28 | 29 | def test_user_media(helpers, api): 30 | uid = "17841406338772941" 31 | 32 | with responses.RequestsMock() as m: 33 | m.add( 34 | method=responses.GET, 35 | url=f"https://graph.instagram.com/{api.version}/{uid}/media", 36 | json=helpers.load_json( 37 | "testdata/instagram_basic/apidata/user/user_medias_p1.json" 38 | ), 39 | ) 40 | m.add( 41 | method=responses.GET, 42 | url=f"https://graph.instagram.com/{api.version}/{uid}/media", 43 | json=helpers.load_json( 44 | "testdata/instagram_basic/apidata/user/user_medias_p2.json" 45 | ), 46 | ) 47 | 48 | media = api.user.get_media( 49 | user_id=uid, 50 | count=None, 51 | limit=2, 52 | ) 53 | assert len(media.data) == 4 54 | assert media.data[0].id == "17846368219941692" 55 | 56 | media_json = api.user.get_media(user_id=uid, limit=2, return_json=True) 57 | assert len(media_json["data"]) == 2 58 | assert media_json["data"][0]["id"] == "17896189813249754" 59 | -------------------------------------------------------------------------------- /tests/instagram_business/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sns-sdks/python-facebook/f51a56229c2a767a64b8295160bb2f49da8a39c7/tests/instagram_business/__init__.py -------------------------------------------------------------------------------- /tests/instagram_business/conftest.py: -------------------------------------------------------------------------------- 1 | import pytest 2 | 3 | from pyfacebook import IGBusinessApi 4 | 5 | 6 | @pytest.fixture 7 | def api(): 8 | return IGBusinessApi( 9 | app_id="123456", 10 | app_secret="xxxxx", 11 | access_token="token", 12 | instagram_business_id="17841407673135339", 13 | ) 14 | -------------------------------------------------------------------------------- /tests/instagram_business/test_publish.py: -------------------------------------------------------------------------------- 1 | """ 2 | Tests for publishes. 3 | """ 4 | 5 | import responses 6 | 7 | 8 | def test_get_info(helpers, api): 9 | container_id = "17966279578433554" 10 | 11 | with responses.RequestsMock() as m: 12 | m.add( 13 | method=responses.GET, 14 | url=f"https://graph.facebook.com/{api.version}/{container_id}", 15 | json=helpers.load_json( 16 | "testdata/instagram/apidata/publish/container_info.json" 17 | ), 18 | ) 19 | 20 | container = api.container.get_info(container_id=container_id) 21 | assert container.id == container_id 22 | 23 | container_json = api.container.get_info( 24 | container_id=container_id, 25 | fields="id,status_code", 26 | return_json=True, 27 | ) 28 | assert container_json["id"] == container_id 29 | 30 | 31 | def test_get_batch(helpers, api): 32 | container_ids = ["17883019676403955", "17966279578433554"] 33 | 34 | with responses.RequestsMock() as m: 35 | m.add( 36 | method=responses.GET, 37 | url=f"https://graph.facebook.com/{api.version}", 38 | json=helpers.load_json( 39 | "testdata/instagram/apidata/publish/containers_info.json" 40 | ), 41 | ) 42 | 43 | containers = api.container.get_batch(ids=container_ids) 44 | assert containers[container_ids[0]].id == container_ids[0] 45 | 46 | containers_json = api.container.get_batch( 47 | ids=container_ids, 48 | fields="id,status_code", 49 | return_json=True, 50 | ) 51 | assert containers_json[container_ids[0]]["id"] == container_ids[0] 52 | -------------------------------------------------------------------------------- /tests/test_basic_display_api.py: -------------------------------------------------------------------------------- 1 | """ 2 | tests for ig basic display api 3 | """ 4 | 5 | import pytest 6 | import responses 7 | 8 | from pyfacebook import BasicDisplayAPI 9 | from pyfacebook.exceptions import LibraryError 10 | 11 | 12 | def test_oath_flow(helpers): 13 | api = BasicDisplayAPI(app_id="id", app_secret="secret", oauth_flow=True) 14 | 15 | # test get authorization url 16 | _, state = api.get_authorization_url() 17 | 18 | # if user give authorize. 19 | resp = "https://localhost/?code=code&state=PyFacebook#_" 20 | 21 | with responses.RequestsMock() as m: 22 | m.add( 23 | method=responses.POST, 24 | url=api.EXCHANGE_ACCESS_TOKEN_URL, 25 | json=helpers.load_json("testdata/base/basic_display_api_user_token.json"), 26 | ) 27 | 28 | r = api.exchange_user_access_token(response=resp) 29 | assert r["access_token"] == "token" 30 | 31 | 32 | def test_exchange_long_lived_token(helpers): 33 | api = BasicDisplayAPI(access_token="token") 34 | 35 | # test exchange long-lived page token 36 | with responses.RequestsMock() as m: 37 | m.add( 38 | method=responses.GET, 39 | url=f"https://graph.instagram.com/access_token", 40 | json=helpers.load_json("testdata/base/long_term_token.json"), 41 | ) 42 | 43 | res = api.exchange_long_lived_user_access_token() 44 | assert res["access_token"] == "token" 45 | 46 | 47 | def test_refresh_token(helpers): 48 | api = BasicDisplayAPI(access_token="token") 49 | 50 | # test exchange long-lived page token 51 | with responses.RequestsMock() as m: 52 | m.add( 53 | method=responses.GET, 54 | url=f"https://graph.instagram.com/refresh_access_token", 55 | json=helpers.load_json("testdata/base/long_term_token.json"), 56 | ) 57 | 58 | res = api.refresh_access_token(access_token=api.access_token) 59 | assert res["access_token"] == "token" 60 | 61 | 62 | def test_not_implemented_methods(): 63 | api = BasicDisplayAPI(access_token="token") 64 | with pytest.raises(LibraryError): 65 | api.exchange_page_access_token(page_id="id") 66 | 67 | with pytest.raises(LibraryError): 68 | api.exchange_long_lived_page_access_token(user_id="id") 69 | 70 | with pytest.raises(LibraryError): 71 | api.get_app_token() 72 | 73 | with pytest.raises(LibraryError): 74 | api.debug_token(input_token="token") 75 | -------------------------------------------------------------------------------- /tests/test_exception.py: -------------------------------------------------------------------------------- 1 | """ 2 | tests for custom exceptions 3 | """ 4 | 5 | from pyfacebook import LibraryError, FacebookError 6 | 7 | 8 | def test_error(): 9 | error = { 10 | "error": { 11 | "message": "Message describing the error", 12 | "type": "OAuthException", 13 | "code": 190, 14 | "error_subcode": 460, 15 | "error_user_title": "A title", 16 | "error_user_msg": "A message", 17 | "fbtrace_id": "EJplcsCHuLu", 18 | } 19 | } 20 | 21 | fb_err = FacebookError(error) 22 | 23 | assert fb_err.code == 190 24 | assert "FacebookError" in repr(fb_err) 25 | 26 | error = {"message": "error message"} 27 | lib_err = LibraryError(error) 28 | 29 | assert lib_err.code == -1 30 | assert "LibraryError" in str(lib_err) 31 | -------------------------------------------------------------------------------- /tests/test_ratelimit.py: -------------------------------------------------------------------------------- 1 | from requests.models import CaseInsensitiveDict 2 | from pyfacebook import RateLimit, PercentSecond 3 | 4 | 5 | def test_parse_headers(): 6 | headers = CaseInsensitiveDict({"key": "None"}) 7 | assert RateLimit.parse_headers(headers, key="key") is None 8 | assert RateLimit.parse_headers(headers, key="key-null") is None 9 | 10 | 11 | def test_app_limit(): 12 | headers = CaseInsensitiveDict( 13 | {"x-app-usage": '{"call_count":91,"total_cputime":15,"total_time":12}'} 14 | ) 15 | r = RateLimit() 16 | r.set_limit(headers) 17 | 18 | assert r.get_limit().total_cputime == 15 19 | assert r.get_limit().max_percent() == 91 20 | assert r.get_max_percent() == 91 21 | assert r.get_sleep_seconds() == 0 22 | 23 | mapping = [PercentSecond(10, 1), PercentSecond(20, 2)] 24 | assert r.get_sleep_seconds(sleep_data=mapping) == 600 25 | 26 | headers = CaseInsensitiveDict( 27 | {"x-app-usage": '{"call_count":16,"total_cputime":15,"total_time":12}'} 28 | ) 29 | r.set_limit(headers) 30 | assert r.get_sleep_seconds(sleep_data=mapping) == 2 31 | 32 | 33 | def test_business_limit(): 34 | headers = CaseInsensitiveDict( 35 | { 36 | "x-business-use-case-usage": '{"112130216863063":[{"type":"pages","call_count":1,"total_cputime":1,"total_time":1,"estimated_time_to_regain_access":0,"ads_api_access_tier":"development_access"}]}' 37 | } 38 | ) 39 | 40 | r = RateLimit() 41 | r.set_limit(headers) 42 | 43 | assert r.get_limit("112130216863063", "pages").call_count == 1 44 | 45 | 46 | def test_ad_account_limit(): 47 | headers = CaseInsensitiveDict( 48 | { 49 | "x-ad-account-usage": '{"acc_id_util_pct":9.67,"reset_time_duration":100,"ads_api_access_tier":"standard_access"}' 50 | } 51 | ) 52 | r = RateLimit() 53 | r.set_limit(headers) 54 | 55 | assert r.get_limit(ad_account_limit=True).acc_id_util_pct == 9.67 56 | -------------------------------------------------------------------------------- /tests/test_threads_graph_api.py: -------------------------------------------------------------------------------- 1 | """ 2 | tests for threads graph api 3 | """ 4 | 5 | import responses 6 | 7 | from pyfacebook import ThreadsGraphAPI 8 | 9 | 10 | def test_threads_get_authorization_url(): 11 | api = ThreadsGraphAPI(app_id="id", app_secret="secret", oauth_flow=True) 12 | 13 | url, state = api.get_authorization_url(scope=["threads_basic"]) 14 | assert ( 15 | url 16 | == "https://threads.net/oauth/authorize?response_type=code&client_id=id&redirect_uri=https%3A%2F%2Flocalhost%2F&scope=threads_basic&state=PyFacebook" 17 | ) 18 | 19 | 20 | def test_threads_exchange_user_access_token(helpers): 21 | api = ThreadsGraphAPI(app_id="id", app_secret="secret", oauth_flow=True) 22 | 23 | resp = "https://localhost/?code=code&state=PyFacebook#_" 24 | 25 | with responses.RequestsMock() as m: 26 | m.add( 27 | method=responses.POST, 28 | url=api.EXCHANGE_ACCESS_TOKEN_URL, 29 | json=helpers.load_json("testdata/base/threads_user_token.json"), 30 | ) 31 | 32 | r = api.exchange_user_access_token(response=resp, scope=["threads_basic"]) 33 | assert r["access_token"] == "THQVJ..." 34 | 35 | 36 | def test_threads_exchange_long_lived_user_access_token(helpers): 37 | api = ThreadsGraphAPI(app_id="id", app_secret="secret", access_token="token") 38 | with responses.RequestsMock() as m: 39 | m.add( 40 | method=responses.GET, 41 | url=f"https://graph.threads.net/oauth/access_token", 42 | json=helpers.load_json("testdata/base/threads_user_long_lived_token.json"), 43 | ) 44 | 45 | r = api.exchange_long_lived_user_access_token() 46 | assert r["access_token"] == "THQVJ..." 47 | 48 | 49 | def test_threads_refresh_access_token(helpers): 50 | api = ThreadsGraphAPI(app_id="id", app_secret="secret", access_token="token") 51 | with responses.RequestsMock() as m: 52 | m.add( 53 | method=responses.GET, 54 | url=f"https://graph.threads.net/refresh_access_token", 55 | json=helpers.load_json("testdata/base/threads_user_long_lived_token.json"), 56 | ) 57 | 58 | r = api.refresh_access_token(access_token=api.access_token) 59 | assert r["access_token"] == "THQVJ..." 60 | -------------------------------------------------------------------------------- /tests/utils/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sns-sdks/python-facebook/f51a56229c2a767a64b8295160bb2f49da8a39c7/tests/utils/__init__.py -------------------------------------------------------------------------------- /tests/utils/test_params_utils.py: -------------------------------------------------------------------------------- 1 | """ 2 | tests for params utils 3 | """ 4 | 5 | import pytest 6 | 7 | from pyfacebook import LibraryError 8 | from pyfacebook.utils.params_utils import enf_comma_separated 9 | 10 | 11 | def test_enf_comma_separated(): 12 | assert enf_comma_separated("fields", "f1") == "f1" 13 | assert enf_comma_separated("fields", ["f1", "f2"]) == "f1,f2" 14 | assert enf_comma_separated("fields", ["f1", "f2", "f2"]) == "f1,f2" 15 | assert enf_comma_separated("fields", ("f1", "f2")) == "f1,f2" 16 | 17 | with pytest.raises(LibraryError): 18 | enf_comma_separated("id", 1) 19 | 20 | with pytest.raises(LibraryError): 21 | enf_comma_separated("id", [None, None]) 22 | -------------------------------------------------------------------------------- /tox.ini: -------------------------------------------------------------------------------- 1 | [tox] 2 | isolated_build = true 3 | envlist =py37, py38, py39, py310, py311 4 | skip_missing_interpreters = True 5 | 6 | [testenv] 7 | deps = poetry 8 | commands = 9 | poetry install -v 10 | poetry run pytest -s 11 | --------------------------------------------------------------------------------