Open shawnrice opened 9 years ago
Sorry, I completely missed this. Will have a look.
I'll give some better specs for the API in a bit.
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.
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"
}
]
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?
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...
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?
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.
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.
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.
Just pushed a new version of the ruby class that has some comments in it.
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.
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?
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.
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?
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.)
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.
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?).
workflow.ini
documented? And the screenshots etc.? That info should be easy to find on the Packal website..alfredworkflow
file is invalid. The one I was using to test the script contains no workflow.ini
file. The API accepted (queued) it, and then silence. The user should ideally receive an error report by email with sufficient details to rectify the error. When I uploaded a completely bullshit file, like an MP3 renamed to Song.alfredworkflow
, the API threw a 500 error. Some error is better than no error, but it'd be cool if the API caught whatever exception is being thrown when I do that and returned 400: invalid workflow file
or similar.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.
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?
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.
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.