1. Core_2_Extreme

    OP Core_2_Extreme Member
    Newcomer

    Joined:
    Feb 11, 2019
    Messages:
    34
    Country:
    Japan
    Download (latest version v1.6.0)
    https://github.com/Core-2-Extreme/Line_for_3DS/releases

    If you have any questions you can ask on this discord server.
    https://discord.gg/Zmx7Euf

    Supported function:
    • Send text ✅
    • Send image ✅ (v1.4.0)
    • Send video ✅(*2) (v1.4.0)
    • Send sound ✅(*2) (v1.4.0)
    • Send sticker ✅ (*1) (v1.3.0)
    • Receive text ✅
    • Receive (View) image ✅ (v1.2.0)
    • Receive (Play) video ❌
    • Receive (Play) sound ⚠(*3) (v1.5.0)
    • Receive (View) sticker ✅(*1) (v1.3.0)
    • View old log ✅ (Max 300 logs)
    • Auto update ✅ (v0.2.0)
    • Group chat ✅
    • Night mode ✅ (v0.2.0)
    • Password ✅ (v0.3.0)
    • Save log to SD card ✅ (v0.3.0)

    *1 The stickers must be included this list
    https://developers.line.biz/media/messaging-api/sticker_list.pdf

    *2 Google drive URL will be sent(not embed).

    *3 There is music player that can play .mp3 and .wav, but line return .m4a file so you can't play line audio file in this version.


    Please open this site.
    https://developers.line.biz/en/
    Click log in.
    Click Log in with LINE account.
    Click Create.

    43147207b4eb4e1684a075e305cb67a2.png
    Type your name and click Create.
    9cc90ea609fef8352e3bca436c3dfadb.png
    Click Create a Messaging API channel.
    2394c4de74d3c34c186f373a02b3f2f6.png
    Type each item and click Create.
    e611043d9c7da0be833f17bd36e62bc5.png
    Click Messaging API.

    73774f8d71e0ca5756e72fda20f94ebd.png

    Find Channel access token (long-lived) and click Issue.
    Then copy Channel access token (long-lived).

    15ffd7c288cbf6ab5144158f5402e3a5.png

    Please open this site.
    https://www.google.com/intl/en_ALL/drive/
    Click Go to google drive and login.
    Click New and click Google sheets(1 time) and click More -> Google apps script (1 time).

    5a603a93e5c14227b22e3bd661c43016.png


    Open created Google sheets and copy sheet id.(DO NOT INCLUDE '/' )

    f22b2c7b64acf04808a118983f744685.png


    Open created Google apps script and Insert name.("Line main" in this guide)

    cf714d96090d736cb42a24b7a8997deb.png

    Copy this code to "
    Line main" and add your sheet ID, access token, client(3DS's ) account name(Your favorite name) and script password(if you want).


    • This code compatible with ver 1.6.0
      Code:
      var ACCESS_TOKEN = "Your acces token here";
      var OPEN_SHEET_ID = "Your sheet id here";
      var SCRIPT_PASSOWRD = "Your google apps script password here";
      var CLIENT_NAME = "Your 3ds's account name here";
      
      var gas_ver = 6;//Do **NOT** edit this value.
      function log_save(message, user_name, write_sheet_name, group_or_user_name, pic_url)
      {
          var google_pic_url;
          var previous_pic_url;
          var response;
          var sheet_pos = 1;
          var spreadsheet = SpreadsheetApp.openById(OPEN_SHEET_ID);
          var write_sheet = spreadsheet.getSheetByName(write_sheet_name);
      
          if (!write_sheet)
          {
              spreadsheet.insertSheet(write_sheet_name);
              write_sheet = spreadsheet.getSheetByName(write_sheet_name);
          }
      
          sheet_pos = get_cache_pos(write_sheet);
      
          while (true)
          {
              var sheet_data = write_sheet.getRange("A" + sheet_pos).getValue();
      
              if (sheet_data == "")
              {
                  write_sheet.getRange("A" + sheet_pos).setValue("" + user_name + " : " + message);
                  break;
              }
              else
                  sheet_pos++;
          }
      
          write_cache_data(write_sheet, (sheet_pos + 1), "B1");
          if (group_or_user_name != "Do not save")
              write_cache_data(write_sheet, group_or_user_name, "B2");
      
          if (pic_url != "Do not save")
          {
              previous_pic_url = get_previous_pic_url(write_sheet);
              if (previous_pic_url != pic_url)
              {
                  response = UrlFetchApp.fetch(pic_url,
                      {
                          'headers': {
                              'Content-Type': 'application/json; charset=UTF-8',
                              'Authorization': 'Bearer ' + ACCESS_TOKEN,
                          },
                          muteHttpExceptions: true,
                      });
      
                  if (response.getResponseCode() == 200)
                  {
                      google_pic_url = get_profile_pic_google_url(response, write_sheet_name);
                      write_cache_data(write_sheet, google_pic_url, "B3");
                      write_cache_data(write_sheet, pic_url, "B4");
                  }
              }
      
          }
      }
      
      function check_folder_exist(input_folders, name)
      {
          var folder;
          while (input_folders.hasNext())
          {
            folder = input_folders.next();
            if(name == folder.getName())
              return folder;
          }
          return undefined;
      }
      
      function log_read(id, num_of_logs)
      {
        var sheet_offset = 1;
        var sheet_start = 1;
        var return_data;
        var sheet_data;
        var spreadsheet = SpreadsheetApp.openById(OPEN_SHEET_ID);
        var read_sheet = spreadsheet.getSheetByName(id);
        if(!read_sheet)
          return "No such sheet.\nPlease duoble check your ID.";
       
        sheet_start = get_cache_pos(read_sheet);
      
        while(true)
        {
          sheet_data = read_sheet.getRange("A" + sheet_start).getValue();
          if(sheet_data == "")
          {
            write_cache_data(read_sheet, sheet_start, "B1");
            if(sheet_start > num_of_logs)
              sheet_start = (sheet_start - num_of_logs);
            else
              sheet_start = 1;
      
            break;
          }
          else
            sheet_start++;
        }
      
        sheet_offset = sheet_start;
        sheet_data = read_sheet.getRange(sheet_start, 1, num_of_logs).getValues();
        return_data = "<0>";
        for(var i = 0; i < num_of_logs; i++)
        {
          if(sheet_data[i] == "")
            break;
      
          return_data += sheet_data[i];
          sheet_offset++;
        }
       
        return_data += "</0>";
        return_data += "<1>" + get_cache_name(read_sheet) + "</1>";
        return_data += "<2>" + get_google_pic_url(read_sheet) + "</2>";
        return_data += "<3>" + sheet_offset + "</3>";
        return_data += "<4>Success</4>";
        return return_data;
      }
      
      function get_cache_pos(sheet_object)
      {
        var cached_sheet_pos = sheet_object.getRange("B1").getValue();
        var sheet_data;
      
        if(parseInt(cached_sheet_pos) > 0)
        {
          cached_sheet_pos = parseInt(cached_sheet_pos);
          sheet_data = sheet_object.getRange("A" + (cached_sheet_pos - 1)).getValue();
      
          if(sheet_data != "")
            return cached_sheet_pos;
        }
        return 1;
      }
      
      function get_cache_name(sheet_object)
      {
        var cached_name = sheet_object.getRange("B2").getValue();
        return cached_name;
      }
      
      function get_google_pic_url(sheet_object)
      {
          var cached_name = sheet_object.getRange("B3").getValue();
          return cached_name;
      }
      
      function get_previous_pic_url(sheet_object)
      {
          var cached_name = sheet_object.getRange("B4").getValue();
          return cached_name;
      }
      
      function write_cache_data(sheet_object, cache_data, pos)
      {
        sheet_object.getRange(pos).setValue(cache_data);
      }
      
      function http_get_content(request_id)
      {
        var response;
        var url = "https://api.line.me/v2/bot/message/" + request_id + "/content";
        response = UrlFetchApp.fetch(url,
        {
        'headers': {
          'Content-Type': 'application/json; charset=UTF-8',
          'Authorization': 'Bearer ' + ACCESS_TOKEN,
          },
          muteHttpExceptions: true,
        });
        return response;
      }
      
      function http_get_user_name(id)
      {
        var response;
        var url = 'https://api.line.me/v2/bot/profile/' + id;
        response = UrlFetchApp.fetch(url, {
          'headers': {
            'Content-Type': 'application/json; charset=UTF-8',
            'Authorization': 'Bearer ' + ACCESS_TOKEN,
          },
          muteHttpExceptions: true,
        });
        return response;
      }
      
      function http_get_group_user_name(id, group_id)
      {
        var response;
        var url = "https://api.line.me/v2/bot/group/" + group_id + "/member/" + id + "/";
        response = UrlFetchApp.fetch(url, {
          'headers': {
            'Content-Type': 'application/json; charset=UTF-8',
            'Authorization': 'Bearer ' + ACCESS_TOKEN,
          },
          muteHttpExceptions: true,
        });
        return response;
      }
      
      function http_get_group_name(group_id)
      {
        var response;
        var url = "https://api.line.me/v2/bot/group/" + group_id +"/summary/";
        response = UrlFetchApp.fetch(url, {
          'headers': {
            'Content-Type': 'application/json; charset=UTF-8',
            'Authorization': 'Bearer ' + ACCESS_TOKEN,
          },
          muteHttpExceptions: true,
        });
        return response;
      }
      
      function http_send_text_reply(reply_token, send_msg)
      {
        var response;
        var url = 'https://api.line.me/v2/bot/message/reply/';
        response = UrlFetchApp.fetch(url, {
          'headers': {
            'Content-Type': 'application/json; charset=UTF-8',
            'Authorization': 'Bearer ' + ACCESS_TOKEN,
          },
          'method': 'post',
          'payload': JSON.stringify({
            'replyToken': reply_token,
            'messages': [{
              'type': 'text',
              'text': send_msg ,
            }],
            'notificationDisabled': 'true',
          }),
          muteHttpExceptions: true,
        });
        return response;
      }
      
      function http_send_text(id, send_msg)
      {
        var response;
        var url = 'https://api.line.me/v2/bot/message/push/';
        response = UrlFetchApp.fetch(url, {
          'headers': {
            'Content-Type': 'application/json; charset=UTF-8',
            'Authorization': 'Bearer ' + ACCESS_TOKEN,
          },
          'method': 'post',
          'payload': JSON.stringify({
        "to": id,
        "messages":
             [{
                "text": send_msg,
                "type": "text",
             }],
            'notificationDisabled': 'false',
          }),
         muteHttpExceptions: true,
        });
        return response;
      }
      
      function http_send_sticker(id, package_id, sticker_id)
      {
        var response;
        var url = 'https://api.line.me/v2/bot/message/push/';
        response = UrlFetchApp.fetch(url, {
          'headers': {
            'Content-Type': 'application/json; charset=UTF-8',
            'Authorization': 'Bearer ' + ACCESS_TOKEN,
          },
          'method': 'post',
          'payload': JSON.stringify({
        "to": id,
        "messages":
             [{
                "type": "sticker",
                "packageId": package_id,
                "stickerId": sticker_id,
             }],
            'notificationDisabled': 'false',
          }),
         muteHttpExceptions: true,
        });
        return response;
      }
      
      function http_send_image(id, img_url, preview_url)
      {
        var response;
        var url = 'https://api.line.me/v2/bot/message/push/';
        response = UrlFetchApp.fetch(url, {
          'headers': {
            'Content-Type': 'application/json; charset=UTF-8',
            'Authorization': 'Bearer ' + ACCESS_TOKEN,
          },
          'method': 'post',
          'payload': JSON.stringify({
        "to": id,
        "messages":
             [{
                "type": "image",
                "originalContentUrl": img_url,
                "previewImageUrl": preview_url,
             }],
            'notificationDisabled': 'false',
          }),
         muteHttpExceptions: true,
        });
        return response;
      }
      
      function send_msg(id, send_message, time)
      {
        var cache;
        var response;
        var return_message = "Success";
      
        response = http_send_text(id, send_message);
        if(response.getResponseCode() != 200)
        {
          cache = "***The message failed to send. Status code = " + response.getResponseCode() + "\n" + JSON.parse(response.getContentText()).message + "*** ";
          cache += send_message;
          send_message = cache;
          return_message = "The message failed to send. Status code = " + response.getResponseCode() + "\n" + JSON.parse(response.getContentText()).message;
        }
       
        send_message += "(" + time + ")";
        log_save(send_message, CLIENT_NAME, id, "Do not save", "Do not save");
        return return_message;
      }
      
      function send_sticker(id, package_id, sticker_id, time)
      {
        var response;
        var return_message = "Success";
        var send_message = "";
      
        response = http_send_sticker(id, package_id, sticker_id);
        if(response.getResponseCode() != 200)
        {
         send_message = "***The sticker failed to send. Status code = " + response.getResponseCode() + " " + JSON.parse(response.getContentText()).message + "*** ";
         return_message = "The sticker failed to send. Status code = " + response.getResponseCode() + "\n" + JSON.parse(response.getContentText()).message;
        }
        send_message += "<sticker>" + sticker_id + "</sticker>(" + time + ")";
        log_save(send_message, CLIENT_NAME, id, "Do not save", "Do not save");
        return return_message;
      }
      
      function get_cache_data(id, cache_name)
      {
        var cache_data = "";
        var cache_file;
        var cache_folder;
        var exist_cache_folders;
        var exist_folders;
        var exist_sub_folders;
        var folder;
        var folder_name = "Line_contents";
        var sub_folder;
      
        exist_folders = DriveApp.searchFolders("'me' in owners");
        folder = check_folder_exist(exist_folders, folder_name);
        if(folder == undefined)
          return undefined;
      
        exist_sub_folders = folder.searchFolders("'me' in owners");
        sub_folder = check_folder_exist(exist_sub_folders, id);
        if(sub_folder == undefined)
          return undefined;
      
        exist_cache_folders = sub_folder.searchFolders("'me' in owners");
        cache_folder = check_folder_exist(exist_cache_folders, cache_name);
        if(cache_folder == undefined)
          return undefined;
      
        for(var i = 0; i < 4096; i++)
        {
          try
          {
            cache_file = cache_folder.getFilesByName(i).next();
            cache_data += cache_file.getBlob().getDataAsString();
          }
          catch(error)
          {
            break;
          }
        }
        cache_folder.setTrashed(true);
        return cache_data;
      }
      
      function upload_content(id, data, count, cache_name, last, time)
      {
        var cache_data;
        var cache_folder;
        var exist_cache_folders;
        var exist_folders;
        var exist_sub_folders;
        var folder;
        var folder_name = "Line_contents";
        var part_of_content;
        var part_of_content_data;
        var return_message = "Success";
        var send_message;
        var sub_folder;
      
        if(count == 0 && last == "true")
          return_message = send_content(id, cache_name, time, data);
        else if(last == "true")
        {
            cache_data = get_cache_data(id, cache_name);
            if(cache_data == undefined)
            {
              send_message = "***The content failed to send. The cache folder does not exist.*** (" + time + ")";
              log_save(send_message, CLIENT_NAME, id, "Do not save", "Do not save");
              return_message = "The content failed to send.\nThe cache folder does not exist.";
            }
            else
            {
              cache_data += data;
              return_message = send_content(id, cache_name, time, cache_data);
            }
        }
        else
        {
          exist_folders = DriveApp.searchFolders("'me' in owners");
          folder = check_folder_exist(exist_folders, folder_name);
          if(folder == undefined)
            folder = DriveApp.createFolder(folder_name);
      
          exist_sub_folders = folder.searchFolders("'me' in owners");
          sub_folder = check_folder_exist(exist_sub_folders, id);
          if(sub_folder == undefined)
            sub_folder = folder.createFolder(id);
      
          exist_cache_folders = sub_folder.searchFolders("'me' in owners");
          cache_folder = check_folder_exist(exist_cache_folders, cache_name);
          if(cache_folder == undefined)
            cache_folder = sub_folder.createFolder(cache_name);
          else if(!(cache_folder == undefined) && count == 0)
          {
            cache_folder.setTrashed(true);
            cache_folder = sub_folder.createFolder(cache_name);
          }
      
          part_of_content_data = Utilities.newBlob(data).setName(count);
          part_of_content = cache_folder.createFile(part_of_content_data);
        }
        return return_message;
      }
      
      function send_content(id, cache_name, time, encoded_data)
      {
        var content;
        var content_data;
        var content_type;
        var content_url = "";
        var exist_folders;
        var exist_sub_folders;
        var folder;
        var folder_name = "Line_contents";
        var preview_content_url = "";
        var response;
        var return_message = "Success";
        var send_message = "";
        var sub_folder;
      
        exist_folders = DriveApp.searchFolders("'me' in owners");
        folder = check_folder_exist(exist_folders, folder_name);
        if(folder == undefined)
          folder = DriveApp.createFolder(folder_name);
      
        exist_sub_folders = folder.searchFolders("'me' in owners");
        sub_folder = check_folder_exist(exist_sub_folders, id);
        if(sub_folder == undefined)
          sub_folder = folder.createFolder(id);
      
        try
        {
          content_data = Utilities.newBlob(Utilities.base64Decode(encoded_data)).setName(cache_name);
        }
        catch (e)
        {
          return_message = "The content failed to send.\nCouldn't decode base64 data.";
          return return_message;
        }
      
        content = sub_folder.createFile(content_data);
        content.setSharing(DriveApp.Access.ANYONE, DriveApp.Permission.VIEW);
        content_type = content.getMimeType();
        if(content_type == MimeType.BMP || content_type == MimeType.GIF || content_type == MimeType.JPEG || content_type == MimeType.PNG || content_type == MimeType.SVG)
        {
          content.setTrashed(true);
          folder_name = "Line_images";
          exist_folders = DriveApp.searchFolders("'me' in owners");
          folder = check_folder_exist(exist_folders, folder_name);
          if(folder == undefined)
          folder = DriveApp.createFolder(folder_name);
      
          exist_sub_folders = folder.searchFolders("'me' in owners");
          sub_folder = check_folder_exist(exist_sub_folders, id);
          if(sub_folder == undefined)
          sub_folder = folder.createFolder(id);
      
          content = sub_folder.createFile(content_data);
          content.setSharing(DriveApp.Access.ANYONE, DriveApp.Permission.VIEW);
          content_url = "https://lh3.googleusercontent.com/d/" + content.getId() + "=w16383-h16383";
          preview_content_url = "https://lh3.googleusercontent.com/d/" + content.getId() + "=w240-h240";
      
          response = http_send_image(id, content_url, preview_content_url);
          if(response.getResponseCode() != 200)
          {
            send_message = "***The image failed to send. Status code = " + response.getResponseCode() + " " + JSON.parse(response.getContentText()).message + "*** ";
            return_message = "The image failed to send. Status code = " + response.getResponseCode() + "\n" + JSON.parse(response.getContentText()).message;
          }
          send_message += "<image_url>" + content_url + "</image_url>(" + time + ")";
          log_save(send_message, CLIENT_NAME, id, "Do not save", "Do not save");
          return return_message;
        }
        else
        {
          content_url = "https://drive.google.com/file/d/" + content.getId() + "/view";
          response = http_send_text(id, content_url);
          if(response.getResponseCode() != 200)
          {
            send_message = "***The content failed to send. Status code = " + response.getResponseCode() + " " + JSON.parse(response.getContentText()).message + "*** ";
            return_message = "The content failed to send. Status code = " + response.getResponseCode() + "\n" + JSON.parse(response.getContentText()).message;
          }
          content_url = "https://drive.google.com/uc?export=download&id=" + content.getId();
          send_message += "<content_url>" + content_url + "</content_url>(" + time + ")";
          log_save(send_message, CLIENT_NAME, id, "Do not save", "Do not save");
          return return_message;
        }
      }
      
      function get_profile_pic_google_url(http_response, group_or_user_id)
      {
          var content_data;
          var content;
          var folder_name = "Line_images";
          var folder;
          var sub_folder;
          var exist_folders;
          var exist_sub_folders;
          var url = "";
      
          exist_folders = DriveApp.searchFolders("'me' in owners");
          folder = check_folder_exist(exist_folders, folder_name);
          if (folder == undefined)
              folder = DriveApp.createFolder(folder_name);
      
          exist_sub_folders = folder.searchFolders("'me' in owners");
          sub_folder = check_folder_exist(exist_sub_folders, group_or_user_id);
          if (sub_folder == undefined)
              sub_folder = folder.createFolder(group_or_user_id);
      
          content_data = http_response.getBlob().getAs("image/jpeg").setName("icon");
          content = sub_folder.createFile(content_data);
          content.setSharing(DriveApp.Access.ANYONE, DriveApp.Permission.VIEW);
          url = "https://lh3.googleusercontent.com/d/" + content.getId() + "=w32-h32";
      
          return url;
      }
      
      function get_content_url(request_id, group_or_user_id, type)
      {
        var content_data;
        var content;
        var exist_folders;
        var exist_sub_folders;
        var folder_name;
        var folder;
        var sub_folder;
        var response;
        var url = "";
      
        if(type == "image")
          folder_name = "Line_images";
        else if(type == "audio")
          folder_name = "Line_audio";
        else if(type == "video")
          folder_name = "Line_videos";
        else if(type == "file")
          folder_name = "Line_contens";
      
      
        exist_folders = DriveApp.searchFolders("'me' in owners");
        folder = check_folder_exist(exist_folders, folder_name);
        if(folder  == undefined)
          folder = DriveApp.createFolder(folder_name);
      
        exist_sub_folders = folder.searchFolders("'me' in owners");
        sub_folder = check_folder_exist(exist_sub_folders, group_or_user_id);
        if(sub_folder  == undefined)
          sub_folder = folder.createFolder(group_or_user_id);
      
        response = http_get_content(request_id);
        if(response.getResponseCode() != 200)
        {
          if(type == "image")
            url = "***Couldn't generate an image URL. Status code = " + response.getResponseCode() + " " + JSON.parse(response.getContentText()).message + "*** ";
          else if(type == "audio")
            url = "***Couldn't generate a audio URL. Status code = " + response.getResponseCode() + " " + JSON.parse(response.getContentText()).message + "*** ";
          else if(type == "video")
            url = "***Couldn't generate a video URL. Status code = " + response.getResponseCode() + " " + JSON.parse(response.getContentText()).message + "*** ";
        }
        else
        {
          if(type == "image")
          {
            content_data = response.getBlob().getAs("image/jpeg").setName(request_id);
            content = sub_folder.createFile(content_data);
            content.setSharing(DriveApp.Access.ANYONE, DriveApp.Permission.VIEW);
            url = "https://lh3.googleusercontent.com/d/" + content.getId() + "=w16383-h16383";
          }
          else if(type == "audio" || type == "video" || type == "file")
          {
            content_data = response.getBlob().setName(request_id);
            content = sub_folder.createFile(content_data);
            content.setSharing(DriveApp.Access.ANYONE, DriveApp.Permission.VIEW);
            url = "https://drive.google.com/uc?export=download&id=" + content.getId();
          }
        }
        return url;
      }
      
      function receive_msg_from_line(user_message, user_id, group_id, reply_token, time, reply)
      {
        var group_name;
        var picture_url = [ "", ""];
        var response = [ "", ""];
        var send_msg;
        var user_name;
      
        if(group_id == "Unknown")
          response[0] = http_get_user_name(user_id);
        else
        {
          response[0] = http_get_group_user_name(user_id, group_id);
          response[1] = http_get_group_name(group_id);
      
          if(response[1].getResponseCode() != 200)
            group_name = "Unknown";
          else
          {
            group_name = JSON.parse(response[1]).groupName;
            picture_url[1] = JSON.parse(response[1]).pictureUrl;
          }
        }
      
        if(response[0].getResponseCode() != 200)
          user_name = "Unknown";
        else
        {
          user_name = JSON.parse(response[0]).displayName;
          picture_url[0] = JSON.parse(response[0]).pictureUrl;
        }
      
        if(user_message == "getid" || user_message == "getgroupid")
        {
          if(user_message == "getid")
            send_msg = user_id;
          else if(user_message == "getgroupid")
            send_msg = group_id;
      
          response[0] = http_send_text_reply(reply_token, send_msg);
          send_msg = "<id>" + send_msg + "</id>";
          if(response[0].getResponseCode() != 200)
            send_msg += "***The message failed to send. Status code = " + response[0].getResponseCode() + " " + JSON.parse(response[0].getContentText()).message + "*** ";
      
          send_msg += "(" + time + ")";
          if(user_message == "getid")
            log_save(send_msg, user_name, "IDs", "BOT", "Do not save");
          else if(user_message == "getgroupid")
            log_save(send_msg, group_name, "IDs", "BOT", "Do not save");
          return;
        }
       
        user_message += "(" + time + ")";
        if(group_id == "Unknown")
          log_save(user_message, user_name, user_id, user_name, picture_url[0]);
        else
          log_save(user_message, user_name, group_id, group_name, picture_url[1]);
      }
      
      function doPost(post_data)
      {
        var time = Utilities.formatDate(new Date(), 'Asia/Tokyo', 'MM/dd hh:mm:ss');
        var data_type;
        var result;
        var client_auth = "Unknown";
        var client_gas_ver = "Unknown";
        var id = "Unknown";
        var lock = LockService.getScriptLock();
        var lock_result = lock.tryLock(100);
        try
        {
          data_type = JSON.parse(post_data.postData.contents).type;
        }
        catch(e)
        {
        }
        while(!lock_result)
        {
          Utilities.sleep(100);
          lock_result = lock.tryLock(100);
        }
      
        if(data_type == undefined)
        {
          for(var i = 0; i < 50; i++)
          {
            var msg_id = "";
            var user_message = "";
            var user_id = "";
            var group_id = "";
            var reply_token = "";
            var msg_type = "";
            var type = "";
       
            try
            {
              type = JSON.parse(post_data.postData.contents).events[i].type;
              user_id = JSON.parse(post_data.postData.contents).events[i].source.userId;
              group_id = JSON.parse(post_data.postData.contents).events[i].source.groupId;
              reply_token = JSON.parse(post_data.postData.contents).events[i].replyToken;
              if(type == "message")
              {
                msg_id = JSON.parse(post_data.postData.contents).events[i].message.id;
                user_message = JSON.parse(post_data.postData.contents).events[i].message.text;
                msg_type = JSON.parse(post_data.postData.contents).events[i].message.type;
              }
            }
            catch(e)
            {
              break;
            }
      
            if(user_id == undefined)
              user_id = "Unknown";
            if(group_id == undefined)
              group_id = "Unknown";
      
      
            if(type == "follow")
              user_message = "getid";
            else if(type == "join")
              user_message = "getgroupid";
            if(type == "leave")
              user_message = "*****Removed by user*****";
            else if(type == "unfollow")
              user_message = "*****Blocked by user*****";
            else if(msg_type == "sticker")
            {
              var sticker_id  = JSON.parse(post_data.postData.contents).events[i].message.stickerId;
              user_message = "<sticker>" + sticker_id + "</sticker>";
            }
            else if(msg_type == "image")
            {
             if(group_id == "Unknown")
               user_message = "<image_url>" + get_content_url(msg_id, user_id, msg_type) + "</image_url>";
             else
               user_message = "<image_url>" + get_content_url(msg_id, group_id, msg_type) + "</image_url>";
            }
            else if(msg_type == "audio")
            {
             if(group_id == "Unknown")
               user_message = "<audio_url>" + get_content_url(msg_id, user_id, msg_type) + "</audio_url>";
             else
               user_message = "<audio_url>" + get_content_url(msg_id, group_id, msg_type) + "</audio_url>";
            }
            else if(msg_type == "video")
            {
             if(group_id == "Unknown")
               user_message = "<video_url>" + get_content_url(msg_id, user_id, msg_type) + "</video_url>";
             else
               user_message = "<video_url>" + get_content_url(msg_id, group_id, msg_type) + "</video_url>";
            }
            else if(msg_type == "file")
            {
             if(group_id == "Unknown")
               user_message = "<file_url>" + get_content_url(msg_id, user_id, msg_type) + "</file_url>";
             else
               user_message = "<file_url>" + get_content_url(msg_id, group_id, msg_type) + "</file_url>";
            }
            else if(user_message == undefined)
              user_message += " : " + msg_type + " " + msg_id;
      
            receive_msg_from_line(user_message, user_id, group_id, reply_token, time);
          }
          lock.releaseLock();
          return;
        }
      
        try
        {
          client_auth = JSON.parse(post_data.postData.contents).auth;
          client_gas_ver = JSON.parse(post_data.postData.contents).gas_ver;
          id = JSON.parse(post_data.postData.contents).id;
        }
        catch(e)
        {
        }
      
        if(SCRIPT_PASSOWRD == client_auth)
        {
          if(gas_ver == client_gas_ver)
          {
            if(data_type == "send_text")
            {
              var send_message = JSON.parse(post_data.postData.contents).message;
              result = send_msg(id, send_message, time);
            }
            else if(data_type == "send_sticker")
            {
              var package_id = JSON.parse(post_data.postData.contents).package_id;
              var sticker_id = JSON.parse(post_data.postData.contents).sticker_id;
              result = send_sticker(id, package_id, sticker_id, time);
            }
            else if(data_type == "upload_content")
            {
              var content_data = JSON.parse(post_data.postData.contents).content_data;
              var count = JSON.parse(post_data.postData.contents).count;
              var name = JSON.parse(post_data.postData.contents).name;
              var last = JSON.parse(post_data.postData.contents).last;
              result = upload_content(id, content_data, count, name, last, time);
            }
            else
              result = "Unknown message type.";
          }
          else
            result = "Google apps script version does not match. Server's gas\nver is " + gas_ver + ", but 3DS's gas ver is " + client_gas_ver + ". Please use the same version.";
        }
        else
          result = "Auth failed. Please set correct password.";
      
        lock.releaseLock();
        return ContentService.createTextOutput(result);
      }
      
      function doGet(post_data)
      {
        var data = "";
        var client_auth = "";
        var client_gas_ver = "";
        var num_of_logs = "";
        var id = "";
        var lock = LockService.getScriptLock();
        var lock_result = lock.tryLock(100);
        while(!lock_result)
        {
          Utilities.sleep(100);
          lock_result = lock.tryLock(100);
        }
        try
        {
          client_auth = post_data.parameter.script_auth;
          client_gas_ver = post_data.parameter.gas_ver;
          num_of_logs = post_data.parameter.logs;
          id = post_data.parameter.id;
        }
        catch(e)
        {
        }
        if(client_auth == undefined)
          client_auth = "";
        if(client_gas_ver == undefined)
          client_gas_ver = -1;
        if(num_of_logs == undefined)
          num_of_logs = 300;
        if(id == undefined)
          id = "unknown";
      
        if(SCRIPT_PASSOWRD == client_auth)
        {
          if(gas_ver == client_gas_ver)
            data = log_read(id, num_of_logs);
          else
            data = "Google apps script version does not match. Server's gas\nver is " + gas_ver + ", but 3DS's gas ver is " + client_gas_ver + ". Please use the same version.";
        }
        else
          data = "Auth failed. Please set correct password.";
      
        lock.releaseLock();
        return ContentService.createTextOutput(data);
      }
      

    • This code compatible with ver 1.5.01.5.2
      ⚠⚠⚠WARNING⚠⚠⚠ I strongly recommend you use the newest version ⚠⚠⚠WARNING⚠⚠⚠

      Code:
      var ACCESS_TOKEN = "Your acces token here";
      var open_sheet_id = "Your sheet id here";
      var account_name_of_3ds = "Your 3ds's account name here";
      var script_password = "Your google apps script password here";
      
      var gas_ver = 5;//Do **NOT** edit this value.
      function log_save(message, user_name, write_sheet_name, group_or_user_name, pic_url)
      {
          var google_pic_url;
          var previous_pic_url;
          var response;
          var sheet_pos = 1;
          var spreadsheet = SpreadsheetApp.openById(open_sheet_id);
          var write_sheet = spreadsheet.getSheetByName(write_sheet_name);
      
          if (!write_sheet)
          {
              spreadsheet.insertSheet(write_sheet_name);
              write_sheet = spreadsheet.getSheetByName(write_sheet_name);
          }
      
          sheet_pos = get_cache_pos(write_sheet);
      
          while (true)
          {
              var sheet_data = write_sheet.getRange("A" + sheet_pos).getValue();
      
              if (sheet_data == "")
              {
                  write_sheet.getRange("A" + sheet_pos).setValue("" + user_name + " : " + message);
                  break;
              }
              else
                  sheet_pos++;
          }
      
          write_cache_data(write_sheet, (sheet_pos + 1), "B1");
          if (group_or_user_name != "Do not save")
              write_cache_data(write_sheet, group_or_user_name, "B2");
      
          if (pic_url != "Do not save")
          {
              previous_pic_url = get_previous_pic_url(write_sheet);
              if (previous_pic_url != pic_url)
              {
                  response = UrlFetchApp.fetch(pic_url,
                      {
                          'headers': {
                              'Content-Type': 'application/json; charset=UTF-8',
                              'Authorization': 'Bearer ' + ACCESS_TOKEN,
                          },
                          muteHttpExceptions: true,
                      });
      
                  if (response.getResponseCode() == 200)
                  {
                      google_pic_url = get_profile_pic_google_url(response, write_sheet_name);
                      write_cache_data(write_sheet, google_pic_url, "B3");
                      write_cache_data(write_sheet, pic_url, "B4");
                  }
              }
      
          }
      }
      
      function check_folder_exist(input_folders, name)
      {
          var folder;
          while (input_folders.hasNext())
          {
            folder = input_folders.next();
            if(name == folder.getName())
              return folder;
          }
          return undefined;
      }
      
      function log_read(id)
      {
        var sheet_start = 1;
        var return_data;
        var sheet_data;
        var spreadsheet = SpreadsheetApp.openById(open_sheet_id);
        var read_sheet = spreadsheet.getSheetByName(id);
        sheet_start = get_cache_pos(read_sheet);
      
        while(true)
        {
          sheet_data = read_sheet.getRange("A" + sheet_start).getValue();
          if(sheet_data == "")
          {
            write_cache_data(read_sheet, sheet_start, "B1");
            if(sheet_start >= 301)
              sheet_start = (sheet_start - 300);
            else
              sheet_start = 1;
       
            break;
          }
          else
            sheet_start++;
        }
      
        sheet_data = read_sheet.getRange(sheet_start, 1, 300).getValues();
        return_data = "<0>";
        for(var i = 0; i < 300; i++)
        {
          if(sheet_data[i] == "")
            break;
      
          return_data += sheet_data[i];
        }
          return_data += "</0>";
          return_data += "<1>" + get_cache_name(read_sheet) + "</1>";
          return_data += "<2>" + get_google_pic_url(read_sheet) + "</2>";
          return_data += "<3>Success</3>";
        return return_data;
      }
      
      function get_cache_pos(sheet_object)
      {
        var cached_sheet_pos = sheet_object.getRange("B1").getValue();
        var sheet_data;
      
        if(parseInt(cached_sheet_pos) > 0)
        {
          cached_sheet_pos = parseInt(cached_sheet_pos);
          sheet_data = sheet_object.getRange("A" + (cached_sheet_pos - 1)).getValue();
       
          if(sheet_data != "")
            return cached_sheet_pos;
        }
        return 1;
      }
      
      function get_cache_name(sheet_object)
      {
        var cached_name = sheet_object.getRange("B2").getValue();
        return cached_name;
      }
      
      function get_google_pic_url(sheet_object)
      {
          var cached_name = sheet_object.getRange("B3").getValue();
          return cached_name;
      }
      
      function get_previous_pic_url(sheet_object)
      {
          var cached_name = sheet_object.getRange("B4").getValue();
          return cached_name;
      }
      
      function write_cache_data(sheet_object, cache_data, pos)
      {
        sheet_object.getRange(pos).setValue(cache_data);
      }
      
      function http_get_content(request_id)
      {
        var response;
        var url = "https://api.line.me/v2/bot/message/" + request_id + "/content";
        response = UrlFetchApp.fetch(url,
        {
        'headers': {
          'Content-Type': 'application/json; charset=UTF-8',
          'Authorization': 'Bearer ' + ACCESS_TOKEN,
          },
          muteHttpExceptions: true,
        });
        return response;
      }
      
      function http_get_user_name(id)
      {
        var response;
        var url = 'https://api.line.me/v2/bot/profile/' + id;
        response = UrlFetchApp.fetch(url, {
          'headers': {
            'Content-Type': 'application/json; charset=UTF-8',
            'Authorization': 'Bearer ' + ACCESS_TOKEN,
          },
          muteHttpExceptions: true,
        });
        return response;
      }
      
      function http_get_group_user_name(id, group_id)
      {
        var response;
        var url = "https://api.line.me/v2/bot/group/" + group_id + "/member/" + id + "/";
        response = UrlFetchApp.fetch(url, {
          'headers': {
            'Content-Type': 'application/json; charset=UTF-8',
            'Authorization': 'Bearer ' + ACCESS_TOKEN,
          },
          muteHttpExceptions: true,
        });
        return response;
      }
      
      function http_get_group_name(group_id)
      {
        var response;
        var url = "https://api.line.me/v2/bot/group/" + group_id +"/summary/";
        response = UrlFetchApp.fetch(url, {
          'headers': {
            'Content-Type': 'application/json; charset=UTF-8',
            'Authorization': 'Bearer ' + ACCESS_TOKEN,
          },
          muteHttpExceptions: true,
        });
        return response;
      }
      
      function http_send_text_reply(reply_token, send_msg)
      {
        var response;
        var url = 'https://api.line.me/v2/bot/message/reply/';
        response = UrlFetchApp.fetch(url, {
          'headers': {
            'Content-Type': 'application/json; charset=UTF-8',
            'Authorization': 'Bearer ' + ACCESS_TOKEN,
          },
          'method': 'post',
          'payload': JSON.stringify({
            'replyToken': reply_token,
            'messages': [{
              'type': 'text',
              'text': send_msg ,
            }],
            'notificationDisabled': 'true',
          }),
          muteHttpExceptions: true,
        });
        return response;
      }
      
      function http_send_text(id, send_msg)
      {
        var response;
        var url = 'https://api.line.me/v2/bot/message/push/';
        response = UrlFetchApp.fetch(url, {
          'headers': {
            'Content-Type': 'application/json; charset=UTF-8',
            'Authorization': 'Bearer ' + ACCESS_TOKEN,
          },
          'method': 'post',
          'payload': JSON.stringify({
        "to": id,
        "messages":
             [{
                "text": send_msg,
                "type": "text",
             }],
            'notificationDisabled': 'false',
          }),
         muteHttpExceptions: true,
        });
        return response;
      }
      
      function http_send_sticker(id, package_id, sticker_id)
      {
        var response;
        var url = 'https://api.line.me/v2/bot/message/push/';
        response = UrlFetchApp.fetch(url, {
          'headers': {
            'Content-Type': 'application/json; charset=UTF-8',
            'Authorization': 'Bearer ' + ACCESS_TOKEN,
          },
          'method': 'post',
          'payload': JSON.stringify({
        "to": id,
        "messages":
             [{
                "type": "sticker",
                "packageId": package_id,
                "stickerId": sticker_id,
             }],
            'notificationDisabled': 'false',
          }),
         muteHttpExceptions: true,
        });
        return response;
      }
      
      function http_send_image(id, img_url, preview_url)
      {
        var response;
        var url = 'https://api.line.me/v2/bot/message/push/';
        response = UrlFetchApp.fetch(url, {
          'headers': {
            'Content-Type': 'application/json; charset=UTF-8',
            'Authorization': 'Bearer ' + ACCESS_TOKEN,
          },
          'method': 'post',
          'payload': JSON.stringify({
        "to": id,
        "messages":
             [{
                "type": "image",
                "originalContentUrl": img_url,
                "previewImageUrl": preview_url,
             }],
            'notificationDisabled': 'false',
          }),
         muteHttpExceptions: true,
        });
        return response;
      }
      
      function send_msg(id, send_message, time)
      {
        var cache;
        var response;
        var return_message = "Success";
       
        response = http_send_text(id, send_message);
        if(response.getResponseCode() != 200)
        {
          cache = "***The message failed to send. Status code = " + response.getResponseCode() + "\n" + JSON.parse(response.getContentText()).message + "*** ";
          cache += send_message;
          send_message = cache;
          return_message = "The message failed to send. Status code = " + response.getResponseCode() + "\n" + JSON.parse(response.getContentText()).message;
        }
        send_message += "(" + time + ")";
        log_save(send_message, account_name_of_3ds, id, "Do not save", "Do not save");
        return return_message;
      }
      
      function send_sticker(id, package_id, sticker_id, time)
      {
        var response;
        var return_message = "Success";
        var send_message = "";
      
        response = http_send_sticker(id, package_id, sticker_id);
        if(response.getResponseCode() != 200)
        {
         send_message = "***The sticker failed to send. Status code = " + response.getResponseCode() + " " + JSON.parse(response.getContentText()).message + "*** ";
         return_message = "The sticker failed to send. Status code = " + response.getResponseCode() + "\n" + JSON.parse(response.getContentText()).message;
        }
        send_message += "<sticker>" + sticker_id + "</sticker>(" + time + ")";
        log_save(send_message, account_name_of_3ds, id, "Do not save", "Do not save");
        return return_message;
      }
      
      function upload_content(id, data, count, cache_name)
      {
        var cache_folder;
        var exist_cache_folders;
        var exist_folders;
        var exist_sub_folders;
        var folder;
        var folder_name = "Line_contents";
        var part_of_content;
        var part_of_content_data;
        var return_message = "Success";
        var sub_folder;
      
        exist_folders = DriveApp.searchFolders("'me' in owners");
        folder = check_folder_exist(exist_folders, folder_name);
        if(folder == undefined)
          folder = DriveApp.createFolder(folder_name);
       
        exist_sub_folders = folder.searchFolders("'me' in owners");
        sub_folder = check_folder_exist(exist_sub_folders, id);
        if(sub_folder == undefined)
          sub_folder = folder.createFolder(id);
       
        exist_cache_folders = sub_folder.searchFolders("'me' in owners");
        cache_folder = check_folder_exist(exist_cache_folders, cache_name);
        if(cache_folder == undefined)
          cache_folder = sub_folder.createFolder(cache_name);
        else if(!(cache_folder == undefined) && count == 0)
        {
          cache_folder.setTrashed(true);
          cache_folder = sub_folder.createFolder(cache_name);
        }
      
        part_of_content_data = Utilities.newBlob(data).setName(count);
        part_of_content = cache_folder.createFile(part_of_content_data);
        return return_message;
      }
      
      function send_content(id, cache_name, time)
      {
        var cache_file;
        var cache_folder;
        var content;
        var content_data;
        var content_type;
        var content_url = "";
        var encoded_data = "";
        var exist_cache_folders;
        var exist_folders;
        var exist_sub_folders;
        var folder;
        var folder_name = "Line_contents";
        var preview_content_url = "";
        var response;
        var return_message = "Success";
        var send_message = "";
        var sub_folder;
      
        exist_folders = DriveApp.searchFolders("'me' in owners");
        folder = check_folder_exist(exist_folders, folder_name);
        if(folder == undefined)
          folder = DriveApp.createFolder(folder_name);
      
        exist_sub_folders = folder.searchFolders("'me' in owners");
        sub_folder = check_folder_exist(exist_sub_folders, id);
        if(sub_folder == undefined)
          sub_folder = folder.createFolder(id);
      
        exist_cache_folders = sub_folder.searchFolders("'me' in owners");
        cache_folder = check_folder_exist(exist_cache_folders, cache_name);
        if(cache_folder == undefined)
        {
          send_message = "***The content failed to send. The cache folder does not exist.*** (" + time + ")";
          log_save(send_message, account_name_of_3ds, id, "Do not save", "Do not save");
          return_message = "The content failed to send.\nThe cache folder does not exist."
          return return_message;
        }
      
        for(var i = 0; i < 4096; i++)
        {
          try
          {
            cache_file = cache_folder.getFilesByName(i).next();
            encoded_data += cache_file.getBlob().getDataAsString();
          }
          catch(error)
          {
            break;
          }
        }
      
        cache_folder.setTrashed(true);
        content_data = Utilities.newBlob(Utilities.base64Decode(encoded_data)).setName(cache_name);
        content = sub_folder.createFile(content_data);
        content.setSharing(DriveApp.Access.ANYONE, DriveApp.Permission.VIEW);
        content_type = content.getMimeType();
        if(content_type == MimeType.BMP || content_type == MimeType.GIF || content_type == MimeType.JPEG || content_type == MimeType.PNG || content_type == MimeType.SVG)
        {
          content.setTrashed(true);
          folder_name = "Line_images";
          exist_folders = DriveApp.searchFolders("'me' in owners");
          folder = check_folder_exist(exist_folders, folder_name);
          if(folder == undefined)
          folder = DriveApp.createFolder(folder_name);
      
          exist_sub_folders = folder.searchFolders("'me' in owners");
          sub_folder = check_folder_exist(exist_sub_folders, id);
          if(sub_folder == undefined)
          sub_folder = folder.createFolder(id);
       
          content = sub_folder.createFile(content_data);
          content.setSharing(DriveApp.Access.ANYONE, DriveApp.Permission.VIEW);
          content_url = "https://lh3.googleusercontent.com/d/" + content.getId() + "=w16383-h16383";
          preview_content_url = "https://lh3.googleusercontent.com/d/" + content.getId() + "=w240-h240";
       
          response = http_send_image(id, content_url, preview_content_url);
          if(response.getResponseCode() != 200)
          {
            send_message = "***The image failed to send. Status code = " + response.getResponseCode() + " " + JSON.parse(response.getContentText()).message + "*** ";
            return_message = "The image failed to send. Status code = " + response.getResponseCode() + "\n" + JSON.parse(response.getContentText()).message;
          }
          send_message += "<image_url>" + content_url + "</image_url>(" + time + ")";
          log_save(send_message, account_name_of_3ds, id, "Do not save", "Do not save");
          return return_message;
        }
        else
        {
          content_url = "https://drive.google.com/file/d/" + content.getId() + "/view";
          response = http_send_text(id, content_url);
          if(response.getResponseCode() != 200)
          {
            send_message = "***The content failed to send. Status code = " + response.getResponseCode() + " " + JSON.parse(response.getContentText()).message + "*** ";
            return_message = "The content failed to send. Status code = " + response.getResponseCode() + "\n" + JSON.parse(response.getContentText()).message;
          }
          content_url = "https://drive.google.com/uc?export=download&id=" + content.getId();
          send_message += "<content_url>" + content_url + "</content_url>(" + time + ")";
          log_save(send_message, account_name_of_3ds, id, "Do not save", "Do not save");
          return return_message;
        }
      }
      
      function get_profile_pic_google_url(http_response, group_or_user_id)
      {
          var content_data;
          var content;
          var folder_name = "Line_images";
          var folder;
          var sub_folder;
          var exist_folders;
          var exist_sub_folders;
          var url = "";
       
          exist_folders = DriveApp.searchFolders("'me' in owners");
          folder = check_folder_exist(exist_folders, folder_name);
          if (folder == undefined)
              folder = DriveApp.createFolder(folder_name);
      
          exist_sub_folders = folder.searchFolders("'me' in owners");
          sub_folder = check_folder_exist(exist_sub_folders, group_or_user_id);
          if (sub_folder == undefined)
              sub_folder = folder.createFolder(group_or_user_id);
      
          content_data = http_response.getBlob().getAs("image/jpeg").setName("icon");
          content = sub_folder.createFile(content_data);
          content.setSharing(DriveApp.Access.ANYONE, DriveApp.Permission.VIEW);
          url = "https://lh3.googleusercontent.com/d/" + content.getId() + "=w32-h32";
      
          return url;
      }
      
      function get_content_url(request_id, group_or_user_id, type)
      {
        var content_data;
        var content;
        var exist_folders;
        var exist_sub_folders;
        var folder_name;
        var folder;
        var sub_folder;
        var response;
        var url = "";
       
        if(type == "image")
          folder_name = "Line_images";
        else if(type == "audio")
          folder_name = "Line_audio";
        else if(type == "video")
          folder_name = "Line_videos";
       
        exist_folders = DriveApp.searchFolders("'me' in owners");
        folder = check_folder_exist(exist_folders, folder_name);
        if(folder  == undefined)
          folder = DriveApp.createFolder(folder_name);
       
        exist_sub_folders = folder.searchFolders("'me' in owners");
        sub_folder = check_folder_exist(exist_sub_folders, group_or_user_id);
        if(sub_folder  == undefined)
          sub_folder = folder.createFolder(group_or_user_id);
      
        response = http_get_content(request_id);
        if(response.getResponseCode() != 200)
        {
          if(type == "image")
            url = "***Couldn't generate an image URL. Status code = " + response.getResponseCode() + " " + JSON.parse(response.getContentText()).message + "*** ";
          else if(type == "audio")
            url = "***Couldn't generate a audio URL. Status code = " + response.getResponseCode() + " " + JSON.parse(response.getContentText()).message + "*** ";
          else if(type == "video")
            url = "***Couldn't generate a video URL. Status code = " + response.getResponseCode() + " " + JSON.parse(response.getContentText()).message + "*** ";
        }
        else
        {
          if(type == "image")
          {
            content_data = response.getBlob().getAs("image/jpeg").setName(request_id);
            content = sub_folder.createFile(content_data);
            content.setSharing(DriveApp.Access.ANYONE, DriveApp.Permission.VIEW);
            url = "https://lh3.googleusercontent.com/d/" + content.getId() + "=w16383-h16383";
          }
          else if(type == "audio" || type == "video")
          {
            content_data = response.getBlob().setName(request_id);
            content = sub_folder.createFile(content_data);
            content.setSharing(DriveApp.Access.ANYONE, DriveApp.Permission.VIEW);
            url = "https://drive.google.com/uc?export=download&id=" + content.getId();
          }
        }
        return url;
      }
      
      function receive_msg_from_line(user_message, user_id, group_id, reply_token, time)
      {
        var group_name;
        var picture_url = [ "", ""];
        var response = [ "", ""];
        var send_msg;
        var user_name;
       
        if(user_message == "getid" || user_message == "getgroupid")
        {
          if(user_message == "getid")
            send_msg = user_id;
          else if(user_message == "getgroupid")
            send_msg = group_id;
       
          response[0] = http_send_text_reply(reply_token, send_msg);
          send_msg = "<id>" + send_msg + "</id>";
          if(response[0].getResponseCode() != 200)
            send_msg += "***The message failed to send. Status code = " + response[0].getResponseCode() + " " + JSON.parse(response[0].getContentText()).message + "*** ";
      
          log_save(send_msg, "BOT", "IDs", "BOT", "Do not save");
          return;
        }
      
        if(group_id == "Unknown")
          response[0] = http_get_user_name(user_id);
        else
        {
          response[0] = http_get_group_user_name(user_id, group_id);
          response[1] = http_get_group_name(group_id);
       
          if(response[1].getResponseCode() != 200)
            group_name = "Unknown";
          else
          {
            group_name = JSON.parse(response[1]).groupName;
            picture_url[1] = JSON.parse(response[1]).pictureUrl;
          }
        }
      
        if(response[0].getResponseCode() != 200)
          user_name = "Unknown";
        else
        {
          user_name = JSON.parse(response[0]).displayName;
          picture_url[0] = JSON.parse(response[0]).pictureUrl;
        }
       
        user_message += "(" + time + ")";
        if(group_id == "Unknown")
          log_save(user_message, user_name, user_id, user_name, picture_url[0]);
        else
          log_save(user_message, user_name, group_id, group_name, picture_url[1]);
      }
      
      function doPost(post_data)
      {
        var date = new Date();
        var time = Utilities.formatDate( date, 'Asia/Tokyo', 'MM/dd hh:mm:ss');
        var type = JSON.parse(post_data.postData.contents).type;
        var result;
        var lock = LockService.getScriptLock();
        var lock_result = lock.tryLock(1000);
        while(!lock_result)
        {
          Utilities.sleep(100);
          lock_result = lock.tryLock(1000);
        }
      
        if(type == undefined)
        {
          for(var i = 0; i < 30; i++)
          {
            try
            {
              var msg_id = JSON.parse(post_data.postData.contents).events[i].message.id;
              var user_message = JSON.parse(post_data.postData.contents).events[i].message.text;
              var user_id = JSON.parse(post_data.postData.contents).events[i].source.userId;
              var group_id = JSON.parse(post_data.postData.contents).events[i].source.groupId;
              var reply_token = JSON.parse(post_data.postData.contents).events[i].replyToken;
              var type = JSON.parse(post_data.postData.contents).events[i].message.type;
            }
            catch(error)
            {
              break;
            }
       
            if(user_id == undefined)
              user_id = "Unknown";
            if(group_id == undefined)
              group_id = "Unknown";
      
            if(type == "sticker")
            {
              var sticker_id  = JSON.parse(post_data.postData.contents).events[0].message.stickerId;
              user_message = "<sticker>" + sticker_id + "</sticker>";
            }
            else if(type == "image")
            {
             if(group_id == "Unknown")
               user_message = "<image_url>" + get_content_url(msg_id, user_id, type) + "</image_url>";
             else
               user_message = "<image_url>" + get_content_url(msg_id, group_id, type) + "</image_url>";
            }
            else if(type == "audio")
            {
             if(group_id == "Unknown")
               user_message = "<audio_url>" + get_content_url(msg_id, user_id, type) + "</audio_url>";
             else
               user_message = "<audio_url>" + get_content_url(msg_id, group_id, type) + "</audio_url>";
            }
            else if(type == "video")
            {
             if(group_id == "Unknown")
               user_message = "<video_url>" + get_content_url(msg_id, user_id, type) + "</video_url>";
             else
               user_message = "<video_url>" + get_content_url(msg_id, group_id, type) + "</video_url>";
            }
            else if(user_message == undefined)
              user_message += " : " + type + " " + msg_id;
      
            receive_msg_from_line(user_message, user_id, group_id, reply_token, time);
          }
          lock.releaseLock();
          return;
        }
      
        var client_auth = JSON.parse(post_data.postData.contents).auth;
        var client_gas_ver = JSON.parse(post_data.postData.contents).gas_ver;
        if(client_auth == undefined)
          client_auth = "";
        if(client_gas_ver == undefined)
          client_gas_ver = -1;
       
        if(script_password == client_auth)
        {
          if(gas_ver == client_gas_ver)
          {
            var id = JSON.parse(post_data.postData.contents).id;
       
            if(type == "send_text")
            {
              var send_message = JSON.parse(post_data.postData.contents).message;
              result = send_msg(id, send_message, time);
            }
            else if(type == "send_sticker")
            {
              var package_id = JSON.parse(post_data.postData.contents).package_id;
              var sticker_id = JSON.parse(post_data.postData.contents).sticker_id;
              result = send_sticker(id, package_id, sticker_id, time);
            }
            else if(type == "upload_content")
            {
              var content_data = JSON.parse(post_data.postData.contents).content_data;
              var count = JSON.parse(post_data.postData.contents).count;
              var name = JSON.parse(post_data.postData.contents).name;
              result = upload_content(id, content_data, count, name);
            }
            else if(type == "send_content")
            {
              var name = JSON.parse(post_data.postData.contents).name;
              result = send_content(id, name, time);
            }
            else
              result = "Unknown message type.";
          }
          else
            result = "Google apps script version does not match. Server's gas\nver is " + gas_ver + ", but 3DS's gas ver is " + client_gas_ver + ". Please use the same version.";
        }
        else
          result = "Auth failed. Please set correct password.";
      
        lock.releaseLock();
        return ContentService.createTextOutput(result);
      }
      
      function doGet(post_data)
      {
        var data = "";
        var client_auth = post_data.parameter.script_auth;
        var client_gas_ver = post_data.parameter.gas_ver;
        if(client_auth == undefined)
          client_auth = "";
        if(client_gas_ver == undefined)
          client_gas_ver = -1;
      
        if(script_password == client_auth)
        {
          if(gas_ver == client_gas_ver)
            data = log_read(post_data.parameter.id);
          else
            data = "Google apps script version does not match. Server's gas\nver is " + gas_ver + ", but 3DS's gas ver is " + client_gas_ver + ". Please use the same version.";
        }
        else
          data = "Auth failed. Please set correct password.";
       
        return ContentService.createTextOutput(data);
      }
      

    • This code compatible with ver 1.4.01.4.2
      ⚠⚠⚠WARNING⚠⚠⚠ I strongly recommend you use the newest version ⚠⚠⚠WARNING⚠⚠⚠

      Code:
      var ACCESS_TOKEN = "Your acces token here";
      var open_sheet_id = "Your sheet id here";
      var account_name_of_3ds = "Your 3ds's account name here";
      var script_password = "Your google apps script password here";
      
      var gas_ver = 4;//Do **NOT** edit this value.
      function log_save(message, user_name, write_sheet_name)
      {
        var sheet_pos = 1;
        var spreadsheet = SpreadsheetApp.openById(open_sheet_id);
        var write_sheet = spreadsheet.getSheetByName(write_sheet_name);
      
        if(!write_sheet)
        {
          spreadsheet.insertSheet(write_sheet_name);
          write_sheet = spreadsheet.getSheetByName(write_sheet_name);
        }
       
        sheet_pos = get_cache_pos(write_sheet);
       
        while(true)
        {
         var sheet_data = write_sheet.getRange("A" + sheet_pos).getValue();
      
         if(sheet_data == "")
         {
           write_sheet.getRange("A" + sheet_pos).setValue("" + user_name + " : " + message);
           break;
         }
         else
           sheet_pos++;
        }
       
        write_cache_pos(write_sheet, (sheet_pos + 1));
      }
      
      function check_folder_exist(input_folders, name)
      {
          var folder;
          while (input_folders.hasNext())
          {
            folder = input_folders.next();
            if(name == folder.getName())
              return folder;
          }
          return undefined;
      }
      
      function log_read(id)
      {
        var sheet_start = 1;
        var return_data;
        var sheet_data;
        var spreadsheet = SpreadsheetApp.openById(open_sheet_id);
        var read_sheet = spreadsheet.getSheetByName(id);
        sheet_start = get_cache_pos(read_sheet);
      
        while(true)
        {
          sheet_data = read_sheet.getRange("A" + sheet_start).getValue();
          if(sheet_data == "")
          {
            write_cache_pos(read_sheet, sheet_start);
            if(sheet_start >= 301)
              sheet_start = (sheet_start - 300);
            else
              sheet_start = 1;
       
            break;
          }
          else
            sheet_start++;
        }
       
        sheet_data = read_sheet.getRange(sheet_start, 1, 300).getValues();
        for(var i = 0; i < 300; i++)
        {
          if(sheet_data[i] == "")
            break;
       
          return_data += sheet_data[i];
        }
        return return_data;
      }
      
      function get_cache_pos(sheet_object)
      {
        var cached_sheet_pos = sheet_object.getRange("B1").getValue();
        var sheet_data;
       
        if(parseInt(cached_sheet_pos) > 0)
        {
          cached_sheet_pos = parseInt(cached_sheet_pos);
          sheet_data = sheet_object.getRange("A" + (cached_sheet_pos - 1)).getValue();
       
          if(sheet_data != "")
            return cached_sheet_pos;
        }
        return 1;
      }
      
      function write_cache_pos(sheet_object, cache_data)
      {
        sheet_object.getRange("B1").setValue(cache_data);
      }
      
      function http_get_content(request_id)
      {
        var response;
        var url = "https://api.line.me/v2/bot/message/" + request_id + "/content";
        response = UrlFetchApp.fetch(url,
        {
        'headers': {
          'Content-Type': 'application/json; charset=UTF-8',
          'Authorization': 'Bearer ' + ACCESS_TOKEN,
          },
          muteHttpExceptions: true,
        });
        return response;
      }
      
      function http_get_user_name(id)
      {
        var response;
        var url = 'https://api.line.me/v2/bot/profile/' + id;
        response = UrlFetchApp.fetch(url, {
          'headers': {
            'Content-Type': 'application/json; charset=UTF-8',
            'Authorization': 'Bearer ' + ACCESS_TOKEN,
          },
          muteHttpExceptions: true,
        });
        return response;
      }
      
      function http_get_group_user_name(id, group_id)
      {
        var response;
        var url = "https://api.line.me/v2/bot/group/" + group_id + "/member/" + id + "/";
        response = UrlFetchApp.fetch(url, {
          'headers': {
            'Content-Type': 'application/json; charset=UTF-8',
            'Authorization': 'Bearer ' + ACCESS_TOKEN,
          },
          muteHttpExceptions: true,
        });
        return response;
      }
      
      function http_send_text_reply(reply_token, send_msg)
      {
        var response;
        var url = 'https://api.line.me/v2/bot/message/reply/';
        response = UrlFetchApp.fetch(url, {
          'headers': {
            'Content-Type': 'application/json; charset=UTF-8',
            'Authorization': 'Bearer ' + ACCESS_TOKEN,
          },
          'method': 'post',
          'payload': JSON.stringify({
            'replyToken': reply_token,
            'messages': [{
              'type': 'text',
              'text': send_msg ,
            }],
            'notificationDisabled': 'true',
          }),
          muteHttpExceptions: true,
        });
        return response;
      }
      
      function http_send_text(id, send_msg)
      {
        var response;
        var url = 'https://api.line.me/v2/bot/message/push/';
        response = UrlFetchApp.fetch(url, {
          'headers': {
            'Content-Type': 'application/json; charset=UTF-8',
            'Authorization': 'Bearer ' + ACCESS_TOKEN,
          },
          'method': 'post',
          'payload': JSON.stringify({
        "to": id,
        "messages":
             [{
                "text": send_msg,
                "type": "text",
             }],
            'notificationDisabled': 'false',
          }),
         muteHttpExceptions: true,
        });
        return response;
      }
      
      function http_send_sticker(id, package_id, sticker_id)
      {
        var response;
        var url = 'https://api.line.me/v2/bot/message/push/';
        response = UrlFetchApp.fetch(url, {
          'headers': {
            'Content-Type': 'application/json; charset=UTF-8',
            'Authorization': 'Bearer ' + ACCESS_TOKEN,
          },
          'method': 'post',
          'payload': JSON.stringify({
        "to": id,
        "messages":
             [{
                "type": "sticker",
                "packageId": package_id,
                "stickerId": sticker_id,
             }],
            'notificationDisabled': 'false',
          }),
         muteHttpExceptions: true,
        });
        return response;
      }
      
      function http_send_image(id, img_url, preview_url)
      {
        var response;
        var url = 'https://api.line.me/v2/bot/message/push/';
        response = UrlFetchApp.fetch(url, {
          'headers': {
            'Content-Type': 'application/json; charset=UTF-8',
            'Authorization': 'Bearer ' + ACCESS_TOKEN,
          },
          'method': 'post',
          'payload': JSON.stringify({
        "to": id,
        "messages":
             [{
                "type": "image",
                "originalContentUrl": img_url,
                "previewImageUrl": preview_url,
             }],
            'notificationDisabled': 'false',
          }),
         muteHttpExceptions: true,
        });
        return response;
      }
      
      function send_msg(id, send_message, time)
      {
        var cache;
        var response;
        var return_message = "Success";
       
        response = http_send_text(id, send_message);
        if(response.getResponseCode() != 200)
        {
          cache = "***The message failed to send. Status code = " + response.getResponseCode() + "\n" + JSON.parse(response.getContentText()).message + "*** ";
          cache += send_message;
          send_message = cache;
          return_message = "The message failed to send. Status code = " + response.getResponseCode() + "\n" + JSON.parse(response.getContentText()).message;
        }
        send_message += "(" + time + ")";
        log_save(send_message, account_name_of_3ds, id);
        return return_message;
      }
      
      function send_sticker(id, package_id, sticker_id, time)
      {
        var response;
        var return_message = "Success";
        var send_message = "";
       
        response = http_send_sticker(id, package_id, sticker_id);
        if(response.getResponseCode() != 200)
        {
         send_message = "***The sticker failed to send. Status code = " + response.getResponseCode() + " " + JSON.parse(response.getContentText()).message + "*** ";
         return_message = "The sticker failed to send. Status code = " + response.getResponseCode() + "\n" + JSON.parse(response.getContentText()).message;
        }
        send_message += "<sticker>" + sticker_id + "</sticker>(" + time + ")";
        log_save(send_message, account_name_of_3ds, id);
        return return_message;
      }
      
      function upload_content(id, data, count, cache_name)
      {
        var cache_folder;
        var exist_cache_folders;
        var exist_folders;
        var exist_sub_folders;
        var folder;
        var folder_name = "Line_contents";
        var part_of_content;
        var part_of_content_data;
        var return_message = "Success";
        var sub_folder;
       
        exist_folders = DriveApp.searchFolders("'me' in owners");
        folder = check_folder_exist(exist_folders, folder_name);
        if(folder == undefined)
          folder = DriveApp.createFolder(folder_name);
       
        exist_sub_folders = folder.searchFolders("'me' in owners");
        sub_folder = check_folder_exist(exist_sub_folders, id);
        if(sub_folder == undefined)
          sub_folder = folder.createFolder(id);
       
        exist_cache_folders = sub_folder.searchFolders("'me' in owners");
        cache_folder = check_folder_exist(exist_cache_folders, cache_name);
        if(cache_folder == undefined)
          cache_folder = sub_folder.createFolder(cache_name);
        else if(!(cache_folder == undefined) && count == 0)
        {
          cache_folder.setTrashed(true);
          cache_folder = sub_folder.createFolder(cache_name);
        }
       
        part_of_content_data = Utilities.newBlob(data).setName(count);
        part_of_content = cache_folder.createFile(part_of_content_data);
        return return_message;
      }
      
      function send_content(id, cache_name, time)
      {
        var cache_file;
        var cache_folder;
        var content;
        var content_data;
        var content_type;
        var content_url = "";
        var encoded_data = "";
        var exist_cache_folders;
        var exist_folders;
        var exist_sub_folders;
        var folder;
        var folder_name = "Line_contents";
        var preview_content_url = "";
        var response;
        var return_message = "Success";
        var send_message = "";
        var sub_folder;
       
        exist_folders = DriveApp.searchFolders("'me' in owners");
        folder = check_folder_exist(exist_folders, folder_name);
        if(folder == undefined)
          folder = DriveApp.createFolder(folder_name);
      
        exist_sub_folders = folder.searchFolders("'me' in owners");
        sub_folder = check_folder_exist(exist_sub_folders, id);
        if(sub_folder == undefined)
          sub_folder = folder.createFolder(id);
      
        exist_cache_folders = sub_folder.searchFolders("'me' in owners");
        cache_folder = check_folder_exist(exist_cache_folders, cache_name);
        if(cache_folder == undefined)
        {
          send_message = "***The content failed to send. The cache folder does not exist.*** (" + time + ")";
          log_save(send_message, account_name_of_3ds, id);
          return_message = "The content failed to send.\nThe cache folder does not exist."
          return return_message;
        }
      
        for(var i = 0; i < 4096; i++)
        {
          try
          {
            cache_file = cache_folder.getFilesByName(i).next();
            encoded_data += cache_file.getBlob().getDataAsString();
          }
          catch(error)
          {
            break;
          }
        }
      
        cache_folder.setTrashed(true);
        content_data = Utilities.newBlob(Utilities.base64Decode(encoded_data)).setName(cache_name);
        content = sub_folder.createFile(content_data);
        content.setSharing(DriveApp.Access.ANYONE, DriveApp.Permission.VIEW);
        content_type = content.getMimeType();
        if(content_type == MimeType.BMP || content_type == MimeType.GIF || content_type == MimeType.JPEG || content_type == MimeType.PNG || content_type == MimeType.SVG)
        {
          content.setTrashed(true);
          folder_name = "Line_images";
          exist_folders = DriveApp.searchFolders("'me' in owners");
          folder = check_folder_exist(exist_folders, folder_name);
          if(folder == undefined)
          folder = DriveApp.createFolder(folder_name);
      
          exist_sub_folders = folder.searchFolders("'me' in owners");
          sub_folder = check_folder_exist(exist_sub_folders, id);
          if(sub_folder == undefined)
          sub_folder = folder.createFolder(id);
       
          content = sub_folder.createFile(content_data);
          content.setSharing(DriveApp.Access.ANYONE, DriveApp.Permission.VIEW);
          content_url = "https://lh3.googleusercontent.com/d/" + content.getId() + "=w16383-h16383";
          preview_content_url = "https://lh3.googleusercontent.com/d/" + content.getId() + "=w240-h240";
       
          response = http_send_image(id, content_url, preview_content_url);
          if(response.getResponseCode() != 200)
          {
            send_message = "***The image failed to send. Status code = " + response.getResponseCode() + " " + JSON.parse(response.getContentText()).message + "*** ";
            return_message = "The image failed to send. Status code = " + response.getResponseCode() + "\n" + JSON.parse(response.getContentText()).message;
          }
          send_message += "<image_url>" + content_url + "</image_url>(" + time + ")";
          log_save(send_message, account_name_of_3ds, id);
          return return_message;
        }
        else
        {
          content_url = "https://drive.google.com/file/d/" + content.getId() + "/view";
          response = http_send_text(id, content_url);
          if(response.getResponseCode() != 200)
          {
            send_message = "***The content failed to send. Status code = " + response.getResponseCode() + " " + JSON.parse(response.getContentText()).message + "*** ";
            return_message = "The content failed to send. Status code = " + response.getResponseCode() + "\n" + JSON.parse(response.getContentText()).message;
          }
          content_url = "https://drive.google.com/uc?export=download&id=" + content.getId();
          send_message += "<content_url>" + content_url + "</content_url>(" + time + ")";
          log_save(send_message, account_name_of_3ds, id);
          return return_message;
        }
      }
      
      function get_content_url(request_id, group_or_user_id, type)
      {
        var content_data;
        var content;
        var url = "";
        var folder_name;
        var folder;
        var sub_folder;
        var exist_folders;
        var exist_sub_folders;
        var response;
       
        if(type == "image")
          folder_name = "Line_images";
        else if(type == "audio")
          folder_name = "Line_audio";
        else if(type == "video")
          folder_name = "Line_videos";
       
        exist_folders = DriveApp.searchFolders("'me' in owners");
        folder = check_folder_exist(exist_folders, folder_name);
        if(folder  == undefined)
          folder = DriveApp.createFolder(folder_name);
       
        exist_sub_folders = folder.searchFolders("'me' in owners");
        sub_folder = check_folder_exist(exist_sub_folders, group_or_user_id);
        if(sub_folder  == undefined)
          sub_folder = folder.createFolder(group_or_user_id);
       
        response = http_get_content(request_id);
        if(response.getResponseCode() != 200)
        {
          if(type == "image")
            url = "***Couldn't generate an image URL. Status code = " + response.getResponseCode() + " " + JSON.parse(response.getContentText()).message + "*** ";
          else if(type == "audio")
            url = "***Couldn't generate a audio URL. Status code = " + response.getResponseCode() + " " + JSON.parse(response.getContentText()).message + "*** ";
          else if(type == "video")
            url = "***Couldn't generate a video URL. Status code = " + response.getResponseCode() + " " + JSON.parse(response.getContentText()).message + "*** ";
        }
        else
        {
          if(type == "image")
          {
            content_data = response.getBlob().getAs("image/jpeg").setName(request_id);
            content = sub_folder.createFile(content_data);
            content.setSharing(DriveApp.Access.ANYONE, DriveApp.Permission.VIEW);
            url = "https://lh3.googleusercontent.com/d/" + content.getId() + "=w16383-h16383";
          }
          else if(type == "audio" || type == "video")
          {
            content_data = response.getBlob().setName(request_id);
            content = sub_folder.createFile(content_data);
            content.setSharing(DriveApp.Access.ANYONE, DriveApp.Permission.VIEW);
            url = "https://drive.google.com/uc?export=download&id=" + content.getId();
          }
        }
        return url;
      }
      
      function receive_msg_from_line(user_message, user_id, group_id, reply_token, time)
      {
        var response;
        var send_msg;
        var user_name;
       
        if(user_message == "getid" || user_message == "getgroupid")
        {
          if(user_message == "getid")
            send_msg = user_id;
          else if(user_message == "getgroupid")
            send_msg = group_id;
       
          response = http_send_text_reply(reply_token, send_msg);
          if(response.getResponseCode() != 200)
            send_msg += "***The message failed to send. Status code = " + response.getResponseCode() + " " + JSON.parse(response.getContentText()).message + "*** ";
      
          log_save(send_msg, "BOT", "IDs");
          return;
        }
       
        if(group_id == "Unknown")
          response = http_get_user_name(user_id);
        else
          response = http_get_group_user_name(user_id, group_id);
       
        if(response.getResponseCode() != 200)
          user_name = "Unknown";
        else
          user_name = JSON.parse(response).displayName;
      
        user_message += "(" + time + ")";
        if(group_id == "Unknown")
          log_save(user_message, user_name, user_id);
        else
          log_save(user_message, user_name, group_id);
      }
      
      function doPost(post_data)
      {
        var date = new Date();
        var time = Utilities.formatDate( date, 'Asia/Tokyo', 'MM/dd hh:mm:ss');
        var type = JSON.parse(post_data.postData.contents).type;
        var result;
        var lock = LockService.getScriptLock();
        var lock_result = lock.tryLock(1000);
        while(!lock_result)
        {
          Utilities.sleep(100);
          lock_result = lock.tryLock(1000);
        }
       
        if(type == undefined)
        {
          for(var i = 0; i < 30; i++)
          {
            try
            {
              var msg_id = JSON.parse(post_data.postData.contents).events[i].message.id;
              var user_message = JSON.parse(post_data.postData.contents).events[i].message.text;
              var user_id = JSON.parse(post_data.postData.contents).events[i].source.userId;
              var group_id = JSON.parse(post_data.postData.contents).events[i].source.groupId;
              var reply_token = JSON.parse(post_data.postData.contents).events[i].replyToken;
              var type = JSON.parse(post_data.postData.contents).events[i].message.type;
            }
            catch(error)
            {
              break;
            }
       
            if(user_id == undefined)
              user_id = "Unknown";
            if(group_id == undefined)
              group_id = "Unknown";
      
            if(type == "sticker")
            {
              var sticker_id  = JSON.parse(post_data.postData.contents).events[0].message.stickerId;
              user_message = "<sticker>" + sticker_id + "</sticker>";
            }
            else if(type == "image")
            {
             if(group_id == "Unknown")
               user_message = "<image_url>" + get_content_url(msg_id, user_id, type) + "</image_url>";
             else
               user_message = "<image_url>" + get_content_url(msg_id, group_id, type) + "</image_url>";
            }
            else if(type == "audio")
            {
             if(group_id == "Unknown")
               user_message = "<audio_url>" + get_content_url(msg_id, user_id, type) + "</audio_url>";
             else
               user_message = "<audio_url>" + get_content_url(msg_id, group_id, type) + "</audio_url>";       }
            else if(type == "video")
            {
             if(group_id == "Unknown")
               user_message = "<video_url>" + get_content_url(msg_id, user_id, type) + "</video_url>";
             else
               user_message = "<video_url>" + get_content_url(msg_id, group_id, type) + "</video_url>";
            }
            else if(user_message == undefined)
              user_message += " : " + type + " " + msg_id;
      
            receive_msg_from_line(user_message, user_id, group_id, reply_token, time);
          }
          lock.releaseLock();
          return;
        }
       
        var client_auth = JSON.parse(post_data.postData.contents).auth;
        var client_gas_ver = JSON.parse(post_data.postData.contents).gas_ver;
        if(client_auth == undefined)
          client_auth = "";
        if(client_gas_ver == undefined)
          client_gas_ver = -1;
       
        if(script_password == client_auth)
        {
          if(gas_ver == client_gas_ver)
          {
            var id = JSON.parse(post_data.postData.contents).id;
       
            if(type == "send_text")
            {
              var send_message = JSON.parse(post_data.postData.contents).message;
              result = send_msg(id, send_message, time);
            }
            else if(type == "send_sticker")
            {
              var package_id = JSON.parse(post_data.postData.contents).package_id;
              var sticker_id = JSON.parse(post_data.postData.contents).sticker_id;
              result = send_sticker(id, package_id, sticker_id, time);
            }
            else if(type == "upload_content")
            {
              var content_data = JSON.parse(post_data.postData.contents).content_data;
              var count = JSON.parse(post_data.postData.contents).count;
              var name = JSON.parse(post_data.postData.contents).name;
              result = upload_content(id, content_data, count, name);
            }
            else if(type == "send_content")
            {
              var name = JSON.parse(post_data.postData.contents).name;
              result = send_content(id, name, time);
            }
            else
              result = "Unknown message type.";
          }
          else
            result = "Google apps script version does not match. Server's gas\nver is " + gas_ver + ", but 3DS's gas ver is " + client_gas_ver + ". Please use the same version.";
        }
        else
          result = "Auth failed. Please set correct password.";
       
        lock.releaseLock();
        return ContentService.createTextOutput(result);
      }
      
      function doGet(post_data)
      {
        var data = "";
        var client_auth = post_data.parameter.script_auth;
        var client_gas_ver = post_data.parameter.gas_ver;
        if(client_auth == undefined)
          client_auth = "";
        if(client_gas_ver == undefined)
          client_gas_ver = -1;
       
        if(script_password == client_auth)
        {
          if(gas_ver == client_gas_ver)
          {
            data = log_read(post_data.parameter.id);
            data += "<success>";
          }
          else
            data = "Google apps script version does not match. Server's gas\nver is " + gas_ver + ", but 3DS's gas ver is " + client_gas_ver + ". Please use the same version.";
        }
        else
          data = "Auth failed. Please set correct password.";
       
        return ContentService.createTextOutput(data);
      }
      


    Then click Publish -> Deploy as web app and set
    "Project version" : New
    "Execute the app as" : Me(***@gmail.com)

    "Who has access to the app" : Anyone,even anonymous
    finally click deploy.

    2380c28d8c9f5f0fdba5bcaad06b5e09.png
    Next click Review permissions and select your google account.
    If "This app isn't verified or You should avoid this app" shown click Advanced and click "
    Go to Line main (unsafe)" (⁂It's safe!) and click allow.
    Copy this url and save.

    578f8adc76932a8223d45d904303d707.png

    Back to Line Messaging API
    Find Webhook URL and click edit.

    ⁂ DO NOT TYPE SHORT URL HERE ⁂

    Type your
    Google apps script URL and click Update

    003b8ec8407b4db43fef03a9a6337a6b.png
    And turn on Use webhook
    5dc4172fb531eacaf26757aa3fdb1b64.png

    Click verify to check webhook works fine.
    Check result and if "success" wasn't displayed, double check your Google apps script URL.
    .
    (delete whole url once and retype is also good idea)

    Please open https://free-url-shortener.rb.gy/ , https://tiny.cc/ or https://tinyurl.com/
    Then shorten your Google apps script URL.
    Your URL should be
    http://tinyurl.com/****** or http://tiny.cc/****** or http://rb.gy/******
    This short URL is needed by next section.
    Then go to (Guide) How to setup (3DS).

    If you have any problems fell free to ask me on this discord server.
    https://discord.gg/bzGnu2a



    Download this
    https://github.com/Core-2-Extreme/Line_for_3DS/releases

    Start app and select Line.
    Set your password (if you don't want use password, enter as empty).


    • This guide compatible with ver 1.5.01.6.0

      Next step there are 2 methods
      Press L + R button (or tap Change main URL (short)) and type your short url

      I do NOT recommend this method because it is hell ;(
      if you want to type whole URL, press X button (or tap Change main URL) and type your google apps script URL.

    • This guide compatible with ver 1.2.01.4.2
      ⚠⚠⚠WARNING⚠⚠⚠ I strongly recommend you use the newest version ⚠⚠⚠WARNING⚠⚠⚠

      Tap "Advanced setting" and Press X button and type your google apps script URL.

    Then go to (Guide)How to add friend.
    If you have any problems fell free to ask me on this discord server.
    https://discord.gg/bzGnu2a




    PC or phone (or android emulator)
    Find Bot information and scan your bot's QR code or search friends by BOT basic ID.

    c5fce08f621dcbde7f904b526a0dde38.png



    • This guide compatible with ver 1.6.0

      3DS

      Press Y button (or tap Add new ID) and type "IDs".

      00000024.jpg
      00000021.jpg

      Select "IDs".

      00000032.jpg

      Tap "Receive" tab and press B button (or tap log update)

      00000030.jpg

      You'll see touch to add this ID and tap it.

      00000029.jpg
      00000031.jpg
      00000033.jpg


    • And send "
      getid".
      00000029.png


      • This guide compatible with ver 1.5.01.5.2
        ⚠⚠⚠WARNING⚠⚠⚠ I strongly recommend you use the newest version ⚠⚠⚠WARNING⚠⚠⚠

        3DS

        Press Y button (or tap Add new ID) and type "IDs".
        00000024.jpg
        00000021.jpg

        Select "IDs".

        00000032.jpg

        Tap "Receive" tab and press B button (or tap log update)

        00000030.jpg

        You'll see touch to add this ID and tap it.
        00000029.jpg
        00000031.jpg
        00000033.jpg


      • This guide compatible with ver 1.2.01.4.2
        ⚠⚠⚠WARNING⚠⚠⚠ I strongly recommend you use the newest version ⚠⚠⚠WARNING⚠⚠⚠

        3DS

        Tap "Advanced setting" and press Y button and type ID.



    If you have any problems fell free to ask me on this discord server.
    https://discord.gg/bzGnu2a




    Enjoy!
     

    Attached Files:

    Last edited by Core_2_Extreme, Sep 13, 2020
  2. BORTZ

    BORTZ The Amazing
    Supervisor

    Joined:
    Dec 2, 2007
    Messages:
    13,064
    Country:
    United States
    This is the kinda homebrew I love to see. Nice work, OP.
     
    Core_2_Extreme likes this.
  3. Issac

    Issac I
    Supervisor

    Joined:
    Apr 10, 2004
    Messages:
    6,730
    Country:
    Sweden
    Wow, really cool! Nice work!

    Edit:
    Do you have any plans to try to implement stamps? Or the other features that it can't do right now :)
     
    Last edited by Issac, May 28, 2019
    Core_2_Extreme likes this.
  4. pilladoll

    pilladoll GBAtemp Regular
    Member

    Joined:
    Nov 14, 2004
    Messages:
    192
    Country:
    Mexico
    Nice!
     
    Core_2_Extreme likes this.
  5. Core_2_Extreme

    OP Core_2_Extreme Member
    Newcomer

    Joined:
    Feb 11, 2019
    Messages:
    34
    Country:
    Japan

    I will try add picture and stamp view. (and send)
    But I don't know it's possible.
     
  6. Issac

    Issac I
    Supervisor

    Joined:
    Apr 10, 2004
    Messages:
    6,730
    Country:
    Sweden
    I don't know how Line works, but it feels like it shouldn't be impossible :) What happens in the 3DS if you send a stamp or picture from the phone?
     
    Core_2_Extreme likes this.
  7. Core_2_Extreme

    OP Core_2_Extreme Member
    Newcomer

    Joined:
    Feb 11, 2019
    Messages:
    34
    Country:
    Japan
    Send from 3DS
    3DS -> Google server -> LINE server -> line app
    Send from line app
    line app -> LINE server -> Google server -> save to message log google server -> 3DS(Request data to google and receive data)

    I will write tutorial how to use line on 3DS. But it will write a little later.

    If you send picture, video, sound, or stamp. 3DS will be displayed "undefined".
    PC
    [​IMG]

    3DS
    [​IMG]
     
    Issac likes this.
  8. Issac

    Issac I
    Supervisor

    Joined:
    Apr 10, 2004
    Messages:
    6,730
    Country:
    Sweden
    Thank you! That's interesting :)
     
    Core_2_Extreme likes this.
  9. This looks awesome!

    How'd you do this?

    I'd be interested to see if something similar could be done w/ Discord, but this is genuinely awesome this is what homebrew this community needs.
     
    Core_2_Extreme likes this.
  10. lone_wolf323

    lone_wolf323 GBAtemp Psycho!
    Member

    Joined:
    May 27, 2011
    Messages:
    3,624
    Country:
    Canada
    discord was already done. and it was shown that it could and highly likely ban your discord account using it.
     
    Core_2_Extreme likes this.
  11. Oh yeah I'm aware but I was thinking ab a client w/ WebSockets
     
    Core_2_Extreme likes this.
  12. Zurdonx

    Zurdonx Advanced Member
    Newcomer

    Joined:
    Oct 2, 2018
    Messages:
    76
    Country:
    Venezuela
    Looks interesting. Great work!
     
    Core_2_Extreme likes this.
  13. Deleted User

    Deleted User Newbie

    Nice work!:D
     
    Core_2_Extreme likes this.
  14. triplekiller
    This message by triplekiller has been removed from public view by Quantumcat, Jun 14, 2019, Reason: Empty/bumping.
    Jun 13, 2019
  15. Deleted-481927
    This message by Deleted-481927 has been removed from public view by Quantumcat, Jun 14, 2019, Reason: Reply to deleted post.
    Jun 13, 2019
  16. Core_2_Extreme

    OP Core_2_Extreme Member
    Newcomer

    Joined:
    Feb 11, 2019
    Messages:
    34
    Country:
    Japan
  17. Core_2_Extreme

    OP Core_2_Extreme Member
    Newcomer

    Joined:
    Feb 11, 2019
    Messages:
    34
    Country:
    Japan
    Last edited by Core_2_Extreme, Mar 17, 2020
    Zurdonx likes this.
  18. junk16

    junk16 Newbie
    Newcomer

    Joined:
    Dec 15, 2019
    Messages:
    1
    Country:
    Japan
    Nice work!! but,when I do it, it crash... sad please tell me how to do ver 1.1
     
    Core_2_Extreme likes this.
  19. Core_2_Extreme

    OP Core_2_Extreme Member
    Newcomer

    Joined:
    Feb 11, 2019
    Messages:
    34
    Country:
    Japan
    I updated guide, please try again.
     
  20. PokeNev

    PokeNev GBAtemp Fan
    Member

    Joined:
    Nov 11, 2018
    Messages:
    322
    Country:
    United States
    Will you ever add the feature to send videos? Or is that out of the question at this point?
     
    Core_2_Extreme likes this.
  21. Core_2_Extreme

    OP Core_2_Extreme Member
    Newcomer

    Joined:
    Feb 11, 2019
    Messages:
    34
    Country:
    Japan
    I think it's impossible to send pictures or videos to line server directly.(but it's maybe possible view pictures)
     
    Zurdonx likes this.
  22. PokeNev

    PokeNev GBAtemp Fan
    Member

    Joined:
    Nov 11, 2018
    Messages:
    322
    Country:
    United States
    Nice
     
    Core_2_Extreme likes this.
Draft saved Draft deleted
Loading...

Hide similar threads Similar threads with keywords - [Release][Guide],