Repository: Clueless-Community/scrape-up (language: python)

Issue:
Koo Scrapping
I would like to extend this scrap-up module to work with koo app as well as there are a lot of users on koo.

So please assign me this under GSSOC'23.


Discussion / hints:
@Akshat103   I would love to contribute to this project under the GSSoC'23. I will be using the beautiful soup & requests libraries primarily. Could you provide more information about the project's objectives and requirements? I'm eager to understand the current state and future goals.
Great idea @imshvishal 
Go ahead. 
**Note**
+ Create a separate module for this, as per the folder and project structure
+ Do not add all methods at once, do add one or two first-like methods to scrape name and bio.

All the best 

Fix patch:
diff --git a/documentation.md b/documentation.md
index 4835b1e4..fe53d235 100644
--- a/documentation.md
+++ b/documentation.md
@@ -205,3 +205,27 @@ following = user.following() #user var taken from above
 print(following)
 ```
 ---
+## KooApp
+```py
+from scrape_up import kooapp
+```
+### Scrap up kooapp user's detail
+Create an instance of `KooUser` class.
+```py
+user = kooapp.KooUser('krvishal')
+```
+| Methods        | Details                                             |
+| -------------- | --------------------------------------------------- |
+| `.get_name()` | Returns the name of the user. |
+| `.get_bio()` | Returns the bio of the user. |
+| `.get_avatar_url()` | Returns the url of first avatar of the user. |
+| `.followers()` | Returns the number of followers of a user.          |
+| `.following()` | Returns the number of people the user is following. |
+| `.get_social_profiles()` | Returns all the connected social media profiles of user. |
+| `.get_profession()` | Returns the title/profession of the user. |
+
+**Example:**
+```py
+name = user.get_name() # user variable is taken from above example
+print(name)
+```
\ No newline at end of file
diff --git a/src/scrape_up/kooapp/__init__.py b/src/scrape_up/kooapp/__init__.py
new file mode 100644
index 00000000..bf9e09e3
--- /dev/null
+++ b/src/scrape_up/kooapp/__init__.py
@@ -0,0 +1,3 @@
+from scrape_up.kooapp.users import KooUser
+
+__all__=["KooUser"]
\ No newline at end of file
diff --git a/src/scrape_up/kooapp/users.py b/src/scrape_up/kooapp/users.py
new file mode 100644
index 00000000..e05087c6
--- /dev/null
+++ b/src/scrape_up/kooapp/users.py
@@ -0,0 +1,130 @@
+import requests
+import json
+from bs4 import BeautifulSoup
+from datetime import datetime
+
+class KooUser:
+    """
+    class - `KooUser`
+
+    Example:
+    ```py
+    user = KooUser('krvishal')
+    avatar = user.get_avatar_url()
+    ```
+    Returns:
+    ```
+    >>> 'https://images.kooapp.com/transcode_input/8074390/profile16851706949505ew9y8.jpg'
+    """
+    def __init__(self, username: str) -> None:
+        self.username = username
+
+    def __str__(self) -> str:
+        return f"The username is: {self.username}"
+
+    @property
+    def profile_url(self) -> str:
+        return f"https://www.kooapp.com/profile/{self.username}"
+
+    def __scrape_page(self) -> requests.Response:
+        try:
+            res = requests.get(self.profile_url)
+            if res.status_code == 404:
+                raise Exception(f"User not found with username: {self.username}")
+            return res
+        except Exception as e:
+            raise Exception(f"An error occurred while fetching the page: {str(e)}")
+    
+    def __parse_page(self) -> dict:
+        res = self.__scrape_page()
+        try:
+            page = BeautifulSoup(res.text, "html.parser")
+            data = json.loads(page.find('script', attrs={'id': '__NEXT_DATA__'}).text)
+            return data
+        except Exception as e:
+            raise Exception(f"An error occurred while parsing the page: {str(e)}")
+
+    def __parse_profile_data(self) -> dict:
+        data = self.__parse_page()
+        try:
+            userdata = data.get('props').get('pageProps').get('initialState').get('profileReducers').get('profileItems')
+            return userdata
+        except Exception as e:
+            raise Exception(f"An error occured while parsing the data: {e}")
+
+    def get_name(self) -> str:
+        """
+        Fetch the name of the user.
+        """
+        userdata = self.__parse_profile_data()
+        name = userdata.get('name')
+        return {
+            'data': name or None,
+            'message': f"Name of the user {self.username} is {name}" if name else f"No name found for the user {self.username}"
+        }
+
+    def get_bio(self) -> str:
+        """
+        Fetch the bio dsecription of the user.
+        """
+        userdata = self.__parse_profile_data()
+        bio = userdata.get('description')
+        return {
+            'data': bio or None,
+            'message': f"Bio found for the user {self.username}" if bio else f"No bio found for the user {self.username}"
+        }
+    
+    def get_avatar_url(self) -> str:
+        """
+        Fetch the avatar url of the user.
+        """
+        userdata = self.__parse_profile_data()
+        avatar = userdata.get("profileImage")
+        return {
+            'data': avatar or None,
+            'message': f"Avatar found for the user {self.username}" if avatar else f"Avatar not found for the user {self.username}"
+        }
+    
+    def followers(self) -> int:
+        """
+        Fetch the number of followers of the Koo user.
+        """
+        userdata = self.__parse_profile_data()
+        followers = userdata.get("followerCount")
+        return {
+            'data': followers,
+            'message': f"There are {followers} follower(s) of the user {self.username}"
+        }
+    
+    def following(self) -> int:
+        """
+        Fetch the number of following of the Koo user.
+        """
+        userdata = self.__parse_profile_data()
+        following = userdata.get("followingCount")
+        return {
+            'data': following,
+            'message': f"There are {following} user(s) followed by {self.username}"
+        }
+    
+    def get_social_profiles(self) -> dict[str, str]:
+        """
+        Fetch all the listed social media profiles of user.
+        """
+        userdata = self.__parse_profile_data()
+        profiles = {s_media: handle for s_media, handle in userdata.get('socialProfile').items() if handle }
+        return {
+            'data': profiles or None,
+            'message': f"Found {len(profiles)} social profiles for the user {self.username}" if profiles else f"No social profiles found for the user {self.username}"
+        }
+
+    def get_profession(self) -> str:
+        """
+        Fetch the profession of the user.
+        """
+        userdata = self.__parse_profile_data()
+        profession = userdata.get('title')
+        return {
+            'data': profession or None,
+            'message': f"Profession found for the user {self.username}" if profession else f"No profession found for the user {self.username}"
+        }


Test patch:
diff --git a/src/test/kooapp_test.py b/src/test/kooapp_test.py
new file mode 100644
index 00000000..e69de29b