Skip to content

Commit

Permalink
Initial v1 commit
Browse files Browse the repository at this point in the history
  • Loading branch information
KevinPayravi committed Aug 17, 2020
0 parents commit 1f3ed95
Show file tree
Hide file tree
Showing 20 changed files with 6,505 additions and 0 deletions.
6 changes: 6 additions & 0 deletions AUTHORS
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
# This is the list of Nookipedia API's significant contributors.
#
# This does not necessarily list everyone who has contributed code.
# To see the full list of contributors, see the revision history in
# source control.
Kevin Payravi <[email protected]>
97 changes: 97 additions & 0 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
# Contributing
Anyone is welcome and encourages to contribute to the Nookipedia API!

## Opening a PR
When contributing, please create a fork of this repository and work off of the `dev` branch. Changes will be merged into `dev` and tested before being merged into `master`.

When making changes to endpoints, please be sure to also update the OpenAPI documenation accordingly (see Documentation section below).

In your pull request (PR), please be sure to provide a detailed description describing the changes you have made.

## File overview
* `app.py`: The Python Flask application that serves the API and routing
* `config.ini`: Configs for `app.py`. Must be filled out before running
* `dashboard-config.cfg`: Configurations for [Flask-MonitoringDashboard](https://github.com/flask-dashboard/Flask-MonitoringDashboard)
* `static/index.html`: The project's homepage (https://api.nookipedia.com/)
* `static/doc.html`: Renders [redoc](https://github.com/Redocly/redoc) OpenAPI documentation page (https://api.nookipedia.com/doc)
* `static/doc.json` & `static/doc.yaml`: YAML and JSON files of the OpenAPI documentation
* `static/css/style.css`: CSS for `static/index.html`
* `static/css/brands.min.css` & `static/css/fontawesome.min.css`: [Font Awesome](https://fontawesome.com/) CSS for rendering icons on homepage
* `static/js/redoc.standalone.js`: JavaScript for [redoc](https://github.com/Redocly/redoc)
* `static/webfonts/*`: [Font Awesome](https://fontawesome.com/) fonts for rendering icons on homepage

## Style guide
Python files:
* Indents are four spaces

HTML + CSS files:
* Indents are two spaces

## Endpoint examples

Below is an example of the endpoint to retrieve details about a specified New Horizons bug, with an explanation following.

```
@app.route('/nh/bugs/<string:bug>', methods=['GET'])
def get_nh_bug(bug):
authorize(DB_KEYS, request)
bug = bug.replace('_', ' ')
tables = 'nh_bug'
fields = 'url,name,number,image_url,catchphrase,catchphrase2,n_availability,n_m1,n_m2,n_m3,n_m4,n_m5,n_m6,n_m7,n_m8,n_m9,n_m10,n_m11,n_m12,s_availability,s_m1,s_m2,s_m3,s_m4,s_m5,s_m6,s_m7,s_m8,s_m9,s_m10,s_m11,s_m12,time,location,rarity,total_catch,sell_nook,sell_flick,tank_width,tank_length'
where = 'name="' + bug + '"'
params = { 'action': 'cargoquery', 'format': 'json', 'tables': tables, 'fields': fields, 'where': where }
return jsonify(months_to_array(call_cargo(params, request.args)))
```

* First, we declare the route (`/<game>/<subject>/<parameter>`) and method type (GET request), as well as the function name.
* `authorize(DB_KEYS, request)` performs the check to ensure the user is authenticated via their API key.
* For the bug name parameter, we need to replace any underscores with a space (`bug = bug.replace('_', ' ')`); the MediaWiki API does not treat them interchangibly.
* We specify the Cargo table(s) we will be querying (see [Special:CargoTables](https://nookipedia.com/wiki/Special:CargoTables) for full list of tables, and [Project Database](https://nookipedia.com/wiki/Nookipedia:Project_Database) for status of tables and if they are ready to be queried in production).
* Declare the fields (columns) that we want to query. Most, if not all, columns will be queried for most endpoints. Sometimes some columns contain data meant to be used exlcusively on-wiki (e.g. formatted wikitext), which we can disclude.
* Since we want a specific resource, we also add a `where` with the bug's name.
* Set up the `params` to pass into the Cargo call.
* Make the Cargo call. `call_cargo` is the function that makes the call to Nookipedia's Cargo API, formats the response as-needed, and returns it. In this case, we also put the response through `months_to_array`, which merges the individual month fields into more easily-parsed arrays.


Below is an example of the endpoint to retrieve all New Horizons bugs, with an explanation following.

```
@app.route('/nh/bugs', methods=['GET'])
def get_nh_bug_all():
authorize(DB_KEYS, request)
limit = '100'
tables = 'nh_bug'
if request.args.get('excludedetails') and (request.args.get('excludedetails') == 'true'):
fields = 'name,n_m1,n_m2,n_m3,n_m4,n_m5,n_m6,n_m7,n_m8,n_m9,n_m10,n_m11,n_m12,s_m1,s_m2,s_m3,s_m4,s_m5,s_m6,s_m7,s_m8,s_m9,s_m10,s_m11,s_m12'
else:
fields = 'url,name,number,image_url,catchphrase,catchphrase2,n_availability,n_m1,n_m2,n_m3,n_m4,n_m5,n_m6,n_m7,n_m8,n_m9,n_m10,n_m11,n_m12,s_availability,s_m1,s_m2,s_m3,s_m4,s_m5,s_m6,s_m7,s_m8,s_m9,s_m10,s_m11,s_m12,time,location,rarity,total_catch,sell_nook,sell_flick,tank_width,tank_length'
return get_critter_list(limit, tables, fields)
```

* First, we declare the route (`/<game>/<subject>`) and method type (GET request), as well as the function name.
* `authorize(DB_KEYS, request)` performs the check to ensure the user is authenticated via their API key.
* We set a limit of 100. The default limit for a Cargo query is 50, and the maximum is 500.
* We specify the Cargo table(s) we will be querying (see [Special:CargoTables](https://nookipedia.com/wiki/Special:CargoTables) for full list of tables, and [Project Database](https://nookipedia.com/wiki/Nookipedia:Project_Database) for status of tables and if they are ready to be queried in production).
* This endpoint lets users specify if the want all details about all bugs (default), or just a list of bug names (via `excludedetails` query parameter). If details are excluded, we only query for name and month availability (in case the user wants a particular month). Otherwise, we request all columns.
* `get_critter_list` is a function made to handle New Horizons all-critter calls to Cargo. This takes care of checking for any `month` filters and formatting the return.

## Documentation
When changing or creating endpoints, please be sure to also update the OpenAPI documentation, located inside the `static` directory.

Copy the YAML into [Swagger editor](https://editor.swagger.io/) and modify accordingly. When finished, save the YAML as well as the JSON copy (File -> Convert and save as JSON).

## Versioning
Version numbers are in #.#.# (Major.Minor.Patch) format.
* A patch update is a small change that won't impact most users. Bug fixes, adding an insignificant queried field, etc.
* A minor update is an impactful change, such as the addition of a new endpoint, new filters, etc.
* A major update would include many large-scale changes and breaking changes. We don't anticipate incrementing from 1.#.# anytime soon.

## Breaking changes
We try our best to avoid breaking changes, but it is bound to happen at some point. Users are asked to send in a `Accept-Version` header with the version they are using; when implementing a breaking change, add a check for version to direct logic accordingly and prevent breaking the API for existing users.

## Licensing
The Nookipedia API codebase is licensed under the MIT license. See [license file](https://github.com/Nookipedia/nookipedia-api/blob/master/LICENSE) for full text.
21 changes: 21 additions & 0 deletions LICENSE
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
MIT License

Copyright (c) 2020 Kevin Payravi

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
78 changes: 78 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
# nookipedia-api
The Nookipedia API is a free RESTful service provides endpoints for retrieving Animal Crossing data pulled from the [Nookipedia wiki](https://nookipedia.com/wiki/Main_Page), the largest community-driven encyclopedia about the series. Built using Python and [Flask](https://flask.palletsprojects.com/en/1.1.x/), the key benefit of using this API is access to clean structured data spanning the entire Animal Crossing series, pulled from information that is constantly updated and expanding as editors work on the wiki.

Visit https://api.nookipedia.com/ for more information.

## Support
Our primary method of supporting users and developers is through the [Nookipedia Discord](https://nookipedia.com/wiki/Nookipedia:Discord); API users and contributors are granted access to the private #wiki-api channel where they can participate in a community of practice and receive near round-the-clock support.

You may also [open an issue](https://github.com/Nookipedia/nookipedia-api/issues/new) here on GitHub if you need help, would like to request a feature, or have a bug to report.

## Contributing
Anyone is welcome and encouraged to contribute to this API!

See the [contributing guide](CONTRIBUTING.md) for full details and guidance.

## Technical Overview
Nookipedia, which runs on the MediaWiki wiki software (same as Wikipedia), utilizes the [Cargo](https://www.mediawiki.org/wiki/Extension:Cargo) extension. Cargo lets editors store data from templates in structured databases. For example, if you visit any villager's article on Nookipedia (e.g. [Rosie](https://nookipedia.com/wiki/Rosie)), there is an infobox at the top-right of the page; all that information as defined in the infobox is also stored in a database on the backend so that it can be queried elsewhere on the wiki, or externally by third parties. See Nookipedia's [Project Database](https://nookipedia.com/wiki/Nookipedia:Project_Database) for more information.

This API is essentially a wrapper for the MediaWiki Cargo API that comes as part of the extension. See the [MediaWiki cargoquery endpoint](https://nookipedia.com/w/api.php?action=help&modules=cargoquery) for how Cargo tables can be queried directly.

While the Cargo API is freely available for querying, we have our custom-built API for the following reasons:
* Far simpler endpoints.
* Nookipedia API way: https://api.nookipedia.com/nh/fish/sea_bass
* Cargo way: https://nookipedia.com/w/api.php?action=cargoquery&format=json&limit=200&tables=nh_fish&fields=name%2Cnumber%2Cimage%2Ccatchphrase%2Ccatchphrase2%2Cn_availability%2Cn_m1%2Cn_m2%2Cn_m3%2Cn_m4%2Cn_m5%2Cn_m6%2Cn_m7%2Cn_m8%2Cn_m9%2Cn_m10%2Cn_m11%2Cn_m12%2Cs_availability%2Cs_m1%2Cs_m2%2Cs_m3%2Cs_m4%2Cs_m5%2Cs_m6%2Cs_m7%2Cs_m8%2Cs_m9%2Cs_m10%2Cs_m11%2Cs_m12%2Ctime%2Clocation%2Cshadow_size%2Crarity%2Ctotal_catch%2Csell_nook%2Csell_cj%2Ctank_width%2Ctank_length&where=name=%27sea%20bass%27
* Hosted on its own dedicated server, so it is highly scalable and not subject to the wiki's performance limitations or downtime.
* Changes Nookipedia makes to its Cargo tables will be reflected in this API, so users can trust that nothing will break as Nookipedia's tables evolve.
* Returns from the Cargo API are cleaned up, simplified, and restructured as needed.
* Caching policies that we can adjust as needed.
* Additional features built in, such as the ability to generate thumbnails of varying size.
* Actively monitored and under development (your feature requests can come to life).

## Deployment
This application requires Python 3.

This application has the following dependencies from `apt get`:
* `software-properties-common`
* `sqlite3`

This application has the following dependencies that will need to be installed via pip:
* `Flask`
* `Flask_Caching`
* `flask_monitoringdashboard`
* `waitress`
* `wheel`

Before running this application:
* Run `export FLASK_APP=app.py`
* Create the database for storing admin/client secrets (replace `<>` values with your desired values):
* `sudo sqlite3 <desired db name>.db`
* `CREATE TABLE <keys table name> ( key varchar(32), email TEXT, project TEXT );`
* `CREATE TABLE <admin keys table name> ( key varchar(32) );`
* The API requires a UUID key to make calls; you can insert one for yourself using `INSERT INTO <keys table name> VALUES ( "<uuid>", "test", "test" );`.
* In `config.ini`:
* Fill in the `SECRET_KEY` with a long random string of bytes (used for securely signing the session cookie; [learn more](https://flask.palletsprojects.com/en/1.1.x/config/#SECRET_KEY))
* Fill in the names for the `DATABASE`, `DB_KEYS`, and `DB_ADMIN_KEYS` as you declared above.
* In `dashboard-config.cfg`, change the dashboard's password to something other than the default `admin`.

### Local / Dev
`flask run`. Easy.

Note that Flask's built-in server is _not_ suitable for production.

### Production
As noted above, Flask's built-in server is _not_ suitable for production.

There are a variety of options out there for setting up a proper production server (cloud services, Gunicorn, uWSGI, etc.). Visit [Flask's deployment page](https://flask.palletsprojects.com/en/1.1.x/deploying/) for a list of options.

Nookipedia's API is deployed via uWSGI and nginx. If you'd like to set up something similar and need help, feel free to get in touch.

## Licensing
The Nookipedia API codebase is licensed under the MIT license. See [license file](LICENSE) for full text.

Dependencies are copyright their respective authors and used under their respective licenses.
* [ReDoc](https://github.com/Redocly/redoc), [MIT License](https://github.com/Redocly/redoc/blob/master/LICENSE), Copyright (c) 2015-present, Rebilly, Inc.
* [Font Awesome Free 5.14.0](https://fontawesome.com), [Font Awesome Free License](https://fontawesome.com/license/free)
* Icons — CC BY 4.0 License
* Fonts — SIL OFL 1.1 License
* Code — MIT License
Loading

0 comments on commit 1f3ed95

Please sign in to comment.