feat(compare): render git diff style output

This commit is contained in:
tiennm99 committed 2026-06-10 09:32:42 +07:00
1 parent 10298f4f5e
commit 24bf801656
2 files changed
+53 -20

No files matched your search

+2 -1
View File
@@ -49,7 +49,8 @@ If `time1` and `time2` are omitted, the command compares the latest two crawls f
python compare.py <group_id> python compare.py <group_id>
``` ```
The output lists members added in `time2` and removed since `time1`. The output uses a git-diff-style view: removed members are prefixed with `-`,
added members are prefixed with `+`, and the hunk header shows member counts.
## Configuration ## Configuration
+51 -19
View File
@@ -1,6 +1,11 @@
import argparse import argparse
import sys import sys
RESET = '\033[0m'
GREEN = '\033[32m'
RED = '\033[31m'
CYAN = '\033[36m'
def parse_args(): def parse_args():
parser = argparse.ArgumentParser( parser = argparse.ArgumentParser(
@@ -48,38 +53,65 @@ def print_summary(group_id, before_record, after_record, added, removed):
title = after_record.get('title') or before_record.get('title') or '' title = after_record.get('title') or before_record.get('title') or ''
before_members = before_record.get('members', []) before_members = before_record.get('members', [])
after_members = after_record.get('members', []) after_members = after_record.get('members', [])
before_time = before_record.get('time')
after_time = after_record.get('time')
label = f'{title} ({group_id})' if title else str(group_id)
print(f'group: {title} ({group_id})' if title else f'group: {group_id}') print(f'diff --telegram-group "{label}"')
print(f'before: {before_record.get("time")} ({len(before_members)} members)') print(color(f'--- crawl/{before_time}', RED))
print(f'after: {after_record.get("time")} ({len(after_members)} members)') print(color(f'+++ crawl/{after_time}', GREEN))
print(color(
f'@@ members: {len(before_members)} -> {len(after_members)} '
f'(+{len(added)} -{len(removed)}) @@',
CYAN,
))
print() print()
print(f'added: {len(added)}') widths = column_widths([*removed, *added])
for member in added:
print(f'+ {format_member(member)}')
print()
print(f'removed: {len(removed)}')
for member in removed: for member in removed:
print(f'- {format_member(member)}') print(color(format_member_row('-', member, widths), RED))
for member in added:
print(color(format_member_row('+', member, widths), GREEN))
if not added and not removed: if not added and not removed:
print() print(' no membership changes.')
print('no membership changes.')
def format_member(member): def color(text, code):
parts = [str(member.get('id'))] if not sys.stdout.isatty():
return text
return f'{code}{text}{RESET}'
def member_columns(member):
username = member.get('username') username = member.get('username')
full_name = ' '.join( full_name = ' '.join(
part for part in [member.get('first_name'), member.get('last_name')] part for part in [member.get('first_name'), member.get('last_name')]
if part if part
) )
if username: return [
parts.append(f'@{username}') str(member.get('id')),
if full_name: f'@{username}' if username else '',
parts.append(full_name) full_name,
return ' | '.join(parts) ]
def column_widths(members):
widths = [2, 8, 4]
for member in members:
for index, value in enumerate(member_columns(member)):
widths[index] = max(widths[index], len(value))
return widths
def format_member_row(prefix, member, widths):
member_id, username, full_name = member_columns(member)
return (
f'{prefix} '
f'{member_id:<{widths[0]}} '
f'{username:<{widths[1]}} '
f'{full_name:<{widths[2]}}'
).rstrip()
if __name__ == '__main__': if __name__ == '__main__':