Hello community,

here is the log from the commit of package python-shodan for openSUSE:Factory 
checked in at 2020-11-09 13:57:52
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/python-shodan (Old)
 and      /work/SRC/openSUSE:Factory/.python-shodan.new.11331 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "python-shodan"

Mon Nov  9 13:57:52 2020 rev:25 rq:846973 version:1.24.0

Changes:
--------
--- /work/SRC/openSUSE:Factory/python-shodan/python-shodan.changes      
2020-09-21 17:42:29.704860549 +0200
+++ /work/SRC/openSUSE:Factory/.python-shodan.new.11331/python-shodan.changes   
2020-11-09 13:59:02.831750052 +0100
@@ -1,0 +2,8 @@
+Sun Nov  1 19:33:22 UTC 2020 - Sebastian Wagner <sebix+novell....@sebix.at>
+
+- Update to version 1.24.0:
+ * use default config dir `~/.config/shodan`, but support existing 
installations
+ * Fix bug that caused extra newlines when converting `.json.gz` data file to 
CSV on Windows
+ * Fix linting error
+
+-------------------------------------------------------------------

Old:
----
  shodan-1.23.1.tar.gz

New:
----
  shodan-1.24.0.tar.gz

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ python-shodan.spec ++++++
--- /var/tmp/diff_new_pack.hakkjt/_old  2020-11-09 13:59:03.447748709 +0100
+++ /var/tmp/diff_new_pack.hakkjt/_new  2020-11-09 13:59:03.447748709 +0100
@@ -19,7 +19,7 @@
 %{?!python_module:%define python_module() python-%{**} python3-%{**}}
 %{!?license: %global license %doc}
 Name:           python-shodan
-Version:        1.23.1
+Version:        1.24.0
 Release:        0
 Summary:        Python library and command-line utility for Shodan
 License:        MIT

++++++ shodan-1.23.1.tar.gz -> shodan-1.24.0.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/shodan-1.23.1/PKG-INFO new/shodan-1.24.0/PKG-INFO
--- old/shodan-1.23.1/PKG-INFO  2020-09-08 02:40:48.000000000 +0200
+++ new/shodan-1.24.0/PKG-INFO  2020-10-12 00:55:18.000000000 +0200
@@ -1,6 +1,6 @@
 Metadata-Version: 2.1
 Name: shodan
-Version: 1.23.1
+Version: 1.24.0
 Summary: Python library and command-line utility for Shodan 
(https://developer.shodan.io)
 Home-page: http://github.com/achillean/shodan-python/tree/master
 Author: John Matherly
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/shodan-1.23.1/setup.py new/shodan-1.24.0/setup.py
--- old/shodan-1.23.1/setup.py  2020-09-08 02:19:46.000000000 +0200
+++ new/shodan-1.24.0/setup.py  2020-10-12 00:24:01.000000000 +0200
@@ -9,7 +9,7 @@
 
 setup(
     name='shodan',
-    version='1.23.1',
+    version='1.24.0',
     description='Python library and command-line utility for Shodan 
(https://developer.shodan.io)',
     long_description=README,
     long_description_content_type='text/x-rst',
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/shodan-1.23.1/shodan/cli/alert.py 
new/shodan-1.24.0/shodan/cli/alert.py
--- old/shodan-1.23.1/shodan/cli/alert.py       2020-04-06 22:06:05.000000000 
+0200
+++ new/shodan-1.24.0/shodan/cli/alert.py       2020-10-12 00:48:51.000000000 
+0200
@@ -1,10 +1,73 @@
 import click
+import csv
 import shodan
 
+from collections import defaultdict
 from operator import itemgetter
 from shodan.cli.helpers import get_api_key
 
 
+MAX_QUERY_LENGTH = 1000
+
+
+def aggregate_facet(api, networks, facets):
+    """Merge the results from multiple facet API queries into a single result 
object.
+    This is necessary because a user might be monitoring a lot of IPs/ 
networks so it doesn't fit
+    into a single API call.
+    """
+    def _merge_custom_facets(lfacets, results):
+        for key in results['facets']:
+            if key not in lfacets:
+                lfacets[key] = defaultdict(int)
+
+            for item in results['facets'][key]:
+                lfacets[key][item['value']] += item['count']
+
+    # We're going to create a custom facets dict where
+    # the key is the value of a facet. Normally the facets
+    # object is a list where each item has a "value" and "count" property.
+    tmp_facets = {}
+    count = 0
+
+    query = 'net:'
+
+    for net in networks:
+        query += '{},'.format(net)
+
+        # Start running API queries if the query length is getting long
+        if len(query) > MAX_QUERY_LENGTH:
+            results = api.count(query[:-1], facets=facets)
+
+            _merge_custom_facets(tmp_facets, results)
+            count += results['total']
+            query = 'net:'
+
+    # Run any remaining search query
+    if query[-1] != ':':
+        results = api.count(query[:-1], facets=facets)
+
+        _merge_custom_facets(tmp_facets, results)
+        count += results['total']
+
+    # Convert the internal facets structure back to the one that
+    # the API returns.
+    new_facets = {}
+    for facet in tmp_facets:
+        sorted_items = sorted(tmp_facets[facet].items(), key=itemgetter(1), 
reverse=True)
+        new_facets[facet] = [{'value': key, 'count': value} for key, value in 
sorted_items]
+
+    # Make sure the facet keys exist even if there weren't any results
+    for facet, _ in facets:
+        if facet not in new_facets:
+            new_facets[facet] = []
+
+    return {
+        'matches': [],
+        'facets': new_facets,
+        'total': count,
+    }
+
+
 @click.group()
 def alert():
     """Manage the network alerts for your account"""
@@ -149,6 +212,95 @@
         click.echo("You haven't created any alerts yet.")
 
 
+@alert.command(name='stats')
+@click.option('--limit', help='The number of results to return.', default=10, 
type=int)
+@click.option('--filename', '-O', help='Save the results in a CSV file of the 
provided name.', default=None)
+@click.argument('facets', metavar='<facets ...>', nargs=-1)
+def alert_stats(limit, filename, facets):
+    """Show summary information about your monitored networks"""
+    # Setup Shodan
+    key = get_api_key()
+    api = shodan.Shodan(key)
+
+    # Make sure the user didn't supply an empty string
+    if not facets:
+        raise click.ClickException('No facets provided')
+
+    facets = [(facet, limit) for facet in facets]
+
+    # Get the list of IPs/ networks that the user is monitoring
+    networks = set()
+    try:
+        alerts = api.alerts()
+        for alert in alerts:
+            for tmp in alert['filters']['ip']:
+                networks.add(tmp)
+    except shodan.APIError as e:
+        raise click.ClickException(e.value)
+
+    # Grab the facets the user requested
+    try:
+        results = aggregate_facet(api, networks, facets)
+    except shodan.APIError as e:
+        raise click.ClickException(e.value)
+
+    # TODO: The below code was taken from __main__.py:stats() - we should 
refactor it so the code can be shared
+    # Print the stats tables
+    for facet in results['facets']:
+        click.echo('Top {} Results for Facet: 
{}'.format(len(results['facets'][facet]), facet))
+
+        for item in results['facets'][facet]:
+            # Force the value to be a string - necessary because some facet 
values are numbers
+            value = u'{}'.format(item['value'])
+
+            click.echo(click.style(u'{:28s}'.format(value), fg='cyan'), 
nl=False)
+            click.echo(click.style(u'{:12,d}'.format(item['count']), 
fg='green'))
+
+        click.echo('')
+
+    # Create the output file if requested
+    fout = None
+    if filename:
+        if not filename.endswith('.csv'):
+            filename += '.csv'
+        fout = open(filename, 'w')
+        writer = csv.writer(fout, dialect=csv.excel)
+
+        # Write the header that contains the facets
+        row = []
+        for facet in results['facets']:
+            row.append(facet)
+            row.append('')
+        writer.writerow(row)
+
+        # Every facet has 2 columns (key, value)
+        counter = 0
+        has_items = True
+        while has_items:
+            # pylint: disable=W0612
+            row = ['' for i in range(len(results['facets']) * 2)]
+
+            pos = 0
+            has_items = False
+            for facet in results['facets']:
+                values = results['facets'][facet]
+
+                # Add the values for the facet into the current row
+                if len(values) > counter:
+                    has_items = True
+                    row[pos] = values[counter]['value']
+                    row[pos + 1] = values[counter]['count']
+
+                pos += 2
+
+            # Write out the row
+            if has_items:
+                writer.writerow(row)
+
+            # Move to the next row of values
+            counter += 1
+
+
 @alert.command(name='remove')
 @click.argument('alert_id', metavar='<alert ID>')
 def alert_remove(alert_id):
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/shodan-1.23.1/shodan/cli/settings.py 
new/shodan-1.24.0/shodan/cli/settings.py
--- old/shodan-1.23.1/shodan/cli/settings.py    2020-09-08 02:37:18.000000000 
+0200
+++ new/shodan-1.24.0/shodan/cli/settings.py    2020-10-12 00:24:28.000000000 
+0200
@@ -4,7 +4,7 @@
 if path.exists(path.expanduser("~/.shodan")):
     SHODAN_CONFIG_DIR = '~/.shodan/'
 else:
-    SHODAN_CONFIG_DIR="~/.config/shodan/"
+    SHODAN_CONFIG_DIR = "~/.config/shodan/"
 
 COLORIZE_FIELDS = {
     'ip_str': 'green',
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/shodan-1.23.1/shodan.egg-info/PKG-INFO 
new/shodan-1.24.0/shodan.egg-info/PKG-INFO
--- old/shodan-1.23.1/shodan.egg-info/PKG-INFO  2020-09-08 02:40:48.000000000 
+0200
+++ new/shodan-1.24.0/shodan.egg-info/PKG-INFO  2020-10-12 00:55:18.000000000 
+0200
@@ -1,6 +1,6 @@
 Metadata-Version: 2.1
 Name: shodan
-Version: 1.23.1
+Version: 1.24.0
 Summary: Python library and command-line utility for Shodan 
(https://developer.shodan.io)
 Home-page: http://github.com/achillean/shodan-python/tree/master
 Author: John Matherly


Reply via email to