Advertisement
Guest User

Bionic - VK

a guest
Jul 27th, 2016
117
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 55.36 KB | None | 0 0
  1.  
  2. ---------------------------------------------------- Библиотеки ----------------------------------------------------------------
  3.  
  4. local advancedLua = require("advancedLua")
  5. local json = require("json")
  6. local serialization = require("serialization")
  7. local event = require("event")
  8. local ecs = require("ECSAPI")
  9. local fs = require("filesystem")
  10. local buffer = require("doubleBuffering")
  11. local context = require("context")
  12. local image = require("image")
  13. local unicode = require("unicode")
  14. local component = require("component")
  15. local computer = require("computer")
  16. local files = require("files")
  17. local GUI = require("GUI")
  18.  
  19. ---------------------------------------------------- Константы ----------------------------------------------------------------
  20.  
  21. local VKAPIVersion = "5.52"
  22.  
  23. local colors = {
  24.     leftBar = 0x262626,
  25.     leftBarAlternative = 0x383838,
  26.     leftBarText = 0xFFFFFF,
  27.     leftBarSelection = 0x00A8FF,
  28.     leftBarSelectionText = 0xFFFFFF,
  29.  
  30.     scrollBar = 0xCCCCCC,
  31.     scrollBarPipe = 0x666666,
  32.  
  33.     mainZone = 0xFFFFFF,
  34.     senderCloudColor = 0x3392FF,
  35.     senderCloudTextColor = 0xFFFFFF,
  36.     yourCloudColor = 0x55BBFF,
  37.     yourCloudTextColor = 0xFFFFFF,
  38.     systemMessageColor = 0x555555,
  39.     dateTime = 0x777777,
  40.  
  41.     loginGUIBackground = 0x002440,
  42.  
  43.     topBar = 0x002440,
  44.     topBarText = 0xFFFFFF,
  45.  
  46.     statusBar = 0x1b1b1b,
  47.     statusBarText = 0xAAAAAA,
  48.  
  49.     audioPlayButton = 0x002440,
  50.     audioPlayButtonText = 0xFFFFFF,
  51.  
  52.     messageInputBarColor = 0xEEEEEE,
  53.     messageInputBarTextBackgroundColor = 0xFFFFFF,
  54.     messsageInputBarTextColor = 0x262626,
  55. }
  56.  
  57. local leftBarHeight = buffer.screen.height - 9
  58. local leftBarWidth = math.floor(buffer.screen.width * 0.20)
  59.  
  60. local topBarHeight = 3
  61.  
  62. local mainZoneWidth = buffer.screen.width - leftBarWidth
  63. local mainZoneHeight = buffer.screen.height - topBarHeight - 1
  64. local mainZoneX = leftBarWidth + 1
  65. local mainZoneY = topBarHeight + 1
  66.  
  67. local cloudWidth = math.floor(mainZoneWidth * 0.7)
  68.  
  69. -------------------------------------------------------------------------------------------------------------------------------
  70.  
  71. local settingsPath = "MineOS/System/VK/Settings.cfg"
  72. local VKLogoImagePath = "MineOS/Applications/VK.app/Resources/VKLogo.pic"
  73. -- local leftBarElements = {"Новости", "Друзья", "Сообщения", "Настройки", "Выход"}
  74. local leftBarElements = { "Моя страница", "Друзья", "Сообщения", "Аудиозаписи", "Новости", "Настройки", "Выход" }
  75. local currentLeftBarElement = 3
  76. local personalInfo
  77. local access_token
  78. local whatIsOnScreen
  79.  
  80. local countOfDialogsToLoadFromServer = 10
  81. local countOfAudioToLoadFromServer = 10
  82. local countOfMessagesToLoadFromServer = 10
  83.  
  84. local dialogToShowFrom = 1
  85. local audioToShowFrom = 1
  86. local messageToShowFrom = 1
  87.  
  88. local dialogScrollSpeed = 5
  89. local audioScrollSpeed = 5
  90. local messagesScrollSpeed = 5
  91. local profileScrollSpeed = 2
  92. local friendsScrollSpeed = 5
  93.  
  94. local countOfFriendsToGetOnFriendsTab = 12
  95. local currentFriendsOffset = 0
  96. local currentFriends = {}
  97.  
  98. local countOfFriendsToDisplayInProfile = 16
  99. local currentProfileY = mainZoneY + 2
  100.  
  101. local currentMessagesPeerID, currentMessagesAvatarText
  102. local dialogPreviewTextLimit = mainZoneWidth - 15
  103. local currentProfile
  104.  
  105. local settings = {saveAuthData = false, addSendingInfo = true}
  106.  
  107. local vip = {
  108.     [7799889] = {avatarColor = 0x000000, avatarTextColor = 0xCCCCCC, avatarBottomText = "DEV", avatarBottomTextColor = 0x1b1b1b},
  109.     [113499693] = {avatarColor = 0xFF99CC, avatarTextColor = 0x000000, avatarBottomText = "DEV", avatarBottomTextColor = 0xff6dbf},
  110.     [60991376] = {avatarColor = 0xEEEEEE, avatarTextColor = 0x000000, avatarBottomText = "DEV", avatarBottomTextColor = 0x555555},
  111. }
  112.  
  113. local messageEndAdderText = " (отправлено с MineOS VKClient)"
  114.  
  115. local news
  116. local currentNews = 1
  117. local countOfNewsToShow = 10
  118. local countOfNewsToGet = 20
  119.  
  120. ---------------------------------------------------- Веб-часть ----------------------------------------------------------------
  121.  
  122. local function loadSettings()
  123.     if fs.exists(settingsPath) then settings = files.loadTableFromFile(settingsPath) end
  124. end
  125.  
  126. local function saveSettings()
  127.     files.saveTableToFile(settingsPath, settings)
  128. end
  129.  
  130. --Объекты
  131. local obj = {}
  132. local function newObj(class, name, ...)
  133.     obj[class] = obj[class] or {}
  134.     obj[class][name] = {...}
  135. end
  136.  
  137. --Дебаг-функция на сохранение говна в файл, МАЛО ЛИ ЧО
  138. local function saveToFile(filename, stro4ka)
  139.     local file = io.open(filename, "w")
  140.     file:write(stro4ka)
  141.     file:close()
  142. end
  143.  
  144. --Банальный URL-запрос, декодирующийся через ЖУСОН в случае успеха, епты
  145. local function request(url)
  146.     local success, response = ecs.internetRequest(url)
  147.     if success then response = json:decode(response) end
  148.     return success, response
  149. end
  150.  
  151. --Отправляем запрос на авторизацию по логину и паролю
  152. local function getLoginDataRequest(username, password)
  153.     local url = "https://oauth.vk.com/token?grant_type=password&client_id=3697615&client_secret=AlVXZFMUqyrnABp8ncuU&username=" .. username .. "&password=" .. password .. "&v=" .. VKAPIVersion
  154.     return request(url)
  155. end
  156.  
  157. --Запрос к методам VK API
  158. local function VKAPIRequest(method, ... )
  159.     local arguments = { ... }
  160.     local stringArguments = ""
  161.  
  162.     local url = "https://api.vk.com/method/" .. method .. "?" .. table.concat(arguments, "&") .. "&access_token=" .. access_token .. "&v=" .. VKAPIVersion
  163.  
  164.     return request(url)
  165. end
  166.  
  167. --Запрос на получение списка диалогов
  168. local function getDialogsRequest(fromDialog, count)
  169.     return VKAPIRequest("messages.getDialogs", "offset=" .. fromDialog, "count=" .. count, "preview_length=" .. dialogPreviewTextLimit)
  170. end
  171.  
  172. --Запрос на получение списка диалогов
  173. local function getMessagesRequest(peerID, fromMessage, count)
  174.     return VKAPIRequest("messages.getHistory", "offset=" .. fromMessage, "count=" .. count, "peer_id=" .. peerID)
  175. end
  176.  
  177. --Запрос на получение списка музычки
  178. local function getAudioRequest(id, fromAudio, count)
  179.     return VKAPIRequest("audio.get", "offset=" .. fromAudio, "count=" .. count, "owner_id=" .. id, "need_user=1")
  180. end
  181.  
  182. --Эта хуйня делает строку охуенной путем замены говна на конфетку
  183. local function optimizeStringForURLSending(code)
  184.   if code then
  185.     code = string.gsub(code, "([^%w ])", function (c)
  186.       return string.format("%%%02X", string.byte(c))
  187.     end)
  188.     code = string.gsub(code, " ", "+")
  189.   end
  190.   return code
  191. end
  192.  
  193. local function optimizeStringForWrongSymbols(s)
  194.     --Удаляем некорректные символы
  195.     s = string.gsub(s, "    ", " ")
  196.     s = string.gsub(s, "\r\n", "\n")
  197.     s = string.gsub(s, "\n", "")
  198.     --Заменяем "широкие" двухпиксельные символы на знак вопроса
  199.     local massiv = {}
  200.     for i = 1, unicode.len(s) do
  201.         massiv[i] = unicode.sub(s, i, i)
  202.         if unicode.isWide(massiv[i]) then massiv[i] = "?" end
  203.     end
  204.     --Возвращаем оптимизрованную строку
  205.     return table.concat(massiv)
  206. end
  207.  
  208. local function convertIDtoPeerID(whatIsThisID, ID)
  209.     if whatIsThisID == "user" then
  210.         return ID
  211.     elseif whatIsThisID == "chat" then
  212.         return (2000000000 + ID)
  213.     elseif whatIsThisID == "group" then
  214.         return -ID
  215.     end
  216. end
  217.  
  218. local function getPeerIDFromMessageArray(messageArray)
  219.     local peerID
  220.     --Если это чат
  221.     if messageArray.users_count then
  222.         peerID = convertIDtoPeerID("chat", messageArray.chat_id)
  223.     --Или если это диалог с группой какой-то
  224.     elseif messageArray.user_id < 0 then
  225.         peerID = convertIDtoPeerID("group", messageArray.user_id)
  226.     --Или если просто какой-то сталкер-одиночка
  227.     else
  228.         peerID = convertIDtoPeerID("user", messageArray.user_id)
  229.     end
  230.  
  231.     return peerID
  232. end
  233.  
  234. --Запрос на отправку сообщения указанному пидору
  235. local function sendMessageRequest(peerID, message)
  236.     --Делаем строчку не пидорской
  237.     message = optimizeStringForURLSending(message)
  238.     return VKAPIRequest("messages.send", "peer_id=" .. peerID, "message=" .. message)
  239. end
  240.  
  241. local function usersInformationRequest(...)
  242.     return VKAPIRequest("users.get", "user_ids=" .. table.concat({...}, ","), "fields=contacts,education,site,city,bdate,online,status,last_seen,quotes,about,games,books,counters,relatives,connections,blacklisted,activities,interests,music,movies,tv")
  243. end
  244.  
  245. local function userFriendsRequest(ID, count, offset, order, nameCase)
  246.     return VKAPIRequest("friends.get", "user_id=" .. ID, "count=" .. count, "offset=" .. offset, "order=" .. order, "name_case=" .. nameCase, "fields=domain,online,last_seen")
  247. end
  248.  
  249. local function userFriendsListsRequest(ID)
  250.     return VKAPIRequest("friends.getLists", "user_id=" .. ID, "return_system=1")
  251. end
  252.  
  253. local function userWallRequest(ID, count, offset)
  254.     return VKAPIRequest("wall.get", "owner_id=" .. ID, "count=" .. count, "offset=" .. offset)
  255. end
  256.  
  257. local function setCurrentAudioPlaying(ownerID, audioID)
  258.     return VKAPIRequest("audio.setBroadcast", "audio=" .. ownerID .. "_" .. audioID)
  259. end
  260.  
  261. local function newsRequest(count)
  262.     return VKAPIRequest("newsfeed.get", "filters=post", "return_banned=1", "max_photos=0", "count=" .. count, "fields=name,first_name,last_name")
  263. end
  264.  
  265. local function setCrazyTypingRequest(peer_id)
  266.     return VKAPIRequest("messages.setActivity", "type=typing", "peer_id=" .. peer_id)
  267. end
  268.  
  269.  
  270.  
  271.  
  272.  
  273. ---------------------------------------------------- GUI-часть ----------------------------------------------------------------
  274.  
  275. local function createAvatarHashColor(hash)
  276.     return math.abs(hash % 0xFFFFFF)
  277. end
  278.  
  279. local function drawAvatar(x, y, width, height, user_id, text)
  280.     local avatarColor = createAvatarHashColor(user_id)
  281.     local textColor = avatarColor > 8388607 and 0x000000 or 0xFFFFFF
  282.  
  283.     --Хочу себе персональную авку, а то че за хуйня?
  284.     if vip[user_id] then
  285.         avatarColor = vip[user_id].avatarColor
  286.         textColor = vip[user_id].avatarTextColor
  287.     end
  288.  
  289.     buffer.square(x, y, width, height, avatarColor, textColor, " ")
  290.     buffer.text(x + math.floor(width / 2) - math.floor(unicode.len(text) / 2), y + math.floor(height / 2), textColor, unicode.upper(text))
  291.  
  292.     if vip[user_id] and vip[user_id].avatarBottomText then buffer.text(x + math.floor(width / 2) - math.floor(unicode.len(text) / 2), y + height - 1, vip[user_id].avatarBottomTextColor, vip[user_id].avatarBottomText) end
  293. end
  294.  
  295. --Проверка клика в определенную область по "объекту". Кому на хуй вссалось ООП?
  296. local function clickedAtZone(x, y, zone)
  297.     if x >= zone[1] and y >= zone[2] and x <= zone[3] and y <= zone[4] then
  298.         return true
  299.     end
  300.     return false
  301. end
  302.  
  303. --Интерфейс логина в аккаунт ВК, постараюсь сделать пографонистей
  304. --Хотя хах! Кого я обманываю, ага
  305. local function loginGUI(startUsername, startPassword)
  306.     local background = 0x002440
  307.     local buttonColor = 0x666DFF
  308.     local textColor = 0x262626
  309.     local username, password = startUsername or "E-Mail или номер телефона", startPassword or "Пароль"
  310.  
  311.     local textFieldWidth = 50
  312.     local textFieldHeight = 3
  313.     local x, y = math.floor(buffer.screen.width / 2 - textFieldWidth / 2), math.floor(buffer.screen.height / 2)
  314.  
  315.     local obj = {}
  316.     obj.username = {x, y, x + textFieldWidth - 1, y + 2}; y = y + textFieldHeight + 1
  317.     obj.password = {x, y, x + textFieldWidth - 1, y + 2}; y = y + textFieldHeight + 1
  318.     obj.button = GUI.button(x, y, textFieldWidth, textFieldHeight, buttonColor, 0xFFFFFF, 0xFFFFFF, buttonColor, "Войти")
  319.  
  320.     local VKLogoImage = image.load(VKLogoImagePath)
  321.  
  322.     local function draw()
  323.         buffer.clear(colors.loginGUIBackground)
  324.  
  325.         buffer.image(x + 5, obj.username[2] - 15, VKLogoImage)
  326.  
  327.         buffer.square(x, obj.username[2], textFieldWidth, 3, 0xFFFFFF, 0x000000, " ")
  328.         buffer.square(x, obj.password[2], textFieldWidth, 3, 0xFFFFFF, 0x000000, " ")
  329.         buffer.text(x + 1, obj.username[2] + 1, textColor, ecs.stringLimit("end", username, textFieldWidth - 2))
  330.         buffer.text(x + 1, obj.password[2] + 1, textColor, ecs.stringLimit("end", string.rep("●", unicode.len(password)), textFieldWidth - 2))
  331.  
  332.         obj.button:draw()
  333.  
  334.         buffer.draw()
  335.     end
  336.  
  337.     while true do
  338.         draw()
  339.         local e = {event.pull()}
  340.         if e[1] == "touch" then
  341.             if clickedAtZone(e[3], e[4], obj.username) then
  342.                 username = ""
  343.                 username = ecs.inputText(x + 1, obj.username[2] + 1, textFieldWidth - 2, username, 0xFFFFFF, 0x262626) or ""
  344.            
  345.             elseif clickedAtZone(e[3], e[4], obj.password) then
  346.                 password = ""
  347.                 password = ecs.inputText(x + 1, obj.password[2] + 1, textFieldWidth - 2, password, 0xFFFFFF, 0x262626, false, "*") or ""
  348.            
  349.             elseif obj.button:isClicked(e[3], e[4]) then
  350.                 obj.button:press(0.2)
  351.                 draw()
  352.                 local success, loginData = getLoginDataRequest(username, password)
  353.                 if success then
  354.                     if settings.saveAuthData then settings.username = username; settings.password = password; saveSettings() end
  355.                     loginData.username = username
  356.                     loginData.password = password
  357.                     return loginData
  358.                 else
  359.                     GUI.error("Ошибка авторизации: " .. tostring(loginData))
  360.                 end
  361.             end
  362.         end
  363.     end
  364. end
  365.  
  366. ---------------------------------------------------- GUI для взаимодействия с VK API ----------------------------------------------
  367.  
  368. local function drawPersonalAvatar(x, y, width, height)
  369.     drawAvatar(x, y, width, height, personalInfo.id, unicode.sub(personalInfo.first_name, 1, 1) .. unicode.sub(personalInfo.last_name, 1, 1))
  370. end
  371.  
  372. local function status(text)
  373.     buffer.square(mainZoneX, buffer.screen.height, mainZoneWidth, 1, colors.statusBar)
  374.     buffer.text(mainZoneX + 1, buffer.screen.height, colors.statusBarText, text)
  375.     buffer.draw()
  376. end
  377.  
  378. local function drawTopBar(text)
  379.     buffer.square(mainZoneX, 1, mainZoneWidth, 3, colors.topBar)
  380.     local x = math.floor(mainZoneX + mainZoneWidth / 2 - unicode.len(text) / 2 - 1)
  381.     buffer.text(x, 2, colors.topBarText, text)
  382. end
  383.  
  384. --Рисуем главную зону
  385. local function clearGUIZone()
  386.     buffer.square(mainZoneX, mainZoneY, mainZoneWidth, mainZoneHeight, colors.mainZone)
  387. end
  388.  
  389. local function drawEmptyCloud(x, y, cloudWidth, cloudHeight, cloudColor, fromYou)
  390.     local upperPixel = "▀"
  391.     local lowerPixel = "▄"
  392.  
  393.     --Рисуем финтифлюшечки
  394.     if not fromYou then
  395.         buffer.set(x, y - cloudHeight + 2, colors.mainZone, cloudColor, upperPixel)
  396.         buffer.set(x + 1, y - cloudHeight + 2, cloudColor, 0xFFFFFF, " ")
  397.         x = x + 2
  398.     else
  399.         buffer.set(x + cloudWidth + 3, y - cloudHeight + 2, colors.mainZone, cloudColor, upperPixel)
  400.         buffer.set(x + cloudWidth + 2, y - cloudHeight + 2, cloudColor, 0xFFFFFF, " ")
  401.     end
  402.  
  403.     --Заполняшечки
  404.     buffer.square(x + 1, y - cloudHeight + 1, cloudWidth, cloudHeight, cloudColor, 0xFFFFFF, " ")
  405.     buffer.square(x, y - cloudHeight + 2, cloudWidth + 2, cloudHeight - 2, cloudColor, 0xFFFFFF, " ")
  406.    
  407.     --Сгругленные краешки
  408.     buffer.set(x, y - cloudHeight + 1, colors.mainZone, cloudColor, lowerPixel)
  409.     buffer.set(x + cloudWidth + 1, y - cloudHeight + 1, colors.mainZone, cloudColor, lowerPixel)
  410.     buffer.set(x, y, colors.mainZone, cloudColor, upperPixel)
  411.     buffer.set(x + cloudWidth + 1, y, colors.mainZone, cloudColor, upperPixel)
  412.  
  413.     return y - cloudHeight + 1
  414. end
  415.  
  416. local function drawTextCloud(x, y, cloudColor, textColor, fromYou, text)
  417.     local y = drawEmptyCloud(x, y, cloudWidth, #text + 2, cloudColor, fromYou)
  418.     x = fromYou and x + 2 or x + 4
  419.  
  420.     for i = 1, #text do
  421.         buffer.text(x, y + i, textColor, text[i])
  422.     end
  423.  
  424.     return y
  425. end
  426.  
  427. local function getAttachments(messageArray)
  428.     local text = "Вложения: "
  429.     for j = 1, #messageArray.attachments do
  430.         if messageArray.attachments[j].type == "sticker" then
  431.             text = text .. "стикер, "
  432.         elseif messageArray.attachments[j].type == "photo" then
  433.             text = text .. "фото, "
  434.         elseif messageArray.attachments[j].type == "video" then
  435.             text = text .. "видео, "
  436.         elseif messageArray.attachments[j].type == "audio" then
  437.             text = text .. "аудио, "
  438.         elseif messageArray.attachments[j].type == "wall" then
  439.             text = text .. "запись на стене, "
  440.         end
  441.     end
  442.     text = unicode.sub(text, 1, -3)
  443.  
  444.     return text
  445. end
  446.  
  447. local function drawMessageInputBar(currentText)
  448.     local x, y = mainZoneX, buffer.screen.height - 5
  449.     obj.messageInputBar = GUI.object(x, y, mainZoneWidth - 4, 4)
  450.     buffer.square(x, y, mainZoneWidth, 5, colors.messageInputBarColor)
  451.     buffer.square(x + 2, y + 1, mainZoneWidth - 4, 3, colors.messageInputBarTextBackgroundColor)
  452.     buffer.text(x + 4, y + 2, colors.messsageInputBarTextColor, ecs.stringLimit("start", currentText or "Введите сообщение", mainZoneWidth - 8))
  453. end
  454.  
  455. local function getUserNamesFromTheirIDs(IDsArray)
  456.     local success, usersData = usersInformationRequest(table.unpack(IDsArray))
  457.     local userNames = {}
  458.     if success and usersData.response then
  459.         for i = 1, #usersData.response do
  460.             userNames[usersData.response[i].id] = {
  461.                 first_name = usersData.response[i].first_name,
  462.                 last_name = usersData.response[i].last_name,
  463.             }
  464.         end
  465.     end
  466.     return success, userNames
  467. end
  468.  
  469. local function messagesGUI()
  470.  
  471.     status("Загружаю историю переписки")
  472.     local success, messages = getMessagesRequest(currentMessagesPeerID, messageToShowFrom - 1, countOfMessagesToLoadFromServer)
  473.     if success and messages.response then
  474.  
  475.         whatIsOnScreen = "messages"
  476.  
  477.         if currentMessagesPeerID > 2000000000 then
  478.             status("Загружаю имена пользователей из переписки (актуально для конференций)")
  479.  
  480.             local IDsArray = {};
  481.             for i = 1, #messages.response.items do table.insert(IDsArray, messages.response.items[i].user_id) end
  482.             local userNamesSuccess, userNames = getUserNamesFromTheirIDs(IDsArray)
  483.             for i = 1, #messages.response.items do
  484.                 messages.response.items[i].first_name = userNames[messages.response.items[i].user_id].first_name or "N/A"
  485.                 messages.response.items[i].last_name = userNames[messages.response.items[i].user_id].last_name or "N/A"
  486.             end
  487.             IDsArray = nil
  488.         end
  489.  
  490.         clearGUIZone()
  491.         drawTopBar("Сообщения")
  492.  
  493.         -- saveToFile("lastMessagesRequest.json", serialization.serialize(messages))
  494.  
  495.         buffer.setDrawLimit(mainZoneX, mainZoneY, mainZoneWidth, mainZoneHeight)
  496.  
  497.         local y = buffer.screen.height - 7
  498.         local xSender = mainZoneX + 2
  499.         local xYou = buffer.screen.width - 7
  500.  
  501.         for i = 1, #messages.response.items do
  502.  
  503.             local messageTextArray = {}
  504.  
  505.             --Если строка пиздатая
  506.             if messages.response.items[i].body ~= "" then table.insert(messageTextArray, optimizeStringForWrongSymbols(messages.response.items[i].body)) end
  507.             if messages.response.items[i].fwd_messages then table.insert(messageTextArray, "Пересланные сообщения") end
  508.             if messages.response.items[i].attachments then table.insert(messageTextArray, getAttachments(messages.response.items[i])) end
  509.             if messages.response.items[i].action == "chat_invite_user" then table.insert(messageTextArray, "Пользователь под ID " .. messages.response.items[i].from_id .. " пригласил в беседу пользователя под ID " .. messages.response.items[i].action_mid) end
  510.  
  511.             messageTextArray = string.wrap(messageTextArray, cloudWidth - 4)
  512.             local peerID = getPeerIDFromMessageArray(messages.response.items[i])
  513.  
  514.             --Делаем дату пиздатой
  515.             -- messages.response.items[i].date = os.date("%d.%m.%y в %X", messages.response.items[i].date)
  516.             messages.response.items[i].date = os.date("%H:%M", messages.response.items[i].date)
  517.  
  518.             if messages.response.items[i].out == 1 then
  519.                 y = drawTextCloud(xYou - cloudWidth - 6, y, colors.yourCloudColor, colors.yourCloudTextColor, true, messageTextArray)
  520.                 drawPersonalAvatar(xYou, y, 6, 3)
  521.                 buffer.text(xYou - cloudWidth - unicode.len(messages.response.items[i].date) - 8, y + 1, colors.dateTime, messages.response.items[i].date)
  522.             else
  523.                 y = drawTextCloud(xSender + 8, y, colors.senderCloudColor, colors.senderCloudTextColor, false, messageTextArray)
  524.                 drawAvatar(xSender, y, 6, 3, peerID, messages.response.items[i].first_name and (unicode.sub(messages.response.items[i].first_name, 1, 1) .. unicode.sub(messages.response.items[i].last_name, 1, 1)) or currentMessagesAvatarText)
  525.                 buffer.text(xSender + cloudWidth + 14, y + 1, colors.dateTime, messages.response.items[i].date)
  526.             end
  527.  
  528.             y = y - 2
  529.         end
  530.  
  531.         local currentText
  532.  
  533.         drawMessageInputBar(currentText)
  534.  
  535.         status("История переписки загружена, ожидаю ввода сообщения")
  536.  
  537.         buffer.resetDrawLimit()
  538.         -- buffer.draw()
  539.     end
  540. end
  541.  
  542. local function drawDialog(y, dialogBackground, avatarID, avatarText, text1, text2, text3)
  543.     --Рисуем подложку под диалог нужного цвета
  544.     buffer.square(mainZoneX, y, mainZoneWidth, 5, dialogBackground)
  545.     --Рисуем аватарку, чо уж
  546.     drawAvatar(mainZoneX + 2, y + 1, 6, 3, avatarID, avatarText)
  547.     --Пишем все, что нужно
  548.     y = y + 1
  549.     if text1 then buffer.text(mainZoneX + 10, y, 0x000000, text1); y = y + 1 end
  550.     if text2 then buffer.text(mainZoneX + 10, y, 0x555555, text2); y = y + 1 end
  551.     if text3 then buffer.text(mainZoneX + 10, y, 0x666666, text3); y = y + 1 end
  552. end
  553.  
  554. local function dialogsGUI()
  555.  
  556.     local success, dialogs = getDialogsRequest(dialogToShowFrom - 1, countOfDialogsToLoadFromServer)
  557.     if success and dialogs.response then
  558.        
  559.         whatIsOnScreen = "dialogs"
  560.  
  561.         obj.dialogList = {}
  562.  
  563.         clearGUIZone()
  564.         drawTopBar("Сообщения")
  565.  
  566.         --Ебашим КНОПАЧКИ спама
  567.         obj.crazyTypingButton = GUI.adaptiveButton(mainZoneX + 2, 2, 1, 0, 0xFFFFFF, colors.topBar, 0xAAAAAA, 0x000000, "CrazyTyping")
  568.         -- obj.spamButton = {buffer.adaptiveButton(obj.crazyTypingButton[3] + 2, 2, 1, 0, 0xFFFFFF, colors.topBar, "Спам")}
  569.  
  570.         --НУ ТЫ ПОНЯЛ, АГА
  571.         status("Получаю имена пользователей по ID")
  572.         local IDsArray = {}
  573.         for i = 1, #dialogs.response.items do
  574.             if not dialogs.response.items[i].message.chat_id and dialogs.response.items[i].message.user_id and dialogs.response.items[i].message.user_id > 0 then
  575.                 table.insert(IDsArray, dialogs.response.items[i].message.user_id)
  576.             end
  577.         end
  578.         local userNamesSuccess, userNames = getUserNamesFromTheirIDs(IDsArray)
  579.         for i = 1, #dialogs.response.items do
  580.             if not dialogs.response.items[i].message.chat_id and dialogs.response.items[i].message.user_id and dialogs.response.items[i].message.user_id > 0 then
  581.                 dialogs.response.items[i].message.title = userNames[dialogs.response.items[i].message.user_id].first_name or "N/A" .. " " .. userNames[dialogs.response.items[i].message.user_id].last_name or ""
  582.             end
  583.         end
  584.  
  585.         local y = mainZoneY
  586.         local avatarText = ""
  587.         local peerID
  588.         local color
  589.  
  590.         for i = 1, #dialogs.response.items do
  591.             --Ебемся с цветами
  592.             if dialogs.response.items[i].unread then
  593.                 if i % 2 == 0 then
  594.                     color = 0xCCDBFF
  595.                 else
  596.                     color = 0xCCDBFF
  597.                 end
  598.             else
  599.                 if i % 2 == 0 then
  600.                     color = 0xEEEEEE
  601.                 else
  602.                     color = 0xFFFFFF
  603.                 end
  604.             end
  605.            
  606.             avatarText = unicode.sub(dialogs.response.items[i].message.title, 1, 2)
  607.             peerID = getPeerIDFromMessageArray(dialogs.response.items[i].message)
  608.  
  609.             --Ебля с текстом диалога
  610.             local text1 = dialogs.response.items[i].message.title
  611.             local text2
  612.             local text3
  613.  
  614.             --Если это банальное сообщение
  615.             if dialogs.response.items[i].message.body and dialogs.response.items[i].message.body ~= "" then
  616.                 text2 = optimizeStringForWrongSymbols(dialogs.response.items[i].message.body)
  617.             end
  618.  
  619.             --Если есть какие-либо пересланные сообщения, то
  620.             if dialogs.response.items[i].message.fwd_messages then
  621.                 text3 = "Пересланные сообщения"
  622.             --Если есть какие-либо вложения, то
  623.             elseif dialogs.response.items[i].message.attachments then
  624.                 text3 = getAttachments(dialogs.response.items[i].message)
  625.             end
  626.  
  627.             --Рисуем диалог
  628.             drawDialog(y, color, peerID, avatarText, text1, text2, text3)
  629.  
  630.             --Рисуем пиздюлинку, показывающую кол-во непрочитанных сообщений
  631.             if dialogs.response.items[i].unread and dialogs.response.items[i].unread ~= 0 then
  632.                 local cyka = tostring(dialogs.response.items[i].unread)
  633.                 local cykaWidth = unicode.len(cyka) + 2
  634.                 local cykaX = buffer.screen.width - cykaWidth - 2
  635.                 buffer.square(cykaX, y + 2, cykaWidth, 1, ecs.colors.blue)
  636.                 buffer.text(cykaX + 1, y + 2, 0xFFFFFF, cyka)
  637.             end
  638.  
  639.             obj.dialogList[i] = GUI.object(mainZoneX, y, mainZoneWidth, 5)
  640.             obj.dialogList[i][5], obj.dialogList[i][6], obj.dialogList[i][7], obj.dialogList[i][8], obj.dialogList[i][9] = peerID, avatarText, text1, text2, text3
  641.  
  642.             y = y + 5
  643.         end
  644.     end
  645.  
  646.     status("Список диалогов получен")
  647. end
  648.  
  649. --Гуишка аудиозаписей
  650. --А-А-А-А!!!!! МОЙ КРАСИВЫЙ ТРЕУГОЛЬНИЧЕК PLAY, БЛЯДЬ!!!! ШТО ТЫ ДЕЛАЕШЬ, SANGAR, ПРЕКРАТИ!!!!
  651. local function audioGUI(ID)
  652.     status("Загружаю список аудиозаписей")
  653.     local success, audios = getAudioRequest(ID, audioToShowFrom - 1, countOfAudioToLoadFromServer)
  654.     if success and audios.response then
  655.         whatIsOnScreen = "audio"
  656.         obj.audio = {}
  657.         clearGUIZone()
  658.         drawTopBar("Аудиозаписи " .. audios.response.items[1].name_gen)
  659.  
  660.         local y = mainZoneY
  661.         local color
  662.         for i = 2, #audios.response.items do
  663.             color = 0xFFFFFF
  664.             if i % 2 == 0 then color = 0xEEEEEE end
  665.  
  666.             buffer.square(mainZoneX, y, mainZoneWidth, 5, color)
  667.             obj.audio[i] = GUI.button(mainZoneX + 2, y + 1, 5, 3, colors.audioPlayButton, colors.audioPlayButtonText, 0x66FF80, colors.audioPlayButton, ">")
  668.             obj.audio[i][5] = audios.response.items[i]
  669.  
  670.             local x = mainZoneX + 9
  671.             buffer.text(x, y + 1, colors.audioPlayButton, audios.response.items[i].artist)
  672.             x = x + unicode.len(audios.response.items[i].artist)
  673.             buffer.text(x, y + 1, 0x000000, " - " .. audios.response.items[i].title)
  674.  
  675.             x = mainZoneX + 9
  676.             local hours = string.format("%02.f", math.floor(audios.response.items[i].duration / 3600))
  677.             local minutes = string.format("%02.f", math.floor(audios.response.items[i].duration / 60 - (hours * 60)))
  678.             local seconds = string.format("%02.f", math.floor(audios.response.items[i].duration - hours * 3600 - minutes * 60))
  679.             buffer.text(x, y + 2, 0x888888, "Длительность: " .. hours .. ":" .. minutes .. ":" .. seconds)
  680.  
  681.             y = y + 5
  682.         end
  683.     else
  684.         GUI.error("Ошибка при получении списка аудиозаписей")
  685.     end
  686. end
  687.  
  688. local function checkField(field)
  689.     if field and field ~= "" and field ~= " " then return true end
  690.     return false
  691. end
  692.  
  693. local function userProfileRequest()
  694.     --Ебашим основную инфу
  695.     status("Загружаю информацию о пользователе под ID " .. currentProfile.ID)
  696.     local profileSuccess, userProfile = usersInformationRequest(currentProfile.ID)
  697.    
  698.     --Ебашим стену
  699.     status("Загружаю содержимое стены пользователя " .. currentProfile.ID)
  700.     local wallSuccess, wall = userWallRequest(currentProfile.ID, 20, currentProfile.wallOffset)
  701.     --Получаем инфу о юзверях со стены
  702.     local userNamesSuccess, userNames
  703.     if wallSuccess and wall.response then
  704.         local IDsArray = {}
  705.         for i = 1, #wall.response.items do table.insert(IDsArray, wall.response.items[i].from_id) end
  706.         status("Загружаю имена людей, оставивших сообщения на стене пользователя " .. currentProfile.ID)
  707.         userNamesSuccess, userNames = getUserNamesFromTheirIDs(IDsArray)
  708.         IDsArray = nil
  709.     end
  710.  
  711.     --Ебашим френдсов
  712.     status("Загружаю информацию о друзьях пользователя под ID " .. currentProfile.ID)
  713.     local friendsSuccess, friends = userFriendsRequest(currentProfile.ID, countOfFriendsToDisplayInProfile, 0, "random", "nom")
  714.  
  715.     --Анализируем на пиздатость
  716.     if (profileSuccess and userProfile.response) and (wallSuccess and wall.response) and (userNamesSuccess) and (friendsSuccess and friends.response) then
  717.         -- saveToFile("lastUserProfileRequest.json", serialization.serialize(userProfile))
  718.         currentProfile.userProfile = userProfile
  719.         currentProfile.wall = wall
  720.         currentProfile.userNames = userNames
  721.         currentProfile.friends = friends
  722.         return true
  723.     else
  724.         GUI.error("Ошибка при загрузке информации о профиле")
  725.         return false
  726.     end
  727. end
  728.  
  729. local function userProfileGUI()
  730.     clearGUIZone()
  731.     whatIsOnScreen = "userProfile"
  732.     drawTopBar("Страница пользователя " .. currentProfile.ID)
  733.  
  734.     buffer.setDrawLimit(mainZoneX, mainZoneY, mainZoneWidth, mainZoneHeight)
  735.  
  736.     local xAvatar, yAvatar = mainZoneX + 4, currentProfileY
  737.     local x, y = xAvatar, yAvatar
  738.     local avatarWidth = 18
  739.     local avatarHeight = math.floor(avatarWidth / 2)
  740.  
  741.     --Рисуем авку
  742.     currentProfile.avatarText =  unicode.sub(currentProfile.userProfile.response[1].first_name, 1, 1) .. unicode.sub(currentProfile.userProfile.response[1].last_name, 1, 1)
  743.     drawAvatar(x, y, avatarWidth, avatarHeight, currentProfile.ID, currentProfile.avatarText)
  744.     --Рисуем имячко и статус
  745.     x = x + avatarWidth + 4
  746.     buffer.text(x, y, 0x000000, currentProfile.userProfile.response[1].first_name .. " " .. currentProfile.userProfile.response[1].last_name); y = y + 1
  747.     buffer.text(x, y, 0xAAAAAA, currentProfile.userProfile.response[1].status); y = y + 2
  748.  
  749.     --Инфааааа
  750.     local informationOffset = 20
  751.     local informationKeyColor = 0x888888
  752.     local informationTitleColor = 0x000000
  753.     local informationValueColor = 0x002440
  754.     local informationSeparatorColor = 0xCCCCCC
  755.  
  756.     local function drawInfo(x, y2, key, value)
  757.         if checkField(value) then
  758.             value = {value}
  759.             value = ecs.stringWrap(value, buffer.screen.width - x - 4 - informationOffset)
  760.             buffer.text(x, y2, informationKeyColor, key)
  761.             for i = 1, #value do
  762.                 buffer.text(x + informationOffset, y2, informationValueColor, value[i])
  763.                 y2 = y2 + 1
  764.             end
  765.             y = y2
  766.         end
  767.     end
  768.  
  769.     local function drawSeparator(x, y2, text)
  770.         buffer.text(x, y2, informationTitleColor, text)
  771.         buffer.text(x + unicode.len(text) + 1, y2, informationSeparatorColor, string.rep("─", buffer.screen.width - x - unicode.len(text)))
  772.         y = y + 1
  773.     end
  774.  
  775.     drawSeparator(x, y, "Основная информация"); y = y + 1
  776.  
  777.     drawInfo(x, y, "Дата рождения:", currentProfile.userProfile.response[1].bdate)
  778.     if currentProfile.userProfile.response[1].city then drawInfo(x, y, "Город:", currentProfile.userProfile.response[1].city.title) end
  779.     drawInfo(x, y, "Образование:", currentProfile.userProfile.response[1].university_name)
  780.     drawInfo(x, y, "Веб-сайт", currentProfile.userProfile.response[1].site); y = y + 1
  781.  
  782.     drawSeparator(x, y, "Контактная информация"); y = y + 1
  783.  
  784.     drawInfo(x, y, "Мобильный телефон:", currentProfile.userProfile.response[1].mobile_phone)
  785.     drawInfo(x, y, "Домашний телефон:", currentProfile.userProfile.response[1].home_phone)
  786.     drawInfo(x, y, "Skype:", currentProfile.userProfile.response[1].skype); y = y + 1
  787.  
  788.     drawSeparator(x, y, "Личная информация"); y = y + 1
  789.  
  790.     drawInfo(x, y, "Интересы:", currentProfile.userProfile.response[1].interests)
  791.     drawInfo(x, y, "Деятельность:", currentProfile.userProfile.response[1].activities)
  792.     drawInfo(x, y, "Любимая музыка:", currentProfile.userProfile.response[1].music)
  793.     drawInfo(x, y, "Любимая фильмы:", currentProfile.userProfile.response[1].movies)
  794.     drawInfo(x, y, "Любимая телешоу:", currentProfile.userProfile.response[1].tv)
  795.     drawInfo(x, y, "Любимая книги:", currentProfile.userProfile.response[1].books)
  796.     drawInfo(x, y, "Любимая игры:", currentProfile.userProfile.response[1].games)
  797.     drawInfo(x, y, "О себе:", currentProfile.userProfile.response[1].about)
  798.  
  799.     -- А ВОТ И СТЕНОЧКА ПОДЪЕХАЛА НА ПРАЗДНИК ДУШИ
  800.     y = y + 1
  801.     buffer.square(x, y, buffer.screen.width - x - 2, 1, 0xCCCCCC); buffer.text(x + 1, y, 0x262626, "Стена"); y = y + 2
  802.     --Перебираем всю стенку
  803.     for i = 1, #currentProfile.wall.response.items do
  804.         --Если это не репост или еще не хуйня какая-то
  805.         if currentProfile.wall.response.items[i].text ~= "" then
  806.             -- GUI.error(userNames)
  807.             drawAvatar(x, y, 6, 3, currentProfile.wall.response.items[i].from_id, unicode.sub(currentProfile.userNames[currentProfile.wall.response.items[i].from_id].first_name, 1, 1) .. unicode.sub(currentProfile.userNames[currentProfile.wall.response.items[i].from_id].last_name, 1, 1))
  808.             buffer.text(x + 8, y, informationValueColor, currentProfile.userNames[currentProfile.wall.response.items[i].from_id].first_name .. " " .. currentProfile.userNames[currentProfile.wall.response.items[i].from_id].last_name)
  809.             local date = os.date("%d.%m.%y в %H:%M", currentProfile.wall.response.items[i].date)
  810.             buffer.text(buffer.screen.width - unicode.len(date) - 2, y, 0xCCCCCC, date)
  811.             y = y + 1
  812.             local text = {currentProfile.wall.response.items[i].text}
  813.             text = ecs.stringWrap(text, buffer.screen.width - x - 10)
  814.             for i = 1, #text do
  815.                 buffer.text(x + 8, y, 0x000000, text[i])
  816.                 y = y + 1
  817.             end
  818.             y = y + 1
  819.             if #text == 1 then y = y + 1 end
  820.         end
  821.     end
  822.  
  823.     --ПодАвочная параша
  824.     informationOffset = 13
  825.     x, y = xAvatar, yAvatar
  826.     y = y + avatarHeight + 1
  827.  
  828.     currentProfile.avatarWidth = avatarWidth
  829.     currentProfile.sendMessageButton = GUI.button(x, y, avatarWidth, 1, 0xCCCCCC, 0x000000, 0x888888, 0x000000,"Сообщение")
  830.     y = y + 2
  831.     currentProfile.audiosButton = GUI.button(x, y, avatarWidth, 1, 0xCCCCCC, 0x000000, 0x888888, 0x000000, "Аудиозаписи")
  832.     y = y + 2
  833.  
  834.     drawInfo(x, y, "Подписчики: ", currentProfile.userProfile.response[1].counters.followers)
  835.     drawInfo(x, y, "Фотографии: ", currentProfile.userProfile.response[1].counters.photos)
  836.     drawInfo(x, y, "Видеозаписи: ", currentProfile.userProfile.response[1].counters.videos)
  837.     drawInfo(x, y, "Аудиозаписи: ", currentProfile.userProfile.response[1].counters.audios)
  838.  
  839.     --Друзяшки, ЕПТАААААА, АХАХАХАХАХАХАХАХАХА     
  840.     y = y + 1
  841.     buffer.square(x, y, avatarWidth, 1, 0xCCCCCC); buffer.text(x + 1, y, 0x262626, "Друзья (" .. currentProfile.userProfile.response[1].counters.friends .. ")"); y = y + 2
  842.     local xPos, yPos = x + 1, y
  843.     local count = 1
  844.     for i = 1, #currentProfile.friends.response.items do
  845.         drawAvatar(xPos, yPos, 6, 3, currentProfile.friends.response.items[i].id, unicode.sub(currentProfile.friends.response.items[i].first_name, 1, 1) .. unicode.sub(currentProfile.friends.response.items[i].last_name, 1, 1))
  846.         buffer.text(xPos - 1, yPos + 3, 0x000000, ecs.stringLimit("end", currentProfile.friends.response.items[i].first_name .. " " .. currentProfile.friends.response.items[i].last_name, 8))
  847.         xPos = xPos + 10
  848.         if i % 2 == 0 then xPos = x + 1; yPos = yPos + 5 end
  849.         count = count + 1
  850.         if count > countOfFriendsToDisplayInProfile then break end
  851.     end
  852.  
  853.     buffer.resetDrawLimit()
  854. end
  855.  
  856. local function loadAndShowProfile(ID)
  857.     currentProfileY = mainZoneY + 2
  858.     currentProfile = {ID = ID, wallOffset = 0}
  859.     if userProfileRequest() then userProfileGUI(currentProfile.ID) end
  860. end
  861.  
  862. local function friendsGUI()
  863.     status("Загружаю список друзей")
  864.     local success, friends = userFriendsRequest(personalInfo.id, countOfFriendsToGetOnFriendsTab, currentFriendsOffset, "hints", "nom")
  865.     status("Загружаю список категорий друзей")
  866.     local successLists, friendsLists = userFriendsListsRequest(personalInfo.id)
  867.     if (success and friends.response) and (successLists and friendsLists.response) then
  868.         -- saveToFile("lastFriendsResponse.json", serialization.serialize(friends))
  869.         clearGUIZone()
  870.         currentFriends = {sendMessageButtons = {}, openProfileButtons = {}}
  871.         whatIsOnScreen = "friends"
  872.         drawTopBar("Друзья")
  873.         buffer.setDrawLimit(mainZoneX, mainZoneY, mainZoneWidth, mainZoneHeight)
  874.  
  875.         local function getListName(listID)
  876.             local name = "N/A"
  877.             for i = 1, #friendsLists.response.items do
  878.                 if friendsLists.response.items[i].id == listID then
  879.                     name = friendsLists.response.items[i].name
  880.                     break
  881.                 end
  882.             end
  883.             return name
  884.         end
  885.  
  886.         local x, y = mainZoneX + 2, mainZoneY
  887.         for i = 1, #friends.response.items do
  888.             --Падложка
  889.             if i % 2 == 0 then buffer.square(mainZoneX, y, mainZoneWidth, 5 + (friends.response.items[i].lists and 1 or 0), 0xEEEEEE) end
  890.             --Юзер
  891.             y = y + 1
  892.             local subbedName = unicode.sub(friends.response.items[i].first_name, 1, 1) .. unicode.sub(friends.response.items[i].last_name, 1, 1)
  893.             drawAvatar(x, y, 6, 3, friends.response.items[i].id, subbedName)
  894.             local text = friends.response.items[i].first_name .. " " .. friends.response.items[i].last_name
  895.             buffer.text(x + 8, y, colors.topBar, text)
  896.             local text2 = friends.response.items[i].last_seen and (", " .. (friends.response.items[i].online == 1 and "онлайн" or "был(а) в сети " .. os.date("%d.%m.%y в %H:%M", friends.response.items[i].last_seen.time))) or " "
  897.             buffer.text(x + 8 + unicode.len(text), y, 0xAAAAAA, text2)
  898.  
  899.             if friends.response.items[i].lists then
  900.                 y = y + 1
  901.                 local cykaX = x + 8
  902.                 for listID = 1, #friends.response.items[i].lists do
  903.                     local listName = getListName(friends.response.items[i].lists[listID])
  904.                     local listWidth = unicode.len(listName) + 2
  905.                     local listBackColor = math.floor(0xFFFFFF / friends.response.items[i].lists[listID])
  906.                     local listTextColor = (listBackColor > 0x7FFFFF and 0x000000 or 0xFFFFFF)
  907.                     buffer.square(cykaX, y, listWidth, 1, listBackColor, listTextColor, " ")
  908.                     buffer.text(cykaX + 1, y, listTextColor, listName)
  909.                     cykaX = cykaX + listWidth + 2
  910.                 end
  911.             end
  912.  
  913.             y = y + 1
  914.             buffer.text(x + 8, y, 0x999999, "Написать сообщение")
  915.             currentFriends.sendMessageButtons[friends.response.items[i].id] = {x + 8, y, x + 18, y, subbedName}
  916.             y = y + 1
  917.             buffer.text(x + 8, y, 0x999999, "Открыть профиль")
  918.             currentFriends.openProfileButtons[friends.response.items[i].id] = {x + 8, y, x + 18, y, subbedName}
  919.  
  920.             y = y + 2
  921.         end
  922.  
  923.         buffer.resetDrawLimit()
  924.     else
  925.         GUI.error("Ошибка при получении списка друзей пользователя")
  926.     end
  927. end
  928.  
  929. local function newsGUI()
  930.     clearGUIZone()
  931.     drawTopBar("Новости")
  932.     whatIsOnScreen = "news"
  933.     buffer.setDrawLimit(mainZoneX, mainZoneY, mainZoneWidth, mainZoneHeight)
  934.  
  935.     local function getAvatarTextAndNameForNews(source_id)
  936.         local avatarText, name = "N/A", "N/A"
  937.         if source_id < 0 then
  938.             for i = 1, #news.response.groups do
  939.                 if news.response.groups[i].id == math.abs(source_id) then
  940.                     avatarText = unicode.sub(news.response.groups[i].name, 1, 2)
  941.                     name = news.response.groups[i].name
  942.                     break
  943.                 end
  944.             end
  945.         else
  946.             for i = 1, #news.response.profiles do
  947.                 if news.response.profiles[i].id == source_id then
  948.                     avatarText = unicode.sub(news.response.profiles[i].first_name, 1, 1) .. unicode.sub(news.response.profiles[i].last_name, 1, 1)
  949.                     name = news.response.profiles[i].first_name .. " " .. news.response.profiles[i].last_name
  950.                     break
  951.                 end
  952.             end
  953.         end
  954.         return avatarText, name
  955.     end
  956.  
  957.     local x, y = mainZoneX + 2, mainZoneY
  958.     for item = currentNews, currentNews + countOfNewsToShow do
  959.         if news.response.items[item] then
  960.             --Делаем текст пиздатым
  961.             news.response.items[item].text = optimizeStringForWrongSymbols(news.response.items[item].text)
  962.             --Убираем говно из новостей
  963.             if news.response.items[item].text == "" then
  964.                 if news.response.items[item].copy_history then
  965.                     news.response.items[item].text = "Репост"
  966.                 elseif news.response.items[item].attachments then
  967.                      news.response.items[item].text = getAttachments(news.response.items[item])
  968.                 end
  969.             end
  970.             --Делаем его еще пизже
  971.             local text = {news.response.items[item].text}; text = ecs.stringWrap(text, buffer.screen.width - x - 10)
  972.             --Получаем инфу нужную
  973.             local avatarText, name = getAvatarTextAndNameForNews(news.response.items[item].source_id)
  974.             --Сместиться потом на стока вот
  975.             local yShift = 5
  976.             if #text > 2 then yShift = yShift + #text - 2 end
  977.            
  978.             --Рисуем авку и название хуйни
  979.             if item % 2 == 0 then buffer.square(mainZoneX, y, mainZoneWidth, yShift, 0xEEEEEE) end
  980.             drawAvatar(x, y + 1, 6, 3, math.abs(news.response.items[item].source_id), avatarText)
  981.             buffer.text(x + 7, y + 1, colors.topBar, name)
  982.             --Рисуем текст
  983.             for line = 1, #text do
  984.                 buffer.text(x + 7, y + line + 1, 0x000000, text[line])
  985.             end
  986.  
  987.             y = y + yShift
  988.         end
  989.     end
  990.  
  991.     buffer.resetDrawLimit()
  992. end
  993.  
  994. local function getAndShowNews()
  995.     status("Загружаю список новостей")
  996.     local success, news1 = newsRequest(countOfNewsToGet)
  997.     if success and news1.response then
  998.         news = news1
  999.         currentNews = 1
  1000.         newsGUI()
  1001.     else
  1002.         GUI.error("Ошибка при получении списка новостей")
  1003.     end
  1004. end
  1005.  
  1006. local function drawLeftBar()
  1007.     --Подложка под элементы
  1008.     buffer.square(1, 1, leftBarWidth, buffer.screen.height, colors.leftBar, 0xFFFFFF, " ")
  1009.    
  1010.     if personalInfo then
  1011.         drawPersonalAvatar(3, 2, 6, 3)
  1012.         buffer.text(11, 3, 0xFFFFFF, ecs.stringLimit("end", personalInfo.first_name .. " " .. personalInfo.last_name, leftBarWidth - 11))
  1013.     end
  1014.  
  1015.     --Элементы
  1016.     obj.leftBar = {}
  1017.     local y, color = 6
  1018.     for i = 1, #leftBarElements do
  1019.         color = colors.leftBarAlternative
  1020.         if i % 2 == 0 then color = colors.leftBar end
  1021.         if i == currentLeftBarElement then color = colors.leftBarSelection end
  1022.  
  1023.         newObj("leftBar", i, 1, y, leftBarWidth, y + 2)
  1024.  
  1025.         buffer.square(1, y, leftBarWidth, 3, color, 0xFFFFFF, " ")
  1026.         y = y + 1
  1027.         buffer.text(3, y, colors.leftBarText, ecs.stringLimit("end", leftBarElements[i], leftBarWidth - 4))
  1028.         y = y + 2
  1029.     end
  1030. end
  1031.  
  1032. --Главное ГУИ с левтбаром и прочим
  1033. local function mainGUI()
  1034.     drawLeftBar()
  1035.     --Отображаем гую нужную выбранную
  1036.     if leftBarElements[currentLeftBarElement] == "Сообщения" then
  1037.         status("Получаю список диалогов")
  1038.         messageToShowFrom = 1
  1039.         dialogToShowFrom = 1
  1040.         dialogsGUI()
  1041.     elseif leftBarElements[currentLeftBarElement] == "Аудиозаписи" then
  1042.         status("Получаю список аудозаписей")
  1043.         audioToShowFrom = 1
  1044.         audioGUI(personalInfo.id)
  1045.     elseif leftBarElements[currentLeftBarElement] == "Моя страница" then
  1046.         loadAndShowProfile(personalInfo.id)
  1047.         -- loadAndShowProfile(186860159)
  1048.     elseif leftBarElements[currentLeftBarElement] == "Друзья" then
  1049.         friendsGUI()
  1050.     elseif leftBarElements[currentLeftBarElement] == "Новости" then
  1051.         getAndShowNews()
  1052.     end
  1053.  
  1054.     buffer.draw()
  1055. end
  1056.  
  1057. local function spam(id)
  1058.     while true do
  1059.         local randomMessages = {
  1060.             "Ты мое золотце",
  1061.             "Ты никогда не сделаешь сайт",
  1062.             "Ты ничтожество",
  1063.             "Твоя жизнь ничего не значит",
  1064.             "Ты ничего не добьешься",
  1065.             "Ты завалишь экзамены",
  1066.             "Ты никому не нужна",
  1067.             "Ты не напишешь курсовую",
  1068.             "Твое животное помрет завтра",
  1069.             "Не добавляй в ЧС!",
  1070.             "Передаем привет от Яши и Меня (а кто я?)",
  1071.             "Хуй!",
  1072.             "Пизда!",
  1073.             "Залупа!",
  1074.             "Пенис!",
  1075.             "Хер!",
  1076.             "Давалка!"
  1077.         }
  1078.         local text = randomMessages[math.random(1, #randomMessages)] .. " (с любовью, отправлено с OpenComputers)"
  1079.         sendMessageRequest(tostring(id), text)
  1080.         print("Отправляю сообщение: " .. text)
  1081.         os.sleep(2)
  1082.     end
  1083. end
  1084.  
  1085.  
  1086. ---------------------------------------------------- Старт скрипта ----------------------------------------------------------------
  1087.  
  1088. --Инициализируем библиотеку двойного буффера
  1089. --Эх, что бы я делал, если б не накодил ее? 0.2 фпс на GPU мертвеца!
  1090. buffer.start()
  1091. --Хуярим настррррроечки
  1092. loadSettings()
  1093. --Активируем форму логина
  1094. local loginData = loginGUI(settings.username or "E-Mail", settings.password or "password")
  1095. access_token = loginData.access_token
  1096. --Получаем персональные данные
  1097. _, personalInfo = usersInformationRequest(loginData.user_id)
  1098. personalInfo = personalInfo.response[1]
  1099.  
  1100. -- --Ебемся в попчанский
  1101. -- spam(21321257)
  1102.  
  1103. --Активируем главное GUI
  1104. clearGUIZone()
  1105. mainGUI()
  1106.  
  1107. while true do
  1108.     local e = {event.pull()}
  1109.     if e[1] == "touch" then
  1110.  
  1111.         if whatIsOnScreen == "audio" then
  1112.             for key in pairs(obj.audio) do
  1113.                 if obj.audio[key]:isClicked(e[3], e[4]) then
  1114.                     obj.audio[key]:press(0.2)
  1115.  
  1116.                     if component.isAvailable("openfm_radio") then
  1117.                         component.openfm_radio.stop()
  1118.                         component.openfm_radio.setURL(obj.audio[key][5].url)
  1119.                         component.openfm_radio.start()
  1120.                         status("Вывожу в статус играемую музыку")
  1121.                         setCurrentAudioPlaying(currentProfile and currentProfile.ID or personalInfo.id, obj.audio[key][5].id)
  1122.                     else
  1123.                         GUI.error("Эта функция доступна только при наличии установленного мода OpenFM, добавляющего полноценное интернет-радио")
  1124.                     end
  1125.  
  1126.                     break
  1127.                 end
  1128.             end
  1129.         end
  1130.  
  1131.         if whatIsOnScreen == "dialogs" then
  1132.             for key in pairs(obj.dialogList) do
  1133.                 if obj.dialogList[key]:isClicked(e[3], e[4]) then
  1134.                     drawDialog(obj.dialogList[key].y, 0xFF8888, obj.dialogList[key][5], obj.dialogList[key][6], obj.dialogList[key][7], obj.dialogList[key][8], obj.dialogList[key][9])
  1135.                     buffer.draw()
  1136.                     os.sleep(0.2)
  1137.                     status("Загружаю переписку с пользователем " .. obj.dialogList[key][7])
  1138.                     currentMessagesPeerID = obj.dialogList[key][5]
  1139.                     currentMessagesAvatarText = obj.dialogList[key][6]
  1140.                     messagesGUI()
  1141.                     break
  1142.                 end
  1143.             end
  1144.  
  1145.             if obj.crazyTypingButton:isClicked(e[3], e[4]) then
  1146.                 obj.crazyTypingButton:press(0.2)
  1147.                 local data = ecs.universalWindow("auto", "auto", 36, 0x262626, true,
  1148.                     {"EmptyLine"},
  1149.                     {"CenterText", ecs.colors.orange, "CrazyTyping"},
  1150.                     {"EmptyLine"},
  1151.                     {"Slider", 0xFFFFFF, ecs.colors.orange, 1, 15, 5, "Количество диалогов: ", ""},
  1152.                     {"Slider", 0xFFFFFF, ecs.colors.orange, 1, 100, 5, "Количество запросов: ", ""},
  1153.                     {"Slider", 0xFFFFFF, ecs.colors.orange, 1, 5000, 500, "Задержка между запросами: ", " мс"},
  1154.                     {"EmptyLine"},
  1155.                     {"Button", {ecs.colors.orange, 0xffffff, "OK"}, {0x999999, 0xffffff, "Отмена"}}
  1156.                 )
  1157.                 if data[4] == "OK" then
  1158.                     for i = 1, data[2] do
  1159.                         local count = 1
  1160.                         for key in pairs(obj.dialogList) do
  1161.                             -- GUI.error("Ебашу спам диалогу под пиром: " .. obj.dialogList[key][5])
  1162.                             ecs.info("auto", "auto", "CrazyTyping", "Запрос: " .. i ..  " из " .. data[2] ..  ", диалог: " .. count .. " из ".. data[1] .. ", peerID: " .. obj.dialogList[key][5])
  1163.                             setCrazyTypingRequest(obj.dialogList[key][5])
  1164.                             count = count + 1
  1165.                             if count > data[1] then break end
  1166.                             os.sleep(data[3] / 1000)
  1167.                         end
  1168.                     end
  1169.                     buffer.draw(true)
  1170.                 end
  1171.             end
  1172.         end
  1173.  
  1174.         if whatIsOnScreen == "messages" then
  1175.             if obj.messageInputBar:isClicked(e[3], e[4]) then
  1176.                 drawMessageInputBar(" ")
  1177.                 buffer.draw()
  1178.                 local newText = ecs.inputText(obj.messageInputBar.x + 4, obj.messageInputBar.y + 2, obj.messageInputBar.width - 4, "", colors.messageInputBarTextBackgroundColor, colors.messsageInputBarTextColor)
  1179.                 if newText and newText ~= " " and newText ~= "" then
  1180.                     computer.beep(1700)
  1181.                     status("Отправляю сообщение пользователю")
  1182.                     sendMessageRequest(currentMessagesPeerID, newText .. (settings.addSendingInfo and messageEndAdderText or ""))
  1183.                     status("Обновляю историю переписки")
  1184.                     messageToShowFrom = 1
  1185.                     messagesGUI()
  1186.                 end
  1187.                 drawMessageInputBar(" ")
  1188.             end
  1189.         end
  1190.  
  1191.         if whatIsOnScreen == "userProfile" then
  1192.             if currentProfile.audiosButton:isClicked(e[3], e[4]) then
  1193.                 currentProfile.audiosButton:press(0.2)
  1194.                 audioToShowFrom = 1
  1195.                 audioGUI(currentProfile.ID)
  1196.                 buffer.draw()
  1197.             elseif currentProfile.sendMessageButton:isClicked(e[3], e[4]) then
  1198.                 currentProfile.sendMessageButton:press(0.2)
  1199.                 currentMessagesPeerID = currentProfile.ID
  1200.                 messageToShowFrom = 1
  1201.                 currentMessagesAvatarText = currentProfile.avatarText
  1202.                 messagesGUI()
  1203.             end
  1204.         end
  1205.  
  1206.         if whatIsOnScreen == "friends" then
  1207.             for ID in pairs(currentFriends.sendMessageButtons) do
  1208.                 if clickedAtZone(e[3], e[4], currentFriends.sendMessageButtons[ID]) then
  1209.                     buffer.text(currentFriends.sendMessageButtons[ID][1], currentFriends.sendMessageButtons[ID][2], 0x000000, "Написать сообщение")
  1210.                     buffer.draw()
  1211.                     currentMessagesPeerID = ID
  1212.                     messageToShowFrom = 1
  1213.                     currentMessagesAvatarText = currentFriends.sendMessageButtons[ID][5]
  1214.                     messagesGUI()
  1215.                     break
  1216.                 end
  1217.             end
  1218.  
  1219.             for ID in pairs(currentFriends.openProfileButtons) do
  1220.                 if clickedAtZone(e[3], e[4], currentFriends.openProfileButtons[ID]) then
  1221.                     buffer.text(currentFriends.openProfileButtons[ID][1], currentFriends.openProfileButtons[ID][2], 0x000000, "Открыть профиль")
  1222.                     buffer.draw()
  1223.                     loadAndShowProfile(ID)
  1224.                     buffer.draw()
  1225.                     break
  1226.                 end
  1227.             end
  1228.         end
  1229.  
  1230.         for key in pairs(obj.leftBar) do
  1231.             if clickedAtZone(e[3], e[4], obj.leftBar[key]) then
  1232.                 -- GUI.error("Кликнули на лефт бар ээлемент")
  1233.                 local oldLeftBarElement = currentLeftBarElement
  1234.                 currentLeftBarElement = key
  1235.  
  1236.                 drawLeftBar()
  1237.                 buffer.draw()
  1238.  
  1239.                 if leftBarElements[currentLeftBarElement] == "Выход" then
  1240.                     os.sleep(0.3)
  1241.                     buffer.clear(0x262626)
  1242.                     ecs.prepareToExit()
  1243.                     return
  1244.                 elseif leftBarElements[currentLeftBarElement] == "Аудиозаписи" then
  1245.                     currentProfile = currentProfile or {}
  1246.                     currentProfile.ID = personalInfo.id
  1247.                 elseif leftBarElements[currentLeftBarElement] == "Настройки" then
  1248.                     local data = ecs.universalWindow("auto", "auto", 36, 0x262626, true,
  1249.                         {"EmptyLine"},
  1250.                         {"CenterText", ecs.colors.orange, "Настройки"},
  1251.                         {"EmptyLine"},
  1252.                         {"Switch", ecs.colors.orange, 0xffffff, 0xFFFFFF, "Сохранять данные авторизации", settings.saveAuthData},
  1253.                         {"EmptyLine"},
  1254.                         {"Switch", ecs.colors.orange, 0xffffff, 0xFFFFFF, "Добавлять приписку \"Отправлено с ...\"", settings.addSendingInfo},
  1255.                         {"EmptyLine"},
  1256.                         {"CenterText", ecs.colors.orange, "OpenComputers VK Client v4.0"},
  1257.                         {"EmptyLine"},
  1258.                         {"CenterText", ecs.colors.white, "Автор: Игорь Тимофеев, vk.com/id7799889"},
  1259.                         {"CenterText", ecs.colors.white, "Все права защищены, епта! Попробуй только спиздить!"},
  1260.                         {"EmptyLine"},
  1261.                         {"Button", {ecs.colors.orange, 0xffffff, "OK"}, {0x999999, 0xffffff, "Отмена"}}
  1262.                     )
  1263.                     if data[3] == "OK" then
  1264.                         settings.saveAuthData = data[1]
  1265.                         settings.addSendingInfo = data[2]
  1266.  
  1267.                         if settings.saveAuthData then
  1268.                             settings.username = loginData.username
  1269.                             settings.password = loginData.password
  1270.                         else
  1271.                             settings.username = nil
  1272.                             settings.password = nil
  1273.                         end
  1274.                         saveSettings()
  1275.  
  1276.                         currentLeftBarElement = oldLeftBarElement
  1277.                     end
  1278.                 end
  1279.  
  1280.                 mainGUI()
  1281.                 break
  1282.             end
  1283.         end
  1284.     elseif e[1] == "scroll" then
  1285.         if e[5] == 1 then
  1286.             if whatIsOnScreen == "dialogs" then
  1287.                 dialogToShowFrom = dialogToShowFrom - dialogScrollSpeed
  1288.                 if dialogToShowFrom < 1 then dialogToShowFrom = 1 end
  1289.                 status("Прокручиваю диалоги, отправляю запрос на сервер")
  1290.                 dialogsGUI()
  1291.                 buffer.draw()
  1292.             elseif whatIsOnScreen == "messages" then
  1293.                 messageToShowFrom = messageToShowFrom + messagesScrollSpeed
  1294.                 status("Прокручиваю сообщения, отправляю запрос на сервер")
  1295.                 messagesGUI()
  1296.                 buffer.draw()
  1297.             elseif whatIsOnScreen == "audio" then
  1298.                 audioToShowFrom = audioToShowFrom - audioScrollSpeed
  1299.                 if audioToShowFrom < 1 then audioToShowFrom = 1 end
  1300.                 status("Прокручиваю аудозаписи, отправляю запрос на сервер")
  1301.                 audioGUI(currentProfile and currentProfile.ID or personalInfo.id)
  1302.                 buffer.draw()
  1303.             elseif whatIsOnScreen == "userProfile" then
  1304.                 currentProfileY = currentProfileY + profileScrollSpeed
  1305.                 if currentProfileY > mainZoneY + 2 then currentProfileY = mainZoneY + 2 end
  1306.                 userProfileGUI()
  1307.                 buffer.draw()
  1308.             elseif whatIsOnScreen == "friends" then
  1309.                 currentFriendsOffset = currentFriendsOffset - friendsScrollSpeed
  1310.                 if currentFriendsOffset < 0 then currentFriendsOffset = 0 end
  1311.                 friendsGUI()
  1312.                 buffer.draw()
  1313.             elseif whatIsOnScreen == "news" then
  1314.                 currentNews = currentNews - 1
  1315.                 if currentNews < 1 then currentNews = 1 end
  1316.                 newsGUI()
  1317.                 buffer.draw()
  1318.             end
  1319.         else
  1320.             if whatIsOnScreen == "dialogs" then
  1321.                 dialogToShowFrom = dialogToShowFrom + dialogScrollSpeed
  1322.                 status("Прокручиваю диалоги, отправляю запрос на сервер")
  1323.                 dialogsGUI()
  1324.                 buffer.draw()
  1325.             elseif whatIsOnScreen == "messages" then
  1326.                 messageToShowFrom = messageToShowFrom - messagesScrollSpeed
  1327.                 if messageToShowFrom < 1 then messageToShowFrom = 1 end
  1328.                 status("Прокручиваю сообщения, отправляю запрос на сервер")
  1329.                 messagesGUI()
  1330.                 buffer.draw()
  1331.             elseif whatIsOnScreen == "audio" then
  1332.                 audioToShowFrom = audioToShowFrom + audioScrollSpeed
  1333.                 status("Прокручиваю аудозаписи, отправляю запрос на сервер")
  1334.                 audioGUI(currentProfile and currentProfile.ID or personalInfo.id)
  1335.                 buffer.draw()
  1336.             elseif whatIsOnScreen == "userProfile" then
  1337.                 currentProfileY = currentProfileY - profileScrollSpeed
  1338.                 userProfileGUI()
  1339.                 buffer.draw()
  1340.             elseif whatIsOnScreen == "friends" then
  1341.                 currentFriendsOffset = currentFriendsOffset + friendsScrollSpeed
  1342.                 friendsGUI()
  1343.                 buffer.draw()
  1344.             elseif whatIsOnScreen == "news" then
  1345.                 currentNews = currentNews + 1
  1346.                 newsGUI()
  1347.                 buffer.draw()
  1348.             end
  1349.         end
  1350.     end
  1351. end
  1352.  
  1353. -- local success, dialogs = getDialogsRequest(0, 5)
  1354. -- saveToFile(serialization.serialize(dialogs))
  1355.  
  1356.  
  1357. -- sendMessageRequest(dialogs.response.items[2], "тестовое сообщение, отправлено через OpenComputers VK Client by Игорь, епта")
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement