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>