commit 263db178a7b2becca9a4f0bd307694cb1d1a1016 Author: Danila Fedorin Date: Tue Mar 20 16:31:49 2018 -0700 Initial commit. diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..8f0c87a --- /dev/null +++ b/.editorconfig @@ -0,0 +1,7 @@ +[*.cr] +charset = utf-8 +end_of_line = lf +insert_final_newline = true +indent_style = space +indent_size = 2 +trim_trailing_whitespace = true diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..0397cf7 --- /dev/null +++ b/.gitignore @@ -0,0 +1,4 @@ +/doc/ +/lib/ +/bin/ +/.shards/ diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000..ffc7b6a --- /dev/null +++ b/.travis.yml @@ -0,0 +1 @@ +language: crystal diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..e66fb36 --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2018 Danila Fedorin + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/README.md b/README.md new file mode 100644 index 0000000..e7d116c --- /dev/null +++ b/README.md @@ -0,0 +1,6 @@ +# Joann's Pupper Bot +This is a small Telegram bot to send Joann Jarvis +a picture from the top of `/r/rarepuppers`. + +## Contributors +- [DanilaFe](https://dev.danilafe.com/DanilaFe) Danila Fedorin - creator, maintainer diff --git a/shard.yml b/shard.yml new file mode 100644 index 0000000..993c4c2 --- /dev/null +++ b/shard.yml @@ -0,0 +1,17 @@ +name: joann-pupper-bot +version: 0.1.0 + +authors: + - Danila Fedorin + +targets: + joann-pupper-bot: + main: src/joann-pupper-bot.cr + +dependencies: + telepathy: + git: http://dev.danilafe.com/Crystal-Bots/telepathy + +crystal: 0.24.1 + +license: MIT diff --git a/src/joann-pupper-bot.cr b/src/joann-pupper-bot.cr new file mode 100644 index 0000000..6f03b16 --- /dev/null +++ b/src/joann-pupper-bot.cr @@ -0,0 +1,65 @@ +require "./joann-pupper-bot/*" +require "logger" +require "telepathy" +require "time" + +# Chat IDs +chatid_joann = 215301902 +chatid_daniel = 220888832 + +# Configuration +subreddit = "rarepuppers" +chatid = chatid_joann +delay = 1.hours +active_hours = 7..24 +bot_token = "599474797:AAEmjQNO32uqurI16blS9FT4OoO7GdUZ6h0" + +# Setup +completed = [] of String +logger = Logger.new(STDOUT) +bot = Telepathy::Bot.new bot_token + +# Commands. +bot.command "ping" do |update, args| + bot.send_message(update.message.as(Telepathy::Message).chat.id, "pong") +end + +bot.command "pupper" do |update, args| + url = get_reddit_post(subreddit, completed) + if url + command_chatid = update.message.as(Telepathy::Message).chat.id + logger.info "Using URL #{url} for request from #{command_chatid}" + bot.send_photo(command_chatid, url) + else + logger.error "Unable to find a post to send." + end +end + +spawn do + loop do + time = Time.now + url = get_reddit_post(subreddit, completed) if (active_hours.includes? time.hour) + if url + logger.info "Sending regular picture to #{chatid}." + bot.send_photo(chatid.to_i64, url) + else + logger.error "Unable to find a post to send. (Or it's quiet hours)" + end + sleep delay + end +end + +# Code to stop the bot on time. +end_channel = Channel(Nil).new(1) + +bot.poll_end do + end_channel.send nil +end + +Signal::INT.trap do + logger.info "Shutting down bot..." + bot.end_poll +end + +bot.poll +end_channel.receive diff --git a/src/joann-pupper-bot/reddit.cr b/src/joann-pupper-bot/reddit.cr new file mode 100644 index 0000000..b66e933 --- /dev/null +++ b/src/joann-pupper-bot/reddit.cr @@ -0,0 +1,26 @@ +require "http/client" +require "json" + +def get_reddit_json(subreddit) + request_url = "https://www.reddit.com/r/#{subreddit}/hot.json?limit=30" + response = HTTP::Client.get(request_url, headers: HTTP::Headers { + "User-agent" => "Joann-Pupper-Bot" + }) + response.body?.try { |body| JSON.parse(body) } +end + +def filter_reddit_json(json, completed) + json["data"]["children"] + .map(&.["data"]) + .select do |it| + url = it["url"].as_s + name = it["name"].as_s + !completed.includes?(name) && (url.ends_with?(".png") || url.ends_with?(".jpg")) + end +end + +def get_reddit_post(subreddit, completed) + json = get_reddit_json(subreddit) + post = json.try { |json| filter_reddit_json(json, completed).first? } + post.try { |post| completed.push(post["name"].as_s); post["url"].as_s } +end