| 31 import socket |
31 import socket |
| 32 import time |
32 import time |
| 33 import sys |
33 import sys |
| 34 import traceback |
34 import traceback |
| 35 import re |
35 import re |
| 36 import json |
|
| 37 import urllib |
36 import urllib |
| 38 import urllib2 |
37 import urllib2 |
| 39 import hgapi |
38 import hgapi |
| 40 import os |
39 import os |
| 41 import suds |
40 import suds |
| 42 import math |
41 import math |
| |
42 import json |
| 43 from datetime import datetime |
43 from datetime import datetime |
| 44 import commandhandler as CommandHandler |
44 import modulecore as ModuleCore |
| 45 |
45 import configfile |
| 46 CommandHandler.init_data() |
46 from configfile import Config |
| |
47 |
| |
48 ModuleCore.init_data() |
| 47 |
49 |
| 48 try: |
50 try: |
| 49 uid = os.geteuid() |
51 uid = os.geteuid() |
| 50 except: |
52 except: |
| 51 uid = -1 |
53 uid = -1 |
| 52 |
54 |
| 53 if uid == 0 and raw_input ('Do you seriously want to run cobalt as root? [y/N] ') != 'y': |
55 if uid == 0 and raw_input ('Do you seriously want to run cobalt as root? [y/N] ') != 'y': |
| 54 quit() |
56 quit() |
| 55 |
57 |
| 56 print 'Loading configuration...' |
58 configfile.init() |
| 57 try: |
59 g_admins = Config.get_value ('admins', default=[]) |
| 58 with open ('cobalt.json', 'r') as fp: |
60 g_mynick = Config.get_value ('nickname', default='cobalt') |
| 59 g_config = json.loads (fp.read()) |
|
| 60 except IOError as e: |
|
| 61 print 'couldn\'t open cobalt.json: %s' % e |
|
| 62 quit() |
|
| 63 |
|
| 64 g_admins = g_config['admins'] |
|
| 65 g_mynick = g_config['nickname'] |
|
| 66 |
|
| 67 g_BotActive = False |
61 g_BotActive = False |
| 68 g_needCommitsTxtRebuild = True |
62 g_needCommitsTxtRebuild = True |
| 69 |
63 |
| 70 # |
64 # |
| 71 # SOAP stuff |
65 # SOAP stuff |
| 82 pass |
76 pass |
| 83 |
77 |
| 84 btannounce_active = False |
78 btannounce_active = False |
| 85 btannounce_timeout = 0 |
79 btannounce_timeout = 0 |
| 86 |
80 |
| 87 def save_config(): |
|
| 88 with open ('cobalt.json', 'w') as fp: |
|
| 89 json.dump (g_config, fp, sort_keys = True, indent = 4) |
|
| 90 |
|
| 91 def cfg (key, default): |
|
| 92 if not hasattr (g_config, key): |
|
| 93 g_config[key] = default |
|
| 94 save_config() |
|
| 95 return default |
|
| 96 return g_config[key] |
|
| 97 |
|
| 98 def bt_updatechecktimeout(): |
81 def bt_updatechecktimeout(): |
| 99 global btannounce_timeout |
82 global btannounce_timeout |
| 100 btannounce_timeout = time.time() + (cfg ('btlatest_checkinterval', 5) * 60) |
83 btannounce_timeout = time.time() + (Config.get_node ('bt').get_value ('checkinterval', default=5) * 60) |
| |
84 |
| |
85 def bt_credentials(): |
| |
86 bt = Config.get_node ('bt') |
| |
87 user = bt.get_value ('username', '') |
| |
88 password = bt.get_value ('password', '') |
| |
89 return [user, password] |
| 101 |
90 |
| 102 if suds_active: |
91 if suds_active: |
| 103 try: |
92 sys.stdout.write ('Retrieving latest tracker ticket... ') |
| 104 sys.stdout.write ('Retrieving latest tracker ticket... ') |
93 user, password = bt_credentials() |
| 105 btannounce_id = suds_client.service.mc_issue_get_biggest_id (g_config['trackeruser'], g_config['trackerpassword'], 0) |
94 btannounce_id = suds_client.service.mc_issue_get_biggest_id (user, password, 0) |
| 106 btannounce_active = True |
95 btannounce_active = True |
| 107 bt_updatechecktimeout() |
96 bt_updatechecktimeout() |
| 108 print btannounce_id |
97 print btannounce_id |
| 109 except Exception as e: |
|
| 110 pass |
|
| 111 |
98 |
| 112 def bt_getissue(ticket): |
99 def bt_getissue(ticket): |
| 113 global suds_client |
100 global suds_client |
| 114 global g_config |
101 user, password = bt_credentials() |
| 115 return suds_client.service.mc_issue_get (g_config['trackeruser'], g_config['trackerpassword'], ticket) |
102 return suds_client.service.mc_issue_get (user, password, ticket) |
| 116 |
103 |
| 117 def bt_checklatest(): |
104 def bt_checklatest(): |
| 118 global btannounce_timeout |
105 global btannounce_timeout |
| 119 global btannounce_id |
106 global btannounce_id |
| 120 |
107 |
| 121 if time.time() >= btannounce_timeout: |
108 if time.time() >= btannounce_timeout: |
| 122 bt_updatechecktimeout() |
109 bt_updatechecktimeout() |
| 123 newid = btannounce_id |
110 newid = btannounce_id |
| 124 try: |
111 try: |
| 125 newid = suds_client.service.mc_issue_get_biggest_id (g_config['trackeruser'], g_config['trackerpassword'], 0) |
112 user, password = bt_credentials() |
| |
113 newid = suds_client.service.mc_issue_get_biggest_id (user, password, 0) |
| 126 except Exception as e: |
114 except Exception as e: |
| 127 pass |
115 pass |
| 128 |
116 |
| 129 while newid > btannounce_id: |
117 while newid > btannounce_id: |
| 130 try: |
118 try: |
| 273 check_repo_exists ('zandronum-stable', 'Torr_Samaho') |
261 check_repo_exists ('zandronum-stable', 'Torr_Samaho') |
| 274 check_repo_exists ('zandronum-sandbox', 'crimsondusk') |
262 check_repo_exists ('zandronum-sandbox', 'crimsondusk') |
| 275 check_repo_exists ('zandronum-sandbox-stable', 'crimsondusk') |
263 check_repo_exists ('zandronum-sandbox-stable', 'crimsondusk') |
| 276 check_repo_exists ('zandronum-everything', '') |
264 check_repo_exists ('zandronum-everything', '') |
| 277 |
265 |
| 278 repocheck_timeout = {'zandronum':(time.time()) + 15, 'zandronum-stable':(time.time() + 15), 'zandronum-sandbox':(time.time()) + 15, 'zandronum-sandbox-stable':(time.time()) + 15} |
266 repocheck_timeout = {(time.time()) + 15} |
| 279 |
267 |
| 280 def get_commit_data (zanrepo, rev, template): |
268 def get_commit_data (zanrepo, rev, template): |
| 281 return zanrepo.hg_command ('log', '-l', '1', '-r', rev, '--template', template) |
269 return zanrepo.hg_command ('log', '-l', '1', '-r', rev, '--template', template) |
| 282 #enddef |
270 #enddef |
| 283 |
271 |
| 332 ' Retrieves and processes commits for zandronum repositories ' |
320 ' Retrieves and processes commits for zandronum repositories ' |
| 333 ' Ensure both repositories are OK before using this! ' |
321 ' Ensure both repositories are OK before using this! ' |
| 334 def process_zan_repo_updates (repo_name): |
322 def process_zan_repo_updates (repo_name): |
| 335 global repocheck_timeout |
323 global repocheck_timeout |
| 336 global suds_client |
324 global suds_client |
| 337 global g_config |
|
| 338 global g_clients |
325 global g_clients |
| |
326 |
| |
327 hgns = Config.get_node ('hg') |
| |
328 |
| |
329 if not hgns.get_value ('track', default=True): |
| |
330 return |
| 339 |
331 |
| 340 usestable = repo_name == 'zandronum-stable' |
332 usestable = repo_name == 'zandronum-stable' |
| 341 usesandbox = repo_name == 'zandronum-sandbox' or repo_name == 'zandronum-sandbox-stable' |
333 usesandbox = repo_name == 'zandronum-sandbox' or repo_name == 'zandronum-sandbox-stable' |
| 342 repo_owner = 'Torr_Samaho' if not usesandbox else 'crimsondusk' |
334 repo_owner = 'Torr_Samaho' if not usesandbox else 'crimsondusk' |
| 343 repo_url = 'https://bitbucket.org/%s/%s' % (repo_owner, repo_name) |
335 repo_url = 'https://bitbucket.org/%s/%s' % (repo_owner, repo_name) |
| 344 num_commits = 0 |
336 num_commits = 0 |
| 345 |
337 btuser, btpassword = bt_credentials() |
| 346 if time.time() < repocheck_timeout[repo_name]: |
338 |
| |
339 if time.time() < repocheck_timeout: |
| 347 return |
340 return |
| 348 |
341 |
| 349 repocheck_timeout[repo_name] = time.time() + (cfg ('hg_checkinterval', 15) * 60) |
342 repocheck_timeout = time.time() + hgns.get_value ('checkinterval', default=15) * 60 |
| 350 zanrepo = hgapi.Repo (repo_name) |
343 zanrepo = hgapi.Repo (repo_name) |
| 351 commit_data = [] |
344 commit_data = [] |
| 352 delimeter = '@@@@@@@@@@' |
345 delimeter = '@@@@@@@@@@' |
| 353 |
346 |
| 354 try: |
347 try: |
| 550 need_update = True |
542 need_update = True |
| 551 #fi |
543 #fi |
| 552 |
544 |
| 553 # Announce on IRC |
545 # Announce on IRC |
| 554 for irc_client in g_clients: |
546 for irc_client in g_clients: |
| 555 for channel in irc_client.cfg['channels']: |
547 for channel in irc_client.channels: |
| 556 if 'btannounce' in channel and channel['btannounce'] == True: |
548 if channel.get_value ('btannounce', default=True): |
| 557 irc_client.privmsg (channel['name'], |
549 irc_client.privmsg (channel.get_value ('name'), |
| 558 "%s: commit %s fixes issue %d: %s" |
550 "%s: commit %s fixes issue %d: %s" |
| 559 % (repo_name, commit_node, ticket_id, commit_message)) |
551 % (repo_name, commit_node, ticket_id, commit_message)) |
| 560 irc_client.privmsg (channel['name'], |
552 irc_client.privmsg (channel.get_value ('name'), |
| 561 "Read all about it here: " + irc_client.get_ticket_url (ticket_id)) |
553 "Read all about it here: " + irc_client.get_ticket_url (ticket_id)) |
| 562 #fi |
554 #fi |
| 563 #done |
555 #done |
| 564 #done |
556 #done |
| 565 |
557 |
| 566 if need_update: |
558 if need_update: |
| 567 # We need to remove the note data, otherwise the ticket notes |
559 # We need to remove the note data, otherwise the ticket notes |
| 568 # will get unnecessary updates. WTF, MantisBT? |
560 # will get unnecessary updates. WTF, MantisBT? |
| 569 ticket_data.notes = [] |
561 ticket_data.notes = [] |
| 570 suds_client.service.mc_issue_update (g_config['trackeruser'], g_config['trackerpassword'], ticket_id, ticket_data) |
562 suds_client.service.mc_issue_update (btuser, btpassword, ticket_id, ticket_data) |
| 571 #fi |
563 #fi |
| 572 |
564 |
| 573 suds_client.service.mc_issue_note_add (g_config['trackeruser'], g_config['trackerpassword'], ticket_id, { 'text': message }) |
565 suds_client.service.mc_issue_note_add (btuser, btpassword, ticket_id, { 'text': message }) |
| 574 num_commits += 1 |
566 num_commits += 1 |
| 575 except Exception as e: |
567 except Exception as e: |
| 576 chanlog ('Error while processing %s: %s' % (commit_node, `e`)) |
568 chanlog ('Error while processing %s: %s' % (commit_node, `e`)) |
| 577 continue |
569 continue |
| 578 #tried |
570 #tried |
| 587 # |
579 # |
| 588 # Main IRC client class |
580 # Main IRC client class |
| 589 # |
581 # |
| 590 class irc_client (asyncore.dispatcher): |
582 class irc_client (asyncore.dispatcher): |
| 591 def __init__ (self, cfg, flags): |
583 def __init__ (self, cfg, flags): |
| 592 self.name = cfg['name'] |
584 self.name = cfg.get_value ('name') |
| 593 self.host = cfg['address'] |
585 self.host = cfg.get_value ('address') |
| 594 self.port = cfg['port'] |
586 self.port = cfg.get_value ('port', default=6667) |
| 595 self.password = cfg['password'] if 'password' in cfg else '' |
587 self.password = cfg.get_value ('password', default='') |
| 596 self.channels = cfg['channels'] |
588 self.channels = cfg.get_nodelist ('channels') |
| 597 self.flags = flags |
589 self.flags = flags |
| 598 self.send_buffer = list() |
590 self.send_buffer = [] |
| 599 self.umode = cfg['umode'] if 'umode' in cfg else '' |
591 self.umode = cfg.get_value ('umode', default='') |
| 600 self.cfg = cfg |
592 self.cfg = cfg |
| 601 self.mynick = '' |
593 self.desired_name = Config.get_value ('nickname', default='cobalt') |
| 602 self.verbose = g_config['verbose'] if 'verbose' in g_config else False |
594 self.mynick = self.desired_name |
| 603 self.commandprefix = g_config['commandprefix'][0] if 'commandprefix' in g_config else '.' |
595 self.verbose = Config.get_value ('verbose', default=False) |
| 604 |
596 self.commandprefix = Config.get_value ('commandprefix', default='.') |
| 605 for channel in self.channels: |
597 |
| 606 if not 'logchannel' in channel: |
|
| 607 channel['logchannel'] = False |
|
| 608 channel['namesdone'] = True |
|
| 609 #channel['haslinkbot'] = False |
|
| 610 |
|
| 611 if not 'conflictsuffix' in self.cfg: |
|
| 612 self.cfg['conflictsuffix'] = '`' |
|
| 613 |
|
| 614 self.desired_name = self.cfg['nickname'] if 'nickname' in self.cfg else g_config['nickname'] |
|
| 615 g_clients.append (self) |
598 g_clients.append (self) |
| 616 asyncore.dispatcher.__init__ (self) |
599 asyncore.dispatcher.__init__ (self) |
| 617 self.create_socket (socket.AF_INET, socket.SOCK_STREAM) |
600 self.create_socket (socket.AF_INET, socket.SOCK_STREAM) |
| 618 self.connect ((self.host, self.port)) |
601 self.connect ((self.host, self.port)) |
| 619 |
602 |
| 620 def register_to_irc (self): |
603 def register_to_irc (self): |
| 621 ident = self.cfg['ident'] if 'ident' in self.cfg else g_config['ident'] |
604 ident = Config.get_value ('ident', default='cobalt') |
| 622 gecos = self.cfg['gecos'] if 'gecos' in self.cfg else g_config['gecos'] |
605 gecos = Config.get_value ('gecos', default='cobalt') |
| 623 if 'password' in self.cfg: |
606 self.write ("PASS %s" % self.password) |
| 624 self.write ("PASS %s" % self.cfg['password']) |
|
| 625 self.write ("USER %s * * :%s" % (ident, gecos)) |
607 self.write ("USER %s * * :%s" % (ident, gecos)) |
| 626 self.write ("NICK %s" % self.mynick) |
608 self.write ("NICK %s" % self.mynick) |
| 627 |
609 |
| 628 def handle_connect (self): |
610 def handle_connect (self): |
| 629 self.mynick = self.desired_name |
|
| 630 print "Connected to [%s] %s:%d" % (self.name, self.host, self.port) |
611 print "Connected to [%s] %s:%d" % (self.name, self.host, self.port) |
| 631 self.register_to_irc() |
612 self.register_to_irc() |
| 632 |
613 |
| 633 def write (self, utfdata): |
614 def write (self, utfdata): |
| 634 try: |
615 try: |
| 673 words = line.split(" ") |
654 words = line.split(" ") |
| 674 if len(words) >= 2: |
655 if len(words) >= 2: |
| 675 if words[1] == "001": |
656 if words[1] == "001": |
| 676 self.flags |= CLIF_CONNECTED |
657 self.flags |= CLIF_CONNECTED |
| 677 |
658 |
| 678 for channel in self.cfg['channels']: |
659 for channel in self.channels: |
| 679 self.write ("JOIN %s %s" % (channel['name'], channel['password'] if 'password' in channel else '')) |
660 self.write ("JOIN %s %s" % (channel.get_value ('name'), channel.get_value ('password', default=''))) |
| 680 |
661 |
| 681 if 'umode' in self.cfg: |
662 umode = self.cfg.get_value ('umode', '') |
| 682 self.write ('MODE %s %s' % (self.mynick, self.cfg['umode'])) |
663 |
| |
664 if umode != '': |
| |
665 self.write ('MODE %s %s' % (self.mynick, self.cfg.get_value ('umode', ''))) |
| 683 elif words[1] == "PRIVMSG": |
666 elif words[1] == "PRIVMSG": |
| 684 self.handle_privmsg (line) |
667 self.handle_privmsg (line) |
| 685 elif words[1] == 'JOIN': |
|
| 686 rex = re.compile (r'^:([^!]+)!([^@]+)@([^ ]+) JOIN :#(.+)') |
|
| 687 match = rex.match (line) |
|
| 688 |
|
| 689 #if match and match.group(1).toLower() == 'linkbot': |
|
| 690 #channel_by_name (match.group(4))['haslinkbot'] = True |
|
| 691 elif words[1] == 'QUIT': |
668 elif words[1] == 'QUIT': |
| 692 rex = re.compile (r'^:([^!]+)!([^@]+)@([^ ]+) QUIT') |
669 rex = re.compile (r'^:([^!]+)!([^@]+)@([^ ]+) QUIT') |
| 693 match = rex.match (line) |
670 match = rex.match (line) |
| 694 |
671 |
| 695 # Try reclaim our nickname if possible |
672 # Try reclaim our nickname if possible |
| 696 if match and match.group(1) == self.desired_name: |
673 if match and match.group(1) == self.desired_name: |
| 697 self.mynick = self.desired_name |
674 self.mynick = self.desired_name |
| 698 self.write ("NICK %s" % self.mynick) |
675 self.write ("NICK %s" % self.mynick) |
| 699 |
|
| 700 #if match and match.group(1).toLower() == 'linkbot': |
|
| 701 #for channel in self.channels: |
|
| 702 #channels['haslinkbot'] = False |
|
| 703 elif words[1] == "433": |
676 elif words[1] == "433": |
| 704 #:irc.localhost 433 * cobalt :Nickname is already in use. |
677 #:irc.localhost 433 * cobalt :Nickname is already in use. |
| 705 self.mynick = '%s%s' % (self.mynick, self.cfg['conflictsuffix']) |
678 self.mynick += self.cfg.get_value ('conflictsuffix', default='`') |
| 706 self.write ("NICK %s" % self.mynick) |
679 self.write ("NICK " + self.mynick) |
| 707 |
680 |
| 708 # Check for new issues on the bugtracker |
681 # Check for new issues on the bugtracker |
| 709 bt_checklatest() |
682 bt_checklatest() |
| 710 |
683 |
| 711 # Check for new commits in the repositories |
684 # Check for new commits in the repositories |
| 712 for n in ['zandronum-stable', 'zandronum', 'zandronum-sandbox', 'zandronum-sandbox-stable']: |
685 for n in ['zandronum-stable', 'zandronum', 'zandronum-sandbox', 'zandronum-sandbox-stable']: |
| 713 process_zan_repo_updates (n) |
686 process_zan_repo_updates (n) |
| 714 |
687 |
| 715 def channel_by_name (self, name): |
688 def channel_by_name (self, name): |
| 716 for channel in self.channels: |
689 for channel in self.channels: |
| 717 if channel['name'].upper() == args[0].upper(): |
690 if channel.get_value ('name').upper() == args[0].upper(): |
| 718 return channel |
691 return channel |
| 719 else: |
692 else: |
| 720 raise logical_exception ('unknown channel ' + args[0]) |
693 raise logical_exception ('unknown channel ' + args[0]) |
| 721 |
694 |
| 722 # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # |
695 # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # |
| 733 channel = match.group (4) |
706 channel = match.group (4) |
| 734 message = match.group (5) |
707 message = match.group (5) |
| 735 replyto = channel if channel != g_mynick else sender |
708 replyto = channel if channel != g_mynick else sender |
| 736 |
709 |
| 737 # Check for tracker url in the message |
710 # Check for tracker url in the message |
| 738 http_regex = re.compile (r'.*http(s?)://%s/view\.php\?id=([0-9]+).*' % g_config['trackerurl']) |
711 url = Config.get_node ('bt').get_value ('url') |
| |
712 http_regex = re.compile (r'.*http(s?)://%s/view\.php\?id=([0-9]+).*' % url) |
| 739 http_match = http_regex.match (line) |
713 http_match = http_regex.match (line) |
| 740 |
714 |
| 741 # Check for command. |
715 # Check for command. |
| 742 if len(message) >= 2 and message[0] == self.commandprefix and message[1] != self.commandprefix: |
716 if len(message) >= 2 and message[0] == self.commandprefix and message[1] != self.commandprefix: |
| 743 stuff = message[1:].split(' ') |
717 stuff = message[1:].split(' ') |
| 757 # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # |
731 # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # |
| 758 # |
732 # |
| 759 # Get the URL for a specified ticket |
733 # Get the URL for a specified ticket |
| 760 # |
734 # |
| 761 def get_ticket_url (self, ticket): |
735 def get_ticket_url (self, ticket): |
| 762 return 'https://%s/view.php?id=%s' % (g_config['trackerurl'], ticket) |
736 url = Config.get_node ('bt').get_value ('url') |
| |
737 return 'https://%s/view.php?id=%s' % (url, ticket) |
| 763 |
738 |
| 764 # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # |
739 # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # |
| 765 # |
740 # |
| 766 # Retrieve a ticket from mantisbt |
741 # Retrieve a ticket from mantisbt |
| 767 # |
742 # |
| 818 # |
790 # |
| 819 def handle_command (self, sender, ident, host, replyto, command, args, message): |
791 def handle_command (self, sender, ident, host, replyto, command, args, message): |
| 820 kvargs = {'sender': sender, 'ident': ident, 'host': host, 'replyto': replyto, 'cmdname': command, 'message': message} |
792 kvargs = {'sender': sender, 'ident': ident, 'host': host, 'replyto': replyto, 'cmdname': command, 'message': message} |
| 821 |
793 |
| 822 try: |
794 try: |
| 823 result = CommandHandler.call_command (self, **kvargs) |
795 result = ModuleCore.call_command (self, **kvargs) |
| 824 |
796 |
| 825 if result: |
797 if result: |
| 826 return |
798 return |
| 827 else: |
799 except ModuleCore.CommandError as e: |
| 828 print 'CommandHandler.call_command returned false' |
|
| 829 except CommandHandler.CommandError as e: |
|
| 830 lines = str (e).split ('\n') |
800 lines = str (e).split ('\n') |
| 831 self.privmsg (replyto, 'error: %s' % lines[0]) |
801 self.privmsg (replyto, 'error: %s' % lines[0]) |
| 832 |
802 |
| 833 for line in lines[1:]: |
803 for line in lines[1:]: |
| 834 self.privmsg (replyto, ' ' + line) |
804 self.privmsg (replyto, ' ' + line) |
| 1028 idstring = "0" + idstring |
998 idstring = "0" + idstring |
| 1029 |
999 |
| 1030 isprivate = data['view_state']['name'] == 'private' |
1000 isprivate = data['view_state']['name'] == 'private' |
| 1031 reporter = data['reporter']['name'] if hasattr (data['reporter'], 'name') else '<nobody>' |
1001 reporter = data['reporter']['name'] if hasattr (data['reporter'], 'name') else '<nobody>' |
| 1032 |
1002 |
| 1033 for channel in self.cfg['channels']: |
1003 for channel in self.channels: |
| 1034 if 'btannounce' in channel and channel['btannounce'] == True: |
1004 if channel.get_value ('btannounce', False): |
| 1035 if not isprivate or ('btprivate' in channel and channel['btprivate'] == True): |
1005 if not isprivate or (channel.get_value ('btprivate', False)): |
| 1036 self.write ("PRIVMSG %s :[%s] New issue %s, reported by %s: %s: %s" % \ |
1006 self.write ("PRIVMSG %s :[%s] New issue %s, reported by %s: %s: %s" % \ |
| 1037 (channel['name'], data['project']['name'], idstring, reporter, |
1007 (channel['name'], data['project']['name'], idstring, reporter, |
| 1038 data['summary'], self.get_ticket_url (idstring))) |
1008 data['summary'], self.get_ticket_url (idstring))) |
| 1039 #fi |
1009 #fi |
| 1040 #fi |
1010 #fi |
| 1066 |
1036 |
| 1067 # |
1037 # |
| 1068 # Main procedure: |
1038 # Main procedure: |
| 1069 # |
1039 # |
| 1070 try: |
1040 try: |
| 1071 for aconn in g_config['autoconnect']: |
1041 autoconnects = Config.get_value ('autoconnect', []) |
| 1072 for conndata in g_config['connections']: |
1042 |
| 1073 if conndata['name'] == aconn: |
1043 if len (autoconnects) == 0: |
| |
1044 print "Nowhere to connect." |
| |
1045 quit() |
| |
1046 |
| |
1047 for aconn in autoconnects: |
| |
1048 for conndata in Config.get_nodelist ('connections'): |
| |
1049 if conndata.get_value ('name') == aconn: |
| 1074 irc_client (conndata, 0) |
1050 irc_client (conndata, 0) |
| 1075 break |
1051 break |
| 1076 else: |
1052 else: |
| 1077 raise logical_exception ("unknown autoconnect entry %s" % (aconn)) |
1053 raise ValueError ("unknown autoconnect entry %s" % (aconn)) |
| 1078 |
1054 |
| 1079 g_BotActive = True |
1055 g_BotActive = True |
| 1080 asyncore.loop() |
1056 asyncore.loop() |
| 1081 except KeyboardInterrupt: |
1057 except KeyboardInterrupt: |
| 1082 for client in g_clients: |
1058 for client in g_clients: |
| 1083 client.keyboardinterrupt() |
1059 client.keyboardinterrupt() |