Advertisement
LDDestroier

encmail test fail durrrr

Apr 20th, 2017
174
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. --[[
  2.  pastebin get JtgbWdV5 enchat
  3.  std pb JtgbWdV5 enchat
  4.  std ld enchat enchat
  5.  
  6. 'Encmail' version 0.1 by EldidiStroyrr (CC Forums: LDDestroier)
  7.  
  8. Encrypted, decentralized, colorized EMAIL program for ComputerCraft 1.6 or later.
  9. Encrypts messages/usernames with a password and os.time()
  10. Color your text with &[color code] and ~[color code].
  11. Disable text formatting with &{, and re-enable it with &}.
  12. Use &k to obfuscate, and ~k to stop obfuscation. Hehe.
  13. This program is based on Enchat, and is incomplete.
  14.  
  15. Forum link for Enchat:
  16. http://www.computercraft.info/forums2/index.php?/topic/25290-enchat-encrypted-decentralized-chat/
  17.  
  18. This is a beta release. You fool!
  19.  
  20. Working on:
  21.  +making an interface like a standard email program
  22.  +making an address book
  23.  +getting a solid folder hierarchy
  24.  +removing all unneccesary fucking garbage text goddamn it
  25. --]]
  26.  
  27. local log,_log,chatlog
  28. local em_path = ".encmail"
  29. local logpath = fs.combine(em_path,"logs")
  30. local configpath = fs.combine(em_path,"config")
  31.  
  32. local displayMode = "mainmenu"
  33.  
  34. local timedivisor = 2 --Must be same as other enchat clients. Can be used to limit scrambling due to using os.time
  35.  
  36. local tArg = {...}
  37. local encKey, yourName = tArg[1], tArg[2]
  38.  
  39. log = {}         --Log formatted for view
  40. _log = {}        --Log with all information
  41. chatlog = {}   --Log with all pre-formatted information
  42. local commandTable   --Contains all commands
  43. local scr_x, scr_y = term.getSize()
  44. local channel = 0 --Do not modify, it's changed anyway
  45. local checksum, modems, scroll, doScroll
  46. local endMode = 0 --0 is exit, 1 is restart
  47. local cfile --Current file. Defined later.
  48. local hasKrazy = false
  49.  
  50. local enchatSettings = {
  51.     fancyMsg = true, --Whether or not to colorize as you type
  52.     doColorize = true, --Whether or not to use color formatting at all
  53.     reverseScroll = false, --Reverses scrolling direction. But why would you want to do that?
  54. }
  55.  
  56. local palate = {
  57.     bg = colors.gray, --Default chat background color
  58.     txt = colors.white, --Default chat text color
  59.     chatbg = colors.white, --Chat prompt background color
  60.     chattxt = colors.black, --Chat prompt text color
  61. }
  62.  
  63. local colors_names = { --this has been modified to use the Paint colors rather than minecraft formatting
  64.     ["0"] = colors.white,
  65.     ["1"] = colors.orange,
  66.     ["2"] = colors.magenta,
  67.     ["3"] = colors.lightBlue,
  68.     ["4"] = colors.yellow,
  69.     ["5"] = colors.lime,
  70.     ["6"] = colors.pink,
  71.     ["7"] = colors.gray,
  72.     ["8"] = colors.lightGray,
  73.     ["9"] = colors.cyan,
  74.     ["a"] = colors.purple,
  75.     ["b"] = colors.blue,
  76.     ["c"] = colors.brown,
  77.     ["d"] = colors.green,
  78.     ["e"] = colors.red,
  79.     ["f"] = colors.black,
  80. }  
  81.  
  82. --going to add compatibility for ComputerCaft 1.63
  83. local _currentcolors = {
  84.     txt = colors.white,
  85.     bg = colors.black,
  86. }
  87. local termsetTextColor,termsetBackgroundColor = term.setTextColor,term.setBackgroundColor
  88. local termsetCursorPos,termclear,termclearLine,termwrite,termgetSize,termsetCursorBlink,termisColor = term.setCursorPos,term.clear,term.clearLine,term.write,term.getSize,term.setCursorBlink,term.isColor
  89. local tableinsert,tableconcat,tableunpack = table.insert,table.concat,table.unpack
  90. local termblit,termgetTextColor,termgetBackgroundColor,termgetCursorPos
  91. local parallelwaitForAny = parallel.waitForAny
  92. local termsetVisible
  93. if term.current then
  94.     termcurrent = term.current
  95. end
  96.  
  97. local oldsettext = term.setTextColor
  98. local oldsetbg = term.setBackgroundColor
  99. if not term.blit then
  100.     termsetTextColor = function(col)
  101.         oldsettext(col)
  102.         _currentcolors.txt = col
  103.     end
  104.     termsetBackgroundColor = function(col)
  105.         oldsetbg(col)
  106.         _currentcolors.bg = col
  107.     end
  108.     termgetTextColor = function()
  109.         return _currentcolors.txt
  110.     end
  111.     termgetBackgroundColor = function()
  112.         return _currentcolors.bg
  113.     end
  114.     termblit = function(txt,tx,bg)
  115.         local pt,pb = _currentcolors.bg,_currentcolors.txt
  116.         if type(txt) ~= "string" or type(tx) ~= "string" or type(bg) ~= "string" then
  117.             error("expected 3 strings, got "..tableconcat({type(txt),type(tx),type(bg)},", "))
  118.         end
  119.         if not ((#txt == #tx) and #tx == #bg) then
  120.             error("all three arguments must be of same length")
  121.         end
  122.         for p = 1, #txt do
  123.             oldsettext(colors_names[tx:sub(p,p)])
  124.             oldsetbg(colors_names[bg:sub(p,p)])
  125.             termwrite(txt:sub(p,p))
  126.         end
  127.         oldsettext(pt)
  128.         oldsettext(pb)
  129.     end
  130. else
  131.     termblit = term.blit
  132.     termgetTextColor = term.getTextColor
  133.     termgetBackgroundColor = term.getBackgroundColor
  134.     termgetCursorPos = term.getCursorPos
  135. end
  136.  
  137. local tableConcat = function(tbl,between)
  138.     local output = ""
  139.     for k,v in pairs(tbl) do
  140.         output = output..k..between
  141.     end
  142.     return output:sub(1,-2)
  143. end
  144.  
  145. --Loading AES encryption functions. AES API ported to CC by SquidDev. Thanks heaps!
  146. local apipath
  147. if shell then apipath = fs.combine(shell.dir(),"aes") else apipath = "" end
  148. if (not aes) and (not fs.exists(apipath)) then
  149.     print("AES API not found! Downloading...")
  150.     local prog = http.get("http://pastebin.com/raw/9E5UHiqv")
  151.     if not prog then error("FAIL!") end
  152.     local file = fs.open(apipath,"w")
  153.     file.write(prog.readAll())
  154.     file.close()
  155. end
  156. if not aes then
  157.     local res = os.loadAPI(apipath)
  158.     if not res then error("Didn't load AES API!") end
  159. end
  160.  
  161. --In case I use an API that uses a different syntax than (msg, key)
  162. local encrite = function(msg, key)
  163.     return aes.encrypt(key, msg)
  164. end
  165.  
  166. local decrite = function(msg, key)
  167.     return aes.decrypt(key, msg)
  168. end
  169.  
  170. local encode = function(txt) --converts string into a table of each character's byte code
  171.     if type(txt) ~= "string" then return false, "requires string" end
  172.     return {txt:byte(1,-1)}
  173. end
  174.  
  175. local decode = function(tbl) --converts an encoded string into something useful.
  176.     if type(tbl) ~= "table" then return false, "requires table" end
  177.     return string.char(tableunpack(tbl))
  178. end
  179.  
  180. local strcapsule = function(txt)
  181.     return "\""..tostring(txt).."\""
  182. end
  183.  
  184. local cwrite = function(txt,setY,doClearLine)
  185.     local scr_x, scr_y = termgetSize()
  186.     local x,y = termgetCursorPos()
  187.     termsetCursorPos((scr_x/2)-(#txt/2),setY or y)
  188.     if doClearLine then termclearLine() end
  189.     write(txt)
  190. end
  191.  
  192. local waitForModem = function()
  193.     local mod
  194.     while true do
  195.         sleep(0.2)
  196.         mod = peripheral.find("modem")
  197.         if mod then
  198.             return mod
  199.         end
  200.     end
  201. end
  202.  
  203. if not peripheral.find("modem") then
  204.     termsetBackgroundColor(colors.gray)
  205.     termsetTextColor(colors.white)
  206.     termclear()
  207.     cwrite("Enchat requires a modem.",3)
  208.     cwrite("Add one, or press a key.",4)
  209.     sleep(0.1)
  210.     local outcome = parallelwaitForAny(function() os.pullEvent("key") end, waitForModem)
  211.     modems = {peripheral.find("modem")}
  212.     if #modems == 0 then
  213.         termsetBackgroundColor(colors.black)
  214.         termsetCursorPos(1,scr_y)
  215.         termclearLine()
  216.         sleep(0)
  217.         return false
  218.     end
  219. end
  220.  
  221. local modemOpen = function(chan)
  222.     for a = 1, #modems do
  223.         modems[a].open(chan)
  224.     end
  225. end
  226.  
  227. local modemClose = function(chan)
  228.     for a = 1, #modems do
  229.         modems[a].close(chan)
  230.     end
  231. end
  232.  
  233. local modemTransmit = function(chan,repchan,msg)
  234.     for a = 1, #modems do
  235.         modems[a].transmit(chan,repchan,msg)
  236.     end
  237. end
  238.  
  239. local tsv = function(visible)
  240.     if termcurrent then
  241.         if termcurrent().setVisible then
  242.             termcurrent().setVisible(visible)
  243.             return true
  244.         else
  245.             return false
  246.         end
  247.     else
  248.         return false
  249.     end
  250. end
  251.  
  252. local logadd = function(name,msg,newline,stopFormatting)
  253.     chatlog[#chatlog+1] = {name,msg,newline,stopFormatting or false}
  254. end
  255.  
  256. local deepCopy = function(tbl)
  257.     local output = {}
  258.     for k,v in pairs(tbl) do
  259.         output[k] = v
  260.     end
  261.     return output
  262. end
  263.  
  264. local explode = function(div,str)
  265.     if (div=='') then return false end
  266.     local pos,arr = 0,{}
  267.     for st,sp in function() return string.find(str,div,pos,false) end do
  268.         tableinsert(arr,string.sub(str,pos,st-1))
  269.         pos = sp + 1
  270.     end
  271.     tableinsert(arr,string.sub(str,pos))
  272.     return arr
  273. end
  274.  
  275. local colors_strnames = { --primarily for use when coloring palate
  276.     ["white"] = colors.white,
  277.     ["orange"] = colors.orange,
  278.     ["magenta"] = colors.magenta,
  279.     ["lightpurple"] = colors.magenta,
  280.     ["light purple"] = colors.magenta,
  281.     ["lightblue"] = colors.lightBlue,
  282.     ["light blue"] = colors.lightBlue,
  283.     ["yellow"] = colors.yellow,
  284.     ["piss"] = colors.yellow,
  285.     ["lemon"] = colors.yellow,
  286.     ["lime"] = colors.lime,
  287.     ["lightgreen"] = colors.lime,
  288.     ["light green"] = colors.lime,
  289.     ["pink"] = colors.pink,
  290.     ["lightish red"] = colors.pink,
  291.     ["gray"] = colors.gray,
  292.     ["grey"] = colors.gray,
  293.     ["lightgray"] = colors.lightGray,
  294.     ["lightgrey"] = colors.lightGray,
  295.     ["light gray"] = colors.lightGray,
  296.     ["light grey"] = colors.lightGray,
  297.     ["cyan"] = colors.cyan,
  298.     ["seawater"] = colors.cyan,
  299.     ["purple"] = colors.purple,
  300.     ["purble"] = colors.purple,
  301.     ["blue"] = colors.blue,
  302.     ["blu"] = colors.blue,
  303.     ["brown"] = colors.brown,
  304.     ["shit"] = colors.brown,
  305.     ["green"] = colors.green,
  306.     ["grass"] = colors.green,
  307.     ["red"] = colors.red,
  308.     ["blood"] = colors.red,
  309.     ["black"] = colors.black,
  310. }
  311.  
  312. for k,v in pairs(colors_names) do
  313.     colors_strnames[k] = v
  314. end
  315.  
  316. local function alterXY()
  317.     local cx,cy = termgetCursorPos()
  318.     if cx == scr_x then
  319.         termsetCursorPos(1,cy+1)
  320.     end
  321. end
  322.  
  323. local blit_names = {}
  324. for k,v in pairs(colors_names) do
  325.     blit_names[v] = k
  326. end
  327.  
  328. local safeColor = function(col) --I could've done much better, but whatever
  329.     if type(col) ~= "number" then
  330.         return false
  331.     else
  332.         if col > 2^15 then
  333.             return false
  334.         else
  335.             if not termisColor() then
  336.                 if (col ~= colors.white) and (col ~= colors.lightGray) and (col ~= colors.gray) and (col ~= colors.black) then
  337.                     return false
  338.                 end
  339.             end
  340.         end
  341.     end
  342.     return true
  343. end
  344.  
  345. local blitWrap = function(text,txt,bg,noWrite)
  346.     local wordNo = 1
  347.     local words = explode(" ",text)
  348.     local lines = 0
  349.     local scr_x, scr_y = termgetSize()
  350.     local cx,cy
  351.     local startX,startY = termgetCursorPos()
  352.     for a = 1, #text do
  353.         cx,cy = termgetCursorPos()
  354.         if text:sub(a,a) == " " and text:sub(a-1,a-1) ~= " " and a > 1 then
  355.             wordNo = wordNo + 1
  356.             if cx + #words[wordNo] > scr_x then
  357.                 termsetCursorPos(1,cy+1)
  358.                 lines = lines + 1
  359.             end
  360.         end
  361.         cx,cy = termgetCursorPos()
  362.         if text:sub(a,a) == "\n" then
  363.             termsetCursorPos(1,cy+1)
  364.             lines = lines + 1
  365.         elseif not (cx == 1 and text:sub(a,a) == " ") then
  366.             if noWrite == true then
  367.                 termsetCursorPos(cx+1,cy)
  368.             else
  369.                 if safeColor(colors_names[txt:sub(a,a)]) then
  370.                     termblit(text:sub(a,a),txt:sub(a,a),bg:sub(a,a))
  371.                 else
  372.                     termwrite(text:sub(a,a))
  373.                 end
  374.             end
  375.         end
  376.         if cx == scr_x then
  377.             termsetCursorPos(1,cy+1)
  378.             lines = lines + 1
  379.         end
  380.     end
  381.     if noWrite == true then
  382.         termsetCursorPos(startX,startY)
  383.     end
  384.     return lines
  385. end
  386.  
  387. local tablefind = function(tbl,str)
  388.     for a = 1, #tbl do
  389.         if tbl[a] == str then
  390.             return a
  391.         end
  392.     end
  393. end
  394.  
  395. local codeNames = {
  396.     ["r"] = "reset",    -- Sets either the text (&) or background (~) colors to their original color.
  397.     ["{"] = "stopFormatting",   --Toggles formatting text off
  398.     ["}"] = "startFormatting",  --Toggles formatting text on
  399.     ["k"] = "krazy" --Makes the font krazy!
  400. }
  401.  
  402. local kraziez = {
  403.     ["l"] = {
  404.         "!",
  405.         "l",
  406.         "1",
  407.         "|",
  408.         "i",
  409.         "I",
  410.         ":",
  411.         ";",
  412.     },
  413.     ["m"] = {
  414.         "M",
  415.         "W",
  416.         "w",
  417.         "m",
  418.         "X",
  419.         "N",
  420.         "_",
  421.         "%",
  422.         "@",
  423.     },
  424.     ["all"] = {}
  425. }
  426. for a = 1, #kraziez["l"] do
  427.     kraziez[kraziez["l"][a]] = kraziez["l"]
  428. end
  429. for k,v in pairs(kraziez) do
  430.     for a = 1, #v do
  431.         kraziez[kraziez[k][a]] = v
  432.     end
  433. end
  434. if _VERSION then
  435.     for a = 1, 255 do
  436.         if (a ~= 32) and (a ~= 13) and (a ~= 10) then
  437.             kraziez["all"][#kraziez["all"]+1] = string.char(a)
  438.         end
  439.     end
  440. else
  441.     for a = 33, 126 do
  442.         kraziez["all"][#kraziez["all"]+1] = string.char(a)
  443.     end
  444. end
  445.  
  446.  
  447. local textToBlit = function(str) --returns output for term.blit, or blitWrap, with formatting codes for color selection. Modified for use specifically with Enchat.
  448.     local p = 1
  449.     local output = ""
  450.     local txcolorout = ""
  451.     local bgcolorout = ""
  452.     local txcode = "&"
  453.     local bgcode = "~"
  454.     local isKrazy = false
  455.     local doFormatting = true
  456.     local usedformats = {}
  457.     local txcol,bgcol = blit_names[termgetTextColor()], blit_names[termgetBackgroundColor()]
  458.     local origTX,origBG = blit_names[termgetTextColor()], blit_names[termgetBackgroundColor()]
  459.     local cx,cy
  460.     local moveOn = function(tx,bg)
  461.         if isKrazy and (str:sub(p,p) ~= " ") and doFormatting then
  462.             if kraziez[str:sub(p,p)] then
  463.                 output = output..kraziez[str:sub(p,p)][math.random(1,#kraziez[str:sub(p,p)])]
  464.             else
  465.                 output = output..kraziez.all[math.random(1,#kraziez.all)]
  466.             end
  467.         else
  468.             output = output..str:sub(p,p)
  469.         end
  470.         txcolorout = txcolorout..(doFormatting and tx or origTX)
  471.         bgcolorout = bgcolorout..(doFormatting and bg or origBG)
  472.     end
  473.     while p <= #str do
  474.         if str:sub(p,p) == txcode then
  475.             if colors_names[str:sub(p+1,p+1)] and doFormatting then
  476.                 txcol = str:sub(p+1,p+1)
  477.                 usedformats.txcol = true
  478.                 p = p + 1
  479.             elseif codeNames[str:sub(p+1,p+1)] then
  480.                 if str:sub(p+1,p+1) == "r" and doFormatting then
  481.                     txcol = blit_names[termgetTextColor()]
  482.                     isKrazy = false
  483.                     p = p + 1
  484.                 elseif str:sub(p+1,p+1) == "{" and doFormatting then
  485.                     doFormatting = false
  486.                     p = p + 1
  487.                 elseif str:sub(p+1,p+1) == "}" and (not doFormatting) then
  488.                     doFormatting = true
  489.                     p = p + 1
  490.                 elseif str:sub(p+1,p+1) == "k" and doFormatting then
  491.                     isKrazy = true
  492.                     usedformats.krazy = true
  493.                     p = p + 1
  494.                 else
  495.                     moveOn(txcol,bgcol)
  496.                 end
  497.             else
  498.                 moveOn(txcol,bgcol)
  499.             end
  500.             p = p + 1
  501.         elseif str:sub(p,p) == bgcode then
  502.             if colors_names[str:sub(p+1,p+1)] and doFormatting then
  503.                 bgcol = str:sub(p+1,p+1)
  504.                 usedformats.bgcol = true
  505.                 p = p + 1
  506.             elseif codeNames[str:sub(p+1,p+1)] and (str:sub(p+1,p+1) == "r") and doFormatting then
  507.                 bgcol = blit_names[termgetBackgroundColor()]
  508.                 p = p + 1
  509.             elseif str:sub(p+1,p+1) == "k" and doFormatting then
  510.                 isKrazy = false
  511.                 p = p + 1
  512.             else
  513.                 moveOn(txcol,bgcol)
  514.             end
  515.             p = p + 1
  516.         else
  517.             moveOn(txcol,bgcol)
  518.             p = p + 1
  519.         end
  520.     end
  521.     return output, txcolorout, bgcolorout, usedformats
  522. end
  523.  
  524. local funcread = function(repchar,rHistory,doFunc,noNewLine,writeFunc,cursorAdjFunc,doFuncEvent)
  525.     local scr_x,scr_y = termgetSize()
  526.     local sx,sy = termgetCursorPos()
  527.     local cursor = 1
  528.     local rCursor = #rHistory+1
  529.     local output = ""
  530.     termsetCursorBlink(true)
  531.     local rite = writeFunc or termwrite
  532.     while true do
  533.         local evt,key = os.pullEvent()
  534.         if evt == doFuncEvent then
  535.             pleaseDoFunc = true
  536.         elseif evt == "key" then
  537.             if key == keys.enter then
  538.                 if not noNewLine then
  539.                     write("\n")
  540.                 end
  541.                 termsetCursorBlink(false)
  542.                 return output
  543.             elseif key == keys.left then
  544.                 if cursor-1 >= 1 then
  545.                     cursor = cursor - 1
  546.                 end
  547.             elseif key == keys.right then
  548.                 if cursor <= #output then
  549.                     cursor = cursor + 1
  550.                 end
  551.             elseif key == keys.up then
  552.                 if rCursor > 1 then
  553.                     rCursor = rCursor - 1
  554.                     termsetCursorPos(sx,sy)
  555.                     rite((" "):rep(#output))
  556.                     output = rHistory[rCursor] or ""
  557.                     cursor = #output+1
  558.                     pleaseDoFunc = true
  559.                 end
  560.             elseif key == keys.down then
  561.                 termsetCursorPos(sx,sy)
  562.                 rite((" "):rep(#output))
  563.                 if rCursor < #rHistory then
  564.                     rCursor = rCursor + 1
  565.                     output = rHistory[rCursor] or ""
  566.                     cursor = #output+1
  567.                     pleaseDoFunc = true
  568.                 else
  569.                     rCursor = #rHistory+1
  570.                     output = ""
  571.                     cursor = 1
  572.                 end
  573.             elseif key == keys.backspace then
  574.                 if cursor > 1 and #output > 0 then
  575.                     output = output:sub(1,cursor-2)..output:sub(cursor)
  576.                     cursor = cursor - 1
  577.                     pleaseDoFunc = true
  578.                 end
  579.             elseif key == keys.delete then
  580.                 if #output:sub(cursor,cursor) == 1 then
  581.                     output = output:sub(1,cursor-1)..output:sub(cursor+1)
  582.                     pleaseDoFunc = true
  583.                 end
  584.             end
  585.         elseif evt == "char" or evt == "paste" then
  586.             output = output:sub(1,cursor-1)..key..output:sub(cursor+(#key-1))
  587.             cursor = cursor + #key
  588.             pleaseDoFunc = true
  589.         end
  590.         local pOut = (output or ""):sub(math.max( 1,(#textToBlit(output)+sx)-scr_x) )
  591.         if pleaseDoFunc then
  592.             pleaseDoFunc = false
  593.             if type(doFunc) == "function" then
  594.                 doFunc(output)
  595.             end
  596.             termsetCursorPos(sx,sy)
  597.             if repchar then
  598.                 rite(repchar:sub(1,1):rep(#pOut))
  599.             else
  600.                 rite(pOut)
  601.             end
  602.             termwrite(" ")
  603.         end
  604.         termsetCursorPos(sx+cursorAdjFunc(pOut)+cursor-math.max( 1,(#textToBlit(output)+sx)-scr_x),sy)
  605.     end
  606. end
  607.  
  608. local generateEncy = function()
  609.     modems = {peripheral.find("modem")}
  610.     modemClose(channel)
  611.     channel = 0
  612.     for a = 1, #encKey do
  613.         channel = channel + string.byte(string.sub(encKey,a,a))
  614.     end
  615.     if channel >= 65535 then
  616.         error("Bad key! Use a smaller one.")
  617.     end
  618.     modemOpen(channel)
  619.     checksum = "ENCMAIL" --Used to eliminate gibberish messages securely, based on the key.
  620.     for a = 1, #encKey do
  621.         checksum = checksum..string.byte(string.sub(encKey,a,a))
  622.     end
  623.     checksum = encrite(checksum,encKey)
  624. end
  625.  
  626. if yourName then
  627.     if textToBlit(yourName) == "con" or textToBlit(yourName) == "*" then return printError("Not that name!") end
  628. end
  629.  
  630. local cf = function(txt) --contextual filter
  631.     if enchatSettings.doColorize then
  632.         return txt
  633.     else
  634.         return textToBlit(txt)
  635.     end
  636. end
  637.  
  638. local writef = function(txt,noWrite)
  639.     if enchatSettings.doColorize then
  640.         local text, textCol, bgCol, usedformats = textToBlit(txt)
  641.         local out = blitWrap(text,textCol,bgCol,noWrite)
  642.         return out, #text, usedformats
  643.     else
  644.         return write(txt), #txt, {}
  645.     end
  646. end
  647.  
  648. local _ftlen = function(text)
  649.     return #textToBlit(text)-#text
  650. end
  651.  
  652. local clearLines = function(top, bottom)
  653.     for a = top, bottom do
  654.         termsetCursorPos(1,a)
  655.         termclearLine()
  656.     end
  657. end
  658.  
  659. scroll = 1
  660. doScroll = true
  661.  
  662. local urkrazy,_ = false
  663. local redrawScreen = function() --renders the chat and other things that change when scrolling.
  664.     tsv(false)
  665.     local prevX, prevY = termgetCursorPos()
  666.     local _logold = _log
  667.     _log,log = {},{}
  668.     for a = 1, #chatlog do
  669.         if not chatlog[a][3] then
  670.             _log[#_log+1] = {"",false}
  671.         end
  672.         if chatlog[a][4] == true then
  673.             _log[#_log+1] = {"<"..chatlog[a][1].."> "..chatlog[a][2],false}
  674.         else
  675.             _log[#_log+1] = {cf("<"..chatlog[a][1].."&r~r> "..chatlog[a][2]),true}
  676.         end
  677.     end
  678.     if not doScroll then
  679.         scroll = scroll + (#_log - #_logold)
  680.     end
  681.     for a = 1, #_log-(scroll-1) do
  682.         log[#log+1] = _log[a]
  683.     end
  684.     termsetCursorPos(1,1)
  685.     termsetBackgroundColor(palate.bg)
  686.     termsetTextColor(palate.txt)
  687.     termwrite(string.rep(" ",scr_x*(scr_y-2)))
  688.     local midPoint = {
  689.         scr_x / 2,
  690.         scr_y / 2,
  691.     }
  692.     local yoffset = 0
  693.     clearLines(1,scr_y-2)
  694.     termsetCursorPos(1,scr_y)
  695.     termclearLine()
  696.     local indent = 1 --in case any line is greater than the length of the screen
  697.     local indentIn = 0 --in the same case, mid writing
  698.     for a = 1, #log do
  699.         if log[a][2] then
  700.             indent = indent + writef(log[a][1],true)
  701.         else
  702.             indent = indent + math.floor(#log[a][1]/scr_x)
  703.         end
  704.     end
  705.     hasKrazy = false
  706.     for a = 1, #log do
  707.         termsetCursorPos(1,((((scr_y-1)+a-#log))-indent)+indentIn)
  708.         if log[a][2] then
  709.             indentIn = indentIn + writef(log[a][1],true)
  710.             _,_,urkrazy = writef(log[a][1],false)
  711.             hasKrazy = hasKrazy or (urkrazy.krazy or false)
  712.         else
  713.             indentIn = indentIn + math.floor((#log[a][1])/scr_x)
  714.             termwrite(log[a][1])
  715.         end
  716.     end
  717.     termsetCursorPos(scr_x,scr_y)
  718.     if doScroll then writef("&8.") else termwrite(" ") end
  719.     termsetCursorPos(prevX,prevY)
  720.     tsv(true)
  721. end
  722.  
  723. local _getTears = function() --to be ran with the /cry command. You freakin' mimsy.
  724.     if (#modems > 0) then modemTransmit(channel, channel, {cry = true, cs = encode(checksum)}) end --ping!
  725.     while true do
  726.         local evt = {os.pullEvent("modem_message")}
  727.         if type(evt[5]) == "table" then
  728.             if type(evt[5].tears) == "table" then evt[5].tears = decode(evt[5].tears) end
  729.             if type(evt[5].tears) == "string" and decrite(decode(evt[5].cs),encKey) == decrite(checksum,encKey) then
  730.                 local tear = decrite(evt[5].tears,encKey)
  731.                 playerList[tear] = true
  732.             end
  733.         end
  734.     end
  735. end
  736.  
  737. local handleCommand = function(commie)
  738.     commie = commie or {}
  739.     local command = commie[1] or ""
  740.     local argument = commie
  741.     if #commie > 0 then
  742.         table.remove(argument,1)
  743.         argument = tableconcat(argument," ") or ""
  744.     else
  745.         argument = ""
  746.     end
  747.     local commandTable
  748.     commandTable = {
  749.         ["exit"] = function() --why would you want to leave??
  750.             endMode = 0
  751.             return "exit"
  752.         end,
  753.         ["key"] = function()
  754.             if #argument > 0 then
  755.                 if argument == encKey then return end
  756.                 os.queueEvent("enchat_send", "con", yourName.."&r~r has left.",encKey)
  757.                 sleep(0)
  758.                 encKey = argument
  759.                 generateEncy()
  760.                 os.queueEvent("enchat_send", "con", yourName.."&r~r moseyed on over.",encKey)
  761.                 logadd("*","Key changed. (channel: "..channel.."&r)",true)
  762.             else
  763.                 generateEncy() --in case you break and reattach a modem, this should fix it right up
  764.                 logadd("*","Modem Channel: "..channel,false,true)
  765.                 logadd("*","Key: "..strcapsule(encKey),true,true)
  766.             end
  767.             redrawScreen()
  768.         end,
  769.         ["heil"] = function() --please don't tell me that you're offended, or I'll get offended
  770.             local heilTable = {
  771.                 "Cobra",
  772.                 "this",
  773.                 "LDD",
  774.                 "unto me",
  775.                 "dan200",
  776.                 "myself",
  777.                 "!",
  778.                 "oeed",
  779.                 "Exerro",
  780.                 "Kepler",
  781.                 "Danny",
  782.                 "Bagel",
  783.                 "Roger",
  784.                 "King Porky",
  785.             }
  786.             local hailer
  787.             if argument ~= "" then hailer = argument else hailer = heilTable[math.random(1,#heilTable)] end
  788.             local mess = "Heil "..hailer.."!"
  789.             os.queueEvent("enchat_send", yourName, mess)
  790.             logadd("con","You heiled "..hailer.."!",false)
  791.             redrawScreen()
  792.         end,
  793.         ["help"] = function() --I would call it "man", but there's only so much you can write about a two-argument function
  794.             local a = false
  795.             for k,v in pairs(commandTable) do
  796.                 strtime = tostring(math.floor(os.time()/timedivisor))
  797.                 logadd("*","&0/&4"..k,a)
  798.                 a = true
  799.             end
  800.             redrawScreen()
  801.         end,
  802.         ["clear"] = function() --*accidentally clears inventory* FUCK
  803.             _log = {}
  804.             log = {}
  805.             chatlog = {}
  806.             redrawScreen()
  807.         end,
  808.         ["cry"] = function() --your annoying tears streaming from your stupid fat face attracts a list of other people
  809.             playerList = {}
  810.             logadd("con","You cried loudly!",true)
  811.             redrawScreen()
  812.             parallelwaitForAny(_getTears, function() sleep(0.5) return end)
  813.             _list = {}
  814.             for k,v in pairs(playerList) do
  815.                 tableinsert(_list,k)
  816.             end
  817.             if #_list > 0 then
  818.                 logadd("con",tableconcat(_list,"&r~r, ").."&r~r responded!",true)
  819.             else
  820.                 logadd("con","&eBut nobody came.",true)
  821.             end
  822.             redrawScreen()
  823.         end,
  824.         ["me"] = function() -- * EldidiStroyrr is dashingly handsome
  825.             os.queueEvent("enchat_send", "*", "~r"..yourName.."~r&2 "..argument)
  826.             logadd("*","~r"..yourName.."~r&2 "..argument,false)
  827.             redrawScreen()
  828.         end,
  829.         ["colors"] = function()
  830.             logadd("*","~0&f0~1&01~22~33~44~55~66~77~88~99~aa~bb~cc~dd~ee~ff",false)
  831.             logadd("*","'&' for text, '~' for background.",false)
  832.             redrawScreen()
  833.         end,
  834.         ["ping"] = function() --what do you mean this command is useless
  835.             logadd("*",(argument ~= "") and argument or "Pong!",false)
  836.             redrawScreen()
  837.         end,
  838.         ["update"] = function()
  839.             local url
  840.             if argument:gsub("%s","") == "beta" then
  841.                 url = "https://pastebin.com/raw/4a6NZaMZ"
  842.             else
  843.                 url = "https://pastebin.com/raw/JtgbWdV5"
  844.             end
  845.             if shell then
  846.                 cfile = shell.getRunningProgram()
  847.             else
  848.                 --termsetBackgroundColor(palate.bg)
  849.                 --termsetTextColor((palate.txt ~= colors.yellow) and colors.yellow or colors.black)
  850.                 --cwrite("Download where?",scr_y,true)
  851.                 logadd("con","&4Download where?",true)
  852.                 scroll = 1
  853.                 redrawScreen()
  854.                 termsetCursorPos(1,scr_y-1)
  855.                 termsetBackgroundColor(colors.lightGray)
  856.                 termsetTextColor(palate.chattxt)
  857.                 termclearLine()
  858.                 write(":")
  859.                 termsetBackgroundColor(palate.chatbg)
  860.                 cfile = read()
  861.             end
  862.             if fs.isReadOnly(cfile) then
  863.                 logadd("*","Unable to update to &4read-only directory.&r",true)
  864.                 redrawScreen()
  865.                 return
  866.             end
  867.             if not http then
  868.                 logadd("*","&4HTTP is disabled.&r Ask an admin to enable it.",true)
  869.                 redrawScreen()
  870.                 return
  871.             else
  872.                 if not http.checkURL(url) then
  873.                     logadd("*","&4It appears the download URL is whitelisted.&r &cPlease slap your admin in their stupid face.",true)
  874.                     redrawScreen()
  875.                     return
  876.                 end
  877.             end
  878.             --termsetBackgroundColor(palate.bg)
  879.             --termsetTextColor((palate.txt ~= colors.yellow) and colors.yellow or colors.black)
  880.             --cwrite("Downloading...",scr_y,true)
  881.             logadd("con","&4Downloading...",true)
  882.             scroll = 1
  883.             redrawScreen()
  884.             local data = http.get(url)
  885.             if not data then
  886.                 logadd("*","&4Couldn't connect to Pastebin.&r Sorry.",true)
  887.                 redrawScreen()
  888.                 return
  889.             else
  890.                 local file = fs.open(cfile,"w")
  891.                 file.write(data.readAll())
  892.                 file.close()
  893.                 --cwrite("Yay! Relaunching.",scr_y,true)
  894.                 logadd("con","&4Yay! Relaunching.",true)
  895.                 scroll = 1
  896.                 redrawScreen()
  897.                 sleep(1)
  898.                 os.queueEvent("enchat_send", "con", yourName.."&r~r redownloaded the program.")
  899.                 sleep(0)
  900.                 endMode = 1
  901.                 return "restart"
  902.             end
  903.         end,
  904.         ["whoami"] = function()
  905.             if argument:lower() == "now" then
  906.                 logadd("*","You are still \""..yourName.."&r~r\"!",true)
  907.             else
  908.                 logadd("*","You are \""..yourName.."&r~r\"!",true)
  909.             end
  910.             redrawScreen()
  911.         end,
  912.         ["nick"] = function()
  913.             if argument ~= "" then
  914.                 if argument ~= yourName then
  915.                     if #argument:gsub("%s","") > 0 then
  916.                         if #textToBlit(argument) < 20 then
  917.                             if textToBlit(argument) ~= "con" and textToBlit(argument) ~= "*" then
  918.                                 os.queueEvent("enchat_send", "con", tostring(yourName.."&r~r is now known as "..strcapsule(argument.."&r~r")))
  919.                                 logadd("*",yourName.."&r~r is now known as "..strcapsule(argument.."&r~r"),false)
  920.                                 yourName = tostring(argument)
  921.                             else
  922.                                 logadd("*","&4Not so fast!!",false)
  923.                             end
  924.                         else
  925.                             logadd("*","&4Maximum 20 non-formatting characters!",false)
  926.                         end
  927.                     else
  928.                         logadd("*","&4Choose a more substantial name.",false)
  929.                     end
  930.                 else
  931.                     logadd("*","&4That's already your name.",false)
  932.                 end
  933.             else
  934.                 logadd("*","&4/nick <newname>",true)
  935.             end
  936.             redrawScreen()
  937.         end,
  938.         ["palate"] = function()
  939.             if argument:gsub("%s","") == "" then
  940.                 logadd("*","&4/palate "..tableConcat(palate,"/").." <color code>",false)
  941.             else
  942.                 argument = explode(" ",argument)
  943.                 if #argument == 1 then
  944.                     if argument[1]:gsub("%s",""):lower() == "reset" then
  945.                         palate = {
  946.                             bg = colors.gray,
  947.                             txt = colors.white,
  948.                             chatbg = colors.white,
  949.                             chattxt = colors.black,
  950.                         }
  951.                         logadd("*","&4You cleansed your palate.",false)
  952.                     else
  953.                         logadd("*","&4Give me a color code next time.",false)
  954.                     end
  955.                 else
  956.                     if #argument > 2 then
  957.                         argument = {argument[1], tableconcat(argument," ",2)}
  958.                     end
  959.                     argument[1] = argument[1]:lower()
  960.                     local newcol = argument[2]:lower()
  961.                     if not palate[argument[1]] then
  962.                         logadd("*","&4That's not a valid palate choice.")
  963.                     else
  964.                         if not colors_strnames[newcol] then
  965.                             logadd("*","&4That isn't a valid color code. (0-f)")
  966.                         else
  967.                             palate[argument[1]] = colors_strnames[newcol]
  968.                             logadd("*","You have such a sense of style.",false)
  969.                         end
  970.                     end
  971.                 end
  972.             end
  973.             redrawScreen()
  974.         end,
  975.     }
  976.     if commandTable[command] then
  977.         return commandTable[command]()
  978.     else
  979.         return false
  980.     end
  981. end
  982.  
  983. local doAndBack = function(func)
  984.     local backColor = termgetBackgroundColor()
  985.     local textColor = termgetTextColor()
  986.     local curX, curY = termgetCursorPos()
  987.     local results = {func()}
  988.     termsetBackgroundColor(backColor)
  989.     termsetTextColor(textColor)
  990.     termsetCursorPos(curX,curY)
  991.     return tableunpack(results)
  992. end
  993.  
  994. local mainMenu = function()
  995.     local options = {"Send","Inbox","Contacts","Back to terminal","Quit"}
  996.     local cursor = 1
  997.     local _rendermenu = function(c)
  998.         for a = 1, #options do
  999.             term.setCursorPos(2,(scr_y-#options)-1+a)
  1000.             if a == c then
  1001.                 writef("&0> "..options[a])
  1002.             else
  1003.                 writef("&7 "..options[a])
  1004.             end
  1005.         end
  1006.     end
  1007.     while true do
  1008.         _rendermenu(cursor)
  1009.        
  1010.     end
  1011. end
  1012.  
  1013. local renderAll = function()
  1014.     while true do
  1015.         local result = mainMenu()
  1016.     end
  1017. end
  1018.  
  1019. local receiveMessages = function()
  1020.     local encMessage
  1021.     local event, side, frequency, replyFrequency, message, distance
  1022.     while true do
  1023.         event, side, frequency, replyFrequency, message, distance = os.pullEvent()
  1024.         if event == "modem_message" then
  1025.             if distance ~= 0 then
  1026.                 if type(message) == "table" then
  1027.                     if message.cry and message.cs then --basically a ping thing
  1028.                         message.cs = decrite(decode(message.cs),encKey)
  1029.                         if type(message.cry) == "boolean" and message.cs == decrite(checksum,encKey) then
  1030.                             modemTransmit(channel, channel, {tears = encode(encrite(yourName,encKey)), cs = encode(checksum)})
  1031.                         end
  1032.                     else
  1033.                         if message.name and message.msg and message.cs then
  1034.                             encMessage = deepCopy(message)
  1035.                             message.cs = decrite(decode(message.cs),encKey)
  1036.                             message.msg = decode(message.msg)
  1037.                             message.name = decode(message.name)
  1038.                             if type(message.name) == "string" and type(message.msg) == "string" and message.cs == decrite(checksum,encKey) then
  1039.                                 local strtime = tostring(math.floor(os.time()/timedivisor))
  1040.                                 local plainname, plainmsg = decrite(decrite(message.name,strtime),encKey), decrite(decrite(message.msg,strtime),encKey)
  1041.                                 logadd(plainname,plainmsg,false)
  1042.                                 os.queueEvent("enchat_receive",message.name,encMessage)
  1043.                                 doAndBack(redrawScreen)
  1044.                             end
  1045.                         end
  1046.                     end
  1047.                 end
  1048.             end
  1049.         --elseif event == "didScroll" then
  1050.         --  doAndBack(redrawScreen)
  1051.         elseif event == "peripheral" or event == "peripheral_detach" then --yaay
  1052.             if peripheral.getType(side) == "modem" then
  1053.                 generateEncy()
  1054.             end
  1055.         end
  1056.     end
  1057. end
  1058.  
  1059. local sendMessages = function()
  1060.     while true do
  1061.         local event, name, message = os.pullEvent("enchat_send",key)
  1062.         local eName = encrite(encrite(tostring(name),key or encKey),tostring(math.floor(os.time()/timedivisor)))
  1063.         local eMessage = encrite(encrite(tostring(message),key or encKey),tostring(math.floor(os.time()/timedivisor)))
  1064.         local sendmsg = {
  1065.             name = encode(eName),
  1066.             msg = encode(eMessage),
  1067.             cs = encode(checksum),
  1068.         }
  1069.         modemTransmit(channel, channel, sendmsg)
  1070.     end
  1071. end
  1072.  
  1073. if termisColor() then
  1074.     colormode = true
  1075.     grayAllowed = true
  1076. else
  1077.     colormode = false
  1078.     if _VERSION then
  1079.         grayAllowed = true
  1080.     else
  1081.         grayAllowed = false
  1082.     end
  1083. end
  1084.  
  1085. termsetBackgroundColor(colors.gray)
  1086. termclear()
  1087. termsetCursorPos(1,1)
  1088. if not encKey or encKey == "" then
  1089.     local posX, posY = termgetCursorPos()
  1090.     repeat
  1091.         termsetBackgroundColor(colors.gray)
  1092.         termsetTextColor(colors.white)
  1093.         termsetCursorPos(posX,posY)
  1094.         termclearLine()
  1095.         cwrite("Enter encryption key:\n")
  1096.         termsetBackgroundColor(colors.lightGray)
  1097.         termsetTextColor(colors.black)
  1098.         termclearLine()
  1099.         write(">")
  1100.         encKey = read("*")
  1101.     until encKey ~= ""
  1102. end
  1103.  
  1104. if not yourName then
  1105.     write("\n")
  1106.     local posX, posY = termgetCursorPos()
  1107.     local prevX,prevY = 1,1
  1108.     local namePrompt = function()
  1109.         termsetCursorPos(prevX,prevY)
  1110.         termsetBackgroundColor(colors.lightGray)
  1111.         termsetTextColor(colors.black)
  1112.         termclearLine()
  1113.         write(">")
  1114.     end
  1115.     repeat
  1116.         termsetBackgroundColor(colors.gray)
  1117.         termsetTextColor(colors.white)
  1118.         termsetCursorPos(posX,posY)
  1119.         termclearLine()
  1120.         cwrite("Enter your name:\n",posY)
  1121.         prevX,prevY = termgetCursorPos()
  1122.         if enchatSettings.doColorize then
  1123.             termsetTextColor(colors.lightGray)
  1124.             cwrite("Color codes:",scr_y-3)
  1125.             cwrite("(&text,~backg.)",scr_y-2)
  1126.             termsetCursorPos((scr_x/2)-8,scr_y-1)
  1127.             termsetBackgroundColor(colors.gray)
  1128.             termclearLine()
  1129.             blitWrap(textToBlit("~0&f0~1&01~22~33~44~55~66~77~88~99~aa~bb~cc~dd~ee~ff"))
  1130.             termsetCursorPos(prevX,prevY)
  1131.         end
  1132.         termsetBackgroundColor(colors.lightGray)
  1133.         termsetTextColor(colors.black)
  1134.         termclearLine()
  1135.         write(">")
  1136.         yourName = enchatSettings.fancyMsg and funcread(nil,{},namePrompt,false,writef,_ftlen) or read()
  1137.         if textToBlit(yourName) == "con" or textToBlit(yourName) == "*" then
  1138.             termsetBackgroundColor(colors.gray)
  1139.             termsetTextColor(colors.white)
  1140.             print("\nBut not that name!")
  1141.         end
  1142.     until (#yourName >= 1) and (yourName ~= "con") and (yourName ~= "*")
  1143. end
  1144. termsetBackgroundColor(colors.gray)
  1145. termsetTextColor(colors.white)
  1146.  
  1147. generateEncy()
  1148.  
  1149. local getScrolling = function()
  1150.     local oldScroll
  1151.     scroll = 1
  1152.     doScroll = true
  1153.     while true do
  1154.         local _,dir,x,y = os.pullEvent("mouse_scroll")
  1155.         oldScroll = scroll
  1156.         if dir == (enchatSettings.reverseScroll and 1 or -1) then
  1157.             if scroll < #_log-1 then
  1158.                 scroll = scroll + 1
  1159.                 doScroll = false
  1160.             end
  1161.         elseif dir == (enchatSettings.reverseScroll and -1 or 1) then
  1162.             if scroll > 1 then
  1163.                 scroll = scroll - 1
  1164.                 if scroll == 1 then
  1165.                     doScroll = true
  1166.                 end
  1167.             end
  1168.         end
  1169.         if oldScroll ~= scroll then
  1170.             os.queueEvent("didScroll",scroll)
  1171.         end
  1172.     end
  1173. end
  1174.  
  1175. local redrawForKrazy = function()
  1176.     while true do
  1177.         if hasKrazy then
  1178.             redrawScreen()
  1179.             os.queueEvent("redrawprompt")
  1180.         else
  1181.             sleep(0.2)
  1182.         end
  1183.         sleep(0.2)
  1184.     end
  1185. end
  1186.  
  1187. os.queueEvent("enchat_send", "con", yourName.."&r~r moseyed on over.")
  1188.  
  1189. local funcList = {
  1190.     receiveMessages,
  1191.     sendMessages,
  1192.     renderAll,
  1193.     getScrolling,
  1194.     redrawForKrazy,
  1195. }
  1196. parallelwaitForAny(tableunpack(funcList))
  1197. if endMode == 1 then
  1198.     if shell then
  1199.         shell.run(strcapsule(cfile),strcapsule(encKey),strcapsule(yourName))
  1200.     else
  1201.         loadfile(cfile)(encKey,yourName)
  1202.     end
  1203. else
  1204.     if modem then modemClose(channel) end
  1205.     termsetCursorPos(1,scr_y)
  1206.     termsetBackgroundColor(colors.black)
  1207.     termclearLine()
  1208. end
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement