1use std::fmt;
10
11use grammers_tl_types as tl;
12
13#[repr(transparent)]
26#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
27pub struct PeerId(i64);
28
29#[repr(transparent)]
36#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
37pub struct PeerAuth(i64);
38
39#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
44pub struct PeerRef {
45 pub id: PeerId,
47 pub auth: PeerAuth,
49}
50
51#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
55pub enum PeerKind {
56 User,
58 UserSelf,
60 Chat,
62 Channel,
64}
65
66#[derive(Clone, Debug, PartialEq, Eq)]
68pub enum PeerInfo {
69 User {
70 id: i64,
74 auth: Option<PeerAuth>,
76 bot: Option<bool>,
78 is_self: Option<bool>,
80 },
81 Chat {
82 id: i64,
87 },
88 Channel {
89 id: i64,
94 auth: Option<PeerAuth>,
96 kind: Option<ChannelKind>,
98 },
99}
100
101#[derive(Clone, Copy, Debug, PartialEq, Eq)]
103pub enum ChannelKind {
104 Megagroup,
106 Broadcast,
108 Gigagroup,
110}
111
112const SELF_USER_ID: PeerId = PeerId(1 << 40);
119
120const EMPTY_CHAT_ID: i64 = -1000000000000;
132
133impl PeerId {
134 pub fn self_user() -> Self {
138 SELF_USER_ID
139 }
140
141 pub fn user(id: i64) -> Self {
143 if !(1 <= id && id <= 0xffffffffff) {
145 panic!("user ID out of range");
146 }
147
148 Self(id)
149 }
150
151 pub fn chat(id: i64) -> Self {
153 if !(1 <= id && id <= 999999999999) {
155 panic!("chat ID out of range");
156 }
157
158 Self(-id)
159 }
160
161 pub fn channel(id: i64) -> Self {
163 if !((1 <= id && id <= 997852516352) || (1002147483649 <= id && id <= 3000000000000)) {
165 panic!("channel ID out of range");
166 }
167
168 Self(-(1000000000000 + id))
169 }
170
171 pub fn kind(self) -> PeerKind {
173 if 1 <= self.0 && self.0 <= 0xffffffffff {
174 PeerKind::User
175 } else if self.0 == SELF_USER_ID.0 {
176 PeerKind::UserSelf
177 } else if -999999999999 <= self.0 && self.0 <= -1 {
178 PeerKind::Chat
179 } else if -1997852516352 <= self.0 && self.0 <= -1000000000001
180 || (-2002147483649 <= self.0 && self.0 <= -4000000000000)
181 {
182 PeerKind::Channel
183 } else {
184 unreachable!()
185 }
186 }
187
188 pub fn bot_api_dialog_id(&self) -> i64 {
193 self.0
194 }
195
196 pub fn bare_id(&self) -> i64 {
198 match self.kind() {
199 PeerKind::User => self.0,
200 PeerKind::UserSelf => panic!("self-user ID not known"),
201 PeerKind::Chat => -self.0,
202 PeerKind::Channel => -self.0 - 1000000000000,
203 }
204 }
205}
206
207impl PeerAuth {
208 pub fn from_hash(access_hash: i64) -> Self {
210 PeerAuth(access_hash)
211 }
212
213 pub fn hash(&self) -> i64 {
215 self.0
216 }
217}
218
219impl Default for PeerAuth {
220 fn default() -> Self {
225 Self(0)
226 }
227}
228
229impl PeerInfo {
230 pub fn id(&self) -> PeerId {
234 match self {
235 PeerInfo::User { id, .. } => PeerId::user(*id),
236 PeerInfo::Chat { id } => PeerId::chat(*id),
237 PeerInfo::Channel { id, .. } => PeerId::channel(*id),
238 }
239 }
240
241 pub fn auth(&self) -> PeerAuth {
243 match self {
244 PeerInfo::User { auth, .. } => auth.unwrap_or_default(),
245 PeerInfo::Chat { .. } => PeerAuth::default(),
246 PeerInfo::Channel { auth, .. } => auth.unwrap_or_default(),
247 }
248 }
249}
250
251impl fmt::Display for PeerId {
252 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
253 self.bot_api_dialog_id().fmt(f)
254 }
255}
256
257impl From<PeerInfo> for PeerRef {
258 fn from(peer: PeerInfo) -> Self {
259 PeerRef {
260 id: peer.id(),
261 auth: peer.auth(),
262 }
263 }
264}
265
266impl From<tl::enums::Peer> for PeerId {
267 fn from(peer: tl::enums::Peer) -> Self {
268 match peer {
269 tl::enums::Peer::User(user) => PeerId::from(user),
270 tl::enums::Peer::Chat(chat) => PeerId::from(chat),
271 tl::enums::Peer::Channel(channel) => PeerId::from(channel),
272 }
273 }
274}
275
276impl From<tl::types::PeerUser> for PeerId {
277 fn from(user: tl::types::PeerUser) -> Self {
278 PeerId::user(user.user_id)
279 }
280}
281
282impl From<tl::types::PeerChat> for PeerId {
283 fn from(chat: tl::types::PeerChat) -> Self {
284 PeerId::chat(chat.chat_id)
285 }
286}
287
288impl From<tl::types::PeerChannel> for PeerId {
289 fn from(channel: tl::types::PeerChannel) -> Self {
290 PeerId::channel(channel.channel_id)
291 }
292}
293
294impl From<tl::enums::InputPeer> for PeerRef {
295 fn from(peer: tl::enums::InputPeer) -> Self {
296 match peer {
297 tl::enums::InputPeer::Empty => {
298 panic!("InputPeer::Empty cannot be converted to any Peer");
299 }
300 tl::enums::InputPeer::PeerSelf => PeerRef {
301 id: SELF_USER_ID,
302 auth: PeerAuth::default(),
303 },
304 tl::enums::InputPeer::User(user) => PeerRef::from(user),
305 tl::enums::InputPeer::Chat(chat) => PeerRef::from(chat),
306 tl::enums::InputPeer::Channel(channel) => PeerRef::from(channel),
307 tl::enums::InputPeer::UserFromMessage(user) => PeerRef::from(*user),
308 tl::enums::InputPeer::ChannelFromMessage(channel) => PeerRef::from(*channel),
309 }
310 }
311}
312
313impl From<tl::types::InputPeerSelf> for PeerRef {
314 fn from(_: tl::types::InputPeerSelf) -> Self {
315 PeerRef {
316 id: SELF_USER_ID,
317 auth: PeerAuth::default(),
318 }
319 }
320}
321
322impl From<tl::types::InputPeerUser> for PeerRef {
323 fn from(user: tl::types::InputPeerUser) -> Self {
324 PeerRef {
325 id: PeerId::user(user.user_id),
326 auth: PeerAuth::from_hash(user.access_hash),
327 }
328 }
329}
330
331impl From<tl::types::InputPeerChat> for PeerRef {
332 fn from(chat: tl::types::InputPeerChat) -> Self {
333 PeerRef {
334 id: PeerId::chat(chat.chat_id),
335 auth: PeerAuth::default(),
336 }
337 }
338}
339
340impl From<tl::types::InputPeerChannel> for PeerRef {
341 fn from(channel: tl::types::InputPeerChannel) -> Self {
342 PeerRef {
343 id: PeerId::channel(channel.channel_id),
344 auth: PeerAuth::from_hash(channel.access_hash),
345 }
346 }
347}
348
349impl From<tl::types::InputPeerUserFromMessage> for PeerRef {
350 fn from(user: tl::types::InputPeerUserFromMessage) -> Self {
351 PeerRef {
353 id: PeerId::user(user.user_id),
354 auth: PeerAuth::default(),
355 }
356 }
357}
358
359impl From<tl::types::InputPeerChannelFromMessage> for PeerRef {
360 fn from(channel: tl::types::InputPeerChannelFromMessage) -> Self {
361 PeerRef {
363 id: PeerId::channel(channel.channel_id),
364 auth: PeerAuth::default(),
365 }
366 }
367}
368
369impl From<tl::enums::User> for PeerRef {
370 fn from(user: tl::enums::User) -> Self {
371 match user {
372 grammers_tl_types::enums::User::Empty(user) => PeerRef::from(user),
373 grammers_tl_types::enums::User::User(user) => PeerRef::from(user),
374 }
375 }
376}
377
378impl From<tl::types::UserEmpty> for PeerRef {
379 fn from(user: tl::types::UserEmpty) -> Self {
380 PeerRef {
381 id: PeerId::user(user.id),
382 auth: PeerAuth::default(),
383 }
384 }
385}
386
387impl From<tl::types::User> for PeerRef {
388 fn from(user: tl::types::User) -> Self {
389 PeerRef {
390 id: if user.is_self {
391 PeerId::self_user()
392 } else {
393 PeerId::user(user.id)
394 },
395 auth: user
396 .access_hash
397 .map(PeerAuth::from_hash)
398 .unwrap_or(PeerAuth::default()),
399 }
400 }
401}
402
403impl From<tl::enums::Chat> for PeerRef {
404 fn from(chat: tl::enums::Chat) -> Self {
405 match chat {
406 grammers_tl_types::enums::Chat::Empty(chat) => PeerRef::from(chat),
407 grammers_tl_types::enums::Chat::Chat(chat) => PeerRef::from(chat),
408 grammers_tl_types::enums::Chat::Forbidden(chat) => PeerRef::from(chat),
409 grammers_tl_types::enums::Chat::Channel(channel) => PeerRef::from(channel),
410 grammers_tl_types::enums::Chat::ChannelForbidden(channel) => PeerRef::from(channel),
411 }
412 }
413}
414
415impl From<tl::types::ChatEmpty> for PeerRef {
416 fn from(chat: tl::types::ChatEmpty) -> Self {
417 PeerRef {
418 id: PeerId::chat(chat.id),
419 auth: PeerAuth::default(),
420 }
421 }
422}
423
424impl From<tl::types::Chat> for PeerRef {
425 fn from(chat: tl::types::Chat) -> Self {
426 PeerRef {
427 id: PeerId::chat(chat.id),
428 auth: PeerAuth::default(),
429 }
430 }
431}
432
433impl From<tl::types::ChatForbidden> for PeerRef {
434 fn from(chat: tl::types::ChatForbidden) -> Self {
435 PeerRef {
436 id: PeerId::chat(chat.id),
437 auth: PeerAuth::default(),
438 }
439 }
440}
441
442impl From<tl::types::Channel> for PeerRef {
443 fn from(channel: tl::types::Channel) -> Self {
444 PeerRef {
445 id: PeerId::channel(channel.id),
446 auth: channel
447 .access_hash
448 .map(PeerAuth::from_hash)
449 .unwrap_or(PeerAuth::default()),
450 }
451 }
452}
453
454impl From<tl::types::ChannelForbidden> for PeerRef {
455 fn from(channel: tl::types::ChannelForbidden) -> Self {
456 PeerRef {
457 id: PeerId::channel(channel.id),
458 auth: PeerAuth::from_hash(channel.access_hash),
459 }
460 }
461}
462
463impl From<PeerId> for tl::enums::Peer {
464 fn from(peer: PeerId) -> Self {
465 match peer.kind() {
466 PeerKind::User => tl::enums::Peer::User(tl::types::PeerUser {
467 user_id: peer.bare_id(),
468 }),
469 PeerKind::UserSelf => panic!("self-user ID not known"),
470 PeerKind::Chat => tl::enums::Peer::Chat(tl::types::PeerChat {
471 chat_id: peer.bare_id(),
472 }),
473 PeerKind::Channel => tl::enums::Peer::Channel(tl::types::PeerChannel {
474 channel_id: peer.bare_id(),
475 }),
476 }
477 }
478}
479
480impl From<PeerRef> for tl::enums::InputPeer {
481 fn from(peer: PeerRef) -> Self {
482 match peer.id.kind() {
483 PeerKind::User => tl::enums::InputPeer::User(tl::types::InputPeerUser {
484 user_id: peer.id.bare_id(),
485 access_hash: peer.auth.hash(),
486 }),
487 PeerKind::UserSelf => tl::enums::InputPeer::PeerSelf,
488 PeerKind::Chat => tl::enums::InputPeer::Chat(tl::types::InputPeerChat {
489 chat_id: peer.id.bare_id(),
490 }),
491 PeerKind::Channel => tl::enums::InputPeer::Channel(tl::types::InputPeerChannel {
492 channel_id: peer.id.bare_id(),
493 access_hash: peer.auth.hash(),
494 }),
495 }
496 }
497}
498
499impl From<PeerRef> for tl::enums::InputUser {
500 fn from(peer: PeerRef) -> Self {
501 match peer.id.kind() {
502 PeerKind::User => tl::enums::InputUser::User(tl::types::InputUser {
503 user_id: peer.id.bare_id(),
504 access_hash: peer.auth.hash(),
505 }),
506 PeerKind::UserSelf => tl::enums::InputUser::UserSelf,
507 PeerKind::Chat => tl::enums::InputUser::Empty,
508 PeerKind::Channel => tl::enums::InputUser::Empty,
509 }
510 }
511}
512
513impl From<PeerRef> for i64 {
514 fn from(peer: PeerRef) -> Self {
515 match peer.id.kind() {
516 PeerKind::User => EMPTY_CHAT_ID,
517 PeerKind::UserSelf => EMPTY_CHAT_ID,
518 PeerKind::Chat => peer.id.bare_id(),
519 PeerKind::Channel => EMPTY_CHAT_ID,
520 }
521 }
522}
523
524impl From<PeerRef> for tl::enums::InputChannel {
525 fn from(peer: PeerRef) -> Self {
526 match peer.id.kind() {
527 PeerKind::User => tl::enums::InputChannel::Empty,
528 PeerKind::UserSelf => tl::enums::InputChannel::Empty,
529 PeerKind::Chat => tl::enums::InputChannel::Empty,
530 PeerKind::Channel => tl::enums::InputChannel::Channel(tl::types::InputChannel {
531 channel_id: peer.id.bare_id(),
532 access_hash: peer.auth.hash(),
533 }),
534 }
535 }
536}