shawnrice / packal-api-libraries

Libraries to Interface with the Packal API
MIT License
4 stars 0 forks source link

Python? #1

Open shawnrice opened 9 years ago

shawnrice commented 9 years ago

Would you want to contribute a Python version for easy uploading to the new Packal?

The spec isn't perfectly finished yet in that I don't see it changing, but it might change.

You can see the example PHP and Ruby versions.

deanishe commented 9 years ago

Sorry, I completely missed this. Will have a look.

shawnrice commented 9 years ago

I'll give some better specs for the API in a bit.

deanishe commented 9 years ago

Yeah, I'm going to need more than comment-free PHP and Ruby code to work with.

Not least, a test server of some sorts somewhere to poke with my Python stick.

shawnrice commented 9 years ago

Feel free to mess with the staging server that's already up. I'm going to rebuild the data before I make that one go live.

Basically, you just need to send a POST request to

With the respective payloads:

[
    "username": "myusername",
    "password": "mypassword",
    "workflow_revision": {
        "version": "1.0.0",
        "file": @BINARY_FILE
    }
]

And

[
    "username": "myusername",
    "password": "mypassword",
    "theme": {
        "uri":"ALFREDTHEMEURI", 
        "description":"This is a description.", 
        "tags":"tag1,tag2,tag3", 
        "name":"Mostly Transparent"
    }
]
deanishe commented 9 years ago

So a POST request with a JSON body?

How do I verify if it worked correctly (i.e. I haven't bollixed up the binary data)? Is there a webpage?

Any chance of changing username/password to some kind of API key? Even if it's just md5(username:password). It would avoid storing passwords in cleartext/having to use Keychain.

Also, wouldn't /api/alfred2/v1/... be a more appropriate URL?

shawnrice commented 9 years ago

Wait, not a json body. Sorry (it had been a json body, but I changed that). Just use a regular post request, but with those fields.

You'll get a status code back with a message. You can then look on https://mellifluously.org to find the workflow / theme there.

Right now, the Packal workflow is using the keychain. I might consider going back to create a sort of API token to check that out, but I'll need to revisit that on the server side to see how much work it's going to be.

The URL is appropriate. It's v1 of the API. So, if I need to change things with the API later that would break it, then the new API will live at v2, etc...

deanishe commented 9 years ago

Re the API, I meant, "shouldn't the name 'alfred2' come before the version?"

WRT Keychain: the library apparently doesn't deal with storing credentials, and I don't care (I'll just copy the code from Alfred-Workflow). But I can imagine many people using the library (if there are any others) won't go to the trouble of doing it properly…

So when you say "a regular POST request", you mean the body is application/x-www-form-urlencoded?

Also, the keys are presumably not nested?

shawnrice commented 9 years ago

The API is for the site, and so the version of the API is about how the site works, which has no direct relation to Alfred, so alfred2 is just a built-in parameter there.

So when you say "a regular POST request", you mean the body is application/x-www-form-urlencoded?

Yes. Sorry for the confusion.

Also, the keys are presumably not nested?

Nope. They are nested. It's a Rails thing. The libraries here are outdated (I think that the Ruby one still almost works). I'll post some commented code in a bit that should help out.

The current libraries don't deal with the keychain at all, but I don't actually think that they should. There's no reason to make them fully functioning because, well, if someone wants to use a prepackaged solution that does everything for them, then they should just use the Packal workflow. There's no need to re-invent that wheel. So, these libraries should provide only the functionality to upload to Packal as well as some pre-validation.

So, if you upload a theme, then it should just accept the theme parameters and verify that the Theme URI is valid, and then it should submit and report back.

If you upload a workflow, then, you should just have to feed it the workflow file (not directory but an already zipped .alfredworkflow file) that will then peek inside the workflow to make sure that there is a workflow.ini file that has, at minimum, a valid SemVer in the workflow section as well as an info.plist file that has a bundleid that is restricted to the charset [a-zA-Z0-9._-]. Ideally, it would then take the SemVer from the workflow.ini file and populate the version param for the post request.

So, example usage for the PHP library would work out to be something like:

require_once( 'Packal.php' ); // or whatever it is called.
$packal = new Packal( 'MYUSERNAME', 'MYPASSWORD' );
$result = $packal->submit( 'workflow', '/path/to/workflow.alfredworkflow' );

(Note: this isn't exactly how the PHP library works yet).

It would be the responsibility of anyone using the library to deal with getting / storing the username / password.

deanishe commented 9 years ago

The API is for the site, and so the version of the API is about how the site works, which has no direct relation to Alfred, so alfred2 is just a built-in parameter there.

Hmm. I'm guessing you know something I don't :)

It would be the responsibility of anyone using the library to deal with getting / storing the username / password.

Indeed. That's the reason I suggested some kind of API key. If the library doesn't take care of storing the credentials semi-securely, they typically won't be.

Anyway, I'll wait till I have some working Ruby/PHP code to look at, or better yet, documentation.

shawnrice commented 8 years ago

Here's a start to the API docs: https://mellifluously.org/api/docs/v1.

The URL names are dynamically set based on the Rails environment, so they should always match up to the correct server that they're hosted on (mellifluously.org = staging; packal.org = production).

I provided examples for each using cURL from the command line, but I also represented the POST fields as JSON to help people see the data structure.

shawnrice commented 8 years ago

Just pushed a new version of the ruby class that has some comments in it.

shawnrice commented 8 years ago

Updated PHP and Ruby examples in this repo. Now both are decently well commented.

I made it so each of them work basically the same way in that there is a Packal class that is accessed the same way in that you use it by passing the type, params, username, and password to it, and it then runs different internal methods based on the type. The error checking is minimal (better error checking should be done before the class).

The three types of possible submissions are workflow, theme, and report. The workflow and theme are obvious enough, but the report is one where you can "report a malicious workflow," which is something that Andrew wanted for this version of Packal. I have a feeling that almost no one will use the theme or report functionality in the classes, but I coded them in there for completeness. For the Python version, feel free just to code the workflow submission functionality.

deanishe commented 8 years ago

I just had a quick squint at the Ruby library, and there's loads of JSON everywhere.

You said above that the POST body is not JSON.

The only useful (i.e. non-Ruby/Rails) code is the cURL examples.

It's not super helpful describing the parameters in terms of a different format to the one they need to be submitted in, at least not when there isn't a direct correspondence.

I think I can figure it out based on the cURL examples, but I really don't understand why this whole nesting business is required. It's not like you can submit multiple workflows with one request.

As best I can tell, the required parameters can be flattened to (in JSON, but JSON that corresponds directly to x-www-url-encoded parameters):

workflow = {
  "file": "/path/to/file",
  "version": "1",
  "username": "me",
  "password": "mypassword"
}

theme = {
  "name": "Sweet Shit",
  "description": "This theme is sweet as shit",
  "uri": "alfred://...",
  "tags": ["tag1", "tag2"],
  "username": "me",
  "password": "mypassword"
}

// Similarly single-level equivalent for `report`  

Have I misunderstood something here?

shawnrice commented 8 years ago

The nesting business is required because that's how Rails expects things to be done, and since the server is written with Rails, submissions have to submit to the will of Rails. The nesting is required for the submission, but the class that I wrote for Ruby let's the user just specify it as something flat, and then the class properly nests everything.

There isn't loads of JSON throughout the Ruby. There is loads of Hashes (they look like JSON but aren't). The server response is JSON.

The content type does need to be x-www-url-encoded for a theme and a report, but it should be multipart/form-data for Workflows.

The nesting example for a workflow is:

{
  "workflow_revision": {
    "file": "file" (worked out via the multi-part),
    "version": "1.0.0"
  },
  "username": "me",
  "password": "my_password"
}

Hence, for the cURL examples, you see workflow_revision[file]=@/path/to/workflow/file/workflow.alfredworkflow for the file param, which is nested under the workflow_revision param.

The representation as JSON is really there to show the nesting.

The nesting is REALLY annoying, but, then again, parts of Rails are really annoying. The standard PHP functions/methods/classes for cURL didn't work as they were supposed to in order to nest a file, and so I have a method in there that actually writes the post data itself. Ruby worked out magically like it was supposed to do so.

shawnrice commented 8 years ago

Here's a simpler version of some code:

require 'rest-client'

def submit_workflow(file_path, version, username, password)
    params = { 
        :username => username, 
        :password => password,
        :workflow_revision => {
            :file => File.new(file_path, 'rb'),
            :version => version
        }
    }
    RestClient::Request.execute(:url => "https://mellifluously.org/api/v1/alfred2/workflow/submit", :payload => params, :method => :post)
end

# example usage:
# submit_workflow('/path/to/alfred/workflow.alfredworkflow', '1.0.0', 'me', 'my_password')

So, that would make it so that the workflow is submitted. The Ruby class is just fancier overall to take care of the other things.

Are you still into trying to get this to work?

deanishe commented 8 years ago

Posting different Ruby code using a different Ruby library isn't really helping, I'm afraid…

I'm trying to figure it out, but I'm using the built-in libraries, which need pairs of strings, not nested mapping objects.

Regarding the API key, I suppose the best thing would be to generate one at random for the user, which they can grab from their user page. (There should probably be a "generate new API key" button as well.)

deanishe commented 8 years ago

I've written a rudimentary library.

Currently, theme and workflow uploads work just dandy.

It took a little bit of dicking around, but fortunately, I was able to copy all the complicated bits straight from Alfred-Workflow's web.py module.

Bad stuff

There are a few things that have come up while writing it (I'm fairly certain most of them don't belong here, but I'm not sure exactly where they do belong. Should I create issues?).

Awesome stuff

I think it's shaping up to be a very promising, and much improved new version. In particular, it's marvellous being able to upload and/or update workflows from the command line.

I hate the GitHub > Packal > Forum > Packal dance.

The only thing that got slightly worse is updating Packal with the URL to the Alfred Forum thread. You can no longer just update the metadata, if I've understood you correctly. You'll have to increment the version of the workflow, too.

It's no biggie for me: I'll just create the forum thread with a link to the GitHub releases, then edit that after I've uploaded to Packal (which will now take but seconds! Yay!), but it is a slight inconvenience for people who only distribute their workflows via Packal.

shawnrice commented 8 years ago

Awesome stuff. I replied to most of this in an email. And I like the ascii art in the Python file.

Do you want to create a Python folder in this repo and push the packal.py file into there?

deanishe commented 8 years ago

I like the ascii art in the Python file

It's awesome in whatever that funny bar on the right of Sublime Text is called. I should probably upload the workflow I use to generate it…

Do you want to create a Python folder in this repo.

Will do.