forked from lug/matterbridge
2
vendor/go.mau.fi/whatsmeow/appstate.go
vendored
2
vendor/go.mau.fi/whatsmeow/appstate.go
vendored
@@ -271,7 +271,7 @@ func (cli *Client) requestAppStateKeys(ctx context.Context, rawKeyIDs [][]byte)
|
||||
},
|
||||
}
|
||||
ownID := cli.getOwnID().ToNonAD()
|
||||
if ownID.IsEmpty() {
|
||||
if ownID.IsEmpty() || len(debugKeyIDs) == 0 {
|
||||
return
|
||||
}
|
||||
cli.Log.Infof("Sending key request for app state keys %+v", debugKeyIDs)
|
||||
|
||||
4629
vendor/go.mau.fi/whatsmeow/binary/proto/def.pb.go
vendored
4629
vendor/go.mau.fi/whatsmeow/binary/proto/def.pb.go
vendored
File diff suppressed because it is too large
Load Diff
BIN
vendor/go.mau.fi/whatsmeow/binary/proto/def.pb.raw
vendored
BIN
vendor/go.mau.fi/whatsmeow/binary/proto/def.pb.raw
vendored
Binary file not shown.
135
vendor/go.mau.fi/whatsmeow/binary/proto/def.proto
vendored
135
vendor/go.mau.fi/whatsmeow/binary/proto/def.proto
vendored
@@ -47,6 +47,10 @@ message DeviceProps {
|
||||
ALOHA = 11;
|
||||
CATALINA = 12;
|
||||
TCL_TV = 13;
|
||||
IOS_PHONE = 14;
|
||||
IOS_CATALYST = 15;
|
||||
ANDROID_PHONE = 16;
|
||||
ANDROID_AMBIGUOUS = 17;
|
||||
}
|
||||
message HistorySyncConfig {
|
||||
optional uint32 fullSyncDaysLimit = 1;
|
||||
@@ -69,33 +73,6 @@ message DeviceProps {
|
||||
optional HistorySyncConfig historySyncConfig = 5;
|
||||
}
|
||||
|
||||
enum PeerDataOperationRequestType {
|
||||
UPLOAD_STICKER = 0;
|
||||
SEND_RECENT_STICKER_BOOTSTRAP = 1;
|
||||
GENERATE_LINK_PREVIEW = 2;
|
||||
}
|
||||
message PeerDataOperationRequestResponseMessage {
|
||||
message PeerDataOperationResult {
|
||||
message LinkPreviewResponse {
|
||||
optional string url = 1;
|
||||
optional string title = 2;
|
||||
optional string description = 3;
|
||||
optional bytes thumbData = 4;
|
||||
optional string canonicalUrl = 5;
|
||||
optional string matchText = 6;
|
||||
optional string previewType = 7;
|
||||
}
|
||||
|
||||
optional MediaRetryNotification.ResultType mediaUploadResult = 1;
|
||||
optional StickerMessage stickerMessage = 2;
|
||||
optional LinkPreviewResponse linkPreviewResponse = 3;
|
||||
}
|
||||
|
||||
optional PeerDataOperationRequestType peerDataOperationRequestType = 1;
|
||||
optional string stanzaId = 2;
|
||||
repeated PeerDataOperationResult peerDataOperationResult = 3;
|
||||
}
|
||||
|
||||
message PeerDataOperationRequestMessage {
|
||||
message RequestUrlPreview {
|
||||
optional string url = 1;
|
||||
@@ -105,9 +82,18 @@ message PeerDataOperationRequestMessage {
|
||||
optional string fileSha256 = 1;
|
||||
}
|
||||
|
||||
message HistorySyncOnDemandRequest {
|
||||
optional string chatJid = 1;
|
||||
optional string oldestMsgId = 2;
|
||||
optional bool oldestMsgFromMe = 3;
|
||||
optional int32 onDemandMsgCount = 4;
|
||||
optional int64 oldestMsgTimestampMs = 5;
|
||||
}
|
||||
|
||||
optional PeerDataOperationRequestType peerDataOperationRequestType = 1;
|
||||
repeated RequestStickerReupload requestStickerReupload = 2;
|
||||
repeated RequestUrlPreview requestUrlPreview = 3;
|
||||
optional HistorySyncOnDemandRequest historySyncOnDemandRequest = 4;
|
||||
}
|
||||
|
||||
message PaymentInviteMessage {
|
||||
@@ -376,6 +362,7 @@ message HistorySyncNotification {
|
||||
RECENT = 3;
|
||||
PUSH_NAME = 4;
|
||||
NON_BLOCKING_DATA = 5;
|
||||
ON_DEMAND = 6;
|
||||
}
|
||||
optional bytes fileSha256 = 1;
|
||||
optional uint64 fileLength = 2;
|
||||
@@ -485,6 +472,11 @@ message ExtendedTextMessage {
|
||||
BRYNDAN_WRITE = 3;
|
||||
BEBASNEUE_REGULAR = 4;
|
||||
OSWALD_HEAVY = 5;
|
||||
DAMION_REGULAR = 6;
|
||||
MORNINGBREEZE_REGULAR = 7;
|
||||
CALISTOGA_REGULAR = 8;
|
||||
EXO2_EXTRABOLD = 9;
|
||||
COURIERPRIME_BOLD = 10;
|
||||
}
|
||||
optional string text = 1;
|
||||
optional string matchedText = 2;
|
||||
@@ -652,6 +644,7 @@ message AudioMessage {
|
||||
optional bytes streamingSidecar = 18;
|
||||
optional bytes waveform = 19;
|
||||
optional fixed32 backgroundArgb = 20;
|
||||
optional bool viewOnce = 21;
|
||||
}
|
||||
|
||||
message AppStateSyncKey {
|
||||
@@ -730,6 +723,11 @@ message HydratedTemplateButton {
|
||||
}
|
||||
}
|
||||
|
||||
message GroupMention {
|
||||
optional string groupJid = 1;
|
||||
optional string groupSubject = 2;
|
||||
}
|
||||
|
||||
message DisappearingMode {
|
||||
enum Initiator {
|
||||
CHANGED_IN_CHAT = 0;
|
||||
@@ -749,6 +747,11 @@ message DeviceListMetadata {
|
||||
}
|
||||
|
||||
message ContextInfo {
|
||||
message UTMInfo {
|
||||
optional string utmSource = 1;
|
||||
optional string utmCampaign = 2;
|
||||
}
|
||||
|
||||
message ExternalAdReplyInfo {
|
||||
enum MediaType {
|
||||
NONE = 0;
|
||||
@@ -808,6 +811,8 @@ message ContextInfo {
|
||||
optional string trustBannerType = 37;
|
||||
optional uint32 trustBannerAction = 38;
|
||||
optional bool isSampled = 39;
|
||||
repeated GroupMention groupMentions = 40;
|
||||
optional UTMInfo utm = 41;
|
||||
}
|
||||
|
||||
message ActionLink {
|
||||
@@ -928,6 +933,12 @@ message Message {
|
||||
optional FutureProofMessage editedMessage = 58;
|
||||
optional FutureProofMessage viewOnceMessageV2Extension = 59;
|
||||
optional PollCreationMessage pollCreationMessageV2 = 60;
|
||||
optional ScheduledCallCreationMessage scheduledCallCreationMessage = 61;
|
||||
optional FutureProofMessage groupMentionedMessage = 62;
|
||||
optional PinMessage pinMessage = 63;
|
||||
optional PollCreationMessage pollCreationMessageV3 = 64;
|
||||
optional ScheduledCallEditMessage scheduledCallEditMessage = 65;
|
||||
optional VideoMessage ptvMessage = 66;
|
||||
}
|
||||
|
||||
message MessageContextInfo {
|
||||
@@ -1050,6 +1061,26 @@ message SendPaymentMessage {
|
||||
optional PaymentBackground background = 4;
|
||||
}
|
||||
|
||||
message ScheduledCallEditMessage {
|
||||
enum EditType {
|
||||
UNKNOWN = 0;
|
||||
CANCEL = 1;
|
||||
}
|
||||
optional MessageKey key = 1;
|
||||
optional EditType editType = 2;
|
||||
}
|
||||
|
||||
message ScheduledCallCreationMessage {
|
||||
enum CallType {
|
||||
UNKNOWN = 0;
|
||||
VOICE = 1;
|
||||
VIDEO = 2;
|
||||
}
|
||||
optional int64 scheduledTimestampMs = 1;
|
||||
optional CallType callType = 2;
|
||||
optional string title = 3;
|
||||
}
|
||||
|
||||
message RequestPhoneNumberMessage {
|
||||
optional ContextInfo contextInfo = 1;
|
||||
}
|
||||
@@ -1163,6 +1194,45 @@ message PollCreationMessage {
|
||||
optional ContextInfo contextInfo = 5;
|
||||
}
|
||||
|
||||
message PinMessage {
|
||||
enum PinMessageType {
|
||||
UNKNOWN_PIN_MESSAGE_TYPE = 0;
|
||||
PIN_FOR_ALL = 1;
|
||||
UNPIN_FOR_ALL = 2;
|
||||
}
|
||||
optional MessageKey key = 1;
|
||||
optional PinMessageType pinMessageType = 2;
|
||||
optional int64 senderTimestampMs = 3;
|
||||
}
|
||||
|
||||
enum PeerDataOperationRequestType {
|
||||
UPLOAD_STICKER = 0;
|
||||
SEND_RECENT_STICKER_BOOTSTRAP = 1;
|
||||
GENERATE_LINK_PREVIEW = 2;
|
||||
HISTORY_SYNC_ON_DEMAND = 3;
|
||||
}
|
||||
message PeerDataOperationRequestResponseMessage {
|
||||
message PeerDataOperationResult {
|
||||
message LinkPreviewResponse {
|
||||
optional string url = 1;
|
||||
optional string title = 2;
|
||||
optional string description = 3;
|
||||
optional bytes thumbData = 4;
|
||||
optional string canonicalUrl = 5;
|
||||
optional string matchText = 6;
|
||||
optional string previewType = 7;
|
||||
}
|
||||
|
||||
optional MediaRetryNotification.ResultType mediaUploadResult = 1;
|
||||
optional StickerMessage stickerMessage = 2;
|
||||
optional LinkPreviewResponse linkPreviewResponse = 3;
|
||||
}
|
||||
|
||||
optional PeerDataOperationRequestType peerDataOperationRequestType = 1;
|
||||
optional string stanzaId = 2;
|
||||
repeated PeerDataOperationResult peerDataOperationResult = 3;
|
||||
}
|
||||
|
||||
message EphemeralSetting {
|
||||
optional sfixed32 duration = 1;
|
||||
optional sfixed64 timestamp = 2;
|
||||
@@ -1220,6 +1290,7 @@ message HistorySync {
|
||||
RECENT = 3;
|
||||
PUSH_NAME = 4;
|
||||
NON_BLOCKING_DATA = 5;
|
||||
ON_DEMAND = 6;
|
||||
}
|
||||
required HistorySyncType syncType = 1;
|
||||
repeated Conversation conversations = 2;
|
||||
@@ -1303,8 +1374,8 @@ message Conversation {
|
||||
optional string description = 33;
|
||||
optional bool support = 34;
|
||||
optional bool isParentGroup = 35;
|
||||
optional bool isDefaultSubgroup = 36;
|
||||
optional string parentGroupId = 37;
|
||||
optional bool isDefaultSubgroup = 36;
|
||||
optional string displayName = 38;
|
||||
optional string pnJid = 39;
|
||||
optional bool shareOwnPn = 40;
|
||||
@@ -1831,6 +1902,7 @@ message ClientPayload {
|
||||
WEAROS = 29;
|
||||
ARDEVICE = 30;
|
||||
VRDEVICE = 31;
|
||||
BLUE_WEB = 32;
|
||||
}
|
||||
message AppVersion {
|
||||
optional uint32 primary = 1;
|
||||
@@ -1912,11 +1984,6 @@ message ClientPayload {
|
||||
NETWORK_SWITCH = 4;
|
||||
PING_RECONNECT = 5;
|
||||
}
|
||||
enum BizMarketSegment {
|
||||
DEFAULT = 0;
|
||||
DEVX = 1;
|
||||
INBOX = 2;
|
||||
}
|
||||
optional uint64 username = 1;
|
||||
optional bool passive = 3;
|
||||
optional UserAgent userAgent = 5;
|
||||
@@ -1941,7 +2008,6 @@ message ClientPayload {
|
||||
optional bytes fbDeviceId = 32;
|
||||
optional bool pull = 33;
|
||||
optional bytes paddingBytes = 34;
|
||||
optional BizMarketSegment bizMarketSegment = 35;
|
||||
optional int32 yearClass = 36;
|
||||
optional int32 memClass = 37;
|
||||
}
|
||||
@@ -2258,6 +2324,7 @@ message PollUpdate {
|
||||
optional PollVoteMessage vote = 2;
|
||||
optional int64 senderTimestampMs = 3;
|
||||
optional int64 serverTimestampMs = 4;
|
||||
optional bool unread = 5;
|
||||
}
|
||||
|
||||
message PollAdditionalMetadata {
|
||||
|
||||
13
vendor/go.mau.fi/whatsmeow/broadcast.go
vendored
13
vendor/go.mau.fi/whatsmeow/broadcast.go
vendored
@@ -30,14 +30,19 @@ func (cli *Client) getBroadcastListParticipants(jid types.JID) ([]types.JID, err
|
||||
return nil, ErrNotLoggedIn
|
||||
}
|
||||
|
||||
var hasSelf bool
|
||||
for _, participant := range list {
|
||||
selfIndex := -1
|
||||
for i, participant := range list {
|
||||
if participant.User == ownID.User {
|
||||
hasSelf = true
|
||||
selfIndex = i
|
||||
break
|
||||
}
|
||||
}
|
||||
if !hasSelf {
|
||||
if selfIndex >= 0 {
|
||||
if cli.DontSendSelfBroadcast {
|
||||
list[selfIndex] = list[len(list)-1]
|
||||
list = list[:len(list)-1]
|
||||
}
|
||||
} else if !cli.DontSendSelfBroadcast {
|
||||
list = append(list, ownID)
|
||||
}
|
||||
return list, nil
|
||||
|
||||
9
vendor/go.mau.fi/whatsmeow/client.go
vendored
9
vendor/go.mau.fi/whatsmeow/client.go
vendored
@@ -123,6 +123,10 @@ type Client struct {
|
||||
// If false, decrypting a message from untrusted devices will fail.
|
||||
AutoTrustIdentity bool
|
||||
|
||||
// Should sending to own devices be skipped when sending broadcasts?
|
||||
// This works around a bug in the WhatsApp android app where it crashes if you send a status message from a linked device.
|
||||
DontSendSelfBroadcast bool
|
||||
|
||||
// Should SubscribePresence return an error if no privacy token is stored for the user?
|
||||
ErrorOnSubscribePresenceWithoutToken bool
|
||||
|
||||
@@ -186,8 +190,9 @@ func NewClient(deviceStore *store.Device, log waLog.Logger) *Client {
|
||||
GetMessageForRetry: func(requester, to types.JID, id types.MessageID) *waProto.Message { return nil },
|
||||
appStateKeyRequests: make(map[string]time.Time),
|
||||
|
||||
EnableAutoReconnect: true,
|
||||
AutoTrustIdentity: true,
|
||||
EnableAutoReconnect: true,
|
||||
AutoTrustIdentity: true,
|
||||
DontSendSelfBroadcast: true,
|
||||
}
|
||||
cli.nodeHandlers = map[string]nodeHandler{
|
||||
"message": cli.handleEncryptedMessage,
|
||||
|
||||
@@ -79,7 +79,10 @@ func (cli *Client) handleIB(node *waBinary.Node) {
|
||||
func (cli *Client) handleConnectFailure(node *waBinary.Node) {
|
||||
ag := node.AttrGetter()
|
||||
reason := events.ConnectFailureReason(ag.Int("reason"))
|
||||
cli.expectDisconnect()
|
||||
// Let the auto-reconnect happen for 503s, for all other failures block it
|
||||
if reason != events.ConnectFailureServiceUnavailable {
|
||||
cli.expectDisconnect()
|
||||
}
|
||||
if reason.IsLoggedOut() {
|
||||
cli.Log.Infof("Got %s connect failure, sending LoggedOut event and deleting session", reason)
|
||||
go cli.dispatchEvent(&events.LoggedOut{OnConnect: true, Reason: reason})
|
||||
@@ -96,6 +99,8 @@ func (cli *Client) handleConnectFailure(node *waBinary.Node) {
|
||||
} else if reason == events.ConnectFailureClientOutdated {
|
||||
cli.Log.Errorf("Client outdated (405) connect failure")
|
||||
go cli.dispatchEvent(&events.ClientOutdated{})
|
||||
} else if reason == events.ConnectFailureServiceUnavailable {
|
||||
cli.Log.Warnf("Got 503 connect failure, assuming automatic reconnect will handle it")
|
||||
} else {
|
||||
cli.Log.Warnf("Unknown connect failure: %s", node.XMLString())
|
||||
go cli.dispatchEvent(&events.ConnectFailure{Reason: reason, Raw: node})
|
||||
|
||||
4
vendor/go.mau.fi/whatsmeow/download.go
vendored
4
vendor/go.mau.fi/whatsmeow/download.go
vendored
@@ -192,10 +192,10 @@ func (cli *Client) Download(msg DownloadableMessage) ([]byte, error) {
|
||||
var isWebWhatsappNetURL bool
|
||||
if ok {
|
||||
url = urlable.GetUrl()
|
||||
isWebWhatsappNetURL = strings.HasPrefix(urlable.GetUrl(), "https://web.whatsapp.net")
|
||||
isWebWhatsappNetURL = strings.HasPrefix(url, "https://web.whatsapp.net")
|
||||
}
|
||||
if len(url) > 0 && !isWebWhatsappNetURL {
|
||||
return cli.downloadAndDecrypt(urlable.GetUrl(), msg.GetMediaKey(), mediaType, getSize(msg), msg.GetFileEncSha256(), msg.GetFileSha256())
|
||||
return cli.downloadAndDecrypt(url, msg.GetMediaKey(), mediaType, getSize(msg), msg.GetFileEncSha256(), msg.GetFileSha256())
|
||||
} else if len(msg.GetDirectPath()) > 0 {
|
||||
return cli.DownloadMediaWithPath(msg.GetDirectPath(), msg.GetFileEncSha256(), msg.GetFileSha256(), msg.GetMediaKey(), getSize(msg), mediaType, mediaTypeToMMSType[mediaType])
|
||||
} else {
|
||||
|
||||
2
vendor/go.mau.fi/whatsmeow/message.go
vendored
2
vendor/go.mau.fi/whatsmeow/message.go
vendored
@@ -345,7 +345,7 @@ func (cli *Client) handleAppStateSyncKeyShare(keys *waProto.AppStateSyncKeyShare
|
||||
cli.Log.Errorf("Failed to store app state sync key %X: %v", key.GetKeyId().GetKeyId(), err)
|
||||
continue
|
||||
}
|
||||
cli.Log.Debugf("Received app state sync key %X", key.GetKeyId().GetKeyId())
|
||||
cli.Log.Debugf("Received app state sync key %X (ts: %d)", key.GetKeyId().GetKeyId(), key.GetKeyData().GetTimestamp())
|
||||
}
|
||||
cli.appStateKeyRequestsLock.RUnlock()
|
||||
|
||||
|
||||
@@ -74,7 +74,7 @@ func (vc WAVersionContainer) ProtoAppVersion() *waProto.ClientPayload_UserAgent_
|
||||
}
|
||||
|
||||
// waVersion is the WhatsApp web client version
|
||||
var waVersion = WAVersionContainer{2, 2301, 6}
|
||||
var waVersion = WAVersionContainer{2, 2310, 5}
|
||||
|
||||
// waVersionHash is the md5 hash of a dot-separated waVersion
|
||||
var waVersionHash [16]byte
|
||||
|
||||
@@ -282,6 +282,7 @@ const (
|
||||
INSERT INTO whatsmeow_app_state_sync_keys (jid, key_id, key_data, timestamp, fingerprint) VALUES ($1, $2, $3, $4, $5)
|
||||
ON CONFLICT (jid, key_id) DO UPDATE
|
||||
SET key_data=excluded.key_data, timestamp=excluded.timestamp, fingerprint=excluded.fingerprint
|
||||
WHERE excluded.timestamp > whatsmeow_app_state_sync_keys.timestamp
|
||||
`
|
||||
getAppStateSyncKeyQuery = `SELECT key_data, timestamp, fingerprint FROM whatsmeow_app_state_sync_keys WHERE jid=$1 AND key_id=$2`
|
||||
)
|
||||
|
||||
@@ -142,6 +142,11 @@ const (
|
||||
ConnectFailureBadUserAgent ConnectFailureReason = 409
|
||||
|
||||
// 400, 500 and 501 are also existing codes, but the meaning is unknown
|
||||
|
||||
// 503 doesn't seem to be included in the web app JS with the other codes, and it's very rare,
|
||||
// but does happen after a 503 stream error sometimes.
|
||||
|
||||
ConnectFailureServiceUnavailable ConnectFailureReason = 503
|
||||
)
|
||||
|
||||
var connectFailureReasonMessage = map[ConnectFailureReason]string{
|
||||
|
||||
1
vendor/go.mau.fi/whatsmeow/types/jid.go
vendored
1
vendor/go.mau.fi/whatsmeow/types/jid.go
vendored
@@ -23,6 +23,7 @@ const (
|
||||
GroupServer = "g.us"
|
||||
LegacyUserServer = "c.us"
|
||||
BroadcastServer = "broadcast"
|
||||
HiddenUserServer = "lid"
|
||||
)
|
||||
|
||||
// Some JIDs that are contacted often.
|
||||
|
||||
46
vendor/go.mau.fi/whatsmeow/user.go
vendored
46
vendor/go.mau.fi/whatsmeow/user.go
vendored
@@ -286,6 +286,7 @@ func (cli *Client) GetProfilePictureInfo(jid types.JID, params *GetProfilePictur
|
||||
attrs := waBinary.Attrs{
|
||||
"query": "url",
|
||||
}
|
||||
var target, to types.JID
|
||||
if params == nil {
|
||||
params = &GetProfilePictureParams{}
|
||||
}
|
||||
@@ -297,27 +298,36 @@ func (cli *Client) GetProfilePictureInfo(jid types.JID, params *GetProfilePictur
|
||||
if params.ExistingID != "" {
|
||||
attrs["id"] = params.ExistingID
|
||||
}
|
||||
var pictureContent []waBinary.Node
|
||||
var expectWrapped bool
|
||||
var content []waBinary.Node
|
||||
namespace := "w:profile:picture"
|
||||
if params.IsCommunity {
|
||||
target = types.EmptyJID
|
||||
namespace = "w:g2"
|
||||
pictureContent = []waBinary.Node{{
|
||||
Tag: "query_linked",
|
||||
Attrs: waBinary.Attrs{
|
||||
"type": "parent_group",
|
||||
"jid": jid,
|
||||
},
|
||||
to = jid
|
||||
attrs["parent_group_jid"] = jid
|
||||
expectWrapped = true
|
||||
content = []waBinary.Node{{
|
||||
Tag: "pictures",
|
||||
Content: []waBinary.Node{{
|
||||
Tag: "picture",
|
||||
Attrs: attrs,
|
||||
}},
|
||||
}}
|
||||
} else {
|
||||
to = types.ServerJID
|
||||
target = jid
|
||||
content = []waBinary.Node{{
|
||||
Tag: "picture",
|
||||
Attrs: attrs,
|
||||
}}
|
||||
}
|
||||
resp, err := cli.sendIQ(infoQuery{
|
||||
Namespace: namespace,
|
||||
Type: "get",
|
||||
To: jid,
|
||||
Content: []waBinary.Node{{
|
||||
Tag: "picture",
|
||||
Attrs: attrs,
|
||||
Content: pictureContent,
|
||||
}},
|
||||
To: to,
|
||||
Target: target,
|
||||
Content: content,
|
||||
})
|
||||
if errors.Is(err, ErrIQNotAuthorized) {
|
||||
return nil, wrapIQError(ErrProfilePictureUnauthorized, err)
|
||||
@@ -326,6 +336,13 @@ func (cli *Client) GetProfilePictureInfo(jid types.JID, params *GetProfilePictur
|
||||
} else if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if expectWrapped {
|
||||
pics, ok := resp.GetOptionalChildByTag("pictures")
|
||||
if !ok {
|
||||
return nil, &ElementMissingError{Tag: "pictures", In: "response to profile picture query"}
|
||||
}
|
||||
resp = &pics
|
||||
}
|
||||
picture, ok := resp.GetOptionalChildByTag("picture")
|
||||
if !ok {
|
||||
if params.ExistingID != "" {
|
||||
@@ -335,6 +352,9 @@ func (cli *Client) GetProfilePictureInfo(jid types.JID, params *GetProfilePictur
|
||||
}
|
||||
var info types.ProfilePictureInfo
|
||||
ag := picture.AttrGetter()
|
||||
if ag.OptionalInt("status") == 304 {
|
||||
return nil, nil
|
||||
}
|
||||
info.ID = ag.String("id")
|
||||
info.URL = ag.String("url")
|
||||
info.Type = ag.String("type")
|
||||
|
||||
Reference in New Issue
Block a user