From 2febab1aced6aa5a930f88b244636b2554e2e3e8 Mon Sep 17 00:00:00 2001 From: SammySam Date: Mon, 22 Apr 2013 20:53:12 -0700 Subject: [PATCH 1/4] merging feature request app to master branch --- plugins/feature_request.rb | 281 +++++++++++++++++++++++++++++++++++++ steggybot.rb | 1 + 2 files changed, 282 insertions(+) create mode 100644 plugins/feature_request.rb diff --git a/plugins/feature_request.rb b/plugins/feature_request.rb new file mode 100644 index 0000000..b04f638 --- /dev/null +++ b/plugins/feature_request.rb @@ -0,0 +1,281 @@ +#todo style app that keeps track of features we wish to implement for steggybot + +require 'cinch' +require 'yaml' + +class FeatureRequest + include Cinch::Plugin + + # Adds your input as a feature request to steggybot. + # Works best if you give your feature request a :<description>. + # Example: !add task feature request: a todo style app that lists features + # and their progress + match /(add feature|add request) (.+)/i, method: :add_request + + # Replies with a list of already requested features. + # For a super lengthy list with all of the detail, type !info : + # If you want to use !info in your app, tell me and I'll change it to + # something else. + match /list/i, method: :print_requests + + # Replies with detailed information on each feature whose title or description + # match your query. + match /info (.+)/i, method: :print_info + + # Replies with specific information on each feature whose title/descr matches + # your query. + match /(status|progress) (?![=])(.+)/i, method: :search_tasks + match /(feature|description) (?![=])(.+)/i, method: :search_tasks + match /(who has claimed) (.+)/i, method: :search_tasks + + # Overwrites specific information on each feature whose title/descr matches + # your query. + # Your query should only match one feature request. + # Fix typos, update progress, or stake a claim. + match /(status =|progress =) (.+) for (.+)/i, method: :search_tasks + + match /(complete)( )(.+)/i, method: :search_tasks + match /(start)( )(.+)/i, method: :search_tasks + match /(change claim to) (.+) for (.+)/i, method: :search_tasks + match /(claim)( )(?!(?:to))(.+)/i, method: :search_tasks + + match /(feature =|request =|description =) (.+) for (.+)/i, method: :search_tasks + + # Please only use to remove troll or test feature requests. + # To remove, you must type the *entire* title+description, aka entire "task". + # If you complete a feature request, change its progress to "Completed" and + # it will be moved to the completed_features.yml. + match /remove (.+)/i, method: :remove_request + + + def initialize(*args) + super + @task_list = config[:task_list] + end + + def add_request(m, unused_message, task) + new_task = {:task => task, + :added_by => m.user.nick, + :created_at => Time.now, + :progress => "not started", + :updated_at => Time.now, + :claim => "no one"} + + old_tasks = get_tasks(@task_list) || [] + combined_tasks = old_tasks << new_task + + store combined_tasks + + m.reply "#{m.user.nick}: Request received and rendered ##{new_task}" + end + + + # Replies with a list of already requested features. + def print_requests(m) + tasks = get_tasks @task_list || [] + if tasks == [] + m.reply "No one has requested a feature yet." + else + m.reply "Listing requested features & their statuses below:" + tasks.each do |task| + m.reply "#{task[:task]} -- Progress: #{task[:progress];}" + end + end + end + + + # Replies with all information on each feature whose title or description + # match your query. + # Works best if you have a name for your feature request. + def print_info(m, title) + tasks = get_tasks @task_list + if tasks + tasks.each do |task| + if task[:task].include? title + m.reply "#{m.user.nick}: Info: #{task}" + end + end + end + end + + + # Please only use to remove mistakes. + # To mark a task completed, use !complete <task> + def remove_request(m, task_description) + tasks = get_tasks @task_list + if tasks + nothing_was_deleted = true + tasks.each do |task| + if task[:task] == task_description && task[:added_by] == m.user.nick + tasks.delete task + nothing_was_deleted = false + m.reply "#{m.user.nick}: Removed mistaken feature request " << + "#{task_description}" + end + end + if nothing_was_deleted + m.reply "#{m.user.nick}: Cannot remove '#{task_description}' because "<< + "it is not the full title/description of an added feature request " << + "or you are not the one who added the feature request initially." + end + + end + + store tasks + end + + + #-------------------------------------------------------------------------------- + # Protected + #-------------------------------------------------------------------------------- + + protected + + def store(tasks) + output = File.new(@task_list, 'w') + output.puts YAML.dump(tasks) + output.close + + end + + def get_tasks(file) + output = File.new(file, 'r') + tasks = YAML.load(output.read) + output.close + + tasks + end + + + # Walks through list searching for query matches. + # Replies with success_message for each query matched. + # success_message is a string stored in a proc for lazy evaluation. + # If you change the variable 'task,' you will need to change the strings too. + # Executes code block for each query matched (e.g. claim a task) + # If no matches found, replies with no matches found message. + def search_tasks(m, message, new_data = nil, query) + + tasks = get_tasks @task_list + if tasks + nothing_was_found = true + tasks.each do |task| + if task[:task].include? query + nothing_was_found = false + if new_data # checking if message is a setter + task = try_setting(m, message, task, new_data) + else # message is a getter + get_data(m, message, task) + end + end + end + store tasks + if nothing_was_found + m.reply "#{m.user.nick}: No requests found that match your query #{query}." + end + end + end + + + def try_setting(m, message, task, new_data) + if claimant(m, task) || (message == "claim" && claim_empty?(m, task)) + task = change_data(m, message, task, new_data) + m.reply success_message(m, message, task) + else + m.reply failure_message(m, message, task) + end + task + end + + def get_data(m, message, task) + m.reply success_message(m, message, task) + end + + def success_message(m, message, task) + case message + when /(status =|progress =)/i + "#{m.user.nick}: Progress successfully changed to #{task[:progress]} " << + "for #{task[:task]}." + + when /(status|progress)/i + "#{m.user.nick}: Progress: #{task[:progress]} -- #{task[:task]}" + + when /(feature =|request =|description =)/i + "#{m.user.nick}: Successfully changed task to #{task[:task]}." + + when /(feature|description)/i + "#{m.user.nick}: #{task[:task]}" + + when /(who has claimed)/i + "#{m.user.nick}: #{task[:claim]} has claimed #{task[:task]}" + + when /(change claim to)/i + "#{m.user.nick}: You have successfully given your claim to" << + " #{task[:claim]} for #{task[:task]}" + + when /(claim)/i + "#{m.user.nick}: You have successfully claimed #{task[:task]}" + + when /(start)/i + "#{m.user.nick}: I'm so glad you're starting to work on #{task[:task]}!" + + when /(complete)/i + "#{m.user.nick}: Congratulations on completing #{task[:task]}!!!" + end + end + + def failure_message(m, message, task) + case message + when /(claim)/i + "#{m.user.nick}: #{task[:claim]} has first" << + " dibs on #{task[:task]}. Please sort it with them." + + else + "#{m.user.nick}: Only the claimant #{task[:claim]} may update #{task[:task]}." + end + end + + + def claimant(m, task) + task[:claim] == m.user.nick + end + + def claim_empty?(m, task) + task[:claim] == "no one" + end + + # Check claimant before calling change_data + def change_data(m, message, task, new_data = nil) + case message + when /(status =|progress =)/i + task[:progress] = new_data + task[:updated_at] = Time.now + task + + when /(feature =|request =|description =)/i + task[:task] = new_data + task + + when /(change claim to)/i + task[:claim] = new_data + task + + when /(claim)/i + task[:claim] = m.user.nick + task + + when /(start)/i + task[:progress] = "begun" + task[:updated_at] = Time.now + task + + when /(complete)/i + task[:progress] = "completed" + task[:updated_at] = Time.now + task + + end + end + + + +end \ No newline at end of file diff --git a/steggybot.rb b/steggybot.rb index 8e70713..9963aa7 100644 --- a/steggybot.rb +++ b/steggybot.rb @@ -25,6 +25,7 @@ c.plugins.options[Pazudora] = { :pddata => "db/pddata.yml" } + } end end From f8fca2f0008621f08481c08478690eebaa8d50ce Mon Sep 17 00:00:00 2001 From: SammySam <arin.skysong@gmail.com> Date: Mon, 22 Apr 2013 20:54:42 -0700 Subject: [PATCH 2/4] added avalon --- .gitignore | 5 +- db/identities.yml | 120 +++++++++++++++-------------- plugins/avalon/spec/avalon_spec.rb | 19 +++++ steggybot.rb | 8 +- tmp/scratch | 82 ++++++++++++++++++++ 5 files changed, 172 insertions(+), 62 deletions(-) create mode 100644 plugins/avalon/spec/avalon_spec.rb create mode 100644 tmp/scratch diff --git a/.gitignore b/.gitignore index 3273337..c8acfef 100644 --- a/.gitignore +++ b/.gitignore @@ -1,7 +1,4 @@ -# Ignore data files -db -*.yml -*.json + # Ignore vim swap files *.sw[a-p] diff --git a/db/identities.yml b/db/identities.yml index cf4a514..8b97982 100644 --- a/db/identities.yml +++ b/db/identities.yml @@ -2,214 +2,215 @@ sederam: :name: a follower :added_by: whunt - :updated_at: !ruby/object:DateTime 2013-02-14 01:58:51.598510113 +00:00 + :updated_at: !ruby/object:DateTime 2013-02-13 17:58:51.598510113 -08:00 songe: :name: angie :added_by: czhang stufflebear: :name: mary :added_by: steggy_meeting - :updated_at: !ruby/object:DateTime 2013-02-11 05:48:32.624819340 +00:00 + :updated_at: !ruby/object:DateTime 2013-02-10 21:48:32.624819340 -08:00 john_galt: - :name: '"Randian Hero"' + :name: ! '"Randian Hero"' :added_by: steggy_meeting - :updated_at: !ruby/object:DateTime 2013-02-11 18:24:33.604853946 +00:00 + :updated_at: !ruby/object:DateTime 2013-02-11 10:24:33.604853946 -08:00 bird: - :name: '"The word"' + :name: ! '"The word"' :added_by: steggy - :updated_at: !ruby/object:DateTime 2013-02-11 19:30:42.143053785 +00:00 + :updated_at: !ruby/object:DateTime 2013-02-11 11:30:42.143053785 -08:00 wsong: :name: wayne :added_by: wsong - :updated_at: !ruby/object:DateTime 2013-02-11 19:37:58.404597566 +00:00 + :updated_at: !ruby/object:DateTime 2013-02-11 11:37:58.404597566 -08:00 nfair: :name: a_man_of_mystery :added_by: nfair - :updated_at: !ruby/object:DateTime 2013-02-19 19:16:54.458409521 +00:00 + :updated_at: !ruby/object:DateTime 2013-02-19 11:16:54.458409521 -08:00 skimbrel: - :name: '"corrected"' + :name: ! '"corrected"' :added_by: skimbrel - :updated_at: !ruby/object:DateTime 2013-02-13 00:30:54.424832899 +00:00 + :updated_at: !ruby/object:DateTime 2013-02-12 16:30:54.424832899 -08:00 steggy: :name: the greatest :added_by: steggy - :updated_at: !ruby/object:DateTime 2013-02-11 19:48:54.030991226 +00:00 + :updated_at: !ruby/object:DateTime 2013-02-11 11:48:54.030991226 -08:00 whunt: :name: neckbeard :added_by: jknew - :updated_at: !ruby/object:DateTime 2013-02-14 19:01:39.851819168 +00:00 + :updated_at: !ruby/object:DateTime 2013-02-14 11:01:39.851819168 -08:00 heidi: :name: a dragon boob :added_by: whunt - :updated_at: !ruby/object:DateTime 2013-02-11 19:56:20.760960197 +00:00 + :updated_at: !ruby/object:DateTime 2013-02-11 11:56:20.760960197 -08:00 virulently: - :name: '"Asterisms opinion against the use of drone strikes"' + :name: ! '"Asterisms opinion against the use of drone strikes"' :added_by: steggy_meeting - :updated_at: !ruby/object:DateTime 2013-02-13 00:28:00.678122180 +00:00 + :updated_at: !ruby/object:DateTime 2013-02-12 16:28:00.678122180 -08:00 hail_spacecake: :name: Shuflin every day :added_by: whunt - :updated_at: !ruby/object:DateTime 2013-03-15 20:55:41.653387200 +00:00 + :updated_at: !ruby/object:DateTime 2013-03-15 13:55:41.653387200 -07:00 steggy_meeting: - :name: '"steggy, but at a meeting"' + :name: ! '"steggy, but at a meeting"' :added_by: steggy_meeting - :updated_at: !ruby/object:DateTime 2013-02-13 00:48:33.909658534 +00:00 + :updated_at: !ruby/object:DateTime 2013-02-12 16:48:33.909658534 -08:00 jag: :name: josh silver :added_by: steggy - :updated_at: !ruby/object:DateTime 2013-02-13 21:14:27.392581259 +00:00 + :updated_at: !ruby/object:DateTime 2013-02-13 13:14:27.392581259 -08:00 heidi_sux: :name: she suxx :added_by: heidi_sux - :updated_at: !ruby/object:DateTime 2013-02-14 00:40:51.057327930 +00:00 + :updated_at: !ruby/object:DateTime 2013-02-13 16:40:51.057327930 -08:00 jknew: :name: Jacob :added_by: jknew - :updated_at: !ruby/object:DateTime 2013-02-14 19:04:50.003894840 +00:00 + :updated_at: !ruby/object:DateTime 2013-02-14 11:04:50.003894840 -08:00 asterism: :name: victor :added_by: steggy - :updated_at: !ruby/object:DateTime 2013-02-14 18:57:17.276003440 +00:00 + :updated_at: !ruby/object:DateTime 2013-02-14 10:57:17.276003440 -08:00 czhang: :name: your majesty :added_by: czhang - :updated_at: !ruby/object:DateTime 2013-02-14 19:04:02.404956045 +00:00 + :updated_at: !ruby/object:DateTime 2013-02-14 11:04:02.404956045 -08:00 whunt1: :name: a ghost of the shitty ApartmentList internet :added_by: whunt1 - :updated_at: !ruby/object:DateTime 2013-02-15 00:09:58.558940282 +00:00 + :updated_at: !ruby/object:DateTime 2013-02-14 16:09:58.558940282 -08:00 songe1: :name: the ghost of angies past :added_by: steggy - :updated_at: !ruby/object:DateTime 2013-02-18 20:28:44.120463795 +00:00 + :updated_at: !ruby/object:DateTime 2013-02-18 12:28:44.120463795 -08:00 tag: :name: nfair> tag -> scott the other engineer on the Pigeon team with me :added_by: czhang - :updated_at: !ruby/object:DateTime 2013-02-21 18:20:52.773062929 +00:00 + :updated_at: !ruby/object:DateTime 2013-02-21 10:20:52.773062929 -08:00 steggybot: :name: the guy who throws gang signs out the window, ya bish :added_by: whunt - :updated_at: !ruby/object:DateTime 2013-02-19 19:07:41.047552113 +00:00 + :updated_at: !ruby/object:DateTime 2013-02-19 11:07:41.047552113 -08:00 tullidil: :name: Neil Strauss :added_by: tullidil - :updated_at: !ruby/object:DateTime 2013-03-12 19:26:08.684971632 +00:00 + :updated_at: !ruby/object:DateTime 2013-03-12 12:26:08.684971632 -07:00 sushis: :name: heidi :added_by: wsong - :updated_at: !ruby/object:DateTime 2013-03-01 18:12:02.020550975 +00:00 + :updated_at: !ruby/object:DateTime 2013-03-01 10:12:02.020550975 -08:00 kiwis: :name: heidi :added_by: wsong - :updated_at: !ruby/object:DateTime 2013-03-02 00:04:58.759563332 +00:00 + :updated_at: !ruby/object:DateTime 2013-03-01 16:04:58.759563332 -08:00 angie: :name: actually little chris. Do not be fooled :added_by: whunt - :updated_at: !ruby/object:DateTime 2013-03-02 01:11:31.928665846 +00:00 + :updated_at: !ruby/object:DateTime 2013-03-01 17:11:31.928665846 -08:00 everyone: :name: a feature that has not been implemented yet :added_by: whunt - :updated_at: !ruby/object:DateTime 2013-03-02 01:13:47.443978078 +00:00 + :updated_at: !ruby/object:DateTime 2013-03-01 17:13:47.443978078 -08:00 mimblewhimble: :name: Luke :added_by: angie - :updated_at: !ruby/object:DateTime 2013-03-02 01:51:02.017336670 +00:00 + :updated_at: !ruby/object:DateTime 2013-03-01 17:51:02.017336670 -08:00 mcint: :name: loren :added_by: wsong - :updated_at: !ruby/object:DateTime 2013-03-04 17:29:39.286906971 +00:00 + :updated_at: !ruby/object:DateTime 2013-03-04 09:29:39.286906971 -08:00 acanyon: :name: superwoman :added_by: acanyon - :updated_at: !ruby/object:DateTime 2013-03-07 00:21:40.881123186 +00:00 + :updated_at: !ruby/object:DateTime 2013-03-06 16:21:40.881123186 -08:00 ians: :name: based god :added_by: ians - :updated_at: !ruby/object:DateTime 2013-03-05 23:50:01.823814647 +00:00 + :updated_at: !ruby/object:DateTime 2013-03-05 15:50:01.823814647 -08:00 goteampeach: :name: angela (ed's gf) :added_by: czhang - :updated_at: !ruby/object:DateTime 2013-03-07 22:00:07.967314786 +00:00 + :updated_at: !ruby/object:DateTime 2013-03-07 14:00:07.967314786 -08:00 jungziege: :name: black ian :added_by: czhang - :updated_at: !ruby/object:DateTime 2013-03-06 19:26:21.536887425 +00:00 + :updated_at: !ruby/object:DateTime 2013-03-06 11:26:21.536887425 -08:00 blackian: :name: black ian :added_by: blackian - :updated_at: !ruby/object:DateTime 2013-03-06 19:28:30.885750926 +00:00 + :updated_at: !ruby/object:DateTime 2013-03-06 11:28:30.885750926 -08:00 sarmiento: :name: not magnum :added_by: blackian - :updated_at: !ruby/object:DateTime 2013-03-06 19:49:16.456633901 +00:00 + :updated_at: !ruby/object:DateTime 2013-03-06 11:49:16.456633901 -08:00 davis: :name: white ian :added_by: czhang - :updated_at: !ruby/object:DateTime 2013-03-06 19:50:36.673238502 +00:00 + :updated_at: !ruby/object:DateTime 2013-03-06 11:50:36.673238502 -08:00 laughinghan: :name: mordred :added_by: czhang - :updated_at: !ruby/object:DateTime 2013-03-07 00:31:10.486539472 +00:00 + :updated_at: !ruby/object:DateTime 2013-03-06 16:31:10.486539472 -08:00 laughinhan: :name: mordred :added_by: shijing - :updated_at: !ruby/object:DateTime 2013-03-07 00:31:11.149988951 +00:00 + :updated_at: !ruby/object:DateTime 2013-03-06 16:31:11.149988951 -08:00 adama: :name: a cylon :added_by: wsong - :updated_at: !ruby/object:DateTime 2013-03-07 00:31:13.907373114 +00:00 + :updated_at: !ruby/object:DateTime 2013-03-06 16:31:13.907373114 -08:00 bordicon: :name: is prepared to 'go robot' for optimus prime :added_by: sean___ - :updated_at: !ruby/object:DateTime 2013-03-27 22:40:12.558413526 +00:00 + :updated_at: !ruby/object:DateTime 2013-03-27 15:40:12.558413526 -07:00 gaius: :name: fucking a cylon :added_by: czhang - :updated_at: !ruby/object:DateTime 2013-03-07 00:32:46.425318958 +00:00 + :updated_at: !ruby/object:DateTime 2013-03-06 16:32:46.425318958 -08:00 yo_momma: :name: a big bitch :added_by: skimbrel - :updated_at: !ruby/object:DateTime 2013-03-09 00:15:37.610585195 +00:00 + :updated_at: !ruby/object:DateTime 2013-03-08 16:15:37.610585195 -08:00 infair: :name: more than fair :added_by: infair - :updated_at: !ruby/object:DateTime 2013-03-09 00:18:26.969788051 +00:00 + :updated_at: !ruby/object:DateTime 2013-03-08 16:18:26.969788051 -08:00 the_real_slim_shady: :name: whoever is standing :added_by: riderofrohan0 - :updated_at: !ruby/object:DateTime 2013-03-09 00:19:00.245318676 +00:00 + :updated_at: !ruby/object:DateTime 2013-03-08 16:19:00.245318676 -08:00 olivm: :name: loren :added_by: wsong - :updated_at: !ruby/object:DateTime 2013-03-13 19:09:50.623634493 +00:00 + :updated_at: !ruby/object:DateTime 2013-03-13 12:09:50.623634493 -07:00 jocob: :name: biotic kanye :added_by: jlhawn_ - :updated_at: !ruby/object:DateTime 2013-03-15 20:56:29.875151841 +00:00 + :updated_at: !ruby/object:DateTime 2013-03-15 13:56:29.875151841 -07:00 jayferd: :name: jay :added_by: jayferd - :updated_at: !ruby/object:DateTime 2013-03-27 22:39:36.016134004 +00:00 + :updated_at: !ruby/object:DateTime 2013-03-27 15:39:36.016134004 -07:00 angie2: :name: a catalyst for steggybot feature arguments :added_by: whunt - :updated_at: !ruby/object:DateTime 2013-03-18 20:26:00.450223622 +00:00 + :updated_at: !ruby/object:DateTime 2013-03-18 13:26:00.450223622 -07:00 foo: :name: a sad test subject forgotten in the dust of the thousands of "fast-paced" start-ups :added_by: whunt - :updated_at: !ruby/object:DateTime 2013-03-18 20:34:01.968589435 +00:00 + :updated_at: !ruby/object:DateTime 2013-03-18 13:34:01.968589435 -07:00 doves: :name: a wild sam :added_by: heidi - :updated_at: !ruby/object:DateTime 2013-03-22 23:25:05.892580611 +00:00 + :updated_at: !ruby/object:DateTime 2013-03-22 16:25:05.892580611 -07:00 tobefree: :name: hehe :added_by: tobefree - :updated_at: !ruby/object:DateTime 2013-03-27 18:35:08.727808982 +00:00 + :updated_at: !ruby/object:DateTime 2013-03-27 11:35:08.727808982 -07:00 nooblet: :name: WHUNT :added_by: czhang +<<<<<<< HEAD:db/identities.yml :updated_at: !ruby/object:DateTime 2013-03-27 18:34:49.580874666 +00:00 judge_dredd: :name: the law @@ -219,3 +220,10 @@ thundara: :name: Nader (Loren's friend) :added_by: wsong :updated_at: !ruby/object:DateTime 2013-03-29 20:47:05.147218908 +00:00 +======= + :updated_at: !ruby/object:DateTime 2013-03-27 11:34:49.580874666 -07:00 +sugis: + :name: steven + :added_by: dovestep + :updated_at: !ruby/object:DateTime 2013-04-04 15:01:12.371347000 -07:00 +>>>>>>> feature-requests:identities.yml diff --git a/plugins/avalon/spec/avalon_spec.rb b/plugins/avalon/spec/avalon_spec.rb new file mode 100644 index 0000000..88341ee --- /dev/null +++ b/plugins/avalon/spec/avalon_spec.rb @@ -0,0 +1,19 @@ +require 'spec_helper' +require File.dirname(__FILE__) + "/../avalon.rb" + +describe Avalon do + before(:all) do + @avalon = Avalon.new(new_test_bot) + end + + it 'starts a game' do + @message = mock :user => (mock :nick => 'doveStep'), + :channel => (mock :name => 'csuavalon') + + @message.should_receive :reply do |reply| + reply.should include('Players, join in!') + end + + @avalon.dispatch(@message, 'start') + end +end diff --git a/steggybot.rb b/steggybot.rb index 9963aa7..b65a288 100644 --- a/steggybot.rb +++ b/steggybot.rb @@ -7,9 +7,11 @@ c.server = "irc.freenode.net" c.nick = "steggybot" c.channels = ["#csua", "#csuatest", "##csua"] - c.plugins.plugins = [Google, UrbanDictionary, TitleGrabber, Quotes, Pokedex, Youtube, - YaBish, Roll, WhoAreThesePeople, PlusPlus, Pazudora] + c.plugins.plugins = [Google, UrbanDictionary, TitleGrabber, Quotes, Pokedex, + Youtube, YaBish, Roll, WhoAreThesePeople, PlusPlus, + Pazudora, FeatureRequest] c.plugins.plugins << Help + c.plugins.options[Quotes] = { :quotes_file => "db/quotes.yml" } @@ -25,6 +27,8 @@ c.plugins.options[Pazudora] = { :pddata => "db/pddata.yml" } + c.plugins.options[FeatureRequest] = { + :task_list => "feature_requests.yml" } end end diff --git a/tmp/scratch b/tmp/scratch new file mode 100644 index 0000000..32d5924 --- /dev/null +++ b/tmp/scratch @@ -0,0 +1,82 @@ +#### + +!avalon status +=> mode: waiting for votes + .... +!avalon who + Current players: <nick>, <nick>... + Current characters: merlin, assassin, ... +!avalon log + + +#### + + +!avalon start [characters...] +!avalon start +=> starting an avalon game + + +# each person +!avalon in +=> 7 players: using merlin, assasin, ... + +!avalon use merl +!avalon use + +!avalon go +=> Darkness falls over camelot. Check your PM for ... + +(pm to each player) +=> You are Merlin (good). Assassin, Morgana, and Oberon are (in some order) jayferd, doveStep, and laughinghan. + +=> laughinghan is King. The hammer is doveStep. +=> King, please propose a team of <n> knights to go a-questing. + +(from han) +!avalon propose <nick> <nick> <nick> + => wrong number of knights +=> laughinghan proposes <nick>, <nick>, and <nick>. Knights of the round table, what say ye? (PM the bot with "yea" or "nay") + +(wait for all votes) +=> <nick> has voted. Still waiting for [<nick>...] + +=> The votes are in! The team is [accepted|rejected] + jayferd: yea + doveStep: nay + laughinghan: yea + ... + +rejected: The team is rejected! +(next king, go to <nick> is King...) + +accepted: The team is accepted! [team members], please PM the bot with "success" or "failure" + +=> <nick> has voted. +=> <nick> has voted. +=> <nick> has voted. +=> The chalices are in. The mission [failed|succeeded]. + + + +"#csua": + players: + - <nick>: merlin + - <nick>: morgana + - ... + features: + - lady (#use, #unuse) + - mordred + - morberon + - merlin + king: <nick> + hammer: <nick> + log: + - success: <bool> + team: <nick>, <nick>... + chalices: true, true, false + - ... + mode: voting + votes: [nick: bool] + chalices: [nick: bool ] + team: [<nick>] From a4c0a11afe02a6682ad15b9a36eee538fbd1bbb0 Mon Sep 17 00:00:00 2001 From: SammySam <arin.skysong@gmail.com> Date: Mon, 22 Apr 2013 21:36:57 -0700 Subject: [PATCH 3/4] cleaning up feature branch --- plugins/google.rb | 29 ----- plugins/pazudora.rb | 219 -------------------------------- plugins/plusplus.rb | 92 -------------- plugins/pokedex.rb | 42 ------ plugins/quotes.rb | 82 ------------ plugins/roll.rb | 17 --- plugins/title_grabber.rb | 26 ---- plugins/urban_dict.rb | 22 ---- plugins/url_shorten.rb | 23 ---- plugins/who_are_these_people.rb | 78 ------------ plugins/youtube.rb | 28 ---- 11 files changed, 658 deletions(-) delete mode 100644 plugins/google.rb delete mode 100644 plugins/pazudora.rb delete mode 100644 plugins/plusplus.rb delete mode 100644 plugins/pokedex.rb delete mode 100644 plugins/quotes.rb delete mode 100644 plugins/roll.rb delete mode 100644 plugins/title_grabber.rb delete mode 100644 plugins/urban_dict.rb delete mode 100644 plugins/url_shorten.rb delete mode 100644 plugins/who_are_these_people.rb delete mode 100644 plugins/youtube.rb diff --git a/plugins/google.rb b/plugins/google.rb deleted file mode 100644 index b9626dc..0000000 --- a/plugins/google.rb +++ /dev/null @@ -1,29 +0,0 @@ -require 'cinch' -require 'open-uri' -require 'nokogiri' -require 'cgi' - -class Google - include Cinch::Plugin - match /google (.+)/ - @help_hash = { - :google => "Usage: !google THING -Example !google Syria -Returns the first google hit for THING" - } - def search(query) - url = "http://www.google.com/search?q=#{CGI.escape(query)}" - res = Nokogiri::HTML(open(url)).at("h3.r") - - title = res.text - link = res.at('a')[:href] - desc = res.at("./following::div").children.first.text - CGI.unescape_html "#{title} - #{desc} (#{link})" - rescue - "No results found" - end - - def execute(m, query) - m.reply(search(query)) - end -end diff --git a/plugins/pazudora.rb b/plugins/pazudora.rb deleted file mode 100644 index 484ef0f..0000000 --- a/plugins/pazudora.rb +++ /dev/null @@ -1,219 +0,0 @@ -require 'cinch' -require 'nokogiri' - -class Pazudora - include Cinch::Plugin - - PUZZLEMON_BASE_URL = "http://www.puzzledragonx.com/en/" - - match /pazudora ([\w-]+) *(.+)*/i, method: :pazudora - match /stupidpuzzledragonbullshit ([\w-]+) *(.+)*/i, method: :pazudora - match /stupiddragonpuzzlebullshit ([\w-]+) *(.+)*/i, method: :pazudora - match /p&d ([\w-]+) *(.+)*/i, method: :pazudora - match /pad ([\w-]+) *(.+)*/i, method: :pazudora - match /puzzlemon ([\w-]+) *(.+)*/i, method: :pazudora - match /puzzledex (.+)*/i, method: :pazudora_lookup - - @help_string = <<-eos - Puzzle and Dragons (on iOS and Android) utility functions. Mostly collects friend codes and tracks the daily dungeon. - Its commands are aliased to pazudora, p&d, pad, and puzzlemon. - eos - @help_hash = { - :add => "Usage: !puzzlemon add NAME CODE -Example: !puzzlemon add steggybot 123,456,789 -Adds user's code to the list of friend codes", - :group => "Usage: !puzzlemon group NAME -Example !puzzlemon group steggybot -Returns the daily dungeon group that the user belongs to.", - :dailies => "Usage: !puzzlemon dailies -Example !puzzlemon dailies -Returns the times (and type) of today's daily dungeons, split by group. If called by -a registered player, also reminds them of their group id.", - :lookup => "Usage: !(puzzlemon lookup|puzzledex) (NAME|ID) -Example !puzzlemon lookup horus, !puzzledex 603 -Returns a description of the puzzlemon. If none is found, returns a pseudorandom (hashed) one.", - :list => "Usage: !puzzlemon list -Example !puzzlemon list -Returns a list of everyone's friends codes." - } - - def initialize(*args) - super - @pddata = config[:pddata] - end - - #Any public method named pazudora_[something] is external and - #can be accessed by the user using the construction "!puzzlemon something [args]". - def pazudora (m, cmd, args) - subr = cmd.downcase.chomp - begin - if args - self.send("pazudora_#{subr}", m, args) - else - self.send("pazudora_#{subr}", m, "") - end - rescue NoMethodError - puts "Pazudora called with invalid command #{subr}." - end - end - - def pazudora_add (m, args) - pargs = args.split - username = pargs[0] - friend_code = pargs[1] - - # add it to the list - friend_codes = load_data || {} - if friend_code =~ /[0-9]{9}/ - friend_code = friend_code.reverse.gsub(/(\d{3})(?=\d)/, '\\1,').reverse - end - if friend_codes[username.downcase] && (friend_codes[username.downcase][:added_by] == username.downcase) - if m.user.nick.downcase == username.downcase - friend_codes[username.downcase] = {:friend_code => friend_code, :added_by => m.user.nick.downcase, :updated_at => DateTime.now} - else - m.reply "#{m.user.nick}: Can't override a user's self-definition." - return - end - else - friend_codes[username.downcase] = {:friend_code => friend_code, :added_by => m.user.nick.downcase, :updated_at => DateTime.now} - end - # write it to the file - output = File.new(@pddata, 'w') - output.puts YAML.dump(friend_codes) - output.close - - m.reply "#{m.user.nick}: #{mangle(username)} successfully added as '#{friend_code}'." - end - - def pazudora_remove(m, args) - pargs = args.split - username = pargs[0] - friend_codes = load_data || {} - - if ! friend_codes[username] - m.reply "#{m.user.nick}: #{mangle(username)} not in friend code list." - return - end - - if (m.user.nick.downcase == username.downcase) || (m.user.nick.downcase == friend_codes[username][:added_by]) - friend_codes.delete(username) - # write it to the file - output = File.new(@pddata, 'w') - output.puts YAML.dump(friend_codes) - output.close - - m.reply "#{m.user.nick}: #{mangle(username)} removed from friend code list." - else - m.reply "#{m.user.nick}: Only the identity creator or subject can remove a friend code from the list." - end - end - - def pazudora_who(m,args) - pargs = args.split - username = pargs[0] - if load_data[username.downcase] - m.reply "#{m.user.nick}: #{mangle(username)}'s friend code is #{load_data[username.downcase][:friend_code]}" - end - end - - def pazudora_list(m,args) - friend_codes = load_data || {} - friend_codes.keys.each_slice(3).with_index { |users, i| - r = i == 0 ? "#{m.user.nick}: " : "" - users.each{ |user| r=r+"#{mangle(user)}:#{friend_codes[user][:friend_code]} " } - m.reply r - } - end - - def pazudora_group(m,args) - pargs = args.split - username = pargs[0] - if load_data[username.downcase] - friend_code = load_data[username.downcase][:friend_code] - group = (Integer(friend_code.split(",")[0][2]) % 5 + 65).chr - m.reply "#{m.user.nick}: #{mangle(username)}'s group is #{group}" - else - m.reply "#{m.user.nick}: #{mangle(username)}'s friend code is not listed. Please use the add command to add it." - end - end - - def pazudora_dailies(m, args) - daily_url = PUZZLEMON_BASE_URL + "option.asp?utc=-8" - - username = args.split[0] || m.user.nick - friend_code = load_data[username.downcase][:friend_code] rescue nil - group_num = friend_code ? group_number_from_friend_code(friend_code) : nil - - unless @daily_timestamp == Time.now.strftime("%m-%d-%y") - @daily_page = nil - @daily_timestamp = Time.now.strftime("%m-%d-%y") - end - - @daily_page ||= Nokogiri::HTML(open(daily_url)) - event_data = @daily_page.css(".event3") - event_rewards = @daily_page.css(".limiteddragon") - - rewards = parse_daily_dungeon_rewards(event_rewards) - m.reply "Dungeons today are: #{rewards.join(', ')}" - - (0..4).each do |i| - m.reply "Group #{(i + 65).chr}: #{event_data[i].text}, #{event_data[i + 5].text}, #{event_data[i + 10].text}" - end - - if group_num - m.reply "User #{username} is in group #{(group_num + 65).chr}" - end - end - - def pazudora_lookup(m, args) - identifier = args - info = get_puzzlemon_info(URI.encode(identifier)) - - #Bypass puzzledragonx's "default to meteor dragon if you can't find the puzzlemon" mechanism to - #get a pseudorandom puzzlemon (up to the max currently released puzzlemon) instead. - meteor_dragon_id = "211" - highest_puzzledex_id = 603 - - if info.css(".name").children.first.text == "Meteor Volcano Dragon" && !(identifier.start_with?("Meteor") || identifier == meteor_dragon_id) - num = (identifier.hash % highest_puzzledex_id) + 1 - info = get_puzzlemon_info(URI.encode(num.to_s)) - end - - desc = info.css("meta [name=description]").first.attributes["content"].text - desc.gsub!(/&/, "&") - m.reply desc - end - - protected - - def mangle(s) - s.chop + "." + s[-1] - end - - def load_data - datafile = File.new(@pddata, 'r') - friend_codes = YAML.load(datafile.read) - datafile.close - return friend_codes - end - - def group_number_from_friend_code(friend_code) - return Integer(friend_code.split(",")[0][2]) % 5 - end - - def parse_daily_dungeon_rewards(rewards) - puzzlemon_numbers = [ - rewards[0].children.first.attributes["src"].value.match(/thumbnail\/(\d+).png/)[1], - rewards[5].children.first.attributes["src"].value.match(/thumbnail\/(\d+).png/)[1], - rewards[10].children.first.attributes["src"].value.match(/thumbnail\/(\d+).png/)[1]] - - puzzlemon_numbers.map{|x| - get_puzzlemon_info(x).css(".name").children.first.text rescue "Unrecognized Name" } - end - - def get_puzzlemon_info(name_or_number) - search_url = PUZZLEMON_BASE_URL + "monster.asp?n=#{name_or_number}" - puzzlemon_info = Nokogiri::HTML(open(search_url)) - end -end - diff --git a/plugins/plusplus.rb b/plugins/plusplus.rb deleted file mode 100644 index c6b0a70..0000000 --- a/plugins/plusplus.rb +++ /dev/null @@ -1,92 +0,0 @@ -require 'cinch' -require 'yaml' - -class PlusPlus - include Cinch::Plugin - @help_hash = { - :person => "Usage: !person NAME -Example: !person steggybot -Returns the plusplus values from all other users about user NAME", - :persons_feelings => "Usage: !persons_feelings NAME -Example !persons_feelings steggybot -Returns the a hash of the people that that NAME has plusplus'ed, and the number of times." - } - match /karma (.*)/i, method: :lookup_sum - listen_to :channel - match /persons_feelings (.*)/i, method: :lookup_feelings - match /person (.*)/i, method: :lookup - - # lookup looks up someone's name and replies with their karma in the - # form: - # czhang's karma: {"czhan.g"=>1}, {"skimbre.l"=>1} - def lookup(m, name) - values = plusplus_file - # Don't want to always nameping people, so we mangle the name a little - values = values.keys.map { |key| {mangle_string(key) => values[key][name]} if values[key][name] }.compact - result = values.empty? ? ["no results"] : values - result = "#{name}'s karma: " + result.join(", ") - m.reply(result) - end - - # This looks up someone's karma and replies with the total sum in - # the form: - # whunt: 9001 - def lookup_sum(m, name) - values = plusplus_file - values = values.keys.map { |key| {mangle_string(key) => values[key][name]} if values[key][name] }.compact - if values.empty? - m.reply("no results for #{name}") - else - total = values.map(&:values).flatten.inject(:+) - m.reply("#{name}'s total karma: #{total}") - end - end - - # This looks up the people that someone has given karma to. It - # replies in the form: - # {"skimbre.l"=>-1, "czhan.g" => 1} - def lookup_feelings(m, name) - values = plusplus_file - base_hash = (values.keys.include? name) ? values[name] : "no results" - result = base_hash.keys.map {|key| [mangle_string(key), base_hash[key]] } - result = Hash[result] - m.reply(result) - end - - # This mangles a name by inserting a '.' - # It is used so this bot does not ping people multiple times - def mangle_string(string) - string.chop + "." + string[-1] - end - - def initialize(*args) - super - @plusplus_file = config[:plusplus] - end - - def listen(m) - plusplus = %r{(?<to>(.*))\+\+$}.match m.message - minusminus = %r{(?<to>(.*))\-\-$}.match m.message - change(m.user.nick, plusplus[:to], :+) if plusplus - change(m.user.nick, minusminus[:to], :-) if minusminus - end - - def plusplus_file() - file = File.new(@plusplus_file, 'r') - values = YAML.load(file.read) - file.close - values - end - - def change(from, to, function) - values = plusplus_file || {} - froms_feelings = (values.keys.include? from) ? values[from] : Hash.new { |hash, key| hash[key] = 0 } - p froms_feelings - p to - froms_feelings[to] = 0 if froms_feelings[to].nil? - froms_feelings[to] = froms_feelings[to].send(function, 1) - froms_feelings.delete(to) if froms_feelings[to] == 0 - values[from] = froms_feelings - File.open(@plusplus_file, 'w') { |f| f.write (YAML.dump values) } - end -end diff --git a/plugins/pokedex.rb b/plugins/pokedex.rb deleted file mode 100644 index 7616462..0000000 --- a/plugins/pokedex.rb +++ /dev/null @@ -1,42 +0,0 @@ -# -*- coding: utf-8 -*- -require 'cinch' -require 'levenshtein' -require 'json' -class Pokedex - include Cinch::Plugin - # match /(all|poke)dex (.+)/ - match /pokedex (.+)/ - - def initialize(*args) - super - @json_data = get_pokedex_json - @all_pokemon = get_list_of_pokemon - end - - def get_pokedex_json - p Dir.pwd - pokedex_file = File.new(config[:pokedex], 'r') - data = JSON.parse(pokedex_file.read) - pokedex_file.close - data - end - - def get_list_of_pokemon - @json_data.keys - end - - def execute(m, given_name) - pokemon = @all_pokemon[@all_pokemon.map{ |this_pokemon| Levenshtein.distance(this_pokemon, given_name)}.each_with_index.min.last] - pokedex = @json_data[pokemon] - species = pokedex['species'] - type = pokedex['type'] - height = pokedex['height'] - weight = pokedex['weight'] - description_choice = pokedex['pokedex'].sample - - rv = "#{pokemon}, the #{species} Pokémon. #{type}, #{height}, #{weight} lb. #{description_choice}" - - m.reply(rv, true ) - end -end - diff --git a/plugins/quotes.rb b/plugins/quotes.rb deleted file mode 100644 index 86a48f1..0000000 --- a/plugins/quotes.rb +++ /dev/null @@ -1,82 +0,0 @@ -require 'cinch' -require 'yaml' - -class Quotes - include Cinch::Plugin - @help_hash = { - :add_quote => "Usage: !addquote Quote -Example: !addquote \"That steggybot sure is something\"", - :quote => "Usage !quote [search] -Example: !quote whunt", - :fortune => "Same as quote" - } - match /addquote (.+)/i, method: :addquote - match /quote (.+)/i, method: :quote - match /fortune/i, method: :quote - - def initialize(*args) - super - - @quotes_file = config[:quotes_file] - end - - def addquote(m, quote) - # make the quote - new_quote = { "quote" => quote, "added_by" => m.user.nick, "created_at" => Time.now, "deleted" => false } - - # add it to the list - existing_quotes = get_quotes || [] - existing_quotes << new_quote - - # find the id of the new quote and set it based on where it was placed in the quote list - new_quote_index = existing_quotes.index(new_quote) - existing_quotes[new_quote_index]["id"] = new_quote_index + 1 - - # write it to the file - output = File.new(@quotes_file, 'w') - output.puts YAML.dump(existing_quotes) - output.close - - # send reply that quote was added - m.reply "#{m.user.nick}: Quote successfully added as ##{new_quote_index + 1}." - end - - def quote(m, search = nil) - quotes = get_quotes.delete_if{ |q| q["deleted"] == true } - if search.nil? # we are pulling random - quote = quotes.sample - m.reply "#{m.user.nick}: ##{quote["id"]} - #{quote["quote"]}" - elsif search.to_i != 0 # then we are searching by id - quote = quotes.find{|q| q["id"] == search.to_i } - if quote.nil? - m.reply "#{m.user.nick}: No quotes found." - else - m.reply "#{m.user.nick}: ##{quote["id"]} - #{quote["quote"]}" - end - else - quotes.keep_if{ |q| q["quote"].downcase.include?(search.downcase) } - if quotes.empty? - m.reply "#{m.user.nick}: No quotes found." - else - quote = quotes.first - m.reply "#{m.user.nick}: ##{quote["id"]} - #{quote["quote"]}" - m.reply "The search term also matched on quote IDs: #{quotes.map{|q| q["id"]}.join(", ")}" if quotes.size > 1 - end - end - end - - #-------------------------------------------------------------------------------- - # Protected - #-------------------------------------------------------------------------------- - - protected - - def get_quotes - output = File.new(@quotes_file, 'r') - quotes = YAML.load(output.read) - output.close - - quotes - end - -end diff --git a/plugins/roll.rb b/plugins/roll.rb deleted file mode 100644 index 870db65..0000000 --- a/plugins/roll.rb +++ /dev/null @@ -1,17 +0,0 @@ -require 'cinch' - -class Roll - include Cinch::Plugin - match /roll (.+)[D|d](.+)/, method: :roll - @help_hash = { - :roll => "Usage: !roll xDy -Example: !roll 5d20 -Returns the values of the dice rolled, as well as their sum" - } - - def roll(m, num_dice, range) - results = [] - values = num_dice.to_i.times {results << (1..range.to_i).to_a.sample} - m.reply "#{m.user.nick}, you got #{results}, sums to #{results.inject(0, :+)}" - end -end diff --git a/plugins/title_grabber.rb b/plugins/title_grabber.rb deleted file mode 100644 index fc42139..0000000 --- a/plugins/title_grabber.rb +++ /dev/null @@ -1,26 +0,0 @@ -require 'open-uri' -require 'cinch' -require 'nokogiri' - -class TitleGrabber - include Cinch::Plugin - @help_string = "Titlegrabber simply sits in the channel watching for HTTP links. When it sees one, it will grab the title, and print it in the channel" - listen_to :channel - - def grab(url) - page = Nokogiri::HTML(open(url)) - return nil if page.css("title").empty? - return page.css("title").first.text - rescue OpenURI::HTTPError - nil - end - - def listen(m) - urls = URI.extract(m.message, "http") - urls.reject! {|url| url.include? "youtube.com"} - titles = urls.map { |url| grab(url) }.compact - unless titles.empty? - m.reply titles.join(", ") - end - end -end diff --git a/plugins/urban_dict.rb b/plugins/urban_dict.rb deleted file mode 100644 index 6a48e6d..0000000 --- a/plugins/urban_dict.rb +++ /dev/null @@ -1,22 +0,0 @@ -require 'cinch' -require 'open-uri' -require 'nokogiri' -require 'cgi' - -class UrbanDictionary - include Cinch::Plugin - @help_hash = { - :urban => "Usage: !urban WORD -Example: !urban bish -Returns the urban dictionary first result related to WORD" - } - match /urban (.+)/ - def lookup(word) - url = "http://www.urbandictionary.com/define.php?term=#{CGI.escape(word)}" - CGI.unescape_html Nokogiri::HTML(open(url)).at("div.definition").text.gsub(/\s+/, ' ') rescue nil - end - - def execute(m, word) - m.reply(lookup(word) || "No results found", true) - end -end diff --git a/plugins/url_shorten.rb b/plugins/url_shorten.rb deleted file mode 100644 index b0ba8f7..0000000 --- a/plugins/url_shorten.rb +++ /dev/null @@ -1,23 +0,0 @@ -require 'open-uri' -require 'cinch' - -class TinyURL - include Cinch::Plugin - - listen_to :channel - - def shorten(url) - url = open("http://tinyurl.com/api-create.php?url=#{URI.escape(url)}").read - url == "Error" ? nil : url - rescue OpenURI::HTTPError - nil - end - - def listen(m) - urls = URI.extract(m.message, "http") - short_urls = urls.map { |url| shorten(url) }.compact - unless short_urls.empty? - m.reply short_urls.join(", ") - end - end -end diff --git a/plugins/who_are_these_people.rb b/plugins/who_are_these_people.rb deleted file mode 100644 index 97ca58f..0000000 --- a/plugins/who_are_these_people.rb +++ /dev/null @@ -1,78 +0,0 @@ -require 'cinch' - -class WhoAreThesePeople - include Cinch::Plugin - - listen_to :channel - match /addwho ([\w-]+) (.+)/i, method: :add - match /removewho ([\w-]+)/i, method: :remove - - def initialize(*args) - super - @identities = config[:identities] - end - - def add (m, username, real_name) - # add it to the list - existing_ids = get_identities || {} - - if existing_ids[username.downcase] && (existing_ids[username.downcase][:added_by] == username.downcase) - if m.user.nick.downcase == username.downcase - existing_ids[username.downcase] = {:name => real_name, :added_by => m.user.nick.downcase, :updated_at => DateTime.now} - else - m.reply "#{m.user.nick}: Can't override a user's self-definition." - return - end - else - existing_ids[username.downcase] = {:name => real_name, :added_by => m.user.nick.downcase, :updated_at => DateTime.now} - end - - # write it to the file - output = File.new(@identities, 'w') - output.puts YAML.dump(existing_ids) - output.close - - m.reply "#{m.user.nick}: #{username} successfully added as '#{real_name}'." - end - - def remove(m, username) - existing_ids = get_identities || {} - - unless existing_ids[username] - m.reply "#{m.user.nick}: #{username} not in identities list." - return - end - - if (m.user.nick.downcase == username.downcase) || (m.user.nick.downcase == existing_ids[username][:added_by]) - existing_ids.delete(username) - # write it to the file - output = File.new(@identities, 'w') - output.puts YAML.dump(existing_ids) - output.close - - m.reply "#{m.user.nick}: #{username} removed from identities list." - else - m.reply "#{m.user.nick}: Only the identity creator or subject can remove an identity from the list." - end - end - - def listen(m) - match = /who is (\w+)/i.match(m.message) - if match - user = match[1] - if get_identities[user.downcase] - m.reply "#{m.user.nick}: #{user} is #{get_identities[user.downcase][:name]}" - end - end - end - - protected - - def get_identities - output = File.new(@identities, 'r') - ids = YAML.load(output.read) - output.close - - ids - end -end diff --git a/plugins/youtube.rb b/plugins/youtube.rb deleted file mode 100644 index 4b9ea43..0000000 --- a/plugins/youtube.rb +++ /dev/null @@ -1,28 +0,0 @@ -require 'cinch' -require 'nokogiri' -require 'open-uri' - -class Youtube - include Cinch::Plugin - listen_to :channel - - def listen(m) - urls = URI.extract(m.message, "http") - urls += URI.extract(m.message, "https") - urls = urls.select{|url| url.include? "youtube.com"} - page_info = urls.map{|url| get_page_info(url)}.compact - unless page_info.empty? - m.reply page_info.join("\n") - end - end - - def get_page_info(url) - page = Nokogiri::HTML(open(url)) - return_string = "Title: " + page.title + ", -Top Comments: \t" - page.css("div.content-container > div.content > div.comment-text")[0..2].each_with_index{|comment, index| return_string += index.to_s + " " + comment.text.strip+ "\n" } - - return_string += " With count: " + page.css("div[@id=watch-actions] span.watch-view-count > strong").text - end -end - From 0d740b871310673d94a5b51ba7e52ac3bea44264 Mon Sep 17 00:00:00 2001 From: Samantha Dove <sdove@guidewire.com> Date: Tue, 28 Jan 2014 00:23:02 -0800 Subject: [PATCH 4/4] adding these plugins to my remote repo because they never should have been deleted lawl --- plugins/google.rb | 1 - plugins/pazudora.rb | 219 +++++++++++++++++++++++++++++++++++++++++ plugins/pokedex.rb | 42 ++++++++ plugins/quotes.rb | 82 +++++++++++++++ plugins/roll.rb | 17 ++++ plugins/urban_dict.rb | 22 +++++ plugins/url_shorten.rb | 23 +++++ plugins/youtube.rb | 28 ++++++ 8 files changed, 433 insertions(+), 1 deletion(-) create mode 100644 plugins/pazudora.rb create mode 100644 plugins/pokedex.rb create mode 100644 plugins/quotes.rb create mode 100644 plugins/roll.rb create mode 100644 plugins/urban_dict.rb create mode 100644 plugins/url_shorten.rb create mode 100644 plugins/youtube.rb diff --git a/plugins/google.rb b/plugins/google.rb index 4093dd1..c759a32 100644 --- a/plugins/google.rb +++ b/plugins/google.rb @@ -7,7 +7,6 @@ class Google include Cinch::Plugin match /google (.+)/, method: :execute match /image (.+)/, method: :image - @help_hash = { :google => "Usage: !google THING Example !google Syria diff --git a/plugins/pazudora.rb b/plugins/pazudora.rb new file mode 100644 index 0000000..484ef0f --- /dev/null +++ b/plugins/pazudora.rb @@ -0,0 +1,219 @@ +require 'cinch' +require 'nokogiri' + +class Pazudora + include Cinch::Plugin + + PUZZLEMON_BASE_URL = "http://www.puzzledragonx.com/en/" + + match /pazudora ([\w-]+) *(.+)*/i, method: :pazudora + match /stupidpuzzledragonbullshit ([\w-]+) *(.+)*/i, method: :pazudora + match /stupiddragonpuzzlebullshit ([\w-]+) *(.+)*/i, method: :pazudora + match /p&d ([\w-]+) *(.+)*/i, method: :pazudora + match /pad ([\w-]+) *(.+)*/i, method: :pazudora + match /puzzlemon ([\w-]+) *(.+)*/i, method: :pazudora + match /puzzledex (.+)*/i, method: :pazudora_lookup + + @help_string = <<-eos + Puzzle and Dragons (on iOS and Android) utility functions. Mostly collects friend codes and tracks the daily dungeon. + Its commands are aliased to pazudora, p&d, pad, and puzzlemon. + eos + @help_hash = { + :add => "Usage: !puzzlemon add NAME CODE +Example: !puzzlemon add steggybot 123,456,789 +Adds user's code to the list of friend codes", + :group => "Usage: !puzzlemon group NAME +Example !puzzlemon group steggybot +Returns the daily dungeon group that the user belongs to.", + :dailies => "Usage: !puzzlemon dailies +Example !puzzlemon dailies +Returns the times (and type) of today's daily dungeons, split by group. If called by +a registered player, also reminds them of their group id.", + :lookup => "Usage: !(puzzlemon lookup|puzzledex) (NAME|ID) +Example !puzzlemon lookup horus, !puzzledex 603 +Returns a description of the puzzlemon. If none is found, returns a pseudorandom (hashed) one.", + :list => "Usage: !puzzlemon list +Example !puzzlemon list +Returns a list of everyone's friends codes." + } + + def initialize(*args) + super + @pddata = config[:pddata] + end + + #Any public method named pazudora_[something] is external and + #can be accessed by the user using the construction "!puzzlemon something [args]". + def pazudora (m, cmd, args) + subr = cmd.downcase.chomp + begin + if args + self.send("pazudora_#{subr}", m, args) + else + self.send("pazudora_#{subr}", m, "") + end + rescue NoMethodError + puts "Pazudora called with invalid command #{subr}." + end + end + + def pazudora_add (m, args) + pargs = args.split + username = pargs[0] + friend_code = pargs[1] + + # add it to the list + friend_codes = load_data || {} + if friend_code =~ /[0-9]{9}/ + friend_code = friend_code.reverse.gsub(/(\d{3})(?=\d)/, '\\1,').reverse + end + if friend_codes[username.downcase] && (friend_codes[username.downcase][:added_by] == username.downcase) + if m.user.nick.downcase == username.downcase + friend_codes[username.downcase] = {:friend_code => friend_code, :added_by => m.user.nick.downcase, :updated_at => DateTime.now} + else + m.reply "#{m.user.nick}: Can't override a user's self-definition." + return + end + else + friend_codes[username.downcase] = {:friend_code => friend_code, :added_by => m.user.nick.downcase, :updated_at => DateTime.now} + end + # write it to the file + output = File.new(@pddata, 'w') + output.puts YAML.dump(friend_codes) + output.close + + m.reply "#{m.user.nick}: #{mangle(username)} successfully added as '#{friend_code}'." + end + + def pazudora_remove(m, args) + pargs = args.split + username = pargs[0] + friend_codes = load_data || {} + + if ! friend_codes[username] + m.reply "#{m.user.nick}: #{mangle(username)} not in friend code list." + return + end + + if (m.user.nick.downcase == username.downcase) || (m.user.nick.downcase == friend_codes[username][:added_by]) + friend_codes.delete(username) + # write it to the file + output = File.new(@pddata, 'w') + output.puts YAML.dump(friend_codes) + output.close + + m.reply "#{m.user.nick}: #{mangle(username)} removed from friend code list." + else + m.reply "#{m.user.nick}: Only the identity creator or subject can remove a friend code from the list." + end + end + + def pazudora_who(m,args) + pargs = args.split + username = pargs[0] + if load_data[username.downcase] + m.reply "#{m.user.nick}: #{mangle(username)}'s friend code is #{load_data[username.downcase][:friend_code]}" + end + end + + def pazudora_list(m,args) + friend_codes = load_data || {} + friend_codes.keys.each_slice(3).with_index { |users, i| + r = i == 0 ? "#{m.user.nick}: " : "" + users.each{ |user| r=r+"#{mangle(user)}:#{friend_codes[user][:friend_code]} " } + m.reply r + } + end + + def pazudora_group(m,args) + pargs = args.split + username = pargs[0] + if load_data[username.downcase] + friend_code = load_data[username.downcase][:friend_code] + group = (Integer(friend_code.split(",")[0][2]) % 5 + 65).chr + m.reply "#{m.user.nick}: #{mangle(username)}'s group is #{group}" + else + m.reply "#{m.user.nick}: #{mangle(username)}'s friend code is not listed. Please use the add command to add it." + end + end + + def pazudora_dailies(m, args) + daily_url = PUZZLEMON_BASE_URL + "option.asp?utc=-8" + + username = args.split[0] || m.user.nick + friend_code = load_data[username.downcase][:friend_code] rescue nil + group_num = friend_code ? group_number_from_friend_code(friend_code) : nil + + unless @daily_timestamp == Time.now.strftime("%m-%d-%y") + @daily_page = nil + @daily_timestamp = Time.now.strftime("%m-%d-%y") + end + + @daily_page ||= Nokogiri::HTML(open(daily_url)) + event_data = @daily_page.css(".event3") + event_rewards = @daily_page.css(".limiteddragon") + + rewards = parse_daily_dungeon_rewards(event_rewards) + m.reply "Dungeons today are: #{rewards.join(', ')}" + + (0..4).each do |i| + m.reply "Group #{(i + 65).chr}: #{event_data[i].text}, #{event_data[i + 5].text}, #{event_data[i + 10].text}" + end + + if group_num + m.reply "User #{username} is in group #{(group_num + 65).chr}" + end + end + + def pazudora_lookup(m, args) + identifier = args + info = get_puzzlemon_info(URI.encode(identifier)) + + #Bypass puzzledragonx's "default to meteor dragon if you can't find the puzzlemon" mechanism to + #get a pseudorandom puzzlemon (up to the max currently released puzzlemon) instead. + meteor_dragon_id = "211" + highest_puzzledex_id = 603 + + if info.css(".name").children.first.text == "Meteor Volcano Dragon" && !(identifier.start_with?("Meteor") || identifier == meteor_dragon_id) + num = (identifier.hash % highest_puzzledex_id) + 1 + info = get_puzzlemon_info(URI.encode(num.to_s)) + end + + desc = info.css("meta [name=description]").first.attributes["content"].text + desc.gsub!(/&/, "&") + m.reply desc + end + + protected + + def mangle(s) + s.chop + "." + s[-1] + end + + def load_data + datafile = File.new(@pddata, 'r') + friend_codes = YAML.load(datafile.read) + datafile.close + return friend_codes + end + + def group_number_from_friend_code(friend_code) + return Integer(friend_code.split(",")[0][2]) % 5 + end + + def parse_daily_dungeon_rewards(rewards) + puzzlemon_numbers = [ + rewards[0].children.first.attributes["src"].value.match(/thumbnail\/(\d+).png/)[1], + rewards[5].children.first.attributes["src"].value.match(/thumbnail\/(\d+).png/)[1], + rewards[10].children.first.attributes["src"].value.match(/thumbnail\/(\d+).png/)[1]] + + puzzlemon_numbers.map{|x| + get_puzzlemon_info(x).css(".name").children.first.text rescue "Unrecognized Name" } + end + + def get_puzzlemon_info(name_or_number) + search_url = PUZZLEMON_BASE_URL + "monster.asp?n=#{name_or_number}" + puzzlemon_info = Nokogiri::HTML(open(search_url)) + end +end + diff --git a/plugins/pokedex.rb b/plugins/pokedex.rb new file mode 100644 index 0000000..7616462 --- /dev/null +++ b/plugins/pokedex.rb @@ -0,0 +1,42 @@ +# -*- coding: utf-8 -*- +require 'cinch' +require 'levenshtein' +require 'json' +class Pokedex + include Cinch::Plugin + # match /(all|poke)dex (.+)/ + match /pokedex (.+)/ + + def initialize(*args) + super + @json_data = get_pokedex_json + @all_pokemon = get_list_of_pokemon + end + + def get_pokedex_json + p Dir.pwd + pokedex_file = File.new(config[:pokedex], 'r') + data = JSON.parse(pokedex_file.read) + pokedex_file.close + data + end + + def get_list_of_pokemon + @json_data.keys + end + + def execute(m, given_name) + pokemon = @all_pokemon[@all_pokemon.map{ |this_pokemon| Levenshtein.distance(this_pokemon, given_name)}.each_with_index.min.last] + pokedex = @json_data[pokemon] + species = pokedex['species'] + type = pokedex['type'] + height = pokedex['height'] + weight = pokedex['weight'] + description_choice = pokedex['pokedex'].sample + + rv = "#{pokemon}, the #{species} Pokémon. #{type}, #{height}, #{weight} lb. #{description_choice}" + + m.reply(rv, true ) + end +end + diff --git a/plugins/quotes.rb b/plugins/quotes.rb new file mode 100644 index 0000000..86a48f1 --- /dev/null +++ b/plugins/quotes.rb @@ -0,0 +1,82 @@ +require 'cinch' +require 'yaml' + +class Quotes + include Cinch::Plugin + @help_hash = { + :add_quote => "Usage: !addquote Quote +Example: !addquote \"That steggybot sure is something\"", + :quote => "Usage !quote [search] +Example: !quote whunt", + :fortune => "Same as quote" + } + match /addquote (.+)/i, method: :addquote + match /quote (.+)/i, method: :quote + match /fortune/i, method: :quote + + def initialize(*args) + super + + @quotes_file = config[:quotes_file] + end + + def addquote(m, quote) + # make the quote + new_quote = { "quote" => quote, "added_by" => m.user.nick, "created_at" => Time.now, "deleted" => false } + + # add it to the list + existing_quotes = get_quotes || [] + existing_quotes << new_quote + + # find the id of the new quote and set it based on where it was placed in the quote list + new_quote_index = existing_quotes.index(new_quote) + existing_quotes[new_quote_index]["id"] = new_quote_index + 1 + + # write it to the file + output = File.new(@quotes_file, 'w') + output.puts YAML.dump(existing_quotes) + output.close + + # send reply that quote was added + m.reply "#{m.user.nick}: Quote successfully added as ##{new_quote_index + 1}." + end + + def quote(m, search = nil) + quotes = get_quotes.delete_if{ |q| q["deleted"] == true } + if search.nil? # we are pulling random + quote = quotes.sample + m.reply "#{m.user.nick}: ##{quote["id"]} - #{quote["quote"]}" + elsif search.to_i != 0 # then we are searching by id + quote = quotes.find{|q| q["id"] == search.to_i } + if quote.nil? + m.reply "#{m.user.nick}: No quotes found." + else + m.reply "#{m.user.nick}: ##{quote["id"]} - #{quote["quote"]}" + end + else + quotes.keep_if{ |q| q["quote"].downcase.include?(search.downcase) } + if quotes.empty? + m.reply "#{m.user.nick}: No quotes found." + else + quote = quotes.first + m.reply "#{m.user.nick}: ##{quote["id"]} - #{quote["quote"]}" + m.reply "The search term also matched on quote IDs: #{quotes.map{|q| q["id"]}.join(", ")}" if quotes.size > 1 + end + end + end + + #-------------------------------------------------------------------------------- + # Protected + #-------------------------------------------------------------------------------- + + protected + + def get_quotes + output = File.new(@quotes_file, 'r') + quotes = YAML.load(output.read) + output.close + + quotes + end + +end diff --git a/plugins/roll.rb b/plugins/roll.rb new file mode 100644 index 0000000..870db65 --- /dev/null +++ b/plugins/roll.rb @@ -0,0 +1,17 @@ +require 'cinch' + +class Roll + include Cinch::Plugin + match /roll (.+)[D|d](.+)/, method: :roll + @help_hash = { + :roll => "Usage: !roll xDy +Example: !roll 5d20 +Returns the values of the dice rolled, as well as their sum" + } + + def roll(m, num_dice, range) + results = [] + values = num_dice.to_i.times {results << (1..range.to_i).to_a.sample} + m.reply "#{m.user.nick}, you got #{results}, sums to #{results.inject(0, :+)}" + end +end diff --git a/plugins/urban_dict.rb b/plugins/urban_dict.rb new file mode 100644 index 0000000..6a48e6d --- /dev/null +++ b/plugins/urban_dict.rb @@ -0,0 +1,22 @@ +require 'cinch' +require 'open-uri' +require 'nokogiri' +require 'cgi' + +class UrbanDictionary + include Cinch::Plugin + @help_hash = { + :urban => "Usage: !urban WORD +Example: !urban bish +Returns the urban dictionary first result related to WORD" + } + match /urban (.+)/ + def lookup(word) + url = "http://www.urbandictionary.com/define.php?term=#{CGI.escape(word)}" + CGI.unescape_html Nokogiri::HTML(open(url)).at("div.definition").text.gsub(/\s+/, ' ') rescue nil + end + + def execute(m, word) + m.reply(lookup(word) || "No results found", true) + end +end diff --git a/plugins/url_shorten.rb b/plugins/url_shorten.rb new file mode 100644 index 0000000..b0ba8f7 --- /dev/null +++ b/plugins/url_shorten.rb @@ -0,0 +1,23 @@ +require 'open-uri' +require 'cinch' + +class TinyURL + include Cinch::Plugin + + listen_to :channel + + def shorten(url) + url = open("http://tinyurl.com/api-create.php?url=#{URI.escape(url)}").read + url == "Error" ? nil : url + rescue OpenURI::HTTPError + nil + end + + def listen(m) + urls = URI.extract(m.message, "http") + short_urls = urls.map { |url| shorten(url) }.compact + unless short_urls.empty? + m.reply short_urls.join(", ") + end + end +end diff --git a/plugins/youtube.rb b/plugins/youtube.rb new file mode 100644 index 0000000..4b9ea43 --- /dev/null +++ b/plugins/youtube.rb @@ -0,0 +1,28 @@ +require 'cinch' +require 'nokogiri' +require 'open-uri' + +class Youtube + include Cinch::Plugin + listen_to :channel + + def listen(m) + urls = URI.extract(m.message, "http") + urls += URI.extract(m.message, "https") + urls = urls.select{|url| url.include? "youtube.com"} + page_info = urls.map{|url| get_page_info(url)}.compact + unless page_info.empty? + m.reply page_info.join("\n") + end + end + + def get_page_info(url) + page = Nokogiri::HTML(open(url)) + return_string = "Title: " + page.title + ", +Top Comments: \t" + page.css("div.content-container > div.content > div.comment-text")[0..2].each_with_index{|comment, index| return_string += index.to_s + " " + comment.text.strip+ "\n" } + + return_string += " With count: " + page.css("div[@id=watch-actions] span.watch-view-count > strong").text + end +end +