Pular para o conteúdo
Development

Rastreando posts agendados do Medium sem uma extensão de navegador

Por Victor Da Luz
railsrubymediumdev-logblog-manager

Venho construindo o blog-manager para lidar com a syndication entre Medium e LinkedIn. A integração com o Medium começou simples: posts são not_imported, draft, ou published. Isso cobria tudo que eu precisava até eu começar a agendar posts no Medium, configurando eles para publicar numa data futura. O Medium não expõe isso pela API dele, então meu app não tinha como saber que um post estava num estado agendado.

A correção é a Fase 1 de uma abordagem em duas fases: modelar o estado no app, me deixar configurar manualmente, e exibir isso na UI. A Fase 2 automatizaria a detecção. Mas antes de construir qualquer automação, eu queria saber: a versão manual realmente cria fricção suficiente para justificar a complexidade? Então construí só o modelo de dados e a UI primeiro.

O que eu adicionei

A mudança central é um novo valor de enum. O Rails torna isso simples, mas há uma regra que vale destacar: os valores inteiros do enum precisam ser estáveis. Se você alguma vez mudar o inteiro por trás de uma chave existente, digamos porque inseriu um valor no meio, toda linha do seu banco de dados silenciosamente muda de significado. Por isso eu sempre adiciono no final:

enum :medium_status, { not_imported: 0, draft: 1, published: 2, scheduled: 3 }, prefix: :medium

Escrevi um teste que verifica o hash exato, não só que o novo valor funciona:

test "medium_status integer mappings are stable" do
  assert_equal({ "not_imported" => 0, "draft" => 1, "published" => 2, "scheduled" => 3 },
               Post.medium_statuses)
end

Esse teste pegaria qualquer reordenação futura imediatamente.

A migration só adiciona uma coluna datetime medium_scheduled_at que aceita nulo. Sem default, sem constraint. A data é opcional porque às vezes eu agendo algo no Medium sem anotar a hora exata.

Para a UI, três coisas precisaram ser atualizadas:

O partial do badge de status já tinha um mapa predefinido indexado pelo valor string do enum. Adicionar "scheduled" ao mapa foi questão de uma linha. Ele herda a classe status-soon (amarela), igual ao draft, o que faz sentido; os dois são estados “ainda não publicado”.

O dropdown de filtro do índice de posts se autopopula a partir de Post.medium_statuses.each_key, então scheduled apareceu ali de graça assim que o enum foi atualizado. Zero mudanças explícitas necessárias no filtro.

O dashboard ganhou um novo widget “Upcoming on Medium”. Ele faz a query Post.kept.where(medium_status: :scheduled).includes(:blog).order(medium_scheduled_at: :asc) e só renderiza quando há resultados. Posts sem data agendada mostram um traço.

O que eu decidi não construir

A issue originalmente incluía um formulário de edição para eu preencher medium_scheduled_at manualmente. Cortei isso. O objetivo inteiro dessa fase é montar o modelo de dados para que a automação da Fase 2 consiga escrever nele. Se eu precisar testar manualmente, um one-liner de rails runner já resolve. Um formulário de edição é escopo de verdade, e prefiro validar que o status aparece corretamente antes de construir a UI de edição.

O que me surpreendeu

O filtro simplesmente funcionou. Eu supunha que precisaria adicionar scheduled explicitamente às opções do select do dropdown, mas como a view itera Post.medium_statuses.each_key, adicionar o valor do enum foi tudo que precisou. Os enums do Rails são surpreendentemente bons nisso.

O que vem a seguir

A Fase 2 é sobre automatizar a detecção, seja fazendo polling do feed RSS do Medium ou fazendo parsing de emails. Isso acabou virando a extensão de navegador em vez disso. Por enquanto, pelo menos consigo marcar posts como agendados manualmente e eles aparecem no dashboard.

Leitura relacionada

Você também pode achar útil

Proton

Proton VPN

VPN comercial com filtragem NetShield e interruptor de desligamento automático.

Como parceiro da Proton, ganho com compras qualificadas dos serviços de privacidade e segurança da Proton (Pass, Mail, VPN, Drive).

Saiba mais
AdGuard

AdGuard para iOS

Bloqueio de anúncios e rastreadores em todo o sistema no iOS, sem necessidade de um servidor DNS separado.

Como afiliado da AdGuard, ganho com compras qualificadas.

Saiba mais
Proton

Proton Drive

Armazenamento em nuvem criptografado, da equipe por trás do Proton Mail.

Como parceiro da Proton, ganho com compras qualificadas dos serviços de privacidade e segurança da Proton (Pass, Mail, VPN, Drive).

Saiba mais