Initial push

This commit is contained in:
Mattia Verga 2022-02-13 14:00:00 +01:00
commit d6212dbe91
3 changed files with 223 additions and 0 deletions

21
LICENSE Normal file
View file

@ -0,0 +1,21 @@
MIT License
Copyright (c) 2017 Mattia Verga
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

40
README.md Normal file
View file

@ -0,0 +1,40 @@
# find-inactive-packagers
A script for detecting inactive user in the Fedora packager group.
The script will search for any activity in the last year in:
- src.fedoraproject.org
- datagrepper (this includes src.fedoraproject.org but it's slower)
- Fedora mailing lists
It will output the `inactive_packagers.csv` file with a list of all users in the packager
group and their email which are found to be inactive. This can be used to contact
the inactive users, asking them to show some activity in pagure, datagrepper or mailing lists.
If `inactive_packagers.csv` is already present in the directory, it will be used as to be the
result of the previous run, so the script will also output the `still_inactive.csv` file.
This other file will list all usernames which were contacted after the previous run,
but still don't show any activity. Therefore we should consider these users to have
abandoned Fedora.
Use the `--privacy` flag to not print emails in the log.
You need fasjson_client to be installed and an active kerberos ticket
to login to fasjson.fedoraproject.org.
## Example usage
```
$ pipenv shell
...
$ pip install fasjson-client
...
$ kinit <USER>@FEDORAPROJECT.ORG
...
$ python find-inactive-packagers.py [--privacy]
```
## License
find-inactive-packagers is licensed under MIT.

162
find_inactive_packagers.py Normal file
View file

@ -0,0 +1,162 @@
# -*- coding:utf-8 -*-
#
# MIT License
#
# Copyright (c) 2022 Mattia Verga <mattia.verga@protonmail.com>
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in all
# copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.
#
"""Detect inactive user in the packager group.
The script will search for any activity in the last year in:
- src.fedoraproject.org
- datagrepper (this includes src.fedoraproject.org but it's slower)
- Fedora mailing lists
It will output the 'inactive_packagers.csv' file with a list of all users in the packager
group and their email which are found to be inactive. This can be used to contact
the inactive users, asking them to show some activity in pagure, datagrepper or mailing lists.
If 'inactive_packagers.csv' is already present in the directory, it will be used as to be the
result of the previous run, so the script will also output the 'still_inactive.csv' file.
This other file will list all usernames which were contacted after the previous run,
but still don't show any activity. Therefore we should consider these users to have
abandoned Fedora.
Use the '--privacy' flag to not print emails in the log.
You need fasjson_client to be installed and an active kerberos ticket
to login to fasjson.fedoraproject.org.
"""
import argparse
import logging
import requests
import sys
from copy import copy
from datetime import datetime, timezone
from os.path import exists as file_exists
from fasjson_client import Client
logging.basicConfig(level=logging.INFO,
format='%(message)s',
handlers=[
logging.FileHandler(f'find_inactive_packagers_{datetime.now(timezone.utc).strftime("%Y_%m_%d")}.log', 'w+'),
logging.StreamHandler(sys.stdout)
])
parser = argparse.ArgumentParser()
parser.add_argument("--privacy", action='store_true', help='Hide users email in log.')
args = parser.parse_args()
prev_results = {}
if file_exists('inactive_packagers.csv'):
with open('inactive_packagers.csv', 'r') as fin:
for line in fin:
user, email = line.split(',')
prev_results[user] = email.strip()
print(prev_results)
# OLD method
# r = requests.get('https://src.fedoraproject.org/api/0/group/packager').json()
# packagers = r.get('members', [])
client = Client('https://fasjson.fedoraproject.org/')
packagers = client.list_group_members(groupname='packager').result
logging.info(f'### Found {len(packagers)} users in the packager group. ###')
inactive_packagers = []
# Check for activity in Pagure
# may take a while...
logging.info(f'Checking users activity in src.fedoraproject.org...')
for i, p in enumerate(packagers):
user = p.get('username')
try:
r = requests.get(f'https://src.fedoraproject.org/api/0/user/{user}/activity/stats').json()
if not r:
logging.info(f'No packaging activity detected for user {user}.')
inactive_packagers.append(user)
except Exception:
# May happen when the user never interacted with pagure
logging.warning(f'Error while retrieving data for user {user} (possibly not existent).')
inactive_packagers.append(user)
if i % 100 == 0:
logging.info(f'Done {i}.')
logging.info(f'### Found {len(inactive_packagers)} users with no activity in pagure over the last year. ###')
# Check for activity Fedora wide by datagrepper
# May take more than a while...
logging.info(f'Checking users activity in datagrepper...')
for i, p in enumerate(copy(inactive_packagers)):
try:
r = requests.get(f'https://apps.fedoraproject.org/datagrepper/raw/?user={p}&order=desc&delta=31536000&rows_per_page=10').json()
if r.get('total', 0) != 0:
logging.info(f'User {p} is still active in Fedora.')
inactive_packagers.remove(p)
except Exception:
# May happen if there are a lot of entries in datagrepper
logging.error(f'Error while retrieving data for user {p}.')
if i % 100 == 0:
logging.info(f'Done {i}.')
logging.info(f'### Found {len(inactive_packagers)} users which also show no activity in datagrepper over the last year. ###')
# Finally, check for any activity in mailing lists
logging.info(f'Checking users activity in mailing lists...')
packager_email_map = {}
for i, p in enumerate(inactive_packagers):
try:
packager = client.get_user(username=p).result
email = packager['emails'][0]
r = requests.get(f'https://lists.fedoraproject.org/archives/api/sender/{email}/emails/?ordering=-date').json()
if r.get('count', 0) != 0:
last_email_date = datetime.fromisoformat(r.get('results')[0]['date'].replace('Z', '+00:00'))
time_delta = datetime.now(timezone.utc) - last_email_date
if time_delta.days > 365:
packager_email_map[p] = email
else:
logging.info(f'Found recent email from user {p}: {last_email_date}.')
else:
packager_email_map[p] = email
except Exception:
logging.error(f'Error while retrieving last mailing lists activity for user {p}.')
packager_email_map[p] = email
if i % 100 == 0:
logging.info(f'Done {i}.')
logging.info(f'### Found {len(packager_email_map)} users which show also no activity in mailing lists over the last year. ###')
if packager_email_map:
logging.info(f'Final results are:')
with open('inactive_packagers.csv', 'w') as fout:
for user, email in packager_email_map.items():
logging.info(f'{user} - {email if not args.privacy else "***"}')
fout.write(f'{user},{email}\n')
if prev_results:
still_inactive = set(prev_results.keys()).intersection(packager_email_map.keys())
logging.info(f'### These {len(still_inactive)} users didn\'t react to previous inquiry: ###')
with open('still_inactive.csv', 'w') as finactive:
for user in still_inactive:
logging.info(f'{user}')
finactive.write(f'{user}\n')