diff --git a/api.md b/api.md new file mode 100644 index 0000000..1680fb6 --- /dev/null +++ b/api.md @@ -0,0 +1,946 @@ + + +

Personal Web Services API v1.0.0

+ +> Scroll down for code samples, example requests and responses. Select a language for code samples from the tabs above or the mobile navigation menu. + +Documentation for various web services hosted under mono.exhq.dev + +

Discord Lookup

+ +Discord user information lookup service + +## get__v1_user_{userId} + +> Code samples + +```shell +# You can also use wget +curl -X GET /v1/user/{userId} \ + -H 'Accept: application/json' + +``` + +```http +GET /v1/user/{userId} HTTP/1.1 + +Accept: application/json + +``` + +```javascript + +const headers = { + 'Accept':'application/json' +}; + +fetch('/v1/user/{userId}', +{ + method: 'GET', + + headers: headers +}) +.then(function(res) { + return res.json(); +}).then(function(body) { + console.log(body); +}); + +``` + +```ruby +require 'rest-client' +require 'json' + +headers = { + 'Accept' => 'application/json' +} + +result = RestClient.get '/v1/user/{userId}', + params: { + }, headers: headers + +p JSON.parse(result) + +``` + +```python +import requests +headers = { + 'Accept': 'application/json' +} + +r = requests.get('/v1/user/{userId}', headers = headers) + +print(r.json()) + +``` + +```php + 'application/json', +); + +$client = new \GuzzleHttp\Client(); + +// Define array of request body. +$request_body = array(); + +try { + $response = $client->request('GET','/v1/user/{userId}', array( + 'headers' => $headers, + 'json' => $request_body, + ) + ); + print_r($response->getBody()->getContents()); + } + catch (\GuzzleHttp\Exception\BadResponseException $e) { + // handle exception or api errors. + print_r($e->getMessage()); + } + + // ... + +``` + +```java +URL obj = new URL("/v1/user/{userId}"); +HttpURLConnection con = (HttpURLConnection) obj.openConnection(); +con.setRequestMethod("GET"); +int responseCode = con.getResponseCode(); +BufferedReader in = new BufferedReader( + new InputStreamReader(con.getInputStream())); +String inputLine; +StringBuffer response = new StringBuffer(); +while ((inputLine = in.readLine()) != null) { + response.append(inputLine); +} +in.close(); +System.out.println(response.toString()); + +``` + +```go +package main + +import ( + "bytes" + "net/http" +) + +func main() { + + headers := map[string][]string{ + "Accept": []string{"application/json"}, + } + + data := bytes.NewBuffer([]byte{jsonReq}) + req, err := http.NewRequest("GET", "/v1/user/{userId}", data) + req.Header = headers + + client := &http.Client{} + resp, err := client.Do(req) + // ... +} + +``` + +`GET /v1/user/{userId}` + +*Look up Discord user information* + +Retrieves information about a Discord user using their ID + +

Parameters

+ +|Name|In|Type|Required|Description| +|---|---|---|---|---| +|userId|path|string|true|none| + +> Example responses + +> 200 Response + +```json +{ + "id": "712639419785412668", + "created_at": "2020-05-20T12:14:37.877Z", + "username": "exhq", + "avatar": { + "id": "93dd1fc1629fb1ec652c68203af4f3f1", + "link": "https://cdn.discordapp.com/avatars/712639419785412668/93dd1fc1629fb1ec652c68203af4f3f1", + "is_animated": false + }, + "avatar_decoration": null, + "badges": [ + "HOUSE_BALANCE" + ], + "accent_color": null, + "global_name": "ECHO 🐈", + "banner": { + "id": null, + "link": null, + "is_animated": false, + "color": null + }, + "raw": { + "id": "712639419785412668", + "username": "exhq", + "avatar": "93dd1fc1629fb1ec652c68203af4f3f1", + "discriminator": "0", + "public_flags": 256, + "flags": 256, + "banner": null, + "accent_color": null, + "global_name": "ECHO 🐈", + "avatar_decoration_data": null, + "banner_color": null, + "clan": null + } +} +``` + +

Responses

+ +|Status|Meaning|Description|Schema| +|---|---|---|---| +|200|[OK](https://tools.ietf.org/html/rfc7231#section-6.3.1)|Successful response with user information|[DiscordUser](#schemadiscorduser)| + + + +

Review System

+ +Backend review system for website + +## get__getreviews + +> Code samples + +```shell +# You can also use wget +curl -X GET /getreviews \ + -H 'Accept: application/json' + +``` + +```http +GET /getreviews HTTP/1.1 + +Accept: application/json + +``` + +```javascript + +const headers = { + 'Accept':'application/json' +}; + +fetch('/getreviews', +{ + method: 'GET', + + headers: headers +}) +.then(function(res) { + return res.json(); +}).then(function(body) { + console.log(body); +}); + +``` + +```ruby +require 'rest-client' +require 'json' + +headers = { + 'Accept' => 'application/json' +} + +result = RestClient.get '/getreviews', + params: { + }, headers: headers + +p JSON.parse(result) + +``` + +```python +import requests +headers = { + 'Accept': 'application/json' +} + +r = requests.get('/getreviews', headers = headers) + +print(r.json()) + +``` + +```php + 'application/json', +); + +$client = new \GuzzleHttp\Client(); + +// Define array of request body. +$request_body = array(); + +try { + $response = $client->request('GET','/getreviews', array( + 'headers' => $headers, + 'json' => $request_body, + ) + ); + print_r($response->getBody()->getContents()); + } + catch (\GuzzleHttp\Exception\BadResponseException $e) { + // handle exception or api errors. + print_r($e->getMessage()); + } + + // ... + +``` + +```java +URL obj = new URL("/getreviews"); +HttpURLConnection con = (HttpURLConnection) obj.openConnection(); +con.setRequestMethod("GET"); +int responseCode = con.getResponseCode(); +BufferedReader in = new BufferedReader( + new InputStreamReader(con.getInputStream())); +String inputLine; +StringBuffer response = new StringBuffer(); +while ((inputLine = in.readLine()) != null) { + response.append(inputLine); +} +in.close(); +System.out.println(response.toString()); + +``` + +```go +package main + +import ( + "bytes" + "net/http" +) + +func main() { + + headers := map[string][]string{ + "Accept": []string{"application/json"}, + } + + data := bytes.NewBuffer([]byte{jsonReq}) + req, err := http.NewRequest("GET", "/getreviews", data) + req.Header = headers + + client := &http.Client{} + resp, err := client.Do(req) + // ... +} + +``` + +`GET /getreviews` + +*Get reviews* + +Retrieves reviews from the backend review system + +> Example responses + +> 200 Response + +```json +[ + { + "reviewID": 1, + "discordID": "712653921692155965", + "reviewText": "meow", + "timestamp": "1708902649485" + } +] +``` + +

Responses

+ +|Status|Meaning|Description|Schema| +|---|---|---|---| +|200|[OK](https://tools.ietf.org/html/rfc7231#section-6.3.1)|Successful response with reviews|Inline| + +

Response Schema

+ +Status Code **200** + +|Name|Type|Required|Restrictions|Description| +|---|---|---|---|---| +|*anonymous*|[[Review](#schemareview)]|false|none|none| +|» reviewID|integer|false|none|none| +|» discordID|string|false|none|none| +|» reviewText|string|false|none|none| +|» timestamp|string|false|none|none| + + + +

Song Link Cache

+ +Cached proxy for song.link API + +## get__ + +> Code samples + +```shell +# You can also use wget +curl -X GET /?url=spotify%3Atrack%3A6BJHsLiE47Sk0wQkuppqhr \ + -H 'Accept: application/json' + +``` + +```http +GET /?url=spotify%3Atrack%3A6BJHsLiE47Sk0wQkuppqhr HTTP/1.1 + +Accept: application/json + +``` + +```javascript + +const headers = { + 'Accept':'application/json' +}; + +fetch('/?url=spotify%3Atrack%3A6BJHsLiE47Sk0wQkuppqhr', +{ + method: 'GET', + + headers: headers +}) +.then(function(res) { + return res.json(); +}).then(function(body) { + console.log(body); +}); + +``` + +```ruby +require 'rest-client' +require 'json' + +headers = { + 'Accept' => 'application/json' +} + +result = RestClient.get '/', + params: { + 'url' => 'string' +}, headers: headers + +p JSON.parse(result) + +``` + +```python +import requests +headers = { + 'Accept': 'application/json' +} + +r = requests.get('/', params={ + 'url': 'spotify:track:6BJHsLiE47Sk0wQkuppqhr' +}, headers = headers) + +print(r.json()) + +``` + +```php + 'application/json', +); + +$client = new \GuzzleHttp\Client(); + +// Define array of request body. +$request_body = array(); + +try { + $response = $client->request('GET','/', array( + 'headers' => $headers, + 'json' => $request_body, + ) + ); + print_r($response->getBody()->getContents()); + } + catch (\GuzzleHttp\Exception\BadResponseException $e) { + // handle exception or api errors. + print_r($e->getMessage()); + } + + // ... + +``` + +```java +URL obj = new URL("/?url=spotify%3Atrack%3A6BJHsLiE47Sk0wQkuppqhr"); +HttpURLConnection con = (HttpURLConnection) obj.openConnection(); +con.setRequestMethod("GET"); +int responseCode = con.getResponseCode(); +BufferedReader in = new BufferedReader( + new InputStreamReader(con.getInputStream())); +String inputLine; +StringBuffer response = new StringBuffer(); +while ((inputLine = in.readLine()) != null) { + response.append(inputLine); +} +in.close(); +System.out.println(response.toString()); + +``` + +```go +package main + +import ( + "bytes" + "net/http" +) + +func main() { + + headers := map[string][]string{ + "Accept": []string{"application/json"}, + } + + data := bytes.NewBuffer([]byte{jsonReq}) + req, err := http.NewRequest("GET", "/", data) + req.Header = headers + + client := &http.Client{} + resp, err := client.Do(req) + // ... +} + +``` + +`GET /` + +*Get cached song.link data* + +Cached proxy for song.link API responses with CORS support + +

Parameters

+ +|Name|In|Type|Required|Description| +|---|---|---|---|---| +|url|query|string|true|Encoded song URL or identifier| + +> Example responses + +> 200 Response + +```json +{ + "entityUniqueId": "SPOTIFY_SONG::6BJHsLiE47Sk0wQkuppqhr", + "userCountry": "US", + "pageUrl": "https://song.link/s/6BJHsLiE47Sk0wQkuppqhr", + "entitiesByUniqueId": { + "property1": { + "id": "6BJHsLiE47Sk0wQkuppqhr", + "type": "song", + "title": "From the Start", + "artistName": "Good Kid", + "thumbnailUrl": "https://i.scdn.co/image/ab67616d0000b273e67835d0a5d81fa4f268b513", + "thumbnailWidth": 640, + "thumbnailHeight": 640, + "apiProvider": "spotify", + "platforms": [ + "spotify" + ] + }, + "property2": { + "id": "6BJHsLiE47Sk0wQkuppqhr", + "type": "song", + "title": "From the Start", + "artistName": "Good Kid", + "thumbnailUrl": "https://i.scdn.co/image/ab67616d0000b273e67835d0a5d81fa4f268b513", + "thumbnailWidth": 640, + "thumbnailHeight": 640, + "apiProvider": "spotify", + "platforms": [ + "spotify" + ] + } + }, + "linksByPlatform": { + "property1": { + "country": "US", + "url": "https://open.spotify.com/track/6BJHsLiE47Sk0wQkuppqhr", + "entityUniqueId": "SPOTIFY_SONG::6BJHsLiE47Sk0wQkuppqhr", + "nativeAppUriMobile": "spotify:track:6BJHsLiE47Sk0wQkuppqhr", + "nativeAppUriDesktop": "spotify:track:6BJHsLiE47Sk0wQkuppqhr" + }, + "property2": { + "country": "US", + "url": "https://open.spotify.com/track/6BJHsLiE47Sk0wQkuppqhr", + "entityUniqueId": "SPOTIFY_SONG::6BJHsLiE47Sk0wQkuppqhr", + "nativeAppUriMobile": "spotify:track:6BJHsLiE47Sk0wQkuppqhr", + "nativeAppUriDesktop": "spotify:track:6BJHsLiE47Sk0wQkuppqhr" + } + } +} +``` + +

Responses

+ +|Status|Meaning|Description|Schema| +|---|---|---|---| +|200|[OK](https://tools.ietf.org/html/rfc7231#section-6.3.1)|Cached song.link response|[SongLinkResponse](#schemasonglinkresponse)| + + + +# Schemas + +

DiscordUser

+ + + + + + +```json +{ + "id": "712639419785412668", + "created_at": "2020-05-20T12:14:37.877Z", + "username": "exhq", + "avatar": { + "id": "93dd1fc1629fb1ec652c68203af4f3f1", + "link": "https://cdn.discordapp.com/avatars/712639419785412668/93dd1fc1629fb1ec652c68203af4f3f1", + "is_animated": false + }, + "avatar_decoration": null, + "badges": [ + "HOUSE_BALANCE" + ], + "accent_color": null, + "global_name": "ECHO 🐈", + "banner": { + "id": null, + "link": null, + "is_animated": false, + "color": null + }, + "raw": { + "id": "712639419785412668", + "username": "exhq", + "avatar": "93dd1fc1629fb1ec652c68203af4f3f1", + "discriminator": "0", + "public_flags": 256, + "flags": 256, + "banner": null, + "accent_color": null, + "global_name": "ECHO 🐈", + "avatar_decoration_data": null, + "banner_color": null, + "clan": null + } +} + +``` + +### Properties + +|Name|Type|Required|Restrictions|Description| +|---|---|---|---|---| +|id|string|false|none|none| +|created_at|string(date-time)|false|none|none| +|username|string|false|none|none| +|avatar|[DiscordAvatar](#schemadiscordavatar)|false|none|none| +|avatar_decoration|string¦null|false|none|none| +|badges|[string]|false|none|none| +|accent_color|string¦null|false|none|none| +|global_name|string|false|none|none| +|banner|[DiscordBanner](#schemadiscordbanner)|false|none|none| +|raw|[DiscordRawData](#schemadiscordrawdata)|false|none|none| + +

DiscordAvatar

+ + + + + + +```json +{ + "id": "93dd1fc1629fb1ec652c68203af4f3f1", + "link": "https://cdn.discordapp.com/avatars/712639419785412668/93dd1fc1629fb1ec652c68203af4f3f1", + "is_animated": false +} + +``` + +### Properties + +|Name|Type|Required|Restrictions|Description| +|---|---|---|---|---| +|id|string|false|none|none| +|link|string|false|none|none| +|is_animated|boolean|false|none|none| + +

DiscordBanner

+ + + + + + +```json +{ + "id": null, + "link": null, + "is_animated": false, + "color": null +} + +``` + +### Properties + +|Name|Type|Required|Restrictions|Description| +|---|---|---|---|---| +|id|string¦null|false|none|none| +|link|string¦null|false|none|none| +|is_animated|boolean|false|none|none| +|color|string¦null|false|none|none| + +

DiscordRawData

+ + + + + + +```json +{ + "id": "712639419785412668", + "username": "exhq", + "avatar": "93dd1fc1629fb1ec652c68203af4f3f1", + "discriminator": "0", + "public_flags": 256, + "flags": 256, + "banner": null, + "accent_color": null, + "global_name": "ECHO 🐈", + "avatar_decoration_data": null, + "banner_color": null, + "clan": null +} + +``` + +### Properties + +|Name|Type|Required|Restrictions|Description| +|---|---|---|---|---| +|id|string|false|none|none| +|username|string|false|none|none| +|avatar|string|false|none|none| +|discriminator|string|false|none|none| +|public_flags|integer|false|none|none| +|flags|integer|false|none|none| +|banner|string¦null|false|none|none| +|accent_color|string¦null|false|none|none| +|global_name|string|false|none|none| +|avatar_decoration_data|string¦null|false|none|none| +|banner_color|string¦null|false|none|none| +|clan|string¦null|false|none|none| + +

Review

+ + + + + + +```json +{ + "reviewID": 1, + "discordID": "712653921692155965", + "reviewText": "meow", + "timestamp": "1708902649485" +} + +``` + +### Properties + +|Name|Type|Required|Restrictions|Description| +|---|---|---|---|---| +|reviewID|integer|false|none|none| +|discordID|string|false|none|none| +|reviewText|string|false|none|none| +|timestamp|string|false|none|none| + +

SongLinkResponse

+ + + + + + +```json +{ + "entityUniqueId": "SPOTIFY_SONG::6BJHsLiE47Sk0wQkuppqhr", + "userCountry": "US", + "pageUrl": "https://song.link/s/6BJHsLiE47Sk0wQkuppqhr", + "entitiesByUniqueId": { + "property1": { + "id": "6BJHsLiE47Sk0wQkuppqhr", + "type": "song", + "title": "From the Start", + "artistName": "Good Kid", + "thumbnailUrl": "https://i.scdn.co/image/ab67616d0000b273e67835d0a5d81fa4f268b513", + "thumbnailWidth": 640, + "thumbnailHeight": 640, + "apiProvider": "spotify", + "platforms": [ + "spotify" + ] + }, + "property2": { + "id": "6BJHsLiE47Sk0wQkuppqhr", + "type": "song", + "title": "From the Start", + "artistName": "Good Kid", + "thumbnailUrl": "https://i.scdn.co/image/ab67616d0000b273e67835d0a5d81fa4f268b513", + "thumbnailWidth": 640, + "thumbnailHeight": 640, + "apiProvider": "spotify", + "platforms": [ + "spotify" + ] + } + }, + "linksByPlatform": { + "property1": { + "country": "US", + "url": "https://open.spotify.com/track/6BJHsLiE47Sk0wQkuppqhr", + "entityUniqueId": "SPOTIFY_SONG::6BJHsLiE47Sk0wQkuppqhr", + "nativeAppUriMobile": "spotify:track:6BJHsLiE47Sk0wQkuppqhr", + "nativeAppUriDesktop": "spotify:track:6BJHsLiE47Sk0wQkuppqhr" + }, + "property2": { + "country": "US", + "url": "https://open.spotify.com/track/6BJHsLiE47Sk0wQkuppqhr", + "entityUniqueId": "SPOTIFY_SONG::6BJHsLiE47Sk0wQkuppqhr", + "nativeAppUriMobile": "spotify:track:6BJHsLiE47Sk0wQkuppqhr", + "nativeAppUriDesktop": "spotify:track:6BJHsLiE47Sk0wQkuppqhr" + } + } +} + +``` + +### Properties + +|Name|Type|Required|Restrictions|Description| +|---|---|---|---|---| +|entityUniqueId|string|false|none|none| +|userCountry|string|false|none|none| +|pageUrl|string|false|none|none| +|entitiesByUniqueId|object|false|none|none| +|» **additionalProperties**|[SongEntity](#schemasongentity)|false|none|none| +|linksByPlatform|object|false|none|none| +|» **additionalProperties**|[PlatformLink](#schemaplatformlink)|false|none|none| + +

SongEntity

+ + + + + + +```json +{ + "id": "6BJHsLiE47Sk0wQkuppqhr", + "type": "song", + "title": "From the Start", + "artistName": "Good Kid", + "thumbnailUrl": "https://i.scdn.co/image/ab67616d0000b273e67835d0a5d81fa4f268b513", + "thumbnailWidth": 640, + "thumbnailHeight": 640, + "apiProvider": "spotify", + "platforms": [ + "spotify" + ] +} + +``` + +### Properties + +|Name|Type|Required|Restrictions|Description| +|---|---|---|---|---| +|id|string|false|none|none| +|type|string|false|none|none| +|title|string|false|none|none| +|artistName|string|false|none|none| +|thumbnailUrl|string|false|none|none| +|thumbnailWidth|integer|false|none|none| +|thumbnailHeight|integer|false|none|none| +|apiProvider|string|false|none|none| +|platforms|[string]|false|none|none| + + + + + + + + +```json +{ + "country": "US", + "url": "https://open.spotify.com/track/6BJHsLiE47Sk0wQkuppqhr", + "entityUniqueId": "SPOTIFY_SONG::6BJHsLiE47Sk0wQkuppqhr", + "nativeAppUriMobile": "spotify:track:6BJHsLiE47Sk0wQkuppqhr", + "nativeAppUriDesktop": "spotify:track:6BJHsLiE47Sk0wQkuppqhr" +} + +``` + +### Properties + +|Name|Type|Required|Restrictions|Description| +|---|---|---|---|---| +|country|string|false|none|none| +|url|string|false|none|none| +|entityUniqueId|string|false|none|none| +|nativeAppUriMobile|string|false|none|none| +|nativeAppUriDesktop|string|false|none|none| +