Рубрики
Без рубрики

Как строить и развернуть многофункциональный бот Twitter

Обновление 20190507: Этот учебник, вероятно, больше не актуален, как Twitter обесценивают части API, это будет меньше и менее актуально. Я не буду обновлять это идти вперед. ? Обновление 20171105: для простоты навигации я собрал всю эту историю в GitBook, это a

Автор оригинала: Scott Spence.

Я снова был занят настроек Twitter!

Если вы посмотрите на мой Профиль GitHub . , вы увидите, что у меня есть несколько репо, относящихся к ботам в Твиттере.

Мой последний проект начал с принятия решения о пересматривать одну из моих тестирующих REPOS в качестве документации о том, как использовать NPM Twit упаковка. Но как я добавил новые примеры, это быстро превратилось в другой бот Twitter.

Этот бот мощена вместе с трех примеров, которые мы перейдем сюда. Я также подробноe, как я использовал Zeit’s сейчас Платформа для развертывания бота на сервер.

Особая благодарность Перейти к Тим Для того, чтобы помочь мне с сейчас Развертывание. И к Ханна Дэвис для EGGHEAD.IO Материал курса. Он имеет несколько довольно аккуратных примеров, которые я связал в соответствующих разделах.

Начать

Эта статья предназначена для меня, и кто-то еще, что заинтересован в Twitter Botts в JavaScript, используя Node.js Отказ Обратите внимание, что все примеры здесь используют NPM Пакет Twit Отказ

Бот Пример 1.: Tweeting Media с изображением NASA дня

Ganymede: самая большая луна pic.twitter.com/6ir3tp1lrm.

Bot Prime 2: Использование RITA, чтобы сделать Markov Bot, который будет использовать ваш архив Twitter, чтобы опубликовать статусы, основанные на вашей истории Tweet.

У меня был лучший пирог Турции и пюре, сделанные моей сестрой в законе # Nomnomnom, штаны все еще не появились?

Пример BOT 3: Размещение ссылок (или другие данные) от электронной таблицы.

https://t.co/9m9k7gmtoa Ссылка из электронной таблицы Google

Мы пройдем настроить простой бот, который мы будем использовать для запуска каждого из этих примеров.

Я собираюсь предположить, что у вас есть Node.js установлен вместе с NPM И что вам удобно с терминалом.

Если вы не знакомы с Node.js Или не настроить свою среду, чтобы использовать его, посмотрите на Readme.md на моем Twitter Bot Bootstrap репо. Он дает подробную информацию о получении настроек приложения Twitter и среды разработки с C9.

Отличный ресурс – Аман Миттал Удивительные боты Twitter Репо, в котором есть ресурсы и примеры бота.

Многие из этой информации уже там, но я надеюсь, что это вся информация, которую кому-то нужно будет начать со своим собственным ботом Twitter. Я делаю это для моего собственного обучения и, надеюсь, другие люди получат что-то из этого.

Установить бот

Прежде чем прикоснуться к терминалу или написанию любого кода, нам нужно создать Приложение Twitter Чтобы получить наши ключи API (нам понадобится все):

Consumer Key (API Key)
Consumer Secret (API Secret)
Access Token
Access Token Secret

Держите ключи где-то в безопасности, поэтому вы можете использовать их снова, когда они нуждаются в них. Мы собираемся использовать их в .env Файл, который мы создадим.

Мы используем доценв Так что если в какой-то момент в будущем мы хотим добавить наш бот в Github, ключевые ключи API Twitter не добавляются в GitHub для всех, чтобы увидеть.

Начиная с нуля, создайте новую папку через терминал и инициализируйте Package.json через NPM или пряжа . Нам понадобится Twit и Доценв Для всех этих примеров.

Я буду использовать пряжа Для всех этих примеров вы можете использовать NPM если хочешь.

Команды терминалов:

mkdir tweebot-play
cd tweebot-play
yarn init -y
yarn add twit dotenv
touch .env .gitignore index.js

Если вы посмотрите на Package.json Это было создано, это должно выглядеть что-то вроде этого:

{
  "name": "tweebot-play",
  "version": "1.0.0",
  "main": "index.js",
  "author": "Scott Spence  (https://spences10.github.io/)",
  "license": "MIT",
  "dependencies": {
    "dotenv": "^4.0.0",
    "twit": "^2.2.5"
  }
}

Добавить NPM Сценарий к Package.json Чтобы загнать бот, когда мы тестируем и ищем вывод:

"scripts": {
    "start": "node index.js"
  },

Это должно выглядеть что-то подобное сейчас:

{
  "name": "tweebot-play",
  "version": "1.0.0",
  "main": "index.js",
  "scripts": {
    "start": "node index.js"
  },
  "author": "Scott Spence  (https://spences10.github.io/)",
  "license": "MIT",
  "dependencies": {
    "dotenv": "^4.0.0",
    "twit": "^2.2.5"
  }
}

Теперь мы можем добавить следующий указатель на бот в index.js , вот так:

require('./src/bot')

Так что, когда мы используем Пряжа начать Чтобы запустить бот, он называет index.js Файл, который запускает bot.js Файл из SRC Папка мы собираемся создать.

Теперь мы добавляем наши клавиши API к .env Файл, он должен выглядеть что-то подобное:

CONSUMER_KEY=AmMSbxxxxxxxxxxNh4BcdMhxg
CONSUMER_SECRET=eQUfMrHbtlxxxxxxxxxxkFNNj1H107xxxxxxxxxx6CZH0fjymV
ACCESS_TOKEN=7xxxxx492-uEcacdl7HJxxxxxxxxxxecKpi90bFhdsGG2N7iII
ACCESS_TOKEN_SECRET=77vGPTt20xxxxxxxxxxxZAU8wxxxxxxxxxx0PhOo43cGO

В .gitignore Файл, который нам нужно добавить .env.env. и node_modules.

# Dependency directories
node_modules

# env files
.env

Тогда init Git:

git init

Хорошо, теперь мы можем начать настроить бот, нам понадобится SRC Папка A bot.js Файл и A config.js файл.

Терминал:

mkdir src
cd src
touch config.js bot.js

Тогда мы можем настроить конфигурацию бота, откройте config.js Файл и добавьте следующее:

require('dotenv').config()

module.exports = {
  consumer_key: process.env.CONSUMER_KEY,
  consumer_secret: process.env.CONSUMER_SECRET,
  access_token: process.env.ACCESS_TOKEN,
  access_token_secret: process.env.ACCESS_TOKEN_SECRET,
}

Хорошо, с конфигурацией бота сделано, теперь мы можем настроить бот. Каждый из примеров подробностей здесь будет те же три строки кода:

const Twit = require('twit')
const config = require('./config')

const bot = new Twit(config)

Сделать тест с Пряжа начать От терминала мы должны получить это для вывода:

yarn start
yarn start v0.23.4
$ node index.js
Done in 0.64s.

Наш бот теперь настроен и готов к работе!

Статусы пост

Чтобы опубликовать статус, используйте .post («Статусы/обновление» ... . Этот пример заставляет BOT опубликовать «Hello World!» положение дел.

bot.post('statuses/update', {
  status: 'hello world!'
}, (err, data, response) => {
  if (err) {
    console.log(err)
  } else {
    console.log(`${data.text} tweeted!`)
  }
})

Работать с пользователями

Чтобы получить список последователей IDS, используйте .get («Подписчики/IDS» ... и включите учетную запись, которую вы хотите подписчики. В этом примере мы используем @Droidscott , но вы можете использовать любой аккаунт, который вам нравится. Затем мы можем ввести их в консоль.

bot.get('followers/ids', {
  screen_name: 'DroidScott',
  count: 5
}, (err, data, response) => {
  if (err) {
    console.log(err)
  } else {
    console.log(data)
  }
})

Вы можете использовать считать Параметр Укажите, сколько результатов вы получаете, до 100 одновременно.

Или получить подробный список, который вы можете использовать .get («подписчики/список» ...

Здесь мы распечатаем список user.screen_name до 200 за звонок.

bot.get('followers/list', {
  screen_name: 'DroidScott',
  count:200
}, (err, data, response) => {
  if (err) {
    console.log(err)
  } else {
    data.users.forEach(user => {
      console.log(user.screen_name)
    })
  }
})

Чтобы следить за последователем, мы можем использовать .post («Дружба/создание» ... Здесь бот следит за спиной пользователя Marcguberti.

Бот должен соответствовать только пользователям, которые следуют за ботом.

bot.post('friendships/create', {
  screen_name: 'MarcGuberti'
}, (err, data, response) => {
  if (err) {
    console.log(err)
  } else {
    console.log(data)
  }
})

Как и мы сделали с последователями, вы можете получить список учетных записей, что ваш бот следит за спиной.

bot.get('friends/ids', {
  screen_name: 'DroidScott'
}, (err, data, response) => {
  if (err) {
    console.log(err)
  } else {
    console.log(data)
  }
})

А также подробный список.

bot.get('friends/list', {
  screen_name: 'DroidScott'
}, (err, data, response) => {
  if (err) {
    console.log(err)
  } else {
    console.log(data)
  }
})

Вы можете получить статусы дружбы. Это полезно для следующих новых подписчиков и дает нам отношение определенного пользователя. Вы можете пройти через список ваших подписчиков и последующую передачу любых пользователей, которые не имеют Следуя связь.

Давайте посмотрим на отношение между нашим ботом и @Scottdevtweets.

bot.get('friendships/lookup', {
  screen_name: 'ScottDevTweets'
}, (err, data, response) => {
  if (err) {
    console.log(err)
  } else {
    console.log(data)
  }
})

Если пользователь следует за ботом, то отношения будут:

[ { name: 'Scott Spence ???♻',
    screen_name: 'ScottDevTweets',
    id: 4897735439,
    id_str: '4897735439',
    connections: [ 'followed_by' ] } ]

Если пользователь и бот следуют друг за другом, отношения будут:

[ { name: 'Scott Spence ???♻',
    screen_name: 'ScottDevTweets',
    id: 4897735439,
    id_str: '4897735439',
    connections: [ 'following', 'followed_by' ] } ]

А также Если нет никаких отношений, то:

[ { name: 'Scott Spence ???♻',
    screen_name: 'ScottDevTweets',
    id: 4897735439,
    id_str: '4897735439',
    connections: [ 'none' ] } ]

Прямое сообщение пользователя с bot.post ('direct_messages/new' ...

Бот должен только DM пользователь, который следует за учетной записью BOT

bot.post('direct_messages/new', {
  screen_name: 'ScottDevTweets',
  text: 'Hello from bot!'
}, (err, data, response) => {
  if (err) {
    console.log(err)
  } else {
    console.log(data)
  }
})

Взаимодействовать с твитами

Чтобы получить список твитов в линию времени бота, используйте .get (статусы/home_timeline '...

bot.get('statuses/home_timeline', {
  count: 1
}, (err, data, response) => {
  if (err) {
    console.log(err)
  } else {
    console.log(data)
  }
})

Чтобы быть более гранулированным, вы можете вытащить конкретную информацию на каждом Tweet.

bot.get('statuses/home_timeline', {
  count: 5
}, (err, data, response) => {
  if (err) {
    console.log(err)
  } else {
    data.forEach(t => {
      console.log(t.text)
      console.log(t.user.screen_name)
      console.log(t.id_str)
      console.log('\n')
    })
  }
})

Чтобы ретвит использовать .Post («Статусы/ретвист/: ID» ... и пройдите в Tweet ID, чтобы ретвит.

bot.post('statuses/retweet/:id', {
  id: '860828247944253440'
}, (err, data, response) => {
  if (err) {
    console.log(err)
  } else {
    console.log(`${data.text} retweet success!`)
  }
})

Для Unretweet просто используйте .POST («Статусы/Unretweet/: ID» ...

bot.post('statuses/unretweet/:id', {
  id: '860828247944253440'
}, (err, data, response) => {
  if (err) {
    console.log(err)
  } else {
    console.log(`${data.text} unretweet success!`)
  }
})

Чтобы любить Tweet, используйте .post («Избранное/Создание» ...

bot.post('favorites/create', {
  id: '860897020726435840'
}, (err, data, response) => {
  if (err) {
    console.log(err)
  } else {
    console.log(`${data.text} tweet liked!`)
  }
})

Чтобы в отличие от почтового использования .post («Избранное/Уничтожение» ...

bot.post('favorites/destroy', {
  id: '860897020726435840'
}, (err, data, response) => {
  if (err) {
    console.log(err)
  } else {
    console.log(`${data.text} tweet unliked!`)
  }
})

Чтобы ответить на Tweet, намного то же самое, что публикует твит, но вам нужно включить In_reply_to_status_id параметр. Кроме того, вам нужно будет поставить на экран имени человека, на который вы отвечаете.

bot.post('statuses/update', {
  status: '@ScottDevTweets I reply to you yes!',
  in_reply_to_status_id: '860900406381211649'
}, (err, data, response) => {
  if (err) {
    console.log(err)
  } else {
    console.log(`${data.text} tweeted!`)
  }
})

Наконец, если вы хотите удалить Tweet, используйте .post («Статусы/уничтожение/: ID» ... Передав твит, если вы хотите удалить.

bot.post('statuses/destroy/:id', {
  id: '860900437993676801'
}, (err, data, response) => {
  if (err) {
    console.log(err)
  } else {
    console.log(`${data.text} tweet deleted!`)
  }
})

Используйте поиск в Твиттере

Использовать поиск, использовать .get («Поиск/твиты», ... . Есть несколько параметров поиска для поиска.

Структура – Q: '' где q для запроса. Вы бы использовали Q: «Манго» Для поиска манго. Мы также можем ограничить результаты, возвращаемые с Счет: n Итак, давайте ограничим счет до 5 в примере.

bot.get('search/tweets', {
  q: 'mango',
  count: 5
}, (err, data, response) => {
  if (err) {
    console.log(err)
  } else {
    console.log(data.statuses)
  }
})

Как мы сделали с временем, мы вытащим конкретные предметы из data.statuses Вернулся, как это:

bot.get('search/tweets', {
  q: 'mango',
  count: 5
}, (err, data, response) => {
  if (err) {
    console.log(err)
  } else {
    data.statuses.forEach(s => {
      console.log(s.text)
      console.log(s.user.screen_name)
      console.log('\n')
    })
  }
})

Поиск API возвращает результаты для релевантности и не полноте. Если вы хотите найти точную фразу, вам нужно обернуть запрос в кавычки "Фиолетовые блины" Отказ Если вы хотите искать одно из двух слов, то используйте Или как «Вкладки или пробелы» Отказ И если вы хотите искать обоих, используйте И как «Вкладки и пробелы» Отказ

Если вы хотите найти Tweet без другого использования Word - как Дональд Трамп . Вы можете использовать его несколько раз, как Дональд -трамб -дак

Вы можете искать твиты с смайликами, как Q: «Грустно:(» попытайся!

Конечно, вы можете искать Hashtags Q: «#towie» Отказ Ищите твиты пользователю Q: 'to: @stephenfry' или от пользователя Q: 'От: @stephenfry'

Вы можете отфильтровать неприличные твиты с Фильтр: безопасный параметр. Вы также можете использовать его для фильтрации для СМИ Твиты, которые вернут твиты, содержащие видео. Вы можете указать для Изображения Чтобы просмотреть твиты с изображениями, и вы можете указать Ссылки для твитов со ссылками.

Если вы хотите твиты с определенного сайта, вы можете указать с URL Параметр, как URL: ASDA

bot.get('search/tweets', {
  q: 'from:@dan_abramov url:facebook filter:images since:2017-01-01',
  count: 5
}, (err, data, response) => {
  if (err) {
    console.log(err)
  } else {
    data.statuses.forEach(s => {
      console.log(s.text)
      console.log(s.user.screen_name)
      console.log('\n')
    })
  }
})

Последние несколько сейчас есть RESLACT_TYPE Параметр, который вернется недавний , популярный или смешанный полученные результаты.

Геокод Параметр принимает формат широты долготы, чем радиус в милях '51 .5033640, -0.1276250,1MI ' пример:

bot.get('search/tweets', {
  q: 'bacon',
  geocode: '51.5033640,-0.1276250,1mi',
  count: 5
}, (err, data, response) => {
  if (err) {
    console.log(err)
  } else {
    data.statuses.forEach(s => {
      console.log(s.text)
      console.log(s.user.screen_name)
      console.log('\n')
    })
  }
})

Используйте Twitter Stream API

Есть два способа использования потока API. Во-первых, есть .Stream («Статусы/образец») Отказ

const stream = bot.stream('statuses/sample');

stream.on('tweet', t => {
  console.log(`${t.text}\n`)
})

Это даст вам случайную выборку твитов.

Для более конкретной информации используйте .Stream («Статусы/фильтр») ... Затем пройдите несколько параметров и используйте Трек: Чтобы указать строку поиска.

var stream = bot.stream('statuses/filter', {
  track: 'bot'
})

stream.on('tweet', function (t) {
  console.log(t.text + '\n')
})

Вы также можете использовать несколько слов в трек Параметр, это получит ваши результаты с помощью твиттер или бот в них.

const stream = bot.stream('statuses/filter', {
  track: 'twitter, bot'
});

stream.on('tweet', t => {
  console.log(`${t.text}\n`)
})

Если вы хотите обоих слов, то удалите запятую , – Вы можете думать о пробегах как И и запятые как Или Отказ

Вы также можете использовать следить: Параметр, который позволяет вводить идентификаторы конкретных пользователей.

const stream = bot.stream('statuses/filter', {
  follow: '4897735439'
});

stream.on('tweet', t => {
  console.log(`${t.text}\n`)
})

Tweet Media Files.

Это EGGHEAD.IO Видео – отличный ресурс для этого раздела благодаря Ханна Дэвис Для удивительного контента!

Это будет просьбой получить Образ НАСА дня и твитнуть это.

Нам понадобится ссылки на Запрос и ФС Для работы с файловой системой.

const Twit = require('twit')
const request = require('request')
const fs = require('fs')
const config = require('./config')

const bot = new Twit(config)

Первый шаг – получить фото с ASA ASA. Нам нужно будет создать объект параметра внутри нашего GetPhoto Функция, которая будет передана в узел HTTP Client Запрос для изображения.

function getPhoto() {
  const parameters = {
    url: 'https://api.nasa.gov/planetary/apod',
    qs: {
      api_key: process.env.NASA_KEY
    },
    encoding: 'binary'
  };
}

Параметры Укажите api_key. Так что для этого вы можете Подать заявку на ключ API Или вы можете использовать Demo_key Отказ Этот ключ API может быть использован для первоначально исследующих API перед регистрацией, но он имеет гораздо более низкие ограничения ставок, поэтому вам рекомендуется подписывать свой собственный ключ API.

В примере вы можете увидеть, что я настроил свой ключ от остальных моих .env Переменные.

CONSUMER_KEY=AmMSbxxxxxxxxxxNh4BcdMhxg
CONSUMER_SECRET=eQUfMrHbtlxxxxxxxxxxkFNNj1H107xxxxxxxxxx6CZH0fjymV
ACCESS_TOKEN=7xxxxx492-uEcacdl7HJxxxxxxxxxxecKpi90bFhdsGG2N7iII
ACCESS_TOKEN_SECRET=77vGPTt20xxxxxxxxxxxZAU8wxxxxxxxxxx0PhOo43cGO

NASA_KEY=DEMO_KEY

Теперь использовать Запрос Чтобы получить изображение:

function getPhoto() {
  const parameters = {
    url: 'https://api.nasa.gov/planetary/apod',
    qs: {
      api_key: process.env.NASA_KEY
    },
    encoding: 'binary'
  };
  request.get(parameters, (err, respone, body) => {
    body = JSON.parse(body)
    saveFile(body, 'nasa.jpg')
  })
}

В Запрос , мы проходим в наших параметрах и разбираем тело как JSON, чтобы мы могли сохранить его с SaveFile функция.

function saveFile(body, fileName) {
  const file = fs.createWriteStream(fileName);
  request(body).pipe(file).on('close', err => {
    if (err) {
      console.log(err)
    } else {
      console.log('Media saved!')
      console.log(body)
    }
  })
}

Запрос (Body) .pipe (файл) .on («Закрыть» ... – это то, что сохраняет файл из файла Переменная. У него есть имя nasa.jpg передан ему из GetPhoto функция.

Призыв GetPhoto () Теперь должен сохранить образ NASA дня до корня вашего проекта.

Теперь мы можем поделиться этим в Twitter. Для этого есть две части, первый – сохранить файл.

function saveFile(body, fileName) {
  const file = fs.createWriteStream(fileName);
  request(body).pipe(file).on('close', err => {
    if (err) {
      console.log(err)
    } else {
      console.log('Media saved!')
      const descriptionText = body.title;
      uploadMedia(descriptionText, fileName)
    }
  })
}

Тогда UploadMedia Чтобы загрузить носитель в Twitter, прежде чем мы сможем опубликовать его. Это заставило меня в тупик, так как у меня есть файлы в SRC папка. Если у вас есть файлы бота вложены в папки, вам нужно будет сделать то же самое, если вы боретесь с Файл не существует ошибки.

Добавить требуется к путь Тогда используйте Присоединяйтесь к с соответствующим относительным файлом.

const path = require('path')
//...
const filePath = path.join(__dirname, '../' + fileName)

Вот полная функция:

function uploadMedia(descriptionText, fileName) {
  console.log(`uploadMedia: file PATH ${fileName}`)
  bot.postMediaChunked({
    file_path: fileName
  }, (err, data, respone) => {
    if (err) {
      console.log(err)
    } else {
      console.log(data)
      const params = {
        status: descriptionText,
        media_ids: data.media_id_string
      }
      postStatus(params)
    }
  })
}

Тогда с Пармы Мы создали в UploadMedia. Мы можем опубликовать простым .post («Статусы/обновление» ...

function postStatus(params) {
  bot.post('statuses/update', params, (err, data, respone) => {
    if (err) {
      console.log(err)
    } else {
      console.log('Status posted!')
    }
  })
}

Позвоните в GetPhoto () Функция для публикации в Twitter … Супер прямо вперед, верно? Я знаю, что это не так. Вот полный модуль:

const Twit = require('twit')
const request = require('request')
const fs = require('fs')
const config = require('./config')
const path = require('path')

const bot = new Twit(config)

function getPhoto() {
  const parameters = {
    url: 'https://api.nasa.gov/planetary/apod',
    qs: {
      api_key: process.env.NASA_KEY
    },
    encoding: 'binary'
  }
  request.get(parameters, (err, respone, body) => {
    body = JSON.parse(body)
    saveFile(body, 'nasa.jpg')
  })
}

function saveFile(body, fileName) {
  const file = fs.createWriteStream(fileName)
  request(body).pipe(file).on('close', err => {
    if (err) {
      console.log(err)
    } else {
      console.log('Media saved!')
      const descriptionText = body.title
      uploadMedia(descriptionText, fileName)
    }
  })
}

function uploadMedia(descriptionText, fileName) {
  const filePath = path.join(__dirname, `../${fileName}`)
  console.log(`file PATH ${filePath}`)
  bot.postMediaChunked({
    file_path: filePath
  }, (err, data, respone) => {
    if (err) {
      console.log(err)
    } else {
      console.log(data)
      const params = {
        status: descriptionText,
        media_ids: data.media_id_string
      }
      postStatus(params)
    }
  })
}

function postStatus(params) {
  bot.post('statuses/update', params, (err, data, respone) => {
    if (err) {
      console.log(err)
    } else {
      console.log('Status posted!')
    }
  })
}

getPhoto()

Сделать Марков Бот

Это довольно аккуратно, снова из EGGHEAD.IO Серия использует Рита Инструментарий натурального языка. Это также использует CSV-Parse Как мы будем читать наш архив Twitter, чтобы сделать бот звучать, как будто это ввигация на нас.

Прежде всего, чтобы настроить Архив твиттера , вам нужно запросить ваши данные с страницы настроек Twitter. Вы будете отправлены по электронной почте ссылку, чтобы загрузить свой архив, затем, когда вы загрузили архив, извлечь Tweets.csv Файл, мы затем поместим это в свою собственную папку, так что из корня вашего проекта:

cd src
mkdir twitter-archive

Мы будем переместить наши Tweets.csv Там добраться до доступа бота, мы собираемся идти сейчас.

Использовать ФС Чтобы настроить прочитанный поток …

const filePath = path.join(__dirname, './twitter-archive/tweets.csv')

const tweetData =
  fs.createReadStream(filePath)
  .pipe(csvparse({
    delimiter: ','
  }))
  .on('data', row => {
    console.log(row[5])
  })

Когда вы запускаете это из консоли, вы должны получить вывод из вашего архива Twitter.

Теперь убрать вещи, как @ и RT Чтобы помочь с обработкой естественного языка. Мы настроим две функции CleanText и Hasnostopwords.

CleanText будет токена текста разграничить его на пространство '' , отфильтруйте слов стоп, затем .присоединиться ('') обратно вместе с пространством, а .trim () Любой пробел, который может быть в начале текста.

function cleanText(text) {
  return rita.RiTa.tokenize(text, ' ')
    .filter(hasNoStopWords)
    .join(' ')
    .trim()
}

Токенизированный текст затем можно подавать в Hasnostopwords Функция, чтобы быть санитарным для использования в TweetData.

function hasNoStopWords(token) {
  const stopwords = ['@', 'http', 'RT'];
  return stopwords.every(sw => !token.includes(sw))
}

Теперь, когда у нас есть данные очищены, мы можем твитнуть его. Заменить console.log (строка [5]) с InputText + '' + Cleantext (строка [5]) Отказ Далее мы можем использовать Рита. Римарков (3) где 3 – количество слов, которые необходимо учитывать. Тогда используйте Markov.Generatesentensents (1) где 1 – количество генерируемых предложений. Мы также будем использовать .нанизывать () и .субринг (0, 140) Чтобы укоренить результат до 140 символов.

const tweetData =
  fs.createReadStream(filePath)
  .pipe(csvparse({
    delimiter: ','
  }))
  .on('data', function (row) {
    inputText = `${inputText} ${cleanText(row[5])}`
  })
  .on('end', function(){
    const markov = new rita.RiMarkov(3)
    markov.loadText(inputText)
    const sentence = markov.generateSentences(1)
      .toString()
      .substring(0, 140)
  }

Теперь мы можем твитнуть это с ботом, используя .POST («Статусы/обновление» ... Передача в … переменная как Статус И введя сообщение на консоль, когда есть твит.

const tweetData =
  fs.createReadStream(filePath)
    .pipe(csvparse({
      delimiter: ','
    }))
    .on('data', row => {
      inputText = `${inputText} ${cleanText(row[5])}`
    })
    .on('end', () => {
      const markov = new rita.RiMarkov(3)
      markov.loadText(inputText)
      const sentence = markov.generateSentences(1)
        .toString()
        .substring(0, 140)
      bot.post('statuses/update', {
        status: sentence
      }, (err, data, response) => {
        if (err) {
          console.log(err)
        } else {
          console.log('Markov status tweeted!', sentence)
        }
      })
    })
}

Если вы хотите, чтобы ваши предложения были ближе к тексту ввода, вы можете увеличить слова, чтобы рассмотреть в Рита. Римарков (6) И если вы хотите сделать его Gibberish, затем снизить количество.

Вот завершенный модуль:

const Twit = require('twit')
const fs = require('fs')
const csvparse = require('csv-parse')
const rita = require('rita')
const config = require('./config')
const path = require('path')

let inputText = ''

const bot = new Twit(config)

const filePath = path.join(__dirname, '../twitter-archive/tweets.csv')

const tweetData =
  fs.createReadStream(filePath)
    .pipe(csvparse({
      delimiter: ','
    }))
    .on('data', row => {
      inputText = `${inputText} ${cleanText(row[5])}`
    })
    .on('end', () => {
      const markov = new rita.RiMarkov(10)
      markov.loadText(inputText)
      const sentence = markov.generateSentences(1)
        .toString()
        .substring(0, 140)
      bot.post('statuses/update', {
        status: sentence
      }, (err, data, response) => {
        if (err) {
          console.log(err)
        } else {
          console.log('Markov status tweeted!', sentence)
        }
      })
    })
}

function hasNoStopWords(token) {
  const stopwords = ['@', 'http', 'RT']
  return stopwords.every(sw => !token.includes(sw))
}

function cleanText(text) {
  return rita.RiTa.tokenize(text, ' ')
    .filter(hasNoStopWords)
    .join(' ')
    .trim()
}

Извлеките и твитнуть данные из листов Google

Если вы хотите твитнуть список ссылок, вы можете использовать Столешница работать, хотя список. В этом примере снова от EGGHEAD.IO Мы пройду через список ссылок.

Итак, настройте бот и требуют Столешница :

const Twit = require('twit')
const config = require('./config')
const Tabletop = require('tabletop')

const bot = new Twit(config)

На вашем Google Spreadsheet Вам нужно будет определить заголовок, а затем добавить свои ссылки, мы будем использовать следующее для примера:

Теперь из листов Google мы можем выбрать «Файл»> «Публикация в Интернете» и скопируйте ссылку, которая генерируется для использования в настольном компьютере.

Теперь init Столешница с тремя параметрами, Ключ: Какой URL-адрес электронной таблицы, A Обратный вызов: Функция, чтобы получить данные и SimPleshet: который является правда Если у вас есть только один лист, как в нашем примере здесь:

const spreadsheetUrl = 'https://docs.google.com/spreadsheets/d/1842GC9JS9qDWHc-9leZoEn9Q_-jcPUcuDvIqd_MMPZQ/pubhtml'

Tabletop.init({
  key: spreadsheetUrl,
  callback(data, tabletop) {
    console.log(data)
  },
  simpleSheet: true
})

Запуск бота теперь должен дать так:

$ node index.js
[ { 'links': 'https://www.freecodecamp.com' },
  { 'links': 'https://github.com' },
  { 'links': 'https://www.reddit.com' },
  { 'links': 'https://twitter.com' } ]

Итак, теперь мы можем чирикать их, используя .POST («Статусы/обновление», ... с помощью Foreach на Data Это возвращено в обратном вызове:

Tabletop.init({
  key: spreadsheetUrl,
  callback(data, tabletop) {
    data.forEach(d => {
      const status = `${d.links} a link from a Google spreadsheet`;
      bot.post('statuses/update', {
        status
      }, (err, response, data) => {
        if (err) {
          console.log(err)
        } else {
          console.log('Post success!')
        }
      })
    })
  },
  simpleSheet: true
})

Обратите внимание, что $ {d.links} Имя заголовка мы используем в электронной таблице Google, я попробовал использовать корпус скелета и верблюда и оба возвращаемых ошибок, поэтому я пошел с одним заголовком имени на электронной таблице.

Завершенный код здесь:

const Twit = require('twit')
const config = require('./config')
const Tabletop = require('tabletop')

const bot = new Twit(config)

const spreadsheetUrl = 'https://docs.google.com/spreadsheets/d/1842GC9JS9qDWHc-9leZoEn9Q_-jcPUcuDvIqd_MMPZQ/pubhtml'

Tabletop.init({
  key: spreadsheetUrl,
  callback(data, tabletop) {
    data.forEach(d => {
      const status = `${d.links} a link from a Google spreadsheet`
      console.log(status)
      bot.post('statuses/update', {
        status
      }, (err, response, data) => {
        if (err) {
          console.log(err)
        } else {
          console.log('Post success!')
        }
      })
    })
  },
  simpleSheet: true
})

Положить все это вместе

Хорошо, поэтому эти примеры были хорошими и всеми, но у нас не так у нас есть бот, у нас? Я имею в виду, вы бежите его с терминала, и это сделано, но мы хотим уметь выбить бот и оставить это, чтобы сделать его вещь.

Один из способов, которым я нашел, это использовать Setinterval который забивает события от главного bot.js модуль.

Возьмите пример, который мы сделали, чтобы списать изображение и добавить его в свой собственный модуль, поэтому из корневого каталога нашего проекта:

cd src
touch picture-bot.js

Возьмите пример код из этого и вставьте его в новый модуль. Затем мы собираемся внести следующие изменения, чтобы GetPhoto :

const getPhoto = () => {
  const parameters = {
    url: 'https://api.nasa.gov/planetary/apod',
    qs: {
      api_key: process.env.NASA_KEY
    },
    encoding: 'binary'
  }
  request.get(parameters, (err, respone, body) => {
    body = JSON.parse(body)
    saveFile(body, 'nasa.jpg')
  })
}

Затем в нижней части модуля добавить:

module.exports = getPhoto

Так что теперь мы можем позвонить в GetPhoto Функция из Picture-Bot.js Модуль в нашем bot.js модуль. Наше bot.js Модуль должен выглядеть что-то вроде этого:

const picture = require('./picture-bot')

picture()

Вот и все, две строки кода, попробуйте бежать с терминала сейчас:

yarn start

Мы должны получить немного выхода:

yarn start v0.23.4
$ node index.js
Media saved!
file PATH C:\Users\path\to\project\tweebot-play\nasa.jpg
{ media_id: 863020197799764000,
  media_id_string: '863020197799763968',
  size: 371664,
  expires_after_secs: 86400,
  image: { image_type: 'image/jpeg', w: 954, h: 944 } }
Status posted!
Done in 9.89s.

Картина дня устанавливается, но он пробежал один раз и завершен. Нам нужно положить его на интервал с Setinterval Отказ Требуется два варианта, функция, которая будет звонить, и значение времени ожидания.

Картинка обновляется каждые 24 часа, так что будет сколько миллисекунд в течение 24 часов [8.64e + 7].

Формула составляет 1000 * минуту, так что 1000 * 60 * 60 * 24, поэтому на данный момент добавим это непосредственно в Setinterval Функция:

const picture = require('./picture-bot')

picture()
setInterval(picture, 1000 * 60 * 60 * 24)

Cool, это бот, который опубликует образ наса дня каждые 24 часа!

Давайте продолжаем идти, теперь давайте добавим некоторую случайность в Markov Bot. Как только мы сделали для картины дня пример, давайте создадим новый модуль для Markov Bot и добавить весь код там из предыдущего примера, поэтому из терминала:

cd src
touch markov-bot.js

Затем скопируйте и вставьте пример Markov Bot в новый модуль и внесите следующие изменения:

const tweetData = () => {
  fs.createReadStream(filePath)
    .pipe(csvparse({
      delimiter: ','
    }))
    .on('data', row => {
      inputText = `${inputText} ${cleanText(row[5])}`
    })
    .on('end', () => {
      const markov = new rita.RiMarkov(10)
      markov.loadText(inputText)
        .toString()
        .substring(0, 140)
      const sentence = markov.generateSentences(1)
      bot.post('statuses/update', {
        status: sentence
      }, (err, data, response) => {
        if (err) {
          console.log(err)
        } else {
          console.log('Markov status tweeted!', sentence)
        }
      })
    })
}

Затем в нижней части модуля добавить:

module.exports = tweetData

Похоже на пример изображения BOT, мы собираемся добавить TweetData Экспорт из Markov-Bot.js нашему bot.js Модуль, который теперь должен выглядеть что-то подобное:

const picture = require('./picture-bot')
const markov = require('./markov-bot')

picture()
setInterval(picture, 1000 * 60 * 60 * 24)

markov()

Давайте сделаем Markov Bot Tweet с случайными интервалами от 5 минут и 3 часа

const picture = require('./picture-bot')
const markov = require('./markov-bot')

picture()
setInterval(picture, 1000 * 60 * 60 * 24)

const markovInterval = (Math.floor(Math.random() * 180) + 1) * 1000
markov()
setInterval(markov, markovInterval)

Хорошо! Изображение бота и Марков бот, оба сделаны.

Сделайте то же самое со ссылкой бота? Хорошо, то же самое, как раньше, вы поняли идею сейчас, верно?

Создайте новый файл в SRC Папка для Link Bot:

touch link-bot.js

Скопируйте и вставьте код из примера Link Bot в новый модуль, как это:

const link = () => {
  Tabletop.init({
    key: spreadsheetUrl,
    callback(data, tabletop) {
      data.forEach(d => {
        const status = `${d.links} a link from a Google spreadsheet`
        console.log(status)
        bot.post('statuses/update', {
          status
        }, (err, response, data) => {
          if (err) {
            console.log(err)
          } else {
            console.log('Post success!')
          }
        })
      })
    },
    simpleSheet: true
  })
}

module.exports = link

Тогда мы можем назвать это из бота, поэтому он должен выглядеть что-то подобное:

const picture = require('./picture-bot')
const markov = require('./markov-bot')
const link = require('./link-bot')

picture()
setInterval(picture, 1000 * 60 * 60 * 24)

const markovInterval = (Math.floor(Math.random() * 180) + 1) * 1000
markov()
setInterval(markov, markovInterval)

link()
setInterval(link, 1000 * 60 * 60 * 24)

Теперь мы можем покинуть бот, чтобы сделать это!

Развертывание до сих пор

У нас есть бот, который делает несколько вещей, но это в нашей среде разработки и не может оставаться там вечно. (Это могло, но это было бы довольно непрактично). Давайте поставим наш бот на сервере где-то делать это.

Мы собираемся использовать Zeit’s сейчас Платформа, которая обеспечивает простые развертывания от CLI. Если вы не знакомы с этим, потом посмотрите на Документация Отказ В этих примерах мы будем использовать Теперь-CLI Отказ

Есть несколько вещей, которые нам нужно сделать, чтобы наш бот готов продолжать Теперь . Давайте перечисляем их быстро, а затем переходите к деталям.

  • Регистрация и установка сейчас-CLI.
  • Добавить сейчас Настройки + .npmignore файл
  • Добавить .env Переменные как секреты
  • Добавить НПМ Развертывание скрипт
  • Re Jig picture-bot.js.

Готовый? Давай сделаем это!

Регистрация и установка сейчас-CLI.

Во-первых, регистрация для z EIT Создавая учетную запись и аутентификацию, затем установите CLI.

Установить Теперь Во всем мире на вашей машине, чтобы вы могли использовать его везде.

npm install -g now

Как только это завершено, войдите в систему с:

now --login

Первый раз, когда вы запустите Теперь , это попросит ваш адрес электронной почты, чтобы идентифицировать вас. Перейдите на учетную запись электронной почты, которую вы поставляетесь при регистрации, нажмите на электронную почту, отправленную вам из сейчас , и вы будете войти в систему автоматически.

Если вам нужно переключить учетную запись или повторно аутентифицировать, снова запустите одну и ту же команду.

Вы всегда можете проверить Теперь-CLI Документация для получения дополнительной информации наряду с Ваше первое развертывание руководство.

Добавлять Теперь настройки

С регистрацией и установкой, мы можем настроить бот для развертывания на сейчас Отказ Сначала давайте добавим сейчас Настройки нашего Package.json файл. Я положил это между моим NPM Скрипты и имя автора в моем Package.json :

"scripts": {
    "start": "node index.js"
  },
  "now": {
    "alias": "my-awesome-alias",
    "files": [
      "src",
      "index.js"
    ]
  },
  "author": "Scott Spence",

Это был источник серьезной путаницы для меня, поэтому я надеюсь, что могу спасти вас, боль, которую я прошел через попытку настроить это. Вся соответствующая документация там, вам просто нужно все вместе.

Если вы найдете что-нибудь здесь, что не имеет смысла или кажется неверным, тогда, пожалуйста Войти выпуск или создать запрос на тягу.

Теперь настройки псевдоним Чтобы дать вашему развертыванию краткомагнитофона над автоматическим URL-адресом, что сейчас создает. Файлы Раздел охватывает то, что мы хотим включить в развертывание в сейчас Что я буду покрывать в ближайшее время. В основном, что входит в Файлы Массив – это все, что передается на сейчас серверы.

Теперь нам нужно добавить .npmignore Файл в корне проекта и добавьте следующую строку к нему:

!tweets.csv

Tweets.csv нужно подняться на сейчас Сервер будет использоваться ботом, но ранее мы включили его в нашу .gitignore Отказ Это то, что сейчас Использует для создания вашего проекта, когда он загружен на сервер. Это означает, что файл не будет загружен, если мы не редактируем .npmignore не игнорировать Tweets.csv Отказ

Добавлять .env.env. Переменные как секреты

Наши супер секретные ключи Twitter должны будут храниться как Секреты в сейчас Отказ Это довольно аккуратная особенность, где вы можете определить что-нибудь как секретное и ссылаться на него как псевдоним.

Синтаксис Теперь секреты добавляют мой секрет "Моя ценность" так для нашего .env Ключи, добавьте их все в, давая им описательный (но короткий!) имя.

Вам не нужно будет обернуть вашу «мою ценность» в кавычках, но документация говорит «, когда сомневаешься, оберните свою ценность в цитатах».

В терминале Теперь секреты Ls должен перечислить свой секреты Вы только что создали:

$ now secrets ls
> 5 secrets found under spences10 [1s]
                            id  name                   created
  sec_xxxxxxxxxxZpLDxxxxxxxxxx  ds-twit-key            23h ago
  sec_xxxxxxxxxxTE5Kxxxxxxxxxx  ds-twit-secret         23h ago
  sec_xxxxxxxxxxNorlxxxxxxxxxx  ds-twit-access         23h ago
  sec_xxxxxxxxxxMe1Cxxxxxxxxxx  ds-twit-access-secret  23h ago
  sec_xxxxxxxxxxMJ2jxxxxxxxxxx  nasa-key               23h ago

Добавить НПМ развертывать скрипт

С определенным определенным секретами мы можем создать скрипт развертывания для развертывания сейчас Отказ В нашем Package.json Добавьте дополнительный скрипт:

"main": "index.js",
  "scripts": {
    "start": "node index.js",
    "deploy": "now -e CONSUMER_KEY=@ds-twit-key -e CONSUMER_SECRET=@ds-twit-secret -e ACCESS_TOKEN=@ds-twit-access  -e ACCESS_TOKEN_SECRET=@ds-twit-access-secret -e NASA_KEY=@nasa-key"
  },
  "now": {

Мы добавили Развертывание , который будет запускать сейчас командовать и пройти все нашу среду Переменные и ассоциированные Секрет ценить. Если мы сломаем его на отдельные строки, это будет немного яснее:

now 
-e CONSUMER_KEY=@ds-twit-key 
-e CONSUMER_SECRET=@ds-twit-secret 
-e ACCESS_TOKEN=@ds-twit-access  
-e ACCESS_TOKEN_SECRET=@ds-twit-access-secret 
-e NASA_KEY=@nasa-key

Повторно джиг picture-bot.js.

Потому что сейчас Развертывание – это неизменный Это означает, что нет доступа к записи на диск, где мы хотим сохранить нашу фотографию NASA в день. Чтобы обойти, что нам нужно использовать /TMP Расположение файла.

Спасибо …| Тим От Zeit, чтобы помочь мне с этим!

В Picture-Bot.js Модуль, добавьте следующие две строки в верхнюю часть модуля:

const os = require('os')
const tmpDir = os.tmpdir()

Эти две линии дают нам Temp каталог операционной системы. Если вы похожи на меня, и вы используете Windows, он будет работать так же, как если вы находитесь в другой системе, как система на основе Linux (что сейчас ). В нашем SaveFile Функция, мы собираемся использовать TMPDIR Чтобы сохранить наш файл.

Мы вывели nasa.jpg от GetPhoto Функция, поскольку мы можем определить эту информацию в SaveFile функция. Фото одинакового дня не всегда JPEG Некоторые предметы размещены там видео. Мы можем определить тип с Тровая функция от Тело Передача, это отправит твит со ссылкой на видео:

function saveFile(body) {
  const fileName = body.media_type === 'image/jpeg' ? 'nasa.jpg' : 'nasa.mp4';
  const filePath = path.join(tmpDir + `/${fileName}`)
  
  console.log(`saveFile: file PATH ${filePath}`)
  if (fileName === 'nasa.mp4') {
    // tweet the link
    const params = {
      status: 'NASA video link: ' + body.url
    }
    postStatus(params)
    return
  }
  const file = fs.createWriteStream(filePath)
  
  request(body).pipe(file).on('close', err => {
    if (err) {
      console.log(err)
    } else {
      console.log('Media saved!')
      const descriptionText = body.title
      uploadMedia(descriptionText, filePath)
    }
  })
}

Завершенный код здесь:

const Twit = require('twit')
const request = require('request')
const fs = require('fs')
const config = require('./config')
const path = require('path')

const bot = new Twit(config)

const os = require('os')
const tmpDir = os.tmpdir()

const getPhoto = () => {
  const parameters = {
    url: 'https://api.nasa.gov/planetary/apod',
    qs: {
      api_key: process.env.NASA_KEY
    },
    encoding: 'binary'
  }
  request.get(parameters, (err, respone, body) => {
    body = JSON.parse(body)
    saveFile(body)
  })
}

function saveFile(body) {
  const fileName = body.media_type === 'image/jpeg' ? 'nasa.jpg' : 'nasa.mp4';
  const filePath = path.join(tmpDir + `/${fileName}`)

  console.log(`saveFile: file PATH ${filePath}`)
  if (fileName === 'nasa.mp4') {
    // tweet the link
    const params = {
      status: 'NASA video link: ' + body.url
    }
    postStatus(params)
    return
  }
  const file = fs.createWriteStream(filePath)

  request(body).pipe(file).on('close', err => {
    if (err) {
      console.log(err)
    } else {
      console.log('Media saved!')
      const descriptionText = body.title
      uploadMedia(descriptionText, filePath)
    }
  })
}

function uploadMedia(descriptionText, fileName) {
  console.log(`uploadMedia: file PATH ${fileName}`)
  bot.postMediaChunked({
    file_path: fileName
  }, (err, data, respone) => {
    if (err) {
      console.log(err)
    } else {
      console.log(data)
      const params = {
        status: descriptionText,
        media_ids: data.media_id_string
      }
      postStatus(params)
    }
  })
}

function postStatus(params) {
  bot.post('statuses/update', params, (err, data, respone) => {
    if (err) {
      console.log(err)
    } else {
      console.log('Status posted!')
    }
  })
}

module.exports = getPhoto

Хорошо, вот это! Мы готовы развернуть в сейчас Действительно

В терминале мы называем наш сценарий развертывания, который мы определили ранее:

yarn deploy

Вы получите некоторые вывод:

λ yarn deploy
yarn deploy v0.24.4
$ now -e CONSUMER_KEY=@ds-twit-key -e CONSUMER_SECRET=@ds-twit-secret -e ACCESS_TOKEN=@ds-twit-access  -e ACCESS_TOKEN_SECRET=@ds-twit-access-secret -e NASA_KEY=@nasa-key
> Deploying ~\gitrepos\tweebot-play under spences10
> Using Node.js 7.10.0 (default)
> Ready! https://twee-bot-play-rapjuiuddx.now.sh (copied to clipboard) [5s]
> Upload [====================] 100% 0.0s
> Sync complete (1.54kB) [2s]
> Initializing…
> Building
> ▲ npm install
> ⧗ Installing:
>  ‣ csv-parse@^1.2.0
>  ‣ dotenv@^4.0.0
>  ‣ rita@^1.1.63
>  ‣ tabletop@^1.5.2
>  ‣ twit@^2.2.5
> ✓ Installed 106 modules [3s]
> ▲ npm start
> > tweet-bot-playground@1.0.0 start /home/nowuser/src
> > node index.js
> saveFile: file PATH /tmp/nasa.jpg
> Media saved!
> uploadMedia: file PATH /tmp/nasa.jpg

Удар! У вас есть развернутый бот!

Если вы нажимаете на ссылку, вы сможете осмотреть бот, как он на сейчас Отказ На странице также есть раздел Handy Logs, где вы можете проверить на наличие вывода.

Ресурсы

удивительные твиттер-боты

Спасибо за прочтение! Если вам понравилась эта история, пожалуйста, не забудьте порекомендовать его, щелкнув кнопку на стороне, и поделившись его с друзьями через социальные сети.

Если вы хотите узнать больше обо мне, вы можете Спроси меня что-нибудь Проверьте мой Гадость или твитнуть меня @Scottdevtweets. .

Оригинал: “https://www.freecodecamp.org/news/how-to-build-and-deploy-a-multifunctional-twitter-bot-49e941bb3092/”