> ## Documentation Index
> Fetch the complete documentation index at: https://docs.squarecloud.app/llms.txt
> Use this file to discover all available pages before exploring further.

# Come ospitare bot per X (Twitter)

> Impara a creare e ospitare un bot per X (Twitter) su Square Cloud. Tutorial completo con configurazione, deploy ed esempi pratici in Node.js e Python.

export const RecommendedPlan = ({lang, plan, tier, cpu, appType}) => {
  const url = `https://squarecloud.app/${lang}/pay?plan=${plan.toLowerCase()}&tier=${tier}`;
  if (lang == 'en') {
    return <Note>
        <b>Wondering how much RAM and CPU your plan needs to host {appType}?</b><br />
        Don't worry, we're here to help.
        Our <a href={url}>{plan}</a> plan offers <b>{tier}GB</b> of RAM and <b>{cpu}vCPU</b>, which should be sufficient for most {appType}. 
        However, if you are working on a larger project and seeking extra stability, we recommend considering our <b>Pro</b> plan. With additional resources, you can maintain stability even during demand spikes. 
        To purchase, simply click <a href="https://squarecloud.app/en/pay?plan=pro">here</a>.
      </Note>;
  } else {
    return <Note>
          <b>Está se perguntando quanta RAM e CPU seu plano precisa para hospedar {appType}?</b><br />
          Não se preocupe, estamos aqui para ajudar.
          Nosso plano <a href={url}>{plan}</a> oferece <b>{tier}GB</b> de RAM e <b>{cpu}vCPU</b>, o que deve ser suficiente para a maioria dos {appType}.
          No entanto, se você estiver trabalhando em um projeto maior e precisar de mais estabilidade, recomendamos considerar nosso plano <b>Pro</b>.
          Com recursos adicionais, você pode manter a estabilidade mesmo durante picos de demanda.
          Para comprar, basta clicar <a href={`https://squarecloud.app/${lang}/pay?plan=pro`}>aqui</a>.
        </Note>;
  }
};

export const appType_0 = "a X (Twitter) bot"

## Introduzione

Per sviluppare e ospitare {appType_0} su Square Cloud, è essenziale seguire una sequenza strutturata di configurazioni e prerequisiti. Questa guida tecnica coprirà l'intero processo, dalla configurazione iniziale al deploy in produzione.

### Prerequisiti

* **Account Square Cloud**: Registrati tramite la [pagina di registrazione](https://squarecloud.app/it/signup) usando la tua email.
* **Piano a pagamento attivo**: Garantisce risorse dedicate e prestazioni ottimizzate per la tua applicazione. Consulta i nostri [piani disponibili](https://squarecloud.app/it/pricing) e scegli quello più adatto alle tue esigenze.

<RecommendedPlan appType="X (Twitter)" plan="Hobby" tier="2" cpu="2" lang="en" />

### Creazione del progetto

È richiesto un account X (Twitter) attivo per l'autenticazione e il funzionamento del bot. Se non hai un account, registrati sul [sito ufficiale di X](https://x.com/).\
È inoltre necessario un account X Developer per accedere alle API. Richiedi l'accesso tramite il [X Developer Portal](https://developer.x.com/en).

### Applicazione bot su X

<Steps>
  <Step title="Accesso al Developer Portal">
    1. Vai al [X Developer Portal](https://developer.x.com/en/portal/dashboard).
    2. Accedi con il tuo account X (Twitter).
    3. Se è la prima volta, completa la procedura di richiesta di accesso da sviluppatore.
  </Step>

  <Step title="Creazione del progetto">
    1. Nella dashboard, clicca su "Create Project".
    2. Scegli un nome per il tuo progetto (ad es. "Square Cloud Bot").
    3. Seleziona il caso d'uso più appropriato (ad es. "Making a bot").
    4. Fornisci una descrizione dettagliata del tuo bot.
    5. Conferma la creazione del progetto.
  </Step>

  <Step title="Configurazione dell'applicazione">
    1. All'interno del progetto creato, clicca su "Create App".
    2. Definisci un nome univoco per la tua applicazione.
    3. Conferma la creazione dell'applicazione.
    4. Annota l'**App ID** generato per riferimento futuro.
  </Step>

  <Step title="Generazione delle chiavi API">
    1. Vai alla sezione "Keys and tokens" della tua applicazione.
    2. Nella sezione "Consumer Keys", clicca su "Regenerate" per generare:
       * **API Key** (Consumer Key)
       * **API Secret Key** (Consumer Secret)
    3. **Importante**: copia e salva queste chiavi immediatamente, poiché non potrai più visualizzarle.
  </Step>

  <Step title="Configurazione dei permessi">
    1. Vai alla sezione "App permissions".
    2. Clicca su "Edit" per modificare i permessi.
    3. Seleziona "Read and write" per consentire al tuo bot di pubblicare tweet.
    4. Se necessario, seleziona "Read and write and Direct message" per la funzionalità di messaggi diretti.
    5. Salva le modifiche.
  </Step>

  <Step title="Generazione degli access token">
    1. Torna alla sezione "Keys and tokens".
    2. Nella sezione "Access Token and Secret", clicca su "Generate".
    3. Conferma la generazione del token.
    4. Copia e salva:
       * **Access Token**
       * **Access Token Secret**
    5. **Attenzione**: questi token non possono essere visualizzati di nuovo dopo aver chiuso la pagina.
  </Step>

  <Step title="Verifica delle credenziali">
    1. Conferma di avere tutte e 4 le credenziali richieste:
       * API Key (Consumer Key)
       * API Secret Key (Consumer Secret)
       * Access Token
       * Access Token Secret
    2. Conserva queste credenziali in un luogo sicuro
    3. **Importante**: non condividere né esporre mai pubblicamente queste credenziali
  </Step>
</Steps>

## Sviluppo del progetto

1. **Verifica di Node.js**: verifica che Node.js sia installato sul tuo sistema. In caso contrario, scaricalo dal [sito ufficiale di Node.js](https://nodejs.org/).

2. **Inizializzazione del progetto**: crea un nuovo progetto Node.js eseguendo:

```bash Terminal theme={null}
npm init -y
```

3. **Installazione delle dipendenze**: installa le librerie richieste per il bot:

```bash Terminal theme={null}
npm install twitter-api-v2
```

4. **Configurazione delle variabili d'ambiente**: crea un file `.env` per memorizzare le tue credenziali in modo sicuro:

```env .env theme={null}
API_KEY=your_api_key_here
API_SECRET_KEY=your_api_secret_key_here
ACCESS_TOKEN=your_access_token_here
ACCESS_TOKEN_SECRET=your_access_token_secret_here
```

5. **Creazione del file principale**: sviluppa il file `index.js` con la struttura base del bot:

```javascript index.js theme={null}
// Import necessary modules
const { TwitterApi } = require('twitter-api-v2');

// Configure Twitter client with authentication
const client = new TwitterApi({
  appKey: process.env.API_KEY,
  appSecret: process.env.API_SECRET_KEY,
  accessToken: process.env.ACCESS_TOKEN,
  accessSecret: process.env.ACCESS_TOKEN_SECRET,
});

// Client with read and write permissions
const rwClient = client.readWrite;

// Stores the authenticated bot user id (set in verifyBot)
let botUserId = null;

// Function to check if the bot is working
async function verifyBot() {
  try {
    // Get authenticated user information (X API v2)
    const me = await rwClient.v2.me();
    botUserId = me.data.id;
    console.log(`Bot successfully initialized! User: @${me.data.username}`);
    return true;
  } catch (error) {
    console.error('Error verifying bot:', error);
    return false;
  }
}

// Function to post a tweet
async function postTweet(text) {
  try {
    const tweet = await rwClient.v2.tweet(text);
    console.log(`Tweet posted successfully! ID: ${tweet.data.id}`);
    return tweet;
  } catch (error) {
    console.error('Error posting tweet:', error);
    throw error;
  }
}

// Function to respond to mentions
async function respondToMentions() {
  if (!botUserId) return;
  try {
    // Fetch recent mentions (X API v2)
    const mentions = await rwClient.v2.userMentionTimeline(botUserId, {
      max_results: 10,
    });

    for (const tweet of mentions.data?.data ?? []) {
      // Check if it's a new mention (implement control logic)
      if (tweet.text.includes('!ping')) {
        // Reply to the mention
        await rwClient.v2.reply(
          'Pong! 🤖 X Bot working correctly!',
          tweet.id
        );
        console.log(`Replied to mention (tweet ID: ${tweet.id})`);
      }
    }
  } catch (error) {
    console.error('Error processing mentions:', error);
  }
}

// Function to search and interact with specific tweets
async function searchAndInteract(query) {
  if (!botUserId) return;
  try {
    // Search recent tweets (X API v2)
    const tweets = await rwClient.v2.search(query, {
      max_results: 10,
    });

    for (const tweet of tweets.data?.data ?? []) {
      // Like the tweet
      await rwClient.v2.like(botUserId, tweet.id);
      console.log(`Liked tweet ID: ${tweet.id}`);

      // Wait a bit between actions to avoid rate limiting
      await new Promise(resolve => setTimeout(resolve, 2000));
    }
  } catch (error) {
    console.error('Error searching and interacting:', error);
  }
}

// Main bot function
async function runBot() {
  console.log('Starting X bot...');
  
  // Check if the bot is configured correctly
  const botOk = await verifyBot();
  if (!botOk) {
    console.error('Bot initialization failed');
    return;
  }
  
  // Example: Post an initialization tweet
  try {
    await postTweet('🤖 X Bot initialized and running on Square Cloud!');
  } catch (error) {
    console.log('Initialization tweet failed, but bot continues running');
  }
  
  // Main bot loop
  setInterval(async () => {
    try {
      // Check and respond to mentions every 5 minutes
      await respondToMentions();
      
      // Example: Search and interact with tweets about a specific topic
      // await searchAndInteract('#SquareCloud');
      
    } catch (error) {
      console.error('Error in main loop:', error);
    }
  }, 5 * 60 * 1000); // 5 minutes
  
  console.log('Bot running. Press Ctrl+C to stop.');
}

// Signal handling for graceful shutdown
process.on('SIGINT', () => {
  console.log('\nShutting down X bot...');
  process.exit(0);
});

process.on('SIGTERM', () => {
  console.log('\nShutting down X bot...');
  process.exit(0);
});

// Initialize the bot
runBot();
```

## Deploy

Dopo aver preparato i file del tuo progetto, puoi ora caricarli su Square Cloud e ospitare il tuo progetto.
Per farlo, crea un file ZIP contenente tutti i file del progetto.

<AccordionGroup>
  <Accordion title="Variabili d'ambiente" icon="key">
    <Note>**Sicurezza**: non includere mai le tue credenziali API direttamente nel codice. Usa sempre le variabili d'ambiente su Square Cloud.</Note>

    Su Square Cloud, configura le seguenti variabili d'ambiente tramite il pannello di controllo:

    * `API_KEY`: la tua chiave API di X
    * `API_SECRET_KEY`: la tua chiave segreta API di X
    * `ACCESS_TOKEN`: il tuo access token
    * `ACCESS_TOKEN_SECRET`: il tuo access token secret
  </Accordion>
</AccordionGroup>

### Tramite dashboard

<Steps>
  <Step title="Accedi alla pagina di upload">
    Accedi alla [pagina di upload](https://squarecloud.app/it/dashboard/new) e carica il file zip del tuo progetto.
  </Step>

  <Step title="Configura il tuo ambiente">
    Dopo aver caricato il tuo zip, dovrai configurare il nome, il file principale o il runtime environment e altre impostazioni per il tuo progetto.\
    Se stai caricando un progetto web, assicurati di selezionare "Web Publication" e di impostare un sottodominio per il tuo progetto.
  </Step>

  <Step title="Esegui il deploy del tuo progetto">
    Infine, clicca sul pulsante "Deploy" per ospitare il tuo progetto su Square Cloud.\
    Dopo il deploy, puoi monitorare lo stato e i log del tuo progetto dalla dashboard.

    <Frame>
      <img src="https://cdn.squarecloud.app/docs/articles/dashboard/uploading.gif" alt="Caricamento dell'applicazione su Square Cloud" style={{ borderRadius: "0.2rem" }} />
    </Frame>
  </Step>
</Steps>

### Tramite CLI

Per utilizzare questo metodo, devi creare un file di configurazione chiamato `squarecloud.app` nella directory principale del tuo progetto. Questo file conterrà la configurazione necessaria per il tuo progetto.

<Card title="Scopri di più su: come creare il file di configurazione per Square Cloud." icon="link" href="/it/getting-started/config-file">
  Il file squarecloud.app è un file di configurazione che verrà utilizzato per configurare la tua applicazione; verrà usato per definire il tuo ambiente.
</Card>

<Steps>
  <Step title="Installa la CLI">
    Per prima cosa, devi avere la CLI installata nel tuo ambiente. Se non la hai ancora, esegui il seguente comando nel tuo terminale:

    ```
    npm install -g @squarecloud/cli
    ```

    Se la hai già, ti consigliamo di aggiornarla. Per farlo, esegui il seguente comando nel tuo terminale:

    <Tabs>
      <Tab title="Windows">
        ```bash theme={null}
        squarecloud update
        ```
      </Tab>

      <Tab title="Linux, macOS e WSL">
        ```bash theme={null}
        curl -fsSL https://cli.squarecloud.app/install | bash
        ```
      </Tab>
    </Tabs>
  </Step>

  <Step title="Autenticati">
    Ora, per autenticarti e utilizzare gli altri comandi della CLI, troverai la tua chiave di autorizzazione [qui](https://squarecloud.app/it/account/security) cliccando su "Request API Key". Dopo aver ottenuto la tua chiave di autorizzazione, esegui il seguente comando:

    ```bash theme={null}
    squarecloud auth login
    ```
  </Step>

  <Step title="Carica il tuo progetto">
    Infine, per eseguire il deploy della tua applicazione su Square Cloud tramite la CLI, devi eseguire il seguente comando:

    ```bash theme={null}
    squarecloud upload 
    ```

    Oppure, se hai creato lo zip manualmente, puoi usare:

    ```bash theme={null}
    squarecloud upload --file <path/to/zip> 
    ```
  </Step>
</Steps>

## Risorse aggiuntive

Per approfondire le tue conoscenze sullo sviluppo di bot per X usando twitter-api-v2, consulta la [documentazione ufficiale della libreria twitter-api-v2](https://github.com/PLhery/node-twitter-api-v2). La documentazione fornisce guide dettagliate, tutorial avanzati e riferimenti API completi per massimizzare la tua implementazione.

Vedi anche:

* [Documentazione ufficiale dell'API di X](https://docs.x.com/overview)
* [Politiche di utilizzo dell'API di X](https://developer.x.com/en/developer-terms/policy)
* [Guida alle best practice per i bot](https://docs.x.com/x-api/getting-started/about-x-api)

### Monitoraggio degli hashtag

```javascript theme={null}
// Function to monitor specific hashtags
async function monitorHashtags(hashtags) {
  for (const hashtag of hashtags) {
    try {
      const tweets = await rwClient.v2.search(`#${hashtag}`, {
        max_results: 10,
      });

      // Process found tweets
      for (const tweet of tweets.data?.data ?? []) {
        console.log(`Tweet found with #${hashtag}: ${tweet.text}`);
        // Implement interaction logic
      }
    } catch (error) {
      console.error(`Error monitoring #${hashtag}:`, error);
    }
  }
}
```

### Post programmati

```javascript theme={null}
// Function to schedule posts
function schedulePost(text, delay) {
  setTimeout(async () => {
    try {
      await postTweet(text);
      console.log('Scheduled post published successfully!');
    } catch (error) {
      console.error('Error publishing scheduled post:', error);
    }
  }, delay);
}

// Example: Schedule a post for 1 hour
schedulePost('🤖 Scheduled post by the bot!', 60 * 60 * 1000);
```

### Rate Limiting

X (Twitter) ha rate limit rigidi. Implementa dei controlli per evitare di superare questi limiti:

```javascript theme={null}
// Rate limiting control
const rateLimiter = {
  lastRequest: 0,
  minInterval: 1000, // 1 second between requests
  
  async wait() {
    const now = Date.now();
    const timeSinceLastRequest = now - this.lastRequest;
    
    if (timeSinceLastRequest < this.minInterval) {
      const waitTime = this.minInterval - timeSinceLastRequest;
      await new Promise(resolve => setTimeout(resolve, waitTime));
    }
    
    this.lastRequest = Date.now();
  }
};
```

### Gestione degli errori

```javascript theme={null}
// Helper function to retry an operation on failure
async function retryOperation(operation, maxRetries = 3) {
  for (let i = 0; i < maxRetries; i++) {
    try {
      return await operation();
    } catch (error) {
      console.error(`Attempt ${i + 1} failed:`, error.message);
      
      if (i === maxRetries - 1) {
        throw error;
      }
      
      // Wait before retrying
      await new Promise(resolve => setTimeout(resolve, 2000 * (i + 1)));
    }
  }
}
```

## Contattaci

Se continui a riscontrare **difficoltà tecniche**, il nostro **team di supporto specializzato** è disponibile ad assisterti. [**Contattaci**](https://squarecloud.app/it/support) e saremo felici di aiutarti a risolvere qualsiasi problema.
