add errorrate
This commit is contained in:
parent
dd192c012a
commit
4845d5d0dc
3 changed files with 100 additions and 9 deletions
|
|
@ -1,6 +1,13 @@
|
||||||
Copy this to BotFather when setting commands with /setcommands:
|
Autopilot bot command list for @BotFather
|
||||||
|
|
||||||
autopilot - Toggle automatic applications (on/off)
|
Use @BotFather -> /setcommands and paste the following lines exactly (one per line):
|
||||||
status - Show current status and stats
|
|
||||||
plot - Show weekly listing patterns
|
/autopilot - Enable or disable automatic applications. Usage: `/autopilot on` or `/autopilot off`
|
||||||
help - Show available commands
|
/status - Show current status and statistics (autopilot state, application counts by company)
|
||||||
|
/plot - Show weekly listing patterns (image)
|
||||||
|
/errorrate - Show autopilot success vs failure plot (image)
|
||||||
|
/help - Show help and command usage
|
||||||
|
|
||||||
|
Example: send `/setcommands` to @BotFather, then paste the above lines and confirm.
|
||||||
|
|
||||||
|
Security reminder: set your bot privacy and only allow the trusted chat id to issue commands. Keep your `TELEGRAM_BOT_TOKEN` secret.
|
||||||
|
|
|
||||||
11
README.md
11
README.md
|
|
@ -91,10 +91,13 @@ python monitor.py
|
||||||
|
|
||||||
## Telegram Commands
|
## Telegram Commands
|
||||||
|
|
||||||
- `/status` - Show current status and recent listings
|
- `/autopilot on|off` - Enable or disable automatic applications (use `/autopilot on` or `/autopilot off`).
|
||||||
- `/autopilot` - Toggle auto-apply on/off
|
- `/status` - Show current status and statistics (autopilot state, application counts by company).
|
||||||
- `/listings` - Show current listings
|
- `/plot` - Generate and send a weekly listing-patterns plot (`data/weekly_plot.png`).
|
||||||
- `/help` - Show available commands
|
- `/errorrate` - Generate and send an autopilot success vs failure plot (`data/error_rate.png`).
|
||||||
|
- `/help` - Show available commands and usage information.
|
||||||
|
|
||||||
|
Note: The bot only processes commands from the configured `TELEGRAM_CHAT_ID`. Use `/autopilot off` while testing selector changes or after modifying configuration to avoid accidental submissions.
|
||||||
|
|
||||||
## Data files
|
## Data files
|
||||||
|
|
||||||
|
|
|
||||||
81
monitor.py
81
monitor.py
|
|
@ -185,6 +185,8 @@ class TelegramBot:
|
||||||
self._handle_help_command()
|
self._handle_help_command()
|
||||||
elif text == "/plot":
|
elif text == "/plot":
|
||||||
self._handle_plot_command()
|
self._handle_plot_command()
|
||||||
|
elif text == "/errorrate":
|
||||||
|
self._handle_error_rate_command()
|
||||||
elif text.startswith("/"):
|
elif text.startswith("/"):
|
||||||
self._handle_unknown_command(text)
|
self._handle_unknown_command(text)
|
||||||
|
|
||||||
|
|
@ -235,6 +237,85 @@ When autopilot is ON, I will automatically apply to new listings."""
|
||||||
|
|
||||||
def _handle_unknown_command(self, text):
|
def _handle_unknown_command(self, text):
|
||||||
cmd = text.split()[0] if text else text
|
cmd = text.split()[0] if text else text
|
||||||
|
|
||||||
|
def _handle_error_rate_command(self):
|
||||||
|
"""Generate and send a plot showing success vs failure ratio for autopilot applications."""
|
||||||
|
logger.info("Generating autopilot errorrate plot...")
|
||||||
|
try:
|
||||||
|
plot_path, summary = self._generate_error_rate_plot()
|
||||||
|
if plot_path:
|
||||||
|
caption = "📉 <b>Autopilot Success vs Failure</b>\n\n" + summary
|
||||||
|
self._send_photo(plot_path, caption)
|
||||||
|
else:
|
||||||
|
self._send_message("📉 Not enough application data to generate errorrate plot.")
|
||||||
|
except Exception as e:
|
||||||
|
logger.error(f"Error generating errorrate plot: {e}")
|
||||||
|
import traceback
|
||||||
|
logger.error(traceback.format_exc())
|
||||||
|
self._send_message(f"❌ Error generating errorrate plot: {str(e)}")
|
||||||
|
|
||||||
|
def _generate_error_rate_plot(self):
|
||||||
|
"""Read applications.json and produce a plot image + summary text.
|
||||||
|
|
||||||
|
Returns (plot_path, summary_text) or (None, "") if insufficient data.
|
||||||
|
"""
|
||||||
|
if not APPLICATIONS_FILE.exists():
|
||||||
|
logger.warning("No applications.json found for errorrate plot")
|
||||||
|
return None, ""
|
||||||
|
|
||||||
|
try:
|
||||||
|
with open(APPLICATIONS_FILE, 'r', encoding='utf-8') as f:
|
||||||
|
apps = json.load(f)
|
||||||
|
if not apps:
|
||||||
|
return None, ""
|
||||||
|
|
||||||
|
# Convert to DataFrame
|
||||||
|
rows = []
|
||||||
|
for _id, rec in apps.items():
|
||||||
|
ts = rec.get('timestamp')
|
||||||
|
try:
|
||||||
|
dt = pd.to_datetime(ts)
|
||||||
|
except Exception:
|
||||||
|
dt = pd.NaT
|
||||||
|
rows.append({'id': _id, 'company': rec.get('company'), 'success': bool(rec.get('success')), 'ts': dt})
|
||||||
|
df = pd.DataFrame(rows)
|
||||||
|
df = df.dropna(subset=['ts'])
|
||||||
|
if df.empty:
|
||||||
|
return None, ""
|
||||||
|
|
||||||
|
df['date'] = df['ts'].dt.floor('D')
|
||||||
|
grouped = df.groupby('date').agg(total=('id','count'), successes=('success', lambda x: x.sum()))
|
||||||
|
grouped['failures'] = grouped['total'] - grouped['successes']
|
||||||
|
grouped['error_rate'] = grouped['failures'] / grouped['total']
|
||||||
|
|
||||||
|
# Prepare plot
|
||||||
|
fig, (ax1, ax2) = plt.subplots(2, 1, figsize=(12, 8), sharex=True)
|
||||||
|
grouped[['successes','failures']].plot(kind='bar', stacked=True, ax=ax1, color=['#2E8B57','#C44A4A'])
|
||||||
|
ax1.set_ylabel('Count')
|
||||||
|
ax1.set_title('Autopilot: Successes vs Failures (by day)')
|
||||||
|
|
||||||
|
ax2.plot(grouped.index, grouped['error_rate'], marker='o', color='#3333AA')
|
||||||
|
ax2.set_ylim(0,1)
|
||||||
|
ax2.set_ylabel('Error rate')
|
||||||
|
ax2.set_xlabel('Date')
|
||||||
|
ax2.set_title('Daily Error Rate (failures / total)')
|
||||||
|
|
||||||
|
plt.tight_layout()
|
||||||
|
plot_path = DATA_DIR / 'error_rate.png'
|
||||||
|
fig.savefig(plot_path)
|
||||||
|
plt.close(fig)
|
||||||
|
|
||||||
|
# Summary
|
||||||
|
total_attempts = int(grouped['total'].sum())
|
||||||
|
total_success = int(grouped['successes'].sum())
|
||||||
|
total_fail = int(grouped['failures'].sum())
|
||||||
|
overall_error = (total_fail / total_attempts) if total_attempts>0 else 0.0
|
||||||
|
summary = f"<b>Total attempts:</b> {total_attempts}\n<b>Successes:</b> {total_success}\n<b>Failures:</b> {total_fail}\n<b>Overall error rate:</b> {overall_error:.1%}"
|
||||||
|
|
||||||
|
return str(plot_path), summary
|
||||||
|
except Exception as e:
|
||||||
|
logger.exception(f"Failed to generate error rate plot: {e}")
|
||||||
|
return None, ""
|
||||||
self._send_message(f"❓ Unknown command: <code>{cmd}</code>\n\nUse /help to see available commands.")
|
self._send_message(f"❓ Unknown command: <code>{cmd}</code>\n\nUse /help to see available commands.")
|
||||||
|
|
||||||
def _handle_plot_command(self):
|
def _handle_plot_command(self):
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue