105 lines
4.3 KiB
C
105 lines
4.3 KiB
C
#include "photo_sender.h"
|
|
#include "instance_lite.h"
|
|
#include "../../../lib/debug_config.h"
|
|
#include "../../../lib/mem.h"
|
|
#include "../../../lib/u_async.h"
|
|
#include "../../../src/chat/chat_core.h"
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <ctype.h>
|
|
#include <time.h>
|
|
#include <sys/stat.h>
|
|
#include <unistd.h>
|
|
#include <libgen.h>
|
|
|
|
int photo_send(const char* channel_id, const char* src_file_path, const char* db_path,
|
|
int width, int height, const uint8_t reply_to[32], uint64_t request_id) {
|
|
if (!channel_id || !src_file_path || !db_path) {
|
|
DEBUG_ERROR(DEBUG_CATEGORY_GENERAL, "photo_send: invalid args");
|
|
return -1;
|
|
}
|
|
|
|
struct UASYNC* ua = instance_lite_get_uasync();
|
|
if (!uasync_is_running(ua)) { DEBUG_ERROR(DEBUG_CATEGORY_GENERAL, "photo_send: core stopped"); return -1; }
|
|
|
|
struct stat st; memset(&st, 0, sizeof(st));
|
|
if (stat(src_file_path, &st) != 0 || st.st_size <= 0) {
|
|
DEBUG_ERROR(DEBUG_CATEGORY_GENERAL, "photo_send: source not found or empty: %s", src_file_path);
|
|
return -1;
|
|
}
|
|
|
|
char path_copy[1024];
|
|
snprintf(path_copy, sizeof(path_copy), "%s", src_file_path);
|
|
char* fname = basename(path_copy);
|
|
char original_basename[256];
|
|
snprintf(original_basename, sizeof(original_basename), "%s", fname);
|
|
char* dot = strrchr(fname, '.');
|
|
char ext[32] = "";
|
|
if (dot) { snprintf(ext, sizeof(ext), "%s", dot + 1); *dot = '\0'; }
|
|
for (char* p = ext; *p; p++) *p = (char)tolower((unsigned char)*p);
|
|
|
|
const char* content_type = "image/jpeg";
|
|
const char* use_ext = "jpg";
|
|
if (strcmp(ext, "png") == 0) { content_type = "image/png"; use_ext = "png"; }
|
|
else if (strcmp(ext, "gif") == 0) { content_type = "image/gif"; use_ext = "gif"; }
|
|
else if (strcmp(ext, "bmp") == 0) { content_type = "image/bmp"; use_ext = "bmp"; }
|
|
else if (strcmp(ext, "webp") == 0) { content_type = "image/webp"; use_ext = "webp"; }
|
|
else if (strcmp(ext, "jpeg") == 0) { use_ext = "jpeg"; }
|
|
|
|
time_t t = time(NULL);
|
|
struct tm tm_buf; localtime_r(&t, &tm_buf);
|
|
char dt[32]; snprintf(dt, sizeof(dt), "%04d%02d%02d-%02d%02d%02d",
|
|
tm_buf.tm_year + 1900, tm_buf.tm_mon + 1, tm_buf.tm_mday,
|
|
tm_buf.tm_hour, tm_buf.tm_min, tm_buf.tm_sec);
|
|
int rnd = rand() & 0xFFFF;
|
|
char suffix[8]; snprintf(suffix, sizeof(suffix), "%04x", rnd);
|
|
|
|
/* ensure media dir exists */
|
|
char media_dir[1024];
|
|
snprintf(media_dir, sizeof(media_dir), "%s/media/%s", db_path, channel_id);
|
|
{
|
|
char tmp[1024]; size_t off = 0;
|
|
for (size_t i = 0; media_dir[i] && off < sizeof(tmp) - 1; i++) {
|
|
tmp[off++] = media_dir[i];
|
|
if (media_dir[i] == '/' && off > 1) { tmp[off] = '\0'; mkdir(tmp, 0755); }
|
|
}
|
|
tmp[off] = '\0';
|
|
mkdir(tmp, 0755);
|
|
}
|
|
|
|
char media_file[1024];
|
|
snprintf(media_file, sizeof(media_file), "%s/%s_%s_%s.%s", media_dir, dt, fname, suffix, use_ext);
|
|
|
|
size_t datalen = strlen(original_basename);
|
|
struct chat_msg_submit* req = u_calloc(1, sizeof(struct chat_msg_submit) + datalen + 1);
|
|
struct posted_task* post = u_calloc(1, sizeof(*post));
|
|
if (!req || !post) {
|
|
DEBUG_ERROR(DEBUG_CATEGORY_MEDIA, "photo_send: allocation failed"); u_free(req); u_free(post); return -1;
|
|
}
|
|
|
|
req->inst = instance_lite_get_instance();
|
|
memcpy(req->reply_to, reply_to, sizeof(req->reply_to));
|
|
req->request_id = request_id;
|
|
snprintf(req->channel_id, sizeof(req->channel_id), "%s", channel_id);
|
|
snprintf(req->content_type, sizeof(req->content_type), "%s", content_type);
|
|
snprintf(req->media_src, sizeof(req->media_src), "%s", src_file_path);
|
|
snprintf(req->media_dest, sizeof(req->media_dest), "%s", media_file);
|
|
req->media_copy = 1;
|
|
req->media_video = 0;
|
|
req->width = width;
|
|
req->height = height;
|
|
req->data = (uint8_t*)(req + 1);
|
|
memcpy(req->data, original_basename, datalen);
|
|
req->data_len = (uint32_t)datalen;
|
|
req->timestamp = 0;
|
|
|
|
DEBUG_INFO(DEBUG_CATEGORY_GENERAL, "photo_send: ch=%s ct=%s src=%s dst=%s name=%s size=%lld %dx%d",
|
|
channel_id, content_type, src_file_path, media_file, original_basename,
|
|
(long long)st.st_size, width, height);
|
|
|
|
post->callback = chat_core_submit_trampoline; post->arg = req;
|
|
uasync_post_reserved(ua, post);
|
|
return 0;
|
|
}
|