1111 * Syntax: TOPICHISTORY channel {LIST | CLEAR | SET entry-num}
1212 *
1313 * Configuration to put into your chanserv config:
14- module { name = "cs_topichistory"; maxhistory = 3; }
15- command { service = "ChanServ"; name = "SET TOPICHISTORY"; command = "chanserv/set/topichistory"; }
16- command { service = "ChanServ"; name = "TOPICHISTORY"; command = "chanserv/topichistory"; group = "chanserv/management"; }
14+ * module { name = "cs_topichistory"; maxhistory = 3; }
15+ * command { service = "ChanServ"; name = "SET TOPICHISTORY"; command = "chanserv/set/topichistory"; }
16+ * command { service = "ChanServ"; name = "TOPICHISTORY"; command = "chanserv/topichistory"; group = "chanserv/management"; }
1717 *
1818 */
1919
@@ -180,7 +180,34 @@ class CommandCSTopicHistory : public Command
180180 /* Create a new List and add the current topic, just like when enabling the option */
181181 TopicHistoryList *entries = ci->Require <TopicHistoryList>(" topichistorylist" );
182182 if ((*entries)->empty ())
183- (*entries)->push_back (new TopicHistoryEntry (ci, ci->last_topic , ci->last_topic_setter , ci->last_topic_time ));
183+ {
184+ Anope::string topic;
185+ Anope::string setter;
186+ time_t when = 0 ;
187+
188+ if (ci->c )
189+ {
190+ topic = ci->c ->topic ;
191+ setter = ci->c ->topic_setter ;
192+ when = ci->c ->topic_time ;
193+ }
194+
195+ if (topic.empty ())
196+ {
197+ topic = ci->last_topic ;
198+ setter = ci->last_topic_setter ;
199+ when = ci->last_topic_time ;
200+ }
201+
202+ if (!topic.empty ())
203+ {
204+ if (when == 0 )
205+ when = Anope::CurTime;
206+ if (setter.empty ())
207+ setter = " unknown" ;
208+ (*entries)->push_back (new TopicHistoryEntry (ci, topic, setter, when));
209+ }
210+ }
184211
185212 Log (source.AccessFor (ci).HasPriv (" TOPIC" ) ? LOG_COMMAND : LOG_OVERRIDE, source, this , ci) << " to remove all historical topics." ;
186213 source.Reply (" Topic history for \002 %s\002 has been cleared." , ci->name .c_str ());
@@ -204,7 +231,8 @@ class CommandCSTopicHistory : public Command
204231 try
205232 {
206233 unsigned i = std::stoi (entrynum.str ());
207- if (i > 0 && i <= (*entries)->size ())
234+ // Index 0 is the current topic (hidden); valid history entries are 1..size-1.
235+ if (i >= 1 && i < (*entries)->size ())
208236 {
209237 if (ci->c ->topic == (*entries)->at (i)->topic )
210238 {
@@ -321,10 +349,39 @@ class CommandCSSetTopicHistory : public Command
321349 source.Reply (" Topic history option for %s is now \002 on\002 ." , ci->name .c_str ());
322350
323351 ci->Extend <bool >(" TOPICHISTORY" );
324- /* If this channel's topic history list is empty, add the current topic as a starting point. */
352+ /* If this channel's topic history list is empty, seed it with the current topic (if any).
353+ * Avoid creating blank/epoch entries when the channel is not in use or has no topic.
354+ */
325355 TopicHistoryList *entries = ci->Require <TopicHistoryList>(" topichistorylist" );
326356 if ((*entries)->empty ())
327- (*entries)->push_back (new TopicHistoryEntry (ci, ci->last_topic , ci->last_topic_setter , ci->last_topic_time ));
357+ {
358+ Anope::string topic;
359+ Anope::string setter;
360+ time_t when = 0 ;
361+
362+ if (ci->c )
363+ {
364+ topic = ci->c ->topic ;
365+ setter = ci->c ->topic_setter ;
366+ when = ci->c ->topic_time ;
367+ }
368+
369+ if (topic.empty ())
370+ {
371+ topic = ci->last_topic ;
372+ setter = ci->last_topic_setter ;
373+ when = ci->last_topic_time ;
374+ }
375+
376+ if (!topic.empty ())
377+ {
378+ if (when == 0 )
379+ when = Anope::CurTime;
380+ if (setter.empty ())
381+ setter = " unknown" ;
382+ (*entries)->push_back (new TopicHistoryEntry (ci, topic, setter, when));
383+ }
384+ }
328385 }
329386 else if (params[1 ].equals_ci (" OFF" ))
330387 {
0 commit comments