9r3nXPaRTa

clubhouse/clubhouse.py is Leak for Metadata

Apr 12th, 2021
291
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 53.12 KB | None | 0 0
  1. #!/usr/bin/python -u
  2. #-*- coding: utf-8 -*-
  3. # pylint: disable=line-too-long,too-many-arguments,too-many-lines
  4. # pylint: disable=no-self-argument,not-callable
  5.  
  6. """
  7. clubhouse.py
  8.  
  9. Developed for education purposes only.
  10. Please make sure to know what you're trying to do!
  11. Sending an odd API request could result in a permanent ban on your account.
  12. """3:
  13.     """
  14.    Clubhouse Class
  15.  
  16.    Decorators:
  17.        @require_authentication:
  18.            - this means that the endpoint requires authentication to access.
  19.  
  20.        @unstable_endpoint
  21.            - This means that the endpoint is never tested.
  22.            - Likely to be endpoints that were taken from a static analysis
  23.    """
  24.  
  25.     # App/API Information
  26.     API_URL = "https://www.clubhouseapi.com/api"
  27.     API_BUILD_ID = "304"
  28.     API_BUILD_VERSION = "0.1.28"
  29.     API_UA = f"clubhouse/{API_BUILD_ID} (iPhone; iOS 14.4; Scale/2.00)"
  30.     API_UA_STATIC = f"Clubhouse/{API_BUILD_ID} CFNetwork/1220.1 Darwin/20.3.0"
  31.  
  32.     # Some useful information for commmunication
  33.     PUBNUB_PUB_KEY = "pub-c-6878d382-5ae6-4494-9099-f930f938868b"
  34.     PUBNUB_SUB_KEY = "sub-c-a4abea84-9ca3-11ea-8e71-f2b83ac9263d"
  35.  
  36.     TWITTER_ID = "NyJhARWVYU1X3qJZtC2154xSI"
  37.     TWITTER_SECRET = "ylFImLBFaOE362uwr4jut8S8gXGWh93S1TUKbkfh7jDIPse02o"
  38.  
  39.     INSTAGRAM_ID = "1352866981588597"
  40.     INSTAGRAM_CALLBACK = "https://www.joinclubhouse.com/callback/instagram"
  41.  
  42.     AGORA_KEY = "938de3e8055e42b281bb8c6f69c21f78"
  43.     SENTRY_KEY = "5374a416cd2d4009a781b49d1bd9ef44@o325556.ingest.sentry.io/5245095"
  44.     INSTABUG_KEY = "4e53155da9b00728caa5249f2e35d6b3"
  45.     AMPLITUDE_KEY = "9098a21a950e7cb0933fb5b30affe5be"
  46.  
  47.     # Useful header information
  48.     HEADERS = {
  49.         "CH-Languages": "en-JP,ja-JP",
  50.         "CH-Locale": "en_JP",
  51.         "Accept": "application/json",
  52.         "Accept-Language": "en-JP;q=1, ja-JP;q=0.9",
  53.         "Accept-Encoding": "gzip, deflate",
  54.         "CH-AppBuild": f"{API_BUILD_ID}",
  55.         "CH-AppVersion": f"{API_BUILD_VERSION}",
  56.         "User-Agent": f"{API_UA}",
  57.         "Connection": "close",
  58.         "Content-Type": "application/json; charset=utf-8",
  59.         "Cookie": f"__cfduid={secrets.token_hex(21)}{random.randint(1, 9)}"
  60.     }
  61.  
  62.     def require_authentication(func):
  63.         """ Simple decorator to check for the authentication """
  64.         @functools.wraps(func)
  65.         def wrap(self, *args, **kwargs):
  66.             if not (self.HEADERS.get("CH-UserID") and
  67.                     self.HEADERS.get("CH-DeviceId") and
  68.                     self.HEADERS.get("Authorization")):
  69.                 raise Exception('Not Authenticated')
  70.             return func(self, *args, **kwargs)
  71.         return wrap
  72.  
  73.     def unstable_endpoint(func):
  74.         """ Simple decorator to warn that this endpoint is never tested at all. """
  75.         @functools.wraps(func)
  76.         def wrap(self, *args, **kwargs):
  77.             print("[!] This endpoint is NEVER TESTED and MAY BE UNSTABLE. BE CAREFUL!")
  78.             return func(self, *args, **kwargs)
  79.         return wrap
  80.  
  81.     def __init__(self, user_id='', user_token='', user_device=''):
  82.         """ (Clubhouse, str, str, str) -> NoneType
  83.        Set authenticated information
  84.        """
  85.         self.HEADERS['CH-UserID'] = user_id if user_id else "(null)"
  86.         if user_token:
  87.             self.HEADERS['Authorization'] = f"Token {user_token}"
  88.         self.HEADERS['CH-DeviceId'] = user_device.upper() if user_device else str(uuid.uuid4()).upper()
  89.  
  90.     def __str__(self):
  91.         """ (Clubhouse) -> str
  92.        Get information about the given class.
  93.        >>> clubhouse = Clubhouse()
  94.        >>> str(clubhouse)
  95.        Clubhouse(user_id=(null), user_token=None, user_device=31525f52-6b67-40de-83c0-8f9fe0f6f409)
  96.        """
  97.         return "Clubhouse(user_Id={}, user_token={}, user_device={}".format(
  98.             self.HEADERS.get('CH-UserID'),
  99.             self.HEADERS.get('Authorization'),
  100.             self.HEADERS.get('CH-DeviceId')
  101.         )
  102.  
  103.     def start_phone_number_auth(self, phone_number):
  104.         """ (Clubhouse, str) -> dict
  105.  
  106.        Begin phone number authentication.
  107.        Some examples for the phone number.
  108.  
  109.        >>> clubhouse = Clubhouse()
  110.        >>> clubhouse.start_phone_number_auth("+821012341337")
  111.        ...
  112.        >>> clubhouse.start_phone_number_auth("+818013371221")
  113.        ...
  114.        """
  115.         if self.HEADERS.get("Authorization"):
  116.             raise Exception('Already Authenticatied')
  117.         data = {
  118.             "phone_number": phone_number
  119.         }
  120.         req = requests.post(f"{self.API_URL}/start_phone_number_auth", headers=self.HEADERS, json=data)
  121.         return req.json()
  122.  
  123.     @unstable_endpoint
  124.     def call_phone_number_auth(self, phone_number):
  125.         """ (Clubhouse, str) -> dict
  126.  
  127.        Call the person and send verification message.
  128.        """
  129.         if self.HEADERS.get("Authorization"):
  130.             raise Exception('Already Authenticatied')
  131.         data = {
  132.             "phone_number": phone_number
  133.         }
  134.         req = requests.post(f"{self.API_URL}/call_phone_number_auth", headers=self.HEADERS, json=data)
  135.         return req.json()
  136.  
  137.     @unstable_endpoint
  138.     def resend_phone_number_auth(self, phone_number):
  139.         """ (Clubhouse, str) -> dict
  140.  
  141.        Resend the verification message
  142.        """
  143.         if self.HEADERS.get("Authorization"):
  144.             raise Exception('Already Authenticatied')
  145.         data = {
  146.             "phone_number": phone_number
  147.         }
  148.         req = requests.post(f"{self.API_URL}/resend_phone_number_auth", headers=self.HEADERS, json=data)
  149.         return req.json()
  150.  
  151.     def complete_phone_number_auth(self, phone_number, verification_code):
  152.         """ (Clubhouse, str, str) -> dict
  153.  
  154.        Complete phone number authentication.
  155.        This should return `auth_token`, `access_token`, `refresh_token`, is_waitlisted, ...
  156.        Please note that output may be different depending on the status of the authenticated user
  157.        """
  158.         if self.HEADERS.get("Authorization"):
  159.             raise Exception('Already Authenticatied')
  160.         data = {
  161.             "phone_number": phone_number,
  162.             "verification_code": verification_code
  163.         }
  164.         req = requests.post(f"{self.API_URL}/complete_phone_number_auth", headers=self.HEADERS, json=data)
  165.         return req.json()
  166.  
  167.     def check_for_update(self, is_testflight=False):
  168.         """ (Clubhouse, bool) -> dict
  169.  
  170.        Check for app updates.
  171.  
  172.        >>> clubhouse = Clubhouse()
  173.        >>> clubhouse.check_for_update(False)
  174.        {'has_update': False, 'success': True}
  175.        """
  176.         query = f"is_testflight={int(is_testflight)}"
  177.         req = requests.get(f"{self.API_URL}/check_for_update?{query}", headers=self.HEADERS)
  178.         return req.json()
  179.  
  180.     @require_authentication
  181.     def get_release_notes(self):
  182.         """ (Clubhouse) -> dict
  183.  
  184.        Get release notes.
  185.        """
  186.         req = requests.post(f"{self.API_URL}/get_release_notes", headers=self.HEADERS)
  187.         return req.json()
  188.  
  189.     @require_authentication
  190.     def check_waitlist_status(self):
  191.         """ (Clubhouse) -> dict
  192.  
  193.        Check whether you're still on a waitlist or not.
  194.        """
  195.         req = requests.post(f"{self.API_URL}/check_waitlist_status", headers=self.HEADERS)
  196.         return req.json()
  197.  
  198.     @require_authentication
  199.     def add_email(self, email):
  200.         """ (Clubhouse, str) -> dict
  201.  
  202.        Request for email verification.
  203.        You only need to do this once.
  204.        """
  205.         data = {
  206.             "email": email
  207.         }
  208.         req = requests.post(f"{self.API_URL}/add_email", headers=self.HEADERS, json=data)
  209.         return req.json()
  210.  
  211.     @require_authentication
  212.     def update_photo(self, photo_filename):
  213.         """ (Clubhouse, str) -> dict
  214.  
  215.        Update photo. Please make sure to upload a JPG format.
  216.        """
  217.         files = {
  218.             "file": ("image.jpg", open(photo_filename, "rb"), "image/jpeg"),
  219.         }
  220.         tmp = self.HEADERS['Content-Type']
  221.         self.HEADERS.pop("Content-Type")
  222.         req = requests.post(f"{self.API_URL}/update_photo", headers=self.HEADERS, files=files)
  223.         self.HEADERS['Content-Type'] = tmp
  224.         return req.json()
  225.  
  226.     @require_authentication
  227.     def follow(self, user_id, user_ids=None, source=4, source_topic_id=None):
  228.         """ (Clubhouse, int, list, int, int) -> dict
  229.  
  230.        Follow a user.
  231.        Different value for `source` may require different parameters to be set
  232.        """
  233.         data = {
  234.             "source_topic_id": source_topic_id,
  235.             "user_ids": user_ids,
  236.             "user_id": int(user_id),
  237.             "source": source
  238.         }
  239.         req = requests.post(f"{self.API_URL}/follow", headers=self.HEADERS, json=data)
  240.         return req.json()
  241.  
  242.     @require_authentication
  243.     def unfollow(self, user_id):
  244.         """ (Clubhouse, int) -> dict
  245.  
  246.        Unfollow a user.
  247.        """
  248.         data = {
  249.             "user_id": int(user_id)
  250.         }
  251.         req = requests.post(f"{self.API_URL}/unfollow", headers=self.HEADERS, json=data)
  252.         return req.json()
  253.  
  254.     @require_authentication
  255.     def block(self, user_id):
  256.         """ (Clubhouse, int) -> dict
  257.  
  258.        Block a user.
  259.        """
  260.         data = {
  261.             "user_id": int(user_id)
  262.         }
  263.         req = requests.post(f"{self.API_URL}/block", headers=self.HEADERS, json=data)
  264.         return req.json()
  265.  
  266.     @require_authentication
  267.     def unblock(self, user_id):
  268.         """ (Clubhouse, int) -> dict
  269.  
  270.        Unfollow a user.
  271.        """
  272.         data = {
  273.             "user_id": int(user_id)
  274.         }
  275.         req = requests.post(f"{self.API_URL}/unblock", headers=self.HEADERS, json=data)
  276.         return req.json()
  277.  
  278.     @require_authentication
  279.     def follow_multiple(self, user_ids, user_id=None, source=7, source_topic_id=None):
  280.         """ (Clubhouse, list, int, int, int) -> dict
  281.  
  282.        Follow multiple users at once.
  283.        Different value for `source` may require different parameters to be set
  284.        """
  285.         data = {
  286.             "source_topic_id": source_topic_id,
  287.             "user_ids": user_ids,
  288.             "user_id": user_id,
  289.             "source": source
  290.         }
  291.         req = requests.post(f"{self.API_URL}/follow_multiple", headers=self.HEADERS, json=data)
  292.         return req.json()
  293.  
  294.     @require_authentication
  295.     def follow_club(self, club_id, source_topic_id=None):
  296.         """ (Clubhouse, int, int) -> dict
  297.  
  298.        Follow a club
  299.        """
  300.         data = {
  301.             "club_id": int(club_id),
  302.             "source_topic_id": source_topic_id
  303.         }
  304.         req = requests.post(f"{self.API_URL}/follow_club", headers=self.HEADERS, json=data)
  305.         return req.json()
  306.  
  307.     @require_authentication
  308.     def unfollow_club(self, club_id, source_topic_id=None):
  309.         """ (Clubhouse, int, int) -> dict
  310.  
  311.        Unfollow a club
  312.        """
  313.         data = {
  314.             "club_id": int(club_id),
  315.             "source_topic_id": source_topic_id
  316.         }
  317.         req = requests.post(f"{self.API_URL}/unfollow_club", headers=self.HEADERS, json=data)
  318.         return req.json()
  319.  
  320.     @require_authentication
  321.     def update_follow_notifications(self, user_id, notification_type=2):
  322.         """ (Clubhouse, str, int) -> dict
  323.  
  324.        Update notification frequency for the given user.
  325.        1 = Always notify, 2 = Sometimes, 3 = Never
  326.        """
  327.         data = {
  328.             "user_id": int(user_id),
  329.             "notification_type": int(notification_type)
  330.         }
  331.         req = requests.post(f"{self.API_URL}/update_follow_notifications", headers=self.HEADERS, json=data)
  332.         return req.json()
  333.  
  334.     @require_authentication
  335.     def get_suggested_follows_similar(self, user_id):
  336.         """ (Clubhouse, int) -> dict
  337.  
  338.        Get similar users based on the given user.
  339.        """
  340.         data = {
  341.             "user_id": int(user_id),
  342.         }
  343.         req = requests.post(f"{self.API_URL}/get_suggested_follows_similar", headers=self.HEADERS, json=data)
  344.         return req.json()
  345.  
  346.     @require_authentication
  347.     def get_suggested_follows_friends_only(self, club_id=None, upload_contacts=True, contacts=()):
  348.         """ (Clubhouse, int, int, list of dict) -> dict
  349.  
  350.        Get users based on the phone number.
  351.        Only seems to be used upon signup.
  352.        """
  353.         data = {
  354.             "club_id": club_id,
  355.             "upload_contacts": upload_contacts,
  356.             "contacts": contacts
  357.         }
  358.         req = requests.post(f"{self.API_URL}/get_suggested_follows_friends_only", headers=self.HEADERS, json=data)
  359.         return req.json()
  360.  
  361.     @require_authentication
  362.     def get_suggested_follows_all(self, in_onboarding=True, page_size=50, page=1):
  363.         """ (Clubhouse, bool, int, int) -> dict
  364.  
  365.        Get all suggested follows.
  366.        """
  367.         query = "in_onboarding={}&page_size={}&page={}".format(
  368.             "true" if in_onboarding else "false",
  369.             page_size,
  370.             page
  371.         )
  372.         req = requests.get(f"{self.API_URL}/get_suggested_follows_all?{query}", headers=self.HEADERS)
  373.         return req.json()
  374.  
  375.     @require_authentication
  376.     def ignore_suggested_follow(self, user_id):
  377.         """ (Clubhouse, str) -> dict
  378.  
  379.        Remove user_id from the suggested follow list.
  380.        """
  381.         data = {
  382.             "user_id": int(user_id)
  383.         }
  384.         req = requests.post(f"{self.API_URL}/user_id", headers=self.HEADERS, json=data)
  385.         return req.json()
  386.  
  387.     @require_authentication
  388.     def get_event(self, event_id=None, user_ids=None, club_id=None, is_member_only=False, event_hashid=None, description=None, time_start_epoch=None, name=None):
  389.         """ (Clubhouse, int, list, int, bool, int, str, int, str) -> dict
  390.  
  391.        Get details about the event
  392.        """
  393.         data = {
  394.             "user_ids": user_ids,
  395.             "club_id": club_id,
  396.             "is_member_only": is_member_only,
  397.             "event_id": int(event_id) if event_id else None,
  398.             "event_hashid": event_hashid,
  399.             "description": description,
  400.             "time_start_epoch": time_start_epoch,
  401.             "name": name
  402.         }
  403.         req = requests.post(f"{self.API_URL}/get_event", headers=self.HEADERS, json=data)
  404.         return req.json()
  405.  
  406.     @require_authentication
  407.     def create_event(self, name, time_start_epoch, description, event_id=None, user_ids=(), club_id=None, is_member_only=False, event_hashid=None):
  408.         """ (Clubhouse, str, int, str, int, list, int, bool, int) -> dict
  409.  
  410.        Create a new event
  411.        """
  412.         data = {
  413.             "user_ids": user_ids,
  414.             "club_id": club_id,
  415.             "is_member_only": is_member_only,
  416.             "event_id": int(event_id) if event_id else None,
  417.             "event_hashid": event_hashid,
  418.             "description": description,
  419.             "time_start_epoch": time_start_epoch,
  420.             "name": name
  421.         }
  422.         req = requests.post(f"{self.API_URL}/edit_event", headers=self.HEADERS, json=data)
  423.         return req.json()
  424.  
  425.     @require_authentication
  426.     def edit_event(self, name, time_start_epoch, description, event_id=None, user_ids=(), club_id=None, is_member_only=False, event_hashid=None):
  427.         """ (Clubhouse, str, int, str, int, list, int, bool, int) -> dict
  428.  
  429.        Edit an event.
  430.        """
  431.         data = {
  432.             "user_ids": user_ids,
  433.             "club_id": club_id,
  434.             "is_member_only": is_member_only,
  435.             "event_id": int(event_id) if event_id else None,
  436.             "event_hashid": event_hashid,
  437.             "description": description,
  438.             "time_start_epoch": time_start_epoch,
  439.             "name": name
  440.         }
  441.         req = requests.post(f"{self.API_URL}/edit_event", headers=self.HEADERS, json=data)
  442.         return req.json()
  443.  
  444.     @require_authentication
  445.     def delete_event(self, event_id, user_ids=None, club_id=None, is_member_only=False, event_hashid=None, description=None, time_start_epoch=None, name=None):
  446.         """ (Clubhouse, str, list, int, bool, int, str, int, str) -> dict
  447.  
  448.        Delete event.
  449.        """
  450.         data = {
  451.             "user_ids": user_ids,
  452.             "club_id": club_id,
  453.             "is_member_only": is_member_only,
  454.             "event_id": int(event_id) if event_id else None,
  455.             "event_hashid": event_hashid,
  456.             "description": description,
  457.             "time_start_epoch": time_start_epoch,
  458.             "name": name
  459.         }
  460.         req = requests.post(f"{self.API_URL}/delete_event", headers=self.HEADERS, json=data)
  461.         return req.json()
  462.  
  463.     @require_authentication
  464.     def get_events(self, is_filtered=True, page_size=25, page=1):
  465.         """ (Clubhouse, bool, int, int) -> dict
  466.  
  467.        Get list of upcoming events with details.
  468.        """
  469.         _is_filtered = "true" if is_filtered else "false"
  470.         query = "is_filtered={}&page_size={}&page={}".format(
  471.             "true" if is_filtered else "false",
  472.             page_size,
  473.             page
  474.         )
  475.         req = requests.get(f"{self.API_URL}/get_events?{query}", headers=self.HEADERS)
  476.         return req.json()
  477.  
  478.     @require_authentication
  479.     def get_club(self, club_id, source_topic_id=None):
  480.         """ (Clubhouse, int, int) -> dict
  481.  
  482.        Get the information about the given club_id.
  483.        """
  484.         data = {
  485.             "club_id": int(club_id),
  486.             "source_topic_id": source_topic_id
  487.         }
  488.         req = requests.post(f"{self.API_URL}/get_club", headers=self.HEADERS, json=data)
  489.         return req.json()
  490.  
  491.     @require_authentication
  492.     def get_club_members(self, club_id, return_followers=False, return_members=True, page_size=50, page=1):
  493.         """ (Clubhouse, int, bool, bool, int, int) -> dict
  494.  
  495.        Get list of members on the given club_id.
  496.        """
  497.         query = "club_id={}&return_followers={}&return_members={}&page_size={}&page={}".format(
  498.             club_id,
  499.             int(return_followers),
  500.             int(return_members),
  501.             page_size,
  502.             page
  503.         )
  504.         req = requests.get(f"{self.API_URL}/get_club_members?{query}", headers=self.HEADERS)
  505.         return req.json()
  506.  
  507.     @require_authentication
  508.     def get_settings(self):
  509.         """ (Clubhouse) -> dict
  510.  
  511.        Receive user's settings.
  512.        """
  513.         req = requests.get(f"{self.API_URL}/get_settings", headers=self.HEADERS)
  514.         return req.json()
  515.  
  516.     @require_authentication
  517.     def get_welcome_channel(self):
  518.         """ (Clubhouse) -> dict
  519.  
  520.        Seems to be called upon sign up. Does not seem to return much data.
  521.        """
  522.         req = requests.get(f"{self.API_URL}/get_welcome_channel", headers=self.HEADERS)
  523.         return req.json()
  524.  
  525.     @require_authentication
  526.     def hide_channel(self, channel, hide=True):
  527.         """ (Clubhouse, str, bool) -> dict
  528.  
  529.        Hide/unhide the channel from the channel list.
  530.        """
  531.         # Join channel
  532.         data = {
  533.             "channel": channel,
  534.             "hide": hide
  535.         }
  536.         req = requests.post(f"{self.API_URL}/hide_channel", headers=self.HEADERS, json=data)
  537.         return req.json()
  538.  
  539.     @require_authentication
  540.     def join_channel(self, channel, attribution_source="feed", attribution_details="eyJpc19leHBsb3JlIjpmYWxzZSwicmFuayI6MX0="):
  541.         """ (Clubhouse, str, str) -> dict
  542.  
  543.        Join the given channel
  544.        """
  545.         data = {
  546.             "channel": channel,
  547.             "attribution_source": attribution_source,
  548.             "attribution_details": attribution_details, # base64_json
  549.         }
  550.         req = requests.post(f"{self.API_URL}/join_channel", headers=self.HEADERS, json=data)
  551.         return req.json()
  552.  
  553.     @require_authentication
  554.     def leave_channel(self, channel):
  555.         """ (Clubhouse, str) -> dict
  556.  
  557.        Leave the given channel
  558.        """
  559.         data = {
  560.             "channel": channel,
  561.             "channel_id": None
  562.         }
  563.         req = requests.post(f"{self.API_URL}/leave_channel", headers=self.HEADERS, json=data)
  564.         return req.json()
  565.  
  566.     @require_authentication
  567.     def make_channel_public(self, channel, channel_id=None):
  568.         """ (Clubhouse, str, int) -> dict
  569.  
  570.        Make the current channel open to public.
  571.        Everyone can join the channel.
  572.        """
  573.         data = {
  574.             "channel": channel,
  575.             "channel_id": channel_id
  576.         }
  577.         req = requests.post(f"{self.API_URL}/make_channel_public", headers=self.HEADERS, json=data)
  578.         return req.json()
  579.  
  580.     @require_authentication
  581.     def make_channel_social(self, channel, channel_id=None):
  582.         """ (Clubhouse, str, int) -> dict
  583.  
  584.        Make the current channel open to public.
  585.        Only people who user follows can join the channel.
  586.        """
  587.         data = {
  588.             "channel": channel,
  589.             "channel_id": channel_id
  590.         }
  591.         req = requests.post(f"{self.API_URL}/make_channel_social", headers=self.HEADERS, json=data)
  592.         return req.json()
  593.  
  594.     @require_authentication
  595.     def end_channel(self, channel, channel_id=None):
  596.         """ (Clubhouse, str, int) -> dict
  597.  
  598.        Kick everyone and close the channel. Requires moderator privilege.
  599.        """
  600.         data = {
  601.             "channel": channel,
  602.             "channel_id": channel_id
  603.         }
  604.         req = requests.post(f"{self.API_URL}/end_channel", headers=self.HEADERS, json=data)
  605.         return req.json()
  606.  
  607.     @require_authentication
  608.     def make_moderator(self, channel, user_id):
  609.         """ (Clubhouse, str, int) -> dict
  610.  
  611.        Make the given user moderator. Requires moderator privilege.
  612.        """
  613.         data = {
  614.             "channel": channel,
  615.             "user_id": int(user_id)
  616.         }
  617.         req = requests.post(f"{self.API_URL}/make_moderator", headers=self.HEADERS, json=data)
  618.         return req.json()
  619.  
  620.     @require_authentication
  621.     def block_from_channel(self, channel, user_id):
  622.         """ (Clubhouse, str, int) -> dict
  623.  
  624.        Remove the user from the channel. The user will not be able to re-join.
  625.        """
  626.         data = {
  627.             "channel": channel,
  628.             "user_id": int(user_id)
  629.         }
  630.         req = requests.post(f"{self.API_URL}/block_from_channel", headers=self.HEADERS, json=data)
  631.         return req.json()
  632.  
  633.     @require_authentication
  634.     def get_profile(self, user_id):
  635.         """ (Clubhouse, str) -> dict
  636.  
  637.        Lookup someone else's profile. It is OK to one's own profile with this method.
  638.        """
  639.         data = {
  640.             "user_id": int(user_id)
  641.         }
  642.         req = requests.post(f"{self.API_URL}/get_profile", headers=self.HEADERS, json=data)
  643.         return req.json()
  644.  
  645.     @require_authentication
  646.     def me(self, return_blocked_ids=False, timezone_identifier="Asia/Tokyo", return_following_ids=False):
  647.         """ (Clubhouse, bool, str, bool) -> dict
  648.  
  649.        Get my information
  650.        """
  651.         data = {
  652.             "return_blocked_ids": return_blocked_ids,
  653.             "timezone_identifier": timezone_identifier,
  654.             "return_following_ids": return_following_ids
  655.         }
  656.         req = requests.post(f"{self.API_URL}/me", headers=self.HEADERS, json=data)
  657.         return req.json()
  658.  
  659.     @require_authentication
  660.     def get_following(self, user_id, page_size=50, page=1):
  661.         """ (Clubhouse, str, int, int) -> dict
  662.  
  663.        Get following users type2
  664.        """
  665.         query = "user_id={}&page_size={}&page={}".format(
  666.             user_id,
  667.             page_size,
  668.             page
  669.         )
  670.         req = requests.get(f"{self.API_URL}/get_following?{query}", headers=self.HEADERS)
  671.         return req.json()
  672.  
  673.     @require_authentication
  674.     def get_followers(self, user_id, page_size=50, page=1):
  675.         """ (Clubhouse, str, int, int) -> dict
  676.  
  677.        Get followers of the given user_id.
  678.        """
  679.         query = "user_id={}&page_size={}&page={}".format(
  680.             user_id,
  681.             page_size,
  682.             page
  683.         )
  684.         req = requests.get(f"{self.API_URL}/get_followers?{query}", headers=self.HEADERS)
  685.         return req.json()
  686.  
  687.     @require_authentication
  688.     def get_mutual_follows(self, user_id, page_size=50, page=1):
  689.         """ (Clubhouse, str, int, int) -> dict
  690.  
  691.        Get mutual followers between the current user and the given user_id.
  692.        """
  693.         query = "user_id={}&page_size={}&page={}".format(
  694.             user_id,
  695.             page_size,
  696.             page
  697.         )
  698.         req = requests.get(f"{self.API_URL}/get_mutual_follows?{query}", headers=self.HEADERS)
  699.         return req.json()
  700.  
  701.     @require_authentication
  702.     def get_all_topics(self):
  703.         """ (Clubhouse) -> dict
  704.  
  705.        Get list of topics, based on the server's channel selection algorithm
  706.        """
  707.         req = requests.get(f"{self.API_URL}/get_all_topics", headers=self.HEADERS)
  708.         return req.json()
  709.  
  710.     @require_authentication
  711.     def get_channels(self):
  712.         """ (Clubhouse) -> dict
  713.  
  714.        Get list of channels, based on the server's channel selection algorithm
  715.        """
  716.         req = requests.get(f"{self.API_URL}/get_channels", headers=self.HEADERS)
  717.         return req.json()
  718.  
  719.     @require_authentication
  720.     def get_channel(self, channel, channel_id=None):
  721.         """ (Clubhouse, str, int) -> dict
  722.  
  723.        Get information of the given channel
  724.        """
  725.         data = {
  726.             "channel": channel,
  727.             "channel_id": channel_id
  728.         }
  729.         req = requests.post(f"{self.API_URL}/get_channel", headers=self.HEADERS, json=data)
  730.         return req.json()
  731.  
  732.     @require_authentication
  733.     def active_ping(self, channel):
  734.         """ (Clubhouse, str) -> dict
  735.  
  736.        Keeping the user active while being in a chatroom
  737.        """
  738.         data = {
  739.             "channel": channel,
  740.             "chanel_id": None
  741.         }
  742.         req = requests.post(f"{self.API_URL}/active_ping", headers=self.HEADERS, json=data)
  743.         return req.json()
  744.  
  745.     @require_authentication
  746.     def audience_reply(self, channel, raise_hands=True, unraise_hands=False):
  747.         """ (Clubhouse, str, bool, bool) -> bool
  748.  
  749.        Request for raise_hands.
  750.        """
  751.         data = {
  752.             "channel": channel,
  753.             "raise_hands": raise_hands,
  754.             "unraise_hands": unraise_hands
  755.         }
  756.         req = requests.post(f"{self.API_URL}/audience_reply", headers=self.HEADERS, json=data)
  757.         return req.json()
  758.  
  759.     @require_authentication
  760.     def change_handraise_settings(self, channel, is_enabled=True, handraise_permission=1):
  761.         """ (Clubhouse, bool, int) -> dict
  762.  
  763.        Change handraise settings. Requires moderator privilege
  764.  
  765.        * handraise_permission(int)
  766.           - 1: Everyone
  767.           - 2: Followed by the speakers
  768.        * is_enabled(bool)
  769.           - True: Enable handraise
  770.           - False: Disable handraise
  771.        """
  772.         handraise_permission = int(handraise_permission)
  773.         if not 1 <= handraise_permission <= 2:
  774.             return False
  775.  
  776.         data = {
  777.             "channel": channel,
  778.             "is_enabled": is_enabled,
  779.             "handraise_permission": handraise_permission
  780.         }
  781.         req = requests.post(f"{self.API_URL}/change_handraise_settings", headers=self.HEADERS, json=data)
  782.         return req.json()
  783.  
  784.     @require_authentication
  785.     def update_skintone(self, skintone=1):
  786.         """ (Clubhouse, int) -> dict
  787.        Updating skinetone for raising hands, etc.
  788.        """
  789.         skintone = int(skintone)
  790.         if not 1 <= skintone <= 5:
  791.             return False
  792.  
  793.         data = {
  794.             "skintone": skintone
  795.         }
  796.         req = requests.post(f"{self.API_URL}/update_skintone", headers=self.HEADERS, json=data)
  797.         return req.json()
  798.  
  799.     @require_authentication
  800.     def get_notifications(self, page_size=20, page=1):
  801.         """ (Clubhouse, int, int) -> dict
  802.  
  803.        Get my notifications.
  804.        """
  805.         query = f"page_size={page_size}&page={page}"
  806.         req = requests.get(f"{self.API_URL}/get_notifications?{query}", headers=self.HEADERS)
  807.         return req.json()
  808.  
  809.     @require_authentication
  810.     def get_actionable_notifications(self):
  811.         """ (Clubhouse, int, int) -> dict
  812.  
  813.        Get notifications. This may return some notifications that require some actions
  814.        """
  815.         req = requests.get(f"{self.API_URL}/get_actionable_notifications", headers=self.HEADERS)
  816.         return req.json()
  817.  
  818.     @require_authentication
  819.     def get_online_friends(self):
  820.         """ (Clubhouse) -> dict
  821.  
  822.        List all online friends.
  823.        """
  824.         req = requests.post(f"{self.API_URL}/get_online_friends", headers=self.HEADERS, json={})
  825.         return req.json()
  826.  
  827.     @require_authentication
  828.     def accept_speaker_invite(self, channel, user_id):
  829.         """ (Clubhouse, str, int) -> dict
  830.  
  831.        Accept speaker's invitation, based on the (channel, invited_moderator)
  832.        `raise_hands` needs to be called first, prior to the invitation.
  833.        """
  834.         data = {
  835.             "channel": channel,
  836.             "user_id": int(user_id)
  837.         }
  838.         req = requests.post(f"{self.API_URL}/accept_speaker_invite", headers=self.HEADERS, json=data)
  839.         return req.json()
  840.  
  841.     @require_authentication
  842.     def reject_speaker_invite(self, channel, user_id):
  843.         """ (Clubhouse, str, int) -> dict
  844.  
  845.        Reject speaker's invitation.
  846.        """
  847.         data = {
  848.             "channel": channel,
  849.             "user_id": int(user_id)
  850.         }
  851.         req = requests.post(f"{self.API_URL}/reject_speaker_invite", headers=self.HEADERS, json=data)
  852.         return req.json()
  853.  
  854.     @require_authentication
  855.     def invite_speaker(self, channel, user_id):
  856.         """ (Clubhouse, str, int) -> dict
  857.  
  858.        Move audience to speaker. Requires moderator privilege.
  859.        """
  860.         data = {
  861.             "channel": channel,
  862.             "user_id": int(user_id)
  863.         }
  864.         req = requests.post(f"{self.API_URL}/invite_speaker", headers=self.HEADERS, json=data)
  865.         return req.json()
  866.  
  867.     @require_authentication
  868.     def uninvite_speaker(self, channel, user_id):
  869.         """ (Clubhouse, str, int) -> dict
  870.  
  871.        Move speaker to audience. Requires moderator privilege.
  872.        """
  873.         data = {
  874.             "channel": channel,
  875.             "user_id": int(user_id)
  876.         }
  877.         req = requests.post(f"{self.API_URL}/uninvite_speaker", headers=self.HEADERS, json=data)
  878.         return req.json()
  879.  
  880.     @require_authentication
  881.     def mute_speaker(self, channel, user_id):
  882.         """ (Clubhouse, str, int) -> dict
  883.  
  884.        Mute speaker. Requires moderator privilege
  885.        """
  886.         data = {
  887.             "channel": channel,
  888.             "user_id": int(user_id)
  889.         }
  890.         req = requests.post(f"{self.API_URL}/mute_speaker", headers=self.HEADERS, json=data)
  891.         return req.json()
  892.  
  893.     @require_authentication
  894.     def get_suggested_speakers(self, channel):
  895.         """ (Clubhouse, str) -> dict
  896.  
  897.        Get suggested speakers from the given channel
  898.        """
  899.         data = {
  900.             "channel": channel
  901.         }
  902.         req = requests.post(f"{self.API_URL}/get_suggested_speakers", headers=self.HEADERS, json=data)
  903.         return req.json()
  904.  
  905.     @require_authentication
  906.     def create_channel(self, topic="", user_ids=(), is_private=False, is_social_mode=False):
  907.         """ (Clubhouse, str, list, bool, bool) -> dict
  908.  
  909.        Create a new channel. Type of the room can be changed
  910.        """
  911.         data = {
  912.             "is_social_mode": is_social_mode,
  913.             "is_private": is_private,
  914.             "club_id": None,
  915.             "user_ids": user_ids,
  916.             "event_id": None,
  917.             "topic": topic
  918.         }
  919.         req = requests.post(f"{self.API_URL}/create_channel", headers=self.HEADERS, json=data)
  920.         return req.json()
  921.  
  922.     @require_authentication
  923.     def get_create_channel_targets(self):
  924.         """ (Clubhouse) -> dict
  925.  
  926.        Not sure what this does. Triggered upon channel creation
  927.        """
  928.         data = {}
  929.         req = requests.post(f"{self.API_URL}/get_create_channel_targets", headers=self.HEADERS, json=data)
  930.         return req.json()
  931.  
  932.     @require_authentication
  933.     def get_suggested_invites(self, club_id=None, upload_contacts=True, contacts=()):
  934.         """ (Clubhouse, int, bool, list of dict) -> dict
  935.  
  936.        Get invitations and user lists based on phone number.
  937.  
  938.        contacts(dict)
  939.            - example: [{"name": "Test Name", "phone_number": "+821043219876"}, ...]
  940.        """
  941.         data = {
  942.             "club_id": club_id,
  943.             "upload_contacts": upload_contacts,
  944.             "contacts": contacts
  945.         }
  946.         req = requests.post(f"{self.API_URL}/get_suggested_invites", headers=self.HEADERS, json=data)
  947.         return req.json()
  948.  
  949.     @require_authentication
  950.     def get_suggested_club_invites(self, upload_contacts=True, contacts=()):
  951.         """ (Clubhouse, int, bool, list of dict) -> dict
  952.  
  953.        Get user lists based on phone number. For inviting clubs.
  954.  
  955.        contacts(dict)
  956.            - example: [{"name": "Test Name", "phone_number": "+821043219876"}, ...]
  957.        """
  958.         data = {
  959.             "upload_contacts": upload_contacts,
  960.             "contacts": contacts
  961.         }
  962.         req = requests.post(f"{self.API_URL}/get_suggested_club_invites", headers=self.HEADERS, json=data)
  963.         return req.json()
  964.  
  965.     @require_authentication
  966.     def invite_to_app(self, name, phone_number, message=None):
  967.         """ (Clubhouse, str, str, str) -> dict
  968.  
  969.        Invite users to app. but this only works when you have a leftover invitation.
  970.        """
  971.         data = {
  972.             "name": name,
  973.             "phone_number": phone_number,
  974.             "message": message
  975.         }
  976.         req = requests.post(f"{self.API_URL}/invite_to_app", headers=self.HEADERS, json=data)
  977.         return req.json()
  978.  
  979.     @require_authentication
  980.     def invite_from_waitlist(self, user_id):
  981.         """ (Clubhouse, str, str, str) -> dict
  982.  
  983.        Invite someone from the waitlist.
  984.        This is much more reliable than inviting someone by invite_to_app
  985.        """
  986.         data = {
  987.             "user_id": int(user_id),
  988.         }
  989.         req = requests.post(f"{self.API_URL}/invite_from_waitlist", headers=self.HEADERS, json=data)
  990.         return req.json()
  991.  
  992.     @require_authentication
  993.     def search_users(self, query, followers_only=False, following_only=False, cofollows_only=False):
  994.         """ (Clubhouse, str, bool, bool, bool) -> dict
  995.  
  996.        Search users based on the given query.
  997.        """
  998.         data = {
  999.             "cofollows_only": cofollows_only,
  1000.             "following_only": following_only,
  1001.             "followers_only": followers_only,
  1002.             "query": query
  1003.         }
  1004.         req = requests.post(f"{self.API_URL}/search_users", headers=self.HEADERS, json=data)
  1005.         return req.json()
  1006.  
  1007.     @require_authentication
  1008.     def search_clubs(self, query, followers_only=False, following_only=False, cofollows_only=False):
  1009.         """ (Clubhouse, str, bool, bool, bool) -> dict
  1010.  
  1011.        Search clubs based on the given query.
  1012.        """
  1013.         data = {
  1014.             "cofollows_only": cofollows_only,
  1015.             "following_only": following_only,
  1016.             "followers_only": followers_only,
  1017.             "query": query
  1018.         }
  1019.         req = requests.post(f"{self.API_URL}/search_clubs", headers=self.HEADERS, json=data)
  1020.         return req.json()
  1021.  
  1022.     @require_authentication
  1023.     def get_topic(self, topic_id):
  1024.         """ (Clubhouse, int) -> dict
  1025.  
  1026.        Get topic's information based on the given topic id.
  1027.        """
  1028.         data = {
  1029.             "topic_id": int(topic_id)
  1030.         }
  1031.         req = requests.post(f"{self.API_URL}/get_topic", headers=self.HEADERS, json=data)
  1032.         return req.json()
  1033.  
  1034.     @require_authentication
  1035.     def get_clubs_for_topic(self, topic_id, page_size=25, page=1):
  1036.         """ (Clubhouse, int, int, int) -> dict
  1037.  
  1038.        Get list of clubs based on the given topic id.
  1039.        """
  1040.         query = "topic_id={}&page_size={}&page={}".format(
  1041.             topic_id,
  1042.             page_size,
  1043.             page
  1044.         )
  1045.         req = requests.get(f"{self.API_URL}/get_clubs_for_topic?{query}", headers=self.HEADERS)
  1046.         return req.json()
  1047.  
  1048.     @require_authentication
  1049.     def get_clubs(self, is_startable_only):
  1050.         """ (Clubhouse, bool) -> dict
  1051.  
  1052.        Get list of clubs the user's in.
  1053.        """
  1054.         data = {
  1055.             "is_startable_only": is_startable_only
  1056.         }
  1057.         req = requests.post(f"{self.API_URL}/get_clubs", headers=self.HEADERS, json=data)
  1058.         return req.json()
  1059.  
  1060.     @require_authentication
  1061.     def get_users_for_topic(self, topic_id, page_size=25, page=1):
  1062.         """ (Clubhouse, int, int, int) -> dict
  1063.  
  1064.        Get list of users based on the given topic id.
  1065.        """
  1066.         query = "topic_id={}&page_size={}&page={}".format(
  1067.             topic_id,
  1068.             page_size,
  1069.             page
  1070.         )
  1071.         req = requests.get(f"{self.API_URL}/get_users_for_topic?{query}", headers=self.HEADERS)
  1072.         return req.json()
  1073.  
  1074.     @require_authentication
  1075.     def invite_to_existing_channel(self, channel, user_id):
  1076.         """ (Clubhouse, str, int) -> dict
  1077.  
  1078.        Invite someone to a currently joined channel.
  1079.        It will send a ping notification to the given user_id.
  1080.        """
  1081.         data = {
  1082.             "channel": channel,
  1083.             "user_id": int(user_id)
  1084.         }
  1085.         req = requests.post(f"{self.API_URL}/invite_to_existing_channel", headers=self.HEADERS, json=data)
  1086.         return req.json()
  1087.  
  1088.     @require_authentication
  1089.     def update_username(self, username):
  1090.         """ (Clubhouse, str) -> dict
  1091.  
  1092.        Change username. YOU HAVE LIMITED NUMBER OF TRIALS TO CHANGE YOUR USERNAME.
  1093.        """
  1094.         data = {
  1095.             "username": username,
  1096.         }
  1097.         req = requests.post(f"{self.API_URL}/update_username", headers=self.HEADERS, json=data)
  1098.         return req.json()
  1099.  
  1100.     @require_authentication
  1101.     def update_name(self, name):
  1102.         """ (Clubhouse, str) -> dict
  1103.  
  1104.        Change your legal name. Be careful of what you're trying to enter.
  1105.            (1) Upon registration
  1106.            (2) Changing your legal name. YOU CAN ONLY DO THIS ONCE.
  1107.        """
  1108.         data = {
  1109.             "name": name,
  1110.         }
  1111.         req = requests.post(f"{self.API_URL}/update_name", headers=self.HEADERS, json=data)
  1112.         return req.json()
  1113.  
  1114.     @unstable_endpoint
  1115.     @require_authentication
  1116.     def update_twitter_username(self, username, twitter_token, twitter_secret):
  1117.         """ (Clubhouse, str, str, str) -> dict
  1118.  
  1119.        Change Twitter username based on Twitter Token.
  1120.  
  1121.        >>> client.update_twitter_username(None, None, None) # Clear username
  1122.        >>> client.update_twitter_username("stereotype32", "...", "...") # Set username
  1123.        """
  1124.         data = {
  1125.             "username": username,
  1126.             "twitter_token": twitter_token,
  1127.             "twitter_secret": twitter_secret
  1128.         }
  1129.         req = requests.post(f"{self.API_URL}/update_twitter_username", headers=self.HEADERS, json=data)
  1130.         return req.json()
  1131.  
  1132.     @unstable_endpoint
  1133.     @require_authentication
  1134.     def update_instagram_username(self, code):
  1135.         """ (Clubhouse, str) -> dict
  1136.  
  1137.        Change Twitter username based on Instagram token.
  1138.  
  1139.        >>> client.update_instagram_username(None) # Clear username
  1140.        >>> client.update_instagram_username("...") # Set username
  1141.        """
  1142.         data = {
  1143.             "code": code
  1144.         }
  1145.         req = requests.post(f"{self.API_URL}/update_instagram_username", headers=self.HEADERS, json=data)
  1146.         return req.json()
  1147.  
  1148.     @require_authentication
  1149.     def update_displayname(self, name):
  1150.         """ (Clubhouse, str) -> dict
  1151.  
  1152.        Change your nickname. YOU CAN ONLY DO THIS ONCE.
  1153.        """
  1154.         data = {
  1155.             "name": name,
  1156.         }
  1157.         req = requests.post(f"{self.API_URL}/update_name", headers=self.HEADERS, json=data)
  1158.         return req.json()
  1159.  
  1160.     @require_authentication
  1161.     def refresh_token(self, refresh_token):
  1162.         """ (Clubhouse, str) -> dict
  1163.  
  1164.        Refresh the JWT token. returns both access and refresh token.
  1165.        """
  1166.         data = {
  1167.             "refresh": refresh_token
  1168.         }
  1169.         req = requests.post(f"{self.API_URL}/refresh_token", headers=self.HEADERS, json=data)
  1170.         return req.json()
  1171.  
  1172.     @require_authentication
  1173.     def update_bio(self, bio):
  1174.         """ (Clubhouse, str) -> dict
  1175.  
  1176.        Update bio on your profile
  1177.        """
  1178.         data = {
  1179.             "bio": bio
  1180.         }
  1181.         req = requests.post(f"{self.API_URL}/update_bio", headers=self.HEADERS, json=data)
  1182.         return req.json()
  1183.  
  1184.     @require_authentication
  1185.     def record_action_trails(self, action_trails=()):
  1186.         """ (Clubhouse, list of dict) -> dict
  1187.  
  1188.        Recording actions of the user interactions while using the app.
  1189.        action_trails: [{"blob_data":{}, "trail_type": "...", ...}, ...]
  1190.        """
  1191.         data = {
  1192.             "action_trails": action_trails
  1193.         }
  1194.         req = requests.post(f"{self.API_URL}/update_bio", headers=self.HEADERS, json=data)
  1195.         return req.json()
  1196.  
  1197.     @require_authentication
  1198.     def add_user_topic(self, club_id=None, topic_id=None):
  1199.         """ (Clubhouse, int, int) -> dict
  1200.  
  1201.        Add user's interest.
  1202.  
  1203.        Some interesting flags for Language has been shared in the following link.
  1204.        Reference: https://github.com/grishka/Houseclub/issues/24
  1205.        """
  1206.         data = {
  1207.             "club_id": int(club_id) if club_id else None,
  1208.             "topic_id": int(topic_id) if topic_id else None
  1209.         }
  1210.         req = requests.post(f"{self.API_URL}/add_user_topic", headers=self.HEADERS, json=data)
  1211.         return req.json()
  1212.  
  1213.     @require_authentication
  1214.     def remove_user_topic(self, club_id, topic_id):
  1215.         """ (Clubhouse, int, int) -> dict
  1216.  
  1217.        Remove user's interest
  1218.        """
  1219.         data = {
  1220.             "club_id": int(club_id) if club_id else None,
  1221.             "topic_id": int(topic_id) if topic_id else None
  1222.         }
  1223.         req = requests.post(f"{self.API_URL}/remove_user_topic", headers=self.HEADERS, json=data)
  1224.         return req.json()
  1225.  
  1226.     @unstable_endpoint
  1227.     @require_authentication
  1228.     def report_incident(self, user_id, channel, incident_type, incident_description, email):
  1229.         """ (Clubhouse, int, str, unknown, str, str) -> dict
  1230.  
  1231.        Report incident
  1232.        There seemed to be a field for attachment, need to trace this later
  1233.        """
  1234.         data = {
  1235.             "user_id": int(user_id),
  1236.             "channel": channel,
  1237.             "incident_type": incident_type,
  1238.             "incident_description": incident_description,
  1239.             "email": email
  1240.         }
  1241.         req = requests.post(f"{self.API_URL}/report_incident", headers=self.HEADERS, json=data)
  1242.         return req.json()
  1243.  
  1244.     @unstable_endpoint
  1245.     @require_authentication
  1246.     def reject_welcome_channel(self):
  1247.         """ (Clubhouse) -> dict
  1248.  
  1249.        Unknown
  1250.        """
  1251.         req = requests.get(f"{self.API_URL}/reject_welcome_channel", headers=self.HEADERS)
  1252.         return req.json()
  1253.  
  1254.     @unstable_endpoint
  1255.     @require_authentication
  1256.     def update_channel_flags(self, channel, visibility, flag_title, unflag_title):
  1257.         """ (Clubhouse, str, bool, unknown, unknown) -> dict
  1258.  
  1259.        Unknown
  1260.        """
  1261.         data = {
  1262.             "channel": channel,
  1263.             "visibility": visibility,
  1264.             "flag_title": flag_title,
  1265.             "unflag_title": unflag_title,
  1266.         }
  1267.         req = requests.post(f"{self.API_URL}/update_channel_flags", headers=self.HEADERS, json=data)
  1268.         return req.json()
  1269.  
  1270.     @unstable_endpoint
  1271.     @require_authentication
  1272.     def ignore_actionable_notification(self, actionable_notification_id):
  1273.         """ (Clubhouse, int) -> dict
  1274.  
  1275.        Ignore the actionable notification.
  1276.        """
  1277.         data = {
  1278.             "actionable_notification_id": actionable_notification_id
  1279.         }
  1280.         req = requests.post(f"{self.API_URL}/ignore_actionable_notification", headers=self.HEADERS, json=data)
  1281.         return req.json()
  1282.  
  1283.     @unstable_endpoint
  1284.     @require_authentication
  1285.     def invite_to_new_channel(self, user_id, channel):
  1286.         """ (Clubhouse, int, str) -> dict
  1287.  
  1288.        Invite someone to the channel
  1289.        """
  1290.         data = {
  1291.             "user_id": int(user_id),
  1292.             "channel": channel
  1293.         }
  1294.         req = requests.post(f"{self.API_URL}/invite_to_new_channel", headers=self.HEADERS, json=data)
  1295.         return req.json()
  1296.  
  1297.     @unstable_endpoint
  1298.     @require_authentication
  1299.     def accept_new_channel_invite(self, channel_invite_id):
  1300.         """ (Clubhouse, int) -> dict
  1301.  
  1302.        Accept Channel Invitation
  1303.        """
  1304.         data = {
  1305.             "channel_invite_id": channel_invite_id
  1306.         }
  1307.         req = requests.post(f"{self.API_URL}/accept_new_channel_invite", headers=self.HEADERS, json=data)
  1308.         return req.json()
  1309.  
  1310.     @unstable_endpoint
  1311.     @require_authentication
  1312.     def reject_new_channel_invite(self, channel_invite_id):
  1313.         """ (Clubhouse, int) -> dict
  1314.  
  1315.        Reject Channel Invitation
  1316.        """
  1317.         data = {
  1318.             "channel_invite_id": channel_invite_id
  1319.         }
  1320.         req = requests.post(f"{self.API_URL}/reject_new_channel_invite", headers=self.HEADERS, json=data)
  1321.         return req.json()
  1322.  
  1323.     @unstable_endpoint
  1324.     @require_authentication
  1325.     def cancel_new_channel_invite(self, channel_invite_id):
  1326.         """ (Clubhouse, int) -> dict
  1327.  
  1328.        Cancel Channel Invitation
  1329.        """
  1330.         data = {
  1331.             "channel_invite_id": channel_invite_id
  1332.         }
  1333.         req = requests.post(f"{self.API_URL}/cancel_new_channel_invite", headers=self.HEADERS, json=data)
  1334.         return req.json()
  1335.  
  1336.     @unstable_endpoint
  1337.     @require_authentication
  1338.     def add_club_admin(self, club_id, user_id):
  1339.         """ (Clubhouse, int, int) -> dict
  1340.  
  1341.        Add Club Admin. Requires privilege.
  1342.        """
  1343.         data = {
  1344.             "club_id": int(club_id),
  1345.             "user_id": int(user_id)
  1346.         }
  1347.         req = requests.post(f"{self.API_URL}/add_club_admin", headers=self.HEADERS, json=data)
  1348.         return req.json()
  1349.  
  1350.     @unstable_endpoint
  1351.     @require_authentication
  1352.     def remove_club_admin(self, club_id, user_id):
  1353.         """ (Clubhouse, int, int) -> dict
  1354.  
  1355.        Remove Club admin. Requires privilege.
  1356.        """
  1357.         data = {
  1358.             "club_id": int(club_id) if club_id else None,
  1359.             "user_id": int(user_id)
  1360.         }
  1361.         req = requests.post(f"{self.API_URL}/remove_club_admin", headers=self.HEADERS, json=data)
  1362.         return req.json()
  1363.  
  1364.     @unstable_endpoint
  1365.     @require_authentication
  1366.     def remove_club_member(self, club_id, user_id):
  1367.         """ (Clubhouse, int, int) -> dict
  1368.  
  1369.        Remove Club member. Requires privilege.
  1370.        """
  1371.         data = {
  1372.             "club_id": int(club_id) if club_id else None,
  1373.             "user_id": int(user_id)
  1374.         }
  1375.         req = requests.post(f"{self.API_URL}/remove_club_member", headers=self.HEADERS, json=data)
  1376.         return req.json()
  1377.  
  1378.     @unstable_endpoint
  1379.     @require_authentication
  1380.     def accept_club_member_invite(self, club_id, source_topic_id=None):
  1381.         """ (Clubhouse, int, int) -> dict
  1382.  
  1383.        Accept Club member invite.
  1384.        """
  1385.         data = {
  1386.             "club_id": int(club_id) if club_id else None,
  1387.             "source_topic_id": source_topic_id
  1388.         }
  1389.         req = requests.post(f"{self.API_URL}/accept_club_member_invite", headers=self.HEADERS, json=data)
  1390.         return req.json()
  1391.  
  1392.     @unstable_endpoint
  1393.     @require_authentication
  1394.     def add_club_member(self, club_id, user_id, name, phone_number, message, reason):
  1395.         """ (Clubhouse, int, int, str, str, str, unknown) -> dict
  1396.  
  1397.        Add club member
  1398.        """
  1399.         data = {
  1400.             "club_id": int(club_id),
  1401.             "user_id": int(user_id),
  1402.             "name": name,
  1403.             "phone_number": phone_number,
  1404.             "message": message,
  1405.             "reason": reason
  1406.         }
  1407.         req = requests.post(f"{self.API_URL}/add_club_member", headers=self.HEADERS, json=data)
  1408.         return req.json()
  1409.  
  1410.     @unstable_endpoint
  1411.     @require_authentication
  1412.     def get_club_nominations(self, club_id, source_topic_id):
  1413.         """ (Club, int, int) -> dict
  1414.  
  1415.        Get club nomination list
  1416.        """
  1417.         data = {
  1418.             "club_id": int(club_id),
  1419.             "source_topic_id": source_topic_id
  1420.         }
  1421.         req = requests.post(f"{self.API_URL}/get_club_nominations", headers=self.HEADERS, json=data)
  1422.         return req.json()
  1423.  
  1424.     @unstable_endpoint
  1425.     @require_authentication
  1426.     def approve_club_nomination(self, club_id, source_topic_id, invite_nomination_id):
  1427.         """ (Club, int, int) -> dict
  1428.  
  1429.        Approve club nomination
  1430.        """
  1431.         data = {
  1432.             "club_id": int(club_id),
  1433.             "source_topic_id": source_topic_id,
  1434.             "invite_nomination_id": invite_nomination_id
  1435.         }
  1436.         req = requests.post(f"{self.API_URL}/approve_club_nomination", headers=self.HEADERS, json=data)
  1437.         return req.json()
  1438.  
  1439.     @unstable_endpoint
  1440.     @require_authentication
  1441.     def reject_club_nomination(self, club_id, source_topic_id, invite_nomination_id):
  1442.         """ (Club, int, int) -> dict
  1443.  
  1444.        Reject club nomination
  1445.        """
  1446.         data = {
  1447.             "club_id": int(club_id),
  1448.             "source_topic_id": source_topic_id,
  1449.             "invite_nomination_id": invite_nomination_id
  1450.         }
  1451.         req = requests.post(f"{self.API_URL}/approve_club_nomination", headers=self.HEADERS, json=data)
  1452.         return req.json()
  1453.  
  1454.     @unstable_endpoint
  1455.     @require_authentication
  1456.     def add_club_topic(self, club_id, topic_id):
  1457.         """ (Club, int, int) -> dict
  1458.  
  1459.        Add club topic
  1460.        """
  1461.         data = {
  1462.             "club_id": int(club_id),
  1463.             "topic_id": int(topic_id)
  1464.         }
  1465.         req = requests.post(f"{self.API_URL}/add_club_topic", headers=self.HEADERS, json=data)
  1466.         return req.json()
  1467.  
  1468.     @unstable_endpoint
  1469.     @require_authentication
  1470.     def remove_club_topic(self, club_id, topic_id):
  1471.         """ (Club, int, int) -> dict
  1472.  
  1473.        Remove club topic
  1474.        """
  1475.         data = {
  1476.             "club_id": int(club_id),
  1477.             "topic_id": int(topic_id)
  1478.         }
  1479.         req = requests.post(f"{self.API_URL}/remove_club_topic", headers=self.HEADERS, json=data)
  1480.         return req.json()
  1481.  
  1482.     @unstable_endpoint
  1483.     @require_authentication
  1484.     def get_events_to_start(self):
  1485.         """ (Clubhouse) -> dict
  1486.  
  1487.        Get events to start
  1488.        """
  1489.         req = requests.get(f"{self.API_URL}/get_events_to_start", headers=self.HEADERS)
  1490.         return req.json()
  1491.  
  1492.     @unstable_endpoint
  1493.     @require_authentication
  1494.     def update_is_follow_allowed(self, club_id, is_follow_allowed=True):
  1495.         """ (Clubhouse, int, bool) -> dict
  1496.  
  1497.        Update follow button of the given Club
  1498.        """
  1499.         data = {
  1500.             "club_id": int(club_id),
  1501.             "is_follow_allowed": is_follow_allowed
  1502.         }
  1503.         req = requests.post(f"{self.API_URL}/update_is_follow_allowed", headers=self.HEADERS, json=data)
  1504.         return req.json()
  1505.  
  1506.     @unstable_endpoint
  1507.     @require_authentication
  1508.     def update_is_membership_private(self, club_id, is_membership_private):
  1509.         """ (Clubhouse, int, bool) -> dict
  1510.  
  1511.        Update membership status of the given Club
  1512.        """
  1513.         data = {
  1514.             "club_id": int(club_id),
  1515.             "is_membership_private": is_membership_private
  1516.         }
  1517.         req = requests.post(f"{self.API_URL}/update_is_membership_private", headers=self.HEADERS, json=data)
  1518.         return req.json()
  1519.  
  1520.     @unstable_endpoint
  1521.     @require_authentication
  1522.     def update_is_community(self, club_id, is_community):
  1523.         """ (Clubhouse, int, bool) -> dict
  1524.  
  1525.        Update community stat of the given Club
  1526.        """
  1527.         data = {
  1528.             "club_id": int(club_id),
  1529.             "is_community": is_community
  1530.         }
  1531.         req = requests.post(f"{self.API_URL}/update_is_community", headers=self.HEADERS, json=data)
  1532.         return req.json()
  1533.  
  1534.     @unstable_endpoint
  1535.     @require_authentication
  1536.     def update_club_description(self, club_id, description):
  1537.         """ (Clubhouse, int, str) -> dict
  1538.  
  1539.        Update description of the given Club
  1540.        """
  1541.         data = {
  1542.             "club_id": int(club_id),
  1543.             "description": description
  1544.         }
  1545.         req = requests.post(f"{self.API_URL}/update_club_description", headers=self.HEADERS, json=data)
  1546.         return req.json()
  1547.  
  1548.     @unstable_endpoint
  1549.     @require_authentication
  1550.     def update_club_rules(self):
  1551.         """ (Clubhouse) -> dict
  1552.  
  1553.        Not implemented method
  1554.        """
  1555.         raise NotImplementedError("Not Implemented!")
  1556.  
  1557.     @unstable_endpoint
  1558.     @require_authentication
  1559.     def update_club_topics(self):
  1560.         """ (Clubhouse) -> dict
  1561.  
  1562.        Not implemented method
  1563.        """
  1564.         raise NotImplementedError("Not Implemented!")
  1565.  
  1566.     @unstable_endpoint
  1567.     @require_authentication
  1568.     def get_events_for_user(self):
  1569.         """ (Clubhouse) -> dict
  1570.  
  1571.        Not implemented method
  1572.        """
  1573.         raise NotImplementedError("Not Implemented!")
Add Comment
Please, Sign In to add comment