mirror of
https://github.com/davegallant/rfd-notify.git
synced 2025-08-05 08:13:39 +00:00
2
.github/workflows/docker.yml
vendored
2
.github/workflows/docker.yml
vendored
@@ -13,7 +13,7 @@ jobs:
|
||||
- name: Publish version to Registry
|
||||
uses: elgohr/Publish-Docker-Github-Action@master
|
||||
with:
|
||||
name: davegallant/npm-groovy-lint-test
|
||||
name: davegallant/rfd-notify
|
||||
username: ${{ secrets.DOCKER_USERNAME }}
|
||||
password: ${{ secrets.DOCKER_PASSWORD }}
|
||||
tag_semver: true
|
||||
|
1
.gitignore
vendored
1
.gitignore
vendored
@@ -1 +1,2 @@
|
||||
/target
|
||||
deals_db/
|
||||
|
607
Cargo.lock
generated
607
Cargo.lock
generated
File diff suppressed because it is too large
Load Diff
13
Cargo.toml
13
Cargo.toml
@@ -1,16 +1,15 @@
|
||||
[package]
|
||||
name = "rfd-notify"
|
||||
version = "0.1.2"
|
||||
version = "0.2.0"
|
||||
authors = ["Dave Gallant <davegallant@gmail.com>"]
|
||||
edition = "2018"
|
||||
|
||||
[dependencies]
|
||||
sendgrid = { version = "0.13.0", features = ["rustls"] }
|
||||
toml = "0.5.7"
|
||||
sendgrid = { version = "0.13.0", default-features = false, features = ["rustls", "blocking"] }
|
||||
serde_derive = "1.0.112"
|
||||
serde = "1.0.117"
|
||||
reqwest = { version = "0.10", default-features = false, features = ["json", "rustls-tls"] }
|
||||
tokio = { version = "0.3", features = ["full"] }
|
||||
tokio = { version = "0.2", features = ["full"] }
|
||||
serde_json = "1.0.59"
|
||||
log = "0.4"
|
||||
pretty_env_logger = "0.4.0"
|
||||
@@ -18,3 +17,9 @@ regex = "1.4.1"
|
||||
rust-crypto = "^0.2"
|
||||
sled = "0.34.4"
|
||||
clap = "2.33.3"
|
||||
envconfig = "0.9.1"
|
||||
envconfig_derive = "0.9.1"
|
||||
serde_yaml = "0.8"
|
||||
|
||||
[dev-dependencies]
|
||||
serial_test = "*"
|
||||
|
69
README.md
69
README.md
@@ -8,11 +8,11 @@
|
||||
This tool looks for regular expressions from [RedFlagDeals.com forums](https://forums.redflagdeals.com/hot-deals-f9/) and will send emails based on matches.
|
||||
|
||||
|
||||
## requirements
|
||||
## Prerequisites
|
||||
|
||||
- a free [SendGrid API key](https://sendgrid.com/pricing/)
|
||||
|
||||
## use
|
||||
## Usage
|
||||
|
||||
```shell
|
||||
USAGE:
|
||||
@@ -27,28 +27,47 @@ OPTIONS:
|
||||
-d, --dbpath <dbpath> Specify path to where the embedded database is stored [default: ./deals_db]
|
||||
```
|
||||
|
||||
### docker
|
||||
## Github action
|
||||
|
||||
```shell
|
||||
# Run the docker image using an example config:
|
||||
docker run -e RUST_LOG=INFO davegallant/rfd-notify -c /examples/config.toml
|
||||
An action can be setup to scan for deals, send a notification and store previously found deals in the repo.
|
||||
|
||||
### Example
|
||||
|
||||
This action can be run on a cron and can store the embedded database by commiting the files to git.
|
||||
|
||||
It also requires the corresponding [encrypted secrets](https://docs.github.com/en/free-pro-team@latest/actions/reference/encrypted-secrets) setup.
|
||||
|
||||
```yaml
|
||||
# .github/workflows/main.yml
|
||||
|
||||
on:
|
||||
schedule:
|
||||
- cron: '*/5 * * * *'
|
||||
jobs:
|
||||
rfd_notify:
|
||||
runs-on: ubuntu-latest
|
||||
name: rfd-notify
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v2
|
||||
with:
|
||||
persist-credentials: false # otherwise, the token used is the GITHUB_TOKEN, instead of your personal token
|
||||
fetch-depth: 0 # otherwise, you will failed to push refs to dest repo
|
||||
- name: Run rfd-notify
|
||||
uses: davegallant/rfd-notify@v0.2.0
|
||||
env:
|
||||
SENDGRID_API_KEY: ${{ secrets.SENDGRID_API_KEY }}
|
||||
SENDGRID_MAIL_FROM: notify@rfd-notify.org
|
||||
SENDGRID_MAIL_TO: ${{ secrets.SENDGRID_MAIL_TO }}
|
||||
- name: Commit files
|
||||
run: |
|
||||
git config --local user.email "action@github.com"
|
||||
git config --local user.name "GitHub Action"
|
||||
git add deals_db/
|
||||
git commit -m "Add changes" -a || true
|
||||
- name: Push changes
|
||||
uses: ad-m/github-push-action@master
|
||||
with:
|
||||
github_token: ${{ secrets.PERSONAL_GITHUB_TOKEN }}
|
||||
branch: ${{ github.ref }}
|
||||
```
|
||||
|
||||
Provide a custom configuration. An example can found in [config.toml](./examples/config.toml)
|
||||
|
||||
```shell
|
||||
# Provide a custom-config.toml that is in the current directory
|
||||
# ensuring the correct user is mapped to the working directory
|
||||
docker run -u "$(id -u):$(id -g)" -w=/tmp -e RUST_LOG=INFO -v "$PWD":/tmp davegallant/rfd-notify -c /tmp/custom-config.toml
|
||||
```
|
||||
|
||||
## cross compile
|
||||
|
||||
I had motivations to run this on a Raspberry Pi Zero (without needing docker on the pi):
|
||||
|
||||
```shell
|
||||
alias rust-musl-builder='docker run --rm -it -v "$(pwd)":/home/rust/src messense/rust-musl-cross:arm-musleabihf'
|
||||
rust-musl-builder cargo build --release
|
||||
```
|
||||
|
||||
The above can be substituted for [other architectures](https://github.com/messense/rust-musl-cross#prebuilt-images).
|
||||
|
7
action.yml
Normal file
7
action.yml
Normal file
@@ -0,0 +1,7 @@
|
||||
name: 'rfd-notify'
|
||||
description: 'get notified of deals based on regex'
|
||||
icon: command
|
||||
color: gray-dark
|
||||
runs:
|
||||
using: 'docker'
|
||||
image: 'github-action/Dockerfile'
|
@@ -1,11 +0,0 @@
|
||||
expressions = [
|
||||
"amazon",
|
||||
"costco",
|
||||
"rx.?5[6789]0",
|
||||
"starbucks"
|
||||
]
|
||||
|
||||
[sendgrid]
|
||||
api_key = "<SENDGRID-API-KEY>"
|
||||
mail_to = "<YOUR-EMAIL>@gmail.com"
|
||||
mail_from = "Notify <notify@rfd-notify.org>"
|
5
examples/config.yaml
Normal file
5
examples/config.yaml
Normal file
@@ -0,0 +1,5 @@
|
||||
expressions:
|
||||
- amazon
|
||||
- costco",
|
||||
- "rx.?5[6789]0"
|
||||
- starbucks
|
3
github-action/Dockerfile
Normal file
3
github-action/Dockerfile
Normal file
@@ -0,0 +1,3 @@
|
||||
FROM davegallant/rfd-notify:0.2.0
|
||||
|
||||
ENTRYPOINT ["/rfd-notify", "-c", "config.yaml"]
|
5
github-action/entrypoint.sh
Executable file
5
github-action/entrypoint.sh
Executable file
@@ -0,0 +1,5 @@
|
||||
#!/bin/sh -l
|
||||
|
||||
echo "Starting rfd-notify with config: $1"
|
||||
|
||||
rfd-notify -c "$1"
|
@@ -1,40 +1,76 @@
|
||||
extern crate toml;
|
||||
use serde_derive::Deserialize;
|
||||
extern crate envconfig;
|
||||
extern crate envconfig_derive;
|
||||
|
||||
use serde::Deserialize;
|
||||
|
||||
use envconfig::Envconfig;
|
||||
use std::fs;
|
||||
use std::vec::Vec;
|
||||
|
||||
#[cfg(test)]
|
||||
extern crate serial_test;
|
||||
#[cfg(test)]
|
||||
use serial_test::serial;
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn parse_config() {
|
||||
let file = "./examples/config.toml";
|
||||
parse(&file);
|
||||
#[should_panic]
|
||||
#[serial]
|
||||
fn load_config_with_missing_sendgrid_api_key() {
|
||||
std::env::remove_var("SENDGRID_API_KEY");
|
||||
let file = "./examples/config.yaml";
|
||||
load(&file);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[serial]
|
||||
fn load_config() {
|
||||
let file = "./examples/config.yaml";
|
||||
std::env::set_var("SENDGRID_API_KEY", "FAKE");
|
||||
std::env::set_var("SENDGRID_MAIL_FROM", "notify@rfd-notify.org");
|
||||
std::env::set_var("SENDGRID_MAIL_TO", "test@email.com");
|
||||
load(&file);
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Deserialize, Debug)]
|
||||
#[derive(Debug)]
|
||||
pub struct Config {
|
||||
pub expressions: Vec<String>,
|
||||
pub sendgrid: Sendgrid,
|
||||
pub sendgrid: SendgridConfig,
|
||||
}
|
||||
|
||||
#[derive(Deserialize, Debug)]
|
||||
pub struct Sendgrid {
|
||||
#[derive(Debug, Deserialize, PartialEq)]
|
||||
pub struct ConfigFile {
|
||||
pub expressions: Vec<String>,
|
||||
}
|
||||
|
||||
#[derive(Envconfig, Debug)]
|
||||
pub struct SendgridConfig {
|
||||
#[envconfig(from = "SENDGRID_MAIL_FROM")]
|
||||
pub mail_from: String,
|
||||
|
||||
#[envconfig(from = "SENDGRID_MAIL_TO")]
|
||||
pub mail_to: String,
|
||||
|
||||
#[envconfig(from = "SENDGRID_API_KEY")]
|
||||
pub api_key: String,
|
||||
}
|
||||
|
||||
pub fn parse(filename: &str) -> Config {
|
||||
pub fn load(filename: &str) -> Config {
|
||||
// Initialize expressions from file
|
||||
let contents = fs::read_to_string(filename)
|
||||
.unwrap_or_else(|e| panic!("Unable to read configuration file '{}'. {}", filename, e));
|
||||
let config: Config = toml::from_str(&contents).unwrap_or_else(|e| {
|
||||
panic!(
|
||||
"Unable to parse configuration with contents: {}. {}",
|
||||
contents, e
|
||||
)
|
||||
});
|
||||
|
||||
config
|
||||
let config_file: ConfigFile = serde_yaml::from_str(&contents).unwrap();
|
||||
|
||||
// Initialize config from environment variables or terminate the process.
|
||||
let sendgrid_config = SendgridConfig::init_from_env().unwrap();
|
||||
|
||||
Config {
|
||||
expressions: config_file.expressions,
|
||||
sendgrid: sendgrid_config,
|
||||
}
|
||||
}
|
||||
|
@@ -39,7 +39,7 @@ fn main() {
|
||||
let matches = app.get_matches();
|
||||
|
||||
let config = matches.value_of("config").unwrap();
|
||||
let parsed_config = config::parse(config);
|
||||
let parsed_config = config::load(config);
|
||||
|
||||
info!("{:?}\n", parsed_config);
|
||||
let hot_deals = rfd::get_hot_deals().map_err(|err| error!("{:?}", err)).ok();
|
||||
|
Reference in New Issue
Block a user