@comasoft/nestjs 0.2.27 β 0.2.28
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
|
@@ -1,22 +1,19 @@
|
|
|
1
1
|
import { ConfigService } from '@nestjs/config';
|
|
2
2
|
import { RedisService } from '../../redis';
|
|
3
|
+
interface KakaoMessage {
|
|
4
|
+
recipient: string;
|
|
5
|
+
user_id: number;
|
|
6
|
+
sender_key?: string;
|
|
7
|
+
template_code?: string;
|
|
8
|
+
template_meta?: any;
|
|
9
|
+
message: string;
|
|
10
|
+
}
|
|
3
11
|
export declare class KakaoService {
|
|
4
12
|
private readonly configService;
|
|
5
13
|
private readonly redis;
|
|
6
14
|
constructor(configService: ConfigService, redis: RedisService);
|
|
7
|
-
send(recipients: Array<
|
|
8
|
-
|
|
9
|
-
user_id: number;
|
|
10
|
-
sender_key: string;
|
|
11
|
-
template_code: string;
|
|
12
|
-
message: string;
|
|
13
|
-
}>): Promise<any[]>;
|
|
14
|
-
sendAligo(recipients: Array<{
|
|
15
|
-
recipient: string;
|
|
16
|
-
user_id: number;
|
|
17
|
-
template_code: string;
|
|
18
|
-
variables?: Record<string, any>;
|
|
19
|
-
}>): Promise<{
|
|
15
|
+
send(recipients: Array<KakaoMessage>): Promise<any[]>;
|
|
16
|
+
sendAligo(recipients: Array<KakaoMessage>): Promise<{
|
|
20
17
|
user_id: number;
|
|
21
18
|
recipient: string;
|
|
22
19
|
success: boolean;
|
|
@@ -24,18 +21,10 @@ export declare class KakaoService {
|
|
|
24
21
|
status: string;
|
|
25
22
|
}[]>;
|
|
26
23
|
private getPpurioToken;
|
|
27
|
-
sendPpurioMessage(recipient:
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
message: string;
|
|
33
|
-
}): Promise<any>;
|
|
34
|
-
sendPpurio(recipients: Array<{
|
|
35
|
-
recipient: string;
|
|
36
|
-
user_id: number;
|
|
37
|
-
sender_key: string;
|
|
38
|
-
template_code: string;
|
|
39
|
-
message: string;
|
|
40
|
-
}>): Promise<any[]>;
|
|
24
|
+
sendPpurioMessage(recipient: KakaoMessage): Promise<any>;
|
|
25
|
+
sendPpurio(recipients: Array<KakaoMessage>): Promise<any[]>;
|
|
26
|
+
private makeNcpSignature;
|
|
27
|
+
sendNcpMessage(recipient: KakaoMessage): Promise<any>;
|
|
28
|
+
sendNcp(recipients: Array<KakaoMessage>): Promise<any[]>;
|
|
41
29
|
}
|
|
30
|
+
export {};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
var e=this&&this.__decorate||function(e,t,i,
|
|
1
|
+
var e=this&&this.__decorate||function(e,t,i,s){var n,r=arguments.length,o=r<3?t:null===s?s=Object.getOwnPropertyDescriptor(t,i):s;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)o=Reflect.decorate(e,t,i,s);else for(var c=e.length-1;c>=0;c--)(n=e[c])&&(o=(r<3?n(o):r>3?n(t,i,o):n(t,i))||o);return r>3&&o&&Object.defineProperty(t,i,o),o},t=this&&this.__metadata||function(e,t){if("object"==typeof Reflect&&"function"==typeof Reflect.metadata)return Reflect.metadata(e,t)},i=this&&this.__awaiter||function(e,t,i,s){return new(i||(i=Promise))(function(n,r){function fulfilled(e){try{step(s.next(e))}catch(e){r(e)}}function rejected(e){try{step(s.throw(e))}catch(e){r(e)}}function step(e){e.done?n(e.value):function adopt(e){return e instanceof i?e:new i(function(t){t(e)})}(e.value).then(fulfilled,rejected)}step((s=s.apply(e,t||[])).next())})};Object.defineProperty(exports,"__esModule",{value:!0}),exports.KakaoService=void 0;const s=require("@nestjs/common"),n=require("@nestjs/config"),r=require("crypto"),o=require("../../redis");let c=class KakaoService{constructor(e,t){this.configService=e,this.redis=t}send(e){return i(this,void 0,void 0,function*(){const t=this.configService.get("KAKAO_PROVIDER");if(!t||!this.configService.get("KAKAO_FROM"))throw new Error("KAKAO_PROVIDER or KAKAO_FROM is not set");return"aligo"===t?this.sendAligo(e):"ppurio"===t?this.sendPpurio(e):"ncp"===t?this.sendNcp(e):[]})}sendAligo(e){return i(this,void 0,void 0,function*(){return console.log("π± [KAKAO] Aligo λ°°μ΄ λ°μ‘:",{count:e.length,from:this.configService.get("KAKAO_FROM"),provider:"aligo",recipients:e.map(e=>({user_id:e.user_id,recipient:e.recipient,template_code:e.template_code})),timestamp:(new Date).toISOString()}),e.map(e=>({user_id:e.user_id,recipient:e.recipient,success:!0,messageId:`aligo-${Date.now()}-${e.user_id}`,status:"sent"}))})}getPpurioToken(){return i(this,void 0,void 0,function*(){if(yield this.redis.get("ppurio_token"))return yield this.redis.get("ppurio_token");const e=this.configService.get("PPURIO_ACCOUNT"),t=this.configService.get("PPURIO_PASSWORD"),i=btoa(`${e}:${t}`),s=yield fetch("https://api.bizppurio.com/v1/token",{method:"POST",headers:{"Content-Type":"application/json; charset=utf-8",Authorization:`Basic ${i}`},body:JSON.stringify({grant_type:"client_credentials"})}),n=yield s.json();if(n.accesstoken)return yield this.redis.set("ppurio_token",n.accesstoken,86e3),yield this.redis.get("ppurio_token");throw new Error(`cannot get ppurio access token: ${JSON.stringify(n)}`)})}sendPpurioMessage(e){return i(this,void 0,void 0,function*(){const t=e.recipient.trim().replace(/-/g,"");if(t.startsWith("0100")||11!==t.length)return;const i=yield this.getPpurioToken(),s=yield fetch("https://api.bizppurio.com/v3/message",{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${i}`},body:JSON.stringify({account:this.configService.get("PPURIO_ACCOUNT"),refkey:this.configService.get("PPURIO_PASSWORD"),type:"at",from:this.configService.get("SMS_FROM"),to:e.recipient,content:{at:{senderkey:e.sender_key,templatecode:e.template_code,message:e.message}}})});return yield s.json()})}sendPpurio(e){return i(this,void 0,void 0,function*(){if("production"!==process.env.NODE_ENV)return console.log("π± [KAKAO] Ppurio λ°μ‘:",{count:e.length,from:this.configService.get("KAKAO_FROM"),provider:"ppurio",recipients:e.map(e=>({user_id:e.user_id,recipient:e.recipient,sender_key:e.sender_key,template_code:e.template_code,message:e.message})),timestamp:(new Date).toISOString()}),e.map(e=>({user_id:e.user_id,recipient:e.recipient,success:!0,messageId:`ppurio-${Date.now()}-${e.user_id}`,message:e.message,status:"sent"}));return yield Promise.all(e.map(e=>this.sendPpurioMessage(e)))})}makeNcpSignature(e,t,i){const s=this.configService.get("NCP_ACCESS_KEY"),n=this.configService.get("NCP_SECRET_KEY"),o=`${e} ${t}\n${i}\n${s}`;return r.createHmac("sha256",n).update(o).digest("base64")}sendNcpMessage(e){return i(this,void 0,void 0,function*(){const t=this.configService.get("NCP_SERVICE_ID"),i=this.configService.get("NCP_ACCESS_KEY");if(!t||!i)throw new Error("NCP_SERVICE_ID or NCP_ACCESS_KEY is not set");const s=Date.now().toString(),n=`/alimtalk/v2/services/${t}/messages`,r=this.makeNcpSignature("POST",n,s),o=e.recipient.trim().replace(/-/g,"");if(o.startsWith("0100")||11!==o.length)return;const c=yield fetch(`https://sens.apigw.ntruss.com${n}`,{method:"POST",headers:{"Content-Type":"application/json; charset=utf-8","x-ncp-apigw-timestamp":s,"x-ncp-iam-access-key":i,"x-ncp-apigw-signature-v2":r},body:JSON.stringify({plusFriendId:this.configService.get("KAKAO_FROM"),templateCode:e.template_code,messages:[Object.assign({countryCode:"82",to:o,content:e.message},e.template_meta?{template:e.template_meta}:{})]})});return yield c.json()})}sendNcp(e){return i(this,void 0,void 0,function*(){if("production"!==process.env.NODE_ENV)return console.log("π± [KAKAO] NCP λ°μ‘:",JSON.stringify({count:e.length,recipients:e.map(e=>({user_id:e.user_id,recipient:e.recipient,sender_key:this.configService.get("KAKAO_FROM"),template_code:e.template_code,template_meta:e.template_meta,message:e.message})),timestamp:(new Date).toISOString()},null,2)),e.map(e=>({user_id:e.user_id,recipient:e.recipient,success:!0,messageId:`ncp-${Date.now()}-${e.user_id}`,status:"sent"}));return yield Promise.all(e.map(e=>this.sendNcpMessage(e)))})}};exports.KakaoService=c,exports.KakaoService=c=e([(0,s.Injectable)(),t("design:paramtypes",[n.ConfigService,o.RedisService])],c);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
var e,t=this&&this.__decorate||function(e,t,i,n){var r,s=arguments.length,a=s<3?t:null===n?n=Object.getOwnPropertyDescriptor(t,i):n;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)a=Reflect.decorate(e,t,i,n);else for(var o=e.length-1;o>=0;o--)(r=e[o])&&(a=(s<3?r(a):s>3?r(t,i,a):r(t,i))||a);return s>3&&a&&Object.defineProperty(t,i,a),a},i=this&&this.__metadata||function(e,t){if("object"==typeof Reflect&&"function"==typeof Reflect.metadata)return Reflect.metadata(e,t)},n=this&&this.__awaiter||function(e,t,i,n){return new(i||(i=Promise))(function(r,s){function fulfilled(e){try{step(n.next(e))}catch(e){s(e)}}function rejected(e){try{step(n.throw(e))}catch(e){s(e)}}function step(e){e.done?r(e.value):function adopt(e){return e instanceof i?e:new i(function(t){t(e)})}(e.value).then(fulfilled,rejected)}step((n=n.apply(e,t||[])).next())})};Object.defineProperty(exports,"__esModule",{value:!0}),exports.NotificationSendService=void 0;const r=require("@nestjs/common"),s=require("../../enums.common"),a=require("./email.service"),o=require("./kakao.service"),c=require("./message-template.service"),l=require("./notification.service"),d=require("./slack.service"),
|
|
1
|
+
var e,t=this&&this.__decorate||function(e,t,i,n){var r,s=arguments.length,a=s<3?t:null===n?n=Object.getOwnPropertyDescriptor(t,i):n;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)a=Reflect.decorate(e,t,i,n);else for(var o=e.length-1;o>=0;o--)(r=e[o])&&(a=(s<3?r(a):s>3?r(t,i,a):r(t,i))||a);return s>3&&a&&Object.defineProperty(t,i,a),a},i=this&&this.__metadata||function(e,t){if("object"==typeof Reflect&&"function"==typeof Reflect.metadata)return Reflect.metadata(e,t)},n=this&&this.__awaiter||function(e,t,i,n){return new(i||(i=Promise))(function(r,s){function fulfilled(e){try{step(n.next(e))}catch(e){s(e)}}function rejected(e){try{step(n.throw(e))}catch(e){s(e)}}function step(e){e.done?r(e.value):function adopt(e){return e instanceof i?e:new i(function(t){t(e)})}(e.value).then(fulfilled,rejected)}step((n=n.apply(e,t||[])).next())})};Object.defineProperty(exports,"__esModule",{value:!0}),exports.NotificationSendService=void 0;const r=require("@nestjs/common"),s=require("../../enums.common"),a=require("./email.service"),o=require("./kakao.service"),c=require("./message-template.service"),l=require("./notification.service"),d=require("./slack.service"),p=require("./sms.service");let h=e=class NotificationSendService{constructor(t,i,n,s,a,o){this.notificationService=t,this.emailService=i,this.smsService=n,this.kakaoService=s,this.slackService=a,this.templateService=o,this.logger=new r.Logger(e.name)}send(e){return n(this,void 0,void 0,function*(){const{title:t,content:i,template_code:n,template_meta:r}=yield this.renderTemplate(e);return 1===e.recipients.length?yield this.sendSingle(e,t,i,n,r):(this.logger.log(`1:N λ°°μΉ μλ¦Ό λ°μ‘ μμ: ${t} (${e.recipients.length}λͺ
)`),yield this.sendBatch(e,t,i,n,r))})}sendSingle(e,t,i,r,a){return n(this,void 0,void 0,function*(){const n=e.recipients[0],o=[];for(const c of e.channels){let l;try{"in_app"===c?(l=yield this.notificationService.createSingle({user_id:n.user_id,recipient:n.recipient,type:"in_app",template_key:e.template_key,event_type:e.event_type,event_id:e.event_id,title:t,content:i,variables:Object.assign(Object.assign({},e.variables),n.variables),meta:Object.assign(Object.assign({},e.meta),{template_code:r||"",template_meta:a||{}})}),l.status=s.NOTIFICATION_STATUS.SENT,l.sent_at=new Date,yield this.notificationService.notificationRepository.save(l)):(l=yield this.notificationService.createSingle({user_id:n.user_id,recipient:n.recipient,type:c,template_key:e.template_key,event_type:e.event_type,event_id:e.event_id,title:t,content:i,variables:Object.assign(Object.assign({},e.variables),n.variables),meta:Object.assign({},e.meta)}),yield this.sendToChannel(c,{recipient:n.recipient,title:t,content:i,user_id:n.user_id,template_code:r,template_meta:a,meta:e.meta}),l.status=s.NOTIFICATION_STATUS.SENT,l.sent_at=new Date,yield this.notificationService.notificationRepository.save(l),this.logger.log(`${c} λ°μ‘ μ±κ³΅: user_id=${n.user_id}`)),o.push({channel:c,status:"success",notification:l})}catch(e){this.logger.error(`${c} λ°μ‘ μ€ν¨: ${e.message}`,e.stack),l&&(l.status=s.NOTIFICATION_STATUS.FAILED,l.failed_at=new Date,l.reason_failed=e.message,yield this.notificationService.notificationRepository.save(l)),o.push({channel:c,status:"failed",error:e.message})}}return o})}sendBatch(e,t,i,r,a){return n(this,void 0,void 0,function*(){const{batch_id:n,total_count:r}=yield this.notificationService.createBatch({batch_id:e.batch_id,recipients:e.recipients,type:"in_app",template_key:e.template_key,event_type:e.event_type,event_id:e.event_id,title:e.title,content:e.content,variables:e.variables,meta:e.meta,channels:e.channels});this.logger.log(`λ°°μΉ μμ± μλ£: ${n} (${r}건)`);const a=e.channels.filter(e=>"in_app"!==e),o=[];for(const r of a)try{yield this.sendBatchToChannel(r,{recipients:e.recipients,title:t,content:i,meta:e.meta}),yield this.notificationService.notificationRepository.update({batch_id:n,type:r},{status:s.NOTIFICATION_STATUS.SENT,sent_at:new Date}),o.push({channel:r,status:"sent"}),this.logger.log(`${r} λ°°μΉ λ°μ‘ μ±κ³΅: ${e.recipients.length}λͺ
`)}catch(e){this.logger.error(`${r} λ°°μΉ λ°μ‘ μ€ν¨: ${e.message}`,e.stack),yield this.notificationService.notificationRepository.update({batch_id:n,type:r},{status:s.NOTIFICATION_STATUS.FAILED,failed_at:new Date,reason_failed:e.message}),o.push({channel:r,status:"failed",error:e.message})}return{batch_id:n,total_count:r,send_results:o}})}sendToChannel(e,t){return n(this,void 0,void 0,function*(){switch(e){case"mobile_push":throw this.logger.warn("mobile_push μ±λμ μμ§ κ΅¬νλμ§ μμμ΅λλ€"),new Error("mobile_push not implemented yet");case"web_push":throw this.logger.warn("web_push μ±λμ μμ§ κ΅¬νλμ§ μμμ΅λλ€"),new Error("web_push not implemented yet");case"email":return yield this.emailService.send([{recipient:t.recipient,user_id:t.user_id,subject:t.title,text:t.content}]);case"sms":return yield this.smsService.send([{recipient:t.recipient,user_id:t.user_id,message:t.content}]);case"kakao":return yield this.kakaoService.send([{recipient:t.recipient,user_id:t.user_id,sender_key:t.sender_key,template_code:t.template_code,template_meta:t.template_meta,message:t.content}]);case"slack":return yield this.slackService.send(t.recipient,t.content);default:throw new Error(`Unknown channel: ${e}`)}})}sendBatchToChannel(e,t){return n(this,void 0,void 0,function*(){switch(e){case"mobile_push":throw this.logger.warn("mobile_push λ°°μΉ λ°μ‘μ μμ§ κ΅¬νλμ§ μμμ΅λλ€"),new Error("mobile_push batch sending not implemented yet");case"web_push":throw this.logger.warn("web_push λ°°μΉ λ°μ‘μ μμ§ κ΅¬νλμ§ μμμ΅λλ€"),new Error("web_push batch sending not implemented yet");case"email":{const e=t.recipients.map(e=>({recipient:e.recipient,user_id:e.user_id,subject:t.title,text:t.content})).filter(e=>e.recipient);if(0===e.length)throw new Error("No email addresses provided");return yield this.emailService.send(e)}case"sms":{const e=t.recipients.map(e=>({recipient:e.recipient,user_id:e.user_id,message:t.content})).filter(e=>e.recipient);if(0===e.length)throw new Error("No phone numbers provided");return yield this.smsService.send(e)}case"kakao":{const e=t.recipients.map(e=>{var i,n;return{recipient:e.recipient,user_id:e.user_id,sender_key:null===(i=t.meta)||void 0===i?void 0:i.sender_key,template_code:null===(n=t.meta)||void 0===n?void 0:n.template_code,message:t.content}}).filter(e=>e.recipient);if(0===e.length)throw new Error("No kakao recipients provided");return yield this.kakaoService.send(e)}default:throw new Error(`Batch sending not supported for ${e}`)}})}resendBatch(e,t){return n(this,void 0,void 0,function*(){this.logger.log(`λ°°μΉ μ¬λ°μ‘ μμ: ${e}, ${t}`);const i=yield this.notificationService.notificationRepository.find({where:{batch_id:e,type:t}});if(0===i.length)throw new Error(`Batch records not found: ${e}, ${t}`);const n=i.map(e=>({user_id:e.user_id,recipient:e.recipient,variables:e.variables})),r=i[0];try{return yield this.sendBatchToChannel(t,{recipients:n,title:r.title,content:r.content,meta:r.meta}),yield this.notificationService.notificationRepository.update({batch_id:e,type:t},{status:s.NOTIFICATION_STATUS.SENT,sent_at:new Date}),this.logger.log(`λ°°μΉ μ¬λ°μ‘ μ±κ³΅: ${e}`),{success:!0,batch_id:e,channel:t,count:n.length}}catch(i){throw this.logger.error(`λ°°μΉ μ¬λ°μ‘ μ€ν¨: ${i.message}`,i.stack),yield this.notificationService.notificationRepository.update({batch_id:e,type:t},{status:s.NOTIFICATION_STATUS.FAILED,failed_at:new Date,reason_failed:i.message}),i}})}renderTemplate(e){return n(this,void 0,void 0,function*(){var t;if(e.template_key){const i=e.channels[0],n=yield this.templateService.getTemplate(i,e.template_key);if(!n)throw new Error(`Template not found: ${e.template_key} for ${i}`);const r=Object.assign(Object.assign({},e.variables),(null===(t=e.recipients[0])||void 0===t?void 0:t.variables)||{}),s=this.templateService.renderTemplate(n,r);return{title:s.title||e.title||"",content:s.content,template_code:n.template_code,template_meta:n.template_meta}}if(!e.title||!e.content)throw new Error("title and content are required when template_key is not provided");return{title:e.title,content:e.content}})}};exports.NotificationSendService=h,exports.NotificationSendService=h=e=t([(0,r.Injectable)(),i("design:paramtypes",[l.NotificationService,a.EmailService,p.SmsService,o.KakaoService,d.SlackService,c.MessageTemplateService])],h);
|