[
  {
    "path": ".github/ISSUE_TEMPLATE/bug_report.md",
    "content": "---\nname: Bug report\nabout: Create a report to help us improve this code\ntitle: ''\nlabels: bug\nassignees: ''\n\n---\n\n**Describe the bug**\nA clear and concise description of what the bug is.\n\n**To Reproduce**\nSteps to reproduce the behavior:\n\n**Expected behavior**\nA clear and concise description of what you expected to happen.\n\n**Additional context**\nAdd any other context about the problem here.\n"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/config.yml",
    "content": "blank_issues_enabled: false\ncontact_links:\n  - name: Question about the API? Ask in the Twitter Developer Community\n    url: https://twittercommunity.com/c/twitter-api/twitter-api-v2/\n    about: For general API functionality questions, please ask in the developer forums.\n"
  },
  {
    "path": ".github/workflows/cla.yml",
    "content": "name: \"CLA Assistant\"\non:\n  issue_comment:\n    types: [created]\n  pull_request_target:\n    types: [opened,closed,synchronize]\n\njobs:\n  CLAssistant:\n    runs-on: ubuntu-latest\n    steps:\n      - name: \"CLA Assistant\"\n        if: (github.event.comment.body == 'recheck' || github.event.comment.body == 'I have read the CLA Document and I hereby sign the CLA') || github.event_name == 'pull_request_target'\n        # Alpha Release\n        uses: cla-assistant/github-action@v2.0.2-alpha\n        env:\n          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}\n          PERSONAL_ACCESS_TOKEN : ${{ secrets.CLA_PAT }}\n        with:\n          remote-organization-name: twitter\n          remote-repository-name: .github-private\n          path-to-signatures: 'cla/signatures.json'\n          path-to-document: 'https://gist.github.com/twitter-service/a1ad5818c024dc4265f8b60e6d043f26'\n          custom-allsigned-prcomment: 'All Contributors have signed the CLA. If the commit check is not passing, a maintainer must go the Checks tab of this PR and rerun the GitHub Action.'\n          branch: 'main'\n"
  },
  {
    "path": ".gitignore",
    "content": "*.gem\n*.rbc\n/.config\n/coverage/\n/InstalledFiles\n/pkg/\n/spec/reports/\n/spec/examples.txt\n/test/tmp/\n/test/version_tmp/\n/tmp/\n.DS_Store\nnode_modules/\npackage-lock.json\npackage.json\nyarn.lock\n../node_modules/\n../package.json\n../yarn.lock\n\n# Used by dotenv library to load environment variables.\n# .env\n\n# Ignore Byebug command history file.\n.byebug_history\n\n## Specific to RubyMotion:\n.dat*\n.repl_history\nbuild/\n*.bridgesupport\nbuild-iPhoneOS/\nbuild-iPhoneSimulator/\n\n## Specific to RubyMotion (use of CocoaPods):\n#\n# We recommend against adding the Pods directory to your .gitignore. However\n# you should judge for yourself, the pros and cons are mentioned at:\n# https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control\n#\n# vendor/Pods/\n\n## Documentation cache and generated files:\n/.yardoc/\n/_yardoc/\n/doc/\n/rdoc/\n\n## Environment normalization:\n/.bundle/\n/vendor/bundle\n/lib/bundler/man/\n\n# for a library or gem, you might want to ignore these files since the code is\n# intended to run in multiple environments; otherwise, check them in:\n# Gemfile.lock\n# .ruby-version\n# .ruby-gemset\n\n# unless supporting rvm < 1.11.0 or doing something fancy, ignore this:\n.rvmrc\n\n# Used by RuboCop. Remote config files pulled in from inherit_from directive.\n# .rubocop-https?--*\n"
  },
  {
    "path": "CODE_OF_CONDUCT.md",
    "content": "We feel that a welcoming community is important and we ask that you follow Twitter's\n[Open Source Code of Conduct](https://github.com/twitter/code-of-conduct/blob/master/code-of-conduct.md)\nin all interactions with the community.\n"
  },
  {
    "path": "LICENSE",
    "content": "                                 Apache License\n                           Version 2.0, January 2004\n                        http://www.apache.org/licenses/\n\n   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION\n\n   1. Definitions.\n\n      \"License\" shall mean the terms and conditions for use, reproduction,\n      and distribution as defined by Sections 1 through 9 of this document.\n\n      \"Licensor\" shall mean the copyright owner or entity authorized by\n      the copyright owner that is granting the License.\n\n      \"Legal Entity\" shall mean the union of the acting entity and all\n      other entities that control, are controlled by, or are under common\n      control with that entity. For the purposes of this definition,\n      \"control\" means (i) the power, direct or indirect, to cause the\n      direction or management of such entity, whether by contract or\n      otherwise, or (ii) ownership of fifty percent (50%) or more of the\n      outstanding shares, or (iii) beneficial ownership of such entity.\n\n      \"You\" (or \"Your\") shall mean an individual or Legal Entity\n      exercising permissions granted by this License.\n\n      \"Source\" form shall mean the preferred form for making modifications,\n      including but not limited to software source code, documentation\n      source, and configuration files.\n\n      \"Object\" form shall mean any form resulting from mechanical\n      transformation or translation of a Source form, including but\n      not limited to compiled object code, generated documentation,\n      and conversions to other media types.\n\n      \"Work\" shall mean the work of authorship, whether in Source or\n      Object form, made available under the License, as indicated by a\n      copyright notice that is included in or attached to the work\n      (an example is provided in the Appendix below).\n\n      \"Derivative Works\" shall mean any work, whether in Source or Object\n      form, that is based on (or derived from) the Work and for which the\n      editorial revisions, annotations, elaborations, or other modifications\n      represent, as a whole, an original work of authorship. For the purposes\n      of this License, Derivative Works shall not include works that remain\n      separable from, or merely link (or bind by name) to the interfaces of,\n      the Work and Derivative Works thereof.\n\n      \"Contribution\" shall mean any work of authorship, including\n      the original version of the Work and any modifications or additions\n      to that Work or Derivative Works thereof, that is intentionally\n      submitted to Licensor for inclusion in the Work by the copyright owner\n      or by an individual or Legal Entity authorized to submit on behalf of\n      the copyright owner. For the purposes of this definition, \"submitted\"\n      means any form of electronic, verbal, or written communication sent\n      to the Licensor or its representatives, including but not limited to\n      communication on electronic mailing lists, source code control systems,\n      and issue tracking systems that are managed by, or on behalf of, the\n      Licensor for the purpose of discussing and improving the Work, but\n      excluding communication that is conspicuously marked or otherwise\n      designated in writing by the copyright owner as \"Not a Contribution.\"\n\n      \"Contributor\" shall mean Licensor and any individual or Legal Entity\n      on behalf of whom a Contribution has been received by Licensor and\n      subsequently incorporated within the Work.\n\n   2. Grant of Copyright License. Subject to the terms and conditions of\n      this License, each Contributor hereby grants to You a perpetual,\n      worldwide, non-exclusive, no-charge, royalty-free, irrevocable\n      copyright license to reproduce, prepare Derivative Works of,\n      publicly display, publicly perform, sublicense, and distribute the\n      Work and such Derivative Works in Source or Object form.\n\n   3. Grant of Patent License. Subject to the terms and conditions of\n      this License, each Contributor hereby grants to You a perpetual,\n      worldwide, non-exclusive, no-charge, royalty-free, irrevocable\n      (except as stated in this section) patent license to make, have made,\n      use, offer to sell, sell, import, and otherwise transfer the Work,\n      where such license applies only to those patent claims licensable\n      by such Contributor that are necessarily infringed by their\n      Contribution(s) alone or by combination of their Contribution(s)\n      with the Work to which such Contribution(s) was submitted. If You\n      institute patent litigation against any entity (including a\n      cross-claim or counterclaim in a lawsuit) alleging that the Work\n      or a Contribution incorporated within the Work constitutes direct\n      or contributory patent infringement, then any patent licenses\n      granted to You under this License for that Work shall terminate\n      as of the date such litigation is filed.\n\n   4. Redistribution. You may reproduce and distribute copies of the\n      Work or Derivative Works thereof in any medium, with or without\n      modifications, and in Source or Object form, provided that You\n      meet the following conditions:\n\n      (a) You must give any other recipients of the Work or\n          Derivative Works a copy of this License; and\n\n      (b) You must cause any modified files to carry prominent notices\n          stating that You changed the files; and\n\n      (c) You must retain, in the Source form of any Derivative Works\n          that You distribute, all copyright, patent, trademark, and\n          attribution notices from the Source form of the Work,\n          excluding those notices that do not pertain to any part of\n          the Derivative Works; and\n\n      (d) If the Work includes a \"NOTICE\" text file as part of its\n          distribution, then any Derivative Works that You distribute must\n          include a readable copy of the attribution notices contained\n          within such NOTICE file, excluding those notices that do not\n          pertain to any part of the Derivative Works, in at least one\n          of the following places: within a NOTICE text file distributed\n          as part of the Derivative Works; within the Source form or\n          documentation, if provided along with the Derivative Works; or,\n          within a display generated by the Derivative Works, if and\n          wherever such third-party notices normally appear. The contents\n          of the NOTICE file are for informational purposes only and\n          do not modify the License. You may add Your own attribution\n          notices within Derivative Works that You distribute, alongside\n          or as an addendum to the NOTICE text from the Work, provided\n          that such additional attribution notices cannot be construed\n          as modifying the License.\n\n      You may add Your own copyright statement to Your modifications and\n      may provide additional or different license terms and conditions\n      for use, reproduction, or distribution of Your modifications, or\n      for any such Derivative Works as a whole, provided Your use,\n      reproduction, and distribution of the Work otherwise complies with\n      the conditions stated in this License.\n\n   5. Submission of Contributions. Unless You explicitly state otherwise,\n      any Contribution intentionally submitted for inclusion in the Work\n      by You to the Licensor shall be under the terms and conditions of\n      this License, without any additional terms or conditions.\n      Notwithstanding the above, nothing herein shall supersede or modify\n      the terms of any separate license agreement you may have executed\n      with Licensor regarding such Contributions.\n\n   6. Trademarks. This License does not grant permission to use the trade\n      names, trademarks, service marks, or product names of the Licensor,\n      except as required for reasonable and customary use in describing the\n      origin of the Work and reproducing the content of the NOTICE file.\n\n   7. Disclaimer of Warranty. Unless required by applicable law or\n      agreed to in writing, Licensor provides the Work (and each\n      Contributor provides its Contributions) on an \"AS IS\" BASIS,\n      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or\n      implied, including, without limitation, any warranties or conditions\n      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A\n      PARTICULAR PURPOSE. You are solely responsible for determining the\n      appropriateness of using or redistributing the Work and assume any\n      risks associated with Your exercise of permissions under this License.\n\n   8. Limitation of Liability. In no event and under no legal theory,\n      whether in tort (including negligence), contract, or otherwise,\n      unless required by applicable law (such as deliberate and grossly\n      negligent acts) or agreed to in writing, shall any Contributor be\n      liable to You for damages, including any direct, indirect, special,\n      incidental, or consequential damages of any character arising as a\n      result of this License or out of the use or inability to use the\n      Work (including but not limited to damages for loss of goodwill,\n      work stoppage, computer failure or malfunction, or any and all\n      other commercial damages or losses), even if such Contributor\n      has been advised of the possibility of such damages.\n\n   9. Accepting Warranty or Additional Liability. While redistributing\n      the Work or Derivative Works thereof, You may choose to offer,\n      and charge a fee for, acceptance of support, warranty, indemnity,\n      or other liability obligations and/or rights consistent with this\n      License. However, in accepting such obligations, You may act only\n      on Your own behalf and on Your sole responsibility, not on behalf\n      of any other Contributor, and only if You agree to indemnify,\n      defend, and hold each Contributor harmless for any liability\n      incurred by, or claims asserted against, such Contributor by reason\n      of your accepting any such warranty or additional liability.\n\n   END OF TERMS AND CONDITIONS\n\n   APPENDIX: How to apply the Apache License to your work.\n\n      To apply the Apache License to your work, attach the following\n      boilerplate notice, with the fields enclosed by brackets \"[]\"\n      replaced with your own identifying information. (Don't include\n      the brackets!)  The text should be enclosed in the appropriate\n      comment syntax for the file format. We also recommend that a\n      file or class name and description of purpose be included on the\n      same \"printed page\" as the copyright notice for easier\n      identification within third-party archives.\n\n   Copyright 2020 @TwitterDev\n\n   Licensed under the Apache License, Version 2.0 (the \"License\");\n   you may not use this file except in compliance with the License.\n   You may obtain a copy of the License at\n\n       http://www.apache.org/licenses/LICENSE-2.0\n\n   Unless required by applicable law or agreed to in writing, software\n   distributed under the License is distributed on an \"AS IS\" BASIS,\n   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n   See the License for the specific language governing permissions and\n   limitations under the License.\n"
  },
  {
    "path": "README.md",
    "content": "# X API v2 Sample Code\n\n[![X API v2](https://img.shields.io/endpoint?url=https%3A%2F%2Ftwbadges.glitch.me%2Fbadges%2Fv2)](https://developer.x.com/en/docs/twitter-api)\n\nWorking code samples for the **X API v2** in Python, JavaScript, Ruby, Java, and R.\n\n## 📁 Repository Structure\n\n```\n├── python/           # 65 Python examples\n├── javascript/       # 59 JavaScript examples  \n├── ruby/             # 58 Ruby examples\n├── java/             # 19 Java examples\n├── r/                # 5 R examples\n├── llms.txt          # LLM-friendly documentation\n└── api-index.json    # Machine-readable endpoint catalog\n```\n\n## 🚀 Quick Start\n\n### 1. Get API Credentials\n\nSign up at the [X Developer Portal](https://developer.x.com/en/portal/dashboard).\n\n### 2. Set Environment Variables\n\n**For read-only operations (search, lookup):**\n```bash\nexport BEARER_TOKEN='your_bearer_token'\n```\n\n**For user actions (post, like, repost, bookmark, etc.):**\n```bash\nexport CLIENT_ID='your_client_id'\nexport CLIENT_SECRET='your_client_secret'\n```\n\n**For OAuth 1.0a (legacy endpoints):**\n```bash\nexport CONSUMER_KEY='your_consumer_key'\nexport CONSUMER_SECRET='your_consumer_secret'\n```\n\n### 3. Run an Example\n\n```bash\n# Python\ncd python && pip install -r requirements.txt\npython posts/search_recent.py\n\n# JavaScript  \ncd javascript\nnode posts/search_recent.js\n\n# Ruby\ncd ruby && bundle install\nruby posts/search_recent.rb\n\n# Java\ncd java\njavac -cp \".:lib/*\" posts/RecentSearchDemo.java\njava -cp \".:lib/*\" RecentSearchDemo\n```\n\n## 📚 Examples by Category\n\n| Category | Python | JavaScript | Ruby | Java | R |\n|----------|--------|------------|------|------|---|\n| Posts (search, create, delete, likes, reposts) | ✅ | ✅ | ✅ | ✅ | ✅ |\n| Users (lookup, followers, following, blocks, mutes) | ✅ | ✅ | ✅ | ✅ | ✅ |\n| Timelines (user, mentions, home) | ✅ | ✅ | ✅ | ✅ | |\n| Streams (filtered, sampled) | ✅ | ✅ | ✅ | ✅ | |\n| Lists (lookup, manage, members, follow) | ✅ | ✅ | ✅ | | |\n| Spaces (lookup, search) | ✅ | ✅ | ✅ | ✅ | |\n| Bookmarks | ✅ | ✅ | ✅ | | |\n| Direct Messages | ✅ | | | | |\n| Media Upload | ✅ | | | | |\n| Compliance | ✅ | ✅ | | | |\n| Usage | ✅ | ✅ | | ✅ | |\n\n## 🔐 Authentication\n\n| Type | Use Case | Env Vars |\n|------|----------|----------|\n| Bearer Token | Read-only (search, lookup) | `BEARER_TOKEN` |\n| OAuth 2.0 PKCE | User actions (post, like, repost, bookmark, mute, etc.) | `CLIENT_ID`, `CLIENT_SECRET` |\n| OAuth 1.0a | Legacy endpoints (if applicable) | `CONSUMER_KEY`, `CONSUMER_SECRET` |\n\n## 🤖 For LLMs\n\n- **`llms.txt`** - Context file for AI assistants\n- **`api-index.json`** - Machine-readable endpoint catalog\n\n## 🔗 Resources\n\n- [X API Documentation](https://developer.x.com/en/docs/twitter-api)\n- [Developer Portal](https://developer.x.com/en/portal/dashboard)\n\n## 📄 License\n\nApache 2.0\n"
  },
  {
    "path": "api-index.json",
    "content": "{\n  \"name\": \"X API v2 Sample Code\",\n  \"version\": \"2.0\",\n  \"base_url\": \"https://api.x.com/2\",\n  \"languages\": [\"python\", \"javascript\", \"ruby\", \"java\"],\n  \"endpoints\": [\n    {\n      \"name\": \"Create Post\",\n      \"path\": \"/tweets\",\n      \"method\": \"POST\",\n      \"auth\": [\"oauth1\", \"oauth2-user\"],\n      \"folder\": \"posts\",\n      \"files\": {\n        \"python\": \"create_post.py\",\n        \"javascript\": \"create_post.js\"\n      },\n      \"docs\": \"https://developer.x.com/en/docs/twitter-api/tweets/manage-tweets/api-reference/post-tweets\"\n    },\n    {\n      \"name\": \"Delete Post\",\n      \"path\": \"/tweets/:id\",\n      \"method\": \"DELETE\",\n      \"auth\": [\"oauth1\", \"oauth2-user\"],\n      \"folder\": \"posts\",\n      \"files\": {\n        \"python\": \"delete_post.py\",\n        \"javascript\": \"delete_post.js\"\n      },\n      \"docs\": \"https://developer.x.com/en/docs/twitter-api/tweets/manage-tweets/api-reference/delete-tweets-id\"\n    },\n    {\n      \"name\": \"Post Lookup\",\n      \"path\": \"/tweets\",\n      \"method\": \"GET\",\n      \"auth\": [\"bearer\", \"oauth1\", \"oauth2-user\"],\n      \"folder\": \"posts\",\n      \"files\": {\n        \"python\": \"lookup.py\",\n        \"javascript\": \"lookup.js\",\n        \"ruby\": \"lookup.rb\"\n      },\n      \"docs\": \"https://developer.x.com/en/docs/twitter-api/tweets/lookup/api-reference/get-tweets\"\n    },\n    {\n      \"name\": \"Recent Search\",\n      \"path\": \"/tweets/search/recent\",\n      \"method\": \"GET\",\n      \"auth\": [\"bearer\", \"oauth2-user\"],\n      \"folder\": \"posts\",\n      \"files\": {\n        \"python\": \"search_recent.py\",\n        \"javascript\": \"search_recent.js\",\n        \"ruby\": \"search_recent.rb\",\n        \"java\": \"SearchRecent.java\"\n      },\n      \"docs\": \"https://developer.x.com/en/docs/twitter-api/tweets/search/api-reference/get-tweets-search-recent\"\n    },\n    {\n      \"name\": \"Full Archive Search\",\n      \"path\": \"/tweets/search/all\",\n      \"method\": \"GET\",\n      \"auth\": [\"bearer\"],\n      \"folder\": \"posts\",\n      \"files\": {\n        \"python\": \"search_full_archive.py\"\n      },\n      \"docs\": \"https://developer.x.com/en/docs/twitter-api/tweets/search/api-reference/get-tweets-search-all\",\n      \"note\": \"Requires Academic Research access\"\n    },\n    {\n      \"name\": \"Recent Post Counts\",\n      \"path\": \"/tweets/counts/recent\",\n      \"method\": \"GET\",\n      \"auth\": [\"bearer\"],\n      \"folder\": \"posts\",\n      \"files\": {\n        \"python\": \"counts_recent.py\"\n      },\n      \"docs\": \"https://developer.x.com/en/docs/twitter-api/tweets/counts/api-reference/get-tweets-counts-recent\"\n    },\n    {\n      \"name\": \"Quote Posts\",\n      \"path\": \"/tweets/:id/quote_tweets\",\n      \"method\": \"GET\",\n      \"auth\": [\"bearer\", \"oauth2-user\"],\n      \"folder\": \"posts\",\n      \"files\": {\n        \"python\": \"quote_posts.py\"\n      },\n      \"docs\": \"https://developer.x.com/en/docs/twitter-api/tweets/quote-tweets/api-reference/get-tweets-id-quote_tweets\"\n    },\n    {\n      \"name\": \"Repost\",\n      \"path\": \"/users/:id/retweets\",\n      \"method\": \"POST\",\n      \"auth\": [\"oauth1\", \"oauth2-user\"],\n      \"folder\": \"posts\",\n      \"files\": {\n        \"python\": \"repost.py\"\n      },\n      \"docs\": \"https://developer.x.com/en/docs/twitter-api/tweets/retweets/api-reference/post-users-id-retweets\"\n    },\n    {\n      \"name\": \"Undo Repost\",\n      \"path\": \"/users/:id/retweets/:source_tweet_id\",\n      \"method\": \"DELETE\",\n      \"auth\": [\"oauth1\", \"oauth2-user\"],\n      \"folder\": \"posts\",\n      \"files\": {\n        \"python\": \"undo_repost.py\"\n      },\n      \"docs\": \"https://developer.x.com/en/docs/twitter-api/tweets/retweets/api-reference/delete-users-id-retweets-tweet_id\"\n    },\n    {\n      \"name\": \"Reposted By\",\n      \"path\": \"/tweets/:id/retweeted_by\",\n      \"method\": \"GET\",\n      \"auth\": [\"bearer\", \"oauth2-user\"],\n      \"folder\": \"posts\",\n      \"files\": {\n        \"python\": \"reposted_by.py\"\n      },\n      \"docs\": \"https://developer.x.com/en/docs/twitter-api/tweets/retweets/api-reference/get-tweets-id-retweeted_by\"\n    },\n    {\n      \"name\": \"Like Post\",\n      \"path\": \"/users/:id/likes\",\n      \"method\": \"POST\",\n      \"auth\": [\"oauth1\", \"oauth2-user\"],\n      \"folder\": \"posts\",\n      \"files\": {\n        \"python\": \"like.py\"\n      },\n      \"docs\": \"https://developer.x.com/en/docs/twitter-api/tweets/likes/api-reference/post-users-id-likes\"\n    },\n    {\n      \"name\": \"Unlike Post\",\n      \"path\": \"/users/:id/likes/:tweet_id\",\n      \"method\": \"DELETE\",\n      \"auth\": [\"oauth1\", \"oauth2-user\"],\n      \"folder\": \"posts\",\n      \"files\": {\n        \"python\": \"unlike.py\"\n      },\n      \"docs\": \"https://developer.x.com/en/docs/twitter-api/tweets/likes/api-reference/delete-users-id-likes-tweet_id\"\n    },\n    {\n      \"name\": \"Liking Users\",\n      \"path\": \"/tweets/:id/liking_users\",\n      \"method\": \"GET\",\n      \"auth\": [\"bearer\", \"oauth2-user\"],\n      \"folder\": \"posts\",\n      \"files\": {\n        \"python\": \"liking_users.py\"\n      },\n      \"docs\": \"https://developer.x.com/en/docs/twitter-api/tweets/likes/api-reference/get-tweets-id-liking_users\"\n    },\n    {\n      \"name\": \"Liked Posts\",\n      \"path\": \"/users/:id/liked_tweets\",\n      \"method\": \"GET\",\n      \"auth\": [\"bearer\", \"oauth2-user\"],\n      \"folder\": \"posts\",\n      \"files\": {\n        \"python\": \"liked_posts.py\"\n      },\n      \"docs\": \"https://developer.x.com/en/docs/twitter-api/tweets/likes/api-reference/get-users-id-liked_tweets\"\n    },\n    {\n      \"name\": \"User Lookup\",\n      \"path\": \"/users/by\",\n      \"method\": \"GET\",\n      \"auth\": [\"bearer\", \"oauth1\", \"oauth2-user\"],\n      \"folder\": \"users\",\n      \"files\": {\n        \"python\": \"lookup.py\",\n        \"javascript\": \"lookup.js\",\n        \"ruby\": \"lookup.rb\",\n        \"java\": \"Lookup.java\"\n      },\n      \"docs\": \"https://developer.x.com/en/docs/twitter-api/users/lookup/api-reference/get-users-by\"\n    },\n    {\n      \"name\": \"Authenticated User (Me)\",\n      \"path\": \"/users/me\",\n      \"method\": \"GET\",\n      \"auth\": [\"oauth1\", \"oauth2-user\"],\n      \"folder\": \"users\",\n      \"files\": {\n        \"python\": \"me.py\"\n      },\n      \"docs\": \"https://developer.x.com/en/docs/twitter-api/users/lookup/api-reference/get-users-me\"\n    },\n    {\n      \"name\": \"User Followers\",\n      \"path\": \"/users/:id/followers\",\n      \"method\": \"GET\",\n      \"auth\": [\"bearer\", \"oauth2-user\"],\n      \"folder\": \"users\",\n      \"files\": {\n        \"python\": \"followers.py\",\n        \"javascript\": \"followers.js\",\n        \"ruby\": \"followers.rb\"\n      },\n      \"docs\": \"https://developer.x.com/en/docs/twitter-api/users/follows/api-reference/get-users-id-followers\"\n    },\n    {\n      \"name\": \"User Following\",\n      \"path\": \"/users/:id/following\",\n      \"method\": \"GET\",\n      \"auth\": [\"bearer\", \"oauth2-user\"],\n      \"folder\": \"users\",\n      \"files\": {\n        \"python\": \"following.py\"\n      },\n      \"docs\": \"https://developer.x.com/en/docs/twitter-api/users/follows/api-reference/get-users-id-following\"\n    },\n    {\n      \"name\": \"Block User\",\n      \"path\": \"/users/:id/blocking\",\n      \"method\": \"POST\",\n      \"auth\": [\"oauth1\", \"oauth2-user\"],\n      \"folder\": \"users\",\n      \"files\": {\n        \"python\": \"block.py\"\n      },\n      \"docs\": \"https://developer.x.com/en/docs/twitter-api/users/blocks/api-reference/post-users-user_id-blocking\"\n    },\n    {\n      \"name\": \"Unblock User\",\n      \"path\": \"/users/:source_user_id/blocking/:target_user_id\",\n      \"method\": \"DELETE\",\n      \"auth\": [\"oauth1\", \"oauth2-user\"],\n      \"folder\": \"users\",\n      \"files\": {\n        \"python\": \"unblock.py\"\n      },\n      \"docs\": \"https://developer.x.com/en/docs/twitter-api/users/blocks/api-reference/delete-users-user_id-blocking\"\n    },\n    {\n      \"name\": \"Blocked Users\",\n      \"path\": \"/users/:id/blocking\",\n      \"method\": \"GET\",\n      \"auth\": [\"oauth1\", \"oauth2-user\"],\n      \"folder\": \"users\",\n      \"files\": {\n        \"python\": \"blocked.py\"\n      },\n      \"docs\": \"https://developer.x.com/en/docs/twitter-api/users/blocks/api-reference/get-users-blocking\"\n    },\n    {\n      \"name\": \"Mute User\",\n      \"path\": \"/users/:id/muting\",\n      \"method\": \"POST\",\n      \"auth\": [\"oauth1\", \"oauth2-user\"],\n      \"folder\": \"users\",\n      \"files\": {\n        \"python\": \"mute.py\"\n      },\n      \"docs\": \"https://developer.x.com/en/docs/twitter-api/users/mutes/api-reference/post-users-user_id-muting\"\n    },\n    {\n      \"name\": \"Unmute User\",\n      \"path\": \"/users/:source_user_id/muting/:target_user_id\",\n      \"method\": \"DELETE\",\n      \"auth\": [\"oauth1\", \"oauth2-user\"],\n      \"folder\": \"users\",\n      \"files\": {\n        \"python\": \"unmute.py\"\n      },\n      \"docs\": \"https://developer.x.com/en/docs/twitter-api/users/mutes/api-reference/delete-users-user_id-muting\"\n    },\n    {\n      \"name\": \"Muted Users\",\n      \"path\": \"/users/:id/muting\",\n      \"method\": \"GET\",\n      \"auth\": [\"oauth1\", \"oauth2-user\"],\n      \"folder\": \"users\",\n      \"files\": {\n        \"python\": \"muted.py\"\n      },\n      \"docs\": \"https://developer.x.com/en/docs/twitter-api/users/mutes/api-reference/get-users-muting\"\n    },\n    {\n      \"name\": \"User Posts Timeline\",\n      \"path\": \"/users/:id/tweets\",\n      \"method\": \"GET\",\n      \"auth\": [\"bearer\", \"oauth2-user\"],\n      \"folder\": \"timelines\",\n      \"files\": {\n        \"python\": \"user_posts.py\",\n        \"javascript\": \"user_posts.js\",\n        \"ruby\": \"user_posts.rb\"\n      },\n      \"docs\": \"https://developer.x.com/en/docs/twitter-api/tweets/timelines/api-reference/get-users-id-tweets\"\n    },\n    {\n      \"name\": \"User Mentions Timeline\",\n      \"path\": \"/users/:id/mentions\",\n      \"method\": \"GET\",\n      \"auth\": [\"bearer\", \"oauth2-user\"],\n      \"folder\": \"timelines\",\n      \"files\": {\n        \"python\": \"user_mentions.py\"\n      },\n      \"docs\": \"https://developer.x.com/en/docs/twitter-api/tweets/timelines/api-reference/get-users-id-mentions\"\n    },\n    {\n      \"name\": \"Home Timeline\",\n      \"path\": \"/users/:id/reverse_chronological_timeline\",\n      \"method\": \"GET\",\n      \"auth\": [\"oauth1\", \"oauth2-user\"],\n      \"folder\": \"timelines\",\n      \"files\": {\n        \"python\": \"home_timeline.py\"\n      },\n      \"docs\": \"https://developer.x.com/en/docs/twitter-api/tweets/timelines/api-reference/get-users-id-reverse-chronological-timeline\"\n    },\n    {\n      \"name\": \"Filtered Stream\",\n      \"path\": \"/tweets/search/stream\",\n      \"method\": \"GET\",\n      \"auth\": [\"bearer\"],\n      \"folder\": \"streams\",\n      \"files\": {\n        \"python\": \"filtered_stream.py\",\n        \"javascript\": \"filtered_stream.js\"\n      },\n      \"docs\": \"https://developer.x.com/en/docs/twitter-api/tweets/filtered-stream/api-reference/get-tweets-search-stream\"\n    },\n    {\n      \"name\": \"Sampled Stream\",\n      \"path\": \"/tweets/sample/stream\",\n      \"method\": \"GET\",\n      \"auth\": [\"bearer\"],\n      \"folder\": \"streams\",\n      \"files\": {\n        \"python\": \"sampled_stream.py\"\n      },\n      \"docs\": \"https://developer.x.com/en/docs/twitter-api/tweets/volume-streams/api-reference/get-tweets-sample-stream\"\n    },\n    {\n      \"name\": \"Bookmarks Lookup\",\n      \"path\": \"/users/:id/bookmarks\",\n      \"method\": \"GET\",\n      \"auth\": [\"oauth2-user\"],\n      \"folder\": \"bookmarks\",\n      \"files\": {\n        \"python\": \"lookup.py\"\n      },\n      \"docs\": \"https://developer.x.com/en/docs/twitter-api/tweets/bookmarks/api-reference/get-users-id-bookmarks\"\n    },\n    {\n      \"name\": \"Create Bookmark\",\n      \"path\": \"/users/:id/bookmarks\",\n      \"method\": \"POST\",\n      \"auth\": [\"oauth2-user\"],\n      \"folder\": \"bookmarks\",\n      \"files\": {\n        \"python\": \"create.py\"\n      },\n      \"docs\": \"https://developer.x.com/en/docs/twitter-api/tweets/bookmarks/api-reference/post-users-id-bookmarks\"\n    },\n    {\n      \"name\": \"Delete Bookmark\",\n      \"path\": \"/users/:id/bookmarks/:tweet_id\",\n      \"method\": \"DELETE\",\n      \"auth\": [\"oauth2-user\"],\n      \"folder\": \"bookmarks\",\n      \"files\": {\n        \"python\": \"delete.py\"\n      },\n      \"docs\": \"https://developer.x.com/en/docs/twitter-api/tweets/bookmarks/api-reference/delete-users-id-bookmarks-tweet_id\"\n    },\n    {\n      \"name\": \"Spaces Lookup\",\n      \"path\": \"/spaces\",\n      \"method\": \"GET\",\n      \"auth\": [\"bearer\", \"oauth2-user\"],\n      \"folder\": \"spaces\",\n      \"files\": {\n        \"python\": \"lookup.py\",\n        \"javascript\": \"lookup.js\"\n      },\n      \"docs\": \"https://developer.x.com/en/docs/twitter-api/spaces/lookup/api-reference/get-spaces\"\n    },\n    {\n      \"name\": \"Spaces Search\",\n      \"path\": \"/spaces/search\",\n      \"method\": \"GET\",\n      \"auth\": [\"bearer\", \"oauth2-user\"],\n      \"folder\": \"spaces\",\n      \"files\": {\n        \"python\": \"search.py\"\n      },\n      \"docs\": \"https://developer.x.com/en/docs/twitter-api/spaces/search/api-reference/get-spaces-search\"\n    },\n    {\n      \"name\": \"List Lookup\",\n      \"path\": \"/lists/:id\",\n      \"method\": \"GET\",\n      \"auth\": [\"bearer\", \"oauth2-user\"],\n      \"folder\": \"lists\",\n      \"files\": {\n        \"python\": \"lookup.py\",\n        \"javascript\": \"lookup.js\",\n        \"ruby\": \"lookup.rb\"\n      },\n      \"docs\": \"https://developer.x.com/en/docs/twitter-api/lists/list-lookup/api-reference/get-lists-id\"\n    },\n    {\n      \"name\": \"Create List\",\n      \"path\": \"/lists\",\n      \"method\": \"POST\",\n      \"auth\": [\"oauth1\", \"oauth2-user\"],\n      \"folder\": \"lists\",\n      \"files\": {\n        \"python\": \"create.py\"\n      },\n      \"docs\": \"https://developer.x.com/en/docs/twitter-api/lists/manage-lists/api-reference/post-lists\"\n    },\n    {\n      \"name\": \"Delete List\",\n      \"path\": \"/lists/:id\",\n      \"method\": \"DELETE\",\n      \"auth\": [\"oauth1\", \"oauth2-user\"],\n      \"folder\": \"lists\",\n      \"files\": {\n        \"python\": \"delete.py\"\n      },\n      \"docs\": \"https://developer.x.com/en/docs/twitter-api/lists/manage-lists/api-reference/delete-lists-id\"\n    },\n    {\n      \"name\": \"DM Events Lookup\",\n      \"path\": \"/dm_events\",\n      \"method\": \"GET\",\n      \"auth\": [\"oauth1\", \"oauth2-user\"],\n      \"folder\": \"direct_messages\",\n      \"files\": {\n        \"python\": \"lookup.py\"\n      },\n      \"docs\": \"https://developer.x.com/en/docs/twitter-api/direct-messages/lookup/api-reference/get-dm-events\"\n    },\n    {\n      \"name\": \"Send DM\",\n      \"path\": \"/dm_conversations/with/:participant_id/messages\",\n      \"method\": \"POST\",\n      \"auth\": [\"oauth1\", \"oauth2-user\"],\n      \"folder\": \"direct_messages\",\n      \"files\": {\n        \"python\": \"send.py\"\n      },\n      \"docs\": \"https://developer.x.com/en/docs/twitter-api/direct-messages/manage/api-reference/post-dm-conversations-with-participant_id-messages\"\n    },\n    {\n      \"name\": \"Create Compliance Job\",\n      \"path\": \"/compliance/jobs\",\n      \"method\": \"POST\",\n      \"auth\": [\"bearer\"],\n      \"folder\": \"compliance\",\n      \"files\": {\n        \"python\": \"create_job.py\"\n      },\n      \"docs\": \"https://developer.x.com/en/docs/twitter-api/compliance/batch-compliance/api-reference/post-compliance-jobs\"\n    },\n    {\n      \"name\": \"Get Compliance Jobs\",\n      \"path\": \"/compliance/jobs\",\n      \"method\": \"GET\",\n      \"auth\": [\"bearer\"],\n      \"folder\": \"compliance\",\n      \"files\": {\n        \"python\": \"get_jobs.py\"\n      },\n      \"docs\": \"https://developer.x.com/en/docs/twitter-api/compliance/batch-compliance/api-reference/get-compliance-jobs\"\n    },\n    {\n      \"name\": \"API Usage\",\n      \"path\": \"/usage/tweets\",\n      \"method\": \"GET\",\n      \"auth\": [\"bearer\"],\n      \"folder\": \"usage\",\n      \"files\": {\n        \"python\": \"get_usage.py\"\n      },\n      \"docs\": \"https://developer.x.com/en/docs/twitter-api/usage/api-reference/get-usage-tweets\"\n    }\n  ]\n}\n"
  },
  {
    "path": "java/README.md",
    "content": "# X API v2 - Java Examples\n\nWorking Java code samples for the X (formerly Twitter) API v2.\n\n## Setup\n\n### 1. Install Java 11+\n\n```bash\njava --version\n```\n\n### 2. Add dependencies\n\nUsing Maven, add to your `pom.xml`:\n\n```xml\n<dependencies>\n    <dependency>\n        <groupId>org.apache.httpcomponents</groupId>\n        <artifactId>httpclient</artifactId>\n        <version>4.5.13</version>\n    </dependency>\n    <dependency>\n        <groupId>com.google.code.gson</groupId>\n        <artifactId>gson</artifactId>\n        <version>2.9.1</version>\n    </dependency>\n</dependencies>\n```\n\n### 3. Set environment variables\n\n**For read-only operations (search, lookup):**\n```bash\nexport BEARER_TOKEN='your_bearer_token'\n```\n\n**For user actions (post, like, repost, bookmark, etc.):**\n```bash\nexport CLIENT_ID='your_client_id'\nexport CLIENT_SECRET='your_client_secret'\n```\n\n**Note:** Most user action examples require OAuth 2.0 authentication with `CLIENT_ID` and `CLIENT_SECRET`. Read-only examples (search, lookup) only require `BEARER_TOKEN`.\n\n## Examples by Category\n\n### Posts\n- `posts/FullArchiveSearchDemo.java` - Full archive search demo\n- `posts/FullArchiveTweetCountsDemo.java` - Full archive tweet counts demo\n- `posts/QuoteTweetsDemo.java` - Get posts that quote a post\n- `posts/RecentSearchDemo.java` - Recent search demo (last 7 days)\n- `posts/RecentTweetCountsDemo.java` - Recent tweet counts demo\n- `posts/SearchRecent.java` - Recent search (last 7 days)\n- `posts/TweetsDemo.java` - Look up posts by ID\n\n### Users\n- `users/FollowersLookupDemo.java` - Get user's followers\n- `users/FollowingLookupDemo.java` - Get users a user is following\n- `users/Lookup.java` - Look up users by username\n- `users/UsersDemo.java` - Users lookup demo\n\n### Timelines\n- `timelines/reverse-chron-home-timeline-java-sdk.java` - Get home timeline (reverse chronological)\n- `timelines/UserMentionsDemo.java` - Get user mentions timeline\n- `timelines/UserTweetsDemo.java` - Get user's posts timeline\n\n### Streams\n- `streams/FilteredStreamDemo.java` - Filtered stream with rules\n- `streams/SampledStream.java` - Sampled stream\n\n### Spaces\n- `spaces/SearchSpacesDemo.java` - Search for Spaces\n- `spaces/SpacesLookupDemo.java` - Look up Spaces by ID\n\n### Usage\n- `usage/UsageTweetsDemo.java` - Get API usage information\n\n## Building and Running\n\n### Compile\n\n```bash\n# Compile a single file\njavac -cp \".:lib/*\" posts/SearchRecent.java\n\n# Or compile all files\nfind . -name \"*.java\" -exec javac -cp \".:lib/*\" {} \\;\n```\n\n### Run\n\n```bash\n# Run a single example\njava -cp \".:lib/*\" posts.SearchRecent\n\n# Or with package structure\njava -cp \".:lib/*\" posts/RecentSearchDemo\n```\n\n## More Information\n\n- [X API Documentation](https://developer.x.com/en/docs/twitter-api)\n- [X Developer Portal](https://developer.x.com/en/portal/dashboard)\n"
  },
  {
    "path": "java/posts/FullArchiveSearchDemo.java",
    "content": "import java.io.IOException;\nimport java.net.URISyntaxException;\nimport java.util.ArrayList;\n\nimport org.apache.http.HttpEntity;\nimport org.apache.http.HttpResponse;\nimport org.apache.http.NameValuePair;\nimport org.apache.http.client.HttpClient;\nimport org.apache.http.client.config.CookieSpecs;\nimport org.apache.http.client.config.RequestConfig;\nimport org.apache.http.client.methods.HttpGet;\nimport org.apache.http.client.utils.URIBuilder;\nimport org.apache.http.impl.client.HttpClients;\nimport org.apache.http.message.BasicNameValuePair;\nimport org.apache.http.util.EntityUtils;\n\n/*\n * Sample code to demonstrate the use of the Full archive search endpoint\n * */\npublic class FullArchiveSearchDemo {\n\n  // To set your enviornment variables in your terminal run the following line:\n  // export 'BEARER_TOKEN'='<your_bearer_token>'\n\n  public static void main(String args[]) throws IOException, URISyntaxException {\n    String bearerToken = System.getenv(\"BEARER_TOKEN\");\n    if (null != bearerToken) {\n      //Replace the search term with a term of your choice\n      String response = search(\"from:TwitterDev OR from:SnowBotDev OR from:DailyNASA\", bearerToken);\n      System.out.println(response);\n    } else {\n      System.out.println(\"There was a problem getting your bearer token. Please make sure you set the BEARER_TOKEN environment variable\");\n    }\n  }\n\n  /*\n   * This method calls the full-archive search endpoint with a the search term passed to it as a query parameter\n   * */\n  private static String search(String searchString, String bearerToken) throws IOException, URISyntaxException {\n    String searchResponse = null;\n\n    HttpClient httpClient = HttpClients.custom()\n        .setDefaultRequestConfig(RequestConfig.custom()\n            .setCookieSpec(CookieSpecs.STANDARD).build())\n        .build();\n\n    URIBuilder uriBuilder = new URIBuilder(\"https://api.x.com/2/tweets/search/all\");\n    ArrayList<NameValuePair> queryParameters;\n    queryParameters = new ArrayList<>();\n    queryParameters.add(new BasicNameValuePair(\"query\", searchString));\n    uriBuilder.addParameters(queryParameters);\n\n    HttpGet httpGet = new HttpGet(uriBuilder.build());\n    httpGet.setHeader(\"Authorization\", String.format(\"Bearer %s\", bearerToken));\n    httpGet.setHeader(\"Content-Type\", \"application/json\");\n\n    HttpResponse response = httpClient.execute(httpGet);\n    HttpEntity entity = response.getEntity();\n    if (null != entity) {\n      searchResponse = EntityUtils.toString(entity, \"UTF-8\");\n    }\n    return searchResponse;\n  }\n\n}"
  },
  {
    "path": "java/posts/FullArchiveTweetCountsDemo.java",
    "content": "import java.io.IOException;\nimport java.net.URISyntaxException;\nimport java.util.ArrayList;\n\nimport org.apache.http.HttpEntity;\nimport org.apache.http.HttpResponse;\nimport org.apache.http.NameValuePair;\nimport org.apache.http.client.HttpClient;\nimport org.apache.http.client.config.CookieSpecs;\nimport org.apache.http.client.config.RequestConfig;\nimport org.apache.http.client.methods.HttpGet;\nimport org.apache.http.client.utils.URIBuilder;\nimport org.apache.http.impl.client.HttpClients;\nimport org.apache.http.message.BasicNameValuePair;\nimport org.apache.http.util.EntityUtils;\n\n/*\n * Sample code to demonstrate the use of the Full-archive Tweet counts endpoint\n * */\npublic class FullArchiveTweetCountsDemo {\n\n  // To set your enviornment variables in your terminal run the following line:\n  // export 'BEARER_TOKEN'='<your_bearer_token>'\n\n  public static void main(String args[]) throws IOException, URISyntaxException {\n    String bearerToken = System.getenv(\"BEARER_TOKEN\");\n    if (null != bearerToken) {\n      //Replace the search term with a term of your choice\n      String response = getTweetCounts(\"from:TwitterDev\", bearerToken);\n      System.out.println(response);\n    } else {\n      System.out.println(\"There was a problem getting your bearer token. Please make sure you set the BEARER_TOKEN environment variable\");\n    }\n  }\n\n  /*\n   * This method calls the full-archive Tweet counts endpoint with a the search term passed to it as a query parameter\n   * */\n  private static String getTweetCounts(String searchString, String bearerToken) throws IOException, URISyntaxException {\n    String searchResponse = null;\n\n    HttpClient httpClient = HttpClients.custom()\n        .setDefaultRequestConfig(RequestConfig.custom()\n            .setCookieSpec(CookieSpecs.STANDARD).build())\n        .build();\n\n    URIBuilder uriBuilder = new URIBuilder(\"https://api.x.com/2/tweets/counts/all\");\n    ArrayList<NameValuePair> queryParameters;\n    queryParameters = new ArrayList<>();\n    queryParameters.add(new BasicNameValuePair(\"query\", searchString));\n    queryParameters.add(new BasicNameValuePair(\"granularity\", \"day\"));\n    queryParameters.add(new BasicNameValuePair(\"start_time\", \"2021-01-01T00:00:00Z\"));\n    uriBuilder.addParameters(queryParameters);\n\n    HttpGet httpGet = new HttpGet(uriBuilder.build());\n    httpGet.setHeader(\"Authorization\", String.format(\"Bearer %s\", bearerToken));\n    httpGet.setHeader(\"Content-Type\", \"application/json\");\n\n    HttpResponse response = httpClient.execute(httpGet);\n    HttpEntity entity = response.getEntity();\n    if (null != entity) {\n      searchResponse = EntityUtils.toString(entity, \"UTF-8\");\n    }\n    return searchResponse;\n  }\n\n}"
  },
  {
    "path": "java/posts/QuoteTweetsDemo.java",
    "content": "import org.apache.http.HttpEntity;\nimport org.apache.http.HttpResponse;\nimport org.apache.http.NameValuePair;\nimport org.apache.http.client.HttpClient;\nimport org.apache.http.client.config.CookieSpecs;\nimport org.apache.http.client.config.RequestConfig;\nimport org.apache.http.client.methods.HttpGet;\nimport org.apache.http.client.utils.URIBuilder;\nimport org.apache.http.impl.client.HttpClients;\nimport org.apache.http.message.BasicNameValuePair;\nimport org.apache.http.util.EntityUtils;\n\nimport java.io.IOException;\nimport java.net.URISyntaxException;\nimport java.util.ArrayList;\n\n/*\n * Sample code to demonstrate the use of the v2 Quote Tweets endpoint\n * */\npublic class QuoteTweetsDemo {\n\n  // To set your environment variables in your terminal run the following line:\n  // export 'BEARER_TOKEN'='<your_bearer_token>'\n\n  public static void main(String args[]) throws IOException, URISyntaxException {\n    final String bearerToken = System.getenv(\"BEARER_TOKEN\");\n    if (null != bearerToken) {\n      //Replace with Tweet ID below\n      String response = getTweets(20, bearerToken);\n      System.out.println(response);\n    } else {\n      System.out.println(\"There was a problem getting your bearer token. Please make sure you set the BEARER_TOKEN environment variable\");\n    }\n  }\n\n  /*\n   * This method calls the v2 Quote Tweets endpoint by Tweet ID\n   * */\n  private static String getTweets(int tweetId, String bearerToken) throws IOException, URISyntaxException {\n    String tweetResponse = null;\n\n    HttpClient httpClient = HttpClients.custom()\n        .setDefaultRequestConfig(RequestConfig.custom()\n            .setCookieSpec(CookieSpecs.STANDARD).build())\n        .build();\n\n    URIBuilder uriBuilder = new URIBuilder(String.format(\"https://api.x.com/2/tweets/%s/quote_tweets\", tweetId));\n    ArrayList<NameValuePair> queryParameters;\n    queryParameters = new ArrayList<>();\n    queryParameters.add(new BasicNameValuePair(\"tweet.fields\", \"created_at\"));\n    uriBuilder.addParameters(queryParameters);\n\n    HttpGet httpGet = new HttpGet(uriBuilder.build());\n    httpGet.setHeader(\"Authorization\", String.format(\"Bearer %s\", bearerToken));\n    httpGet.setHeader(\"Content-Type\", \"application/json\");\n\n    HttpResponse response = httpClient.execute(httpGet);\n    HttpEntity entity = response.getEntity();\n    if (null != entity) {\n      tweetResponse = EntityUtils.toString(entity, \"UTF-8\");\n    }\n    return tweetResponse;\n  }\n}\n"
  },
  {
    "path": "java/posts/RecentSearchDemo.java",
    "content": "import java.io.IOException;\nimport java.net.URISyntaxException;\nimport java.util.ArrayList;\n\nimport org.apache.http.HttpEntity;\nimport org.apache.http.HttpResponse;\nimport org.apache.http.NameValuePair;\nimport org.apache.http.client.HttpClient;\nimport org.apache.http.client.config.CookieSpecs;\nimport org.apache.http.client.config.RequestConfig;\nimport org.apache.http.client.methods.HttpGet;\nimport org.apache.http.client.utils.URIBuilder;\nimport org.apache.http.impl.client.HttpClients;\nimport org.apache.http.message.BasicNameValuePair;\nimport org.apache.http.util.EntityUtils;\n\n/*\n * Sample code to demonstrate the use of the Recent search endpoint\n * */\npublic class RecentSearchDemo {\n\n  // To set your enviornment variables in your terminal run the following line:\n  // export 'BEARER_TOKEN'='<your_bearer_token>'\n\n  public static void main(String args[]) throws IOException, URISyntaxException {\n    String bearerToken = System.getenv(\"BEARER_TOKEN\");\n    if (null != bearerToken) {\n      //Replace the search term with a term of your choice\n      String response = search(\"from:TwitterDev OR from:SnowBotDev OR from:DailyNASA\", bearerToken);\n      System.out.println(response);\n    } else {\n      System.out.println(\"There was a problem getting you bearer token. Please make sure you set the BEARER_TOKEN environment variable\");\n    }\n  }\n\n  /*\n   * This method calls the recent search endpoint with a the search term passed to it as a query parameter\n   * */\n  private static String search(String searchString, String bearerToken) throws IOException, URISyntaxException {\n    String searchResponse = null;\n\n    HttpClient httpClient = HttpClients.custom()\n        .setDefaultRequestConfig(RequestConfig.custom()\n            .setCookieSpec(CookieSpecs.STANDARD).build())\n        .build();\n\n    URIBuilder uriBuilder = new URIBuilder(\"https://api.x.com/2/tweets/search/recent\");\n    ArrayList<NameValuePair> queryParameters;\n    queryParameters = new ArrayList<>();\n    queryParameters.add(new BasicNameValuePair(\"query\", searchString));\n    uriBuilder.addParameters(queryParameters);\n\n    HttpGet httpGet = new HttpGet(uriBuilder.build());\n    httpGet.setHeader(\"Authorization\", String.format(\"Bearer %s\", bearerToken));\n    httpGet.setHeader(\"Content-Type\", \"application/json\");\n\n    HttpResponse response = httpClient.execute(httpGet);\n    HttpEntity entity = response.getEntity();\n    if (null != entity) {\n      searchResponse = EntityUtils.toString(entity, \"UTF-8\");\n    }\n    return searchResponse;\n  }\n\n}"
  },
  {
    "path": "java/posts/RecentTweetCountsDemo.java",
    "content": "import java.io.IOException;\nimport java.net.URISyntaxException;\nimport java.util.ArrayList;\n\nimport org.apache.http.HttpEntity;\nimport org.apache.http.HttpResponse;\nimport org.apache.http.NameValuePair;\nimport org.apache.http.client.HttpClient;\nimport org.apache.http.client.config.CookieSpecs;\nimport org.apache.http.client.config.RequestConfig;\nimport org.apache.http.client.methods.HttpGet;\nimport org.apache.http.client.utils.URIBuilder;\nimport org.apache.http.impl.client.HttpClients;\nimport org.apache.http.message.BasicNameValuePair;\nimport org.apache.http.util.EntityUtils;\n\n/*\n * Sample code to demonstrate the use of the Recent Tweet counts endpoint\n * */\npublic class RecentTweetCountsDemo {\n\n  // To set your enviornment variables in your terminal run the following line:\n  // export 'BEARER_TOKEN'='<your_bearer_token>'\n\n  public static void main(String args[]) throws IOException, URISyntaxException {\n    String bearerToken = System.getenv(\"BEARER_TOKEN\");\n    if (null != bearerToken) {\n      //Replace the search term with a term of your choice\n      String response = getTweetCounts(\"from:TwitterDev\", bearerToken);\n      System.out.println(response);\n    } else {\n      System.out.println(\"There was a problem getting you bearer token. Please make sure you set the BEARER_TOKEN environment variable\");\n    }\n  }\n\n  /*\n   * This method calls the recent Tweet counts endpoint with a the search term passed to it as a query parameter\n   * */\n  private static String getTweetCounts(String searchString, String bearerToken) throws IOException, URISyntaxException {\n    String searchResponse = null;\n\n    HttpClient httpClient = HttpClients.custom()\n        .setDefaultRequestConfig(RequestConfig.custom()\n            .setCookieSpec(CookieSpecs.STANDARD).build())\n        .build();\n\n    URIBuilder uriBuilder = new URIBuilder(\"https://api.x.com/2/tweets/counts/recent\");\n    ArrayList<NameValuePair> queryParameters;\n    queryParameters = new ArrayList<>();\n    queryParameters.add(new BasicNameValuePair(\"query\", searchString));\n    queryParameters.add(new BasicNameValuePair(\"granularity\", \"day\"));\n    uriBuilder.addParameters(queryParameters);\n\n    HttpGet httpGet = new HttpGet(uriBuilder.build());\n    httpGet.setHeader(\"Authorization\", String.format(\"Bearer %s\", bearerToken));\n    httpGet.setHeader(\"Content-Type\", \"application/json\");\n\n    HttpResponse response = httpClient.execute(httpGet);\n    HttpEntity entity = response.getEntity();\n    if (null != entity) {\n      searchResponse = EntityUtils.toString(entity, \"UTF-8\");\n    }\n    return searchResponse;\n  }\n\n}"
  },
  {
    "path": "java/posts/SearchRecent.java",
    "content": "/**\n * Recent Search - X API v2\n * \n * Endpoint: GET https://api.x.com/2/tweets/search/recent\n * Docs: https://developer.x.com/en/docs/twitter-api/tweets/search/api-reference/get-tweets-search-recent\n * \n * Authentication: Bearer Token (App-only)\n * Required env vars: BEARER_TOKEN\n * \n * Dependencies: org.apache.httpcomponents:httpclient, com.google.code.gson:gson\n */\n\nimport java.io.IOException;\nimport java.net.URISyntaxException;\nimport org.apache.http.HttpEntity;\nimport org.apache.http.HttpResponse;\nimport org.apache.http.client.HttpClient;\nimport org.apache.http.client.config.CookieSpecs;\nimport org.apache.http.client.config.RequestConfig;\nimport org.apache.http.client.methods.HttpGet;\nimport org.apache.http.client.utils.URIBuilder;\nimport org.apache.http.impl.client.HttpClients;\nimport org.apache.http.util.EntityUtils;\n\npublic class SearchRecent {\n\n    public static void main(String[] args) throws IOException, URISyntaxException {\n        String bearerToken = System.getenv(\"BEARER_TOKEN\");\n        \n        if (bearerToken == null) {\n            System.err.println(\"BEARER_TOKEN environment variable not set\");\n            System.exit(1);\n        }\n\n        String response = search(\"from:XDevelopers -is:retweet\", bearerToken);\n        System.out.println(response);\n    }\n\n    private static String search(String query, String bearerToken) throws IOException, URISyntaxException {\n        String searchUrl = \"https://api.x.com/2/tweets/search/recent\";\n\n        HttpClient httpClient = HttpClients.custom()\n                .setDefaultRequestConfig(RequestConfig.custom()\n                        .setCookieSpec(CookieSpecs.STANDARD).build())\n                .build();\n\n        URIBuilder uriBuilder = new URIBuilder(searchUrl);\n        uriBuilder.addParameter(\"query\", query);\n        uriBuilder.addParameter(\"tweet.fields\", \"author_id,created_at\");\n\n        HttpGet httpGet = new HttpGet(uriBuilder.build());\n        httpGet.setHeader(\"Authorization\", \"Bearer \" + bearerToken);\n        httpGet.setHeader(\"User-Agent\", \"v2RecentSearchJava\");\n\n        HttpResponse response = httpClient.execute(httpGet);\n        HttpEntity entity = response.getEntity();\n        \n        if (entity != null) {\n            return EntityUtils.toString(entity, \"UTF-8\");\n        } else {\n            return \"No response\";\n        }\n    }\n}\n"
  },
  {
    "path": "java/posts/TweetsDemo.java",
    "content": "import org.apache.http.HttpEntity;\nimport org.apache.http.HttpResponse;\nimport org.apache.http.NameValuePair;\nimport org.apache.http.client.HttpClient;\nimport org.apache.http.client.config.CookieSpecs;\nimport org.apache.http.client.config.RequestConfig;\nimport org.apache.http.client.methods.HttpGet;\nimport org.apache.http.client.utils.URIBuilder;\nimport org.apache.http.impl.client.HttpClients;\nimport org.apache.http.message.BasicNameValuePair;\nimport org.apache.http.util.EntityUtils;\n\nimport java.io.IOException;\nimport java.net.URISyntaxException;\nimport java.util.ArrayList;\n\n/*\n * Sample code to demonstrate the use of the v2 Tweets endpoint\n * */\npublic class TweetsDemo {\n\n  // To set your enviornment variables in your terminal run the following line:\n  // export 'BEARER_TOKEN'='<your_bearer_token>'\n\n  public static void main(String args[]) throws IOException, URISyntaxException {\n    String bearerToken = System.getenv(\"BEARER_TOKEN\");\n    if (null != bearerToken) {\n      //Replace comma separated ids with Tweets Ids of your choice\n      String response = getTweets(\"1138505981460193280,1261326399320715264\", bearerToken);\n      System.out.println(response);\n    } else {\n      System.out.println(\"There was a problem getting you bearer token. Please make sure you set the BEARER_TOKEN environment variable\");\n    }\n  }\n\n  /*\n   * This method calls the v2 Tweets endpoint with ids as query parameter\n   * */\n  private static String getTweets(String ids, String bearerToken) throws IOException, URISyntaxException {\n    String tweetResponse = null;\n\n    HttpClient httpClient = HttpClients.custom()\n        .setDefaultRequestConfig(RequestConfig.custom()\n            .setCookieSpec(CookieSpecs.STANDARD).build())\n        .build();\n\n    URIBuilder uriBuilder = new URIBuilder(\"https://api.x.com/2/tweets\");\n    ArrayList<NameValuePair> queryParameters;\n    queryParameters = new ArrayList<>();\n    queryParameters.add(new BasicNameValuePair(\"ids\", ids));\n    queryParameters.add(new BasicNameValuePair(\"tweet.fields\", \"created_at\"));\n    uriBuilder.addParameters(queryParameters);\n\n    HttpGet httpGet = new HttpGet(uriBuilder.build());\n    httpGet.setHeader(\"Authorization\", String.format(\"Bearer %s\", bearerToken));\n    httpGet.setHeader(\"Content-Type\", \"application/json\");\n\n    HttpResponse response = httpClient.execute(httpGet);\n    HttpEntity entity = response.getEntity();\n    if (null != entity) {\n      tweetResponse = EntityUtils.toString(entity, \"UTF-8\");\n    }\n    return tweetResponse;\n  }\n}"
  },
  {
    "path": "java/spaces/SearchSpacesDemo.java",
    "content": "import java.io.IOException;\nimport java.net.URISyntaxException;\nimport java.util.ArrayList;\n\nimport org.apache.http.HttpEntity;\nimport org.apache.http.HttpResponse;\nimport org.apache.http.NameValuePair;\nimport org.apache.http.client.HttpClient;\nimport org.apache.http.client.config.CookieSpecs;\nimport org.apache.http.client.config.RequestConfig;\nimport org.apache.http.client.methods.HttpGet;\nimport org.apache.http.client.utils.URIBuilder;\nimport org.apache.http.impl.client.HttpClients;\nimport org.apache.http.message.BasicNameValuePair;\nimport org.apache.http.util.EntityUtils;\n\n/*\n * Sample code to demonstrate the use of the Spaces lookup endpoint\n * */\npublic class SpacesLookupDemo {\n\n  // To set your enviornment variables in your terminal run the following line:\n  // export 'BEARER_TOKEN'='<your_bearer_token>'\n\n  public static void main(String args[]) throws IOException, URISyntaxException {\n    String bearerToken = System.getenv(\"BEARER_TOKEN\");\n    if (null != bearerToken) {\n      //Replace SPACE_ID with the ID of a Space\n      String response = getSpaceById(\"SPACE_ID\", bearerToken);\n      System.out.println(response);\n    } else {\n      System.out.println(\"There was a problem getting your bearer token. Please make sure you set the BEARER_TOKEN environment variable\");\n    }\n  }\n\n  /*\n   * This method calls the Spaces lookup endpoint with the ID passed to it as a query parameter\n   * */\n  private static String getSpaceById(String spaceId, String bearerToken) throws IOException, URISyntaxException {\n    String searchResponse = null;\n\n    HttpClient httpClient = HttpClients.custom()\n        .setDefaultRequestConfig(RequestConfig.custom()\n            .setCookieSpec(CookieSpecs.STANDARD).build())\n        .build();\n\n    URIBuilder uriBuilder = new URIBuilder(\"https://api.x.com/2/spaces\");\n    ArrayList<NameValuePair> queryParameters;\n    queryParameters = new ArrayList<>();\n    queryParameters.add(new BasicNameValuePair(\"ids\", spaceId));\n    uriBuilder.addParameters(queryParameters);\n\n    HttpGet httpGet = new HttpGet(uriBuilder.build());\n    httpGet.setHeader(\"Authorization\", String.format(\"Bearer %s\", bearerToken));\n    httpGet.setHeader(\"User-Agent\", \"v2SpacesLookupJava\");\n    httpGet.setHeader(\"Content-Type\", \"application/json\");\n\n    HttpResponse response = httpClient.execute(httpGet);\n    HttpEntity entity = response.getEntity();\n    if (null != entity) {\n      searchResponse = EntityUtils.toString(entity, \"UTF-8\");\n    }\n    return searchResponse;\n  }\n\n}"
  },
  {
    "path": "java/spaces/SpacesLookupDemo.java",
    "content": "import java.io.IOException;\nimport java.net.URISyntaxException;\nimport java.util.ArrayList;\n\nimport org.apache.http.HttpEntity;\nimport org.apache.http.HttpResponse;\nimport org.apache.http.NameValuePair;\nimport org.apache.http.client.HttpClient;\nimport org.apache.http.client.config.CookieSpecs;\nimport org.apache.http.client.config.RequestConfig;\nimport org.apache.http.client.methods.HttpGet;\nimport org.apache.http.client.utils.URIBuilder;\nimport org.apache.http.impl.client.HttpClients;\nimport org.apache.http.message.BasicNameValuePair;\nimport org.apache.http.util.EntityUtils;\n\n/*\n * Sample code to demonstrate the use of the Spaces lookup endpoint\n * */\npublic class SpacesLookupDemo {\n\n  // To set your enviornment variables in your terminal run the following line:\n  // export 'BEARER_TOKEN'='<your_bearer_token>'\n\n  public static void main(String args[]) throws IOException, URISyntaxException {\n    String bearerToken = System.getenv(\"BEARER_TOKEN\");\n    if (null != bearerToken) {\n      //Replace SPACE_ID with the ID of a Space\n      String response = getSpaceById(\"SPACE_ID\", bearerToken);\n      System.out.println(response);\n    } else {\n      System.out.println(\"There was a problem getting your bearer token. Please make sure you set the BEARER_TOKEN environment variable\");\n    }\n  }\n\n  /*\n   * This method calls the Spaces lookup endpoint with the ID passed to it as a query parameter\n   * */\n  private static String getSpaceById(String spaceId, String bearerToken) throws IOException, URISyntaxException {\n    String searchResponse = null;\n\n    HttpClient httpClient = HttpClients.custom()\n        .setDefaultRequestConfig(RequestConfig.custom()\n            .setCookieSpec(CookieSpecs.STANDARD).build())\n        .build();\n\n    URIBuilder uriBuilder = new URIBuilder(\"https://api.x.com/2/spaces\");\n    ArrayList<NameValuePair> queryParameters;\n    queryParameters = new ArrayList<>();\n    queryParameters.add(new BasicNameValuePair(\"ids\", spaceId));\n    uriBuilder.addParameters(queryParameters);\n\n    HttpGet httpGet = new HttpGet(uriBuilder.build());\n    httpGet.setHeader(\"Authorization\", String.format(\"Bearer %s\", bearerToken));\n    httpGet.setHeader(\"User-Agent\", \"v2SpacesLookupJava\");\n    httpGet.setHeader(\"Content-Type\", \"application/json\");\n\n    HttpResponse response = httpClient.execute(httpGet);\n    HttpEntity entity = response.getEntity();\n    if (null != entity) {\n      searchResponse = EntityUtils.toString(entity, \"UTF-8\");\n    }\n    return searchResponse;\n  }\n\n}"
  },
  {
    "path": "java/streams/FilteredStreamDemo.java",
    "content": "import org.apache.http.HttpEntity;\nimport org.apache.http.HttpResponse;\nimport org.apache.http.client.HttpClient;\nimport org.apache.http.client.config.CookieSpecs;\nimport org.apache.http.client.config.RequestConfig;\nimport org.apache.http.client.methods.HttpGet;\nimport org.apache.http.client.methods.HttpPost;\nimport org.apache.http.client.utils.URIBuilder;\nimport org.apache.http.entity.StringEntity;\nimport org.apache.http.impl.client.HttpClients;\nimport org.apache.http.util.EntityUtils;\nimport org.json.JSONArray;\nimport org.json.JSONObject;\n\nimport java.io.*;\nimport java.net.URISyntaxException;\nimport java.util.*;\n\n/*\n * Sample code to demonstrate the use of the Filtered Stream endpoint\n * */\npublic class FilteredStreamDemo {\n  // To set your enviornment variables in your terminal run the following line:\n  // export 'BEARER_TOKEN'='<your_bearer_token>'\n\n  public static void main(String args[]) throws IOException, URISyntaxException {\n    String bearerToken = System.getenv(\"BEARER_TOKEN\");\n    if (null != bearerToken) {\n      Map<String, String> rules = new HashMap<>();\n      rules.put(\"cats has:images\", \"cat images\");\n      rules.put(\"dogs has:images\", \"dog images\");\n      setupRules(bearerToken, rules);\n      connectStream(bearerToken);\n    } else {\n      System.out.println(\"There was a problem getting your bearer token. Please make sure you set the BEARER_TOKEN environment variable\");\n    }\n  }\n\n  /*\n   * This method calls the filtered stream endpoint and streams Tweets from it\n   * */\n  private static void connectStream(String bearerToken) throws IOException, URISyntaxException {\n\n    HttpClient httpClient = HttpClients.custom()\n        .setDefaultRequestConfig(RequestConfig.custom()\n            .setCookieSpec(CookieSpecs.STANDARD).build())\n        .build();\n\n    URIBuilder uriBuilder = new URIBuilder(\"https://api.x.com/2/tweets/search/stream\");\n\n    HttpGet httpGet = new HttpGet(uriBuilder.build());\n    httpGet.setHeader(\"Authorization\", String.format(\"Bearer %s\", bearerToken));\n\n    HttpResponse response = httpClient.execute(httpGet);\n    HttpEntity entity = response.getEntity();\n    if (null != entity) {\n      BufferedReader reader = new BufferedReader(new InputStreamReader((entity.getContent())));\n      String line = reader.readLine();\n      while (line != null) {\n        System.out.println(line);\n        line = reader.readLine();\n      }\n    }\n\n  }\n\n  /*\n   * Helper method to setup rules before streaming data\n   * */\n  private static void setupRules(String bearerToken, Map<String, String> rules) throws IOException, URISyntaxException {\n    List<String> existingRules = getRules(bearerToken);\n    if (existingRules.size() > 0) {\n      deleteRules(bearerToken, existingRules);\n    }\n    createRules(bearerToken, rules);\n  }\n\n  /*\n   * Helper method to create rules for filtering\n   * */\n  private static void createRules(String bearerToken, Map<String, String> rules) throws URISyntaxException, IOException {\n    HttpClient httpClient = HttpClients.custom()\n        .setDefaultRequestConfig(RequestConfig.custom()\n            .setCookieSpec(CookieSpecs.STANDARD).build())\n        .build();\n\n    URIBuilder uriBuilder = new URIBuilder(\"https://api.x.com/2/tweets/search/stream/rules\");\n\n    HttpPost httpPost = new HttpPost(uriBuilder.build());\n    httpPost.setHeader(\"Authorization\", String.format(\"Bearer %s\", bearerToken));\n    httpPost.setHeader(\"content-type\", \"application/json\");\n    StringEntity body = new StringEntity(getFormattedString(\"{\\\"add\\\": [%s]}\", rules));\n    httpPost.setEntity(body);\n    HttpResponse response = httpClient.execute(httpPost);\n    HttpEntity entity = response.getEntity();\n    if (null != entity) {\n      System.out.println(EntityUtils.toString(entity, \"UTF-8\"));\n    }\n  }\n\n  /*\n   * Helper method to get existing rules\n   * */\n  private static List<String> getRules(String bearerToken) throws URISyntaxException, IOException {\n    List<String> rules = new ArrayList<>();\n    HttpClient httpClient = HttpClients.custom()\n        .setDefaultRequestConfig(RequestConfig.custom()\n            .setCookieSpec(CookieSpecs.STANDARD).build())\n        .build();\n\n    URIBuilder uriBuilder = new URIBuilder(\"https://api.x.com/2/tweets/search/stream/rules\");\n\n    HttpGet httpGet = new HttpGet(uriBuilder.build());\n    httpGet.setHeader(\"Authorization\", String.format(\"Bearer %s\", bearerToken));\n    httpGet.setHeader(\"content-type\", \"application/json\");\n    HttpResponse response = httpClient.execute(httpGet);\n    HttpEntity entity = response.getEntity();\n    if (null != entity) {\n      JSONObject json = new JSONObject(EntityUtils.toString(entity, \"UTF-8\"));\n      if (json.length() > 1) {\n        JSONArray array = (JSONArray) json.get(\"data\");\n        for (int i = 0; i < array.length(); i++) {\n          JSONObject jsonObject = (JSONObject) array.get(i);\n          rules.add(jsonObject.getString(\"id\"));\n        }\n      }\n    }\n    return rules;\n  }\n\n  /*\n   * Helper method to delete rules\n   * */\n  private static void deleteRules(String bearerToken, List<String> existingRules) throws URISyntaxException, IOException {\n    HttpClient httpClient = HttpClients.custom()\n        .setDefaultRequestConfig(RequestConfig.custom()\n            .setCookieSpec(CookieSpecs.STANDARD).build())\n        .build();\n\n    URIBuilder uriBuilder = new URIBuilder(\"https://api.x.com/2/tweets/search/stream/rules\");\n\n    HttpPost httpPost = new HttpPost(uriBuilder.build());\n    httpPost.setHeader(\"Authorization\", String.format(\"Bearer %s\", bearerToken));\n    httpPost.setHeader(\"content-type\", \"application/json\");\n    StringEntity body = new StringEntity(getFormattedString(\"{ \\\"delete\\\": { \\\"ids\\\": [%s]}}\", existingRules));\n    httpPost.setEntity(body);\n    HttpResponse response = httpClient.execute(httpPost);\n    HttpEntity entity = response.getEntity();\n    if (null != entity) {\n      System.out.println(EntityUtils.toString(entity, \"UTF-8\"));\n    }\n  }\n\n  private static String getFormattedString(String string, List<String> ids) {\n    StringBuilder sb = new StringBuilder();\n    if (ids.size() == 1) {\n      return String.format(string, \"\\\"\" + ids.get(0) + \"\\\"\");\n    } else {\n      for (String id : ids) {\n        sb.append(\"\\\"\" + id + \"\\\"\" + \",\");\n      }\n      String result = sb.toString();\n      return String.format(string, result.substring(0, result.length() - 1));\n    }\n  }\n\n  private static String getFormattedString(String string, Map<String, String> rules) {\n    StringBuilder sb = new StringBuilder();\n    if (rules.size() == 1) {\n      String key = rules.keySet().iterator().next();\n      return String.format(string, \"{\\\"value\\\": \\\"\" + key + \"\\\", \\\"tag\\\": \\\"\" + rules.get(key) + \"\\\"}\");\n    } else {\n      for (Map.Entry<String, String> entry : rules.entrySet()) {\n        String value = entry.getKey();\n        String tag = entry.getValue();\n        sb.append(\"{\\\"value\\\": \\\"\" + value + \"\\\", \\\"tag\\\": \\\"\" + tag + \"\\\"}\" + \",\");\n      }\n      String result = sb.toString();\n      return String.format(string, result.substring(0, result.length() - 1));\n    }\n  }\n\n}\n"
  },
  {
    "path": "java/streams/SampledStream.java",
    "content": "import org.apache.http.HttpEntity;\nimport org.apache.http.HttpResponse;\nimport org.apache.http.client.HttpClient;\nimport org.apache.http.client.config.CookieSpecs;\nimport org.apache.http.client.config.RequestConfig;\nimport org.apache.http.client.methods.HttpGet;\nimport org.apache.http.client.utils.URIBuilder;\nimport org.apache.http.impl.client.HttpClients;\n\nimport java.io.BufferedReader;\nimport java.io.IOException;\nimport java.io.InputStreamReader;\nimport java.net.URISyntaxException;\n\n/*\n * Sample code to demonstrate the use of the Sampled Stream endpoint\n * */\npublic class SampledStreamDemo {\n\n  // To set your enviornment variables in your terminal run the following line:\n  // export 'BEARER_TOKEN'='<your_bearer_token>'\n\n  public static void main(String args[]) throws IOException, URISyntaxException {\n    String bearerToken = System.getenv(\"BEARER_TOKEN\");\n    if (null != bearerToken) {\n      connectStream(bearerToken);\n    } else {\n      System.out.println(\"There was a problem getting your bearer token. Please make sure you set the BEARER_TOKEN environment variable\");\n    }\n\n  }\n\n  /*\n   * This method calls the sample stream endpoint and streams Tweets from it\n   * */\n  private static void connectStream(String bearerToken) throws IOException, URISyntaxException {\n\n    HttpClient httpClient = HttpClients.custom()\n        .setDefaultRequestConfig(RequestConfig.custom()\n            .setCookieSpec(CookieSpecs.STANDARD).build())\n        .build();\n\n    URIBuilder uriBuilder = new URIBuilder(\"https://api.x.com/2/tweets/sample/stream\");\n\n    HttpGet httpGet = new HttpGet(uriBuilder.build());\n    httpGet.setHeader(\"Authorization\", String.format(\"Bearer %s\", bearerToken));\n\n    HttpResponse response = httpClient.execute(httpGet);\n    HttpEntity entity = response.getEntity();\n    if (null != entity) {\n      BufferedReader reader = new BufferedReader(new InputStreamReader((entity.getContent())));\n      String line = reader.readLine();\n      while (line != null) {\n        System.out.println(line);\n        line = reader.readLine();\n      }\n    }\n\n  }\n}\n"
  },
  {
    "path": "java/timelines/UserMentionsDemo.java",
    "content": "import org.apache.http.HttpEntity;\nimport org.apache.http.HttpResponse;\nimport org.apache.http.NameValuePair;\nimport org.apache.http.client.HttpClient;\nimport org.apache.http.client.config.CookieSpecs;\nimport org.apache.http.client.config.RequestConfig;\nimport org.apache.http.client.methods.HttpGet;\nimport org.apache.http.client.utils.URIBuilder;\nimport org.apache.http.impl.client.HttpClients;\nimport org.apache.http.message.BasicNameValuePair;\nimport org.apache.http.util.EntityUtils;\n\nimport java.io.IOException;\nimport java.net.URISyntaxException;\nimport java.util.ArrayList;\n\n/*\n * Sample code to demonstrate the use of the v2 User Mentions timeline endpoint\n * */\npublic class UserMentionsDemo {\n\n  // To set your environment variables in your terminal run the following line:\n  // export 'BEARER_TOKEN'='<your_bearer_token>'\n\n  public static void main(String args[]) throws IOException, URISyntaxException {\n    final String bearerToken = System.getenv(\"BEARER_TOKEN\");\n    if (null != bearerToken) {\n      //Replace with user ID below\n      String response = getTweets(\"2244994945\", bearerToken);\n      System.out.println(response);\n    } else {\n      System.out.println(\"There was a problem getting your bearer token. Please make sure you set the BEARER_TOKEN environment variable\");\n    }\n  }\n\n  /*\n   * This method calls the v2 User Mentions timeline endpoint by user ID\n   * */\n  private static String getTweets(String userId, String bearerToken) throws IOException, URISyntaxException {\n    String tweetResponse = null;\n\n    HttpClient httpClient = HttpClients.custom()\n        .setDefaultRequestConfig(RequestConfig.custom()\n            .setCookieSpec(CookieSpecs.STANDARD).build())\n        .build();\n\n    URIBuilder uriBuilder = new URIBuilder(String.format(\"https://api.x.com/2/users/%s/mentions\", userId));\n    ArrayList<NameValuePair> queryParameters;\n    queryParameters = new ArrayList<>();\n    queryParameters.add(new BasicNameValuePair(\"tweet.fields\", \"created_at\"));\n    uriBuilder.addParameters(queryParameters);\n\n    HttpGet httpGet = new HttpGet(uriBuilder.build());\n    httpGet.setHeader(\"Authorization\", String.format(\"Bearer %s\", bearerToken));\n    httpGet.setHeader(\"Content-Type\", \"application/json\");\n\n    HttpResponse response = httpClient.execute(httpGet);\n    HttpEntity entity = response.getEntity();\n    if (null != entity) {\n      tweetResponse = EntityUtils.toString(entity, \"UTF-8\");\n    }\n    return tweetResponse;\n  }\n}\n"
  },
  {
    "path": "java/timelines/UserTweetsDemo.java",
    "content": "import org.apache.http.HttpEntity;\nimport org.apache.http.HttpResponse;\nimport org.apache.http.NameValuePair;\nimport org.apache.http.client.HttpClient;\nimport org.apache.http.client.config.CookieSpecs;\nimport org.apache.http.client.config.RequestConfig;\nimport org.apache.http.client.methods.HttpGet;\nimport org.apache.http.client.utils.URIBuilder;\nimport org.apache.http.impl.client.HttpClients;\nimport org.apache.http.message.BasicNameValuePair;\nimport org.apache.http.util.EntityUtils;\n\nimport java.io.IOException;\nimport java.net.URISyntaxException;\nimport java.util.ArrayList;\n\n/*\n * Sample code to demonstrate the use of the v2 User Tweet timeline endpoint\n * */\npublic class UserTweetsDemo {\n\n  // To set your environment variables in your terminal run the following line:\n  // export 'BEARER_TOKEN'='<your_bearer_token>'\n\n  public static void main(String args[]) throws IOException, URISyntaxException {\n    final String bearerToken = System.getenv(\"BEARER_TOKEN\");\n    if (null != bearerToken) {\n      // Replace with user ID below\n      String response = getTweets(\"2244994945\", bearerToken);\n      System.out.println(response);\n    } else {\n      System.out.println(\"There was a problem getting your bearer token. Please make sure you set the BEARER_TOKEN environment variable\");\n    }\n  }\n\n  /*\n   * This method calls the v2 User Tweet timeline endpoint by user ID\n   * */\n  private static String getTweets(String userId, String bearerToken) throws IOException, URISyntaxException {\n    String tweetResponse = null;\n\n    HttpClient httpClient = HttpClients.custom()\n        .setDefaultRequestConfig(RequestConfig.custom()\n            .setCookieSpec(CookieSpecs.STANDARD).build())\n        .build();\n\n    URIBuilder uriBuilder = new URIBuilder(String.format(\"https://api.x.com/2/users/%s/tweets\", userId));\n    ArrayList<NameValuePair> queryParameters;\n    queryParameters = new ArrayList<>();\n    queryParameters.add(new BasicNameValuePair(\"tweet.fields\", \"created_at\"));\n    uriBuilder.addParameters(queryParameters);\n\n    HttpGet httpGet = new HttpGet(uriBuilder.build());\n    httpGet.setHeader(\"Authorization\", String.format(\"Bearer %s\", bearerToken));\n    httpGet.setHeader(\"Content-Type\", \"application/json\");\n\n    HttpResponse response = httpClient.execute(httpGet);\n    HttpEntity entity = response.getEntity();\n    if (null != entity) {\n      tweetResponse = EntityUtils.toString(entity, \"UTF-8\");\n    }\n    return tweetResponse;\n  }\n}\n"
  },
  {
    "path": "java/timelines/reverse-chron-home-timeline-java-sdk.java",
    "content": "package com.twitter.clientlib.auth;\n\nimport java.util.HashSet;\nimport java.util.Scanner;\nimport java.util.Set;\n\nimport com.github.scribejava.core.model.OAuth2AccessToken;\nimport com.github.scribejava.core.pkce.PKCE;\nimport com.github.scribejava.core.pkce.PKCECodeChallengeMethod;\nimport com.twitter.clientlib.TwitterCredentialsBearer;\nimport com.twitter.clientlib.ApiClient;\nimport com.twitter.clientlib.ApiException;\nimport com.twitter.clientlib.Configuration;\nimport com.twitter.clientlib.auth.*;\nimport com.twitter.clientlib.model.*;\nimport com.twitter.clientlib.TwitterCredentialsOAuth2;\n\n\nimport com.twitter.clientlib.api.TwitterApi;\n\nimport com.twitter.clientlib.api.BookmarksApi;\nimport java.util.List;\nimport java.util.Set;\nimport java.util.Arrays;\nimport java.util.HashSet;\nimport java.time.OffsetDateTime;\nimport org.json.*;\n\n/**\n* This is an example of getting an OAuth2 access token and using it to call an API.\n* It's expected to set TWITTER_OAUTH2_CLIENT_ID & TWITTER_OAUTH2_CLIENT_SECRET in TwitterCredentialsOAuth2\n*\n* Example steps:\n* 1. Getting the App Authorization URL.\n* 2. User should click the URL and authorize it.\n* 3. After receiving the access token, setting the values into TwitterCredentialsOAuth2.\n* 4. Call the API.\n*/\n\npublic class OAuth20GetAccessToken {\n\n  public static void main(String[] args) {\n    OAuth20GetAccessToken example = new OAuth20GetAccessToken();\n    TwitterCredentialsOAuth2 credentials = new TwitterCredentialsOAuth2(\"REPLACE-WITH-CLIENT-ID\",\n        \"REPLACE-WITH-CLIENT-SECRET\",\n        null,\n        null);\n\n    OAuth2AccessToken accessToken = example.getAccessToken(credentials);\n    if (accessToken == null) {\n      return;\n    }\n\n    // Setting the access & refresh tokens into TwitterCredentialsOAuth2\n    credentials.setTwitterOauth2AccessToken(accessToken.getAccessToken());\n    credentials.setTwitterOauth2RefreshToken(accessToken.getRefreshToken());\n    example.callApi(credentials);\n  }\n\n  public OAuth2AccessToken getAccessToken(TwitterCredentialsOAuth2 credentials) {\n    TwitterOAuth20Service service = new TwitterOAuth20Service(\n        credentials.getTwitterOauth2ClientId(),\n        credentials.getTwitterOAuth2ClientSecret(),\n        \"https://www.example.com/oauth\",\n        \"offline.access tweet.read users.read\");\n\n    OAuth2AccessToken accessToken = null;\n    try {\n      final Scanner in = new Scanner(System.in, \"UTF-8\");\n      System.out.println(\"Fetching the Authorization URL...\");\n\n      final String secretState = \"state\";\n      PKCE pkce = new PKCE();\n      pkce.setCodeChallenge(\"challenge\");\n      pkce.setCodeChallengeMethod(PKCECodeChallengeMethod.PLAIN);\n      pkce.setCodeVerifier(\"challenge\");\n      String authorizationUrl = service.getAuthorizationUrl(pkce, secretState);\n\n      System.out.println(\"Go to the Authorization URL and authorize your App:\\n\" +\n          authorizationUrl + \"\\nAfter that paste the authorization code here\\n>>\");\n      final String code = in.nextLine();\n      System.out.println(\"\\nTrading the Authorization Code for an Access Token...\");\n      accessToken = service.getAccessToken(pkce, code);\n\n      System.out.println(\"Access token: \" + accessToken.getAccessToken());\n      System.out.println(\"Refresh token: \" + accessToken.getRefreshToken());\n    } catch (Exception e) {\n      System.err.println(\"Error while getting the access token:\\n \" + e);\n      e.printStackTrace();\n    }\n    return accessToken;\n  }\n\n  public void callApi(TwitterCredentialsOAuth2 credentials) {\n    TwitterApi apiInstance = new TwitterApi();\n    apiInstance.setTwitterCredentials(credentials);\n\n    // Set the params values\n    String sinceId = \"791775337160081409\"; // String | The minimum Tweet ID to be included in the result set. This parameter takes precedence over start_time if both are specified.\n    String untilId = \"1346889436626259968\"; // String | The maximum Tweet ID to be included in the result set. This parameter takes precedence over end_time if both are specified.\n    Integer maxResults = 56; // Integer | The maximum number of results\n    String paginationToken = \"paginationToken_example\"; // String | This parameter is used to get the next 'page' of results.\n    OffsetDateTime startTime = OffsetDateTime.parse(\"2021-02-01T18:40:40.000Z\"); // OffsetDateTime | YYYY-MM-DDTHH:mm:ssZ. The earliest UTC timestamp from which the Tweets will be provided. The since_id parameter takes precedence if it is also specified.\n    OffsetDateTime endTime = OffsetDateTime.parse(\"2021-02-14T18:40:40.000Z\"); // OffsetDateTime | YYYY-MM-DDTHH:mm:ssZ. The latest UTC timestamp to which the Tweets will be provided. The until_id parameter takes precedence if it is also specified.\n    Set<String> expansions = new HashSet<>(Arrays.asList()); // Set<String> | A comma separated list of fields to expand.\n    Set<String> tweetFields = new HashSet<>(Arrays.asList()); // Set<String> | A comma separated list of Tweet fields to display.\n    Set<String> userFields = new HashSet<>(Arrays.asList()); // Set<String> | A comma separated list of User fields to display.\n    Set<String> mediaFields = new HashSet<>(Arrays.asList()); // Set<String> | A comma separated list of Media fields to display.\n    Set<String> placeFields = new HashSet<>(Arrays.asList()); // Set<String> | A comma separated list of Place fields to display.\n    Set<String> pollFields = new HashSet<>(Arrays.asList()); // Set<String> | A comma separated list of Poll fields to display.\n\n    try {\n      //Gets the authorized user ID and parses it into an JSON object\n      SingleUserLookupResponse userData = apiInstance.users().findMyUser(null, null, null);\n      String jsonString = userData.getData().toJson();\n      JSONObject obj = new JSONObject(jsonString);\n      String userId = obj.getString(\"id\");\n      \n      //Passes the parsed ID into the userIdTimeline request\n      GenericTweetsTimelineResponse result = apiInstance.tweets().usersIdTimeline(userId, sinceId, untilId, maxResults, null, paginationToken, startTime, endTime, expansions, tweetFields, userFields, mediaFields, placeFields, pollFields);\n      System.out.println(result);\n    } catch (ApiException e) {\n      System.err.println(\"Exception when calling UsersApi#usersIdTimeline\");\n      System.err.println(\"Status code: \" + e.getCode());\n      System.err.println(\"Reason: \" + e.getResponseBody());\n      System.err.println(\"Response headers: \" + e.getResponseHeaders());\n      e.printStackTrace();\n    }\n  }\n}\n"
  },
  {
    "path": "java/usage/UsageTweetsDemo.java",
    "content": "import org.apache.http.HttpEntity;\nimport org.apache.http.HttpResponse;\nimport org.apache.http.NameValuePair;\nimport org.apache.http.client.HttpClient;\nimport org.apache.http.client.config.CookieSpecs;\nimport org.apache.http.client.config.RequestConfig;\nimport org.apache.http.client.methods.HttpGet;\nimport org.apache.http.client.utils.URIBuilder;\nimport org.apache.http.impl.client.HttpClients;\nimport org.apache.http.message.BasicNameValuePair;\nimport org.apache.http.util.EntityUtils;\n\nimport java.io.IOException;\nimport java.net.URISyntaxException;\nimport java.util.ArrayList;\n\n/*\n * Sample code to demonstrate the use of the v2 Usage Tweets endpoint\n * */\npublic class UsageTweetsDemo {\n\n  // To set your enviornment variables in your terminal run the following line:\n  // export 'BEARER_TOKEN'='<your_bearer_token>'\n\n  public static void main(String args[]) throws IOException, URISyntaxException {\n    String bearerToken = System.getenv(\"BEARER_TOKEN\");\n    if (null != bearerToken) {\n      String response = getUsageTweets(bearerToken);\n      System.out.println(response);\n    } else {\n      System.out.println(\"There was a problem getting you bearer token. Please make sure you set the BEARER_TOKEN environment variable\");\n    }\n  }\n\n  /*\n   * This method calls the v2 Usage Tweets endpoint\n   * */\n  private static String getUsageTweets(String bearerToken) throws IOException, URISyntaxException {\n    String usageTweetsResponse = null;\n\n    HttpClient httpClient = HttpClients.custom()\n        .setDefaultRequestConfig(RequestConfig.custom()\n            .setCookieSpec(CookieSpecs.STANDARD).build())\n        .build();\n\n    URIBuilder uriBuilder = new URIBuilder(\"https://api.x.com/2/usage/tweets\");\n    HttpGet httpGet = new HttpGet(uriBuilder.build());\n    httpGet.setHeader(\"Authorization\", String.format(\"Bearer %s\", bearerToken));\n    httpGet.setHeader(\"Content-Type\", \"application/json\");\n\n    HttpResponse response = httpClient.execute(httpGet);\n    HttpEntity entity = response.getEntity();\n    if (null != entity) {\n      usageTweetsResponse = EntityUtils.toString(entity, \"UTF-8\");\n    }\n    return usageTweetsResponse;\n  }\n}"
  },
  {
    "path": "java/users/FollowersLookupDemo.java",
    "content": "import org.apache.http.HttpEntity;\nimport org.apache.http.HttpResponse;\nimport org.apache.http.NameValuePair;\nimport org.apache.http.client.HttpClient;\nimport org.apache.http.client.config.CookieSpecs;\nimport org.apache.http.client.config.RequestConfig;\nimport org.apache.http.client.methods.HttpGet;\nimport org.apache.http.client.utils.URIBuilder;\nimport org.apache.http.impl.client.HttpClients;\nimport org.apache.http.message.BasicNameValuePair;\nimport org.apache.http.util.EntityUtils;\n\nimport java.io.IOException;\nimport java.net.URISyntaxException;\nimport java.util.ArrayList;\n\n/*\n * Sample code to demonstrate the use of the v2 followers lookup endpoint\n * */\npublic class FollowersLookupDemo {\n\n  // To set your environment variables in your terminal run the following line:\n  // export 'BEARER_TOKEN'='<your_bearer_token>'\n\n  public static void main(String args[]) throws IOException, URISyntaxException {\n    final String bearerToken = System.getenv(\"BEARER_TOKEN\");\n    if (null != bearerToken) {\n      // Replace with user ID below\n      String response = getFollowers(\"2244994945\", bearerToken);\n      System.out.println(response);\n    } else {\n      System.out.println(\"There was a problem getting your bearer token. Please make sure you set the BEARER_TOKEN environment variable\");\n    }\n  }\n\n  /*\n   * This method calls the v2 followers lookup endpoint by user ID\n   * */\n  private static String getFollowers(String userId, String bearerToken) throws IOException, URISyntaxException {\n    String tweetResponse = null;\n\n    HttpClient httpClient = HttpClients.custom()\n        .setDefaultRequestConfig(RequestConfig.custom()\n            .setCookieSpec(CookieSpecs.STANDARD).build())\n        .build();\n\n    URIBuilder uriBuilder = new URIBuilder(String.format(\"https://api.x.com/2/users/%s/followers\", userId));\n    ArrayList<NameValuePair> queryParameters;\n    queryParameters = new ArrayList<>();\n    queryParameters.add(new BasicNameValuePair(\"user.fields\", \"created_at\"));\n    uriBuilder.addParameters(queryParameters);\n\n    HttpGet httpGet = new HttpGet(uriBuilder.build());\n    httpGet.setHeader(\"Authorization\", String.format(\"Bearer %s\", bearerToken));\n    httpGet.setHeader(\"Content-Type\", \"application/json\");\n\n    HttpResponse response = httpClient.execute(httpGet);\n    HttpEntity entity = response.getEntity();\n    if (null != entity) {\n      tweetResponse = EntityUtils.toString(entity, \"UTF-8\");\n    }\n    return tweetResponse;\n  }\n}\n"
  },
  {
    "path": "java/users/FollowingLookupDemo.java",
    "content": "import org.apache.http.HttpEntity;\nimport org.apache.http.HttpResponse;\nimport org.apache.http.NameValuePair;\nimport org.apache.http.client.HttpClient;\nimport org.apache.http.client.config.CookieSpecs;\nimport org.apache.http.client.config.RequestConfig;\nimport org.apache.http.client.methods.HttpGet;\nimport org.apache.http.client.utils.URIBuilder;\nimport org.apache.http.impl.client.HttpClients;\nimport org.apache.http.message.BasicNameValuePair;\nimport org.apache.http.util.EntityUtils;\n\nimport java.io.IOException;\nimport java.net.URISyntaxException;\nimport java.util.ArrayList;\n\n/*\n * Sample code to demonstrate the use of the v2 following lookup endpoint\n * */\npublic class FollowingLookupDemo {\n\n  // To set your environment variables in your terminal run the following line:\n  // export 'BEARER_TOKEN'='<your_bearer_token>'\n\n  public static void main(String args[]) throws IOException, URISyntaxException {\n    final String bearerToken = System.getenv(\"BEARER_TOKEN\");\n    if (null != bearerToken) {\n      // Replace with user ID below\n      String response = getFollowing(\"2244994945\", bearerToken);\n      System.out.println(response);\n    } else {\n      System.out.println(\"There was a problem getting your bearer token. Please make sure you set the BEARER_TOKEN environment variable\");\n    }\n  }\n\n  /*\n   * This method calls the v2 following lookup endpoint\n   * */\n  private static String getFollowing(String userId, String bearerToken) throws IOException, URISyntaxException {\n    String tweetResponse = null;\n\n    HttpClient httpClient = HttpClients.custom()\n        .setDefaultRequestConfig(RequestConfig.custom()\n            .setCookieSpec(CookieSpecs.STANDARD).build())\n        .build();\n\n    URIBuilder uriBuilder = new URIBuilder(String.format(\"https://api.x.com/2/users/%s/following\", userId));\n    ArrayList<NameValuePair> queryParameters;\n    queryParameters = new ArrayList<>();\n    queryParameters.add(new BasicNameValuePair(\"user.fields\", \"created_at\"));\n    uriBuilder.addParameters(queryParameters);\n\n    HttpGet httpGet = new HttpGet(uriBuilder.build());\n    httpGet.setHeader(\"Authorization\", String.format(\"Bearer %s\", bearerToken));\n    httpGet.setHeader(\"Content-Type\", \"application/json\");\n\n    HttpResponse response = httpClient.execute(httpGet);\n    HttpEntity entity = response.getEntity();\n    if (null != entity) {\n      tweetResponse = EntityUtils.toString(entity, \"UTF-8\");\n    }\n    return tweetResponse;\n  }\n}\n"
  },
  {
    "path": "java/users/Lookup.java",
    "content": "/**\n * User Lookup - X API v2\n * \n * Endpoint: GET https://api.x.com/2/users/by\n * Docs: https://developer.x.com/en/docs/twitter-api/users/lookup/api-reference/get-users-by\n * \n * Authentication: Bearer Token (App-only)\n * Required env vars: BEARER_TOKEN\n * \n * Dependencies: org.apache.httpcomponents:httpclient, com.google.code.gson:gson\n */\n\nimport java.io.IOException;\nimport java.net.URISyntaxException;\nimport org.apache.http.HttpEntity;\nimport org.apache.http.HttpResponse;\nimport org.apache.http.client.HttpClient;\nimport org.apache.http.client.config.CookieSpecs;\nimport org.apache.http.client.config.RequestConfig;\nimport org.apache.http.client.methods.HttpGet;\nimport org.apache.http.client.utils.URIBuilder;\nimport org.apache.http.impl.client.HttpClients;\nimport org.apache.http.util.EntityUtils;\n\npublic class Lookup {\n\n    public static void main(String[] args) throws IOException, URISyntaxException {\n        String bearerToken = System.getenv(\"BEARER_TOKEN\");\n        \n        if (bearerToken == null) {\n            System.err.println(\"BEARER_TOKEN environment variable not set\");\n            System.exit(1);\n        }\n\n        String response = lookupUsers(\"XDevelopers,X\", bearerToken);\n        System.out.println(response);\n    }\n\n    private static String lookupUsers(String usernames, String bearerToken) throws IOException, URISyntaxException {\n        String userLookupUrl = \"https://api.x.com/2/users/by\";\n\n        HttpClient httpClient = HttpClients.custom()\n                .setDefaultRequestConfig(RequestConfig.custom()\n                        .setCookieSpec(CookieSpecs.STANDARD).build())\n                .build();\n\n        URIBuilder uriBuilder = new URIBuilder(userLookupUrl);\n        uriBuilder.addParameter(\"usernames\", usernames);\n        uriBuilder.addParameter(\"user.fields\", \"created_at,description,public_metrics\");\n\n        HttpGet httpGet = new HttpGet(uriBuilder.build());\n        httpGet.setHeader(\"Authorization\", \"Bearer \" + bearerToken);\n        httpGet.setHeader(\"User-Agent\", \"v2UserLookupJava\");\n\n        HttpResponse response = httpClient.execute(httpGet);\n        HttpEntity entity = response.getEntity();\n        \n        if (entity != null) {\n            return EntityUtils.toString(entity, \"UTF-8\");\n        } else {\n            return \"No response\";\n        }\n    }\n}\n"
  },
  {
    "path": "java/users/UsersDemo.java",
    "content": "import org.apache.http.HttpEntity;\nimport org.apache.http.HttpResponse;\nimport org.apache.http.NameValuePair;\nimport org.apache.http.client.HttpClient;\nimport org.apache.http.client.config.CookieSpecs;\nimport org.apache.http.client.config.RequestConfig;\nimport org.apache.http.client.methods.HttpGet;\nimport org.apache.http.client.utils.URIBuilder;\nimport org.apache.http.impl.client.HttpClients;\nimport org.apache.http.message.BasicNameValuePair;\nimport org.apache.http.util.EntityUtils;\n\nimport java.io.IOException;\nimport java.net.URISyntaxException;\nimport java.util.ArrayList;\n\n/*\n * Sample code to demonstrate the use of the v2 Users endpoint\n * */\npublic class UsersDemo {\n\n  // To set your enviornment variables in your terminal run the following line:\n  // export 'BEARER_TOKEN'='<your_bearer_token>'\n\n  public static void main(String args[]) throws IOException, URISyntaxException {\n    String bearerToken = System.getenv(\"BEARER_TOKEN\");\n    if (null != bearerToken) {\n      //Replace comma separated usernames with usernames of your choice\n      String response = getUsers(\"TwitterDev,TwitterEng\", bearerToken);\n      System.out.println(response);\n    } else {\n      System.out.println(\"There was a problem getting you bearer token. Please make sure you set the BEARER_TOKEN environment variable\");\n    }\n  }\n\n  /*\n   * This method calls the v2 Users endpoint with usernames as query parameter\n   * */\n  private static String getUsers(String usernames, String bearerToken) throws IOException, URISyntaxException {\n    String userResponse = null;\n\n    HttpClient httpClient = HttpClients.custom()\n        .setDefaultRequestConfig(RequestConfig.custom()\n            .setCookieSpec(CookieSpecs.STANDARD).build())\n        .build();\n\n    URIBuilder uriBuilder = new URIBuilder(\"https://api.x.com/2/users/by\");\n    ArrayList<NameValuePair> queryParameters;\n    queryParameters = new ArrayList<>();\n    queryParameters.add(new BasicNameValuePair(\"usernames\", usernames));\n    queryParameters.add(new BasicNameValuePair(\"user.fields\", \"created_at,description,pinned_tweet_id\"));\n    uriBuilder.addParameters(queryParameters);\n\n    HttpGet httpGet = new HttpGet(uriBuilder.build());\n    httpGet.setHeader(\"Authorization\", String.format(\"Bearer %s\", bearerToken));\n    httpGet.setHeader(\"Content-Type\", \"application/json\");\n\n    HttpResponse response = httpClient.execute(httpGet);\n    HttpEntity entity = response.getEntity();\n    if (null != entity) {\n      userResponse = EntityUtils.toString(entity, \"UTF-8\");\n    }\n    return userResponse;\n  }\n\n}"
  },
  {
    "path": "javascript/README.md",
    "content": "# X API v2 - JavaScript (Node.js) Examples\n\nWorking JavaScript code samples for the X (formerly Twitter) API v2.\n\n## Setup\n\n### 1. Install Node.js 14+\n\n```bash\nnode --version\n```\n\n### 2. Install dependencies\n\nNo package.json is required. Examples use Node.js built-in modules or standard libraries.\n\n### 3. Set environment variables\n\n**For read-only operations (search, lookup):**\n```bash\nexport BEARER_TOKEN='your_bearer_token'\n```\n\n**For user actions (post, like, repost, bookmark, mute, etc.):**\n```bash\nexport CLIENT_ID='your_client_id'\nexport CLIENT_SECRET='your_client_secret'\n```\n\n**Note:** Most user action examples (create post, like, repost, bookmark, mute, block, etc.) require OAuth 2.0 authentication with `CLIENT_ID` and `CLIENT_SECRET`. Read-only examples (search, lookup) only require `BEARER_TOKEN`.\n\n## Examples by Category\n\n### Posts\n- `posts/create_post.js` - Create a new post (requires `CLIENT_ID`, `CLIENT_SECRET`)\n- `posts/delete_post.js` - Delete a post (requires `CLIENT_ID`, `CLIENT_SECRET`)\n- `posts/get_liking_users.js` - Get users who liked a post (requires `CLIENT_ID`, `CLIENT_SECRET` for user context)\n- `posts/get_post_counts_all.js` - Get post counts (full archive)\n- `posts/get_post_counts_recent.js` - Get post counts (recent)\n- `posts/get_posts_by_ids.js` - Look up posts by ID (bearer token)\n- `posts/get_posts_by_ids_user_context.js` - Look up posts by ID (user context) (requires `CLIENT_ID`, `CLIENT_SECRET`)\n- `posts/get_quoted_posts.js` - Get posts that quote a post\n- `posts/get_reposted_by.js` - Get users who reposted a post\n- `posts/search_all.js` - Full archive search\n- `posts/search_recent.js` - Recent search (last 7 days)\n\n### Users\n- `users/get_users_by_usernames.js` - Look up users by username (bearer token)\n- `users/get_users_by_usernames_user_context.js` - Look up users by username (user context) (requires `CLIENT_ID`, `CLIENT_SECRET`)\n- `users/get_users_me.js` - Get authenticated user (me) (requires `CLIENT_ID`, `CLIENT_SECRET`)\n\n#### User Actions - Block\n- `users/block/get_blocking.js` - Get users blocked by a user (requires `CLIENT_ID`, `CLIENT_SECRET`)\n\n#### User Actions - Bookmark\n- `users/bookmark/create_bookmark.js` - Create a bookmark (requires `CLIENT_ID`, `CLIENT_SECRET`)\n- `users/bookmark/delete_bookmark.js` - Delete a bookmark (requires `CLIENT_ID`, `CLIENT_SECRET`)\n- `users/bookmark/get_bookmarks.js` - Get user's bookmarks (requires `CLIENT_ID`, `CLIENT_SECRET`)\n\n#### User Actions - Follow\n- `users/follow/get_followers.js` - Get user's followers\n- `users/follow/get_followers_paginated.js` - Get user's followers (paginated)\n- `users/follow/get_following_paginated.js` - Get users a user is following (paginated)\n\n#### User Actions - Like\n- `users/like/get_liked_posts.js` - Get posts liked by a user (requires `CLIENT_ID`, `CLIENT_SECRET`)\n- `users/like/like_post.js` - Like a post (requires `CLIENT_ID`, `CLIENT_SECRET`)\n- `users/like/unlike_post.js` - Unlike a post (requires `CLIENT_ID`, `CLIENT_SECRET`)\n\n#### User Actions - Lists\n- `users/lists/follow_list.js` - Follow a list (requires `CLIENT_ID`, `CLIENT_SECRET`)\n- `users/lists/get_followed_lists.js` - Get lists followed by a user\n- `users/lists/get_list_memberships.js` - Get list memberships\n- `users/lists/get_owned_lists.js` - Get lists owned by a user\n- `users/lists/pin_list.js` - Pin a list (requires `CLIENT_ID`, `CLIENT_SECRET`)\n- `users/lists/unfollow_list.js` - Unfollow a list (requires `CLIENT_ID`, `CLIENT_SECRET`)\n- `users/lists/unpin_list.js` - Unpin a list (requires `CLIENT_ID`, `CLIENT_SECRET`)\n\n#### User Actions - Mute\n- `users/mute/get_muting.js` - Get users muted by a user (requires `CLIENT_ID`, `CLIENT_SECRET`)\n- `users/mute/mute_user.js` - Mute a user (requires `CLIENT_ID`, `CLIENT_SECRET`)\n- `users/mute/unmute_user.js` - Unmute a user (requires `CLIENT_ID`, `CLIENT_SECRET`)\n\n#### User Actions - Repost\n- `users/repost/repost_post.js` - Repost a post (requires `CLIENT_ID`, `CLIENT_SECRET`)\n- `users/repost/unrepost_post.js` - Undo a repost (requires `CLIENT_ID`, `CLIENT_SECRET`)\n\n#### User Actions - Timeline\n- `users/timeline/get_home_timeline.js` - Get home timeline (requires `CLIENT_ID`, `CLIENT_SECRET`)\n- `users/timeline/get_mentions.js` - Get user mentions timeline\n- `users/timeline/get_posts.js` - Get user's posts timeline\n- `users/timeline/get_posts_paginated.js` - Get user's posts timeline (paginated)\n\n### Timelines\n- See `users/timeline/` directory for timeline examples\n\n### Streams\n- `streams/stream_posts_filtered.js` - Filtered stream with rules\n- `streams/stream_posts_sample.js` - Sampled stream\n\n### Lists\n- `lists/add_member.js` - Add member to a list (requires `CLIENT_ID`, `CLIENT_SECRET`)\n- `lists/create_list.js` - Create a new list (requires `CLIENT_ID`, `CLIENT_SECRET`)\n- `lists/delete_list.js` - Delete a list (requires `CLIENT_ID`, `CLIENT_SECRET`)\n- `lists/get_list_by_id.js` - Get list by ID\n- `lists/get_list_followers.js` - Get list followers\n- `lists/get_list_members.js` - Get list members\n- `lists/get_list_posts.js` - Get posts from a list\n- `lists/remove_member.js` - Remove member from a list (requires `CLIENT_ID`, `CLIENT_SECRET`)\n- `lists/update_list.js` - Update a list (requires `CLIENT_ID`, `CLIENT_SECRET`)\n\n### Spaces\n- `spaces/get_spaces_by_ids.js` - Look up Spaces by ID\n- `spaces/search_spaces.js` - Search for Spaces\n\n### Compliance\n- `compliance/create_jobs.js` - Create compliance job\n- `compliance/download_results.js` - Download compliance results\n- `compliance/get_jobs_by_id.js` - Get compliance job by ID\n- `compliance/get_jobs.js` - Get compliance jobs\n- `compliance/upload_ids.js` - Upload IDs for compliance\n\n### Usage\n- `usage/get_usage.js` - Get API usage information\n\n## Running Examples\n\n```bash\n# Make sure environment variables are set\nnode posts/search_recent.js\n```\n\n## More Information\n\n- [X API Documentation](https://developer.x.com/en/docs/twitter-api)\n- [X Developer Portal](https://developer.x.com/en/portal/dashboard)\n"
  },
  {
    "path": "javascript/compliance/create_jobs.js",
    "content": "const { Client } = require('@xdevplatform/xdk');\n\n// The code below sets the bearer token from your environment variables\n// To set environment variables on macOS or Linux, run the export command below from the terminal:\n// export BEARER_TOKEN='YOUR-TOKEN'\nconst token = process.env.BEARER_TOKEN;\nconst client = new Client({ bearerToken: token });\n\n// For User Compliance Job, replace type value with users instead of tweets\n// Also replace the name value with your desired job name\nconst data = {\n    type: \"tweets\",\n    name: 'my_batch_compliance_job'\n};\n\n(async () => {\n    try {\n        // Make request\n        const response = await client.compliance.createJobs(data);\n        \n        console.dir(response, {\n            depth: null\n        });\n\n    } catch (e) {\n        console.log(e);\n        process.exit(-1);\n    }\n    process.exit();\n})();\n"
  },
  {
    "path": "javascript/compliance/download_results.js",
    "content": "// Replace with your job download_url\ndownloadUrl = ''\n\nasync function getRequest() {\n    const res = await fetch(downloadUrl, {\n        headers: {\n            'Accept-Encoding': 'gzip, deflate, br'\n        }\n    })\n\n    if (res.ok) {\n        return await res.text();\n    } else {\n        throw new Error('Unsuccessful request');\n    }\n}\n\n(async () => {\n\n    try {\n        // Make request\n        const response = await getRequest();\n        console.dir(response, {\n            depth: null\n        });\n\n    } catch (e) {\n        console.log(e);\n        process.exit(-1);\n    }\n    process.exit();\n})();"
  },
  {
    "path": "javascript/compliance/get_jobs.js",
    "content": "const { Client } = require('@xdevplatform/xdk');\n\n// The code below sets the bearer token from your environment variables\n// To set environment variables on macOS or Linux, run the export command below from the terminal:\n// export BEARER_TOKEN='YOUR-TOKEN'\nconst token = process.env.BEARER_TOKEN;\nconst client = new Client({ bearerToken: token });\n\n// For User Compliance job, replace the value for type with users\nconst params = {\n    type: \"tweets\"\n};\n\n(async () => {\n    try {\n        // Make request\n        const response = await client.compliance.getJobs(params);\n        \n        console.dir(response, {\n            depth: null\n        });\n\n    } catch (e) {\n        console.log(e);\n        process.exit(-1);\n    }\n    process.exit();\n})();\n"
  },
  {
    "path": "javascript/compliance/get_jobs_by_id.js",
    "content": "const { Client } = require('@xdevplatform/xdk');\n\n// The code below sets the bearer token from your environment variables\n// To set environment variables on macOS or Linux, run the export command below from the terminal:\n// export BEARER_TOKEN='YOUR-TOKEN'\nconst token = process.env.BEARER_TOKEN;\nconst client = new Client({ bearerToken: token });\n\n// Replace with your job ID\nconst jobId = '';\n\n(async () => {\n    try {\n        // Make request\n        const response = await client.compliance.getJobsById(jobId);\n        \n        console.dir(response, {\n            depth: null\n        });\n\n    } catch (e) {\n        console.log(e);\n        process.exit(-1);\n    }\n    process.exit();\n})();\n"
  },
  {
    "path": "javascript/compliance/upload_ids.js",
    "content": "const fs = require('fs');\n\n// Replace with your job download_url\nconst uploadUrl = '';\n\n// Replace with your file path that contains the list of Post IDs or User IDs, one ID per line\nconst filePath = '/path/to/file';\n\nasync function getRequest() {\n    const readStream = fs.createReadStream(filePath);\n    const fileBuffer = await new Promise((resolve, reject) => {\n        const chunks = [];\n        readStream.on('data', chunk => chunks.push(chunk));\n        readStream.on('end', () => resolve(Buffer.concat(chunks)));\n        readStream.on('error', reject);\n    });\n\n    const res = await fetch(uploadUrl, {\n        method: 'PUT',\n        body: fileBuffer,\n        headers: {\n            \"Content-Type\": \"text/plain\"\n        }\n    });\n\n    if (res.ok) {\n        return res.status;\n    } else {\n        throw new Error('Unsuccessful request');\n    }\n}\n\n(async () => {\n    try {\n        // Make request\n        const response = await getRequest();\n        console.dir(response, {\n            depth: null\n        });\n    } catch (e) {\n        console.log(e);\n        process.exit(-1);\n    }\n    process.exit();\n})();\n"
  },
  {
    "path": "javascript/lists/add_member.js",
    "content": "// Add member to a list using OAuth 2.0 to authorize the user\n// https://developer.twitter.com/en/docs/twitter-api/lists/manage-lists/quick-start\nconst { \n  Client, \n  OAuth2,\n  generateCodeVerifier,\n  generateCodeChallenge\n} = require('@xdevplatform/xdk');\n\nconst readline = require(\"readline\").createInterface({\n  input: process.stdin,\n  output: process.stdout,\n});\n\n// The code below sets the client ID and client secret from your environment variables\n// To set environment variables on macOS or Linux, run the export commands below from the terminal:\n// export CLIENT_ID='YOUR-CLIENT-ID'\n// export CLIENT_SECRET='YOUR-CLIENT-SECRET'\nconst clientId = process.env.CLIENT_ID;\nconst clientSecret = process.env.CLIENT_SECRET;\n\n// Be sure to replace your-list-id with your own list ID or one of an authenticated user\nconst listId = \"your-list-id\";\n\n// Be sure to replace user-id-to-add with the user id you wish to add.\n// You can find a user ID by using the user lookup endpoint\nconst userId = \"user-id-to-add\";\n\nasync function input(prompt) {\n  return new Promise((resolve) => {\n    readline.question(prompt, (out) => {\n      readline.close();\n      resolve(out);\n    });\n  });\n}\n\n// Helper function to parse callback URL\nconst getQueryStringParams = (query) => {\n  return query\n    ? (/^[?#]/.test(query) ? query.slice(1) : query)\n        .split(/[\\?\\&]/)\n        .reduce((params, param) => {\n          let [key, value] = param.split(\"=\");\n          params[key] = value\n            ? decodeURIComponent(value.replace(/\\+/g, \" \"))\n            : \"\";\n          return params;\n        }, {})\n    : {};\n};\n\n(async () => {\n  try {\n    // Configure OAuth 2.0\n    const oauth2Config = {\n      clientId: clientId,\n      clientSecret: clientSecret,\n      redirectUri: 'https://example.com',\n      scope: ['tweet.read', 'users.read', 'list.read', 'list.write', 'offline.access']\n    };\n\n    const oauth2 = new OAuth2(oauth2Config);\n\n    // Generate PKCE parameters\n    const state = 'example-state';\n    const codeVerifier = generateCodeVerifier();\n    const codeChallenge = await generateCodeChallenge(codeVerifier);\n    \n    oauth2.setPkceParameters(codeVerifier, codeChallenge);\n    \n    // Get authorization URL\n    const authUrl = await oauth2.getAuthorizationUrl(state);\n    console.log(\"Please go here and authorize:\", authUrl);\n\n    // Input callback URL from terminal\n    const redirectCallback = await input(\"Paste the redirected callback URL here: \");\n\n    // Parse callback\n    const { state: returnedState, code } = getQueryStringParams(redirectCallback);\n    if (returnedState !== state) {\n      console.log(\"State doesn't match\");\n      process.exit(-1);\n    }\n\n    // Exchange code for tokens\n    const tokens = await oauth2.exchangeCode(code, codeVerifier);\n\n    // Create client with access token\n    const client = new Client({\n      accessToken: tokens.access_token\n    });\n\n    // Make the request using SDK\n    const response = await client.lists.addMember(listId, { body: { user_id: userId } });\n    console.dir(response, {\n      depth: null,\n    });\n  } catch (e) {\n    console.log(e);\n    process.exit(-1);\n  }\n  process.exit();\n})();\n"
  },
  {
    "path": "javascript/lists/create_list.js",
    "content": "// Create a new list using OAuth 2.0 to authorize the user\n// https://developer.twitter.com/en/docs/twitter-api/lists/manage-lists/quick-start\nconst { \n  Client, \n  OAuth2,\n  generateCodeVerifier,\n  generateCodeChallenge\n} = require('@xdevplatform/xdk');\n\nconst readline = require(\"readline\").createInterface({\n  input: process.stdin,\n  output: process.stdout,\n});\n\n// The code below sets the client ID and client secret from your environment variables\n// To set environment variables on macOS or Linux, run the export commands below from the terminal:\n// export CLIENT_ID='YOUR-CLIENT-ID'\n// export CLIENT_SECRET='YOUR-CLIENT-SECRET'\nconst clientId = process.env.CLIENT_ID;\nconst clientSecret = process.env.CLIENT_SECRET;\n\n// Be sure to add replace name-of-list with the name you wish to call the list.\n// description and private keys are optional\nconst data = {\n  name: \"name-of-list\",\n  description: \"description-of-list\",\n  private: false,\n};\n\nasync function input(prompt) {\n  return new Promise((resolve) => {\n    readline.question(prompt, (out) => {\n      readline.close();\n      resolve(out);\n    });\n  });\n}\n\n// Helper function to parse callback URL\nconst getQueryStringParams = (query) => {\n  return query\n    ? (/^[?#]/.test(query) ? query.slice(1) : query)\n        .split(/[\\?\\&]/)\n        .reduce((params, param) => {\n          let [key, value] = param.split(\"=\");\n          params[key] = value\n            ? decodeURIComponent(value.replace(/\\+/g, \" \"))\n            : \"\";\n          return params;\n        }, {})\n    : {};\n};\n\n(async () => {\n  try {\n    // Configure OAuth 2.0\n    const oauth2Config = {\n      clientId: clientId,\n      clientSecret: clientSecret,\n      redirectUri: 'https://example.com',\n      scope: ['tweet.read', 'users.read', 'list.read', 'list.write', 'offline.access']\n    };\n\n    const oauth2 = new OAuth2(oauth2Config);\n\n    // Generate PKCE parameters\n    const state = 'example-state';\n    const codeVerifier = generateCodeVerifier();\n    const codeChallenge = await generateCodeChallenge(codeVerifier);\n    \n    oauth2.setPkceParameters(codeVerifier, codeChallenge);\n    \n    // Get authorization URL\n    const authUrl = await oauth2.getAuthorizationUrl(state);\n    console.log(\"Please go here and authorize:\", authUrl);\n\n    // Input callback URL from terminal\n    const redirectCallback = await input(\"Paste the redirected callback URL here: \");\n\n    // Parse callback\n    const { state: returnedState, code } = getQueryStringParams(redirectCallback);\n    if (returnedState !== state) {\n      console.log(\"State doesn't match\");\n      process.exit(-1);\n    }\n\n    // Exchange code for tokens\n    const tokens = await oauth2.exchangeCode(code, codeVerifier);\n\n    // Create client with access token\n    const client = new Client({\n      accessToken: tokens.access_token\n    });\n\n    // Make the request using SDK\n    const response = await client.lists.create({ body: data });\n    console.dir(response, {\n      depth: null,\n    });\n  } catch (e) {\n    console.log(e);\n    process.exit(-1);\n  }\n  process.exit();\n})();\n"
  },
  {
    "path": "javascript/lists/delete_list.js",
    "content": "// Delete an existing list the authenticated user owns - using OAuth 2.0 to authorize the user\n// https://developer.twitter.com/en/docs/twitter-api/lists/manage-lists/quick-start\nconst { \n  Client, \n  OAuth2,\n  generateCodeVerifier,\n  generateCodeChallenge\n} = require('@xdevplatform/xdk');\n\nconst readline = require(\"readline\").createInterface({\n  input: process.stdin,\n  output: process.stdout,\n});\n\n// The code below sets the client ID and client secret from your environment variables\n// To set environment variables on macOS or Linux, run the export commands below from the terminal:\n// export CLIENT_ID='YOUR-CLIENT-ID'\n// export CLIENT_SECRET='YOUR-CLIENT-SECRET'\nconst clientId = process.env.CLIENT_ID;\nconst clientSecret = process.env.CLIENT_SECRET;\n\n// Be sure to add replace the your-list-id with the id of the list you wish to delete.\nconst targetListId = \"your-list-id\";\n\nasync function input(prompt) {\n  return new Promise((resolve) => {\n    readline.question(prompt, (out) => {\n      readline.close();\n      resolve(out);\n    });\n  });\n}\n\n// Helper function to parse callback URL\nconst getQueryStringParams = (query) => {\n  return query\n    ? (/^[?#]/.test(query) ? query.slice(1) : query)\n        .split(/[\\?\\&]/)\n        .reduce((params, param) => {\n          let [key, value] = param.split(\"=\");\n          params[key] = value\n            ? decodeURIComponent(value.replace(/\\+/g, \" \"))\n            : \"\";\n          return params;\n        }, {})\n    : {};\n};\n\n(async () => {\n  try {\n    // Configure OAuth 2.0\n    const oauth2Config = {\n      clientId: clientId,\n      clientSecret: clientSecret,\n      redirectUri: 'https://example.com',\n      scope: ['tweet.read', 'users.read', 'list.read', 'list.write', 'offline.access']\n    };\n\n    const oauth2 = new OAuth2(oauth2Config);\n\n    // Generate PKCE parameters\n    const state = 'example-state';\n    const codeVerifier = generateCodeVerifier();\n    const codeChallenge = await generateCodeChallenge(codeVerifier);\n    \n    oauth2.setPkceParameters(codeVerifier, codeChallenge);\n    \n    // Get authorization URL\n    const authUrl = await oauth2.getAuthorizationUrl(state);\n    console.log(\"Please go here and authorize:\", authUrl);\n\n    // Input callback URL from terminal\n    const redirectCallback = await input(\"Paste the redirected callback URL here: \");\n\n    // Parse callback\n    const { state: returnedState, code } = getQueryStringParams(redirectCallback);\n    if (returnedState !== state) {\n      console.log(\"State doesn't match\");\n      process.exit(-1);\n    }\n\n    // Exchange code for tokens\n    const tokens = await oauth2.exchangeCode(code, codeVerifier);\n\n    // Create client with access token\n    const client = new Client({\n      accessToken: tokens.access_token\n    });\n\n    // Make the request using SDK\n    const response = await client.lists.delete(targetListId);\n    console.dir(response, {\n      depth: null,\n    });\n  } catch (e) {\n    console.log(e);\n    process.exit(-1);\n  }\n  process.exit();\n})();\n"
  },
  {
    "path": "javascript/lists/get_list_by_id.js",
    "content": "/**\n * List Lookup - X API v2\n * \n * Endpoint: GET https://api.x.com/2/lists/:id\n * Docs: https://developer.x.com/en/docs/twitter-api/lists/list-lookup/api-reference/get-lists-id\n * \n * Authentication: Bearer Token (App-only) or OAuth (User Context)\n * Required env vars: BEARER_TOKEN\n */\n\nconst { Client } = require('@xdevplatform/xdk');\n\nconst token = process.env.BEARER_TOKEN;\nconst client = new Client({ bearerToken: token });\n\n// Replace with the list ID you want to look up\nconst listId = \"84839422\";\n\n(async () => {\n    try {\n        const response = await client.lists.getById(listId, {\n            listFields: ['created_at', 'follower_count', 'member_count', 'owner_id', 'description']\n        });\n        \n        console.dir(response, { depth: null });\n    } catch (e) {\n        console.log(e);\n        process.exit(-1);\n    }\n    process.exit();\n})();\n"
  },
  {
    "path": "javascript/lists/get_list_followers.js",
    "content": "const { Client } = require('@xdevplatform/xdk');\n\n// The code below sets the bearer token from your environment variables\n// To set environment variables on macOS or Linux, run the export command below from the terminal:\n// export BEARER_TOKEN='YOUR-TOKEN'\n\nconst token = process.env.BEARER_TOKEN;\nconst client = new Client({ bearerToken: token });\nconst id = \"list-id\";\n\n(async () => {\n  try {\n    // These are the parameters for the API request\n    // by default, only the User ID and name are returned\n    const response = await client.lists.getFollowers(id, {\n      userFields: ['pinned_tweet_id', 'created_at'], // Edit optional query parameters here\n      expansions: ['pinned_tweet_id'], // expansions is used to include the Post object\n      tweetFields: ['created_at'] // Edit optional query parameters here\n    });\n    \n    console.dir(response, {\n      depth: null,\n    });\n  } catch (e) {\n    console.log(e);\n    process.exit(-1);\n  }\n  process.exit();\n})();\n"
  },
  {
    "path": "javascript/lists/get_list_members.js",
    "content": "const { Client } = require('@xdevplatform/xdk');\n\n// The code below sets the bearer token from your environment variables\n// To set environment variables on macOS or Linux, run the export command below from the terminal:\n// export BEARER_TOKEN='YOUR-TOKEN'\n\nconst token = process.env.BEARER_TOKEN;\nconst client = new Client({ bearerToken: token });\nconst id = \"list-id\";\n\n(async () => {\n  try {\n    // These are the parameters for the API request\n    // by default, only the User ID and name are returned\n    const response = await client.lists.getMembers(id, {\n      userFields: ['pinned_tweet_id', 'created_at'], // Edit optional query parameters here\n      expansions: ['pinned_tweet_id'], // expansions is used to include the Post object\n      tweetFields: ['created_at'] // Edit optional query parameters here\n    });\n    \n    console.dir(response, {\n      depth: null,\n    });\n  } catch (e) {\n    console.log(e);\n    process.exit(-1);\n  }\n  process.exit();\n})();\n"
  },
  {
    "path": "javascript/lists/get_list_posts.js",
    "content": "const { Client } = require('@xdevplatform/xdk');\n\n// The code below sets the bearer token from your environment variables\n// To set environment variables on macOS or Linux, run the export command below from the terminal:\n// export BEARER_TOKEN='YOUR-TOKEN'\n\nconst token = process.env.BEARER_TOKEN;\nconst client = new Client({ bearerToken: token });\nconst id = \"list-id\";\n\n(async () => {\n  try {\n    // These are the parameters for the API request\n    // by default, only the Post ID and text are returned\n    const response = await client.lists.getPosts(id, {\n      tweetFields: ['lang', 'author_id'], // Edit optional query parameters here\n      expansions: ['author_id'], // expansions is used to include the user object\n      userFields: ['created_at'] // Edit optional query parameters here\n    });\n    \n    console.dir(response, {\n      depth: null,\n    });\n  } catch (e) {\n    console.log(e);\n    process.exit(-1);\n  }\n  process.exit();\n})();\n\n"
  },
  {
    "path": "javascript/lists/remove_member.js",
    "content": "// Remove member from a list using OAuth 2.0 to authorize the user\n// https://developer.twitter.com/en/docs/twitter-api/lists/manage-lists/quick-start\nconst { \n  Client, \n  OAuth2,\n  generateCodeVerifier,\n  generateCodeChallenge\n} = require('@xdevplatform/xdk');\n\nconst readline = require(\"readline\").createInterface({\n  input: process.stdin,\n  output: process.stdout,\n});\n\n// The code below sets the client ID and client secret from your environment variables\n// To set environment variables on macOS or Linux, run the export commands below from the terminal:\n// export CLIENT_ID='YOUR-CLIENT-ID'\n// export CLIENT_SECRET='YOUR-CLIENT-SECRET'\nconst clientId = process.env.CLIENT_ID;\nconst clientSecret = process.env.CLIENT_SECRET;\n\n// Be sure to replace your-list-id with your own list ID or one of an authenticated user\nconst listId = \"your-list-id\";\n\n// Be sure to replace user-id-to-remove with the user id you wish to remove.\n// You can find a user ID by using the user lookup endpoint\nconst userId = \"user-id-to-remove\";\n\nasync function input(prompt) {\n  return new Promise((resolve) => {\n    readline.question(prompt, (out) => {\n      readline.close();\n      resolve(out);\n    });\n  });\n}\n\n// Helper function to parse callback URL\nconst getQueryStringParams = (query) => {\n  return query\n    ? (/^[?#]/.test(query) ? query.slice(1) : query)\n        .split(/[\\?\\&]/)\n        .reduce((params, param) => {\n          let [key, value] = param.split(\"=\");\n          params[key] = value\n            ? decodeURIComponent(value.replace(/\\+/g, \" \"))\n            : \"\";\n          return params;\n        }, {})\n    : {};\n};\n\n(async () => {\n  try {\n    // Configure OAuth 2.0\n    const oauth2Config = {\n      clientId: clientId,\n      clientSecret: clientSecret,\n      redirectUri: 'https://example.com',\n      scope: ['tweet.read', 'users.read', 'list.read', 'list.write', 'offline.access']\n    };\n\n    const oauth2 = new OAuth2(oauth2Config);\n\n    // Generate PKCE parameters\n    const state = 'example-state';\n    const codeVerifier = generateCodeVerifier();\n    const codeChallenge = await generateCodeChallenge(codeVerifier);\n    \n    oauth2.setPkceParameters(codeVerifier, codeChallenge);\n    \n    // Get authorization URL\n    const authUrl = await oauth2.getAuthorizationUrl(state);\n    console.log(\"Please go here and authorize:\", authUrl);\n\n    // Input callback URL from terminal\n    const redirectCallback = await input(\"Paste the redirected callback URL here: \");\n\n    // Parse callback\n    const { state: returnedState, code } = getQueryStringParams(redirectCallback);\n    if (returnedState !== state) {\n      console.log(\"State doesn't match\");\n      process.exit(-1);\n    }\n\n    // Exchange code for tokens\n    const tokens = await oauth2.exchangeCode(code, codeVerifier);\n\n    // Create client with access token\n    const client = new Client({\n      accessToken: tokens.access_token\n    });\n\n    // Make the request using SDK\n    const response = await client.lists.removeMemberByUserId(listId, userId);\n    console.dir(response, {\n      depth: null,\n    });\n  } catch (e) {\n    console.log(e);\n    process.exit(-1);\n  }\n  process.exit();\n})();\n"
  },
  {
    "path": "javascript/lists/update_list.js",
    "content": "// Update the metadata of an existing list the authenticated user owns - using OAuth 2.0 to authorize the user\n// https://developer.twitter.com/en/docs/twitter-api/lists/manage-lists/quick-start\nconst { \n  Client, \n  OAuth2,\n  generateCodeVerifier,\n  generateCodeChallenge\n} = require('@xdevplatform/xdk');\n\nconst readline = require(\"readline\").createInterface({\n  input: process.stdin,\n  output: process.stdout,\n});\n\n// The code below sets the client ID and client secret from your environment variables\n// To set environment variables on macOS or Linux, run the export commands below from the terminal:\n// export CLIENT_ID='YOUR-CLIENT-ID'\n// export CLIENT_SECRET='YOUR-CLIENT-SECRET'\nconst clientId = process.env.CLIENT_ID;\nconst clientSecret = process.env.CLIENT_SECRET;\n\n// Be sure to add replace update-name-of-list with the name you wish to call the list.\n// name, description and private are all optional\nconst data = {\n  name: \"update-name-of-list\",\n  description: \"update-description-of-list\",\n  private: false,\n};\n\n// Be sure to add replace the your-list-id with the list id of the list you wish to update.\nconst targetListId = \"your-list-id\";\n\nasync function input(prompt) {\n  return new Promise((resolve) => {\n    readline.question(prompt, (out) => {\n      readline.close();\n      resolve(out);\n    });\n  });\n}\n\n// Helper function to parse callback URL\nconst getQueryStringParams = (query) => {\n  return query\n    ? (/^[?#]/.test(query) ? query.slice(1) : query)\n        .split(/[\\?\\&]/)\n        .reduce((params, param) => {\n          let [key, value] = param.split(\"=\");\n          params[key] = value\n            ? decodeURIComponent(value.replace(/\\+/g, \" \"))\n            : \"\";\n          return params;\n        }, {})\n    : {};\n};\n\n(async () => {\n  try {\n    // Configure OAuth 2.0\n    const oauth2Config = {\n      clientId: clientId,\n      clientSecret: clientSecret,\n      redirectUri: 'https://example.com',\n      scope: ['tweet.read', 'users.read', 'list.read', 'list.write', 'offline.access']\n    };\n\n    const oauth2 = new OAuth2(oauth2Config);\n\n    // Generate PKCE parameters\n    const state = 'example-state';\n    const codeVerifier = generateCodeVerifier();\n    const codeChallenge = await generateCodeChallenge(codeVerifier);\n    \n    oauth2.setPkceParameters(codeVerifier, codeChallenge);\n    \n    // Get authorization URL\n    const authUrl = await oauth2.getAuthorizationUrl(state);\n    console.log(\"Please go here and authorize:\", authUrl);\n\n    // Input callback URL from terminal\n    const redirectCallback = await input(\"Paste the redirected callback URL here: \");\n\n    // Parse callback\n    const { state: returnedState, code } = getQueryStringParams(redirectCallback);\n    if (returnedState !== state) {\n      console.log(\"State doesn't match\");\n      process.exit(-1);\n    }\n\n    // Exchange code for tokens\n    const tokens = await oauth2.exchangeCode(code, codeVerifier);\n\n    // Create client with access token\n    const client = new Client({\n      accessToken: tokens.access_token\n    });\n\n    // Make the request using SDK\n    const response = await client.lists.update(targetListId, { body: data });\n    console.dir(response, {\n      depth: null,\n    });\n  } catch (e) {\n    console.log(e);\n    process.exit(-1);\n  }\n  process.exit();\n})();\n"
  },
  {
    "path": "javascript/posts/create_post.js",
    "content": "/**\n * Create Post - X API v2\n * \n * Endpoint: POST https://api.x.com/2/posts\n * Docs: https://developer.x.com/en/docs/twitter-api/tweets/manage-tweets/api-reference/post-tweets\n * \n * Authentication: OAuth 2.0 (User Context)\n * Required env vars: CLIENT_ID, CLIENT_SECRET\n */\n\nconst { \n  Client, \n  OAuth2,\n  generateCodeVerifier,\n  generateCodeChallenge\n} = require('@xdevplatform/xdk');\n\nconst readline = require('readline').createInterface({\n  input: process.stdin,\n  output: process.stdout\n});\n\nconst clientId = process.env.CLIENT_ID;\nconst clientSecret = process.env.CLIENT_SECRET;\n\n// The text content of the post. You can also add parameters for polls,\n// quote posts, reply settings, and more.\nconst data = {\n  text: \"Hello world!\"\n};\n\nasync function input(prompt) {\n  return new Promise((resolve) => {\n    readline.question(prompt, (out) => {\n      readline.close();\n      resolve(out);\n    });\n  });\n}\n\n// Helper function to parse callback URL\nconst getQueryStringParams = (query) => {\n  return query\n    ? (/^[?#]/.test(query) ? query.slice(1) : query)\n        .split(/[\\?\\&]/)\n        .reduce((params, param) => {\n          let [key, value] = param.split(\"=\");\n          params[key] = value\n            ? decodeURIComponent(value.replace(/\\+/g, \" \"))\n            : \"\";\n          return params;\n        }, {})\n    : {};\n};\n\n(async () => {\n  try {\n    // Configure OAuth 2.0\n    const oauth2Config = {\n      clientId: clientId,\n      clientSecret: clientSecret,\n      redirectUri: 'https://example.com',\n      scope: ['tweet.read', 'users.read', 'tweet.write', 'offline.access']\n    };\n\n    const oauth2 = new OAuth2(oauth2Config);\n\n    // Generate PKCE parameters\n    const state = 'example-state';\n    const codeVerifier = generateCodeVerifier();\n    const codeChallenge = await generateCodeChallenge(codeVerifier);\n    \n    oauth2.setPkceParameters(codeVerifier, codeChallenge);\n    \n    // Get authorization URL\n    const authUrl = await oauth2.getAuthorizationUrl(state);\n    console.log('Please go here and authorize:', authUrl);\n\n    // Input callback URL from terminal\n    const redirectCallback = await input('Paste the redirected callback URL here: ');\n\n    // Parse callback\n    const { state: returnedState, code } = getQueryStringParams(redirectCallback);\n    if (returnedState !== state) {\n      console.log(\"State doesn't match\");\n      process.exit(-1);\n    }\n\n    // Exchange code for tokens\n    const tokens = await oauth2.exchangeCode(code, codeVerifier);\n\n    // Create client with access token\n    const client = new Client({\n      accessToken: tokens.access_token\n    });\n\n    // Make the request using SDK\n    const response = await client.posts.create(data);\n    console.dir(response, { depth: null });\n  } catch (e) {\n    console.log(e);\n    process.exit(-1);\n  }\n  process.exit();\n})();\n"
  },
  {
    "path": "javascript/posts/delete_post.js",
    "content": "/**\n * Delete Post - X API v2\n * \n * Endpoint: DELETE https://api.x.com/2/posts/:id\n * Docs: https://developer.x.com/en/docs/twitter-api/tweets/manage-tweets/api-reference/delete-tweets-id\n * \n * Authentication: OAuth 2.0 (User Context)\n * Required env vars: CLIENT_ID, CLIENT_SECRET\n */\n\nconst { \n  Client, \n  OAuth2,\n  generateCodeVerifier,\n  generateCodeChallenge\n} = require('@xdevplatform/xdk');\n\nconst readline = require('readline').createInterface({\n  input: process.stdin,\n  output: process.stdout\n});\n\nconst clientId = process.env.CLIENT_ID;\nconst clientSecret = process.env.CLIENT_SECRET;\n\n// Replace with the post ID you want to delete\nconst postId = \"post-id-to-delete\";\n\nasync function input(prompt) {\n  return new Promise((resolve) => {\n    readline.question(prompt, (out) => {\n      readline.close();\n      resolve(out);\n    });\n  });\n}\n\n// Helper function to parse callback URL\nconst getQueryStringParams = (query) => {\n  return query\n    ? (/^[?#]/.test(query) ? query.slice(1) : query)\n        .split(/[\\?\\&]/)\n        .reduce((params, param) => {\n          let [key, value] = param.split(\"=\");\n          params[key] = value\n            ? decodeURIComponent(value.replace(/\\+/g, \" \"))\n            : \"\";\n          return params;\n        }, {})\n    : {};\n};\n\n(async () => {\n  try {\n    // Configure OAuth 2.0\n    const oauth2Config = {\n      clientId: clientId,\n      clientSecret: clientSecret,\n      redirectUri: 'https://example.com',\n      scope: ['tweet.read', 'users.read', 'tweet.write','offline.access']\n    };\n\n    const oauth2 = new OAuth2(oauth2Config);\n\n    // Generate PKCE parameters\n    const state = 'example-state';\n    const codeVerifier = generateCodeVerifier();\n    const codeChallenge = await generateCodeChallenge(codeVerifier);\n    \n    oauth2.setPkceParameters(codeVerifier, codeChallenge);\n    \n    // Get authorization URL\n    const authUrl = await oauth2.getAuthorizationUrl(state);\n    console.log('Please go here and authorize:', authUrl);\n\n    // Input callback URL from terminal\n    const redirectCallback = await input('Paste the redirected callback URL here: ');\n\n    // Parse callback\n    const { state: returnedState, code } = getQueryStringParams(redirectCallback);\n    if (returnedState !== state) {\n      console.log(\"State doesn't match\");\n      process.exit(-1);\n    }\n\n    // Exchange code for tokens\n    const tokens = await oauth2.exchangeCode(code, codeVerifier);\n\n    // Create client with access token\n    const client = new Client({\n      accessToken: tokens.access_token\n    });\n\n    // Make the request using SDK\n    const response = await client.posts.delete(postId);\n    console.dir(response, { depth: null });\n  } catch (e) {\n    console.log(e);\n    process.exit(-1);\n  }\n  process.exit();\n})();\n"
  },
  {
    "path": "javascript/posts/get_liking_users.js",
    "content": "// Get liking users for a post using OAuth 2.0 to authorize the user\n// https://developer.twitter.com/en/docs/twitter-api/tweets/likes/api-reference/get-tweets-id-liking_users\nconst { \n  Client, \n  OAuth2,\n  generateCodeVerifier,\n  generateCodeChallenge\n} = require('@xdevplatform/xdk');\n\nconst readline = require(\"readline\").createInterface({\n  input: process.stdin,\n  output: process.stdout,\n});\n\n// The code below sets the client ID and client secret from your environment variables\n// To set environment variables on macOS or Linux, run the export commands below from the terminal:\n// export CLIENT_ID='YOUR-CLIENT-ID'\n// export CLIENT_SECRET='YOUR-CLIENT-SECRET'\nconst clientId = process.env.CLIENT_ID;\nconst clientSecret = process.env.CLIENT_SECRET;\n\n// You can replace the ID given with the Post ID you wish to get liking users for.\n// You can find an ID by using the Post lookup endpoint\nconst id = \"1354143047324299264\";\n\nasync function input(prompt) {\n  return new Promise((resolve) => {\n    readline.question(prompt, (out) => {\n      readline.close();\n      resolve(out);\n    });\n  });\n}\n\n// Helper function to parse callback URL\nconst getQueryStringParams = (query) => {\n  return query\n    ? (/^[?#]/.test(query) ? query.slice(1) : query)\n        .split(/[\\?\\&]/)\n        .reduce((params, param) => {\n          let [key, value] = param.split(\"=\");\n          params[key] = value\n            ? decodeURIComponent(value.replace(/\\+/g, \" \"))\n            : \"\";\n          return params;\n        }, {})\n    : {};\n};\n\n(async () => {\n  try {\n    // Configure OAuth 2.0\n    const oauth2Config = {\n      clientId: clientId,\n      clientSecret: clientSecret,\n      redirectUri: 'https://example.com',\n      scope: ['tweet.read', 'users.read', 'like.read', 'offline.access']\n    };\n\n    const oauth2 = new OAuth2(oauth2Config);\n\n    // Generate PKCE parameters\n    const state = 'example-state';\n    const codeVerifier = generateCodeVerifier();\n    const codeChallenge = await generateCodeChallenge(codeVerifier);\n    \n    oauth2.setPkceParameters(codeVerifier, codeChallenge);\n    \n    // Get authorization URL\n    const authUrl = await oauth2.getAuthorizationUrl(state);\n    console.log(\"Please go here and authorize:\", authUrl);\n\n    // Input callback URL from terminal\n    const redirectCallback = await input(\"Paste the redirected callback URL here: \");\n\n    // Parse callback\n    const { state: returnedState, code } = getQueryStringParams(redirectCallback);\n    if (returnedState !== state) {\n      console.log(\"State doesn't match\");\n      process.exit(-1);\n    }\n\n    // Exchange code for tokens\n    const tokens = await oauth2.exchangeCode(code, codeVerifier);\n\n    // Create client with access token\n    const client = new Client({\n      accessToken: tokens.access_token\n    });\n\n    // These are the parameters for the API request\n    // by default, only the Post ID and text are returned\n    const response = await client.posts.getLikingUsers(id, {\n      tweetFields: ['lang', 'author_id'], // Edit optional query parameters here\n      userFields: ['created_at'] // Edit optional query parameters here\n    });\n    \n    console.dir(response, {\n      depth: null,\n    });\n  } catch (e) {\n    console.log(e);\n    process.exit(-1);\n  }\n  process.exit();\n})();\n"
  },
  {
    "path": "javascript/posts/get_post_counts_all.js",
    "content": "// Search for public posts across the whole Twitter archive\n// https://developer.twitter.com/en/docs/twitter-api/tweets/search/quick-start/full-archive-search\n\nconst { Client } = require('@xdevplatform/xdk');\n\n// The code below sets the bearer token from your environment variables\n// To set environment variables on macOS or Linux, run the export command below from the terminal:\n// export BEARER_TOKEN='YOUR-TOKEN'\nconst token = process.env.BEARER_TOKEN;\nconst client = new Client({ bearerToken: token });\n\n(async () => {\n    try {\n        // Edit query parameters below and specify a search query\n        // optional params: start_time,end_time,since_id,until_id,next_token,granularity\n        const response = await client.posts.getCountsAll('from:xdevelopers', {\n            granularity: 'day',\n            startTime: '2021-01-01T00:00:00Z'\n        });\n        \n        console.dir(response, {\n            depth: null\n        });\n\n    } catch (e) {\n        console.log(e);\n        process.exit(-1);\n    }\n    process.exit();\n})();"
  },
  {
    "path": "javascript/posts/get_post_counts_recent.js",
    "content": "// Search for posts within the past seven days\n// https://developer.twitter.com/en/docs/twitter-api/tweets/search/quick-start/recent-search\n\nconst { Client } = require('@xdevplatform/xdk');\n\n// The code below sets the bearer token from your environment variables\n// To set environment variables on macOS or Linux, run the export command below from the terminal:\n// export BEARER_TOKEN='YOUR-TOKEN'\nconst token = process.env.BEARER_TOKEN;\nconst client = new Client({ bearerToken: token });\n\n(async () => {\n    try {\n        // Edit query parameters below and specify a search query\n        // optional params: start_time,end_time,since_id,until_id,next_token,granularity\n        const response = await client.posts.getCountsRecent('from:xdevelopers', {\n            granularity: 'day'\n        });\n        \n        console.dir(response, {\n            depth: null\n        });\n\n    } catch (e) {\n        console.log(e);\n        process.exit(-1);\n    }\n    process.exit();\n})();\n\n"
  },
  {
    "path": "javascript/posts/get_posts_by_ids.js",
    "content": "/**\n * Post Lookup - X API v2\n * \n * Endpoint: GET https://api.x.com/2/posts\n * Docs: https://developer.x.com/en/docs/twitter-api/tweets/lookup/api-reference/get-tweets\n * \n * Authentication: Bearer Token (App-only) or OAuth (User Context)\n * Required env vars: BEARER_TOKEN\n */\n\nconst { Client } = require('@xdevplatform/xdk');\n\nconst token = process.env.BEARER_TOKEN;\nconst client = new Client({ bearerToken: token });\n\n// These are the parameters for the API request\n// specify Post IDs to fetch, and any additional fields that are required\n// by default, only the Post ID and text are returned\nconst postIDs = ['1278747501642657792', '1275828087666679809']; // Edit the Post IDs to look up\n\n\n(async () => {\n    try {\n        // Post IDs to look up (comma-separated, up to 100)\n        const response = await client.posts.getByIds(postIDs, {\n            tweetFields: ['created_at', 'author_id', 'lang', 'source', 'public_metrics'],\n            userFields: ['created_at'],\n            expansions: ['author_id']\n        });\n        \n        console.dir(response, { depth: null });\n    } catch (e) {\n        console.log(e);\n        process.exit(-1);\n    }\n    process.exit();\n})();\n"
  },
  {
    "path": "javascript/posts/get_posts_by_ids_user_context.js",
    "content": "// Get Post objects by ID, using user authentication\n// https://developer.twitter.com/en/docs/twitter-api/tweets/lookup/quick-start\n\nconst { \n  Client, \n  OAuth2,\n  generateCodeVerifier,\n  generateCodeChallenge\n} = require('@xdevplatform/xdk');\n\nconst readline = require('readline').createInterface({\n  input: process.stdin,\n  output: process.stdout\n});\n\n// The code below sets the client ID and client secret from your environment variables\n// To set environment variables on macOS or Linux, run the export commands below from the terminal:\n// export CLIENT_ID='YOUR-CLIENT-ID'\n// export CLIENT_SECRET='YOUR-CLIENT-SECRET'\nconst clientId = process.env.CLIENT_ID;\nconst clientSecret = process.env.CLIENT_SECRET;\n\n// These are the parameters for the API request\n// specify Post IDs to fetch, and any additional fields that are required\n// by default, only the Post ID and text are returned\nconst postIDs = ['1278747501642657792', '1275828087666679809']; // Edit the Post IDs to look up\n\nasync function input(prompt) {\n  return new Promise((resolve) => {\n    readline.question(prompt, (out) => {\n      readline.close();\n      resolve(out);\n    });\n  });\n}\n\n// Helper function to parse callback URL\nconst getQueryStringParams = (query) => {\n  return query\n    ? (/^[?#]/.test(query) ? query.slice(1) : query)\n        .split(/[\\?\\&]/)\n        .reduce((params, param) => {\n          let [key, value] = param.split(\"=\");\n          params[key] = value\n            ? decodeURIComponent(value.replace(/\\+/g, \" \"))\n            : \"\";\n          return params;\n        }, {})\n    : {};\n};\n\n(async () => {\n  try {\n    // Configure OAuth 2.0\n    const oauth2Config = {\n      clientId: clientId,\n      clientSecret: clientSecret,\n      redirectUri: 'https://example.com',\n      scope: ['tweet.read', 'users.read', 'offline.access']\n    };\n\n    const oauth2 = new OAuth2(oauth2Config);\n\n    // Generate PKCE parameters\n    const state = 'example-state';\n    const codeVerifier = generateCodeVerifier();\n    const codeChallenge = await generateCodeChallenge(codeVerifier);\n    \n    oauth2.setPkceParameters(codeVerifier, codeChallenge);\n    \n    // Get authorization URL\n    const authUrl = await oauth2.getAuthorizationUrl(state);\n    console.log('Please go here and authorize:', authUrl);\n\n    // Input callback URL from terminal\n    const redirectCallback = await input('Paste the redirected callback URL here: ');\n\n    // Parse callback\n    const { state: returnedState, code } = getQueryStringParams(redirectCallback);\n    if (returnedState !== state) {\n      console.log(\"State doesn't match\");\n      process.exit(-1);\n    }\n\n    // Exchange code for tokens\n    const tokens = await oauth2.exchangeCode(code, codeVerifier);\n\n    // Create client with access token\n    const client = new Client({\n      accessToken: tokens.access_token\n    });\n\n    // Make the request using SDK\n    const response = await client.posts.getByIds(postIDs, {\n      tweetFields: ['lang', 'author_id'],\n      userFields: ['created_at']\n    });\n    \n    console.dir(response, {\n      depth: null\n    });\n\n  } catch (e) {\n    console.log(e);\n    process.exit(-1);\n  }\n  process.exit();\n})();\n\n"
  },
  {
    "path": "javascript/posts/get_quoted_posts.js",
    "content": "// Get Quote Posts by Post ID\n// https://developer.twitter.com/en/docs/twitter-api/tweets/quote-tweets-lookup/quick-start\n\nconst { Client, PostPaginator } = require('@xdevplatform/xdk');\n\nconst postId = '1980412193624785337';\n\n// The code below sets the bearer token from your environment variables\n// To set environment variables on macOS or Linux, run the export command below from the terminal:\n// export BEARER_TOKEN='YOUR-TOKEN'\nconst bearerToken = process.env.BEARER_TOKEN;\nconst client = new Client({ bearerToken: bearerToken });\n\nconst getQuotePosts = async () => {\n    console.log(\"Retrieving quote posts...\");\n    \n    // Use paginator for automatic pagination\n    const quotePosts = new PostPaginator(\n        async (token) => {\n            const res = await client.posts.getQuoted(postId, {\n                maxResults: 100,\n                paginationToken: token,\n                tweetFields: ['created_at']\n            });\n            return {\n                data: res.data ?? [],\n                meta: res.meta,\n                includes: res.includes,\n                errors: res.errors\n            };\n        }\n    );\n\n    // Fetch all pages\n    await quotePosts.fetchNext();\n    while (!quotePosts.done) {\n        await quotePosts.fetchNext();\n    }\n\n    console.dir(quotePosts.posts, {\n        depth: null\n    });\n\n    console.log(`Got ${quotePosts.posts.length} quote posts for Post ID ${postId}!`);\n}\n\ngetQuotePosts().catch(err => {\n    console.error('Error:', err);\n    process.exit(-1);\n});\n\n"
  },
  {
    "path": "javascript/posts/get_reposted_by.js",
    "content": "// Get Reposted By (Users who reposted) by Post ID\n// https://developer.twitter.com/en/docs/twitter-api/tweets/retweets/api-reference/get-tweets-id-retweeted_by\n\nconst { Client, UserPaginator } = require('@xdevplatform/xdk');\n\n// The code below sets the bearer token from your environment variables\n// To set environment variables on macOS or Linux, run the export command below from the terminal:\n// export BEARER_TOKEN='YOUR-TOKEN'\nconst bearerToken = process.env.BEARER_TOKEN;\nconst client = new Client({ bearerToken: bearerToken });\n\n// You can replace the ID given with the Post ID you wish to lookup reposting users for\n// You can find an ID by using the Post lookup endpoint\nconst postId = \"1980412193624785337\";\n\nconst getRepostedBy = async () => {\n    console.log(\"Retrieving users who reposted...\");\n    \n    // Use paginator for automatic pagination\n    const repostedBy = new UserPaginator(\n        async (token) => {\n            const res = await client.posts.getRepostedBy(postId, {\n                maxResults: 100,\n                paginationToken: token,\n                tweetFields: ['lang', 'author_id'],\n                userFields: ['created_at']\n            });\n            return {\n                data: res.data ?? [],\n                meta: res.meta,\n                includes: res.includes,\n                errors: res.errors\n            };\n        }\n    );\n\n    // Fetch all pages\n    await repostedBy.fetchNext();\n    while (!repostedBy.done) {\n        await repostedBy.fetchNext();\n    }\n\n    console.dir(repostedBy.users, {\n        depth: null\n    });\n\n    console.log(`Got ${repostedBy.users.length} users who reposted Post ID ${postId}!`);\n}\n\ngetRepostedBy().catch(err => {\n    console.error('Error:', err);\n    process.exit(-1);\n});\n\n"
  },
  {
    "path": "javascript/posts/search_all.js",
    "content": "// Search for public posts across the whole Twitter archive\n// https://developer.twitter.com/en/docs/twitter-api/tweets/search/quick-start/full-archive-search\n\nconst { Client, PostPaginator } = require('@xdevplatform/xdk');\n\n// The code below sets the bearer token from your environment variables\n// To set environment variables on macOS or Linux, run the export command below from the terminal:\n// export BEARER_TOKEN='YOUR-TOKEN'\nconst bearerToken = process.env.BEARER_TOKEN;\nconst client = new Client({ bearerToken: bearerToken });\n\nconst query = 'from:xdevelopers';\n\nconst searchAll = async () => {\n    console.log(\"Searching full archive...\");\n    \n    // Use paginator for automatic pagination\n    const searchResults = new PostPaginator(\n        async (token) => {\n            const res = await client.posts.searchAll(query, {\n                maxResults: 100,\n                nextToken: token,\n                tweetFields: ['author_id']\n            });\n            return {\n                data: res.data ?? [],\n                meta: res.meta,\n                includes: res.includes,\n                errors: res.errors\n            };\n        }\n    );\n\n    // Fetch all pages\n    await searchResults.fetchNext();\n    while (!searchResults.done) {\n        await searchResults.fetchNext();\n    }\n\n    console.dir(searchResults.posts, {\n        depth: null\n    });\n\n    console.log(`Got ${searchResults.posts.length} posts for query: ${query}`);\n}\n\nsearchAll().catch(err => {\n    console.error('Error:', err);\n    process.exit(-1);\n});\n"
  },
  {
    "path": "javascript/posts/search_recent.js",
    "content": "/**\n * Recent Search - X API v2\n * \n * Endpoint: GET https://api.x.com/2/posts/search/recent\n * Docs: https://developer.x.com/en/docs/twitter-api/tweets/search/api-reference/get-tweets-search-recent\n * \n * Authentication: Bearer Token (App-only)\n * Required env vars: BEARER_TOKEN\n * \n * Note: Returns posts from the last 7 days.\n * This example demonstrates automatic pagination using PostPaginator\n * to fetch all pages of results.\n */\n\nconst { Client, PostPaginator } = require('@xdevplatform/xdk');\n\nconst bearerToken = process.env.BEARER_TOKEN;\nconst client = new Client({ bearerToken: bearerToken });\n\nconst query = 'from:x -is:retweet';\n\nconst searchRecent = async () => {\n    console.log(\"Searching recent posts...\");\n    \n    // Use paginator for automatic pagination\n    const searchResults = new PostPaginator(\n        async (token) => {\n            const res = await client.posts.searchRecent(query, {\n                maxResults: 100,\n                nextToken: token,\n                tweetFields: ['author_id', 'created_at']\n            });\n            return {\n                data: res.data ?? [],\n                meta: res.meta,\n                includes: res.includes,\n                errors: res.errors\n            };\n        }\n    );\n\n    // Fetch all pages\n    await searchResults.fetchNext();\n    while (!searchResults.done) {\n        await searchResults.fetchNext();\n    }\n\n    console.dir(searchResults.posts, {\n        depth: null\n    });\n\n    console.log(`Got ${searchResults.posts.length} posts for query: ${query}`);\n}\n\nsearchRecent().catch(err => {\n    console.error('Error:', err);\n    process.exit(-1);\n});\n"
  },
  {
    "path": "javascript/spaces/get_spaces_by_ids.js",
    "content": "/**\n * Spaces Lookup - X API v2\n * \n * Endpoint: GET https://api.x.com/2/spaces\n * Docs: https://developer.x.com/en/docs/twitter-api/spaces/lookup/api-reference/get-spaces\n * \n * Authentication: Bearer Token (App-only) or OAuth (User Context)\n * Required env vars: BEARER_TOKEN\n */\n\nconst { Client } = require('@xdevplatform/xdk');\n\nconst token = process.env.BEARER_TOKEN;\nconst client = new Client({ bearerToken: token });\n\nconst spaceIds = ['1DXxyRYNejbKM'];\n\n(async () => {\n    try {\n        // Replace with Space IDs you want to look up\n        const response = await client.spaces.getByIds(spaceIds, {\n            spaceFields: ['host_ids', 'created_at', 'creator_id', 'participant_count', 'title', 'state']\n        });\n        \n        console.dir(response, { depth: null });\n    } catch (e) {\n        console.log(e);\n        process.exit(-1);\n    }\n    process.exit();\n})();\n"
  },
  {
    "path": "javascript/spaces/search_spaces.js",
    "content": "// Lookup Spaces by ID\n// https://developer.twitter.com/en/docs/twitter-api/spaces/lookup\n\nconst { Client } = require('@xdevplatform/xdk');\n\n// The code below sets the bearer token from your environment variables\n// To set environment variables on macOS or Linux, run the export command below from the terminal:\n// export BEARER_TOKEN='YOUR-TOKEN'\nconst token = process.env.BEARER_TOKEN;\nconst client = new Client({ bearerToken: token });\n\nconst query = 'NBA';\n\n(async () => {\n    try {\n        // Edit query parameters below and specify a search query\n        // optional params: host_ids,conversation_controls,created_at,creator_id,id,invited_user_ids,is_ticketed,lang,media_key,participants,scheduled_start,speaker_ids,started_at,state,title,updated_at\n        const response = await client.spaces.search(query, {\n            spaceFields: ['title', 'created_at'],\n            expansions: ['creator_id']\n        });\n        \n        console.dir(response, {\n            depth: null\n        });\n\n    } catch (e) {\n        console.log(e);\n        process.exit(-1);\n    }\n    process.exit();\n})();\n"
  },
  {
    "path": "javascript/streams/stream_posts_filtered.js",
    "content": "// Open a realtime stream of posts, filtered according to rules\n// https://developer.twitter.com/en/docs/twitter-api/tweets/filtered-stream/quick-start\n\nconst { Client } = require('@xdevplatform/xdk');\n\n// The code below sets the bearer token from your environment variables\n// To set environment variables on macOS or Linux, run the export command below from the terminal:\n// export BEARER_TOKEN='YOUR-TOKEN'\nconst token = process.env.BEARER_TOKEN;\nconst client = new Client({ bearerToken: token });\n\n// this sets up two rules - the value is the search terms to match on, and the tag is an identifier that\n// will be applied to the posts returned to show which rule they matched\n// with a standard project with Basic Access, you can add up to 25 concurrent rules to your stream, and\n// each rule can be up to 512 characters long\n\n// Edit rules as desired below\nconst rules = [{\n        value: 'dog has:images -is:retweet',\n        tag: 'dog pictures'\n    },\n    {\n        value: 'cat has:images -grumpy',\n        tag: 'cat pictures'\n    },\n];\n\n(async () => {\n    try {\n        // Gets the complete list of rules currently applied to the stream\n        const currentRules = await client.stream.getRules();\n\n        // Delete all rules. Comment the line below if you want to keep your existing rules.\n        if (currentRules.data && currentRules.data.length > 0) {\n            const ids = currentRules.data.map(rule => rule.id);\n            await client.stream.updateRules({ delete: { ids: ids } });\n        }\n\n        // Add rules to the stream. Comment the line below if you don't want to add new rules.\n        await client.stream.updateRules({ add: rules });\n\n        // Listen to the stream\n        const stream = await client.stream.posts({\n            tweetFields: ['id', 'text', 'created_at']\n        });\n\n        stream.on('data', (event) => {\n            // event is the parsed JSON line (data/includes/matching_rules)\n            console.log('New data:', event);\n        });\n\n        stream.on('error', (e) => {\n            console.error('Stream error:', e);\n            if (e.detail === \"This stream is currently at the maximum allowed connection limit.\") {\n                console.log(e.detail);\n                process.exit(1);\n            }\n        });\n\n        stream.on('keepAlive', () => {\n            // heartbeat event - keep alive signal received\n        });\n\n        stream.on('close', () => {\n            console.log('Stream closed');\n        });\n\n    } catch (e) {\n        console.error(e);\n        process.exit(1);\n    }\n})();\n"
  },
  {
    "path": "javascript/streams/stream_posts_sample.js",
    "content": "// Open a live stream of roughly 1% random sample of publicly available posts\n// https://developer.twitter.com/en/docs/twitter-api/tweets/volume-streams/quick-start\n\nconst { Client } = require('@xdevplatform/xdk');\n\n// The code below sets the bearer token from your environment variables\n// To set environment variables on macOS or Linux, run the export command below from the terminal:\n// export BEARER_TOKEN='YOUR-TOKEN'\nconst token = process.env.BEARER_TOKEN;\nconst client = new Client({ bearerToken: token });\n\n(async () => {\n  try {\n    // 1% sampled public posts\n    const stream = await client.stream.postsSample({\n      tweetFields: ['id', 'text', 'created_at']\n    });\n\n    // Listen to events\n    stream.on('data', (event) => {\n      // event is the parsed JSON line (data/includes/matching_rules)\n      console.log('New data:', event);\n    });\n\n    stream.on('error', (e) => {\n      console.error('Stream error:', e);\n      if (e.status === 401) {\n        console.log('Unauthorized');\n        process.exit(1);\n      } else if (e.detail === \"This stream is currently at the maximum allowed connection limit.\") {\n        console.log(e.detail);\n        process.exit(1);\n      }\n    });\n\n    stream.on('keepAlive', () => {\n      // heartbeat event - keep alive signal received\n    });\n\n    stream.on('close', () => {\n      console.log('Stream closed');\n    });\n  } catch (e) {\n    console.error('Error:', e);\n    process.exit(1);\n  }\n})();\n"
  },
  {
    "path": "javascript/usage/get_usage.js",
    "content": "// Get Posts Usage\n// https://developer.twitter.com/en/docs/twitter-api/usage/tweets\n\nconst { Client } = require('@xdevplatform/xdk');\n\n// The code below sets the bearer token from your environment variables\n// To set environment variables on macOS or Linux, run the export command below from the terminal:\n// export BEARER_TOKEN='YOUR-TOKEN'\nconst token = process.env.BEARER_TOKEN;\nconst client = new Client({ bearerToken: token });\n\n(async () => {\n    try {\n        // Make request\n        const response = await client.usage.get();\n        \n        console.dir(response, {\n            depth: null\n        });\n\n    } catch (e) {\n        console.log(e);\n        process.exit(-1);\n    }\n    process.exit();\n})();\n\n"
  },
  {
    "path": "javascript/users/block/get_blocking.js",
    "content": "// Block a user, using user authentication\n// https://developer.twitter.com/en/docs/twitter-api/users/blocks/quick-start\nconst { \n  Client, \n  OAuth2,\n  generateCodeVerifier,\n  generateCodeChallenge\n} = require('@xdevplatform/xdk');\n\nconst readline = require('readline').createInterface({\n  input: process.stdin,\n  output: process.stdout\n});\n\n// The code below sets the client ID and client secret from your environment variables\n// To set environment variables on macOS or Linux, run the export commands below from the terminal:\n// export CLIENT_ID='YOUR-CLIENT-ID'\n// export CLIENT_SECRET='YOUR-CLIENT-SECRET'\nconst clientId = process.env.CLIENT_ID;\nconst clientSecret = process.env.CLIENT_SECRET;\n\n// Be sure to replace your-user-id with your own user ID or one of an authenticated user\n// You can find a user ID by using the user lookup endpoint\nconst userId = \"your-user-id\";\n\nasync function input(prompt) {\n  return new Promise((resolve) => {\n    readline.question(prompt, (out) => {\n      readline.close();\n      resolve(out);\n    });\n  });\n}\n\n// Helper function to parse callback URL\nconst getQueryStringParams = (query) => {\n  return query\n    ? (/^[?#]/.test(query) ? query.slice(1) : query)\n        .split(/[\\?\\&]/)\n        .reduce((params, param) => {\n          let [key, value] = param.split(\"=\");\n          params[key] = value\n            ? decodeURIComponent(value.replace(/\\+/g, \" \"))\n            : \"\";\n          return params;\n        }, {})\n    : {};\n};\n\n(async () => {\n  try {\n    // Configure OAuth 2.0\n    const oauth2Config = {\n      clientId: clientId,\n      clientSecret: clientSecret,\n      redirectUri: 'https://example.com',\n      scope: ['tweet.read', 'users.read', 'tweet.write', 'offline.access', 'block.read']\n    };\n\n    const oauth2 = new OAuth2(oauth2Config);\n\n    // Generate PKCE parameters\n    const state = 'example-state';\n    const codeVerifier = generateCodeVerifier();\n    const codeChallenge = await generateCodeChallenge(codeVerifier);\n    \n    oauth2.setPkceParameters(codeVerifier, codeChallenge);\n    \n    // Get authorization URL\n    const authUrl = await oauth2.getAuthorizationUrl(state);\n    console.log('Please go here and authorize:', authUrl);\n\n    // Input callback URL from terminal\n    const redirectCallback = await input('Paste the redirected callback URL here: ');\n\n    // Parse callback\n    const { state: returnedState, code } = getQueryStringParams(redirectCallback);\n    if (returnedState !== state) {\n      console.log(\"State doesn't match\");\n      process.exit(-1);\n    }\n\n    // Exchange code for tokens\n    const tokens = await oauth2.exchangeCode(code, codeVerifier);\n\n    // Create client with access token\n    const client = new Client({\n      accessToken: tokens.access_token\n    });\n\n    // Make the request using SDK\n    const response = await client.users.getBlocking(userId);\n    console.dir(response, {\n      depth: null\n    });\n  } catch (e) {\n    console.log(e);\n    process.exit(-1);\n  }\n  process.exit();\n})();\n"
  },
  {
    "path": "javascript/users/bookmark/create_bookmark.js",
    "content": "const { \n  Client, \n  OAuth2,\n  generateCodeVerifier,\n  generateCodeChallenge\n} = require('@xdevplatform/xdk');\n\nconst readline = require(\"readline\").createInterface({\n  input: process.stdin,\n  output: process.stdout,\n});\n\n//Helper function to parse callback\nconst getQueryStringParams = (query) => {\n  return query\n    ? (/^[?#]/.test(query) ? query.slice(1) : query)\n        .split(/[\\?\\&]/)\n        .reduce((params, param) => {\n          let [key, value] = param.split(\"=\");\n          params[key] = value\n            ? decodeURIComponent(value.replace(/\\+/g, \" \"))\n            : \"\";\n          return params;\n        }, {})\n    : {};\n};\n\n//Helper terminal input function\nasync function input(prompt) {\n  return new Promise((resolve) => {\n    readline.question(prompt, (out) => {\n      readline.close();\n      resolve(out);\n    });\n  });\n}\n\n// The code below sets the client ID and client secret from your environment variables\n// To set environment variables on macOS or Linux, run the export commands below from the terminal:\n// export CLIENT_ID='YOUR-CLIENT-ID'\n// export CLIENT_SECRET='YOUR-CLIENT-SECRET'\nconst CLIENT_ID = process.env.CLIENT_ID;\nconst CLIENT_SECRET = process.env.CLIENT_SECRET;\n\n// Include the ID of the Post you wish to bookmark\nconst tweetId = \"post-id\"; // Replace with the ID of the Post you wish to bookmark\n\n(async () => {\n  try {\n    // Configure OAuth 2.0\n    const oauth2Config = {\n      clientId: CLIENT_ID,\n      clientSecret: CLIENT_SECRET,\n      redirectUri: 'https://example.com',\n      scope: ['tweet.read', 'users.read', 'bookmark.write']\n    };\n\n    const oauth2 = new OAuth2(oauth2Config);\n\n    // Generate PKCE parameters\n    const STATE = \"my-state\";\n    const codeVerifier = generateCodeVerifier();\n    const codeChallenge = await generateCodeChallenge(codeVerifier);\n    \n    oauth2.setPkceParameters(codeVerifier, codeChallenge);\n    \n    // Get authorization URL\n    const authUrl = await oauth2.getAuthorizationUrl(STATE);\n    console.log(`Please go here and authorize:`, authUrl);\n\n    //Input users callback url in terminal\n    const redirectCallback = await input(\"Paste the redirected callback here: \");\n\n    //Parse callback\n    const { state, code } = getQueryStringParams(redirectCallback);\n    if (state !== STATE) {\n      console.log(\"State isn't matching\");\n      process.exit(-1);\n    }\n\n    // Exchange code for tokens\n    const tokens = await oauth2.exchangeCode(code, codeVerifier);\n\n    // Create client with access token\n    const client = new Client({\n      accessToken: tokens.access_token\n    });\n\n    //Get the user ID\n    const meResponse = await client.users.getMe();\n    const userId = meResponse.data?.id;\n\n    if (!userId) {\n      throw new Error('Could not get user ID');\n    }\n\n    //Makes api call\n    const postBookmark = await client.users.createBookmark(userId, { tweet_id: tweetId });\n    console.dir(postBookmark, {\n      depth: null,\n    });\n    process.exit();\n  } catch (error) {\n    console.log(error);\n    process.exit(-1);\n  }\n})();\n"
  },
  {
    "path": "javascript/users/bookmark/delete_bookmark.js",
    "content": "const { \n  Client, \n  OAuth2,\n  generateCodeVerifier,\n  generateCodeChallenge\n} = require('@xdevplatform/xdk');\n\nconst readline = require(\"readline\").createInterface({\n  input: process.stdin,\n  output: process.stdout,\n});\n\n//Helper function to parse callback\nconst getQueryStringParams = (query) => {\n  return query\n    ? (/^[?#]/.test(query) ? query.slice(1) : query)\n        .split(/[\\?\\&]/)\n        .reduce((params, param) => {\n          let [key, value] = param.split(\"=\");\n          params[key] = value\n            ? decodeURIComponent(value.replace(/\\+/g, \" \"))\n            : \"\";\n          return params;\n        }, {})\n    : {};\n};\n\n//Helper terminal input function\nasync function input(prompt) {\n  return new Promise((resolve) => {\n    readline.question(prompt, (out) => {\n      readline.close();\n      resolve(out);\n    });\n  });\n}\n\n// The code below sets the client ID and client secret from your environment variables\n// To set environment variables on macOS or Linux, run the export commands below from the terminal:\n// export CLIENT_ID='YOUR-CLIENT-ID'\n// export CLIENT_SECRET='YOUR-CLIENT-SECRET'\nconst CLIENT_ID = process.env.CLIENT_ID;\nconst CLIENT_SECRET = process.env.CLIENT_SECRET;\n\n// Include the ID of the Post you wish to unbookmark\nconst tweetId = \"1996314591996129694\";\n\n(async () => {\n  try {\n    // Configure OAuth 2.0\n    const oauth2Config = {\n      clientId: CLIENT_ID,\n      clientSecret: CLIENT_SECRET,\n      redirectUri: 'https://example.com',\n      scope: ['tweet.read', 'users.read', 'bookmark.write']\n    };\n\n    const oauth2 = new OAuth2(oauth2Config);\n\n    // Generate PKCE parameters\n    const STATE = \"my-state\";\n    const codeVerifier = generateCodeVerifier();\n    const codeChallenge = await generateCodeChallenge(codeVerifier);\n    \n    oauth2.setPkceParameters(codeVerifier, codeChallenge);\n    \n    // Get authorization URL\n    const authUrl = await oauth2.getAuthorizationUrl(STATE);\n    console.log(`Please go here and authorize:`, authUrl);\n\n    //Input users callback url in terminal\n    const redirectCallback = await input(\"Paste the redirected callback here: \");\n\n    //Parse callback\n    const { state, code } = getQueryStringParams(redirectCallback);\n    if (state !== STATE) {\n      console.log(\"State isn't matching\");\n      process.exit(-1);\n    }\n\n    // Exchange code for tokens\n    const tokens = await oauth2.exchangeCode(code, codeVerifier);\n\n    // Create client with access token\n    const client = new Client({\n      accessToken: tokens.access_token\n    });\n\n    //Get the user ID\n    const meResponse = await client.users.getMe();\n    const userId = meResponse.data?.id;\n\n    if (!userId) {\n      throw new Error('Could not get user ID');\n    }\n\n    //Makes api call\n    const deleteBookmark = await client.users.deleteBookmark(userId, tweetId);\n    console.dir(deleteBookmark, {\n      depth: null,\n    });\n    process.exit();\n  } catch (error) {\n    console.log(error);\n    process.exit(-1);\n  }\n})();\n"
  },
  {
    "path": "javascript/users/bookmark/get_bookmarks.js",
    "content": "const { \n  Client, \n  OAuth2,\n  generateCodeVerifier,\n  generateCodeChallenge\n} = require('@xdevplatform/xdk');\n\nconst readline = require(\"readline\").createInterface({\n  input: process.stdin,\n  output: process.stdout,\n});\n\n//Helper function to parse callback\nconst getQueryStringParams = (query) => {\n  return query\n    ? (/^[?#]/.test(query) ? query.slice(1) : query)\n        .split(/[\\?\\&]/)\n        .reduce((params, param) => {\n          let [key, value] = param.split(\"=\");\n          params[key] = value\n            ? decodeURIComponent(value.replace(/\\+/g, \" \"))\n            : \"\";\n          return params;\n        }, {})\n    : {};\n};\n\n//Helper terminal input function\nasync function input(prompt) {\n  return new Promise((resolve) => {\n    readline.question(prompt, (out) => {\n      readline.close();\n      resolve(out);\n    });\n  });\n}\n\n// The code below sets the client ID and client secret from your environment variables\n// To set environment variables on macOS or Linux, run the export commands below from the terminal:\n// export CLIENT_ID='YOUR-CLIENT-ID'\n// export CLIENT_SECRET='YOUR-CLIENT-SECRET'\nconst CLIENT_ID = process.env.CLIENT_ID;\nconst CLIENT_SECRET = process.env.CLIENT_SECRET;\n\n// Optional parameters for additional payload data\nconst params = {\n  expansions: ['author_id'],\n  userFields: ['username', 'created_at'],\n  tweetFields: ['geo', 'entities', 'context_annotations']\n};\n\n(async () => {\n  try {\n    // Configure OAuth 2.0\n    const oauth2Config = {\n      clientId: CLIENT_ID,\n      clientSecret: CLIENT_SECRET,\n      redirectUri: 'https://example.com',\n      scope: ['tweet.read', 'users.read', 'bookmark.read']\n    };\n\n    const oauth2 = new OAuth2(oauth2Config);\n\n    // Generate PKCE parameters\n    const STATE = \"my-state\";\n    const codeVerifier = generateCodeVerifier();\n    const codeChallenge = await generateCodeChallenge(codeVerifier);\n    \n    oauth2.setPkceParameters(codeVerifier, codeChallenge);\n    \n    // Get authorization URL\n    const authUrl = await oauth2.getAuthorizationUrl(STATE);\n    console.log(`Please go here and authorize:`, authUrl);\n\n    //Input users callback url in terminal\n    const redirectCallback = await input(\"Paste the redirected callback here: \");\n\n    //Parse callback\n    const { state, code } = getQueryStringParams(redirectCallback);\n    if (state !== STATE) {\n      console.log(\"State isn't matching\");\n      process.exit(-1);\n    }\n\n    // Exchange code for tokens\n    const tokens = await oauth2.exchangeCode(code, codeVerifier);\n\n    // Create client with access token\n    const client = new Client({\n      accessToken: tokens.access_token\n    });\n\n    //Get the user ID\n    const meResponse = await client.users.getMe();\n    const userId = meResponse.data?.id;\n\n    if (!userId) {\n      throw new Error('Could not get user ID');\n    }\n\n    //Makes api call\n    const getBookmark = await client.users.getBookmarks(userId, params);\n    console.dir(getBookmark, {\n      depth: null,\n    });\n    process.exit();\n  } catch (error) {\n    console.log(error);\n    process.exit(-1);\n  }\n})();\n"
  },
  {
    "path": "javascript/users/follow/get_followers.js",
    "content": "// Fetch the followers of a user account, by ID\n// https://developer.twitter.com/en/docs/twitter-api/users/follows/quick-start\n\nconst { Client, UserPaginator } = require('@xdevplatform/xdk');\n\n// this is the ID for @XDevelopers\nconst userId = '2244994945';\nconst bearerToken = process.env.BEARER_TOKEN;\nconst client = new Client({ bearerToken: bearerToken });\n\nconst getFollowers = async () => {\n    console.log(\"Retrieving followers...\");\n    \n    // Use paginator for automatic pagination\n    const followers = new UserPaginator(\n        async (token) => {\n            const res = await client.users.getFollowers(userId, {\n                maxResults: 1000,\n                paginationToken: token,\n                userFields: ['created_at']\n            });\n            return {\n                data: res.data ?? [],\n                meta: res.meta,\n                includes: res.includes,\n                errors: res.errors\n            };\n        }\n    );\n\n    // Fetch all pages\n    await followers.fetchNext();\n    while (!followers.done) {\n        await followers.fetchNext();\n    }\n\n    console.log(followers.users);\n    console.log(`Got ${followers.users.length} users.`);\n}\n\ngetFollowers().catch(err => {\n    console.error('Error:', err);\n    process.exit(-1);\n});\n"
  },
  {
    "path": "javascript/users/follow/get_followers_paginated.js",
    "content": "/**\n * User Followers Lookup (Paginated) - X API v2\n * \n * Endpoint: GET https://api.x.com/2/users/:id/followers\n * Docs: https://developer.x.com/en/docs/twitter-api/users/follows/api-reference/get-users-id-followers\n * \n * Authentication: Bearer Token (App-only) or OAuth (User Context)\n * Required env vars: BEARER_TOKEN\n * \n * This example demonstrates automatic pagination using UserPaginator\n * to fetch all pages of results. For a simple single-request example,\n * see followers_lookup.js\n */\n\nconst { Client, UserPaginator } = require('@xdevplatform/xdk');\n\n// this is the ID for @XDevelopers\nconst userId = '2244994945';\nconst bearerToken = process.env.BEARER_TOKEN;\nconst client = new Client({ bearerToken: bearerToken });\n\nconst getFollowers = async () => {\n    console.log(\"Retrieving followers...\");\n    \n    // Use paginator for automatic pagination\n    const followers = new UserPaginator(\n        async (token) => {\n            const res = await client.users.getFollowers(userId, {\n                maxResults: 1000,\n                paginationToken: token,\n                userFields: ['created_at']\n            });\n            return {\n                data: res.data ?? [],\n                meta: res.meta,\n                includes: res.includes,\n                errors: res.errors\n            };\n        }\n    );\n\n    // Fetch all pages\n    await followers.fetchNext();\n    while (!followers.done) {\n        await followers.fetchNext();\n    }\n\n    console.log(followers.users);\n    console.log(`Got ${followers.users.length} users.`);\n}\n\ngetFollowers().catch(err => {\n    console.error('Error:', err);\n    process.exit(-1);\n});\n\n"
  },
  {
    "path": "javascript/users/follow/get_following_paginated.js",
    "content": "/**\n * User Following Lookup (Paginated) - X API v2\n * \n * Endpoint: GET https://api.x.com/2/users/:id/following\n * Docs: https://developer.x.com/en/docs/twitter-api/users/follows/api-reference/get-users-id-following\n * \n * Authentication: Bearer Token (App-only) or OAuth (User Context)\n * Required env vars: BEARER_TOKEN\n * \n * This example demonstrates automatic pagination using UserPaginator\n * to fetch all pages of results.\n */\n\nconst { Client, UserPaginator } = require('@xdevplatform/xdk');\n\n// this is the ID for @XDevelopers\nconst userId = '2244994945';\nconst bearerToken = process.env.BEARER_TOKEN;\nconst client = new Client({ bearerToken: bearerToken });\n\nconst getFollowing = async () => {\n    console.log(\"Retrieving users this user is following...\");\n\n    // Use paginator for automatic pagination\n    const following = new UserPaginator(\n        async (token) => {\n            const res = await client.users.getFollowing(userId, {\n                maxResults: 1000,\n                paginationToken: token,\n                userFields: ['created_at']\n            });\n            return {\n                data: res.data ?? [],\n                meta: res.meta,\n                includes: res.includes,\n                errors: res.errors\n            };\n        }\n    );\n\n    // Fetch all pages\n    await following.fetchNext();\n    while (!following.done) {\n        await following.fetchNext();\n    }\n\n    console.log(following.users);\n    console.log(`Got ${following.users.length} users.`);\n}\n\ngetFollowing().catch(err => {\n    console.error('Error:', err);\n    process.exit(-1);\n});\n\n"
  },
  {
    "path": "javascript/users/get_users_by_usernames.js",
    "content": "/**\n * User Lookup - X API v2\n * \n * Endpoint: GET https://api.x.com/2/users/by\n * Docs: https://developer.x.com/en/docs/twitter-api/users/lookup/api-reference/get-users-by\n * \n * Authentication: Bearer Token (App-only) or OAuth (User Context)\n * Required env vars: BEARER_TOKEN\n */\n\nconst { Client } = require('@xdevplatform/xdk');\n\nconst token = process.env.BEARER_TOKEN;\nconst client = new Client({ bearerToken: token });\n\nconst usernames = ['XDevelopers', 'X'];\n(async () => {\n    try {\n        // Usernames to look up (up to 100)\n        const response = await client.users.getByUsernames(usernames, {\n            userFields: ['created_at', 'description', 'public_metrics'],\n            expansions: ['pinned_tweet_id']\n        });\n        \n        console.dir(response, { depth: null });\n    } catch (e) {\n        console.log(e);\n        process.exit(-1);\n    }\n    process.exit();\n})();\n"
  },
  {
    "path": "javascript/users/get_users_by_usernames_user_context.js",
    "content": "// Get User objects by username, using user authentication\n// https://developer.twitter.com/en/docs/twitter-api/users/lookup/quick-start\n\nconst { \n  Client, \n  OAuth2,\n  generateCodeVerifier,\n  generateCodeChallenge\n} = require('@xdevplatform/xdk');\n\nconst readline = require('readline').createInterface({\n  input: process.stdin,\n  output: process.stdout\n});\n\n// The code below sets the client ID and client secret from your environment variables\n// To set environment variables on macOS or Linux, run the export commands below from the terminal:\n// export CLIENT_ID='YOUR-CLIENT-ID'\n// export CLIENT_SECRET='YOUR-CLIENT-SECRET'\nconst clientId = process.env.CLIENT_ID;\nconst clientSecret = process.env.CLIENT_SECRET;\n\n// These are the parameters for the API request\n// specify usernames to fetch, and any additional fields that are required\n// by default, only the User ID, name and username are returned\nconst usernames = ['XDevelopers', 'X']; // Edit usernames to look up\n\nasync function input(prompt) {\n  return new Promise((resolve) => {\n    readline.question(prompt, (out) => {\n      readline.close();\n      resolve(out);\n    });\n  });\n}\n\n// Helper function to parse callback URL\nconst getQueryStringParams = (query) => {\n  return query\n    ? (/^[?#]/.test(query) ? query.slice(1) : query)\n        .split(/[\\?\\&]/)\n        .reduce((params, param) => {\n          let [key, value] = param.split(\"=\");\n          params[key] = value\n            ? decodeURIComponent(value.replace(/\\+/g, \" \"))\n            : \"\";\n          return params;\n        }, {})\n    : {};\n};\n\n(async () => {\n  try {\n    // Configure OAuth 2.0\n    const oauth2Config = {\n      clientId: clientId,\n      clientSecret: clientSecret,\n      redirectUri: 'https://example.com',\n      scope: ['tweet.read', 'users.read', 'offline.access']\n    };\n\n    const oauth2 = new OAuth2(oauth2Config);\n\n    // Generate PKCE parameters\n    const state = 'example-state';\n    const codeVerifier = generateCodeVerifier();\n    const codeChallenge = await generateCodeChallenge(codeVerifier);\n    \n    oauth2.setPkceParameters(codeVerifier, codeChallenge);\n    \n    // Get authorization URL\n    const authUrl = await oauth2.getAuthorizationUrl(state);\n    console.log('Please go here and authorize:', authUrl);\n\n    // Input callback URL from terminal\n    const redirectCallback = await input('Paste the redirected callback URL here: ');\n\n    // Parse callback\n    const { state: returnedState, code } = getQueryStringParams(redirectCallback);\n    if (returnedState !== state) {\n      console.log(\"State doesn't match\");\n      process.exit(-1);\n    }\n\n    // Exchange code for tokens\n    const tokens = await oauth2.exchangeCode(code, codeVerifier);\n\n    // Create client with access token\n    const client = new Client({\n      accessToken: tokens.access_token\n    });\n\n    // Make the request using SDK\n    const response = await client.users.getByUsernames(usernames, {\n      userFields: ['created_at', 'description'],\n      expansions: ['pinned_tweet_id']\n    });\n    \n    console.dir(response, {\n      depth: null\n    });\n\n  } catch (e) {\n    console.log(e);\n    process.exit(-1);\n  }\n  process.exit();\n})();\n"
  },
  {
    "path": "javascript/users/get_users_me.js",
    "content": "const { \n  Client, \n  OAuth2,\n  generateCodeVerifier,\n  generateCodeChallenge\n} = require('@xdevplatform/xdk');\n\nconst readline = require('readline').createInterface({\n  input: process.stdin,\n  output: process.stdout\n});\n\n// The code below sets the client ID and client secret from your environment variables\n// To set environment variables on macOS or Linux, run the export commands below from the terminal:\n// export CLIENT_ID='YOUR-CLIENT-ID'\n// export CLIENT_SECRET='YOUR-CLIENT-SECRET'\nconst clientId = process.env.CLIENT_ID;\nconst clientSecret = process.env.CLIENT_SECRET;\n\nasync function input(prompt) {\n  return new Promise((resolve) => {\n    readline.question(prompt, (out) => {\n      readline.close();\n      resolve(out);\n    });\n  });\n}\n\n// Helper function to parse callback URL\nconst getQueryStringParams = (query) => {\n  return query\n    ? (/^[?#]/.test(query) ? query.slice(1) : query)\n        .split(/[\\?\\&]/)\n        .reduce((params, param) => {\n          let [key, value] = param.split(\"=\");\n          params[key] = value\n            ? decodeURIComponent(value.replace(/\\+/g, \" \"))\n            : \"\";\n          return params;\n        }, {})\n    : {};\n};\n\n(async () => {\n  try {\n    // Configure OAuth 2.0\n    const oauth2Config = {\n      clientId: clientId,\n      clientSecret: clientSecret,\n      redirectUri: 'https://example.com',\n      scope: ['tweet.read', 'users.read', 'offline.access']\n    };\n\n    const oauth2 = new OAuth2(oauth2Config);\n\n    // Generate PKCE parameters\n    const state = 'example-state';\n    const codeVerifier = generateCodeVerifier();\n    const codeChallenge = await generateCodeChallenge(codeVerifier);\n    \n    oauth2.setPkceParameters(codeVerifier, codeChallenge);\n    \n    // Get authorization URL\n    const authUrl = await oauth2.getAuthorizationUrl(state);\n    console.log('Please go here and authorize:', authUrl);\n\n    // Input callback URL from terminal\n    const redirectCallback = await input('Paste the redirected callback URL here: ');\n\n    // Parse callback\n    const { state: returnedState, code } = getQueryStringParams(redirectCallback);\n    if (returnedState !== state) {\n      console.log(\"State doesn't match\");\n      process.exit(-1);\n    }\n\n    // Exchange code for tokens\n    const tokens = await oauth2.exchangeCode(code, codeVerifier);\n\n    // Create client with access token\n    const client = new Client({\n      accessToken: tokens.access_token\n    });\n\n    // Make the request using SDK - get authenticated user\n    const response = await client.users.getMe({\n      userFields: ['created_at', 'description'],\n      expansions: ['pinned_tweet_id']\n    });\n    \n    console.dir(response, {\n      depth: null\n    });\n\n  } catch (e) {\n    console.log(e);\n    process.exit(-1);\n  }\n  process.exit();\n})();\n"
  },
  {
    "path": "javascript/users/like/get_liked_posts.js",
    "content": "// Get Liked Posts by User ID using OAuth 2.0 to authorize the user\n// https://developer.twitter.com/en/docs/twitter-api/tweets/likes/api-reference/get-users-id-liked_tweets\n\nconst { \n  Client, \n  OAuth2,\n  PostPaginator,\n  generateCodeVerifier,\n  generateCodeChallenge\n} = require('@xdevplatform/xdk');\n\nconst readline = require(\"readline\").createInterface({\n  input: process.stdin,\n  output: process.stdout,\n});\n\n// The code below sets the client ID and client secret from your environment variables\n// To set environment variables on macOS or Linux, run the export commands below from the terminal:\n// export CLIENT_ID='YOUR-CLIENT-ID'\n// export CLIENT_SECRET='YOUR-CLIENT-SECRET'\nconst clientId = process.env.CLIENT_ID;\nconst clientSecret = process.env.CLIENT_SECRET;\n\n// You can replace the ID given with the User ID you wish to get liked posts for.\n// You can find a user ID by using the user lookup endpoint\nconst userId = \"your-user-id\";\n\nasync function input(prompt) {\n  return new Promise((resolve) => {\n    readline.question(prompt, (out) => {\n      readline.close();\n      resolve(out);\n    });\n  });\n}\n\n// Helper function to parse callback URL\nconst getQueryStringParams = (query) => {\n  return query\n    ? (/^[?#]/.test(query) ? query.slice(1) : query)\n        .split(/[\\?\\&]/)\n        .reduce((params, param) => {\n          let [key, value] = param.split(\"=\");\n          params[key] = value\n            ? decodeURIComponent(value.replace(/\\+/g, \" \"))\n            : \"\";\n          return params;\n        }, {})\n    : {};\n};\n\n(async () => {\n  try {\n    // Configure OAuth 2.0\n    const oauth2Config = {\n      clientId: clientId,\n      clientSecret: clientSecret,\n      redirectUri: 'https://example.com',\n      scope: ['tweet.read', 'users.read', 'like.read', 'offline.access']\n    };\n\n    const oauth2 = new OAuth2(oauth2Config);\n\n    // Generate PKCE parameters\n    const state = 'example-state';\n    const codeVerifier = generateCodeVerifier();\n    const codeChallenge = await generateCodeChallenge(codeVerifier);\n    \n    oauth2.setPkceParameters(codeVerifier, codeChallenge);\n    \n    // Get authorization URL\n    const authUrl = await oauth2.getAuthorizationUrl(state);\n    console.log(\"Please go here and authorize:\", authUrl);\n\n    // Input callback URL from terminal\n    const redirectCallback = await input(\"Paste the redirected callback URL here: \");\n\n    // Parse callback\n    const { state: returnedState, code } = getQueryStringParams(redirectCallback);\n    if (returnedState !== state) {\n      console.log(\"State doesn't match\");\n      process.exit(-1);\n    }\n\n    // Exchange code for tokens\n    const tokens = await oauth2.exchangeCode(code, codeVerifier);\n\n    // Create client with access token\n    const client = new Client({\n      accessToken: tokens.access_token\n    });\n\n    console.log(\"Retrieving liked posts...\");\n    \n    // Use paginator for automatic pagination\n    const likedPosts = new PostPaginator(\n        async (token) => {\n            const res = await client.users.getLikedPosts(userId, {\n                maxResults: 100,\n                paginationToken: token,\n                tweetFields: ['lang', 'author_id'],\n                userFields: ['created_at']\n            });\n            return {\n                data: res.data ?? [],\n                meta: res.meta,\n                includes: res.includes,\n                errors: res.errors\n            };\n        }\n    );\n\n    // Fetch all pages\n    await likedPosts.fetchNext();\n    while (!likedPosts.done) {\n        await likedPosts.fetchNext();\n    }\n\n    console.dir(likedPosts.posts, {\n        depth: null\n    });\n\n    console.log(`Got ${likedPosts.posts.length} liked posts for user ID ${userId}!`);\n  } catch (e) {\n    console.log(e);\n    process.exit(-1);\n  }\n  process.exit();\n})();\n\n"
  },
  {
    "path": "javascript/users/like/like_post.js",
    "content": "const { \n  Client, \n  OAuth2,\n  generateCodeVerifier,\n  generateCodeChallenge\n} = require('@xdevplatform/xdk');\n\nconst readline = require('readline').createInterface({\n  input: process.stdin,\n  output: process.stdout\n});\n\n// The code below sets the client ID and client secret from your environment variables\n// To set environment variables on macOS or Linux, run the export commands below from the terminal:\n// export CLIENT_ID='YOUR-CLIENT-ID'\n// export CLIENT_SECRET='YOUR-CLIENT-SECRET'\nconst clientId = process.env.CLIENT_ID;\nconst clientSecret = process.env.CLIENT_SECRET;\n\n// Be sure to replace your-user-id with your own user ID or one of an authenticating user\n// You can find a user ID by using the user lookup endpoint\nconst userId = \"your-user-id\";\n\n// You can replace Post ID given with the Post ID you wish to like.\n// You can find a Post ID by using the Post lookup endpoint\nconst postId = \"1354143047324299264\";\n\nasync function input(prompt) {\n  return new Promise((resolve) => {\n    readline.question(prompt, (out) => {\n      readline.close();\n      resolve(out);\n    });\n  });\n}\n\n// Helper function to parse callback URL\nconst getQueryStringParams = (query) => {\n  return query\n    ? (/^[?#]/.test(query) ? query.slice(1) : query)\n        .split(/[\\?\\&]/)\n        .reduce((params, param) => {\n          let [key, value] = param.split(\"=\");\n          params[key] = value\n            ? decodeURIComponent(value.replace(/\\+/g, \" \"))\n            : \"\";\n          return params;\n        }, {})\n    : {};\n};\n\n(async () => {\n  try {\n    // Configure OAuth 2.0\n    const oauth2Config = {\n      clientId: clientId,\n      clientSecret: clientSecret,\n      redirectUri: 'https://example.com',\n      scope: ['tweet.read', 'users.read', 'tweet.write', 'offline.access', 'like.write']\n    };\n\n    const oauth2 = new OAuth2(oauth2Config);\n\n    // Generate PKCE parameters\n    const state = 'example-state';\n    const codeVerifier = generateCodeVerifier();\n    const codeChallenge = await generateCodeChallenge(codeVerifier);\n    \n    oauth2.setPkceParameters(codeVerifier, codeChallenge);\n    \n    // Get authorization URL\n    const authUrl = await oauth2.getAuthorizationUrl(state);\n    console.log('Please go here and authorize:', authUrl);\n\n    // Input callback URL from terminal\n    const redirectCallback = await input('Paste the redirected callback URL here: ');\n\n    // Parse callback\n    const { state: returnedState, code } = getQueryStringParams(redirectCallback);\n    if (returnedState !== state) {\n      console.log(\"State doesn't match\");\n      process.exit(-1);\n    }\n\n    // Exchange code for tokens\n    const tokens = await oauth2.exchangeCode(code, codeVerifier);\n\n    // Create client with access token\n    const client = new Client({\n      accessToken: tokens.access_token\n    });\n\n    // Make the request using SDK\n    const response = await client.users.likePost(userId, {body: {tweet_id: postId}});\n    console.dir(response, {\n      depth: null\n    });\n  } catch (e) {\n    console.log(e);\n    process.exit(-1);\n  }\n  process.exit();\n})();\n\n"
  },
  {
    "path": "javascript/users/like/unlike_post.js",
    "content": "const { \n  Client, \n  OAuth2,\n  generateCodeVerifier,\n  generateCodeChallenge\n} = require('@xdevplatform/xdk');\n\nconst readline = require('readline').createInterface({\n  input: process.stdin,\n  output: process.stdout\n});\n\n// The code below sets the client ID and client secret from your environment variables\n// To set environment variables on macOS or Linux, run the export commands below from the terminal:\n// export CLIENT_ID='YOUR-CLIENT-ID'\n// export CLIENT_SECRET='YOUR-CLIENT-SECRET'\nconst clientId = process.env.CLIENT_ID;\nconst clientSecret = process.env.CLIENT_SECRET;\n\n// Be sure to replace your-user-id with your own user ID or one of an authenticating user\n// You can find a user ID by using the user lookup endpoint\nconst userId = \"your-user-id\";\n\n// You can replace Post ID given with the Post ID you wish to unlike.\n// You can find a Post ID by using the Post lookup endpoint\nconst postId = \"1354143047324299264\";\n\nasync function input(prompt) {\n  return new Promise((resolve) => {\n    readline.question(prompt, (out) => {\n      readline.close();\n      resolve(out);\n    });\n  });\n}\n\n// Helper function to parse callback URL\nconst getQueryStringParams = (query) => {\n  return query\n    ? (/^[?#]/.test(query) ? query.slice(1) : query)\n        .split(/[\\?\\&]/)\n        .reduce((params, param) => {\n          let [key, value] = param.split(\"=\");\n          params[key] = value\n            ? decodeURIComponent(value.replace(/\\+/g, \" \"))\n            : \"\";\n          return params;\n        }, {})\n    : {};\n};\n\n(async () => {\n  try {\n    // Configure OAuth 2.0\n    const oauth2Config = {\n      clientId: clientId,\n      clientSecret: clientSecret,\n      redirectUri: 'https://example.com',\n      scope: ['tweet.read', 'users.read', 'tweet.write', 'offline.access', 'like.write']\n    };\n\n    const oauth2 = new OAuth2(oauth2Config);\n\n    // Generate PKCE parameters\n    const state = 'example-state';\n    const codeVerifier = generateCodeVerifier();\n    const codeChallenge = await generateCodeChallenge(codeVerifier);\n    \n    oauth2.setPkceParameters(codeVerifier, codeChallenge);\n    \n    // Get authorization URL\n    const authUrl = await oauth2.getAuthorizationUrl(state);\n    console.log('Please go here and authorize:', authUrl);\n\n    // Input callback URL from terminal\n    const redirectCallback = await input('Paste the redirected callback URL here: ');\n\n    // Parse callback\n    const { state: returnedState, code } = getQueryStringParams(redirectCallback);\n    if (returnedState !== state) {\n      console.log(\"State doesn't match\");\n      process.exit(-1);\n    }\n\n    // Exchange code for tokens\n    const tokens = await oauth2.exchangeCode(code, codeVerifier);\n\n    // Create client with access token\n    const client = new Client({\n      accessToken: tokens.access_token\n    });\n\n    // Make the request using SDK\n    const response = await client.users.unlikePost(userId, postId);\n    console.dir(response, {\n      depth: null\n    });\n  } catch (e) {\n    console.log(e);\n    process.exit(-1);\n  }\n  process.exit();\n})();\n\n"
  },
  {
    "path": "javascript/users/lists/follow_list.js",
    "content": "// Follow a list using OAuth 2.0 to authorize the user\n// https://developer.twitter.com/en/docs/twitter-api/lists/manage-lists/quick-start\nconst { \n  Client, \n  OAuth2,\n  generateCodeVerifier,\n  generateCodeChallenge\n} = require('@xdevplatform/xdk');\n\nconst readline = require(\"readline\").createInterface({\n  input: process.stdin,\n  output: process.stdout,\n});\n\n// The code below sets the client ID and client secret from your environment variables\n// To set environment variables on macOS or Linux, run the export commands below from the terminal:\n// export CLIENT_ID='YOUR-CLIENT-ID'\n// export CLIENT_SECRET='YOUR-CLIENT-SECRET'\nconst clientId = process.env.CLIENT_ID;\nconst clientSecret = process.env.CLIENT_SECRET;\n\n// Be sure to replace your-user-id with your own user ID or one of an authenticated user\n// You can find a user ID by using the user lookup endpoint\nconst userId = \"your-user-id\";\n\n// Be sure to add replace list-id-to-follow with the list id you wish to follow.\nconst listId = \"list-id-to-follow\";\n\nasync function input(prompt) {\n  return new Promise((resolve) => {\n    readline.question(prompt, (out) => {\n      readline.close();\n      resolve(out);\n    });\n  });\n}\n\n// Helper function to parse callback URL\nconst getQueryStringParams = (query) => {\n  return query\n    ? (/^[?#]/.test(query) ? query.slice(1) : query)\n        .split(/[\\?\\&]/)\n        .reduce((params, param) => {\n          let [key, value] = param.split(\"=\");\n          params[key] = value\n            ? decodeURIComponent(value.replace(/\\+/g, \" \"))\n            : \"\";\n          return params;\n        }, {})\n    : {};\n};\n\n(async () => {\n  try {\n    // Configure OAuth 2.0\n    const oauth2Config = {\n      clientId: clientId,\n      clientSecret: clientSecret,\n      redirectUri: 'https://example.com',\n      scope: ['tweet.read', 'users.read', 'list.read', 'list.write', 'offline.access']\n    };\n\n    const oauth2 = new OAuth2(oauth2Config);\n\n    // Generate PKCE parameters\n    const state = 'example-state';\n    const codeVerifier = generateCodeVerifier();\n    const codeChallenge = await generateCodeChallenge(codeVerifier);\n    \n    oauth2.setPkceParameters(codeVerifier, codeChallenge);\n    \n    // Get authorization URL\n    const authUrl = await oauth2.getAuthorizationUrl(state);\n    console.log(\"Please go here and authorize:\", authUrl);\n\n    // Input callback URL from terminal\n    const redirectCallback = await input(\"Paste the redirected callback URL here: \");\n\n    // Parse callback\n    const { state: returnedState, code } = getQueryStringParams(redirectCallback);\n    if (returnedState !== state) {\n      console.log(\"State doesn't match\");\n      process.exit(-1);\n    }\n\n    // Exchange code for tokens\n    const tokens = await oauth2.exchangeCode(code, codeVerifier);\n\n    // Create client with access token\n    const client = new Client({\n      accessToken: tokens.access_token\n    });\n\n    // Make the request using SDK\n    const response = await client.users.followList(userId, {body: {list_id: listId}});\n    console.dir(response, {\n      depth: null,\n    });\n  } catch (e) {\n    console.log(e);\n    process.exit(-1);\n  }\n  process.exit();\n})();\n"
  },
  {
    "path": "javascript/users/lists/get_followed_lists.js",
    "content": "const { Client } = require('@xdevplatform/xdk');\n\n// The code below sets the bearer token from your environment variables\n// To set environment variables on macOS or Linux, run the export command below from the terminal:\n// export BEARER_TOKEN='YOUR-TOKEN'\n\nconst token = process.env.BEARER_TOKEN;\nconst client = new Client({ bearerToken: token });\nconst id = \"user-id\";\n\n(async () => {\n  try {\n    // These are the parameters for the API request\n    // by default, only the List ID and name are returned\n    const response = await client.users.getFollowedLists(id, {\n      listFields: ['owner_id'], // Edit optional query parameters here\n      expansions: ['owner_id'], // expansions is used to include the user object\n      userFields: ['created_at', 'verified'] // Edit optional query parameters here\n    });\n    \n    console.dir(response, {\n      depth: null,\n    });\n  } catch (e) {\n    console.log(e);\n    process.exit(-1);\n  }\n  process.exit();\n})();\n"
  },
  {
    "path": "javascript/users/lists/get_list_memberships.js",
    "content": "const { Client } = require('@xdevplatform/xdk');\n\n// The code below sets the bearer token from your environment variables\n// To set environment variables on macOS or Linux, run the export command below from the terminal:\n// export BEARER_TOKEN='YOUR-TOKEN'\n\nconst token = process.env.BEARER_TOKEN;\nconst client = new Client({ bearerToken: token });\nconst id = \"user-id\";\n\n(async () => {\n  try {\n    // These are the parameters for the API request\n    // by default, only the List ID and name are returned\n    const response = await client.users.getListMemberships(id, {\n      listFields: ['owner_id'], // Edit optional query parameters here\n      expansions: ['owner_id'], // expansions is used to include the user object\n      userFields: ['created_at', 'verified'] // Edit optional query parameters here\n    });\n    \n    console.dir(response, {\n      depth: null,\n    });\n  } catch (e) {\n    console.log(e);\n    process.exit(-1);\n  }\n  process.exit();\n})();\n"
  },
  {
    "path": "javascript/users/lists/get_owned_lists.js",
    "content": "const { Client } = require('@xdevplatform/xdk');\n\n// The code below sets the bearer token from your environment variables\n// To set environment variables on macOS or Linux, run the export command below from the terminal:\n// export BEARER_TOKEN='YOUR-TOKEN'\n\nconst token = process.env.BEARER_TOKEN;\nconst client = new Client({ bearerToken: token });\nconst id = \"user-id\";\n\n(async () => {\n  try {\n    // These are the parameters for the API request\n    // by default, only the List ID and name are returned\n    const response = await client.users.getOwnedLists(id, {\n      listFields: ['owner_id'], // Edit optional query parameters here\n      expansions: ['owner_id'], // expansions is used to include the user object\n      userFields: ['created_at', 'verified'] // Edit optional query parameters here\n    });\n    \n    console.dir(response, {\n      depth: null,\n    });\n  } catch (e) {\n    console.log(e);\n    process.exit(-1);\n  }\n  process.exit();\n})();\n"
  },
  {
    "path": "javascript/users/lists/pin_list.js",
    "content": "// Pin a list using OAuth 2.0 to authorize the user\n// https://developer.twitter.com/en/docs/twitter-api/lists/manage-lists/quick-start\nconst { \n  Client, \n  OAuth2,\n  generateCodeVerifier,\n  generateCodeChallenge\n} = require('@xdevplatform/xdk');\n\nconst readline = require(\"readline\").createInterface({\n  input: process.stdin,\n  output: process.stdout,\n});\n\n// The code below sets the client ID and client secret from your environment variables\n// To set environment variables on macOS or Linux, run the export commands below from the terminal:\n// export CLIENT_ID='YOUR-CLIENT-ID'\n// export CLIENT_SECRET='YOUR-CLIENT-SECRET'\nconst clientId = process.env.CLIENT_ID;\nconst clientSecret = process.env.CLIENT_SECRET;\n\n// Be sure to replace your-user-id with your own user ID or one of an authenticated user\n// You can find a user ID by using the user lookup endpoint\nconst userId = \"your-user-id\";\n\n// Be sure to add replace list-id-to-pin with the list id you wish to pin.\nconst listId = \"list-id-to-pin\";\n\nasync function input(prompt) {\n  return new Promise((resolve) => {\n    readline.question(prompt, (out) => {\n      readline.close();\n      resolve(out);\n    });\n  });\n}\n\n// Helper function to parse callback URL\nconst getQueryStringParams = (query) => {\n  return query\n    ? (/^[?#]/.test(query) ? query.slice(1) : query)\n        .split(/[\\?\\&]/)\n        .reduce((params, param) => {\n          let [key, value] = param.split(\"=\");\n          params[key] = value\n            ? decodeURIComponent(value.replace(/\\+/g, \" \"))\n            : \"\";\n          return params;\n        }, {})\n    : {};\n};\n\n(async () => {\n  try {\n    // Configure OAuth 2.0\n    const oauth2Config = {\n      clientId: clientId,\n      clientSecret: clientSecret,\n      redirectUri: 'https://example.com',\n      scope: ['tweet.read', 'users.read', 'list.read', 'list.write', 'offline.access']\n    };\n\n    const oauth2 = new OAuth2(oauth2Config);\n\n    // Generate PKCE parameters\n    const state = 'example-state';\n    const codeVerifier = generateCodeVerifier();\n    const codeChallenge = await generateCodeChallenge(codeVerifier);\n    \n    oauth2.setPkceParameters(codeVerifier, codeChallenge);\n    \n    // Get authorization URL\n    const authUrl = await oauth2.getAuthorizationUrl(state);\n    console.log(\"Please go here and authorize:\", authUrl);\n\n    // Input callback URL from terminal\n    const redirectCallback = await input(\"Paste the redirected callback URL here: \");\n\n    // Parse callback\n    const { state: returnedState, code } = getQueryStringParams(redirectCallback);\n    if (returnedState !== state) {\n      console.log(\"State doesn't match\");\n      process.exit(-1);\n    }\n\n    // Exchange code for tokens\n    const tokens = await oauth2.exchangeCode(code, codeVerifier);\n\n    // Create client with access token\n    const client = new Client({\n      accessToken: tokens.access_token\n    });\n\n    // Make the request using SDK\n    const response = await client.users.pinList(userId, {list_id: listId});\n    console.dir(response, {\n      depth: null,\n    });\n  } catch (e) {\n    console.log(e);\n    process.exit(-1);\n  }\n  process.exit();\n})();\n"
  },
  {
    "path": "javascript/users/lists/unfollow_list.js",
    "content": "// Unfollow a list using OAuth 2.0 to authorize the user\n// https://developer.twitter.com/en/docs/twitter-api/lists/manage-lists/quick-start\nconst { \n  Client, \n  OAuth2,\n  generateCodeVerifier,\n  generateCodeChallenge\n} = require('@xdevplatform/xdk');\n\nconst readline = require(\"readline\").createInterface({\n  input: process.stdin,\n  output: process.stdout,\n});\n\n// The code below sets the client ID and client secret from your environment variables\n// To set environment variables on macOS or Linux, run the export commands below from the terminal:\n// export CLIENT_ID='YOUR-CLIENT-ID'\n// export CLIENT_SECRET='YOUR-CLIENT-SECRET'\nconst clientId = process.env.CLIENT_ID;\nconst clientSecret = process.env.CLIENT_SECRET;\n\n// Be sure to replace your-user-id with your own user ID or one of an authenticated user\n// You can find a user ID by using the user lookup endpoint\nconst userId = \"your-user-id\";\n\n// Be sure to replace list-id-to-unfollow with the list id you wish to unfollow.\nconst listId = \"list-id-to-unfollow\";\n\nasync function input(prompt) {\n  return new Promise((resolve) => {\n    readline.question(prompt, (out) => {\n      readline.close();\n      resolve(out);\n    });\n  });\n}\n\n// Helper function to parse callback URL\nconst getQueryStringParams = (query) => {\n  return query\n    ? (/^[?#]/.test(query) ? query.slice(1) : query)\n        .split(/[\\?\\&]/)\n        .reduce((params, param) => {\n          let [key, value] = param.split(\"=\");\n          params[key] = value\n            ? decodeURIComponent(value.replace(/\\+/g, \" \"))\n            : \"\";\n          return params;\n        }, {})\n    : {};\n};\n\n(async () => {\n  try {\n    // Configure OAuth 2.0\n    const oauth2Config = {\n      clientId: clientId,\n      clientSecret: clientSecret,\n      redirectUri: 'https://example.com',\n      scope: ['tweet.read', 'users.read', 'list.read', 'list.write', 'offline.access']\n    };\n\n    const oauth2 = new OAuth2(oauth2Config);\n\n    // Generate PKCE parameters\n    const state = 'example-state';\n    const codeVerifier = generateCodeVerifier();\n    const codeChallenge = await generateCodeChallenge(codeVerifier);\n    \n    oauth2.setPkceParameters(codeVerifier, codeChallenge);\n    \n    // Get authorization URL\n    const authUrl = await oauth2.getAuthorizationUrl(state);\n    console.log(\"Please go here and authorize:\", authUrl);\n\n    // Input callback URL from terminal\n    const redirectCallback = await input(\"Paste the redirected callback URL here: \");\n\n    // Parse callback\n    const { state: returnedState, code } = getQueryStringParams(redirectCallback);\n    if (returnedState !== state) {\n      console.log(\"State doesn't match\");\n      process.exit(-1);\n    }\n\n    // Exchange code for tokens\n    const tokens = await oauth2.exchangeCode(code, codeVerifier);\n\n    // Create client with access token\n    const client = new Client({\n      accessToken: tokens.access_token\n    });\n\n    // Make the request using SDK\n    const response = await client.users.unfollowList(userId, listId);\n    console.dir(response, {\n      depth: null,\n    });\n  } catch (e) {\n    console.log(e);\n    process.exit(-1);\n  }\n  process.exit();\n})();\n"
  },
  {
    "path": "javascript/users/lists/unpin_list.js",
    "content": "// Unpin a list using OAuth 2.0 to authorize the user\n// https://developer.twitter.com/en/docs/twitter-api/lists/manage-lists/quick-start\nconst { \n  Client, \n  OAuth2,\n  generateCodeVerifier,\n  generateCodeChallenge\n} = require('@xdevplatform/xdk');\n\nconst readline = require(\"readline\").createInterface({\n  input: process.stdin,\n  output: process.stdout,\n});\n\n// The code below sets the client ID and client secret from your environment variables\n// To set environment variables on macOS or Linux, run the export commands below from the terminal:\n// export CLIENT_ID='YOUR-CLIENT-ID'\n// export CLIENT_SECRET='YOUR-CLIENT-SECRET'\nconst clientId = process.env.CLIENT_ID;\nconst clientSecret = process.env.CLIENT_SECRET;\n\n// Be sure to replace your-user-id with your own user ID or one of an authenticated user\n// You can find a user ID by using the user lookup endpoint\nconst userId = \"your-user-id\";\n\n// Be sure to replace list-id-to-unpin with the list id you wish to unpin.\nconst listId = \"list-id-to-unpin\";\n\nasync function input(prompt) {\n  return new Promise((resolve) => {\n    readline.question(prompt, (out) => {\n      readline.close();\n      resolve(out);\n    });\n  });\n}\n\n// Helper function to parse callback URL\nconst getQueryStringParams = (query) => {\n  return query\n    ? (/^[?#]/.test(query) ? query.slice(1) : query)\n        .split(/[\\?\\&]/)\n        .reduce((params, param) => {\n          let [key, value] = param.split(\"=\");\n          params[key] = value\n            ? decodeURIComponent(value.replace(/\\+/g, \" \"))\n            : \"\";\n          return params;\n        }, {})\n    : {};\n};\n\n(async () => {\n  try {\n    // Configure OAuth 2.0\n    const oauth2Config = {\n      clientId: clientId,\n      clientSecret: clientSecret,\n      redirectUri: 'https://example.com',\n      scope: ['tweet.read', 'users.read', 'list.read', 'list.write', 'offline.access']\n    };\n\n    const oauth2 = new OAuth2(oauth2Config);\n\n    // Generate PKCE parameters\n    const state = 'example-state';\n    const codeVerifier = generateCodeVerifier();\n    const codeChallenge = await generateCodeChallenge(codeVerifier);\n    \n    oauth2.setPkceParameters(codeVerifier, codeChallenge);\n    \n    // Get authorization URL\n    const authUrl = await oauth2.getAuthorizationUrl(state);\n    console.log(\"Please go here and authorize:\", authUrl);\n\n    // Input callback URL from terminal\n    const redirectCallback = await input(\"Paste the redirected callback URL here: \");\n\n    // Parse callback\n    const { state: returnedState, code } = getQueryStringParams(redirectCallback);\n    if (returnedState !== state) {\n      console.log(\"State doesn't match\");\n      process.exit(-1);\n    }\n\n    // Exchange code for tokens\n    const tokens = await oauth2.exchangeCode(code, codeVerifier);\n\n    // Create client with access token\n    const client = new Client({\n      accessToken: tokens.access_token\n    });\n\n    // Make the request using SDK\n    const response = await client.users.unpinList(userId, listId);\n    console.dir(response, {\n      depth: null,\n    });\n  } catch (e) {\n    console.log(e);\n    process.exit(-1);\n  }\n  process.exit();\n})();\n"
  },
  {
    "path": "javascript/users/mute/get_muting.js",
    "content": "// Retrieve accounts muted by authenticated user\n// https://developer.twitter.com/en/docs/twitter-api/users/mutes/quick-start\nconst { \n  Client, \n  OAuth2,\n  generateCodeVerifier,\n  generateCodeChallenge\n} = require('@xdevplatform/xdk');\n\nconst readline = require(\"readline\").createInterface({\n  input: process.stdin,\n  output: process.stdout,\n});\n\n// The code below sets the client ID and client secret from your environment variables\n// To set environment variables on macOS or Linux, run the export commands below from the terminal:\n// export CLIENT_ID='YOUR-CLIENT-ID'\n// export CLIENT_SECRET='YOUR-CLIENT-SECRET'\nconst clientId = process.env.CLIENT_ID;\nconst clientSecret = process.env.CLIENT_SECRET;\n\n// Be sure to replace your-user-id with your own user ID or one of an authenticated user\n// You can find a user ID by using the user lookup endpoint\nconst userId = \"your-user-id\";\n\nasync function input(prompt) {\n  return new Promise((resolve) => {\n    readline.question(prompt, (out) => {\n      readline.close();\n      resolve(out);\n    });\n  });\n}\n\n// Helper function to parse callback URL\nconst getQueryStringParams = (query) => {\n  return query\n    ? (/^[?#]/.test(query) ? query.slice(1) : query)\n        .split(/[\\?\\&]/)\n        .reduce((params, param) => {\n          let [key, value] = param.split(\"=\");\n          params[key] = value\n            ? decodeURIComponent(value.replace(/\\+/g, \" \"))\n            : \"\";\n          return params;\n        }, {})\n    : {};\n};\n\n(async () => {\n  try {\n    // Configure OAuth 2.0\n    const oauth2Config = {\n      clientId: clientId,\n      clientSecret: clientSecret,\n      redirectUri: 'https://example.com',\n      scope: ['tweet.read', 'users.read', 'tweet.write', 'offline.access', 'mute.read']\n    };\n\n    const oauth2 = new OAuth2(oauth2Config);\n\n    // Generate PKCE parameters\n    const state = 'example-state';\n    const codeVerifier = generateCodeVerifier();\n    const codeChallenge = await generateCodeChallenge(codeVerifier);\n    \n    oauth2.setPkceParameters(codeVerifier, codeChallenge);\n    \n    // Get authorization URL\n    const authUrl = await oauth2.getAuthorizationUrl(state);\n    console.log(\"Please go here and authorize:\", authUrl);\n\n    // Input callback URL from terminal\n    const redirectCallback = await input(\"Paste the redirected callback URL here: \");\n\n    // Parse callback\n    const { state: returnedState, code } = getQueryStringParams(redirectCallback);\n    if (returnedState !== state) {\n      console.log(\"State doesn't match\");\n      process.exit(-1);\n    }\n\n    // Exchange code for tokens\n    const tokens = await oauth2.exchangeCode(code, codeVerifier);\n\n    // Create client with access token\n    const client = new Client({\n      accessToken: tokens.access_token\n    });\n\n    // Make the request using SDK\n    const response = await client.users.getMuting(userId);\n    console.dir(response, {\n      depth: null,\n    });\n  } catch (e) {\n    console.log(e);\n    process.exit(-1);\n  }\n  process.exit();\n})();\n"
  },
  {
    "path": "javascript/users/mute/mute_user.js",
    "content": "// mute a user, using user authentication\n// https://developer.twitter.com/en/docs/twitter-api/users/mutes/quick-start\nconst { \n  Client, \n  OAuth2,\n  generateCodeVerifier,\n  generateCodeChallenge\n} = require('@xdevplatform/xdk');\n\nconst readline = require('readline').createInterface({\n  input: process.stdin,\n  output: process.stdout\n});\n\n// The code below sets the client ID and client secret from your environment variables\n// To set environment variables on macOS or Linux, run the export commands below from the terminal:\n// export CLIENT_ID='YOUR-CLIENT-ID'\n// export CLIENT_SECRET='YOUR-CLIENT-SECRET'\nconst clientId = process.env.CLIENT_ID;\nconst clientSecret = process.env.CLIENT_SECRET;\n\n// Be sure to replace your-user-id with your own user ID or one of an authenticated user\n// You can find a user ID by using the user lookup endpoint\nconst userId = \"your-user-id\";\n\n// Be sure to add replace id-to-mute with the user id you wish to mute.\n// You can find a user ID by using the user lookup endpoint\nconst targetUserId = \"id-to-mute\";\n\nasync function input(prompt) {\n  return new Promise((resolve) => {\n    readline.question(prompt, (out) => {\n      readline.close();\n      resolve(out);\n    });\n  });\n}\n\n// Helper function to parse callback URL\nconst getQueryStringParams = (query) => {\n  return query\n    ? (/^[?#]/.test(query) ? query.slice(1) : query)\n        .split(/[\\?\\&]/)\n        .reduce((params, param) => {\n          let [key, value] = param.split(\"=\");\n          params[key] = value\n            ? decodeURIComponent(value.replace(/\\+/g, \" \"))\n            : \"\";\n          return params;\n        }, {})\n    : {};\n};\n\n(async () => {\n  try {\n    // Configure OAuth 2.0\n    const oauth2Config = {\n      clientId: clientId,\n      clientSecret: clientSecret,\n      redirectUri: 'https://example.com',\n      scope: ['tweet.read', 'users.read', 'tweet.write', 'offline.access', 'mute.write']\n    };\n\n    const oauth2 = new OAuth2(oauth2Config);\n\n    // Generate PKCE parameters\n    const state = 'example-state';\n    const codeVerifier = generateCodeVerifier();\n    const codeChallenge = await generateCodeChallenge(codeVerifier);\n    \n    oauth2.setPkceParameters(codeVerifier, codeChallenge);\n    \n    // Get authorization URL\n    const authUrl = await oauth2.getAuthorizationUrl(state);\n    console.log('Please go here and authorize:', authUrl);\n\n    // Input callback URL from terminal\n    const redirectCallback = await input('Paste the redirected callback URL here: ');\n\n    // Parse callback\n    const { state: returnedState, code } = getQueryStringParams(redirectCallback);\n    if (returnedState !== state) {\n      console.log(\"State doesn't match\");\n      process.exit(-1);\n    }\n\n    // Exchange code for tokens\n    const tokens = await oauth2.exchangeCode(code, codeVerifier);\n\n    // Create client with access token\n    const client = new Client({\n      accessToken: tokens.access_token\n    });\n\n    // Make the request using SDK\n    const response = await client.users.muteUser(userId, { body: { target_user_id: targetUserId } });\n    console.dir(response, {\n      depth: null\n    });\n  } catch (e) {\n    console.log(e);\n    process.exit(-1);\n  }\n  process.exit();\n})();\n"
  },
  {
    "path": "javascript/users/mute/unmute_user.js",
    "content": "// Unmute a user, using user authentication\nconst { \n  Client, \n  OAuth2,\n  generateCodeVerifier,\n  generateCodeChallenge\n} = require('@xdevplatform/xdk');\n\nconst readline = require('readline').createInterface({\n  input: process.stdin,\n  output: process.stdout\n});\n\n// The code below sets the client ID and client secret from your environment variables\n// To set environment variables on macOS or Linux, run the export commands below from the terminal:\n// export CLIENT_ID='YOUR-CLIENT-ID'\n// export CLIENT_SECRET='YOUR-CLIENT-SECRET'\nconst clientId = process.env.CLIENT_ID;\nconst clientSecret = process.env.CLIENT_SECRET;\n\n// Be sure to replace your-user-id with your own user ID or one of an authenticated user\n// You can find a user ID by using the user lookup endpoint\nconst sourceUserId = \"your-user-id\";\n\n// Be sure to add replace the id-to-unmute with the user id of the you wish to unmute.\n// You can find a user ID by using the user lookup endpoint\nconst targetUserId = \"id-to-unmute\";\n\nasync function input(prompt) {\n  return new Promise((resolve) => {\n    readline.question(prompt, (out) => {\n      readline.close();\n      resolve(out);\n    });\n  });\n}\n\n// Helper function to parse callback URL\nconst getQueryStringParams = (query) => {\n  return query\n    ? (/^[?#]/.test(query) ? query.slice(1) : query)\n        .split(/[\\?\\&]/)\n        .reduce((params, param) => {\n          let [key, value] = param.split(\"=\");\n          params[key] = value\n            ? decodeURIComponent(value.replace(/\\+/g, \" \"))\n            : \"\";\n          return params;\n        }, {})\n    : {};\n};\n\n(async () => {\n  try {\n    // Configure OAuth 2.0\n    const oauth2Config = {\n      clientId: clientId,\n      clientSecret: clientSecret,\n      redirectUri: 'https://example.com',\n      scope: ['tweet.read', 'users.read', 'tweet.write', 'offline.access', 'mute.write']\n    };\n\n    const oauth2 = new OAuth2(oauth2Config);\n\n    // Generate PKCE parameters\n    const state = 'example-state';\n    const codeVerifier = generateCodeVerifier();\n    const codeChallenge = await generateCodeChallenge(codeVerifier);\n    \n    oauth2.setPkceParameters(codeVerifier, codeChallenge);\n    \n    // Get authorization URL\n    const authUrl = await oauth2.getAuthorizationUrl(state);\n    console.log('Please go here and authorize:', authUrl);\n\n    // Input callback URL from terminal\n    const redirectCallback = await input('Paste the redirected callback URL here: ');\n\n    // Parse callback\n    const { state: returnedState, code } = getQueryStringParams(redirectCallback);\n    if (returnedState !== state) {\n      console.log(\"State doesn't match\");\n      process.exit(-1);\n    }\n\n    // Exchange code for tokens\n    const tokens = await oauth2.exchangeCode(code, codeVerifier);\n\n    // Create client with access token\n    const client = new Client({\n      accessToken: tokens.access_token\n    });\n\n    // Make the request using SDK\n    const response = await client.users.unmuteUser(sourceUserId, targetUserId);\n    console.dir(response, {\n      depth: null\n    });\n  } catch (e) {\n    console.log(e);\n    process.exit(-1);\n  }\n  process.exit();\n})();\n"
  },
  {
    "path": "javascript/users/repost/repost_post.js",
    "content": "const { \n  Client, \n  OAuth2,\n  generateCodeVerifier,\n  generateCodeChallenge\n} = require('@xdevplatform/xdk');\n\nconst readline = require('readline').createInterface({\n  input: process.stdin,\n  output: process.stdout\n});\n\n// The code below sets the client ID and client secret from your environment variables\n// To set environment variables on macOS or Linux, run the export commands below from the terminal:\n// export CLIENT_ID='YOUR-CLIENT-ID'\n// export CLIENT_SECRET='YOUR-CLIENT-SECRET'\nconst clientId = process.env.CLIENT_ID;\nconst clientSecret = process.env.CLIENT_SECRET;\n\n// Be sure to replace your-user-id with your own user ID or one of an authenticated user\n// You can find a user ID by using the user lookup endpoint\nconst userId = \"your-user-id\";\n\n// You can replace the given Post ID with the Post ID you want to repost\n// You can find a Post ID by using the Post lookup endpoint\nconst postId = \"1412865600439738368\";\n\nasync function input(prompt) {\n  return new Promise((resolve) => {\n    readline.question(prompt, (out) => {\n      readline.close();\n      resolve(out);\n    });\n  });\n}\n\n// Helper function to parse callback URL\nconst getQueryStringParams = (query) => {\n  return query\n    ? (/^[?#]/.test(query) ? query.slice(1) : query)\n        .split(/[\\?\\&]/)\n        .reduce((params, param) => {\n          let [key, value] = param.split(\"=\");\n          params[key] = value\n            ? decodeURIComponent(value.replace(/\\+/g, \" \"))\n            : \"\";\n          return params;\n        }, {})\n    : {};\n};\n\n(async () => {\n  try {\n    // Configure OAuth 2.0\n    const oauth2Config = {\n      clientId: clientId,\n      clientSecret: clientSecret,\n      redirectUri: 'https://example.com',\n      scope: ['tweet.read', 'users.read', 'tweet.write', 'offline.access']\n    };\n\n    const oauth2 = new OAuth2(oauth2Config);\n\n    // Generate PKCE parameters\n    const state = 'example-state';\n    const codeVerifier = generateCodeVerifier();\n    const codeChallenge = await generateCodeChallenge(codeVerifier);\n    \n    oauth2.setPkceParameters(codeVerifier, codeChallenge);\n    \n    // Get authorization URL\n    const authUrl = await oauth2.getAuthorizationUrl(state);\n    console.log('Please go here and authorize:', authUrl);\n\n    // Input callback URL from terminal\n    const redirectCallback = await input('Paste the redirected callback URL here: ');\n\n    // Parse callback\n    const { state: returnedState, code } = getQueryStringParams(redirectCallback);\n    if (returnedState !== state) {\n      console.log(\"State doesn't match\");\n      process.exit(-1);\n    }\n\n    // Exchange code for tokens\n    const tokens = await oauth2.exchangeCode(code, codeVerifier);\n\n    // Create client with access token\n    const client = new Client({\n      accessToken: tokens.access_token\n    });\n\n    // Make the request using SDK\n    const response = await client.users.repostPost(userId, { body: { tweet_id: postId } });\n    console.dir(response, {\n      depth: null\n    });\n  } catch (e) {\n    console.log(e);\n    process.exit(-1);\n  }\n  process.exit();\n})();\n\n"
  },
  {
    "path": "javascript/users/repost/unrepost_post.js",
    "content": "const { \n  Client, \n  OAuth2,\n  generateCodeVerifier,\n  generateCodeChallenge\n} = require('@xdevplatform/xdk');\n\nconst readline = require('readline').createInterface({\n  input: process.stdin,\n  output: process.stdout\n});\n\n// The code below sets the client ID and client secret from your environment variables\n// To set environment variables on macOS or Linux, run the export commands below from the terminal:\n// export CLIENT_ID='YOUR-CLIENT-ID'\n// export CLIENT_SECRET='YOUR-CLIENT-SECRET'\nconst clientId = process.env.CLIENT_ID;\nconst clientSecret = process.env.CLIENT_SECRET;\n\n// Be sure to replace your-user-id with your own user ID or one of an authenticating user\n// You can find a user ID by using the user lookup endpoint\nconst userId = \"your-user-id\";\n\n// You can replace the given Post ID with the Post ID you want to undo repost\n// You can find a Post ID by using the Post lookup endpoint\nconst sourceTweetId = \"1412865600439738368\";\n\nasync function input(prompt) {\n  return new Promise((resolve) => {\n    readline.question(prompt, (out) => {\n      readline.close();\n      resolve(out);\n    });\n  });\n}\n\n// Helper function to parse callback URL\nconst getQueryStringParams = (query) => {\n  return query\n    ? (/^[?#]/.test(query) ? query.slice(1) : query)\n        .split(/[\\?\\&]/)\n        .reduce((params, param) => {\n          let [key, value] = param.split(\"=\");\n          params[key] = value\n            ? decodeURIComponent(value.replace(/\\+/g, \" \"))\n            : \"\";\n          return params;\n        }, {})\n    : {};\n};\n\n(async () => {\n  try {\n    // Configure OAuth 2.0\n    const oauth2Config = {\n      clientId: clientId,\n      clientSecret: clientSecret,\n      redirectUri: 'https://example.com',\n      scope: ['tweet.read', 'users.read', 'tweet.write', 'offline.access']\n    };\n\n    const oauth2 = new OAuth2(oauth2Config);\n\n    // Generate PKCE parameters\n    const state = 'example-state';\n    const codeVerifier = generateCodeVerifier();\n    const codeChallenge = await generateCodeChallenge(codeVerifier);\n    \n    oauth2.setPkceParameters(codeVerifier, codeChallenge);\n    \n    // Get authorization URL\n    const authUrl = await oauth2.getAuthorizationUrl(state);\n    console.log('Please go here and authorize:', authUrl);\n\n    // Input callback URL from terminal\n    const redirectCallback = await input('Paste the redirected callback URL here: ');\n\n    // Parse callback\n    const { state: returnedState, code } = getQueryStringParams(redirectCallback);\n    if (returnedState !== state) {\n      console.log(\"State doesn't match\");\n      process.exit(-1);\n    }\n\n    // Exchange code for tokens\n    const tokens = await oauth2.exchangeCode(code, codeVerifier);\n\n    // Create client with access token\n    const client = new Client({\n      accessToken: tokens.access_token\n    });\n\n    // Make the request using SDK\n    const response = await client.users.unrepostPost(userId, sourceTweetId);\n    console.dir(response, {\n      depth: null\n    });\n  } catch (e) {\n    console.log(e);\n    process.exit(-1);\n  }\n  process.exit();\n})();\n\n"
  },
  {
    "path": "javascript/users/timeline/get_home_timeline.js",
    "content": "// Get reverse chronological home timeline\n// https://developer.twitter.com/en/docs/twitter-api/tweets/timelines/api-reference/get-users-id-reverse-chronological-timeline\nconst { \n  Client, \n  OAuth2,\n  generateCodeVerifier,\n  generateCodeChallenge\n} = require('@xdevplatform/xdk');\n\nconst readline = require(\"readline\").createInterface({\n  input: process.stdin,\n  output: process.stdout,\n});\n\n// The code below sets the client ID and client secret from your environment variables\n// To set environment variables on macOS or Linux, run the export commands below from the terminal:\n// export CLIENT_ID='YOUR-CLIENT-ID'\n// export CLIENT_SECRET='YOUR-CLIENT-SECRET'\nconst clientId = process.env.CLIENT_ID;\nconst clientSecret = process.env.CLIENT_SECRET;\n\n// Be sure to replace your-user-id with your own user ID or one of an authenticated user\n// You can find a user ID by using the user lookup endpoint\nconst userId = \"your-user-id\";\n\nasync function input(prompt) {\n  return new Promise((resolve) => {\n    readline.question(prompt, (out) => {\n      readline.close();\n      resolve(out);\n    });\n  });\n}\n\n// Helper function to parse callback URL\nconst getQueryStringParams = (query) => {\n  return query\n    ? (/^[?#]/.test(query) ? query.slice(1) : query)\n        .split(/[\\?\\&]/)\n        .reduce((params, param) => {\n          let [key, value] = param.split(\"=\");\n          params[key] = value\n            ? decodeURIComponent(value.replace(/\\+/g, \" \"))\n            : \"\";\n          return params;\n        }, {})\n    : {};\n};\n\n(async () => {\n  try {\n    // Configure OAuth 2.0\n    const oauth2Config = {\n      clientId: clientId,\n      clientSecret: clientSecret,\n      redirectUri: 'https://example.com',\n      scope: ['tweet.read', 'users.read', 'offline.access']\n    };\n\n    const oauth2 = new OAuth2(oauth2Config);\n\n    // Generate PKCE parameters\n    const state = 'example-state';\n    const codeVerifier = generateCodeVerifier();\n    const codeChallenge = await generateCodeChallenge(codeVerifier);\n    \n    oauth2.setPkceParameters(codeVerifier, codeChallenge);\n    \n    // Get authorization URL\n    const authUrl = await oauth2.getAuthorizationUrl(state);\n    console.log(\"Please go here and authorize:\", authUrl);\n\n    // Input callback URL from terminal\n    const redirectCallback = await input(\"Paste the redirected callback URL here: \");\n\n    // Parse callback\n    const { state: returnedState, code } = getQueryStringParams(redirectCallback);\n    if (returnedState !== state) {\n      console.log(\"State doesn't match\");\n      process.exit(-1);\n    }\n\n    // Exchange code for tokens\n    const tokens = await oauth2.exchangeCode(code, codeVerifier);\n\n    // Create client with access token\n    const client = new Client({\n      accessToken: tokens.access_token\n    });\n\n    // Make the request using SDK\n    const response = await client.users.getTimeline(userId);\n    console.dir(response, {\n      depth: null,\n    });\n  } catch (e) {\n    console.log(e);\n    process.exit(-1);\n  }\n  process.exit();\n})();\n"
  },
  {
    "path": "javascript/users/timeline/get_mentions.js",
    "content": "// Get User mentions timeline by user ID\n// https://developer.twitter.com/en/docs/twitter-api/tweets/timelines/quick-start\n\nconst { Client, PostPaginator } = require('@xdevplatform/xdk');\n\nconst userId = '2244994945';\n\n// The code below sets the bearer token from your environment variables\n// To set environment variables on macOS or Linux, run the export command below from the terminal:\n// export BEARER_TOKEN='YOUR-TOKEN'\nconst bearerToken = process.env.BEARER_TOKEN;\nconst client = new Client({ bearerToken: bearerToken });\n\n// this is the ID for @TwitterDev\nconst getUserMentions = async () => {\n    console.log(\"Retrieving mentions...\");\n\n    // Use paginator for automatic pagination\n    const userMentions = new PostPaginator(\n        async (token) => {\n            const res = await client.users.getMentions(userId, {\n                maxResults: 100,\n                paginationToken: token,\n                tweetFields: ['created_at']\n            });\n            return {\n                data: res.data ?? [],\n                meta: res.meta,\n                includes: res.includes,\n                errors: res.errors\n            };\n        }\n    );\n\n    // Fetch all pages\n    await userMentions.fetchNext();\n    while (!userMentions.done) {\n        await userMentions.fetchNext();\n    }\n\n    console.dir(userMentions.posts, {\n        depth: null\n    });\n\n    console.log(`Got ${userMentions.posts.length} mentions for user ID ${userId}!`);\n}\n\ngetUserMentions().catch(err => {\n    console.error('Error:', err);\n    process.exit(-1);\n});\n"
  },
  {
    "path": "javascript/users/timeline/get_posts.js",
    "content": "/**\n * User Posts Timeline - X API v2\n * \n * Endpoint: GET https://api.x.com/2/users/:id/posts\n * Docs: https://developer.x.com/en/docs/twitter-api/tweets/timelines/api-reference/get-users-id-tweets\n * \n * Authentication: Bearer Token (App-only) or OAuth (User Context)\n * Required env vars: BEARER_TOKEN\n * \n * This is a simple example that makes a single request.\n * For automatic pagination, see user_posts_paginated.js\n */\n\nconst { Client } = require('@xdevplatform/xdk');\n\nconst token = process.env.BEARER_TOKEN;\nconst client = new Client({ bearerToken: token });\n\n// Replace with the user ID you want to get posts for\nconst userId = \"2244994945\";\n\n(async () => {\n    try {\n        const response = await client.users.getPosts(userId, {\n            tweetFields: ['created_at', 'public_metrics'],\n            maxResults: 10\n        });\n        \n        console.dir(response, { depth: null });\n    } catch (e) {\n        console.log(e);\n        process.exit(-1);\n    }\n    process.exit();\n})();\n"
  },
  {
    "path": "javascript/users/timeline/get_posts_paginated.js",
    "content": "/**\n * User Posts Timeline (Paginated) - X API v2\n * \n * Endpoint: GET https://api.x.com/2/users/:id/posts\n * Docs: https://developer.x.com/en/docs/twitter-api/tweets/timelines/api-reference/get-users-id-tweets\n * \n * Authentication: Bearer Token (App-only) or OAuth (User Context)\n * Required env vars: BEARER_TOKEN\n * \n * This example demonstrates automatic pagination using PostPaginator\n * to fetch all pages of results. For a simple single-request example,\n * see user_posts.js\n */\n\nconst { Client, PostPaginator } = require('@xdevplatform/xdk');\n\n// this is the ID for @TwitterDev\nconst userId = \"2244994945\";\n\n// The code below sets the bearer token from your environment variables\n// To set environment variables on macOS or Linux, run the export command below from the terminal:\n// export BEARER_TOKEN='YOUR-TOKEN'\nconst bearerToken = process.env.BEARER_TOKEN;\nconst client = new Client({ bearerToken: bearerToken });\n\nconst getUserTweets = async () => {\n    console.log(\"Retrieving Tweets...\");\n\n    // Use paginator for automatic pagination\n    // we request the author_id expansion so that we can print out the user name later\n    const userTweets = new PostPaginator(\n        async (token) => {\n            const res = await client.users.getPosts(userId, {\n                maxResults: 100,\n                paginationToken: token,\n                tweetFields: ['created_at'],\n                expansions: ['author_id']\n            });\n            return {\n                data: res.data ?? [],\n                meta: res.meta,\n                includes: res.includes,\n                errors: res.errors\n            };\n        }\n    );\n\n    // Fetch all pages\n    await userTweets.fetchNext();\n    while (!userTweets.done) {\n        await userTweets.fetchNext();\n    }\n\n    let userName;\n    if (userTweets.includes?.users && userTweets.includes.users.length > 0) {\n        userName = userTweets.includes.users[0].username;\n    }\n\n    console.dir(userTweets.posts, {\n        depth: null\n    });\n    console.log(`Got ${userTweets.posts.length} Tweets from ${userName || 'user'} (user ID ${userId})!`);\n}\n\ngetUserTweets().catch(err => {\n    console.error('Error:', err);\n    process.exit(-1);\n});\n\n"
  },
  {
    "path": "llms.txt",
    "content": "# X API v2 Sample Code Repository\n\n> This file provides context for LLMs (Large Language Models) to understand and navigate this codebase.\n\n## Purpose\n\nThis repository contains working code examples for the X (formerly Twitter) API v2. Examples are provided in Python, JavaScript (Node.js), Ruby, and Java.\n\n## Repository Structure\n\n```\n/\n├── python/           # Python examples\n│   ├── posts/        # Create, delete, search, lookup posts\n│   ├── users/        # User lookup, followers, blocks, mutes\n│   ├── timelines/    # User posts, mentions, home timeline\n│   ├── streams/      # Filtered and sampled streams\n│   ├── bookmarks/    # Bookmark management\n│   ├── spaces/       # Spaces lookup and search\n│   ├── lists/        # List management\n│   ├── direct_messages/  # DM lookup and sending\n│   ├── media/        # Media upload\n│   ├── compliance/   # Batch compliance jobs\n│   └── usage/        # API usage stats\n├── javascript/       # JavaScript (Node.js) examples\n├── ruby/             # Ruby examples\n├── java/             # Java examples\n└── docs/             # Endpoint documentation (language-agnostic)\n```\n\n## File Naming Conventions\n\n- Python: `snake_case.py` (e.g., `create_post.py`)\n- JavaScript: `snake_case.js` (e.g., `create_post.js`)\n- Ruby: `snake_case.rb` (e.g., `search_recent.rb`)\n- Java: `PascalCase.java` (e.g., `SearchRecent.java`)\n\n## Authentication Types\n\n1. **Bearer Token** (App-only): For read-only endpoints that don't require user context\n   - Env var: `BEARER_TOKEN`\n   \n2. **OAuth 1.0a** (User Context): For endpoints that act on behalf of a user\n   - Env vars: `CONSUMER_KEY`, `CONSUMER_SECRET`\n   \n3. **OAuth 2.0 with PKCE** (User Context): For newer endpoints like bookmarks\n   - Requires OAuth 2.0 flow to get user access token\n\n## API Base URL\n\nAll endpoints use: `https://api.x.com/2/`\n\n## Key Terminology (Rebrand)\n\n| Old Term | New Term |\n|----------|----------|\n| Tweet | Post |\n| Retweet | Repost |\n| Twitter | X |\n| TwitterDev | XDevelopers |\n\nNote: The API endpoints still use `/tweets/` in the URL path for backwards compatibility.\n\n## Common Operations by Category\n\n### Posts (formerly Tweets)\n- `POST /2/tweets` - Create a post\n- `DELETE /2/tweets/:id` - Delete a post\n- `GET /2/tweets` - Look up posts by ID\n- `GET /2/tweets/search/recent` - Search recent posts (7 days)\n- `GET /2/tweets/search/all` - Search all posts (Academic access)\n- `GET /2/tweets/counts/recent` - Count recent posts\n- `GET /2/tweets/:id/quote_tweets` - Get quote posts\n- `POST /2/users/:id/retweets` - Repost\n- `DELETE /2/users/:id/retweets/:tweet_id` - Undo repost\n\n### Users\n- `GET /2/users/by` - Look up users by username\n- `GET /2/users/me` - Get authenticated user\n- `GET /2/users/:id/followers` - Get followers\n- `GET /2/users/:id/following` - Get following\n- `POST /2/users/:id/blocking` - Block user\n- `POST /2/users/:id/muting` - Mute user\n\n### Timelines\n- `GET /2/users/:id/tweets` - User's posts\n- `GET /2/users/:id/mentions` - User's mentions\n- `GET /2/users/:id/reverse_chronological_timeline` - Home timeline\n\n### Streams (Real-time)\n- `GET /2/tweets/search/stream` - Filtered stream\n- `GET /2/tweets/sample/stream` - 1% sampled stream\n\n### Likes\n- `POST /2/users/:id/likes` - Like a post\n- `DELETE /2/users/:id/likes/:tweet_id` - Unlike a post\n- `GET /2/tweets/:id/liking_users` - Users who liked\n- `GET /2/users/:id/liked_tweets` - Posts user liked\n\n### Bookmarks\n- `GET /2/users/:id/bookmarks` - Get bookmarks\n- `POST /2/users/:id/bookmarks` - Create bookmark\n- `DELETE /2/users/:id/bookmarks/:tweet_id` - Delete bookmark\n\n### Lists\n- `GET /2/lists/:id` - Look up list\n- `POST /2/lists` - Create list\n- `DELETE /2/lists/:id` - Delete list\n\n### Spaces\n- `GET /2/spaces` - Look up Spaces by ID\n- `GET /2/spaces/search` - Search Spaces\n\n### Direct Messages\n- `GET /2/dm_events` - Get DM events\n- `POST /2/dm_conversations/with/:participant_id/messages` - Send DM\n\n## Quick Start\n\n1. Get API credentials at https://developer.x.com/portal\n2. Set environment variables:\n   ```bash\n   export BEARER_TOKEN='your_token'\n   export CONSUMER_KEY='your_key'\n   export CONSUMER_SECRET='your_secret'\n   ```\n3. Navigate to desired language folder\n4. Install dependencies (see language-specific README)\n5. Run example\n\n## Dependencies by Language\n\n### Python\n```bash\npip install requests requests-oauthlib\n```\n\n### JavaScript\n```bash\nnpm install needle got oauth-1.0a\n```\n\n### Ruby\n```bash\ngem install typhoeus oauth\n```\n\n### Java\n- Apache HttpClient 4.5+\n- Gson 2.9+\n\n## External Resources\n\n- API Documentation: https://developer.x.com/en/docs/twitter-api\n- Developer Portal: https://developer.x.com/en/portal/dashboard\n- API Reference: https://developer.x.com/en/docs/api-reference-index\n"
  },
  {
    "path": "python/README.md",
    "content": "# X API v2 - Python Examples\n\nWorking Python examples for the X API v2.\n\n## Setup\n\n```bash\npip install -r requirements.txt\n```\n\nThe `requirements.txt` file includes:\n- `xdk>=0.4.5` - X Developer Kit for Python\n\n## Environment Variables\n\n**For read-only operations (search, lookup):**\n```bash\nexport BEARER_TOKEN='your_bearer_token'\n```\n\n**For user actions (post, like, repost, bookmark, mute, etc.):**\n```bash\nexport CLIENT_ID='your_client_id'\nexport CLIENT_SECRET='your_client_secret'\n```\n\n**Note:** Most user action examples (create post, like, repost, bookmark, mute, block, etc.) require OAuth 2.0 authentication with `CLIENT_ID` and `CLIENT_SECRET`. Read-only examples (search, lookup) only require `BEARER_TOKEN`.\n\n## Examples\n\n### Posts\n- `posts/create_post.py` - Create a new post (requires `CLIENT_ID`, `CLIENT_SECRET`)\n- `posts/delete_post.py` - Delete a post (requires `CLIENT_ID`, `CLIENT_SECRET`)\n- `posts/get_liking_users.py` - Get users who liked a post\n- `posts/get_post_counts_all.py` - Get post counts (full archive)\n- `posts/get_post_counts_recent.py` - Get post counts (recent)\n- `posts/get_posts_by_ids.py` - Look up posts by ID\n- `posts/get_quoted_posts.py` - Get posts that quote a post\n- `posts/get_reposted_by.py` - Get users who reposted a post\n- `posts/search_all.py` - Full archive search\n- `posts/search_recent.py` - Recent search (last 7 days)\n\n### Users\n- `users/get_users_by_usernames.py` - Look up users by username (bearer token)\n- `users/get_users_by_usernames_user_context.py` - Look up user by username (user context) (requires `CLIENT_ID`, `CLIENT_SECRET`)\n- `users/get_users_me.py` - Get authenticated user (me) (requires `CLIENT_ID`, `CLIENT_SECRET`)\n\n#### User Actions - Block\n- `users/block/get_blocking.py` - Get users blocked by a user (requires `CLIENT_ID`, `CLIENT_SECRET`)\n\n#### User Actions - Bookmark\n- `users/bookmark/get_bookmarks.py` - Get user's bookmarks (requires `CLIENT_ID`, `CLIENT_SECRET`)\n- `users/bookmark/create_bookmark.py` - Create a bookmark (requires `CLIENT_ID`, `CLIENT_SECRET`)\n- `users/bookmark/delete_bookmark.py` - Delete a bookmark (requires `CLIENT_ID`, `CLIENT_SECRET`)\n\n#### User Actions - Follow\n- `users/follow/get_followers.py` - Get user's followers\n- `users/follow/get_following.py` - Get users a user is following\n\n#### User Actions - Like\n- `users/like/get_liked_posts.py` - Get posts liked by a user (requires `CLIENT_ID`, `CLIENT_SECRET`)\n- `users/like/like_post.py` - Like a post (requires `CLIENT_ID`, `CLIENT_SECRET`)\n- `users/like/unlike_post.py` - Unlike a post (requires `CLIENT_ID`, `CLIENT_SECRET`)\n\n#### User Actions - Lists\n- `users/lists/follow_list.py` - Follow a list (requires `CLIENT_ID`, `CLIENT_SECRET`)\n- `users/lists/get_followed_lists.py` - Get lists followed by a user\n- `users/lists/get_list_memberships.py` - Get list memberships\n- `users/lists/get_owned_lists.py` - Get lists owned by a user\n- `users/lists/get_pinned_lists.py` - Get pinned lists (requires `CLIENT_ID`, `CLIENT_SECRET`)\n- `users/lists/pin_list.py` - Pin a list (requires `CLIENT_ID`, `CLIENT_SECRET`)\n- `users/lists/unfollow_list.py` - Unfollow a list (requires `CLIENT_ID`, `CLIENT_SECRET`)\n- `users/lists/unpin_list.py` - Unpin a list (requires `CLIENT_ID`, `CLIENT_SECRET`)\n\n#### User Actions - Mute\n- `users/mute/get_muting.py` - Get users muted by a user (requires `CLIENT_ID`, `CLIENT_SECRET`)\n- `users/mute/mute_user.py` - Mute a user (requires `CLIENT_ID`, `CLIENT_SECRET`)\n- `users/mute/unmute_user.py` - Unmute a user (requires `CLIENT_ID`, `CLIENT_SECRET`)\n\n#### User Actions - Repost\n- `users/repost/repost_post.py` - Repost a post (requires `CLIENT_ID`, `CLIENT_SECRET`)\n- `users/repost/unrepost_post.py` - Undo a repost (requires `CLIENT_ID`, `CLIENT_SECRET`)\n\n#### User Actions - Timeline\n- `users/timeline/get_mentions.py` - Get user mentions timeline\n- `users/timeline/get_posts.py` - Get user's posts timeline\n- `users/timeline/get_home_timeline.py` - Get home timeline (requires `CLIENT_ID`, `CLIENT_SECRET`)\n\n### Streams\n- `streams/stream_posts_filtered.py` - Filtered stream with rules\n- `streams/stream_posts_sample.py` - Sampled stream\n\n### Lists\n- `lists/add_member.py` - Add member to a list (requires `CLIENT_ID`, `CLIENT_SECRET`)\n- `lists/create_list.py` - Create a new list (requires `CLIENT_ID`, `CLIENT_SECRET`)\n- `lists/delete_list.py` - Delete a list (requires `CLIENT_ID`, `CLIENT_SECRET`)\n- `lists/get_list_by_id.py` - Get list by ID\n- `lists/get_list_followers.py` - Get list followers\n- `lists/get_list_members.py` - Get list members\n- `lists/get_list_posts.py` - Get posts from a list\n- `lists/remove_member.py` - Remove member from a list (requires `CLIENT_ID`, `CLIENT_SECRET`)\n- `lists/update_list.py` - Update a list (requires `CLIENT_ID`, `CLIENT_SECRET`)\n\n### Spaces\n- `spaces/get_spaces_by_ids.py` - Look up Spaces by ID\n- `spaces/search_spaces.py` - Search for Spaces\n\n### Direct Messages\n- `direct_messages/get_events_by_conversation.py` - Get DM events by conversation (requires `CLIENT_ID`, `CLIENT_SECRET`)\n- `direct_messages/get_one_to_one_conversation_events.py` - Get one-to-one conversation events (requires `CLIENT_ID`, `CLIENT_SECRET`)\n- `direct_messages/get_user_conversation_events.py` - Get user conversation events (requires `CLIENT_ID`, `CLIENT_SECRET`)\n- `direct_messages/post_dm_to_conversation.py` - Post DM to conversation (requires `CLIENT_ID`, `CLIENT_SECRET`)\n- `direct_messages/post_group_conversation_dm.py` - Post group conversation DM (requires `CLIENT_ID`, `CLIENT_SECRET`)\n- `direct_messages/post_one_to_one_dm.py` - Post one-to-one DM (requires `CLIENT_ID`, `CLIENT_SECRET`)\n\n### Media\n- `media/media_upload_v2.py` - Media upload v2 (requires `CLIENT_ID`, `CLIENT_SECRET`)\n- `media/upload.py` - Media upload (requires `CLIENT_ID`, `CLIENT_SECRET`)\n\n### Compliance\n- `compliance/create_jobs.py` - Create compliance job\n- `compliance/download_results.py` - Download compliance results\n- `compliance/get_jobs_by_id.py` - Get compliance job by ID\n- `compliance/get_jobs.py` - Get compliance jobs\n- `compliance/upload_ids.py` - Upload IDs for compliance\n\n### Usage\n- `usage/get_usage.py` - Get API usage information\n\n## Running Examples\n\n```bash\n# Make sure environment variables are set\npython posts/search_recent.py\n```\n\n## More Information\n\n- [X API Documentation](https://developer.x.com/en/docs/twitter-api)\n- [X Developer Portal](https://developer.x.com/en/portal/dashboard)\n"
  },
  {
    "path": "python/activity/create_subscription.py",
    "content": "\"\"\"\nCreate Activity Subscription - X API v2\n========================================\nEndpoint: POST https://api.x.com/2/activity/subscriptions\nDocs: https://docs.x.com/x-api/activity/introduction\n\nCreates a subscription to receive real-time activity events for a specified\nevent type and filter. Once created, matching events will be delivered to the\nactivity stream (see stream_events.py) and optionally to a registered webhook.\n\nSupported public event types include:\n  - profile.update.bio\n  - profile.update.picture\n  - profile.update.banner\n  - profile.update.location\n  - profile.update.url\n  - profile.update.username\n\nAuthentication: Bearer Token (App-only)\nRequired env vars: BEARER_TOKEN\n\"\"\"\n\nimport os\nimport json\nfrom xdk import Client\n\nbearer_token = os.environ.get(\"BEARER_TOKEN\")\nclient = Client(bearer_token=bearer_token)\n\n# Replace with the user ID you want to monitor for activity events\nuser_id = \"2244994945\"\n\n# Replace with the event type you want to subscribe to.\n# See the supported event types listed in the docstring above.\nevent_type = \"profile.update.bio\"\n\n# Optional: replace with a registered webhook ID to also receive events via webhook delivery.\n# If omitted, events are only available on the activity stream.\nwebhook_id = None\n\ndef main():\n    payload = {\n        \"event_type\": event_type,\n        \"filter\": {\n            \"user_id\": user_id\n        }\n    }\n\n    # Attach a label to help identify this subscription in the stream\n    payload[\"tag\"] = f\"{event_type} for user {user_id}\"\n\n    # Optionally route events to a registered webhook in addition to the stream\n    if webhook_id:\n        payload[\"webhook_id\"] = webhook_id\n\n    response = client.activity.create_subscription(body=payload)\n\n    print(\"Response code: 201\")\n    print(json.dumps(response.data, indent=4, sort_keys=True))\n\n\nif __name__ == \"__main__\":\n    main()\n"
  },
  {
    "path": "python/activity/delete_subscription.py",
    "content": "\"\"\"\nDelete Activity Subscription - X API v2\n========================================\nEndpoint: DELETE https://api.x.com/2/activity/subscriptions/:id\nDocs: https://docs.x.com/x-api/activity/introduction\n\nDeletes an activity subscription. Once deleted, events matching that subscription\nwill no longer be delivered to the stream or associated webhook. Use\nlist_subscriptions.py to find the subscription_id you wish to remove.\n\nAuthentication: Bearer Token (App-only)\nRequired env vars: BEARER_TOKEN\n\"\"\"\n\nimport os\nimport json\nfrom xdk import Client\n\nbearer_token = os.environ.get(\"BEARER_TOKEN\")\nclient = Client(bearer_token=bearer_token)\n\n# Replace with the subscription ID you wish to delete.\n# You can find subscription IDs by running list_subscriptions.py\nsubscription_id = \"your-subscription-id\"\n\ndef main():\n    response = client.activity.delete_subscription(subscription_id)\n\n    print(\"Response code: 200\")\n    print(json.dumps(response.data, indent=4, sort_keys=True))\n\n\nif __name__ == \"__main__\":\n    main()\n"
  },
  {
    "path": "python/activity/list_subscriptions.py",
    "content": "\"\"\"\nList Activity Subscriptions - X API v2\n=======================================\nEndpoint: GET https://api.x.com/2/activity/subscriptions\nDocs: https://docs.x.com/x-api/activity/introduction\n\nReturns all active activity subscriptions for your app. Use the subscription_id\nfrom the response to update or delete individual subscriptions.\n\nAuthentication: Bearer Token (App-only)\nRequired env vars: BEARER_TOKEN\n\"\"\"\n\nimport os\nimport json\nfrom xdk import Client\n\nbearer_token = os.environ.get(\"BEARER_TOKEN\")\nclient = Client(bearer_token=bearer_token)\n\ndef main():\n    response = client.activity.get_subscriptions()\n\n    # Access data attribute safely\n    response_data = getattr(response, 'data', None)\n    if response_data:\n        print(json.dumps(response_data, indent=4, sort_keys=True))\n    else:\n        print(json.dumps(response, indent=4, sort_keys=True))\n\n\nif __name__ == \"__main__\":\n    main()\n"
  },
  {
    "path": "python/activity/stream_events.py",
    "content": "\"\"\"\nActivity Stream - X API v2\n==========================\nEndpoint: GET https://api.x.com/2/activity/stream\nDocs: https://docs.x.com/x-api/activity/introduction\n\nOpens a persistent HTTP connection and streams real-time activity events\nmatching your active subscriptions. Events are delivered as they occur on\nthe platform — no polling required.\n\nYou must create at least one subscription (see create_subscription.py) before\nevents will be delivered to this stream.\n\nAuthentication: Bearer Token (App-only)\nRequired env vars: BEARER_TOKEN\n\"\"\"\n\nimport os\nimport json\nfrom xdk import Client\n\nbearer_token = os.environ.get(\"BEARER_TOKEN\")\nclient = Client(bearer_token=bearer_token)\n\ndef main():\n    print(\"Connecting to activity stream... (press Ctrl+C to stop)\")\n\n    # The stream() method returns a generator that yields events as they arrive.\n    # The SDK manages reconnection with exponential backoff automatically.\n    for event in client.activity.stream():\n        # Access data attribute (model uses extra='allow' so data should be available)\n        # Use getattr with fallback in case data field is missing from response\n        event_data = getattr(event, 'data', None)\n        if event_data:\n            print(json.dumps(event_data, indent=4, sort_keys=True))\n\n\nif __name__ == \"__main__\":\n    main()\n"
  },
  {
    "path": "python/activity/update_subscription.py",
    "content": "\"\"\"\nUpdate Activity Subscription - X API v2\n========================================\nEndpoint: PUT https://api.x.com/2/activity/subscriptions/:id\nDocs: https://docs.x.com/x-api/activity/introduction\n\nUpdates an existing activity subscription. You can change the filter (e.g. target\na different user ID), the tag, or the associated webhook. Use list_subscriptions.py\nto find the subscription_id you wish to update.\n\nAuthentication: Bearer Token (App-only)\nRequired env vars: BEARER_TOKEN\n\"\"\"\n\nimport os\nimport json\nfrom xdk import Client\n\nbearer_token = os.environ.get(\"BEARER_TOKEN\")\nclient = Client(bearer_token=bearer_token)\n\n# Replace with the subscription ID you wish to update.\n# You can find subscription IDs by running list_subscriptions.py\nsubscription_id = \"your-subscription-id\"\n\n# Replace with the updated user ID you want to monitor\nupdated_user_id = \"2244994945\"\n\ndef main():\n    payload = {\n        \"filter\": {\n            \"user_id\": updated_user_id\n        }\n    }\n\n    response = client.activity.update_subscription(subscription_id, body=payload)\n\n    print(\"Response code: 200\")\n    print(json.dumps(response.data, indent=4, sort_keys=True))\n\n\nif __name__ == \"__main__\":\n    main()\n"
  },
  {
    "path": "python/compliance/create_jobs.py",
    "content": "\"\"\"\nCreate Compliance Job - X API v2\n================================\nEndpoint: POST https://api.x.com/2/compliance/jobs\nDocs: https://developer.x.com/en/docs/twitter-api/compliance/batch-compliance/api-reference/post-compliance-jobs\n\nAuthentication: Bearer Token (App-only)\nRequired env vars: BEARER_TOKEN\n\"\"\"\n\nimport os\nimport json\nfrom xdk import Client\n\nbearer_token = os.environ.get(\"BEARER_TOKEN\")\nclient = Client(bearer_token=bearer_token)\n\n# For User Compliance Job, replace the type value with users instead of tweets\n# Also replace the name value with your desired job name\npayload = {\"type\": \"tweets\", \"name\": \"my_batch_compliance_job\"}\n\ndef main():\n    response = client.compliance.create_job(body=payload)\n    \n    print(json.dumps(response.data, indent=4, sort_keys=True))\n\nif __name__ == \"__main__\":\n    main()\n"
  },
  {
    "path": "python/compliance/download_results.py",
    "content": "\"\"\"\nDownload Compliance Results - X API v2\n======================================\nEndpoint: GET <download_url> (provided in compliance job response)\nDocs: https://developer.x.com/en/docs/twitter-api/compliance/batch-compliance/api-reference/get-compliance-jobs-id\n\nNote: This endpoint uses a pre-signed URL from the compliance job response.\nThe download_url is provided when you check the status of a compliance job.\n\"\"\"\n\nimport requests\n\n# Replace with your job download_url (from the compliance job response)\ndownload_url = ''\n\ndef main():\n    response = requests.get(download_url)\n    \n    print(f\"Response code: {response.status_code}\")\n    if response.status_code != 200:\n        raise Exception(response.status_code, response.text)\n    \n    entries = response.text.splitlines()\n    for entry in entries:\n        print(entry)\n\nif __name__ == \"__main__\":\n    main()\n"
  },
  {
    "path": "python/compliance/get_jobs.py",
    "content": "\"\"\"\nGet Compliance Jobs - X API v2\n==============================\nEndpoint: GET https://api.x.com/2/compliance/jobs\nDocs: https://developer.x.com/en/docs/twitter-api/compliance/batch-compliance/api-reference/get-compliance-jobs\n\nAuthentication: Bearer Token (App-only)\nRequired env vars: BEARER_TOKEN\n\"\"\"\n\nimport os\nimport json\nfrom xdk import Client\n\nbearer_token = os.environ.get(\"BEARER_TOKEN\")\nclient = Client(bearer_token=bearer_token)\n\n# Type can be \"tweets\" or \"users\"\njob_type = \"tweets\"\n\ndef main():\n    response = client.compliance.get_jobs(type=job_type)\n    \n    print(json.dumps(response.data, indent=4, sort_keys=True))\n\nif __name__ == \"__main__\":\n    main()\n"
  },
  {
    "path": "python/compliance/get_jobs_by_id.py",
    "content": "\"\"\"\nGet Compliance Job by ID - X API v2\n===================================\nEndpoint: GET https://api.x.com/2/compliance/jobs/:id\nDocs: https://developer.x.com/en/docs/twitter-api/compliance/batch-compliance/api-reference/get-compliance-jobs-id\n\nAuthentication: Bearer Token (App-only)\nRequired env vars: BEARER_TOKEN\n\"\"\"\n\nimport os\nimport json\nfrom xdk import Client\n\nbearer_token = os.environ.get(\"BEARER_TOKEN\")\nclient = Client(bearer_token=bearer_token)\n\n# Replace with your job ID below\njob_id = ''\n\ndef main():\n    response = client.compliance.get_job(job_id)\n    \n    print(json.dumps(response.data, indent=4, sort_keys=True))\n\nif __name__ == \"__main__\":\n    main()\n"
  },
  {
    "path": "python/compliance/upload_ids.py",
    "content": "\"\"\"\nUpload IDs for Compliance Job - X API v2\n========================================\nEndpoint: PUT <upload_url> (provided in compliance job response)\nDocs: https://developer.x.com/en/docs/twitter-api/compliance/batch-compliance/api-reference/post-compliance-jobs\n\nNote: This endpoint uses a pre-signed URL from the compliance job response.\nThe upload_url is provided when you create a compliance job.\n\"\"\"\n\nimport os\nimport requests\n\n# Replace with your job upload_url (from the compliance job response)\nupload_url = ''\n\n# Replace with your file path that contains the list of Tweet IDs or User IDs, one ID per line\nfile_path = ''\n\ndef main():\n    headers = {'Content-Type': \"text/plain\"}\n    \n    with open(file_path, 'rb') as f:\n        response = requests.put(upload_url, data=f, headers=headers)\n    \n    print(f\"Response code: {response.status_code}\")\n    if response.status_code != 200:\n        raise Exception(response.status_code, response.text)\n    \n    print(response.text)\n\nif __name__ == \"__main__\":\n    main()\n"
  },
  {
    "path": "python/direct_messages/get_events_by_conversation.py",
    "content": "\"\"\"\nGet Events by Conversation ID - X API v2\n=========================================\nEndpoint: GET https://api.x.com/2/dm_conversations/:dm_conversation_id/dm_events\nDocs: https://developer.x.com/en/docs/twitter-api/direct-messages/lookup/api-reference/get-dm-conversations-dm_conversation_id-dm_events\n\nAuthentication: OAuth 2.0 (User Context)\nRequired env vars: CLIENT_ID, CLIENT_SECRET\n\nThis example retrieves Direct Message events by conversation ID.\nThis supports both one-to-one and group conversations.\n\"\"\"\n\nimport os\nimport json\nfrom xdk import Client\nfrom xdk.oauth2_auth import OAuth2PKCEAuth\n\n# The code below sets the client ID and client secret from your environment variables\n# To set environment variables on macOS or Linux, run the export commands below from the terminal:\n# export CLIENT_ID='YOUR-CLIENT-ID'\n# export CLIENT_SECRET='YOUR-CLIENT-SECRET'\nclient_id = os.environ.get(\"CLIENT_ID\")\nclient_secret = os.environ.get(\"CLIENT_SECRET\")\n\n# Replace the following URL with your callback URL, which can be obtained from your App's auth settings.\nredirect_uri = \"https://example.com\"\n\n# Set the scopes\nscopes = [\"dm.read\", \"tweet.read\", \"users.read\", \"offline.access\"]\n\n# What is the ID of the conversation to retrieve?\ndm_conversation_id = \"1512210732774948865\"\n\ndef main():\n    # Step 1: Create PKCE instance\n    auth = OAuth2PKCEAuth(\n        client_id=client_id,\n        client_secret=client_secret,\n        redirect_uri=redirect_uri,\n        scope=scopes\n    )\n    \n    # Step 2: Get authorization URL\n    auth_url = auth.get_authorization_url()\n    print(\"Visit the following URL to authorize your App on behalf of your X handle in a browser:\")\n    print(auth_url)\n    \n    # Step 3: Handle callback\n    callback_url = input(\"Paste the full callback URL here: \")\n    \n    # Step 4: Exchange code for tokens\n    tokens = auth.fetch_token(authorization_response=callback_url)\n    access_token = tokens[\"access_token\"]\n    \n    # Step 5: Create client\n    client = Client(access_token=access_token)\n    \n    # Step 6: Get events by conversation ID with automatic pagination\n    all_events = []\n    for page in client.direct_messages.get_events_by_conversation_id(\n        dm_conversation_id,\n        max_results=100\n    ):\n        # Access data attribute (model uses extra='allow' so data should be available)\n        # Use getattr with fallback in case data field is missing from response\n        page_data = getattr(page, 'data', []) or []\n        all_events.extend(page_data)\n        print(f\"Fetched {len(page_data)} events (total: {len(all_events)})\")\n    \n    print(f\"\\nTotal Conversation Events: {len(all_events)}\")\n    print(json.dumps({\"data\": all_events[:5]}, indent=4, sort_keys=True))  # Print first 5 as example\n\nif __name__ == \"__main__\":\n    main()\n"
  },
  {
    "path": "python/direct_messages/get_one_to_one_conversation_events.py",
    "content": "\"\"\"\nGet One-to-One Conversation Events - X API v2\n=============================================\nEndpoint: GET https://api.x.com/2/dm_conversations/with/:participant_id/dm_events\nDocs: https://developer.x.com/en/docs/twitter-api/direct-messages/lookup/api-reference/get-dm-conversations-with-participant_id-dm_events\n\nAuthentication: OAuth 2.0 (User Context)\nRequired env vars: CLIENT_ID, CLIENT_SECRET\n\nThis example retrieves Direct Message conversation events associated with a one-to-one message.\nCurrently, the v2 DM endpoints support three conversation event types: MessageCreate, ParticipantsJoin, and ParticipantsLeave.\n\"\"\"\n\nimport os\nimport json\nfrom xdk import Client\nfrom xdk.oauth2_auth import OAuth2PKCEAuth\n\n# The code below sets the client ID and client secret from your environment variables\n# To set environment variables on macOS or Linux, run the export commands below from the terminal:\n# export CLIENT_ID='YOUR-CLIENT-ID'\n# export CLIENT_SECRET='YOUR-CLIENT-SECRET'\nclient_id = os.environ.get(\"CLIENT_ID\")\nclient_secret = os.environ.get(\"CLIENT_SECRET\")\n\n# Replace the following URL with your callback URL, which can be obtained from your App's auth settings.\nredirect_uri = \"https://example.com\"\n\n# Set the scopes\nscopes = [\"dm.read\", \"tweet.read\", \"users.read\", \"offline.access\"]\n\n# Who is this one-to-one conversation with?\nparticipant_id = \"1716450569358098432\"\n\ndef main():\n    # Step 1: Create PKCE instance\n    auth = OAuth2PKCEAuth(\n        client_id=client_id,\n        client_secret=client_secret,\n        redirect_uri=redirect_uri,\n        scope=scopes\n    )\n    \n    # Step 2: Get authorization URL\n    auth_url = auth.get_authorization_url()\n    print(\"Visit the following URL to authorize your App on behalf of your X handle in a browser:\")\n    print(auth_url)\n    \n    # Step 3: Handle callback\n    callback_url = input(\"Paste the full callback URL here: \")\n    \n    # Step 4: Exchange code for tokens\n    tokens = auth.fetch_token(authorization_response=callback_url)\n    access_token = tokens[\"access_token\"]\n    \n    # Step 5: Create client\n    client = Client(access_token=access_token)\n    \n    # Step 6: Get one-to-one conversation events with automatic pagination\n    all_events = []\n    for page in client.direct_messages.get_events_by_participant_id(\n        participant_id,\n        max_results=100\n    ):\n        # Access data attribute (model uses extra='allow' so data should be available)\n        # Use getattr with fallback in case data field is missing from response\n        page_data = getattr(page, 'data', []) or []\n        all_events.extend(page_data)\n        print(f\"Fetched {len(page_data)} events (total: {len(all_events)})\")\n    \n    print(f\"\\nTotal Conversation Events: {len(all_events)}\")\n    print(json.dumps({\"data\": all_events[:5]}, indent=4, sort_keys=True))  # Print first 5 as example\n\nif __name__ == \"__main__\":\n    main()\n"
  },
  {
    "path": "python/direct_messages/get_user_conversation_events.py",
    "content": "\"\"\"\nGet User Conversation Events - X API v2\n=======================================\nEndpoint: GET https://api.x.com/2/dm_events\nDocs: https://developer.x.com/en/docs/twitter-api/direct-messages/lookup/api-reference/get-dm-events\n\nAuthentication: OAuth 2.0 (User Context)\nRequired env vars: CLIENT_ID, CLIENT_SECRET\n\nThis example retrieves Direct Message events of the authenticating user.\nThis supports both one-to-one and group conversations.\n\"\"\"\n\nimport os\nimport json\nfrom xdk import Client\nfrom xdk.oauth2_auth import OAuth2PKCEAuth\n\n# The code below sets the client ID and client secret from your environment variables\n# To set environment variables on macOS or Linux, run the export commands below from the terminal:\n# export CLIENT_ID='YOUR-CLIENT-ID'\n# export CLIENT_SECRET='YOUR-CLIENT-SECRET'\nclient_id = os.environ.get(\"CLIENT_ID\")\nclient_secret = os.environ.get(\"CLIENT_SECRET\")\n\n# Replace the following URL with your callback URL, which can be obtained from your App's auth settings.\nredirect_uri = \"https://example.com\"\n\n# Set the scopes\nscopes = [\"dm.read\", \"tweet.read\", \"users.read\", \"offline.access\"]\n\ndef main():\n    # Step 1: Create PKCE instance\n    auth = OAuth2PKCEAuth(\n        client_id=client_id,\n        client_secret=client_secret,\n        redirect_uri=redirect_uri,\n        scope=scopes\n    )\n    \n    # Step 2: Get authorization URL\n    auth_url = auth.get_authorization_url()\n    print(\"Visit the following URL to authorize your App on behalf of your X handle in a browser:\")\n    print(auth_url)\n    \n    # Step 3: Handle callback\n    callback_url = input(\"Paste the full callback URL here: \")\n    \n    # Step 4: Exchange code for tokens\n    tokens = auth.fetch_token(authorization_response=callback_url)\n    access_token = tokens[\"access_token\"]\n    \n    # Step 5: Create client\n    client = Client(access_token=access_token)\n    \n    # Step 6: Get user conversation events with automatic pagination\n    # DM event fields are adjustable. Options include:\n    # id, text, event_type, created_at, dm_conversation_id,\n    # sender_id, participant_ids, referenced_tweets, attachments\n    all_events = []\n    for page in client.direct_messages.get_events(\n        max_results=100,\n        dm_event_fields=[\"id\", \"text\", \"event_type\", \"created_at\", \"sender_id\"]\n    ):\n        # Access data attribute (model uses extra='allow' so data should be available)\n        # Use getattr with fallback in case data field is missing from response\n        page_data = getattr(page, 'data', []) or []\n        all_events.extend(page_data)\n        print(f\"Fetched {len(page_data)} events (total: {len(all_events)})\")\n    \n    print(f\"\\nTotal DM Events: {len(all_events)}\")\n    print(json.dumps({\"data\": all_events[:5]}, indent=4, sort_keys=True))  # Print first 5 as example\n\nif __name__ == \"__main__\":\n    main()\n"
  },
  {
    "path": "python/direct_messages/post_dm_to_conversation.py",
    "content": "\"\"\"\nPost DM to Conversation - X API v2\n===================================\nEndpoint: POST https://api.x.com/2/dm_conversations/:dm_conversation_id/messages\nDocs: https://developer.x.com/en/docs/twitter-api/direct-messages/manage/api-reference/post-dm-conversations-dm_conversation_id-messages\n\nAuthentication: OAuth 2.0 (User Context)\nRequired env vars: CLIENT_ID, CLIENT_SECRET\n\"\"\"\n\nimport os\nimport json\nfrom xdk import Client\nfrom xdk.oauth2_auth import OAuth2PKCEAuth\n\n# The code below sets the client ID and client secret from your environment variables\n# To set environment variables on macOS or Linux, run the export commands below from the terminal:\n# export CLIENT_ID='YOUR-CLIENT-ID'\n# export CLIENT_SECRET='YOUR-CLIENT-SECRET'\nclient_id = os.environ.get(\"CLIENT_ID\")\nclient_secret = os.environ.get(\"CLIENT_SECRET\")\n\n# Replace the following URL with your callback URL, which can be obtained from your App's auth settings.\nredirect_uri = \"https://example.com\"\n\n# Set the scopes\nscopes = [\"dm.read\", \"dm.write\", \"tweet.read\", \"users.read\", \"offline.access\"]\n\n# Provide the ID of the conversation this message should be added to.\ndm_conversation_id = \"1856843062712176900\"\n\n# Set the text of the message to be sent.\ntext_message = \"Hi, I am adding a message to an existing conversation by referencing its ID.\"\n\ndef main():\n    # Step 1: Create PKCE instance\n    auth = OAuth2PKCEAuth(\n        client_id=client_id,\n        client_secret=client_secret,\n        redirect_uri=redirect_uri,\n        scope=scopes\n    )\n    \n    # Step 2: Get authorization URL\n    auth_url = auth.get_authorization_url()\n    print(\"Visit the following URL to authorize your App on behalf of your X handle in a browser:\")\n    print(auth_url)\n    \n    # Step 3: Handle callback\n    callback_url = input(\"Paste the full callback URL here: \")\n    \n    # Step 4: Exchange code for tokens\n    tokens = auth.fetch_token(authorization_response=callback_url)\n    access_token = tokens[\"access_token\"]\n    \n    # Step 5: Create client\n    client = Client(access_token=access_token)\n    \n    # Step 6: Add DM to conversation\n    payload = {\"text\": text_message}\n    response = client.direct_messages.create_by_conversation_id(dm_conversation_id, body=payload)\n    \n    print(\"Response code: 201\")\n    print(json.dumps(response.data, indent=4, sort_keys=True))\n\nif __name__ == \"__main__\":\n    main()\n"
  },
  {
    "path": "python/direct_messages/post_group_conversation_dm.py",
    "content": "\"\"\"\nPost Group Conversation Direct Message - X API v2\n=================================================\nEndpoint: POST https://api.x.com/2/dm_conversations\nDocs: https://developer.x.com/en/docs/twitter-api/direct-messages/manage/api-reference/post-dm-conversations\n\nAuthentication: OAuth 2.0 (User Context)\nRequired env vars: CLIENT_ID, CLIENT_SECRET\n\"\"\"\n\nimport os\nimport json\nfrom xdk import Client\nfrom xdk.oauth2_auth import OAuth2PKCEAuth\n\n# The code below sets the client ID and client secret from your environment variables\n# To set environment variables on macOS or Linux, run the export commands below from the terminal:\n# export CLIENT_ID='YOUR-CLIENT-ID'\n# export CLIENT_SECRET='YOUR-CLIENT-SECRET'\nclient_id = os.environ.get(\"CLIENT_ID\")\nclient_secret = os.environ.get(\"CLIENT_SECRET\")\n\n# Replace the following URL with your callback URL, which can be obtained from your App's auth settings.\nredirect_uri = \"https://example.com\"\n\n# Set the scopes\nscopes = [\"dm.read\", \"dm.write\", \"tweet.read\", \"users.read\", \"offline.access\"]\n\n# Who is in this group conversation? Reference their User IDs.\nparticipant_ids = [\"2244994945\", \"1716450569358098432\"]\n\n# Set the text of the message to be sent.\ntext_message = \"Hi, I am creating a new *group* conversation, and starting it with the this message.\"\n\ndef main():\n    # Step 1: Create PKCE instance\n    auth = OAuth2PKCEAuth(\n        client_id=client_id,\n        client_secret=client_secret,\n        redirect_uri=redirect_uri,\n        scope=scopes\n    )\n    \n    # Step 2: Get authorization URL\n    auth_url = auth.get_authorization_url()\n    print(\"Visit the following URL to authorize your App on behalf of your X handle in a browser:\")\n    print(auth_url)\n    \n    # Step 3: Handle callback\n    callback_url = input(\"Paste the full callback URL here: \")\n    \n    # Step 4: Exchange code for tokens\n    tokens = auth.fetch_token(authorization_response=callback_url)\n    access_token = tokens[\"access_token\"]\n    \n    # Step 5: Create client\n    client = Client(access_token=access_token)\n    \n    # Step 6: Create group conversation with DM\n    payload = {\n        \"message\": {\"text\": text_message},\n        \"participant_ids\": participant_ids,\n        \"conversation_type\": \"Group\"\n    }\n    response = client.direct_messages.create_conversation(body=payload)\n    \n    print(\"Response code: 201\")\n    print(json.dumps(response.data, indent=4, sort_keys=True))\n\nif __name__ == \"__main__\":\n    main()\n"
  },
  {
    "path": "python/direct_messages/post_one_to_one_dm.py",
    "content": "\"\"\"\nPost One-to-One Direct Message - X API v2\n==========================================\nEndpoint: POST https://api.x.com/2/dm_conversations/with/:participant_id/messages\nDocs: https://developer.x.com/en/docs/twitter-api/direct-messages/manage/api-reference/post-dm-conversations-with-participant_id-messages\n\nAuthentication: OAuth 2.0 (User Context)\nRequired env vars: CLIENT_ID, CLIENT_SECRET\n\"\"\"\n\nimport os\nimport json\nfrom xdk import Client\nfrom xdk.oauth2_auth import OAuth2PKCEAuth\n\n# The code below sets the client ID and client secret from your environment variables\n# To set environment variables on macOS or Linux, run the export commands below from the terminal:\n# export CLIENT_ID='YOUR-CLIENT-ID'\n# export CLIENT_SECRET='YOUR-CLIENT-SECRET'\nclient_id = os.environ.get(\"CLIENT_ID\")\nclient_secret = os.environ.get(\"CLIENT_SECRET\")\n\n# Replace the following URL with your callback URL, which can be obtained from your App's auth settings.\nredirect_uri = \"https://example.com\"\n\n# Set the scopes\nscopes = [\"dm.read\", \"dm.write\", \"tweet.read\", \"users.read\", \"offline.access\"]\n\n# Who is this DM being sent to? Reference their User ID.\nparticipant_id = \"1716450569358098432\"\n\n# Set the text of the message to be sent.\ntext_message = \"Hi, I am DMing you using the v2 DM one-to-one endpoint.\"\n\ndef main():\n    # Step 1: Create PKCE instance\n    auth = OAuth2PKCEAuth(\n        client_id=client_id,\n        client_secret=client_secret,\n        redirect_uri=redirect_uri,\n        scope=scopes\n    )\n    \n    # Step 2: Get authorization URL\n    auth_url = auth.get_authorization_url()\n    print(\"Visit the following URL to authorize your App on behalf of your X handle in a browser:\")\n    print(auth_url)\n    \n    # Step 3: Handle callback\n    callback_url = input(\"Paste the full callback URL here: \")\n    \n    # Step 4: Exchange code for tokens\n    tokens = auth.fetch_token(authorization_response=callback_url)\n    access_token = tokens[\"access_token\"]\n    \n    # Step 5: Create client\n    client = Client(access_token=access_token)\n    \n    # Step 6: Send one-to-one DM\n    payload = {\"text\": text_message}\n    response = client.direct_messages.create_by_participant_id(participant_id, body=payload)\n    \n    print(\"Response code: 201\")\n    print(json.dumps(response.data, indent=4, sort_keys=True))\n\nif __name__ == \"__main__\":\n    main()\n"
  },
  {
    "path": "python/lists/add_member.py",
    "content": "\"\"\"\nAdd List Member - X API v2\n==========================\nEndpoint: POST https://api.x.com/2/lists/:id/members\nDocs: https://developer.x.com/en/docs/twitter-api/lists/list-members/api-reference/post-lists-id-members\n\nAuthentication: OAuth 2.0 (User Context)\nRequired env vars: CLIENT_ID, CLIENT_SECRET\n\"\"\"\n\nimport os\nimport json\nfrom xdk import Client\nfrom xdk.oauth2_auth import OAuth2PKCEAuth\n\n# The code below sets the client ID and client secret from your environment variables\n# To set environment variables on macOS or Linux, run the export commands below from the terminal:\n# export CLIENT_ID='YOUR-CLIENT-ID'\n# export CLIENT_SECRET='YOUR-CLIENT-SECRET'\nclient_id = os.environ.get(\"CLIENT_ID\")\nclient_secret = os.environ.get(\"CLIENT_SECRET\")\n\n# Replace the following URL with your callback URL, which can be obtained from your App's auth settings.\nredirect_uri = \"https://example.com\"\n\n# Set the scopes\nscopes = [\"tweet.read\", \"users.read\", \"list.read\", \"list.write\", \"offline.access\"]\n\n# Be sure to replace your-list-id with your own list ID or one of an authenticated user\nlist_id = \"your-list-id\"\n\n# Be sure to replace user-id-to-add with the user id you wish to add.\nuser_id = \"user-id-to-add\"\n\ndef main():\n    # Step 1: Create PKCE instance\n    auth = OAuth2PKCEAuth(\n        client_id=client_id,\n        client_secret=client_secret,\n        redirect_uri=redirect_uri,\n        scope=scopes\n    )\n    \n    # Step 2: Get authorization URL\n    auth_url = auth.get_authorization_url()\n    print(\"Visit the following URL to authorize your App on behalf of your X handle in a browser:\")\n    print(auth_url)\n    \n    # Step 3: Handle callback\n    callback_url = input(\"Paste the full callback URL here: \")\n    \n    # Step 4: Exchange code for tokens\n    tokens = auth.fetch_token(authorization_response=callback_url)\n    access_token = tokens[\"access_token\"]\n    \n    # Step 5: Create client\n    client = Client(access_token=access_token)\n    \n    # Step 6: Add member to list\n    payload = {\"user_id\": user_id}\n    response = client.lists.add_member(list_id, body=payload)\n    \n    print(\"Response code: 200\")\n    print(json.dumps(response.data, indent=4, sort_keys=True))\n\nif __name__ == \"__main__\":\n    main()\n"
  },
  {
    "path": "python/lists/create_list.py",
    "content": "\"\"\"\nCreate List - X API v2\n======================\nEndpoint: POST https://api.x.com/2/lists\nDocs: https://developer.x.com/en/docs/twitter-api/lists/manage-lists/api-reference/post-lists\n\nAuthentication: OAuth 2.0 (User Context)\nRequired env vars: CLIENT_ID, CLIENT_SECRET\n\"\"\"\n\nimport os\nimport json\nfrom xdk import Client\nfrom xdk.oauth2_auth import OAuth2PKCEAuth\n\n# The code below sets the client ID and client secret from your environment variables\n# To set environment variables on macOS or Linux, run the export commands below from the terminal:\n# export CLIENT_ID='YOUR-CLIENT-ID'\n# export CLIENT_SECRET='YOUR-CLIENT-SECRET'\nclient_id = os.environ.get(\"CLIENT_ID\")\nclient_secret = os.environ.get(\"CLIENT_SECRET\")\n\n# Replace the following URL with your callback URL, which can be obtained from your App's auth settings.\nredirect_uri = \"https://example.com\"\n\n# Set the scopes\nscopes = [\"tweet.read\", \"users.read\", \"list.read\", \"list.write\", \"offline.access\"]\n\n# Be sure to replace name-of-list with the name you wish to call the list.\n# description and private keys are optional\npayload = {\n    \"name\": \"name-of-list\",\n    \"description\": \"description-of-list\",\n    \"private\": False\n}\n\ndef main():\n    # Step 1: Create PKCE instance\n    auth = OAuth2PKCEAuth(\n        client_id=client_id,\n        client_secret=client_secret,\n        redirect_uri=redirect_uri,\n        scope=scopes\n    )\n    \n    # Step 2: Get authorization URL\n    auth_url = auth.get_authorization_url()\n    print(\"Visit the following URL to authorize your App on behalf of your X handle in a browser:\")\n    print(auth_url)\n    \n    # Step 3: Handle callback\n    callback_url = input(\"Paste the full callback URL here: \")\n    \n    # Step 4: Exchange code for tokens\n    tokens = auth.fetch_token(authorization_response=callback_url)\n    access_token = tokens[\"access_token\"]\n    \n    # Step 5: Create client\n    client = Client(access_token=access_token)\n    \n    # Step 6: Create the list\n    response = client.lists.create(body=payload)\n    \n    print(\"Response code: 201\")\n    print(json.dumps(response.data, indent=4, sort_keys=True))\n\nif __name__ == \"__main__\":\n    main()\n"
  },
  {
    "path": "python/lists/delete_list.py",
    "content": "\"\"\"\nDelete List - X API v2\n======================\nEndpoint: DELETE https://api.x.com/2/lists/:id\nDocs: https://developer.x.com/en/docs/twitter-api/lists/manage-lists/api-reference/delete-lists-id\n\nAuthentication: OAuth 2.0 (User Context)\nRequired env vars: CLIENT_ID, CLIENT_SECRET\n\"\"\"\n\nimport os\nimport json\nfrom xdk import Client\nfrom xdk.oauth2_auth import OAuth2PKCEAuth\n\n# The code below sets the client ID and client secret from your environment variables\n# To set environment variables on macOS or Linux, run the export commands below from the terminal:\n# export CLIENT_ID='YOUR-CLIENT-ID'\n# export CLIENT_SECRET='YOUR-CLIENT-SECRET'\nclient_id = os.environ.get(\"CLIENT_ID\")\nclient_secret = os.environ.get(\"CLIENT_SECRET\")\n\n# Replace the following URL with your callback URL, which can be obtained from your App's auth settings.\nredirect_uri = \"https://example.com\"\n\n# Set the scopes\nscopes = [\"tweet.read\", \"users.read\", \"list.read\", \"list.write\", \"offline.access\"]\n\n# Be sure to replace your-list-id with the id of the list you wish to delete.\n# The authenticated user must own the list in order to delete it.\nlist_id = \"your-list-id\"\n\ndef main():\n    # Step 1: Create PKCE instance\n    auth = OAuth2PKCEAuth(\n        client_id=client_id,\n        client_secret=client_secret,\n        redirect_uri=redirect_uri,\n        scope=scopes\n    )\n    \n    # Step 2: Get authorization URL\n    auth_url = auth.get_authorization_url()\n    print(\"Visit the following URL to authorize your App on behalf of your X handle in a browser:\")\n    print(auth_url)\n    \n    # Step 3: Handle callback\n    callback_url = input(\"Paste the full callback URL here: \")\n    \n    # Step 4: Exchange code for tokens\n    tokens = auth.fetch_token(authorization_response=callback_url)\n    access_token = tokens[\"access_token\"]\n    \n    # Step 5: Create client\n    client = Client(access_token=access_token)\n    \n    # Step 6: Delete the list\n    response = client.lists.delete_list(list_id)\n    \n    print(\"Response code: 200\")\n    print(json.dumps(response.data, indent=4, sort_keys=True))\n\nif __name__ == \"__main__\":\n    main()\n"
  },
  {
    "path": "python/lists/get_list_by_id.py",
    "content": "\"\"\"\nList Lookup by ID - X API v2\n=============================\nEndpoint: GET https://api.x.com/2/lists/:id\nDocs: https://developer.x.com/en/docs/twitter-api/lists/list-lookup/api-reference/get-lists-id\n\nAuthentication: Bearer Token (App-only) or OAuth (User Context)\nRequired env vars: BEARER_TOKEN\n\"\"\"\n\nimport os\nimport json\nfrom xdk import Client\n\nbearer_token = os.environ.get(\"BEARER_TOKEN\")\nif not bearer_token:\n    raise ValueError(\"BEARER_TOKEN environment variable is not set\")\n\nclient = Client(bearer_token=bearer_token)\n\n# You can replace the ID given with the List ID you wish to lookup.\nlist_id = \"list-id\"\n\ndef main():\n    # List fields are adjustable. Options include:\n    # created_at, follower_count, member_count, private, description, owner_id\n    response = client.lists.get_by_id(\n        list_id,\n        list_fields=[\"created_at\", \"follower_count\", \"member_count\", \"owner_id\", \"description\"]\n    )\n    \n    print(json.dumps(response.data, indent=4, sort_keys=True))\n\nif __name__ == \"__main__\":\n    main()\n"
  },
  {
    "path": "python/lists/get_list_followers.py",
    "content": "\"\"\"\nList Followers Lookup - X API v2\n=================================\nEndpoint: GET https://api.x.com/2/lists/:id/followers\nDocs: https://developer.x.com/en/docs/twitter-api/lists/list-follows/api-reference/get-lists-id-followers\n\nAuthentication: Bearer Token (App-only) or OAuth (User Context)\nRequired env vars: BEARER_TOKEN\n\"\"\"\n\nimport os\nimport json\nfrom xdk import Client\n\nbearer_token = os.environ.get(\"BEARER_TOKEN\")\nif not bearer_token:\n    raise ValueError(\"BEARER_TOKEN environment variable is not set\")\n\nclient = Client(bearer_token=bearer_token)\n\n# You can replace list-id with the List ID you wish to find followers of.\n# Note: Private lists require OAuth 2.0 user context authentication.\nlist_id = \"list-id\"\n\ndef main():\n    # Get list followers with automatic pagination\n    # User fields are adjustable, options include:\n    # created_at, description, entities, id, location, name,\n    # pinned_tweet_id, profile_image_url, protected,\n    # public_metrics, url, username, verified, and withheld\n    all_users = []\n    for page in client.lists.get_followers(\n        list_id,\n        max_results=100,\n        user_fields=[\"created_at\", \"description\", \"verified\"]\n    ):\n        # Access data attribute (model uses extra='allow' so data should be available)\n        # Use getattr with fallback in case data field is missing from response\n        page_data = getattr(page, 'data', []) or []\n        all_users.extend(page_data)\n        print(f\"Fetched {len(page_data)} users (total: {len(all_users)})\")\n    \n    print(f\"\\nTotal Followers: {len(all_users)}\")\n    print(json.dumps({\"data\": all_users[:5]}, indent=4, sort_keys=True))  # Print first 5 as example\n\nif __name__ == \"__main__\":\n    main()"
  },
  {
    "path": "python/lists/get_list_members.py",
    "content": "\"\"\"\nList Members Lookup - X API v2\n==============================\nEndpoint: GET https://api.x.com/2/lists/:id/members\nDocs: https://developer.x.com/en/docs/twitter-api/lists/list-members/api-reference/get-lists-id-members\n\nAuthentication: Bearer Token (App-only) or OAuth (User Context)\nRequired env vars: BEARER_TOKEN\n\"\"\"\n\nimport os\nimport json\nfrom xdk import Client\n\nbearer_token = os.environ.get(\"BEARER_TOKEN\")\nclient = Client(bearer_token=bearer_token)\n\n# You can replace list-id with the List ID you wish to find members of.\nlist_id = \"list-id\"\n\ndef main():\n    # Get list members with automatic pagination\n    # User fields are adjustable, options include:\n    # created_at, description, entities, id, location, name,\n    # pinned_tweet_id, profile_image_url, protected,\n    # public_metrics, url, username, verified, and withheld\n    all_users = []\n    for page in client.lists.get_members(\n        list_id,\n        max_results=100,\n        user_fields=[\"created_at\", \"description\", \"verified\"]\n    ):\n        # Access data attribute (model uses extra='allow' so data should be available)\n        # Use getattr with fallback in case data field is missing from response\n        page_data = getattr(page, 'data', []) or []\n        all_users.extend(page_data)\n        print(f\"Fetched {len(page_data)} users (total: {len(all_users)})\")\n    \n    print(f\"\\nTotal Members: {len(all_users)}\")\n    print(json.dumps({\"data\": all_users[:5]}, indent=4, sort_keys=True))  # Print first 5 as example\n\nif __name__ == \"__main__\":\n    main()\n"
  },
  {
    "path": "python/lists/get_list_posts.py",
    "content": "\"\"\"\nList Tweets - X API v2\n======================\nEndpoint: GET https://api.x.com/2/lists/:id/tweets\nDocs: https://developer.x.com/en/docs/twitter-api/lists/list-tweets/api-reference/get-lists-id-tweets\n\nAuthentication: Bearer Token (App-only) or OAuth (User Context)\nRequired env vars: BEARER_TOKEN\n\"\"\"\n\nimport os\nimport json\nfrom xdk import Client\n\nbearer_token = os.environ.get(\"BEARER_TOKEN\")\nclient = Client(bearer_token=bearer_token)\n\n# Be sure to replace list-id with any List ID\nlist_id = \"list-id\"\n\ndef main():\n    # Get list tweets with automatic pagination\n    # Tweet fields are adjustable.\n    # Options include:\n    # attachments, author_id, context_annotations,\n    # conversation_id, created_at, entities, geo, id,\n    # in_reply_to_user_id, lang, non_public_metrics, organic_metrics,\n    # possibly_sensitive, promoted_metrics, public_metrics, referenced_tweets,\n    # source, text, and withheld\n    all_posts = []\n    for page in client.lists.get_posts(\n        list_id,\n        max_results=100,\n        tweet_fields=[\"lang\", \"author_id\"]\n    ):\n        # Access data attribute (model uses extra='allow' so data should be available)\n        # Use getattr with fallback in case data field is missing from response\n        page_data = getattr(page, 'data', []) or []\n        all_posts.extend(page_data)\n        print(f\"Fetched {len(page_data)} posts (total: {len(all_posts)})\")\n    \n    print(f\"\\nTotal Posts: {len(all_posts)}\")\n    print(json.dumps({\"data\": all_posts[:5]}, indent=4, sort_keys=True))  # Print first 5 as example\n\nif __name__ == \"__main__\":\n    main()\n"
  },
  {
    "path": "python/lists/remove_member.py",
    "content": "\"\"\"\nRemove List Member - X API v2\n==============================\nEndpoint: DELETE https://api.x.com/2/lists/:id/members/:user_id\nDocs: https://developer.x.com/en/docs/twitter-api/lists/list-members/api-reference/delete-lists-id-members-user_id\n\nAuthentication: OAuth 2.0 (User Context)\nRequired env vars: CLIENT_ID, CLIENT_SECRET\n\"\"\"\n\nimport os\nimport json\nfrom xdk import Client\nfrom xdk.oauth2_auth import OAuth2PKCEAuth\n\n# The code below sets the client ID and client secret from your environment variables\n# To set environment variables on macOS or Linux, run the export commands below from the terminal:\n# export CLIENT_ID='YOUR-CLIENT-ID'\n# export CLIENT_SECRET='YOUR-CLIENT-SECRET'\nclient_id = os.environ.get(\"CLIENT_ID\")\nclient_secret = os.environ.get(\"CLIENT_SECRET\")\n\n# Replace the following URL with your callback URL, which can be obtained from your App's auth settings.\nredirect_uri = \"https://example.com\"\n\n# Set the scopes\nscopes = [\"tweet.read\", \"users.read\", \"list.read\", \"list.write\", \"offline.access\"]\n\n# Be sure to replace your-list-id with your own list ID or one of an authenticated user\nlist_id = \"your-list-id\"\n\n# Be sure to replace user-id-to-remove with the id of the user you wish to remove.\n# You can find a user ID by using the user lookup endpoint\nuser_id = \"user-id-to-remove\"\n\ndef main():\n    # Step 1: Create PKCE instance\n    auth = OAuth2PKCEAuth(\n        client_id=client_id,\n        client_secret=client_secret,\n        redirect_uri=redirect_uri,\n        scope=scopes\n    )\n    \n    # Step 2: Get authorization URL\n    auth_url = auth.get_authorization_url()\n    print(\"Visit the following URL to authorize your App on behalf of your X handle in a browser:\")\n    print(auth_url)\n    \n    # Step 3: Handle callback\n    callback_url = input(\"Paste the full callback URL here: \")\n    \n    # Step 4: Exchange code for tokens\n    tokens = auth.fetch_token(authorization_response=callback_url)\n    access_token = tokens[\"access_token\"]\n    \n    # Step 5: Create client\n    client = Client(access_token=access_token)\n    \n    # Step 6: Remove member from list\n    response = client.lists.remove_member(list_id, user_id)\n    \n    print(\"Response code: 200\")\n    print(json.dumps(response.data, indent=4, sort_keys=True))\n\nif __name__ == \"__main__\":\n    main()\n"
  },
  {
    "path": "python/lists/update_list.py",
    "content": "\"\"\"\nUpdate List - X API v2\n======================\nEndpoint: PUT https://api.x.com/2/lists/:id\nDocs: https://developer.x.com/en/docs/twitter-api/lists/manage-lists/api-reference/put-lists-id\n\nAuthentication: OAuth 2.0 (User Context)\nRequired env vars: CLIENT_ID, CLIENT_SECRET\n\"\"\"\n\nimport os\nimport json\nfrom xdk import Client\nfrom xdk.oauth2_auth import OAuth2PKCEAuth\n\n# The code below sets the client ID and client secret from your environment variables\n# To set environment variables on macOS or Linux, run the export commands below from the terminal:\n# export CLIENT_ID='YOUR-CLIENT-ID'\n# export CLIENT_SECRET='YOUR-CLIENT-SECRET'\nclient_id = os.environ.get(\"CLIENT_ID\")\nclient_secret = os.environ.get(\"CLIENT_SECRET\")\n\n# Replace the following URL with your callback URL, which can be obtained from your App's auth settings.\nredirect_uri = \"https://example.com\"\n\n# Set the scopes\nscopes = [\"tweet.read\", \"users.read\", \"list.read\", \"list.write\", \"offline.access\"]\n\n# Be sure to replace update-name-of-list with the name you wish to call the list.\n# name, description and private are all optional\npayload = {\n    \"name\": \"update-name-of-list\",\n    \"description\": \"update-description-of-list\",\n    \"private\": False\n}\n\n# Be sure to replace your-list-id with the id of the list you wish to update.\n# The authenticated user must own the list in order to update it.\nlist_id = \"list-id\"\n\ndef main():\n    # Step 1: Create PKCE instance\n    auth = OAuth2PKCEAuth(\n        client_id=client_id,\n        client_secret=client_secret,\n        redirect_uri=redirect_uri,\n        scope=scopes\n    )\n    \n    # Step 2: Get authorization URL\n    auth_url = auth.get_authorization_url()\n    print(\"Visit the following URL to authorize your App on behalf of your X handle in a browser:\")\n    print(auth_url)\n    \n    # Step 3: Handle callback\n    callback_url = input(\"Paste the full callback URL here: \")\n    \n    # Step 4: Exchange code for tokens\n    tokens = auth.fetch_token(authorization_response=callback_url)\n    access_token = tokens[\"access_token\"]\n    \n    # Step 5: Create client\n    client = Client(access_token=access_token)\n    \n    # Step 6: Update the list\n    response = client.lists.update(list_id, body=payload)\n    \n    print(\"Response code: 200\")\n    print(json.dumps(response.data, indent=4, sort_keys=True))\n\nif __name__ == \"__main__\":\n    main()\n"
  },
  {
    "path": "python/media/media_upload_v2.py",
    "content": "\"\"\"\nMedia Upload v2 (Video) - X API v2\n===================================\nEndpoint: POST https://api.x.com/2/media/upload\nDocs: https://developer.x.com/en/docs/twitter-api/media/upload-media/api-reference\n\nAuthentication: OAuth 2.0 (User Context)\nRequired env vars: CLIENT_ID, CLIENT_SECRET\n\nThis example demonstrates uploading a video file using chunked uploads.\n\"\"\"\n\nimport os\nimport sys\nimport time\nimport requests\nfrom xdk.oauth2_auth import OAuth2PKCEAuth\n\nMEDIA_ENDPOINT_URL = 'https://api.x.com/2/media/upload'\nPOST_TO_X_URL = 'https://api.x.com/2/tweets'\n\n# Replace with path to file\nVIDEO_FILENAME = 'REPLACE_ME'\n\n# The code below sets the client ID and client secret from your environment variables\n# To set environment variables on macOS or Linux, run the export commands below from the terminal:\n# export CLIENT_ID='YOUR-CLIENT-ID'\n# export CLIENT_SECRET='YOUR-CLIENT-SECRET'\nclient_id = os.environ.get(\"CLIENT_ID\")\nclient_secret = os.environ.get(\"CLIENT_SECRET\")\n\n# Replace the following URL with your callback URL, which can be obtained from your App's auth settings.\nredirect_uri = \"https://example.com\"\n\n# Set the scopes\nscopes = [\"media.write\", \"users.read\", \"tweet.read\", \"tweet.write\", \"offline.access\"]\n\n# Step 1: Create PKCE instance\nauth = OAuth2PKCEAuth(\n    client_id=client_id,\n    client_secret=client_secret,\n    redirect_uri=redirect_uri,\n    scope=scopes\n)\n\n# Step 2: Get authorization URL\nauth_url = auth.get_authorization_url()\nprint(\"Visit the following URL to authorize your App on behalf of your X handle in a browser:\")\nprint(auth_url)\n\n# Step 3: Handle callback\ncallback_url = input(\"Paste the full callback URL here: \")\n\n# Step 4: Exchange code for tokens\ntokens = auth.fetch_token(authorization_response=callback_url)\naccess = tokens[\"access_token\"]\n\nheaders = {\n    \"Authorization\": \"Bearer {}\".format(access),\n    \"Content-Type\": \"application/json\",\n    \"User-Agent\": \"MediaUploadSampleCode\",\n}\n\n\nclass VideoPost(object):\n\n    def __init__(self, file_name):\n        # Defines video Post properties\n        self.video_filename = file_name\n        self.total_bytes = os.path.getsize(self.video_filename)\n        self.media_id = None\n        self.processing_info = None\n\n    def upload_init(self):\n        # Initializes Upload\n        print('INIT')\n\n        request_data = {\n            'command': 'INIT',\n            'media_type': 'video/mp4',\n            'total_bytes': self.total_bytes,\n            'media_category': 'tweet_video'\n        }\n\n        req = requests.post(url=MEDIA_ENDPOINT_URL, params=request_data, headers=headers)\n        print(req.status_code)\n        print(req.text)\n        media_id = req.json()['data']['id']\n\n        self.media_id = media_id\n\n        print('Media ID: %s' % str(media_id))\n\n    def upload_append(self):\n        segment_id = 0\n        bytes_sent = 0\n        with open(self.video_filename, 'rb') as file:\n            while bytes_sent < self.total_bytes:\n                chunk = file.read(4 * 1024 * 1024)  # 4MB chunk size\n\n                print('APPEND')\n\n                files = {'media': ('chunk', chunk, 'application/octet-stream')}\n\n                data = {\n                    'command': 'APPEND',\n                    'media_id': self.media_id,\n                    'segment_index': segment_id\n                }\n\n                headers = {\n                    \"Authorization\": f\"Bearer {access}\",\n                    \"User-Agent\": \"MediaUploadSampleCode\",\n                }\n\n                req = requests.post(url=MEDIA_ENDPOINT_URL, data=data, files=files, headers=headers)\n\n                if req.status_code < 200 or req.status_code > 299:\n                    print(req.status_code)\n                    print(req.text)\n                    sys.exit(0)\n\n                segment_id += 1\n                bytes_sent = file.tell()\n\n                print(f'{bytes_sent} of {self.total_bytes} bytes uploaded')\n\n        print('Upload chunks complete.')\n\n    def upload_finalize(self):\n\n        # Finalizes uploads and starts video processing\n        print('FINALIZE')\n\n        request_data = {\n            'command': 'FINALIZE',\n            'media_id': self.media_id\n        }\n\n        req = requests.post(url=MEDIA_ENDPOINT_URL, params=request_data, headers=headers)\n\n        print(req.json())\n\n        self.processing_info = req.json()['data'].get('processing_info', None)\n        self.check_status()\n\n    def check_status(self):\n        # Checks video processing status\n        if self.processing_info is None:\n            return\n\n        state = self.processing_info['state']\n\n        print('Media processing status is %s ' % state)\n\n        if state == u'succeeded':\n            return\n\n        if state == u'failed':\n            sys.exit(0)\n\n        check_after_secs = self.processing_info['check_after_secs']\n\n        print('Checking after %s seconds' % str(check_after_secs))\n        time.sleep(check_after_secs)\n\n        print('STATUS')\n\n        request_params = {\n            'command': 'STATUS',\n            'media_id': self.media_id\n        }\n\n        req = requests.get(url=MEDIA_ENDPOINT_URL, params=request_params, headers=headers)\n\n        self.processing_info = req.json()['data'].get('processing_info', None)\n        self.check_status()\n\n    def post(self):\n\n        # Publishes Post with attached video\n        payload = {\n            'text': 'I just uploaded a video with the media upload v2 @XDevelopers API.',\n            'media': {\n                'media_ids': [self.media_id]\n            }\n        }\n\n        req = requests.post(url=POST_TO_X_URL, json=payload, headers=headers)\n\n        print(req.json())\n\n\nif __name__ == '__main__':\n    videoPost = VideoPost(VIDEO_FILENAME)\n    videoPost.upload_init()\n    videoPost.upload_append()\n    videoPost.upload_finalize()\n    videoPost.post()\n"
  },
  {
    "path": "python/media/upload.py",
    "content": "\"\"\"\nMedia Upload - X API v2\n=======================\nEndpoint: POST https://upload.x.com/1.1/media/upload.json\nDocs: https://developer.x.com/en/docs/twitter-api/media/upload-media/api-reference\n\nAuthentication: OAuth 2.0 (User Context)\nRequired env vars: CLIENT_ID, CLIENT_SECRET\n\nThis example demonstrates uploading an image to attach to a post.\n\"\"\"\n\nimport os\nimport json\nimport base64\nfrom xdk import Client\nfrom xdk.oauth2_auth import OAuth2PKCEAuth\n\n# The code below sets the client ID and client secret from your environment variables\n# To set environment variables on macOS or Linux, run the export commands below from the terminal:\n# export CLIENT_ID='YOUR-CLIENT-ID'\n# export CLIENT_SECRET='YOUR-CLIENT-SECRET'\nclient_id = os.environ.get(\"CLIENT_ID\")\nclient_secret = os.environ.get(\"CLIENT_SECRET\")\n\n# Replace the following URL with your callback URL, which can be obtained from your App's auth settings.\nredirect_uri = \"https://example.com\"\n\n# Set the scopes\nscopes = [\"tweet.read\", \"tweet.write\", \"users.read\", \"offline.access\"]\n\n# Path to the media file you want to upload\nmedia_path = \"path/to/your/image.jpg\"\n\ndef main():\n    # Step 1: Create PKCE instance\n    auth = OAuth2PKCEAuth(\n        client_id=client_id,\n        client_secret=client_secret,\n        redirect_uri=redirect_uri,\n        scope=scopes\n    )\n    \n    # Step 2: Get authorization URL\n    auth_url = auth.get_authorization_url()\n    print(\"Visit the following URL to authorize your App on behalf of your X handle in a browser:\")\n    print(auth_url)\n    \n    # Step 3: Handle callback\n    callback_url = input(\"Paste the full callback URL here: \")\n    \n    # Step 4: Exchange code for tokens\n    tokens = auth.fetch_token(authorization_response=callback_url)\n    access_token = tokens[\"access_token\"]\n    \n    # Step 5: Create client\n    client = Client(access_token=access_token)\n    \n    # Step 6: Read and upload the media file\n    with open(media_path, \"rb\") as media_file:\n        media_data = base64.b64encode(media_file.read()).decode(\"utf-8\")\n    \n    payload = {\"media_data\": media_data}\n    response = client.media.upload_media(body=payload)\n    \n    print(\"Response code: 200\")\n    \n    # Get the media_id to use when creating a post\n    media_id = response.data[\"media_id_string\"]\n    print(\"Media ID: {}\".format(media_id))\n    print(json.dumps(response.data, indent=4, sort_keys=True))\n    \n    # You can now use this media_id when creating a post:\n    # payload = {\"text\": \"My post with media!\", \"media\": {\"media_ids\": [media_id]}}\n\nif __name__ == \"__main__\":\n    main()\n"
  },
  {
    "path": "python/posts/create_post.py",
    "content": "\"\"\"\nCreate Tweet - X API v2\n=======================\nEndpoint: POST https://api.x.com/2/tweets\nDocs: https://developer.x.com/en/docs/twitter-api/tweets/manage-tweets/api-reference/post-tweets\n\nAuthentication: OAuth 2.0 (User Context)\nRequired env vars: CLIENT_ID, CLIENT_SECRET\n\"\"\"\n\nimport os\nimport json\nfrom xdk import Client\nfrom xdk.oauth2_auth import OAuth2PKCEAuth\n\n# The code below sets the client ID and client secret from your environment variables\n# To set environment variables on macOS or Linux, run the export commands below from the terminal:\n# export CLIENT_ID='YOUR-CLIENT-ID'\n# export CLIENT_SECRET='YOUR-CLIENT-SECRET'\nclient_id = os.environ.get(\"CLIENT_ID\")\nclient_secret = os.environ.get(\"CLIENT_SECRET\")\n\n# Replace the following URL with your callback URL, which can be obtained from your App's auth settings.\nredirect_uri = \"https://example.com\"\n\n# Set the scopes\nscopes = [\"tweet.read\", \"tweet.write\", \"users.read\", \"offline.access\"]\n\n# Be sure to replace the text with the text you wish to Tweet. \n# You can also add parameters to post polls, quote Tweets, Tweet with reply settings, and Tweet to Super Followers in addition to other features.\npayload = {\"text\": \"Hello world!\"}\n\ndef main():\n    # Step 1: Create PKCE instance\n    auth = OAuth2PKCEAuth(\n        client_id=client_id,\n        client_secret=client_secret,\n        redirect_uri=redirect_uri,\n        scope=scopes\n    )\n    \n    # Step 2: Get authorization URL\n    auth_url = auth.get_authorization_url()\n    print(\"Visit the following URL to authorize your App on behalf of your X handle in a browser:\")\n    print(auth_url)\n    \n    # Step 3: Handle callback\n    callback_url = input(\"Paste the full callback URL here: \")\n    \n    # Step 4: Exchange code for tokens\n    tokens = auth.fetch_token(authorization_response=callback_url)\n    access_token = tokens[\"access_token\"]\n    \n    # Step 5: Create client\n    client = Client(access_token=access_token)\n    \n    # Step 6: Create the tweet\n    response = client.posts.create(body=payload)\n    \n    print(\"Response code: 201\")\n    print(json.dumps(response.data, indent=4, sort_keys=True))\n\nif __name__ == \"__main__\":\n    main()\n"
  },
  {
    "path": "python/posts/delete_post.py",
    "content": "\"\"\"\nDelete Tweet - X API v2\n=======================\nEndpoint: DELETE https://api.x.com/2/tweets/:id\nDocs: https://developer.x.com/en/docs/twitter-api/tweets/manage-tweets/api-reference/delete-tweets-id\n\nAuthentication: OAuth 2.0 (User Context)\nRequired env vars: CLIENT_ID, CLIENT_SECRET\n\"\"\"\n\nimport os\nimport json\nfrom xdk import Client\nfrom xdk.oauth2_auth import OAuth2PKCEAuth\n\n# The code below sets the client ID and client secret from your environment variables\n# To set environment variables on macOS or Linux, run the export commands below from the terminal:\n# export CLIENT_ID='YOUR-CLIENT-ID'\n# export CLIENT_SECRET='YOUR-CLIENT-SECRET'\nclient_id = os.environ.get(\"CLIENT_ID\")\nclient_secret = os.environ.get(\"CLIENT_SECRET\")\n\n# Replace the following URL with your callback URL, which can be obtained from your App's auth settings.\nredirect_uri = \"https://example.com\"\n\n# Set the scopes\nscopes = [\"tweet.read\", \"tweet.write\", \"users.read\", \"offline.access\"]\n\n# Be sure to replace tweet-id-to-delete with the id of the Tweet you wish to delete.\n# The authenticated user must own the Tweet in order to delete it.\npost_id = \"1997118644242014409\"\n\ndef main():\n    # Step 1: Create PKCE instance\n    auth = OAuth2PKCEAuth(\n        client_id=client_id,\n        client_secret=client_secret,\n        redirect_uri=redirect_uri,\n        scope=scopes\n    )\n    \n    # Step 2: Get authorization URL\n    auth_url = auth.get_authorization_url()\n    print(\"Visit the following URL to authorize your App on behalf of your X handle in a browser:\")\n    print(auth_url)\n    \n    # Step 3: Handle callback\n    callback_url = input(\"Paste the full callback URL here: \")\n    \n    # Step 4: Exchange code for tokens\n    tokens = auth.fetch_token(authorization_response=callback_url)\n    access_token = tokens[\"access_token\"]\n    \n    # Step 5: Create client\n    client = Client(access_token=access_token)\n    \n    # Step 6: Delete the tweet\n    response = client.posts.delete(post_id)\n    \n    print(\"Response code: 200\")\n    print(json.dumps(response.data, indent=4, sort_keys=True))\n\nif __name__ == \"__main__\":\n\n    main()\n"
  },
  {
    "path": "python/posts/get_liking_users.py",
    "content": "\"\"\"\nLiking Users - X API v2\n======================\nEndpoint: GET https://api.x.com/2/tweets/:id/liking_users\nDocs: https://developer.x.com/en/docs/twitter-api/tweets/likes/api-reference/get-tweets-id-liking_users\n\nAuthentication: OAuth 2.0 (User Context)\nRequired env vars: CLIENT_ID, CLIENT_SECRET\n\"\"\"\n\nimport os\nimport json\nfrom xdk import Client\nfrom xdk.oauth2_auth import OAuth2PKCEAuth\nfrom requests.exceptions import HTTPError\n\n# The code below sets the client ID and client secret from your environment variables\n# To set environment variables on macOS or Linux, run the export commands below from the terminal:\n# export CLIENT_ID='YOUR-CLIENT-ID'\n# export CLIENT_SECRET='YOUR-CLIENT-SECRET'\nclient_id = os.environ.get(\"CLIENT_ID\")\nclient_secret = os.environ.get(\"CLIENT_SECRET\")\n\n# Replace the following URL with your callback URL, which can be obtained from your App's auth settings.\nredirect_uri = \"https://example.com\"\n\n# Set the scopes\nscopes = [\"tweet.read\", \"users.read\", \"like.read\", \"offline.access\"]\n\n# You can replace the ID given with the Post ID you wish to get liking users for.\n# You can find an ID by using the Post lookup endpoint\npost_id = \"post-id\"\n\ndef main():\n    # Step 1: Create PKCE instance\n    auth = OAuth2PKCEAuth(\n        client_id=client_id,\n        client_secret=client_secret,\n        redirect_uri=redirect_uri,\n        scope=scopes\n    )\n    \n    # Step 2: Get authorization URL\n    auth_url = auth.get_authorization_url()\n    print(\"Visit the following URL to authorize your App on behalf of your X handle in a browser:\")\n    print(auth_url)\n    \n    # Step 3: Handle callback\n    callback_url = input(\"Paste the full callback URL here: \")\n    \n    # Step 4: Exchange code for tokens\n    tokens = auth.fetch_token(authorization_response=callback_url)\n    access_token = tokens[\"access_token\"]\n    \n    # Step 5: Create client\n    client = Client(access_token=access_token)\n    \n    # Step 6: Get liking users with automatic pagination\n    # User fields are adjustable, options include:\n    # created_at, description, entities, id, location, name,\n    # pinned_tweet_id, profile_image_url, protected,\n    # public_metrics, url, username, verified, and withheld\n    all_users = []\n    for page in client.posts.get_liking_users(\n        post_id,\n        max_results=100,\n        user_fields=[\"created_at\", \"description\"]\n    ):\n        # Access data attribute (model uses extra='allow' so data should be available)\n        # Use getattr with fallback in case data field is missing from response\n        page_data = getattr(page, 'data', []) or []\n        all_users.extend(page_data)\n        print(f\"Fetched {len(page_data)} users (total: {len(all_users)})\")\n    \n    print(f\"\\nTotal Users: {len(all_users)}\")\n    print(json.dumps({\"data\": all_users[:5]}, indent=4, sort_keys=True))  # Print first 5 as example\n\nif __name__ == \"__main__\":\n    main()\n"
  },
  {
    "path": "python/posts/get_post_by_id.py",
    "content": "\"\"\"\nSingle Post Lookup - X API v2\n=============================\nEndpoint: GET https://api.x.com/2/tweets/:id\nDocs: https://developer.x.com/en/docs/twitter-api/tweets/lookup/api-reference/get-tweets-id\n\nAuthentication: Bearer Token (App-only) or OAuth (User Context)\nRequired env vars: BEARER_TOKEN\n\"\"\"\n\nimport os\nimport json\nfrom xdk import Client\n\nbearer_token = os.environ.get(\"BEARER_TOKEN\")\nclient = Client(bearer_token=bearer_token)\n\n# Replace with the Post ID you want to look up\npost_id = \"post-id\"\n\ndef main():\n    # Post fields are adjustable. Options include:\n    # attachments, author_id, context_annotations, conversation_id,\n    # created_at, entities, geo, id, in_reply_to_user_id, lang,\n    # non_public_metrics, organic_metrics, possibly_sensitive,\n    # promoted_metrics, public_metrics, referenced_tweets,\n    # source, text, and withheld\n    response = client.posts.get_by_id(\n        post_id,\n        tweet_fields=[\"created_at\", \"author_id\", \"lang\", \"source\", \"public_metrics\", \"entities\"]\n    )\n\n    print(json.dumps(response.data, indent=4, sort_keys=True))\n\n\nif __name__ == \"__main__\":\n    main()\n"
  },
  {
    "path": "python/posts/get_post_counts_all.py",
    "content": "\"\"\"\nFull-Archive Post Counts - X API v2\n===================================\nEndpoint: GET https://api.x.com/2/tweets/counts/all\nDocs: https://developer.x.com/en/docs/twitter-api/tweets/counts/api-reference/get-tweets-counts-all\n\nAuthentication: Bearer Token (App-only)\nRequired env vars: BEARER_TOKEN\n\nNote: Requires Academic Research access. Returns counts from the entire archive.\n\"\"\"\n\nimport os\nimport json\nfrom xdk import Client\n\nbearer_token = os.environ.get(\"BEARER_TOKEN\")\nclient = Client(bearer_token=bearer_token)\n\nquery = \"from:XDevelopers\"\n\ndef main():\n    # Get counts with automatic pagination\n    # Optional: You can add start_time parameter to limit the date range\n    # Example: start_time=\"2021-01-01T00:00:00Z\"\n    all_counts = []\n    for page in client.posts.get_counts_all(\n        query=query,\n        granularity=\"day\"\n        # start_time=\"2021-01-01T00:00:00Z\"  # Optional: uncomment to add date range\n    ):\n        # Access data attribute (model uses extra='allow' so data should be available)\n        # Use getattr with fallback in case data field is missing from response\n        page_data = getattr(page, 'data', []) or []\n        all_counts.extend(page_data)\n        print(f\"Fetched {len(page_data)} count buckets (total: {len(all_counts)})\")\n    \n    print(f\"\\nTotal Count Buckets: {len(all_counts)}\")\n    print(json.dumps({\"data\": all_counts}, indent=4, sort_keys=True))\n\n\nif __name__ == \"__main__\":\n    main()\n"
  },
  {
    "path": "python/posts/get_post_counts_recent.py",
    "content": "\"\"\"\nRecent Post Counts - X API v2\n=============================\nEndpoint: GET https://api.x.com/2/tweets/counts/recent\nDocs: https://developer.x.com/en/docs/twitter-api/tweets/counts/api-reference/get-tweets-counts-recent\n\nAuthentication: Bearer Token (App-only)\nRequired env vars: BEARER_TOKEN\n\nNote: Returns count of posts from the last 7 days matching your query.\n\"\"\"\n\nimport os\nimport json\nfrom xdk import Client\n\nbearer_token = os.environ.get(\"BEARER_TOKEN\")\nclient = Client(bearer_token=bearer_token)\n\nquery = \"from:XDevelopers\"\n\ndef main():\n    # Get counts with automatic pagination\n    all_counts = []\n    for page in client.posts.get_counts_recent(\n        query=query,\n        granularity=\"day\"\n    ):\n        # Access data attribute (model uses extra='allow' so data should be available)\n        # Use getattr with fallback in case data field is missing from response\n        page_data = getattr(page, 'data', []) or []\n        all_counts.extend(page_data)\n        print(f\"Fetched {len(page_data)} count buckets (total: {len(all_counts)})\")\n    \n    print(f\"\\nTotal Count Buckets: {len(all_counts)}\")\n    print(json.dumps({\"data\": all_counts}, indent=4, sort_keys=True))\n\n\nif __name__ == \"__main__\":\n    main()\n"
  },
  {
    "path": "python/posts/get_posts_by_ids.py",
    "content": "\"\"\"\nPost Lookup - X API v2\n======================\nEndpoint: GET https://api.x.com/2/tweets\nDocs: https://developer.x.com/en/docs/twitter-api/tweets/lookup/api-reference/get-tweets\n\nAuthentication: Bearer Token (App-only) or OAuth (User Context)\nRequired env vars: BEARER_TOKEN\n\"\"\"\n\nimport os\nimport json\nfrom xdk import Client\n\nbearer_token = os.environ.get(\"BEARER_TOKEN\")\nclient = Client(bearer_token=bearer_token)\n\n# Post IDs to look up (comma-separated list, up to 100)\n# You can adjust ids to include a single Post or add up to 100 comma-separated IDs\npost_ids = [\"post-id-1\", \"post-id-2\"]\n\ndef main():\n    # Post fields are adjustable. Options include:\n    # attachments, author_id, context_annotations, conversation_id,\n    # created_at, entities, geo, id, in_reply_to_user_id, lang,\n    # non_public_metrics, organic_metrics, possibly_sensitive,\n    # promoted_metrics, public_metrics, referenced_tweets,\n    # source, text, and withheld\n    response = client.posts.get_by_ids(\n        ids=post_ids,\n        tweet_fields=[\"created_at\", \"author_id\", \"lang\", \"source\", \"public_metrics\", \"context_annotations\", \"entities\"]\n    )\n    \n    print(json.dumps(response.data, indent=4, sort_keys=True))\n\n\nif __name__ == \"__main__\":\n    main()\n"
  },
  {
    "path": "python/posts/get_quoted_posts.py",
    "content": "\"\"\"\nQuote Tweets Lookup - X API v2\n==============================\nEndpoint: GET https://api.x.com/2/tweets/:id/quote_tweets\nDocs: https://developer.x.com/en/docs/twitter-api/tweets/quote-tweets/api-reference/get-tweets-id-quote_tweets\n\nAuthentication: Bearer Token (App-only) or OAuth (User Context)\nRequired env vars: BEARER_TOKEN\n\"\"\"\n\nimport os\nimport json\nfrom xdk import Client\n\nbearer_token = os.environ.get(\"BEARER_TOKEN\")\nclient = Client(bearer_token=bearer_token)\n\n# Replace with the post ID you want to get quotes for\npost_id = \"1409931481552543749\"\n\ndef main():\n    # Get quote tweets with automatic pagination\n    # Tweet fields are adjustable.\n    # Options include:\n    # attachments, author_id, context_annotations,\n    # conversation_id, created_at, entities, geo, id,\n    # in_reply_to_user_id, lang, non_public_metrics, organic_metrics,\n    # possibly_sensitive, promoted_metrics, public_metrics, referenced_tweets,\n    # source, text, and withheld\n    all_posts = []\n    for page in client.posts.get_quoted(\n        post_id,\n        max_results=100,\n        tweet_fields=[\"created_at\"]\n    ):\n        all_posts.extend(page.data)\n        print(f\"Fetched {len(page.data)} posts (total: {len(all_posts)})\")\n    \n    print(f\"\\nTotal Quote Tweets: {len(all_posts)}\")\n    print(json.dumps({\"data\": all_posts[:5]}, indent=4, sort_keys=True))  # Print first 5 as example\n\nif __name__ == \"__main__\":\n    main()\n    "
  },
  {
    "path": "python/posts/get_reposted_by.py",
    "content": "\"\"\"\nRetweeted By (Users who reposted) - X API v2\n============================================\nEndpoint: GET https://api.x.com/2/tweets/:id/retweeted_by\nDocs: https://developer.x.com/en/docs/twitter-api/tweets/retweets/api-reference/get-tweets-id-retweeted_by\n\nAuthentication: Bearer Token (App-only) or OAuth (User Context)\nRequired env vars: BEARER_TOKEN\n\"\"\"\n\nimport os\nimport json\nfrom xdk import Client\n\nbearer_token = os.environ.get(\"BEARER_TOKEN\")\nclient = Client(bearer_token=bearer_token)\n\n# You can replace the ID given with the Post ID you wish to lookup reposting users for\n# You can find an ID by using the Post lookup endpoint\npost_id = \"post-id\"\n\ndef main():\n    # Get reposted by users with automatic pagination\n    # User fields are adjustable, options include:\n    # created_at, description, entities, id, location, name,\n    # pinned_tweet_id, profile_image_url, protected,\n    # public_metrics, url, username, verified, and withheld\n    all_users = []\n    for page in client.posts.get_reposted_by(\n        post_id,\n        max_results=100,\n        user_fields=[\"created_at\", \"description\"]\n    ):\n        # Access data attribute (model uses extra='allow' so data should be available)\n        # Use getattr with fallback in case data field is missing from response\n        page_data = getattr(page, 'data', []) or []\n        all_users.extend(page_data)\n        print(f\"Fetched {len(page_data)} users (total: {len(all_users)})\")\n    \n    print(f\"\\nTotal Users: {len(all_users)}\")\n    print(json.dumps({\"data\": all_users[:5]}, indent=4, sort_keys=True))  # Print first 5 as example\n\nif __name__ == \"__main__\":\n    main()\n"
  },
  {
    "path": "python/posts/hide_reply.py",
    "content": "\"\"\"\nHide Reply - X API v2\n=====================\nEndpoint: PUT https://api.x.com/2/tweets/:id/hidden\nDocs: https://developer.x.com/en/docs/twitter-api/tweets/hide-replies/api-reference/put-tweets-id-hidden\n\nAuthentication: OAuth 2.0 (User Context)\nRequired env vars: CLIENT_ID, CLIENT_SECRET\n\nNote: You can only hide or unhide replies to conversations you authored.\nPass hidden=True to hide a reply, or hidden=False to unhide one.\n\"\"\"\n\nimport os\nimport json\nfrom xdk import Client\nfrom xdk.oauth2_auth import OAuth2PKCEAuth\n\n# The code below sets the client ID and client secret from your environment variables\n# To set environment variables on macOS or Linux, run the export commands below from the terminal:\n# export CLIENT_ID='YOUR-CLIENT-ID'\n# export CLIENT_SECRET='YOUR-CLIENT-SECRET'\nclient_id = os.environ.get(\"CLIENT_ID\")\nclient_secret = os.environ.get(\"CLIENT_SECRET\")\n\n# Replace the following URL with your callback URL, which can be obtained from your App's auth settings.\nredirect_uri = \"https://example.com\"\n\n# Set the scopes\nscopes = [\"tweet.read\", \"tweet.write\", \"users.read\", \"offline.access\"]\n\n# Replace with the ID of the reply you wish to hide.\n# You can only hide replies to conversations you authored.\ntweet_id = \"reply-tweet-id-to-hide\"\n\ndef main():\n    # Step 1: Create PKCE instance\n    auth = OAuth2PKCEAuth(\n        client_id=client_id,\n        client_secret=client_secret,\n        redirect_uri=redirect_uri,\n        scope=scopes\n    )\n\n    # Step 2: Get authorization URL\n    auth_url = auth.get_authorization_url()\n    print(\"Visit the following URL to authorize your App on behalf of your X handle in a browser:\")\n    print(auth_url)\n\n    # Step 3: Handle callback\n    callback_url = input(\"Paste the full callback URL here: \")\n\n    # Step 4: Exchange code for tokens\n    tokens = auth.fetch_token(authorization_response=callback_url)\n    access_token = tokens[\"access_token\"]\n\n    # Step 5: Create client\n    client = Client(access_token=access_token)\n\n    # Step 6: Hide the reply\n    # Set hidden=False to unhide a previously hidden reply\n    response = client.posts.hide_reply(tweet_id, hidden=True)\n\n    print(\"Response code: 200\")\n    print(json.dumps(response.data, indent=4, sort_keys=True))\n\n\nif __name__ == \"__main__\":\n    main()\n"
  },
  {
    "path": "python/posts/search_all.py",
    "content": "\"\"\"\nFull-Archive Search - X API v2\n==============================\nEndpoint: GET https://api.x.com/2/tweets/search/all\nDocs: https://developer.x.com/en/docs/twitter-api/tweets/search/api-reference/get-tweets-search-all\n\nAuthentication: Bearer Token (App-only)\nRequired env vars: BEARER_TOKEN\n\nNote: Requires Academic Research access. Returns posts from the entire archive.\nThis example demonstrates automatic pagination using the iterate() method\nto fetch all pages of results.\n\"\"\"\n\nimport os\nimport json\nfrom xdk import Client\n\nbearer_token = os.environ.get(\"BEARER_TOKEN\")\nclient = Client(bearer_token=bearer_token)\n\nquery = '(from:xdevelopers -is:retweet) OR #xdevelopers'\n\ndef main():\n    # Search with automatic pagination\n    all_posts = []\n    for page in client.posts.search_all(\n        query=query,\n        max_results=100,  # Per page\n        tweet_fields=[\"author_id\", \"created_at\"]\n    ):\n        # Access data attribute (model uses extra='allow' so data should be available)\n        # Use getattr with fallback in case data field is missing from response\n        page_data = getattr(page, 'data', []) or []\n        all_posts.extend(page_data)\n        print(f\"Fetched {len(page_data)} Posts (total: {len(all_posts)})\")\n    \n    print(f\"\\nTotal Posts: {len(all_posts)}\")\n    print(json.dumps({\"data\": all_posts[:5]}, indent=4, sort_keys=True))  # Print first 5 as example\n\n\nif __name__ == \"__main__\":\n    main()"
  },
  {
    "path": "python/posts/search_recent.py",
    "content": "\"\"\"\nRecent Search - X API v2\n========================\nEndpoint: GET https://api.x.com/2/tweets/search/recent\nDocs: https://developer.x.com/en/docs/twitter-api/tweets/search/api-reference/get-tweets-search-recent\n\nAuthentication: Bearer Token (App-only)\nRequired env vars: BEARER_TOKEN\n\nNote: Returns posts from the last 7 days.\nThis example demonstrates automatic pagination using the iterate() method\nto fetch all pages of results.\n\"\"\"\n\nimport os\nimport json\nfrom xdk import Client\n\nbearer_token = os.environ.get(\"BEARER_TOKEN\")\nclient = Client(bearer_token=bearer_token)\n\nquery = '(from:XDevelopers -is:retweet) OR #XDevelopers'\n\ndef main():\n    # Search with automatic pagination\n    all_posts = []\n    for page in client.posts.search_recent(\n        query=query,\n        max_results=100,  # Per page\n        tweet_fields=[\"author_id\", \"created_at\"]\n    ):\n        # Access data attribute (model uses extra='allow' so data should be available)\n        # Use getattr with fallback in case data field is missing from response\n        page_data = getattr(page, 'data', []) or []\n        all_posts.extend(page_data)\n        print(f\"Fetched {len(page_data)} Posts (total: {len(all_posts)})\")\n    \n    print(f\"\\nTotal Posts: {len(all_posts)}\")\n    print(json.dumps({\"data\": all_posts[:5]}, indent=4, sort_keys=True))  # Print first 5 as example\n\n\nif __name__ == \"__main__\":\n    main()\n"
  },
  {
    "path": "python/requirements.txt",
    "content": "xdk>=0.4.5\nflask>=3.0.0\nwaitress>=3.0.0\n"
  },
  {
    "path": "python/spaces/get_spaces_by_ids.py",
    "content": "\"\"\"\nSpaces Lookup - X API v2\n========================\nEndpoint: GET https://api.x.com/2/spaces\nDocs: https://developer.x.com/en/docs/twitter-api/spaces/lookup/api-reference/get-spaces\n\nAuthentication: Bearer Token (App-only) or OAuth (User Context)\nRequired env vars: BEARER_TOKEN\n\"\"\"\n\nimport os\nimport json\nfrom xdk import Client\n\nbearer_token = os.environ.get(\"BEARER_TOKEN\")\nclient = Client(bearer_token=bearer_token)\n\n# Space IDs to look up (list)\n# You can replace the IDs with actual Space IDs you want to look up\nspace_ids = [\"space-id-1\", \"space-id-2\"]\n\ndef main():\n    # Optional params: host_ids, conversation_controls, created_at, creator_id, id, invited_user_ids,\n    # is_ticketed, lang, media_key, participants, scheduled_start, speaker_ids, started_at, state, title, updated_at\n    response = client.spaces.get_by_ids(\n        ids=space_ids,\n        space_fields=[\"title\", \"created_at\"],\n        expansions=[\"creator_id\"]\n    )\n    \n    print(json.dumps(response.data, indent=4, sort_keys=True))\n\nif __name__ == \"__main__\":\n    main()"
  },
  {
    "path": "python/spaces/search_spaces.py",
    "content": "\"\"\"\nSearch Spaces - X API v2\n========================\nEndpoint: GET https://api.x.com/2/spaces/search\nDocs: https://developer.x.com/en/docs/twitter-api/spaces/search/api-reference/get-spaces-search\n\nAuthentication: Bearer Token (App-only) or OAuth (User Context)\nRequired env vars: BEARER_TOKEN\n\"\"\"\n\nimport os\nimport json\nfrom xdk import Client\n\nbearer_token = os.environ.get(\"BEARER_TOKEN\")\nclient = Client(bearer_token=bearer_token)\n\n# Replace this value with your search term\nsearch_term = 'NBA'\n\ndef main():\n    # Optional params: host_ids, conversation_controls, created_at, creator_id, id, invited_user_ids,\n    # is_ticketed, lang, media_key, participants, scheduled_start, speaker_ids, started_at, state, title, updated_at\n    response = client.spaces.search(\n        query=search_term,\n        space_fields=[\"title\", \"created_at\"],\n        expansions=[\"creator_id\"]\n    )\n    \n    print(json.dumps(response.data, indent=4, sort_keys=True))\n\nif __name__ == \"__main__\":\n    main()"
  },
  {
    "path": "python/streams/stream_posts_filtered.py",
    "content": "\"\"\"\nFiltered Stream - X API v2\n==========================\nEndpoint: GET https://api.x.com/2/tweets/search/stream\nDocs: https://developer.x.com/en/docs/twitter-api/tweets/filtered-stream/api-reference/get-tweets-search-stream\n\nAuthentication: Bearer Token (App-only)\nRequired env vars: BEARER_TOKEN\n\nNote: Streams posts matching your filter rules in real-time.\n\"\"\"\n\nimport os\nimport json\nfrom xdk import Client\n\nbearer_token = os.environ.get(\"BEARER_TOKEN\")\nclient = Client(bearer_token=bearer_token)\n\ndef get_rules():\n    response = client.stream.get_rules()\n    # Access data attribute safely\n    rules_data = getattr(response, 'data', None)\n    if rules_data:\n        print(json.dumps(rules_data, indent=4, sort_keys=True))\n    return rules_data\n\n\ndef delete_all_rules(rules):\n    if rules is None or not rules:\n        return None\n\n    ids = [rule[\"id\"] for rule in rules]\n    payload = {\"delete\": {\"ids\": ids}}\n    response = client.stream.update_rules(body=payload)\n    # Access data attribute safely\n    response_data = getattr(response, 'data', None)\n    if response_data:\n        print(json.dumps(response_data, indent=4, sort_keys=True))\n\n\ndef set_rules():\n    # You can adjust the rules if needed\n    sample_rules = [\n        {\"value\": \"dog has:images\", \"tag\": \"dog pictures\"},\n        {\"value\": \"cat has:images -grumpy\", \"tag\": \"cat pictures\"},\n    ]\n    payload = {\"add\": sample_rules}\n    response = client.stream.update_rules(body=payload)\n    # Access data attribute safely\n    response_data = getattr(response, 'data', None)\n    if response_data:\n        print(json.dumps(response_data, indent=4, sort_keys=True))\n\n\ndef get_stream():\n    # Stream posts matching the filter rules in real-time\n    # The posts() method is the filtered stream\n    try:\n        for post in client.stream.posts():\n            # Access data attribute safely\n            post_data = getattr(post, 'data', None)\n            if post_data:\n                print(json.dumps(post_data, indent=4, sort_keys=True))\n    except Exception as e:\n        print(f\"Error streaming posts: {e}\")\n        print(\"Note: This could be a temporary API issue (503 Service Unavailable)\")\n        print(\"or the stream endpoint may be experiencing issues.\")\n        raise\n\n\ndef main():\n    rules = get_rules()\n    delete_all_rules(rules)\n    set_rules()\n    get_stream()\n\n\nif __name__ == \"__main__\":\n    main()\n"
  },
  {
    "path": "python/streams/stream_posts_sample.py",
    "content": "\"\"\"\nSampled Stream (1% Volume) - X API v2\n=====================================\nEndpoint: GET https://api.x.com/2/tweets/sample/stream\nDocs: https://developer.x.com/en/docs/twitter-api/tweets/volume-streams/api-reference/get-tweets-sample-stream\n\nAuthentication: Bearer Token (App-only)\nRequired env vars: BEARER_TOKEN\n\nNote: Returns approximately 1% of all public posts in real-time.\n\"\"\"\n\nimport os\nimport json\nfrom xdk import Client\n\nbearer_token = os.environ.get(\"BEARER_TOKEN\")\nclient = Client(bearer_token=bearer_token)\n\ndef main():\n    # Stream posts in real-time\n    for post in client.stream.posts_sample():\n        print(json.dumps(post.data, indent=4, sort_keys=True))\n\nif __name__ == \"__main__\":\n    main()\n"
  },
  {
    "path": "python/usage/get_usage.py",
    "content": "\"\"\"\nUsage Posts - X API v2\n======================\nEndpoint: GET https://api.x.com/2/usage/tweets\nDocs: https://developer.x.com/en/docs/twitter-api/usage/api-reference/get-usage-tweets\n\nAuthentication: Bearer Token (App-only)\nRequired env vars: BEARER_TOKEN\n\nReturns the number of posts read from the API.\n\"\"\"\n\nimport os\nimport json\nfrom xdk import Client\n\nbearer_token = os.environ.get(\"BEARER_TOKEN\")\nclient = Client(bearer_token=bearer_token)\n\ndef main():\n    # Get usage statistics for tweets\n    # days: Number of days to retrieve usage for (default: 7)\n    # usage_fields: Fields to include in the response (optional)\n    response = client.usage.get(days=7)\n    \n    # Access data attribute safely\n    response_data = getattr(response, 'data', None)\n    if response_data:\n        print(json.dumps(response_data, indent=4, sort_keys=True))\n    else:\n        print(json.dumps(response, indent=4, sort_keys=True))\n\nif __name__ == \"__main__\":\n    main()\n"
  },
  {
    "path": "python/users/block/get_blocking.py",
    "content": "\"\"\"\nBlocked Users Lookup - X API v2\n===============================\nEndpoint: GET https://api.x.com/2/users/:id/blocking\nDocs: https://developer.x.com/en/docs/twitter-api/users/blocks/api-reference/get-users-blocking\n\nAuthentication: OAuth 2.0 (User Context)\nRequired env vars: CLIENT_ID, CLIENT_SECRET\n\"\"\"\n\nimport os\nimport json\nfrom xdk import Client\nfrom xdk.oauth2_auth import OAuth2PKCEAuth\nfrom requests.exceptions import HTTPError\n\n# The code below sets the client ID and client secret from your environment variables\n# To set environment variables on macOS or Linux, run the export commands below from the terminal:\n# export CLIENT_ID='YOUR-CLIENT-ID'\n# export CLIENT_SECRET='YOUR-CLIENT-SECRET'\nclient_id = os.environ.get(\"CLIENT_ID\")\nclient_secret = os.environ.get(\"CLIENT_SECRET\")\n\n# Replace the following URL with your callback URL, which can be obtained from your App's auth settings.\nredirect_uri = \"https://example.com\"\n\n# Set the scopes\nscopes = [\"tweet.read\", \"users.read\", \"offline.access\", \"block.read\"]\n\ndef main():\n    # Step 1: Create PKCE instance\n    auth = OAuth2PKCEAuth(\n        client_id=client_id,\n        client_secret=client_secret,\n        redirect_uri=redirect_uri,\n        scope=scopes\n    )\n    \n    # Step 2: Get authorization URL\n    auth_url = auth.get_authorization_url()\n    print(\"Visit the following URL to authorize your App on behalf of your X handle in a browser:\")\n    print(auth_url)\n    \n    # Step 3: Handle callback\n    callback_url = input(\"Paste the full callback URL here: \")\n    \n    # Step 4: Exchange code for tokens\n    tokens = auth.fetch_token(authorization_response=callback_url)\n    access_token = tokens[\"access_token\"]\n    \n    # Step 5: Create client\n    client = Client(access_token=access_token)\n    \n    # Step 6: Get the authenticated user's ID\n    me_response = client.users.get_me()\n    user_id = me_response.data[\"id\"]\n    \n    # Step 7: Get blocked users with automatic pagination\n    # User fields are adjustable, options include:\n    # created_at, description, entities, id, location, name,\n    # pinned_tweet_id, profile_image_url, protected,\n    # public_metrics, url, username, verified, and withheld\n    all_users = []\n    try:\n        for page in client.users.get_blocking(\n            user_id,\n            max_results=100,\n            user_fields=[\"created_at\", \"description\"]\n        ):\n            # Access data attribute (model uses extra='allow' so data should be available)\n            # Use getattr with fallback in case data field is missing from response\n            page_data = getattr(page, 'data', []) or []\n            all_users.extend(page_data)\n            print(f\"Fetched {len(page_data)} users (total: {len(all_users)})\")\n        \n        print(f\"\\nTotal Blocked Users: {len(all_users)}\")\n        print(json.dumps({\"data\": all_users[:5]}, indent=4, sort_keys=True))  # Print first 5 as example\n    except HTTPError as e:\n        print(f\"Error occurred: {e}\")\n        if hasattr(e.response, 'json'):\n            try:\n                error_data = e.response.json()\n                if 'errors' in error_data:\n                    print(\"Detailed errors:\")\n                    print(json.dumps(error_data['errors'], indent=2))\n            except:\n                pass\n        raise\n\nif __name__ == \"__main__\":\n    main()\n"
  },
  {
    "path": "python/users/bookmark/create_bookmark.py",
    "content": "\"\"\"\nCreate Bookmark - X API v2\n==========================\nEndpoint: POST https://api.x.com/2/users/:id/bookmarks\nDocs: https://developer.x.com/en/docs/twitter-api/tweets/bookmarks/api-reference/post-users-id-bookmarks\n\nAuthentication: OAuth 2.0 (User Context)\nRequired env vars: CLIENT_ID, CLIENT_SECRET\n\"\"\"\n\nimport os\nimport json\nfrom xdk import Client\nfrom xdk.oauth2_auth import OAuth2PKCEAuth\n\n# The code below sets the client ID and client secret from your environment variables\n# To set environment variables on macOS or Linux, run the export commands below from the terminal:\n# export CLIENT_ID='YOUR-CLIENT-ID'\n# export CLIENT_SECRET='YOUR-CLIENT-SECRET'\nclient_id = os.environ.get(\"CLIENT_ID\")\nclient_secret = os.environ.get(\"CLIENT_SECRET\")\n\n# Replace the following URL with your callback URL, which can be obtained from your App's auth settings.\nredirect_uri = \"https://example.com\"\n\n# Set the scopes\nscopes = [\"tweet.read\", \"users.read\", \"bookmark.write\", \"offline.access\"]\n\n# Replace with a Post ID you want to Bookmark\npost_id = \"post-id-to-bookmark\"\n\ndef main():\n    # Step 1: Create PKCE instance\n    auth = OAuth2PKCEAuth(\n        client_id=client_id,\n        client_secret=client_secret,\n        redirect_uri=redirect_uri,\n        scope=scopes\n    )\n    \n    # Step 2: Get authorization URL\n    auth_url = auth.get_authorization_url()\n    print(\"Visit the following URL to authorize your App on behalf of your X handle in a browser:\")\n    print(auth_url)\n    \n    # Step 3: Handle callback\n    callback_url = input(\"Paste the full callback URL here: \")\n    \n    # Step 4: Exchange code for tokens\n    tokens = auth.fetch_token(authorization_response=callback_url)\n    access_token = tokens[\"access_token\"]\n    \n    # Step 5: Create client\n    client = Client(access_token=access_token)\n    \n    # Step 6: Get authenticated user ID\n    me_response = client.users.get_me()\n    user_id = me_response.data[\"id\"]\n    \n    # Step 7: Create bookmark\n    payload = {\"tweet_id\": post_id}\n    response = client.users.create_bookmark(user_id, body=payload)\n    \n    print(\"Response code: 200\")\n    print(json.dumps(response.data, indent=4, sort_keys=True))\n\nif __name__ == \"__main__\":\n    main()\n"
  },
  {
    "path": "python/users/bookmark/delete_bookmark.py",
    "content": "\"\"\"\nDelete Bookmark - X API v2\n==========================\nEndpoint: DELETE https://api.x.com/2/users/:id/bookmarks/:tweet_id\nDocs: https://developer.x.com/en/docs/twitter-api/tweets/bookmarks/api-reference/delete-users-id-bookmarks-tweet_id\n\nAuthentication: OAuth 2.0 (User Context)\nRequired env vars: CLIENT_ID, CLIENT_SECRET\n\"\"\"\n\nimport os\nimport json\nfrom xdk import Client\nfrom xdk.oauth2_auth import OAuth2PKCEAuth\n\n# The code below sets the client ID and client secret from your environment variables\n# To set environment variables on macOS or Linux, run the export commands below from the terminal:\n# export CLIENT_ID='YOUR-CLIENT-ID'\n# export CLIENT_SECRET='YOUR-CLIENT-SECRET'\nclient_id = os.environ.get(\"CLIENT_ID\")\nclient_secret = os.environ.get(\"CLIENT_SECRET\")\n\n# Replace the following URL with your callback URL, which can be obtained from your App's auth settings.\nredirect_uri = \"https://example.com\"\n\n# Set the scopes\nscopes = [\"tweet.read\", \"users.read\", \"bookmark.write\", \"offline.access\"]\n\n# Replace with a Post ID you want to remove Bookmark of\npost_id = \"post-id-to-unbookmark\"\n\ndef main():\n    # Step 1: Create PKCE instance\n    auth = OAuth2PKCEAuth(\n        client_id=client_id,\n        client_secret=client_secret,\n        redirect_uri=redirect_uri,\n        scope=scopes\n    )\n    \n    # Step 2: Get authorization URL\n    auth_url = auth.get_authorization_url()\n    print(\"Visit the following URL to authorize your App on behalf of your X handle in a browser:\")\n    print(auth_url)\n    \n    # Step 3: Handle callback\n    callback_url = input(\"Paste the full callback URL here: \")\n    \n    # Step 4: Exchange code for tokens\n    tokens = auth.fetch_token(authorization_response=callback_url)\n    access_token = tokens[\"access_token\"]\n    \n    # Step 5: Create client\n    client = Client(access_token=access_token)\n    \n    # Step 6: Get authenticated user ID\n    me_response = client.users.get_me()\n    user_id = me_response.data[\"id\"]\n    \n    # Step 7: Delete bookmark\n    response = client.users.delete_bookmark(user_id, post_id)\n    \n    print(\"Response code: 200\")\n    print(json.dumps(response.data, indent=4, sort_keys=True))\n\nif __name__ == \"__main__\":\n    main()\n"
  },
  {
    "path": "python/users/bookmark/get_bookmarks.py",
    "content": "\"\"\"\nBookmarks Lookup - X API v2\n===========================\nEndpoint: GET https://api.x.com/2/users/:id/bookmarks\nDocs: https://developer.x.com/en/docs/twitter-api/bookmarks/api-reference/get-users-id-bookmarks\n\nAuthentication: OAuth 2.0 (User Context)\nRequired env vars: CLIENT_ID, CLIENT_SECRET\n\"\"\"\n\nimport os\nimport json\nfrom xdk import Client\nfrom xdk.oauth2_auth import OAuth2PKCEAuth\n\n# The code below sets the client ID and client secret from your environment variables\n# To set environment variables on macOS or Linux, run the export commands below from the terminal:\n# export CLIENT_ID='YOUR-CLIENT-ID'\n# export CLIENT_SECRET='YOUR-CLIENT-SECRET'\nclient_id = os.environ.get(\"CLIENT_ID\")\nclient_secret = os.environ.get(\"CLIENT_SECRET\")\n\n# Replace the following URL with your callback URL, which can be obtained from your App's auth settings.\nredirect_uri = \"https://example.com\"\n\n# Set the scopes\nscopes = [\"bookmark.read\", \"tweet.read\", \"users.read\", \"offline.access\"]\n\ndef main():\n    # Step 1: Create PKCE instance\n    auth = OAuth2PKCEAuth(\n        client_id=client_id,\n        client_secret=client_secret,\n        redirect_uri=redirect_uri,\n        scope=scopes\n    )\n    \n    # Step 2: Get authorization URL\n    auth_url = auth.get_authorization_url()\n    print(\"Visit the following URL to authorize your App on behalf of your X handle in a browser:\")\n    print(auth_url)\n    \n    # Step 3: Handle callback\n    callback_url = input(\"Paste the full callback URL here: \")\n    \n    # Step 4: Exchange code for tokens\n    tokens = auth.fetch_token(authorization_response=callback_url)\n    access_token = tokens[\"access_token\"]\n    \n    # Step 5: Create client\n    client = Client(access_token=access_token)\n    \n    # Step 6: Get authenticated user ID\n    user_me = client.users.get_me()\n    user_id = user_me.data[\"id\"]\n    \n    # Step 7: Get bookmarks with automatic pagination\n    all_bookmarks = []\n    for page in client.users.get_bookmarks(\n        user_id,\n        max_results=100,\n        tweetfields=[\"created_at\"]\n    ):\n        all_bookmarks.extend(page.data)\n        print(f\"Fetched {len(page.data)} bookmarks (total: {len(all_bookmarks)})\")\n    \n    print(f\"\\nTotal Bookmarks: {len(all_bookmarks)}\")\n    print(json.dumps({\"data\": all_bookmarks[:5]}, indent=4, sort_keys=True))  # Print first 5 as example\n\nif __name__ == \"__main__\":\n    main()\n"
  },
  {
    "path": "python/users/follow/follow_user.py",
    "content": "\"\"\"\nFollow User - X API v2\n======================\nEndpoint: POST https://api.x.com/2/users/:id/following\nDocs: https://developer.x.com/en/docs/twitter-api/users/follows/api-reference/post-users-id-following\n\nAuthentication: OAuth 2.0 (User Context)\nRequired env vars: CLIENT_ID, CLIENT_SECRET\n\"\"\"\n\nimport os\nimport json\nfrom xdk import Client\nfrom xdk.oauth2_auth import OAuth2PKCEAuth\n\n# The code below sets the client ID and client secret from your environment variables\n# To set environment variables on macOS or Linux, run the export commands below from the terminal:\n# export CLIENT_ID='YOUR-CLIENT-ID'\n# export CLIENT_SECRET='YOUR-CLIENT-SECRET'\nclient_id = os.environ.get(\"CLIENT_ID\")\nclient_secret = os.environ.get(\"CLIENT_SECRET\")\n\n# Replace the following URL with your callback URL, which can be obtained from your App's auth settings.\nredirect_uri = \"https://example.com\"\n\n# Set the scopes\nscopes = [\"tweet.read\", \"users.read\", \"follows.write\", \"offline.access\"]\n\n# Be sure to replace user-id-to-follow with the user id you wish to follow.\n# You can find a user ID by using the user lookup endpoint\ntarget_user_id = \"user-id-to-follow\"\n\ndef main():\n    # Step 1: Create PKCE instance\n    auth = OAuth2PKCEAuth(\n        client_id=client_id,\n        client_secret=client_secret,\n        redirect_uri=redirect_uri,\n        scope=scopes\n    )\n\n    # Step 2: Get authorization URL\n    auth_url = auth.get_authorization_url()\n    print(\"Visit the following URL to authorize your App on behalf of your X handle in a browser:\")\n    print(auth_url)\n\n    # Step 3: Handle callback\n    callback_url = input(\"Paste the full callback URL here: \")\n\n    # Step 4: Exchange code for tokens\n    tokens = auth.fetch_token(authorization_response=callback_url)\n    access_token = tokens[\"access_token\"]\n\n    # Step 5: Create client\n    client = Client(access_token=access_token)\n\n    # Step 6: Get the authenticated user's ID\n    me_response = client.users.get_me()\n    user_id = me_response.data[\"id\"]\n\n    # Step 7: Follow the user\n    payload = {\"target_user_id\": target_user_id}\n    response = client.users.follow_user(user_id, body=payload)\n\n    print(\"Response code: 200\")\n    print(json.dumps(response.data, indent=4, sort_keys=True))\n\n\nif __name__ == \"__main__\":\n    main()\n"
  },
  {
    "path": "python/users/follow/get_followers.py",
    "content": "\"\"\"\nUser Followers Lookup - X API v2\n================================\nEndpoint: GET https://api.x.com/2/users/:id/followers\nDocs: https://developer.x.com/en/docs/twitter-api/users/follows/api-reference/get-users-id-followers\n\nAuthentication: Bearer Token (App-only) or OAuth (User Context)\nRequired env vars: BEARER_TOKEN\n\"\"\"\n\nimport os\nimport json\nfrom xdk import Client\n\nbearer_token = os.environ.get(\"BEARER_TOKEN\")\nclient = Client(bearer_token=bearer_token)\n\n# Replace with the user ID you want to get followers for\nuser_id = \"2244994945\"\n\ndef main():\n    # Get followers with automatic pagination\n    all_users = []\n    for page in client.users.get_followers(\n        user_id,\n        max_results=100,\n        user_fields=[\"created_at\"]\n    ):\n        # Access data attribute (model uses extra='allow' so data should be available)\n        # Use getattr with fallback in case data field is missing from response\n        page_data = getattr(page, 'data', []) or []\n        all_users.extend(page_data)\n        print(f\"Fetched {len(page_data)} users (total: {len(all_users)})\")\n    \n    print(f\"\\nTotal Followers: {len(all_users)}\")\n    print(json.dumps({\"data\": all_users[:5]}, indent=4, sort_keys=True))  # Print first 5 as example\n\nif __name__ == \"__main__\":\n    main()\n"
  },
  {
    "path": "python/users/follow/get_following.py",
    "content": "\"\"\"\nUser Following Lookup - X API v2\n================================\nEndpoint: GET https://api.x.com/2/users/:id/following\nDocs: https://developer.x.com/en/docs/twitter-api/users/follows/api-reference/get-users-id-following\n\nAuthentication: Bearer Token (App-only) or OAuth (User Context)\nRequired env vars: BEARER_TOKEN\n\"\"\"\n\nimport os\nimport json\nfrom xdk import Client\n\nbearer_token = os.environ.get(\"BEARER_TOKEN\")\nclient = Client(bearer_token=bearer_token)\n\n# Replace with the user ID you want to get following for\nuser_id = \"2244994945\"\n\ndef main():\n    # Get following with automatic pagination\n    all_users = []\n    for page in client.users.get_following(\n        user_id,\n        max_results=100,\n        user_fields=[\"created_at\"]\n    ):\n        # Access data attribute (model uses extra='allow' so data should be available)\n        # Use getattr with fallback in case data field is missing from response\n        page_data = getattr(page, 'data', []) or []\n        all_users.extend(page_data)\n        print(f\"Fetched {len(page_data)} users (total: {len(all_users)})\")\n    \n    print(f\"\\nTotal Following: {len(all_users)}\")\n    print(json.dumps({\"data\": all_users[:5]}, indent=4, sort_keys=True))  # Print first 5 as example\n\nif __name__ == \"__main__\":\n    main()\n"
  },
  {
    "path": "python/users/follow/unfollow_user.py",
    "content": "\"\"\"\nUnfollow User - X API v2\n========================\nEndpoint: DELETE https://api.x.com/2/users/:source_user_id/following/:target_user_id\nDocs: https://developer.x.com/en/docs/twitter-api/users/follows/api-reference/delete-users-source_user_id-following\n\nAuthentication: OAuth 2.0 (User Context)\nRequired env vars: CLIENT_ID, CLIENT_SECRET\n\"\"\"\n\nimport os\nimport json\nfrom xdk import Client\nfrom xdk.oauth2_auth import OAuth2PKCEAuth\n\n# The code below sets the client ID and client secret from your environment variables\n# To set environment variables on macOS or Linux, run the export commands below from the terminal:\n# export CLIENT_ID='YOUR-CLIENT-ID'\n# export CLIENT_SECRET='YOUR-CLIENT-SECRET'\nclient_id = os.environ.get(\"CLIENT_ID\")\nclient_secret = os.environ.get(\"CLIENT_SECRET\")\n\n# Replace the following URL with your callback URL, which can be obtained from your App's auth settings.\nredirect_uri = \"https://example.com\"\n\n# Set the scopes\nscopes = [\"tweet.read\", \"users.read\", \"follows.write\", \"offline.access\"]\n\n# Be sure to replace user-id-to-unfollow with the id of the user you wish to unfollow.\n# You can find a user ID by using the user lookup endpoint\ntarget_user_id = \"user-id-to-unfollow\"\n\ndef main():\n    # Step 1: Create PKCE instance\n    auth = OAuth2PKCEAuth(\n        client_id=client_id,\n        client_secret=client_secret,\n        redirect_uri=redirect_uri,\n        scope=scopes\n    )\n\n    # Step 2: Get authorization URL\n    auth_url = auth.get_authorization_url()\n    print(\"Visit the following URL to authorize your App on behalf of your X handle in a browser:\")\n    print(auth_url)\n\n    # Step 3: Handle callback\n    callback_url = input(\"Paste the full callback URL here: \")\n\n    # Step 4: Exchange code for tokens\n    tokens = auth.fetch_token(authorization_response=callback_url)\n    access_token = tokens[\"access_token\"]\n\n    # Step 5: Create client\n    client = Client(access_token=access_token)\n\n    # Step 6: Get the authenticated user's ID\n    me_response = client.users.get_me()\n    user_id = me_response.data[\"id\"]\n\n    # Step 7: Unfollow the user\n    response = client.users.unfollow_user(user_id, target_user_id)\n\n    print(\"Response code: 200\")\n    print(json.dumps(response.data, indent=4, sort_keys=True))\n\n\nif __name__ == \"__main__\":\n    main()\n"
  },
  {
    "path": "python/users/get_users_by_usernames.py",
    "content": "\"\"\"\nUser Lookup - X API v2\n======================\nEndpoint: GET https://api.x.com/2/users/by\nDocs: https://developer.x.com/en/docs/twitter-api/users/lookup/api-reference/get-users-by\n\nAuthentication: Bearer Token (App-only) or OAuth (User Context)\nRequired env vars: BEARER_TOKEN\n\"\"\"\n\nimport os\nimport json\nfrom xdk import Client\n\nbearer_token = os.environ.get(\"BEARER_TOKEN\")\nclient = Client(bearer_token=bearer_token)\n\n# Specify the usernames that you want to lookup (list, up to 100)\nusernames = [\"XDevelopers\", \"API\"]\n\ndef main():\n    # User fields are adjustable, options include:\n    # created_at, description, entities, id, location, name,\n    # pinned_tweet_id, profile_image_url, protected,\n    # public_metrics, url, username, verified, and withheld\n    response = client.users.get_by_usernames(\n        usernames=usernames,\n        user_fields=[\"description\", \"created_at\"]\n    )\n    \n    # Access data attribute safely\n    response_data = getattr(response, 'data', None)\n    if response_data:\n        print(json.dumps(response_data, indent=4, sort_keys=True))\n    else:\n        print(json.dumps(response, indent=4, sort_keys=True))\n\n\nif __name__ == \"__main__\":\n    main()\n"
  },
  {
    "path": "python/users/get_users_by_usernames_user_context.py",
    "content": "\"\"\"\nUser Lookup (User Context) - X API v2\n=====================================\nEndpoint: GET https://api.x.com/2/users/by\nDocs: https://developer.x.com/en/docs/twitter-api/users/lookup/api-reference/get-users-by\n\nAuthentication: OAuth 2.0 (User Context)\nRequired env vars: CLIENT_ID, CLIENT_SECRET\n\"\"\"\n\nimport os\nimport json\nfrom xdk import Client\nfrom xdk.oauth2_auth import OAuth2PKCEAuth\n\n# The code below sets the client ID and client secret from your environment variables\n# To set environment variables on macOS or Linux, run the export commands below from the terminal:\n# export CLIENT_ID='YOUR-CLIENT-ID'\n# export CLIENT_SECRET='YOUR-CLIENT-SECRET'\nclient_id = os.environ.get(\"CLIENT_ID\")\nclient_secret = os.environ.get(\"CLIENT_SECRET\")\n\n# Replace the following URL with your callback URL, which can be obtained from your App's auth settings.\nredirect_uri = \"https://example.com\"\n\n# Set the scopes\nscopes = [\"tweet.read\", \"users.read\", \"offline.access\"]\n\n# Specify the usernames that you want to lookup (list, up to 100)\nusernames = [\"XDevelopers\", \"API\"]\n\ndef main():\n    # Step 1: Create PKCE instance\n    auth = OAuth2PKCEAuth(\n        client_id=client_id,\n        client_secret=client_secret,\n        redirect_uri=redirect_uri,\n        scope=scopes\n    )\n    \n    # Step 2: Get authorization URL\n    auth_url = auth.get_authorization_url()\n    print(\"Visit the following URL to authorize your App on behalf of your X handle in a browser:\")\n    print(auth_url)\n    \n    # Step 3: Handle callback\n    callback_url = input(\"Paste the full callback URL here: \")\n    \n    # Step 4: Exchange code for tokens\n    tokens = auth.fetch_token(authorization_response=callback_url)\n    access_token = tokens[\"access_token\"]\n    \n    # Step 5: Create client\n    client = Client(access_token=access_token)\n    \n    # Step 6: Get users\n    # User fields are adjustable, options include:\n    # created_at, description, entities, id, location, name,\n    # pinned_tweet_id, profile_image_url, protected,\n    # public_metrics, url, username, verified, and withheld\n    response = client.users.get_by_usernames(\n        usernames=usernames,\n        user_fields=[\"created_at\", \"description\"]\n    )\n    \n    # Access data attribute safely\n    response_data = getattr(response, 'data', None)\n    if response_data:\n        print(json.dumps(response_data, indent=4, sort_keys=True))\n    else:\n        print(json.dumps(response, indent=4, sort_keys=True))\n\nif __name__ == \"__main__\":\n    main()\n"
  },
  {
    "path": "python/users/get_users_me.py",
    "content": "\"\"\"\nAuthenticated User Lookup (Me) - X API v2\n=========================================\nEndpoint: GET https://api.x.com/2/users/me\nDocs: https://developer.x.com/en/docs/twitter-api/users/lookup/api-reference/get-users-me\n\nAuthentication: OAuth 2.0 (User Context)\nRequired env vars: CLIENT_ID, CLIENT_SECRET\n\"\"\"\n\nimport os\nimport json\nfrom xdk import Client\nfrom xdk.oauth2_auth import OAuth2PKCEAuth\n\n# The code below sets the client ID and client secret from your environment variables\n# To set environment variables on macOS or Linux, run the export commands below from the terminal:\n# export CLIENT_ID='YOUR-CLIENT-ID'\n# export CLIENT_SECRET='YOUR-CLIENT-SECRET'\nclient_id = os.environ.get(\"CLIENT_ID\")\nclient_secret = os.environ.get(\"CLIENT_SECRET\")\n\n# Replace the following URL with your callback URL, which can be obtained from your App's auth settings.\nredirect_uri = \"https://example.com\"\n\n# Set the scopes\nscopes = [\"tweet.read\", \"users.read\", \"offline.access\"]\n\ndef main():\n    # Step 1: Create PKCE instance\n    auth = OAuth2PKCEAuth(\n        client_id=client_id,\n        client_secret=client_secret,\n        redirect_uri=redirect_uri,\n        scope=scopes\n    )\n    \n    # Step 2: Get authorization URL\n    auth_url = auth.get_authorization_url()\n    print(\"Visit the following URL to authorize your App on behalf of your X handle in a browser:\")\n    print(auth_url)\n    \n    # Step 3: Handle callback\n    callback_url = input(\"Paste the full callback URL here: \")\n    \n    # Step 4: Exchange code for tokens\n    tokens = auth.fetch_token(authorization_response=callback_url)\n    access_token = tokens[\"access_token\"]\n    \n    # Step 5: Create client\n    client = Client(access_token=access_token)\n    \n    # Step 6: Get authenticated user info\n    # User fields are adjustable, options include:\n    # created_at, description, entities, id, location, name,\n    # pinned_tweet_id, profile_image_url, protected,\n    # public_metrics, url, username, verified, and withheld\n    response = client.users.get_me(\n        user_fields=[\"created_at\", \"description\"]\n    )\n    \n    print(json.dumps(response.data, indent=4, sort_keys=True))\n\nif __name__ == \"__main__\":\n    main()\n"
  },
  {
    "path": "python/users/like/get_liked_posts.py",
    "content": "\"\"\"\nLiked Tweets - X API v2\n======================\nEndpoint: GET https://api.x.com/2/users/:id/liked_tweets\nDocs: https://developer.x.com/en/docs/twitter-api/tweets/likes/api-reference/get-users-id-liked_tweets\n\nAuthentication: OAuth 2.0 (User Context)\nRequired env vars: CLIENT_ID, CLIENT_SECRET\n\"\"\"\n\nimport os\nimport json\nfrom xdk import Client\nfrom xdk.oauth2_auth import OAuth2PKCEAuth\n\n# The code below sets the client ID and client secret from your environment variables\n# To set environment variables on macOS or Linux, run the export commands below from the terminal:\n# export CLIENT_ID='YOUR-CLIENT-ID'\n# export CLIENT_SECRET='YOUR-CLIENT-SECRET'\nclient_id = os.environ.get(\"CLIENT_ID\")\nclient_secret = os.environ.get(\"CLIENT_SECRET\")\n\n# Replace the following URL with your callback URL, which can be obtained from your App's auth settings.\nredirect_uri = \"https://example.com\"\n\n# Set the scopes\nscopes = [\"tweet.read\", \"users.read\", \"like.read\", \"offline.access\"]\n\ndef main():\n    # Step 1: Create PKCE instance\n    auth = OAuth2PKCEAuth(\n        client_id=client_id,\n        client_secret=client_secret,\n        redirect_uri=redirect_uri,\n        scope=scopes\n    )\n    \n    # Step 2: Get authorization URL\n    auth_url = auth.get_authorization_url()\n    print(\"Visit the following URL to authorize your App on behalf of your X handle in a browser:\")\n    print(auth_url)\n    \n    # Step 3: Handle callback\n    callback_url = input(\"Paste the full callback URL here: \")\n    \n    # Step 4: Exchange code for tokens\n    tokens = auth.fetch_token(authorization_response=callback_url)\n    access_token = tokens[\"access_token\"]\n    \n    # Step 5: Create client\n    client = Client(access_token=access_token)\n    \n    # Step 6: Get the authenticated user's ID\n    user_me = client.users.get_me()\n    user_id = user_me.data[\"id\"]\n    \n    # Step 7: Get liked tweets with automatic pagination\n    # Tweet fields are adjustable.\n    # Options include:\n    # attachments, author_id, context_annotations,\n    # conversation_id, created_at, entities, geo, id,\n    # in_reply_to_user_id, lang, non_public_metrics, organic_metrics,\n    # possibly_sensitive, promoted_metrics, public_metrics, referenced_tweets,\n    # source, text, and withheld\n    all_posts = []\n    for page in client.users.get_liked_posts(\n        user_id,\n        max_results=100,\n        tweet_fields=[\"lang\", \"author_id\"]\n    ):\n        # Access data attribute (model uses extra='allow' so data should be available)\n        # Use getattr with fallback in case data field is missing from response\n        page_data = getattr(page, 'data', []) or []\n        all_posts.extend(page_data)\n        print(f\"Fetched {len(page_data)} posts (total: {len(all_posts)})\")\n    \n    print(f\"\\nTotal Liked Tweets: {len(all_posts)}\")\n    print(json.dumps({\"data\": all_posts[:5]}, indent=4, sort_keys=True))  # Print first 5 as example\n\nif __name__ == \"__main__\":\n    main()\n"
  },
  {
    "path": "python/users/like/like_post.py",
    "content": "\"\"\"\nLike a Tweet - X API v2\n======================\nEndpoint: POST https://api.x.com/2/users/:id/likes\nDocs: https://developer.x.com/en/docs/twitter-api/tweets/likes/api-reference/post-users-id-likes\n\nAuthentication: OAuth 2.0 (User Context)\nRequired env vars: CLIENT_ID, CLIENT_SECRET\n\"\"\"\n\nimport os\nimport json\nfrom xdk import Client\nfrom xdk.oauth2_auth import OAuth2PKCEAuth\n\n# The code below sets the client ID and client secret from your environment variables\n# To set environment variables on macOS or Linux, run the export commands below from the terminal:\n# export CLIENT_ID='YOUR-CLIENT-ID'\n# export CLIENT_SECRET='YOUR-CLIENT-SECRET'\nclient_id = os.environ.get(\"CLIENT_ID\")\nclient_secret = os.environ.get(\"CLIENT_SECRET\")\n\n# Replace the following URL with your callback URL, which can be obtained from your App's auth settings.\nredirect_uri = \"https://example.com\"\n\n# Set the scopes\nscopes = [\"tweet.read\", \"tweet.write\", \"users.read\", \"offline.access\", \"like.write\"]\n\n# You can replace Tweet ID given with the Tweet ID you wish to like.\n# You can find a Tweet ID by using the Tweet lookup endpoint\npost_id = \"post-id\"\n\ndef main():\n    # Step 1: Create PKCE instance\n    auth = OAuth2PKCEAuth(\n        client_id=client_id,\n        client_secret=client_secret,\n        redirect_uri=redirect_uri,\n        scope=scopes\n    )\n    \n    # Step 2: Get authorization URL\n    auth_url = auth.get_authorization_url()\n    print(\"Visit the following URL to authorize your App on behalf of your X handle in a browser:\")\n    print(auth_url)\n    \n    # Step 3: Handle callback\n    callback_url = input(\"Paste the full callback URL here: \")\n    \n    # Step 4: Exchange code for tokens\n    tokens = auth.fetch_token(authorization_response=callback_url)\n    access_token = tokens[\"access_token\"]\n    \n    # Step 5: Create client\n    client = Client(access_token=access_token)\n    \n    # Step 6: Get the authenticated user's ID\n    user_me = client.users.get_me()\n    user_id = user_me.data[\"id\"]\n    \n    # Step 7: Like the tweet\n    payload = {\"tweet_id\": post_id}\n    response = client.users.like_post(user_id, body=payload)\n    \n    print(\"Response code: 200\")\n    print(json.dumps(response.data, indent=4, sort_keys=True))\n\nif __name__ == \"__main__\":\n    main()\n"
  },
  {
    "path": "python/users/like/unlike_post.py",
    "content": "\"\"\"\nUnlike a Tweet - X API v2\n========================\nEndpoint: DELETE https://api.x.com/2/users/:id/likes/:tweet_id\nDocs: https://developer.x.com/en/docs/twitter-api/tweets/likes/api-reference/delete-users-id-likes-tweet_id\n\nAuthentication: OAuth 2.0 (User Context)\nRequired env vars: CLIENT_ID, CLIENT_SECRET\n\"\"\"\n\nimport os\nimport json\nfrom xdk import Client\nfrom xdk.oauth2_auth import OAuth2PKCEAuth\n\n# The code below sets the client ID and client secret from your environment variables\n# To set environment variables on macOS or Linux, run the export commands below from the terminal:\n# export CLIENT_ID='YOUR-CLIENT-ID'\n# export CLIENT_SECRET='YOUR-CLIENT-SECRET'\nclient_id = os.environ.get(\"CLIENT_ID\")\nclient_secret = os.environ.get(\"CLIENT_SECRET\")\n\n# Replace the following URL with your callback URL, which can be obtained from your App's auth settings.\nredirect_uri = \"https://example.com\"\n\n# Set the scopes\nscopes = [\"tweet.read\", \"tweet.write\", \"users.read\", \"offline.access\", \"like.write\"]\n\n# You can replace Tweet ID given with the Tweet ID you wish to unlike.\n# You can find a Tweet ID by using the Tweet lookup endpoint\npost_id = \"post-id\"\n\ndef main():\n    # Step 1: Create PKCE instance\n    auth = OAuth2PKCEAuth(\n        client_id=client_id,\n        client_secret=client_secret,\n        redirect_uri=redirect_uri,\n        scope=scopes\n    )\n    \n    # Step 2: Get authorization URL\n    auth_url = auth.get_authorization_url()\n    print(\"Visit the following URL to authorize your App on behalf of your X handle in a browser:\")\n    print(auth_url)\n    \n    # Step 3: Handle callback\n    callback_url = input(\"Paste the full callback URL here: \")\n    \n    # Step 4: Exchange code for tokens\n    tokens = auth.fetch_token(authorization_response=callback_url)\n    access_token = tokens[\"access_token\"]\n    \n    # Step 5: Create client\n    client = Client(access_token=access_token)\n    \n    # Step 6: Get the authenticated user's ID\n    user_me = client.users.get_me()\n    user_id = user_me.data[\"id\"]\n    \n    # Step 7: Unlike the tweet\n    response = client.users.unlike_post(user_id, tweet_id=post_id)\n    \n    print(\"Response code: 200\")\n    print(json.dumps(response.data, indent=4, sort_keys=True))\n\nif __name__ == \"__main__\":\n    main()\n"
  },
  {
    "path": "python/users/lists/follow_list.py",
    "content": "\"\"\"\nFollow List - X API v2\n=====================\nEndpoint: POST https://api.x.com/2/users/:id/followed_lists\nDocs: https://developer.x.com/en/docs/twitter-api/lists/list-follows/api-reference/post-users-id-followed_lists\n\nAuthentication: OAuth 2.0 (User Context)\nRequired env vars: CLIENT_ID, CLIENT_SECRET\n\"\"\"\n\nimport os\nimport json\nfrom xdk import Client\nfrom xdk.oauth2_auth import OAuth2PKCEAuth\n\n# The code below sets the client ID and client secret from your environment variables\n# To set environment variables on macOS or Linux, run the export commands below from the terminal:\n# export CLIENT_ID='YOUR-CLIENT-ID'\n# export CLIENT_SECRET='YOUR-CLIENT-SECRET'\nclient_id = os.environ.get(\"CLIENT_ID\")\nclient_secret = os.environ.get(\"CLIENT_SECRET\")\n\n# Replace the following URL with your callback URL, which can be obtained from your App's auth settings.\nredirect_uri = \"https://example.com\"\n\n# Set the scopes\nscopes = [\"tweet.read\", \"users.read\", \"list.read\", \"list.write\", \"offline.access\"]\n\n# Be sure to replace your-user-id with your own user ID or one of an authenticated user\n# You can find a user ID by using the user lookup endpoint\nuser_id = \"your-user-id\"\n\n# Be sure to replace list-id-to-follow with the list id you wish to follow.\nlist_id = \"list-id-to-follow\"\n\ndef main():\n    # Step 1: Create PKCE instance\n    auth = OAuth2PKCEAuth(\n        client_id=client_id,\n        client_secret=client_secret,\n        redirect_uri=redirect_uri,\n        scope=scopes\n    )\n    \n    # Step 2: Get authorization URL\n    auth_url = auth.get_authorization_url()\n    print(\"Visit the following URL to authorize your App on behalf of your X handle in a browser:\")\n    print(auth_url)\n    \n    # Step 3: Handle callback\n    callback_url = input(\"Paste the full callback URL here: \")\n    \n    # Step 4: Exchange code for tokens\n    tokens = auth.fetch_token(authorization_response=callback_url)\n    access_token = tokens[\"access_token\"]\n    \n    # Step 5: Create client\n    client = Client(access_token=access_token)\n    \n    # Step 6: Follow the list\n    payload = {\"list_id\": list_id}\n    response = client.users.follow_list(user_id, body=payload)\n    \n    print(\"Response code: 200\")\n    print(json.dumps(response.data, indent=4, sort_keys=True))\n\nif __name__ == \"__main__\":\n    main()\n"
  },
  {
    "path": "python/users/lists/get_followed_lists.py",
    "content": "\"\"\"\nUser Followed Lists Lookup - X API v2\n======================================\nEndpoint: GET https://api.x.com/2/users/:id/followed_lists\nDocs: https://developer.x.com/en/docs/twitter-api/lists/list-follows/api-reference/get-users-id-followed_lists\n\nAuthentication: Bearer Token (App-only) or OAuth (User Context)\nRequired env vars: BEARER_TOKEN\n\"\"\"\n\nimport os\nimport json\nfrom xdk import Client\n\nbearer_token = os.environ.get(\"BEARER_TOKEN\")\nclient = Client(bearer_token=bearer_token)\n\n# You can replace the user-id with any valid User ID you wish to find what Lists they are following.\nuser_id = \"user-id\"\n\ndef main():\n    # Get user followed lists with automatic pagination\n    # List fields are adjustable, options include:\n    # created_at, description, owner_id,\n    # private, follower_count, member_count,\n    all_lists = []\n    for page in client.users.get_followed_lists(\n        user_id,\n        max_results=100,\n        list_fields=[\"created_at\", \"follower_count\"]\n    ):\n        # Access data attribute (model uses extra='allow' so data should be available)\n        # Use getattr with fallback in case data field is missing from response\n        page_data = getattr(page, 'data', []) or []\n        all_lists.extend(page_data)\n        print(f\"Fetched {len(page_data)} lists (total: {len(all_lists)})\")\n    \n    print(f\"\\nTotal Followed Lists: {len(all_lists)}\")\n    print(json.dumps({\"data\": all_lists[:5]}, indent=4, sort_keys=True))  # Print first 5 as example\n\nif __name__ == \"__main__\":\n    main()\n"
  },
  {
    "path": "python/users/lists/get_list_memberships.py",
    "content": "\"\"\"\nUser List Memberships Lookup - X API v2\n=======================================\nEndpoint: GET https://api.x.com/2/users/:id/list_memberships\nDocs: https://developer.x.com/en/docs/twitter-api/lists/list-members/api-reference/get-users-id-list_memberships\n\nAuthentication: Bearer Token (App-only) or OAuth (User Context)\nRequired env vars: BEARER_TOKEN\n\"\"\"\n\nimport os\nimport json\nfrom xdk import Client\n\nbearer_token = os.environ.get(\"BEARER_TOKEN\")\nclient = Client(bearer_token=bearer_token)\n\n# You can replace the user-id with any valid User ID you wish to find what Lists they are members of.\nuser_id = \"user-id\"\n\ndef main():\n    # Get user list memberships with automatic pagination\n    # List fields are adjustable, options include:\n    # created_at, description, owner_id,\n    # private, follower_count, member_count,\n    all_lists = []\n    for page in client.users.get_list_memberships(\n        user_id,\n        max_results=100,\n        list_fields=[\"created_at\", \"follower_count\"]\n    ):\n        # Access data attribute (model uses extra='allow' so data should be available)\n        # Use getattr with fallback in case data field is missing from response\n        page_data = getattr(page, 'data', []) or []\n        all_lists.extend(page_data)\n        print(f\"Fetched {len(page_data)} lists (total: {len(all_lists)})\")\n    \n    print(f\"\\nTotal List Memberships: {len(all_lists)}\")\n    print(json.dumps({\"data\": all_lists[:5]}, indent=4, sort_keys=True))  # Print first 5 as example\n\nif __name__ == \"__main__\":\n    main()\n"
  },
  {
    "path": "python/users/lists/get_owned_lists.py",
    "content": "\"\"\"\nUser Owned Lists Lookup - X API v2\n===================================\nEndpoint: GET https://api.x.com/2/users/:id/owned_lists\nDocs: https://developer.x.com/en/docs/twitter-api/lists/list-lookup/api-reference/get-users-id-owned_lists\n\nAuthentication: Bearer Token (App-only) or OAuth (User Context)\nRequired env vars: BEARER_TOKEN\n\"\"\"\n\nimport os\nimport json\nfrom xdk import Client\n\nbearer_token = os.environ.get(\"BEARER_TOKEN\")\nclient = Client(bearer_token=bearer_token)\n\n# You can replace user-id with any valid User ID to see if they own any Lists.\nuser_id = \"user-id\"\n\ndef main():\n    # Get user owned lists with automatic pagination\n    # List fields are adjustable, options include:\n    # created_at, description, owner_id,\n    # private, follower_count, member_count,\n    all_lists = []\n    for page in client.users.get_owned_lists(\n        user_id,\n        max_results=100,\n        list_fields=[\"created_at\", \"follower_count\"]\n    ):\n        # Access data attribute (model uses extra='allow' so data should be available)\n        # Use getattr with fallback in case data field is missing from response\n        page_data = getattr(page, 'data', []) or []\n        all_lists.extend(page_data)\n        print(f\"Fetched {len(page_data)} lists (total: {len(all_lists)})\")\n    \n    print(f\"\\nTotal Owned Lists: {len(all_lists)}\")\n    print(json.dumps({\"data\": all_lists[:5]}, indent=4, sort_keys=True))  # Print first 5 as example\n\nif __name__ == \"__main__\":\n    main()\n"
  },
  {
    "path": "python/users/lists/get_pinned_lists.py",
    "content": "\"\"\"\nPinned Lists Lookup - X API v2\n==============================\nEndpoint: GET https://api.x.com/2/users/:id/pinned_lists\nDocs: https://developer.x.com/en/docs/twitter-api/lists/pinned-lists/api-reference/get-users-id-pinned_lists\n\nAuthentication: OAuth 2.0 (User Context)\nRequired env vars: CLIENT_ID, CLIENT_SECRET\n\"\"\"\n\nimport os\nimport json\nfrom xdk import Client\nfrom xdk.oauth2_auth import OAuth2PKCEAuth\n\n# The code below sets the client ID and client secret from your environment variables\n# To set environment variables on macOS or Linux, run the export commands below from the terminal:\n# export CLIENT_ID='YOUR-CLIENT-ID'\n# export CLIENT_SECRET='YOUR-CLIENT-SECRET'\nclient_id = os.environ.get(\"CLIENT_ID\")\nclient_secret = os.environ.get(\"CLIENT_SECRET\")\n\n# Replace the following URL with your callback URL, which can be obtained from your App's auth settings.\nredirect_uri = \"https://example.com\"\n\n# Set the scopes\nscopes = [\"tweet.read\", \"users.read\", \"list.read\", \"offline.access\"]\n\n# Be sure to replace your-user-id with your own user ID or one of an authenticated user\n# You can find a user ID by using the user lookup endpoint\nuser_id = \"your-user-id\"\n\ndef main():\n    # Step 1: Create PKCE instance\n    auth = OAuth2PKCEAuth(\n        client_id=client_id,\n        client_secret=client_secret,\n        redirect_uri=redirect_uri,\n        scope=scopes\n    )\n    \n    # Step 2: Get authorization URL\n    auth_url = auth.get_authorization_url()\n    print(\"Visit the following URL to authorize your App on behalf of your X handle in a browser:\")\n    print(auth_url)\n    \n    # Step 3: Handle callback\n    callback_url = input(\"Paste the full callback URL here: \")\n    \n    # Step 4: Exchange code for tokens\n    tokens = auth.fetch_token(authorization_response=callback_url)\n    access_token = tokens[\"access_token\"]\n    \n    # Step 5: Create client\n    client = Client(access_token=access_token)\n    \n    # Step 6: Get pinned lists\n    # List fields are adjustable, options include:\n    # created_at, description, owner_id,\n    # private, follower_count, member_count,\n    response = client.users.get_pinned_lists(\n        user_id,\n        list_fields=[\"created_at\", \"description\", \"private\"]\n    )\n    \n    # Access data attribute (model uses extra='allow' so data should be available)\n    response_data = getattr(response, 'data', None)\n    if response_data is None:\n        # Try accessing via model_dump if data attribute doesn't exist\n        response_dict = response.model_dump() if hasattr(response, 'model_dump') else {}\n        response_data = response_dict.get('data', response_dict)\n    \n    print(f\"Total Pinned Lists: {len(response_data) if isinstance(response_data, list) else 1}\")\n    print(json.dumps(response_data, indent=4, sort_keys=True))\n\nif __name__ == \"__main__\":\n    main()\n"
  },
  {
    "path": "python/users/lists/pin_list.py",
    "content": "\"\"\"\nPin List - X API v2\n==================\nEndpoint: POST https://api.x.com/2/users/:id/pinned_lists\nDocs: https://developer.x.com/en/docs/twitter-api/lists/pinned-lists/api-reference/post-users-id-pinned_lists\n\nAuthentication: OAuth 2.0 (User Context)\nRequired env vars: CLIENT_ID, CLIENT_SECRET\n\"\"\"\n\nimport os\nimport json\nfrom xdk import Client\nfrom xdk.oauth2_auth import OAuth2PKCEAuth\n\n# The code below sets the client ID and client secret from your environment variables\n# To set environment variables on macOS or Linux, run the export commands below from the terminal:\n# export CLIENT_ID='YOUR-CLIENT-ID'\n# export CLIENT_SECRET='YOUR-CLIENT-SECRET'\nclient_id = os.environ.get(\"CLIENT_ID\")\nclient_secret = os.environ.get(\"CLIENT_SECRET\")\n\n# Replace the following URL with your callback URL, which can be obtained from your App's auth settings.\nredirect_uri = \"https://example.com\"\n\n# Set the scopes\nscopes = [\"tweet.read\", \"users.read\", \"list.read\", \"list.write\", \"offline.access\"]\n\n# Be sure to replace your-user-id with your own user ID or one of an authenticated user\n# You can find a user ID by using the user lookup endpoint\nuser_id = \"your-user-id\"\n\n# Be sure to replace list-id-to-pin with the list id you wish to pin.\nlist_id = \"list-id-to-pin\"\n\ndef main():\n    # Step 1: Create PKCE instance\n    auth = OAuth2PKCEAuth(\n        client_id=client_id,\n        client_secret=client_secret,\n        redirect_uri=redirect_uri,\n        scope=scopes\n    )\n    \n    # Step 2: Get authorization URL\n    auth_url = auth.get_authorization_url()\n    print(\"Visit the following URL to authorize your App on behalf of your X handle in a browser:\")\n    print(auth_url)\n    \n    # Step 3: Handle callback\n    callback_url = input(\"Paste the full callback URL here: \")\n    \n    # Step 4: Exchange code for tokens\n    tokens = auth.fetch_token(authorization_response=callback_url)\n    access_token = tokens[\"access_token\"]\n    \n    # Step 5: Create client\n    client = Client(access_token=access_token)\n    \n    # Step 6: Pin the list\n    payload = {\"list_id\": list_id}\n    response = client.users.pin_list(user_id, body=payload)\n    \n    print(\"Response code: 200\")\n    print(json.dumps(response.data, indent=4, sort_keys=True))\n\nif __name__ == \"__main__\":\n    main()\n"
  },
  {
    "path": "python/users/lists/unfollow_list.py",
    "content": "\"\"\"\nUnfollow List - X API v2\n========================\nEndpoint: DELETE https://api.x.com/2/users/:id/followed_lists/:list_id\nDocs: https://developer.x.com/en/docs/twitter-api/lists/list-follows/api-reference/delete-users-id-followed_lists-list_id\n\nAuthentication: OAuth 2.0 (User Context)\nRequired env vars: CLIENT_ID, CLIENT_SECRET\n\"\"\"\n\nimport os\nimport json\nfrom xdk import Client\nfrom xdk.oauth2_auth import OAuth2PKCEAuth\n\n# The code below sets the client ID and client secret from your environment variables\n# To set environment variables on macOS or Linux, run the export commands below from the terminal:\n# export CLIENT_ID='YOUR-CLIENT-ID'\n# export CLIENT_SECRET='YOUR-CLIENT-SECRET'\nclient_id = os.environ.get(\"CLIENT_ID\")\nclient_secret = os.environ.get(\"CLIENT_SECRET\")\n\n# Replace the following URL with your callback URL, which can be obtained from your App's auth settings.\nredirect_uri = \"https://example.com\"\n\n# Set the scopes\nscopes = [\"tweet.read\", \"users.read\", \"list.read\", \"list.write\", \"offline.access\"]\n\n# Be sure to replace your-user-id with your own user ID or one of an authenticated user\n# You can find a user ID by using the user lookup endpoint\nuser_id = \"your-user-id\"\n\n# Be sure to replace list-id-to-unfollow with the id of the list you wish to unfollow.\nlist_id = \"list-id-to-unfollow\"\n\ndef main():\n    # Step 1: Create PKCE instance\n    auth = OAuth2PKCEAuth(\n        client_id=client_id,\n        client_secret=client_secret,\n        redirect_uri=redirect_uri,\n        scope=scopes\n    )\n    \n    # Step 2: Get authorization URL\n    auth_url = auth.get_authorization_url()\n    print(\"Visit the following URL to authorize your App on behalf of your X handle in a browser:\")\n    print(auth_url)\n    \n    # Step 3: Handle callback\n    callback_url = input(\"Paste the full callback URL here: \")\n    \n    # Step 4: Exchange code for tokens\n    tokens = auth.fetch_token(authorization_response=callback_url)\n    access_token = tokens[\"access_token\"]\n    \n    # Step 5: Create client\n    client = Client(access_token=access_token)\n    \n    # Step 6: Unfollow the list\n    response = client.users.unfollow_list(user_id, list_id)\n    \n    print(\"Response code: 200\")\n    print(json.dumps(response.data, indent=4, sort_keys=True))\n\nif __name__ == \"__main__\":\n    main()\n"
  },
  {
    "path": "python/users/lists/unpin_list.py",
    "content": "\"\"\"\nUnpin List - X API v2\n=====================\nEndpoint: DELETE https://api.x.com/2/users/:id/pinned_lists/:list_id\nDocs: https://developer.x.com/en/docs/twitter-api/lists/pinned-lists/api-reference/delete-users-id-pinned_lists-list_id\n\nAuthentication: OAuth 2.0 (User Context)\nRequired env vars: CLIENT_ID, CLIENT_SECRET\n\"\"\"\n\nimport os\nimport json\nfrom xdk import Client\nfrom xdk.oauth2_auth import OAuth2PKCEAuth\n\n# The code below sets the client ID and client secret from your environment variables\n# To set environment variables on macOS or Linux, run the export commands below from the terminal:\n# export CLIENT_ID='YOUR-CLIENT-ID'\n# export CLIENT_SECRET='YOUR-CLIENT-SECRET'\nclient_id = os.environ.get(\"CLIENT_ID\")\nclient_secret = os.environ.get(\"CLIENT_SECRET\")\n\n# Replace the following URL with your callback URL, which can be obtained from your App's auth settings.\nredirect_uri = \"https://example.com\"\n\n# Set the scopes\nscopes = [\"tweet.read\", \"users.read\", \"list.read\", \"list.write\", \"offline.access\"]\n\n# Be sure to replace your-user-id with your own user ID or one of an authenticated user\n# You can find a user ID by using the user lookup endpoint\nuser_id = \"your-user-id\"\n\n# Be sure to replace list-id-to-unpin with the id of the list you wish to unpin.\nlist_id = \"list-id-to-unpin\"\n\ndef main():\n    # Step 1: Create PKCE instance\n    auth = OAuth2PKCEAuth(\n        client_id=client_id,\n        client_secret=client_secret,\n        redirect_uri=redirect_uri,\n        scope=scopes\n    )\n    \n    # Step 2: Get authorization URL\n    auth_url = auth.get_authorization_url()\n    print(\"Visit the following URL to authorize your App on behalf of your X handle in a browser:\")\n    print(auth_url)\n    \n    # Step 3: Handle callback\n    callback_url = input(\"Paste the full callback URL here: \")\n    \n    # Step 4: Exchange code for tokens\n    tokens = auth.fetch_token(authorization_response=callback_url)\n    access_token = tokens[\"access_token\"]\n    \n    # Step 5: Create client\n    client = Client(access_token=access_token)\n    \n    # Step 6: Unpin the list\n    response = client.users.unpin_list(user_id, list_id)\n    \n    print(\"Response code: 200\")\n    print(json.dumps(response.data, indent=4, sort_keys=True))\n\nif __name__ == \"__main__\":\n    main()\n"
  },
  {
    "path": "python/users/mute/get_muting.py",
    "content": "\"\"\"\nMuted Users Lookup - X API v2\n=============================\nEndpoint: GET https://api.x.com/2/users/:id/muting\nDocs: https://developer.x.com/en/docs/twitter-api/users/mutes/api-reference/get-users-muting\n\nAuthentication: OAuth 2.0 (User Context)\nRequired env vars: CLIENT_ID, CLIENT_SECRET\n\"\"\"\n\nimport os\nimport json\nfrom xdk import Client\nfrom xdk.oauth2_auth import OAuth2PKCEAuth\nfrom requests.exceptions import HTTPError\n\n# The code below sets the client ID and client secret from your environment variables\n# To set environment variables on macOS or Linux, run the export commands below from the terminal:\n# export CLIENT_ID='YOUR-CLIENT-ID'\n# export CLIENT_SECRET='YOUR-CLIENT-SECRET'\nclient_id = os.environ.get(\"CLIENT_ID\")\nclient_secret = os.environ.get(\"CLIENT_SECRET\")\n\n# Replace the following URL with your callback URL, which can be obtained from your App's auth settings.\nredirect_uri = \"https://example.com\"\n\n# Set the scopes\nscopes = [\"tweet.read\", \"users.read\", \"offline.access\", \"mute.read\"]\n\ndef main():\n    # Step 1: Create PKCE instance\n    auth = OAuth2PKCEAuth(\n        client_id=client_id,\n        client_secret=client_secret,\n        redirect_uri=redirect_uri,\n        scope=scopes\n    )\n    \n    # Step 2: Get authorization URL\n    auth_url = auth.get_authorization_url()\n    print(\"Visit the following URL to authorize your App on behalf of your X handle in a browser:\")\n    print(auth_url)\n    \n    # Step 3: Handle callback\n    callback_url = input(\"Paste the full callback URL here: \")\n    \n    # Step 4: Exchange code for tokens\n    tokens = auth.fetch_token(authorization_response=callback_url)\n    access_token = tokens[\"access_token\"]\n    \n    # Step 5: Create client\n    client = Client(access_token=access_token)\n    \n    # Step 6: Get the authenticated user's ID\n    me_response = client.users.get_me()\n    user_id = me_response.data[\"id\"]\n    \n    # Step 7: Get muted users with automatic pagination\n    # User fields are adjustable, options include:\n    # created_at, description, entities, id, location, name,\n    # pinned_tweet_id, profile_image_url, protected,\n    # public_metrics, url, username, verified, and withheld\n    all_users = []\n    try:\n        for page in client.users.get_muting(\n            user_id,\n            max_results=100,\n            user_fields=[\"created_at\", \"description\"]\n        ):\n            # Access data attribute (model uses extra='allow' so data should be available)\n            # Use getattr with fallback in case data field is missing from response\n            page_data = getattr(page, 'data', []) or []\n            all_users.extend(page_data)\n            print(f\"Fetched {len(page_data)} users (total: {len(all_users)})\")\n        \n        print(f\"\\nTotal Muted Users: {len(all_users)}\")\n        print(json.dumps({\"data\": all_users[:5]}, indent=4, sort_keys=True))  # Print first 5 as example\n    except HTTPError as e:\n        print(f\"Error occurred: {e}\")\n        if hasattr(e.response, 'json'):\n            try:\n                error_data = e.response.json()\n                if 'errors' in error_data:\n                    print(\"Detailed errors:\")\n                    print(json.dumps(error_data['errors'], indent=2))\n            except:\n                pass\n        raise\n\nif __name__ == \"__main__\":\n    main()"
  },
  {
    "path": "python/users/mute/mute_user.py",
    "content": "\"\"\"\nMute User - X API v2\n====================\nEndpoint: POST https://api.x.com/2/users/:id/muting\nDocs: https://developer.x.com/en/docs/twitter-api/users/mutes/api-reference/post-users-user_id-muting\n\nAuthentication: OAuth 2.0 (User Context)\nRequired env vars: CLIENT_ID, CLIENT_SECRET\n\"\"\"\n\nimport os\nimport json\nfrom xdk import Client\nfrom xdk.oauth2_auth import OAuth2PKCEAuth\n\n# The code below sets the client ID and client secret from your environment variables\n# To set environment variables on macOS or Linux, run the export commands below from the terminal:\n# export CLIENT_ID='YOUR-CLIENT-ID'\n# export CLIENT_SECRET='YOUR-CLIENT-SECRET'\nclient_id = os.environ.get(\"CLIENT_ID\")\nclient_secret = os.environ.get(\"CLIENT_SECRET\")\n\n# Replace the following URL with your callback URL, which can be obtained from your App's auth settings.\nredirect_uri = \"https://example.com\"\n\n# Set the scopes\nscopes = [\"tweet.read\", \"users.read\", \"tweet.write\", \"offline.access\", \"mute.write\"]\n\n# Be sure to replace your-user-id with your own user ID or one of an authenticated user\n# You can find a user ID by using the user lookup endpoint\nuser_id = \"your-user-id\"\n\n# Be sure to replace id-to-mute with the user id you wish to mute.\ntarget_user_id = \"id-to-mute\"\n\ndef main():\n    # Step 1: Create PKCE instance\n    auth = OAuth2PKCEAuth(\n        client_id=client_id,\n        client_secret=client_secret,\n        redirect_uri=redirect_uri,\n        scope=scopes\n    )\n    \n    # Step 2: Get authorization URL\n    auth_url = auth.get_authorization_url()\n    print(\"Visit the following URL to authorize your App on behalf of your X handle in a browser:\")\n    print(auth_url)\n    \n    # Step 3: Handle callback\n    callback_url = input(\"Paste the full callback URL here: \")\n    \n    # Step 4: Exchange code for tokens\n    tokens = auth.fetch_token(authorization_response=callback_url)\n    access_token = tokens[\"access_token\"]\n    \n    # Step 5: Create client\n    client = Client(access_token=access_token)\n    \n    # Step 6: Mute the user\n    payload = {\"target_user_id\": target_user_id}\n    response = client.users.mute_user(user_id, body=payload)\n    \n    print(\"Response code: 200\")\n    print(json.dumps(response.data, indent=4, sort_keys=True))\n\nif __name__ == \"__main__\":\n    main()\n"
  },
  {
    "path": "python/users/mute/unmute_user.py",
    "content": "\"\"\"\nUnmute User - X API v2\n======================\nEndpoint: DELETE https://api.x.com/2/users/:source_user_id/muting/:target_user_id\nDocs: https://developer.x.com/en/docs/twitter-api/users/mutes/api-reference/delete-users-user_id-muting\n\nAuthentication: OAuth 2.0 (User Context)\nRequired env vars: CLIENT_ID, CLIENT_SECRET\n\"\"\"\n\nimport os\nimport json\nfrom xdk import Client\nfrom xdk.oauth2_auth import OAuth2PKCEAuth\n\n# The code below sets the client ID and client secret from your environment variables\n# To set environment variables on macOS or Linux, run the export commands below from the terminal:\n# export CLIENT_ID='YOUR-CLIENT-ID'\n# export CLIENT_SECRET='YOUR-CLIENT-SECRET'\nclient_id = os.environ.get(\"CLIENT_ID\")\nclient_secret = os.environ.get(\"CLIENT_SECRET\")\n\n# Replace the following URL with your callback URL, which can be obtained from your App's auth settings.\nredirect_uri = \"https://example.com\"\n\n# Set the scopes\nscopes = [\"tweet.read\", \"users.read\", \"tweet.write\", \"offline.access\", \"mute.write\"]\n\n# Be sure to replace your-user-id with your own user ID or one of an authenticated user\n# You can find a user ID by using the user lookup endpoint\nuser_id = \"your-user-id\"\n\n# Be sure to replace id-to-unmute with the id of the user you wish to unmute.\n# You can find a user ID by using the user lookup endpoint\ntarget_user_id = \"id-to-unmute\"\n\ndef main():\n    # Step 1: Create PKCE instance\n    auth = OAuth2PKCEAuth(\n        client_id=client_id,\n        client_secret=client_secret,\n        redirect_uri=redirect_uri,\n        scope=scopes\n    )\n    \n    # Step 2: Get authorization URL\n    auth_url = auth.get_authorization_url()\n    print(\"Visit the following URL to authorize your App on behalf of your X handle in a browser:\")\n    print(auth_url)\n    \n    # Step 3: Handle callback\n    callback_url = input(\"Paste the full callback URL here: \")\n    \n    # Step 4: Exchange code for tokens\n    tokens = auth.fetch_token(authorization_response=callback_url)\n    access_token = tokens[\"access_token\"]\n    \n    # Step 5: Create client\n    client = Client(access_token=access_token)\n    \n    # Step 6: Unmute the user\n    response = client.users.unmute_user(user_id, target_user_id)\n    \n    print(\"Response code: 200\")\n    print(json.dumps(response.data, indent=4, sort_keys=True))\n\nif __name__ == \"__main__\":\n    main()\n"
  },
  {
    "path": "python/users/repost/get_reposts_of_me.py",
    "content": "\"\"\"\nReposts of Me - X API v2\n=========================\nEndpoint: GET https://api.x.com/2/users/reposts_of_me\nDocs: https://docs.x.com/x-api/users/get-reposts-of-me\n\nAuthentication: OAuth 2.0 (User Context)\nRequired env vars: CLIENT_ID, CLIENT_SECRET\n\nNote: Returns posts from the authenticated user's timeline that have been reposted.\n\"\"\"\n\nimport os\nimport json\nfrom xdk import Client\nfrom xdk.oauth2_auth import OAuth2PKCEAuth\n\n# The code below sets the client ID and client secret from your environment variables\n# To set environment variables on macOS or Linux, run the export commands below from the terminal:\n# export CLIENT_ID='YOUR-CLIENT-ID'\n# export CLIENT_SECRET='YOUR-CLIENT-SECRET'\nclient_id = os.environ.get(\"CLIENT_ID\")\nclient_secret = os.environ.get(\"CLIENT_SECRET\")\n\n# Replace the following URL with your callback URL, which can be obtained from your App's auth settings.\nredirect_uri = \"https://example.com\"\n\n# Set the scopes\nscopes = [\"tweet.read\", \"users.read\", \"offline.access\"]\n\ndef main():\n    # Step 1: Create PKCE instance\n    auth = OAuth2PKCEAuth(\n        client_id=client_id,\n        client_secret=client_secret,\n        redirect_uri=redirect_uri,\n        scope=scopes\n    )\n\n    # Step 2: Get authorization URL\n    auth_url = auth.get_authorization_url()\n    print(\"Visit the following URL to authorize your App on behalf of your X handle in a browser:\")\n    print(auth_url)\n\n    # Step 3: Handle callback\n    callback_url = input(\"Paste the full callback URL here: \")\n\n    # Step 4: Exchange code for tokens\n    tokens = auth.fetch_token(authorization_response=callback_url)\n    access_token = tokens[\"access_token\"]\n\n    # Step 5: Create client\n    client = Client(access_token=access_token)\n\n    # Step 6: Get the authenticated user's posts that have been reposted\n    # Post fields are adjustable. Options include:\n    # attachments, author_id, context_annotations, conversation_id,\n    # created_at, entities, geo, id, in_reply_to_user_id, lang,\n    # non_public_metrics, organic_metrics, possibly_sensitive,\n    # promoted_metrics, public_metrics, referenced_tweets,\n    # source, text, and withheld\n    all_posts = []\n    for page in client.users.get_reposts_of_me(\n        max_results=100,\n        tweet_fields=[\"created_at\", \"public_metrics\"]\n    ):\n        # Access data attribute (model uses extra='allow' so data should be available)\n        # Use getattr with fallback in case data field is missing from response\n        page_data = getattr(page, 'data', []) or []\n        all_posts.extend(page_data)\n        print(f\"Fetched {len(page_data)} posts (total: {len(all_posts)})\")\n\n    print(f\"\\nTotal Reposted Posts: {len(all_posts)}\")\n    print(json.dumps({\"data\": all_posts[:5]}, indent=4, sort_keys=True))  # Print first 5 as example\n\n\nif __name__ == \"__main__\":\n    main()\n"
  },
  {
    "path": "python/users/repost/repost_post.py",
    "content": "\"\"\"\nRetweet (Repost) - X API v2\n===========================\nEndpoint: POST https://api.x.com/2/users/:id/retweets\nDocs: https://developer.x.com/en/docs/twitter-api/tweets/retweets/api-reference/post-users-id-retweets\n\nAuthentication: OAuth 2.0 (User Context)\nRequired env vars: CLIENT_ID, CLIENT_SECRET\n\"\"\"\n\nimport os\nimport json\nfrom xdk import Client\nfrom xdk.oauth2_auth import OAuth2PKCEAuth\n\n# The code below sets the client ID and client secret from your environment variables\n# To set environment variables on macOS or Linux, run the export commands below from the terminal:\n# export CLIENT_ID='YOUR-CLIENT-ID'\n# export CLIENT_SECRET='YOUR-CLIENT-SECRET'\nclient_id = os.environ.get(\"CLIENT_ID\")\nclient_secret = os.environ.get(\"CLIENT_SECRET\")\n\n# Replace the following URL with your callback URL, which can be obtained from your App's auth settings.\nredirect_uri = \"https://example.com\"\n\n# Set the scopes\nscopes = [\"tweet.read\", \"tweet.write\", \"users.read\", \"offline.access\"]\n\n# You can replace the given Tweet ID with the Tweet ID you want to Retweet\n# You can find a Tweet ID by using the Tweet lookup endpoint\npost_id = \"post-id\"\n\ndef main():\n    # Step 1: Create PKCE instance\n    auth = OAuth2PKCEAuth(\n        client_id=client_id,\n        client_secret=client_secret,\n        redirect_uri=redirect_uri,\n        scope=scopes\n    )\n    \n    # Step 2: Get authorization URL\n    auth_url = auth.get_authorization_url()\n    print(\"Visit the following URL to authorize your App on behalf of your X handle in a browser:\")\n    print(auth_url)\n    \n    # Step 3: Handle callback\n    callback_url = input(\"Paste the full callback URL here: \")\n    \n    # Step 4: Exchange code for tokens\n    tokens = auth.fetch_token(authorization_response=callback_url)\n    access_token = tokens[\"access_token\"]\n    \n    # Step 5: Create client\n    client = Client(access_token=access_token)\n    \n    # Step 6: Get the authenticated user's ID\n    user_me = client.users.get_me()\n    user_id = user_me.data[\"id\"]\n    \n    # Step 7: Retweet the tweet\n    payload = {\"tweet_id\": post_id}\n    response = client.users.repost_post(user_id, body=payload)\n    \n    print(\"Response code: 200\")\n    print(json.dumps(response.data, indent=4, sort_keys=True))\n\nif __name__ == \"__main__\":\n    main()\n"
  },
  {
    "path": "python/users/repost/unrepost_post.py",
    "content": "\"\"\"\nUndo Retweet (Unrepost) - X API v2\n==================================\nEndpoint: DELETE https://api.x.com/2/users/:id/retweets/:source_tweet_id\nDocs: https://developer.x.com/en/docs/twitter-api/tweets/retweets/api-reference/delete-users-id-retweets-tweet_id\n\nAuthentication: OAuth 2.0 (User Context)\nRequired env vars: CLIENT_ID, CLIENT_SECRET\n\"\"\"\n\nimport os\nimport json\nfrom xdk import Client\nfrom xdk.oauth2_auth import OAuth2PKCEAuth\n\n# The code below sets the client ID and client secret from your environment variables\n# To set environment variables on macOS or Linux, run the export commands below from the terminal:\n# export CLIENT_ID='YOUR-CLIENT-ID'\n# export CLIENT_SECRET='YOUR-CLIENT-SECRET'\nclient_id = os.environ.get(\"CLIENT_ID\")\nclient_secret = os.environ.get(\"CLIENT_SECRET\")\n\n# Replace the following URL with your callback URL, which can be obtained from your App's auth settings.\nredirect_uri = \"https://example.com\"\n\n# Set the scopes\nscopes = [\"tweet.read\", \"tweet.write\", \"users.read\", \"offline.access\"]\n\n# You can replace the given Tweet ID with the Tweet ID you want to undo retweet for\n# You can find a Tweet ID by using the Tweet lookup endpoint\nsource_post_id = \"post-id\"\n\ndef main():\n    # Step 1: Create PKCE instance\n    auth = OAuth2PKCEAuth(\n        client_id=client_id,\n        client_secret=client_secret,\n        redirect_uri=redirect_uri,\n        scope=scopes\n    )\n    \n    # Step 2: Get authorization URL\n    auth_url = auth.get_authorization_url()\n    print(\"Visit the following URL to authorize your App on behalf of your X handle in a browser:\")\n    print(auth_url)\n    \n    # Step 3: Handle callback\n    callback_url = input(\"Paste the full callback URL here: \")\n    \n    # Step 4: Exchange code for tokens\n    tokens = auth.fetch_token(authorization_response=callback_url)\n    access_token = tokens[\"access_token\"]\n    \n    # Step 5: Create client\n    client = Client(access_token=access_token)\n    \n    # Step 6: Get the authenticated user's ID\n    user_me = client.users.get_me()\n    user_id = user_me.data[\"id\"]\n    \n    # Step 7: Undo retweet\n    response = client.users.unrepost_post(user_id, source_tweet_id=source_post_id)\n    \n    print(\"Response code: 200\")\n    print(json.dumps(response.data, indent=4, sort_keys=True))\n\nif __name__ == \"__main__\":\n    main()\n"
  },
  {
    "path": "python/users/timeline/get_home_timeline.py",
    "content": "\"\"\"\nReverse Chronological Home Timeline - X API v2\n==============================================\nEndpoint: GET https://api.x.com/2/users/:id/timelines/reverse_chronological\nDocs: https://developer.x.com/en/docs/twitter-api/tweets/timelines/api-reference/get-users-id-reverse-chronological-timeline\n\nAuthentication: OAuth 2.0 (User Context)\nRequired env vars: CLIENT_ID, CLIENT_SECRET\n\"\"\"\n\nimport os\nimport json\nfrom xdk import Client\nfrom xdk.oauth2_auth import OAuth2PKCEAuth\n\n# The code below sets the client ID and client secret from your environment variables\n# To set environment variables on macOS or Linux, run the export commands below from the terminal:\n# export CLIENT_ID='YOUR-CLIENT-ID'\n# export CLIENT_SECRET='YOUR-CLIENT-SECRET'\nclient_id = os.environ.get(\"CLIENT_ID\")\nclient_secret = os.environ.get(\"CLIENT_SECRET\")\n\n# Replace the following URL with your callback URL, which can be obtained from your App's auth settings.\nredirect_uri = \"https://example.com\"\n\n# Set the scopes\nscopes = [\"tweet.read\", \"users.read\", \"offline.access\"]\n\ndef main():\n    # Step 1: Create PKCE instance\n    auth = OAuth2PKCEAuth(\n        client_id=client_id,\n        client_secret=client_secret,\n        redirect_uri=redirect_uri,\n        scope=scopes\n    )\n    \n    # Step 2: Get authorization URL\n    auth_url = auth.get_authorization_url()\n    print(\"Visit the following URL to authorize your App on behalf of your X handle in a browser:\")\n    print(auth_url)\n    \n    # Step 3: Handle callback\n    callback_url = input(\"Paste the full callback URL here: \")\n    \n    # Step 4: Exchange code for tokens\n    tokens = auth.fetch_token(authorization_response=callback_url)\n    access_token = tokens[\"access_token\"]\n    \n    # Step 5: Create client\n    client = Client(access_token=access_token)\n    \n    # Step 6: Get authenticated user ID\n    me_response = client.users.get_me()\n    user_id = me_response.data[\"id\"]\n    \n    # Step 7: Get reverse chronological timeline with automatic pagination\n    # Post fields are adjustable. Options include:\n    # attachments, author_id, context_annotations, conversation_id,\n    # created_at, entities, geo, id, in_reply_to_user_id, lang,\n    # possibly_sensitive, public_metrics, referenced_tweets, source, text\n    all_posts = []\n    for page in client.users.get_timeline(\n        user_id,\n        max_results=100,\n        tweet_fields=[\"created_at\"]\n    ):\n        # Access data attribute (model uses extra='allow' so data should be available)\n        # Use getattr with fallback in case data field is missing from response\n        page_data = getattr(page, 'data', []) or []\n        all_posts.extend(page_data)\n        print(f\"Fetched {len(page_data)} posts (total: {len(all_posts)})\")\n    \n    print(f\"\\nTotal Posts: {len(all_posts)}\")\n    print(json.dumps({\"data\": all_posts[:5]}, indent=4, sort_keys=True))  # Print first 5 as example\n\nif __name__ == \"__main__\":\n    main()\n"
  },
  {
    "path": "python/users/timeline/get_mentions.py",
    "content": "\"\"\"\nUser Mentions Timeline - X API v2\n==================================\nEndpoint: GET https://api.x.com/2/users/:id/mentions\nDocs: https://developer.x.com/en/docs/twitter-api/tweets/timelines/api-reference/get-users-id-mentions\n\nAuthentication: Bearer Token (App-only) or OAuth (User Context)\nRequired env vars: BEARER_TOKEN\n\"\"\"\n\nimport os\nimport json\nfrom xdk import Client\n\nbearer_token = os.environ.get(\"BEARER_TOKEN\")\nclient = Client(bearer_token=bearer_token)\n\n# Replace with user ID below\nuser_id = \"2244994945\"\n\ndef main():\n    # Get user mentions with automatic pagination\n    # Tweet fields are adjustable.\n    # Options include:\n    # attachments, author_id, context_annotations,\n    # conversation_id, created_at, entities, geo, id,\n    # in_reply_to_user_id, lang, non_public_metrics, organic_metrics,\n    # possibly_sensitive, promoted_metrics, public_metrics, referenced_tweets,\n    # source, text, and withheld\n    all_posts = []\n    for page in client.users.get_mentions(\n        user_id,\n        max_results=100,\n        tweet_fields=[\"created_at\"]\n    ):\n        # Access data attribute (model uses extra='allow' so data should be available)\n        # Use getattr with fallback in case data field is missing from response\n        page_data = getattr(page, 'data', []) or []\n        all_posts.extend(page_data)\n        print(f\"Fetched {len(page_data)} posts (total: {len(all_posts)})\")\n    \n    print(f\"\\nTotal Mentions: {len(all_posts)}\")\n    print(json.dumps({\"data\": all_posts[:5]}, indent=4, sort_keys=True))  # Print first 5 as example\n\nif __name__ == \"__main__\":\n    main()\n    "
  },
  {
    "path": "python/users/timeline/get_posts.py",
    "content": "\"\"\"\nUser Posts Timeline - X API v2\n==============================\nEndpoint: GET https://api.x.com/2/users/:id/tweets\nDocs: https://developer.x.com/en/docs/twitter-api/tweets/timelines/api-reference/get-users-id-tweets\n\nAuthentication: Bearer Token (App-only) or OAuth (User Context)\nRequired env vars: BEARER_TOKEN\n\"\"\"\n\nimport os\nimport json\nfrom xdk import Client\n\nbearer_token = os.environ.get(\"BEARER_TOKEN\")\nclient = Client(bearer_token=bearer_token)\n\n# Replace with the user ID you want to get posts for\nuser_id = \"2244994945\"\n\ndef main():\n    # Get user posts with automatic pagination\n    # Post fields are adjustable. Options include:\n    # attachments, author_id, context_annotations, conversation_id,\n    # created_at, entities, geo, id, in_reply_to_user_id, lang,\n    # non_public_metrics, organic_metrics, possibly_sensitive,\n    # promoted_metrics, public_metrics, referenced_tweets, source, text, and withheld\n    all_posts = []\n    for page in client.users.get_posts(\n        user_id,\n        max_results=100,\n        tweet_fields=[\"created_at\"]\n    ):\n        # Access data attribute (model uses extra='allow' so data should be available)\n        # Use getattr with fallback in case data field is missing from response\n        page_data = getattr(page, 'data', []) or []\n        all_posts.extend(page_data)\n        print(f\"Fetched {len(page_data)} posts (total: {len(all_posts)})\")\n    \n    print(f\"\\nTotal Posts: {len(all_posts)}\")\n    print(json.dumps({\"data\": all_posts[:5]}, indent=4, sort_keys=True))  # Print first 5 as example\n\nif __name__ == \"__main__\":\n    main()\n"
  },
  {
    "path": "python/webhooks/delete_webhook.py",
    "content": "\"\"\"\nDelete Webhook - X API v2\n=========================\nEndpoint: DELETE https://api.x.com/2/webhooks/:webhook_id\nDocs: https://docs.x.com/x-api/webhooks/introduction\n\nDeletes a registered webhook. After deletion, X will stop delivering events\nto the associated URL. Use list_webhooks.py to find your webhook_id.\n\nAuthentication: Bearer Token (App-only)\nRequired env vars: BEARER_TOKEN\n\"\"\"\n\nimport os\nimport json\nfrom xdk import Client\n\nbearer_token = os.environ.get(\"BEARER_TOKEN\")\nclient = Client(bearer_token=bearer_token)\n\n# Replace with the webhook ID you wish to delete.\n# You can find your webhook IDs by running list_webhooks.py\nwebhook_id = \"your-webhook-id\"\n\ndef main():\n    response = client.webhooks.delete(webhook_id)\n\n    print(\"Response code: 200\")\n    print(json.dumps(response.data, indent=4, sort_keys=True))\n\n\nif __name__ == \"__main__\":\n    main()\n"
  },
  {
    "path": "python/webhooks/list_webhooks.py",
    "content": "\"\"\"\nList Webhooks - X API v2\n========================\nEndpoint: GET https://api.x.com/2/webhooks\nDocs: https://docs.x.com/x-api/webhooks/introduction\n\nReturns all registered webhooks for your app. Use the webhook_id from the\nresponse when managing subscriptions or deleting a webhook.\n\nAuthentication: Bearer Token (App-only)\nRequired env vars: BEARER_TOKEN\n\"\"\"\n\nimport os\nimport json\nfrom xdk import Client\n\nbearer_token = os.environ.get(\"BEARER_TOKEN\")\nclient = Client(bearer_token=bearer_token)\n\ndef main():\n    response = client.webhooks.get()\n\n    print(json.dumps(response.data, indent=4, sort_keys=True))\n\n\nif __name__ == \"__main__\":\n    main()\n"
  },
  {
    "path": "python/webhooks/register_webhook.py",
    "content": "\"\"\"\nRegister Webhook - X API v2\n===========================\nEndpoint: POST https://api.x.com/2/webhooks\nDocs: https://docs.x.com/x-api/webhooks/introduction\n\nRegisters a new webhook URL with X. When you make this request, X immediately\nsends a CRC challenge GET request to your URL to verify ownership. Your server\nmust respond correctly before the webhook is saved — see webhook_server.py.\n\nAuthentication: Bearer Token (App-only)\nRequired env vars: BEARER_TOKEN\n\"\"\"\n\nimport os\nimport json\nfrom xdk import Client\n\nbearer_token = os.environ.get(\"BEARER_TOKEN\")\nclient = Client(bearer_token=bearer_token)\n\n# Replace with your publicly accessible HTTPS webhook URL.\n# The URL must be reachable by X at the time of registration so the CRC check can complete.\n# For local development you can use a tool like ngrok to expose a local server.\nwebhook_url = \"https://your-domain.com/webhooks\"\n\ndef main():\n    payload = {\"url\": webhook_url}\n    response = client.webhooks.create(body=payload)\n\n    print(\"Response code: 200\")\n    print(json.dumps(response.data, indent=4, sort_keys=True))\n\n\nif __name__ == \"__main__\":\n    main()\n"
  },
  {
    "path": "python/webhooks/validate_webhook.py",
    "content": "\"\"\"\nValidate Webhook (Trigger CRC) - X API v2\n==========================================\nEndpoint: PUT https://api.x.com/2/webhooks/:webhook_id\nDocs: https://docs.x.com/x-api/webhooks/introduction\n\nManually triggers a CRC (Challenge-Response Check) for the specified webhook.\nUse this to re-validate your server's ownership or to re-enable a webhook that\nwas disabled due to failed CRC checks. Your webhook server must be running and\nable to respond to the challenge before calling this endpoint.\n\nAuthentication: Bearer Token (App-only)\nRequired env vars: BEARER_TOKEN\n\"\"\"\n\nimport os\nimport json\nfrom xdk import Client\n\nbearer_token = os.environ.get(\"BEARER_TOKEN\")\nclient = Client(bearer_token=bearer_token)\n\n# Replace with the webhook ID you wish to validate.\n# You can find your webhook IDs by running list_webhooks.py\nwebhook_id = \"your-webhook-id\"\n\ndef main():\n    response = client.webhooks.validate(webhook_id)\n\n    print(\"Response code: 200\")\n    print(json.dumps(response.data, indent=4, sort_keys=True))\n\n\nif __name__ == \"__main__\":\n    main()\n"
  },
  {
    "path": "python/webhooks/webhook_server.py",
    "content": "\"\"\"\nWebhook Server - X API v2\n=========================\nDocs: https://docs.x.com/x-api/webhooks/introduction\n\nThis is a minimal webhook consumer server that handles two responsibilities:\n  1. CRC (Challenge-Response Check) validation via GET — X sends a crc_token\n     and expects back an HMAC-SHA256 hash signed with your Consumer Secret.\n     This is required when registering a webhook and periodically thereafter\n     to confirm your server is still alive.\n  2. Event delivery via POST — X sends account activity or filtered stream\n     events as JSON payloads to this endpoint in real time.\n\nTo receive events you must:\n  1. Run this server at a publicly accessible HTTPS URL (e.g. via ngrok).\n  2. Register the URL with X: see register_webhook.py\n  3. Subscribe user accounts or set stream rules to start receiving events.\n\nAuthentication: Consumer Secret (HMAC-SHA256 for CRC validation)\nRequired env vars: CONSUMER_SECRET\nDependencies: flask, waitress (pip install flask waitress)\n\"\"\"\n\nimport base64\nimport hashlib\nimport hmac\nimport json\nimport os\nimport sys\n\nfrom flask import Flask, jsonify, request\nfrom waitress import serve\n\napp = Flask(__name__)\n\n# Your app's Consumer Secret — used to sign the CRC response.\n# To set environment variables on macOS or Linux, run the export commands below from the terminal:\n# export CONSUMER_SECRET='YOUR-CONSUMER-SECRET'\nCONSUMER_SECRET = os.environ.get(\"CONSUMER_SECRET\")\nif CONSUMER_SECRET is None:\n    print(\"Missing consumer secret. Ensure CONSUMER_SECRET env var is set.\")\n    sys.exit(1)\n\nHOST = \"0.0.0.0\"\nPORT = 8080\n\n\n@app.route('/webhooks', methods=['GET', 'POST'])\ndef webhook_request():\n    # Handle GET request (CRC challenge)\n    if request.method == 'GET':\n        crc_token = request.args.get('crc_token')\n        print(f\"CRC Token received: {crc_token}\")\n\n        if crc_token is None:\n            print(\"Error: No crc_token found in the request.\")\n            return jsonify({'error': 'No crc_token'}), 400\n\n        # Creates HMAC SHA-256 hash from the incoming token and your Consumer Secret\n        sha256_hash_digest = hmac.new(\n            CONSUMER_SECRET.encode('utf-8'),\n            msg=crc_token.encode('utf-8'),\n            digestmod=hashlib.sha256\n        ).digest()\n\n        # Construct response data with base64 encoded hash\n        response = {\n            'response_token': 'sha256=' + base64.b64encode(sha256_hash_digest).decode('utf-8')\n        }\n\n        # Returns properly formatted json response\n        return jsonify(response)\n\n    # Handle POST request (webhook event delivery)\n    elif request.method == 'POST':\n        event_data = request.get_json()\n        if event_data:\n            print(json.dumps(event_data, indent=2))\n        else:\n            # Log if the request body wasn't JSON or was empty\n            print(f\"Body: {request.data.decode('utf-8')}\")\n\n        # Return 200 OK immediately to acknowledge receipt.\n        # X will retry delivery if it does not receive a 2xx response promptly.\n        return '', 200\n\n    return 'Method Not Allowed', 405\n\n\ndef main():\n    print(\"--- Starting Webhook Server ---\")\n    print(f\"Listening on {HOST}:{PORT}\")\n    print(\"Expose this server publicly (e.g. via ngrok) then register the URL with register_webhook.py\")\n    serve(app, host=HOST, port=PORT)\n\n\nif __name__ == '__main__':\n    main()\n"
  },
  {
    "path": "r/posts/full-archive-search.r",
    "content": "library(httr)\n\n# Replace the bearer token below with\nbearer_token = \"\"\n\nheaders = c(\n  `Authorization` = sprintf('Bearer %s', bearer_token)\n)\n\nparams = list(\n  `query` = 'from:twitterdev lang:en',\n  `max_results` = '10',\n  `tweet.fields` = 'created_at,lang,context_annotations'\n)\n\nresponse <- httr::GET(url = 'https://api.x.com/2/tweets/search/all', httr::add_headers(.headers=headers), query = params)\n\nfas_body <-\n  content(\n    response,\n    as = 'parsed',\n    type = 'application/json',\n    simplifyDataFrame = TRUE\n  )\n\nView(fas_body$data)"
  },
  {
    "path": "r/posts/full_archive_tweet_counts.r",
    "content": "library(httr)\n\n# Replace the bearer token below with\nbearer_token = \"\"\n\nheaders = c(\n  `Authorization` = sprintf('Bearer %s', bearer_token)\n)\n\nparams = list(\n  `query` = 'from:twitterdev',\n  `granularity` = 'day'\n)\n\nresponse <- httr::GET(url = 'https://api.x.com/2/tweets/counts/all', httr::add_headers(.headers=headers), query = params)\n\nbody <-\n  content(\n    response,\n    as = 'parsed',\n    type = 'application/json',\n    simplifyDataFrame = TRUE\n  )\n\nView(body$data)"
  },
  {
    "path": "r/posts/recent-search.r",
    "content": "require(httr)\n\n\nbearer_token = \"\"\nheaders = c(\n  `Authorization` = sprintf('Bearer %s', bearer_token)\n)\n\n\nparams = list(\n  `query` = 'from:TwitterDev',\n  `max_results` = '10',\n  `tweet.fields` = 'created_at,lang,conversation_id'\n)\n\n\nresponse <- httr::GET(url = 'https://api.x.com/2/tweets/search/recent', httr::add_headers(.headers=headers), query = params)\n\n\nrecent_search_body <-\n  content(\n    response,\n    as = 'parsed',\n    type = 'application/json',\n    simplifyDataFrame = TRUE\n  )\n\nView(recent_search_body$data)\n"
  },
  {
    "path": "r/posts/recent_tweet_counts.r",
    "content": "library(httr)\n\n# Replace the bearer token below with\nbearer_token = \"\"\n\nheaders = c(\n  `Authorization` = sprintf('Bearer %s', bearer_token)\n)\n\nparams = list(\n  `query` = 'from:twitterdev',\n  `granularity` = 'day'\n)\n\nresponse <- httr::GET(url = 'https://api.x.com/2/tweets/counts/recent', httr::add_headers(.headers=headers), query = params)\n\nbody <-\n  content(\n    response,\n    as = 'parsed',\n    type = 'application/json',\n    simplifyDataFrame = TRUE\n  )\n\nView(body$data)"
  },
  {
    "path": "r/users/get_users_with_bearer_token.r",
    "content": "require(httr)\n\nbearer_token <- \"\"\n\nheaders <- c(`Authorization` = sprintf('Bearer %s', bearer_token))\n\nparams <- list(`user.fields` = 'description')\n\nhandle <- 'TwitterDev'\n\nurl_handle <-\n  sprintf('https://api.x.com/2/users/by?usernames=%s', handle)\n\nresponse <-\n  httr::GET(url = url_handle,\n            httr::add_headers(.headers = headers),\n            query = params)\n\nobj <- httr::content(res, as = \"text\")\nprint(obj)\n"
  },
  {
    "path": "ruby/Gemfile",
    "content": "source 'https://rubygems.org'\ngem 'typhoeus', '~> 1.4'\ngem 'oauth', '~> 1.1'\n"
  },
  {
    "path": "ruby/README.md",
    "content": "# X API v2 - Ruby Examples\n\nWorking Ruby code samples for the X (formerly Twitter) API v2.\n\n## Setup\n\n### 1. Install Ruby 2.7+\n\n```bash\nruby --version\n```\n\n### 2. Install dependencies\n\n```bash\nbundle install\n```\n\nOr manually:\n```bash\ngem install typhoeus\ngem install oauth  # For OAuth 1.0a examples\n```\n\nThe `Gemfile` includes:\n- `typhoeus` (~> 1.4) - HTTP client library\n- `oauth` (~> 1.1) - OAuth 1.0a library\n\n### 3. Set environment variables\n\n**For read-only operations (search, lookup):**\n```bash\nexport BEARER_TOKEN='your_bearer_token'\n```\n\n**For user actions (post, like, repost, bookmark, etc.):**\n```bash\nexport CLIENT_ID='your_client_id'\nexport CLIENT_SECRET='your_client_secret'\n```\n\n**For OAuth 1.0a (legacy endpoints):**\n```bash\nexport CONSUMER_KEY='your_consumer_key'\nexport CONSUMER_SECRET='your_consumer_secret'\n```\n\n**Note:** Most user action examples require OAuth 2.0 authentication with `CLIENT_ID` and `CLIENT_SECRET`. Read-only examples (search, lookup) only require `BEARER_TOKEN`.\n\n## Examples by Category\n\n### Posts\n- `posts/create_tweet.rb` - Create a new post\n- `posts/delete_tweet.rb` - Delete a post\n- `posts/full_archive_tweet_counts.rb` - Full archive tweet counts\n- `posts/full-archive-search.rb` - Full archive search\n- `posts/get_tweets_with_bearer_token.rb` - Look up posts by ID (bearer token)\n- `posts/get_tweets_with_user_context.rb` - Look up posts by ID (user context)\n- `posts/like_a_tweet.rb` - Like a post\n- `posts/liked_tweets.rb` - Get posts liked by a user\n- `posts/liking_users.rb` - Get users who liked a post\n- `posts/lookup.rb` - Look up posts by ID\n- `posts/quote_tweets.rb` - Get posts that quote a post\n- `posts/recent_search.rb` - Recent search (last 7 days)\n- `posts/recent_tweet_counts.rb` - Recent tweet counts\n- `posts/retweet_a_tweet.rb` - Repost a post\n- `posts/retweeted_by.rb` - Get users who reposted a post\n- `posts/search_recent.rb` - Recent search (alternative)\n- `posts/undo_a_retweet.rb` - Undo a repost\n- `posts/unlike_a_tweet.rb` - Unlike a post\n\n### Users\n- `users/block_a_user.rb` - Block a user\n- `users/followers-lookup.rb` - Get user's followers (lookup)\n- `users/followers.rb` - Get user's followers\n- `users/following-lookup.rb` - Get users a user is following\n- `users/get_users_me_with_user_context.rb` - Get authenticated user (me)\n- `users/get_users_with_bearer_token.rb` - Look up users by username (bearer token)\n- `users/get_users_with_user_context.rb` - Look up users by username (user context)\n- `users/lookup_blocks.rb` - Get users blocked by a user\n- `users/lookup_mutes.rb` - Get users muted by a user\n- `users/lookup.rb` - Look up users by username\n- `users/mute_a_user.rb` - Mute a user\n- `users/unblock_a_user.rb` - Unblock a user\n- `users/unmute_a_user.rb` - Unmute a user\n\n### Timelines\n- `timelines/reverse-chron-home-timeline.rb` - Get home timeline (reverse chronological)\n- `timelines/user_posts.rb` - Get user's posts timeline\n- `timelines/user-mentions.rb` - Get user mentions timeline\n- `timelines/user-tweets.rb` - Get user's tweets timeline\n\n### Streams\n- `streams/filtered_stream.rb` - Filtered stream with rules\n- `streams/sampled_stream.rb` - Sampled stream\n\n### Lists\n- `lists/add_member.rb` - Add member to a list\n- `lists/create_a_list.rb` - Create a new list\n- `lists/delete_a_list.rb` - Delete a list\n- `lists/follow_list.rb` - Follow a list\n- `lists/list-followers-lookup.rb` - Get list followers\n- `lists/list-lookup-by-id.rb` - Get list by ID\n- `lists/list-member-lookup.rb` - Get list members\n- `lists/List-Tweets.rb` - Get posts from a list\n- `lists/lookup.rb` - Look up a list\n- `lists/pin_list.rb` - Pin a list\n- `lists/Pinned-List.rb` - Get pinned lists\n- `lists/remove_member.rb` - Remove member from a list\n- `lists/unfollow_list.rb` - Unfollow a list\n- `lists/unpin_list.rb` - Unpin a list\n- `lists/update_a_list.rb` - Update a list\n- `lists/user-list-followed.rb` - Get lists followed by a user\n- `lists/user-list-memberships.rb` - Get list memberships\n- `lists/user-owned-list-lookup.rb` - Get lists owned by a user\n\n### Bookmarks\n- `bookmarks/bookmarks_lookup.rb` - Get user's bookmarks\n\n### Spaces\n- `spaces/search_spaces.rb` - Search for Spaces\n- `spaces/spaces_lookup.rb` - Look up Spaces by ID\n\n## Running Examples\n\n```bash\n# Make sure environment variables are set\nruby posts/search_recent.rb\n```\n\n## More Information\n\n- [X API Documentation](https://developer.x.com/en/docs/twitter-api)\n- [X Developer Portal](https://developer.x.com/en/portal/dashboard)\n"
  },
  {
    "path": "ruby/bookmarks/bookmarks_lookup.rb",
    "content": "require 'json'\nrequire 'typhoeus'\nrequire 'twitter_oauth2'\n\n# First, you will need to enable OAuth 2.0 in your App’s auth settings in the Developer Portal to get your client ID.\n# Inside your terminal you will need to set an enviornment variable\n# export CLIENT_ID='your-client-id'\nclient_id = ENV[\"CLIENT_ID\"]\n\n# If you have selected a type of App that is a confidential client you will need to set a client secret.\n# Confidential Clients securely authenticate with the authorization server.\n\n# Inside your terminal you will need to set an enviornment variable\n# export CLIENT_SECRET='your-client-secret'\n\n# Remove the comment on the following line if you are using a confidential client\n# client_secret = ENV[\"CLIENT_SECRET\"]\n\n\n# Replace the following URL with your callback URL, which can be obtained from your App's auth settings.\nredirect_uri = \"https://www.example.com\"\n\n# Start an OAuth 2.0 session with a public client\nclient = TwitterOAuth2::Client.new(\n  identifier: \"#{client_id}\",\n  redirect_uri: \"#{redirect_uri}\"\n)\n\n# Start an OAuth 2.0 session with a confidential client\n\n# Remove the comment on the following lines if you are using a confidential client\n# client = TwitterOAuth2::Client.new(\n#   identifier: \"#{client_id}\",\n#   secret: \"#{client_secret}\",\n#   redirect_uri: \"#{redirect_uri}\"\n# )\n\n# Create your authorize url\nauthorization_url = client.authorization_uri(\n  # Update scopes if needed\n  scope: [\n    :'users.read',\n    :'tweet.read',\n    :'bookmark.read',\n    :'offline.access'\n  ]\n)\n\n# Set code verifier and state\ncode_verifier = client.code_verifier\nstate = client.state\n\n# Visit the URL to authorize your App to make requests on behalf of a user\nprint 'Visit the following URL to authorize your App on behalf of your Twitter handle in a browser'\nputs authorization_url\n`open \"#{authorization_url}\"`\n\nprint 'Paste in the full URL after you authorized your App: ' and STDOUT.flush\n\n# Fetch your access token\nfull_text = gets.chop\nnew_code = full_text.split(\"code=\")\ncode = new_code[1]\nclient.authorization_code = code\n\n# Your access token\ntoken_response = client.access_token! code_verifier\n\n# Make a request to the users/me endpoint to get your user ID\ndef users_me(url, token_response)\n  options = {\n    method: 'get',\n    headers: {\n      \"User-Agent\": \"BookmarksSampleCode\",\n      \"Authorization\": \"Bearer #{token_response}\"\n    },\n  }\n\n  request = Typhoeus::Request.new(url, options)\n  response = request.run\n\n  return response\nend\n\nurl = \"https://api.x.com/2/users/me\"\nme_response = users_me(url, token_response)\n\njson_s = JSON.parse(me_response.body)\nuser_id = json_s[\"data\"][\"id\"]\n\n# Make a request to the bookmarks url\nbookmarks_url = \"https://api.x.com/2/users/#{user_id}/bookmarks\"\n\ndef bookmarked_tweets(bookmarks_url, token_response)\n  options = {\n    method: 'get',\n    headers: {\n      \"User-Agent\": \"BookmarksSampleCode\",\n      \"Authorization\": \"Bearer #{token_response}\"\n    }\n  }\n\n  request = Typhoeus::Request.new(bookmarks_url, options)\n  response = request.run\n\n  return response\nend\n\nresponse = bookmarked_tweets(bookmarks_url, token_response)\nputs response.code, JSON.pretty_generate(JSON.parse(response.body))\n"
  },
  {
    "path": "ruby/lists/List-Tweets.rb",
    "content": "# This script uses your bearer token to authenticate and retrieve the specified Tweet objects (by List ID)\n\nrequire 'json'\nrequire 'typhoeus'\n\n# The code below sets the bearer token from your environment variables\n# To set environment variables on Mac OS X, run the export command below from the terminal:\n# export BEARER_TOKEN='YOUR-TOKEN'\nbearer_token = ENV[\"BEARER_TOKEN\"]\n\n# Be sure to replace list-id with any List ID\nid = \"list-id\"\nurl = \"https://api.x.com/2/lists/#{id}/tweets\"\n\n\nparams = {\n  # Tweet fields are adjustable.\n  # Options include:\n  # attachments, author_id, context_annotations,\n  # conversation_id, created_at, entities, geo, id,\n  # in_reply_to_user_id, lang, non_public_metrics, organic_metrics,\n  # possibly_sensitive, promoted_metrics, public_metrics, referenced_tweets,\n  # source, text, and withheld\n  \"tweet.fields\": \"lang,author_id\",\n}\n\ndef list_tweets(url, bearer_token, params)\n  options = {\n    method: 'get',\n    headers: {\n      \"User-Agent\": \"v2ListTweetsLookupRuby\",\n      \"Authorization\": \"Bearer #{bearer_token}\"\n    },\n    params: params\n  }\n\n  request = Typhoeus::Request.new(url, options)\n  response = request.run\n\n  return response\nend\n\nresponse = list_tweets(url, bearer_token, params)\nputs response.code, JSON.pretty_generate(JSON.parse(response.body))\n"
  },
  {
    "path": "ruby/lists/Pinned-List.rb",
    "content": "# This script implements the PIN-based OAuth flow to obtain access tokens for a user context request\nrequire 'oauth'\nrequire 'json'\nrequire 'typhoeus'\nrequire 'oauth/request_proxy/typhoeus_request'\n\n# The code below sets the consumer key and secret from your environment variables\n# To set environment variables on Mac OS X, run the export command below from the terminal:\n# export CONSUMER_KEY='YOUR-KEY', CONSUMER_SECRET='YOUR-SECRET'\nconsumer_key = ENV[\"CONSUMER_KEY\"]\nconsumer_secret = ENV[\"CONSUMER_SECRET\"]\n\n# Be sure to replace your-user-id with your own user ID or one of an authenticating user\n# You can find a user ID by using the user lookup endpoint\nid = \"your-user-id\"\n\nurl = \"https://api.x.com/2/users/#{id}/pinned_lists\"\n\n@params = {\n    # List fields are adjustable, options include:\n    # created_at, description, owner_id,\n    # private, follower_count, member_count,\n  \"list.fields\": \"created_at,follower_count\"\n}\n\nconsumer = OAuth::Consumer.new(consumer_key, consumer_secret,\n\t                                :site => 'https://api.x.com',\n\t                                :authorize_path => '/oauth/authenticate',\n\t                                :debug_output => false)\n\ndef get_request_token(consumer)\n\n\trequest_token = consumer.get_request_token()\n\n  return request_token\nend\n\ndef get_user_authorization(request_token)\n\tputs \"Follow this URL to have a user authorize your app: #{request_token.authorize_url()}\"\n\tputs \"Enter PIN: \"\n\tpin = gets.strip\n\n  return pin\nend\n\ndef obtain_access_token(consumer, request_token, pin)\n\ttoken = request_token.token\n\ttoken_secret = request_token.secret\n\thash = { :oauth_token => token, :oauth_token_secret => token_secret }\n\trequest_token  = OAuth::RequestToken.from_hash(consumer, hash)\n\n\t# Get access token\n\taccess_token = request_token.get_access_token({:oauth_verifier => pin})\n\n\treturn access_token\nend\n\n\ndef pin_list(url, oauth_params)\n\toptions = {\n\t    :method => :get,\n\t    headers: {\n\t    \"User-Agent\": \"v2pinListLookupRuby\",\n        \"content-type\": \"application/json\"\n\t    },\n\t\tparams: @params\n\t}\n\trequest = Typhoeus::Request.new(url, options)\n\toauth_helper = OAuth::Client::Helper.new(request, oauth_params.merge(:request_uri => url))\n\trequest.options[:headers].merge!({\"Authorization\" => oauth_helper.header}) # Signs the request\n\tresponse = request.run\n\n\treturn response\nend\n\n\n\n# PIN-based OAuth flow - Step 1\nrequest_token = get_request_token(consumer)\n# PIN-based OAuth flow - Step 2\npin = get_user_authorization(request_token)\n# PIN-based OAuth flow - Step 3\naccess_token = obtain_access_token(consumer, request_token, pin)\n\noauth_params = {:consumer => consumer, :token => access_token}\n\n\nresponse = pin_list(url, oauth_params)\nputs response.code, JSON.pretty_generate(JSON.parse(response.body))\n"
  },
  {
    "path": "ruby/lists/add_member.rb",
    "content": "# This script implements the PIN-based OAuth flow to obtain access tokens for a user context request\nrequire 'oauth'\nrequire 'json'\nrequire 'typhoeus'\nrequire 'oauth/request_proxy/typhoeus_request'\n\n# The code below sets the consumer key and secret from your environment variables\n# To set environment variables on Mac OS X, run the export command below from the terminal:\n# export CONSUMER_KEY='YOUR-KEY', CONSUMER_SECRET='YOUR-SECRET'\nconsumer_key = ENV[\"CONSUMER_KEY\"]\nconsumer_secret = ENV[\"CONSUMER_SECRET\"]\n\n# Be sure to replace your-list-id with your own list ID or one of an authenticating user\nid = \"your-list-id\"\n\nmember_url = \"https://api.x.com/2/lists/#{id}/members\"\n\n# Be sure to replace user-id-to-add with the user id you wish to add.\n@user_id = { \"user_id\": \"user-id-to-add\" }\n\nconsumer = OAuth::Consumer.new(consumer_key, consumer_secret,\n\t                                :site => 'https://api.x.com',\n\t                                :authorize_path => '/oauth/authenticate',\n\t                                :debug_output => false)\n\ndef get_request_token(consumer)\n\n\trequest_token = consumer.get_request_token()\n\n  return request_token\nend\n\ndef get_user_authorization(request_token)\n\tputs \"Follow this URL to have a user authorize your app: #{request_token.authorize_url()}\"\n\tputs \"Enter PIN: \"\n\tpin = gets.strip\n\n  return pin\nend\n\ndef obtain_access_token(consumer, request_token, pin)\n\ttoken = request_token.token\n\ttoken_secret = request_token.secret\n\thash = { :oauth_token => token, :oauth_token_secret => token_secret }\n\trequest_token  = OAuth::RequestToken.from_hash(consumer, hash)\n\n\t# Get access token\n\taccess_token = request_token.get_access_token({:oauth_verifier => pin})\n\n\treturn access_token\nend\n\n\ndef add_member(url, oauth_params)\n\toptions = {\n\t    :method => :post,\n\t    headers: {\n\t     \t\"User-Agent\": \"v2addMemberRuby\",\n        \"content-type\": \"application/json\"\n\t    },\n\t    body: JSON.dump(@user_id)\n\t}\n\trequest = Typhoeus::Request.new(url, options)\n\toauth_helper = OAuth::Client::Helper.new(request, oauth_params.merge(:request_uri => url))\n\trequest.options[:headers].merge!({\"Authorization\" => oauth_helper.header}) # Signs the request\n\tresponse = request.run\n\n\treturn response\nend\n\n\n\n# PIN-based OAuth flow - Step 1\nrequest_token = get_request_token(consumer)\n# PIN-based OAuth flow - Step 2\npin = get_user_authorization(request_token)\n# PIN-based OAuth flow - Step 3\naccess_token = obtain_access_token(consumer, request_token, pin)\n\noauth_params = {:consumer => consumer, :token => access_token}\n\n\nresponse = add_member(member_url, oauth_params)\nputs response.code, JSON.pretty_generate(JSON.parse(response.body))\n"
  },
  {
    "path": "ruby/lists/create_a_list.rb",
    "content": "# This script implements the PIN-based OAuth flow to obtain access tokens for a user context request\n# It then makes a User lookup request (by usernames) with OAuth 1.0a authentication (user context)\nrequire 'oauth'\nrequire 'json'\nrequire 'typhoeus'\nrequire 'oauth/request_proxy/typhoeus_request'\n\n# The code below sets the consumer key and secret from your environment variables\n# To set environment variables on Mac OS X, run the export command below from the terminal:\n# export CONSUMER_KEY='YOUR-KEY', CONSUMER_SECRET='YOUR-SECRET'\nconsumer_key = ENV[\"CONSUMER_KEY\"]\nconsumer_secret = ENV[\"CONSUMER_SECRET\"]\n\n\ncreate_list_url = \"https://api.x.com/2/lists\"\n\n# Be sure to add replace name-of-list with the name you wish to call the list.\n# description and private keys are optional\n@json_payload = { \"name\": \"name-of-list\",\n\"description\": \"description-of-list\",\n\"private\": false}\n\nconsumer = OAuth::Consumer.new(consumer_key, consumer_secret,\n\t                                :site => 'https://api.x.com',\n\t                                :authorize_path => '/oauth/authenticate',\n\t                                :debug_output => false)\n\ndef get_request_token(consumer)\n\n\trequest_token = consumer.get_request_token()\n\n  return request_token\nend\n\ndef get_user_authorization(request_token)\n\tputs \"Follow this URL to have a user authorize your app: #{request_token.authorize_url()}\"\n\tputs \"Enter PIN: \"\n\tpin = gets.strip\n\n  return pin\nend\n\ndef obtain_access_token(consumer, request_token, pin)\n\ttoken = request_token.token\n\ttoken_secret = request_token.secret\n\thash = { :oauth_token => token, :oauth_token_secret => token_secret }\n\trequest_token  = OAuth::RequestToken.from_hash(consumer, hash)\n\n\t# Get access token\n\taccess_token = request_token.get_access_token({:oauth_verifier => pin})\n\n\treturn access_token\nend\n\n\ndef create_list(url, oauth_params)\n\toptions = {\n\t    :method => :post,\n\t    headers: {\n\t     \t\"User-Agent\": \"v2createListRuby\",\n        \"content-type\": \"application/json\"\n\t    },\n\t    body: JSON.dump(@json_payload)\n\t}\n\trequest = Typhoeus::Request.new(url, options)\n\toauth_helper = OAuth::Client::Helper.new(request, oauth_params.merge(:request_uri => url))\n\trequest.options[:headers].merge!({\"Authorization\" => oauth_helper.header}) # Signs the request\n\tresponse = request.run\n\n\treturn response\nend\n\n\n\n# PIN-based OAuth flow - Step 1\nrequest_token = get_request_token(consumer)\n# PIN-based OAuth flow - Step 2\npin = get_user_authorization(request_token)\n# PIN-based OAuth flow - Step 3\naccess_token = obtain_access_token(consumer, request_token, pin)\n\noauth_params = {:consumer => consumer, :token => access_token}\n\n\nresponse = create_list(create_list_url, oauth_params)\nputs response.code, JSON.pretty_generate(JSON.parse(response.body))\n"
  },
  {
    "path": "ruby/lists/delete_a_list.rb",
    "content": "# This script implements the PIN-based OAuth flow to obtain access tokens for a user context request\n# It then makes a User lookup request (by usernames) with OAuth 1.0a authentication (user context)\nrequire 'oauth'\nrequire 'json'\nrequire 'typhoeus'\nrequire 'oauth/request_proxy/typhoeus_request'\n\n# The code below sets the consumer key and secret from your environment variables\n# To set environment variables on Mac OS X, run the export command below from the terminal:\n# export CONSUMER_KEY='YOUR-KEY', CONSUMER_SECRET='YOUR-SECRET'\nconsumer_key = ENV[\"CONSUMER_KEY\"]\nconsumer_secret = ENV[\"CONSUMER_SECRET\"]\n\n# Be sure to replace your-list-id with the id of the list you wish to delete. The authenticated user must own the list in order to delete\n\nid = \"your-list-id\"\n\ndelete_list_url = \"https://api.x.com/2/lists/#{id}\"\n\n\nconsumer = OAuth::Consumer.new(consumer_key, consumer_secret,\n\t                                :site => 'https://api.x.com',\n\t                                :authorize_path => '/oauth/authenticate',\n\t                                :debug_output => false)\n\ndef get_request_token(consumer)\n\n\trequest_token = consumer.get_request_token()\n\n  return request_token\nend\n\ndef get_user_authorization(request_token)\n\tputs \"Follow this URL to have a user authorize your app: #{request_token.authorize_url()}\"\n\tputs \"Enter PIN: \"\n\tpin = gets.strip\n\n  return pin\nend\n\ndef obtain_access_token(consumer, request_token, pin)\n\ttoken = request_token.token\n\ttoken_secret = request_token.secret\n\thash = { :oauth_token => token, :oauth_token_secret => token_secret }\n\trequest_token  = OAuth::RequestToken.from_hash(consumer, hash)\n\n\t# Get access token\n\taccess_token = request_token.get_access_token({:oauth_verifier => pin})\n\n\treturn access_token\nend\n\n\ndef delete_list(url, oauth_params)\n\toptions = {\n\t    :method => :delete,\n\t    headers: {\n\t     \t\"User-Agent\": \"v2deleteListRuby\",\n        \"content-type\": \"application/json\"\n\t    }\n\t}\n\trequest = Typhoeus::Request.new(url, options)\n\toauth_helper = OAuth::Client::Helper.new(request, oauth_params.merge(:request_uri => url))\n\trequest.options[:headers].merge!({\"Authorization\" => oauth_helper.header}) # Signs the request\n\tresponse = request.run\n\n\treturn response\nend\n\n\n\n# PIN-based OAuth flow - Step 1\nrequest_token = get_request_token(consumer)\n# PIN-based OAuth flow - Step 2\npin = get_user_authorization(request_token)\n# PIN-based OAuth flow - Step 3\naccess_token = obtain_access_token(consumer, request_token, pin)\n\noauth_params = {:consumer => consumer, :token => access_token}\n\n\nresponse = delete_list(delete_list_url, oauth_params)\nputs response.code, JSON.pretty_generate(JSON.parse(response.body))\n"
  },
  {
    "path": "ruby/lists/follow_list.rb",
    "content": "# This script implements the PIN-based OAuth flow to obtain access tokens for a user context request\nrequire 'oauth'\nrequire 'json'\nrequire 'typhoeus'\nrequire 'oauth/request_proxy/typhoeus_request'\n\n# The code below sets the consumer key and secret from your environment variables\n# To set environment variables on Mac OS X, run the export command below from the terminal:\n# export CONSUMER_KEY='YOUR-KEY', CONSUMER_SECRET='YOUR-SECRET'\nconsumer_key = ENV[\"CONSUMER_KEY\"]\nconsumer_secret = ENV[\"CONSUMER_SECRET\"]\n\n# Be sure to replace your-user-id with your own user ID or one of an authenticating user\n# You can find a user ID by using the user lookup endpoint\nid = \"your-user-id\"\n\nfollowing_url = \"https://api.x.com/2/users/#{id}/followed_lists\"\n\n# Be sure to add replace list-id-to-follow with the list id you wish to follow.\n@list_id = { \"list_id\": \"list-id-to-follow\" }\n\nconsumer = OAuth::Consumer.new(consumer_key, consumer_secret,\n\t                                :site => 'https://api.x.com',\n\t                                :authorize_path => '/oauth/authenticate',\n\t                                :debug_output => false)\n\ndef get_request_token(consumer)\n\n\trequest_token = consumer.get_request_token()\n\n  return request_token\nend\n\ndef get_user_authorization(request_token)\n\tputs \"Follow this URL to have a user authorize your app: #{request_token.authorize_url()}\"\n\tputs \"Enter PIN: \"\n\tpin = gets.strip\n\n  return pin\nend\n\ndef obtain_access_token(consumer, request_token, pin)\n\ttoken = request_token.token\n\ttoken_secret = request_token.secret\n\thash = { :oauth_token => token, :oauth_token_secret => token_secret }\n\trequest_token  = OAuth::RequestToken.from_hash(consumer, hash)\n\n\t# Get access token\n\taccess_token = request_token.get_access_token({:oauth_verifier => pin})\n\n\treturn access_token\nend\n\n\ndef follow_list(url, oauth_params)\n\toptions = {\n\t    :method => :post,\n\t    headers: {\n\t     \t\"User-Agent\": \"v2followListRuby\",\n        \"content-type\": \"application/json\"\n\t    },\n\t    body: JSON.dump(@list_id)\n\t}\n\trequest = Typhoeus::Request.new(url, options)\n\toauth_helper = OAuth::Client::Helper.new(request, oauth_params.merge(:request_uri => url))\n\trequest.options[:headers].merge!({\"Authorization\" => oauth_helper.header}) # Signs the request\n\tresponse = request.run\n\n\treturn response\nend\n\n\n\n# PIN-based OAuth flow - Step 1\nrequest_token = get_request_token(consumer)\n# PIN-based OAuth flow - Step 2\npin = get_user_authorization(request_token)\n# PIN-based OAuth flow - Step 3\naccess_token = obtain_access_token(consumer, request_token, pin)\n\noauth_params = {:consumer => consumer, :token => access_token}\n\n\nresponse = follow_list(following_url, oauth_params)\nputs response.code, JSON.pretty_generate(JSON.parse(response.body))\n"
  },
  {
    "path": "ruby/lists/list-followers-lookup.rb",
    "content": "# This script uses your bearer token to authenticate and retrieve followers of a List specified by List ID\n\nrequire 'json'\nrequire 'typhoeus'\n\n# The code below sets the bearer token from your environment variables\n# To set environment variables on Mac OS X, run the export command below from the terminal:\n# export BEARER_TOKEN='YOUR-TOKEN'\nbearer_token = ENV[\"BEARER_TOKEN\"]\n\n# Be sure to replace list-id with any List ID\nid = \"list-id\"\nurl = \"https://api.x.com/2/lists/#{id}/followers\"\n\n\nparams = {\n    # User fields are adjustable, options include:\n    # created_at, description, entities, id, location, name,\n    # pinned_tweet_id, profile_image_url, protected,\n    # public_metrics, url, username, verified, and withheld\n  \"user.fields\": \"created_at,verified\",\n}\n\ndef lists(url, bearer_token, params)\n  options = {\n    method: 'get',\n    headers: {\n      \"User-Agent\": \"v2ListFollowersLookupRuby\",\n      \"Authorization\": \"Bearer #{bearer_token}\"\n    },\n    params: params\n  }\n\n  request = Typhoeus::Request.new(url, options)\n  response = request.run\n\n  return response\nend\n\nresponse = lists(url, bearer_token, params)\nputs response.code, JSON.pretty_generate(JSON.parse(response.body))\n"
  },
  {
    "path": "ruby/lists/list-lookup-by-id.rb",
    "content": "# This script uses your bearer token to authenticate and retrieve the specified List objects (by ID)\n\nrequire 'json'\nrequire 'typhoeus'\n\n# The code below sets the bearer token from your environment variables\n# To set environment variables on Mac OS X, run the export command below from the terminal:\n# export BEARER_TOKEN='YOUR-TOKEN'\nbearer_token = ENV[\"BEARER_TOKEN\"]\n\n# Be sure to replace list-id with any List ID\nid = \"list-id\"\nurl = \"https://api.x.com/2/lists/#{id}\"\n\n\nparams = {\n    # List fields are adjustable, options include:\n    # created_at, description, owner_id,\n    # private, follower_count, member_count,\n  \"list.fields\": \"created_at,follower_count\",\n}\n\ndef lists(url, bearer_token, params)\n  options = {\n    method: 'get',\n    headers: {\n      \"User-Agent\": \"v2ListLookupRuby\",\n      \"Authorization\": \"Bearer #{bearer_token}\"\n    },\n    params: params\n  }\n\n  request = Typhoeus::Request.new(url, options)\n  response = request.run\n\n  return response\nend\n\nresponse = lists(url, bearer_token, params)\nputs response.code, JSON.pretty_generate(JSON.parse(response.body))\n"
  },
  {
    "path": "ruby/lists/list-member-lookup.rb",
    "content": "# This script uses your bearer token to authenticate and retrieve members of a List specified by List ID\n\nrequire 'json'\nrequire 'typhoeus'\n\n# The code below sets the bearer token from your environment variables\n# To set environment variables on Mac OS X, run the export command below from the terminal:\n# export BEARER_TOKEN='YOUR-TOKEN'\nbearer_token = ENV[\"BEARER_TOKEN\"]\n\n# Be sure to replace list-id with any List ID\nid = \"list-id\"\nurl = \"https://api.x.com/2/lists/#{id}/members\"\n\n\nparams = {\n    # User fields are adjustable, options include:\n    # created_at, description, entities, id, location, name,\n    # pinned_tweet_id, profile_image_url, protected,\n    # public_metrics, url, username, verified, and withheld\n  \"user.fields\": \"created_at,verified\",\n}\n\ndef lists(url, bearer_token, params)\n  options = {\n    method: 'get',\n    headers: {\n      \"User-Agent\": \"v2ListMembersLookupRuby\",\n      \"Authorization\": \"Bearer #{bearer_token}\"\n    },\n    params: params\n  }\n\n  request = Typhoeus::Request.new(url, options)\n  response = request.run\n\n  return response\nend\n\nresponse = lists(url, bearer_token, params)\nputs response.code, JSON.pretty_generate(JSON.parse(response.body))\n"
  },
  {
    "path": "ruby/lists/lookup.rb",
    "content": "# List Lookup - X API v2\n#\n# Endpoint: GET https://api.x.com/2/lists/:id\n# Docs: https://developer.x.com/en/docs/twitter-api/lists/list-lookup/api-reference/get-lists-id\n#\n# Authentication: Bearer Token (App-only) or OAuth (User Context)\n# Required env vars: BEARER_TOKEN\n\nrequire 'json'\nrequire 'typhoeus'\n\nbearer_token = ENV[\"BEARER_TOKEN\"]\n\n# Replace with the list ID you want to look up\nlist_id = \"84839422\"\nurl = \"https://api.x.com/2/lists/#{list_id}\"\n\nquery_params = {\n  \"list.fields\": \"created_at,follower_count,member_count,owner_id,description\"\n}\n\ndef lookup_list(url, bearer_token, query_params)\n  options = {\n    method: 'get',\n    headers: {\n      \"User-Agent\": \"v2ListLookupRuby\",\n      \"Authorization\": \"Bearer #{bearer_token}\"\n    },\n    params: query_params\n  }\n\n  request = Typhoeus::Request.new(url, options)\n  response = request.run\n\n  return response\nend\n\nresponse = lookup_list(url, bearer_token, query_params)\nputs response.code, JSON.pretty_generate(JSON.parse(response.body))\n"
  },
  {
    "path": "ruby/lists/pin_list.rb",
    "content": "# This script implements the PIN-based OAuth flow to obtain access tokens for a user context request\nrequire 'oauth'\nrequire 'json'\nrequire 'typhoeus'\nrequire 'oauth/request_proxy/typhoeus_request'\n\n# The code below sets the consumer key and secret from your environment variables\n# To set environment variables on Mac OS X, run the export command below from the terminal:\n# export CONSUMER_KEY='YOUR-KEY', CONSUMER_SECRET='YOUR-SECRET'\nconsumer_key = ENV[\"CONSUMER_KEY\"]\nconsumer_secret = ENV[\"CONSUMER_SECRET\"]\n\n# Be sure to replace your-user-id with your own user ID or one of an authenticating user\n# You can find a user ID by using the user lookup endpoint\nid = \"your-user-id\"\n\npin_url = \"https://api.x.com/2/users/#{id}/pinned_lists\"\n\n# Be sure to add replace list-id-to-pin with the list id you wish to pin.\n@list_id = { \"list_id\": \"list-id-to-pin\" }\n\nconsumer = OAuth::Consumer.new(consumer_key, consumer_secret,\n\t                                :site => 'https://api.x.com',\n\t                                :authorize_path => '/oauth/authenticate',\n\t                                :debug_output => false)\n\ndef get_request_token(consumer)\n\n\trequest_token = consumer.get_request_token()\n\n  return request_token\nend\n\ndef get_user_authorization(request_token)\n\tputs \"Follow this URL to have a user authorize your app: #{request_token.authorize_url()}\"\n\tputs \"Enter PIN: \"\n\tpin = gets.strip\n\n  return pin\nend\n\ndef obtain_access_token(consumer, request_token, pin)\n\ttoken = request_token.token\n\ttoken_secret = request_token.secret\n\thash = { :oauth_token => token, :oauth_token_secret => token_secret }\n\trequest_token  = OAuth::RequestToken.from_hash(consumer, hash)\n\n\t# Get access token\n\taccess_token = request_token.get_access_token({:oauth_verifier => pin})\n\n\treturn access_token\nend\n\n\ndef pin_list(url, oauth_params)\n\toptions = {\n\t    :method => :post,\n\t    headers: {\n\t     \t\"User-Agent\": \"v2pinListRuby\",\n        \"content-type\": \"application/json\"\n\t    },\n\t    body: JSON.dump(@list_id)\n\t}\n\trequest = Typhoeus::Request.new(url, options)\n\toauth_helper = OAuth::Client::Helper.new(request, oauth_params.merge(:request_uri => url))\n\trequest.options[:headers].merge!({\"Authorization\" => oauth_helper.header}) # Signs the request\n\tresponse = request.run\n\n\treturn response\nend\n\n\n\n# PIN-based OAuth flow - Step 1\nrequest_token = get_request_token(consumer)\n# PIN-based OAuth flow - Step 2\npin = get_user_authorization(request_token)\n# PIN-based OAuth flow - Step 3\naccess_token = obtain_access_token(consumer, request_token, pin)\n\noauth_params = {:consumer => consumer, :token => access_token}\n\n\nresponse = pin_list(pin_url, oauth_params)\nputs response.code, JSON.pretty_generate(JSON.parse(response.body))\n"
  },
  {
    "path": "ruby/lists/remove_member.rb",
    "content": "# This script implements the PIN-based OAuth flow to obtain access tokens for a user context request\nrequire 'oauth'\nrequire 'json'\nrequire 'typhoeus'\nrequire 'oauth/request_proxy/typhoeus_request'\n\n# The code below sets the consumer key and secret from your environment variables\n# To set environment variables on Mac OS X, run the export command below from the terminal:\n# export CONSUMER_KEY='YOUR-KEY', CONSUMER_SECRET='YOUR-SECRET'\nconsumer_key = ENV[\"CONSUMER_KEY\"]\nconsumer_secret = ENV[\"CONSUMER_SECRET\"]\n\n# Be sure to replace your-list-id with your own list ID or one of an authenticating user\nid = \"your-list-id\"\n\n# Be sure to replace user-id-to-remove with the user id you wish to remove.\nuser_id = \"user-id-to-remove\" \n\nmember_url = \"https://api.x.com/2/lists/#{id}/members/#{user_id}\"\n\nconsumer = OAuth::Consumer.new(consumer_key, consumer_secret,\n\t                                :site => 'https://api.x.com',\n\t                                :authorize_path => '/oauth/authenticate',\n\t                                :debug_output => false)\n\ndef get_request_token(consumer)\n\n\trequest_token = consumer.get_request_token()\n\n  return request_token\nend\n\ndef get_user_authorization(request_token)\n\tputs \"Follow this URL to have a user authorize your app: #{request_token.authorize_url()}\"\n\tputs \"Enter PIN: \"\n\tpin = gets.strip\n\n  return pin\nend\n\ndef obtain_access_token(consumer, request_token, pin)\n\ttoken = request_token.token\n\ttoken_secret = request_token.secret\n\thash = { :oauth_token => token, :oauth_token_secret => token_secret }\n\trequest_token  = OAuth::RequestToken.from_hash(consumer, hash)\n\n\t# Get access token\n\taccess_token = request_token.get_access_token({:oauth_verifier => pin})\n\n\treturn access_token\nend\n\n\ndef remove_member(url, oauth_params)\n\toptions = {\n\t    :method => :delete,\n\t    headers: {\n\t     \t\"User-Agent\": \"v2removeMemberRuby\",\n        \"content-type\": \"application/json\"\n\t    }\n\t}\n\trequest = Typhoeus::Request.new(url, options)\n\toauth_helper = OAuth::Client::Helper.new(request, oauth_params.merge(:request_uri => url))\n\trequest.options[:headers].merge!({\"Authorization\" => oauth_helper.header}) # Signs the request\n\tresponse = request.run\n\n\treturn response\nend\n\n\n\n# PIN-based OAuth flow - Step 1\nrequest_token = get_request_token(consumer)\n# PIN-based OAuth flow - Step 2\npin = get_user_authorization(request_token)\n# PIN-based OAuth flow - Step 3\naccess_token = obtain_access_token(consumer, request_token, pin)\n\noauth_params = {:consumer => consumer, :token => access_token}\n\n\nresponse = remove_member(member_url, oauth_params)\nputs response.code, JSON.pretty_generate(JSON.parse(response.body))\n"
  },
  {
    "path": "ruby/lists/unfollow_list.rb",
    "content": "# This script implements the PIN-based OAuth flow to obtain access tokens for a user context request\nrequire 'oauth'\nrequire 'json'\nrequire 'typhoeus'\nrequire 'oauth/request_proxy/typhoeus_request'\n\n# The code below sets the consumer key and secret from your environment variables\n# To set environment variables on Mac OS X, run the export command below from the terminal:\n# export CONSUMER_KEY='YOUR-KEY', CONSUMER_SECRET='YOUR-SECRET'\nconsumer_key = ENV[\"CONSUMER_KEY\"]\nconsumer_secret = ENV[\"CONSUMER_SECRET\"]\n\n# Be sure to replace your-user-id with your own user ID or one of an authenticating user\n# You can find a user ID by using the user lookup endpoint\nid = \"your-user-id\"\n\n# Be sure to add replace list-id-to-unfollow with the user id of the user you wish to unfollow.\nlist_id = \"list-id-to-unfollow\"\n\n# Returns a user object for one or more users specified by the requested usernames\nunfollow_url = \"https://api.x.com/2/users/#{id}/followed_lists/#{list_id}\"\n\nconsumer = OAuth::Consumer.new(consumer_key, consumer_secret,\n\t                                :site => 'https://api.x.com',\n\t                                :authorize_path => '/oauth/authenticate',\n\t                                :debug_output => false)\n\ndef get_request_token(consumer)\n\n\trequest_token = consumer.get_request_token()\n\n  return request_token\nend\n\ndef get_user_authorization(request_token)\n\tputs \"Follow this URL to have a user authorize your app: #{request_token.authorize_url()}\"\n\tputs \"Enter PIN: \"\n\tpin = gets.strip\n\n  return pin\nend\n\ndef obtain_access_token(consumer, request_token, pin)\n\ttoken = request_token.token\n\ttoken_secret = request_token.secret\n\thash = { :oauth_token => token, :oauth_token_secret => token_secret }\n\trequest_token  = OAuth::RequestToken.from_hash(consumer, hash)\n\n\t# Get access token\n\taccess_token = request_token.get_access_token({:oauth_verifier => pin})\n\n\treturn access_token\nend\n\n\ndef unfollow_list(url, oauth_params)\n\toptions = {\n\t    :method => :delete,\n\t    headers: {\n\t     \t\"User-Agent\": \"v2unfollowListRuby\"\n\t    }\n\t}\n\trequest = Typhoeus::Request.new(url, options)\n\toauth_helper = OAuth::Client::Helper.new(request, oauth_params.merge(:request_uri => url))\n\trequest.options[:headers].merge!({\"Authorization\" => oauth_helper.header}) # Signs the request\n\tresponse = request.run\n\n\treturn response\nend\n\n# PIN-based OAuth flow - Step 1\nrequest_token = get_request_token(consumer)\n# PIN-based OAuth flow - Step 2\npin = get_user_authorization(request_token)\n# PIN-based OAuth flow - Step 3\naccess_token = obtain_access_token(consumer, request_token, pin)\n\noauth_params = {:consumer => consumer, :token => access_token}\n\nresponse = unfollow_list(unfollow_url, oauth_params)\nputs response.code, JSON.pretty_generate(JSON.parse(response.body))\n"
  },
  {
    "path": "ruby/lists/unpin_list.rb",
    "content": "# This script implements the PIN-based OAuth flow to obtain access tokens for a user context request\nrequire 'oauth'\nrequire 'json'\nrequire 'typhoeus'\nrequire 'oauth/request_proxy/typhoeus_request'\n\n# The code below sets the consumer key and secret from your environment variables\n# To set environment variables on Mac OS X, run the export command below from the terminal:\n# export CONSUMER_KEY='YOUR-KEY', CONSUMER_SECRET='YOUR-SECRET'\nconsumer_key = ENV[\"CONSUMER_KEY\"]\nconsumer_secret = ENV[\"CONSUMER_SECRET\"]\n\n# Be sure to replace your-user-id with your own user ID or one of an authenticating user\n# You can find a user ID by using the user lookup endpoint\nid = \"your-user-id\"\n\n# Be sure to add replace list-id-to-unpin with the user id of the user you wish to unpin.\nlist_id = \"list-id-to-unpin\"\n\n# Returns a user object for one or more users specified by the requested usernames\nunpin_url = \"https://api.x.com/2/users/#{id}/pinned_lists/#{list_id}\"\n\nconsumer = OAuth::Consumer.new(consumer_key, consumer_secret,\n\t                                :site => 'https://api.x.com',\n\t                                :authorize_path => '/oauth/authenticate',\n\t                                :debug_output => false)\n\ndef get_request_token(consumer)\n\n\trequest_token = consumer.get_request_token()\n\n  return request_token\nend\n\ndef get_user_authorization(request_token)\n\tputs \"Follow this URL to have a user authorize your app: #{request_token.authorize_url()}\"\n\tputs \"Enter PIN: \"\n\tpin = gets.strip\n\n  return pin\nend\n\ndef obtain_access_token(consumer, request_token, pin)\n\ttoken = request_token.token\n\ttoken_secret = request_token.secret\n\thash = { :oauth_token => token, :oauth_token_secret => token_secret }\n\trequest_token  = OAuth::RequestToken.from_hash(consumer, hash)\n\n\t# Get access token\n\taccess_token = request_token.get_access_token({:oauth_verifier => pin})\n\n\treturn access_token\nend\n\n\ndef unpin_list(url, oauth_params)\n\toptions = {\n\t    :method => :delete,\n\t    headers: {\n\t     \t\"User-Agent\": \"v2unpinListRuby\"\n\t    }\n\t}\n\trequest = Typhoeus::Request.new(url, options)\n\toauth_helper = OAuth::Client::Helper.new(request, oauth_params.merge(:request_uri => url))\n\trequest.options[:headers].merge!({\"Authorization\" => oauth_helper.header}) # Signs the request\n\tresponse = request.run\n\n\treturn response\nend\n\n# PIN-based OAuth flow - Step 1\nrequest_token = get_request_token(consumer)\n# PIN-based OAuth flow - Step 2\npin = get_user_authorization(request_token)\n# PIN-based OAuth flow - Step 3\naccess_token = obtain_access_token(consumer, request_token, pin)\n\noauth_params = {:consumer => consumer, :token => access_token}\n\nresponse = unpin_list(unpin_url, oauth_params)\nputs response.code, JSON.pretty_generate(JSON.parse(response.body))\n"
  },
  {
    "path": "ruby/lists/update_a_list.rb",
    "content": "# This script implements the PIN-based OAuth flow to obtain access tokens for a user context request\n# It then makes a User lookup request (by usernames) with OAuth 1.0a authentication (user context)\nrequire 'oauth'\nrequire 'json'\nrequire 'typhoeus'\nrequire 'oauth/request_proxy/typhoeus_request'\n\n# The code below sets the consumer key and secret from your environment variables\n# To set environment variables on Mac OS X, run the export command below from the terminal:\n# export CONSUMER_KEY='YOUR-KEY', CONSUMER_SECRET='YOUR-SECRET'\nconsumer_key = ENV[\"CONSUMER_KEY\"]\nconsumer_secret = ENV[\"CONSUMER_SECRET\"]\n\n# Be sure to add replace update-name-of-list with the name you wish to call the list.\n# name, description and private are all optional\n@json_payload = {  \"name\": \"update-name-of-list-ruby\",\n  \"description\": \"update-description-of-list\",\n  \"private\": false}\n  \n# Be sure to replace your-list-id with the id of the list you wish to update. The authenticated user must own the list in order to update\nid = \"your-list-id\"\n\nupdate_list_url = \"https://api.x.com/2/lists/#{id}\"\n\n\nconsumer = OAuth::Consumer.new(consumer_key, consumer_secret,\n\t                                :site => 'https://api.x.com',\n\t                                :authorize_path => '/oauth/authenticate',\n\t                                :debug_output => false)\n\ndef get_request_token(consumer)\n\n\trequest_token = consumer.get_request_token()\n\n  return request_token\nend\n\ndef get_user_authorization(request_token)\n\tputs \"Follow this URL to have a user authorize your app: #{request_token.authorize_url()}\"\n\tputs \"Enter PIN: \"\n\tpin = gets.strip\n\n  return pin\nend\n\ndef obtain_access_token(consumer, request_token, pin)\n\ttoken = request_token.token\n\ttoken_secret = request_token.secret\n\thash = { :oauth_token => token, :oauth_token_secret => token_secret }\n\trequest_token  = OAuth::RequestToken.from_hash(consumer, hash)\n\n\t# Get access token\n\taccess_token = request_token.get_access_token({:oauth_verifier => pin})\n\n\treturn access_token\nend\n\n\ndef update_list(url, oauth_params)\n\toptions = {\n\t    :method => :put,\n\t    headers: {\n\t     \t\"User-Agent\": \"v2updateListRuby\",\n        \"content-type\": \"application/json\"\n\t    },\n\t    body: JSON.dump(@json_payload)\n\t}\n\trequest = Typhoeus::Request.new(url, options)\n\toauth_helper = OAuth::Client::Helper.new(request, oauth_params.merge(:request_uri => url))\n\trequest.options[:headers].merge!({\"Authorization\" => oauth_helper.header}) # Signs the request\n\tresponse = request.run\n\n\treturn response\nend\n\n\n\n# PIN-based OAuth flow - Step 1\nrequest_token = get_request_token(consumer)\n# PIN-based OAuth flow - Step 2\npin = get_user_authorization(request_token)\n# PIN-based OAuth flow - Step 3\naccess_token = obtain_access_token(consumer, request_token, pin)\n\noauth_params = {:consumer => consumer, :token => access_token}\n\n\nresponse = update_list(update_list_url, oauth_params)\nputs response.code, JSON.pretty_generate(JSON.parse(response.body))\n"
  },
  {
    "path": "ruby/lists/user-list-followed.rb",
    "content": "# This script uses your bearer token to authenticate and retrieve the specified List objects (by user ID)\n\nrequire 'json'\nrequire 'typhoeus'\n\n# The code below sets the bearer token from your environment variables\n# To set environment variables on Mac OS X, run the export command below from the terminal:\n# export BEARER_TOKEN='YOUR-TOKEN'\nbearer_token = ENV[\"BEARER_TOKEN\"]\n\n# Be sure to replace user-id with any User ID\nid = \"user-id\"\nurl = \"https://api.x.com/2/users/#{id}/followed_lists\"\n\n\nparams = {\n    # List fields are adjustable, options include:\n    # created_at, description, owner_id,\n    # private, follower_count, member_count,\n  \"list.fields\": \"created_at,private\",\n}\n\ndef lists(url, bearer_token, params)\n  options = {\n    method: 'get',\n    headers: {\n      \"User-Agent\": \"v2userMembershipsRuby\",\n      \"Authorization\": \"Bearer #{bearer_token}\"\n    },\n    params: params\n  }\n\n  request = Typhoeus::Request.new(url, options)\n  response = request.run\n\n  return response\nend\n\nresponse = lists(url, bearer_token, params)\nputs response.code, JSON.pretty_generate(JSON.parse(response.body))\n"
  },
  {
    "path": "ruby/lists/user-list-memberships.rb",
    "content": "# This script uses your bearer token to authenticate and retrieve the specified List objects (by user ID)\n\nrequire 'json'\nrequire 'typhoeus'\n\n# The code below sets the bearer token from your environment variables\n# To set environment variables on Mac OS X, run the export command below from the terminal:\n# export BEARER_TOKEN='YOUR-TOKEN'\nbearer_token = ENV[\"BEARER_TOKEN\"]\n\n# Be sure to replace user-id with any User ID\nid = \"user-id\"\nurl = \"https://api.x.com/2/users/#{id}/list_memberships\"\n\n\nparams = {\n    # List fields are adjustable, options include:\n    # created_at, description, owner_id,\n    # private, follower_count, member_count,\n  \"list.fields\": \"created_at,private\",\n}\n\ndef lists(url, bearer_token, params)\n  options = {\n    method: 'get',\n    headers: {\n      \"User-Agent\": \"v2userMembershipsRuby\",\n      \"Authorization\": \"Bearer #{bearer_token}\"\n    },\n    params: params\n  }\n\n  request = Typhoeus::Request.new(url, options)\n  response = request.run\n\n  return response\nend\n\nresponse = lists(url, bearer_token, params)\nputs response.code, JSON.pretty_generate(JSON.parse(response.body))\n"
  },
  {
    "path": "ruby/lists/user-owned-list-lookup.rb",
    "content": "# This script uses your bearer token to authenticate and retrieve any user owned Lists specified by user ID\n\nrequire 'json'\nrequire 'typhoeus'\n\n# The code below sets the bearer token from your environment variables\n# To set environment variables on Mac OS X, run the export command below from the terminal:\n# export BEARER_TOKEN='YOUR-TOKEN'\nbearer_token = ENV[\"BEARER_TOKEN\"]\n\n    # You can replace the ID with the User ID to see if they own any Lists.\nid = \"user-id\"\nurl = \"https://api.x.com/2/users/#{id}/owned_lists\"\n\n\nparams = {\n    # List fields are adjustable, options include:\n    # created_at, description, owner_id,\n    # private, follower_count, member_count,\n  \"list.fields\": \"created_at,follower_count\",\n}\n\ndef lists(url, bearer_token, params)\n  options = {\n    method: 'get',\n    headers: {\n      \"User-Agent\": \"v2ListLookupRuby\",\n      \"Authorization\": \"Bearer #{bearer_token}\"\n    },\n    params: params\n  }\n\n  request = Typhoeus::Request.new(url, options)\n  response = request.run\n\n  return response\nend\n\nresponse = lists(url, bearer_token, params)\nputs response.code, JSON.pretty_generate(JSON.parse(response.body))\n"
  },
  {
    "path": "ruby/posts/create_tweet.rb",
    "content": "require 'oauth'\nrequire 'json'\nrequire 'typhoeus'\nrequire 'oauth/request_proxy/typhoeus_request'\n\n# The code below sets the consumer key and secret from your environment variables\n# To set environment variables on Mac OS X, run the export command below from the terminal:\n# export CONSUMER_KEY='YOUR-KEY', CONSUMER_SECRET='YOUR-SECRET'\nconsumer_key = ENV[\"CONSUMER_KEY\"]\nconsumer_secret = ENV[\"CONSUMER_SECRET\"]\n\n\ncreate_tweet_url = \"https://api.x.com/2/tweets\"\n\n# Be sure to add replace the text of the with the text you wish to Tweet.\n# You can also add parameters to post polls, quote Tweets, Tweet with reply settings, and Tweet to Super Followers in addition to other features.\n@json_payload = {\"text\": \"Hello world!\"}\n\nconsumer = OAuth::Consumer.new(consumer_key, consumer_secret,\n\t                                :site => 'https://api.x.com',\n\t                                :authorize_path => '/oauth/authenticate',\n\t                                :debug_output => false)\n\ndef get_request_token(consumer)\n\n\trequest_token = consumer.get_request_token()\n\n  return request_token\nend\n\ndef get_user_authorization(request_token)\n\tputs \"Follow this URL to have a user authorize your app: #{request_token.authorize_url()}\"\n\tputs \"Enter PIN: \"\n\tpin = gets.strip\n\n  return pin\nend\n\ndef obtain_access_token(consumer, request_token, pin)\n\ttoken = request_token.token\n\ttoken_secret = request_token.secret\n\thash = { :oauth_token => token, :oauth_token_secret => token_secret }\n\trequest_token  = OAuth::RequestToken.from_hash(consumer, hash)\n\n\t# Get access token\n\taccess_token = request_token.get_access_token({:oauth_verifier => pin})\n\n\treturn access_token\nend\n\n\ndef create_tweet(url, oauth_params)\n\toptions = {\n\t    :method => :post,\n\t    headers: {\n\t     \t\"User-Agent\": \"v2CreateTweetRuby\",\n        \"content-type\": \"application/json\"\n\t    },\n\t    body: JSON.dump(@json_payload)\n\t}\n\trequest = Typhoeus::Request.new(url, options)\n\toauth_helper = OAuth::Client::Helper.new(request, oauth_params.merge(:request_uri => url))\n\trequest.options[:headers].merge!({\"Authorization\" => oauth_helper.header}) # Signs the request\n\tresponse = request.run\n\n\treturn response\nend\n\n\n\n# PIN-based OAuth flow - Step 1\nrequest_token = get_request_token(consumer)\n# PIN-based OAuth flow - Step 2\npin = get_user_authorization(request_token)\n# PIN-based OAuth flow - Step 3\naccess_token = obtain_access_token(consumer, request_token, pin)\n\noauth_params = {:consumer => consumer, :token => access_token}\n\n\nresponse = create_tweet(create_tweet_url, oauth_params)\nputs response.code, JSON.pretty_generate(JSON.parse(response.body))\n"
  },
  {
    "path": "ruby/posts/delete_tweet.rb",
    "content": "require 'oauth'\nrequire 'json'\nrequire 'typhoeus'\nrequire 'oauth/request_proxy/typhoeus_request'\n\n# The code below sets the consumer key and secret from your environment variables\n# To set environment variables on Mac OS X, run the export command below from the terminal:\n# export CONSUMER_KEY='YOUR-KEY', CONSUMER_SECRET='YOUR-SECRET'\nconsumer_key = ENV[\"CONSUMER_KEY\"]\nconsumer_secret = ENV[\"CONSUMER_SECRET\"]\n\n# Be sure to replace your-tweet-id with the id of the Tweet you wish to delete.\nid = \"your-tweet-id\"\n\ndelete_tweet_url = \"https://api.x.com/2/tweets/#{id}\"\n\n\nconsumer = OAuth::Consumer.new(consumer_key, consumer_secret,\n\t                                :site => 'https://api.x.com',\n\t                                :authorize_path => '/oauth/authenticate',\n\t                                :debug_output => false)\n\ndef get_request_token(consumer)\n\n\trequest_token = consumer.get_request_token()\n\n  return request_token\nend\n\ndef get_user_authorization(request_token)\n\tputs \"Follow this URL to have a user authorize your app: #{request_token.authorize_url()}\"\n\tputs \"Enter PIN: \"\n\tpin = gets.strip\n\n  return pin\nend\n\ndef obtain_access_token(consumer, request_token, pin)\n\ttoken = request_token.token\n\ttoken_secret = request_token.secret\n\thash = { :oauth_token => token, :oauth_token_secret => token_secret }\n\trequest_token  = OAuth::RequestToken.from_hash(consumer, hash)\n\n\t# Get access token\n\taccess_token = request_token.get_access_token({:oauth_verifier => pin})\n\n\treturn access_token\nend\n\n\ndef delete_tweet(url, oauth_params)\n\toptions = {\n\t    :method => :delete,\n\t    headers: {\n\t     \t\"User-Agent\": \"v2DeleteTweetRuby\",\n        \"content-type\": \"application/json\"\n\t    }\n\t}\n\trequest = Typhoeus::Request.new(url, options)\n\toauth_helper = OAuth::Client::Helper.new(request, oauth_params.merge(:request_uri => url))\n\trequest.options[:headers].merge!({\"Authorization\" => oauth_helper.header}) # Signs the request\n\tresponse = request.run\n\n\treturn response\nend\n\n\n\n# PIN-based OAuth flow - Step 1\nrequest_token = get_request_token(consumer)\n# PIN-based OAuth flow - Step 2\npin = get_user_authorization(request_token)\n# PIN-based OAuth flow - Step 3\naccess_token = obtain_access_token(consumer, request_token, pin)\n\noauth_params = {:consumer => consumer, :token => access_token}\n\n\nresponse = delete_tweet(delete_tweet_url, oauth_params)\n"
  },
  {
    "path": "ruby/posts/full-archive-search.rb",
    "content": "# This script uses your bearer token to authenticate and make a Search request\n\nrequire 'json'\nrequire 'typhoeus'\n\n# The code below sets the bearer token from your environment variables\n# To set environment variables on Mac OS X, run the export command below from the terminal:\n# export BEARER_TOKEN='YOUR-TOKEN'\nbearer_token = ENV[\"BEARER_TOKEN\"]\n\n# Endpoint URL for the Full-archive Search API\nsearch_url = \"https://api.x.com/2/tweets/search/all\"\n\n# Set the query value here. Value can be up to 512 characters\nquery = \"from:Twitter OR from:TwitterDev OR from:DailyNasa\"\n\n# Add or remove parameters below to adjust the query and response fields within the payload\n# See docs for list of param options: https://developer.twitter.com/en/docs/twitter-api/tweets/search/api-reference/get-tweets-search-all\nquery_params = {\n  \"query\": query, # Required\n  \"max_results\": 10,\n  # \"start_time\": \"2020-07-01T00:00:00Z\",\n  # \"end_time\": \"2020-07-02T18:00:00Z\",\n  # \"expansions\": \"attachments.poll_ids,attachments.media_keys,author_id\",\n  \"tweet.fields\": \"attachments,author_id,conversation_id,created_at,entities,id,lang\",\n  \"user.fields\": \"description\"\n  # \"media.fields\": \"url\", \n  # \"place.fields\": \"country_code\",\n  # \"poll.fields\": \"options\"\n}\n\ndef search_tweets(url, bearer_token, query_params)\n  options = {\n    method: 'get',\n    headers: {\n      \"User-Agent\": \"v2FullArchiveSearchRuby\",\n      \"Authorization\": \"Bearer #{bearer_token}\"\n    },\n    params: query_params\n  }\n\n  request = Typhoeus::Request.new(url, options)\n  response = request.run\n\n  return response\nend\n\nresponse = search_tweets(search_url, bearer_token, query_params)\nputs response.code, JSON.pretty_generate(JSON.parse(response.body))\n"
  },
  {
    "path": "ruby/posts/full_archive_tweet_counts.rb",
    "content": "# This script uses your bearer token to authenticate and make a Search request\n\nrequire 'json'\nrequire 'typhoeus'\n\n# The code below sets the bearer token from your environment variables\n# To set environment variables on Mac OS X, run the export command below from the terminal:\n# export BEARER_TOKEN='YOUR-TOKEN'\nbearer_token = ENV[\"BEARER_TOKEN\"]\n\n# Endpoint URL for the Full-archive Search API\nsearch_url = \"https://api.x.com/2/tweets/counts/all\"\n\n# Set the query value here. Value can be up to 1024 characters\nquery = \"from:TwitterDev\"\n\n# Add or remove parameters below to adjust the query and response fields within the payload\n# See docs for list of param options: https://developer.twitter.com/en/docs/twitter-api/tweets/search/api-reference/get-tweets-counts-all\nquery_params = {\n  \"query\": query, # Required\n  \"start_time\": \"2021-01-01T00:00:00Z\",\n  \"granularity\": \"day\"\n}\n\ndef get_tweet_counts(url, bearer_token, query_params)\n  options = {\n    method: 'get',\n    headers: {\n      \"User-Agent\": \"v2FullArchiveTweetCountsRuby\",\n      \"Authorization\": \"Bearer #{bearer_token}\"\n    },\n    params: query_params\n  }\n\n  request = Typhoeus::Request.new(url, options)\n  response = request.run\n\n  return response\nend\n\nresponse = get_tweet_counts(search_url, bearer_token, query_params)\nputs response.code, JSON.pretty_generate(JSON.parse(response.body))\n"
  },
  {
    "path": "ruby/posts/get_tweets_with_bearer_token.rb",
    "content": "# This script uses your bearer token to authenticate and retrieve the specified Tweet objects (by ID)\n\nrequire 'json'\nrequire 'typhoeus'\n\n# The code below sets the bearer token from your environment variables\n# To set environment variables on Mac OS X, run the export command below from the terminal:\n# export BEARER_TOKEN='YOUR-TOKEN'\nbearer_token = ENV[\"BEARER_TOKEN\"]\n\ntweet_lookup_url = \"https://api.x.com/2/tweets\"\n\n# Specify the Tweet IDs that you want to lookup below (to 100 per request)\ntweet_ids = \"1261326399320715264,1278347468690915330\"\n\n# Add or remove optional parameters values from the params object below. Full list of parameters and their values can be found in the docs:\n# https://developer.twitter.com/en/docs/twitter-api/tweets/lookup/api-reference\nparams = {\n\t\"ids\": tweet_ids,\n  # \"expansions\": \"author_id,referenced_tweets.id\",\n  \"tweet.fields\": \"attachments,author_id,conversation_id,created_at,entities,geo,id,in_reply_to_user_id,lang\",\n  # \"user.fields\": \"name\"\n  # \"media.fields\": \"url\", \n  # \"place.fields\": \"country_code\",\n  # \"poll.fields\": \"options\"\n}\n\ndef tweet_lookup(url, bearer_token, params)\n  options = {\n    method: 'get',\n    headers: {\n      \"User-Agent\": \"v2TweetLookupRuby\",\n      \"Authorization\": \"Bearer #{bearer_token}\"\n    },\n    params: params\n  }\n\n  request = Typhoeus::Request.new(url, options)\n  response = request.run\n\n  return response\nend\n\nresponse = tweet_lookup(tweet_lookup_url, bearer_token, params)\nputs response.code, JSON.pretty_generate(JSON.parse(response.body))\n"
  },
  {
    "path": "ruby/posts/get_tweets_with_user_context.rb",
    "content": "# This script implements the PIN-based OAuth flow to obtain access tokens for a user context request\n# It then makes a Tweet lookup request (by IDs) with OAuth 1.0a authentication (user context)\n\nrequire 'oauth'\nrequire 'json'\nrequire 'typhoeus'\nrequire 'oauth/request_proxy/typhoeus_request'\n\n# The code below sets the consumer key and secret from your environment variables\n# To set environment variables on Mac OS X, run the export command below from the terminal:\n# export CONSUMER_KEY='YOUR-KEY', CONSUMER_SECRET='YOUR-SECRET'\nconsumer_key = ENV[\"CONSUMER_KEY\"]\nconsumer_secret = ENV[\"CONSUMER_SECRET\"]\n\n# Returns a Tweet object for one or more Tweets IDs as specified by the request\ntweet_lookup_url = \"https://api.x.com/2/tweets\"\n\n# Specify the Tweet IDs that you want to lookup below (to 100 per request)\ntweet_ids = \"1261326399320715264,1278347468690915330\"\n\n# Add or remove optional parameters values from the params object below. Full list of parameters and their values can be found in the docs:\n# https://developer.twitter.com/en/docs/twitter-api/tweets/lookup/api-reference\nquery_params = {\n\t\"ids\": tweet_ids,\n  # \"expansions\": \"author_id,referenced_tweets.id\",\n  \"tweet.fields\": \"attachments,author_id,conversation_id,created_at,entities,geo,id,in_reply_to_user_id,lang\",\n  # \"user.fields\": \"name\"\n  # \"media.fields\": \"url\", \n  # \"place.fields\": \"country_code\",\n  # \"poll.fields\": \"options\"\n}\n\nconsumer = OAuth::Consumer.new(consumer_key, consumer_secret,\n\t                                :site => 'https://api.x.com',\n\t                                :authorize_path => '/oauth/authenticate',\n\t                                :debug_output => false)\n\ndef get_request_token(consumer)\n\n\trequest_token = consumer.get_request_token()\n\n  return request_token\nend\n\ndef get_user_authorization(request_token)\n\tputs \"Follow this URL to have a user authorize your app: #{request_token.authorize_url()}\"\n\tputs \"Enter PIN: \"\n\tpin = gets.strip\n  \n  return pin\nend\n\ndef obtain_access_token(consumer, request_token, pin)\n\ttoken = request_token.token\n\ttoken_secret = request_token.secret\n\thash = { :oauth_token => token, :oauth_token_secret => token_secret }\n\trequest_token  = OAuth::RequestToken.from_hash(consumer, hash)\n\t\n\t# Get access token\n\taccess_token = request_token.get_access_token({:oauth_verifier => pin})\n\n\treturn access_token\nend\n\ndef tweet_lookup(url, oauth_params, query_params)\n\toptions = {\n\t    :method => :get,\n\t    headers: {\n\t     \t\"User-Agent\": \"v2TweetLookupRuby\"\n\t    },\n\t    params: query_params\n\t}\n\trequest = Typhoeus::Request.new(url, options)\n\toauth_helper = OAuth::Client::Helper.new(request, oauth_params.merge(:request_uri => url))\n\trequest.options[:headers].merge!({\"Authorization\" => oauth_helper.header}) # Signs the request\n\tresponse = request.run\n\n\treturn response\nend\n\n# PIN-based OAuth flow - Step 1\nrequest_token = get_request_token(consumer)\n# PIN-based OAuth flow - Step 2\npin = get_user_authorization(request_token)\n# PIN-based OAuth flow - Step 3\naccess_token = obtain_access_token(consumer, request_token, pin)\n\noauth_params = {:consumer => consumer, :token => access_token}\n\nresponse = tweet_lookup(tweet_lookup_url, oauth_params, query_params)\nputs response.code, JSON.pretty_generate(JSON.parse(response.body))\n"
  },
  {
    "path": "ruby/posts/like_a_tweet.rb",
    "content": "# This script implements the PIN-based OAuth flow to obtain access tokens for a user context request\n# It then makes a User lookup request (by usernames) with OAuth 1.0a authentication (user context)\nrequire 'oauth'\nrequire 'json'\nrequire 'typhoeus'\nrequire 'oauth/request_proxy/typhoeus_request'\n\n# The code below sets the consumer key and secret from your environment variables\n# To set environment variables on Mac OS X, run the export command below from the terminal:\n# export CONSUMER_KEY='YOUR-KEY', CONSUMER_SECRET='YOUR-SECRET'\nconsumer_key = ENV[\"CONSUMER_KEY\"]\nconsumer_secret = ENV[\"CONSUMER_SECRET\"]\n\n# Be sure to replace your-user-id with your own user ID or one of an authenticating user\n# You can find a user ID by using the user lookup endpoint\nid = \"your-user-id\"\nlikes_url = \"https://api.x.com/2/users/#{id}/likes\"\n\n# You can replace Tweet ID given with the Tweet ID you wish to like.\n# You can find a Tweet ID by using the Tweet lookup endpoint\n@tweet_id = { \"tweet_id\": \"1354143047324299264\" }\n\nconsumer = OAuth::Consumer.new(consumer_key, consumer_secret,\n\t                                :site => 'https://api.x.com',\n\t                                :authorize_path => '/oauth/authenticate',\n\t                                :debug_output => false)\n\ndef get_request_token(consumer)\n\n\trequest_token = consumer.get_request_token()\n\n  return request_token\nend\n\ndef get_user_authorization(request_token)\n\tputs \"Follow this URL to have a user authorize your app: #{request_token.authorize_url()}\"\n\tputs \"Enter PIN: \"\n\tpin = gets.strip\n\n  return pin\nend\n\ndef obtain_access_token(consumer, request_token, pin)\n\ttoken = request_token.token\n\ttoken_secret = request_token.secret\n\thash = { :oauth_token => token, :oauth_token_secret => token_secret }\n\trequest_token  = OAuth::RequestToken.from_hash(consumer, hash)\n\n\t# Get access token\n\taccess_token = request_token.get_access_token({:oauth_verifier => pin})\n\n\treturn access_token\nend\n\n\ndef user_like(url, oauth_params)\n\toptions = {\n\t    :method => :post,\n\t    headers: {\n\t     \t\"User-Agent\": \"v2LikeTweetRuby\",\n        \"content-type\": \"application/json\"\n\t    },\n\t    body: JSON.dump(@tweet_id)\n\t}\n\trequest = Typhoeus::Request.new(url, options)\n\toauth_helper = OAuth::Client::Helper.new(request, oauth_params.merge(:request_uri => url))\n\trequest.options[:headers].merge!({\"Authorization\" => oauth_helper.header}) # Signs the request\n\tresponse = request.run\n\n\treturn response\nend\n\n\n\n# PIN-based OAuth flow - Step 1\nrequest_token = get_request_token(consumer)\n# PIN-based OAuth flow - Step 2\npin = get_user_authorization(request_token)\n# PIN-based OAuth flow - Step 3\naccess_token = obtain_access_token(consumer, request_token, pin)\n\noauth_params = {:consumer => consumer, :token => access_token}\n\n\nresponse = user_like(likes_url, oauth_params)\nputs response.code, JSON.pretty_generate(JSON.parse(response.body))\n"
  },
  {
    "path": "ruby/posts/liked_tweets.rb",
    "content": "# This script uses your bearer token to authenticate and retrieve the specified User objects (by ID)\n\nrequire 'json'\nrequire 'typhoeus'\n\n# The code below sets the bearer token from your environment variables\n# To set environment variables on Mac OS X, run the export command below from the terminal:\n# export BEARER_TOKEN='YOUR-TOKEN'\nbearer_token = ENV[\"BEARER_TOKEN\"]\n\n# Be sure to replace your-user-id with your own user ID or one of an authenticating user\n# You can find a user ID by using the user lookup endpoint\nid = \"your-user-id\"\nurl = \"https://api.x.com/2/users/#{id}/liked_tweets\"\n\n\nparams = {\n  # Tweet fields are adjustable.\n  # Options include:\n  # attachments, author_id, context_annotations,\n  # conversation_id, created_at, entities, geo, id,\n  # in_reply_to_user_id, lang, non_public_metrics, organic_metrics,\n  # possibly_sensitive, promoted_metrics, public_metrics, referenced_tweets,\n  # source, text, and withheld\n  \"tweet.fields\": \"lang,author_id\",\n}\n\ndef liked_tweets(url, bearer_token, params)\n  options = {\n    method: 'get',\n    headers: {\n      \"User-Agent\": \"v2LikedTweetsRuby\",\n      \"Authorization\": \"Bearer #{bearer_token}\"\n    },\n    params: params\n  }\n\n  request = Typhoeus::Request.new(url, options)\n  response = request.run\n\n  return response\nend\n\nresponse = liked_tweets(url, bearer_token, params)\nputs response.code, JSON.pretty_generate(JSON.parse(response.body))\n"
  },
  {
    "path": "ruby/posts/liking_users.rb",
    "content": "# This script uses your bearer token to authenticate and retrieve the specified User objects (by ID)\n\nrequire 'json'\nrequire 'typhoeus'\n\n# The code below sets the bearer token from your environment variables\n# To set environment variables on Mac OS X, run the export command below from the terminal:\n# export BEARER_TOKEN='YOUR-TOKEN'\nbearer_token = ENV[\"BEARER_TOKEN\"]\n\n\n# You can replace the ID given with the Tweet ID you wish to like.\n# You can find an ID by using the Tweet lookup endpoint\nid = \"1354143047324299264\"\n\nurl = \"https://api.x.com/2/tweets/#{id}/liking_users\"\n\nparams = {\n  # User fields are adjustable, options include:\n  # created_at, description, entities, id, location, name,\n  # pinned_tweet_id, profile_image_url, protected,\n  # public_metrics, url, username, verified, and withheld\n  \"user.fields\": \"created_at,description\",\n}\n\ndef liking_users(url, bearer_token, params)\n  options = {\n    method: 'get',\n    headers: {\n      \"User-Agent\": \"v2LikingUsersRuby\",\n      \"Authorization\": \"Bearer #{bearer_token}\"\n    },\n    params: params\n  }\n\n  request = Typhoeus::Request.new(url, options)\n  response = request.run\n\n  return response\nend\n\nresponse = liking_users(url, bearer_token, params)\nputs response.code, JSON.pretty_generate(JSON.parse(response.body))\n"
  },
  {
    "path": "ruby/posts/lookup.rb",
    "content": "# Post Lookup - X API v2\n#\n# Endpoint: GET https://api.x.com/2/tweets\n# Docs: https://developer.x.com/en/docs/twitter-api/tweets/lookup/api-reference/get-tweets\n#\n# Authentication: Bearer Token (App-only) or OAuth (User Context)\n# Required env vars: BEARER_TOKEN\n\nrequire 'json'\nrequire 'typhoeus'\n\nbearer_token = ENV[\"BEARER_TOKEN\"]\n\n# Post IDs to look up (comma-separated, up to 100)\npost_ids = \"1278747501642657792,1255542774432063488\"\nurl = \"https://api.x.com/2/tweets\"\n\nquery_params = {\n  \"ids\": post_ids,\n  \"tweet.fields\": \"created_at,author_id,lang,source,public_metrics\"\n}\n\ndef lookup_posts(url, bearer_token, query_params)\n  options = {\n    method: 'get',\n    headers: {\n      \"User-Agent\": \"v2PostLookupRuby\",\n      \"Authorization\": \"Bearer #{bearer_token}\"\n    },\n    params: query_params\n  }\n\n  request = Typhoeus::Request.new(url, options)\n  response = request.run\n\n  return response\nend\n\nresponse = lookup_posts(url, bearer_token, query_params)\nputs response.code, JSON.pretty_generate(JSON.parse(response.body))\n"
  },
  {
    "path": "ruby/posts/quote_tweets.rb",
    "content": "# This script uses your bearer token to authenticate and make a request to the Quote Tweets endpoint.\nrequire 'json'\nrequire 'typhoeus'\n\n# The code below sets the bearer token from your environment variables\n# To set environment variables on Mac OS X, run the export command below from the terminal:\n# export BEARER_TOKEN='YOUR-TOKEN'\nbearer_token = ENV[\"BEARER_TOKEN\"]\n\n# Endpoint URL for the Quote Tweets endpoint.\nendpoint_url = \"https://api.x.com/2/tweets/:id/quote_tweets\"\n\n# Specify the Tweet ID for this request.\nid = 20\n\n# Add or remove parameters below to adjust the query and response fields within the payload\n# TODO: See docs for list of param options: https://developer.twitter.com/en/docs/twitter-api/tweets/\nquery_params = {\n  \"max_results\" => 100,\n  \"expansions\" => \"attachments.poll_ids,attachments.media_keys,author_id\",\n  \"tweet.fields\" => \"attachments,author_id,conversation_id,created_at,entities,id,lang\",\n  \"user.fields\" => \"description\"\n}\n\ndef get_quote_tweets(url, bearer_token, query_params)\n  options = {\n    method: 'get',\n    headers: {\n      \"User-Agent\" => \"v2RubyExampleCode\",\n      \"Authorization\" => \"Bearer #{bearer_token}\"\n    },\n    params: query_params\n  }\n\n  request = Typhoeus::Request.new(url, options)\n  response = request.run\n\n  return response\nend\n\nendpoint_url = endpoint_url.gsub(':id',id.to_s())\n\nresponse = get_quote_tweets(endpoint_url, bearer_token, query_params)\nputs response.code, JSON.pretty_generate(JSON.parse(response.body))\n"
  },
  {
    "path": "ruby/posts/recent_search.rb",
    "content": "# This script uses your bearer token to authenticate and make a Search request\n\nrequire 'json'\nrequire 'typhoeus'\n\n# The code below sets the bearer token from your environment variables\n# To set environment variables on Mac OS X, run the export command below from the terminal:\n# export BEARER_TOKEN='YOUR-TOKEN'\nbearer_token = ENV[\"BEARER_TOKEN\"]\n\n# Endpoint URL for the Recent Search API\nsearch_url = \"https://api.x.com/2/tweets/search/recent\"\n\n# Set the query value here. Value can be up to 512 characters\nquery = \"from:Twitter OR from:TwitterDev OR from:DailyNasa\"\n\n# Add or remove parameters below to adjust the query and response fields within the payload\n# See docs for list of param options: https://developer.twitter.com/en/docs/twitter-api/tweets/search/api-reference/get-tweets-search-recent\nquery_params = {\n  \"query\": query, # Required\n  \"max_results\": 10,\n  # \"start_time\": \"2020-07-01T00:00:00Z\",\n  # \"end_time\": \"2020-07-02T18:00:00Z\",\n  # \"expansions\": \"attachments.poll_ids,attachments.media_keys,author_id\",\n  \"tweet.fields\": \"attachments,author_id,conversation_id,created_at,entities,id,lang\",\n  \"user.fields\": \"description\"\n  # \"media.fields\": \"url\", \n  # \"place.fields\": \"country_code\",\n  # \"poll.fields\": \"options\"\n}\n\ndef search_tweets(url, bearer_token, query_params)\n  options = {\n    method: 'get',\n    headers: {\n      \"User-Agent\": \"v2RecentSearchRuby\",\n      \"Authorization\": \"Bearer #{bearer_token}\"\n    },\n    params: query_params\n  }\n\n  request = Typhoeus::Request.new(url, options)\n  response = request.run\n\n  return response\nend\n\nresponse = search_tweets(search_url, bearer_token, query_params)\nputs response.code, JSON.pretty_generate(JSON.parse(response.body))\n"
  },
  {
    "path": "ruby/posts/recent_tweet_counts.rb",
    "content": "# This script uses your bearer token to authenticate and make a Search request\n\nrequire 'json'\nrequire 'typhoeus'\n\n# The code below sets the bearer token from your environment variables\n# To set environment variables on Mac OS X, run the export command below from the terminal:\n# export BEARER_TOKEN='YOUR-TOKEN'\nbearer_token = ENV[\"BEARER_TOKEN\"]\n\n# Endpoint URL for the Recent Search API\nsearch_url = \"https://api.x.com/2/tweets/counts/recent\"\n\n# Set the query value here. Value can be up to 512 characters\nquery = \"from:TwitterDev\"\n\n# Add or remove parameters below to adjust the query and response fields within the payload\n# See docs for list of param options: https://developer.twitter.com/en/docs/twitter-api/tweets/search/api-reference/get-tweets-counts-recent\nquery_params = {\n  \"query\": query, # Required\n  \"granularity\": \"day\"\n}\n\ndef get_tweet_counts(url, bearer_token, query_params)\n  options = {\n    method: 'get',\n    headers: {\n      \"User-Agent\": \"v2RecentTweetCountsRuby\",\n      \"Authorization\": \"Bearer #{bearer_token}\"\n    },\n    params: query_params\n  }\n\n  request = Typhoeus::Request.new(url, options)\n  response = request.run\n\n  return response\nend\n\nresponse = get_tweet_counts(search_url, bearer_token, query_params)\nputs response.code, JSON.pretty_generate(JSON.parse(response.body))\n"
  },
  {
    "path": "ruby/posts/retweet_a_tweet.rb",
    "content": "# This script implements the PIN-based OAuth flow to obtain access tokens for a user context request\n# It then makes a User lookup request (by usernames) with OAuth 1.0a authentication (user context)\nrequire 'oauth'\nrequire 'json'\nrequire 'typhoeus'\nrequire 'oauth/request_proxy/typhoeus_request'\n\n# The code below sets the consumer key and secret from your environment variables\n# To set environment variables on Mac OS X, run the export command below from the terminal:\n# export CONSUMER_KEY='YOUR-KEY', CONSUMER_SECRET='YOUR-SECRET'\nconsumer_key = ENV[\"CONSUMER_KEY\"]\nconsumer_secret = ENV[\"CONSUMER_SECRET\"]\n\n# Be sure to add replace id of the user you wish to retweet on behalf of.\n# You can find a user ID by using the user lookup endpoint\nid = \"your-user-id\"\nretweets_url = \"https://api.x.com/2/users/#{id}/retweets\"\n\n# Be sure to replace tweet-id with your the Tweet ID you want to retweet\n# You can find a Tweet ID by using the Tweet lookup endpoint\n@tweet_id = { \"tweet_id\": \"1412865600439738368\" }\n\nconsumer = OAuth::Consumer.new(consumer_key, consumer_secret,\n\t                                :site => 'https://api.x.com',\n\t                                :authorize_path => '/oauth/authenticate',\n\t                                :debug_output => false)\n\ndef get_request_token(consumer)\n\n\trequest_token = consumer.get_request_token()\n\n  return request_token\nend\n\ndef get_user_authorization(request_token)\n\tputs \"Follow this URL to have a user authorize your app: #{request_token.authorize_url()}\"\n\tputs \"Enter PIN: \"\n\tpin = gets.strip\n\n  return pin\nend\n\ndef obtain_access_token(consumer, request_token, pin)\n\ttoken = request_token.token\n\ttoken_secret = request_token.secret\n\thash = { :oauth_token => token, :oauth_token_secret => token_secret }\n\trequest_token  = OAuth::RequestToken.from_hash(consumer, hash)\n\n\t# Get access token\n\taccess_token = request_token.get_access_token({:oauth_verifier => pin})\n\n\treturn access_token\nend\n\n\ndef user_retweet(url, oauth_params)\n\toptions = {\n\t    :method => :post,\n\t    headers: {\n\t     \t\"User-Agent\": \"v2retweetUserRuby\",\n        \"content-type\": \"application/json\"\n\t    },\n\t    body: JSON.dump(@tweet_id)\n\t}\n\trequest = Typhoeus::Request.new(url, options)\n\toauth_helper = OAuth::Client::Helper.new(request, oauth_params.merge(:request_uri => url))\n\trequest.options[:headers].merge!({\"Authorization\" => oauth_helper.header}) # Signs the request\n\tresponse = request.run\n\n\treturn response\nend\n\n\n\n# PIN-based OAuth flow - Step 1\nrequest_token = get_request_token(consumer)\n# PIN-based OAuth flow - Step 2\npin = get_user_authorization(request_token)\n# PIN-based OAuth flow - Step 3\naccess_token = obtain_access_token(consumer, request_token, pin)\n\noauth_params = {:consumer => consumer, :token => access_token}\n\n\nresponse = user_retweet(retweets_url, oauth_params)\nputs response.code, JSON.pretty_generate(JSON.parse(response.body))\n"
  },
  {
    "path": "ruby/posts/retweeted_by.rb",
    "content": "# This script uses your bearer token to authenticate and retrieve the specified User objects (by ID)\n\nrequire 'json'\nrequire 'typhoeus'\n\n# The code below sets the bearer token from your environment variables\n# To set environment variables on Mac OS X, run the export command below from the terminal:\n# export BEARER_TOKEN='YOUR-TOKEN'\nbearer_token = ENV[\"BEARER_TOKEN\"]\n\n\n# You can replace the ID given with the Tweet ID you wish to lookup Retweeting users for\n# You can find an ID by using the Tweet lookup endpoint\nid = \"1412865600439738368\"\n\nurl = \"https://api.x.com/2/tweets/#{id}/retweeted_by\"\n\nparams = {\n  # User fields are adjustable, options include:\n  # created_at, description, entities, id, location, name,\n  # pinned_tweet_id, profile_image_url, protected,\n  # public_metrics, url, username, verified, and withheld\n  \"user.fields\": \"created_at,description\",\n}\n\ndef retweeted_by_users(url, bearer_token, params)\n  options = {\n    method: 'get',\n    headers: {\n      \"User-Agent\": \"v2RetweetedbyUsersRuby\",\n      \"Authorization\": \"Bearer #{bearer_token}\"\n    },\n    params: params\n  }\n\n  request = Typhoeus::Request.new(url, options)\n  response = request.run\n\n  return response\nend\n\nresponse = retweeted_by_users(url, bearer_token, params)\nputs response.code, JSON.pretty_generate(JSON.parse(response.body))\n"
  },
  {
    "path": "ruby/posts/search_recent.rb",
    "content": "# Recent Search - X API v2\n#\n# Endpoint: GET https://api.x.com/2/tweets/search/recent\n# Docs: https://developer.x.com/en/docs/twitter-api/tweets/search/api-reference/get-tweets-search-recent\n#\n# Authentication: Bearer Token (App-only)\n# Required env vars: BEARER_TOKEN\n#\n# Note: Returns posts from the last 7 days.\n\nrequire 'json'\nrequire 'typhoeus'\n\nbearer_token = ENV[\"BEARER_TOKEN\"]\n\nsearch_url = \"https://api.x.com/2/tweets/search/recent\"\n\n# Set the query value here. Value can be up to 512 characters\nquery = \"from:XDevelopers -is:retweet\"\n\n# See docs for list of param options:\n# https://developer.x.com/en/docs/twitter-api/tweets/search/api-reference/get-tweets-search-recent\nquery_params = {\n  \"query\": query,\n  \"max_results\": 10,\n  \"tweet.fields\": \"attachments,author_id,conversation_id,created_at,entities,id,lang\",\n  \"user.fields\": \"description\"\n}\n\ndef search_posts(url, bearer_token, query_params)\n  options = {\n    method: 'get',\n    headers: {\n      \"User-Agent\": \"v2RecentSearchRuby\",\n      \"Authorization\": \"Bearer #{bearer_token}\"\n    },\n    params: query_params\n  }\n\n  request = Typhoeus::Request.new(url, options)\n  response = request.run\n\n  return response\nend\n\nresponse = search_posts(search_url, bearer_token, query_params)\nputs response.code, JSON.pretty_generate(JSON.parse(response.body))\n"
  },
  {
    "path": "ruby/posts/undo_a_retweet.rb",
    "content": "# This script implements the PIN-based OAuth flow to obtain access tokens for a user context request\n# It then makes a User lookup request (by usernames) with OAuth 1.0a authentication (user context)\n\nrequire 'oauth'\nrequire 'json'\nrequire 'typhoeus'\nrequire 'oauth/request_proxy/typhoeus_request'\n\n# The code below sets the consumer key and secret from your environment variables\n# To set environment variables on Mac OS X, run the export command below from the terminal:\n# export CONSUMER_KEY='YOUR-KEY', CONSUMER_SECRET='YOUR-SECRET'\nconsumer_key = ENV[\"CONSUMER_KEY\"]\nconsumer_secret = ENV[\"CONSUMER_SECRET\"]\n\n# Be sure to replace your-user-id with your own user ID or one of an authenticating user\n# You can find a user ID by using the user lookup endpoint\nid = \"your-user-id\"\n\n# You can replace the given Tweet ID with your the Tweet ID you want to Retweet\n# You can find a Tweet ID by using the Tweet lookup endpoint\nsource_tweet_id = \"1412865600439738368\"\n\n# Returns a user object for one or more users specified by the requested usernames\nuser_unretweet_url = \"https://api.x.com/2/users/#{id}/retweets/#{source_tweet_id}\"\n\nconsumer = OAuth::Consumer.new(consumer_key, consumer_secret,\n\t                                :site => 'https://api.x.com',\n\t                                :authorize_path => '/oauth/authenticate',\n\t                                :debug_output => false)\n\ndef get_request_token(consumer)\n\n\trequest_token = consumer.get_request_token()\n\n  return request_token\nend\n\ndef get_user_authorization(request_token)\n\tputs \"Follow this URL to have a user authorize your app: #{request_token.authorize_url()}\"\n\tputs \"Enter PIN: \"\n\tpin = gets.strip\n\n  return pin\nend\n\ndef obtain_access_token(consumer, request_token, pin)\n\ttoken = request_token.token\n\ttoken_secret = request_token.secret\n\thash = { :oauth_token => token, :oauth_token_secret => token_secret }\n\trequest_token  = OAuth::RequestToken.from_hash(consumer, hash)\n\n\t# Get access token\n\taccess_token = request_token.get_access_token({:oauth_verifier => pin})\n\n\treturn access_token\nend\n\n\ndef user_unretweet(url, oauth_params)\n\toptions = {\n\t    :method => :delete,\n\t    headers: {\n\t     \t\"User-Agent\": \"v2UndoRetweetUserRuby\"\n\t    }\n\t}\n\trequest = Typhoeus::Request.new(url, options)\n\toauth_helper = OAuth::Client::Helper.new(request, oauth_params.merge(:request_uri => url))\n\trequest.options[:headers].merge!({\"Authorization\" => oauth_helper.header}) # Signs the request\n\tresponse = request.run\n\n\treturn response\nend\n\n# PIN-based OAuth flow - Step 1\nrequest_token = get_request_token(consumer)\n# PIN-based OAuth flow - Step 2\npin = get_user_authorization(request_token)\n# PIN-based OAuth flow - Step 3\naccess_token = obtain_access_token(consumer, request_token, pin)\n\noauth_params = {:consumer => consumer, :token => access_token}\n\nresponse = user_unretweet(user_unretweet_url, oauth_params)\nputs response.code, JSON.pretty_generate(JSON.parse(response.body))\n"
  },
  {
    "path": "ruby/posts/unlike_a_tweet.rb",
    "content": "# This script implements the PIN-based OAuth flow to obtain access tokens for a user context request\n# It then makes a User lookup request (by usernames) with OAuth 1.0a authentication (user context)\n\nrequire 'oauth'\nrequire 'json'\nrequire 'typhoeus'\nrequire 'oauth/request_proxy/typhoeus_request'\n\n# The code below sets the consumer key and secret from your environment variables\n# To set environment variables on Mac OS X, run the export command below from the terminal:\n# export CONSUMER_KEY='YOUR-KEY', CONSUMER_SECRET='YOUR-SECRET'\nconsumer_key = ENV[\"CONSUMER_KEY\"]\nconsumer_secret = ENV[\"CONSUMER_SECRET\"]\n\n# Be sure to replace your-user-id with your own user ID or one of an authenticated user\n# You can find a user ID by using the user lookup endpoint\nid = \"your-user-id\"\n\n# You can replace Tweet ID given with the Tweet ID you wish to like.\n# You can find a Tweet ID by using the Tweet lookup endpoint\ntweet_id = \"1354143047324299264\"\n\n# Returns a user object for one or more users specified by the requested usernames\ntweet_unlike_url = \"https://api.x.com/2/users/#{id}/likes/#{tweet_id}\"\n\nconsumer = OAuth::Consumer.new(consumer_key, consumer_secret,\n\t                                :site => 'https://api.x.com',\n\t                                :authorize_path => '/oauth/authenticate',\n\t                                :debug_output => false)\n\ndef get_request_token(consumer)\n\n\trequest_token = consumer.get_request_token()\n\n  return request_token\nend\n\ndef get_user_authorization(request_token)\n\tputs \"Follow this URL to have a user authorize your app: #{request_token.authorize_url()}\"\n\tputs \"Enter PIN: \"\n\tpin = gets.strip\n\n  return pin\nend\n\ndef obtain_access_token(consumer, request_token, pin)\n\ttoken = request_token.token\n\ttoken_secret = request_token.secret\n\thash = { :oauth_token => token, :oauth_token_secret => token_secret }\n\trequest_token  = OAuth::RequestToken.from_hash(consumer, hash)\n\n\t# Get access token\n\taccess_token = request_token.get_access_token({:oauth_verifier => pin})\n\n\treturn access_token\nend\n\n\ndef tweet_unlike(url, oauth_params)\n\toptions = {\n\t    :method => :delete,\n\t    headers: {\n\t     \t\"User-Agent\": \"v2UnlikeTweetRuby\"\n\t    }\n\t}\n\trequest = Typhoeus::Request.new(url, options)\n\toauth_helper = OAuth::Client::Helper.new(request, oauth_params.merge(:request_uri => url))\n\trequest.options[:headers].merge!({\"Authorization\" => oauth_helper.header}) # Signs the request\n\tresponse = request.run\n\n\treturn response\nend\n\n# PIN-based OAuth flow - Step 1\nrequest_token = get_request_token(consumer)\n# PIN-based OAuth flow - Step 2\npin = get_user_authorization(request_token)\n# PIN-based OAuth flow - Step 3\naccess_token = obtain_access_token(consumer, request_token, pin)\n\noauth_params = {:consumer => consumer, :token => access_token}\n\nresponse = tweet_unlike(tweet_unlike_url, oauth_params)\nputs response.code, JSON.pretty_generate(JSON.parse(response.body))\n"
  },
  {
    "path": "ruby/spaces/search_spaces.rb",
    "content": "# This script uses your bearer token to authenticate and make a Spaces lookup request\n\nrequire 'json'\nrequire 'typhoeus'\n\n# The code below sets the bearer token from your environment variables\n# To set environment variables on macOS, run the export command below from the terminal:\n# export BEARER_TOKEN='YOUR-TOKEN'\nbearer_token = ENV[\"BEARER_TOKEN\"]\n\n# Endpoint URL\nspaces_search_url = \"https://api.x.com/2/spaces/search\"\n\n# Replace this value with your search term\nquery = \"NBA\"\n\n# Add or remove parameters below to adjust the query and response fields within the payload\n# See docs for list of param options: https://developer.twitter.com/en/docs/twitter-api/spaces/search/api-reference\nquery_params = {\n  \"query\": query, # Required\n  \"space.fields\": 'title,created_at', \n  'expansions': 'creator_id'\n}\n\ndef get_space(url, bearer_token, query_params)\n  options = {\n    method: 'get',\n    headers: {\n      \"User-Agent\": \"v2SpacesSearchRuby\",\n      \"Authorization\": \"Bearer #{bearer_token}\"\n    },\n    params: query_params\n  }\n\n  request = Typhoeus::Request.new(url, options)\n  response = request.run\n\n  return response\nend\n\nresponse = get_space(spaces_search_url, bearer_token, query_params)\nputs response.code, JSON.pretty_generate(JSON.parse(response.body))\n"
  },
  {
    "path": "ruby/spaces/spaces_lookup.rb",
    "content": "# This script uses your bearer token to authenticate and make a Spaces lookup request\n\nrequire 'json'\nrequire 'typhoeus'\n\n# The code below sets the bearer token from your environment variables\n# To set environment variables on macOS, run the export command below from the terminal:\n# export BEARER_TOKEN='YOUR-TOKEN'\nbearer_token = ENV[\"BEARER_TOKEN\"]\n\n# Endpoint URL for Spaces lookup\nspaces_lookup_url = \"https://api.x.com/2/spaces\"\n\n# Replace SPACE_ID with the ID of a Space\nid = \"SPACE_ID\"\n\n# Add or remove parameters below to adjust the query and response fields within the payload\n# See docs for list of param options: https://developer.twitter.com/en/docs/twitter-api/spaces/lookup/api-reference\nquery_params = {\n  \"ids\": id, # Required\n  \"space.fields\": 'title,created_at', \n  'expansions': 'creator_id'\n}\n\ndef get_space(url, bearer_token, query_params)\n  options = {\n    method: 'get',\n    headers: {\n      \"User-Agent\": \"v2SpacesLookupRuby\",\n      \"Authorization\": \"Bearer #{bearer_token}\"\n    },\n    params: query_params\n  }\n\n  request = Typhoeus::Request.new(url, options)\n  response = request.run\n\n  return response\nend\n\nresponse = get_space(spaces_lookup, bearer_token, query_params)\nputs response.code, JSON.pretty_generate(JSON.parse(response.body))\n"
  },
  {
    "path": "ruby/streams/filtered_stream.rb",
    "content": "# This script contains methods to add, remove, and retrieve rules from your stream.\n# It will also connect to the stream endpoint and begin outputting data.\n# Run as-is, the script gives you the option to replace existing rules with new ones and begin streaming data\n\nrequire 'json'\nrequire 'typhoeus'\n\n# The code below sets the bearer token from your environment variables\n# To set environment variables on Mac OS X, run the export command below from the terminal:\n# export BEARER_TOKEN='YOUR-TOKEN'\n@bearer_token = ENV[\"BEARER_TOKEN\"]\n\n@stream_url = \"https://api.x.com/2/tweets/search/stream\"\n@rules_url = \"https://api.x.com/2/tweets/search/stream/rules\"\n\n@sample_rules = [\n  { 'value': 'dog has:images', 'tag': 'dog pictures' },\n  { 'value': 'cat has:images -grumpy', 'tag': 'cat pictures' },\n]\n\n# Add or remove values from the optional parameters below. Full list of parameters can be found in the docs:\n# https://developer.twitter.com/en/docs/twitter-api/tweets/filtered-stream/api-reference/get-tweets-search-stream\nparams = {\n  \"expansions\": \"attachments.poll_ids,attachments.media_keys,author_id,entities.mentions.username,geo.place_id,in_reply_to_user_id,referenced_tweets.id,referenced_tweets.id.author_id\",\n  \"tweet.fields\": \"attachments,author_id,conversation_id,created_at,entities,geo,id,in_reply_to_user_id,lang\",\n  # \"user.fields\": \"description\",\n  # \"media.fields\": \"url\", \n  # \"place.fields\": \"country_code\",\n  # \"poll.fields\": \"options\"\n}\n\n# Get request to rules endpoint. Returns list of of active rules from your stream \ndef get_all_rules\n  @options = {\n    headers: {\n      \"User-Agent\": \"v2FilteredStreamRuby\",\n      \"Authorization\": \"Bearer #{@bearer_token}\"\n    }\n  }\n\n  @response = Typhoeus.get(@rules_url, @options)\n\n  raise \"An error occurred while retrieving active rules from your stream: #{@response.body}\" unless @response.success?\n\n  @body = JSON.parse(@response.body)\nend\n\n# Post request to add rules to your stream\ndef set_rules(rules)\n  return if rules.nil?\n\n  @payload = {\n    add: rules\n  }\n\n  @options = {\n    headers: {\n      \"User-Agent\": \"v2FilteredStreamRuby\",\n      \"Authorization\": \"Bearer #{@bearer_token}\",\n      \"Content-type\": \"application/json\"\n    },\n    body: JSON.dump(@payload)\n  }\n\n  @response = Typhoeus.post(@rules_url, @options)\n  raise \"An error occurred while adding rules: #{@response.status_message}\" unless @response.success?\nend\n\n# Post request with a delete body to remove rules from your stream\ndef delete_all_rules(rules)\n  return if rules.nil?\n\n  @ids = rules['data'].map { |rule| rule[\"id\"] }\n  @payload = {\n    delete: {\n      ids: @ids\n    }\n  }\n\n  @options = {\n    headers: {\n      \"User-Agent\": \"v2FilteredStreamRuby\",\n      \"Authorization\": \"Bearer #{@bearer_token}\",\n      \"Content-type\": \"application/json\"\n    },\n    body: JSON.dump(@payload)\n  }\n\n  @response = Typhoeus.post(@rules_url, @options)\n\n  raise \"An error occurred while deleting your rules: #{@response.status_message}\" unless @response.success?\nend\n\n# Helper method that gets active rules and prompts to delete (y/n), then adds new rules set in line 17 (@sample_rules)\ndef setup_rules\n  # Gets the complete list of rules currently applied to the stream\n  @rules = get_all_rules\n  puts \"Found existing rules on the stream:\\n #{@rules}\\n\"\n\n  puts \"Do you want to delete existing rules and replace with new rules? [y/n]\"\n  answer = gets.chomp\n  if answer == \"y\"\n    # Delete all rules\n    delete_all_rules(@rules)\n  else\n    puts \"Keeping existing rules and adding new ones.\"\n  end\n  \n  # Add rules to the stream\n  set_rules(@sample_rules)\nend\n\n# Connects to the stream and returns data (Tweet payloads) in chunks\ndef stream_connect(params)\n  @options = {\n    timeout: 20,\n    method: 'get',\n    headers: {\n      \"User-Agent\": \"v2FilteredStreamRuby\",\n      \"Authorization\": \"Bearer #{@bearer_token}\"\n    },\n    params: params\n  }\n\n  @request = Typhoeus::Request.new(@stream_url, @options)\n  @request.on_body do |chunk|\n    puts chunk\n  end\n  @request.run\nend\n\n# Comment this line if you already setup rules and want to keep them\nsetup_rules\n\n# Listen to the stream.\n# This reconnection logic will attempt to reconnect when a disconnection is detected.\n# To avoid rate limites, this logic implements exponential backoff, so the wait time\n# will increase if the client cannot reconnect to the stream.\ntimeout = 0\nwhile true\n  stream_connect(params)\n  sleep 2 ** timeout\n  timeout += 1\nend"
  },
  {
    "path": "ruby/streams/sampled_stream.rb",
    "content": "# This script connects to the Sample stream endpoint and outputs data\n\nrequire 'json'\nrequire 'typhoeus'\n\n# The code below sets the bearer token from your environment variables\n# To set environment variables on Mac OS X, run the export command below from the terminal:\n# export BEARER_TOKEN='YOUR-TOKEN'\nbearer_token = ENV[\"BEARER_TOKEN\"]\n\nstream_url = \"https://api.x.com/2/tweets/sample/stream\"\n\n# Add or remove optional parameters values from the params object below. Full list of parameters and their values can be found in the docs:\n# https://developer.twitter.com/en/docs/twitter-api/tweets/volume-streams/api-reference/get-tweets-sample-stream\nparams = {\n  # \"expansions\": \"author_id,referenced_tweets.id\",\n  \"tweet.fields\": \"attachments,author_id,conversation_id,created_at,entities,geo,id,in_reply_to_user_id,lang\",\n  # \"user.fields\": \"name\"\n  # \"media.fields\": \"url\",\n  # \"place.fields\": \"country_code\",\n  # \"poll.fields\": \"options\"\n}\n\ndef stream_connect(url, bearer_token, params)\n  options = {\n    timeout: 20,\n    method: 'get',\n    headers: {\n      \"User-Agent\": \"v2SampledStreamRuby\",\n      \"Authorization\": \"Bearer #{bearer_token}\"\n    },\n    params: params\n  }\n\n  request = Typhoeus::Request.new(url, options)\n  request.on_body do |chunk|\n    puts chunk\n  end\n  request.run\nend\n\n# Listen to the stream.\n# This reconnection logic will attempt to reconnect when a disconnection is detected.\n# To avoid rate limites, this logic implements exponential backoff, so the wait time\n# will increase if the client cannot reconnect to the stream.\ntimeout = 0\nwhile true\n  stream_connect(stream_url, bearer_token, params)\n  sleep 2 ** timeout\n  timeout += 1\nend\n"
  },
  {
    "path": "ruby/timelines/reverse-chron-home-timeline.rb",
    "content": "require 'json'\nrequire 'typhoeus'\nrequire 'twitter_oauth2'\n\n# First, you will need to enable OAuth 2.0 in your App’s auth settings in the Developer Portal to get your client ID.\n# Inside your terminal you will need to set an enviornment variable\n# export CLIENT_ID='your-client-id'\nclient_id = ENV[\"CLIENT_ID\"]\n\n# If you have selected a type of App that is a confidential client you will need to set a client secret.\n# Confidential Clients securely authenticate with the authorization server.\n\n# Inside your terminal you will need to set an enviornment variable\n# export CLIENT_SECRET='your-client-secret'\n\n# Remove the comment on the following line if you are using a confidential client\n# client_secret = ENV[\"CLIENT_SECRET\"]\n\n\n# Replace the following URL with your callback URL, which can be obtained from your App's auth settings.\nredirect_uri = \"https://www.example.com\"\n\n# Start an OAuth 2.0 session with a public client\nclient = TwitterOAuth2::Client.new(\n  identifier: \"#{client_id}\",\n  redirect_uri: \"#{redirect_uri}\"\n)\n\n# Start an OAuth 2.0 session with a confidential client\n\n# Remove the comment on the following lines if you are using a confidential client\n# client = TwitterOAuth2::Client.new(\n#   identifier: \"#{client_id}\",\n#   secret: \"#{client_secret}\",\n#   redirect_uri: \"#{redirect_uri}\"\n# )\n\n# Create your authorize url\nauthorization_url = client.authorization_uri(\n  # Update scopes if needed\n  scope: [\n    :'users.read',\n    :'tweet.read',\n    :'offline.access'\n  ]\n)\n\n# Set code verifier and state\ncode_verifier = client.code_verifier\nstate = client.state\n\n# Visit the URL to authorize your App to make requests on behalf of a user\nprint 'Visit the following URL to authorize your App on behalf of your Twitter handle in a browser'\nputs authorization_url\n`open \"#{authorization_url}\"`\n\nprint 'Paste in the full URL after you authorized your App: ' and STDOUT.flush\n\n# Fetch your access token\nfull_text = gets.chop\nnew_code = full_text.split(\"code=\")\ncode = new_code[1]\nclient.authorization_code = code\n\n# Your access token\ntoken_response = client.access_token! code_verifier\n\n# Make a request to the users/me endpoint to get your user ID\ndef users_me(url, token_response)\n  options = {\n    method: 'get',\n    headers: {\n      \"User-Agent\": \"ReverseChronHomeTimelineSampleCode\",\n      \"Authorization\": \"Bearer #{token_response}\"\n    },\n  }\n\n  request = Typhoeus::Request.new(url, options)\n  response = request.run\n\n  return response\nend\n\nurl = \"https://api.x.com/2/users/me\"\nme_response = users_me(url, token_response)\n\njson_s = JSON.parse(me_response.body)\nuser_id = json_s[\"data\"][\"id\"]\n\n# Make a request to the reverse chronological home timeline endpoint\nurl = \"https://api.x.com/2/users/#{user_id}/timelines/reverse_chronological\"\n\n\ndef reverse_chron_timeline(url, token_response)\n  options = {\n    method: 'get',\n    headers: {\n      \"User-Agent\": \"ReverseChronTimelinesSampleCode\",\n      \"Authorization\": \"Bearer #{token_response}\"\n    }\n  }\n\n  request = Typhoeus::Request.new(url, options)\n  response = request.run\n\n  return response\nend\n\nresponse = reverse_chron_timeline(url, token_response)\nputs response.code, JSON.pretty_generate(JSON.parse(response.body))\n"
  },
  {
    "path": "ruby/timelines/user-mentions.rb",
    "content": "# This script uses your bearer token to authenticate and make a request to the User mentions timeline endpoint.\nrequire 'json'\nrequire 'typhoeus'\n\n# The code below sets the bearer token from your environment variables\n# To set environment variables on Mac OS X, run the export command below from the terminal:\n# export BEARER_TOKEN='YOUR-TOKEN'\nbearer_token = ENV[\"BEARER_TOKEN\"]\n\n# Endpoint URL for the User mentions timelines.\nendpoint_url = \"https://api.x.com/2/users/:id/mentions\"\n\n# Specify the User ID for this request.\nid = 2244994945 #@TwitterDev's numeric User ID. \n\n# Add or remove parameters below to adjust the query and response fields within the payload\n# TODO: See docs for list of param options: https://developer.twitter.com/en/docs/twitter-api/tweets/\nquery_params = {\n  \"max_results\" => 100,\n  # \"start_time\" => \"2020-07-01T00:00:00Z\",\n  # \"end_time\" => \"2020-07-02T18:00:00Z\",\n  \"expansions\" => \"attachments.poll_ids,attachments.media_keys,author_id\",\n  \"tweet.fields\" => \"attachments,author_id,conversation_id,created_at,entities,id,lang\",\n  \"user.fields\" => \"description\"\n  # \"media.fields\" => \"url\", \n  # \"place.fields\" => \"country_code\",\n  # \"poll.fields\" => \"options\"\n}\n\ndef get_user_mentions(url, bearer_token, query_params)\n  options = {\n    method: 'get',\n    headers: {\n      \"User-Agent\" => \"v2RubyExampleCode\",\n      \"Authorization\" => \"Bearer #{bearer_token}\"\n    },\n    params: query_params\n  }\n\n  request = Typhoeus::Request.new(url, options)\n  response = request.run\n\n  return response\nend\n\nendpoint_url = endpoint_url.gsub(':id',id.to_s())\n\nresponse = get_user_mentions(endpoint_url, bearer_token, query_params)\nputs response.code, JSON.pretty_generate(JSON.parse(response.body))\n"
  },
  {
    "path": "ruby/timelines/user-tweets.rb",
    "content": "# This script uses your bearer token to authenticate and make a request to the User Tweets timeline endpoint.\n\n#Based on recent search example and updated for User mention timeline.\n#Next steps: \n# [] Refactor for User Tweets timeline..\n# [] Refactor for Full-archive search.\n\nrequire 'json'\nrequire 'typhoeus'\n\n# The code below sets the bearer token from your environment variables\n# To set environment variables on Mac OS X, run the export command below from the terminal:\n# export BEARER_TOKEN='YOUR-TOKEN'\nbearer_token = ENV[\"BEARER_TOKEN\"]\n\n# Endpoint URL for the Recent Search API\nendpoint_url = \"https://api.x.com/2/users/:id/tweets\"\n\n# Specify the User ID for this request.\nid = 2244994945 #@TwitterDev's numeric User ID.\n\n# Add or remove parameters below to adjust the query and response fields within the payload\n# TODO: See docs for list of param options: https://developer.twitter.com/en/docs/twitter-api/tweets/\nquery_params = {\n  \"max_results\" => 100,\n  # \"start_time\" => \"2020-07-01T00:00:00Z\",\n  # \"end_time\" => \"2020-07-02T18:00:00Z\",\n  \"expansions\" => \"attachments.poll_ids,attachments.media_keys,author_id\",\n  \"tweet.fields\" => \"attachments,author_id,conversation_id,created_at,entities,id,lang\",\n  \"user.fields\" => \"description\"\n  # \"media.fields\" => \"url\", \n  # \"place.fields\" => \"country_code\",\n  # \"poll.fields\" => \"options\"\n}\n\ndef get_user_tweets(url, bearer_token, query_params)\n  options = {\n    method: 'get',\n    headers: {\n      \"User-Agent\" => \"v2RubyExampleCode\",\n      \"Authorization\" => \"Bearer #{bearer_token}\"\n    },\n    params: query_params\n  }\n\n  request = Typhoeus::Request.new(url, options)\n  response = request.run\n\n  return response\nend\n\nendpoint_url = endpoint_url.gsub(':id',id.to_s())\n\nresponse = get_user_tweets(endpoint_url, bearer_token, query_params)\nputs response.code, JSON.pretty_generate(JSON.parse(response.body))\n"
  },
  {
    "path": "ruby/timelines/user_posts.rb",
    "content": "# User Posts Timeline - X API v2\n#\n# Endpoint: GET https://api.x.com/2/users/:id/tweets\n# Docs: https://developer.x.com/en/docs/twitter-api/tweets/timelines/api-reference/get-users-id-tweets\n#\n# Authentication: Bearer Token (App-only) or OAuth (User Context)\n# Required env vars: BEARER_TOKEN\n\nrequire 'json'\nrequire 'typhoeus'\n\nbearer_token = ENV[\"BEARER_TOKEN\"]\n\n# Replace with the user ID you want to get posts for\nuser_id = \"2244994945\"\nurl = \"https://api.x.com/2/users/#{user_id}/tweets\"\n\nquery_params = {\n  \"tweet.fields\": \"created_at,public_metrics\",\n  \"max_results\": 10\n}\n\ndef get_user_posts(url, bearer_token, query_params)\n  options = {\n    method: 'get',\n    headers: {\n      \"User-Agent\": \"v2UserPostsRuby\",\n      \"Authorization\": \"Bearer #{bearer_token}\"\n    },\n    params: query_params\n  }\n\n  request = Typhoeus::Request.new(url, options)\n  response = request.run\n\n  return response\nend\n\nresponse = get_user_posts(url, bearer_token, query_params)\nputs response.code, JSON.pretty_generate(JSON.parse(response.body))\n"
  },
  {
    "path": "ruby/users/block_a_user.rb",
    "content": "# This script implements the PIN-based OAuth flow to obtain access tokens for a user context request\n# It then makes a User lookup request (by usernames) with OAuth 1.0a authentication (user context)\nrequire 'oauth'\nrequire 'json'\nrequire 'typhoeus'\nrequire 'oauth/request_proxy/typhoeus_request'\n\n# The code below sets the consumer key and secret from your environment variables\n# To set environment variables on Mac OS X, run the export command below from the terminal:\n# export CONSUMER_KEY='YOUR-KEY', CONSUMER_SECRET='YOUR-SECRET'\nconsumer_key = ENV[\"CONSUMER_KEY\"]\nconsumer_secret = ENV[\"CONSUMER_SECRET\"]\n\n# Be sure to replace your-user-id with your own user ID or one of an authenticating user\n# You can find a user ID by using the user lookup endpoint\nid = \"your-user-id\"\nblocking_url = \"https://api.x.com/2/users/#{id}/blocking\"\n\n# Be sure to add replace id-to-block with the id of the user you wish to block.\n# You can find a user ID by using the user lookup endpoint\n@target_user_id = { \"target_user_id\": \"id-to-block\" }\n\nconsumer = OAuth::Consumer.new(consumer_key, consumer_secret,\n\t                                :site => 'https://api.x.com',\n\t                                :authorize_path => '/oauth/authenticate',\n\t                                :debug_output => false)\n\ndef get_request_token(consumer)\n\n\trequest_token = consumer.get_request_token()\n\n  return request_token\nend\n\ndef get_user_authorization(request_token)\n\tputs \"Follow this URL to have a user authorize your app: #{request_token.authorize_url()}\"\n\tputs \"Enter PIN: \"\n\tpin = gets.strip\n\n  return pin\nend\n\ndef obtain_access_token(consumer, request_token, pin)\n\ttoken = request_token.token\n\ttoken_secret = request_token.secret\n\thash = { :oauth_token => token, :oauth_token_secret => token_secret }\n\trequest_token  = OAuth::RequestToken.from_hash(consumer, hash)\n\n\t# Get access token\n\taccess_token = request_token.get_access_token({:oauth_verifier => pin})\n\n\treturn access_token\nend\n\n\ndef user_block(url, oauth_params)\n\toptions = {\n\t    :method => :post,\n\t    headers: {\n\t     \t\"User-Agent\": \"v2BlockUserRuby\",\n        \"content-type\": \"application/json\"\n\t    },\n\t    body: JSON.dump(@target_user_id)\n\t}\n\trequest = Typhoeus::Request.new(url, options)\n\toauth_helper = OAuth::Client::Helper.new(request, oauth_params.merge(:request_uri => url))\n\trequest.options[:headers].merge!({\"Authorization\" => oauth_helper.header}) # Signs the request\n\tresponse = request.run\n\n\treturn response\nend\n\n\n\n# PIN-based OAuth flow - Step 1\nrequest_token = get_request_token(consumer)\n# PIN-based OAuth flow - Step 2\npin = get_user_authorization(request_token)\n# PIN-based OAuth flow - Step 3\naccess_token = obtain_access_token(consumer, request_token, pin)\n\noauth_params = {:consumer => consumer, :token => access_token}\n\n\nresponse = user_block(blocking_url, oauth_params)\nputs response.code, JSON.pretty_generate(JSON.parse(response.body))\n"
  },
  {
    "path": "ruby/users/followers-lookup.rb",
    "content": "require 'json'\nrequire 'typhoeus'\n\n# The code below sets the bearer token from your environment variables\n# To set environment variables on macOS or Linux, run the export command below from the terminal:\n# export BEARER_TOKEN='YOUR-TOKEN'\nbearer_token = ENV[\"BEARER_TOKEN\"]\n\n# Endpoint URL for the user followers\nendpoint_url = \"https://api.x.com/2/users/:id/followers\"\n\n# Specify the User ID for this request.\nid = 2244994945\n\n# Add or remove parameters below to adjust the query and response fields within the payload\nquery_params = {\n  \"max_results\" => 1000,\n  \"user.fields\" => \"created_at\"\n}\n\ndef get_followers(url, bearer_token, query_params)\n  options = {\n    method: 'get',\n    headers: {\n      \"User-Agent\" => \"v2RubyExampleCode\",\n      \"Authorization\" => \"Bearer #{bearer_token}\",\n    },\n    params: query_params\n  }\n\n  request = Typhoeus::Request.new(url, options)\n  response = request.run\n\n  return response\nend\n\nendpoint_url = endpoint_url.gsub(':id',id.to_s())\n\nresponse = get_followers(endpoint_url, bearer_token, query_params)\nputs response.code, JSON.pretty_generate(JSON.parse(response.body))\n"
  },
  {
    "path": "ruby/users/followers.rb",
    "content": "# User Followers Lookup - X API v2\n#\n# Endpoint: GET https://api.x.com/2/users/:id/followers\n# Docs: https://developer.x.com/en/docs/twitter-api/users/follows/api-reference/get-users-id-followers\n#\n# Authentication: Bearer Token (App-only) or OAuth (User Context)\n# Required env vars: BEARER_TOKEN\n\nrequire 'json'\nrequire 'typhoeus'\n\nbearer_token = ENV[\"BEARER_TOKEN\"]\n\n# Replace with the user ID you want to get followers for\nuser_id = \"2244994945\"\nurl = \"https://api.x.com/2/users/#{user_id}/followers\"\n\nquery_params = {\n  \"user.fields\": \"created_at,description\",\n  \"max_results\": 100\n}\n\ndef get_followers(url, bearer_token, query_params)\n  options = {\n    method: 'get',\n    headers: {\n      \"User-Agent\": \"v2FollowersRuby\",\n      \"Authorization\": \"Bearer #{bearer_token}\"\n    },\n    params: query_params\n  }\n\n  request = Typhoeus::Request.new(url, options)\n  response = request.run\n\n  return response\nend\n\nresponse = get_followers(url, bearer_token, query_params)\nputs response.code, JSON.pretty_generate(JSON.parse(response.body))\n"
  },
  {
    "path": "ruby/users/following-lookup.rb",
    "content": "require 'json'\nrequire 'typhoeus'\n\n# The code below sets the bearer token from your environment variables\n# To set environment variables on macOS or Linux, run the export command below from the terminal:\n# export BEARER_TOKEN='YOUR-TOKEN'\nbearer_token = ENV[\"BEARER_TOKEN\"]\n\n# Endpoint URL for the user following API\nendpoint_url = \"https://api.x.com/2/users/:id/following\"\n\n# Specify the User ID for this request.\nid = 2244994945\n\n# Add or remove parameters below to adjust the query and response fields within the payload\nquery_params = {\n  \"max_results\" => 1000,\n  \"user.fields\" => \"created_at\"\n}\n\ndef get_following(url, bearer_token, query_params)\n  options = {\n    method: 'get',\n    headers: {\n      \"User-Agent\" => \"v2RubyExampleCode\",\n      \"Authorization\" => \"Bearer #{bearer_token}\",\n    },\n    params: query_params\n  }\n\n  request = Typhoeus::Request.new(url, options)\n  response = request.run\n\n  return response\nend\n\nendpoint_url = endpoint_url.gsub(':id',id.to_s())\n\nresponse = get_following(endpoint_url, bearer_token, query_params)\nputs response.code, JSON.pretty_generate(JSON.parse(response.body))\n"
  },
  {
    "path": "ruby/users/get_users_me_with_user_context.rb",
    "content": "require 'oauth'\nrequire 'json'\nrequire 'typhoeus'\nrequire 'oauth/request_proxy/typhoeus_request'\n\n# The code below sets the consumer key and secret from your environment variables\n# To set environment variables on Mac OS X, run the export command below from the terminal:\n# export CONSUMER_KEY='YOUR-KEY', CONSUMER_SECRET='YOUR-SECRET'\nconsumer_key = ENV[\"CONSUMER_KEY\"]\nconsumer_secret = ENV[\"CONSUMER_SECRET\"]\n\nuser_lookup_url = \"https://api.x.com/2/users/me\"\n\nconsumer = OAuth::Consumer.new(consumer_key, consumer_secret,\n\t                                :site => 'https://api.x.com',\n\t                                :authorize_path => '/oauth/authenticate',\n\t                                :debug_output => false)\n\ndef get_request_token(consumer)\n\n\trequest_token = consumer.get_request_token()\n\n  return request_token\nend\n\ndef get_user_authorization(request_token)\n\tputs \"Follow this URL to have a user authorize your app: #{request_token.authorize_url()}\"\n\tputs \"Enter PIN: \"\n\tpin = gets.strip\n\n  return pin\nend\n\ndef obtain_access_token(consumer, request_token, pin)\n\ttoken = request_token.token\n\ttoken_secret = request_token.secret\n\thash = { :oauth_token => token, :oauth_token_secret => token_secret }\n\trequest_token  = OAuth::RequestToken.from_hash(consumer, hash)\n\n\t# Get access token\n\taccess_token = request_token.get_access_token({:oauth_verifier => pin})\n\n\treturn access_token\nend\n\n# Add or remove optional parameters values from the params object below. Full list of parameters and their values can be found in the docs:\n# https://developer.twitter.com/en/docs/twitter-api/users/lookup/api-reference/get-users\nquery_params = {\n  # \"expansions\": \"pinned_tweet_id\",\n  # \"tweet.fields\": \"attachments,author_id,conversation_id,created_at,entities,geo,id,in_reply_to_user_id,lang\",\n  \"user.fields\": \"created_at,description\"\n}\n\ndef user_lookup(url, oauth_params, query_params)\n\toptions = {\n\t    :method => :get,\n\t    headers: {\n\t     \t\"User-Agent\": \"v2UserLookupRuby\"\n\t    },\n\t    params: query_params\n\t}\n\trequest = Typhoeus::Request.new(url, options)\n\toauth_helper = OAuth::Client::Helper.new(request, oauth_params.merge(:request_uri => url))\n\trequest.options[:headers].merge!({\"Authorization\" => oauth_helper.header}) # Signs the request\n\tresponse = request.run\n\n\treturn response\nend\n\n# PIN-based OAuth flow - Step 1\nrequest_token = get_request_token(consumer)\n# PIN-based OAuth flow - Step 2\npin = get_user_authorization(request_token)\n# PIN-based OAuth flow - Step 3\naccess_token = obtain_access_token(consumer, request_token, pin)\n\noauth_params = {:consumer => consumer, :token => access_token}\n\nresponse = user_lookup(user_lookup_url, oauth_params, query_params)\nputs response.code, JSON.pretty_generate(JSON.parse(response.body))\n"
  },
  {
    "path": "ruby/users/get_users_with_bearer_token.rb",
    "content": "# This script uses your bearer token to authenticate and retrieve the specified User objects (by ID)\n\nrequire 'json'\nrequire 'typhoeus'\n\n# The code below sets the bearer token from your environment variables\n# To set environment variables on Mac OS X, run the export command below from the terminal:\n# export BEARER_TOKEN='YOUR-TOKEN'\nbearer_token = ENV[\"BEARER_TOKEN\"]\n\nuser_lookup_url = \"https://api.x.com/2/users\"\n\n# Specify the User IDs that you want to lookup below (to 100 per request)\nuser_ids = \"2244994945,783214\"\n\n# Add or remove optional parameters values from the params object below. Full list of parameters and their values can be found in the docs\nparams = {\n\t\"ids\": user_ids,\n  \"expansions\": \"pinned_tweet_id\",\n  \"tweet.fields\": \"attachments,author_id,conversation_id,created_at,entities,geo,id,in_reply_to_user_id,lang\",\n  # \"user.fields\": \"name\"\n  # \"media.fields\": \"url\",\n  # \"place.fields\": \"country_code\",\n  # \"poll.fields\": \"options\"\n}\n\ndef user_lookup(url, bearer_token, params)\n  options = {\n    method: 'get',\n    headers: {\n      \"User-Agent\": \"v2UserLookupRuby\",\n      \"Authorization\": \"Bearer #{bearer_token}\"\n    },\n    params: params\n  }\n\n  request = Typhoeus::Request.new(url, options)\n  response = request.run\n\n  return response\nend\n\nresponse = user_lookup(user_lookup_url, bearer_token, params)\nputs response.code, JSON.pretty_generate(JSON.parse(response.body))\n"
  },
  {
    "path": "ruby/users/get_users_with_user_context.rb",
    "content": "# This script implements the PIN-based OAuth flow to obtain access tokens for a user context request\n# It then makes a User lookup request (by usernames) with OAuth 1.0a authentication (user context)\n\nrequire 'oauth'\nrequire 'json'\nrequire 'typhoeus'\nrequire 'oauth/request_proxy/typhoeus_request'\n\n# The code below sets the consumer key and secret from your environment variables\n# To set environment variables on Mac OS X, run the export command below from the terminal:\n# export CONSUMER_KEY='YOUR-KEY', CONSUMER_SECRET='YOUR-SECRET'\nconsumer_key = ENV[\"CONSUMER_KEY\"]\nconsumer_secret = ENV[\"CONSUMER_SECRET\"]\n\n# Returns a user object for one or more users specified by the requested usernames\nuser_lookup_url = \"https://api.x.com/2/users/by\"\n\n# Specify the usernames that you want to lookup below (to 100 per request)\nusernames = \"Twitter,TwitterDev\"\n\nconsumer = OAuth::Consumer.new(consumer_key, consumer_secret,\n\t                                :site => 'https://api.x.com',\n\t                                :authorize_path => '/oauth/authenticate',\n\t                                :debug_output => false)\n\ndef get_request_token(consumer)\n\n\trequest_token = consumer.get_request_token()\n\n  return request_token\nend\n\ndef get_user_authorization(request_token)\n\tputs \"Follow this URL to have a user authorize your app: #{request_token.authorize_url()}\"\n\tputs \"Enter PIN: \"\n\tpin = gets.strip\n  \n  return pin\nend\n\ndef obtain_access_token(consumer, request_token, pin)\n\ttoken = request_token.token\n\ttoken_secret = request_token.secret\n\thash = { :oauth_token => token, :oauth_token_secret => token_secret }\n\trequest_token  = OAuth::RequestToken.from_hash(consumer, hash)\n\t\n\t# Get access token\n\taccess_token = request_token.get_access_token({:oauth_verifier => pin})\n\n\treturn access_token\nend\n\n# Add or remove optional parameters values from the params object below. Full list of parameters and their values can be found in the docs:\n# https://developer.twitter.com/en/docs/twitter-api/users/lookup/api-reference/get-users\nquery_params = {\n\t\"usernames\": usernames,\n  # \"expansions\": \"pinned_tweet_id\",\n  \"tweet.fields\": \"attachments,author_id,conversation_id,created_at,entities,geo,id,in_reply_to_user_id,lang\",\n  # \"user.fields\": \"name\"\n}\n\ndef user_lookup(url, oauth_params, query_params)\n\toptions = {\n\t    :method => :get,\n\t    headers: {\n\t     \t\"User-Agent\": \"v2UserLookupRuby\"\n\t    },\n\t    params: query_params\n\t}\n\trequest = Typhoeus::Request.new(url, options)\n\toauth_helper = OAuth::Client::Helper.new(request, oauth_params.merge(:request_uri => url))\n\trequest.options[:headers].merge!({\"Authorization\" => oauth_helper.header}) # Signs the request\n\tresponse = request.run\n\n\treturn response\nend\n\n# PIN-based OAuth flow - Step 1\nrequest_token = get_request_token(consumer)\n# PIN-based OAuth flow - Step 2\npin = get_user_authorization(request_token)\n# PIN-based OAuth flow - Step 3\naccess_token = obtain_access_token(consumer, request_token, pin)\n\noauth_params = {:consumer => consumer, :token => access_token}\n\nresponse = user_lookup(user_lookup_url, oauth_params, query_params)\nputs response.code, JSON.pretty_generate(JSON.parse(response.body))\n"
  },
  {
    "path": "ruby/users/lookup.rb",
    "content": "# User Lookup - X API v2\n#\n# Endpoint: GET https://api.x.com/2/users/by\n# Docs: https://developer.x.com/en/docs/twitter-api/users/lookup/api-reference/get-users-by\n#\n# Authentication: Bearer Token (App-only) or OAuth (User Context)\n# Required env vars: BEARER_TOKEN\n\nrequire 'json'\nrequire 'typhoeus'\n\nbearer_token = ENV[\"BEARER_TOKEN\"]\n\nurl = \"https://api.x.com/2/users/by\"\n\n# Usernames to look up (up to 100 comma-separated)\nquery_params = {\n  \"usernames\": \"XDevelopers,X\",\n  \"user.fields\": \"created_at,description,public_metrics\"\n}\n\ndef lookup_users(url, bearer_token, query_params)\n  options = {\n    method: 'get',\n    headers: {\n      \"User-Agent\": \"v2UserLookupRuby\",\n      \"Authorization\": \"Bearer #{bearer_token}\"\n    },\n    params: query_params\n  }\n\n  request = Typhoeus::Request.new(url, options)\n  response = request.run\n\n  return response\nend\n\nresponse = lookup_users(url, bearer_token, query_params)\nputs response.code, JSON.pretty_generate(JSON.parse(response.body))\n"
  },
  {
    "path": "ruby/users/lookup_blocks.rb",
    "content": "# This script implements the PIN-based OAuth flow to obtain access tokens for a user context request\n# It then makes a User lookup request (by usernames) with OAuth 1.0a authentication (user context)\nrequire 'oauth'\nrequire 'json'\nrequire 'typhoeus'\nrequire 'oauth/request_proxy/typhoeus_request'\n\n# The code below sets the consumer key and secret from your environment variables\n# To set environment variables on Mac OS X, run the export command below from the terminal:\n# export CONSUMER_KEY='YOUR-KEY', CONSUMER_SECRET='YOUR-SECRET'\nconsumer_key = ENV[\"CONSUMER_KEY\"]\nconsumer_secret = ENV[\"CONSUMER_SECRET\"]\n\n# Be sure to replace your-user-id with your own user ID or one of an authenticating user\n# You can find a user ID by using the user lookup endpoint\nid = \"your-user-id\"\n\nblocking_url = \"https://api.x.com/2/users/#{id}/blocking\"\n\nconsumer = OAuth::Consumer.new(consumer_key, consumer_secret,\n\t                                :site => 'https://api.x.com',\n\t                                :authorize_path => '/oauth/authenticate',\n\t                                :debug_output => false)\n\ndef get_request_token(consumer)\n\n\trequest_token = consumer.get_request_token()\n\n  return request_token\nend\n\ndef get_user_authorization(request_token)\n\tputs \"Follow this URL to have a user authorize your app: #{request_token.authorize_url()}\"\n\tputs \"Enter PIN: \"\n\tpin = gets.strip\n\n  return pin\nend\n\ndef obtain_access_token(consumer, request_token, pin)\n\ttoken = request_token.token\n\ttoken_secret = request_token.secret\n\thash = { :oauth_token => token, :oauth_token_secret => token_secret }\n\trequest_token  = OAuth::RequestToken.from_hash(consumer, hash)\n\n\t# Get access token\n\taccess_token = request_token.get_access_token({:oauth_verifier => pin})\n\n\treturn access_token\nend\n\n\ndef user_block(url, oauth_params)\n\toptions = {\n\t    :method => :get,\n\t    headers: {\n\t     \t\"User-Agent\": \"v2BlocksLookupRuby\"\n\t    }\n\t}\n\trequest = Typhoeus::Request.new(url, options)\n\toauth_helper = OAuth::Client::Helper.new(request, oauth_params.merge(:request_uri => url))\n\trequest.options[:headers].merge!({\"Authorization\" => oauth_helper.header}) # Signs the request\n\tresponse = request.run\n\n\treturn response\nend\n\n\n\n# PIN-based OAuth flow - Step 1\nrequest_token = get_request_token(consumer)\n# PIN-based OAuth flow - Step 2\npin = get_user_authorization(request_token)\n# PIN-based OAuth flow - Step 3\naccess_token = obtain_access_token(consumer, request_token, pin)\n\noauth_params = {:consumer => consumer, :token => access_token}\n\n\nresponse = user_block(blocking_url, oauth_params)\nputs response.code, JSON.pretty_generate(JSON.parse(response.body))\n"
  },
  {
    "path": "ruby/users/lookup_mutes.rb",
    "content": "# This script implements the PIN-based OAuth flow to obtain access tokens for a user context request\n# It then makes a Mutes lookup request (by usernames) with OAuth 1.0a authentication (user context)\nrequire 'oauth'\nrequire 'json'\nrequire 'typhoeus'\nrequire 'oauth/request_proxy/typhoeus_request'\n\n# The code below sets the consumer key and secret from your environment variables\n# To set environment variables on Mac OS X, run the export command below from the terminal:\n# export CONSUMER_KEY='YOUR-KEY', CONSUMER_SECRET='YOUR-SECRET'\nconsumer_key = ENV[\"CONSUMER_KEY\"]\nconsumer_secret = ENV[\"CONSUMER_SECRET\"]\n\n# Be sure to replace your-user-id with your own user ID or one of an authenticating user\n# You can find a user ID by using the user lookup endpoint\nid = \"your-user-id\"\n\nmuting_url = \"https://api.x.com/2/users/#{id}/muting\"\n\nconsumer = OAuth::Consumer.new(consumer_key, consumer_secret,\n\t                                :site => 'https://api.x.com',\n\t                                :authorize_path => '/oauth/authenticate',\n\t                                :debug_output => false)\n\ndef get_request_token(consumer)\n\n\trequest_token = consumer.get_request_token()\n\n  return request_token\nend\n\ndef get_user_authorization(request_token)\n\tputs \"Follow this URL to have a user authorize your app: #{request_token.authorize_url()}\"\n\tputs \"Enter PIN: \"\n\tpin = gets.strip\n\n  return pin\nend\n\ndef obtain_access_token(consumer, request_token, pin)\n\ttoken = request_token.token\n\ttoken_secret = request_token.secret\n\thash = { :oauth_token => token, :oauth_token_secret => token_secret }\n\trequest_token  = OAuth::RequestToken.from_hash(consumer, hash)\n\n\t# Get access token\n\taccess_token = request_token.get_access_token({:oauth_verifier => pin})\n\n\treturn access_token\nend\n\n\ndef users_muted(url, oauth_params)\n\toptions = {\n\t    :method => :get,\n\t    headers: {\n\t     \t\"User-Agent\": \"v2MutesLookupRuby\"\n\t    }\n\t}\n\trequest = Typhoeus::Request.new(url, options)\n\toauth_helper = OAuth::Client::Helper.new(request, oauth_params.merge(:request_uri => url))\n\trequest.options[:headers].merge!({\"Authorization\" => oauth_helper.header}) # Signs the request\n\tresponse = request.run\n\n\treturn response\nend\n\n\n\n# PIN-based OAuth flow - Step 1\nrequest_token = get_request_token(consumer)\n# PIN-based OAuth flow - Step 2\npin = get_user_authorization(request_token)\n# PIN-based OAuth flow - Step 3\naccess_token = obtain_access_token(consumer, request_token, pin)\n\noauth_params = {:consumer => consumer, :token => access_token}\n\n\nresponse = users_muted(muting_url, oauth_params)\nputs response.code, JSON.pretty_generate(JSON.parse(response.body))"
  },
  {
    "path": "ruby/users/mute_a_user.rb",
    "content": "# This script implements the PIN-based OAuth flow to obtain access tokens for a user context request\nrequire 'oauth'\nrequire 'json'\nrequire 'typhoeus'\nrequire 'oauth/request_proxy/typhoeus_request'\n\n# The code below sets the consumer key and secret from your environment variables\n# To set environment variables on Mac OS X, run the export command below from the terminal:\n# export CONSUMER_KEY='YOUR-KEY', CONSUMER_SECRET='YOUR-SECRET'\nconsumer_key = ENV[\"CONSUMER_KEY\"]\nconsumer_secret = ENV[\"CONSUMER_SECRET\"]\n\n# Be sure to replace your-user-id with your own user ID or one of an authenticating user\n# You can find a user ID by using the user lookup endpoint\nid = \"your-user-id\"\nmuting_url = \"https://api.x.com/2/users/#{id}/muting\"\n\n# Be sure to add replace id-to-mute with the id of the user you wish to mute.\n# You can find a user ID by using the user lookup endpoint\n@target_user_id = { \"target_user_id\": \"id-to-mute\" }\n\nconsumer = OAuth::Consumer.new(consumer_key, consumer_secret,\n\t                                :site => 'https://api.x.com',\n\t                                :authorize_path => '/oauth/authenticate',\n\t                                :debug_output => false)\n\ndef get_request_token(consumer)\n\n\trequest_token = consumer.get_request_token()\n\n  return request_token\nend\n\ndef get_user_authorization(request_token)\n\tputs \"Follow this URL to have a user authorize your app: #{request_token.authorize_url()}\"\n\tputs \"Enter PIN: \"\n\tpin = gets.strip\n\n  return pin\nend\n\ndef obtain_access_token(consumer, request_token, pin)\n\ttoken = request_token.token\n\ttoken_secret = request_token.secret\n\thash = { :oauth_token => token, :oauth_token_secret => token_secret }\n\trequest_token  = OAuth::RequestToken.from_hash(consumer, hash)\n\n\t# Get access token\n\taccess_token = request_token.get_access_token({:oauth_verifier => pin})\n\n\treturn access_token\nend\n\n\ndef user_mute(url, oauth_params)\n\toptions = {\n\t    :method => :post,\n\t    headers: {\n\t     \t\"User-Agent\": \"v2muteUserRuby\",\n        \"content-type\": \"application/json\"\n\t    },\n\t    body: JSON.dump(@target_user_id)\n\t}\n\trequest = Typhoeus::Request.new(url, options)\n\toauth_helper = OAuth::Client::Helper.new(request, oauth_params.merge(:request_uri => url))\n\trequest.options[:headers].merge!({\"Authorization\" => oauth_helper.header}) # Signs the request\n\tresponse = request.run\n\n\treturn response\nend\n\n\n\n# PIN-based OAuth flow - Step 1\nrequest_token = get_request_token(consumer)\n# PIN-based OAuth flow - Step 2\npin = get_user_authorization(request_token)\n# PIN-based OAuth flow - Step 3\naccess_token = obtain_access_token(consumer, request_token, pin)\n\noauth_params = {:consumer => consumer, :token => access_token}\n\n\nresponse = user_mute(muting_url, oauth_params)\nputs response.code, JSON.pretty_generate(JSON.parse(response.body))\n"
  },
  {
    "path": "ruby/users/unblock_a_user.rb",
    "content": "# This script implements the PIN-based OAuth flow to obtain access tokens for a user context request\n# It then makes a User lookup request (by usernames) with OAuth 1.0a authentication (user context)\n\nrequire 'oauth'\nrequire 'json'\nrequire 'typhoeus'\nrequire 'oauth/request_proxy/typhoeus_request'\n\n# The code below sets the consumer key and secret from your environment variables\n# To set environment variables on Mac OS X, run the export command below from the terminal:\n# export CONSUMER_KEY='YOUR-KEY', CONSUMER_SECRET='YOUR-SECRET'\nconsumer_key = ENV[\"CONSUMER_KEY\"]\nconsumer_secret = ENV[\"CONSUMER_SECRET\"]\n\n# Be sure to replace your-user-id with your own user ID or one of an authenticating user\n# You can find a user ID by using the user lookup endpoint\nsource_user_id = \"your-user-id\"\n\n# Be sure to add replace id-to-unblock with the user id of the user you wish to unblock.\n# You can find a user ID by using the user lookup endpoint\ntarget_user_id = \"id-to-unblock\"\n\n# Returns a user object for one or more users specified by the requested usernames\nuser_unblock_url = \"https://api.x.com/2/users/#{source_user_id}/blocking/#{target_user_id}\"\n\nconsumer = OAuth::Consumer.new(consumer_key, consumer_secret,\n\t                                :site => 'https://api.x.com',\n\t                                :authorize_path => '/oauth/authenticate',\n\t                                :debug_output => false)\n\ndef get_request_token(consumer)\n\n\trequest_token = consumer.get_request_token()\n\n  return request_token\nend\n\ndef get_user_authorization(request_token)\n\tputs \"Follow this URL to have a user authorize your app: #{request_token.authorize_url()}\"\n\tputs \"Enter PIN: \"\n\tpin = gets.strip\n\n  return pin\nend\n\ndef obtain_access_token(consumer, request_token, pin)\n\ttoken = request_token.token\n\ttoken_secret = request_token.secret\n\thash = { :oauth_token => token, :oauth_token_secret => token_secret }\n\trequest_token  = OAuth::RequestToken.from_hash(consumer, hash)\n\n\t# Get access token\n\taccess_token = request_token.get_access_token({:oauth_verifier => pin})\n\n\treturn access_token\nend\n\n\ndef user_unblock(url, oauth_params)\n\toptions = {\n\t    :method => :delete,\n\t    headers: {\n\t     \t\"User-Agent\": \"v2UnblockUserRuby\"\n\t    }\n\t}\n\trequest = Typhoeus::Request.new(url, options)\n\toauth_helper = OAuth::Client::Helper.new(request, oauth_params.merge(:request_uri => url))\n\trequest.options[:headers].merge!({\"Authorization\" => oauth_helper.header}) # Signs the request\n\tresponse = request.run\n\n\treturn response\nend\n\n# PIN-based OAuth flow - Step 1\nrequest_token = get_request_token(consumer)\n# PIN-based OAuth flow - Step 2\npin = get_user_authorization(request_token)\n# PIN-based OAuth flow - Step 3\naccess_token = obtain_access_token(consumer, request_token, pin)\n\noauth_params = {:consumer => consumer, :token => access_token}\n\nresponse = user_unblock(user_unblock_url, oauth_params)\nputs response.code, JSON.pretty_generate(JSON.parse(response.body))\n\n# Note: If you were following the user you blocked, you have removed your follow and will have to refollow the user, even if you did unblock the user.\n"
  },
  {
    "path": "ruby/users/unmute_a_user.rb",
    "content": "# This script implements the PIN-based OAuth flow to obtain access tokens for a user context request\nrequire 'oauth'\nrequire 'json'\nrequire 'typhoeus'\nrequire 'oauth/request_proxy/typhoeus_request'\n\n# The code below sets the consumer key and secret from your environment variables\n# To set environment variables on Mac OS X, run the export command below from the terminal:\n# export CONSUMER_KEY='YOUR-KEY', CONSUMER_SECRET='YOUR-SECRET'\nconsumer_key = ENV[\"CONSUMER_KEY\"]\nconsumer_secret = ENV[\"CONSUMER_SECRET\"]\n\n# Be sure to replace your-user-id with your own user ID or one of an authenticating user\n# You can find a user ID by using the user lookup endpoint\nsource_user_id = \"your-user-id\"\n\n# Be sure to add replace id-to-unmute with the user id of the user you wish to unmute.\n# You can find a user ID by using the user lookup endpoint\ntarget_user_id = \"id-to-unmute\"\n\n# Returns a user object for one or more users specified by the requested usernames\nuser_unmute_url = \"https://api.x.com/2/users/#{source_user_id}/muting/#{target_user_id}\"\n\nconsumer = OAuth::Consumer.new(consumer_key, consumer_secret,\n\t                                :site => 'https://api.x.com',\n\t                                :authorize_path => '/oauth/authenticate',\n\t                                :debug_output => false)\n\ndef get_request_token(consumer)\n\n\trequest_token = consumer.get_request_token()\n\n  return request_token\nend\n\ndef get_user_authorization(request_token)\n\tputs \"Follow this URL to have a user authorize your app: #{request_token.authorize_url()}\"\n\tputs \"Enter PIN: \"\n\tpin = gets.strip\n\n  return pin\nend\n\ndef obtain_access_token(consumer, request_token, pin)\n\ttoken = request_token.token\n\ttoken_secret = request_token.secret\n\thash = { :oauth_token => token, :oauth_token_secret => token_secret }\n\trequest_token  = OAuth::RequestToken.from_hash(consumer, hash)\n\n\t# Get access token\n\taccess_token = request_token.get_access_token({:oauth_verifier => pin})\n\n\treturn access_token\nend\n\n\ndef user_unmute(url, oauth_params)\n\toptions = {\n\t    :method => :delete,\n\t    headers: {\n\t     \t\"User-Agent\": \"v2UnmuteUserRuby\"\n\t    }\n\t}\n\trequest = Typhoeus::Request.new(url, options)\n\toauth_helper = OAuth::Client::Helper.new(request, oauth_params.merge(:request_uri => url))\n\trequest.options[:headers].merge!({\"Authorization\" => oauth_helper.header}) # Signs the request\n\tresponse = request.run\n\n\treturn response\nend\n\n# PIN-based OAuth flow - Step 1\nrequest_token = get_request_token(consumer)\n# PIN-based OAuth flow - Step 2\npin = get_user_authorization(request_token)\n# PIN-based OAuth flow - Step 3\naccess_token = obtain_access_token(consumer, request_token, pin)\n\noauth_params = {:consumer => consumer, :token => access_token}\n\nresponse = user_unmute(user_unmute_url, oauth_params)\nputs response.code, JSON.pretty_generate(JSON.parse(response.body))\n"
  }
]