This forum uses cookies
This forum makes use of cookies to store your login information if you are registered, and your last visit if you are not. Cookies are small text documents stored on your computer; the cookies set by this forum can only be used on this website and pose no security risk. Cookies on this forum also track the specific topics you have read and when you last read them. Please confirm that you accept these cookies being set.

Send image form ip camera to telegram
#1
I have an IP camera working and I can view it trough my logic machine.
The next step I like to reach is to send the snapshot to my telegram.
I have already configured my telegram, I can send messages. But it's impossible to send a snapshot.
I have a DAHUA camera, and the url to view the snapshot is this:
Http: // user: password@cameraip/cgi-bin/snapshot.cgi
I can view it in chrome without problems.
I try to send it with "sendphoto" command and with the example from here, in this case send through email.
https://forum.logicmachine.net/showthread.php?tid=1061

I do not know what else to do. Can someone help me?
Thanks.
Reply
#2
First you need to retrieve the image using http request.
Then you can send the image using this example. filedata variable must contain image data as a string, change PUT_CHAT_ID_HERE and PUT_BOT_TOKEN_HERE placeholders
Code:
require('ssl.https')

boundary = os.date('%d%m%Y%H%M%S')
filedata = '...' -- snapshot image data as a string

params = {
  {
    name = 'chat_id',
    value = 'PUT_CHAT_ID_HERE',
  },
  {
    name = 'photo',
    filename = 'snapshot.jpg',
    ctype = 'image/jpeg',
    value = filedata,
  }
}

body = { '--' .. boundary }

for _, param in ipairs(params) do
  line = string.format('Content-Disposition: form-data; name=%q', param.name)
  if param.filename then
    line = string.format('%s; filename=%q', line, param.filename)
  end
  body[ #body + 1 ] = line

  if param.ctype then
    body[ #body + 1 ] = string.format('Content-Type: %s', param.ctype)
  end

  body[ #body + 1 ] = ''
  body[ #body + 1 ] = param.value
  body[ #body + 1 ] = '--' .. boundary
end

-- last boundary
body[ #body ] = body[ #body ] .. '--'
-- empty line at the end
body[ #body + 1 ] = ''

bodydata = table.concat(body, '\r\n')

resp = {}

log(
  ssl.https.request({
    url = 'https://api.telegram.org/PUT_BOT_TOKEN_HERE/sendPhoto',
    sink = ltn12.sink.table(resp),
    method = 'POST',
    source = ltn12.source.string(bodydata),
    headers = {
      ['content-length'] = #bodydata,
      ['content-type'] = 'multipart/form-data; boundary=' .. boundary
    }
  })
)

log(table.concat(resp))
Reply
#3
Thanks for the answer.
I put my url snapshot on "filedata" and my CHATID and BOT_TOKEN, but it doesn't work.
The log says:


* arg: 1
* number: 1
* arg: 2
* number: 400
* arg: 3
* table:
["server"]
* string: nginx/1.16.1
["access-control-expose-headers"]
* string: Content-Length,Content-Type,Date,Server,Connection
["content-type"]
* string: application/json
["connection"]
* string: close
["content-length"]
* string: 79
["date"]
* string: Thu, 13 Aug 2020 15:18:09 GMT
["strict-transport-security"]
* string: max-age=31536000; includeSubDomains; preload
["access-control-allow-origin"]
* string: *
* arg: 4
* string: HTTP/1.1 400 Bad Request


* string: {"ok":false,"error_code":400,"description":"Bad Request: IMAGE_PROCESS_FAILED"}
Reply
#4
As mentioned before first you need to retrieve the image from your camera via http request. You cannot pass a url to the snapshot here because telegram server cannot access your camera.
Reply
#5
Ok.
As you can see I'm a completely noob with LUA.
I will search info about that.

Thanks again.
Reply
#6
Hello.

I have tried to retrieve the image with no results.
I have used these examples:


https://forum.logicmachine.net/showthrea...tp+request

https://forum.logicmachine.net/showthrea...64#pid9364

Can you explain me how I need to do this?
Thanks in advance.
Reply
#7
Log what you get when sending a request to the camera. Make sure that the URL is correct and it actually returns an image not a HTML page containing the image.
Code:
require('socket.http')
log(socket.http.request('http://user:password@cameraip/cgi-bin/snapshot.cgi'))
Reply
#8
(14.08.2020, 08:08)admin Wrote: Log what you get when sending a request to the camera. Make sure that the URL is correct and it actually returns an image not a HTML page containing the image.
Code:
require('socket.http')
log(socket.http.request('http://user:password@cameraip/cgi-bin/snapshot.cgi'))

Sure:

* arg: 1
  * string:
* arg: 2
  * number: 401
* arg: 3
  * table:
  ["content-length"]
    * string: 0
  ["www-authenticate"]
    * string: Digest realm="Login to 5L02EC8PAGC1BC0", qop="auth", nonce="762101674", opaque="e65481894c6ae41a2f1296db7e53d66882f66471"
  ["connection"]
    * string: close
* arg: 4
  * string: HTTP/1.1 401 Unauthorized
Reply
#9
This means that you need to use digest code example from here: https://forum.logicmachine.net/showthrea...64#pid9364
log what you get from the request:
Code:
url = 'http://user:password@cameraip/cgi-bin/snapshot.cgi'
image, err, hdrs = request(url)
log(image, err, hdrs)
Reply
#10
(14.08.2020, 08:47)admin Wrote: This means that you need to use digest code example from here: https://forum.logicmachine.net/showthrea...64#pid9364
log what you get from the request:
Code:
url = 'http://user:password@cameraip/cgi-bin/snapshot.cgi'
image, err, hdrs = request(url)
log(image, err, hdrs)

With the last code I have not had any records, instead that I had an error:

User script:21: attempt to call global 'request' (a nil value)
stack traceback:
User script:21: in main chunk
Reply
#11
You need to copy the whole code from here: https://forum.logicmachine.net/showthrea...64#pid9364
And change the last lines as in my previous post.
Reply
#12
(14.08.2020, 08:53)admin Wrote: You need to copy the whole code from here: https://forum.logicmachine.net/showthrea...64#pid9364
And change the last lines as in my previous post.

Ok, sorry. This is the log:

Code:
* arg: 1
  * string: ����
Reply
#13
EDIT
It's working, I have to put on filedata, the name without ' '.

Thanks admin.

This is my whole code:
Code:
local skthttp = require('socket.http')
local skturl = require('socket.url')
local ltn12 = require('ltn12')
local md5sum = require('encdec').md5

local hash = function(...)
  return md5sum(table.concat({...}, ':'))
end

local parse_header = function(header)
  local result = {}
  for key, value in (header .. ','):gmatch('(%w+)=(.-),') do
    if value:sub(1, 1) == '"' then -- strip quotes
      result[ key:lower() ] = value:sub(2, -2)
    else
      result[ key:lower() ] = value
    end
  end
  return result
end

local make_digest_header = function(headers)
  local digest = {}
  for _, header in ipairs(headers) do
    if not header.unquote then
      header[ 2 ] = '"' .. header[ 2 ] .. '"'
    end

    digest[ #digest + 1 ] = header[ 1 ] .. '=' .. header[ 2 ]
  end
  return 'Digest ' .. table.concat(digest, ', ')
end

local _request = function(req)
  if not req.url then
    return nil, 'missing url'
  end

  local url = skturl.parse(req.url)
  local user, password = url.user, url.password
  if not user or not password then
    return nil, 'missing credentials in url'
  end

  url.user, url.password, url.authority, url.userinfo = nil, nil, nil, nil
  req.url = skturl.build(url)
  local source
  if req.source then
    local chunks = {}
    local capture = function(chunk)
      if chunk then
        chunks[ #chunks + 1 ] = chunk
      end
      return chunk
    end
    local chunk_id = 0
    source = function()
      chunk_id = chunk_id + 1
      return chunks[ chunk_id ]
    end
    req.source = ltn12.source.chain(req.source, capture)
  end
  local body, code, hdrs = skthttp.request(req)
  if code == 401 and hdrs['www-authenticate'] then
    local ht = parse_header(hdrs['www-authenticate'])
    if not ht.realm or not ht.nonce then
      return nil, 'missing realm/nonce from response'
    end
    if ht.qop ~= 'auth' then
      return nil, 'unsupported qop ' .. tostring(ht.qop)
    end
    if ht.algorithm and ht.algorithm:lower() ~= 'md5' then
      return nil, 'unsupported algo ' .. tostring(ht.algorithm)
    end
    local nc = '00000001'
    local cnonce = string.format('%08x', os.time())
    local uri = skturl.build({ path = url.path, query = url.query })
    local method = req.method or 'GET'
    local response = hash(
      hash(user, ht.realm, password),
      ht.nonce,
      nc,
      cnonce,
      'auth',
      hash(method, uri)
    )
    req.headers = req.headers or {}
    local auth = {
      { 'username', user },
      { 'realm', ht.realm },
      { 'nonce', ht.nonce },
      { 'uri', uri },
      { 'cnonce', cnonce },
      { 'nc', nc, unquote = true },
      { 'qop', 'auth' },
      { 'algorithm', 'MD5' },
      { 'response', response },
    }
    if ht.opaque then
      table.insert(auth, { 'opaque', ht.opaque })
    end
    req.headers.authorization = make_digest_header(auth)
    if not req.headers.cookie and hdrs['set-cookie'] then
      -- not really correct but enough for httpbin
      local cookie = (hdrs['set-cookie'] .. ';'):match('(.-=.-)[;,]')
      if cookie then
        req.headers.cookie = '$Version: 0; ' .. cookie .. ';'
      end
    end
    if req.source then
      req.source = source
    end
    body, code, hdrs = skthttp.request(req)
  end

  return body, code, hdrs
end

local request = function(url)
  local t = type(url)
  if t == 'table' then
    return _request(table.clone(url))
  elseif t == 'string' then
    local req = {}
    local _, code, headers = _request({ url = url, sink = ltn12.sink.table(req) })
    return table.concat(req), code, headers
  end
end

url = 'http://USER:PASS@CAM IP/cgi-bin/snapshot.cgi?1&ts=123/snapshot.jpeg'
image, err, hdrs = request(url)
log(image, err, hdrs)


require('ssl.https')

boundary = os.date('%d%m%Y%H%M%S')
filedata = image -- snapshot image data as a string

params = {
  {
    name = 'chat_id',
    value = 'MY CHAT ID',
  },
  {
    name = 'photo',
    filename = 'snapshot.jpg',
    ctype = 'image/jpeg',
    value = filedata,
  }
}

body = { '--' .. boundary }

for _, param in ipairs(params) do
  line = string.format('Content-Disposition: form-data; name=%q', param.name)
  if param.filename then
    line = string.format('%s; filename=%q', line, param.filename)
  end
  body[ #body + 1 ] = line

  if param.ctype then
    body[ #body + 1 ] = string.format('Content-Type: %s', param.ctype)
  end

  body[ #body + 1 ] = ''
  body[ #body + 1 ] = param.value
  body[ #body + 1 ] = '--' .. boundary
end

-- last boundary
body[ #body ] = body[ #body ] .. '--'
-- empty line at the end
body[ #body + 1 ] = ''

bodydata = table.concat(body, '\r\n')

resp = {}

log(
  ssl.https.request({
    url = 'https://api.telegram.org/MY BOT/sendPhoto',
    sink = ltn12.sink.table(resp),
    method = 'POST',
    source = ltn12.source.string(bodydata),
    headers = {
      ['content-length'] = #bodydata,
      ['content-type'] = 'multipart/form-data; boundary=' .. boundary
    }
  })
)

log(table.concat(resp))
Reply
#14
This line is incorrect:
Code:
filedata = 'image'

It should be
Code:
filedata = image
Reply
#15
(14.08.2020, 11:08)admin Wrote: This line is incorrect:
Code:
filedata = 'image'

It should be
Code:
filedata = image

Yes, I just put it in my previous post. Thank you very much again.
Reply


Forum Jump: