Skip to content

Commit

Permalink
Merge pull request #30 from scarlehoff/add_quiet_option
Browse files Browse the repository at this point in the history
Add quiet option
  • Loading branch information
scarlehoff committed Jul 12, 2024
2 parents 5e837fc + fcc0c4f commit f0f4aac
Show file tree
Hide file tree
Showing 19 changed files with 102 additions and 53 deletions.
10 changes: 7 additions & 3 deletions pybliotecario.ini.example
Original file line number Diff line number Diff line change
@@ -1,8 +1,12 @@
[DEFAULT]
TOKEN = <telegram bot token>
chat_id = <chat_id number>
main_folder = /home/<username>/.pybliotecario

# chat_id accepts also a list of IDs separated by comma, the first one is considered the main one
chat_id = <chat_id number>
main_folder = /home/<username>/.local/share/pybliotecario
# quiet defaults to false, whether the bot should always reply back
quiet = false
# when chivato is true, the bot will write to the main chat_id whenever an user not in chat_id writes to the bot
chivato = false #

[FACEBOOK]
verify = <verify token from fb>
Expand Down
3 changes: 2 additions & 1 deletion src/pybliotecario/argument_parser.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
"""
Wrapper for the argument parser and the initialization
"""

from argparse import Action, ArgumentParser, ArgumentTypeError
import configparser
import glob
Expand Down Expand Up @@ -93,7 +94,7 @@ def configure_telegram():
token = input("Authorization token: ")

# Try to fire up the bot with the given token
telegram_API = TelegramUtil(token, timeout=20)
telegram_API = TelegramUtil(token=token, timeout=20)
print("Thanks, let's test this out. Say something (anything!) to your bot in telegram")

for _ in range(20): # Allow for 20 tries
Expand Down
16 changes: 15 additions & 1 deletion src/pybliotecario/backend/basic_backend.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
"""

from abc import ABC, abstractmethod
from configparser import ConfigParser
import json
import logging
import urllib
Expand Down Expand Up @@ -160,7 +161,14 @@ class Backend(ABC):
"""

_max_size = 99999
def __init__(self, config=None, debug=False, **kwargs):
if config is None:
# If no config is passed, generate and empty one
config = ConfigParser()
self._max_size = 99999
self._quiet = config.getboolean("DEFAULT", "quiet", fallback=False)
self._config = config
self._debug = debug

@abstractmethod
def _get_updates(self, not_empty=False):
Expand All @@ -175,6 +183,12 @@ def raw_updates(self):
def send_message(self, text, chat, **kwargs):
"""Sends a message to the chat"""

def send_quiet_message(self, text, chat, **kwargs):
"""Like ``send_message`` but only sends the message if quiet is set to False
otherwise, do nothing"""
if not self._quiet:
return self.send_message(text, chat, **kwargs)

@property
@abstractmethod
def _message_class(self):
Expand Down
29 changes: 22 additions & 7 deletions src/pybliotecario/backend/facebook_util.py
Original file line number Diff line number Diff line change
Expand Up @@ -79,20 +79,31 @@ class FacebookUtil(Backend):
_message_class = FacebookMessage
_max_size = MAX_SIZE

def __init__(self, PAGE_TOKEN, VERIFY_TOKEN, host="0.0.0.0", port=3000, debug=False):
def __init__(self, config=None, host="0.0.0.0", port=3000, **kwargs):
super().__init__(config, **kwargs)
if config is None:
raise ValueError("A configuration with a FACEBOOK section must be given")

try:
fb_config = config["FACEBOOK"]
except KeyError:
raise ValueError("No facebook section found for facebook in pybliotecario.ini")

if not _HAS_FLASK:
# Raise the error now
raise ModuleNotFoundError("No module named 'flask'")
raise ModuleNotFoundError("No module named 'flask', needed for Facebook backend")

self.page_access_token = PAGE_TOKEN
self.verify_token = VERIFY_TOKEN
verify_token = fb_config.get("verify")
page_token = fb_config.get("app_token")

self.page_access_token = page_token
self.verify_token = verify_token
self.port = port
self.host = host
app = Flask(__name__)
# Load the listener into the webhook endpoint
app.add_url_rule("/webhook", "webhook", self.listener, methods=["POST", "GET"])
self.flask_app = app
self.debug = debug
self.action_function = None
self.auth = {"access_token": self.page_access_token}

Expand Down Expand Up @@ -121,7 +132,7 @@ def act_on_updates(self, action_function, not_empty=False):
opens the webhook to wait ofr updates and act on them
"""
self.action_function = action_function
self.flask_app.run(host=self.host, port=self.port, debug=self.debug)
self.flask_app.run(host=self.host, port=self.port, debug=self._debug)

def _get_updates(self, not_empty=False):
"""This class skips get_updates and uses act_on_updates directly"""
Expand Down Expand Up @@ -184,8 +195,12 @@ def send_file(self, filepath, chat):


if __name__ == "__main__":
from configparser import ConfigParser

logger.info("Testing FB Util")
verify = "your_verify_token"
app_token = "your_app_key"
fb_util = FacebookUtil(app_token, verify, debug=True)
config = ConfigParser()
config["FACEBOOK"] = {"verify": verify, "app_token": app_token}
fb_util = FacebookUtil(config, debug=True)
fb_util.act_on_updates(lambda x: print(x))
17 changes: 11 additions & 6 deletions src/pybliotecario/backend/telegram_util.py
Original file line number Diff line number Diff line change
Expand Up @@ -106,13 +106,18 @@ class TelegramUtil(Backend):

_message_class = TelegramMessage

def __init__(self, TOKEN, debug=False, timeout=300):
def __init__(self, config=None, token=None, timeout=300, **kwargs):
super().__init__(config, **kwargs)
if token is None:
if config is None:
raise ValueError("Either a config or a token must be provided for Telegram")
token = config.defaults().get("token")

self.offset = None
self.debug = debug
self.timeout = timeout
# Build app the API urls
base_URL = TELEGRAM_URL + f"bot{TOKEN}/"
self.base_fileURL = TELEGRAM_URL + f"file/bot{TOKEN}/"
base_URL = TELEGRAM_URL + f"bot{token}/"
self.base_fileURL = TELEGRAM_URL + f"file/bot{token}/"
self.send_msg = base_URL + "sendMessage"
self.send_img = base_URL + "sendPhoto"
self.send_doc = base_URL + "sendDocument"
Expand Down Expand Up @@ -185,7 +190,7 @@ def _get_updates(self, not_empty=False):
if not updates and not_empty:
return self._get_updates(not_empty=True)

if self.debug:
if self._debug:
logger.info("Request url: %s", url)
logger.info("Obtained updates: %s", updates)

Expand Down Expand Up @@ -254,7 +259,7 @@ def download_file(self, file_id, file_path):
if __name__ == "__main__":
logger.info("Testing TelegramUtil")
token = "must put a token here to test"
ut = TelegramUtil(token, debug=True)
ut = TelegramUtil(token=token, debug=True)
# noinspection PyProtectedMember
results = ut._get_updates()
for res in results:
Expand Down
13 changes: 11 additions & 2 deletions src/pybliotecario/components/component_core.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
the class Component will just pass the text of the msg (or the command)
to the `act_on_command` or `act_on_message` methods.
"""

import logging
import os
import sys
Expand Down Expand Up @@ -138,11 +139,15 @@ def act_on_command(self, content=None):
self.telegram.send_message("Command line argument invoked", self.chat_id)

# Some useful wrappers
def send_msg(self, msg, chat_id=None, markdown=False):
def send_msg(self, msg, chat_id=None, markdown=False, quiet=False):
"""Wrapper around API send_msg, if chat_id is not defined
it will use the chat_id this class was instantiated to"""
it will use the chat_id this class was instantiated to.
If ``quiet`` == True, use `send_quiet_message`
"""
if chat_id is None:
chat_id = self.interaction_chat
if quiet:
return self.telegram.send_quiet_message(msg, chat_id, markdown=markdown)
return self.telegram.send_message(msg, chat_id, markdown=markdown)

def send_img(self, imgpath, chat_id=None, delete=False):
Expand All @@ -168,3 +173,7 @@ def send_file(self, filepath, chat_id=None, delete=False):
self.telegram.send_file(filepath, chat_id)
if delete:
os.remove(filepath)

def _not_allowed_msg(self, chat_id=None):
"""Tell the calling ID they are not allowed to use this component"""
return self.send_msg("You are not allowed to use this", quiet=True, chat_id=chat_id)
1 change: 1 addition & 0 deletions src/pybliotecario/components/dnd.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
"""
Module implementing some functions useful for playing DnD over the internet
"""

import logging
from random import randint
import re
Expand Down
1 change: 1 addition & 0 deletions src/pybliotecario/components/github_component.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/creating-a-personal-access-token
and follow the instructions
"""

import datetime
import logging

Expand Down
8 changes: 4 additions & 4 deletions src/pybliotecario/components/ip_lookup.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
""" Server-helper function to look up the current IP of the program """

import logging
import urllib.request

Expand All @@ -24,10 +25,9 @@ class IpLookup(Component):
def telegram_message(self, msg):
"""If the chat id asking is the correct one
sends a msg with the current ip, otherwise fails"""
if self.check_identity(msg):
send_msg = ip_lookup()
else:
send_msg = "You are not allowed to see this"
if not self.check_identity(msg):
return self._not_allowed_msg()
send_msg = ip_lookup()
self.telegram.send_message(send_msg, msg.chat_id)

def cmdline_command(self, args):
Expand Down
4 changes: 2 additions & 2 deletions src/pybliotecario/components/photocol.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
It's a companion to https://github.com/scarlehoff/websito/blob/master/views/foto.pug
"""

from datetime import datetime
import json
import logging
Expand Down Expand Up @@ -106,8 +107,7 @@ def telegram_message(self, msg):
return self.send_msg("Command not understood")

if not self.check_identity(msg):
self.send_msg("You are not allowed to interact with this command!")
return
return self._not_allowed_msg()

if msg.command == "photocol_remove":
return self._remove_from_db(msg.text)
Expand Down
21 changes: 10 additions & 11 deletions src/pybliotecario/components/pid.py
Original file line number Diff line number Diff line change
Expand Up @@ -101,17 +101,16 @@ def alive(pid):
return is_it_alive(pid)

def telegram_message(self, msg):
if self.check_identity(msg):
pid_string = msg.text.strip()
if msg.command == "kill_pid":
if pid_string.isdigit():
return_msg = self.kill(int(pid_string))
else:
return_msg = f"{pid_string} is not a PID?"
elif msg.command == "is_pid_alive":
return_msg = self.alive(pid_string)
if not self.check_identity(msg):
return self._not_allowed_msg
pid_string = msg.text.strip()
if msg.command == "kill_pid":
if pid_string.isdigit():
return_msg = self.kill(int(pid_string))
else:
return_msg = f"Command {msg.command} not understood?"
return_msg = f"{pid_string} is not a PID?"
elif msg.command == "is_pid_alive":
return_msg = self.alive(pid_string)
else:
return_msg = "You are not allowed to use this"
return_msg = f"Command {msg.command} not understood?"
self.send_msg(return_msg)
5 changes: 3 additions & 2 deletions src/pybliotecario/components/scripts.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
For instant, good_morning will call the command defined in
/script good_morning will call the command defined in [SCRIPTS] good_morning
"""

import logging
import pathlib
import shlex
Expand Down Expand Up @@ -121,7 +122,7 @@ def configure_me(cls):
def telegram_message(self, msg):
if not self.check_identity(msg) and not self._allow_everyone:
self.blocked = True
self.send_msg("You are not allowed to run scripts here")
self._not_allowed_msg()
if self.blocked:
return

Expand All @@ -148,7 +149,7 @@ def telegram_message(self, msg):
else:
cmd_list = [f"./{command_path.name}"] + script_args
sp.run(cmd_list, check=True, cwd=command_path.parent)
self.send_msg("Command ran")
self.send_msg("Command ran", quiet=True)
except sp.CalledProcessError:
self.send_msg("Command ran but failed")
else:
Expand Down
1 change: 1 addition & 0 deletions src/pybliotecario/components/stocks.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
},
"""

import json
import logging

Expand Down
4 changes: 2 additions & 2 deletions src/pybliotecario/components/system.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
This component contains system-commands to be run
remotely
"""

import subprocess as sp

from pybliotecario.components.component_core import Component
Expand Down Expand Up @@ -32,8 +33,7 @@ def __init__(self, telegram_object, **kwargs):
def telegram_message(self, msg):
# Allow only the main user to use system
if not self.check_identity(msg):
self.send_msg("You are not allowed to run scripts here")
return
return self._not_allowed_msg()
command_key = msg.text.strip()
command_name = ACCEPTED_COMMANDS.get(command_key)
# Check whether the command is in the accepted_commands dictionary
Expand Down
1 change: 1 addition & 0 deletions src/pybliotecario/components/twitter.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
consumer_secret = <consumer_secret>
```
"""

import logging

import tweepy as tw
Expand Down
5 changes: 3 additions & 2 deletions src/pybliotecario/core_loop.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
This module manages the core loop of the pybliotecario
when it is called with daemon mode -d
"""

from datetime import datetime
import logging
from pathlib import Path
Expand Down Expand Up @@ -109,7 +110,7 @@ def act_on_message(message):
file_path = _monthly_folder(main_folder) / file_name
result = tele_api.download_file(message.file_id, file_path)
if result:
tele_api.send_message("¡Archivo recibido y guardado!", chat_id)
tele_api.send_quiet_message("¡Archivo recibido y guardado!", chat_id)
logger.info("File saved to %s", file_path)
else:
tele_api.send_message("There was some problem with this, sorry", chat_id)
Expand All @@ -119,7 +120,7 @@ def act_on_message(message):
# Otherwise just save the msg to the log and send a funny reply
_write_to_daily_log(main_folder, message.text)
random_msg = still_alive()
tele_api.send_message(random_msg, chat_id)
tele_api.send_quiet_message(random_msg, chat_id)
except_counter = 0
except Exception as e:
logger.error(f"This message produced an exception: {e}")
Expand Down
1 change: 1 addition & 0 deletions src/pybliotecario/customconf.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
Define custom parsers for the config reader
and default data/config locations
"""

from configparser import ConfigParser
from copy import copy
from os import environ
Expand Down
1 change: 1 addition & 0 deletions src/pybliotecario/on_cmd_message.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
This is a design choice as this way it is not necessary to have all dependencies
if you want to run only some submodules of the pybliotecario.
"""

import importlib
import logging

Expand Down
Loading

0 comments on commit f0f4aac

Please sign in to comment.