001/*
002 * Copyright (c) 2009 The openGion Project.
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 *     http://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
013 * either express or implied. See the License for the specific language
014 * governing permissions and limitations under the License.
015 */
016package org.opengion.fukurou.util;
017
018import org.opengion.fukurou.system.OgRuntimeException ;
019
020import java.io.OutputStream;
021import java.io.BufferedWriter;
022import java.io.OutputStreamWriter;
023import java.net.HttpURLConnection;
024import java.net.URL;
025import java.net.Proxy;
026import java.net.InetSocketAddress;
027import java.net.URLEncoder;
028
029/**
030 * LineNotify は、Line Notify を利用してLineメッセージを送信します。
031 *
032 * 《手順》
033 *  1.https://notify-bot.line.me/ja/ からログインして
034 *    マイページから「アクセストークンを発行」をクリック
035 *  2.トークンを設定する。
036 *
037 * <pre>
038 * Usage: java org.opengion.fukurou.util.LineNotify -token アクセストークン -message メッセージ -stickerPackageId 4 -stickerId 614
039 * </pre>
040 *
041 * 《SystemのProxy設定を使用》
042 * java 起動時に、-Djava.net.useSystemProxies=true を指定する。
043 * プログラム内で設定済みです。
044 *
045 * @og.rev 7.2.6.2 (2020/07/22) 新規作成
046 *
047 * @version  7.2
048 * @author   Kazuhiko Hasegawa
049 * @since    JDK11.0,
050 */
051public class LineNotify {
052        private final String token;
053        private final Proxy  proxy;
054
055        private String  stmpPkg ;
056        private String  stmpId ;
057
058        /**
059         * アクセストークンを指定した、コンストラクター
060         *
061         * Proxyは、java.net.useSystemProxies=true 設定を使用します。
062         *
063         * @param       token   アクセストークン
064         */
065        public LineNotify( final String token ) {
066                this.token = token;
067                this.proxy = null;
068
069                System.setProperty("java.net.useSystemProxies","true");         // Proxyの自動設定
070        }
071
072        /**
073         * アクセストークンを指定した、コンストラクター
074         *
075         * Proxyが、nullか、ゼロ文字列の場合は、Proxy.NO_PROXY を指定します。
076         * そうでない場合は、アドレス:ポート形式で指定します。
077         *
078         *
079         * @param       token   アクセストークン(Line Notifyで取得したID)
080         * @param       proxy   アドレス:ポート形式で指定します。
081         */
082        public LineNotify( final String token,final String proxy ) {
083                this.token = token;
084                if( proxy == null || proxy.isEmpty() ) {
085                        this.proxy = Proxy.NO_PROXY;
086                }
087                else {
088                        final int ad = proxy.indexOf( ':' );
089                        final String adrs = proxy.substring( 0,ad );
090                        final int    port = Integer.parseInt( proxy.substring( ad+1 ) );
091
092                        this.proxy = new Proxy(Proxy.Type.HTTP, new InetSocketAddress(adrs, port));
093                }
094        }
095
096        /**
097         * スタンプ(スティッカー)を指定します。
098         *
099         * 指定は、パッケージIDとIDの両方とも必要です。
100         *
101         * @param       stmpPkg stickerPackageIdを指定します。
102         * @param       stmpId  stickerIdを指定します。
103         */
104        public void setStamp( final String stmpPkg , final String stmpId ) {
105                this.stmpPkg = stmpPkg;
106                this.stmpId  = stmpId ;
107        }
108
109        /**
110         * メッセージを送信します。
111         *
112         * 送信は、コネクションを毎回disconnectします。
113         *
114         * @param       message 送信するメッセージ
115         */
116        public void notify( final String message ) {
117                HttpURLConnection connection = null;
118                try {
119                        final URL url = new URL( "https://notify-api.line.me/api/notify" );
120                        if( proxy == null ) {
121                                connection = (HttpURLConnection) url.openConnection();
122                        }
123                        else {
124                                connection = (HttpURLConnection) url.openConnection(proxy);
125                        }
126                        connection.setDoOutput( true );                         // POST可能にする
127                        connection.setDoInput( true );                          // getResponseCode を取得するため
128                        connection.setRequestMethod( "POST" );
129                        connection.addRequestProperty( "Authorization", "Bearer " + token );
130                        connection.setConnectTimeout( 10*1000 );        // 10秒でタイムアウト
131
132                        try( OutputStream os = connection.getOutputStream();
133                                 final BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(os, "UTF-8")) ) {
134
135//                              writer.append( "message=" ).append( message );
136                                writer.append( "message=" ).append( URLEncoder.encode(message, "UTF-8") );
137                                if( !StringUtil.isNull( stmpPkg,stmpId ) ) {
138                                        writer.append( "&stickerPackageId=" ).append( stmpPkg );
139                                        writer.append( "&stickerId="        ).append( stmpId  );
140                                }
141                                writer.flush();
142
143
144                                final int status = connection.getResponseCode();
145                                if( status != HttpURLConnection.HTTP_OK ) {
146                                        final String errMsg = HttpConnect.code2Message( status );
147                                        throw new OgRuntimeException( errMsg );
148                                }
149                        }
150                }
151                catch( final Throwable th ) {
152                        throw new OgRuntimeException( th );
153                }
154                finally {
155                        if( connection != null ) {
156                                connection.disconnect();
157                        }
158                }
159        }
160
161        /**
162         * サンプル実行用のメインメソッド。
163         *
164         * @param       args    コマンド引数配列。
165         */
166        public static void main( final String[] args ) {
167                String token   = "XXXX";
168                String message = "テスト";
169                String stmpPkg = "4";
170                String stmpId  = "614";
171
172                for( int i=0; i<args.length; i++ ) {
173                        if( "-token".equalsIgnoreCase( args[i] ) ) {
174                                token = args[++i];
175                        }
176                        else if( "-message".equalsIgnoreCase( args[i] ) ) {
177                                message = args[++i];
178                        }
179                        else if( "-stickerPackageId".equalsIgnoreCase( args[i] ) ) {
180                                stmpPkg = args[++i];
181                        }
182                        else if( "-stickerId".equalsIgnoreCase( args[i] ) ) {
183                                stmpId = args[++i];
184                        }
185                }
186
187                final LineNotify lineNotify = new LineNotify( token );
188                lineNotify.setStamp( stmpPkg,stmpId );
189                lineNotify.notify( message );
190        }
191}