Advertisement
ddoscom

Untitled

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