Compare commits
No commits in common. "8d90b052a001a6101dc691a907a16de4fb0a26ee" and "5150d965a34deae354a34e24d384644024473e5b" have entirely different histories.
8d90b052a0
...
5150d965a3
@ -10,11 +10,7 @@ targets:
|
|||||||
|
|
||||||
dependencies:
|
dependencies:
|
||||||
telepathy:
|
telepathy:
|
||||||
git: https://dev.danilafe.com/Crystal-Bots/telepathy
|
git: http://dev.danilafe.com/Crystal-Bots/telepathy
|
||||||
cron_scheduler:
|
|
||||||
github: kostya/cron_scheduler
|
|
||||||
sqlite3:
|
|
||||||
github: crystal-lang/crystal-sqlite3
|
|
||||||
|
|
||||||
crystal: 0.24.1
|
crystal: 0.24.1
|
||||||
|
|
||||||
|
@ -1,18 +1,67 @@
|
|||||||
require "./joann-pupper-bot/*"
|
require "./joann-pupper-bot/*"
|
||||||
require "option_parser"
|
require "logger"
|
||||||
|
require "telepathy"
|
||||||
|
require "time"
|
||||||
|
|
||||||
config_file = "./config.yaml"
|
# Chat IDs
|
||||||
|
chatid_joann = 215301902
|
||||||
|
chatid_daniel = 220888832
|
||||||
|
|
||||||
OptionParser.parse do |parser|
|
# Configuration
|
||||||
parser.banner = "Usage: joann-pupper-bot [arguments]"
|
subreddit = "rarepuppers"
|
||||||
parser.on("-c", "--config=CONFIG", "Select config file") do |c|
|
chatid = chatid_daniel
|
||||||
config_file = c
|
delay = 1.hours
|
||||||
end
|
active_hours = 7..24
|
||||||
parser.on("-h", "--help", "Show this message") do
|
bot_token = "599474797:AAEmjQNO32uqurI16blS9FT4OoO7GdUZ6h0"
|
||||||
puts parser
|
|
||||||
exit
|
# 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_tuple = get_reddit_post(subreddit, completed)
|
||||||
|
if url_tuple
|
||||||
|
url, title = url_tuple
|
||||||
|
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, title)
|
||||||
|
else
|
||||||
|
logger.error "Unable to find a post to send."
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
botc = PupperBot.new(BotConfiguration.from_yaml(File.open(config_file)))
|
spawn do
|
||||||
sleep
|
loop do
|
||||||
|
time = Time.local
|
||||||
|
url_tuple = get_reddit_post(subreddit, completed) if (active_hours.includes? time.hour)
|
||||||
|
if url_tuple
|
||||||
|
url, title = url_tuple
|
||||||
|
logger.info "Sending regular picture to #{chatid}."
|
||||||
|
bot.send_photo(chatid.to_i64, url, title)
|
||||||
|
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
|
||||||
|
@ -1,83 +0,0 @@
|
|||||||
require "logger"
|
|
||||||
require "telepathy"
|
|
||||||
require "time"
|
|
||||||
require "sqlite3"
|
|
||||||
require "cron_scheduler"
|
|
||||||
|
|
||||||
EXTENSIONS = ["png", "jpeg", "jpg"]
|
|
||||||
LOGGER = Logger.new(STDOUT)
|
|
||||||
|
|
||||||
class PupperBot
|
|
||||||
@db : DB::Database
|
|
||||||
|
|
||||||
def initialize(@configuration : BotConfiguration)
|
|
||||||
@telegram_bot = Telepathy::Bot.new configuration.token
|
|
||||||
@db = DB.open "sqlite3://#{configuration.database}"
|
|
||||||
initialize_db
|
|
||||||
update_database
|
|
||||||
initialize_timers
|
|
||||||
initialize_telegram
|
|
||||||
send_broadcast
|
|
||||||
end
|
|
||||||
|
|
||||||
private def initialize_db
|
|
||||||
@db.exec "create table if not exists posts(id integer primary key, title text, url text unique)"
|
|
||||||
@db.exec "create table if not exists recepient_posts(recepient integer, post integer, foreign key(post) references posts(id))"
|
|
||||||
end
|
|
||||||
|
|
||||||
private def initialize_timers
|
|
||||||
CronScheduler.define do
|
|
||||||
at(@configuration.send_cron) { send_broadcast }
|
|
||||||
at(@configuration.refresh_cron) { update_database }
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
private def initialize_telegram
|
|
||||||
@telegram_bot.command "ping" do |update, args|
|
|
||||||
@telegram_bot.send_message(update.message.as(Telepathy::Message).chat.id, "pong")
|
|
||||||
end
|
|
||||||
|
|
||||||
@telegram_bot.command "pupper" do |update, args|
|
|
||||||
command_chatid = update.message.as(Telepathy::Message).chat.id
|
|
||||||
send_single command_chatid
|
|
||||||
end
|
|
||||||
|
|
||||||
@telegram_bot.poll
|
|
||||||
end
|
|
||||||
|
|
||||||
def send_single(chatid)
|
|
||||||
unsent_query = "select id, title, url from posts where not exists (select * from recepient_posts where recepient=? and post=id) limit 1"
|
|
||||||
|
|
||||||
unless to_send = @db.query_one? unsent_query, chatid, as: { Int64, String, String }
|
|
||||||
LOGGER.info "Unable to find a post to send to #{chatid}."
|
|
||||||
return
|
|
||||||
end
|
|
||||||
|
|
||||||
id, title, url = to_send
|
|
||||||
LOGGER.info "Using URL #{url} for request from #{chatid}"
|
|
||||||
@db.exec "insert into recepient_posts(recepient, post) values(?, ?)", chatid, id
|
|
||||||
@telegram_bot.send_photo(chatid, url, title)
|
|
||||||
end
|
|
||||||
|
|
||||||
def send_broadcast
|
|
||||||
@configuration.recipients.each do |recepient|
|
|
||||||
send_single recepient
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def update_database
|
|
||||||
unless response = RedditResponse.from_subreddits(@configuration.subreddits)
|
|
||||||
LOGGER.info "Unable to find more posts for the database"
|
|
||||||
return
|
|
||||||
end
|
|
||||||
|
|
||||||
posts = response.data.posts_matching { |post| EXTENSIONS.any? { |it| post.url.ends_with? it } }
|
|
||||||
posts.each do |post|
|
|
||||||
LOGGER.info "Trying to save post #{post.title} #{post.url}"
|
|
||||||
begin
|
|
||||||
@db.exec "insert into posts(title, url) values(?, ?)", post.title, post.url
|
|
||||||
rescue
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
@ -1,11 +0,0 @@
|
|||||||
require "yaml"
|
|
||||||
|
|
||||||
class BotConfiguration
|
|
||||||
YAML.mapping(
|
|
||||||
token: String,
|
|
||||||
database: { type: String, default: "./data.sqlite" },
|
|
||||||
subreddits: { type: Array(String), default: [ "rarepuppers" ] },
|
|
||||||
send_cron: { type: String, default: "*/30 8-21 * * *" },
|
|
||||||
refresh_cron: { type: String, default: "*/15 * * * *" },
|
|
||||||
recipients: Array(Int64))
|
|
||||||
end
|
|
@ -21,7 +21,7 @@ class RedditResponse
|
|||||||
children: Array(RedditWrapper(RedditChild)))
|
children: Array(RedditWrapper(RedditChild)))
|
||||||
|
|
||||||
def self.from_subreddits(subreddits : Array(String))
|
def self.from_subreddits(subreddits : Array(String))
|
||||||
request_url = URI.new scheme: "https", host: "www.reddit.com", path: "/r/#{subreddits.join "+"}/hot.json", query: "limit=30"
|
request_url = URI.new scheme: "https", host: "www.reddit.com", path: "/r/hot.json", query: "limit=30"
|
||||||
response = HTTP::Client.get(request_url, headers: HTTP::Headers {
|
response = HTTP::Client.get(request_url, headers: HTTP::Headers {
|
||||||
"User-agent" => "Joann-Pupper-Bot"
|
"User-agent" => "Joann-Pupper-Bot"
|
||||||
})
|
})
|
||||||
@ -30,7 +30,7 @@ class RedditResponse
|
|||||||
|
|
||||||
begin
|
begin
|
||||||
RedditWrapper(RedditResponse).from_json body
|
RedditWrapper(RedditResponse).from_json body
|
||||||
rescue e
|
rescue
|
||||||
nil
|
nil
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@ -45,3 +45,16 @@ class RedditResponse
|
|||||||
.select { |it| yield it }
|
.select { |it| yield it }
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def filter_reddit_json(json, completed, extensions = ["png", "json"])
|
||||||
|
json.data.posts_matching do |post|
|
||||||
|
extensions.any? { |it| post.url.ends_with? it } && !completed.includes? post.url
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def get_reddit_post(subreddit, completed)
|
||||||
|
return nil unless json = RedditResponse.from_subreddit subreddit
|
||||||
|
return nil unless post = filter_reddit_json(json, completed).first?
|
||||||
|
completed.push(post.name)
|
||||||
|
return { post.url, post.title }
|
||||||
|
end
|
||||||
|
Loading…
Reference in New Issue
Block a user