Пример #1
0
def calc_list():
    '''Generate data'''
    output = []
    people_list = []
    flag = 0
    group_name = 'cla_done'
    username = raw_input("Username: "******"Password: "******" " + item[
                'username'] + " " + item['email'] + " " + str(
                    item['country_code']) + " " + item['status'] + "\n"
            output_file.write(output_data)

    output_file.close()

    print 'File successfully generated!'
Пример #2
0
    def __init__(self, fas_username, fas_password, fas_url):
        self.fasclient = AccountSystem(fas_url,
                                       username=fas_username,
                                       password=fas_password)

        anonymous = User(name='', fullname='', emails=[])
        self.fasuser = {'': anonymous}
Пример #3
0
    def __init__(self, irc):
        super(Fedora, self).__init__(irc)

        # caches, automatically downloaded on __init__, manually refreshed on
        # .refresh
        self.userlist = None

        # To get the information, we need a username and password to FAS.
        # DO NOT COMMIT YOUR USERNAME AND PASSWORD TO THE PUBLIC REPOSITORY!
        self.fasurl = self.registryValue('fas.url')
        self.username = self.registryValue('fas.username')
        self.password = self.registryValue('fas.password')

        self.fasclient = AccountSystem(self.fasurl,
                                       username=self.username,
                                       password=self.password)
        # URLs
        # self.url = {}

        self.github_oauth_token = self.registryValue('github.oauth_token')

        self.karma_tokens = ('++', '--') if self.allow_negative else ('++', )

        # fetch necessary caches
        self._refresh()

        # Pull in /etc/fedmsg.d/ so we can build the fedmsg.meta processors.
        fm_config = fedmsg.config.load_config()
        fedmsg.meta.make_processors(**fm_config)
Пример #4
0
    def fasidCheck(request):
        try:
            fas = AccountSystem(username=settings.ADMIN_USERNAME, password=settings.ADMIN_PASSWORD)
            fasid = request.GET['fasid']
            person = fas.person_by_username(fasid)
            if not person:
                logger.error("The FAS username does not exist!")
                response = JsonResponse({'error':'The FAS username does not exist!'})
                response.status_code = 404
                return response
            if person['privacy']:
                logger.warning("The privacy is set to not view the name!")
            user = {
                'privacy': person['privacy'],
                'email': person['email'],
                'name': person['human_name']
            }
            request.session['fasid'] = fasid
            request.session['recipient_email'] = person['email']
            return JsonResponse(user)

        except Exception as ex:
            response = JsonResponse({'error': 'Internal Server Error'})
            response.status_code = 500
            return response
Пример #5
0
 def form_valid(self, form):
     message = form.save(commit=False)
     message.sender_ip = self.request.META['REMOTE_ADDR']
     message.sender_name = self.request.user.first_name
     message.sender_email = self.request.user.email
     message.save()
     if self.request.session.get('fasid',False) and self.request.session.get('recipient_email',False) == message.recipient_email:
         message.recipient_username = self.request.session['fasid']
     elif '@fedoraproject.org' in message.recipient_email:
         message.recipient_username = message.recipient_email[0:-18]
     else:
         fas = AccountSystem(username=settings.ADMIN_USERNAME, password=settings.ADMIN_PASSWORD)
         try:
             query = fas.people_query(constraints={'email': message.recipient_email}, columns=['username'])
         except AppError as error:
             logger.error(error) 
         else:
             if query:
                 message.recipient_username = query[0]['username']
             else:
                 logger.warn("No FAS username associated with the recipient's email ID.")  
     message.save()  
     if self.request.session.get('fasid', False):
         del self.request.session['fasid']
         del self.request.session['recipient_email']
     message.send_sender_confirmation(self.request.is_secure(), self.request.get_host())
     return HttpResponseRedirect(reverse('messaging:sender_confirmation_sent'))
Пример #6
0
def init_globals():
    '''Initialize global variables.

This is mostly connections to services like FAS, bugzilla, and loading
    constants from the database.
    '''
    global fas, LOG, STATUS
    # Things to do on startup
    STATUS = StatusCache()
    STATUS.refresh_status()
    LOG = logging.getLogger('pkgdb.controllers')

    # Get a connection to the Account System server
    fas_url = config.get('fas.url',
                         'https://admin.fedoraproject.org/accounts/')
    username = config.get('fas.username', 'admin')
    password = config.get('fas.password', 'admin')

    fas = AccountSystem(fas_url,
                        username=username,
                        password=password,
                        cache_session=False)
    fas.cache = UserCache(fas)

    view.variable_providers.append(custom_template_vars)
Пример #7
0
def get_email():
	uid = raw_input("Enter the username you wish to search> ") 
	fas = AccountSystem(username=str(USERNAME), password=str(PASSWORD))
	value = fas.people_by_key(key='email', search=uid, fields=['email'])
	email_id = value.keys()
	if str(email_id)[12:][:-3] == '':
		print ("No email id associated to this account")
	else:
		print ("Email id to the user " + str(uid) + " is " +str(email_id)[12:][:-3])
	sys.exit()
Пример #8
0
def get_email(id):
    print()
    fas = AccountSystem(username=USERNAME, password=PASSWORD)
    value = fas.people_by_key(key='email', search=id, fields=['email'])
    mail = value.keys()
    if str(mail)[12:][:-3] == '':
        print(colors.RED + "[-]NO EMAIL FOUND!!! \n[-]QUITTING NOW..." +
              colors.STOP + "\n")
    else:
        print(colors.GREEN + "[+]EMAIL:    " + str(mail)[12:][:-3] +
              colors.STOP + "\n")
    sys.exit(0)
Пример #9
0
 def create_fas_object(self):
     if self._environ:
         identity = self._environ.get('repoze.who.identity')
     else:
         identity = None
     if identity:
         return AccountSystem(base_url=self._base_url,
                              session_id=identity.get('session_id'))
     else:
         return AccountSystem(base_url=self._base_url,
                              username=_fas_minimal_user,
                              password=_fas_minimal_pass)
Пример #10
0
 def __init__(self, config):
     self.fas = AccountSystem(
         "https://admin.fedoraproject.org/accounts",
         username=config["fas"]["username"],
         password=config["fas"]["password"],
     )
     self._replay = config["replay"]
     self._recorder = vcr.VCR(
         ignore_hosts=config["ipa"]["instances"],
         record_mode="new_episodes",
         match_on=["method", "path", "query", "body"],
     )
Пример #11
0
def get_email(username):
    USER_NAME = str(input("Enter your user name: "))
    PASSWORD = str(input("Enter password: "))
    try:
        fas = AccountSystem(username=USER_NAME, password=PASSWORD)
        people = fas.people_by_key(key='username',
                                   search=username,
                                   fields=['email'])
        if username in people:
            return people[username]['email']
        return 0
    except AuthError as e:
        print(str(e))
        exit()
Пример #12
0
 def __init__(self, config, inst_conf):
     self.inst_conf = inst_conf
     self.fas = AccountSystem(
         inst_conf["url"],
         username=inst_conf["username"],
         password=inst_conf["password"],
     )
     self._replay = config["replay"]
     self._recorder = vcr.VCR(
         ignore_hosts=config["ipa"]["instances"],
         record_mode="new_episodes",
         filter_post_data_parameters=self._remove_from_request_body,
     )
     self._recorder.register_matcher("fas2ipa", self._vcr_match_request)
Пример #13
0
    def __init__(self, irc):
        super(Fedora, self).__init__(irc)

        # caches, automatically downloaded on __init__, manually refreshed on
        # .refresh
        self.userlist = None
        self.bugzacl = None

        # To get the information, we need a username and password to FAS.
        # DO NOT COMMIT YOUR USERNAME AND PASSWORD TO THE PUBLIC REPOSITORY!
        self.fasurl = self.registryValue('fas.url')
        self.username = self.registryValue('fas.username')
        self.password = self.registryValue('fas.password')

        self.fasclient = AccountSystem(self.fasurl, username=self.username,
                                       password=self.password)
        self.pkgdb = PkgDB()
        # URLs
        # self.url = {}

        self.github_oauth_token = self.registryValue('github.oauth_token')

        # fetch necessary caches
        self._refresh()

        # Pull in /etc/fedmsg.d/ so we can build the fedmsg.meta processors.
        fm_config = fedmsg.config.load_config()
        fedmsg.meta.make_processors(**fm_config)
Пример #14
0
def get_fas():  # pragma: no cover
    ''' Retrieve a connection to the Fedora Account System.
    '''
    global _FAS
    if _FAS is not None:
        return _FAS

    # Get a connection to FAS
    fas_url = pkgdb2.APP.config['PKGDB2_FAS_URL']
    if not fas_url:
        raise pkgdb2.lib.PkgdbException('No PKGDB2_FAS_URL configured')

    fas_user = pkgdb2.APP.config['PKGDB2_FAS_USER']
    if not fas_user:  # pragma: no cover
        raise pkgdb2.lib.PkgdbException('No PKGDB2_FAS_USER configured')

    fas_pass = pkgdb2.APP.config['PKGDB2_FAS_PASSWORD']
    if not fas_pass:  # pragma: no cover
        raise pkgdb2.lib.PkgdbException('No PKGDB2_FAS_PASSWORD configured')

    fas_insecure = pkgdb2.APP.config.get('PKGDB2_FAS_INSECURE', False)

    _FAS = AccountSystem(fas_url,
                         username=fas_user,
                         password=fas_pass,
                         cache_session=False,
                         insecure=fas_insecure)

    return _FAS
Пример #15
0
def get_fas(config):
    """ Return a fedora.client.fas2.AccountSystem object if the provided
    configuration contains a FAS username and password.
    """
    global _FAS
    if _FAS is not None:
        return _FAS

    # In some development environments, having fas_credentials around is a
    # pain.. so, let things proceed here, but emit a warning.
    try:
        creds = config['fas_credentials']
    except KeyError:
        log.warning("No fas_credentials available.  Unable to query FAS.")
        return None

    default_url = 'https://admin.fedoraproject.org/accounts/'

    _FAS = AccountSystem(creds.get('base_url', default_url),
                         username=creds['username'],
                         password=creds['password'],
                         cache_session=False,
                         insecure=creds.get('insecure', False))

    return _FAS
Пример #16
0
    def __init__(self, fas_username, fas_password, fas_url):
        ''' Instantiate a FASclient object '''

        self.fasclient = AccountSystem(fas_url, username=fas_username,
                                       password=fas_password)

        anonymous = User(name='', fullname='', emails=[])
        self.fasuser = {'': anonymous}
Пример #17
0
 def fas_client(self):
     if not self._fas_client:
         self._fas_client = AccountSystem(base_url=self.fas_url,
                                          insecure=self.insecure,
                                          useragent=self.user_agent,
                                          username=self.bind_user,
                                          password=self.bind_pass)
     return self._fas_client
Пример #18
0
def create_user_cert(username=None):
    if not username:
        username = input('FAS Username: '******'FAS Password: '******'https://admin.rpmfusion.org/accounts/',
                            username=username,
                            password=password)
        cert = fas.user_gencert()
        fas.logout()
    except AuthError:
        raise rpmfusion_cert_error("Invalid username/password.")
    except CLAError:
        fas.logout()
        raise rpmfusion_cert_error(
            """You must sign the CLA before you can generate your certificate.\n
To do this, go to https://admin.rpmfusion.org/accounts/cla/""")
    cert_file = os.path.join(os.path.expanduser('~'), ".rpmfusion.cert")
    try:
        FILE = open(cert_file, "w")
        FILE.write(cert)
        FILE.close()
    except:
        raise rpmfusion_cert_error("""Can not open cert file for writing.
Please paste certificate into ~/.rpmfusion.cert\n\n%s""" % cert)
Пример #19
0
    def __init__(self, bot):
        self.bot = bot

        fas_url = bot.config['fas']['url']
        fas_username = bot.config['fas']['username']
        fas_password = bot.config['fas']['password']
        self.fasclient = AccountSystem(fas_url,
                                       username=fas_username,
                                       password=fas_password)

        #self.log.info("Downloading package owners cache")
        data = requests.get(
            'https://admin.fedoraproject.org/pkgdb/api/bugzilla?format=json',
            verify=True).json()
        self.bugzacl = data['bugzillaAcls']

        self.pkgdb = PkgDB()

        # Pull in /etc/fedmsg.d/ so we can build the fedmsg.meta processors.
        fm_config = fedmsg.config.load_config()
        fedmsg.meta.make_processors(**fm_config)
Пример #20
0
class FASWrapper:
    def __init__(self, config):
        self.fas = AccountSystem(
            "https://admin.fedoraproject.org/accounts",
            username=config["fas"]["username"],
            password=config["fas"]["password"],
        )
        self._replay = config["replay"]
        self._recorder = vcr.VCR(
            ignore_hosts=config["ipa"]["instances"],
            record_mode="new_episodes",
            match_on=["method", "path", "query", "body"],
        )

    def send_request(self, url, *args, **kwargs):
        if not self._replay:
            return self.fas.send_request(url, *args, **kwargs)

        cassette_path = ["fixtures/fas-", url[1:].replace("/", "_"), ".yaml"]
        with self._recorder.use_cassette("".join(cassette_path)):
            return self.fas.send_request(url, *args, **kwargs)
Пример #21
0
def init_globals():
    '''Initialize global variables.

This is mostly connections to services like FAS, bugzilla, and loading
    constants from the database.
    '''
    global fas, LOG, STATUS
    # Things to do on startup
    STATUS = StatusCache()
    STATUS.refresh_status()
    LOG = logging.getLogger('pkgdb.controllers')

    # Get a connection to the Account System server
    fas_url = config.get('fas.url', 'https://admin.fedoraproject.org/accounts/')
    username = config.get('fas.username', 'admin')
    password = config.get('fas.password', 'admin')

    fas = AccountSystem(fas_url, username=username, password=password,
            cache_session=False)
    fas.cache = UserCache(fas)

    view.variable_providers.append(custom_template_vars)
def calc_list():
    '''Generate data'''
    output = []
    people_list = []
    flag = 0
    group_name = 'cla_done'
    username = '******'
    password = '******'

    fas = AccountSystem(username=username, password=password)

    print 'Generating data file. Wait...'  
    data = fas.people_by_key(key='username', search=u'*', fields=['human_name', 'username', 'email', 'status', 'country_code'])
    
    output_file = codecs.open('/tmp/hungary.txt', encoding='utf-8', mode='w+')

    for item in data.values():
	if str(item['country_code']) == 'HU' and item['status'] == 'active':
	    output_data = item['human_name'] + " " + item['username'] + " " + item['email'] + " " + str(item['country_code']) + " " + item['status'] + "\n"
	    output_file.write(output_data)
	
    output_file.close()

    print 'file successfully generated'
Пример #23
0
def main():
    my_account = AccountSystem(
        username='******',
        password='******')  #initializing the account
    username = input(
        colored("[#]please enter the username you want to search for---->",
                "green"))
    if method2(
            my_account, username
    ) != "USERNAME NOT FOUND":  #well..you can change the method if you want,the results are the same
        print(
            colored(
                "[-]here is his email:-->>> " + method2(my_account, username),
                "yellow"))
    else:
        print(colored(method2(my_account, username) + "\n", "red"))
Пример #24
0
def get_fas(config):
    """ Return a fedora.client.fas2.AccountSystem object if the provided
    configuration contains a FAS username and password.
    """
    global _FAS
    if _FAS is not None:
        return _FAS

    creds = config['fas_credentials']
    default_url = 'https://admin.fedoraproject.org/accounts/'

    _FAS = AccountSystem(creds.get('base_url', default_url),
                         username=creds['username'],
                         password=creds['password'],
                         cache_session=False,
                         insecure=creds.get('insecure', False))

    return _FAS
Пример #25
0
class FASclient():
    def __init__(self, fas_username, fas_password, fas_url):
        self.fasclient = AccountSystem(fas_url,
                                       username=fas_username,
                                       password=fas_password)

        anonymous = User(name='', fullname='', emails=[])
        self.fasuser = {'': anonymous}

    def find_fas_user(self, user):

        if user not in self.fasuser.keys():
            person = self.fasclient.person_by_username(user)
            if not person:
                return self.fasuser['']

            self.fasuser[user] = User(name=user,
                                      fullname=person['human_name'],
                                      emails=[person['email']])
        return self.fasuser[user]
Пример #26
0
    def __init__(self, bot):
        self.bot = bot

        fas_url = bot.config['fas']['url']
        fas_username = bot.config['fas']['username']
        fas_password = bot.config['fas']['password']
        self.fasclient = AccountSystem(
            fas_url, username=fas_username, password=fas_password)

        #self.log.info("Downloading package owners cache")
        data = requests.get(
            'https://admin.fedoraproject.org/pkgdb/api/bugzilla?format=json',
            verify=True).json()
        self.bugzacl = data['bugzillaAcls']

        self.pkgdb = PkgDB()

        # Pull in /etc/fedmsg.d/ so we can build the fedmsg.meta processors.
        fm_config = fedmsg.config.load_config()
        fedmsg.meta.make_processors(**fm_config)
Пример #27
0
class FASclient ():
    ''' Creates a FAS User object based on the credentials given '''

    def __init__(self, fas_username, fas_password, fas_url):
        ''' Instantiate a FASclient object '''

        self.fasclient = AccountSystem(fas_url, username=fas_username,
                                       password=fas_password)

        anonymous = User(name='', fullname='', emails=[])
        self.fasuser = {'': anonymous}

    def find_fas_user(self, user):
        ''' Queries FAS and returns the FAS user '''

        if user not in self.fasuser.keys():
            person = self.fasclient.person_by_username(user)
            if not person:
                return self.fasuser['']

            self.fasuser[user] = User(name=user,
                                      fullname=person['human_name'],
                                      emails=[person['email']])
        return self.fasuser[user]
Пример #28
0
def create_user_cert(username=None):
    if not username:
        username = raw_input('FAS Username: '******'FAS Password: '******'https://admin.fedoraproject.org/accounts/', username=username, password=password)
    except AuthError:
        raise fedora_cert_error("Invalid username/password.")

    try:
        cert = fas.user_gencert()
        fas.logout()
    except CLAError:
        fas.logout()
        raise fedora_cert_error("""You must sign the CLA before you can generate your certificate.\n
To do this, go to https://admin.fedoraproject.org/accounts/cla/""")
    cert_file = os.path.join(os.path.expanduser('~'), ".fedora.cert")
    try:
        FILE = open(cert_file,"w")
        FILE.write(cert)
        FILE.close()
    except:
        raise fedora_cert_error("""Can not open cert file for writing.
Please paste certificate into ~/.fedora.cert\n\n%s""" % cert)
Пример #29
0
class FedoraPlugin:
    """A plugin is a class which take the IrcBot as argument
    """

    requires = [
        'irc3.plugins.core',
        'irc3.plugins.command',
    ]

    def __init__(self, bot):
        self.bot = bot

        fas_url = bot.config['fas']['url']
        fas_username = bot.config['fas']['username']
        fas_password = bot.config['fas']['password']
        self.fasclient = AccountSystem(
            fas_url, username=fas_username, password=fas_password)

        #self.log.info("Downloading package owners cache")
        data = requests.get(
            'https://admin.fedoraproject.org/pkgdb/api/bugzilla?format=json',
            verify=True).json()
        self.bugzacl = data['bugzillaAcls']

        self.pkgdb = PkgDB()

        # Pull in /etc/fedmsg.d/ so we can build the fedmsg.meta processors.
        fm_config = fedmsg.config.load_config()
        fedmsg.meta.make_processors(**fm_config)

    @staticmethod
    def _future_meetings(location):
        if not location.endswith('@irc.freenode.net'):
            location = '*****@*****.**' % location
        meetings = FedoraPlugin._query_fedocal(location=location)
        now = datetime.datetime.utcnow()

        for meeting in meetings:
            string = "%s %s" % (meeting['meeting_date'],
                                meeting['meeting_time_start'])
            dt = datetime.datetime.strptime(string, "%Y-%m-%d %H:%M:%S")

            if now < dt:
                yield dt, meeting

    @staticmethod
    def _meetings_for(calendar):
        meetings = FedoraPlugin._query_fedocal(calendar=calendar)
        now = datetime.datetime.utcnow()

        for meeting in meetings:
            string = "%s %s" % (meeting['meeting_date'],
                                meeting['meeting_time_start'])
            start = datetime.datetime.strptime(string, "%Y-%m-%d %H:%M:%S")
            string = "%s %s" % (meeting['meeting_date_end'],
                                meeting['meeting_time_stop'])
            end = datetime.datetime.strptime(string, "%Y-%m-%d %H:%M:%S")

            if now >= start and now <= end:
                yield meeting

    @staticmethod
    def _query_fedocal(**kwargs):
        url = 'https://apps.fedoraproject.org/calendar/api/meetings'
        return requests.get(url, params=kwargs).json()['meetings']

    @command
    def admins(self, mask, target, args):
        """admins <group name>

        Return the administrators list for the selected group

            %%admins <group_name>
        """
        name = args['<group_name>']

        msg = None
        try:
            group = self.fasclient.group_members(name)
            sponsors = ''
            for person in group:
                if person['role_type'] == 'administrator':
                    sponsors += person['username'] + ' '
            msg = 'Administrators for %s: %s' % (name, sponsors)
        except AppError:
            msg = 'There is no group %s.' % name

        if msg is not None:
            self.bot.privmsg(target, '%s: %s' % (mask.nick, msg))

    @command
    def badges(self, mask, target, args):
        """badges <username>

        Return badges statistics about a user.

            %%badges <username>
        """
        name = args['<username>']

        url = "https://badges.fedoraproject.org/user/" + name
        d = requests.get(url + "/json").json()

        if 'error' in d:
            response = d['error']
        else:
            template = "{name} has unlocked {n} Fedora Badges:  {url}"
            n = len(d['assertions'])
            response = template.format(name=name, url=url, n=n)

        self.bot.privmsg(target, '%s: %s' % (mask.nick, response))

    @command
    def branches(self, mask, target, args):
        """branches <package>

        Return the branches a package is in.

            %%branches <package>
        """
        package = args['<package>']

        try:
            pkginfo = self.pkgdb.get_package(package)
        except AppError:
            msg = "No such package exists."
            self.bot.privmsg(target, '%s: %s' % (mask.nick, msg))
            return

        branch_list = []
        for listing in pkginfo['packages']:
            branch_list.append(listing['collection']['branchname'])
        branch_list.sort()
        msg = ' '.join(branch_list)
        self.bot.privmsg(target, '%s: %s' % (mask.nick, msg))

    @command
    def fas(self, mask, target, args):
        """fas <pattern>

        Searches a pattern in the list of FAS user

            %%fas <pattern>
        """
        users = self.fasclient.people_query(
                constraints={
                    #'username': args['<pattern>'],
                    'ircnick': args['<pattern>'],
                },
                columns=['username', 'ircnick', 'email']
            )
        if users:
            msg = ', '.join(
                [
                '%s (%s) <%s>' % (user.username, user.ircnick, user.email)
                for user in users
                ]
            )
        else:
            msg = 'No user matching found'
        self.bot.privmsg(target, '%s: %s' % (mask.nick, msg))

    @command
    def fasinfo(self, mask, target, args):
        """fasinfo <pattern>

        Return more information about the specified user

            %%fasinfo <username>
        """
        name = args['<username>']

        try:
            person = self.fasclient.person_by_username(name)
        except:
            msg = 'Error getting info for user: "******"' % name
            self.bot.privmsg(target, '%s: %s' % (mask.nick, msg))
            return

        if not person:
            msg = 'User "%s" doesn\'t exist' % name
            self.bot.privmsg(target, '%s: %s' % (mask.nick, msg))
            return

        person['creation'] = person['creation'].split(' ')[0]
        string = (
            "User: %(username)s, Name: %(human_name)s"
            ", email: %(email)s, Creation: %(creation)s"
            ", IRC Nick: %(ircnick)s, Timezone: %(timezone)s"
            ", Locale: %(locale)s"
            ", GPG key ID: %(gpg_keyid)s, Status: %(status)s") % person
        self.bot.privmsg(target, '%s: %s' % (mask.nick, string))

        # List of unapproved groups is easy
        unapproved = ''
        for group in person['unapproved_memberships']:
            unapproved = unapproved + "%s " % group['name']
        if unapproved != '':
            msg = 'Unapproved Groups: %s' % unapproved
            self.bot.privmsg(target, '%s: %s' % (mask.nick, msg))

        # List of approved groups requires a separate query to extract roles
        constraints = {
            'username': name, 'group': '%',
            'role_status': 'approved'}
        columns = ['username', 'group', 'role_type']
        roles = []
        try:
            roles = self.fasclient.people_query(
                constraints=constraints,
                columns=columns)
        except:
            msg = 'Error getting group memberships.'
            self.bot.privmsg(target, '%s: %s' % (mask.nick, msg))
            return

        approved = ''
        for role in roles:
            if role['role_type'] == 'sponsor':
                approved += '+' + role['group'] + ' '
            elif role['role_type'] == 'administrator':
                approved += '@' + role['group'] + ' '
            else:
                approved += role['group'] + ' '
        if approved == '':
            approved = "None"
        msg = 'Approved Groups: %s' % approved
        self.bot.privmsg(target, '%s: %s' % (mask.nick, msg))

    @command
    def group(self, mask, target, args):
        """group <group short name>

        Return information about a Fedora Account System group.

            %%group <group_name>
        """
        name = args['<group_name>']

        msg = None
        try:
            group = self.fasclient.group_by_name(name)
            msg = '%s: %s' % (name, group['display_name'])
        except AppError:
            msg = 'There is no group "%s".' % name

        if msg is not None:
            self.bot.privmsg(target, '%s: %s' % (mask.nick, msg))

    @command
    def hellomynameis(self, mask, target, args):
        """hellomynameis <username>

        Return brief information about a Fedora Account System username. Useful
        for things like meeting roll call and calling attention to yourself.

            %%hellomynameis <username>
        """
        name = args['<username>']
        msg = None
        try:
            person = self.fasclient.person_by_username(name)
        except:
            msg = 'Something blew up, please try again'
        if not person:
            msg = 'Sorry, but you don\'t exist'
        else:
            msg = '%(username)s \'%(human_name)s\' <%(email)s>' % person

        if msg is not None:
            self.bot.privmsg(target, '%s: %s' % (mask.nick, msg))

    @command
    def himynameis(self, mask, target, args):
        """himynameis <username>

        Return information about a Fedora Account System group.

            %%himynameis <username>
        """
        name = args['<username>']
        msg = None
        try:
            person = self.fasclient.person_by_username(name)
        except:
            msg = 'Something blew up, please try again'
        if not person:
            msg = 'Sorry, but you don\'t exist'
        else:
            msg = '%(username)s \'Slim Shady\' <%(email)s>' % person

        if msg is not None:
            self.bot.privmsg(target, '%s: %s' % (mask.nick, msg))

    @command
    def localtime(self, mask, target, args):
        """localtime <username>

        Returns the current time of the user.
        The timezone is queried from FAS.

            %%localtime <username>
        """
        name = args['<username>']

        try:
            person = self.fasclient.person_by_username(name)
        except:
            msg = 'Error getting info user user: "******"' % name
            self.bot.privmsg(target, '%s: %s' % (mask.nick, msg))
            return

        if not person:
            msg = 'User "%s" doesn\'t exist' % name
            self.bot.privmsg(target, '%s: %s' % (mask.nick, msg))
            return

        timezone_name = person['timezone']
        if timezone_name is None:
            msg = 'User "%s" doesn\'t share his timezone' % name
            self.bot.privmsg(target, '%s: %s' % (mask.nick, msg))
            return
        try:
            time = datetime.datetime.now(pytz.timezone(timezone_name))
        except:
            msg = 'The timezone of "%s" was unknown: "%s"' % (
                name, timezone_name)
            self.bot.privmsg(target, '%s: %s' % (mask.nick, msg))
            return

        msg = 'The current local time of "%s" is: "%s" (timezone: %s)' % (
            name, time.strftime('%H:%M'), timezone_name)
        self.bot.privmsg(target, '%s: %s' % (mask.nick, msg))

    @command
    def members(self, mask, target, args):
        """members <group short name>

        Return the list of members for the selected group

            %%members <group_name>
        """
        name = args['<group_name>']

        msg = None
        try:
            group = self.fasclient.group_members(name)
            members = ''
            for person in group:
                if person['role_type'] == 'administrator':
                    members += '@' + person['username'] + ' '
                elif person['role_type'] == 'sponsor':
                    members += '+' + person['username'] + ' '
                else:
                    members += person['username'] + ' '
            msg = 'Members of %s: %s' % (name, members)
        except AppError:
            msg = 'There is no group %s.' % name

        if msg is not None:
            self.bot.privmsg(target, '%s: %s' % (mask.nick, msg))

    @command
    def nextmeeting(self, mask, target, args):
        """nextmeeting <channel>

        Return the next meeting scheduled for a particular channel.

            %%nextmeeting <channel>
        """
        channel = args['<channel>']

        channel = channel.strip('#').split('@')[0]
        meetings = sorted(self._future_meetings(channel), key=itemgetter(0))

        test, meetings = tee(meetings)
        try:
            test.next()
        except StopIteration:
            response = "There are no meetings scheduled for #%s." % channel
            self.bot.privmsg(target, '%s: %s' % (mask.nick, response))
            return

        for date, meeting in islice(meetings, 0, 3):
            response = "In #%s is %s (starting %s)" % (
                channel,
                meeting['meeting_name'],
                arrow.get(date).humanize(),
            )
            self.bot.privmsg(target, '%s: %s' % (mask.nick, response))
        base = "https://apps.fedoraproject.org/calendar/location/"
        url = base + urllib.quote("%[email protected]/" % channel)
        self.bot.privmsg(target, '%s: - %s' % (mask.nick, url))

    @command
    def nextmeetings(self, mask, target, args):
        """nextmeetings

        Return the next meetings scheduled for any channel(s).

            %%nextmeetings
        """
        msg = 'One moment, please...  Looking up the channel list.'
        self.bot.privmsg(target, '%s: %s' % (mask.nick, msg))

        url = 'https://apps.fedoraproject.org/calendar/api/locations/'
        locations = requests.get(url).json()['locations']
        meetings = sorted(chain(*[
            self._future_meetings(location)
            for location in locations
            if 'irc.freenode.net' in location
        ]), key=itemgetter(0))

        test, meetings = tee(meetings)
        try:
            test.next()
        except StopIteration:
            response = "There are no meetings scheduled at all."
            self.bot.privmsg(target, '%s: %s' % (mask.nick, response))
            return

        for date, meeting in islice(meetings, 0, 5):
            response = "In #%s is %s (starting %s)" % (
                meeting['meeting_location'].split('@')[0].strip(),
                meeting['meeting_name'],
                arrow.get(date).humanize(),
            )
            self.bot.privmsg(target, '%s: %s' % (mask.nick, response))

    @command
    def pushduty(self, mask, target, args):
        """pushduty

        Return the list of people who are on releng push duty right now.

            %%pushduty
        """

        def get_persons():
            for meeting in self._meetings_for('release-engineering'):
                yield meeting['meeting_name']

        persons = list(get_persons())

        url = "https://apps.fedoraproject.org/" + \
            "calendar/release-engineering/"

        if not persons:
            response = "Nobody is listed as being on push duty right now..."
            self.bot.privmsg(target, '%s: %s' % (mask.nick, response))
            self.bot.privmsg(target, '%s: - %s' % (mask.nick, url))
            return

        persons = ", ".join(persons)
        response = "The following people are on push duty: %s" % persons
        self.bot.privmsg(target, '%s: %s' % (mask.nick, response))
        self.bot.privmsg(target, '%s: - %s' % (mask.nick, url))

    @command
    def quote(self, mask, target, args):
        """quote <SYMBOL> [daily, weekly, monthly, quarterly]

        Return some datagrepper statistics on fedmsg categories.

            %%quote <symbol> <frame>
        """

        symbol = args['<symbol>']
        frame = 'daily'
        if '<frame>' in args:
            frame = args['<frame>']

        # Second, build a lookup table for symbols.  By default, we'll use the
        # fedmsg category names, take their first 3 characters and uppercase
        # them.  That will take things like "wiki" and turn them into "WIK" and
        # "bodhi" and turn them into "BOD".  This handles a lot for us.  We'll
        # then override those that don't make sense manually here.  For
        # instance "fedoratagger" by default would be "FED", but that's no
        # good.  We want "TAG".
        # Why all this trouble?  Well, as new things get added to the fedmsg
        # bus, we don't want to have keep coming back here and modifying this
        # code.  Hopefully this dance will at least partially future-proof us.
        symbols = dict([
            (processor.__name__.lower(), processor.__name__[:3].upper())
            for processor in fedmsg.meta.processors
        ])
        symbols.update({
            'fedoratagger': 'TAG',
            'fedbadges': 'BDG',
            'buildsys': 'KOJ',
            'pkgdb': 'PKG',
            'meetbot': 'MTB',
            'planet': 'PLN',
            'trac': 'TRC',
            'mailman': 'MM3',
        })

        # Now invert the dict so we can lookup the argued symbol.
        # Yes, this is vulnerable to collisions.
        symbols = dict([(sym, name) for name, sym in symbols.items()])

        # These aren't user-facing topics, so drop 'em.
        del symbols['LOG']
        del symbols['UNH']
        del symbols['ANN']  # And this one is unused...

        key_fmt = lambda d: ', '.join(sorted(d.keys()))

        if symbol not in symbols:
            response = "No such symbol %r.  Try one of %s"
            msg = response % (symbol, key_fmt(symbols))
            self.bot.privmsg(target, '%s: %s' % (mask.nick, msg))
            return

        # Now, build another lookup of our various timeframes.
        frames = dict(
            daily=datetime.timedelta(days=1),
            weekly=datetime.timedelta(days=7),
            monthly=datetime.timedelta(days=30),
            quarterly=datetime.timedelta(days=91),
        )

        if frame not in frames:
            response = "No such timeframe %r.  Try one of %s"
            msg = response % (frame, key_fmt(frames))
            self.bot.privmsg(target, '%s: %s' % (mask.nick, msg))
            return

        category = [symbols[symbol]]

        t2 = datetime.datetime.utcnow()
        t1 = t2 - frames[frame]
        t0 = t1 - frames[frame]

        # Count the number of messages between t0 and t1, and between t1 and t2
        query1 = dict(start=t0, end=t1, category=category)
        query2 = dict(start=t1, end=t2, category=category)

        # Do this async for superfast datagrepper queries.
        tpool = ThreadPool()
        batched_values = tpool.map(datagrepper_query, [
            dict(start=x, end=y, category=category)
            for x, y in Utils.daterange(t1, t2, SPARKLINE_RESOLUTION)
        ] + [query1, query2])

        count2 = batched_values.pop()
        count1 = batched_values.pop()

        # Just rename the results.  We'll use the rest for the sparkline.
        sparkline_values = batched_values

        yester_phrases = dict(
            daily="yesterday",
            weekly="the week preceding this one",
            monthly="the month preceding this one",
            quarterly="the 3 months preceding these past three months",
        )
        phrases = dict(
            daily="24 hours",
            weekly="week",
            monthly="month",
            quarterly="3 months",
        )

        if count1 and count2:
            percent = ((float(count2) / count1) - 1) * 100
        elif not count1 and count2:
            # If the older of the two time periods had zero messages, but there
            # are some in the more current period.. well, that's an infinite
            # percent increase.
            percent = float('inf')
        elif not count1 and not count2:
            # If counts are zero for both periods, then the change is 0%.
            percent = 0
        else:
            # Else, if there were some messages in the old time period, but
            # none in the current... then that's a 100% drop off.
            percent = -100

        sign = lambda value: value >= 0 and '+' or '-'

        template = u"{sym}, {name} {sign}{percent:.2f}% over {phrase}"
        response = template.format(
            sym=symbol,
            name=symbols[symbol],
            sign=sign(percent),
            percent=abs(percent),
            phrase=yester_phrases[frame],
        )
        self.bot.privmsg(target, '%s: %s' % (mask.nick, response))

        # Now, make a graph out of it.
        sparkline = Utils.sparkline(sparkline_values)

        template = u"     {sparkline}  ⤆ over {phrase}"
        response = template.format(
            sym=symbol,
            sparkline=sparkline,
            phrase=phrases[frame]
        )
        self.bot.privmsg(target, '%s: %s' % (mask.nick, response))

        to_utc = lambda t: time.gmtime(time.mktime(t.timetuple()))
        # And a final line for "x-axis tics"
        t1_fmt = time.strftime("%H:%M UTC %m/%d", to_utc(t1))
        t2_fmt = time.strftime("%H:%M UTC %m/%d", to_utc(t2))
        padding = u" " * (SPARKLINE_RESOLUTION - len(t1_fmt) - 3)
        template = u"     ↑ {t1}{padding}↑ {t2}"
        response = template.format(t1=t1_fmt, t2=t2_fmt, padding=padding)
        self.bot.privmsg(target, '%s: %s' % (mask.nick, response))

    @command
    def sponsors(self, mask, target, args):
        """sponsors <group short name>

        Return the sponsors list for the selected group

            %%sponsors <group_name>
        """
        name = args['<group_name>']

        msg = None
        try:
            group = self.fasclient.group_members(name)
            sponsors = ''
            for person in group:
                if person['role_type'] == 'sponsor':
                    sponsors += person['username'] + ' '
                elif person['role_type'] == 'administrator':
                    sponsors += '@' + person['username'] + ' '
            msg = 'Sponsors for %s: %s' % (name, sponsors)
        except AppError:
            msg = 'There is no group %s.' % name

        if msg is not None:
            self.bot.privmsg(target, '%s: %s' % (mask.nick, msg))

    @command
    def vacation(self, mask, target, args):
        """vacation

        Return the list of people who are on vacation right now according
        to fedocal.

            %%vacation
        """

        def get_persons():
            for meeting in self._meetings_for('vacation'):
                for manager in meeting['meeting_manager']:
                    yield manager

        persons = list(get_persons())

        if not persons:
            response = "Nobody is listed as being on vacation right now..."
            self.bot.privmsg(target, '%s: %s' % (mask.nick, response))
            url = "https://apps.fedoraproject.org/calendar/vacation/"
            self.bot.privmsg(target, '%s: - %s' % (mask.nick, url))
            return

        persons = ", ".join(persons)
        response = "The following people are on vacation: %s" % persons
        self.bot.privmsg(target, '%s: %s' % (mask.nick, response))
        url = "https://apps.fedoraproject.org/calendar/vacation/"
        self.bot.privmsg(target, '%s: - %s' % (mask.nick, url))

    @command
    def what(self, mask, target, args):
        """what <package>

        Returns a description of a given package.

            %%what <package>
        """
        package = args['<package>']
        msg = None
        try:
            summary = self.bugzacl['Fedora'][package]['summary']
            msg = "%s: %s" % (package, summary)
        except KeyError:
            msg = "No such package exists."

        if msg is not None:
            self.bot.privmsg(target, '%s: %s' % (mask.nick, msg))

    @command
    def whoowns(self, mask, target, args):
        """whoowns <package>

        Return more information about the specified user

            %%whoowns <package>
        """

        package = args['<package>']

        try:
            mainowner = self.bugzacl['Fedora'][package]['owner']
        except KeyError:
            msg = "No such package exists."
            self.bot.privmsg(target, '%s: %s' % (mask.nick, msg))
            return

        others = []
        for key in self.bugzacl:
            if key == 'Fedora':
                continue
            try:
                owner = self.bugzacl[key][package]['owner']
                if owner == mainowner:
                    continue
            except KeyError:
                continue
            others.append("%s in %s" % (owner, key))

        if others == []:
            self.bot.privmsg(target, '%s: %s' % (mask.nick, mainowner))
        else:
            msg = "%s (%s)" % (mainowner, ', '.join(others))
            self.bot.privmsg(target, '%s: %s' % (mask.nick, msg))

    @command
    def wikilink(self, mask, target, args):
        """wikilink <username>

        Return MediaWiki link syntax for a FAS user's page on the wiki.

            %%wikilink <username>
        """
        name = args['<username>']

        person = msg = None
        try:
            person = self.fasclient.person_by_username(name)
        except:
            msg = 'Error getting info for user: "******"' % name
        if not person:
            msg = 'User "%s" doesn\'t exist' % name
        else:
            msg = "[[User:%s|%s]]" % (person["username"],
                                      person["human_name"] or '')

        if msg is not None:
            self.bot.privmsg(target, '%s: %s' % (mask.nick, msg))
Пример #30
0
    output = []
    people_list = []
    flag = 0    
        
    group_name = 'ambassadors'
    
    username = '******'
    password = '******'

{% if env == "staging" %}
    base_url = 'https://admin.stg.fedoraproject.org/accounts/'
{% else %}
    base_url = 'https://admin.fedoraproject.org/accounts/'
{% endif %}

    fas = AccountSystem(base_url=base_url, username=username, password=password)

    print 'Generating data file. Wait...'

    
    # Get a dictinary of all people in FAS
    data = fas.people_by_key(key='id', search=u'*', fields=['human_name', \
    'username', 'email', 'status', 'country_code', 'latitude', 'longitude'])
#    print data
    #get all data from a group
    group_people = fas.group_members(group_name)
    
    #make a list of usernames of a group    
    for item in group_people:
        people_list.append(item['username'])
        
Пример #31
0
            smtp_server=APP.config.get('SMTP_SERVER', '127.0.0.1'),
            mail_admin=APP.config.get('MAIL_ADMIN',
                                      '*****@*****.**')))

# Log to stderr as well
STDERR_LOG = logging.StreamHandler(sys.stderr)
STDERR_LOG.setLevel(logging.INFO)
APP.logger.addHandler(STDERR_LOG)

LOG = APP.logger

APP.wsgi_app = fedora_elections.proxy.ReverseProxied(APP.wsgi_app)

# FAS for usernames.
FAS2 = AccountSystem(APP.config['FAS_BASE_URL'],
                     username=APP.config['FAS_USERNAME'],
                     password=APP.config['FAS_PASSWORD'],
                     insecure=not APP.config['FAS_CHECK_CERT'])

# modular imports
from fedora_elections import models  # noqa
SESSION = models.create_session(APP.config['DB_URL'])
from fedora_elections import forms  # noqa

from fedora_elections.utils import build_name_map  # noqa


def is_authenticated():
    ''' Return a boolean specifying if the user is authenticated or not.
    '''
    return hasattr(flask.g, 'fas_user') and flask.g.fas_user is not None
Пример #32
0
import sys
from getpass import getpass

from fedora.client import AuthError
from fedora.client.fas2 import AccountSystem

username = input("Enter your username: "******"Enter your password: "******"Enter username to query: ")

    response = FAS.person_by_username(username=username_query)

    print(f"\nEmail found: {response['email']}")

except AuthError:
    print("\nYou entered your details wrong.")
    sys.exit(1)

except KeyError:
    print("\nUsername not found. Please enter a valid username.")
Пример #33
0
 def __init__(self, fas_user: str = None, fas_password: str = None):
     self.db = PersistentDict(hash_name="whitelist")
     self._fas: AccountSystem = AccountSystem(username=fas_user,
                                              password=fas_password)
Пример #34
0
from fedora.client.fas2 import AccountSystem
from fedora.client import AuthError

import getpass

print()
userName = input("Enter your Fedora Account UserName >>> ")
password = getpass.getpass("Enter your Fedora Account Password >>> ")

FAS = AccountSystem(username=userName, password=password)

try:
    people = FAS.people_by_key(fields=['username', 'email'])
    for person in people.items():
        if person[1].username == userName:
            print("Your Fedora Email is " + person[1].email)
except:
    print("Error")
Пример #35
0
    full_name = {'AS' : 'APAC', 'NA' : 'North America', \
'SA' : 'LATAM', 'AF' : 'Africa', 'EU' : 'EMEA', 'Unknown' : 'Unknown'}


    group_name = 'ambassadors'
    username = '******'
    password = '******'
#    username = raw_input('Username: '******'Password: '******'https://admin.stg.fedoraproject.org/accounts/'
{% else %}
    base_url = 'https://admin.fedoraproject.org/accounts/'
{% endif %}

    fas = AccountSystem(base_url=base_url, username=username, password=password)

    # Call fedoraproject API with mwclient
{% if env == "staging" %}
    site = mwclient.Site(('https', 'stg.fedoraproject.org'), path='/w/') 
{% else %}
    site = mwclient.Site(('https', 'fedoraproject.org'), path='/w/') 
{% endif %}

    site.login(username, password) # Optional
    # Specify which page to edit
    page = site.Pages['Ambassadors/MembershipService/Verification2']

    #delete all the erswhile contents.
    page.text()
    blank_page = "updating..."
Пример #36
0
class Fedora(callbacks.Plugin):
    """Use this plugin to retrieve Fedora-related information."""
    threaded = True

    def __init__(self, irc):
        super(Fedora, self).__init__(irc)

        # caches, automatically downloaded on __init__, manually refreshed on
        # .refresh
        self.userlist = None
        self.bugzacl = None

        # To get the information, we need a username and password to FAS.
        # DO NOT COMMIT YOUR USERNAME AND PASSWORD TO THE PUBLIC REPOSITORY!
        self.fasurl = self.registryValue('fas.url')
        self.username = self.registryValue('fas.username')
        self.password = self.registryValue('fas.password')

        self.fasclient = AccountSystem(self.fasurl, username=self.username,
                                       password=self.password)
        self.pkgdb = PkgDB()
        # URLs
        # self.url = {}

        self.github_oauth_token = self.registryValue('github.oauth_token')

        self.karma_tokens = ('++', '--') if self.allow_negative else ('++',)

        # fetch necessary caches
        self._refresh()

        # Pull in /etc/fedmsg.d/ so we can build the fedmsg.meta processors.
        fm_config = fedmsg.config.load_config()
        fedmsg.meta.make_processors(**fm_config)

    def _refresh(self):
        timeout = socket.getdefaulttimeout()
        socket.setdefaulttimeout(None)
        self.log.info("Downloading user data")
        request = self.fasclient.send_request('/user/list',
                                              req_params={'search': '*'},
                                              auth=True,
                                              timeout=240)
        users = request['people'] + request['unapproved_people']
        del request
        self.log.info("Caching necessary user data")
        self.users = {}
        self.faslist = {}
        self.nickmap = {}
        for user in users:
            name = user['username']
            self.users[name] = {}
            self.users[name]['id'] = user['id']
            key = ' '.join([user['username'], user['email'] or '',
                            user['human_name'] or '', user['ircnick'] or ''])
            key = key.lower()
            value = "%s '%s' <%s>" % (user['username'], user['human_name'] or
                                      '', user['email'] or '')
            self.faslist[key] = value
            if user['ircnick']:
                self.nickmap[user['ircnick']] = name

        self.log.info("Downloading package owners cache")
        data = requests.get(
            'https://admin.fedoraproject.org/pkgdb/api/bugzilla?format=json',
            verify=True).json()
        self.bugzacl = data['bugzillaAcls']
        socket.setdefaulttimeout(timeout)

    def refresh(self, irc, msg, args):
        """takes no arguments

        Refresh the necessary caches."""

        irc.reply("Downloading caches.  This could take a while...")
        self._refresh()
        irc.replySuccess()
    refresh = wrap(refresh)

    @property
    def karma_db_path(self):
        return self.registryValue('karma.db_path')

    @property
    def allow_unaddressed_karma(self):
        return self.registryValue('karma.unaddressed')

    @property
    def allow_negative(self):
        return self.registryValue('karma.allow_negative')

    def _load_json(self, url):
        timeout = socket.getdefaulttimeout()
        socket.setdefaulttimeout(45)
        json = simplejson.loads(utils.web.getUrl(url))
        socket.setdefaulttimeout(timeout)
        return json

    def pulls(self, irc, msg, args, slug):
        """<username[/repo]>

        List the latest pending pull requests on github/pagure repos.
        """

        slug = slug.strip()
        if not slug or slug.count('/') != 0:
            irc.reply('Must be a GitHub org/username or pagure tag')
            return

        irc.reply('One moment, please...  Looking up %s.' % slug)
        fail_on_github, fail_on_pagure = False, False
        github_repos, pagure_repos = [], []
        try:
            github_repos = list(self.yield_github_repos(slug))
        except IOError as e:
            self.log.exception(e.message)
            fail_on_github = True

        try:
            pagure_repos = list(self.yield_pagure_repos(slug))
        except IOError as e:
            self.log.exception(e.message)
            fail_on_pagure = True

        if fail_on_github and fail_on_pagure:
            irc.reply('Could not find %s on GitHub or pagure.io' % slug)
            return

        results = sum([
            list(self.yield_github_pulls(slug, r)) for r in github_repos
        ], []) + sum([
            list(self.yield_pagure_pulls(slug, r)) for r in pagure_repos
        ], [])

        # Reverse-sort by time (newest-first)
        comparator = lambda a, b: cmp(b['age_numeric'], a['age_numeric'])
        results.sort(comparator)

        if not results:
            irc.reply('No pending pull requests on {slug}'.format(slug=slug))
        else:
            n = 6  # Show 6 pull requests
            for pull in results[:n]:
                irc.reply(u'@{user}\'s "{title}" {url} filed {age}'.format(
                    user=pull['user'],
                    title=pull['title'],
                    url=pull['url'],
                    age=pull['age'],
                ).encode('utf-8'))

            if len(results) > n:
                irc.reply('... and %i more.' % (len(results) - n))
    pulls = wrap(pulls, ['text'])

    def yield_github_repos(self, username):
        self.log.info("Finding github repos for %r" % username)
        tmpl = "https://api.github.com/users/{username}/repos?per_page=100"
        url = tmpl.format(username=username)
        auth = dict(access_token=self.github_oauth_token)
        for result in self.yield_github_results(url, auth):
            yield result['name']

    def yield_github_pulls(self, username, repo):
        self.log.info("Finding github pull requests for %r %r" % (username, repo))
        tmpl = "https://api.github.com/repos/{username}/{repo}/" + \
            "pulls?per_page=100"
        url = tmpl.format(username=username, repo=repo)
        auth = dict(access_token=self.github_oauth_token)
        for result in self.yield_github_results(url, auth):
            yield dict(
                user=result['user']['login'],
                title=result['title'],
                url=result['html_url'],
                age=arrow.get(result['created_at']).humanize(),
                age_numeric=arrow.get(result['created_at']),
            )

    def yield_github_results(self, url, auth):
        results = []
        link = dict(next=url)
        while 'next' in link:
            response = requests.get(link['next'], params=auth)

            if response.status_code == 404:
                raise IOError("404 for %r" % link['next'])

            # And.. if we didn't get good results, just bail.
            if response.status_code != 200:
                raise IOError(
                    "Non-200 status code %r; %r; %r" % (
                        response.status_code, link['next'], response.json))

            results = response.json()

            for result in results:
                yield result

            field = response.headers.get('link', None)

            link = dict()
            if field:
                link = dict([
                    (
                        part.split('; ')[1][5:-1],
                        part.split('; ')[0][1:-1],
                    ) for part in field.split(', ')
                ])

    def yield_pagure_repos(self, tag):
        self.log.info("Finding pagure repos for %r" % tag)
        tmpl = "https://pagure.io/api/0/projects?tags={tag}"
        url = tmpl.format(tag=tag)
        for result in self.yield_pagure_results(url, 'projects'):
            yield result['name']

    def yield_pagure_pulls(self, tag, repo):
        self.log.info("Finding pagure pull requests for %r %r" % (tag, repo))
        tmpl = "https://pagure.io/api/0/{repo}/pull-requests"
        url = tmpl.format(tag=tag, repo=repo)
        for result in self.yield_pagure_results(url, 'requests'):
            yield dict(
                user=result['user']['name'],
                title=result['title'],
                url='https://pagure.io/{repo}/pull-request/{id}'.format(
                    repo=result['project']['name'], id=result['id']),
                age=arrow.get(result['date_created']).humanize(),
                age_numeric=arrow.get(result['date_created']),
            )

    def yield_pagure_results(self, url, key):
        response = requests.get(url)

        if response.status_code == 404:
            raise IOError("404 for %r" % url)

        # And.. if we didn't get good results, just bail.
        if response.status_code != 200:
            raise IOError(
                "Non-200 status code %r; %r; %r" % (
                    response.status_code, url, response.text))

        results = response.json()
        results = results[key]

        for result in results:
            yield result

    def whoowns(self, irc, msg, args, package):
        """<package>

        Retrieve the owner of a given package
        """
        try:
            mainowner = self.bugzacl['Fedora'][package]['owner']
        except KeyError:
            irc.reply("No such package exists.")
            return
        others = []
        for key in self.bugzacl:
            if key == 'Fedora':
                continue
            try:
                owner = self.bugzacl[key][package]['owner']
                if owner == mainowner:
                    continue
            except KeyError:
                continue
            others.append("%s in %s" % (owner, key))
        if others == []:
            irc.reply(mainowner)
        else:
            irc.reply("%s (%s)" % (mainowner, ', '.join(others)))
    whoowns = wrap(whoowns, ['text'])

    def branches(self, irc, msg, args, package):
        """<package>

        Return the branches a package is in."""
        try:
            pkginfo = self.pkgdb.get_package(package)
        except AppError:
            irc.reply("No such package exists.")
            return
        branch_list = []
        for listing in pkginfo['packages']:
            branch_list.append(listing['collection']['branchname'])
        branch_list.sort()
        irc.reply(' '.join(branch_list))
        return
    branches = wrap(branches, ['text'])

    def what(self, irc, msg, args, package):
        """<package>

        Returns a description of a given package.
        """
        try:
            summary = self.bugzacl['Fedora'][package]['summary']
            irc.reply("%s: %s" % (package, summary))
        except KeyError:
            irc.reply("No such package exists.")
            return
    what = wrap(what, ['text'])

    def fas(self, irc, msg, args, find_name):
        """<query>

        Search the Fedora Account System usernames, full names, and email
        addresses for a match."""
        find_name = to_unicode(find_name)
        matches = []
        for entry in self.faslist.keys():
            if entry.find(find_name.lower()) != -1:
                matches.append(entry)
        if len(matches) == 0:
            irc.reply("'%s' Not Found!" % find_name)
        else:
            output = []
            for match in matches:
                output.append(self.faslist[match])
            irc.reply(' - '.join(output).encode('utf-8'))
    fas = wrap(fas, ['text'])

    def hellomynameis(self, irc, msg, args, name):
        """<username>

        Return brief information about a Fedora Account System username. Useful
        for things like meeting roll call and calling attention to yourself."""
        try:
            person = self.fasclient.person_by_username(name)
        except:
            irc.reply('Something blew up, please try again')
            return
        if not person:
            irc.reply('Sorry, but you don\'t exist')
            return
        irc.reply(('%(username)s \'%(human_name)s\' <%(email)s>' %
                   person).encode('utf-8'))
    hellomynameis = wrap(hellomynameis, ['text'])

    def himynameis(self, irc, msg, args, name):
        """<username>

        Will the real Slim Shady please stand up?"""
        try:
            person = self.fasclient.person_by_username(name)
        except:
            irc.reply('Something blew up, please try again')
            return
        if not person:
            irc.reply('Sorry, but you don\'t exist')
            return
        irc.reply(('%(username)s \'Slim Shady\' <%(email)s>' %
                   person).encode('utf-8'))
    himynameis = wrap(himynameis, ['text'])

    def dctime(self, irc, msg, args, dcname):
        """<dcname>

        Returns the current time of the datacenter identified by dcname.
        Supported DCs: PHX2, RDU, AMS, osuosl, ibiblio."""
        timezone_name = ''
        dcname_lower = dcname.lower()
        if dcname_lower == 'phx2':
            timezone_name = 'US/Arizona'
        elif dcname_lower in ['rdu', 'ibiblio']:
            timezone_name = 'US/Eastern'
        elif dcname_lower == 'osuosl':
            timezone_name = 'US/Pacific'
        elif dcname_lower in ['ams', 'internetx']:
            timezone_name = 'Europe/Amsterdam'
        else:
            irc.reply('Datacenter %s is unknown' % dcname)
            return
        try:
            time = datetime.datetime.now(pytz.timezone(timezone_name))
        except:
            irc.reply('The timezone of "%s" was unknown: "%s"' % (
                dcname, timezone_name))
            return
        irc.reply('The current local time of "%s" is: "%s" (timezone: %s)' %
                  (dcname, time.strftime('%H:%M'), timezone_name))
    dctime = wrap(dctime, ['text'])

    def localtime(self, irc, msg, args, name):
        """<username>

        Returns the current time of the user.
        The timezone is queried from FAS."""
        try:
            person = self.fasclient.person_by_username(name)
        except:
            irc.reply('Error getting info user user: "******"' % name)
            return
        if not person:
            irc.reply('User "%s" doesn\'t exist' % name)
            return
        timezone_name = person['timezone']
        if timezone_name is None:
            irc.reply('User "%s" doesn\'t share his timezone' % name)
            return
        try:
            time = datetime.datetime.now(pytz.timezone(timezone_name))
        except:
            irc.reply('The timezone of "%s" was unknown: "%s"' % (
                name, timezone_name))
            return
        irc.reply('The current local time of "%s" is: "%s" (timezone: %s)' %
                  (name, time.strftime('%H:%M'), timezone_name))
    localtime = wrap(localtime, ['text'])

    def fasinfo(self, irc, msg, args, name):
        """<username>

        Return information on a Fedora Account System username."""
        try:
            person = self.fasclient.person_by_username(name)
        except:
            irc.reply('Error getting info for user: "******"' % name)
            return
        if not person:
            irc.reply('User "%s" doesn\'t exist' % name)
            return
        person['creation'] = person['creation'].split(' ')[0]
        string = ("User: %(username)s, Name: %(human_name)s"
                  ", email: %(email)s, Creation: %(creation)s"
                  ", IRC Nick: %(ircnick)s, Timezone: %(timezone)s"
                  ", Locale: %(locale)s"
                  ", GPG key ID: %(gpg_keyid)s, Status: %(status)s") % person
        irc.reply(string.encode('utf-8'))

        # List of unapproved groups is easy
        unapproved = ''
        for group in person['unapproved_memberships']:
            unapproved = unapproved + "%s " % group['name']
        if unapproved != '':
            irc.reply('Unapproved Groups: %s' % unapproved)

        # List of approved groups requires a separate query to extract roles
        constraints = {'username': name, 'group': '%',
                       'role_status': 'approved'}
        columns = ['username', 'group', 'role_type']
        roles = []
        try:
            roles = self.fasclient.people_query(constraints=constraints,
                                                columns=columns)
        except:
            irc.reply('Error getting group memberships.')
            return

        approved = ''
        for role in roles:
            if role['role_type'] == 'sponsor':
                approved += '+' + role['group'] + ' '
            elif role['role_type'] == 'administrator':
                approved += '@' + role['group'] + ' '
            else:
                approved += role['group'] + ' '
        if approved == '':
            approved = "None"

        irc.reply('Approved Groups: %s' % approved)
    fasinfo = wrap(fasinfo, ['text'])

    def group(self, irc, msg, args, name):
        """<group short name>

        Return information about a Fedora Account System group."""
        try:
            group = self.fasclient.group_by_name(name)
            irc.reply('%s: %s' %
                      (name, group['display_name']))
        except AppError:
            irc.reply('There is no group "%s".' % name)
    group = wrap(group, ['text'])

    def admins(self, irc, msg, args, name):
        """<group short name>

        Return the administrators list for the selected group"""

        try:
            group = self.fasclient.group_members(name)
            sponsors = ''
            for person in group:
                if person['role_type'] == 'administrator':
                    sponsors += person['username'] + ' '
            irc.reply('Administrators for %s: %s' % (name, sponsors))
        except AppError:
            irc.reply('There is no group %s.' % name)

    admins = wrap(admins, ['text'])

    def sponsors(self, irc, msg, args, name):
        """<group short name>

        Return the sponsors list for the selected group"""

        try:
            group = self.fasclient.group_members(name)
            sponsors = ''
            for person in group:
                if person['role_type'] == 'sponsor':
                    sponsors += person['username'] + ' '
                elif person['role_type'] == 'administrator':
                    sponsors += '@' + person['username'] + ' '
            irc.reply('Sponsors for %s: %s' % (name, sponsors))
        except AppError:
            irc.reply('There is no group %s.' % name)

    sponsors = wrap(sponsors, ['text'])

    def members(self, irc, msg, args, name):
        """<group short name>

        Return a list of members of the specified group"""
        try:
            group = self.fasclient.group_members(name)
            members = ''
            for person in group:
                if person['role_type'] == 'administrator':
                    members += '@' + person['username'] + ' '
                elif person['role_type'] == 'sponsor':
                    members += '+' + person['username'] + ' '
                else:
                    members += person['username'] + ' '
            irc.reply('Members of %s: %s' % (name, members))
        except AppError:
            irc.reply('There is no group %s.' % name)

    members = wrap(members, ['text'])

    def showticket(self, irc, msg, args, baseurl, number):
        """<baseurl> <number>

        Return the name and URL of a trac ticket or bugzilla bug.
        """
        url = format(baseurl, str(number))
        size = conf.supybot.protocols.http.peekSize()
        text = utils.web.getUrl(url, size=size)
        parser = Title()
        try:
            parser.feed(text)
        except sgmllib.SGMLParseError:
            irc.reply(format('Encountered a problem parsing %u', url))
        if parser.title:
            irc.reply(utils.web.htmlToText(parser.title.strip()) + ' - ' + url)
        else:
            irc.reply(format('That URL appears to have no HTML title ' +
                             'within the first %i bytes.', size))
    showticket = wrap(showticket, ['httpUrl', 'int'])

    def swedish(self, irc, msg, args):
        """takes no arguments

        Humor mmcgrath."""

        # Import this here to avoid a circular import problem.
        from __init__ import __version__

        irc.reply(str('kwack kwack'))
        irc.reply(str('bork bork bork'))
        irc.reply(str('(supybot-fedora version %s)' % __version__))
    swedish = wrap(swedish)

    def invalidCommand(self, irc, msg, tokens):
        """ Handle any command not otherwise handled.

        We use this to accept karma commands directly.
        """
        channel = msg.args[0]
        if not irc.isChannel(channel):
            return

        agent = msg.nick
        line = tokens[-1].strip()
        words = line.split()
        for word in words:
            if word[-2:] in self.karma_tokens:
                self._do_karma(irc, channel, agent, word, line, explicit=True)

    def doPrivmsg(self, irc, msg):
        """ Handle everything.

        The name is misleading.  This hook actually gets called for all
        IRC activity in every channel.
        """
        # We don't handle this if we've been addressed because invalidCommand
        # will handle it for us.  This prevents us from accessing the db twice
        # and therefore crashing.
        if (msg.addressed or msg.repliedTo):
            return

        channel = msg.args[0]
        if irc.isChannel(channel) and self.allow_unaddressed_karma:
            irc = callbacks.SimpleProxy(irc, msg)
            agent = msg.nick
            line = msg.args[1].strip()

            # First try to handle karma commands
            words = line.split()
            for word in words:
                if word[-2:] in self.karma_tokens:
                    self._do_karma(
                        irc, channel, agent, word, line, explicit=False)

        blacklist = self.registryValue('naked_ping_channel_blacklist')
        if irc.isChannel(channel) and not channel in blacklist:
            # Also, handle naked pings for
            # https://github.com/fedora-infra/supybot-fedora/issues/26
            pattern = '\w* ?[:,] ?ping\W*$'
            if re.match(pattern, line):
                admonition = self.registryValue('naked_ping_admonition')
                irc.reply(admonition)

    def get_current_release(self):
        url = 'https://admin.fedoraproject.org/pkgdb/api/collections/'
        query = {
            'clt_status': 'Active',
            'pattern': 'f*',
        }
        response = requests.get(url, params=query)
        data = response.json()
        collections = data['collections']
        collections.sort(key=lambda c: int(c['version']))
        return collections[-1]['branchname'].encode('utf-8')

    def open_karma_db(self):
        data = shelve.open(self.karma_db_path)
        if 'backwards' in data:
            # This is the old style data.  convert it to the new form.
            release = self.get_current_release()
            data['forwards-' + release] = copy.copy(data['forwards'])
            data['backwards-' + release] = copy.copy(data['backwards'])
            del data['forwards']
            del data['backwards']
            data.sync()
        return data

    def karma(self, irc, msg, args, name):
        """<username>

        Return the total karma for a FAS user."""
        data = None
        try:
            data = self.open_karma_db()
            if name in self.nickmap:
                name = self.nickmap[name]
            release = self.get_current_release()
            votes = data['backwards-' + release].get(name, {})
            alltime = []
            for key in data:
                if 'backwards-' not in key:
                    continue
                alltime.append(data[key].get(name, {}))
        finally:
            if data:
                data.close()

        inc = len([v for v in votes.values() if v == 1])
        dec = len([v for v in votes.values() if v == -1])
        total = inc - dec

        inc, dec = 0, 0
        for release in alltime:
            inc += len([v for v in release.values() if v == 1])
            dec += len([v for v in release.values() if v == -1])
        alltime_total = inc - dec

        irc.reply("Karma for %s has been increased %i times and "
                    "decreased %i times this release cycle for a "
                    "total of %i (%i all time)" % (
                    name, inc, dec, total, alltime_total))


    karma = wrap(karma, ['text'])

    def _do_karma(self, irc, channel, agent, recip, line, explicit=False):
        recip, direction = recip[:-2], recip[-2:]
        if not recip:
            return

        # Extract 'puiterwijk' out of 'have a cookie puiterwijk++'
        recip = recip.strip().split()[-1]

        # Exclude 'c++', 'g++' or 'i++' (c,g,i), issue #30
        if str(recip).lower() in ['c','g','i']:
            return

        increment = direction == '++' # If not, then it must be decrement

        # Check that these are FAS users
        if not agent in self.nickmap and not agent in self.users:
            self.log.info(
                "Saw %s from %s, but %s not in FAS" % (recip, agent, agent))
            if explicit:
                irc.reply("Couldn't find %s in FAS" % agent)
            return

        if not recip in self.nickmap and not recip in self.users:
            self.log.info(
                "Saw %s from %s, but %s not in FAS" % (recip, agent, recip))
            if explicit:
                irc.reply("Couldn't find %s in FAS" % recip)
            return

        # Transform irc nicks into fas usernames if possible.
        if agent in self.nickmap:
            agent = self.nickmap[agent]

        if recip in self.nickmap:
            recip = self.nickmap[recip]

        if agent == recip:
            irc.reply("You may not modify your own karma.")
            return

        release = self.get_current_release()

        # Check our karma db to make sure this hasn't already been done.
        data = None
        try:
            data = shelve.open(self.karma_db_path)
            fkey = 'forwards-' + release
            bkey = 'backwards-' + release
            if fkey not in data:
                data[fkey] = {}

            if bkey not in data:
                data[bkey] = {}

            if agent not in data[fkey]:
                forwards = data[fkey]
                forwards[agent] = {}
                data[fkey] = forwards

            if recip not in data[bkey]:
                backwards = data[bkey]
                backwards[recip] = {}
                data[bkey] = backwards

            vote = 1 if increment else -1

            if data[fkey][agent].get(recip) == vote:
                ## People found this response annoying.
                ## https://github.com/fedora-infra/supybot-fedora/issues/25
                #irc.reply(
                #    "You have already given %i karma to %s" % (vote, recip))
                return

            forwards = data[fkey]
            forwards[agent][recip] = vote
            data[fkey] = forwards

            backwards = data[bkey]
            backwards[recip][agent] = vote
            data[bkey] = backwards

            # Count the number of karmas for old so-and-so.
            total_this_release = sum(data[bkey][recip].values())

            total_all_time = 0
            for key in data:
                if 'backwards-' not in key:
                    continue
                total_all_time += sum(data[key].get(recip, {}).values())
        finally:
            if data:
                data.close()

        fedmsg.publish(
            name="supybot.%s" % socket.gethostname(),
            modname="irc", topic="karma",
            msg={
                'agent': agent,
                'recipient': recip,
                'total': total_all_time,  # The badge rules use this value
                'total_this_release': total_this_release,
                'vote': vote,
                'channel': channel,
                'line': line,
                'release': release,
            },
        )

        url = self.registryValue('karma.url')
        irc.reply(
            'Karma for %s changed to %r '
            '(for the %s release cycle):  %s' % (
                recip, total_this_release, release, url))


    def wikilink(self, irc, msg, args, name):
        """<username>

        Return MediaWiki link syntax for a FAS user's page on the wiki."""
        try:
            person = self.fasclient.person_by_username(name)
        except:
            irc.reply('Error getting info for user: "******"' % name)
            return
        if not person:
            irc.reply('User "%s" doesn\'t exist' % name)
            return
        string = "[[User:%s|%s]]" % (person["username"],
                                     person["human_name"] or '')
        irc.reply(string.encode('utf-8'))
    wikilink = wrap(wikilink, ['text'])

    def mirroradmins(self, irc, msg, args, hostname):
        """<hostname>

        Return MirrorManager list of FAS usernames which administer <hostname>.
        <hostname> must be the FQDN of the host."""
        url = ("https://admin.fedoraproject.org/mirrormanager/api/"
               "mirroradmins?name=" + hostname)
        result = self._load_json(url)
        if not 'admins' in result:
            irc.reply(result.get('message', 'Something went wrong'))
            return
        string = 'Mirror Admins of %s: ' % hostname
        string += ' '.join(result['admins'])
        irc.reply(string.encode('utf-8'))
    mirroradmins = wrap(mirroradmins, ['text'])

    def pushduty(self, irc, msg, args):
        """

        Return the list of people who are on releng push duty right now.
        """

        def get_persons():
            for meeting in self._meetings_for('release-engineering'):
                yield meeting['meeting_name']

        persons = list(get_persons())

        url = "https://apps.fedoraproject.org/" + \
            "calendar/release-engineering/"

        if not persons:
            response = "Nobody is listed as being on push duty right now..."
            irc.reply(response.encode('utf-8'))
            irc.reply("- " + url.encode('utf-8'))
            return

        persons = ", ".join(persons)
        response = "The following people are on push duty: %s" % persons
        irc.reply(response.encode('utf-8'))
        irc.reply("- " + url.encode('utf-8'))
    pushduty = wrap(pushduty)

    def vacation(self, irc, msg, args):
        """

        Return the list of people who are on vacation right now.
        """

        def get_persons():
            for meeting in self._meetings_for('vacation'):
                for manager in meeting['meeting_manager']:
                    yield manager

        persons = list(get_persons())

        if not persons:
            response = "Nobody is listed as being on vacation right now..."
            irc.reply(response.encode('utf-8'))
            url = "https://apps.fedoraproject.org/calendar/vacation/"
            irc.reply("- " + url.encode('utf-8'))
            return

        persons = ", ".join(persons)
        response = "The following people are on vacation: %s" % persons
        irc.reply(response.encode('utf-8'))
        url = "https://apps.fedoraproject.org/calendar/vacation/"
        irc.reply("- " + url.encode('utf-8'))
    vacation = wrap(vacation)

    def nextmeetings(self, irc, msg, args):
        """
        Return the next meetings scheduled for any channel(s).
        """
        irc.reply('One moment, please...  Looking up the channel list.')
        url = 'https://apps.fedoraproject.org/calendar/api/locations/'
        locations = requests.get(url).json()['locations']
        meetings = sorted(chain(*[
            self._future_meetings(location)
            for location in locations
            if 'irc.freenode.net' in location
        ]), key=itemgetter(0))

        test, meetings = tee(meetings)
        try:
            test.next()
        except StopIteration:
            response = "There are no meetings scheduled at all."
            irc.reply(response.encode('utf-8'))
            return

        for date, meeting in islice(meetings, 0, 5):
            response = "In #%s is %s (starting %s)" % (
                meeting['meeting_location'].split('@')[0].strip(),
                meeting['meeting_name'],
                arrow.get(date).humanize(),
            )
            irc.reply(response.encode('utf-8'))
    nextmeetings = wrap(nextmeetings, [])

    def nextmeeting(self, irc, msg, args, channel):
        """<channel>

        Return the next meeting scheduled for a particular channel.
        """

        channel = channel.strip('#').split('@')[0]
        meetings = sorted(self._future_meetings(channel), key=itemgetter(0))

        test, meetings = tee(meetings)
        try:
            test.next()
        except StopIteration:
            response = "There are no meetings scheduled for #%s." % channel
            irc.reply(response.encode('utf-8'))
            return

        for date, meeting in islice(meetings, 0, 3):
            response = "In #%s is %s (starting %s)" % (
                channel,
                meeting['meeting_name'],
                arrow.get(date).humanize(),
            )
            irc.reply(response.encode('utf-8'))
        base = "https://apps.fedoraproject.org/calendar/location/"
        url = base + urllib.quote("%[email protected]/" % channel)
        irc.reply("- " + url.encode('utf-8'))
    nextmeeting = wrap(nextmeeting, ['text'])

    @staticmethod
    def _future_meetings(location):
        if not location.endswith('@irc.freenode.net'):
            location = '*****@*****.**' % location
        meetings = Fedora._query_fedocal(location=location)
        now = datetime.datetime.utcnow()

        for meeting in meetings:
            string = "%s %s" % (meeting['meeting_date'],
                                meeting['meeting_time_start'])
            dt = datetime.datetime.strptime(string, "%Y-%m-%d %H:%M:%S")

            if now < dt:
                yield dt, meeting

    @staticmethod
    def _meetings_for(calendar):
        meetings = Fedora._query_fedocal(calendar=calendar)
        now = datetime.datetime.utcnow()

        for meeting in meetings:
            string = "%s %s" % (meeting['meeting_date'],
                                meeting['meeting_time_start'])
            start = datetime.datetime.strptime(string, "%Y-%m-%d %H:%M:%S")
            string = "%s %s" % (meeting['meeting_date_end'],
                                meeting['meeting_time_stop'])
            end = datetime.datetime.strptime(string, "%Y-%m-%d %H:%M:%S")

            if now >= start and now <= end:
                yield meeting

    @staticmethod
    def _query_fedocal(**kwargs):
        url = 'https://apps.fedoraproject.org/calendar/api/meetings'
        return requests.get(url, params=kwargs).json()['meetings']

    def badges(self, irc, msg, args, name):
        """<username>

        Return badges statistics about a user.
        """
        url = "https://badges.fedoraproject.org/user/" + name
        d = requests.get(url + "/json").json()

        if 'error' in d:
            response = d['error']
        else:
            template = "{name} has unlocked {n} Fedora Badges:  {url}"
            n = len(d['assertions'])
            response = template.format(name=name, url=url, n=n)

        irc.reply(response.encode('utf-8'))
    badges = wrap(badges, ['text'])

    def quote(self, irc, msg, args, arguments):
        """<SYMBOL> [daily, weekly, monthly, quarterly]

        Return some datagrepper statistics on fedmsg categories.
        """

        # First, some argument parsing.  Supybot should be able to do this for
        # us, but I couldn't figure it out.  The supybot.plugins.additional
        # object is the thing to use... except its weird.
        tokens = arguments.split(None, 1)
        if len(tokens) == 1:
            symbol, frame = tokens[0], 'daily'
        else:
            symbol, frame = tokens

        # Second, build a lookup table for symbols.  By default, we'll use the
        # fedmsg category names, take their first 3 characters and uppercase
        # them.  That will take things like "wiki" and turn them into "WIK" and
        # "bodhi" and turn them into "BOD".  This handles a lot for us.  We'll
        # then override those that don't make sense manually here.  For
        # instance "fedoratagger" by default would be "FED", but that's no
        # good.  We want "TAG".
        # Why all this trouble?  Well, as new things get added to the fedmsg
        # bus, we don't want to have keep coming back here and modifying this
        # code.  Hopefully this dance will at least partially future-proof us.
        symbols = dict([
            (processor.__name__.lower(), processor.__name__[:3].upper())
            for processor in fedmsg.meta.processors
        ])
        symbols.update({
            'fedoratagger': 'TAG',
            'fedbadges': 'BDG',
            'buildsys': 'KOJ',
            'pkgdb': 'PKG',
            'meetbot': 'MTB',
            'planet': 'PLN',
            'trac': 'TRC',
            'mailman': 'MM3',
        })

        # Now invert the dict so we can lookup the argued symbol.
        # Yes, this is vulnerable to collisions.
        symbols = dict([(sym, name) for name, sym in symbols.items()])

        # These aren't user-facing topics, so drop 'em.
        del symbols['LOG']
        del symbols['UNH']
        del symbols['ANN']  # And this one is unused...

        key_fmt = lambda d: ', '.join(sorted(d.keys()))

        if symbol not in symbols:
            response = "No such symbol %r.  Try one of %s"
            irc.reply((response % (symbol, key_fmt(symbols))).encode('utf-8'))
            return

        # Now, build another lookup of our various timeframes.
        frames = dict(
            daily=datetime.timedelta(days=1),
            weekly=datetime.timedelta(days=7),
            monthly=datetime.timedelta(days=30),
            quarterly=datetime.timedelta(days=91),
        )

        if frame not in frames:
            response = "No such timeframe %r.  Try one of %s"
            irc.reply((response % (frame, key_fmt(frames))).encode('utf-8'))
            return

        category = [symbols[symbol]]

        t2 = datetime.datetime.utcnow()
        t1 = t2 - frames[frame]
        t0 = t1 - frames[frame]

        # Count the number of messages between t0 and t1, and between t1 and t2
        query1 = dict(start=t0, end=t1, category=category)
        query2 = dict(start=t1, end=t2, category=category)

        # Do this async for superfast datagrepper queries.
        tpool = ThreadPool()
        batched_values = tpool.map(datagrepper_query, [
            dict(start=x, end=y, category=category)
            for x, y in Utils.daterange(t1, t2, SPARKLINE_RESOLUTION)
        ] + [query1, query2])

        count2 = batched_values.pop()
        count1 = batched_values.pop()

        # Just rename the results.  We'll use the rest for the sparkline.
        sparkline_values = batched_values

        yester_phrases = dict(
            daily="yesterday",
            weekly="the week preceding this one",
            monthly="the month preceding this one",
            quarterly="the 3 months preceding these past three months",
        )
        phrases = dict(
            daily="24 hours",
            weekly="week",
            monthly="month",
            quarterly="3 months",
        )

        if count1 and count2:
            percent = ((float(count2) / count1) - 1) * 100
        elif not count1 and count2:
            # If the older of the two time periods had zero messages, but there
            # are some in the more current period.. well, that's an infinite
            # percent increase.
            percent = float('inf')
        elif not count1 and not count2:
            # If counts are zero for both periods, then the change is 0%.
            percent = 0
        else:
            # Else, if there were some messages in the old time period, but
            # none in the current... then that's a 100% drop off.
            percent = -100

        sign = lambda value: value >= 0 and '+' or '-'

        template = u"{sym}, {name} {sign}{percent:.2f}% over {phrase}"
        response = template.format(
            sym=symbol,
            name=symbols[symbol],
            sign=sign(percent),
            percent=abs(percent),
            phrase=yester_phrases[frame],
        )
        irc.reply(response.encode('utf-8'))

        # Now, make a graph out of it.
        sparkline = Utils.sparkline(sparkline_values)

        template = u"     {sparkline}  ⤆ over {phrase}"
        response = template.format(
            sym=symbol,
            sparkline=sparkline,
            phrase=phrases[frame]
        )
        irc.reply(response.encode('utf-8'))

        to_utc = lambda t: time.gmtime(time.mktime(t.timetuple()))
        # And a final line for "x-axis tics"
        t1_fmt = time.strftime("%H:%M UTC %m/%d", to_utc(t1))
        t2_fmt = time.strftime("%H:%M UTC %m/%d", to_utc(t2))
        padding = u" " * (SPARKLINE_RESOLUTION - len(t1_fmt) - 3)
        template = u"     ↑ {t1}{padding}↑ {t2}"
        response = template.format(t1=t1_fmt, t2=t2_fmt, padding=padding)
        irc.reply(response.encode('utf-8'))
    quote = wrap(quote, ['text'])
Пример #37
0
class Fedora(callbacks.Plugin):
    """Use this plugin to retrieve Fedora-related information."""
    threaded = True

    def __init__(self, irc):
        super(Fedora, self).__init__(irc)

        # caches, automatically downloaded on __init__, manually refreshed on
        # .refresh
        self.userlist = None
        self.bugzacl = None

        # To get the information, we need a username and password to FAS.
        # DO NOT COMMIT YOUR USERNAME AND PASSWORD TO THE PUBLIC REPOSITORY!
        self.fasurl = self.registryValue('fas.url')
        self.username = self.registryValue('fas.username')
        self.password = self.registryValue('fas.password')

        self.fasclient = AccountSystem(self.fasurl, username=self.username,
                                       password=self.password)
        self.pkgdb = PkgDB()
        # URLs
        # self.url = {}

        self.github_oauth_token = self.registryValue('github.oauth_token')

        # fetch necessary caches
        self._refresh()

        # Pull in /etc/fedmsg.d/ so we can build the fedmsg.meta processors.
        fm_config = fedmsg.config.load_config()
        fedmsg.meta.make_processors(**fm_config)

    def _refresh(self):
        timeout = socket.getdefaulttimeout()
        socket.setdefaulttimeout(None)
        self.log.info("Downloading user data")
        request = self.fasclient.send_request('/user/list',
                                              req_params={'search': '*'},
                                              auth=True,
                                              timeout=240)
        users = request['people'] + request['unapproved_people']
        del request
        self.log.info("Caching necessary user data")
        self.users = {}
        self.faslist = {}
        for user in users:
            name = user['username']
            self.users[name] = {}
            self.users[name]['id'] = user['id']
            key = ' '.join([user['username'], user['email'] or '',
                            user['human_name'] or '', user['ircnick'] or ''])
            key = key.lower()
            value = "%s '%s' <%s>" % (user['username'], user['human_name'] or
                                      '', user['email'] or '')
            self.faslist[key] = value
        self.log.info("Downloading package owners cache")
        data = requests.get(
            'https://admin.fedoraproject.org/pkgdb/api/bugzilla?format=json',
            verify=True).json()
        self.bugzacl = data['bugzillaAcls']
        socket.setdefaulttimeout(timeout)

    def refresh(self, irc, msg, args):
        """takes no arguments

        Refresh the necessary caches."""
        self._refresh()
        irc.replySuccess()
    refresh = wrap(refresh)

    def _load_json(self, url):
        timeout = socket.getdefaulttimeout()
        socket.setdefaulttimeout(45)
        json = simplejson.loads(utils.web.getUrl(url))
        socket.setdefaulttimeout(timeout)
        return json

    def pulls(self, irc, msg, args, slug):
        """<username/repo>

        List the pending pull requests on a github repo.
        """

        if slug.count('/') != 1:
            irc.reply('Must be GitHub repo of the format <username/repo>')
            return

        username, repo = slug.strip().split('/')

        tmpl = "https://api.github.com/repos/{username}/{repo}/" + \
            "pulls?per_page=100"
        url = tmpl.format(username=username, repo=repo)
        auth = dict(access_token=self.github_oauth_token)

        results = []
        link = dict(next=url)
        while 'next' in link:
            response = requests.get(link['next'], params=auth)

            if response.status_code == 404:
                irc.reply('No such GitHub repository %r' % slug)
                return

            # And.. if we didn't get good results, just bail.
            if response.status_code != 200:
                raise IOError(
                    "Non-200 status code %r; %r; %r" % (
                        response.status_code, url, response.json))

            if callable(response.json):
                # Newer python-requests
                results += response.json()
            else:
                # Older python-requests
                results += response.json

            field = response.headers.get('link', None)

            link = dict()
            if field:
                link = dict([
                    (
                        part.split('; ')[1][5:-1],
                        part.split('; ')[0][1:-1],
                    ) for part in field.split(', ')
                ])

        if not results:
            irc.reply('No pending pull requests on {slug}'.format(slug=slug))
        else:
            n = 4
            for pull in results[:n]:
                irc.reply('@{user}\'s "{title}" {url}'.format(
                    user=pull['user']['login'],
                    title=pull['title'],
                    url=pull['html_url']))

            if len(results) > n:
                irc.reply('... and %i more.' % (len(results) - n))


    pulls = wrap(pulls, ['text'])

    def whoowns(self, irc, msg, args, package):
        """<package>

        Retrieve the owner of a given package
        """
        try:
            mainowner = self.bugzacl['Fedora'][package]['owner']
        except KeyError:
            irc.reply("No such package exists.")
            return
        others = []
        for key in self.bugzacl:
            if key == 'Fedora':
                continue
            try:
                owner = self.bugzacl[key][package]['owner']
                if owner == mainowner:
                    continue
            except KeyError:
                continue
            others.append("%s in %s" % (owner, key))
        if others == []:
            irc.reply(mainowner)
        else:
            irc.reply("%s (%s)" % (mainowner, ', '.join(others)))
    whoowns = wrap(whoowns, ['text'])

    def branches(self, irc, msg, args, package):
        """<package>

        Return the branches a package is in."""
        try:
            pkginfo = self.pkgdb.get_package(package)
        except AppError:
            irc.reply("No such package exists.")
            return
        branch_list = []
        for listing in pkginfo['packages']:
            branch_list.append(listing['collection']['branchname'])
        branch_list.sort()
        irc.reply(' '.join(branch_list))
        return
    branches = wrap(branches, ['text'])

    def what(self, irc, msg, args, package):
        """<package>

        Returns a description of a given package.
        """
        try:
            summary = self.bugzacl['Fedora'][package]['summary']
            irc.reply("%s: %s" % (package, summary))
        except KeyError:
            irc.reply("No such package exists.")
            return
    what = wrap(what, ['text'])

    def fas(self, irc, msg, args, find_name):
        """<query>

        Search the Fedora Account System usernames, full names, and email
        addresses for a match."""
        find_name = to_unicode(find_name)
        matches = []
        for entry in self.faslist.keys():
            if entry.find(find_name.lower()) != -1:
                matches.append(entry)
        if len(matches) == 0:
            irc.reply("'%s' Not Found!" % find_name)
        else:
            output = []
            for match in matches:
                output.append(self.faslist[match])
            irc.reply(' - '.join(output).encode('utf-8'))
    fas = wrap(fas, ['text'])

    def hellomynameis(self, irc, msg, args, name):
        """<username>

        Return brief information about a Fedora Account System username. Useful
        for things like meeting roll call and calling attention to yourself."""
        try:
            person = self.fasclient.person_by_username(name)
        except:
            irc.reply('Something blew up, please try again')
            return
        if not person:
            irc.reply('Sorry, but you don\'t exist')
            return
        irc.reply(('%(username)s \'%(human_name)s\' <%(email)s>' %
                   person).encode('utf-8'))
    hellomynameis = wrap(hellomynameis, ['text'])

    def himynameis(self, irc, msg, args, name):
        """<username>

        Will the real Slim Shady please stand up?"""
        try:
            person = self.fasclient.person_by_username(name)
        except:
            irc.reply('Something blew up, please try again')
            return
        if not person:
            irc.reply('Sorry, but you don\'t exist')
            return
        irc.reply(('%(username)s \'Slim Shady\' <%(email)s>' %
                   person).encode('utf-8'))
    himynameis = wrap(himynameis, ['text'])

    def localtime(self, irc, msg, args, name):
        """<username>

        Returns the current time of the user.
        The timezone is queried from FAS."""
        try:
            person = self.fasclient.person_by_username(name)
        except:
            irc.reply('Error getting info user user: "******"' % name)
            return
        if not person:
            irc.reply('User "%s" doesn\'t exist' % name)
            return
        timezone_name = person['timezone']
        if timezone_name is None:
            irc.reply('User "%s" doesn\'t share his timezone' % name)
            return
        try:
            time = datetime.datetime.now(pytz.timezone(timezone_name))
        except:
            irc.reply('The timezone of "%s" was unknown: "%s"' % (name,
                                                                  timezone))
            return
        irc.reply('The current local time of "%s" is: "%s" (timezone: %s)' %
                  (name, time.strftime('%H:%M'), timezone_name))
    localtime = wrap(localtime, ['text'])

    def fasinfo(self, irc, msg, args, name):
        """<username>

        Return information on a Fedora Account System username."""
        try:
            person = self.fasclient.person_by_username(name)
        except:
            irc.reply('Error getting info for user: "******"' % name)
            return
        if not person:
            irc.reply('User "%s" doesn\'t exist' % name)
            return
        person['creation'] = person['creation'].split(' ')[0]
        string = ("User: %(username)s, Name: %(human_name)s"
                  ", email: %(email)s, Creation: %(creation)s"
                  ", IRC Nick: %(ircnick)s, Timezone: %(timezone)s"
                  ", Locale: %(locale)s"
                  ", GPG key ID: %(gpg_keyid)s, Status: %(status)s") % person
        irc.reply(string.encode('utf-8'))

        # List of unapproved groups is easy
        unapproved = ''
        for group in person['unapproved_memberships']:
            unapproved = unapproved + "%s " % group['name']
        if unapproved != '':
            irc.reply('Unapproved Groups: %s' % unapproved)

        # List of approved groups requires a separate query to extract roles
        constraints = {'username': name, 'group': '%',
                       'role_status': 'approved'}
        columns = ['username', 'group', 'role_type']
        roles = []
        try:
            roles = self.fasclient.people_query(constraints=constraints,
                                                columns=columns)
        except:
            irc.reply('Error getting group memberships.')
            return

        approved = ''
        for role in roles:
            if role['role_type'] == 'sponsor':
                approved += '+' + role['group'] + ' '
            elif role['role_type'] == 'administrator':
                approved += '@' + role['group'] + ' '
            else:
                approved += role['group'] + ' '
        if approved == '':
            approved = "None"

        irc.reply('Approved Groups: %s' % approved)
    fasinfo = wrap(fasinfo, ['text'])

    def group(self, irc, msg, args, name):
        """<group short name>

        Return information about a Fedora Account System group."""
        try:
            group = self.fasclient.group_by_name(name)
            irc.reply('%s: %s' %
                      (name, group['display_name']))
        except AppError:
            irc.reply('There is no group "%s".' % name)
    group = wrap(group, ['text'])

    def admins(self, irc, msg, args, name):
        """<group short name>

        Return the administrators list for the selected group"""

        try:
            group = self.fasclient.group_members(name)
            sponsors = ''
            for person in group:
                if person['role_type'] == 'administrator':
                    sponsors += person['username'] + ' '
            irc.reply('Administrators for %s: %s' % (name, sponsors))
        except AppError:
            irc.reply('There is no group %s.' % name)

    admins = wrap(admins, ['text'])

    def sponsors(self, irc, msg, args, name):
        """<group short name>

        Return the sponsors list for the selected group"""

        try:
            group = self.fasclient.group_members(name)
            sponsors = ''
            for person in group:
                if person['role_type'] == 'sponsor':
                    sponsors += person['username'] + ' '
                elif person['role_type'] == 'administrator':
                    sponsors += '@' + person['username'] + ' '
            irc.reply('Sponsors for %s: %s' % (name, sponsors))
        except AppError:
            irc.reply('There is no group %s.' % name)

    sponsors = wrap(sponsors, ['text'])

    def members(self, irc, msg, args, name):
        """<group short name>

        Return a list of members of the specified group"""
        try:
            group = self.fasclient.group_members(name)
            members = ''
            for person in group:
                if person['role_type'] == 'administrator':
                    members += '@' + person['username'] + ' '
                elif person['role_type'] == 'sponsor':
                    members += '+' + person['username'] + ' '
                else:
                    members += person['username'] + ' '
            irc.reply('Members of %s: %s' % (name, members))
        except AppError:
            irc.reply('There is no group %s.' % name)

    members = wrap(members, ['text'])

    def showticket(self, irc, msg, args, baseurl, number):
        """<baseurl> <number>

        Return the name and URL of a trac ticket or bugzilla bug.
        """
        url = format(baseurl, str(number))
        size = conf.supybot.protocols.http.peekSize()
        text = utils.web.getUrl(url, size=size)
        parser = Title()
        try:
            parser.feed(text)
        except sgmllib.SGMLParseError:
            irc.reply(format('Encountered a problem parsing %u', url))
        if parser.title:
            irc.reply(utils.web.htmlToText(parser.title.strip()) + ' - ' + url)
        else:
            irc.reply(format('That URL appears to have no HTML title ' +
                             'within the first %i bytes.', size))
    showticket = wrap(showticket, ['httpUrl', 'int'])

    def swedish(self, irc, msg, args):
        """takes no arguments

        Humor mmcgrath."""

        # Import this here to avoid a circular import problem.
        from __init__ import __version__

        irc.reply(str('kwack kwack'))
        irc.reply(str('bork bork bork'))
        irc.reply(str('(supybot-fedora version %s)' % __version__))
    swedish = wrap(swedish)

    def wikilink(self, irc, msg, args, name):
        """<username>

        Return MediaWiki link syntax for a FAS user's page on the wiki."""
        try:
            person = self.fasclient.person_by_username(name)
        except:
            irc.reply('Error getting info for user: "******"' % name)
            return
        if not person:
            irc.reply('User "%s" doesn\'t exist' % name)
            return
        string = "[[User:%s|%s]]" % (person["username"],
                                     person["human_name"] or '')
        irc.reply(string.encode('utf-8'))
    wikilink = wrap(wikilink, ['text'])

    def mirroradmins(self, irc, msg, args, hostname):
        """<hostname>

        Return MirrorManager list of FAS usernames which administer <hostname>.
        <hostname> must be the FQDN of the host."""
        url = ("https://admin.fedoraproject.org/mirrormanager/mirroradmins?"
               "tg_format=json&host=" + hostname)
        result = self._load_json(url)['values']
        if len(result) == 0:
            irc.reply('Hostname "%s" not found' % hostname)
            return
        string = 'Mirror Admins of %s: ' % hostname
        string += ' '.join(result)
        irc.reply(string.encode('utf-8'))
    mirroradmins = wrap(mirroradmins, ['text'])

    def pushduty(self, irc, msg, args):
        """

        Return the list of people who are on releng push duty right now.
        """

        def get_persons():
            for meeting in self._meetings_for('release-engineering'):
                yield meeting['meeting_name']

        persons = list(get_persons())

        url = "https://apps.fedoraproject.org/" + \
            "calendar/release-engineering/"

        if not persons:
            response = "Nobody is listed as being on push duty right now..."
            irc.reply(response.encode('utf-8'))
            irc.reply("- " + url.encode('utf-8'))
            return

        persons = ", ".join(persons)
        response = "The following people are on push duty: %s" % persons
        irc.reply(response.encode('utf-8'))
        irc.reply("- " + url.encode('utf-8'))
    pushduty = wrap(pushduty)

    def vacation(self, irc, msg, args):
        """

        Return the list of people who are on vacation right now.
        """

        def get_persons():
            for meeting in self._meetings_for('vacation'):
                for manager in meeting['meeting_manager']:
                    yield manager

        persons = list(get_persons())

        if not persons:
            response = "Nobody is listed as being on vacation right now..."
            irc.reply(response.encode('utf-8'))
            url = "https://apps.fedoraproject.org/calendar/vacation/"
            irc.reply("- " + url.encode('utf-8'))
            return

        persons = ", ".join(persons)
        response = "The following people are on vacation: %s" % persons
        irc.reply(response.encode('utf-8'))
        url = "https://apps.fedoraproject.org/calendar/vacation/"
        irc.reply("- " + url.encode('utf-8'))
    vacation = wrap(vacation)

    def nextmeeting(self, irc, msg, args, channel):
        """<channel>

        Return the next meeting scheduled for a particular channel.
        """

        channel = channel.strip('#').split('@')[0]
        meetings = list(self._future_meetings(channel))
        if not meetings:
            response = "There are no meetings scheduled for #%s." % channel
            irc.reply(response.encode('utf-8'))
            return

        date, meeting = meetings[0]
        response = "The next meeting in #%s is %s (starting %s)" % (
            channel,
            meeting['meeting_name'],
            arrow.get(date).humanize(),
        )
        irc.reply(response.encode('utf-8'))
        base = "https://apps.fedoraproject.org/calendar/location/"
        url = base + urllib.quote("%[email protected]/" % channel)
        irc.reply("- " + url.encode('utf-8'))
    nextmeeting = wrap(nextmeeting, ['text'])

    @staticmethod
    def _future_meetings(channel):
        location = '*****@*****.**' % channel
        meetings = Fedora._query_fedocal(location=location)
        now = datetime.datetime.utcnow()

        for meeting in meetings:
            string = "%s %s" % (meeting['meeting_date'],
                                meeting['meeting_time_start'])
            dt = datetime.datetime.strptime(string, "%Y-%m-%d %H:%M:%S")

            if now < dt:
                yield dt, meeting

    @staticmethod
    def _meetings_for(calendar):
        meetings = Fedora._query_fedocal(calendar=calendar)
        now = datetime.datetime.utcnow()

        for meeting in meetings:
            string = "%s %s" % (meeting['meeting_date'],
                                meeting['meeting_time_start'])
            start = datetime.datetime.strptime(string, "%Y-%m-%d %H:%M:%S")
            string = "%s %s" % (meeting['meeting_date_end'],
                                meeting['meeting_time_stop'])
            end = datetime.datetime.strptime(string, "%Y-%m-%d %H:%M:%S")

            if now >= start and now <= end:
                yield meeting

    @staticmethod
    def _query_fedocal(**kwargs):
        url = 'https://apps.fedoraproject.org/calendar/api/meetings'
        return requests.get(url, params=kwargs).json()['meetings']

    def badges(self, irc, msg, args, name):
        """<username>

        Return badges statistics about a user.
        """
        url = "https://badges.fedoraproject.org/user/" + name
        d = requests.get(url + "/json").json()

        if 'error' in d:
            response = d['error']
        else:
            template = "{name} has unlocked {n} Fedora Badges:  {url}"
            n = len(d['assertions'])
            response = template.format(name=name, url=url, n=n)

        irc.reply(response.encode('utf-8'))
    badges = wrap(badges, ['text'])

    def quote(self, irc, msg, args, arguments):
        """<SYMBOL> [daily, weekly, monthly, quarterly]

        Return some datagrepper statistics on fedmsg categories.
        """

        # First, some argument parsing.  Supybot should be able to do this for
        # us, but I couldn't figure it out.  The supybot.plugins.additional
        # object is the thing to use... except its weird.
        tokens = arguments.split(None, 1)
        if len(tokens) == 1:
            symbol, frame = tokens[0], 'daily'
        else:
            symbol, frame = tokens

        # Second, build a lookup table for symbols.  By default, we'll use the
        # fedmsg category names, take their first 3 characters and uppercase
        # them.  That will take things like "wiki" and turn them into "WIK" and
        # "bodhi" and turn them into "BOD".  This handles a lot for us.  We'll
        # then override those that don't make sense manually here.  For
        # instance "fedoratagger" by default would be "FED", but that's no
        # good.  We want "TAG".
        # Why all this trouble?  Well, as new things get added to the fedmsg
        # bus, we don't want to have keep coming back here and modifying this
        # code.  Hopefully this dance will at least partially future-proof us.
        symbols = dict([
            (processor.__name__.lower(), processor.__name__[:3].upper())
            for processor in fedmsg.meta.processors
        ])
        symbols.update({
            'fedoratagger': 'TAG',
            'fedbadges': 'BDG',
            'buildsys': 'KOJ',
            'pkgdb': 'PKG',
            'meetbot': 'MTB',
            'planet': 'PLN',
            'trac': 'TRC',
            'mailman': 'MM3',
        })

        # Now invert the dict so we can lookup the argued symbol.
        # Yes, this is vulnerable to collisions.
        symbols = dict([(sym, name) for name, sym in symbols.items()])

        # These aren't user-facing topics, so drop 'em.
        del symbols['LOG']
        del symbols['UNH']
        del symbols['ANN']  # And this one is unused...

        key_fmt = lambda d: ', '.join(sorted(d.keys()))

        if symbol not in symbols:
            response = "No such symbol %r.  Try one of %s"
            irc.reply((response % (symbol, key_fmt(symbols))).encode('utf-8'))
            return

        # Now, build another lookup of our various timeframes.
        frames = dict(
            daily=datetime.timedelta(days=1),
            weekly=datetime.timedelta(days=7),
            monthly=datetime.timedelta(days=30),
            quarterly=datetime.timedelta(days=91),
        )

        if frame not in frames:
            response = "No such timeframe %r.  Try one of %s"
            irc.reply((response % (frame, key_fmt(frames))).encode('utf-8'))
            return

        category = [symbols[symbol]]

        t2 = datetime.datetime.utcnow()
        t1 = t2 - frames[frame]
        t0 = t1 - frames[frame]

        # Count the number of messages between t0 and t1, and between t1 and t2
        query1 = dict(start=t0, end=t1, category=category)
        query2 = dict(start=t1, end=t2, category=category)

        # Do this async for superfast datagrepper queries.
        tpool = ThreadPool()
        batched_values = tpool.map(datagrepper_query, [
            dict(start=x, end=y, category=category)
            for x, y in Utils.daterange(t1, t2, SPARKLINE_RESOLUTION)
        ] + [query1, query2])

        count2 = batched_values.pop()
        count1 = batched_values.pop()

        # Just rename the results.  We'll use the rest for the sparkline.
        sparkline_values = batched_values

        yester_phrases = dict(
            daily="yesterday",
            weekly="the week preceding this one",
            monthly="the month preceding this one",
            quarterly="the 3 months preceding these past three months",
        )
        phrases = dict(
            daily="24 hours",
            weekly="week",
            monthly="month",
            quarterly="3 months",
        )

        if count1 and count2:
            percent = ((float(count2) / count1) - 1) * 100
        elif not count1 and count2:
            # If the older of the two time periods had zero messages, but there
            # are some in the more current period.. well, that's an infinite
            # percent increase.
            percent = float('inf')
        elif not count1 and not count2:
            # If counts are zero for both periods, then the change is 0%.
            percent = 0
        else:
            # Else, if there were some messages in the old time period, but
            # none in the current... then that's a 100% drop off.
            percent = -100

        sign = lambda value: value >= 0 and '+' or '-'

        template = u"{sym}, {name} {sign}{percent:.2f}% over {phrase}"
        response = template.format(
            sym=symbol,
            name=symbols[symbol],
            sign=sign(percent),
            percent=abs(percent),
            phrase=yester_phrases[frame],
        )
        irc.reply(response.encode('utf-8'))

        # Now, make a graph out of it.
        sparkline = Utils.sparkline(sparkline_values)

        template = u"     {sparkline}  ⤆ over {phrase}"
        response = template.format(
            sym=symbol,
            sparkline=sparkline,
            phrase=phrases[frame]
        )
        irc.reply(response.encode('utf-8'))

        to_utc = lambda t: time.gmtime(time.mktime(t.timetuple()))
        # And a final line for "x-axis tics"
        t1_fmt = time.strftime("%H:%M UTC %m/%d", to_utc(t1))
        t2_fmt = time.strftime("%H:%M UTC %m/%d", to_utc(t2))
        padding = u" " * (SPARKLINE_RESOLUTION - len(t1_fmt) - 3)
        template = u"     ↑ {t1}{padding}↑ {t2}"
        response = template.format(t1=t1_fmt, t2=t2_fmt, padding=padding)
        irc.reply(response.encode('utf-8'))
    quote = wrap(quote, ['text'])
Пример #38
0
def calc_list():
    '''
    Calculate a list of APAC contributors in different teams
    '''

    output = []
    people_list = []
    country_list = []
    flag = 0
    final_output_list_as = [] 
    final_output_list_eu = []
    final_output_list_na = []
    final_output_list_latam = []
    final_output_list_africa = []
    final_output_list_unknown = []
    full_name = {'AS' : 'APAC', 'NA' : 'North America', \
'SA' : 'LATAM', 'AF' : 'Africa', 'EU' : 'EMEA', 'Unknown' : 'Unknown'}


    #username = '******'
    #password = '******'
    #username = raw_input('Username: '******'Password: '******'output-log.txt','w')

    # Get a dictinary of all people in FAS
    data = fas.people_by_key(key='id', search=u'*', \
fields=['human_name', 'username', 'email', 'status', 'country_code', 'last_seen'])

    # Get a list of people in the groups we care about
    for group_name in group_list:
        log.write ("Getting list for group: %s\n" % group_name)
        # Get the people from this group
        group_people = fas.group_members(group_name)

        #make a list of usernames of a group
        for person in group_people:
        # match our people list to all of FAS now
            for item in data.values():
                user_name = item['username']
                human_name = item['human_name']
                country_code = item['country_code']
                status = item['status']
                #email = item['username'] + '@fedoraproject.org'
                last_seen = item['last_seen']


                if status == 'active':
                    # It's 'oh', not zero!
                    if country_code != None and country_code != 'O1' and country_code != '  ':
                        continent_code = CONTINENT_MAP[country_code]

                        if person['username'] == user_name:
                            entry = [group_name, user_name, 
                                     country_code, last_seen]
                            if continent_code == 'AS' or continent_code == 'AU':
                                apac_list.append(entry)
                            elif continent_code == 'NA':
                                na_list.append(entry)
                            elif continent_code ==  'SA':
                                latam_list.append(entry)
                            elif continent_code == 'AF':
                                africa_list.append(entry)
                            elif continent_code == 'EU':
                                emea_list.append(entry)
                            else:
                                unknown_list.append(entry)

                else:
                    if country_code != None and country_code != 'O1' and country_code != '  ':
                        continent_code = CONTINENT_MAP[country_code]

                        if person['username'] == user_name:
                            entry = [group_name, user_name,
                                     country_code, last_seen]
                            inactive_list.append(entry)

# Now we have a output list like 
#[['rdsharma4u', 'Ravi Datta Sharma','India','*****@*****.**','1','AS'],
#['red', 'Sandro Mathys', 'Switzerland', '*****@*****.**', '10', 'EU']]

    log.write ("ACTIVE CONTRIBUTORS LIST:\n")
    log.write ("** APAC **\n")
    for person in apac_list:
        log.write ("%s: - %s FROM %s last seen on %s\n" % (person[0], person[1], person[2], person[3] ))
    log.write ("** NA **\n")
    for person in na_list:
        log.write ("%s: - %s FROM %s last seen on %s\n" % (person[0], person[1], person[2], person[3] ))
    log.write ("** LATAM **\n")
    for person in latam_list:
        log.write ("%s: - %s FROM %s last seen on %s\n" % (person[0], person[1], person[2], person[3] ))
    log.write ("** Africa **\n")
    for person in africa_list:
        log.write ("%s: - %s FROM %s last seen on %s\n" % (person[0], person[1], person[2], person[3] ))
    log.write ("** EMEA **\n")
    for person in emea_list:
        log.write ("%s: - %s FROM %s last seen on %s\n" % (person[0], person[1], person[2], person[3] ))

    log.write ("INACTIVE CONTRIBUTORS LIST:")
    for person in inactive_list:
        log.write ("%s: - %s FROM %s last seen on %s\n" % (person[0], person[1], person[2], person[3] ))
Пример #39
0
def calc_list():
    '''
    Calculate a list of APAC contributors in different teams
    '''

    output = []
    people_list = []
    country_list = []
    flag = 0
    final_output_list_as = [] 
    final_output_list_eu = []
    final_output_list_na = []
    final_output_list_latam = []
    final_output_list_africa = []
    final_output_list_unknown = []
    full_name = {'AS' : 'APAC', 'NA' : 'North America', \
'SA' : 'LATAM', 'AF' : 'Africa', 'EU' : 'EMEA', 'Unknown' : 'Unknown'}


#    username = '******'
#    password = '******'    
    username = raw_input('Username: '******'Password: '******'id', search=u'*', \
fields=['human_name', 'username', 'email', 'status', 'country_code'])

    # Get a list of people in the groups we care about
    for group_name in group_list:
        print "Getting list for group: %s" % group_name
        # Get the people from this group
        group_people = fas.group_members(group_name)

        #make a list of usernames of a group
        for person in group_people:
        # match our people list to all of FAS now
            for item in data.values():
                user_name = item['username']
                human_name = item['human_name']
                country_code = item['country_code']
                status = item['status']
                #email = item['username'] + '@fedoraproject.org'


                if status == 'active':
                    # It's 'oh', not zero!
                    if country_code != None and country_code != 'O1' and country_code != '  ':
                        continent_code = CONTINENT_MAP[country_code]

                        if continent_code == 'AS' or continent_code == 'AU':
                            if person['username'] == user_name:
                                entry = [group_name, user_name, human_name, country_code]
                                output.append(entry)

# Now we have a output list like 
#[['rdsharma4u', 'Ravi Datta Sharma','India','*****@*****.**','1','AS'],
#['red', 'Sandro Mathys', 'Switzerland', '*****@*****.**', '10', 'EU']]

    for person in output:
        print ("%s: %s - %s" % (person[0], person[1], person[2]))
Пример #40
0
def calc_list():
    '''
    Calculate a list of APAC contributors in different teams
    '''

    output = []
    people_list = []
    country_list = []
    flag = 0
    final_output_list_as = []
    final_output_list_eu = []
    final_output_list_na = []
    final_output_list_latam = []
    final_output_list_africa = []
    final_output_list_unknown = []
    full_name = {'AS' : 'APAC', 'NA' : 'North America', \
'SA' : 'LATAM', 'AF' : 'Africa', 'EU' : 'EMEA', 'Unknown' : 'Unknown'}

    #    username = '******'
    #    password = '******'
    username = raw_input('Username: '******'Password: '******'id', search=u'*', \
fields=['human_name', 'username', 'email', 'status', 'country_code'])

    # Get a list of people in the groups we care about
    for group_name in group_list:
        print "Getting list for group: %s" % group_name
        # Get the people from this group
        group_people = fas.group_members(group_name)

        #make a list of usernames of a group
        for person in group_people:
            # match our people list to all of FAS now
            for item in data.values():
                user_name = item['username']
                human_name = item['human_name']
                country_code = item['country_code']
                status = item['status']
                #email = item['username'] + '@fedoraproject.org'

                if status == 'active':
                    # It's 'oh', not zero!
                    if country_code != None and country_code != 'O1' and country_code != '  ':
                        continent_code = CONTINENT_MAP[country_code]

                        if continent_code == 'AS' or continent_code == 'AU':
                            if person['username'] == user_name:
                                entry = [
                                    group_name, user_name, human_name,
                                    country_code
                                ]
                                output.append(entry)


# Now we have a output list like
#[['rdsharma4u', 'Ravi Datta Sharma','India','*****@*****.**','1','AS'],
#['red', 'Sandro Mathys', 'Switzerland', '*****@*****.**', '10', 'EU']]

    for person in output:
        print("%s: %s - %s" % (person[0], person[1], person[2]))
Пример #41
0
from fedora.client.fas2 import AccountSystem
import re

fas = AccountSystem(username='******',
                    password='******')

user_id = input()

ret_val = fas.people_by_key(key='email', search=user_id, fields=['id'])

email = str(ret_val.keys()).split("'")[1::2]
print('\n'.join(email))
Пример #42
0
def calc_list():
    '''
    Calculate a list of APAC contributors in different teams
    '''

    output = []
    people_list = []
    country_list = []
    flag = 0
    final_output_list_as = []
    final_output_list_eu = []
    final_output_list_na = []
    final_output_list_latam = []
    final_output_list_africa = []
    final_output_list_unknown = []
    full_name = {'AS' : 'APAC', 'NA' : 'North America', \
'SA' : 'LATAM', 'AF' : 'Africa', 'EU' : 'EMEA', 'Unknown' : 'Unknown'}

    #username = '******'
    #password = '******'
    #username = raw_input('Username: '******'Password: '******'output-log.txt', 'w')

    # Get a dictinary of all people in FAS
    data = fas.people_by_key(key='id', search=u'*', \
fields=['human_name', 'username', 'email', 'status', 'country_code', 'last_seen'])

    # Get a list of people in the groups we care about
    for group_name in group_list:
        log.write("Getting list for group: %s\n" % group_name)
        # Get the people from this group
        group_people = fas.group_members(group_name)

        #make a list of usernames of a group
        for person in group_people:
            # match our people list to all of FAS now
            for item in data.values():
                user_name = item['username']
                human_name = item['human_name']
                country_code = item['country_code']
                status = item['status']
                #email = item['username'] + '@fedoraproject.org'
                last_seen = item['last_seen']

                if status == 'active':
                    # It's 'oh', not zero!
                    if country_code != None and country_code != 'O1' and country_code != '  ':
                        continent_code = CONTINENT_MAP[country_code]

                        if person['username'] == user_name:
                            entry = [
                                group_name, user_name, country_code, last_seen
                            ]
                            if continent_code == 'AS' or continent_code == 'AU':
                                apac_list.append(entry)
                            elif continent_code == 'NA':
                                na_list.append(entry)
                            elif continent_code == 'SA':
                                latam_list.append(entry)
                            elif continent_code == 'AF':
                                africa_list.append(entry)
                            elif continent_code == 'EU':
                                emea_list.append(entry)
                            else:
                                unknown_list.append(entry)

                else:
                    if country_code != None and country_code != 'O1' and country_code != '  ':
                        continent_code = CONTINENT_MAP[country_code]

                        if person['username'] == user_name:
                            entry = [
                                group_name, user_name, country_code, last_seen
                            ]
                            inactive_list.append(entry)


# Now we have a output list like
#[['rdsharma4u', 'Ravi Datta Sharma','India','*****@*****.**','1','AS'],
#['red', 'Sandro Mathys', 'Switzerland', '*****@*****.**', '10', 'EU']]

    log.write("ACTIVE CONTRIBUTORS LIST:\n")
    log.write("** APAC **\n")
    for person in apac_list:
        log.write("%s: - %s FROM %s last seen on %s\n" %
                  (person[0], person[1], person[2], person[3]))
    log.write("** NA **\n")
    for person in na_list:
        log.write("%s: - %s FROM %s last seen on %s\n" %
                  (person[0], person[1], person[2], person[3]))
    log.write("** LATAM **\n")
    for person in latam_list:
        log.write("%s: - %s FROM %s last seen on %s\n" %
                  (person[0], person[1], person[2], person[3]))
    log.write("** Africa **\n")
    for person in africa_list:
        log.write("%s: - %s FROM %s last seen on %s\n" %
                  (person[0], person[1], person[2], person[3]))
    log.write("** EMEA **\n")
    for person in emea_list:
        log.write("%s: - %s FROM %s last seen on %s\n" %
                  (person[0], person[1], person[2], person[3]))

    log.write("INACTIVE CONTRIBUTORS LIST:")
    for person in inactive_list:
        log.write("%s: - %s FROM %s last seen on %s\n" %
                  (person[0], person[1], person[2], person[3]))
Пример #43
0
 def __init__(self, fas_user: str = None, fas_password: str = None):
     self._fas: AccountSystem = AccountSystem(username=fas_user,
                                              password=fas_password)
Пример #44
0
def login(username, password):
    fas = AccountSystem(username=username, password=password)
    roles = fas.people_query(constraints={
        'username': username, 'group': '%', 'role_status': 'approved'},
        columns=['group'])
    return roles