Skip to content

Conversation

@rnons
Copy link
Contributor

@rnons rnons commented Dec 1, 2025

No description provided.

@rnons rnons requested a review from tulir December 1, 2025 12:18
_ bridgev2.GroupCreatingNetworkAPI = (*LinkedInClient)(nil)
)

func (l *LinkedInClient) ResolveIdentifier(ctx context.Context, id string, _ bool) (*bridgev2.ResolveIdentifierResponse, error) {
Copy link
Contributor Author

Choose a reason for hiding this comment

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

do i need to implement this? CreateGroup seems to work without it

Copy link
Member

Choose a reason for hiding this comment

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

Yes, clients can't create groups if they can't get user IDs for the group participants. Starting DMs should be implemented too.

It might be sufficient for ResolveIdentifier to accept internal IDs, but you can also allow usernames/emails/phone numbers if linkedin has sensible query APIs for those (search-like APIs probably shouldn't be used for resolve identifier). SearchUsers and/or GetContactList are also good to have depending on what APIs are available.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

linkedin can only message connected people, I tried but didn't find an api to get all connections. Maybe the best we can do is pulling all participants from existing conversations

Comment on lines 34 to 36
CreateDM: true,
LookupUsername: true,
ContactList: true,
Copy link
Member

Choose a reason for hiding this comment

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

Faking these is not allowed, they need to reflect what ResolveIdentifier, SearchUsers and GetContactList can actually do

Copy link
Contributor Author

Choose a reason for hiding this comment

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

with these at least I can create group with participants from existing conversations
without these, linkedin participants don't show up in the options list at all

Comment on lines 212 to 217
body := SendMessageBody{
Text: topic,
}
if topic == "" {
body.Text = title
}
Copy link
Member

Choose a reason for hiding this comment

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

Is this going to send an actual message to the chat? 🤔

Copy link
Contributor Author

Choose a reason for hiding this comment

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

yes, the message body is required. I tried to set Topic: bridgev2.GroupFieldCapability{Allowed: true, Required: true}, but beeper desktop doesn't seem to have a topic input when creating group

Copy link
Member

Choose a reason for hiding this comment

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

Topic is for the group description, not initial message. If group descriptions don't exist, it shouldn't be advertised at all. For now, probably best to hardcode some temporary message like "Group created"


func (l *LinkedInClient) ResolveIdentifier(ctx context.Context, identifier string, createChat bool) (*bridgev2.ResolveIdentifierResponse, error) {
id := networkid.UserID(identifier)
ghost, _ := l.main.Bridge.GetGhostByID(ctx, id)
Copy link
Member

Choose a reason for hiding this comment

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

Errors should be propagated rather than ignored

)

func (l *LinkedInClient) ResolveIdentifier(ctx context.Context, identifier string, createChat bool) (*bridgev2.ResolveIdentifierResponse, error) {
id := networkid.UserID(identifier)
Copy link
Member

Choose a reason for hiding this comment

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

The input can be absolutely anything, so this needs to validate that it looks like a linkedin identifier. Implementing ValidateUserID on the network connector and calling that should be sufficient


func (l *LinkedInClient) CreateGroup(ctx context.Context, params *bridgev2.GroupCreateParams) (*bridgev2.CreateChatResponse, error) {
chatInfo := &bridgev2.ChatInfo{
Type: ptr.Ptr(database.RoomTypeGroupDM),
Copy link
Member

Choose a reason for hiding this comment

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

I had missed that chatinfo.go makes this mistake too, but groups are not group DMs, the default room type should be used instead

Membership: event.MembershipJoin,
}
}
resp, err := l.client.NewChat(ctx, ptr.Val(chatInfo.Name), participants)
Copy link
Member

Choose a reason for hiding this comment

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

Do we get the proper conversation info from this? I don't like the way this ChatInfo is formed completely separately from the code in chatinfo.go, would be preferable to reuse conversationToChatInfo if we get the canonical info from the server

(if we don't get the info, then this is fine for now)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

we only get conversation urn

res = {
  value: {
    renderContentUnions: [],
    entityUrn: '',
    backendConversationUrn: '',
    senderUrn: '',
    originToken: '',
    body: { attributes: [], text: 'c' },
    backendUrn: '',
    conversationUrn: '',
    deliveredAt: 1764378815883,
  },
}

Copy link
Member

Choose a reason for hiding this comment

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

Then the current code is fine for now


func (*LinkedInConnector) GetBridgeInfoVersion() (info, capabilities int) {
return 1, 7
return 1, 8
Copy link
Member

Choose a reason for hiding this comment

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

The capability version only applies to room features, not general capabilities, no need to bump it here

)

func (l *LinkedInConnector) ValidateUserID(id networkid.UserID) bool {
return strings.HasPrefix(string(id), "ACoAA")
Copy link
Contributor Author

Choose a reason for hiding this comment

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

not sure how reliable this prefix is, should we check id length instead?

Copy link
Member

Choose a reason for hiding this comment

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

If it's fixed length, then definitely check the length. Also if it's always base64 or something, can try decoding it

Copy link
Contributor Author

Choose a reason for hiding this comment

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

it looks like base64, but decoded to binary string

Copy link
Member

Choose a reason for hiding this comment

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

So probably check length (greater than X if it's not fixed length) and that it's valid base64, probably no need to inspect the contents further

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

Labels

None yet

Development

Successfully merging this pull request may close these issues.

3 participants