Skip to main content

Overview

The TwitterBot component handles all Twitter interactions including posting audit results, repository updates, daily summaries, and processing DM commands.

Initialization

from twitter_bot import TwitterBot, TwitterCredentials

twitter_creds = TwitterCredentials(
    api_key=config.twitter_api_key,
    api_secret=config.twitter_api_secret,
    access_token=config.twitter_access_token,
    access_secret=config.twitter_access_secret,
    bearer_token=config.twitter_bearer_token
)

twitter_bot = TwitterBot(twitter_creds)
```python

### TwitterCredentials

<ParamField path="api_key" type="str" required>
  Twitter API key (Consumer Key)
</ParamField>

<ParamField path="api_secret" type="str" required>
  Twitter API secret (Consumer Secret)
</ParamField>

<ParamField path="access_token" type="str" required>
  Twitter access token
</ParamField>

<ParamField path="access_secret" type="str" required>
  Twitter access token secret
</ParamField>

<ParamField path="bearer_token" type="str" required>
  Twitter bearer token for v2 API
</ParamField>

## Key Methods

### post_audit()

Posts an audit result tweet.

```python
tweet = twitter_bot.post_audit(contract, audit, findings_summary)
```python

**Parameters:**
- `contract` (Contract): Contract object
- `audit` (Audit): Audit result object
- `findings_summary` (str, optional): Optional summary text

**Returns:** `Tweet | None` - Tweet object if successful

### post_detailed_findings()

Posts detailed findings as a thread.

```python
tweet_ids = twitter_bot.post_detailed_findings(contract, audit, findings)
```python

**Parameters:**
- `contract` (Contract): Contract object
- `audit` (Audit): Audit result object
- `findings` (list): List of Finding objects

**Returns:** `list[str]` - List of posted tweet IDs

### post_repo_update()

Posts a repository update notification.

```python
tweet = twitter_bot.post_repo_update(
    repo_name="owner/repo",
    commit_message="Fix security issue",
    commit_url="https://github.com/owner/repo/commit/abc123"
)
```python

**Returns:** `Tweet | None` - Tweet object if successful

### post_daily_summary()

Posts daily audit statistics summary.

```python
tweet = twitter_bot.post_daily_summary(stats)
```python

**Parameters:**
- `stats` (dict): Statistics dictionary with keys:
  - `contracts_scanned`: Number of contracts scanned
  - `total_audits`: Total audits completed
  - `total_critical`: Critical issues found
  - `total_high`: High severity issues
  - `total_medium`: Medium severity issues
  - `total_low`: Low severity issues

**Returns:** `Tweet | None` - Tweet object if successful

### post_thread()

Posts a thread of tweets.

```python
tweet_ids = twitter_bot.post_thread(messages)
```python

**Parameters:**
- `messages` (list[str]): List of tweet messages

**Returns:** `list[str]` - List of posted tweet IDs

### check_dm_commands()

Checks for DM commands like "audit [address]".

```python
commands = twitter_bot.check_dm_commands()
```python

**Returns:** `list[dict]` - List of command dictionaries:
```python
{
    "type": "audit",
    "address": "0x...",
    "sender_id": "...",
    "dm_id": "..."
}
```python

### send_dm()

Sends a direct message to a user.

```python
success = twitter_bot.send_dm(user_id, message)
```python

**Returns:** `bool` - True if successful

## Tweet Formats

### Audit Tweet

```python
🔍 New audit: ContractName

📊 Findings: 5 issue(s) found
⚠️ Critical: 1 | High: 2 | Medium: 2

🔗 Contract: https://basescan.org/address/0x...
📁 Repo: owner/repository

#BaseChain #SmartContractSecurity
```python

### Detailed Findings Thread

```python
🧵 Detailed Audit: ContractName

📊 3 significant issue(s) found
⬇️ Thread with details below

#BaseChain #SmartContractSecurity

---

🚨 Finding 1: Reentrancy Vulnerability

Severity: Critical
External call before state update allows reentrancy attack...

💡 Fix: Update state before external calls...
```python

### Repository Update

```python
🔄 Update detected: owner/repo

📝 Fix security vulnerability in transfer function

🔗 https://github.com/owner/repo/commit/abc123

#BaseChain #Development
```python

### Daily Summary

```python
📊 Daily Audit Summary

🔍 Contracts scanned: 15
✅ Audits completed: 8
⚠️ Issues found: 23
   - Critical: 2
   - High: 5
   - Medium: 10

#BaseChain #SmartContractSecurity
```python

## Usage Examples

### Posting Audit Results

From `bot.py:325-341`:

```python
def _post_audit_tweet(self, contract: Contract, audit: Audit, report: FullAuditReport):
    """Post audit results to Twitter."""
    try:
        tweet = self.twitter_bot.post_audit(contract, audit)

        if tweet:
            self.db.add_tweet(tweet)
            logger.info(f"Posted audit tweet: {tweet.tweet_id}")

            # Post detailed thread for significant findings
            if report.critical_count > 0 or report.high_count >= 2:
                self.twitter_bot.post_detailed_findings(
                    contract, audit, report.findings
                )

    except Exception as e:
        logger.error(f"Error posting tweet: {e}")
```python

### Processing DM Commands

From `bot.py:343-400`:

```python
def _check_dm_commands(self):
    """Check for and process DM commands."""
    try:
        commands = self.twitter_bot.check_dm_commands()

        for cmd in commands:
            if cmd["type"] == "audit":
                address = cmd["address"]
                sender_id = cmd["sender_id"]

                logger.info(f"Received audit command for {address}")

                # Process the audit request
                contract = self.db.get_contract_by_address(address)

                if not contract:
                    # Check if verified and audit
                    self.twitter_bot.send_dm(
                        sender_id,
                        f"Checking contract {address}..."
                    )
                    # ... perform audit ...

    except Exception as e:
        logger.error(f"Error checking DM commands: {e}")
```python

### Posting Daily Summary

From `bot.py:402-423`:

```python
def _check_daily_summary(self):
    """Check if it's time to post daily summary."""
    now = datetime.utcnow()

    # Post at midnight UTC
    if self.last_daily_summary is None or (now - self.last_daily_summary) > timedelta(hours=24):
        # Check if it's near midnight (within 15 minutes)
        if now.hour == 0 and now.minute < 15:
            try:
                stats = self.db.get_daily_stats()
                stats["contracts_scanned"] = self.db.get_contracts_scanned_today()

                if stats["total_audits"] > 0:
                    tweet = self.twitter_bot.post_daily_summary(stats)

                    if tweet:
                        self.db.add_tweet(tweet)
                        self.last_daily_summary = now
                        logger.info("Posted daily summary")

            except Exception as e:
                logger.error(f"Error posting daily summary: {e}")
```python

## Tweet Object

```python
@dataclass
class Tweet:
    id: Optional[int]          # Database ID
    audit_id: Optional[int]    # Associated audit ID
    tweet_id: str              # Twitter tweet ID
    posted_at: datetime        # Post timestamp
    tweet_type: str            # 'audit', 'update', 'summary'
    content: str               # Tweet content
```python

## Features

<CardGroup cols={2}>
  <Card title="Automatic Truncation" icon="scissors">
    Automatically truncates tweets to fit 280 character limit
  </Card>
  <Card title="Thread Support" icon="link">
    Posts detailed findings as threaded replies
  </Card>
  <Card title="Rate Limit Handling" icon="clock">
    Automatic wait on rate limits via tweepy
  </Card>
  <Card title="DM Commands" icon="message">
    Process direct message commands for manual audits
  </Card>
</CardGroup>

## Configuration

<ResponseField name="MAX_TWEET_LENGTH" type="int" default="280">
  Maximum tweet length (Twitter's character limit)
</ResponseField>

## Authentication

The bot uses both OAuth 1.0a and OAuth 2.0:
- **OAuth 1.0a**: For posting tweets (v1.1 API)
- **OAuth 2.0**: For v2 endpoints (create_tweet)

Both are required for full functionality.

<Warning>
  The bot requires Twitter API Elevated access for DM functionality. Standard access only supports public tweets.
</Warning>

## Error Handling

All Twitter operations gracefully handle errors:
- Failed authentication raises an exception on initialization
- Failed tweets/DMs return None and log errors
- Rate limits are automatically handled by tweepy
- Network errors are caught and logged

<Note>
  The bot automatically respects Twitter's rate limits using tweepy's `wait_on_rate_limit=True` parameter.
</Note>

Build docs developers (and LLMs) love