Skip to content

Commit

Permalink
Merge pull request #12 from snus-kin/v2
Browse files Browse the repository at this point in the history
Twitter API V2 Endpoints
  • Loading branch information
snus-kin authored Jun 5, 2022
2 parents 02cd10c + 53f8da6 commit afe1a53
Show file tree
Hide file tree
Showing 29 changed files with 1,119 additions and 2,286 deletions.
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
*~
src/twitter
examples/example
examples/credential.json
credential.json
nimcache/
*.swp
twitter
test.jpg
test.mp4
examples/v2example/v2example
40 changes: 20 additions & 20 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,31 +1,35 @@
# twitter ![.github/workflows/tests.yml](https://github.com/snus-kin/twitter.nim/workflows/.github/workflows/tests.yml/badge.svg?branch=master)
# twitter ![.github/workflows/tests.yml](https://github.com/snus-kin/twitter.nim/workflows/.github/workflows/tests.yml/badge.svg?branch=master) ![](https://img.shields.io/endpoint?url=https%3A%2F%2Ftwbadges.glitch.me%2Fbadges%2Fstandard) ![](https://img.shields.io/endpoint?url=https%3A%2F%2Ftwbadges.glitch.me%2Fbadges%2Fv2)

Low-level twitter API wrapper library for Nim.
Low-level Twitter API wrapper library for Nim.

[Documentation](https://snus-kin.github.io/twitter.nim/twitter.html)

## Installation

From Nimble:

```console
$ nimble install twitter
```

From Github:
From GitHub:

```console
$ git clone git://github.com/snus-kin/twitter.nim
$ cd twitter.nim && nimble install
```

## Usage
To use the library, `import twitter` and compile with `-d:ssl`

Note: only the standard (free) endpoints are wrapped. All mentioned in the
To use the library, `import twitter` and compile with `-d:ssl`

Note: only the free endpoints are wrapped. All mentioned in the
[API Reference Index](https://developer.twitter.com/en/docs/api-reference-index)
have been implemented, please open an issue if you find one that isn't in this
reference.
reference or if anything new's been added I haven't seen yet.

## Example

```nim
import twitter, json, strtabs
Expand All @@ -39,27 +43,23 @@ when isMainModule:
parsed["AccessTokenSecret"].str)
# Simply get.
var resp = twitterAPI.get("account/verify_credentials.json")
var resp = twitterAPI.get("1.1/account/verify_credentials.json")
echo resp.status
# Using proc corresponding twitter REST APIs.
resp = twitterAPI.userTimeline()
echo parseJson(resp.body)
# ditto, but selected by screen name.
resp = twitterAPI.usersLookup("sn_fk_n")
resp = twitter.v1.usersLookup(twitterAPI, "sn_fk_n")
echo pretty parseJson(resp.body)
# Using `callAPI` template.
let status = {"status": "Hello world!"}.newStringTable
resp = twitterAPI.callAPI(statusesUpdate, status)
# Using proc corresponding twitter REST APIs.
resp = twitter.v1.statusesUserTimeline(twitterAPI)
echo pretty parseJson(resp.body)
# Upload media
var ubody = {"media_type": "twitter_image"}.newStringTable
var image = readFile("example.png")
resp = twitterAPI.post("media/upload.json", ubody, media=true, data=image)
echo parseJson(resp.body)
# Using `callAPI` template.
let status = {"status": "hello world"}.newStringTable
resp = twitterAPI.callAPI(twitter.v1.statusesUpdate, status)
echo pretty parseJson(resp.body)
```

See also: `examples/` for more extensive examples on the library's use.

To use basic auth, you will have to construct the request using the bare request object.
File renamed without changes.
Binary file added examples/v1example/example
Binary file not shown.
24 changes: 12 additions & 12 deletions examples/example.nim → examples/v1example/example.nim
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import json, strtabs, httpclient, streams, os
import ../src/twitter
import ../../src/twitter

when isMainModule:
var parsed = parseFile("credential.json")
Expand All @@ -11,20 +11,20 @@ when isMainModule:
parsed["AccessTokenSecret"].str)

# Simply get.
var resp = twitterAPI.get("account/verify_credentials.json")
var resp = twitterAPI.get("1.1/account/verify_credentials.json")
echo resp.status

# ditto, but selected by screen name.
resp = twitterAPI.usersLookup("sn_fk_n")
resp = twitter.v1.usersLookup(twitterAPI, "sn_fk_n")
echo pretty parseJson(resp.body)

# Using proc corresponding twitter REST APIs.
resp = twitterAPI.statusesUserTimeline()
resp = twitter.v1.statusesUserTimeline(twitterAPI)
echo pretty parseJson(resp.body)

# Using `callAPI` template.
let status = {"status": "hello world"}.newStringTable
resp = twitterAPI.callAPI(statusesUpdate, status)
resp = twitterAPI.callAPI(twitter.v1.statusesUpdate, status)
echo pretty parseJson(resp.body)

# Upload files in a stream
Expand All @@ -33,7 +33,7 @@ when isMainModule:
let mediaSize = "test.jpg".getFileSize

# INIT
resp = twitterAPI.mediaUploadInit("image/jpg", $ mediaSize)
resp = twitter.v1.mediaUploadInit(twitterAPI, "image/jpg", $ mediaSize)
let initResp = parseJson(resp.body)
echo pretty initResp
let mediaId = initResp["media_id_string"].getStr
Expand All @@ -45,15 +45,15 @@ when isMainModule:
while not mediaStream.atEnd():
buffer = mediaStream.readStr(buffersize)
echo "Uploading segment: ", segment
resp = twitterAPI.mediaUploadAppend(mediaId, $ segment, buffer)
resp = twitter.v1.mediaUploadAppend(twitterAPI, mediaId, $ segment, buffer)
# Response should be 204
if resp.status != "204 No Content":
stderr.writeLine "Error when uploading, server returned: " & resp.status
quit(1)
segment += 1

# FINALIZE
resp = twitterAPI.mediaUploadFinalize(mediaId)
resp = twitter.v1.mediaUploadFinalize(twitterAPI, mediaId)
echo pretty parseJson(resp.body)
let finalResp = parseJson(resp.body)
let finalMediaId = finalResp["media_id_string"].getStr
Expand All @@ -64,12 +64,12 @@ when isMainModule:
# STATUS
# If the API tells use it has to process the media
if finalResp.hasKey("processing_info"):
resp = twitterAPI.mediaUploadStatus(finalMediaId)
resp = twitter.v1.mediaUploadStatus(twitterAPI, finalMediaId)
var respBody = parseJson(resp.body)
# Loop until it reaches the end state of 'failed' or 'succeeded'
while respBody["processing_info"]["state"].getStr notin ["failed", "succeeded"]:
echo pretty parseJson(resp.body)
resp = twitterAPI.mediaUploadStatus(finalMediaId)
resp = twitter.v1.mediaUploadStatus(twitterAPI, finalMediaId)
respBody = parseJson(resp.body)
# Sleep for the amount of seconds it tells you to
sleep(respBody["processing_info"]["check_after_secs"].getInt * 100)
Expand All @@ -79,10 +79,10 @@ when isMainModule:

# Attach metadata
let mediaMetadata = %* {"media_id": mediaId, "alt_text":{"text":"This is an example of alt text"}}
resp = twitterAPI.mediaMetadataCreate(mediaMetadata)
resp = twitter.v1.mediaMetadataCreate(twitterAPI, mediaMetadata)
# This should be 2xx
echo resp.status

# Send a tweet with that media
let mediaStatus = {"media_ids": finalMediaId}.newStringTable
resp = twitterAPI.statusesUpdate("This is a media upload test", mediaStatus)
resp = twitter.v1.statusesUpdate(twitterAPI, "This is a media upload test", mediaStatus)
File renamed without changes.
10 changes: 10 additions & 0 deletions examples/v2example/v2example.nim
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import json, strtabs, httpclient, streams, os
import ../../src/twitter

when isMainModule:
let parsed = parseFile("credential.json")
var twitterAPI = newTwitterAPI(parsed["BearerToken"].str)

# Bearer token get info about an account
let resp = twitter.v2.usersId(twitterAPI, "1140672492220162052")
echo pretty parseJson(resp.body)
2 changes: 2 additions & 0 deletions examples/v2example/v2example.nim.cfg
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@

-d:ssl
12 changes: 11 additions & 1 deletion src/endpoints/auth.nim → src/auth.nim
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import strtabs, httpclient
import ../utility/[requests, types]
import utility/[requests, types]
# --------------
# authentication
# --------------
Expand Down Expand Up @@ -66,3 +66,13 @@ proc oauth2Token*(twitter: TwitterAPI, grantType: string,
else:
return post(twitter, "oauth2/token", {
"grant_type": grantType}.newStringTable)

proc v2oauth2Token*(twitter: TwitterAPI, grantType: string,
additionalParams: StringTableRef = nil): Response =
## `oauth2/token` endpoint, I'm not sure how this is different to the previous endpoint, as of now I have no clarification.
if additionalParams != nil:
additionalParams["grant_type"] = grantType
return post(twitter, "2/oauth2/token", additionalParams)
else:
return post(twitter, "2/oauth2/token", {
"grant_type": grantType}.newStringTable)
Loading

0 comments on commit afe1a53

Please sign in to comment.