Skip to content

Commit

Permalink
Merge pull request #10 from samoht/range
Browse files Browse the repository at this point in the history
Display activity range
  • Loading branch information
talex5 committed Dec 28, 2020
2 parents 4f09aff + d32980e commit e8005af
Show file tree
Hide file tree
Showing 6 changed files with 82 additions and 39 deletions.
23 changes: 6 additions & 17 deletions contributions.ml
Expand Up @@ -3,9 +3,9 @@ module Json = Yojson.Safe
let ( / ) a b = Json.Util.member b a

let query =
{| query($from: DateTime!) {
viewer {
contributionsCollection(from: $from) {
{| query($from: DateTime!, $to: DateTime!) {
viewer {
contributionsCollection(from: $from, to: $to) {
issueContributions(first: 100) {
nodes {
occurredAt
Expand Down Expand Up @@ -54,21 +54,11 @@ let query =
}
}|}

let to_8601 t =
let open Unix in
let t = gmtime t in
Printf.sprintf "%04d-%02d-%02dT%02d:%02d:%02dZ"
(t.tm_year + 1900)
(t.tm_mon + 1)
(t.tm_mday)
(t.tm_hour)
(t.tm_min)
(t.tm_sec)

let fetch ~from ~token =
let fetch ~period:(start, finish) ~token =
Lwt_main.run begin
let variables = [
"from", `String (to_8601 from);
"from", `String start;
"to", `String finish;
] in
Graphql.exec token ~variables query
end
Expand Down Expand Up @@ -133,7 +123,6 @@ let read_repos json =
{ kind = `New_repo; date; url; title = "Created new repository"; body = ""; repo }

let of_json ~from json =
let from = to_8601 from in
let contribs = json / "data" / "viewer" / "contributionsCollection" in
let items =
read_issues (contribs / "issueContributions") @
Expand Down
7 changes: 2 additions & 5 deletions contributions.mli
@@ -1,14 +1,11 @@
type t

val fetch : from:float -> token:Token.t -> Yojson.Safe.t
val fetch : period:(string * string) -> token:Token.t -> Yojson.Safe.t

val of_json : from:float -> Yojson.Safe.t -> t
val of_json : from:string -> Yojson.Safe.t -> t
(** We pass [from] again here so we can filter out anything that GitHub included by accident. *)

val is_empty : t -> bool

val to_8601 : float -> string
(** [to_8601 time] is [time] formatted as an ISO 8601 datestamp. *)

val pp : t Fmt.t
(** [pp] formats as markdown. *)
2 changes: 1 addition & 1 deletion dune
@@ -1,4 +1,4 @@
(executable
(name main)
(public_name get-activity)
(libraries cohttp cohttp-lwt cohttp-lwt-unix yojson))
(libraries cohttp cohttp-lwt cohttp-lwt-unix yojson cmdliner))
4 changes: 3 additions & 1 deletion dune-project
Expand Up @@ -5,11 +5,13 @@
(source (github talex5/get-activity))
(authors "talex5@gmail.com")
(maintainers "talex5@gmail.com")

(package
(name get-activity)
(synopsis "collect activity as markdown")
(depends
cmdliner
cohttp
cohttp-lwt
cohttp-lwt-unix
yojson
(ocaml (>= 4.08))))
3 changes: 3 additions & 0 deletions get-activity.opam
Expand Up @@ -7,6 +7,9 @@ homepage: "https://github.com/talex5/get-activity"
bug-reports: "https://github.com/talex5/get-activity/issues"
depends: [
"dune" {>= "2.3"}
"cmdliner"
"cohttp"
"cohttp-lwt"
"cohttp-lwt-unix"
"yojson"
"ocaml" {>= "4.08"}
Expand Down
82 changes: 67 additions & 15 deletions main.ml
Expand Up @@ -38,39 +38,91 @@ let set_mtime path time =
let get_token () =
Token.load (home / ".github" / "github-activity-token")

(* Run [fn timestamp], where [timestamp] is the last recorded timestamp (if any).
On success, update the timestamp to the start time. *)
let with_timestamp fn =
let to_8601 t =
let open Unix in
let t = gmtime t in
Printf.sprintf "%04d-%02d-%02dT%02d:%02d:%02dZ"
(t.tm_year + 1900)
(t.tm_mon + 1)
(t.tm_mday)
(t.tm_hour)
(t.tm_min)
(t.tm_sec)

(* Run [fn (start, finish)], where [(start, finish)] is the period specified by [period].
If [period] is [`Since_last_fetch] or [`Last_week] then update the last-fetch timestamp on success. *)
let with_period period fn =
let now = Unix.time () in
let last_fetch = mtime last_fetch_file in
fn last_fetch;
set_mtime last_fetch_file now
let last_week = now -. one_week in
let range =
match period with
| `Since_last_fetch ->
let last_fetch = Option.value ~default:last_week (mtime last_fetch_file) in
(to_8601 last_fetch, to_8601 now)
| `Last_week ->
(to_8601 last_week, to_8601 now)
| `Range r -> r
in
fn range;
match period with
| `Since_last_fetch | `Last_week -> set_mtime last_fetch_file now
| `Range _ -> ()

let show ~from json =
let contribs = Contributions.of_json ~from json in
if Contributions.is_empty contribs then
Fmt.epr "(no activity found since %s)@." (Contributions.to_8601 from)
Fmt.epr "(no activity found since %s)@." from
else
Fmt.pr "@[<v>%a@]@." Contributions.pp contribs

let mode = `Normal

let () =
open Cmdliner

let from =
let doc =
Arg.info ~docv:"TIMESTAMP" ~doc:"Starting date (ISO8601)." [ "from" ]
in
Arg.(value & opt (some string) None & doc)

let to_ =
let doc = Arg.info ~docv:"TIMESTAMP" ~doc:"Ending date (ISO8601)." [ "to" ] in
Arg.(value & opt (some string) None & doc)

let last_week =
let doc = Arg.info ~doc:"Show activity from last week" [ "last-week" ] in
Arg.(value & flag doc)

let period =
let f from to_ last_week =
if last_week then `Last_week
else
match (from, to_) with
| None, None -> `Since_last_fetch
| Some x, Some y -> `Range (x, y)
| _ -> Fmt.invalid_arg "--to and --from should be provided together"
in
Term.(pure f $ from $ to_ $ last_week)

let info = Term.info "get-activity"

let run period : unit =
match mode with
| `Normal ->
with_timestamp (fun last_fetch ->
let from = Option.value last_fetch ~default:(Unix.time () -. one_week) in
with_period period (fun period ->
(* Fmt.pr "period: %a@." Fmt.(pair string string) period; *)
let token = get_token () |> or_die in
show ~from @@ Contributions.fetch ~from ~token
show ~from:(fst period) @@ Contributions.fetch ~period ~token
)
| `Save ->
with_timestamp (fun last_fetch ->
let from = Option.value last_fetch ~default:(Unix.time () -. one_week) in
with_period period (fun period ->
let token = get_token () |> or_die in
Contributions.fetch ~from ~token
Contributions.fetch ~period ~token
|> Yojson.Safe.to_file "activity.json"
)
| `Load ->
(* When testing formatting changes, it is quicker to fetch the data once and then load it again for each test: *)
let from = mtime last_fetch_file |> Option.value ~default:0.0 in
let from = mtime last_fetch_file |> Option.value ~default:0.0 |> to_8601 in
show ~from @@ Yojson.Safe.from_file "activity.json"

let () = Term.exit @@ Term.eval (Term.(pure run $ period), info)

0 comments on commit e8005af

Please sign in to comment.