Retrieve and search chat history: Difference between revisions

Added FreeBASIC
(Added FreeBASIC)
 
(6 intermediate revisions by 5 users not shown)
Line 34:
=={{header|C}}==
Starts from current date, prints out lines containing matching substring and also if the string is not found at all in the log of that particular day and also if the log of a day cannot be read for any reason, requires [https://curl.haxx.se/libcurl/ libcurl]
<syntaxhighlight lang="c">
<lang C>
#include<curl/curl.h>
#include<string.h>
Line 110:
return 0;
}
</syntaxhighlight>
</lang>
Invocation and some output, actual output can be huge :
<pre>
Line 125:
 
=={{header|Elixir}}==
<langsyntaxhighlight lang="elixir">#! /usr/bin/env elixir
defmodule Mentions do
def get(url) do
Line 172:
IO.puts("#{url}\n------\n#{Enum.join([h | t], "\n")}\n------\n")
end
end</langsyntaxhighlight>
 
=={{header|FreeBASIC}}==
<syntaxhighlight lang="vbnet">#include "curl.bi"
#include "vbcompat.bi"
#define NULL 0
 
Dim Shared As CURL Ptr curl = NULL
 
Function WriteMemoryCallback(Byval contents As Any Ptr, Byval size As Uinteger, Byval nmemb As Uinteger, Byval userp As String Ptr) As Uinteger
Dim As Uinteger realsize = size * nmemb
*userp &= *Cptr(ZString Ptr, contents)
Return realsize
End Function
 
Function download(url As String) As String
If curl = NULL Then
curl_global_init(CURL_GLOBAL_DEFAULT)
curl = curl_easy_init()
End If
Dim As String readBuffer = ""
curl_easy_setopt(curl, CURLOPT_URL, url)
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, @WriteMemoryCallback)
curl_easy_setopt(curl, CURLOPT_WRITEDATA, @readBuffer)
Dim As CURLcode res = curl_easy_perform(curl)
If res <> 0 Then
Print "libcurl error "; res; " ("; *curl_easy_strerror(res); ")"
Return ""
End If
Return readBuffer
End Function
 
Function grep(needle As String, haystack As String) As String
Dim As Integer i, j
Dim As String res = ""
j = 1
For i = 1 To Len(haystack)
If Mid(haystack, i, 1) = Chr(10) Then
Dim As String linea = Mid(haystack, j, i - j)
If Instr(linea, needle) Then
res &= linea & Chr(10)
End If
j = i + 1
End If
Next i
If Len(res) = 0 Then res = "no occurrences"
Return res
End Function
 
Dim As String needle = "github"
Dim As Integer days = 10
Dim As Integer i
For i = -days To 0
Dim As String dateStr = Format(Dateadd("d", i, Cdbl(Date)), "yyyy-mm-dd")
Dim As String url = "http://tclers.tk/conferences/tcl/" & dateStr & ".tcl"
Dim As String contents = download(url)
If Len(contents) = 0 Then Exit For
Print url
Print grep(needle, contents)
Next i
 
Sleep</syntaxhighlight>
 
=={{header|F_Sharp|F#}}==
<langsyntaxhighlight lang="fsharp">#!/usr/bin/env fsharpi
let server_tz =
try
Line 214 ⟶ 275:
| x ->
printfn "Usage: %s literal" (Array.get x 0)
System.Environment.Exit(1)</langsyntaxhighlight>
 
=={{header|Go}}==
<langsyntaxhighlight lang="go">package main
 
import (
Line 277 ⟶ 338:
}
}
}
}</lang>
</syntaxhighlight>
 
=={{header|Java}}==
<syntaxhighlight lang="java">
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
import java.time.LocalDate;
import java.time.ZoneId;
import java.time.ZonedDateTime;
 
public final class RetrieveAndSearchChatHistory {
 
public static void main(String[] aArgs) throws URISyntaxException, IOException {
String subjectOfSearch = aArgs[0]; // The string 'available' was used to produce the displayed output.
 
ZonedDateTime now = ZonedDateTime.now(ZoneId.of("Europe/Berlin"));
LocalDate tomorrow = now.toLocalDate().plusDays(1);
LocalDate testDate = tomorrow.minusDays(10);
 
while ( ! testDate.equals(tomorrow ) ) {
URL address = new URI("http://tclers.tk/conferences/tcl/" + testDate + ".tcl").toURL();
HttpURLConnection connection = (HttpURLConnection) address.openConnection();
BufferedReader reader = new BufferedReader( new InputStreamReader(connection.getInputStream()) );
System.out.println("Searching chat logs for " + testDate);
String line = "";
while ( ( line = reader.readLine() ).contains(subjectOfSearch) ) {
System.out.println(line);
}
reader.close();
connection.disconnect();
testDate = testDate.plusDays(1);
}
}
 
}
</syntaxhighlight>
{{ out }}
<pre>
Searching chat logs for 2023-08-28
m 2023-08-27T22:01:36Z {} {kurisu2 has become available}
Searching chat logs for 2023-08-29
Searching chat logs for 2023-08-30
m 2023-08-29T22:04:31Z {} {kevin_walzer has become available}
Searching chat logs for 2023-08-31
Searching chat logs for 2023-09-01
Searching chat logs for 2023-09-02
Searching chat logs for 2023-09-03
Searching chat logs for 2023-09-04
Searching chat logs for 2023-09-05
Searching chat logs for 2023-09-06
</pre>
 
=={{header|Julia}}==
<langsyntaxhighlight lang="julia">using Dates, TimeZones, HTTP, Printf
 
function geturlbyday(n)
Line 307 ⟶ 426:
searchlogs()
end
</syntaxhighlight>
</lang>
 
=={{header|Mathematica}}==
<lang Mathematica>matchFrom[url_String, str_String] := Select[StringSplit[Import[url, "String"], "\n"], StringMatchQ[str]]
 
=={{header|Mathematica}}/{{header|Wolfram Language}}==
<syntaxhighlight lang="mathematica">matchFrom[url_String, str_String] := Select[StringSplit[Import[url, "String"], "\n"], StringMatchQ[str]]
getLogLinks[n_] :=
Select[Import["http://tclers.tk/conferences/tcl/", "Hyperlinks"],
Line 317 ⟶ 435:
StringCases[#1, "tcl/" ~~ date__ ~~ ".tcl" :> DateDifference[DateObject[URLDecode[date], TimeZone -> "Europe/Berlin"], Now]]] <=
Quantity[n, "Days"] & ]
 
searchLogs[str_String] := Block[{data},
Map[
Line 324 ⟶ 441:
Print /@ Join[{#, "-----"}, data, {"----\n"}]]) &,
getLogLinks[10]]]
searchLogs["*lazy*"];</syntaxhighlight>
 
searchLogs["*lazy*"];</lang>
{{out}}
<pre>http://tclers.tk/conferences/tcl/2017%2d09%2d25.tcl
-----
m 2017-09-25T14:38:02Z hypnotoad {I'm lazy and the old implementation was called "zvfs", and there a lot of kit builders who are looking for that command}
----</pre>
 
----
</pre>
 
=={{header|Nim}}==
{{trans|Python}}
<langsyntaxhighlight Nimlang="nim">import httpclient, os, re, strformat, strutils, sugar, times
 
const Template = "'http://tclers.tk/conferences/tcl/'yyyy-MM-dd'.tcl'"
Line 362 ⟶ 476:
line
if mentions.len > 0:
echo &"{url}\n------\n{mentions.join()}------\n"</langsyntaxhighlight>
 
{{out}}
Line 380 ⟶ 494:
=={{header|Perl}}==
{{Trans|Raku}}
<langsyntaxhighlight lang="perl"># 20210316 Perl programming solution
 
use strict;
Line 414 ⟶ 528:
 
# find and print needle lines
for (@haystack) { say $_ if (index($_, $needle) != -1) }</langsyntaxhighlight>
 
=={{header|Phix}}==
{{trans|Go}}
{{libheader|Phix/libcurl}}
<!--<syntaxhighlight lang="phix">-->
<lang Phix>include builtins\libcurl.e
<span style="color: #008080;">include</span> <span style="color: #000000;">builtins</span><span style="color: #0000FF;">\</span><span style="color: #000000;">libcurl</span><span style="color: #0000FF;">.</span><span style="color: #000000;">e</span>
atom curl = NULL
<span style="color: #004080;">atom</span> <span style="color: #000000;">curl</span> <span style="color: #0000FF;">=</span> <span style="color: #004600;">NULL</span>
 
function download(string url)
<span style="color: #008080;">function</span> <span style="color: #000000;">download</span><span style="color: #0000FF;">(</span><span style="color: #004080;">string</span> <span style="color: #000000;">url</span><span style="color: #0000FF;">)</span>
if curl=NULL then
<span style="color: #008080;">if</span> <span style="color: #000000;">curl</span><span style="color: #0000FF;">=</span><span style="color: #004600;">NULL</span> <span style="color: #008080;">then</span>
curl_global_init()
<span style="color: #7060A8;">curl_global_init</span><span style="color: #0000FF;">()</span>
curl = curl_easy_init()
<span style="color: #000000;">curl</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">curl_easy_init</span><span style="color: #0000FF;">()</span>
end if
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
curl_easy_setopt(curl, CURLOPT_URL, url)
<span style="color: #7060A8;">curl_easy_setopt</span><span style="color: #0000FF;">(</span><span style="color: #000000;">curl</span><span style="color: #0000FF;">,</span> <span style="color: #004600;">CURLOPT_URL</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">url</span><span style="color: #0000FF;">)</span>
object res = curl_easy_perform_ex(curl)
<span style="color: #004080;">object</span> <span style="color: #000000;">res</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">curl_easy_perform_ex</span><span style="color: #0000FF;">(</span><span style="color: #000000;">curl</span><span style="color: #0000FF;">)</span>
if integer(res) then
<span style="color: #008080;">if</span> <span style="color: #004080;">integer</span><span style="color: #0000FF;">(</span><span style="color: #000000;">res</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">then</span>
printf(1,"libcurl error %d (%s)\n",{res,curl_easy_strerror(res)})
<span style="color: #7060A8;">printf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"libcurl error %d (%s)\n"</span><span style="color: #0000FF;">,{</span><span style="color: #000000;">res</span><span style="color: #0000FF;">,</span><span style="color: #7060A8;">curl_easy_strerror</span><span style="color: #0000FF;">(</span><span style="color: #000000;">res</span><span style="color: #0000FF;">)})</span>
return ""
<span style="color: #008080;">return</span> <span style="color: #008000;">""</span>
end if
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
return res
<span style="color: #008080;">return</span> <span style="color: #000000;">res</span>
end function
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
 
function grep(string needle, haystack)
<span style="color: #008080;">function</span> <span style="color: #000000;">grep</span><span style="color: #0000FF;">(</span><span style="color: #004080;">string</span> <span style="color: #000000;">needle</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">haystack</span><span style="color: #0000FF;">)</span>
sequence lines = split(haystack,"\n"),
<span style="color: #004080;">sequence</span> <span style="color: #000000;">lines</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">split</span><span style="color: #0000FF;">(</span><span style="color: #000000;">haystack</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"\n"</span><span style="color: #0000FF;">),</span>
res = {}
<span style="color: #000000;">res</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{}</span>
for i=1 to length(lines) do
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">lines</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">do</span>
if match(needle,lines[i]) then
<span style="color: #008080;">if</span> <span style="color: #7060A8;">match</span><span style="color: #0000FF;">(</span><span style="color: #000000;">needle</span><span style="color: #0000FF;">,</span><span style="color: #000000;">lines</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">])</span> <span style="color: #008080;">then</span>
res = append(res,lines[i])
<span style="color: #000000;">res</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">append</span><span style="color: #0000FF;">(</span><span style="color: #000000;">res</span><span style="color: #0000FF;">,</span><span style="color: #000000;">lines</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">])</span>
end if
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
end for
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
if res={} then res = {"no occurences"} end if
<span style="color: #008080;">if</span> <span style="color: #000000;">res</span><span style="color: #0000FF;">={}</span> <span style="color: #008080;">then</span> <span style="color: #000000;">res</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{</span><span style="color: #008000;">"no occurences"</span><span style="color: #0000FF;">}</span> <span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
return res
<span style="color: #008080;">return</span> <span style="color: #000000;">res</span>
end function
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
include builtins\timedate.e
<span style="color: #008080;">include</span> <span style="color: #000000;">builtins</span><span style="color: #0000FF;">\</span><span style="color: #004080;">timedate</span><span style="color: #0000FF;">.</span><span style="color: #000000;">e</span>
 
function gen_url(integer i, string timezone)
<span style="color: #008080;">function</span> <span style="color: #000000;">gen_url</span><span style="color: #0000FF;">(</span><span style="color: #004080;">integer</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">,</span> <span style="color: #004080;">string</span> <span style="color: #000000;">timezone</span><span style="color: #0000FF;">)</span>
timedate td = set_timezone(date(),timezone)
<span style="color: #004080;">timedate</span> <span style="color: #000000;">td</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">set_timezone</span><span style="color: #0000FF;">(</span><span style="color: #7060A8;">date</span><span style="color: #0000FF;">(),</span><span style="color: #000000;">timezone</span><span style="color: #0000FF;">)</span>
td = adjust_timedate(td,timedelta(days:=i))
<span style="color: #000000;">td</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">adjust_timedate</span><span style="color: #0000FF;">(</span><span style="color: #000000;">td</span><span style="color: #0000FF;">,</span><span style="color: #7060A8;">timedelta</span><span style="color: #0000FF;">(</span><span style="color: #000000;">days</span><span style="color: #0000FF;">:=</span><span style="color: #000000;">i</span><span style="color: #0000FF;">))</span>
return format_timedate(td,"'http://tclers.tk/conferences/tcl/'YYYY-MM-DD'.tcl'")
<span style="color: #008080;">return</span> <span style="color: #7060A8;">format_timedate</span><span style="color: #0000FF;">(</span><span style="color: #000000;">td</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"'http://tclers.tk/conferences/tcl/'YYYY-MM-DD'.tcl'"</span><span style="color: #0000FF;">)</span>
end function
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
sequence cl = command_line()
<span style="color: #004080;">sequence</span> <span style="color: #000000;">cl</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">command_line</span><span style="color: #0000FF;">()</span>
string needle = "github"
<span style="color: #004080;">string</span> <span style="color: #000000;">needle</span> <span style="color: #0000FF;">=</span> <span style="color: #008000;">"github"</span>
integer days = 10
<span style="color: #004080;">integer</span> <span style="color: #000000;">days</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">10</span>
if length(cl)>=3 then
<span style="color: #008080;">if</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">cl</span><span style="color: #0000FF;">)>=</span><span style="color: #000000;">3</span> <span style="color: #008080;">then</span>
needle := cl[3]
<span style="color: #000000;">needle</span> <span style="color: #0000FF;">:=</span> <span style="color: #000000;">cl</span><span style="color: #0000FF;">[</span><span style="color: #000000;">3</span><span style="color: #0000FF;">]</span>
if length(cl)>=4 then
<span style="color: #008080;">if</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">cl</span><span style="color: #0000FF;">)>=</span><span style="color: #000000;">4</span> <span style="color: #008080;">then</span>
days := to_integer(cl[4])
<span style="color: #000000;">days</span> <span style="color: #0000FF;">:=</span> <span style="color: #7060A8;">to_integer</span><span style="color: #0000FF;">(</span><span style="color: #000000;">cl</span><span style="color: #0000FF;">[</span><span style="color: #000000;">4</span><span style="color: #0000FF;">])</span>
if days=0 or length(cl)>=5 then ?9/0 end if
<span style="color: #008080;">if</span> <span style="color: #000000;">days</span><span style="color: #0000FF;">=</span><span style="color: #000000;">0</span> <span style="color: #008080;">or</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">cl</span><span style="color: #0000FF;">)>=</span><span style="color: #000000;">5</span> <span style="color: #008080;">then</span> <span style="color: #0000FF;">?</span><span style="color: #000000;">9</span><span style="color: #0000FF;">/</span><span style="color: #000000;">0</span> <span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
end if
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
end if
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
for i=-days to 0 do
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=-</span><span style="color: #000000;">days</span> <span style="color: #008080;">to</span> <span style="color: #000000;">0</span> <span style="color: #008080;">do</span>
string url := gen_url(i, "CEST"),
<span style="color: #004080;">string</span> <span style="color: #000000;">url</span> <span style="color: #0000FF;">:=</span> <span style="color: #000000;">gen_url</span><span style="color: #0000FF;">(</span><span style="color: #000000;">i</span><span style="color: #0000FF;">,</span> <span style="color: #008000;">"CEST"</span><span style="color: #0000FF;">),</span>
contents = download(url)
<span style="color: #000000;">contents</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">download</span><span style="color: #0000FF;">(</span><span style="color: #000000;">url</span><span style="color: #0000FF;">)</span>
if contents="" then exit end if
<span style="color: #008080;">if</span> <span style="color: #000000;">contents</span><span style="color: #0000FF;">=</span><span style="color: #008000;">""</span> <span style="color: #008080;">then</span> <span style="color: #008080;">exit</span> <span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
?url
<span style="color: #0000FF;">?</span><span style="color: #000000;">url</span>
printf(1,"%s\n",join(grep(needle,contents),"\n"))
<span style="color: #7060A8;">printf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"%s\n"</span><span style="color: #0000FF;">,</span><span style="color: #7060A8;">join</span><span style="color: #0000FF;">(</span><span style="color: #000000;">grep</span><span style="color: #0000FF;">(</span><span style="color: #000000;">needle</span><span style="color: #0000FF;">,</span><span style="color: #000000;">contents</span><span style="color: #0000FF;">),</span><span style="color: #008000;">"\n"</span><span style="color: #0000FF;">))</span>
end for</lang>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<!--</syntaxhighlight>-->
{{out}}
(manually wrapped)
Line 520 ⟶ 636:
 
=={{header|Python|Python 3}}==
<langsyntaxhighlight lang="python">#! /usr/bin/env python3
import datetime
import re
Line 551 ⟶ 667:
.format(url, '\n'.join(mentions)))
 
main()</langsyntaxhighlight>
 
=={{header|Racket}}==
Retrieves logs from 9 days ago until today and only outputs results if there are matches for the day. Setting the time zone to that of Germany works on Linux and may work on MacOS but has not been tested. Setting the time zone on your machine to Europe/Berlin before running this code will take care of the issue no matter what operating system you're using.
 
<langsyntaxhighlight lang="scheme">#lang racket
(require net/url)
(require racket/date)
Line 611 ⟶ 727:
;; display usage info if no search string is provided
(cond ((= 0 (vector-length (current-command-line-arguments))) (display "USAGE: chat_history <search term>\n"))
(else (display-matches-for-last-10-days (vector-ref (current-command-line-arguments) 0))))</langsyntaxhighlight>
{{out}}
Sample output using a search term of 'github.com'
Line 638 ⟶ 754:
No dependencies or third party libraries huh? How about no modules, no requires, no libraries, no imports at all. Implemented using a bare compiler, strictly with built-ins. (Which makes it kind-of verbose, but thems the trade-offs.)
 
<syntaxhighlight lang="raku" perl6line>my $needle = @*ARGS.shift // '';
my @haystack;
 
Line 685 ⟶ 801:
 
# find and print needle lines
.say if .contains( $needle ) for @haystack;</langsyntaxhighlight>
{{out}}
Sample output using a needle of 'github.com'
Line 717 ⟶ 833:
 
=={{header|Ruby}}==
<langsyntaxhighlight lang="ruby">#! /usr/bin/env ruby
require 'net/http'
require 'time'
Line 745 ⟶ 861:
end
 
main</langsyntaxhighlight>
 
=={{header|Scala}}==
<langsyntaxhighlight lang="scala">import java.net.Socket
import java.net.URL
import java.time
Line 782 ⟶ 898:
case x => s"$url\n------\n${x.mkString("\n")}\n------\n\n"
})
}</langsyntaxhighlight>
 
=={{header|Smalltalk}}==
Line 790 ⟶ 906:
Save as a " .st" file, load into a Pharo 7 image (Tools -> File Browser -> Select the file -> FileIn), navigate using the System Browser to the RosettaCode package to read it more comfortably, save the image, and run on the OS shell with "pharo -headless [image] searchHistory term".
 
<langsyntaxhighlight lang="smalltalk">
CommandLineHandler subclass: #ChatHistorySearchCommandLineHandler
instanceVariableNames: ''
Line 842 ⟶ 958:
^ 'searchHistory'! !
 
</syntaxhighlight>
</lang>
 
=={{header|Tcl}}==
 
===Tcl 8.5+===
<langsyntaxhighlight lang="tcl">#! /usr/bin/env tclsh
package require http
 
Line 882 ⟶ 998:
}
 
main $argv</langsyntaxhighlight>
 
===Jim Tcl===
<langsyntaxhighlight lang="tcl">#! /usr/bin/env jimsh
proc get url {
if {![regexp {http://([a-z.]+)(:[0-9]+)?(/.*)} $url _ host port path]} {
Line 929 ⟶ 1,045:
}
 
main $argv</langsyntaxhighlight>
 
=={{header|Wren}}==
{{libheader|libcurl}}
{{libheader|Wren-date}}
Currently Wren CLI does not have methods to download files or even determine the current date/time in its standard library.
 
However, it is designed to be used primarily as an embedded scripting language and we can therefore ask the host (in this case a C program) to call the necessary functions from its own libraries and pass the results back to Wren. We can then manipulate the date using the above module, search the downloaded files for the string in question and print the results.
<syntaxhighlight lang="wren">/* Retrieve_and_search_chat_history.wren */
 
import "./date" for Date
 
var CURLOPT_URL = 10002
var CURLOPT_FOLLOWLOCATION = 52
var CURLOPT_WRITEFUNCTION = 20011
var CURLOPT_WRITEDATA = 10001
 
class C {
foreign static searchStr
foreign static utcNow // format will be yyyy-mm-dd hh:MM:ss
}
 
foreign class Buffer {
construct new() {} // C will allocate buffer of a suitable size
 
foreign value // returns buffer contents as a string
}
 
foreign class Curl {
construct easyInit() {}
 
foreign easySetOpt(opt, param)
 
foreign easyPerform()
 
foreign easyCleanup()
}
 
var curl = Curl.easyInit()
 
var getContent = Fn.new { |url|
var buffer = Buffer.new()
curl.easySetOpt(CURLOPT_URL, url)
curl.easySetOpt(CURLOPT_FOLLOWLOCATION, 1)
curl.easySetOpt(CURLOPT_WRITEFUNCTION, 0) // write function to be supplied by C
curl.easySetOpt(CURLOPT_WRITEDATA, buffer)
curl.easyPerform()
return buffer.value
}
 
var baseUrl = "http://tclers.tk/conferences/tcl/"
var searchStr = C.searchStr
var now = C.utcNow
var d = Date.parse(now)
d = d.adjustTime("CET") // adjust to German time
var fmt = "mmmm| |d| |yyyy| |H|:|MM|am| |zz|"
System.print("It's %(d.format(fmt)) just now in Germany.")
System.print("Searching for '%(searchStr)' in the TCL Chatroom logs for the last 10 days:\n")
for (i in 0..9) {
var date = d.toString.split(" ")[0]
var url = baseUrl + date + ".tcl"
var underline = "-" * url.count
var content = getContent.call(url)
var lines = content.split("\n")
System.print("%(url)")
System.print(underline)
for (line in lines) {
if (line.indexOf(searchStr) >= 0) System.print(line)
}
System.print(underline + "\n")
d = d.addDays(-1)
}
 
curl.easyCleanup()</syntaxhighlight>
<br>
We now embed this in the following C program, build and run. Note that, whilst it would be possible to embed the Wren script ''directly'' into the C program (so there's only a single file), we have refrained from doing so in the interests of clarity.
<syntaxhighlight lang="c">/* gcc Retrieve_and_search_chat_history.c -o Retrieve_and_search_chat_history -lcurl -lwren -lm */
 
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <curl/curl.h>
#include <time.h>
#include "wren.h"
 
const char *searchStr;
 
struct MemoryStruct {
char *memory;
size_t size;
};
 
/* C <=> Wren interface functions */
 
static size_t WriteMemoryCallback(void *contents, size_t size, size_t nmemb, void *userp) {
size_t realsize = size * nmemb;
struct MemoryStruct *mem = (struct MemoryStruct *)userp;
char *ptr = realloc(mem->memory, mem->size + realsize + 1);
if(!ptr) {
/* out of memory! */
printf("not enough memory (realloc returned NULL)\n");
return 0;
}
 
mem->memory = ptr;
memcpy(&(mem->memory[mem->size]), contents, realsize);
mem->size += realsize;
mem->memory[mem->size] = 0;
return realsize;
}
 
void C_searchStr(WrenVM* vm) {
wrenSetSlotString(vm, 0, searchStr);
}
 
void C_utcNow(WrenVM* vm) {
time_t now = time(NULL);
struct tm *ptm = gmtime(&now);
char dateTimeStr[20];
strftime(dateTimeStr, 20, "%Y-%m-%d %H:%M:%S", ptm);
wrenSetSlotString(vm, 0, dateTimeStr);
}
 
void C_bufferAllocate(WrenVM* vm) {
struct MemoryStruct *ms = (struct MemoryStruct *)wrenSetSlotNewForeign(vm, 0, 0, sizeof(struct MemoryStruct));
ms->memory = malloc(1);
ms->size = 0;
}
 
void C_bufferFinalize(void* data) {
struct MemoryStruct *ms = (struct MemoryStruct *)data;
free(ms->memory);
}
 
void C_curlAllocate(WrenVM* vm) {
CURL** pcurl = (CURL**)wrenSetSlotNewForeign(vm, 0, 0, sizeof(CURL*));
*pcurl = curl_easy_init();
}
 
void C_value(WrenVM* vm) {
struct MemoryStruct *ms = (struct MemoryStruct *)wrenGetSlotForeign(vm, 0);
wrenSetSlotString(vm, 0, ms->memory);
}
 
void C_easyPerform(WrenVM* vm) {
CURL* curl = *(CURL**)wrenGetSlotForeign(vm, 0);
curl_easy_perform(curl);
}
 
void C_easyCleanup(WrenVM* vm) {
CURL* curl = *(CURL**)wrenGetSlotForeign(vm, 0);
curl_easy_cleanup(curl);
}
 
void C_easySetOpt(WrenVM* vm) {
CURL* curl = *(CURL**)wrenGetSlotForeign(vm, 0);
CURLoption opt = (CURLoption)wrenGetSlotDouble(vm, 1);
if (opt < 10000) {
long lparam = (long)wrenGetSlotDouble(vm, 2);
curl_easy_setopt(curl, opt, lparam);
} else if (opt < 20000) {
if (opt == CURLOPT_WRITEDATA) {
struct MemoryStruct *ms = (struct MemoryStruct *)wrenGetSlotForeign(vm, 2);
curl_easy_setopt(curl, opt, (void *)ms);
} else if (opt == CURLOPT_URL) {
const char *url = wrenGetSlotString(vm, 2);
curl_easy_setopt(curl, opt, url);
}
} else if (opt < 30000) {
if (opt == CURLOPT_WRITEFUNCTION) {
curl_easy_setopt(curl, opt, &WriteMemoryCallback);
}
}
}
 
WrenForeignClassMethods bindForeignClass(WrenVM* vm, const char* module, const char* className) {
WrenForeignClassMethods methods;
methods.allocate = NULL;
methods.finalize = NULL;
if (strcmp(module, "main") == 0) {
if (strcmp(className, "Buffer") == 0) {
methods.allocate = C_bufferAllocate;
methods.finalize = C_bufferFinalize;
} else if (strcmp(className, "Curl") == 0) {
methods.allocate = C_curlAllocate;
}
}
return methods;
}
 
WrenForeignMethodFn bindForeignMethod(
WrenVM* vm,
const char* module,
const char* className,
bool isStatic,
const char* signature) {
if (strcmp(module, "main") == 0) {
if (strcmp(className, "Buffer") == 0) {
if (!isStatic && strcmp(signature, "value") == 0) return C_value;
} else if (strcmp(className, "C") == 0) {
if (isStatic && strcmp(signature, "searchStr") == 0) return C_searchStr;
if (isStatic && strcmp(signature, "utcNow") == 0) return C_utcNow;
} else if (strcmp(className, "Curl") == 0) {
if (!isStatic && strcmp(signature, "easySetOpt(_,_)") == 0) return C_easySetOpt;
if (!isStatic && strcmp(signature, "easyPerform()") == 0) return C_easyPerform;
if (!isStatic && strcmp(signature, "easyCleanup()") == 0) return C_easyCleanup;
}
}
return NULL;
}
 
static void writeFn(WrenVM* vm, const char* text) {
printf("%s", text);
}
 
void errorFn(WrenVM* vm, WrenErrorType errorType, const char* module, const int line, const char* msg) {
switch (errorType) {
case WREN_ERROR_COMPILE:
printf("[%s line %d] [Error] %s\n", module, line, msg);
break;
case WREN_ERROR_STACK_TRACE:
printf("[%s line %d] in %s\n", module, line, msg);
break;
case WREN_ERROR_RUNTIME:
printf("[Runtime Error] %s\n", msg);
break;
}
}
 
char *readFile(const char *fileName) {
FILE *f = fopen(fileName, "r");
fseek(f, 0, SEEK_END);
long fsize = ftell(f);
rewind(f);
char *script = malloc(fsize + 1);
fread(script, 1, fsize, f);
fclose(f);
script[fsize] = 0;
return script;
}
 
static void loadModuleComplete(WrenVM* vm, const char* module, WrenLoadModuleResult result) {
if( result.source) free((void*)result.source);
}
 
WrenLoadModuleResult loadModule(WrenVM* vm, const char* name) {
WrenLoadModuleResult result = {0};
if (strcmp(name, "random") != 0 && strcmp(name, "meta") != 0) {
result.onComplete = loadModuleComplete;
char fullName[strlen(name) + 6];
strcpy(fullName, name);
strcat(fullName, ".wren");
result.source = readFile(fullName);
}
return result;
}
 
int main(int argc, char **argv) {
if (argc != 2) {
printf("Please pass the string to be searched for.\n");
return 0;
}
searchStr = argv[1];
WrenConfiguration config;
wrenInitConfiguration(&config);
config.writeFn = &writeFn;
config.errorFn = &errorFn;
config.bindForeignClassFn = &bindForeignClass;
config.bindForeignMethodFn = &bindForeignMethod;
config.loadModuleFn = &loadModule;
WrenVM* vm = wrenNewVM(&config);
const char* module = "main";
const char* fileName = "Retrieve_and_search_chat_history.wren";
char *script = readFile(fileName);
WrenInterpretResult result = wrenInterpret(vm, module, script);
switch (result) {
case WREN_RESULT_COMPILE_ERROR:
printf("Compile Error!\n");
break;
case WREN_RESULT_RUNTIME_ERROR:
printf("Runtime Error!\n");
break;
case WREN_RESULT_SUCCESS:
break;
}
wrenFreeVM(vm);
free(script);
return 0;
}</syntaxhighlight>
 
{{out}}
Sample input/output:
<pre>
$ ./Retrieve_and_search_chat_history "now known as"
It's January 9 2022 4:07pm CET just now in Germany.
Searching for 'now known as' in the TCL Chatroom logs for the last 10 days:
 
http://tclers.tk/conferences/tcl/2022-01-09.tcl
-----------------------------------------------
m 2022-01-08T23:29:00Z ijchain {*** wilk_ is now known as wilk}
m 2022-01-09T01:45:17Z ijchain {*** rhobart1 is now known as rhobart}
-----------------------------------------------
 
http://tclers.tk/conferences/tcl/2022-01-08.tcl
-----------------------------------------------
-----------------------------------------------
 
http://tclers.tk/conferences/tcl/2022-01-07.tcl
-----------------------------------------------
-----------------------------------------------
 
http://tclers.tk/conferences/tcl/2022-01-06.tcl
-----------------------------------------------
m 2022-01-06T22:01:29Z ijchain {*** Ellenor is now known as Reinhilde}
-----------------------------------------------
 
http://tclers.tk/conferences/tcl/2022-01-05.tcl
-----------------------------------------------
-----------------------------------------------
 
http://tclers.tk/conferences/tcl/2022-01-04.tcl
-----------------------------------------------
m 2022-01-04T11:45:20Z ijchain {*** tinytoas1 is now known as tinystoat}
-----------------------------------------------
 
http://tclers.tk/conferences/tcl/2022-01-03.tcl
-----------------------------------------------
m 2022-01-03T20:28:27Z ijchain {*** MrChristmas is now known as MrC}
-----------------------------------------------
 
http://tclers.tk/conferences/tcl/2022-01-02.tcl
-----------------------------------------------
m 2022-01-02T18:51:07Z ijchain {*** Festive_Dragon is now known as A_Dragon}
m 2022-01-02T20:21:14Z ijchain {*** uhu- is now known as uhu}
m 2022-01-02T20:40:40Z ijchain {*** ninex_ is now known as ninex}
m 2022-01-02T21:41:13Z ijchain {*** Akuli is now known as Akuli[testing]}
m 2022-01-02T21:41:18Z ijchain {*** Akuli[testing] is now known as Akuli}
-----------------------------------------------
 
http://tclers.tk/conferences/tcl/2022-01-01.tcl
-----------------------------------------------
-----------------------------------------------
 
http://tclers.tk/conferences/tcl/2021-12-31.tcl
-----------------------------------------------
-----------------------------------------------
</pre>
 
=={{header|zkl}}==
<langsyntaxhighlight lang="zkl">#<<<#
http://tclers.tk/conferences/tcl/:
2017-04-03.tcl 30610 bytes Apr 03, 2017 21:55:37
Line 958 ⟶ 1,421:
mentions:=haystack.filter("find",needle); // search lines
if(mentions) println("%s\n------\n%s------\n".fmt(url,mentions.text));
}</langsyntaxhighlight>
While zkl supports TCP natively and talking simple HTTP is easy,
Curl is way easier and fully supports the protocol.
2,130

edits