Skip to content

Add support for fetching subscribed newsletters (Whatsapp Channels) - #13

Closed
javiercr wants to merge 3 commits into
masterfrom
javi/channels
Closed

Add support for fetching subscribed newsletters (Whatsapp Channels)#13
javiercr wants to merge 3 commits into
masterfrom
javi/channels

Conversation

@javiercr

@javiercr javiercr commented Jan 22, 2024

Copy link
Copy Markdown
Contributor

Contributes to PLT-1089.

Context

Description

This PR adds the initial support for Whatsapp Channels, known as "newsletters" internally.

The code has been ported from whatsmeow:

The implementation of newsletters in Whatsapp is somehow different to other features in their API: it uses GraphQL queries and mutations and messages are not e2e. GraphQL queries are identified by a hardcoded ID.

So far the only method ported is getSubscribedNewsletters, as this is the only one we need in Texts so far. This method is needed because received newsletter messages don't include the channel name, and subscribed newsletters are not part of the initial history sync, so we need to fetch all subscribed newsletters on connect (this is done in platform-whatsapp's PR).

TODO methods:

queries

  • subscribedNewsletters
  • fetchNewsletter
  • fetchNewsletterDehydrated
  • recommendedNewsletters
  • newslettersDirectory
  • newsletterSubscribers

mutations

  • muteNewsletter
  • unmuteNewsletter
  • updateNewsletter
  • createNewsletter
  • unfollowNewsletter
  • followNewsletter

We should discuss what features from this list we want to support in Texts, other than just receiving messages for them.

@linear

linear Bot commented Jan 22, 2024

Copy link
Copy Markdown
PLT-1089 Whatsapp: support for Channels

https://faq.whatsapp.com/549900560675125

AKA "broadcast channels" or "newsletters" internally in the WA codebase.

Their id is in the form of [id]newsletter

image.png

Comment thread src/Socket/index.ts
import { DEFAULT_CONNECTION_CONFIG } from '../Defaults'
import { UserFacingSocketConfig } from '../Types'
import { makeRegistrationSocket as _makeSocket } from './registration'
import { makeNewslettersSocket as _makeSocket } from './newsletters'

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Baileys uses factory functions to create the final socket object:

  • makeMessagesRecvSocket
  • makeMessagesRecvSocket
  • makeMessagesSocket
  • makeGroupsSocket
  • makeBusinessSocket
  • makeChatsSocket
  • makeRegistrationSocket

Each one call the next. I'm not sure if the order matters here, so I just put makeNewslettersSocket a the end.

Any insight here?

Comment thread src/Types/Newsletter.ts
Comment on lines +1 to +78
export interface NewsletterMuted {
muted: boolean
}

interface WrappedNewsletterState {
type: string
}

export interface NewsletterMetadata {
id: string
state: WrappedNewsletterState
threadMetadata: NewsletterThreadMetadata
viewerMetadata: NewsletterViewerMetadata | null
}

interface NewsletterViewerMetadata {
mute: string
role: string
}

interface NewsletterReactionSettings {
value: string
}

interface NewsletterSettings {
reactionCodes: NewsletterReactionSettings
}

interface ProfilePictureInfo {
url: string
id: string
type: string
directPath: string
}

interface NewsletterThreadMetadata {
creationTime: string
invite: string
name: NewsletterText
description: NewsletterText
subscribersCount: number
verification: string
picture: ProfilePictureInfo | null
preview: ProfilePictureInfo
settings: NewsletterSettings
}

interface NewsletterText {
text: string
id: string
updateTime: string
}

export interface NewsletterMessage {
messageServerId: string
viewsCount: number
reactionCounts: { [key: string]: number }
message: any // Replace with actual type
}

interface GraphQLErrorExtensions {
errorCode: number
isRetryable: boolean
severity: string
}

interface GraphQLError {
extensions: GraphQLErrorExtensions
message: string
path: string[]
}

interface GraphQLErrors extends Array<GraphQLError> {}

export interface GraphQLResponse {
data: any // Replace with actual type
errors: GraphQLErrors
} No newline at end of file

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Some of these types (ported from whatsmeow) are not used yet, but they will be once the remaining queries/mutations are implemented.

Comment thread src/Socket/newsletters.ts
Comment on lines +36 to +47
// const queryFetchNewsletter = '6563316087068696'
// const queryFetchNewsletterDehydrated = '7272540469429201'
// const queryRecommendedNewsletters = '7263823273662354' // variables -> input -> {limit: 20, country_codes: [string]}, output: xwa2_newsletters_recommended
// const queryNewslettersDirectory = '6190824427689257' // variables -> input -> {view: "RECOMMENDED", limit: 50, start_cursor: base64, filters: {country_codes: [string]}}
const querySubscribedNewsletters = '6388546374527196' // variables -> empty, output: xwa2_newsletter_subscribed
// const queryNewsletterSubscribers = '9800646650009898' // variables -> input -> {newsletter_id, count}, output: xwa2_newsletter_subscribers -> subscribers -> edges
// const mutationMuteNewsletter = '6274038279359549' // variables -> {newsletter_id, updates->{description, settings}}, output: xwa2_newsletter_update -> NewsletterMetadata without viewer meta
// const mutationUnmuteNewsletter = '6068417879924485'
// const mutationUpdateNewsletter = '7150902998257522'
// const mutationCreateNewsletter = '6234210096708695'
// const mutationUnfollowNewsletter = '6392786840836363'
// const mutationFollowNewsletter = '9926858900719341'

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Leaving the ids for the remaining queries and mutations here for future reference.

@github-actions

Copy link
Copy Markdown

This PR is stale because it has been open 6 days with no activity. Remove the stale label or comment or this will be closed in 2 days

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant