117 lines
4.4 KiB
Python
Executable File
117 lines
4.4 KiB
Python
Executable File
#!/usr/bin/env python3
|
|
""" Script to send SMSes using the Free mobile API
|
|
"""
|
|
import sys
|
|
import logging
|
|
import argparse
|
|
import readline
|
|
import configparser
|
|
from itertools import count
|
|
|
|
import requests
|
|
|
|
|
|
class SMSApiManager:
|
|
""" Class to manage ending SMS notification using Free Mobile API.
|
|
"""
|
|
FREE_API_URL = "https://smsapi.free-mobile.fr/sendmsg"
|
|
MAX_LENGTH = 999
|
|
RETURN_CODE = {200: "Message sent",
|
|
400: "Mandatory parameter is missing",
|
|
402: "Too many SMS sent in to few time",
|
|
403: "Service disabled",
|
|
500: "Server error, please try again later"}
|
|
def __init__(self, conf_file_path):
|
|
self._pass = ""
|
|
self.user_id = ""
|
|
self.read_config(conf_file_path)
|
|
|
|
def send_sms(self, msg: str):
|
|
""" Send a SMS to a user using its passphrase and user ID
|
|
Return the response object from requests.
|
|
"""
|
|
# Make sure we do not send more than MAX_LENGTH characters
|
|
msg = msg[:self.MAX_LENGTH]
|
|
data = {"user": self.user_id,
|
|
"pass": self._pass,
|
|
"msg": msg}
|
|
res = requests.get(self.FREE_API_URL, params=data)
|
|
logging.info(self.RETURN_CODE[res.status_code])
|
|
return res
|
|
|
|
def read_config(self, conf_file_path):
|
|
""" Read and apply the configuration from a config file.
|
|
That config file must have a 'creds' section, and the following options:
|
|
- 'user_id', that contains the user identifier for the API
|
|
- 'passphrase', that contains this user's API key
|
|
"""
|
|
conf_parser = configparser.ConfigParser()
|
|
conf_parser.read(conf_file_path)
|
|
self.user_id = conf_parser["creds"]["user_id"]
|
|
self._pass = conf_parser["creds"]["passphrase"]
|
|
|
|
|
|
def parse_args():
|
|
""" Parse the script's command line argument, and return the args object.
|
|
"""
|
|
my_parser = argparse.ArgumentParser(description="Script to send a SMS to a person. "
|
|
"The message must be at most "
|
|
f"{SMSApiManager.MAX_LENGTH} characters long.")
|
|
my_parser.add_argument("-c", "--config", help="Path to the config file.",
|
|
default="secrets.ini")
|
|
my_parser.add_argument("message", nargs="?",
|
|
help="Message to send to the recipient. If no message is given, "
|
|
f"read up to {SMSApiManager.MAX_LENGTH} characters from the "
|
|
"standard input")
|
|
my_parser.add_argument("-i", "--interactive", action="store_true",
|
|
help="Send messages in interactive mode "
|
|
"instead of from the command line.")
|
|
return my_parser.parse_args()
|
|
|
|
|
|
def rlinput(prompt, prefill=''):
|
|
""" Prefill the input content with the value of `prefill`
|
|
All credits go to https://stackoverflow.com/a/2533142
|
|
"""
|
|
readline.set_startup_hook(lambda: readline.insert_text(prefill))
|
|
try:
|
|
return input(prompt)
|
|
finally:
|
|
readline.set_startup_hook()
|
|
|
|
def main():
|
|
""" Instantiate an sms_manager, and send SMS
|
|
"""
|
|
args = parse_args()
|
|
sms_manager = SMSApiManager(args.config)
|
|
while args.interactive:
|
|
# Interactive mode is enabled, loop indefinetely until user hits Ctrl+C or Ctrl+D
|
|
try:
|
|
message=[]
|
|
for i in count():
|
|
message.append(rlinput(f"What is your message (line {i+1})?: ",
|
|
prefill=args.message))
|
|
args.message=""
|
|
if not message[i]:
|
|
break
|
|
res = sms_manager.send_sms(msg='\n'.join(message))
|
|
if res.status_code != 200:
|
|
print("Error while sending the message:")
|
|
print(f"{sms_manager.RETURN_CODE[res.status_code]}")
|
|
except (EOFError, KeyboardInterrupt):
|
|
print("\nBye !")
|
|
break
|
|
else:
|
|
# Else either get message from command line or stdin.
|
|
logging.basicConfig(level=logging.INFO)
|
|
if args.message:
|
|
# Send the requested message
|
|
sms_manager.send_sms(msg=args.message)
|
|
else:
|
|
# Read the message from stdin
|
|
msg = sys.stdin.read(sms_manager.MAX_LENGTH)
|
|
res = sms_manager.send_sms(msg=msg)
|
|
|
|
if __name__ == "__main__":
|
|
main()
|