i decided to make my G Suite “mdmtool” a bit more robust and release-worthy, instead of just proof of concept code.
(link: https://github.com/rickt/mdmtool) github.com/rickt/mdmtool.
enjoy!
i decided to make my G Suite “mdmtool” a bit more robust and release-worthy, instead of just proof of concept code.
(link: https://github.com/rickt/mdmtool) github.com/rickt/mdmtool.
enjoy!
Our desktop support & G Suite admin folks needed a simple, fast command-line tool to query basic info about our company’s mobile devices (which are all managed using G Suite’s built-in MDM).
So I wrote one.
Since this tool needs to be run via command-line, it can’t use any interactive or browser-based authentication, so we need to use a service account for authentication.
Pre-requisites (GCP & G Suite):
client_id
. Make a note of it!client_id
of your service account for the necessary API scopes. In the Admin Console for your G Suite domain (Admin Console –> Security –> Advanced Settings –> Authentication –> Manage API Client Access), add your client_id
in the “Client Name” box, and add https://www.googleapis.com/auth/admin.directory.device.mobile.readonlyin the “One or more API scopes” box
Pre-requisites (Go)
You’ll need to “go get” a few packages:
go get -u golang.org/x/oauth2/google
go get -u google.golang.org/api/admin/directory/v1
go get -u github.com/dustin/go-humanize
Pre-requisites (Environment Variables)
Because it’s never good to store runtime configuration within code, you’ll notice that the code references several environment variables. Setup them up to suit your preference but something like this will do:
export GSUITE_COMPANYID="A01234567" export SVC_ACCOUNT_CREDS_JSON="/home/rickt/dev/adminsdk/golang/creds.json export GSUITE_ADMINUSER="foo@bar.com"
And finally, the code
Gist URL: https://gist.github.com/rickt/199ca2be87522496e83de77bd5cd7db2
it’s been really hot in Los Angeles recently, and i realised i was switching back to my web browser from the Slack app to find out the current temperature downstairs an awful lot before leaving the office.
i realised that a /weather command would far more efficient. say hello to slack-weather-bot.
a simple golang backend that take a request for /weather?zip=NNNNN and then posts a quick one-liner of current conditions back to you on Slack. enjoy.
https://github.com/rickt/slack-weather-bot
package slackweatherbot | |
import ( | |
owm "github.com/briandowns/openweathermap" | |
"golang.org/x/net/context" | |
"google.golang.org/appengine" | |
"google.golang.org/appengine/log" | |
"google.golang.org/appengine/urlfetch" | |
"net/http" | |
"os" | |
"strconv" | |
"text/template" | |
) | |
const ( | |
weatherTemplate = `It's currently {{.Main.Temp}} °F ({{range .Weather}} {{.Description}} {{end}}) ` | |
) | |
// get the current weather conditions from openweather | |
func getCurrent(zip int, units, lang string, ctx context.Context) *owm.CurrentWeatherData { | |
// create a urlfetch http client because we're in appengine and can't use net/http default | |
cl := urlfetch.Client(ctx) | |
// establish connection to openweather API | |
cc, err := owm.NewCurrent(units, lang, owm.WithHttpClient(cl)) | |
if err != nil { | |
log.Errorf(ctx, "ERROR handler() during owm.NewCurrent: %s", err) | |
return nil | |
} | |
cc.CurrentByZip(zip, "US") | |
return cc | |
} | |
// redirect requests to / to /weather | |
func handler_redirect(w http.ResponseWriter, r *http.Request) { | |
http.Redirect(w, r, "/weather", 302) | |
} | |
// handle requests to /weather | |
// currently supports parameter of ?zip=NNNNNN or no zip parameter, in which case DEFAULT_ZIP is used | |
func handler_weather(w http.ResponseWriter, r *http.Request) { | |
// create an appengine context so we can log | |
ctx := appengine.NewContext(r) | |
// check the parameters | |
zip := r.URL.Query().Get("zip") | |
switch zip { | |
// if no zip parameter given, get the DEFAULT_ZIP from our env vars | |
case "": | |
zip = os.Getenv("DEFAULT_ZIP") | |
} | |
// convert the zip string to an int because that's what openweather wants | |
var zipint int | |
zipint, err := strconv.Atoi(zip) | |
if err != nil { | |
log.Errorf(ctx, "ERROR handler_weather() zip conversion problem: %s", err) | |
return | |
} | |
// get the current weather data | |
wd := getCurrent(zipint, os.Getenv("UNITS"), os.Getenv("LANG"), ctx) | |
// make the template | |
tmpl, err := template.New("weather").Parse(weatherTemplate) | |
if err != nil { | |
log.Errorf(ctx, "ERROR handler_weather() during template.New: %s", err) | |
return | |
} | |
// execute the template | |
err = tmpl.Execute(w, wd) | |
if err != nil { | |
log.Errorf(ctx, "ERROR handler_weather() during template.Execute: %s", err) | |
return | |
} | |
// we're done here | |
return | |
} | |
// because we're in appengine, there is no main() | |
func init() { | |
http.HandleFunc("/", handler_redirect) | |
http.HandleFunc("/weather", handler_weather) | |
} | |
// EOF |
are you curious if your [corporate] Slack users are logging into Slack using a Slack desktop or mobile app, or if they’re just using the Slack webpage? here’s some example code to call the slack team.accessLogs API to output which of your Slack users are not using a desktop or mobile Slack app.
https://github.com/rickt/golang-slack-tools/blob/master/slackaccessloglooker.go
stable release of Slack Translator Bot.
http://github.com/rickt/slack-translator-bot
what is Slack Translator Bot? the [as-is demo] code gets you get a couple of Slack /slash
commands that let you translate from English to Japanese, and vice-versa.
below screenshot shows example response to a Slack user wanting to translate “the rain in spain falls mainly on the plane” by typing:
within slack:
TL;DR/HOW-TO
stable release of Slack Team Directory Bot.
http://github.com/rickt/slack-team-directory-bot
what is Slack Team Directory Bot? you get a Slack /slash
command that lets you search your Slack Team Directory quick as a flash.
below screenshot shows example response to a Slack trying to find someone in your accounting department by typing:
within slack:
TL;DR/HOW-TO
http://gist-it.appspot.com/http://github.com/rickt/slack-team-directory-bot/blob/master/slackteamdirectorybot.go
rickt/slack-team-directory-bot
i’ve updated my example Golang code that authenticates with the Core Reporting API using service account OAuth2 (two-legged) authentication to use the newly updated golang.org/x/oauth2 library.
my previous post & full explanation of service account pre-reqs/setup:
http://code.rickt.org/post/142452087425/how-to-download-google-analytics-data-with-golang
full code:
have fun!
drop me a line or say hello on twitter if any questions.
stable release of my modified-for Google Appengine fork of https://github.com/bluele/slack. i have this working in production on several Appengine-hosted /slash commands & bots.
http://github.com/rickt/slack-appengine
the TL;DR on my modifications:
https://github.com/rickt/slack-appengine
a slack mini “sniffer”; connects to slack and (assuming a valid token), outputs the messages received over the slack websocket
https://github.com/rickt/golang-slack-tools/blob/master/slackminisniffer.go
stable release of Slack Timebot.
https://github.com/rickt/timebot-simple
what is Slack Timebot? at work, i very often have to know what time it is in the following regions:
so i wrote a mini go backend app that i threw into a free Google Appengine app and so now i can get the time instantly by using any of these new Slack /slash commands:
TL;DR/HOW-TO
http://gist-it.appspot.com/http://github.com/rickt/timebot-simple/blob/master/timebot-simple.go