Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

bot api for managing lists and list status #162

Open
bnfinet opened this issue Apr 12, 2019 · 1 comment
Open

bot api for managing lists and list status #162

bnfinet opened this issue Apr 12, 2019 · 1 comment
Labels

Comments

@bnfinet
Copy link

bnfinet commented Apr 12, 2019

Is there an API? Is there some place in the javascript which would show how to query the redis?

I use a go chat bot instance to manage daily life. I'd like to query current state or Add or Remove list items with...

> me: !listhero buy tomatoes
> bot: okay, tomatoes added to Produce 

which would be

  • query the current lists to find which one includes Tomatoes
  • if found move from LRU to list
  • if not found, add to list
@flash1293 flash1293 added the tech label Apr 12, 2019
@flash1293
Copy link
Owner

This is an interesting idea. It's not going to be straight forward because Listhero doesn't use a standard set of REST endpoints as one might expect. I'm trying to explain it from the perspective of your use case, but it probably makes sense to add a little bit of documentation around that. I might try to come up with a simple client lib for that if I find the time :).

The Listhero server communicates with the client by passing "actions" which are little JSON documents which don't describe the state itself but what happened on a semantic level (e.g. add an item, move an item, add a list, etc.). Adding an item to the list and moving it there from LRU is actually just one action which means you don't have to take care of that yourself - the app will do it if you send it the right action.

To append new actions to the action log on the server, the client issues a POST request to /api with a JSON payload which contains an action array and the current length of the action log on the client: { actions: [...], startFrom: 123 }. The server appends the actions to the log and responds with all the actions which the client currently doesn't have in it's local log (for example because another client added some actions in the mean time). If you just care about adding your action you could just pass a very high number there and the server will think the client is up to date and reply without sending too much data ({ actions: [...], startFrom: 99999999 }). The action for adding an item looks like this (they are all defined in client/src/redux/actions.js):

{
    type: "ADD_ITEM",
    list: "ID OF THE LIST",
    uid: "NEW RANDOM ID OF THE ITEM",
    name: "ITEM ITSELF"
  }

However there are two more things to consider:

Authentication: The server looks for an authorization header in the HTTP requests which has to contain a JWT token (you can see the one used by your browser by looking into the development tools and search for requests to api). You can either copy the token which your browser currently uses or issue a new one by sending a POST request to /token which contains a request body like this:

{ "username": "USERNAME", password: "PASSWORD" }

Username and password are a bit misleading here since you don't choose them yourself - Listhero is just creating random ones for you behind the scenes. You can get yours from the app by opening the console in the developer tools and executing JSON.parse(JSON.parse(localStorage.getItem('persist:ekofe-5')).user)

Encryption (the hardest part): The command from above also gives you the encryption key of your data - Listhero encrypts everything on your device before sending it to the server, so the server can't look into your action log. The encryption key for that is only stored on the clients and shared via the sync link. If you want to place an action on the server, you also have to encrypt it before sending it. The encrypting scheme lives in client/src/redux/syncMiddleware.js and looks like this:

  • Stringify the JSON payload of the action
  • Get 128 bits of random data (the seed for the encryption algorithm)
  • Initialize AES 128 in CTR mode with the seed
  • escape special unicode characters with the global escape function (only necessary if there are things like emoji in the payload)
  • Encrypt the string with AES
  • Encode the encrypted string as a hex string
  • Encode the used seed as a hex string
  • Concatenate the seed and the encrypted string like this: 0x<SEED IN HEX>;<ENCRYPTED PAYLOAD IN HEX> (e.g. 0x6177a06d0617c190106155ff111a99e2;db168....)

The final request would for example like this:

POST /api
authorization: Bearer authorization: Bearer ezHhbG....
{ "actions": ["0x6177a06d0617c190106155ff111a99e2;db168...."], "startFrom": 99999999 }

I have a feeling that this is a bit too much custom code in the Go bot to be worthwhile for the use case, however if you want to tackle it just for fun I'm more than willing to help where I can.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants