Skip to content

Instantly share code, notes, and snippets.

@lnanase
Last active May 16, 2020 04:08
Show Gist options
  • Save lnanase/69e710db55782d238b40a588523a96e0 to your computer and use it in GitHub Desktop.
Save lnanase/69e710db55782d238b40a588523a96e0 to your computer and use it in GitHub Desktop.
imastodonでちひろさんbotが動かしているプログラム置き場

## twitter TWITTER_CONSUMER_KEY=”” TWITTER_CONSUMER_SECRET=”” TWITTER_ACCESS_TOKEN=”” TWITTER_ACCESS_TOKEN_SECRET=””

## imastodon MASTODON_HOST=”” TB_RANKING_CLIENT_ID=”” TB_RANKING_CLIENT_SECRET=”” TB_RANKING_BEARER=”” CHIHIRO_CLIENT_ID=”” CHIHIRO_CLIENT_SECRET=”” CHIHIRO_BEARER=”” PIYO_CLIENT_ID=”” PIYO_CLIENT_SECRET=”” PIYO_BEARER=”” TRENDON_CLIENT_ID=”” TRENDON_CLIENT_SECRET=”” TRENDON_BEARER=””

GRAVE_CSV_PATH=””

59 23 * * * sleep 40;(cd $HOME/scripts/rb && ruby push_imastodon_what_report.rb >> /tmp/push_imastodon_w.log 2>&1) > /dev/null
01 00 * * * (cd $HOME/scripts/rb && ruby push_imastodon_grave_report.rb >> /tmp/push_imastodon_g.log 2>&1) > /dev/null
00 * * * * (cd $HOME/scripts/rb && ruby push_imastodon_imascg.rb >> /tmp/push_imastodon_cg.log 2>&1) > /dev/null
30 23 * * * (cd $HOME/scripts/rb && ruby push_imastodon_imascg.rb >> /tmp/push_imastodon_cg.log 2>&1) > /dev/null
01 07,18,22 * * * (cd $HOME/scripts/rb && ruby push_imastodon_goods_info.rb >> /tmp/push_imastodon_info.log 2>&1) > /dev/null
50 17 28-31 * * (cd $HOME/scripts/rb && ruby push_imastodon_call_gacha.rb > /tmp/push_imastodon_call.log 2>&1) > /dev/null
05 07,13,22 * * * (cd $HOME/scripts/rb && ruby push_imastodon_shiny_daily.rb >> /tmp/push_imastodon_shiny.log 2>&1) > /dev/null
# frozen_string_literal: true
# A sample Gemfile
source "https://rubygems.org"
# gem "rails"
gem "http"
gem "mail"
gem "mechanize"
gem "ruby-gmail"
gem "selenium-webdriver", ">= 3.142.3"
gem "twitter", ">= 6.2.0"
gem "dotenv"
gem "mini_magick"
gem "natto"
# -*- coding: utf-8 -*-
# imastodonに月末ガチャの告知をする
#
# usage: push_imastodon_call_gacha.rb
require 'rubygems'
require 'bundler'
Bundler.require(:default)
Dotenv.load
# const
UA = 'Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.84 Safari/537.36' #Chrome
# mechanize
agent = Mechanize.new
agent.user_agent = UA
agent.request_headers = {'accept-language' => 'ja, ja-JP', 'accept-encoding' => 'utf-8'}
now = Time.now
tomorrow = now + 60 * 60 * 24
if tomorrow.month != now.month
agent.request_headers = {'Authorization' => 'Bearer ' + ENV['CHIHIRO_BEARER']}
# toot
res = agent.post(ENV['MASTODON_HOST'] + 'api/v1/statuses', {
'status': "さぁ月末ガチャ10分前ですよ!準備はいいですか!\nhttps://www.amazon.co.jp/dp/B01E3JRRKE/",
'visibility': 'public'
})
p res.code
end
# -*- coding: utf-8 -*-
# imastodonにアイマスの新商品発売の告知をする
#
# usage: push_imastodon_goods_info.rb
require 'rubygems'
require 'bundler'
Bundler.require(:default)
Dotenv.load
# const
IMAS_INFO_URL = 'http://imasnews765.com/'
UA = 'Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.84 Safari/537.36' #Chrome
def find_imas_goods_news(agent)
result = []
is_date_element = false
tmp = nil
page = agent.get(IMAS_INFO_URL)
page.at('#text-3').at('.textwidget').children.each do |elem|
if elem.instance_of?(Nokogiri::XML::Text)
date_str = elem.text.strip
if date_str == ''
break
end
tmp = [date_str]
is_date_element = true
elsif is_date_element
item = elem.inner_text.strip
# CloudFlareのScrapeShield E-mail obfuscation optionが動作している場合の対策
if item.include?('[email protected]')
item = item.gsub('[email protected]', 'IDOLM@STER')
end
tmp.push(item)
result.push(tmp)
is_date_element = false
end
end
result
end
def send_message(agent, list)
send_message = ''
now = Time.now
before = now + 60 * 60 * 7
today = now.strftime("%Y/%m/%d")
yesterday = before.strftime("%Y/%m/%d")
# 前日18時以降から当日は告知する
list.each do |row|
if row[0].nil?
next
end
if row[0] == today or row[0] == yesterday
send_message = send_message + row[0] + 'に' + row[1] + "\n"
end
end
unless send_message.empty?
p send_message
agent.request_headers = {'Authorization' => 'Bearer ' + ENV['CHIHIRO_BEARER']}
# toot
res = agent.post(ENV['MASTODON_HOST'] + 'api/v1/statuses', {
'status': "#{send_message}が発売になります。是非お買い求めくださいね。",
'spoiler_text': '新商品発売のご案内です!',
'visibility': 'public'
})
p res.code
end
end
# mechanize
agent = Mechanize.new
agent.user_agent = UA
agent.request_headers = {'accept-language' => 'ja, ja-JP', 'accept-encoding' => 'utf-8'}
items = []
# アイドルマスター情報まとめ から商品情報をスクレイピング
items.concat(find_imas_goods_news(agent))
p items
send_message(agent, items)
# -*- coding: utf-8 -*-
# imastodonに前日のUsa_botが建てた墓の数を送信する
# https://imastodon.net/@Usa_bot
#
# usage: push_imastodon_grave_report.rb
require 'rubygems'
require 'bundler'
Bundler.require(:default)
Dotenv.load
# CONST
TARGET_ACCOUNT_ID = '17061' #@Usa_bot
UA = 'Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.84 Safari/537.36' #Chrome
# imastodon
agent = Mechanize.new
agent.user_agent = UA
agent.request_headers = {'accept-language' => 'ja, ja-JP', 'accept-encoding' => 'utf-8'}
agent.request_headers = {'Authorization' => 'Bearer ' + ENV['CHIHIRO_BEARER']}
yesterday = Time.now - 24 * 60 * 60
max_id = -1
grave = 0
p yesterday
# grave search
get_uri = ENV['MASTODON_HOST'] + 'api/v1/accounts/' + TARGET_ACCOUNT_ID + '/statuses'
get_params = {'limit': 40}
# MAX40件しかget出来ないのでループ
until max_id.nil? do
res = agent.get(get_uri, get_params)
JSON.parse(res.body).each {|status|
created_at = Time.parse(status['created_at'])
created_at.localtime("+09:00")
if yesterday.day == created_at.day
content = status['content']
p created_at
# 墓検索
if !content.index('[grave]', -15).nil?
p 'grave'
p content
grave = grave + 1
end
max_id = status['id']
get_params['max_id'] = max_id
end
if max_id != -1 and max_id != status['id']
max_id = nil
break
end
}
end
p grave
# toot
res = agent.post(ENV['MASTODON_HOST'] + 'api/v1/statuses', {
'status': '昨日' + yesterday.strftime('%Y年%m月%d日') + "、建てられた墓の数は#{grave}個です。\nhttps://gcp-lnanase.ooguy.com/grave/ #R_I_P",
'visibility': 'public'
})
p res.code
# add csv
open(ENV['GRAVE_CSV_PATH'], 'a') {|f| f.puts yesterday.strftime("%Y-%m-%d") + ',' + grave.to_s }
# -*- coding: utf-8 -*-
# imastodonにモバマス/デレステイベントの終了時間を送信する
#
# usage: push_imastodon_imascg.rb
require 'rubygems'
require 'bundler'
Bundler.require(:default)
Dotenv.load
# const
IMAS_CG_URL = 'http://seesaawiki.jp/imascg/'
SLSTAGE_URL = 'https://imascg-slstage-wiki.gamerch.com/'
THEATER_URL = 'https://imasml-theater-wiki.gamerch.com/'
MSTAGE_URL = 'https://wikiwiki.jp/sidemstage/'
UA = 'Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.84 Safari/537.36' #Chrome
def find_imascg_events(agent)
result = []
type = 'シンデレラガールズ'
page = agent.get(IMAS_CG_URL)
elements = page.at('.user-area').search('.wiki-section-2')
elements.each do |elem|
elem.search('b').each do |b_e|
if b_e.nil? or !['開催期間', 'イベント期間'].include?(b_e.inner_text)
next
end
title = elem.at('h4').inner_text
if md = title.match(/「(.*)」/)
title = md[1]
end
term = b_e.next_sibling.inner_text.strip.split('〜')
if term.size < 2
next
end
result.push({:type => type, :title => title, :start => extend_time_parse(term[0]), :end => term[1] ? extend_time_parse(term[1]) : nil})
end
end
result
end
def find_slstage_events(agent)
result = []
type = 'スターライトステージ'
page = agent.get(SLSTAGE_URL)
elements = page.at('#js_async_main_column_text').search('.ui_anchor_container')
elements.each do |elem|
h4_elem = elem.at('h4')
if !h4_elem.nil?
ul_elem = elem.next_element.next_element.next_element
if !ul_elem.nil? and !ul_elem.at('li').nil?
ul_elem.search('li').each do |li|
if li.nil? or !li.inner_text.include?('開催期間')
next
end
title = h4_elem.inner_text
term = li.inner_text.strip.split("\t")[2].split('~')
if term.size < 2
next
end
result.push({:type => type, :title => title, :start => extend_time_parse(term[0]), :end => term[1] ? extend_time_parse(term[1]) : nil})
break
end
end
end
end
result
end
def find_theater_events(agent)
result = []
type = 'シアターデイズ'
page = agent.get(THEATER_URL)
elements = page.at('#js_async_main_column_text').search('.ui_anchor_container')
elements.each do |elem|
h4_elem = elem.at('h4')
if !h4_elem.nil?
ul_elem = elem.next_element.next_element.next_element
if !ul_elem.nil? and !ul_elem.at('li').nil?
ul_elem.search('li').each do |li|
if li.nil? or !li.inner_text.include?('開催期間')
next
end
title = h4_elem.inner_text
term = li.inner_text.strip.split(':')[1].split('~')
if term.size < 2
next
end
result.push({:type => type, :title => title, :start => extend_time_parse(term[0]), :end => term[1] ? extend_time_parse(term[1]) : nil})
end
end
end
end
result
end
def find_mstage_events(agent)
result = []
type = 'LIVE ON ST@GE!'
page = agent.get(MSTAGE_URL)
elements = page.at('#body').search('h3')
elements.each do |elem|
title_elem = elem.at('a').attribute('title')
ul_elem = elem.next.next.next.next
if ul_elem and !ul_elem.at('li').nil?
ul_elem.search('li').each do |li|
if li.nil? or (!li.inner_text.include?('開催期間') and !li.inner_text.include?('開催日時'))
next
end
title = title_elem.inner_text.sub('開催!', '')
term = li.inner_text.split('~')
if term.size < 2
next
end
result.push({:type => type, :title => title, :start => extend_time_parse(term[0]), :end => term[1] ? extend_time_parse(term[1]) : nil})
break
end
end
end
result
end
def extend_time_parse(str)
tmp = str.gsub(/([0-9]+)年([0-9]+)月([0-9]+)日(.*)/, '\1/\2/\3\4')
begin
return Time.parse(tmp)
rescue ArgumentError => e
p e
return nil
end
end
def get_summary_message(list)
now = Time.now
send_message = ''
list.each do |row|
if row[:end] and now.yday == row[:end].yday
send_message = send_message + row[:type] + '、' + row[:title] + ' ' + row[:end].strftime('%m月%d日 %H時%M分') + "まで\n"
end
end
{:status => send_message, :spoiler_text => '本日終了予定のイベントは以下になります。'}
end
def get_announcement_message(list)
# 2時間前から告知するよう判定
now = Time.now
after = now + 60 * 60 * 2.5
before = now + 60 * 60 * 0.5
send_message = ''
list.each do |row|
if row[:end] and before < row[:end] and after > row[:end]
send_message = send_message + row[:type] + '、' + row[:title] + 'の終了日時は' + row[:end].strftime('%m月%d日 %H時%M分') + "です。\n"
end
end
{:status => send_message.empty? ? '' : "#{send_message}お忘れにならないようにお気を付けくださいね!", :spoiler_text => ''}
end
def get_miraicha_message(list)
# ドリンクの飲み忘れ警告
events = [
'シンデレラロード',
'シンデレラキャラバン',
'LIVE Groove',
'LIVE Parade',
'LIVE PARTY',
'ミリコレ',
'THEATER SHOW TIME',
'MILLION LIVE WORKING',
'UNI-ON@IR',
]
now = Time.now
send_message = {:status => '', :spoiler_text => ''}
list.each do |row|
if events.any? {|e| row[:title].include?(e) }
if row[:start] < now and row[:end] and row[:end].year >= now.year and row[:end].yday >= now.yday
p row
return {:status => "(っ'ヮ'c)ウゥッヒョオアアァアアアァイェイL('ω')┘三└('ω')」イェイイェイL('ω')┘三└('ω')」イェイはよ当日ドリンク飲め言うたろイェイL('ω')┘三└('ω')」イェイ", :spoiler_text => '山崎はるかさんよりメッセージがあります'}
end
end
end
send_message
end
def get_message(list)
now = Time.now
if now.min >= 30
messages = get_miraicha_message(list)
elsif now.hour == 0 or now.hour == 12
messages = get_summary_message(list)
else
messages = get_announcement_message(list)
end
messages
end
def send_message(agent, messages)
if messages.empty? == false and messages[:status].empty? == false
p messages
body = {'status': messages[:status], 'visibility': 'public'}
if messages[:spoiler_text].empty? == false
body['spoiler_text'] = messages[:spoiler_text]
end
# toot
agent.request_headers = {'Authorization' => 'Bearer ' + ENV['CHIHIRO_BEARER']}
res = agent.post(ENV['MASTODON_HOST'] + 'api/v1/statuses', body)
p res.code
end
end
## main
# mechanize
agent = Mechanize.new
agent.user_agent = UA
agent.request_headers = {'accept-language' => 'ja, ja-JP', 'accept-encoding' => 'utf-8'}
events = []
# imas_cg
events.concat(find_imascg_events(agent))
# slstage
events.concat(find_slstage_events(agent))
# theater_days
events.concat(find_theater_events(agent))
# mstage
events.concat(find_mstage_events(agent))
p events
send_message(agent, get_message(events))
# -*- coding: utf-8 -*-
# imastodonにshinycolorsの日替わり特価品を通知する
# https://twitter.com/daily_rinze
#
# usage: push_imastodon_shiny_daily.rb
require 'rubygems'
require 'bundler'
Bundler.require(:default)
Dotenv.load
# CONST
TARGET_USERNAME = 'daily_rinze'
UA = 'Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.84 Safari/537.36' #Chrome
client = Twitter::REST::Client.new do |config|
config.consumer_key = ENV['TWITTER_CONSUMER_KEY']
config.consumer_secret = ENV['TWITTER_CONSUMER_SECRET']
config.access_token = ENV['TWITTER_ACCESS_TOKEN']
config.access_token_secret = ENV['TWITTER_ACCESS_TOKEN_SECRET']
end
now = DateTime.now
# 日替り商品をお知らせする杜野凛世Botから取得
body = ''
tweet_uri = ''
client.user_timeline(TARGET_USERNAME, { count: 5 } ).each do |timeline|
tweet = client.status(timeline.id)
created = DateTime.parse(tweet.created_at.to_s) + Rational(9, 24) #Asia/Tokyo
if now.day == created.day
if tweet.text.to_s.include?('本日の日替り商品')
body = tweet.text.to_s
tweet_uri = tweet.uri.to_s
end
else
break
end
end
if body.empty?
puts "本日の特価商品がありません。"
exit
end
if body.include?('おはようございます。')
body = body.sub('おはようございます。', '')
end
p now.to_s
if now.hour > 18
body = 'こんばんは、いかがお過ごしですか。' << body
elsif now.hour > 11
body = 'こんにちは、いかがお過ごしですか。' << body
else
body = 'おはようございます。' << body
end
p body
# imastodon
agent = Mechanize.new
agent.user_agent = UA
agent.request_headers = {'accept-language' => 'ja, ja-JP', 'accept-encoding' => 'utf-8'}
agent.request_headers = {'Authorization' => 'Bearer ' + ENV['CHIHIRO_BEARER']}
# toot
res = agent.post(ENV['MASTODON_HOST'] + 'api/v1/statuses', {
'status': body << "\n元ツイート: " << tweet_uri,
'spoiler_text': 'これより杜野凛世さんによる町内放送があります',
'visibility': 'public'
})
p res.code
# -*- coding: utf-8 -*-
# imastodonに当日のUsa_botがわからないわ単語を送信する
# https://imastodon.net/@Usa_bot
#
# usage: push_imastodon_what_report.rb
require 'rubygems'
require 'bundler'
Bundler.require(:default)
Dotenv.load
# CONST
TARGET_ACCOUNT_ID = '17061' #@Usa_bot
UA = 'Mozilla/5.0 (Windows NT 6.3; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.132 Safari/537.36' #Chrome
# imastodon
agent = Mechanize.new
agent.user_agent = UA
agent.request_headers = {'accept-language' => 'ja, ja-JP', 'accept-encoding' => 'utf-8'}
agent.request_headers = {'Authorization' => 'Bearer ' + ENV['CHIHIRO_BEARER']}
today = Time.now
max_id = -1
words = []
p today
# grave search
get_uri = ENV['MASTODON_HOST'] + 'api/v1/accounts/' + TARGET_ACCOUNT_ID + '/statuses'
get_params = {'limit': 40}
# MAX40件しかget出来ないのでループ
until max_id.nil? do
res = agent.get(get_uri, get_params)
JSON.parse(res.body).each {|status|
created_at = Time.parse(status['created_at'])
created_at.localtime("+09:00")
if today.day == created_at.day
content = status['content']
p created_at
# データベースにない単語検索
if content.include?('Usa_botデータベースには見つかりませんでした')
word = content[/【(.*?)】/, 1]
p word
words.push(word)
end
max_id = status['id']
get_params['max_id'] = max_id
end
if max_id != -1 and max_id != status['id']
max_id = nil
break
end
}
end
p words
# toot
res = agent.post(ENV['MASTODON_HOST'] + 'api/v1/statuses', {
'status': words.join(' ') << "\n\n(本日のウサちゃんロボの知らなかった単語です)\n\n#Usa_botわかんない",
'spoiler_text': '知らなかったキーワード ' << today.strftime('%Y%m%d'),
'visibility': 'public'
})
p res.code
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment