Loving the new (beta) API!!
I'm having a great time experimenting with the new API that's in beta. (https://developers.mural.co/public/reference/intro) What's everybody else building with it? Here are a few use cases I've been working through:
- Cluster stickies using NLP, then group them in the mural, and produce a report
- Read stickies and then summarize/consolidate into a document using NLP
- Pull status updates from a Slack channel into a mural for review/reflection
- Automatically save data from team murals into a database every week
Here's a GitHub repo where I started collecting samples:
https://github.com/spackows/MURAL-API-Samples
I'm starting with small pieces and adding more over time.
Does anybody else have examples you've already been experimenting with that you'd share? I know it's still early days for the API, but I'm pretty excited about its potential. 😁
Comments
-
Hello Sarah!
We love that you are loving experimenting with MURAL API and building such cool stuff with it! Thank you for sharing your MURAL API creativity with us - keep them coming!! 😍
Cheers!
1 -
Hi @spackows
I am curious how you did authentication to get the auth token in your python scripting.
I wanted to create stickies in a new mural based on reading github issues through python scripting.
The api setup guide talks about registering an app, auth through browser and callback urls which I don't know how that works in when using a python script.
0 -
Hi, @CharekC
Yes, that detail is vague in those notebooks. Sorry! I'll add some comments to the notebooks explaining.
They way I do it is like this: I deployed a Node.js web app to go through that OAuth 2.0 web app/callback flow to get a token (and/or refresh it.) Then I copy the token into the notebook.
I happened to have set up the same OAuth flow for other projects before. So I was able to refactor my previous work to authenticate with the MURAL API too. Because of that, it wasn't a lot of work for me. But if you're starting from scratch and just want to kick the tires on the new MURAL API, I recognize that feels like a lot of work.
On this page, they describe the OAuth flow pretty nicely and there's a link to download a sample app:
*For anybody who hasn't set up OAuth 2.0 before, knowing how to set that up is a pretty handy thing. Maybe this is a good time to dig into it? If it helps anybody, I'll copy my Node.js authentication app into GitHub too. I'll post a comment here when that's done.
1 -
Hi, again. I finally got back to this...
Here is a little explanation (with an animated video!) and a simpler sample app that might be easier to start with if you haven't worked through OAuth 2.0 before: Mural and OAuth 2.0 easy as 1-2-3
I hope that's helpful to someone. 😀
5 -
Hi @spackows thank you for the hard work and creating some workflow examples! I'm attempting to run through the OAuth2 workflow purely in python using the Requests-OAuthlib lib: https://requests-oauthlib.readthedocs.io/en/latest/
I'm following the Web Application Flow: https://requests-oauthlib.readthedocs.io/en/latest/oauth2_workflow.html#web-application-flow
I have a dummy redirect URL in the Mural App I created. When I manually call the generated Auth URL I'd expect to go to the Mural Auth page first, but I'm just getting sent straight to my redirect URL. Any thoughts? I realize I may not be able to automate everything in Python but still trying to understand the flow components.
This is the returned redirect URL (I added the space to stop auto formatting):
https:// my.dummy.app /?error=invalid_request&state=agGwNyVnZMfMmOOpGbXbbdS3hcKfu1
So I assume I'm still not doing something correctly to generate the Auth URL since it's adding an error to the redirect URL.
Here's my basic Python code:
#=====================================
from requests_oauthlib import OAuth2Session
import requests
clientID = "--------" # Get from Mural app creation
clientSecret = "-----------" # Get from Mural app creation
baseURL = "https://app.mural.co"
authBaseURL = baseURL + "/api/public/v1/authorization/oauth2"
tokenURL = baseURL + "/api/public/v1/authorization/oauth2/token"
def login():
mural = OAuth2Session(clientID)
authURL, state = mural.authorization_url(authBaseURL)
print(authURL) # I then copy-paste this into the browser
login()
#=====================================
Any hints to get me started?
Thanks!
0 -
Hi.
A working Python MURAL OAuth sample would be nice to have... so let's make one. 😁
Flashback: I remember really struggling to get SAML redirects working with my Python (Flask) apps at first.
Anyway, I'll read through the docs you link to above and see what I can get working. Then I'll post an update here.
2 -
Hah just added the scope param and started working :)
scope= "murals:read murals:write"
def login():
mural = OAuth2Session(clientID, scope=scope)
authURL, state = mural.authorization_url(authBaseURL)
print(authURL) # Loading this URL in the browser showed the Mural permission page then redirected to my dummy URL with code, scopes and state params
0 -
Here's a min/janky example of getting the auth code and token in Python. I set my redirect URL in the Mural app config to http://localhost:8088:
#=====================================
from http.server import BaseHTTPRequestHandler, HTTPServer
from urllib.parse import urlparse, parse_qs
import webbrowser
import json
import os
from oauthlib.oauth2 import BackendApplicationClient
from requests_oauthlib import OAuth2Session
clientID = "------------" # Get from Mural app creation
clientSecret = "------------" # Get from Mural app creation
baseURL = "https://app.mural.co"
authBaseURL = baseURL + "/api/public/v1/authorization/oauth2"
tokenURL = baseURL + "/api/public/v1/authorization/oauth2/token"
scopes= "murals:read murals:write"
localHostName = "localhost"
localServerPort = 8088
redirectURL = "http://" + localHostName + ":" + str(localServerPort)
class LocalServer(BaseHTTPRequestHandler):
keepRunning = True
authResponse = ""
def do_GET(self):
queryDict = parse_qs(urlparse(self.path).query)
self.send_response(200)
self.send_header("Content-type", "text/html")
self.end_headers()
self.wfile.write(bytes("<html><head><title>Mural Auth Local Redirect</title></head><body>", "utf-8"))
if "code" in queryDict.keys():
self.wfile.write(bytes("<p>Mural Authentication Successfull! The script should continue to run automatically. You may close this window/tab</p>", "utf-8"))
LocalServer.authResponse = self.path
else:
self.wfile.write(bytes("<p>Mural Authentication Error!</p>", "utf-8"))
self.wfile.write(bytes("<p>" + (json.dumps(queryDict)) + "</p>", "utf-8"))
self.wfile.write(bytes("</body></html>", "utf-8"))
LocalServer.keepRunning = False
def login():
# Get Auth URL
os.environ['OAUTHLIB_INSECURE_TRANSPORT'] = '1' # Required since our local server is HTTP. Should implement local HTTPS
mural = OAuth2Session(clientID, redirect_uri=redirectURL, scope=scopes)
authURL, state = mural.authorization_url(authBaseURL)
# Open URL in default browser
webbrowser.open(authURL, new=1)
# Start local HTTP server to handle redirect
webServer = HTTPServer((localHostName, localServerPort), LocalServer)
try:
print("Starting server")
while(LocalServer.keepRunning):
webServer.handle_request()
except KeyboardInterrupt:
pass
print("Closing server")
webServer.server_close()
# We now have the Auth code, now need to get token
token = mural.fetch_token(tokenURL, client_secret=clientSecret, authorization_response=LocalServer.authResponse)
# We now have the token
print(token)
login()
#=====================================
1 -
I'm having a go with something - using the API to generate ~200 stickynotes that represent github issues. I'm doing the digital equivalent of getting a machine to auto-cut me a bunch of index cards which i'd throw on a table.
Basically, I'd like a better organisational view of my repo issues, so I'm trying to use mural as that org tool - there's So.Many.Assumptions I'm making (so the prototype is as brittle as all heck) but as a base thing, I'm doing a 1-way sync of all github issues to a mural. Once they're in mural I move/cluster and just get a better visual representation of relationships using arrows/icons/areas/text, etc.
If this works, then I'll consider a push-back, but the main idea is that I want a representation of issues that i can visually cluster and organise, so first wave of tooling is 1-way. The staging is:
- (done!) shove down 150 tickets by hand, cluster - is it vaulable? worth moving to code?
- (done! but hacky and inefficient) pull new issues into mural, each new issue is tagged and linked correctly
- (next) resync (apply/remove new tags, change bg colour or some attrib of closed issues)
- (maybe) retag in mural -> pushback to git
- (maaaybe) bring in JIRA tickets
2