Skip to content

Instantly share code, notes, and snippets.

@FestivalBobcats
Created July 1, 2014 23:05
Show Gist options
  • Save FestivalBobcats/35587c736ded6d9c7a28 to your computer and use it in GitHub Desktop.
Save FestivalBobcats/35587c736ded6d9c7a28 to your computer and use it in GitHub Desktop.
Quinky (GroupMe haiku bot)
require 'json'
require 'typhoeus'
require 'ansi'
ACCESS_TOKEN = #
GROUP_ID = #
def register_bot(name, avatar_url=nil)
url = "https://api.groupme.com/v3/bots?token=#{ACCESS_TOKEN}"
body = {
bot: {
name: name,
group_id: GROUP_ID,
avatar_url: avatar_url
}
}.to_json
resp = Typhoeus.post(url, body: body)
JSON.parse(resp.body)['response']['bot']['bot_id']
end
def post_as_bot(bot_id, opts)
url = "https://api.groupme.com/v3/bots/post?token=#{ACCESS_TOKEN}"
body = {
bot_id: bot_id
}.merge(opts).to_json
Typhoeus.post(url, body: body)
end
def get_messages(size)
messages = []
last_msg_id = nil
while messages.size < size
print '.'.ansi(:magenta)
url = "https://api.groupme.com/v3/groups/#{GROUP_ID}/messages?token=#{ACCESS_TOKEN}"
args = [url]
args << {body: {before_id: last_msg_id}} if last_msg_id
resp = Typhoeus.get(*args)
msgs = JSON.parse(resp.body)['response']['messages']
last_msg_id = msgs[-1]['id']
messages += msgs.map {|m| m['text'] }
end
messages
end
def count_syllables(word)
word.downcase!
return 1 if word.length <= 3
word.sub!(/(?:[^laeiouy]es|ed|[^laeiouy]e)$/, '')
word.sub!(/^y/, '')
word.scan(/[aeiouy]{1,2}/).size
end
def get_most_recent_words
recent_msgs = get_messages(1_500)
recent_msgs.join(' ').split(/[\.\/ \n]+/i).select {|w| w[/[a-z]{2,}/i] }.reject {|w| w[/[^[a-zA-Z]]{3,}/] }.map do |word|
word.gsub(/(\W{2,}|[^a-zA-Z0-9]\z|\A[^a-zA-Z0-9])/, '').downcase
end
end
def make_gibberish_haiku
all_words = get_most_recent_words
word_syllable_count = all_words.reduce({}) do |hash, word|
hash[word] ||= count_syllables(word.dup)
hash
end
all_syl_counts = word_syllable_count.values
max_syl_per_word = all_syl_counts.select {|v| all_syl_counts.select {|vv| vv == v }.size > 3 }.max
words_used = []
lines = [5, 7, 5].map do |s|
word_syllables_this_line = []
loop do
print '.'.ansi(:green)
sum = word_syllables_this_line.inject(:+) || 0
ws = [(1..s).to_a.shuffle.first, max_syl_per_word].min
if sum + ws > s
next
# elsif sum + ws == s && word_syllables_this_line[-1] == 1 && ws == 1
# word_syllables_this_line << 2
# break
# elsif (s - (sum + ws)) == 1 # don't end with 1 syllable
#
# if ws == 1
# word_syllables_this_line.pop
# word_syllables_this_line << 2
#
# break
# else # just make the one syllable come first
# word_syllables_this_line << 1
# word_syllables_this_line << ws
# break
# end
#
# next
elsif sum + ws == s
word_syllables_this_line << ws
break
else # < s
word_syllables_this_line << ws
end
end
words = word_syllables_this_line.map do |ws|
begin
print '.'.ansi(:red)
word = word_syllable_count.to_a.shuffle.find {|k, v| v == ws }[0]
if words_used.select {|w| w == word }.size >= 1 \
|| words_used.last == word \
|| word.size == 1
raise "Retry"
end
words_used << word
word
rescue
retry
end
end
words.join(' ')
end
lines.join("\n")
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment