<!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 &lt;nick&gt; location &lt;location&gt;
    specifies physical location of a nick
 * port remember &lt;nick&gt; timezone &lt;timezone&gt;
    specifies timezone for a nick (relative to /usr/share/zoneinfo)
 * port forget &lt;nick&gt; email
    forgets email correspondance for nick
 * port forget &lt;nick&gt; location
    forgets location correspondance for nick
 * port forget &lt;nick&gt; timezone
    forgets timezone correspondance for nick
 * port whereis
 &lt;nick&gt;
    tells what it knows about &lt;nick&gt;'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 &quot;herald&quot;
</span><span class="cx">                         return &quot;herald enable|disable =&gt; enable or disable heralding by port&quot;
</span><span class="cx">                   when &quot;remember&quot;
</span><del>-                        return &quot;remember &lt;nick&gt; email &lt;address&gt; =&gt; remember what port maintainer email &lt;nick&gt; belongs to&quot;
</del><ins>+                        return &quot;remember &lt;nick&gt; email &lt;address&gt; =&gt; remember what port maintainer email &lt;nick&gt; belongs to; &quot; +
+                                        &quot;remember &lt;nick&gt; timezone &lt;timezone&gt; =&gt; remember the local timezone for &lt;nick&gt;; &quot; +
+                                        &quot;remember &lt;nick&gt; location &lt;location&gt; =&gt; remember the physical location for &lt;nick&gt;&quot;
</ins><span class="cx">                   when &quot;forget&quot;
</span><del>-                        return &quot;forget &lt;nick&gt; =&gt; forget email correspondance for &lt;nick&gt;&quot;
</del><ins>+                        return &quot;forget &lt;nick&gt; =&gt; forget all information for &lt;nick&gt;; &quot; +
+                                &quot;forget email &lt;nick&gt; =&gt; forget email correspondance for &lt;nick&gt;; &quot; +
+                                &quot;forget timezone &lt;nick&gt; =&gt; forget local timezone for &lt;nick&gt;; &quot; +
+                                &quot;forget location &lt;nick&gt; =&gt; forget physical location for &lt;nick&gt;&quot;
+                  when &quot;whois&quot;
+                          return &quot;whois &lt;nick&gt; =&gt; give a summary of information for &lt;nick&gt;&quot;
+                  when &quot;whereis&quot;
+                          return &quot;whereis &lt;nick&gt; =&gt; tell what is know about timezone and location of &lt;nick&gt;&quot;
</ins><span class="cx">                   else
</span><del>-                        return &quot;port (MacPorts) commands: info, maintainer, version, herald, remember, forget, whois&quot;
</del><ins>+                        return &quot;port (MacPorts) commands: info, maintainer, version, herald, remember, forget, whois, whereis&quot;
</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(&quot;|-&quot;, &quot;w+&quot;) { |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 &gt;&gt;= 8
+                
+                return rc
+        end
+
</ins><span class="cx">         def callPort(*args)
</span><span class="cx">                 Utils.safe_exec(&quot;/opt/local/bin/port&quot;, *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[&quot;email_#{nick}&quot;] = email
</span><span class="cx">                 m.reply &quot;okay, #{nick} is #{email}&quot;
</span><span class="cx">         end
</span><span class="cx">         
</span><ins>+        def rememberTimeZone(m, params)
+                nick = params[:nick]
+                timezone = params[:timezone]
+                @registry[&quot;timezone_#{nick}&quot;] = timezone
+                m.reply &quot;okay, #{nick} is in timezone #{timezone}&quot;
+        end
+        
+        def rememberLocation(m, params)
+                nick = params[:nick]
+                location = params[:location].join(' ')
+                @registry[&quot;location_#{nick}&quot;] = location
+                m.reply &quot;okay, #{nick} is in #{location}&quot;
+        end
+        
</ins><span class="cx">         def forget(m, params)
</span><span class="cx">                 nick = params[:nick]
</span><span class="cx">                 @registry.delete(&quot;email_#{nick}&quot;)
</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(&quot;email_#{nick}&quot;)
+                @registry.delete(&quot;timezone_#{nick}&quot;)
+                @registry.delete(&quot;location_#{nick}&quot;)
+                m.okay
+        end
+
+        def forgetTimeZone(m, params)
+                nick = params[:nick]
+                @registry.delete(&quot;timezone_#{nick}&quot;)
+                m.okay
+        end
+
+        def forgetLocation(m, params)
+                nick = params[:nick]
+                @registry.delete(&quot;location_#{nick}&quot;)
+                m.okay
+        end
+
</ins><span class="cx">         def whois(m, params)
</span><span class="cx">                 nick = params[:nick]
</span><span class="cx">                 email = @registry[&quot;email_#{nick}&quot;]
</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(&quot;&quot;, &quot;r+&quot;) { |o|
+                        runCmd(&quot;/bin/date&quot;, &quot;+%a %H:%M %Z&quot;, nil, o, { &quot;TZ&quot; =&gt; timeZone } )
+                        o.close_write
+                        localTime = o.string
+                }
+                return localTime
+        end
+        
+        def whereisNick(nick)
+                location = @registry[&quot;location_#{nick}&quot;]
+                timeZone = @registry[&quot;timezone_#{nick}&quot;]
+                
+                localTime = nil
+                if timeZone
+                        localTime = localTimeInTimeZone(timeZone)
+                end
+                
+                if location &amp;&amp; localTime
+                        whereis = &quot;is in #{location}; local time is #{localTime}&quot;
+                elsif location
+                        whereis = &quot;is in #{location}&quot;
+                elsif localTime
+                        whereis = &quot;is at local time #{localTime}&quot;
+                else
+                        whereis = nil
+                end
+        end
+        
+        def whereis(m, params)
+                nick = params[:nick]
+                
+                where = whereisNick(nick)
+                if where
+                        m.reply &quot;#{nick} #{where}&quot;
+                else
+                        m.reply &quot;I don't know where #{nick} is&quot;
+                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, &quot;#{nick} is #{email}&quot;
</del><ins>+                                        msg = &quot;#{nick} is #{email}&quot;
</ins><span class="cx">                                 elsif (portCount &lt;= showMax)
</span><del>-                                        @bot.say where, &quot;#{nick} is #{email} and maintainer of &quot; +
</del><ins>+                                        msg = &quot;#{nick} is #{email} and maintainer of &quot; +
</ins><span class="cx">                                                 textEnumeration(somePorts)
</span><span class="cx">                                 else
</span><del>-                                        @bot.say where, &quot;#{nick} is #{email} and maintainer of &quot; +
</del><ins>+                                        msg = &quot;#{nick} is #{email} and maintainer of &quot; +
</ins><span class="cx">                                                 textEnumeration(somePorts) +
</span><span class="cx">                                                 &quot; (of #{portCount} total)&quot;
</span><del>-                                end        
</del><ins>+                                end
+                                
+                                whereis = whereisNick(nick)
+                                if whereis
+                                        msg = msg + &quot; and #{whereis}&quot;
+                                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 =&gt; 'herald_enable'
</span><span class="cx"> plugin.map 'port herald disable', :action =&gt; 'herald_disable'
</span><del>-plugin.map 'port remember :nick email :email', :action =&gt; 'remember'
</del><ins>+plugin.map 'port remember :nick timezone :timezone', :action =&gt; 'rememberTimeZone'
+plugin.map 'port remember :nick email :email', :action =&gt; 'rememberEmail'
+plugin.map 'port remember :nick location *location', :action =&gt; 'rememberLocation'
</ins><span class="cx"> plugin.map 'port forget :nick', :action =&gt; 'forget'
</span><ins>+plugin.map 'port forget :nick email', :action =&gt; 'forgetEmail'
+plugin.map 'port forget :nick timezone', :action =&gt; 'forgetTimeZone'
+plugin.map 'port forget :nick location', :action =&gt; 'forgetLocation'
</ins><span class="cx"> plugin.map 'port whois :nick', :action =&gt; 'whois'
</span><ins>+plugin.map 'port whereis :nick', :action =&gt; 'whereis'
</ins></span></pre>
</div>
</div>

</body>
</html>