├── LICENSE ├── README.md ├── requirements.txt ├── setup.py └── way2sms ├── __init__.py └── app.py /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2020 The Python Packaging Authority 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy 4 | of this software and associated documentation files (the "Software"), to deal 5 | in the Software without restriction, including without limitation the rights 6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | copies of the Software, and to permit persons to whom the Software is 8 | furnished to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in all 11 | copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 19 | SOFTWARE. 20 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Way2Sms 2 | 3 | Send upto 2 free [SMS](https://www.way2sms.com/) instantly. 4 | 5 | [Way2Sms](https://www.way2sms.com/) provides free SMS service upto 2 messages daily with message length upto **139**. 6 | 7 | ## Install 8 | 9 | ``` 10 | pip3 install sch-way2sms==0.0.1 11 | ``` 12 | 13 | ## Usage 14 | 15 | ``` 16 | import way2sms 17 | # your login credentials 18 | sms = way2sms.Sms("9XXXXXXXXX", "PASSWORD") 19 | sms.send("9XXXXXXXXX", "Hi, this package is awesome! Lets me send free messages") 20 | sms.logout() 21 | ``` 22 | 23 | Future Message added by [AbdHan](https://github.com/abdhan) 24 | -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | beautifulsoup4 2 | requests 3 | setuptools 4 | -------------------------------------------------------------------------------- /setup.py: -------------------------------------------------------------------------------- 1 | """ 2 | Way2sms 3 | """ 4 | 5 | import setuptools 6 | 7 | with open("README.md", "r") as fh: 8 | long_description = fh.read() 9 | 10 | setuptools.setup( 11 | name="sch-way2sms", 12 | version="0.0.1", 13 | author="Shubham Choudhary", 14 | author_email="shubhamc183@gmail.com", 15 | description="Send free sms WAY2SMS", 16 | long_description="Way2sms, 2 free messages per day in India", 17 | long_description_content_type="text/markdown", 18 | url="https://github.com/shubhamc183/way2sms", 19 | packages=setuptools.find_packages(), 20 | classifiers=[ 21 | "Programming Language :: Python :: 3", 22 | "License :: OSI Approved :: MIT License", 23 | "Operating System :: OS Independent", 24 | ], 25 | python_requires='>=3.6', 26 | install_requires=[ 27 | 'beautifulsoup4', 28 | 'requests' 29 | ] 30 | ) 31 | -------------------------------------------------------------------------------- /way2sms/__init__.py: -------------------------------------------------------------------------------- 1 | """ 2 | Way2sms 3 | """ 4 | 5 | from way2sms.app import Sms 6 | -------------------------------------------------------------------------------- /way2sms/app.py: -------------------------------------------------------------------------------- 1 | import requests 2 | from bs4 import BeautifulSoup 3 | 4 | BASE_URL = "https://www.way2sms.com/" 5 | 6 | 7 | def _login_check(func): 8 | """ 9 | A decorator to check if user is logged in or not 10 | """ 11 | def wrapper(*args): 12 | """ 13 | Decorator inner method 14 | """ 15 | if not args[0].logged_in: 16 | print("Can't perform action since NOT logged in..!") 17 | return False 18 | return func(*args) 19 | return wrapper 20 | 21 | 22 | class Sms: 23 | """ 24 | SMS Class 25 | """ 26 | 27 | def __init__(self, mobile_number, password): 28 | """ 29 | Login with mobile_number and password to create a Session 30 | """ 31 | self._login_url = BASE_URL + "re-login" 32 | self._msg_url = BASE_URL + "smstoss" 33 | self._msg_left_url = BASE_URL + "sentSMS?Token=" 34 | self._future_msg_url = BASE_URL + "schedulesms" 35 | self._logout_url = BASE_URL + "Logout" 36 | self._session = requests.Session() 37 | self._session.headers['User-Agent'] = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML,"\ 38 | "like Gecko) Chrome/67.0.3396.99 Safari/537.36" 39 | # Do a http GET to get the cookies 40 | self._session.get(BASE_URL) 41 | self._session.headers['X-Requested-With'] = 'XMLHttpRequest' 42 | self._session.headers['Cookie'] = "JSESSIONID=" + self._session.cookies.get_dict()['JSESSIONID'] 43 | payload = {'mobileNo': mobile_number, 'password': password, 'CatType': '', 'redirectPage': '', 'pid': ''} 44 | response = self._session.post(self._login_url, data=payload) 45 | if response.status_code == 200 and response.text == "send-sms": 46 | print("Successfully logged in..!") 47 | self.logged_in = True 48 | else: 49 | print("Can't login, once check credential..!") 50 | self.logged_in = False 51 | # JSID is the main KEY and is produced every time a session starts 52 | self._jsid = self._session.cookies.get_dict()['JSESSIONID'][4:] 53 | 54 | @_login_check 55 | def msg_sent_today(self): 56 | """ 57 | Returns number of SMS sent today as there is a limit of 100 messages everyday..! 58 | """ 59 | response = self._session.get(self._msg_left_url + self._jsid) 60 | # we want the number of messages sent which is present in the 61 | soup = BeautifulSoup(response.text, 'html.parser') 62 | # div element with class "hed" -> h2 63 | h2_text = soup.find("div", {"class": "hed"}).h2.text 64 | message_sent_count = 0 65 | for _ in h2_text: 66 | if _.isdecimal(): 67 | message_sent_count = 10 * message_sent_count + int(_) 68 | return message_sent_count 69 | 70 | @_login_check 71 | def send(self, mobile_number, msg): 72 | """ 73 | Sends the message to the given mobile number and return boolean 74 | """ 75 | # checks whether the given message is of length less than equal to 139 and mobile number is valid 76 | if len(msg) > 139 or len(mobile_number) != 10 or not mobile_number.isdecimal(): 77 | return False 78 | # I analyzed the NETWORK section in Inspect Element while messaging someone from browser 79 | payload = { 80 | 'ssaction': 'ss', 81 | 'Token': self._jsid, 82 | 'toMobile': mobile_number, 83 | 'message': msg, 84 | 'sederId': 'WAYSMS' 85 | } 86 | response = self._session.post(self._msg_url, data=payload) 87 | return response.status_code == 200 88 | 89 | @_login_check 90 | def send_later(self, mobile_number, msg, date, time): 91 | """ 92 | Function for future SMS feature. 93 | date must be in dd/mm/yyyy format 94 | time must be in 24hr format. For ex: 18:05 95 | """ 96 | if len(msg) > 139 or len(mobile_number) != 10 or not mobile_number.isdecimal(): 97 | return False 98 | # These steps to check for valid date and time and formatting 99 | dateparts = date.split('/') 100 | timeparts = time.split(':') 101 | if int(dateparts[0]) < 1 or int(dateparts[0]) > 32 or int(dateparts[1]) > 12 or int(dateparts[1]) < 1 or int( 102 | dateparts[2]) < 2017 or int(timeparts[0]) < 0 or int(timeparts[0]) > 23 or int( 103 | timeparts[1]) > 59 or int(timeparts[1]) < 0: 104 | return False 105 | date = dateparts[0].zfill(2) + "/" + dateparts[1].zfill(2) + "/" + dateparts[2] 106 | time = timeparts[0].zfill(2) + ":" + timeparts[1].zfill(2) 107 | payload = { 108 | 'Token': self._jsid, 109 | 'toMobile': mobile_number, 110 | 'sdate': date, 111 | 'stime': time, 112 | 'message': msg 113 | } 114 | response = self._session.post(self._future_msg_url, data=payload) 115 | return response.status_code == 200 116 | 117 | @_login_check 118 | def logout(self): 119 | """ 120 | Closes the session and mimics a logout 121 | """ 122 | self._session.get(self._logout_url) 123 | self._session.close() 124 | self.logged_in = False 125 | print("Successfully logged OUT..!") 126 | --------------------------------------------------------------------------------