From 2ad4571b5be69672ba77ce3cd2b28154eb2eb24a Mon Sep 17 00:00:00 2001 From: Peter Saxton Date: Mon, 12 Aug 2024 10:21:53 +0200 Subject: [PATCH] add user info --- src/midas/sdk/google.gleam | 36 +++++++++++- src/midas/sdk/google/gmail.gleam | 95 ++++++++++++++++++++------------ 2 files changed, 94 insertions(+), 37 deletions(-) diff --git a/src/midas/sdk/google.gleam b/src/midas/sdk/google.gleam index 1f38e0b..171019e 100644 --- a/src/midas/sdk/google.gleam +++ b/src/midas/sdk/google.gleam @@ -1,6 +1,5 @@ import gleam/bit_array import gleam/dynamic -import gleam/http import gleam/http/request import gleam/http/response import gleam/int @@ -67,6 +66,7 @@ pub fn auth_redirect(redirect) { use access_token <- try(key_find(parts, "access_token")) use token_type <- try(key_find(parts, "token_type")) use returned_state <- try(key_find(parts, "state")) + // other parts expires_in and scope Ok(#(access_token, token_type, returned_state)) } @@ -74,3 +74,37 @@ fn key_find(items, key) { list.key_find(items, key) |> result.replace_error("Did not find key: " <> key) } + +const openid_host = "openidconnect.googleapis.com" + +const userinfo_path = "/v1/userinfo" + +pub fn userinfo(token) { + let request = userinfo_request(token) + use response <- t.do(t.fetch(request)) + use response <- t.try(userinfo_response(response)) + t.Done(response) +} + +pub fn userinfo_request(token) { + request.new() + |> request.set_host(openid_host) + |> request.prepend_header("Authorization", string.append("Bearer ", token)) + |> request.set_path(userinfo_path) + |> request.set_body(<<>>) +} + +pub fn userinfo_response(response: response.Response(BitArray)) { + use json <- try( + bit_array.to_string(response.body) + |> result.replace_error(snag.new("not utf8 encoded")), + ) + use message <- try( + json.decode_bits(response.body, dynamic.field("email", dynamic.string)) + |> result.map_error(fn(reason) { + snag.new(string.inspect(reason)) + |> snag.layer("failed to decode message") + }), + ) + Ok(message) +} diff --git a/src/midas/sdk/google/gmail.gleam b/src/midas/sdk/google/gmail.gleam index ce7555b..ed16786 100644 --- a/src/midas/sdk/google/gmail.gleam +++ b/src/midas/sdk/google/gmail.gleam @@ -3,13 +3,9 @@ import gleam/dynamic import gleam/http import gleam/http/request import gleam/http/response -import gleam/int import gleam/json -import gleam/list -import gleam/option.{None, Some} import gleam/result.{try} import gleam/string -import gleam/uri.{Uri} import midas/task as t import snag @@ -21,11 +17,11 @@ fn base_request(token) { |> request.prepend_header("Authorization", string.append("Bearer ", token)) } -// fn get(token, path) { -// base_request(token) -// |> request.set_path(path) -// |> request.set_body(<<>>) -// } +fn get(token, path) { + base_request(token) + |> request.set_path(path) + |> request.set_body(<<>>) +} fn post(token, path, mime, content) { base_request(token) @@ -43,24 +39,20 @@ pub fn send(token, from, to, message) { } pub fn send_request(token, from, to, message) { + let path = "/gmail/v1/users/" <> from <> "/messages/send" let mime = "application/json; charset=UTF-8" let email = "From: " <> from - <> " To: " + <> "\r\nTo: " <> to - <> " Content-Type: text/html; charset=utf-8 " + <> "\r\nContent-Type: text/html; charset=utf-8 " + <> "\r\n" <> message let raw = bit_array.base64_encode(<>, True) let body = json.object([#("raw", json.string(raw))]) |> json.to_string - request.new() - // non-standard host - |> request.set_host("content-gmail.googleapis.com") + post(token, path, mime, <>) |> request.set_query([#("alt", "json")]) - |> request.prepend_header("Authorization", string.append("Bearer ", token)) - |> request.set_path("/gmail/v1/users/" <> from <> "/messages/send") - |> request.prepend_header("content-type", mime) - |> request.set_body(<>) } pub fn send_response(response: response.Response(BitArray)) { @@ -68,22 +60,53 @@ pub fn send_response(response: response.Response(BitArray)) { bit_array.to_string(response.body) |> result.replace_error(snag.new("not utf8 encoded")), ) - // let decoder = dynamic.list(site_decoder) - // use videos <- try( - // json.decode_bits(response.body, decoder) - // |> result.map_error(fn(reason) { - // snag.new(string.inspect(reason)) - // |> snag.layer("failed to decode sites") - // }), - // ) - Ok(json) + use message <- try( + json.decode_bits(response.body, message_decoder) + |> result.map_error(fn(reason) { + snag.new(string.inspect(reason)) + |> snag.layer("failed to decode message") + }), + ) + Ok(message) +} + +pub type Message { + Message(id: String, thread_id: String) +} + +fn message_decoder(raw) { + dynamic.decode2( + Message, + dynamic.field("id", dynamic.string), + dynamic.field("threadId", dynamic.string), + // dynamic.field("labelIds", dynamic.list(dynamic.string)), + )(raw) +} + +pub fn list_messages(token, user_id) { + let request = list_messages_request(token, user_id) + use response <- t.do(t.fetch(request)) + use response <- t.try(list_messages_response(response)) + t.Done(response) +} + +pub fn list_messages_request(token, user_id) { + let path = "/gmail/v1/users/" <> user_id <> "/messages" + get(token, path) +} + +pub fn list_messages_response(response: response.Response(BitArray)) { + use json <- try( + bit_array.to_string(response.body) + |> result.replace_error(snag.new("not utf8 encoded")), + ) + let decoder = dynamic.field("messages", dynamic.list(message_decoder)) + use message <- try( + json.decode_bits(response.body, decoder) + |> result.map_error(fn(reason) { + snag.new(string.inspect(reason)) + |> snag.layer("failed to decode messages") + }), + ) + Ok(message) } -// fn site_decoder(raw) { -// dynamic.decode4( -// Site, -// dynamic.field("id", dynamic.string), -// dynamic.field("state", dynamic.string), -// dynamic.field("name", dynamic.string), -// dynamic.field("url", dynamic.string), -// )(raw) -// }