Compare commits

...

16 Commits

Author SHA1 Message Date
drymer fcf8436fca
Bump version 2018-11-07 20:57:10 +01:00
drymer f219cc07b8 Merge branch 'dev' of drymer/jabbergram into master 2017-07-21 09:09:42 +02:00
drymer 220cc1e26e Bump version 2017-07-21 08:56:44 +02:00
drymer 2b47e3528d Merge branch 'dev' of drymer/jabbergram into master 2017-07-21 08:29:37 +02:00
drymer 2679ad6f2e Adapt to telegram-bot api's change 2017-07-18 22:38:36 +02:00
drymer 002df9336e Adapt to changes in telegram's api 2017-07-09 03:07:57 +02:00
drymer fe1cc0eed9 Fix typo 2017-07-09 03:04:15 +02:00
drymer fca55ee84b Add docstrings 2017-07-08 21:46:10 +02:00
drymer 7f2c2513cf Rearrange imports to adapt it to pep8 2017-07-08 21:45:07 +02:00
drymer 1453f3955f Change repository's url 2017-07-08 19:51:07 +02:00
drymer c5505f8eef Upload stickers with http upload
And fix minor things
2017-04-30 22:12:40 +02:00
drymer ed6d8a142e Make it clearer 2017-04-30 21:42:17 +02:00
drymer cdb54ef612 Fix typo 2017-04-30 21:41:11 +02:00
drymer 9e4e5d3852 Fix the "answer" option and some minor things 2017-02-22 17:12:11 +00:00
drymer d926f974b7 Add name when replying 2017-01-29 02:47:46 +00:00
drymer fa9c44b45c Add commands and support using name on telegram group name 2017-01-27 10:04:36 +00:00
7 changed files with 180 additions and 100 deletions

View File

@ -48,7 +48,7 @@ Install via pip:
Clone the repository:
$ git clone git://daemons.cf/jabbergram
$ git clone https://git.daemons.it/drymer/jabbergram
$ cd jabbergram
$ su -c "pip3 install -r requirements.txt"
$ su -c "python3 setup.py install"
@ -128,9 +128,9 @@ Instalar a través de `pip`:
Clonar el repositorio:
$ git clone git://daemons.cf/jabbergram
$ git clone https://git.daemons.it/drymer/jabbergram
$ cd jabbergram
$ su -c "pip3 instalar -r requirements.txt"
$ su -c "pip3 install -r requirements.txt"
$ su -c "python3 setup.py install"
### Configuración<a id="orgheadline9"></a>
@ -145,7 +145,7 @@ Este programa es simple, no tiene ni un menú de `ayuda`. Lo primero que hay que
NombreDelBot
# Ahora hay que pulsar desactivar
La opción `/setprivacy` es para hacer que el robot pueda leer todo lo que se dice en el grupo, no sólo cuando se utilizan los comandos. Es necesario para hacer que `jabbergram` funcione. Más información sobre la creación los bots de `Telegrama` en su [página web](https://core.telegram.org/bots).
La opción `/setprivacy` es para hacer que el robot pueda leer todo lo que se dice en el grupo, no sólo cuando se utilizan los comandos. Es necesario para hacer que `jabbergram` funcione. Más información sobre la creación los bots de `Telegram` en su [página web](https://core.telegram.org/bots).
A continuación, hay que crear un archivo de configuración, que llamaremos `config.ini`. En ese archivo, introduce los siguientes parámetros:
@ -173,7 +173,7 @@ Sólo puede haber un archivo de configuración. Esto es debido a que sólo puede
token = jabbergramBotTokken
group = -10293943920 120301203
De este modo, el muc "exampleMuc@muc.nope.org" se sincronizará con el grupo "-10293943920", y "segunda@muc.sip.org" con "120301203".
De este modo, el muc "exampleMuc@muc.nope.org" se sincronizará con el grupo "-10293943920", y "segunda@muc.sip.org" con "120301203". Hecho esto, solo queda ejecutarlo en la terminal: `python3 jabbergram.py config.ini`. Hay que tenerla activa siempre que se quiera que funcione, obviamente.
### Licencia<a id="orgheadline11"></a>

View File

@ -14,7 +14,7 @@
Clone the repository:
#+BEGIN_SRC sh
$ git clone git://daemons.cf/jabbergram
$ git clone https://git.daemons.it/drymer/jabbergram
$ cd jabbergram
$ su -c "pip3 install -r requirements.txt"
$ su -c "python3 setup.py install"
@ -93,9 +93,9 @@
Clonar el repositorio:
#+BEGIN_SRC sh
$ git clone git://daemons.cf/jabbergram
$ git clone https://git.daemons.it/drymer/jabbergram
$ cd jabbergram
$ su -c "pip3 instalar -r requirements.txt"
$ su -c "pip3 install -r requirements.txt"
$ su -c "python3 setup.py install"
#+END_SRC
*** Configuración
@ -111,7 +111,7 @@
# Ahora hay que pulsar desactivar
#+END_SRC
La opción =/setprivacy= es para hacer que el robot pueda leer todo lo que se dice en el grupo, no sólo cuando se utilizan los comandos. Es necesario para hacer que =jabbergram= funcione. Más información sobre la creación los bots de =Telegrama= en su [[https://core.telegram.org/bots][página web]].
La opción =/setprivacy= es para hacer que el robot pueda leer todo lo que se dice en el grupo, no sólo cuando se utilizan los comandos. Es necesario para hacer que =jabbergram= funcione. Más información sobre la creación los bots de =Telegram= en su [[https://core.telegram.org/bots][página web]].
A continuación, hay que crear un archivo de configuración, que llamaremos =config.ini=. En ese archivo, introduce los siguientes parámetros:
@ -141,7 +141,7 @@
group = -10293943920 120301203
#+END_SRC
De este modo, el muc "exampleMuc@muc.nope.org" se sincronizará con el grupo "-10293943920", y "segunda@muc.sip.org" con "120301203".
De este modo, el muc "exampleMuc@muc.nope.org" se sincronizará con el grupo "-10293943920", y "segunda@muc.sip.org" con "120301203". Hecho esto, solo queda ejecutarlo en la terminal: =python3 jabbergram.py config.ini=. Hay que tenerla activa siempre que se quiera que funcione, obviamente.
*** Licencia
#+BEGIN_SRC text
This program is free software: you can redistribute it and / or modify

View File

@ -31,7 +31,7 @@ Clone the repository:
.. code-block:: sh
:number-lines: 0
$ git clone git://daemons.cf/jabbergram
$ git clone https://git.daemons.it/drymer/jabbergram
$ cd jabbergram
$ su -c "pip3 install -r requirements.txt"
$ su -c "python3 setup.py install"
@ -135,7 +135,7 @@ Clonar el repositorio:
.. code-block:: sh
:number-lines: 0
$ git clone git://daemons.cf/jabbergram
$ git clone https://git.daemons.it/drymer/jabbergram
$ cd jabbergram
$ su -c "pip3 instalar -r requirements.txt"
$ su -c "python3 setup.py install"

View File

@ -1,33 +1,42 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import configparser
import logging
from sys import argv
from threading import Thread
from time import sleep
from xml.dom import minidom
import sleekxmpp
import telegram
from sleekxmpp.xmlstream.stanzabase import ElementBase
from telegram.error import NetworkError, Unauthorized
try:
import requests
except:
print("HTTP Upload support disabled.")
import sleekxmpp
import telegram
import configparser
from threading import Thread
from queue import Queue
from telegram.error import NetworkError, Unauthorized
from time import sleep
from sys import argv
from sys import exit
from sleekxmpp.xmlstream.stanzabase import ElementBase
from sleekxmpp.stanza.iq import Iq
from xml.dom import minidom
logging.error("HTTP Upload support disabled.")
class Request(ElementBase):
"""Special class to create http_upload requests."""
namespace = 'urn:xmpp:http:upload'
name = 'request'
plugin_attrib = 'request'
interfaces = set(('filename', 'size'))
sub_interfaces = interfaces
class Jabbergram(sleekxmpp.ClientXMPP):
def __init__(self, jid, password, rooms, nick, token, groups):
"""Main object."""
def __init__(self, jid, password, rooms, nick, token, groups, verify_ssl):
"""
Executed when the class is initialized. It adds session handlers, muc
handlers and send the telegram reading function and the HTTP upload
initializing functions to their respective threads.
"""
# XMPP
super(Jabbergram, self).__init__(jid, password)
self.add_event_handler('session_start', self.start)
@ -38,6 +47,7 @@ class Jabbergram(sleekxmpp.ClientXMPP):
self.token = token
self.xmpp_users = {}
self.jid = jid
self.verify_ssl = verify_ssl
for muc in self.muc_rooms:
self.add_event_handler("muc::%s::got_online" % muc,
@ -65,6 +75,11 @@ class Jabbergram(sleekxmpp.ClientXMPP):
'connected')
def init_http(self):
"""
Initializes HTTP upload support. Sends a discovery stanza to the server
to find the HTTP upload component and asks for the max size a file can
be.
"""
self.http_upload = self.HttpUpload(self)
self.component = self.http_upload.discovery()
@ -84,6 +99,7 @@ class Jabbergram(sleekxmpp.ClientXMPP):
self.max_size = None
def read_tg(self):
"""Main telegram function."""
update_id = 0
# wait until http_upload has been tested
@ -92,12 +108,29 @@ class Jabbergram(sleekxmpp.ClientXMPP):
try:
for update in self.bot.getUpdates(offset=update_id,
timeout=10):
name = ''
size = 0
if update.edited_message:
update_id = update.update_id + 1
continue
if update.message.from_user:
user = update.message.from_user.username
# sometimes there's no user. weird, but it happens
if not user:
user = update.message.from_user.first_name
# sometimes there's no user. weird, but it happens
elif update.message['from']:
user = str(update.message['from'].first_name)
if update.message.audio or update.message.document or \
update.message.photo or update.message.video \
or update.message.voice:
or update.message.voice or update.message.sticker:
# proceed only if http upload is available
if self.max_size is not None:
if update.message.audio:
d_file = update.message.audio
@ -119,13 +152,18 @@ class Jabbergram(sleekxmpp.ClientXMPP):
d_file = update.message.voice
ext = '.ogg'
size = d_file.file_size
if self.max_size >= size:
elif update.message.sticker:
d_file = update.message.sticker
ext = '.png'
size = d_file.file_size
if self.max_size >= int(size):
t_file = self.bot.getFile(d_file.file_id)
name = '/tmp/' + d_file.file_id + ext
t_file.download(name)
f_name = '/tmp/' + d_file.file_id + ext
t_file.download(f_name)
url = self.http_upload.upload(
self.component,
'', name, size)
self.component,
self.verify_ssl,
f_name, size)
if update.message.caption:
message = update.message.caption + ' '
@ -134,52 +172,65 @@ class Jabbergram(sleekxmpp.ClientXMPP):
message += url
else:
message = 'A file has been uploaded to Telegra'
'm, but is too big.'
message = 'A file has been uploaded to Telegr'\
'am, but is too big.'
else:
message = 'A file has been uploaderd to Telegram, '
'but the XMPP server doesn\'t support HTTP Upload.'
message = 'A file has been uploaded to Telegram,'\
'but the XMPP server doesn\'t support H'\
'TTP Upload.'
elif update.message.new_chat_member:
elif update.message.new_chat_members:
message = 'This user has joined the group.'
elif update.message.left_chat_member:
message = 'This user has left the group.'
elif update.message.new_chat_title:
message = 'The group\'s title has changed: '+ \
message = 'The group\'s title has changed: ' + \
update.message.new_chat_title
elif update.message.new_chat_photo:
message = 'The group\'s photo haschanged.'
message = 'The group\'s photo has changed.'
else:
message = update.message.text
if update.message.reply_to_message:
name = update.message.reply_to_message.from_user\
.username
if name != self.bot.username:
message = name + ': ' + \
update.message.reply_to_message.text
else:
message = update.message.reply_to_message.text
else:
message = update.message.text
user = str(update.message.from_user.username)
if name:
msg = message + ' <- ' + user + ": " + \
update.message.text
else:
msg = user + ": " + message
# sometimes there's no user. weird, but it happens
if not user:
user = str(update.message.from_user.first_name)
if update.message.chat.type == 'supergroup' and \
update.message.chat.username:
chat = '@' + update.message.chat.username
else:
chat = str(update.message.chat.id)
# even weirder is that username or first_name exists
# let's take last_name
if not user:
user = str(update.message.from_user.last_name)
if chat not in self.groups:
chat = str(update.message.chat_id)
msg = user + ": " + message
chat_id = update.message.chat_id
if message and str(chat_id) in self.groups:
index = self.groups.index(str(chat_id))
if message and chat in self.groups:
index = self.groups.index(chat)
receiver = self.muc_rooms[index]
if chat_id in self.telegram_users:
if user not in self.telegram_users[chat_id]:
self.telegram_users[chat_id] += ' ' + user
if chat in self.telegram_users:
if user not in self.telegram_users[chat]:
self.telegram_users[chat] += ' ' + user
else:
self.telegram_users[chat_id] = ' ' + user
self.telegram_users[chat] = ' ' + user
if message == '.users':
index = self.groups.index(str(chat_id))
muc = self.muc_rooms[index]
self.say_users('telegram', muc, chat_id)
self.say_users('telegram', receiver, chat)
elif message == '.help':
self.say_help('telegram', receiver, chat)
elif message == '.where':
self.say_where('telegram', receiver, chat)
else:
self.send_message(mto=receiver, mbody=msg,
mtype='groupchat')
@ -189,7 +240,7 @@ class Jabbergram(sleekxmpp.ClientXMPP):
print(e)
sleep(1)
except Unauthorized:
except Unauthorized as e:
print(e)
sleep(1)
@ -198,6 +249,7 @@ class Jabbergram(sleekxmpp.ClientXMPP):
print(e)
def start(self, event):
"""Does some initial setup for XMPP and joins all mucs."""
self.get_roster()
self.send_presence()
@ -205,18 +257,23 @@ class Jabbergram(sleekxmpp.ClientXMPP):
self.plugin['xep_0045'].joinMUC(muc, self.nick, wait=True)
def muc_message(self, msg):
"""Muc message's handler."""
muc_room = str(msg['from']).split('/')[0]
index = self.muc_rooms.index(muc_room)
tg_group = self.groups[index]
if msg['body'] == '.users':
self.say_users('xmpp', muc_room, tg_group)
elif msg['body'] == '.help':
self.say_help('xmpp', muc_room, tg_group)
elif msg['body'] == '.where':
self.say_where('xmpp', muc_room, tg_group)
elif msg['mucnick'] != self.nick:
message = str(msg['from']).split('/')[1] + ': ' + str(msg['body'])
self.bot.sendMessage(tg_group, text=message)
def muc_online(self, presence):
"""Muc presence's handler."""
user = presence['muc']['nick']
muc = presence['from'].bare
@ -227,6 +284,7 @@ class Jabbergram(sleekxmpp.ClientXMPP):
self.xmpp_users[muc] = [presence['muc']['nick']]
def muc_offline(self, presence):
"""Muc presence's handler."""
user = presence['muc']['nick']
muc = presence['from'].bare
@ -234,39 +292,58 @@ class Jabbergram(sleekxmpp.ClientXMPP):
self.xmpp_users[muc].remove(presence['muc']['nick'])
def say_users(self, service, muc, group):
xmpp_users = ""
tg_users = ""
group = int(group)
if muc in self.xmpp_users:
for i in self.xmpp_users[muc]:
xmpp_users = xmpp_users + ' _' + i
else:
xmpp_users = ""
msg1 = 'XMPP Users:' + xmpp_users
if group in self.telegram_users:
tg_users = self.telegram_users[group]
else:
tg_users = ""
msg2 = 'Telegram Users:' + tg_users
message = msg1 + '\n' + msg2
"""It returns the users on XMPP or Telegram."""
if service == 'xmpp':
self.send_message(mto=muc, mbody=message, mtype='groupchat')
if group in self.telegram_users:
tg_users = self.telegram_users[group]
else:
tg_users = ""
msg = 'Telegram Users:' + tg_users
self.send_message(mto=muc, mbody=msg, mtype='groupchat')
elif service == 'telegram':
self.bot.sendMessage(group, text=message)
xmpp_users = ""
if muc in self.xmpp_users:
for i in self.xmpp_users[muc]:
xmpp_users = xmpp_users + ' ' + i
else:
xmpp_users = ""
msg = 'XMPP Users:' + xmpp_users
self.bot.sendMessage(group, text=msg)
def say_help(self, service, muc, group):
"""Help command."""
msg = 'Hi, I\'m ' + self.bot.username + '. I have two commands : ".us'\
'ers" and ".where".'
if service == 'xmpp':
self.send_message(mto=muc, mbody=msg, mtype='groupchat')
elif service == 'telegram':
self.bot.sendMessage(group, text=msg)
def say_where(self, service, muc, group):
"""Returns Telegram's group location if it's public."""
if service == 'xmpp':
if '@' in group:
msg = 'I\'m on http://telegram.me/' + group.split('@')[1] + '.'
else:
msg = 'Sorry, I\'m on a private group, you\'ll have to ask fo'\
'r an invitation.'
self.send_message(mto=muc, mbody=msg, mtype='groupchat')
elif service == 'telegram':
msg = 'I\'m on ' + muc + '.'
self.bot.sendMessage(group, text=msg)
class HttpUpload():
"""HTTP upload main class."""
def __init__(self, parent_self):
"""Init... Yep."""
self.parent_self = parent_self
def discovery(self):
"""Discovers all server's components."""
disco = sleekxmpp.basexmpp.BaseXMPP.Iq(self.parent_self)
disco['query'] = "http://jabber.org/protocol/disco#items"
disco['type'] = 'get'
@ -290,17 +367,18 @@ class Jabbergram(sleekxmpp.ClientXMPP):
return http_upload_component
def disco_info(self, component):
"""Discovers HTTP upload components attributes."""
info = sleekxmpp.basexmpp.BaseXMPP.Iq(self.parent_self)
info['query'] = "http://jabber.org/protocol/disco#info"
info['type'] = 'get'
info['from'] = self.parent_self.jid
info['to'] = component
response = str(info.send(timeout=30))
return str(info.send(timeout=30))
return response
def upload(self, component, verify_ssl, u_file, size):
"""Uploads to HTTP upload."""
peticion = Request()
peticion['filename'] = u_file.split('/')[-1]
peticion['size'] = str(size)
@ -316,7 +394,6 @@ class Jabbergram(sleekxmpp.ClientXMPP):
xml = minidom.parseString(str(send))
put_url = xml.getElementsByTagName('put')[0].firstChild.data
verify_ssl = ''
if verify_ssl == 'False':
req = requests.put(put_url, data=open(u_file, 'rb'),
verify=False)
@ -347,8 +424,10 @@ if __name__ == '__main__':
nick = config[3]
token = config[4]
groups = config[5]
verify_ssl = config[6]
xmpp = Jabbergram(jid, password, muc_rooms, nick, token, groups)
xmpp = Jabbergram(jid, password, muc_rooms, nick, token, groups,
verify_ssl)
xmpp.register_plugin('xep_0045')
if xmpp.connect():
@ -356,5 +435,3 @@ if __name__ == '__main__':
print("Done")
else:
print("Unable to connect.")
# Vols un gram nen?

View File

@ -1,3 +1,3 @@
sleekxmpp >= 1.3.1
python-telegram-bot >= 4.0.3
sleekxmpp >= 1.3.2
python-telegram-bot >= 6.1.0
requests >= 2.11.1

View File

@ -30,6 +30,9 @@ printed = []
while True:
try:
for update in bot.getUpdates(offset=update_id, timeout=10):
if update.edited_message:
update_id = update.update_id + 1
continue
chat_id = update.message.chat_id
chat_title = update.message
if chat_id not in printed:

View File

@ -2,7 +2,7 @@
from setuptools import setup
VERSION = '0.1.6'
VERSION = '0.1.8'
setup(name='jabbergram',
version=VERSION,
@ -10,13 +10,13 @@ setup(name='jabbergram',
long_description=open('README.rst', encoding='utf-8').read(),
author='drymer',
author_email='drymer@autistici.org',
url='http://daemons.cf/cgit/jabbergram/about/',
download_url='http://daemons.cf/cgit/jabbergram/snapshot/jabbergram-' + VERSION + '.tar.gz',
url='http://git.daemons.it/drymer/jabbergram/about/',
download_url='https://git.daemons.it/drymer/jabbergram/archive/' + VERSION + '.tar.gz',
scripts=['jabbergram.py'],
license="GPLv3",
install_requires=[
"sleekxmpp>=1.3.1",
"python-telegram-bot>=4.0.3",
"python-telegram-bot>=6.0.1",
"requests>=2.11.1",
],
classifiers=["Development Status :: 4 - Beta",