Browse Source

render_stream

master
boB Rudis 5 years ago
parent
commit
174f1d40c0
No known key found for this signature in database GPG Key ID: 1D7529BE14E2BBA9
  1. 2
      .Rbuildignore
  2. 5
      DESCRIPTION
  3. 1
      NAMESPACE
  4. 9
      R/feedly-stream.R
  5. 127
      R/render-stream.R
  6. 37
      README.Rmd
  7. 50
      README.md
  8. 37
      man/render_stream.Rd
  9. BIN
      report-thumb.png
  10. BIN
      sample-report.jpg

2
.Rbuildignore

@ -12,3 +12,5 @@
^notes$
^\.gitlab-ci\.yml$
^\.httr-oauth$
^sample-report\.jpg$
^report-thumb\.png$

5
DESCRIPTION

@ -20,7 +20,10 @@ Encoding: UTF-8
License: AGPL
Suggests:
testthat,
covr
covr,
rmarkdown,
htmltools,
glue
Depends:
R (>= 3.2.0)
Imports:

1
NAMESPACE

@ -10,6 +10,7 @@ export(feedly_search_contents)
export(feedly_search_title)
export(feedly_stream)
export(feedly_tags)
export(render_stream)
import(httr)
importFrom(jsonlite,fromJSON)
importFrom(magrittr,"%>%")

9
R/feedly-stream.R

@ -142,15 +142,22 @@ feedly_stream <- function(stream_id,
if ("actionTimestamp" %in% cn) res$items$actionTimestamp <- as.POSIXct(res$items$actionTimestamp/1000, origin = "1970-01-01")
# column bind all the data frame columns so we can make res$items a tbl
# also prepend the old column name in front so we can ensure they won't
# be overwritten or have conflicts (e.g. 'summary' has a 'content' component)
isdf <- sapply(res$items, class)
df_cols <- names(isdf[isdf == "data.frame"])
for (cname in df_cols) {
cn <- cn[cn != cname]
res$items <- cbind.data.frame(res$items[,cn], res$items[,cname])
x <- res$items[[cname]]
colnames(x) <- sprintf("%s_%s", cname, colnames(x))
res$items <- cbind.data.frame(res$items[,cn], x)
cn <- c(cn, colnames(x))
}
colnames(res$items) <- tolower(colnames(res$items))
class(res$items) <- c("tbl_df", "tbl", "data.frame")
}

127
R/render-stream.R

@ -0,0 +1,127 @@
tmpl <- "
### {title}
**URL**: [{prt_url}]({alt_url}) \n**Published**: {published} \n
{vis}
{summary_content}
<a class='lnk' href='{alt_url}'></a>
<center><span style='font-size:32pt; padding-bottom:12pt;'>&Cconint;</span><br/></center>
"
#' Render a Feedly Stream Data Frame to RMarkdown
#'
#' This function takes a minimalist approach to formatting an R Markdown
#' document from the contents of a Feedly stream. It uses the feed item
#' title, URL (first `alternate` one), published data and summary content to make
#' each entry.
#'
#' @md
#' @param feedly_stream output from [feedly_stream()]. Ideally, you'll filter
#' this so it has a minimal number of elements (unless you like scrolling
#' through large HTML documents)
#' @param title A title for your "report"
#' @param include_visual if `TRUE` then any `visual_url` image content will
#' be rendered with the summary text. Default is `FALSE`.
#' @param browse if `TRUE` open the HTML document for viewing. Default is `FALSE`
#' @param quiet passed on to [rmarkdown::render()]. Default is `TRUE`.
#' @note This function requires that `htmltools`, `rmarkdown` and `glue` are installed
#' on your system.
#' @return a list with the contents of the R Markdown document and the
#' rendered HTML file (so you can save/tweak before publishing).
#' @export
render_stream <- function(feedly_stream,
title = "Feedly Stream Summary",
include_visual = FALSE,
browse = FALSE,
quiet = TRUE) {
if (!requireNamespace("htmltools", quietly = TRUE)) {
stop("htmltools must be installed to use this function", call. = FALSE)
}
if (!requireNamespace("rmarkdown", quietly = TRUE)) {
stop("rmarkdown must be installed to use this function", call. = FALSE)
}
if (!requireNamespace("glue", quietly = TRUE)) {
stop("glue must be installed to use this function", call. = FALSE)
}
tf <- tempfile(fileext = ".Rmd")
feedly_stream$vis <- ""
feedly_stream$alt_url <- sapply(feedly_stream$alternate, function(.x) .x[[1]])
ifelse(
test = nchar(feedly_stream$alt_url) > 75,
yes = sprintf("%s&hellip;", substr(feedly_stream$alt_url, 1, 75)),
no = feedly_stream$alt_url
) -> feedly_stream$prt_url
if (include_visual) {
ifelse(
test = (grepl("image", feedly_stream$visual_contenttype) &
((!is.na(feedly_stream$visual_url)) |
(feedly_stream$visual_url != ""))),
yes = sprintf("![](%s)", feedly_stream$visual_url),
no = ""
) -> feedly_stream$vis
}
bs <- "\\"
cat(glue::glue(
"---
title: {title}
output:
html_document:
self_contained: false
---
```{{css, echo=FALSE}}
html, body, div {{
font-family: 'Lato', 'Helvetica', 'sans-serif'
}}
a:link, a:visited, a:hover, a:active {{
text-decoration: none;
color: #6a3d9a;
}}
a.lnk::before {{
content: '{bs}01F517';
}}
```
"), file = tf)
cat(
glue::glue_data(feedly_stream, tmpl),
file = tf, append = TRUE, sep = ""
)
of <- rmarkdown::render(tf, quiet=quiet)
on.exit(unlink(tf), add=TRUE)
on.exit(unlink(of), add=TRUE)
list(
rmd = rawToChar(readBin(tf, "raw", n = file.size(tf))),
html = rawToChar(readBin(of, "raw", n = file.size(of)))
) -> out
if (browse) htmltools::html_print(htmltools::HTML(out$html))
invisible(out)
}

37
README.Rmd

@ -20,7 +20,7 @@ Tools to Work with the 'Feedly' 'API'
## What's Inside The Tin
The following functions are implemented:
The following API functions are implemented:
- `feedly_access_token`: Retrieve the Feedly Developer Token
- `feedly_collections`: Retrieve Feedly Connections
@ -32,6 +32,10 @@ The following functions are implemented:
- `feedly_stream`: Retrieve contents of a Feedly "stream"
- `feedly_tags`: Retrieve List of Tags
The following helper functions are åvailable:
- `render_stream`: Render a Feedly Stream Data Frame to RMarkdown
The following helper references are available:
- `global_resource_ids`: Global Resource Ids Helper Reference
@ -120,6 +124,37 @@ fp <- feedly_profile()
fp[grepl("rate_limit", names(fp))]
```
### Sample Stream Report
```{r sample_stream_report, eval=FALSE}
fp <- feedly_profile() # get profile to get my id
# use the id to get my "security" category feed
fs <- feedly_stream(sprintf("user/%s/category/security", fp$id))
# get the top 10 items with engagement >= third quartile of all posts
# and don't include duplicates in the report
mutate(fs$items, published = as.Date(published)) %>%
filter(published >= as.Date("2018-12-01")) %>%
filter(engagement > fivenum(engagement)[4]) %>%
filter(!is.na(summary_content)) %>%
mutate(alt_url = map_chr(alternate, ~.x[[1]])) %>%
distinct(alt_url, .keep_all = TRUE) %>%
slice(1:10) -> for_report
# render the report
render_stream(
feedly_stream = for_report,
title = "Cybersecurity News",
include_visual = TRUE,
browse = TRUE
)
```
Click on the following to see the complete render:
<center><a href="sample-report.jpg"><img src="report-thumb.png"/></a></center>
## Package Code Metrics
```{r pkg_metrics}

50
README.md

@ -16,7 +16,7 @@ collections and streams.
## What’s Inside The Tin
The following functions are implemented:
The following API functions are implemented:
- `feedly_access_token`: Retrieve the Feedly Developer Token
- `feedly_collections`: Retrieve Feedly Connections
@ -28,6 +28,10 @@ The following functions are implemented:
- `feedly_stream`: Retrieve contents of a Feedly “stream”
- `feedly_tags`: Retrieve List of Tags
The following helper functions are åvailable:
- `render_stream`: Render a Feedly Stream Data Frame to RMarkdown
The following helper references are available:
- `global_resource_ids`: Global Resource Ids Helper Reference
@ -277,16 +281,52 @@ fp[grepl("rate_limit", names(fp))]
## $x_rate_limit_reset
## [1] "38413"
### Sample Stream Report
``` r
fp <- feedly_profile() # get profile to get my id
# use the id to get my "security" category feed
fs <- feedly_stream(sprintf("user/%s/category/security", fp$id))
# get the top 10 items with engagement >= third quartile of all posts
# and don't include duplicates in the report
mutate(fs$items, published = as.Date(published)) %>%
filter(published >= as.Date("2018-12-01")) %>%
filter(engagement > fivenum(engagement)[4]) %>%
filter(!is.na(summary_content)) %>%
mutate(alt_url = map_chr(alternate, ~.x[[1]])) %>%
distinct(alt_url, .keep_all = TRUE) %>%
slice(1:10) -> for_report
# render the report
render_stream(
feedly_stream = for_report,
title = "Cybersecurity News",
include_visual = TRUE,
browse = TRUE
)
```
Click on the following to see the complete
render:
<center>
<a href="sample-report.jpg"><img src="report-thumb.png"/></a>
</center>
## Package Code Metrics
``` r
cloc::cloc_pkg_md()
```
| Lang | \# Files | (%) | LoC | (%) | Blank lines | (%) | \# Lines | (%) |
| :--- | -------: | ---: | --: | ---: | ----------: | ---: | -------: | ---: |
| R | 15 | 0.94 | 279 | 0.92 | 105 | 0.72 | 307 | 0.83 |
| Rmd | 1 | 0.06 | 25 | 0.08 | 41 | 0.28 | 65 | 0.17 |
| Lang | \# Files | (%) | LoC | (%) | Blank lines | (%) | \# Lines | (%) |
| :--- | -------: | ---: | --: | --: | ----------: | ---: | -------: | ---: |
| R | 16 | 0.94 | 356 | 0.9 | 138 | 0.73 | 331 | 0.81 |
| Rmd | 1 | 0.06 | 40 | 0.1 | 50 | 0.27 | 76 | 0.19 |
## Image Credit

37
man/render_stream.Rd

@ -0,0 +1,37 @@
% Generated by roxygen2: do not edit by hand
% Please edit documentation in R/render-stream.R
\name{render_stream}
\alias{render_stream}
\title{Render a Feedly Stream Data Frame to RMarkdown}
\usage{
render_stream(feedly_stream, title = "Feedly Stream Summary",
include_visual = FALSE, browse = FALSE, quiet = TRUE)
}
\arguments{
\item{feedly_stream}{output from \code{\link[=feedly_stream]{feedly_stream()}}. Ideally, you'll filter
this so it has a minimal number of elements (unless you like scrolling
through large HTML documents)}
\item{title}{A title for your "report"}
\item{include_visual}{if \code{TRUE} then any \code{visual_url} image content will
be rendered with the summary text. Default is \code{FALSE}.}
\item{browse}{if \code{TRUE} open the HTML document for viewing. Default is \code{FALSE}}
\item{quiet}{passed on to \code{\link[rmarkdown:render]{rmarkdown::render()}}. Default is \code{TRUE}.}
}
\value{
a list with the contents of the R Markdown document and the
rendered HTML file (so you can save/tweak before publishing).
}
\description{
This function takes a minimalist approach to formatting an R Markdown
document from the contents of a Feedly stream. It uses the feed item
title, URL (first \code{alternate} one), published data and summary content to make
each entry.
}
\note{
This function requires that \code{htmltools}, \code{rmarkdown} and \code{glue} are installed
on your system.
}

BIN
report-thumb.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 355 KiB

BIN
sample-report.jpg

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 MiB

Loading…
Cancel
Save