12-cactus / espinoso

:cactus: Unfriendly Bot for Telegram
3 stars 3 forks source link

Espi v2 #131

Open laendoor opened 6 years ago

laendoor commented 6 years ago

Idea:

Ejemplo

// Ruta para telegram
Route::post('/handle-update', 'TelegramController@handleUpdate')

// Controller
class TelegramController extends Controller {
  public function handleUpdate(TelegramDelivery $delivery, RulesProvider $rules) {
    $message = $telegram->getIncomingMessage();
    $responses = $rules->applyMatches($message);
    return $telegram->applyResponses($responses);
  }
}

// Common Input Message interface
interface InputMessage {
  public function getChat(): Model; // i.e. Eloquent classes, like TelegramChat
  public function getSender(): Model; // ídem
  public function getText(): string;
  ...
}

// Rules
Rules::with(EventsTransformer::class)
  ->match('espi cumple {id}', 'EventsManager@getBirthday')
  ->match('espi cumple {id} {date}', 'EventsManager@setBirthday');

Rules::with(BardoDelEspinosoTransformer::class)
  ->match('send me nudes', 'BardoDelEspinosoManager@sendNudes');

class EventsTransformer implements MessagesTransformerInterface {
  public function getMatches() {
    return [
      'espi cumple @{username}' => [
        '/^espi\s+cumple\s+(?'username'\w+)$/',
        '/^espi decime el cumple de (?'username'\w+)$/',
        ...
      ]
    ];
  }
}

// Manager
class EventsManager extends Manager {
  public function getBirthday($id) {
    $user = User::find($id);
    return ReplyResponses(trans('messages.events.birthday', [
      'name' => $user->name,
      'birthday' => $user->birthday
    ]));
  }
}

abstract class Manager {
  protected $delivery;
  public function __construct(DeliveryInterface $delivery) {
    $this->delivery = $delivery;
  }
}

@marivgil @danwyryunq @sirDemian

queda esto abierto para seguir acomodando ideas

laendoor commented 6 years ago

Estuve pensando un ligero cambio en la arquitectura. ¿Qué les parecería si en lugar de los ya amados Handlers/Managers logramos usar los Controllers nativos de laravel?

Mi idea que es cuando llegue un mensaje al handleUpdates como llega hoy, eso se parse a un texto más simple (al igual que como está planteado en el comentario anterior). Pero que en vez de ser algo tipo espi cumple @{name} se parsee a una route común de laravel, i.e. /cumple/{id}.

Ese pequeño cambio nos puede habilitar a que desde el handleUpdate se puedan hacer varios requests independientes. Además nos habilita todas las ventajas de trabajar con los controllers nativos, como la injección de dependencias, el request completo, etc. Inclusive, en lugar de tener muchos arrays de traducción, se pueden tener vistas que retornar el markdown, siendo más simple tener templates de mensajes, etc.

Por otro lado elimina la necesidad de tener que rearmar o reutilizar el sistema de ruteo; directamente usamos el existente así como viene.

También estuve pensando en cuestiones de dependencia que planteaba @danwyryunq. Va a haber momentos en donde va a ser difícil que un método de un controllador sea completamente independiente de la plataforma con la cual se tiene que comunicar. Creo que podemos dejar por el momento cierto nivel de acoplamiento solo en los controladores; y si agregamos otra plataforma usamos otro controller y listo; y las funcionalidades comunes las agrupamos en un controlador padre, o algo similar.

Opiniones? Ideas? Sugerencias?

laendoor commented 6 years ago
// Ruta para telegram
Route::post('/handle-update', 'TelegramController@handleUpdate')

// Controller
class TelegramController extends Controller {
  public function handleUpdate(TelegramListener $delivery, TranslatorCollection $translator) {
    $message = $telegram->getIncomingMessage();
    $routes = $translator->getRoutes($message->getText());
    $routes->each(function (string $route) {
      GuzzleClient::put($routes, ['form_params' => 
        'delivery' => 'telegram',
        'orig_message' => $message->raw()
      ])
    });
    return null;
  }
}

// TranslatorCollection es una Collection de <Translator>

class EventsTranslator implements TranslatorInterface {
  public function getRoutes($text) {
    return collect([
      'cumple/{id}' => [
        '/^espi\s+cumple\s+(?'username'\w+)$/',
        '/^espi decime el cumple de (?'username'\w+)$/',
        ...
      ])->map(function ($rule) {
          return $this->somethingMagic($rule);
      })->filter()->getKeys():
    ];
  }
}

// Rutas
Route::put('/cumples/{id}', 'BirthdayController@get');
Route::put('/cumples/{id}/set/{date}', 'BirthdayController@set');

// Controllers
class BirthdayController extends Controller {
  public function getBirthday($id, Request $request) {
    $delivery = resolv($request->input('delivery'));
    $user = User::find($id);
    return reply(trans('messages.events.birthday', [
      'name' => $user->name,
      'birthday' => $user->birthday
    ]));
  }
}