📜 ⬆️ ⬇️

Jabber webcam bot

This idea came to me somehow by chance. Get a snapshot of a webcam that is at home, being at work or in another city and not sharing the camera via the web ... And not connecting via ssh ... It's funny ... What if you get it in one request in jabber! It sounds crazy, but I started to implement this nonsense!

All of the above does not pretend to manual or instruction to action. Repetition of these dances with a tambourine can damage your technique or your brain. So be careful)
So, for starters, I learned what means to combat Jabber exist. First I looked for libraries for Java. There is a choice, but for some reason, everything is quite difficult to do, and something does not work with individual servers (jabber.ru, for example). Therefore, I began to choose from this list . The choice fell on ... Ruby) Firstly, because I do not know him, secondly, because of the simplicity of the first example. As a result, I stopped at xmpp4r . In the chop, I am a complete novice, so you can safely criticize and throw tomatoes) Code in the studio:
#!/usr/bin/ruby
require 'xmpp4r/client'

include Jabber

class BasicClient
MSG_DEFAULT= "If your see this message you client doesn`t support html"
MSG_DENIED= "Access denied!"

def initialize(args)
puts(args[0])
puts "Jabber WebCamBot initializing"
@my_jid=args[0]
@my_pwd=args[1]
@user_jid=args[2]
if args[3] == "debug"
Jabber::debug = true
end
puts "Will connect to " + @my_jid + " and accept messages only from " + @user_jid
do_connect
do_auth
start_work
end

def do_connect()
@jid = JID. new (@my_jid)
@cl = Client. new (@jid)
@cl.connect
end

def do_auth
@cl.auth(@my_pwd)
presense = Presence. new (:dnd, "server running" )
@cl.send(presense)
end

def start_work
mainthread = Thread.current
@cl.add_message_callback do |m|
if m.type != :error
msg_jid=m. from .node + "@" + m. from .domain
puts(msg_jid)
if msg_jid != @user_jid
puts( "Unknown user" )
m2 = Message. new (m. from , MSG_DENIED)
@cl.send(m2)
else
get_image
m2 = Message. new (m. from , MSG_DEFAULT)
m2.type = m.type
h = REXML::Element:: new ( "html" )
h.add_namespace( 'http://jabber.org/protocol/xhtml-im' )

b = REXML::Element:: new ( "body" )
b.add_namespace( 'http://www.w3.org/1999/xhtml' )

t = REXML::Text. new ( @cam_image,
false , nil, true , nil, %r/.^/ )
b.add(t)
h.add(b)
m2.add_element(h)
puts(m. from )
@cl.send(m2)
end
end
end
Thread.stop
end

def get_image
system( "./make.img" )
image_file = File . new ( "data.html" , "r" )
@cam_image = image_file.read()
end
end

BasicClient. new (ARGV)


The script is passed 4 arguments:


The essence of this code is that it connects to the server and waits until it receives a message from a certain known user (tobish me, who is at work). When this message is received, the script runs an external command ./make.img (it will be described in detail later) and forms, based on the data.html file generated by it, a jabber message, which contains our image in the html tag.
')
Here we come to the most interesting. How to transfer a picture to see it? My initial idea was to use ascii-art. But, having tried, I realized that to see something would be unreal. Therefore, we need to pass an html img tag with data encapsulated into it (via base64 encoding). The make.img script will help us generate such a package:

#!/bin/bash

uvccapture -mv -o out.jpg
convert out.jpg -quality 20 out.jpg
IMG=$(cat out.jpg | base64)
DATE=$(date -R)
echo "Created: $DATE < br />< img src =\ "data:image/png;base64,$IMG\" /> " > data.html


This script captures the image from the camera (uvccapture - there may be a thousand options, everyone chooses the capture tool that works for him. I have already earned uvccture). Next, we reduce the quality of it through ImageMagick (do we need a high-quality image in Jabber?), Then we do base64 encoding and form an html message.

But this is only half the battle. We need to see this message somewhere else. I found only one client who frivolously shows pictures in messages. This is synapse . He appeared recently, and about him recently wrote on Habré . It works quite simply, though a certain amount of time passes between the request for receiving the picture and the drawing - it's unclear because of what ... Well, in the end, I present a screenshot of our conversation with the bot:
webcambot

PS Of course, you can say that it is better than to engage in such nonsense to look for a solution to NP-complex problems, to optimize algorithms of computational physics, or to create start-ups. Maybe, but the thing turned out to be funny)
PPS I hope the code is not absolutely terrible and there are not many ochepyatok in the text)

Source: https://habr.com/ru/post/56684/


All Articles