python ir c бот пытается использовать две разные системы обмена сообщениями - PullRequest
2 голосов
/ 17 июня 2020

Я использую модуль python ir c [1] и модуль pika в python для создания бота ir c, который прослушивает как сообщения канала, так и очередь rabbitmq.

Я взял исходный код из [2] и добавил к нему элементы pika:

#! /usr/bin/env python
#
# Example program using irc.client.
#
# This program is free without restrictions; do anything you like with
# it.
#
# Joel Rosdahl <joel@rosdahl.net>

import sys
import argparse
import itertools

import irc.client
import pika


target = "#test"
"The nick or channel to which to send messages"


def on_connect(connection, event):
  if irc.client.is_channel(target):
      connection.join(target)
      return
  main_loop(connection)


def on_join(connection, event):
  main_loop(connection)


def get_lines():
  while True:
      yield sys.stdin.readline().strip()


def main_loop(connection):
  for line in itertools.takewhile(bool, get_lines()):
      print(line)
      connection.privmsg(target, line)
  connection.quit("Using irc.client.py")


def on_disconnect(connection, event):
  raise SystemExit()


def get_args():
  parser = argparse.ArgumentParser()
  parser.add_argument('server')
  parser.add_argument('nickname')
  parser.add_argument('target', help="a nickname or channel")
  parser.add_argument('-p', '--port', default=6667, type=int)
  jaraco.logging.add_arguments(parser)
  return parser.parse_args()


def callback(ch, method, properties, body):
  print(" [x] Received %r" % body)


def get_channel():
  creds = pika.PlainCredentials('testuser', 'testing')

  params = pika.ConnectionParameters(
      host="localhost",
      virtual_host="/test",
      credentials=creds)

  connection = pika.BlockingConnection(params)
  channel = connection.channel()

  channel.queue_declare(queue='test')

  channel.basic_consume(
      queue='test', on_message_callback=callback, auto_ack=True)

  return channel


def main():
  chan = get_channel()

  reactor = irc.client.Reactor()
  try:
      c = reactor.server().connect("irc.local", 6667, "testuser")
  except irc.client.ServerConnectionError:
      print(sys.exc_info()[1])
      raise SystemExit(1)

  c.add_global_handler("welcome", on_connect)
  c.add_global_handler("join", on_join)
  c.add_global_handler("disconnect", on_disconnect)

  print("Processing reactor")
  reactor.process_forever()
  print("Channel : start consuming")
  channel.start_consuming()


if __name__ == '__main__':
  main()

Проблема с приведенным выше кодом в том, что я не изменил код get_lines (), чтобы фактически получить из очереди сообщений, так как я застрял с тем, на что его изменить.

Кроме того, строка «response.process_forever ()» блокирует строку «channel.start_consuming ()» и, очевидно, если я перемещаю канал .start_consuming () выше response.process_forever (), response.process_forever () не запускается.

На этом этапе я в тупике. Я думал об использовании многопроцессорных потоков; но мой опыт работы с потоками нулевой, и даже после прочтения [3] я не совсем уверен, что это поможет. Честно говоря, это смутило меня немного больше.

Я думал добавить обработчик обратного вызова on_ *, но поскольку все эти события основаны на ir c, обработчик не будет слушать очередь rabbitmq.

Может у кого-нибудь есть предложение, как одновременно запустить process_forever () l oop и цикл start_consuming (); то есть заставить бота прослушивать канал ir c и очередь сообщений?

Спасибо!

: ed

[1] - https://github.com/jaraco/irc

[2] - https://github.com/jaraco/irc/blob/master/scripts/irccat.py

[3] - https://realpython.com/intro-to-python-threading/

1 Ответ

1 голос
/ 17 июня 2020

Спасибо @fura (слава!) За помощь в разъяснении того, что я могу сделать. Окончательный рабочий результирующий код выглядит следующим образом:

#! /usr/bin/env python
#
# Example program using irc.client.
#
# This program is free without restrictions; do anything you like with
# it.
#
# Joel Rosdahl <joel@rosdahl.net>

import sys
import argparse
import itertools

import irc.client
import pika


target = "#test"
"The nick or channel to which to send messages"


def on_connect(connection, event):
    if irc.client.is_channel(target):
        connection.join(target)
        return


def on_disconnect(connection, event):
    raise SystemExit()


def get_channel():
    creds = pika.PlainCredentials('testuser', 'testing')

    params = pika.ConnectionParameters(
        host="msg.local",
        virtual_host="/test",
        credentials=creds)

    connection = pika.BlockingConnection(params)
    channel = connection.channel()

    channel.queue_declare(queue='test')

    return channel


def main():
    chan = get_channel()

    reactor = irc.client.Reactor()
    try:
        print("connect to server")
        c = reactor.server().connect("irc.local", 6667, "testUser")
    except irc.client.ServerConnectionError:
        print(sys.exc_info()[1])
        raise SystemExit(1)

    c.add_global_handler("welcome", on_connect)
    c.add_global_handler("disconnect", on_disconnect)

    print("Processing reactor")
    while True:
        reactor.process_once()
        mf, hdr, bd = chan.basic_get("test")
        if mf:
            chan.basic_ack(mf.delivery_tag)
            bdd = bd.decode('utf-8')
            if "cmd:" in bdd:
                p = bdd.replace("cmd:", "").strip()
                if p.lower() == "quit":
                    c.quit("Buckeroo Banzai!")
                else:
                    c.privmsg("#test", bdd)
            else:
                c.privmsg("#test", bdd)


if __name__ == '__main__':
    main()

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

Опять же, @fura, ценю помощь и совет!

: Ed

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