Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 6 additions & 6 deletions .github/workflows/context7-refresh.yml
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ jobs:
set -euo pipefail

if [ -z "$CONTEXT7_API_KEY" ]; then
echo "::warning ::CONTEXT7_API_KEY secret is not configured. Configure it to enable automatic Context7 refreshes."
echo "::warning ::CONTEXT7_API_KEY is missing. Add the secret to refresh Context7 automatically."
exit 0
fi

Expand All @@ -55,30 +55,30 @@ jobs:
;;
400)
if grep -Eiq "active-task|being processed|already.*process" "$body_file"; then
echo "::warning ::Context7 is already processing another library. Retry on the next docs change."
echo "::warning ::Context7 is processing another library. Retry after the next docs change."
cat "$body_file"
elif grep -Eiq "too-early|minimum .* days|required between updates" "$body_file"; then
echo "::warning ::Context7 refresh is not due yet."
cat "$body_file"
else
echo "::error ::Context7 refresh returned HTTP $status."
echo "::error ::Context7 refresh returned HTTP $status. Review the response."
cat "$body_file"
exit 1
fi
;;
404)
echo "::warning ::Context7 library /xquik-dev/x-twitter-scraper-java is not available yet. Add processing may still be pending."
echo "::warning ::Context7 library /xquik-dev/x-twitter-scraper-java is unavailable. Wait for initial indexing."
cat "$body_file"
;;
401|403)
echo "::error ::Context7 authentication failed."
echo "::error ::Context7 authentication failed. Check CONTEXT7_API_KEY."
exit 1
;;
429)
echo "::warning ::Context7 refresh is rate limited. Retry on the next docs change."
;;
*)
echo "::error ::Context7 refresh returned HTTP $status."
echo "::error ::Context7 refresh returned HTTP $status. Review the response."
cat "$body_file"
exit 1
;;
Expand Down
2 changes: 0 additions & 2 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
# Contributing

Thank you for improving the Xquik Java SDK.

Read [GOVERNANCE.md](GOVERNANCE.md) before proposing major changes.

Follow the shared [Xquik contribution policy][contribution-policy].
Expand Down
14 changes: 7 additions & 7 deletions OPENSSF.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ No OpenSSF-defined ineligibility applies.
| Governance | Public roles, decisions, releases, and continuity policy |
| Security reporting | Private reporting, response targets, boundaries, and threat model |
| Runtime compatibility | Java 8 bytecode with JDK 26 tests |
| Functional tests | 1,342 tests across 316 suites with no skips |
| Functional tests | 1,418 tests across 329 suites with no skips |
| Line coverage | `./scripts/coverage` enforces 90% |
| Branch coverage | `./scripts/coverage` enforces 80% |
| Static analysis | Compiler checks, formatting checks, and CodeQL |
Expand All @@ -36,17 +36,17 @@ No OpenSSF-defined ineligibility applies.
| CI | Pull requests and pushes run pinned, least-privilege workflows |
| Two-factor authentication | The Xquik-dev organization requires 2FA |

The maintained-source gate covers 1,194 of 1,319 executable lines.
The maintained-source gate covers 1,198 of 1,319 executable lines.

That result is 90.52% line coverage.
That result is 90.83% line coverage.

It covers 420 of 520 branches, or 80.77%.
It covers 424 of 520 branches, or 81.54%.

The raw report keeps untouched generated-source coverage visible.

It covers 37,702 of 91,257 generated-inclusive lines, or 41.31%.
It covers 104,652 of 110,632 generated-inclusive lines, or 94.59%.

It covers 5,220 of 23,952 generated-inclusive branches, or 21.79%.
It covers 27,560 of 30,010 generated-inclusive branches, or 91.84%.

Exclusions use the repository-owned, provider-neutral generated-source header prefix.

Expand Down Expand Up @@ -93,7 +93,7 @@ Do not claim Gold while any mandatory criterion remains unmet.
| Human security review | No completed review exists within 5 years | Commission and publish a scoped review |
| Generated code coverage | Gold does not explicitly exempt generated code | Confirm applicability or raise generated-inclusive coverage |

This remediation pull request needs a different human reviewer.
Gold eligibility still requires review by a different human.

## Maintenance

Expand Down
70 changes: 34 additions & 36 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
# X (Twitter) Scraper Java SDK: Tweet Search, Timelines, Followers & Posting
# Xquik Java SDK: Twitter Search, Followers & X Automation

[![CI](https://github.com/Xquik-dev/x-twitter-scraper-java/actions/workflows/ci.yml/badge.svg)](https://github.com/Xquik-dev/x-twitter-scraper-java/actions/workflows/ci.yml)
[![OpenSSF Best Practices](https://www.bestpractices.dev/projects/13735/badge)](https://www.bestpractices.dev/projects/13735)

Use Xquik's typed Java client for X data and confirmed actions.
Use the Xquik Java SDK for Twitter search, timelines, profiles & followers.

It supports tweet search, timeline extraction, follower exports, monitoring, and posting.
Manage media, webhooks & X automation with typed Java methods.

Use it as a typed X API or Twitter API alternative.
It provides a Twitter API alternative through documented Xquik REST routes.

[API reference](https://docs.xquik.com/api-reference/overview) ·
[Authentication](https://xquik.com/auth.md) ·
Expand All @@ -23,39 +23,36 @@ Use it as a typed X API or Twitter API alternative.
## Choose the Java SDK

Choose this client for Java services using builders and typed models.
Use the synchronous client for simple request flows.
Call `client.async()` for `CompletableFuture` pipelines.
Use synchronous calls or `client.async()` for `CompletableFuture` pipelines.

## Common X Data Tasks
## Common Twitter & X Tasks

These questions map customer language to exact routes and Java services.
Map each task to its REST route and Java service.

| Customer Question | REST Route | Java Service |
| Task | REST Route | Java Service |
| --- | --- | --- |
| How do I search tweets without the X API? | `GET /x/tweets/search` | `client.x().tweets()` |
| How do I retrieve tweets, threads, replies, or quotes? | `GET /x/tweets/{id}`, `GET /x/tweets/{id}/thread` | `client.x().tweets()` |
| How do I search X or Twitter users? | `GET /x/users/search` | `client.x().users()` |
| How do I scrape an X profile timeline? | `GET /x/users/{id}/tweets` | `client.x().users()` |
| How do I export X followers? | `GET /x/users/{id}/followers` | `client.x().users()` |
| How do I export X following accounts? | `GET /x/users/{id}/following` | `client.x().users()` |
| How do I collect verified followers? | `GET /x/users/{id}/verified-followers` | `client.x().users()` |
| How do I collect mentions, likes, replies, or media? | `GET /x/users/{id}/mentions`, `GET /x/users/{id}/likes` | `client.x().users()` |
| How do I extract my X home timeline? | `GET /x/timeline` | `client.x()` |
| How do I extract list tweets, members, or followers? | `GET /x/lists/{id}/tweets`, `GET /x/lists/{id}/members` | `client.x().lists()` |
| How do I search communities and collect their tweets? | `GET /x/communities/search`, `GET /x/communities/{id}/tweets` | `client.x().communities()` |
| How do I read bookmarks and bookmark folders? | `GET /x/bookmarks`, `GET /x/bookmarks/folders` | `client.x().bookmarks()` |
| How do I read notifications or direct messages? | `GET /x/notifications`, `GET /x/dm/{userId}/history` | `client.x()`, `client.x().dm()` |
| How do I discover X trends? | `GET /x/trends` | `client.x().getTrends()` |
| How do I export large X datasets? | `POST /extractions` | `client.extractions()` |
| How do I monitor tweet keywords or accounts? | `POST /monitors/keywords`, `POST /monitors` | `client.monitors()` |
| How do I receive signed event deliveries? | `POST /webhooks` | `client.webhooks()` |
| How do I post, like, retweet, or follow? | `POST /x/tweets`, `POST /x/users/{id}/follow` | `client.x().tweets()`, `client.x().users()` |
| How do I send media or update a profile? | `POST /x/media`, `PATCH /x/profile` | `client.x().media()`, `client.x().profile()` |
| How do I manage connected X accounts? | `GET /x/accounts`, `POST /x/accounts` | `client.x().accounts()` |

Use [Javadocs](https://javadoc.io/doc/com.xquik.api/x-twitter-scraper-java) for typed methods.

Use [API reference](https://docs.xquik.com/api-reference/overview) for request contracts.
| Search tweets without the X API | `GET /x/tweets/search` | `client.x().tweets()` |
| Retrieve tweets, threads, replies, or quotes | `GET /x/tweets/{id}`, `GET /x/tweets/{id}/thread` | `client.x().tweets()` |
| Search X or Twitter users | `GET /x/users/search` | `client.x().users()` |
| Scrape an X profile timeline | `GET /x/users/{id}/tweets` | `client.x().users()` |
| Export X followers | `GET /x/users/{id}/followers` | `client.x().users()` |
| Export X following accounts | `GET /x/users/{id}/following` | `client.x().users()` |
| Collect verified followers | `GET /x/users/{id}/verified-followers` | `client.x().users()` |
| Collect mentions, likes, replies, or media | `GET /x/users/{id}/mentions`, `GET /x/users/{id}/likes` | `client.x().users()` |
| Extract an X home timeline | `GET /x/timeline` | `client.x()` |
| Extract list tweets, members, or followers | `GET /x/lists/{id}/tweets`, `GET /x/lists/{id}/members` | `client.x().lists()` |
| Search communities and collect their tweets | `GET /x/communities/search`, `GET /x/communities/{id}/tweets` | `client.x().communities()` |
| Read bookmarks and bookmark folders | `GET /x/bookmarks`, `GET /x/bookmarks/folders` | `client.x().bookmarks()` |
| Read notifications or direct messages | `GET /x/notifications`, `GET /x/dm/{userId}/history` | `client.x()`, `client.x().dm()` |
| Discover X trends | `GET /x/trends` | `client.x().getTrends()` |
| Export large X datasets | `POST /extractions` | `client.extractions()` |
| Monitor tweet keywords or accounts | `POST /monitors/keywords`, `POST /monitors` | `client.monitors()` |
| Receive signed event deliveries | `POST /webhooks` | `client.webhooks()` |
| Post, like, retweet, or follow | `POST /x/tweets`, `POST /x/users/{id}/follow` | `client.x().tweets()`, `client.x().users()` |
| Send media or update a profile | `POST /x/media`, `PATCH /x/profile` | `client.x().media()`, `client.x().profile()` |
| Manage connected X accounts | `GET /x/accounts`, `POST /x/accounts` | `client.x().accounts()` |

Use [Javadocs](https://javadoc.io/doc/com.xquik.api/x-twitter-scraper-java) for methods and the [API reference](https://docs.xquik.com/api-reference/overview) for contracts.

## Install

Expand Down Expand Up @@ -83,11 +80,12 @@ Maven:

Every Maven Central file has a detached OpenPGP signature.

Verify the main Java artifact:
Set `VERSION` to the release version. Then verify the main artifact:

```sh
artifact="x-twitter-scraper-java-0.5.2.jar"
base="https://repo.maven.apache.org/maven2/com/xquik/api/x-twitter-scraper-java/0.5.2"
version=VERSION
artifact="x-twitter-scraper-java-$version.jar"
base="https://repo.maven.apache.org/maven2/com/xquik/api/x-twitter-scraper-java/$version"
curl --fail --location --remote-name "$base/$artifact"
curl --fail --location --remote-name "$base/$artifact.asc"
gpg --keyserver hkps://keyserver.ubuntu.com --recv-keys 0xD2037E4157E62A59
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ configure<MavenPublishBaseExtension> {
pom {
name.set("Xquik Java SDK")
description.set(
"Java SDK for the Xquik REST API. Xquik is an independent third-party service. " +
"Java SDK for Twitter search, followers, webhooks & X automation through Xquik. " +
"Not affiliated with X Corp. \"Twitter\" and \"X\" are trademarks of X Corp."
)
url.set("https://xquik.com")
Expand Down