├── .flake8 ├── .github └── workflows │ ├── flake-test.yml │ └── python-publish.yml ├── .gitignore ├── LICENSE ├── MANIFEST.in ├── README.md ├── iterapi ├── __init__.py └── iterapi.py └── setup.py /.flake8: -------------------------------------------------------------------------------- 1 | [flake8] 2 | exclude = .git, 3 | __pycache__, 4 | .github, 5 | build, 6 | dist, 7 | .eggs, 8 | iterapi.egg-info, 9 | setup.py -------------------------------------------------------------------------------- /.github/workflows/flake-test.yml: -------------------------------------------------------------------------------- 1 | name: Flake Test 2 | 3 | on: [push, pull_request] 4 | 5 | jobs: 6 | test: 7 | 8 | runs-on: ubuntu-latest 9 | 10 | steps: 11 | - uses: actions/checkout@v2 12 | - name: Set up Python 13 | uses: actions/setup-python@v2 14 | with: 15 | python-version: '3.x' 16 | - name: Install dependencies 17 | run: | 18 | python -m pip install --upgrade pip 19 | pip install flake8 20 | - name: Run Flake 21 | run: flake8 -------------------------------------------------------------------------------- /.github/workflows/python-publish.yml: -------------------------------------------------------------------------------- 1 | # This workflows will upload a Python Package using Twine when a release is created 2 | # For more information see: https://help.github.com/en/actions/language-and-framework-guides/using-python-with-github-actions#publishing-to-package-registries 3 | 4 | name: Upload Python Package 5 | 6 | on: 7 | push: 8 | branches: 9 | - 'master' 10 | 11 | jobs: 12 | deploy: 13 | 14 | runs-on: ubuntu-latest 15 | 16 | steps: 17 | - uses: actions/checkout@v2 18 | - name: Set up Python 19 | uses: actions/setup-python@v2 20 | with: 21 | python-version: '3.x' 22 | - name: Install dependencies 23 | run: | 24 | python -m pip install --upgrade pip 25 | pip install setuptools wheel twine 26 | - name: Build and publish 27 | env: 28 | TWINE_USERNAME: ${{ secrets.PYPI_USERNAME }} 29 | TWINE_PASSWORD: ${{ secrets.PYPI_PASSWORD }} 30 | run: | 31 | python setup.py sdist bdist_wheel 32 | twine upload --skip-existing dist/* 33 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # general things to ignore 2 | build/ 3 | dist/ 4 | *.egg-info/ 5 | *.egg 6 | .eggs/ 7 | *.py[cod] 8 | __pycache__/ 9 | *.so 10 | *~ 11 | *.jpg 12 | .idea/ 13 | *.pdf -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 Subhrajit Prusty 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /MANIFEST.in: -------------------------------------------------------------------------------- 1 | # Include the README 2 | include *.md 3 | 4 | # Include the license file 5 | include LICENSE 6 | 7 | # Include the data files 8 | recursive-include data * 9 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # iterapi 2 | Python API to Student's Campus portal of ITER 3 | 4 | [![GitHub top language][ico-lang]][link-github] 5 | [![Licence][ico-licence]][link-pypi] 6 | [![Latest Version][ico-version]][link-pypi] 7 | [![Format][ico-format]][link-pypi] 8 | [![Status][ico-status]][link-pypi] 9 | 10 | ## Installation 11 | 12 | Requires Python 3.6+ 13 | 14 | `pip install iterapi` 15 | 16 | ## Usage 17 | 18 | Import and use the class. 19 | 20 | Example 21 | 22 | ```python 23 | from iterapi import Student 24 | 25 | st = Student('regdno','password') # Login to the portal 26 | st.getInfo() # returns a dictionary containing student details 27 | st.getPhoto() # writes photo as registration_no.jpg 28 | st.getAttendance() # returns a dictionary containing attendance 29 | st.getResult() # returns a dictionary containing results 30 | st.getDetailedResult(sem_no) # returns a dictionary containing details of a semester result 31 | st.downloadSemResult(sem_no) # writes result document as registrationno_sem_no.pdf 32 | 33 | ``` 34 | 35 | [ico-lang]: https://img.shields.io/github/languages/top/SubhrajitPrusty/iterapi.svg?style=for-the-badge 36 | [ico-version]: https://img.shields.io/pypi/v/iterapi.svg?style=for-the-badge 37 | [ico-licence]: https://img.shields.io/pypi/l/iterapi.svg?style=for-the-badge 38 | [ico-format]: https://img.shields.io/pypi/format/iterapi.svg?style=for-the-badge 39 | [ico-status]: https://img.shields.io/pypi/status/iterapi.svg?style=for-the-badge 40 | [ico-build]: https://img.shields.io/github/workflow/status/SubhrajitPrusty/iterapi/Upload%20Python%20Package?style=for-the-badge 41 | 42 | 43 | [link-github]: https://github.com/SubhrajitPrusty/iterapi 44 | [link-pypi]: https://pypi.org/project/iterapi 45 | -------------------------------------------------------------------------------- /iterapi/__init__.py: -------------------------------------------------------------------------------- 1 | from .iterapi import Student # noqa: F401 2 | -------------------------------------------------------------------------------- /iterapi/iterapi.py: -------------------------------------------------------------------------------- 1 | import requests 2 | from json.decoder import JSONDecodeError 3 | 4 | 5 | class Student(object): 6 | """ 7 | Student Object containing functions to retrieve various student details 8 | """ 9 | 10 | DOMAIN = "http://115.240.101.51:8282" 11 | LOGIN_URL = DOMAIN+"/CampusPortalSOA/login" 12 | STUDENTINFO_URL = DOMAIN+"/CampusPortalSOA/studentinfo" 13 | REGID_URL = DOMAIN+"/CampusPortalSOA/studentSemester/lov" 14 | STUDENTPHOTO_URL = DOMAIN+"/CampusPortalSOA/image/studentPhoto" # noqa: E501 15 | STUDENTRESULT_URL = DOMAIN+"/CampusPortalSOA/stdrst" 16 | # styno = int(1-8) semester number 17 | RESULTDETAIL_URL = DOMAIN+"/CampusPortalSOA/rstdtl" 18 | ATTENDANCE_URL = DOMAIN+"/CampusPortalSOA/attendanceinfo" 19 | RESULTDOWNLOAD_URL = DOMAIN+"/CampusPortalSOA/downresultpdf" # noqa: E501 20 | 21 | HEADERS = {"Content-Type": "application/json"} 22 | 23 | def __init__(self, regdno, password): 24 | super(Student, self).__init__() 25 | self.regdno = regdno 26 | self.password = password 27 | self.cookies = self.login() 28 | self.details = None 29 | self.attendance = None 30 | self.img_path = None 31 | self.result_path = None 32 | self.results = None 33 | self.resultDetail = {} 34 | try: 35 | self.registerationid = self.getRegisterationId() 36 | except Exception: 37 | self.registerationid = None 38 | 39 | def login(self): 40 | """ 41 | Logs in the student portal to retrieve cookies 42 | 43 | self.cookies -> request.Response.cookies 44 | 45 | """ 46 | payload = str({"username": self.regdno, 47 | "password": self.password, 48 | "MemberType": "S"}) 49 | 50 | response = requests.post( 51 | Student.LOGIN_URL, 52 | data=payload, 53 | headers=Student.HEADERS) 54 | if response.status_code == 200: 55 | if "login successful" in response.json()['message'].lower(): 56 | return response.cookies 57 | else: 58 | print('Invalid username or password') 59 | raise Exception('Invalid username or password') 60 | else: 61 | print("Error: ", response.status_code) 62 | return None 63 | 64 | def getRegisterationId(self): 65 | """ 66 | Get Registration ID for current semester 67 | 68 | self.registerationid -> str 69 | 70 | """ 71 | if self.cookies: 72 | response = requests.post( 73 | Student.REGID_URL, 74 | data={}, 75 | cookies=self.cookies).json() 76 | try: 77 | return response["studentdata"][0].get("REGISTRATIONID") 78 | except Exception as e: 79 | raise e 80 | else: 81 | print('User is not logged in') 82 | raise Exception('User is not logged in') 83 | 84 | def getInfo(self): 85 | """ 86 | Gets studentinfo 87 | 88 | self.details -> dict() 89 | 90 | """ 91 | response = requests.post( 92 | Student.STUDENTINFO_URL, 93 | data={}, 94 | headers=Student.HEADERS, 95 | cookies=self.cookies) # login 96 | 97 | if response.status_code == 200: 98 | self.details = response.json() 99 | return self.details 100 | else: 101 | print("Error: ", response.status_code) 102 | return None 103 | 104 | def getPhoto(self): 105 | """ 106 | Downloads Student Profile Picture 107 | 108 | self.img_path -> str # Path to the image written 109 | 110 | """ 111 | response = requests.get( 112 | Student.STUDENTPHOTO_URL, 113 | data={}, 114 | headers=Student.HEADERS, 115 | cookies=self.cookies) 116 | res = response.content 117 | 118 | if response.content is None: 119 | print("Error: ", response.status_code) 120 | return None 121 | else: 122 | self.img_path = self.regdno + ".jpg" 123 | with open(self.img_path, "wb+") as image: 124 | image.write(res) 125 | print("File written to {}".format(self.img_path)) 126 | return self.img_path 127 | 128 | def getAttendance(self): 129 | """ 130 | Gets current Attendance 131 | 132 | self.attendance -> dict() 133 | 134 | """ 135 | if not self.registerationid: 136 | return [] 137 | payload = str({"registerationid": self.registerationid}) 138 | response = requests.post( 139 | Student.ATTENDANCE_URL, 140 | data=payload, 141 | headers=Student.HEADERS, 142 | cookies=self.cookies) 143 | 144 | if response.status_code == 200: 145 | self.attendance = response.json() 146 | return self.attendance 147 | else: 148 | print("Error: ", response.status_code) 149 | return None 150 | 151 | def getResult(self): 152 | """ 153 | Gets results 154 | 155 | self.results -> dict() 156 | 157 | """ 158 | 159 | payload = "{}" 160 | response = requests.post( 161 | Student.STUDENTRESULT_URL, 162 | data=payload, 163 | headers=Student.HEADERS, 164 | cookies=self.cookies) 165 | 166 | if response.status_code == 200: 167 | self.results = response.json() 168 | return self.results 169 | else: 170 | print("Cannot fetch results.", response.status_code) 171 | return None 172 | 173 | def getDetailedResult(self, sem): 174 | """ 175 | Gets result details of a semester 176 | 177 | Stored in self.resultDetail[sem] -> dict() 178 | 179 | """ 180 | 181 | payload = {"styno": str(sem)} 182 | 183 | response = requests.post( 184 | Student.RESULTDETAIL_URL, 185 | data=str(payload), 186 | headers=Student.HEADERS, 187 | cookies=self.cookies) 188 | 189 | if response.status_code == 200: 190 | try: 191 | self.resultDetail[sem] = response.json() 192 | except JSONDecodeError: 193 | print("Invalid Semester") 194 | raise Exception("Invalid Semester") 195 | except Exception as e: 196 | raise e 197 | return self.resultDetail[sem] 198 | else: 199 | print("Cannot fetch results.", response.status_code) 200 | return None 201 | 202 | def updatePassword(self, new_password): 203 | """ 204 | Updates the current password to the given password 205 | 206 | """ 207 | payload = { 208 | "newpassword": new_password, 209 | "confirmpassword": new_password 210 | } 211 | 212 | response = requests.post( 213 | Student.LOGIN_URL, 214 | data=str(payload), 215 | headers=Student.HEADERS, 216 | cookies=self.cookies) 217 | 218 | if response.status_code == 200: 219 | return response.json() 220 | else: 221 | print("Error: ", response.status_code) 222 | return None 223 | 224 | def downloadSemResult(self, sem): 225 | """ 226 | Gets result pdf downloaded 227 | 228 | self.result_path-> str # path to the store the Result pdf 229 | """ 230 | payload = {"stynumber": str(sem), "publish": "Y"} 231 | 232 | response = requests.post( 233 | Student.RESULTDOWNLOAD_URL, 234 | data=str(payload), 235 | headers=Student.HEADERS, 236 | cookies=self.cookies) 237 | 238 | if response.status_code == 200: 239 | try: 240 | self.result_path = self.regdno + "_sem_" + str(sem) + ".pdf" 241 | with open(self.result_path, 'wb') as f: 242 | f.write(response.content) 243 | except JSONDecodeError: 244 | print("Invalid Semester") 245 | raise Exception("Invalid Semester") 246 | except Exception as e: 247 | raise e 248 | else: 249 | print("Cannot fetch Results for semester:" + 250 | str(sem) + ".", response.status_code) 251 | return None 252 | -------------------------------------------------------------------------------- /setup.py: -------------------------------------------------------------------------------- 1 | import contextlib 2 | from setuptools import setup 3 | from codecs import open 4 | from os import path 5 | 6 | here = path.abspath(path.dirname(__file__)) 7 | 8 | 9 | def readme(): 10 | with contextlib.suppress(Exception): 11 | with open('README.md') as f: 12 | return f.read() 13 | 14 | 15 | setup( 16 | name='iterapi', 17 | version='1.2.7', 18 | description='Python API to student portal of ITER', 19 | 20 | long_description=readme(), 21 | long_description_content_type='text/markdown', 22 | 23 | url='https://github.com/SubhrajitPrusty/iterapi', 24 | author='Subhrajit Prusty', 25 | author_email='subhrajit1997@gmail.com', 26 | 27 | setup_requires=['setuptools>=38.6.0'], 28 | 29 | classifiers=[ 30 | 'Development Status :: 4 - Beta', 31 | 32 | 'Intended Audience :: Developers', 33 | 'Topic :: Software Development :: Build Tools', 34 | 35 | 'License :: OSI Approved :: MIT License', 36 | 37 | 'Programming Language :: Python :: 3', 38 | 'Programming Language :: Python :: 3.4', 39 | 'Programming Language :: Python :: 3.5', 40 | 'Programming Language :: Python :: 3.6', 41 | ], 42 | 43 | keywords='api ITER development', 44 | license='MIT', 45 | packages=['iterapi'], 46 | install_requires=['requests'], 47 | ) 48 | --------------------------------------------------------------------------------