<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head><meta http-equiv="content-type" content="text/html; charset=utf-8" /><style type="text/css"><!--
#msg dl { border: 1px #006 solid; background: #369; padding: 6px; color: #fff; }
#msg dt { float: left; width: 6em; font-weight: bold; }
#msg dt:after { content:':';}
#msg dl, #msg dt, #msg ul, #msg li, #header, #footer { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; }
#msg dl a { font-weight: bold}
#msg dl a:link { color:#fc3; }
#msg dl a:active { color:#ff0; }
#msg dl a:visited { color:#cc6; }
h3 { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; font-weight: bold; }
#msg pre { overflow: auto; background: #ffc; border: 1px #fc0 solid; padding: 6px; }
#msg ul, pre { overflow: auto; }
#header, #footer { color: #fff; background: #636; border: 1px #300 solid; padding: 6px; }
#patch { width: 100%; }
#patch h4 {font-family: verdana,arial,helvetica,sans-serif;font-size:10pt;padding:8px;background:#369;color:#fff;margin:0;}
#patch .propset h4, #patch .binary h4 {margin:0;}
#patch pre {padding:0;line-height:1.2em;margin:0;}
#patch .diff {width:100%;background:#eee;padding: 0 0 10px 0;overflow:auto;}
#patch .propset .diff, #patch .binary .diff {padding:10px 0;}
#patch span {display:block;padding:0 10px;}
#patch .modfile, #patch .addfile, #patch .delfile, #patch .propset, #patch .binary, #patch .copfile {border:1px solid #ccc;margin:10px 0;}
#patch ins {background:#dfd;text-decoration:none;display:block;padding:0 10px;}
#patch del {background:#fdd;text-decoration:none;display:block;padding:0 10px;}
#patch .lines, .info {color:#888;background:#fff;}
--></style>
<title>[21884] trunk/base/portmgr/bots/port.rb</title>
</head>
<body>
<div id="msg">
<dl>
<dt>Revision</dt> <dd><a href="http://trac.macosforge.org/projects/macports/changeset/21884">21884</a></dd>
<dt>Author</dt> <dd>jberry@macports.org</dd>
<dt>Date</dt> <dd>2007-02-10 16:30:55 -0800 (Sat, 10 Feb 2007)</dd>
</dl>
<h3>Log Message</h3>
<pre>Add new commands to mpbot's port plugin:
* port remember <nick> location <location>
specifies physical location of a nick
* port remember <nick> timezone <timezone>
specifies timezone for a nick (relative to /usr/share/zoneinfo)
* port forget <nick> email
forgets email correspondance for nick
* port forget <nick> location
forgets location correspondance for nick
* port forget <nick> timezone
forgets timezone correspondance for nick
* port whereis
<nick>
tells what it knows about <nick>'s location and timezone
* port whois and the herald message also include some whereis info.</pre>
<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkbaseportmgrbotsportrb">trunk/base/portmgr/bots/port.rb</a></li>
</ul>
</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkbaseportmgrbotsportrb"></a>
<div class="modfile"><h4>Modified: trunk/base/portmgr/bots/port.rb (21883 => 21884)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/base/portmgr/bots/port.rb 2007-02-10 23:48:14 UTC (rev 21883)
+++ trunk/base/portmgr/bots/port.rb 2007-02-11 00:30:55 UTC (rev 21884)
</span><span class="lines">@@ -10,6 +10,10 @@
</span><span class="cx"> #
</span><span class="cx">
</span><span class="cx">
</span><ins>+require 'fileutils.rb'
+require 'stringio'
+
+
</ins><span class="cx"> module Shuffle
</span><span class="cx">
</span><span class="cx"> def shuffle!
</span><span class="lines">@@ -45,14 +49,78 @@
</span><span class="cx"> when "herald"
</span><span class="cx"> return "herald enable|disable => enable or disable heralding by port"
</span><span class="cx"> when "remember"
</span><del>- return "remember <nick> email <address> => remember what port maintainer email <nick> belongs to"
</del><ins>+ return "remember <nick> email <address> => remember what port maintainer email <nick> belongs to; " +
+ "remember <nick> timezone <timezone> => remember the local timezone for <nick>; " +
+ "remember <nick> location <location> => remember the physical location for <nick>"
</ins><span class="cx"> when "forget"
</span><del>- return "forget <nick> => forget email correspondance for <nick>"
</del><ins>+ return "forget <nick> => forget all information for <nick>; " +
+ "forget email <nick> => forget email correspondance for <nick>; " +
+ "forget timezone <nick> => forget local timezone for <nick>; " +
+ "forget location <nick> => forget physical location for <nick>"
+ when "whois"
+ return "whois <nick> => give a summary of information for <nick>"
+ when "whereis"
+ return "whereis <nick> => tell what is know about timezone and location of <nick>"
</ins><span class="cx"> else
</span><del>- return "port (MacPorts) commands: info, maintainer, version, herald, remember, forget, whois"
</del><ins>+ return "port (MacPorts) commands: info, maintainer, version, herald, remember, forget, whois, whereis"
</ins><span class="cx"> end
</span><span class="cx"> end
</span><span class="cx">
</span><ins>+ def runCmd(cmd, args, input=nil, output=nil, env={})
+ # Open pipes for stdin, and stdout
+ stdin, inwrite = IO.pipe
+ outread, stdout = IO.pipe
+
+ # Fork the child
+ pid = fork {
+ # In child
+
+ # Change the environment
+ ENV.update(env)
+
+ # Redirect IO to the pipes
+ inwrite.close
+ $stdin.reopen(stdin)
+ stdin.close
+
+ outread.close
+ $stdout.reopen(stdout)
+ $stderr.reopen(stdout)
+ stdout.close
+
+ # Execute the command
+ exec(cmd, *args)
+ # shouldn't return
+ }
+
+ # Close unneeded pipe-ends in this process
+ [stdin, stdout].each { |io| io.close }
+
+ # In order to avoid deadlock, invoke a secondary process to write the input
+ open("|-", "w+") { |p|
+ if (p == nil)
+ # In child
+ FileUtils.copy_stream(input, inwrite) if !input.nil?
+ inwrite.close
+ end
+ }
+
+ # Close remaining write pipe into command
+ inwrite.close
+
+ # Read the stdout from the command, writing it to output
+ FileUtils.copy_stream(outread, output) if !output.nil?
+
+ # Close remaining pipe ends
+ [outread].each { |io| io.close }
+
+ # Collect the return code
+ pid, rc = Process.waitpid2(pid)
+ rc >>= 8
+
+ return rc
+ end
+
</ins><span class="cx"> def callPort(*args)
</span><span class="cx"> Utils.safe_exec("/opt/local/bin/port", *args)
</span><span class="cx"> end
</span><span class="lines">@@ -90,19 +158,53 @@
</span><span class="cx"> m.okay
</span><span class="cx"> end
</span><span class="cx">
</span><del>- def remember(m, params)
</del><ins>+ def rememberEmail(m, params)
</ins><span class="cx"> nick = params[:nick]
</span><span class="cx"> email = params[:email]
</span><span class="cx"> @registry["email_#{nick}"] = email
</span><span class="cx"> m.reply "okay, #{nick} is #{email}"
</span><span class="cx"> end
</span><span class="cx">
</span><ins>+ def rememberTimeZone(m, params)
+ nick = params[:nick]
+ timezone = params[:timezone]
+ @registry["timezone_#{nick}"] = timezone
+ m.reply "okay, #{nick} is in timezone #{timezone}"
+ end
+
+ def rememberLocation(m, params)
+ nick = params[:nick]
+ location = params[:location].join(' ')
+ @registry["location_#{nick}"] = location
+ m.reply "okay, #{nick} is in #{location}"
+ end
+
</ins><span class="cx"> def forget(m, params)
</span><span class="cx"> nick = params[:nick]
</span><span class="cx"> @registry.delete("email_#{nick}")
</span><span class="cx"> m.okay
</span><span class="cx"> end
</span><span class="cx">
</span><ins>+ def forgetEmail(m, params)
+ nick = params[:nick]
+ @registry.delete("email_#{nick}")
+ @registry.delete("timezone_#{nick}")
+ @registry.delete("location_#{nick}")
+ m.okay
+ end
+
+ def forgetTimeZone(m, params)
+ nick = params[:nick]
+ @registry.delete("timezone_#{nick}")
+ m.okay
+ end
+
+ def forgetLocation(m, params)
+ nick = params[:nick]
+ @registry.delete("location_#{nick}")
+ m.okay
+ end
+
</ins><span class="cx"> def whois(m, params)
</span><span class="cx"> nick = params[:nick]
</span><span class="cx"> email = @registry["email_#{nick}"]
</span><span class="lines">@@ -113,6 +215,47 @@
</span><span class="cx"> end
</span><span class="cx"> end
</span><span class="cx">
</span><ins>+ def localTimeInTimeZone(timeZone)
+ localTime = nil
+ StringIO.open("", "r+") { |o|
+ runCmd("/bin/date", "+%a %H:%M %Z", nil, o, { "TZ" => timeZone } )
+ o.close_write
+ localTime = o.string
+ }
+ return localTime
+ end
+
+ def whereisNick(nick)
+ location = @registry["location_#{nick}"]
+ timeZone = @registry["timezone_#{nick}"]
+
+ localTime = nil
+ if timeZone
+ localTime = localTimeInTimeZone(timeZone)
+ end
+
+ if location && localTime
+ whereis = "is in #{location}; local time is #{localTime}"
+ elsif location
+ whereis = "is in #{location}"
+ elsif localTime
+ whereis = "is at local time #{localTime}"
+ else
+ whereis = nil
+ end
+ end
+
+ def whereis(m, params)
+ nick = params[:nick]
+
+ where = whereisNick(nick)
+ if where
+ m.reply "#{nick} #{where}"
+ else
+ m.reply "I don't know where #{nick} is"
+ end
+ end
+
</ins><span class="cx"> def textEnumeration(a)
</span><span class="cx"> sz = a.size
</span><span class="cx"> case sz
</span><span class="lines">@@ -137,16 +280,25 @@
</span><span class="cx"> showMax = 4
</span><span class="cx"> somePorts = ports.extend(Shuffle).shuffle!.slice(0, showMax)
</span><span class="cx">
</span><ins>+ msg = nil;
+
</ins><span class="cx"> if (portCount == 0)
</span><del>- @bot.say where, "#{nick} is #{email}"
</del><ins>+ msg = "#{nick} is #{email}"
</ins><span class="cx"> elsif (portCount <= showMax)
</span><del>- @bot.say where, "#{nick} is #{email} and maintainer of " +
</del><ins>+ msg = "#{nick} is #{email} and maintainer of " +
</ins><span class="cx"> textEnumeration(somePorts)
</span><span class="cx"> else
</span><del>- @bot.say where, "#{nick} is #{email} and maintainer of " +
</del><ins>+ msg = "#{nick} is #{email} and maintainer of " +
</ins><span class="cx"> textEnumeration(somePorts) +
</span><span class="cx"> " (of #{portCount} total)"
</span><del>- end
</del><ins>+ end
+
+ whereis = whereisNick(nick)
+ if whereis
+ msg = msg + " and #{whereis}"
+ end
+
+ @bot.say where, msg
</ins><span class="cx"> end
</span><span class="cx"> end
</span><span class="cx"> end
</span><span class="lines">@@ -198,6 +350,12 @@
</span><span class="cx">
</span><span class="cx"> plugin.map 'port herald enable', :action => 'herald_enable'
</span><span class="cx"> plugin.map 'port herald disable', :action => 'herald_disable'
</span><del>-plugin.map 'port remember :nick email :email', :action => 'remember'
</del><ins>+plugin.map 'port remember :nick timezone :timezone', :action => 'rememberTimeZone'
+plugin.map 'port remember :nick email :email', :action => 'rememberEmail'
+plugin.map 'port remember :nick location *location', :action => 'rememberLocation'
</ins><span class="cx"> plugin.map 'port forget :nick', :action => 'forget'
</span><ins>+plugin.map 'port forget :nick email', :action => 'forgetEmail'
+plugin.map 'port forget :nick timezone', :action => 'forgetTimeZone'
+plugin.map 'port forget :nick location', :action => 'forgetLocation'
</ins><span class="cx"> plugin.map 'port whois :nick', :action => 'whois'
</span><ins>+plugin.map 'port whereis :nick', :action => 'whereis'
</ins></span></pre>
</div>
</div>
</body>
</html>