diff --git a/.idea/.gitignore b/.idea/.gitignore new file mode 100644 index 0000000..73f69e0 --- /dev/null +++ b/.idea/.gitignore @@ -0,0 +1,8 @@ +# Default ignored files +/shelf/ +/workspace.xml +# Datasource local storage ignored files +/dataSources/ +/dataSources.local.xml +# Editor-based HTTP Client requests +/httpRequests/ diff --git a/.idea/autoficher.iml b/.idea/autoficher.iml new file mode 100644 index 0000000..d0876a7 --- /dev/null +++ b/.idea/autoficher.iml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/.idea/inspectionProfiles/Project_Default.xml b/.idea/inspectionProfiles/Project_Default.xml new file mode 100644 index 0000000..6ad0d1a --- /dev/null +++ b/.idea/inspectionProfiles/Project_Default.xml @@ -0,0 +1,19 @@ + + + + \ No newline at end of file diff --git a/.idea/inspectionProfiles/profiles_settings.xml b/.idea/inspectionProfiles/profiles_settings.xml new file mode 100644 index 0000000..105ce2d --- /dev/null +++ b/.idea/inspectionProfiles/profiles_settings.xml @@ -0,0 +1,6 @@ + + + + \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml new file mode 100644 index 0000000..d4fc832 --- /dev/null +++ b/.idea/misc.xml @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/.idea/modules.xml b/.idea/modules.xml new file mode 100644 index 0000000..dfc3532 --- /dev/null +++ b/.idea/modules.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml new file mode 100644 index 0000000..94a25f7 --- /dev/null +++ b/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..78fae8d --- /dev/null +++ b/README.md @@ -0,0 +1,25 @@ +Autoficher para Timenet +============================== + +Que es esto? +------------- + +Aplicación simple para fichar y desfichar automáticamente + +Como se usa? +--------------- + +1. Ejecutamos `pip3 install -r requirements.txt` para instalar los componentes +2. Ejecutamos `python3 ./autofitcher.py -u -p [-t <0 = Entrada, 1 = Salida>| -bt]` +3. Opcionalmente podemos ponerlo en un Crontab de linux para que se ejecute cada X tiempo y se realize el fichado automatico + +Parametros obligatorios +--------------- + +-u > Usuario de timenet (Pista Cero = 4c26cc59-ee52-4c47-b7fe-1065a5e5bf84) +-p > Pin de usuario + +Tendremos que escojer también entre --basedtime o --type + +-bt > No requiere argumento. Esto ficha y desficha basado en la configuración de horas a seguir +-t <0 = Entrada, 1 = Salida> > Forzamos estado al entrar/salir \ No newline at end of file diff --git a/autoficher.py b/autoficher.py index aca0f36..f941f19 100755 --- a/autoficher.py +++ b/autoficher.py @@ -17,75 +17,108 @@ # Creado: Omar Sánchez 04-05-2019 # Importamos librerias -import os import json -import sys -from datetime import datetime, timedelta +from datetime import datetime + +import pytz import requests -import urllib.parse import argparse +import telegram + # Introducimos los argumentos obligatorios y opcionales parser = argparse.ArgumentParser(add_help=False) parser._action_groups.pop() obligatoryArgs = parser.add_argument_group("Argumentos obligatorios") obligatoryArgs.add_argument('-u', '--user', help="Usuario", required=True) -obligatoryArgs.add_argument('-p', '--pin', help="Contraseña", required=True) -obligatoryArgs.add_argument('-t', '--type', help="Tipo marcado. 0 = Entrada, 1 = Salida", required=True) +obligatoryArgs.add_argument('-p', '--pin', help="Contraseña", type=int, required=True) +obligatoryArgs.add_argument('-t', '--type', help="Tipo marcado. 0 = Entrada, 1 = Salida", type=int) optionalArgs = parser.add_argument_group("Argumentos opcionales") -optionalArgs.add_argument('-f', '--festive', action="store_false", help="Comprobar festivo") +optionalArgs.add_argument('-bt', '--basedtime', help="Hacer check o descheck según la hora del dia", action="store_true") optionalArgs.add_argument('-h', '--help', action="help", help="Esta ayuda") args = parser.parse_args() class AutoFicher(): # URL de la api - url = "https://timenet.gpisoftware.com/api/v1/cp/" - # Definimos las variables de tiempo - date = datetime.now().strftime("%d/%m/%Y+%H:%M:%S") - #calendar = (datetime.now() + timedelta(days=3)).strftime("%d/%m/%Y") - calendar = datetime.now().strftime("%d/%m/%Y") + headers = { + "Content-type": "application/x-www-form-urlencoded; charset=UTF-8", + "tn-v": "3.0.9", + "User-Agent": "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/93.0.4577.82 Safari/537.36" + } + config = None - token = "" + def __init__(self): + self.loadConfig() - def __init__(self, task = ''): - # Iniciamos Sesión y obtenemos el token - headers = {'user': args.user, 'pass': args.pin} - response = requests.get(self.url+'login', headers=headers) - self.token = response.text.replace('"','') + def loadConfig(self): + with open('config.json', 'r') as f: + self.config = json.load(f) - def isFestive(self): - # Comprobamos si esta habilitado el comprobar festivo (Por defecto es True) - if args.festive: - # Revisamos el dia en el calendario y comprobamos si es festivo o no - headers = {'token': self.token} - response = requests.get(self.url+"calendar?start="+self.calendar+"&end="+self.calendar, headers=headers) - dayType = json.loads(response.text)["DayTypes"][0]["dayMode"] + def sendReport(self, message): + bot = telegram.Bot(token=self.config['telegram']['token']) + bot.sendMessage(chat_id=self.config['telegram']['chat_id'], text=str(message)) + + def get(self, url, data={}, headers={}): + if url != "version": + self.url = self.url + "v1/" + return requests.get(self.config['api_url']+url, data=data, headers=headers) + + def post(self, url, data={}, headers={}): + if url != "version": + self.url = self.url + "v1/" + return requests.post(self.config['api_url']+url, data=data, headers=headers) + + def updateTime(self): + self.headers["tn-d"] = "\""+datetime.now().astimezone(pytz.UTC).strftime(self.config['time_format'])+"\"" + + def getVersion(self): + self.updateTime() + return self.get('version', self.headers) + + def getInfo(self): + return self.get('check/info', {"guid": args.user}) - if dayType == "NO_WORK": - return True - else: - return False - else: - return False - def sendUpdate(self): - # Si no es festivo.. - if not self.isFestive(): - # Hacemos la llamada a la api para marcar o desmarcar - print("Dia de curro") - headers = {"Content-type": "application/x-www-form-urlencoded", "token": self.token} - data = {"typ": args.type, "date": urllib.parse.quote(self.date), "geoLatitude": "41.3908992", "geoLongitude": "2.154496", "geoErrors": ""} - - response = requests.post(self.url+"checks", data=data, headers=headers) - if response.status_code != 200: - print("Error "+str(response.status_code)+" al realizar el envio: "+ response.request.body) + self.updateTime() + + typ = 0 + if args.basedtime and not args.type: + hour = datetime.now().strftime("%H") + + hIN = self.config['in_hours'] + + hOUT = self.config['out_hours'] + + if hour in hIN: + typ = 0 + elif hour in hOUT: + typ = 1 else: - print(response.text) + print("No se ha fichado ni desfichado ya que estamos en horario laboral, fuerze el estado con el parametro --type <0 = Entrada, 1 = Salida>") else: - print("Hoy no se trabaja") + typ = args.type + + data = { + "cp": args.user, + "pin": args.pin, + "typ": typ, + "date": self.headers['tn-d'], + "geoLatitude": self.config['geo']['latitude'], + "geoLongitude": self.config['geo']['longitude'], + "geoError": "", + "c": 1, + "geoAccuracy": self.config['geo']['accuracy'] + } + + response = self.post("check", data, self.headers) + + if response.status_code != 200: + self.sendReport('Has fichado correctamente a las ' + str(datetime.strptime(self.headers["tn-d"]).strftime("%H:%M"))) + else: + self.sendReport("No se ha podido fichar, la web no ha devuelto 200 OK") if __name__ == '__main__': - AutoFicher().sendUpdate() + af = AutoFicher() diff --git a/config.json b/config.json new file mode 100644 index 0000000..68bac22 --- /dev/null +++ b/config.json @@ -0,0 +1,28 @@ +{ + "in_hours": [ + "07", + "08", + "09", + "10", + "11", + "15" + ], + "out_hours": [ + "13", + "14", + "15", + "17", + "18" + ], + "api_url": "https://timenet.gpisoftware.com/api/", + "telegram": { + "token": "1502426217:AAEBG7XF6dZqJ6cRmPQk_YykGS5mJFeUEto", + "chat_id": 12878473 + }, + "geo": { + "latitude": 41.3908992, + "longitude": 2.154496, + "accuracy": 98.31 + }, + "time_format": "%Y-%m-%dT%H:%M:%SZ" +} \ No newline at end of file diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..b856f1d --- /dev/null +++ b/requirements.txt @@ -0,0 +1 @@ +python-telegram \ No newline at end of file